3
|
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis |
|
2 * |
|
3 * LibTomCrypt is a library that provides various cryptographic |
|
4 * algorithms in a highly modular and flexible manner. |
|
5 * |
|
6 * The library is free for all purposes without any express |
|
7 * guarantee it works. |
|
8 * |
|
9 * Tom St Denis, [email protected], http://libtomcrypt.org |
|
10 */ |
|
11 #include "mycrypt.h" |
|
12 |
|
13 /* PKCS #1 PSS Signature Padding -- Tom St Denis */ |
|
14 |
|
15 #ifdef PKCS_1 |
|
16 |
|
17 int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, |
15
|
18 unsigned long saltlen, prng_state *prng, |
|
19 int prng_idx, int hash_idx, |
3
|
20 unsigned long modulus_bitlen, |
|
21 unsigned char *out, unsigned long *outlen) |
|
22 { |
|
23 unsigned char DB[1024], mask[sizeof(DB)], salt[sizeof(DB)], hash[sizeof(DB)]; |
|
24 unsigned long x, y, hLen, modulus_len; |
|
25 int err; |
|
26 hash_state md; |
|
27 |
|
28 _ARGCHK(msghash != NULL); |
|
29 _ARGCHK(out != NULL); |
|
30 _ARGCHK(outlen != NULL); |
|
31 |
|
32 /* ensure hash and PRNG are valid */ |
|
33 if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { |
|
34 return err; |
|
35 } |
|
36 if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { |
|
37 return err; |
|
38 } |
|
39 |
|
40 hLen = hash_descriptor[hash_idx].hashsize; |
|
41 modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); |
|
42 |
|
43 /* check sizes */ |
|
44 if ((saltlen > sizeof(salt)) || (modulus_len > sizeof(DB)) || (modulus_len < hLen + saltlen + 2)) { |
|
45 return CRYPT_INVALID_ARG; |
|
46 } |
|
47 |
|
48 /* generate random salt */ |
|
49 if (saltlen > 0) { |
|
50 if (prng_descriptor[prng_idx].read(salt, saltlen, prng) != saltlen) { |
|
51 return CRYPT_ERROR_READPRNG; |
|
52 } |
|
53 } |
|
54 |
|
55 /* M = (eight) 0x00 || msghash || salt, hash = H(M) */ |
|
56 hash_descriptor[hash_idx].init(&md); |
|
57 zeromem(DB, 8); |
|
58 if ((err = hash_descriptor[hash_idx].process(&md, DB, 8)) != CRYPT_OK) { |
|
59 return err; |
|
60 } |
|
61 if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) { |
|
62 return err; |
|
63 } |
|
64 if ((err = hash_descriptor[hash_idx].process(&md, salt, saltlen)) != CRYPT_OK) { |
|
65 return err; |
|
66 } |
|
67 if ((err = hash_descriptor[hash_idx].done(&md, hash)) != CRYPT_OK) { |
|
68 return err; |
|
69 } |
|
70 |
|
71 /* generate DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */ |
|
72 for (x = 0; x < (modulus_len - saltlen - hLen - 2); x++) { |
|
73 DB[x] = 0x00; |
|
74 } |
|
75 DB[x++] = 0x01; |
|
76 for (y = 0; y < saltlen; y++) { |
|
77 DB[x++] = salt[y]; |
|
78 } |
|
79 |
|
80 /* generate mask of length modulus_len - hLen - 1 from hash */ |
|
81 if ((err = pkcs_1_mgf1(hash, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) { |
|
82 return err; |
|
83 } |
|
84 |
|
85 /* xor against DB */ |
|
86 for (y = 0; y < (modulus_len - hLen - 1); y++) { |
|
87 DB[y] ^= mask[y]; |
|
88 } |
|
89 |
|
90 /* output is DB || hash || 0xBC */ |
|
91 if (*outlen < modulus_len) { |
|
92 return CRYPT_BUFFER_OVERFLOW; |
|
93 } |
|
94 |
|
95 /* DB */ |
|
96 for (y = x = 0; x < modulus_len - hLen - 1; x++) { |
|
97 out[y++] = DB[x]; |
|
98 } |
|
99 /* hash */ |
|
100 for (x = 0; x < hLen; x++) { |
|
101 out[y++] = hash[x]; |
|
102 } |
|
103 /* 0xBC */ |
|
104 out[y] = 0xBC; |
|
105 |
|
106 /* now clear the 8*modulus_len - modulus_bitlen most significant bits */ |
15
|
107 out[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)); |
3
|
108 |
|
109 /* store output size */ |
|
110 *outlen = modulus_len; |
|
111 |
|
112 #ifdef CLEAN_STACK |
|
113 zeromem(DB, sizeof(DB)); |
|
114 zeromem(mask, sizeof(mask)); |
|
115 zeromem(salt, sizeof(salt)); |
|
116 zeromem(hash, sizeof(hash)); |
|
117 #endif |
|
118 |
|
119 return CRYPT_OK; |
|
120 } |
|
121 |
|
122 #endif /* PKCS_1 */ |