1
8
9
16
17
18
19
20
21
22
23
24
25
34
35
43
44
45
46
47
48
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
163
164
165
166
172
173
174
175
182
183
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
245
246
247
248
249
250
251
258
259
260
266
267
268
269
270
276
277
278
279
284
285
286
287
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
315
316
317
318
319
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
/* ... */
#include "includes.h"
#include "common.h"
#include "crypto/crypto.h"
#include "rsa.h"
#include "asn1.h"
#include "pkcs1.h"6 includes
static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen,
const u8 *in, size_t inlen,
u8 *out, size_t *outlen)
{
size_t ps_len;
u8 *pos;
/* ... */
if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) {
wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer "
"lengths (modlen=%lu outlen=%lu inlen=%lu)",
__func__, (unsigned long) modlen,
(unsigned long) *outlen,
(unsigned long) inlen);
return -1;
}{...}
pos = out;
*pos++ = 0x00;
*pos++ = block_type;
ps_len = modlen - inlen - 3;
switch (block_type) {
case 0:
os_memset(pos, 0x00, ps_len);
pos += ps_len;
break;...
case 1:
os_memset(pos, 0xff, ps_len);
pos += ps_len;
break;...
case 2:
if (os_get_random(pos, ps_len) < 0) {
wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get "
"random data for PS", __func__);
return -1;
}{...}
while (ps_len--) {
if (*pos == 0x00)
*pos = 0x01;
pos++;
}{...}
break;...
default:
wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type "
"%d", __func__, block_type);
return -1;...
}{...}
*pos++ = 0x00;
os_memcpy(pos, in, inlen);
return 0;
}{ ... }
int pkcs1_encrypt(int block_type, struct crypto_rsa_key *key,
int use_private, const u8 *in, size_t inlen,
u8 *out, size_t *outlen)
{
size_t modlen;
modlen = crypto_rsa_get_modulus_len(key);
if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen,
out, outlen) < 0)
return -1;
return crypto_rsa_exptmod(out, modlen, out, outlen, key, use_private);
}{ ... }
int pkcs1_v15_private_key_decrypt(struct crypto_rsa_key *key,
const u8 *in, size_t inlen,
u8 *out, size_t *outlen)
{
int res;
u8 *pos, *end;
res = crypto_rsa_exptmod(in, inlen, out, outlen, key, 1);
if (res)
return res;
if (*outlen < 2 || out[0] != 0 || out[1] != 2)
return -1;
pos = out + 2;
end = out + *outlen;
while (*pos && pos < end)
pos++;
if (pos == end)
return -1;
if (pos - out - 2 < 8) {
wpa_printf(MSG_INFO, "LibTomCrypt: Too short padding");
return -1;
}{...}
pos++;
*outlen -= pos - out;
os_memmove(out, pos, *outlen);
return 0;
}{ ... }
int pkcs1_decrypt_public_key(struct crypto_rsa_key *key,
const u8 *crypt, size_t crypt_len,
u8 *plain, size_t *plain_len)
{
size_t len;
u8 *pos;
len = *plain_len;
if (crypto_rsa_exptmod(crypt, crypt_len, plain, &len, key, 0) < 0)
return -1;
/* ... */
if (len < 3 + 8 + 16 ||
plain[0] != 0x00 || plain[1] != 0x01) {
wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
"structure");
wpa_hexdump_key(MSG_DEBUG, "Signature EB", plain, len);
return -1;
}{...}
pos = plain + 3;
if (plain[2] != 0xff) {
wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature "
"PS (BT=01)");
wpa_hexdump_key(MSG_DEBUG, "Signature EB", plain, len);
return -1;
}{...}
while (pos < plain + len && *pos == 0xff)
pos++;
if (pos - plain - 2 < 8) {
wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature "
"padding");
wpa_hexdump_key(MSG_DEBUG, "Signature EB", plain, len);
return -1;
}{...}
if (pos + 16 >= plain + len || *pos != 0x00) {
wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
"structure (2)");
wpa_hexdump_key(MSG_DEBUG, "Signature EB", plain, len);
return -1;
}{...}
pos++;
len -= pos - plain;
os_memmove(plain, pos, len);
*plain_len = len;
return 0;
}{ ... }
int pkcs1_v15_sig_ver(struct crypto_public_key *pk,
const u8 *s, size_t s_len,
const struct asn1_oid *hash_alg,
const u8 *hash, size_t hash_len)
{
int res;
u8 *decrypted;
size_t decrypted_len;
const u8 *pos, *end, *next, *da_end;
struct asn1_hdr hdr;
struct asn1_oid oid;
decrypted = os_malloc(s_len);
if (decrypted == NULL)
return -1;
decrypted_len = s_len;
res = crypto_public_key_decrypt_pkcs1(pk, s, s_len, decrypted,
&decrypted_len);
if (res < 0) {
wpa_printf(MSG_INFO, "PKCS #1: RSA decrypt failed");
os_free(decrypted);
return -1;
}{...}
wpa_hexdump(MSG_DEBUG, "Decrypted(S)", decrypted, decrypted_len);
/* ... */
if (asn1_get_next(decrypted, decrypted_len, &hdr) < 0 ||
!asn1_is_sequence(&hdr)) {
asn1_unexpected(&hdr,
"PKCS #1: Expected SEQUENCE (DigestInfo)");
os_free(decrypted);
return -1;
}{...}
wpa_hexdump(MSG_MSGDUMP, "PKCS #1: DigestInfo",
hdr.payload, hdr.length);
pos = hdr.payload;
end = pos + hdr.length;
/* ... */
if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
!asn1_is_sequence(&hdr)) {
asn1_unexpected(&hdr,
"PKCS #1: Expected SEQUENCE (AlgorithmIdentifier)");
os_free(decrypted);
return -1;
}{...}
wpa_hexdump(MSG_MSGDUMP, "PKCS #1: DigestAlgorithmIdentifier",
hdr.payload, hdr.length);
da_end = hdr.payload + hdr.length;
if (asn1_get_oid(hdr.payload, hdr.length, &oid, &next)) {
wpa_printf(MSG_DEBUG,
"PKCS #1: Failed to parse digestAlgorithm");
os_free(decrypted);
return -1;
}{...}
wpa_hexdump(MSG_MSGDUMP, "PKCS #1: Digest algorithm parameters",
next, da_end - next);
/* ... */
if (da_end > next &&
(asn1_get_next(next, da_end - next, &hdr) < 0 ||
!asn1_is_null(&hdr) ||
hdr.payload + hdr.length != da_end)) {
wpa_printf(MSG_DEBUG,
"PKCS #1: Unexpected digest algorithm parameters");
os_free(decrypted);
return -1;
}{...}
if (!asn1_oid_equal(&oid, hash_alg)) {
char txt[100], txt2[100];
asn1_oid_to_str(&oid, txt, sizeof(txt));
asn1_oid_to_str(hash_alg, txt2, sizeof(txt2));
wpa_printf(MSG_DEBUG,
"PKCS #1: Hash alg OID mismatch: was %s, expected %s",
txt, txt2);
os_free(decrypted);
return -1;
}{...}
pos = da_end;
if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
!asn1_is_octetstring(&hdr)) {
asn1_unexpected(&hdr,
"PKCS #1: Expected OCTETSTRING (Digest)");
os_free(decrypted);
return -1;
}{...}
wpa_hexdump(MSG_MSGDUMP, "PKCS #1: Decrypted Digest",
hdr.payload, hdr.length);
if (hdr.length != hash_len ||
os_memcmp_const(hdr.payload, hash, hdr.length) != 0) {
wpa_printf(MSG_INFO, "PKCS #1: Digest value does not match calculated hash");
os_free(decrypted);
return -1;
}{...}
if (hdr.payload + hdr.length != decrypted + decrypted_len) {
wpa_printf(MSG_INFO,
"PKCS #1: Extra data after signature - reject");
wpa_hexdump(MSG_DEBUG, "PKCS #1: Extra data",
hdr.payload + hdr.length,
decrypted + decrypted_len - hdr.payload -
hdr.length);
os_free(decrypted);
return -1;
}{...}
os_free(decrypted);
return 0;
}{ ... }