/src/hostap/src/tls/rsa.c
Line | Count | Source |
1 | | /* |
2 | | * RSA |
3 | | * Copyright (c) 2006-2014, Jouni Malinen <j@w1.fi> |
4 | | * |
5 | | * This software may be distributed under the terms of the BSD license. |
6 | | * See README for more details. |
7 | | */ |
8 | | |
9 | | #include "includes.h" |
10 | | |
11 | | #include "common.h" |
12 | | #include "asn1.h" |
13 | | #include "bignum.h" |
14 | | #include "rsa.h" |
15 | | |
16 | | |
17 | | struct crypto_rsa_key { |
18 | | int private_key; /* whether private key is set */ |
19 | | struct bignum *n; /* modulus (p * q) */ |
20 | | struct bignum *e; /* public exponent */ |
21 | | /* The following parameters are available only if private_key is set */ |
22 | | struct bignum *d; /* private exponent */ |
23 | | struct bignum *p; /* prime p (factor of n) */ |
24 | | struct bignum *q; /* prime q (factor of n) */ |
25 | | struct bignum *dmp1; /* d mod (p - 1); CRT exponent */ |
26 | | struct bignum *dmq1; /* d mod (q - 1); CRT exponent */ |
27 | | struct bignum *iqmp; /* 1 / q mod p; CRT coefficient */ |
28 | | }; |
29 | | |
30 | | |
31 | | static const u8 * crypto_rsa_parse_integer(const u8 *pos, const u8 *end, |
32 | | struct bignum *num) |
33 | 18 | { |
34 | 18 | struct asn1_hdr hdr; |
35 | | |
36 | 18 | if (pos == NULL) |
37 | 0 | return NULL; |
38 | | |
39 | 18 | if (asn1_get_next(pos, end - pos, &hdr) < 0 || |
40 | 18 | !asn1_is_integer(&hdr)) { |
41 | 0 | asn1_unexpected(&hdr, "RSA: Expected INTEGER"); |
42 | 0 | return NULL; |
43 | 0 | } |
44 | | |
45 | 18 | if (bignum_set_unsigned_bin(num, hdr.payload, hdr.length) < 0) { |
46 | 0 | wpa_printf(MSG_DEBUG, "RSA: Failed to parse INTEGER"); |
47 | 0 | return NULL; |
48 | 0 | } |
49 | | |
50 | 18 | return hdr.payload + hdr.length; |
51 | 18 | } |
52 | | |
53 | | |
54 | | /** |
55 | | * crypto_rsa_import_public_key - Import an RSA public key |
56 | | * @buf: Key buffer (DER encoded RSA public key) |
57 | | * @len: Key buffer length in bytes |
58 | | * Returns: Pointer to the public key or %NULL on failure |
59 | | */ |
60 | | struct crypto_rsa_key * |
61 | | crypto_rsa_import_public_key(const u8 *buf, size_t len) |
62 | 0 | { |
63 | 0 | struct crypto_rsa_key *key; |
64 | 0 | struct asn1_hdr hdr; |
65 | 0 | const u8 *pos, *end; |
66 | |
|
67 | 0 | key = os_zalloc(sizeof(*key)); |
68 | 0 | if (key == NULL) |
69 | 0 | return NULL; |
70 | | |
71 | 0 | key->n = bignum_init(); |
72 | 0 | key->e = bignum_init(); |
73 | 0 | if (key->n == NULL || key->e == NULL) { |
74 | 0 | crypto_rsa_free(key); |
75 | 0 | return NULL; |
76 | 0 | } |
77 | | |
78 | | /* |
79 | | * PKCS #1, 7.1: |
80 | | * RSAPublicKey ::= SEQUENCE { |
81 | | * modulus INTEGER, -- n |
82 | | * publicExponent INTEGER -- e |
83 | | * } |
84 | | */ |
85 | | |
86 | 0 | if (asn1_get_next(buf, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) { |
87 | 0 | asn1_unexpected(&hdr, "RSA: Expected SEQUENCE (public key)"); |
88 | 0 | goto error; |
89 | 0 | } |
90 | 0 | pos = hdr.payload; |
91 | 0 | end = pos + hdr.length; |
92 | |
|
93 | 0 | pos = crypto_rsa_parse_integer(pos, end, key->n); |
94 | 0 | pos = crypto_rsa_parse_integer(pos, end, key->e); |
95 | |
|
96 | 0 | if (pos == NULL) |
97 | 0 | goto error; |
98 | | |
99 | 0 | if (pos != end) { |
100 | 0 | wpa_hexdump(MSG_DEBUG, |
101 | 0 | "RSA: Extra data in public key SEQUENCE", |
102 | 0 | pos, end - pos); |
103 | 0 | goto error; |
104 | 0 | } |
105 | | |
106 | 0 | return key; |
107 | | |
108 | 0 | error: |
109 | 0 | crypto_rsa_free(key); |
110 | 0 | return NULL; |
111 | 0 | } |
112 | | |
113 | | |
114 | | struct crypto_rsa_key * |
115 | | crypto_rsa_import_public_key_parts(const u8 *n, size_t n_len, |
116 | | const u8 *e, size_t e_len) |
117 | 0 | { |
118 | 0 | struct crypto_rsa_key *key; |
119 | |
|
120 | 0 | key = os_zalloc(sizeof(*key)); |
121 | 0 | if (key == NULL) |
122 | 0 | return NULL; |
123 | | |
124 | 0 | key->n = bignum_init(); |
125 | 0 | key->e = bignum_init(); |
126 | 0 | if (key->n == NULL || key->e == NULL || |
127 | 0 | bignum_set_unsigned_bin(key->n, n, n_len) < 0 || |
128 | 0 | bignum_set_unsigned_bin(key->e, e, e_len) < 0) { |
129 | 0 | crypto_rsa_free(key); |
130 | 0 | return NULL; |
131 | 0 | } |
132 | | |
133 | 0 | return key; |
134 | 0 | } |
135 | | |
136 | | |
137 | | /** |
138 | | * crypto_rsa_import_private_key - Import an RSA private key |
139 | | * @buf: Key buffer (DER encoded RSA private key) |
140 | | * @len: Key buffer length in bytes |
141 | | * Returns: Pointer to the private key or %NULL on failure |
142 | | */ |
143 | | struct crypto_rsa_key * |
144 | | crypto_rsa_import_private_key(const u8 *buf, size_t len) |
145 | 4 | { |
146 | 4 | struct crypto_rsa_key *key; |
147 | 4 | struct bignum *zero; |
148 | 4 | struct asn1_hdr hdr; |
149 | 4 | const u8 *pos, *end; |
150 | | |
151 | 4 | key = os_zalloc(sizeof(*key)); |
152 | 4 | if (key == NULL) |
153 | 0 | return NULL; |
154 | | |
155 | 4 | key->private_key = 1; |
156 | | |
157 | 4 | key->n = bignum_init(); |
158 | 4 | key->e = bignum_init(); |
159 | 4 | key->d = bignum_init(); |
160 | 4 | key->p = bignum_init(); |
161 | 4 | key->q = bignum_init(); |
162 | 4 | key->dmp1 = bignum_init(); |
163 | 4 | key->dmq1 = bignum_init(); |
164 | 4 | key->iqmp = bignum_init(); |
165 | | |
166 | 4 | if (key->n == NULL || key->e == NULL || key->d == NULL || |
167 | 4 | key->p == NULL || key->q == NULL || key->dmp1 == NULL || |
168 | 4 | key->dmq1 == NULL || key->iqmp == NULL) { |
169 | 0 | crypto_rsa_free(key); |
170 | 0 | return NULL; |
171 | 0 | } |
172 | | |
173 | | /* |
174 | | * PKCS #1, 7.2: |
175 | | * RSAPrivateKey ::= SEQUENCE { |
176 | | * version Version, |
177 | | * modulus INTEGER, -- n |
178 | | * publicExponent INTEGER, -- e |
179 | | * privateExponent INTEGER, -- d |
180 | | * prime1 INTEGER, -- p |
181 | | * prime2 INTEGER, -- q |
182 | | * exponent1 INTEGER, -- d mod (p-1) |
183 | | * exponent2 INTEGER, -- d mod (q-1) |
184 | | * coefficient INTEGER -- (inverse of q) mod p |
185 | | * } |
186 | | * |
187 | | * Version ::= INTEGER -- shall be 0 for this version of the standard |
188 | | */ |
189 | 4 | if (asn1_get_next(buf, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) { |
190 | 2 | asn1_unexpected(&hdr, "RSA: Expected SEQUENCE (public key)"); |
191 | 2 | goto error; |
192 | 2 | } |
193 | 2 | pos = hdr.payload; |
194 | 2 | end = pos + hdr.length; |
195 | | |
196 | 2 | zero = bignum_init(); |
197 | 2 | if (zero == NULL) |
198 | 0 | goto error; |
199 | 2 | pos = crypto_rsa_parse_integer(pos, end, zero); |
200 | 2 | if (pos == NULL || bignum_cmp_d(zero, 0) != 0) { |
201 | 0 | wpa_printf(MSG_DEBUG, "RSA: Expected zero INTEGER in the " |
202 | 0 | "beginning of private key; not found"); |
203 | 0 | bignum_deinit(zero); |
204 | 0 | goto error; |
205 | 0 | } |
206 | 2 | bignum_deinit(zero); |
207 | | |
208 | 2 | pos = crypto_rsa_parse_integer(pos, end, key->n); |
209 | 2 | pos = crypto_rsa_parse_integer(pos, end, key->e); |
210 | 2 | pos = crypto_rsa_parse_integer(pos, end, key->d); |
211 | 2 | pos = crypto_rsa_parse_integer(pos, end, key->p); |
212 | 2 | pos = crypto_rsa_parse_integer(pos, end, key->q); |
213 | 2 | pos = crypto_rsa_parse_integer(pos, end, key->dmp1); |
214 | 2 | pos = crypto_rsa_parse_integer(pos, end, key->dmq1); |
215 | 2 | pos = crypto_rsa_parse_integer(pos, end, key->iqmp); |
216 | | |
217 | 2 | if (pos == NULL) |
218 | 0 | goto error; |
219 | | |
220 | 2 | if (pos != end) { |
221 | 0 | wpa_hexdump(MSG_DEBUG, |
222 | 0 | "RSA: Extra data in public key SEQUENCE", |
223 | 0 | pos, end - pos); |
224 | 0 | goto error; |
225 | 0 | } |
226 | | |
227 | 2 | return key; |
228 | | |
229 | 2 | error: |
230 | 2 | crypto_rsa_free(key); |
231 | 2 | return NULL; |
232 | 2 | } |
233 | | |
234 | | |
235 | | /** |
236 | | * crypto_rsa_get_modulus_len - Get the modulus length of the RSA key |
237 | | * @key: RSA key |
238 | | * Returns: Modulus length of the key |
239 | | */ |
240 | | size_t crypto_rsa_get_modulus_len(struct crypto_rsa_key *key) |
241 | 0 | { |
242 | 0 | return bignum_get_unsigned_bin_len(key->n); |
243 | 0 | } |
244 | | |
245 | | |
246 | | /** |
247 | | * crypto_rsa_exptmod - RSA modular exponentiation |
248 | | * @in: Input data |
249 | | * @inlen: Input data length |
250 | | * @out: Buffer for output data |
251 | | * @outlen: Maximum size of the output buffer and used size on success |
252 | | * @key: RSA key |
253 | | * @use_private: 1 = Use RSA private key, 0 = Use RSA public key |
254 | | * Returns: 0 on success, -1 on failure |
255 | | */ |
256 | | int crypto_rsa_exptmod(const u8 *in, size_t inlen, u8 *out, size_t *outlen, |
257 | | struct crypto_rsa_key *key, int use_private) |
258 | 0 | { |
259 | 0 | struct bignum *tmp, *a = NULL, *b = NULL; |
260 | 0 | int ret = -1; |
261 | 0 | size_t modlen; |
262 | |
|
263 | 0 | if (use_private && !key->private_key) |
264 | 0 | return -1; |
265 | | |
266 | 0 | tmp = bignum_init(); |
267 | 0 | if (tmp == NULL) |
268 | 0 | return -1; |
269 | | |
270 | 0 | if (bignum_set_unsigned_bin(tmp, in, inlen) < 0) |
271 | 0 | goto error; |
272 | 0 | if (bignum_cmp(key->n, tmp) < 0) { |
273 | | /* Too large input value for the RSA key modulus */ |
274 | 0 | goto error; |
275 | 0 | } |
276 | | |
277 | 0 | if (use_private) { |
278 | | /* |
279 | | * Decrypt (or sign) using Chinese remainder theorem to speed |
280 | | * up calculation. This is equivalent to tmp = tmp^d mod n |
281 | | * (which would require more CPU to calculate directly). |
282 | | * |
283 | | * dmp1 = (1/e) mod (p-1) |
284 | | * dmq1 = (1/e) mod (q-1) |
285 | | * iqmp = (1/q) mod p, where p > q |
286 | | * m1 = c^dmp1 mod p |
287 | | * m2 = c^dmq1 mod q |
288 | | * h = q^-1 (m1 - m2) mod p |
289 | | * m = m2 + hq |
290 | | */ |
291 | 0 | a = bignum_init(); |
292 | 0 | b = bignum_init(); |
293 | 0 | if (a == NULL || b == NULL) |
294 | 0 | goto error; |
295 | | |
296 | | /* a = tmp^dmp1 mod p */ |
297 | 0 | if (bignum_exptmod(tmp, key->dmp1, key->p, a) < 0) |
298 | 0 | goto error; |
299 | | |
300 | | /* b = tmp^dmq1 mod q */ |
301 | 0 | if (bignum_exptmod(tmp, key->dmq1, key->q, b) < 0) |
302 | 0 | goto error; |
303 | | |
304 | | /* tmp = (a - b) * (1/q mod p) (mod p) */ |
305 | 0 | if (bignum_sub(a, b, tmp) < 0 || |
306 | 0 | bignum_mulmod(tmp, key->iqmp, key->p, tmp) < 0) |
307 | 0 | goto error; |
308 | | |
309 | | /* tmp = b + q * tmp */ |
310 | 0 | if (bignum_mul(tmp, key->q, tmp) < 0 || |
311 | 0 | bignum_add(tmp, b, tmp) < 0) |
312 | 0 | goto error; |
313 | 0 | } else { |
314 | | /* Encrypt (or verify signature) */ |
315 | | /* tmp = tmp^e mod N */ |
316 | 0 | if (bignum_exptmod(tmp, key->e, key->n, tmp) < 0) |
317 | 0 | goto error; |
318 | 0 | } |
319 | | |
320 | 0 | modlen = crypto_rsa_get_modulus_len(key); |
321 | 0 | if (modlen > *outlen) { |
322 | 0 | *outlen = modlen; |
323 | 0 | goto error; |
324 | 0 | } |
325 | | |
326 | 0 | if (bignum_get_unsigned_bin_len(tmp) > modlen) |
327 | 0 | goto error; /* should never happen */ |
328 | | |
329 | 0 | *outlen = modlen; |
330 | 0 | os_memset(out, 0, modlen); |
331 | 0 | if (bignum_get_unsigned_bin( |
332 | 0 | tmp, out + |
333 | 0 | (modlen - bignum_get_unsigned_bin_len(tmp)), NULL) < 0) |
334 | 0 | goto error; |
335 | | |
336 | 0 | ret = 0; |
337 | |
|
338 | 0 | error: |
339 | 0 | bignum_deinit(tmp); |
340 | 0 | bignum_deinit(a); |
341 | 0 | bignum_deinit(b); |
342 | 0 | return ret; |
343 | 0 | } |
344 | | |
345 | | |
346 | | /** |
347 | | * crypto_rsa_free - Free RSA key |
348 | | * @key: RSA key to be freed |
349 | | * |
350 | | * This function frees an RSA key imported with either |
351 | | * crypto_rsa_import_public_key() or crypto_rsa_import_private_key(). |
352 | | */ |
353 | | void crypto_rsa_free(struct crypto_rsa_key *key) |
354 | 8 | { |
355 | 8 | if (key) { |
356 | 4 | bignum_deinit(key->n); |
357 | 4 | bignum_deinit(key->e); |
358 | 4 | bignum_deinit(key->d); |
359 | 4 | bignum_deinit(key->p); |
360 | 4 | bignum_deinit(key->q); |
361 | 4 | bignum_deinit(key->dmp1); |
362 | 4 | bignum_deinit(key->dmq1); |
363 | 4 | bignum_deinit(key->iqmp); |
364 | 4 | os_free(key); |
365 | 4 | } |
366 | 8 | } |