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 { |
143
|
23 unsigned char *DB, *mask, *salt, *hash; |
3
|
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 |
143
|
43 /* allocate ram for DB/mask/salt/hash of size modulus_len */ |
|
44 DB = XMALLOC(modulus_len); |
|
45 mask = XMALLOC(modulus_len); |
|
46 salt = XMALLOC(modulus_len); |
|
47 hash = XMALLOC(modulus_len); |
|
48 if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) { |
|
49 if (DB != NULL) { |
|
50 XFREE(DB); |
|
51 } |
|
52 if (mask != NULL) { |
|
53 XFREE(mask); |
|
54 } |
|
55 if (salt != NULL) { |
|
56 XFREE(salt); |
|
57 } |
|
58 if (hash != NULL) { |
|
59 XFREE(hash); |
|
60 } |
|
61 return CRYPT_MEM; |
|
62 } |
|
63 |
|
64 |
3
|
65 /* check sizes */ |
143
|
66 if ((saltlen > modulus_len) || (modulus_len < hLen + saltlen + 2)) { |
|
67 err = CRYPT_INVALID_ARG; |
|
68 goto __ERR; |
3
|
69 } |
|
70 |
|
71 /* generate random salt */ |
|
72 if (saltlen > 0) { |
|
73 if (prng_descriptor[prng_idx].read(salt, saltlen, prng) != saltlen) { |
143
|
74 err = CRYPT_ERROR_READPRNG; |
|
75 goto __ERR; |
3
|
76 } |
|
77 } |
|
78 |
|
79 /* M = (eight) 0x00 || msghash || salt, hash = H(M) */ |
143
|
80 if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) { |
|
81 goto __ERR; |
|
82 } |
3
|
83 zeromem(DB, 8); |
|
84 if ((err = hash_descriptor[hash_idx].process(&md, DB, 8)) != CRYPT_OK) { |
143
|
85 goto __ERR; |
3
|
86 } |
|
87 if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) { |
143
|
88 goto __ERR; |
3
|
89 } |
|
90 if ((err = hash_descriptor[hash_idx].process(&md, salt, saltlen)) != CRYPT_OK) { |
143
|
91 goto __ERR; |
3
|
92 } |
|
93 if ((err = hash_descriptor[hash_idx].done(&md, hash)) != CRYPT_OK) { |
143
|
94 goto __ERR; |
3
|
95 } |
|
96 |
|
97 /* generate DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */ |
|
98 for (x = 0; x < (modulus_len - saltlen - hLen - 2); x++) { |
|
99 DB[x] = 0x00; |
|
100 } |
|
101 DB[x++] = 0x01; |
|
102 for (y = 0; y < saltlen; y++) { |
|
103 DB[x++] = salt[y]; |
|
104 } |
|
105 |
|
106 /* generate mask of length modulus_len - hLen - 1 from hash */ |
|
107 if ((err = pkcs_1_mgf1(hash, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) { |
143
|
108 goto __ERR; |
3
|
109 } |
|
110 |
|
111 /* xor against DB */ |
|
112 for (y = 0; y < (modulus_len - hLen - 1); y++) { |
|
113 DB[y] ^= mask[y]; |
|
114 } |
|
115 |
|
116 /* output is DB || hash || 0xBC */ |
|
117 if (*outlen < modulus_len) { |
143
|
118 err = CRYPT_BUFFER_OVERFLOW; |
|
119 goto __ERR; |
3
|
120 } |
|
121 |
|
122 /* DB */ |
|
123 for (y = x = 0; x < modulus_len - hLen - 1; x++) { |
|
124 out[y++] = DB[x]; |
|
125 } |
|
126 /* hash */ |
|
127 for (x = 0; x < hLen; x++) { |
|
128 out[y++] = hash[x]; |
|
129 } |
|
130 /* 0xBC */ |
|
131 out[y] = 0xBC; |
|
132 |
|
133 /* now clear the 8*modulus_len - modulus_bitlen most significant bits */ |
15
|
134 out[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)); |
3
|
135 |
|
136 /* store output size */ |
|
137 *outlen = modulus_len; |
143
|
138 err = CRYPT_OK; |
|
139 __ERR: |
3
|
140 #ifdef CLEAN_STACK |
143
|
141 zeromem(DB, modulus_len); |
|
142 zeromem(mask, modulus_len); |
|
143 zeromem(salt, modulus_len); |
|
144 zeromem(hash, modulus_len); |
3
|
145 #endif |
|
146 |
143
|
147 XFREE(hash); |
|
148 XFREE(salt); |
|
149 XFREE(mask); |
|
150 XFREE(DB); |
|
151 |
|
152 return err; |
3
|
153 } |
|
154 |
|
155 #endif /* PKCS_1 */ |