/src/samba/third_party/heimdal/lib/hcrypto/rsa.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan |
3 | | * (Royal Institute of Technology, Stockholm, Sweden). |
4 | | * All rights reserved. |
5 | | * |
6 | | * Redistribution and use in source and binary forms, with or without |
7 | | * modification, are permitted provided that the following conditions |
8 | | * are met: |
9 | | * |
10 | | * 1. Redistributions of source code must retain the above copyright |
11 | | * notice, this list of conditions and the following disclaimer. |
12 | | * |
13 | | * 2. Redistributions in binary form must reproduce the above copyright |
14 | | * notice, this list of conditions and the following disclaimer in the |
15 | | * documentation and/or other materials provided with the distribution. |
16 | | * |
17 | | * 3. Neither the name of the Institute nor the names of its contributors |
18 | | * may be used to endorse or promote products derived from this software |
19 | | * without specific prior written permission. |
20 | | * |
21 | | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND |
22 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
23 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
24 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE |
25 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
26 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
27 | | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
28 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
29 | | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
30 | | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
31 | | * SUCH DAMAGE. |
32 | | */ |
33 | | |
34 | | #include <config.h> |
35 | | #include <roken.h> |
36 | | #include <krb5-types.h> |
37 | | #include <rfc2459_asn1.h> |
38 | | |
39 | | #include <der.h> |
40 | | |
41 | | #include <rsa.h> |
42 | | |
43 | | #include "common.h" |
44 | | |
45 | | /** |
46 | | * @page page_rsa RSA - public-key cryptography |
47 | | * |
48 | | * RSA is named by its inventors (Ron Rivest, Adi Shamir, and Leonard |
49 | | * Adleman) (published in 1977), patented expired in 21 September 2000. |
50 | | * |
51 | | * |
52 | | * Speed for RSA in seconds |
53 | | * no key blinding |
54 | | * 1000 iteration, |
55 | | * same rsa keys (1024 and 2048) |
56 | | * operation performed each eteration sign, verify, encrypt, decrypt on a random bit pattern |
57 | | * |
58 | | * name 1024 2048 4098 |
59 | | * ================================= |
60 | | * gmp: 0.73 6.60 44.80 |
61 | | * tfm: 2.45 -- -- |
62 | | * ltm: 3.79 20.74 105.41 (default in hcrypto) |
63 | | * openssl: 4.04 11.90 82.59 |
64 | | * cdsa: 15.89 102.89 721.40 |
65 | | * imath: 40.62 -- -- |
66 | | * |
67 | | * See the library functions here: @ref hcrypto_rsa |
68 | | */ |
69 | | |
70 | | /** |
71 | | * Same as RSA_new_method() using NULL as engine. |
72 | | * |
73 | | * @return a newly allocated RSA object. Free with RSA_free(). |
74 | | * |
75 | | * @ingroup hcrypto_rsa |
76 | | */ |
77 | | |
78 | | RSA * |
79 | | RSA_new(void) |
80 | 0 | { |
81 | 0 | return RSA_new_method(NULL); |
82 | 0 | } |
83 | | |
84 | | /** |
85 | | * Allocate a new RSA object using the engine, if NULL is specified as |
86 | | * the engine, use the default RSA engine as returned by |
87 | | * ENGINE_get_default_RSA(). |
88 | | * |
89 | | * @param engine Specific what ENGINE RSA provider should be used. |
90 | | * |
91 | | * @return a newly allocated RSA object. Free with RSA_free(). |
92 | | * |
93 | | * @ingroup hcrypto_rsa |
94 | | */ |
95 | | |
96 | | RSA * |
97 | | RSA_new_method(ENGINE *engine) |
98 | 0 | { |
99 | 0 | RSA *rsa; |
100 | |
|
101 | 0 | rsa = calloc(1, sizeof(*rsa)); |
102 | 0 | if (rsa == NULL) |
103 | 0 | return NULL; |
104 | | |
105 | 0 | rsa->references = 1; |
106 | |
|
107 | 0 | if (engine) { |
108 | 0 | ENGINE_up_ref(engine); |
109 | 0 | rsa->engine = engine; |
110 | 0 | } else { |
111 | 0 | rsa->engine = ENGINE_get_default_RSA(); |
112 | 0 | } |
113 | |
|
114 | 0 | if (rsa->engine) { |
115 | 0 | rsa->meth = ENGINE_get_RSA(rsa->engine); |
116 | 0 | if (rsa->meth == NULL) { |
117 | 0 | ENGINE_finish(rsa->engine); |
118 | 0 | free(rsa); |
119 | 0 | return 0; |
120 | 0 | } |
121 | 0 | } |
122 | | |
123 | 0 | if (rsa->meth == NULL) |
124 | 0 | rsa->meth = rk_UNCONST(RSA_get_default_method()); |
125 | |
|
126 | 0 | (*rsa->meth->init)(rsa); |
127 | |
|
128 | 0 | return rsa; |
129 | 0 | } |
130 | | |
131 | | /** |
132 | | * Free an allocation RSA object. |
133 | | * |
134 | | * @param rsa the RSA object to free. |
135 | | * @ingroup hcrypto_rsa |
136 | | */ |
137 | | |
138 | | void |
139 | | RSA_free(RSA *rsa) |
140 | 0 | { |
141 | 0 | if (rsa->references <= 0) |
142 | 0 | abort(); |
143 | | |
144 | 0 | if (--rsa->references > 0) |
145 | 0 | return; |
146 | | |
147 | 0 | (*rsa->meth->finish)(rsa); |
148 | |
|
149 | 0 | if (rsa->engine) |
150 | 0 | ENGINE_finish(rsa->engine); |
151 | |
|
152 | 0 | #define free_if(f) if (f) { BN_free(f); } |
153 | 0 | free_if(rsa->n); |
154 | 0 | free_if(rsa->e); |
155 | 0 | free_if(rsa->d); |
156 | 0 | free_if(rsa->p); |
157 | 0 | free_if(rsa->q); |
158 | 0 | free_if(rsa->dmp1); |
159 | 0 | free_if(rsa->dmq1); |
160 | 0 | free_if(rsa->iqmp); |
161 | 0 | #undef free_if |
162 | |
|
163 | 0 | memset_s(rsa, sizeof(*rsa), 0, sizeof(*rsa)); |
164 | 0 | free(rsa); |
165 | 0 | } |
166 | | |
167 | | /** |
168 | | * Add an extra reference to the RSA object. The object should be free |
169 | | * with RSA_free() to drop the reference. |
170 | | * |
171 | | * @param rsa the object to add reference counting too. |
172 | | * |
173 | | * @return the current reference count, can't safely be used except |
174 | | * for debug printing. |
175 | | * |
176 | | * @ingroup hcrypto_rsa |
177 | | */ |
178 | | |
179 | | int |
180 | | RSA_up_ref(RSA *rsa) |
181 | 0 | { |
182 | 0 | return ++rsa->references; |
183 | 0 | } |
184 | | |
185 | | /** |
186 | | * Return the RSA_METHOD used for this RSA object. |
187 | | * |
188 | | * @param rsa the object to get the method from. |
189 | | * |
190 | | * @return the method used for this RSA object. |
191 | | * |
192 | | * @ingroup hcrypto_rsa |
193 | | */ |
194 | | |
195 | | const RSA_METHOD * |
196 | | RSA_get_method(const RSA *rsa) |
197 | 0 | { |
198 | 0 | return rsa->meth; |
199 | 0 | } |
200 | | |
201 | | /** |
202 | | * Set a new method for the RSA keypair. |
203 | | * |
204 | | * @param rsa rsa parameter. |
205 | | * @param method the new method for the RSA parameter. |
206 | | * |
207 | | * @return 1 on success. |
208 | | * |
209 | | * @ingroup hcrypto_rsa |
210 | | */ |
211 | | |
212 | | int |
213 | | RSA_set_method(RSA *rsa, const RSA_METHOD *method) |
214 | 0 | { |
215 | 0 | (*rsa->meth->finish)(rsa); |
216 | |
|
217 | 0 | if (rsa->engine) { |
218 | 0 | ENGINE_finish(rsa->engine); |
219 | 0 | rsa->engine = NULL; |
220 | 0 | } |
221 | |
|
222 | 0 | rsa->meth = method; |
223 | 0 | (*rsa->meth->init)(rsa); |
224 | 0 | return 1; |
225 | 0 | } |
226 | | |
227 | | /** |
228 | | * Set the application data for the RSA object. |
229 | | * |
230 | | * @param rsa the rsa object to set the parameter for |
231 | | * @param arg the data object to store |
232 | | * |
233 | | * @return 1 on success. |
234 | | * |
235 | | * @ingroup hcrypto_rsa |
236 | | */ |
237 | | |
238 | | int |
239 | | RSA_set_app_data(RSA *rsa, void *arg) |
240 | 0 | { |
241 | 0 | rsa->ex_data.sk = arg; |
242 | 0 | return 1; |
243 | 0 | } |
244 | | |
245 | | /** |
246 | | * Get the application data for the RSA object. |
247 | | * |
248 | | * @param rsa the rsa object to get the parameter for |
249 | | * |
250 | | * @return the data object |
251 | | * |
252 | | * @ingroup hcrypto_rsa |
253 | | */ |
254 | | |
255 | | void * |
256 | | RSA_get_app_data(const RSA *rsa) |
257 | 0 | { |
258 | 0 | return rsa->ex_data.sk; |
259 | 0 | } |
260 | | |
261 | | int |
262 | | RSA_check_key(const RSA *key) |
263 | 0 | { |
264 | 0 | static const unsigned char inbuf[] = "hello, world!"; |
265 | 0 | RSA *rsa = rk_UNCONST(key); |
266 | 0 | void *buffer; |
267 | 0 | int ret; |
268 | | |
269 | | /* |
270 | | * XXX I have no clue how to implement this w/o a bignum library. |
271 | | * Well, when we have a RSA key pair, we can try to encrypt/sign |
272 | | * and then decrypt/verify. |
273 | | */ |
274 | |
|
275 | 0 | if (rsa->n == NULL) |
276 | 0 | return 0; |
277 | | |
278 | 0 | if (rsa->d == NULL && |
279 | 0 | (rsa->p == NULL || rsa->q || rsa->dmp1 == NULL || rsa->dmq1 == NULL || rsa->iqmp == NULL)) |
280 | 0 | return 0; |
281 | | |
282 | 0 | buffer = malloc(RSA_size(rsa)); |
283 | 0 | if (buffer == NULL) |
284 | 0 | return 0; |
285 | | |
286 | 0 | ret = RSA_private_encrypt(sizeof(inbuf), inbuf, buffer, |
287 | 0 | rsa, RSA_PKCS1_PADDING); |
288 | 0 | if (ret == -1) { |
289 | 0 | free(buffer); |
290 | 0 | return 0; |
291 | 0 | } |
292 | | |
293 | 0 | ret = RSA_public_decrypt(ret, buffer, buffer, |
294 | 0 | rsa, RSA_PKCS1_PADDING); |
295 | 0 | if (ret == -1) { |
296 | 0 | free(buffer); |
297 | 0 | return 0; |
298 | 0 | } |
299 | | |
300 | 0 | if (ret == sizeof(inbuf) && ct_memcmp(buffer, inbuf, sizeof(inbuf)) == 0) { |
301 | 0 | free(buffer); |
302 | 0 | return 1; |
303 | 0 | } |
304 | 0 | free(buffer); |
305 | 0 | return 0; |
306 | 0 | } |
307 | | |
308 | | int |
309 | | RSA_size(const RSA *rsa) |
310 | 0 | { |
311 | 0 | return BN_num_bytes(rsa->n); |
312 | 0 | } |
313 | | |
314 | | #define RSAFUNC(name, body) \ |
315 | | int \ |
316 | 0 | name(int flen,const unsigned char* f, unsigned char* t, RSA* r, int p){\ |
317 | 0 | return body; \ |
318 | 0 | } Unexecuted instantiation: hc_RSA_public_encrypt Unexecuted instantiation: hc_RSA_public_decrypt Unexecuted instantiation: hc_RSA_private_encrypt Unexecuted instantiation: hc_RSA_private_decrypt Unexecuted instantiation: rsa.c:null_rsa_public_encrypt Unexecuted instantiation: rsa.c:null_rsa_public_decrypt Unexecuted instantiation: rsa.c:null_rsa_private_encrypt Unexecuted instantiation: rsa.c:null_rsa_private_decrypt |
319 | | |
320 | | RSAFUNC(RSA_public_encrypt, (r)->meth->rsa_pub_enc(flen, f, t, r, p)) |
321 | | RSAFUNC(RSA_public_decrypt, (r)->meth->rsa_pub_dec(flen, f, t, r, p)) |
322 | | RSAFUNC(RSA_private_encrypt, (r)->meth->rsa_priv_enc(flen, f, t, r, p)) |
323 | | RSAFUNC(RSA_private_decrypt, (r)->meth->rsa_priv_dec(flen, f, t, r, p)) |
324 | | |
325 | | static const heim_octet_string null_entry_oid = { 2, rk_UNCONST("\x05\x00") }; |
326 | | |
327 | | static const unsigned sha1_oid_tree[] = { 1, 3, 14, 3, 2, 26 }; |
328 | | static const AlgorithmIdentifier _signature_sha1_data = { |
329 | | { 6, rk_UNCONST(sha1_oid_tree) }, rk_UNCONST(&null_entry_oid) |
330 | | }; |
331 | | static const unsigned sha256_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 1 }; |
332 | | static const AlgorithmIdentifier _signature_sha256_data = { |
333 | | { 9, rk_UNCONST(sha256_oid_tree) }, rk_UNCONST(&null_entry_oid) |
334 | | }; |
335 | | static const unsigned md5_oid_tree[] = { 1, 2, 840, 113549, 2, 5 }; |
336 | | static const AlgorithmIdentifier _signature_md5_data = { |
337 | | { 6, rk_UNCONST(md5_oid_tree) }, rk_UNCONST(&null_entry_oid) |
338 | | }; |
339 | | |
340 | | |
341 | | int |
342 | | RSA_sign(int type, const unsigned char *from, unsigned int flen, |
343 | | unsigned char *to, unsigned int *tlen, RSA *rsa) |
344 | 0 | { |
345 | 0 | if (rsa->meth->rsa_sign) |
346 | 0 | return rsa->meth->rsa_sign(type, from, flen, to, tlen, rsa); |
347 | | |
348 | 0 | if (rsa->meth->rsa_priv_enc) { |
349 | 0 | heim_octet_string indata; |
350 | 0 | DigestInfo di; |
351 | 0 | size_t size; |
352 | 0 | int ret; |
353 | |
|
354 | 0 | memset(&di, 0, sizeof(di)); |
355 | |
|
356 | 0 | if (type == NID_sha1) { |
357 | 0 | di.digestAlgorithm = _signature_sha1_data; |
358 | 0 | } else if (type == NID_md5) { |
359 | 0 | di.digestAlgorithm = _signature_md5_data; |
360 | 0 | } else if (type == NID_sha256) { |
361 | 0 | di.digestAlgorithm = _signature_sha256_data; |
362 | 0 | } else |
363 | 0 | return -1; |
364 | | |
365 | 0 | di.digest.data = rk_UNCONST(from); |
366 | 0 | di.digest.length = flen; |
367 | |
|
368 | 0 | ASN1_MALLOC_ENCODE(DigestInfo, |
369 | 0 | indata.data, |
370 | 0 | indata.length, |
371 | 0 | &di, |
372 | 0 | &size, |
373 | 0 | ret); |
374 | 0 | if (ret) |
375 | 0 | return ret; |
376 | 0 | if (indata.length != size) |
377 | 0 | abort(); |
378 | | |
379 | 0 | ret = rsa->meth->rsa_priv_enc(indata.length, indata.data, to, |
380 | 0 | rsa, RSA_PKCS1_PADDING); |
381 | 0 | free(indata.data); |
382 | 0 | if (ret > 0) { |
383 | 0 | *tlen = ret; |
384 | 0 | ret = 1; |
385 | 0 | } else |
386 | 0 | ret = 0; |
387 | |
|
388 | 0 | return ret; |
389 | 0 | } |
390 | | |
391 | 0 | return 0; |
392 | 0 | } |
393 | | |
394 | | int |
395 | | RSA_verify(int type, const unsigned char *from, unsigned int flen, |
396 | | unsigned char *sigbuf, unsigned int siglen, RSA *rsa) |
397 | 0 | { |
398 | 0 | if (rsa->meth->rsa_verify) |
399 | 0 | return rsa->meth->rsa_verify(type, from, flen, sigbuf, siglen, rsa); |
400 | | |
401 | 0 | if (rsa->meth->rsa_pub_dec) { |
402 | 0 | const AlgorithmIdentifier *digest_alg; |
403 | 0 | void *data; |
404 | 0 | DigestInfo di; |
405 | 0 | size_t size; |
406 | 0 | int ret, ret2; |
407 | |
|
408 | 0 | data = malloc(RSA_size(rsa)); |
409 | 0 | if (data == NULL) |
410 | 0 | return -1; |
411 | | |
412 | 0 | memset(&di, 0, sizeof(di)); |
413 | |
|
414 | 0 | ret = rsa->meth->rsa_pub_dec(siglen, sigbuf, data, rsa, RSA_PKCS1_PADDING); |
415 | 0 | if (ret <= 0) { |
416 | 0 | free(data); |
417 | 0 | return -2; |
418 | 0 | } |
419 | | |
420 | 0 | ret2 = decode_DigestInfo(data, ret, &di, &size); |
421 | 0 | free(data); |
422 | 0 | if (ret2 != 0) |
423 | 0 | return -3; |
424 | 0 | if (ret != size) { |
425 | 0 | free_DigestInfo(&di); |
426 | 0 | return -4; |
427 | 0 | } |
428 | | |
429 | 0 | if (flen != di.digest.length || ct_memcmp(di.digest.data, from, flen) != 0) { |
430 | 0 | free_DigestInfo(&di); |
431 | 0 | return -5; |
432 | 0 | } |
433 | | |
434 | 0 | if (type == NID_sha1) { |
435 | 0 | digest_alg = &_signature_sha1_data; |
436 | 0 | } else if (type == NID_md5) { |
437 | 0 | digest_alg = &_signature_md5_data; |
438 | 0 | } else if (type == NID_sha256) { |
439 | 0 | digest_alg = &_signature_sha256_data; |
440 | 0 | } else { |
441 | 0 | free_DigestInfo(&di); |
442 | 0 | return -1; |
443 | 0 | } |
444 | | |
445 | 0 | ret = der_heim_oid_cmp(&digest_alg->algorithm, |
446 | 0 | &di.digestAlgorithm.algorithm); |
447 | 0 | free_DigestInfo(&di); |
448 | |
|
449 | 0 | if (ret != 0) |
450 | 0 | return 0; |
451 | 0 | return 1; |
452 | 0 | } |
453 | | |
454 | 0 | return 0; |
455 | 0 | } |
456 | | |
457 | | /* |
458 | | * A NULL RSA_METHOD that returns failure for all operations. This is |
459 | | * used as the default RSA method if we don't have any native |
460 | | * support. |
461 | | */ |
462 | | |
463 | | static RSAFUNC(null_rsa_public_encrypt, -1) |
464 | | static RSAFUNC(null_rsa_public_decrypt, -1) |
465 | | static RSAFUNC(null_rsa_private_encrypt, -1) |
466 | | static RSAFUNC(null_rsa_private_decrypt, -1) |
467 | | |
468 | | /* |
469 | | * |
470 | | */ |
471 | | |
472 | | int |
473 | | RSA_generate_key_ex(RSA *r, int bits, BIGNUM *e, BN_GENCB *cb) |
474 | 0 | { |
475 | 0 | if (r->meth->rsa_keygen) |
476 | 0 | return (*r->meth->rsa_keygen)(r, bits, e, cb); |
477 | 0 | return 0; |
478 | 0 | } |
479 | | |
480 | | |
481 | | /* |
482 | | * |
483 | | */ |
484 | | |
485 | | static int |
486 | | null_rsa_init(RSA *rsa) |
487 | 0 | { |
488 | 0 | return 1; |
489 | 0 | } |
490 | | |
491 | | static int |
492 | | null_rsa_finish(RSA *rsa) |
493 | 0 | { |
494 | 0 | return 1; |
495 | 0 | } |
496 | | |
497 | | static const RSA_METHOD rsa_null_method = { |
498 | | "hcrypto null RSA", |
499 | | null_rsa_public_encrypt, |
500 | | null_rsa_public_decrypt, |
501 | | null_rsa_private_encrypt, |
502 | | null_rsa_private_decrypt, |
503 | | NULL, |
504 | | NULL, |
505 | | null_rsa_init, |
506 | | null_rsa_finish, |
507 | | 0, |
508 | | NULL, |
509 | | NULL, |
510 | | NULL, |
511 | | NULL |
512 | | }; |
513 | | |
514 | | const RSA_METHOD * |
515 | | RSA_null_method(void) |
516 | 0 | { |
517 | 0 | return &rsa_null_method; |
518 | 0 | } |
519 | | |
520 | | extern const RSA_METHOD hc_rsa_gmp_method; |
521 | | extern const RSA_METHOD hc_rsa_tfm_method; |
522 | | extern const RSA_METHOD hc_rsa_ltm_method; |
523 | | static const RSA_METHOD *default_rsa_method = &hc_rsa_ltm_method; |
524 | | |
525 | | |
526 | | const RSA_METHOD * |
527 | | RSA_get_default_method(void) |
528 | 0 | { |
529 | 0 | return default_rsa_method; |
530 | 0 | } |
531 | | |
532 | | void |
533 | | RSA_set_default_method(const RSA_METHOD *meth) |
534 | 0 | { |
535 | 0 | default_rsa_method = meth; |
536 | 0 | } |
537 | | |
538 | | /* |
539 | | * |
540 | | */ |
541 | | |
542 | | RSA * |
543 | | d2i_RSAPrivateKey(RSA *rsa, const unsigned char **pp, size_t len) |
544 | 0 | { |
545 | 0 | RSAPrivateKey data; |
546 | 0 | RSA *k = rsa; |
547 | 0 | size_t size; |
548 | 0 | int ret; |
549 | |
|
550 | 0 | ret = decode_RSAPrivateKey(*pp, len, &data, &size); |
551 | 0 | if (ret) |
552 | 0 | return NULL; |
553 | | |
554 | 0 | *pp += size; |
555 | |
|
556 | 0 | if (k == NULL) { |
557 | 0 | k = RSA_new(); |
558 | 0 | if (k == NULL) { |
559 | 0 | free_RSAPrivateKey(&data); |
560 | 0 | return NULL; |
561 | 0 | } |
562 | 0 | } |
563 | | |
564 | 0 | k->n = _hc_integer_to_BN(&data.modulus, NULL); |
565 | 0 | k->e = _hc_integer_to_BN(&data.publicExponent, NULL); |
566 | 0 | k->d = _hc_integer_to_BN(&data.privateExponent, NULL); |
567 | 0 | k->p = _hc_integer_to_BN(&data.prime1, NULL); |
568 | 0 | k->q = _hc_integer_to_BN(&data.prime2, NULL); |
569 | 0 | k->dmp1 = _hc_integer_to_BN(&data.exponent1, NULL); |
570 | 0 | k->dmq1 = _hc_integer_to_BN(&data.exponent2, NULL); |
571 | 0 | k->iqmp = _hc_integer_to_BN(&data.coefficient, NULL); |
572 | 0 | free_RSAPrivateKey(&data); |
573 | |
|
574 | 0 | if (k->n == NULL || k->e == NULL || k->d == NULL || k->p == NULL || |
575 | 0 | k->q == NULL || k->dmp1 == NULL || k->dmq1 == NULL || k->iqmp == NULL) |
576 | 0 | { |
577 | 0 | RSA_free(k); |
578 | 0 | return NULL; |
579 | 0 | } |
580 | | |
581 | 0 | return k; |
582 | 0 | } |
583 | | |
584 | | int |
585 | | i2d_RSAPrivateKey(RSA *rsa, unsigned char **pp) |
586 | 0 | { |
587 | 0 | RSAPrivateKey data; |
588 | 0 | size_t size; |
589 | 0 | int ret; |
590 | |
|
591 | 0 | if (rsa->n == NULL || rsa->e == NULL || rsa->d == NULL || rsa->p == NULL || |
592 | 0 | rsa->q == NULL || rsa->dmp1 == NULL || rsa->dmq1 == NULL || |
593 | 0 | rsa->iqmp == NULL) |
594 | 0 | return -1; |
595 | | |
596 | 0 | memset(&data, 0, sizeof(data)); |
597 | |
|
598 | 0 | ret = _hc_BN_to_integer(rsa->n, &data.modulus); |
599 | 0 | ret |= _hc_BN_to_integer(rsa->e, &data.publicExponent); |
600 | 0 | ret |= _hc_BN_to_integer(rsa->d, &data.privateExponent); |
601 | 0 | ret |= _hc_BN_to_integer(rsa->p, &data.prime1); |
602 | 0 | ret |= _hc_BN_to_integer(rsa->q, &data.prime2); |
603 | 0 | ret |= _hc_BN_to_integer(rsa->dmp1, &data.exponent1); |
604 | 0 | ret |= _hc_BN_to_integer(rsa->dmq1, &data.exponent2); |
605 | 0 | ret |= _hc_BN_to_integer(rsa->iqmp, &data.coefficient); |
606 | 0 | if (ret) { |
607 | 0 | free_RSAPrivateKey(&data); |
608 | 0 | return -1; |
609 | 0 | } |
610 | | |
611 | 0 | if (pp == NULL) { |
612 | 0 | size = length_RSAPrivateKey(&data); |
613 | 0 | free_RSAPrivateKey(&data); |
614 | 0 | } else { |
615 | 0 | void *p; |
616 | 0 | size_t len; |
617 | |
|
618 | 0 | ASN1_MALLOC_ENCODE(RSAPrivateKey, p, len, &data, &size, ret); |
619 | 0 | free_RSAPrivateKey(&data); |
620 | 0 | if (ret) |
621 | 0 | return -1; |
622 | 0 | if (len != size) |
623 | 0 | abort(); |
624 | | |
625 | 0 | memcpy(*pp, p, size); |
626 | 0 | free(p); |
627 | |
|
628 | 0 | *pp += size; |
629 | |
|
630 | 0 | } |
631 | 0 | return size; |
632 | 0 | } |
633 | | |
634 | | int |
635 | | i2d_RSAPublicKey(RSA *rsa, unsigned char **pp) |
636 | 0 | { |
637 | 0 | RSAPublicKey data; |
638 | 0 | size_t size; |
639 | 0 | int ret; |
640 | |
|
641 | 0 | memset(&data, 0, sizeof(data)); |
642 | |
|
643 | 0 | if (_hc_BN_to_integer(rsa->n, &data.modulus) || |
644 | 0 | _hc_BN_to_integer(rsa->e, &data.publicExponent)) |
645 | 0 | { |
646 | 0 | free_RSAPublicKey(&data); |
647 | 0 | return -1; |
648 | 0 | } |
649 | | |
650 | 0 | if (pp == NULL) { |
651 | 0 | size = length_RSAPublicKey(&data); |
652 | 0 | free_RSAPublicKey(&data); |
653 | 0 | } else { |
654 | 0 | void *p; |
655 | 0 | size_t len; |
656 | |
|
657 | 0 | ASN1_MALLOC_ENCODE(RSAPublicKey, p, len, &data, &size, ret); |
658 | 0 | free_RSAPublicKey(&data); |
659 | 0 | if (ret) |
660 | 0 | return -1; |
661 | 0 | if (len != size) |
662 | 0 | abort(); |
663 | | |
664 | 0 | memcpy(*pp, p, size); |
665 | 0 | free(p); |
666 | |
|
667 | 0 | *pp += size; |
668 | 0 | } |
669 | | |
670 | 0 | return size; |
671 | 0 | } |
672 | | |
673 | | RSA * |
674 | | d2i_RSAPublicKey(RSA *rsa, const unsigned char **pp, size_t len) |
675 | 0 | { |
676 | 0 | RSAPublicKey data; |
677 | 0 | RSA *k = rsa; |
678 | 0 | size_t size; |
679 | 0 | int ret; |
680 | |
|
681 | 0 | ret = decode_RSAPublicKey(*pp, len, &data, &size); |
682 | 0 | if (ret) |
683 | 0 | return NULL; |
684 | | |
685 | 0 | *pp += size; |
686 | |
|
687 | 0 | if (k == NULL) { |
688 | 0 | k = RSA_new(); |
689 | 0 | if (k == NULL) { |
690 | 0 | free_RSAPublicKey(&data); |
691 | 0 | return NULL; |
692 | 0 | } |
693 | 0 | } |
694 | | |
695 | 0 | k->n = _hc_integer_to_BN(&data.modulus, NULL); |
696 | 0 | k->e = _hc_integer_to_BN(&data.publicExponent, NULL); |
697 | |
|
698 | 0 | free_RSAPublicKey(&data); |
699 | |
|
700 | 0 | if (k->n == NULL || k->e == NULL) { |
701 | 0 | RSA_free(k); |
702 | 0 | return NULL; |
703 | 0 | } |
704 | | |
705 | 0 | return k; |
706 | 0 | } |