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_decode(const unsigned char *msghash, unsigned long msghashlen, |
|
18 const unsigned char *sig, unsigned long siglen, |
|
19 unsigned long saltlen, int hash_idx, |
|
20 unsigned long modulus_bitlen, int *res) |
|
21 { |
143
|
22 unsigned char *DB, *mask, *salt, *hash; |
3
|
23 unsigned long x, y, hLen, modulus_len; |
|
24 int err; |
|
25 hash_state md; |
|
26 |
|
27 _ARGCHK(msghash != NULL); |
|
28 _ARGCHK(res != NULL); |
|
29 |
|
30 /* default to invalid */ |
|
31 *res = 0; |
|
32 |
|
33 /* ensure hash is valid */ |
|
34 if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { |
|
35 return err; |
|
36 } |
|
37 |
|
38 hLen = hash_descriptor[hash_idx].hashsize; |
|
39 modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); |
|
40 |
143
|
41 /* allocate ram for DB/mask/salt/hash of size modulus_len */ |
|
42 DB = XMALLOC(modulus_len); |
|
43 mask = XMALLOC(modulus_len); |
|
44 salt = XMALLOC(modulus_len); |
|
45 hash = XMALLOC(modulus_len); |
|
46 if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) { |
|
47 if (DB != NULL) { |
|
48 XFREE(DB); |
|
49 } |
|
50 if (mask != NULL) { |
|
51 XFREE(mask); |
|
52 } |
|
53 if (salt != NULL) { |
|
54 XFREE(salt); |
|
55 } |
|
56 if (hash != NULL) { |
|
57 XFREE(hash); |
|
58 } |
|
59 return CRYPT_MEM; |
|
60 } |
|
61 |
3
|
62 /* check sizes */ |
143
|
63 if ((saltlen > modulus_len) || |
3
|
64 (modulus_len < hLen + saltlen + 2) || (siglen != modulus_len)) { |
143
|
65 err = CRYPT_INVALID_ARG; |
|
66 goto __ERR; |
3
|
67 } |
|
68 |
|
69 /* ensure the 0xBC byte */ |
|
70 if (sig[siglen-1] != 0xBC) { |
143
|
71 err = CRYPT_OK; |
|
72 goto __ERR; |
3
|
73 } |
|
74 |
|
75 /* copy out the DB */ |
|
76 for (x = 0; x < modulus_len - hLen - 1; x++) { |
|
77 DB[x] = sig[x]; |
|
78 } |
|
79 |
|
80 /* copy out the hash */ |
|
81 for (y = 0; y < hLen; y++) { |
|
82 hash[y] = sig[x++]; |
|
83 } |
|
84 |
|
85 /* check the MSB */ |
15
|
86 if ((sig[0] & ~(0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)))) != 0) { |
143
|
87 err = CRYPT_OK; |
|
88 goto __ERR; |
3
|
89 } |
|
90 |
|
91 /* generate mask of length modulus_len - hLen - 1 from hash */ |
|
92 if ((err = pkcs_1_mgf1(hash, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) { |
143
|
93 goto __ERR; |
3
|
94 } |
|
95 |
|
96 /* xor against DB */ |
|
97 for (y = 0; y < (modulus_len - hLen - 1); y++) { |
|
98 DB[y] ^= mask[y]; |
|
99 } |
15
|
100 |
|
101 /* now clear the first byte [make sure smaller than modulus] */ |
|
102 DB[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)); |
3
|
103 |
|
104 /* DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */ |
|
105 |
|
106 /* check for zeroes and 0x01 */ |
|
107 for (x = 0; x < modulus_len - saltlen - hLen - 2; x++) { |
|
108 if (DB[x] != 0x00) { |
143
|
109 err = CRYPT_OK; |
|
110 goto __ERR; |
3
|
111 } |
|
112 } |
|
113 |
143
|
114 /* check for the 0x01 */ |
3
|
115 if (DB[x++] != 0x01) { |
143
|
116 err = CRYPT_OK; |
|
117 goto __ERR; |
3
|
118 } |
|
119 |
|
120 /* M = (eight) 0x00 || msghash || salt, mask = H(M) */ |
143
|
121 if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) { |
|
122 goto __ERR; |
|
123 } |
3
|
124 zeromem(mask, 8); |
|
125 if ((err = hash_descriptor[hash_idx].process(&md, mask, 8)) != CRYPT_OK) { |
143
|
126 goto __ERR; |
3
|
127 } |
|
128 if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) { |
143
|
129 goto __ERR; |
3
|
130 } |
|
131 if ((err = hash_descriptor[hash_idx].process(&md, DB+x, saltlen)) != CRYPT_OK) { |
143
|
132 goto __ERR; |
3
|
133 } |
|
134 if ((err = hash_descriptor[hash_idx].done(&md, mask)) != CRYPT_OK) { |
143
|
135 goto __ERR; |
3
|
136 } |
|
137 |
|
138 /* mask == hash means valid signature */ |
|
139 if (memcmp(mask, hash, hLen) == 0) { |
|
140 *res = 1; |
|
141 } |
|
142 |
143
|
143 err = CRYPT_OK; |
|
144 __ERR: |
3
|
145 #ifdef CLEAN_STACK |
143
|
146 zeromem(DB, modulus_len); |
|
147 zeromem(mask, modulus_len); |
|
148 zeromem(salt, modulus_len); |
|
149 zeromem(hash, modulus_len); |
3
|
150 #endif |
|
151 |
143
|
152 XFREE(hash); |
|
153 XFREE(salt); |
|
154 XFREE(mask); |
|
155 XFREE(DB); |
|
156 |
|
157 return err; |
3
|
158 } |
|
159 |
|
160 #endif /* PKCS_1 */ |