15b876b3fcba06baff8bc58a67ac149332cd8b0a
[strongswan.git] / src / libstrongswan / plugins / gcrypt / gcrypt_rsa_private_key.c
1 /*
2 * Copyright (C) 2005-2009 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include <gcrypt.h>
17
18 #include "gcrypt_rsa_private_key.h"
19
20 #include <utils/debug.h>
21 #include <asn1/oid.h>
22 #include <asn1/asn1.h>
23 #include <asn1/asn1_parser.h>
24
25 typedef struct private_gcrypt_rsa_private_key_t private_gcrypt_rsa_private_key_t;
26
27 /**
28 * Private data of a gcrypt_rsa_private_key_t object.
29 */
30 struct private_gcrypt_rsa_private_key_t {
31
32 /**
33 * Public interface
34 */
35 gcrypt_rsa_private_key_t public;
36
37 /**
38 * gcrypt S-expression representing an RSA key
39 */
40 gcry_sexp_t key;
41
42 /**
43 * reference count
44 */
45 refcount_t ref;
46 };
47
48 /**
49 * find a token in a S-expression. If a key is given, its length is used to
50 * pad the output to a given length.
51 */
52 chunk_t gcrypt_rsa_find_token(gcry_sexp_t sexp, char *name, gcry_sexp_t key)
53 {
54 gcry_sexp_t token;
55 chunk_t data = chunk_empty, tmp;
56 size_t len = 0;
57
58 token = gcry_sexp_find_token(sexp, name, 1);
59 if (token)
60 {
61 data.ptr = (char*)gcry_sexp_nth_data(token, 1, &data.len);
62 if (!data.ptr)
63 {
64 data.len = 0;
65 }
66 else
67 {
68 if (key)
69 {
70 /* gcrypt might return more bytes than necessary. Truncate
71 * to key length if key given, or prepend zeros if needed */
72 len = gcry_pk_get_nbits(key);
73 len = len / 8 + (len % 8 ? 1 : 0);
74 if (len > data.len)
75 {
76 tmp = chunk_alloc(len);
77 len -= data.len;
78 memset(tmp.ptr, 0, tmp.len - len);
79 memcpy(tmp.ptr + len, data.ptr, data.len);
80 data = tmp;
81 }
82 else if (len < data.len)
83 {
84 data = chunk_clone(chunk_skip(data, data.len - len));
85 }
86 else
87 {
88 data = chunk_clone(data);
89 }
90 }
91 else
92 {
93 data = chunk_clone(data);
94 }
95 }
96 gcry_sexp_release(token);
97 }
98 return data;
99 }
100
101 /**
102 * Sign a chunk of data with direct PKCS#1 encoding, no hash OID
103 */
104 static bool sign_raw(private_gcrypt_rsa_private_key_t *this,
105 chunk_t data, chunk_t *signature)
106 {
107 gcry_sexp_t in, out;
108 gcry_error_t err;
109 chunk_t em;
110 size_t k;
111
112 /* EM = 0x00 || 0x01 || PS || 0x00 || T
113 * PS = 0xFF padding, with length to fill em
114 * T = data
115 */
116 k = gcry_pk_get_nbits(this->key) / 8;
117 if (data.len > k - 3)
118 {
119 return FALSE;
120 }
121 em = chunk_alloc(k);
122 memset(em.ptr, 0xFF, em.len);
123 em.ptr[0] = 0x00;
124 em.ptr[1] = 0x01;
125 em.ptr[em.len - data.len - 1] = 0x00;
126 memcpy(em.ptr + em.len - data.len, data.ptr, data.len);
127
128 err = gcry_sexp_build(&in, NULL, "(data(flags raw)(value %b))",
129 em.len, em.ptr);
130 chunk_free(&em);
131 if (err)
132 {
133 DBG1(DBG_LIB, "building signature S-expression failed: %s",
134 gpg_strerror(err));
135 return FALSE;
136 }
137 err = gcry_pk_sign(&out, in, this->key);
138 gcry_sexp_release(in);
139 if (err)
140 {
141 DBG1(DBG_LIB, "creating pkcs1 signature failed: %s", gpg_strerror(err));
142 return FALSE;
143 }
144 *signature = gcrypt_rsa_find_token(out, "s", this->key);
145 gcry_sexp_release(out);
146 return !!signature->len;
147 }
148
149 /**
150 * Sign a chunk of data using hashing and PKCS#1 encoding
151 */
152 static bool sign_pkcs1(private_gcrypt_rsa_private_key_t *this,
153 hash_algorithm_t hash_algorithm, char *hash_name,
154 chunk_t data, chunk_t *signature)
155 {
156 hasher_t *hasher;
157 chunk_t hash;
158 gcry_error_t err;
159 gcry_sexp_t in, out;
160 int hash_oid;
161
162 hash_oid = hasher_algorithm_to_oid(hash_algorithm);
163 if (hash_oid == OID_UNKNOWN)
164 {
165 return FALSE;
166 }
167 hasher = lib->crypto->create_hasher(lib->crypto, hash_algorithm);
168 if (!hasher || !hasher->allocate_hash(hasher, data, &hash))
169 {
170 DESTROY_IF(hasher);
171 return FALSE;
172 }
173 hasher->destroy(hasher);
174
175 err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(hash %s %b))",
176 hash_name, hash.len, hash.ptr);
177 chunk_free(&hash);
178 if (err)
179 {
180 DBG1(DBG_LIB, "building signature S-expression failed: %s", gpg_strerror(err));
181 return FALSE;
182 }
183 err = gcry_pk_sign(&out, in, this->key);
184 gcry_sexp_release(in);
185 if (err)
186 {
187 DBG1(DBG_LIB, "creating pkcs1 signature failed: %s", gpg_strerror(err));
188 return FALSE;
189 }
190 *signature = gcrypt_rsa_find_token(out, "s", this->key);
191 gcry_sexp_release(out);
192 return !!signature->len;
193 }
194
195 METHOD(private_key_t, get_type, key_type_t,
196 private_gcrypt_rsa_private_key_t *this)
197 {
198 return KEY_RSA;
199 }
200
201 METHOD(private_key_t, sign, bool,
202 private_gcrypt_rsa_private_key_t *this, signature_scheme_t scheme,
203 chunk_t data, chunk_t *sig)
204 {
205 switch (scheme)
206 {
207 case SIGN_RSA_EMSA_PKCS1_NULL:
208 return sign_raw(this, data, sig);
209 case SIGN_RSA_EMSA_PKCS1_SHA2_224:
210 return sign_pkcs1(this, HASH_SHA224, "sha224", data, sig);
211 case SIGN_RSA_EMSA_PKCS1_SHA2_256:
212 return sign_pkcs1(this, HASH_SHA256, "sha256", data, sig);
213 case SIGN_RSA_EMSA_PKCS1_SHA2_384:
214 return sign_pkcs1(this, HASH_SHA384, "sha384", data, sig);
215 case SIGN_RSA_EMSA_PKCS1_SHA2_512:
216 return sign_pkcs1(this, HASH_SHA512, "sha512", data, sig);
217 case SIGN_RSA_EMSA_PKCS1_SHA1:
218 return sign_pkcs1(this, HASH_SHA1, "sha1", data, sig);
219 case SIGN_RSA_EMSA_PKCS1_MD5:
220 return sign_pkcs1(this, HASH_MD5, "md5", data, sig);
221 default:
222 DBG1(DBG_LIB, "signature scheme %N not supported in RSA",
223 signature_scheme_names, scheme);
224 return FALSE;
225 }
226 }
227
228 METHOD(private_key_t, decrypt, bool,
229 private_gcrypt_rsa_private_key_t *this, encryption_scheme_t scheme,
230 chunk_t encrypted, chunk_t *plain)
231 {
232 gcry_error_t err;
233 gcry_sexp_t in, out;
234 chunk_t padded;
235 u_char *pos = NULL;;
236
237 if (scheme != ENCRYPT_RSA_PKCS1)
238 {
239 DBG1(DBG_LIB, "encryption scheme %N not supported",
240 encryption_scheme_names, scheme);
241 return FALSE;
242 }
243 err = gcry_sexp_build(&in, NULL, "(enc-val(flags)(rsa(a %b)))",
244 encrypted.len, encrypted.ptr);
245 if (err)
246 {
247 DBG1(DBG_LIB, "building decryption S-expression failed: %s",
248 gpg_strerror(err));
249 return FALSE;
250 }
251 err = gcry_pk_decrypt(&out, in, this->key);
252 gcry_sexp_release(in);
253 if (err)
254 {
255 DBG1(DBG_LIB, "decrypting pkcs1 data failed: %s", gpg_strerror(err));
256 return FALSE;
257 }
258 padded.ptr = (u_char*)gcry_sexp_nth_data(out, 1, &padded.len);
259 /* result is padded, but gcrypt strips leading zero:
260 * 00 | 02 | RANDOM | 00 | DATA */
261 if (padded.ptr && padded.len > 2 && padded.ptr[0] == 0x02)
262 {
263 pos = memchr(padded.ptr, 0x00, padded.len - 1);
264 if (pos)
265 {
266 pos++;
267 *plain = chunk_clone(chunk_create(
268 pos, padded.len - (pos - padded.ptr)));
269 }
270 }
271 gcry_sexp_release(out);
272 if (!pos)
273 {
274 DBG1(DBG_LIB, "decrypted data has invalid pkcs1 padding");
275 return FALSE;
276 }
277 return TRUE;
278 }
279
280 METHOD(private_key_t, get_keysize, int,
281 private_gcrypt_rsa_private_key_t *this)
282 {
283 return gcry_pk_get_nbits(this->key);
284 }
285
286 METHOD(private_key_t, get_public_key, public_key_t*,
287 private_gcrypt_rsa_private_key_t *this)
288 {
289 chunk_t n, e;
290 public_key_t *public;
291
292 n = gcrypt_rsa_find_token(this->key, "n", NULL);
293 e = gcrypt_rsa_find_token(this->key, "e", NULL);
294
295 public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
296 BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_END);
297 chunk_free(&n);
298 chunk_free(&e);
299
300 return public;
301 }
302
303 METHOD(private_key_t, get_encoding, bool,
304 private_gcrypt_rsa_private_key_t *this, cred_encoding_type_t type,
305 chunk_t *encoding)
306 {
307 chunk_t cn, ce, cp, cq, cd, cu, cexp1 = chunk_empty, cexp2 = chunk_empty;
308 gcry_mpi_t p = NULL, q = NULL, d = NULL, exp1, exp2;
309 gcry_error_t err;
310 bool success;
311
312 /* p and q are swapped, gcrypt expects p < q */
313 cp = gcrypt_rsa_find_token(this->key, "q", NULL);
314 cq = gcrypt_rsa_find_token(this->key, "p", NULL);
315 cd = gcrypt_rsa_find_token(this->key, "d", NULL);
316
317 err = gcry_mpi_scan(&p, GCRYMPI_FMT_USG, cp.ptr, cp.len, NULL)
318 | gcry_mpi_scan(&q, GCRYMPI_FMT_USG, cq.ptr, cq.len, NULL)
319 | gcry_mpi_scan(&d, GCRYMPI_FMT_USG, cd.ptr, cd.len, NULL);
320 if (err)
321 {
322 gcry_mpi_release(p);
323 gcry_mpi_release(q);
324 gcry_mpi_release(d);
325 chunk_clear(&cp);
326 chunk_clear(&cq);
327 chunk_clear(&cd);
328 DBG1(DBG_LIB, "scanning mpi for export failed: %s", gpg_strerror(err));
329 return FALSE;
330 }
331
332 gcry_mpi_sub_ui(p, p, 1);
333 exp1 = gcry_mpi_new(gcry_pk_get_nbits(this->key));
334 gcry_mpi_mod(exp1, d, p);
335 gcry_mpi_release(p);
336
337 gcry_mpi_sub_ui(q, q, 1);
338 exp2 = gcry_mpi_new(gcry_pk_get_nbits(this->key));
339 gcry_mpi_mod(exp2, d, q);
340 gcry_mpi_release(q);
341
342 err = gcry_mpi_aprint(GCRYMPI_FMT_USG, &cexp1.ptr, &cexp1.len, exp1)
343 | gcry_mpi_aprint(GCRYMPI_FMT_USG, &cexp2.ptr, &cexp2.len, exp2);
344
345 gcry_mpi_release(d);
346 gcry_mpi_release(exp1);
347 gcry_mpi_release(exp2);
348
349 if (err)
350 {
351 DBG1(DBG_LIB, "printing mpi for export failed: %s", gpg_strerror(err));
352 chunk_clear(&cp);
353 chunk_clear(&cq);
354 chunk_clear(&cd);
355 chunk_clear(&cexp1);
356 chunk_clear(&cexp2);
357 return FALSE;
358 }
359
360 cn = gcrypt_rsa_find_token(this->key, "n", NULL);
361 ce = gcrypt_rsa_find_token(this->key, "e", NULL);
362 cu = gcrypt_rsa_find_token(this->key, "u", NULL);
363
364 success = lib->encoding->encode(lib->encoding, type, NULL, encoding,
365 CRED_PART_RSA_MODULUS, cn,
366 CRED_PART_RSA_PUB_EXP, ce, CRED_PART_RSA_PRIV_EXP, cd,
367 CRED_PART_RSA_PRIME1, cp, CRED_PART_RSA_PRIME2, cq,
368 CRED_PART_RSA_EXP1, cexp1, CRED_PART_RSA_EXP2, cexp2,
369 CRED_PART_RSA_COEFF, cu, CRED_PART_END);
370 chunk_free(&cn);
371 chunk_free(&ce);
372 chunk_clear(&cd);
373 chunk_clear(&cp);
374 chunk_clear(&cq);
375 chunk_clear(&cexp1);
376 chunk_clear(&cexp2);
377 chunk_clear(&cu);
378
379 return success;
380 }
381
382 METHOD(private_key_t, get_fingerprint, bool,
383 private_gcrypt_rsa_private_key_t *this, cred_encoding_type_t type,
384 chunk_t *fp)
385 {
386 chunk_t n, e;
387 bool success;
388
389 if (lib->encoding->get_cache(lib->encoding, type, this, fp))
390 {
391 return TRUE;
392 }
393 n = gcrypt_rsa_find_token(this->key, "n", NULL);
394 e = gcrypt_rsa_find_token(this->key, "e", NULL);
395
396 success = lib->encoding->encode(lib->encoding,
397 type, this, fp, CRED_PART_RSA_MODULUS, n,
398 CRED_PART_RSA_PUB_EXP, e, CRED_PART_END);
399 chunk_free(&n);
400 chunk_free(&e);
401 return success;
402 }
403
404 METHOD(private_key_t, get_ref, private_key_t*,
405 private_gcrypt_rsa_private_key_t *this)
406 {
407 ref_get(&this->ref);
408 return &this->public.key;
409 }
410
411 METHOD(private_key_t, destroy, void,
412 private_gcrypt_rsa_private_key_t *this)
413 {
414 if (ref_put(&this->ref))
415 {
416 gcry_sexp_release(this->key);
417 lib->encoding->clear_cache(lib->encoding, this);
418 free(this);
419 }
420 }
421
422 /**
423 * Internal generic constructor
424 */
425 static private_gcrypt_rsa_private_key_t *create_empty()
426 {
427 private_gcrypt_rsa_private_key_t *this;
428
429 INIT(this,
430 .public = {
431 .key = {
432 .get_type = _get_type,
433 .sign = _sign,
434 .decrypt = _decrypt,
435 .get_keysize = _get_keysize,
436 .get_public_key = _get_public_key,
437 .equals = private_key_equals,
438 .belongs_to = private_key_belongs_to,
439 .get_fingerprint = _get_fingerprint,
440 .has_fingerprint = private_key_has_fingerprint,
441 .get_encoding = _get_encoding,
442 .get_ref = _get_ref,
443 .destroy = _destroy,
444 },
445 },
446 .ref = 1,
447 );
448
449 return this;
450 }
451
452 /**
453 * See header.
454 */
455 gcrypt_rsa_private_key_t *gcrypt_rsa_private_key_gen(key_type_t type,
456 va_list args)
457 {
458 private_gcrypt_rsa_private_key_t *this;
459 gcry_sexp_t param;
460 gcry_error_t err;
461 u_int key_size = 0;
462
463 while (TRUE)
464 {
465 switch (va_arg(args, builder_part_t))
466 {
467 case BUILD_KEY_SIZE:
468 key_size = va_arg(args, u_int);
469 continue;
470 case BUILD_END:
471 break;
472 default:
473 return NULL;
474 }
475 break;
476 }
477 if (!key_size)
478 {
479 return NULL;
480 }
481
482 err = gcry_sexp_build(&param, NULL, "(genkey(rsa(nbits %d)))", key_size);
483 if (err)
484 {
485 DBG1(DBG_LIB, "building S-expression failed: %s", gpg_strerror(err));
486 return NULL;
487 }
488 this = create_empty();
489 err = gcry_pk_genkey(&this->key, param);
490 gcry_sexp_release(param);
491 if (err)
492 {
493 free(this);
494 DBG1(DBG_LIB, "generating RSA key failed: %s", gpg_strerror(err));
495 return NULL;
496 }
497 return &this->public;
498 }
499
500 /**
501 * See header.
502 */
503 gcrypt_rsa_private_key_t *gcrypt_rsa_private_key_load(key_type_t type,
504 va_list args)
505 {
506 private_gcrypt_rsa_private_key_t *this;
507 chunk_t n, e, d, p, q, u;
508 gcry_error_t err;
509
510 n = e = d = p = q = u = chunk_empty;
511 while (TRUE)
512 {
513 switch (va_arg(args, builder_part_t))
514 {
515 case BUILD_RSA_MODULUS:
516 n = va_arg(args, chunk_t);
517 continue;
518 case BUILD_RSA_PUB_EXP:
519 e = va_arg(args, chunk_t);
520 continue;
521 case BUILD_RSA_PRIV_EXP:
522 d = va_arg(args, chunk_t);
523 continue;
524 case BUILD_RSA_PRIME1:
525 /* swap p and q, gcrypt expects p < q */
526 q = va_arg(args, chunk_t);
527 continue;
528 case BUILD_RSA_PRIME2:
529 p = va_arg(args, chunk_t);
530 continue;
531 case BUILD_RSA_EXP1:
532 case BUILD_RSA_EXP2:
533 /* not required for gcrypt */
534 va_arg(args, chunk_t);
535 continue;
536 case BUILD_RSA_COEFF:
537 u = va_arg(args, chunk_t);
538 continue;
539 case BUILD_END:
540 break;
541 default:
542 return NULL;
543 }
544 break;
545 }
546
547 this = create_empty();
548 err = gcry_sexp_build(&this->key, NULL,
549 "(private-key(rsa(n %b)(e %b)(d %b)(p %b)(q %b)(u %b)))",
550 n.len, n.ptr, e.len, e.ptr, d.len, d.ptr,
551 p.len, p.ptr, q.len, q.ptr, u.len, u.ptr);
552 if (err)
553 {
554 DBG1(DBG_LIB, "loading private key failed: %s", gpg_strerror(err));
555 free(this);
556 return NULL;
557 }
558 err = gcry_pk_testkey(this->key);
559 if (err)
560 {
561 DBG1(DBG_LIB, "private key sanity check failed: %s", gpg_strerror(err));
562 destroy(this);
563 return NULL;
564 }
565 return &this->public;
566 }
567