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 /* OAEP Padding for PKCS #1 -- Tom St Denis */ |
|
14 |
|
15 #ifdef PKCS_1 |
|
16 |
|
17 int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, |
15
|
18 const unsigned char *lparam, unsigned long lparamlen, |
|
19 unsigned long modulus_bitlen, int hash_idx, |
|
20 unsigned char *out, unsigned long *outlen, |
|
21 int *res) |
3
|
22 { |
143
|
23 unsigned char *DB, *seed, *mask; |
3
|
24 unsigned long hLen, x, y, modulus_len; |
|
25 int err; |
|
26 |
|
27 _ARGCHK(msg != NULL); |
|
28 _ARGCHK(out != NULL); |
|
29 _ARGCHK(outlen != NULL); |
15
|
30 _ARGCHK(res != NULL); |
|
31 |
|
32 /* default to invalid packet */ |
|
33 *res = 0; |
3
|
34 |
|
35 /* test valid hash */ |
|
36 if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { |
|
37 return err; |
|
38 } |
|
39 hLen = hash_descriptor[hash_idx].hashsize; |
|
40 modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); |
|
41 |
143
|
42 /* allocate ram for DB/mask/salt of size modulus_len */ |
|
43 DB = XMALLOC(modulus_len); |
|
44 mask = XMALLOC(modulus_len); |
|
45 seed = XMALLOC(modulus_len); |
|
46 if (DB == NULL || mask == NULL || seed == NULL) { |
|
47 if (DB != NULL) { |
|
48 XFREE(DB); |
|
49 } |
|
50 if (mask != NULL) { |
|
51 XFREE(mask); |
|
52 } |
|
53 if (seed != NULL) { |
|
54 XFREE(seed); |
|
55 } |
|
56 return CRYPT_MEM; |
|
57 } |
|
58 |
|
59 |
3
|
60 /* test message size */ |
143
|
61 if (msglen != modulus_len) { |
|
62 err = CRYPT_PK_INVALID_SIZE; |
|
63 goto __ERR; |
3
|
64 } |
|
65 |
|
66 /* ok so it's now in the form |
|
67 |
|
68 0x00 || maskedseed || maskedDB |
|
69 |
|
70 1 || hLen || modulus_len - hLen - 1 |
|
71 |
|
72 */ |
|
73 |
|
74 /* must have leading 0x00 byte */ |
|
75 if (msg[0] != 0x00) { |
143
|
76 err = CRYPT_OK; |
|
77 goto __ERR; |
3
|
78 } |
|
79 |
|
80 /* now read the masked seed */ |
|
81 for (x = 1, y = 0; y < hLen; y++) { |
|
82 seed[y] = msg[x++]; |
|
83 } |
|
84 |
|
85 /* now read the masked DB */ |
|
86 for (y = 0; y < modulus_len - hLen - 1; y++) { |
|
87 DB[y] = msg[x++]; |
|
88 } |
|
89 |
|
90 /* compute MGF1 of maskedDB (hLen) */ |
|
91 if ((err = pkcs_1_mgf1(DB, modulus_len - hLen - 1, hash_idx, mask, hLen)) != CRYPT_OK) { |
143
|
92 goto __ERR; |
3
|
93 } |
|
94 |
|
95 /* XOR against seed */ |
|
96 for (y = 0; y < hLen; y++) { |
|
97 seed[y] ^= mask[y]; |
|
98 } |
|
99 |
|
100 /* compute MGF1 of seed (k - hlen - 1) */ |
|
101 if ((err = pkcs_1_mgf1(seed, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) { |
143
|
102 goto __ERR; |
3
|
103 } |
|
104 |
|
105 /* xor against DB */ |
|
106 for (y = 0; y < (modulus_len - hLen - 1); y++) { |
|
107 DB[y] ^= mask[y]; |
|
108 } |
|
109 |
|
110 /* now DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */ |
|
111 |
|
112 /* compute lhash and store it in seed [reuse temps!] */ |
143
|
113 x = modulus_len; |
3
|
114 if (lparam != NULL) { |
|
115 if ((err = hash_memory(hash_idx, lparam, lparamlen, seed, &x)) != CRYPT_OK) { |
143
|
116 goto __ERR; |
3
|
117 } |
|
118 } else { |
|
119 /* can't pass hash_memory a NULL so use DB with zero length */ |
|
120 if ((err = hash_memory(hash_idx, DB, 0, seed, &x)) != CRYPT_OK) { |
143
|
121 goto __ERR; |
3
|
122 } |
|
123 } |
|
124 |
|
125 /* compare the lhash'es */ |
|
126 if (memcmp(seed, DB, hLen) != 0) { |
143
|
127 err = CRYPT_OK; |
|
128 goto __ERR; |
3
|
129 } |
|
130 |
|
131 /* now zeroes before a 0x01 */ |
|
132 for (x = hLen; x < (modulus_len - hLen - 1) && DB[x] == 0x00; x++) { |
|
133 /* step... */ |
|
134 } |
|
135 |
|
136 /* error out if wasn't 0x01 */ |
|
137 if (x == (modulus_len - hLen - 1) || DB[x] != 0x01) { |
143
|
138 err = CRYPT_OK; |
|
139 goto __ERR; |
3
|
140 } |
|
141 |
|
142 /* rest is the message (and skip 0x01) */ |
143
|
143 if ((modulus_len - hLen - 1) - ++x > *outlen) { |
|
144 err = CRYPT_BUFFER_OVERFLOW; |
|
145 goto __ERR; |
3
|
146 } |
|
147 |
|
148 /* copy message */ |
|
149 *outlen = (modulus_len - hLen - 1) - x; |
|
150 for (y = 0; x != (modulus_len - hLen - 1); ) { |
|
151 out[y++] = DB[x++]; |
|
152 } |
|
153 |
15
|
154 /* valid packet */ |
|
155 *res = 1; |
|
156 |
143
|
157 err = CRYPT_OK; |
|
158 __ERR: |
|
159 #ifdef CLEAN_STACK |
|
160 zeromem(DB, modulus_len); |
|
161 zeromem(seed, modulus_len); |
|
162 zeromem(mask, modulus_len); |
|
163 #endif |
|
164 |
|
165 XFREE(seed); |
|
166 XFREE(mask); |
|
167 XFREE(DB); |
|
168 |
|
169 return err; |
3
|
170 } |
|
171 |
|
172 #endif /* PKCS_1 */ |