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 { |
|
23 unsigned char DB[1024], seed[MAXBLOCKSIZE], mask[sizeof(DB)]; |
|
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 |
|
42 /* test message size */ |
|
43 if (modulus_len >= sizeof(DB) || msglen != modulus_len) { |
|
44 return CRYPT_PK_INVALID_SIZE; |
|
45 } |
|
46 |
|
47 /* ok so it's now in the form |
|
48 |
|
49 0x00 || maskedseed || maskedDB |
|
50 |
|
51 1 || hLen || modulus_len - hLen - 1 |
|
52 |
|
53 */ |
|
54 |
|
55 /* must have leading 0x00 byte */ |
|
56 if (msg[0] != 0x00) { |
15
|
57 return CRYPT_OK; |
3
|
58 } |
|
59 |
|
60 /* now read the masked seed */ |
|
61 for (x = 1, y = 0; y < hLen; y++) { |
|
62 seed[y] = msg[x++]; |
|
63 } |
|
64 |
|
65 /* now read the masked DB */ |
|
66 for (y = 0; y < modulus_len - hLen - 1; y++) { |
|
67 DB[y] = msg[x++]; |
|
68 } |
|
69 |
|
70 /* compute MGF1 of maskedDB (hLen) */ |
|
71 if ((err = pkcs_1_mgf1(DB, modulus_len - hLen - 1, hash_idx, mask, hLen)) != CRYPT_OK) { |
|
72 return err; |
|
73 } |
|
74 |
|
75 /* XOR against seed */ |
|
76 for (y = 0; y < hLen; y++) { |
|
77 seed[y] ^= mask[y]; |
|
78 } |
|
79 |
|
80 /* compute MGF1 of seed (k - hlen - 1) */ |
|
81 if ((err = pkcs_1_mgf1(seed, 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 /* now DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */ |
|
91 |
|
92 /* compute lhash and store it in seed [reuse temps!] */ |
|
93 x = sizeof(seed); |
|
94 if (lparam != NULL) { |
|
95 if ((err = hash_memory(hash_idx, lparam, lparamlen, seed, &x)) != CRYPT_OK) { |
|
96 return err; |
|
97 } |
|
98 } else { |
|
99 /* can't pass hash_memory a NULL so use DB with zero length */ |
|
100 if ((err = hash_memory(hash_idx, DB, 0, seed, &x)) != CRYPT_OK) { |
|
101 return err; |
|
102 } |
|
103 } |
|
104 |
|
105 /* compare the lhash'es */ |
|
106 if (memcmp(seed, DB, hLen) != 0) { |
15
|
107 return CRYPT_OK; |
3
|
108 } |
|
109 |
|
110 /* now zeroes before a 0x01 */ |
|
111 for (x = hLen; x < (modulus_len - hLen - 1) && DB[x] == 0x00; x++) { |
|
112 /* step... */ |
|
113 } |
|
114 |
|
115 /* error out if wasn't 0x01 */ |
|
116 if (x == (modulus_len - hLen - 1) || DB[x] != 0x01) { |
15
|
117 return CRYPT_OK; |
3
|
118 } |
|
119 |
|
120 /* rest is the message (and skip 0x01) */ |
|
121 if (msglen - ++x > *outlen) { |
|
122 return CRYPT_BUFFER_OVERFLOW; |
|
123 } |
|
124 |
|
125 /* copy message */ |
|
126 *outlen = (modulus_len - hLen - 1) - x; |
|
127 for (y = 0; x != (modulus_len - hLen - 1); ) { |
|
128 out[y++] = DB[x++]; |
|
129 } |
|
130 |
|
131 #ifdef CLEAN_STACK |
|
132 zeromem(DB, sizeof(DB)); |
|
133 zeromem(seed, sizeof(seed)); |
|
134 zeromem(mask, sizeof(mask)); |
|
135 #endif |
|
136 |
15
|
137 /* valid packet */ |
|
138 *res = 1; |
|
139 |
3
|
140 return CRYPT_OK; |
|
141 } |
|
142 |
|
143 #endif /* PKCS_1 */ |