2 * Copyright (C) 2017 Tobias Brunner
3 * Copyright (C) 2005-2009 Martin Willi
4 * HSR Hochschule fuer Technik Rapperswil
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 #include "gcrypt_rsa_private_key.h"
21 #include <utils/debug.h>
23 #include <asn1/asn1.h>
24 #include <asn1/asn1_parser.h>
25 #include <credentials/keys/signature_params.h>
27 typedef struct private_gcrypt_rsa_private_key_t private_gcrypt_rsa_private_key_t
;
30 * Private data of a gcrypt_rsa_private_key_t object.
32 struct private_gcrypt_rsa_private_key_t
{
37 gcrypt_rsa_private_key_t
public;
40 * gcrypt S-expression representing an RSA key
51 * find a token in a S-expression. If a key is given, its length is used to
52 * pad the output to a given length.
54 chunk_t
gcrypt_rsa_find_token(gcry_sexp_t sexp
, char *name
, gcry_sexp_t key
)
57 chunk_t data
= chunk_empty
, tmp
;
60 token
= gcry_sexp_find_token(sexp
, name
, 1);
63 data
.ptr
= (char*)gcry_sexp_nth_data(token
, 1, &data
.len
);
72 /* gcrypt might return more bytes than necessary. Truncate
73 * to key length if key given, or prepend zeros if needed */
74 len
= gcry_pk_get_nbits(key
);
75 len
= len
/ 8 + (len
% 8 ? 1 : 0);
78 tmp
= chunk_alloc(len
);
80 memset(tmp
.ptr
, 0, tmp
.len
- len
);
81 memcpy(tmp
.ptr
+ len
, data
.ptr
, data
.len
);
84 else if (len
< data
.len
)
86 data
= chunk_clone(chunk_skip(data
, data
.len
- len
));
90 data
= chunk_clone(data
);
95 data
= chunk_clone(data
);
98 gcry_sexp_release(token
);
104 * Sign a chunk of data with direct PKCS#1 encoding, no hash OID
106 static bool sign_raw(private_gcrypt_rsa_private_key_t
*this,
107 chunk_t data
, chunk_t
*signature
)
114 /* EM = 0x00 || 0x01 || PS || 0x00 || T
115 * PS = 0xFF padding, with length to fill em
118 k
= gcry_pk_get_nbits(this->key
) / 8;
119 if (data
.len
> k
- 3)
124 memset(em
.ptr
, 0xFF, em
.len
);
127 em
.ptr
[em
.len
- data
.len
- 1] = 0x00;
128 memcpy(em
.ptr
+ em
.len
- data
.len
, data
.ptr
, data
.len
);
130 err
= gcry_sexp_build(&in
, NULL
, "(data(flags raw)(value %b))",
135 DBG1(DBG_LIB
, "building signature S-expression failed: %s",
139 err
= gcry_pk_sign(&out
, in
, this->key
);
140 gcry_sexp_release(in
);
143 DBG1(DBG_LIB
, "creating pkcs1 signature failed: %s", gpg_strerror(err
));
146 *signature
= gcrypt_rsa_find_token(out
, "s", this->key
);
147 gcry_sexp_release(out
);
148 return !!signature
->len
;
152 * Sign a chunk of data using hashing and PKCS#1v1.5/EMSA-PSS encoding
154 static bool sign_pkcs1(private_gcrypt_rsa_private_key_t
*this,
155 hash_algorithm_t hash_algorithm
, rsa_pss_params_t
*pss
,
156 chunk_t data
, chunk_t
*signature
)
162 char *hash_name
= enum_to_name(hash_algorithm_short_names
, hash_algorithm
);
164 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, hash_algorithm
);
167 DBG1(DBG_LIB
, "hash algorithm %N not supported",
168 hash_algorithm_names
, hash_algorithm
);
171 if (!hasher
->allocate_hash(hasher
, data
, &hash
))
173 hasher
->destroy(hasher
);
176 hasher
->destroy(hasher
);
182 err
= gcry_sexp_build(&in
, NULL
,
183 "(data(flags pss)(salt-length %u)"
184 "(random-override %b)(hash %s %b))",
185 pss
->salt
.len
, pss
->salt
.len
, pss
->salt
.ptr
,
186 hash_name
, hash
.len
, hash
.ptr
);
190 u_int slen
= pss
->salt_len
;
191 err
= gcry_sexp_build(&in
, NULL
,
192 "(data(flags pss)(salt-length %u)(hash %s %b))",
193 slen
, hash_name
, hash
.len
, hash
.ptr
);
198 err
= gcry_sexp_build(&in
, NULL
, "(data(flags pkcs1)(hash %s %b))",
199 hash_name
, hash
.len
, hash
.ptr
);
204 DBG1(DBG_LIB
, "building signature S-expression failed: %s",
208 err
= gcry_pk_sign(&out
, in
, this->key
);
209 gcry_sexp_release(in
);
212 DBG1(DBG_LIB
, "creating pkcs1 signature failed: %s",
217 *signature
= gcrypt_rsa_find_token(out
, "s", this->key
);
218 gcry_sexp_release(out
);
219 return !!signature
->len
;
222 #if GCRYPT_VERSION_NUMBER >= 0x010700
224 * Sign a chunk of data using hashing and EMSA-PSS encoding
226 static bool sign_pss(private_gcrypt_rsa_private_key_t
*this,
227 rsa_pss_params_t
*params
, chunk_t data
, chunk_t
*signature
)
233 if (params
->mgf1_hash
!= params
->hash
)
235 DBG1(DBG_LIB
, "unable to use a different MGF1 hash for RSA-PSS");
238 return sign_pkcs1(this, params
->hash
, params
, data
, signature
);
242 METHOD(private_key_t
, get_type
, key_type_t
,
243 private_gcrypt_rsa_private_key_t
*this)
248 METHOD(private_key_t
, sign
, bool,
249 private_gcrypt_rsa_private_key_t
*this, signature_scheme_t scheme
,
250 void *params
, chunk_t data
, chunk_t
*sig
)
254 case SIGN_RSA_EMSA_PKCS1_NULL
:
255 return sign_raw(this, data
, sig
);
256 case SIGN_RSA_EMSA_PKCS1_SHA2_224
:
257 return sign_pkcs1(this, HASH_SHA224
, NULL
, data
, sig
);
258 case SIGN_RSA_EMSA_PKCS1_SHA2_256
:
259 return sign_pkcs1(this, HASH_SHA256
, NULL
, data
, sig
);
260 case SIGN_RSA_EMSA_PKCS1_SHA2_384
:
261 return sign_pkcs1(this, HASH_SHA384
, NULL
, data
, sig
);
262 case SIGN_RSA_EMSA_PKCS1_SHA2_512
:
263 return sign_pkcs1(this, HASH_SHA512
, NULL
, data
, sig
);
264 case SIGN_RSA_EMSA_PKCS1_SHA1
:
265 return sign_pkcs1(this, HASH_SHA1
, NULL
, data
, sig
);
266 case SIGN_RSA_EMSA_PKCS1_MD5
:
267 return sign_pkcs1(this, HASH_MD5
, NULL
, data
, sig
);
268 #if GCRYPT_VERSION_NUMBER >= 0x010700
269 case SIGN_RSA_EMSA_PSS
:
270 return sign_pss(this, params
, data
, sig
);
273 DBG1(DBG_LIB
, "signature scheme %N not supported in RSA",
274 signature_scheme_names
, scheme
);
279 METHOD(private_key_t
, decrypt
, bool,
280 private_gcrypt_rsa_private_key_t
*this, encryption_scheme_t scheme
,
281 void *params
, chunk_t encrypted
, chunk_t
*plain
)
285 chunk_t label
= chunk_empty
, decrypted
;
290 case ENCRYPT_RSA_PKCS1
:
291 sexp
= "(enc-val(flags pkcs1)(rsa(a %b)))";
293 case ENCRYPT_RSA_OAEP_SHA1
:
294 sexp
= "(enc-val(flags oaep)(rsa(a %b)))";
297 DBG1(DBG_LIB
, "encryption scheme %N not supported",
298 encryption_scheme_names
, scheme
);
302 if (scheme
== ENCRYPT_RSA_OAEP_SHA1
&& params
!= NULL
)
304 label
= *(chunk_t
*)params
;
307 DBG1(DBG_LIB
, "RSA OAEP decryption with a label not supported");
312 err
= gcry_sexp_build(&in
, NULL
, sexp
, encrypted
.len
, encrypted
.ptr
);
315 DBG1(DBG_LIB
, "building decryption S-expression failed: %s",
320 err
= gcry_pk_decrypt(&out
, in
, this->key
);
321 gcry_sexp_release(in
);
324 DBG1(DBG_LIB
, "RSA decryption failed: %s", gpg_strerror(err
));
328 decrypted
.ptr
= (u_char
*)gcry_sexp_nth_data(out
, 1, &decrypted
.len
);
329 *plain
= chunk_clone(decrypted
);
330 gcry_sexp_release(out
);
335 METHOD(private_key_t
, get_keysize
, int,
336 private_gcrypt_rsa_private_key_t
*this)
338 return gcry_pk_get_nbits(this->key
);
341 METHOD(private_key_t
, get_public_key
, public_key_t
*,
342 private_gcrypt_rsa_private_key_t
*this)
345 public_key_t
*public;
347 n
= gcrypt_rsa_find_token(this->key
, "n", NULL
);
348 e
= gcrypt_rsa_find_token(this->key
, "e", NULL
);
350 public = lib
->creds
->create(lib
->creds
, CRED_PUBLIC_KEY
, KEY_RSA
,
351 BUILD_RSA_MODULUS
, n
, BUILD_RSA_PUB_EXP
, e
, BUILD_END
);
358 METHOD(private_key_t
, get_encoding
, bool,
359 private_gcrypt_rsa_private_key_t
*this, cred_encoding_type_t type
,
362 chunk_t cn
, ce
, cp
, cq
, cd
, cu
, cexp1
= chunk_empty
, cexp2
= chunk_empty
;
363 gcry_mpi_t p
= NULL
, q
= NULL
, d
= NULL
, exp1
, exp2
;
367 /* p and q are swapped, gcrypt expects p < q */
368 cp
= gcrypt_rsa_find_token(this->key
, "q", NULL
);
369 cq
= gcrypt_rsa_find_token(this->key
, "p", NULL
);
370 cd
= gcrypt_rsa_find_token(this->key
, "d", NULL
);
372 err
= gcry_mpi_scan(&p
, GCRYMPI_FMT_USG
, cp
.ptr
, cp
.len
, NULL
)
373 | gcry_mpi_scan(&q
, GCRYMPI_FMT_USG
, cq
.ptr
, cq
.len
, NULL
)
374 | gcry_mpi_scan(&d
, GCRYMPI_FMT_USG
, cd
.ptr
, cd
.len
, NULL
);
383 DBG1(DBG_LIB
, "scanning mpi for export failed: %s", gpg_strerror(err
));
387 gcry_mpi_sub_ui(p
, p
, 1);
388 exp1
= gcry_mpi_new(gcry_pk_get_nbits(this->key
));
389 gcry_mpi_mod(exp1
, d
, p
);
392 gcry_mpi_sub_ui(q
, q
, 1);
393 exp2
= gcry_mpi_new(gcry_pk_get_nbits(this->key
));
394 gcry_mpi_mod(exp2
, d
, q
);
397 err
= gcry_mpi_aprint(GCRYMPI_FMT_USG
, &cexp1
.ptr
, &cexp1
.len
, exp1
)
398 | gcry_mpi_aprint(GCRYMPI_FMT_USG
, &cexp2
.ptr
, &cexp2
.len
, exp2
);
401 gcry_mpi_release(exp1
);
402 gcry_mpi_release(exp2
);
406 DBG1(DBG_LIB
, "printing mpi for export failed: %s", gpg_strerror(err
));
415 cn
= gcrypt_rsa_find_token(this->key
, "n", NULL
);
416 ce
= gcrypt_rsa_find_token(this->key
, "e", NULL
);
417 cu
= gcrypt_rsa_find_token(this->key
, "u", NULL
);
419 success
= lib
->encoding
->encode(lib
->encoding
, type
, NULL
, encoding
,
420 CRED_PART_RSA_MODULUS
, cn
,
421 CRED_PART_RSA_PUB_EXP
, ce
, CRED_PART_RSA_PRIV_EXP
, cd
,
422 CRED_PART_RSA_PRIME1
, cp
, CRED_PART_RSA_PRIME2
, cq
,
423 CRED_PART_RSA_EXP1
, cexp1
, CRED_PART_RSA_EXP2
, cexp2
,
424 CRED_PART_RSA_COEFF
, cu
, CRED_PART_END
);
437 METHOD(private_key_t
, get_fingerprint
, bool,
438 private_gcrypt_rsa_private_key_t
*this, cred_encoding_type_t type
,
444 if (lib
->encoding
->get_cache(lib
->encoding
, type
, this, fp
))
448 n
= gcrypt_rsa_find_token(this->key
, "n", NULL
);
449 e
= gcrypt_rsa_find_token(this->key
, "e", NULL
);
451 success
= lib
->encoding
->encode(lib
->encoding
,
452 type
, this, fp
, CRED_PART_RSA_MODULUS
, n
,
453 CRED_PART_RSA_PUB_EXP
, e
, CRED_PART_END
);
459 METHOD(private_key_t
, get_ref
, private_key_t
*,
460 private_gcrypt_rsa_private_key_t
*this)
463 return &this->public.key
;
466 METHOD(private_key_t
, destroy
, void,
467 private_gcrypt_rsa_private_key_t
*this)
469 if (ref_put(&this->ref
))
471 gcry_sexp_release(this->key
);
472 lib
->encoding
->clear_cache(lib
->encoding
, this);
478 * Internal generic constructor
480 static private_gcrypt_rsa_private_key_t
*create_empty()
482 private_gcrypt_rsa_private_key_t
*this;
487 .get_type
= _get_type
,
490 .get_keysize
= _get_keysize
,
491 .get_public_key
= _get_public_key
,
492 .equals
= private_key_equals
,
493 .belongs_to
= private_key_belongs_to
,
494 .get_fingerprint
= _get_fingerprint
,
495 .has_fingerprint
= private_key_has_fingerprint
,
496 .get_encoding
= _get_encoding
,
510 gcrypt_rsa_private_key_t
*gcrypt_rsa_private_key_gen(key_type_t type
,
513 private_gcrypt_rsa_private_key_t
*this;
520 switch (va_arg(args
, builder_part_t
))
523 key_size
= va_arg(args
, u_int
);
537 err
= gcry_sexp_build(¶m
, NULL
, "(genkey(rsa(nbits %d)))", key_size
);
540 DBG1(DBG_LIB
, "building S-expression failed: %s", gpg_strerror(err
));
543 this = create_empty();
544 err
= gcry_pk_genkey(&this->key
, param
);
545 gcry_sexp_release(param
);
549 DBG1(DBG_LIB
, "generating RSA key failed: %s", gpg_strerror(err
));
552 return &this->public;
556 * Recover the primes from n, e and d using the algorithm described in
557 * Appendix C of NIST SP 800-56B.
559 static bool calculate_pqu(chunk_t cn
, chunk_t ce
, chunk_t cd
, chunk_t
*cp
,
560 chunk_t
*cq
, chunk_t
*cu
)
562 gcry_mpi_t n
, e
, d
, p
, q
, u
, k
, r
, g
, y
, n1
, x
, two
;
565 bool success
= FALSE
;
567 n
= e
= d
= p
= q
= u
= k
= r
= g
= y
= n1
= x
= two
= NULL
;
568 err
= gcry_mpi_scan(&n
, GCRYMPI_FMT_USG
, cn
.ptr
, cn
.len
, NULL
)
569 | gcry_mpi_scan(&e
, GCRYMPI_FMT_USG
, ce
.ptr
, ce
.len
, NULL
)
570 | gcry_mpi_scan(&d
, GCRYMPI_FMT_USG
, cd
.ptr
, cd
.len
, NULL
);
575 /* k = (d * e) - 1 */
576 k
= gcry_mpi_new(gcry_mpi_get_nbits(n
));
577 gcry_mpi_mul(k
, d
, e
);
578 gcry_mpi_sub_ui(k
, k
, 1);
579 if (gcry_mpi_test_bit(k
, 0))
583 /* k = 2^t * r, where r is the largest odd integer dividing k, and t >= 1 */
584 r
= gcry_mpi_copy(k
);
585 for (t
= 0; !gcry_mpi_test_bit(r
, 0); t
++)
587 gcry_mpi_rshift(r
, r
, 1);
589 /* we need n-1 below */
590 n1
= gcry_mpi_new(gcry_mpi_get_nbits(n
));
591 gcry_mpi_sub_ui(n1
, n
, 1);
592 y
= gcry_mpi_new(gcry_mpi_get_nbits(n
));
593 g
= gcry_mpi_new(gcry_mpi_get_nbits(n
));
594 x
= gcry_mpi_new(gcry_mpi_get_nbits(n
));
595 two
= gcry_mpi_set_ui(NULL
, 2);
596 for (i
= 0; i
< 100; i
++)
597 { /* generate random integer g in [0, n-1] */
600 gcry_mpi_randomize(g
, gcry_mpi_get_nbits(n
), GCRY_WEAK_RANDOM
);
602 while (gcry_mpi_cmp(n
, g
) <= 0);
604 gcry_mpi_powm(y
, g
, r
, n
);
605 /* try again if y == 1 or y == n-1 */
606 if (gcry_mpi_cmp_ui(y
, 1) == 0 || gcry_mpi_cmp(y
, n1
) == 0)
610 for (j
= 0; j
< t
; j
++)
611 { /* x = y^2 mod n */
612 gcry_mpi_powm(x
, y
, two
, n
);
614 if (gcry_mpi_cmp_ui(x
, 1) == 0)
618 /* retry with new g if x = n-1 */
619 if (gcry_mpi_cmp(x
, n1
) == 0)
630 /* p = gcd(y-1, n) */
631 gcry_mpi_sub_ui(y
, y
, 1);
632 p
= gcry_mpi_new(gcry_mpi_get_nbits(n
));
633 gcry_mpi_gcd(p
, y
, n
);
635 q
= gcry_mpi_new(gcry_mpi_get_nbits(n
));
636 gcry_mpi_div(q
, NULL
, n
, p
, 0);
637 if (gcry_mpi_cmp(p
, q
) > 0)
638 { /* gcrypt expects q < p */
642 u
= gcry_mpi_new(gcry_mpi_get_nbits(n
));
643 gcry_mpi_invm(u
, p
, q
);
644 err
= gcry_mpi_aprint(GCRYMPI_FMT_USG
, &cp
->ptr
, &cp
->len
, p
)
645 | gcry_mpi_aprint(GCRYMPI_FMT_USG
, &cq
->ptr
, &cq
->len
, q
)
646 | gcry_mpi_aprint(GCRYMPI_FMT_USG
, &cu
->ptr
, &cu
->len
, u
);
664 gcry_mpi_release(n1
);
666 gcry_mpi_release(two
);
673 gcrypt_rsa_private_key_t
*gcrypt_rsa_private_key_load(key_type_t type
,
676 private_gcrypt_rsa_private_key_t
*this;
677 chunk_t n
, e
, d
, p
, q
, u
, np
, nq
, nu
;
680 n
= e
= d
= p
= q
= u
= np
= nq
= nu
= chunk_empty
;
683 switch (va_arg(args
, builder_part_t
))
685 case BUILD_RSA_MODULUS
:
686 n
= va_arg(args
, chunk_t
);
688 case BUILD_RSA_PUB_EXP
:
689 e
= va_arg(args
, chunk_t
);
691 case BUILD_RSA_PRIV_EXP
:
692 d
= va_arg(args
, chunk_t
);
694 case BUILD_RSA_PRIME1
:
695 /* swap p and q, gcrypt expects p < q */
696 q
= va_arg(args
, chunk_t
);
698 case BUILD_RSA_PRIME2
:
699 p
= va_arg(args
, chunk_t
);
703 /* not required for gcrypt */
704 va_arg(args
, chunk_t
);
706 case BUILD_RSA_COEFF
:
707 u
= va_arg(args
, chunk_t
);
716 if (!p
.len
|| !q
.len
|| !u
.len
)
718 if (!calculate_pqu(n
, e
, d
, &np
, &nq
, &nu
))
726 this = create_empty();
727 err
= gcry_sexp_build(&this->key
, NULL
,
728 "(private-key(rsa(n %b)(e %b)(d %b)(p %b)(q %b)(u %b)))",
729 n
.len
, n
.ptr
, e
.len
, e
.ptr
, d
.len
, d
.ptr
,
730 p
.len
, p
.ptr
, q
.len
, q
.ptr
, u
.len
, u
.ptr
);
737 DBG1(DBG_LIB
, "loading private key failed: %s", gpg_strerror(err
));
741 err
= gcry_pk_testkey(this->key
);
744 DBG1(DBG_LIB
, "private key sanity check failed: %s", gpg_strerror(err
));
748 return &this->public;