2 * Copyright (C) 2005-2009 Martin Willi
3 * Hochschule fuer Technik Rapperswil
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>.
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
18 #include "gcrypt_rsa_private_key.h"
22 #include <asn1/asn1.h>
23 #include <asn1/asn1_parser.h>
25 typedef struct private_gcrypt_rsa_private_key_t private_gcrypt_rsa_private_key_t
;
28 * Private data of a gcrypt_rsa_private_key_t object.
30 struct private_gcrypt_rsa_private_key_t
{
35 gcrypt_rsa_private_key_t
public;
38 * gcrypt S-expression representing an RSA key
43 * Keyid formed as a SHA-1 hash of a publicKey object
45 identification_t
* keyid
;
48 * Keyid formed as a SHA-1 hash of a publicKeyInfo object
50 identification_t
* keyid_info
;
59 * Implemented in gcrypt_rsa_public_key.c
61 public_key_t
*gcrypt_rsa_public_key_create_from_sexp(gcry_sexp_t key
);
64 * find a token in a S-expression
66 chunk_t
gcrypt_rsa_find_token(gcry_sexp_t sexp
, char *name
)
69 chunk_t data
= chunk_empty
;
71 token
= gcry_sexp_find_token(sexp
, name
, 1);
74 data
.ptr
= (char*)gcry_sexp_nth_data(token
, 1, &data
.len
);
79 data
= chunk_clone(data
);
80 gcry_sexp_release(token
);
86 * Sign a chunk of data with direct PKCS#1 encoding, no hash OID
88 static bool sign_raw(private_gcrypt_rsa_private_key_t
*this,
89 chunk_t data
, chunk_t
*signature
)
96 /* EM = 0x00 || 0x01 || PS || 0x00 || T
97 * PS = 0xFF padding, with length to fill em
100 k
= gcry_pk_get_nbits(this->key
) / 8;
101 if (data
.len
> k
- 3)
106 memset(em
.ptr
, 0xFF, em
.len
);
109 em
.ptr
[em
.len
- data
.len
- 1] = 0x00;
110 memcpy(em
.ptr
+ em
.len
- data
.len
, data
.ptr
, data
.len
);
112 err
= gcry_sexp_build(&in
, NULL
, "(data(flags raw)(value %b))",
117 DBG1("building signature S-expression failed: %s", gpg_strerror(err
));
120 err
= gcry_pk_sign(&out
, in
, this->key
);
121 gcry_sexp_release(in
);
124 DBG1("creating pkcs1 signature failed: %s", gpg_strerror(err
));
127 *signature
= gcrypt_rsa_find_token(out
, "s");
128 gcry_sexp_release(out
);
129 return !!signature
->len
;
133 * Sign a chunk of data using hashing and PKCS#1 encoding
135 static bool sign_pkcs1(private_gcrypt_rsa_private_key_t
*this,
136 hash_algorithm_t hash_algorithm
, char *hash_name
,
137 chunk_t data
, chunk_t
*signature
)
145 hash_oid
= hasher_algorithm_to_oid(hash_algorithm
);
146 if (hash_oid
== OID_UNKNOWN
)
150 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, hash_algorithm
);
155 hasher
->allocate_hash(hasher
, data
, &hash
);
156 hasher
->destroy(hasher
);
158 err
= gcry_sexp_build(&in
, NULL
, "(data(flags pkcs1)(hash %s %b))",
159 hash_name
, hash
.len
, hash
.ptr
);
163 DBG1("building signature S-expression failed: %s", gpg_strerror(err
));
166 err
= gcry_pk_sign(&out
, in
, this->key
);
167 gcry_sexp_release(in
);
170 DBG1("creating pkcs1 signature failed: %s", gpg_strerror(err
));
173 *signature
= gcrypt_rsa_find_token(out
, "s");
174 gcry_sexp_release(out
);
175 return !!signature
->len
;
179 * Implementation of gcrypt_rsa_private_key.destroy.
181 static key_type_t
get_type(private_gcrypt_rsa_private_key_t
*this)
187 * Implementation of gcrypt_rsa_private_key.destroy.
189 static bool sign(private_gcrypt_rsa_private_key_t
*this, signature_scheme_t scheme
,
190 chunk_t data
, chunk_t
*sig
)
194 case SIGN_RSA_EMSA_PKCS1_NULL
:
195 return sign_raw(this, data
, sig
);
196 case SIGN_RSA_EMSA_PKCS1_SHA1
:
197 return sign_pkcs1(this, HASH_SHA1
, "sha1", data
, sig
);
198 case SIGN_RSA_EMSA_PKCS1_SHA256
:
199 return sign_pkcs1(this, HASH_SHA256
, "sha256", data
, sig
);
200 case SIGN_RSA_EMSA_PKCS1_SHA384
:
201 return sign_pkcs1(this, HASH_SHA384
, "sha384", data
, sig
);
202 case SIGN_RSA_EMSA_PKCS1_SHA512
:
203 return sign_pkcs1(this, HASH_SHA512
, "sha512", data
, sig
);
204 case SIGN_RSA_EMSA_PKCS1_MD5
:
205 return sign_pkcs1(this, HASH_MD5
, "md5", data
, sig
);
207 DBG1("signature scheme %N not supported in RSA",
208 signature_scheme_names
, scheme
);
214 * Implementation of gcrypt_rsa_private_key.destroy.
216 static bool decrypt(private_gcrypt_rsa_private_key_t
*this,
217 chunk_t encrypted
, chunk_t
*plain
)
224 err
= gcry_sexp_build(&in
, NULL
, "(enc-val(flags)(rsa(a %b)))",
225 encrypted
.len
, encrypted
.ptr
);
228 DBG1("building decryption S-expression failed: %s", gpg_strerror(err
));
231 err
= gcry_pk_decrypt(&out
, in
, this->key
);
232 gcry_sexp_release(in
);
235 DBG1("decrypting pkcs1 data failed: %s", gpg_strerror(err
));
238 padded
.ptr
= (u_char
*)gcry_sexp_nth_data(out
, 1, &padded
.len
);
239 /* result is padded, but gcrypt strips leading zero:
240 * 00 | 02 | RANDOM | 00 | DATA */
241 if (padded
.ptr
&& padded
.len
> 2 && padded
.ptr
[0] == 0x02)
243 pos
= memchr(padded
.ptr
, 0x00, padded
.len
- 1);
247 *plain
= chunk_clone(chunk_create(
248 pos
, padded
.len
- (pos
- padded
.ptr
)));
251 gcry_sexp_release(out
);
254 DBG1("decrypted data has invalid pkcs1 padding");
261 * Implementation of gcrypt_rsa_private_key.get_keysize.
263 static size_t get_keysize(private_gcrypt_rsa_private_key_t
*this)
265 return gcry_pk_get_nbits(this->key
) / 8;
269 * Implementation of gcrypt_rsa_private_key.destroy.
271 static identification_t
* get_id(private_gcrypt_rsa_private_key_t
*this,
276 case ID_PUBKEY_INFO_SHA1
:
277 return this->keyid_info
;
286 * Implementation of gcrypt_rsa_private_key.get_public_key.
288 static public_key_t
* get_public_key(private_gcrypt_rsa_private_key_t
*this)
290 return gcrypt_rsa_public_key_create_from_sexp(this->key
);
294 * Implementation of gcrypt_rsa_private_key.equals.
296 static bool equals(private_gcrypt_rsa_private_key_t
*this, private_key_t
*other
)
298 identification_t
*keyid
;
300 if (&this->public.interface
== other
)
304 if (other
->get_type(other
) != KEY_RSA
)
308 keyid
= other
->get_id(other
, ID_PUBKEY_SHA1
);
309 if (keyid
&& keyid
->equals(keyid
, this->keyid
))
313 keyid
= other
->get_id(other
, ID_PUBKEY_INFO_SHA1
);
314 if (keyid
&& keyid
->equals(keyid
, this->keyid_info
))
322 * Implementation of gcrypt_rsa_private_key.belongs_to.
324 static bool belongs_to(private_gcrypt_rsa_private_key_t
*this,
325 public_key_t
*public)
327 identification_t
*keyid
;
329 if (public->get_type(public) != KEY_RSA
)
333 keyid
= public->get_id(public, ID_PUBKEY_SHA1
);
334 if (keyid
&& keyid
->equals(keyid
, this->keyid
))
338 keyid
= public->get_id(public, ID_PUBKEY_INFO_SHA1
);
339 if (keyid
&& keyid
->equals(keyid
, this->keyid_info
))
347 * Implementation of private_key_t.get_encoding.
349 static chunk_t
get_encoding(private_gcrypt_rsa_private_key_t
*this)
351 chunk_t cp
, cq
, cd
, cexp1
= chunk_empty
, cexp2
= chunk_empty
;
352 gcry_mpi_t p
= NULL
, q
= NULL
, d
= NULL
, exp1
, exp2
;
355 /* p and q are swapped, gcrypt expects p < q */
356 cp
= gcrypt_rsa_find_token(this->key
, "q");
357 cq
= gcrypt_rsa_find_token(this->key
, "p");
358 cd
= gcrypt_rsa_find_token(this->key
, "d");
360 err
= gcry_mpi_scan(&p
, GCRYMPI_FMT_USG
, cp
.ptr
, cp
.len
, NULL
)
361 | gcry_mpi_scan(&q
, GCRYMPI_FMT_USG
, cq
.ptr
, cq
.len
, NULL
)
362 | gcry_mpi_scan(&d
, GCRYMPI_FMT_USG
, cd
.ptr
, cd
.len
, NULL
);
371 DBG1("scanning mpi for export failed: %s", gpg_strerror(err
));
375 gcry_mpi_sub_ui(p
, p
, 1);
376 exp1
= gcry_mpi_new(gcry_pk_get_nbits(this->key
));
377 gcry_mpi_mod(exp1
, d
, p
);
380 gcry_mpi_sub_ui(q
, q
, 1);
381 exp2
= gcry_mpi_new(gcry_pk_get_nbits(this->key
));
382 gcry_mpi_mod(exp1
, d
, q
);
385 err
= gcry_mpi_aprint(GCRYMPI_FMT_USG
, &cexp1
.ptr
, &cexp1
.len
, exp1
)
386 | gcry_mpi_aprint(GCRYMPI_FMT_USG
, &cexp2
.ptr
, &cexp2
.len
, exp2
);
389 gcry_mpi_release(exp1
);
390 gcry_mpi_release(exp2
);
394 DBG1("printing mpi for export failed: %s", gpg_strerror(err
));
403 return asn1_wrap(ASN1_SEQUENCE
, "cmmmmmmmm", ASN1_INTEGER_0
,
404 asn1_integer("m", gcrypt_rsa_find_token(this->key
, "n")),
405 asn1_integer("m", gcrypt_rsa_find_token(this->key
, "e")),
406 asn1_integer("m", cd
),
407 asn1_integer("m", cp
),
408 asn1_integer("m", cq
),
409 asn1_integer("m", cexp1
),
410 asn1_integer("m", cexp2
),
411 asn1_integer("m", gcrypt_rsa_find_token(this->key
, "u")));
415 * Implementation of gcrypt_rsa_private_key.get_ref.
417 static private_key_t
* get_ref(private_gcrypt_rsa_private_key_t
*this)
420 return &this->public.interface
;
424 * Implementation of gcrypt_rsa_private_key.destroy.
426 static void destroy(private_gcrypt_rsa_private_key_t
*this)
428 if (ref_put(&this->ref
))
430 DESTROY_IF(this->keyid
);
431 DESTROY_IF(this->keyid_info
);
432 gcry_sexp_release(this->key
);
438 * Internal generic constructor
440 static private_gcrypt_rsa_private_key_t
*gcrypt_rsa_private_key_create_empty()
442 private_gcrypt_rsa_private_key_t
*this = malloc_thing(private_gcrypt_rsa_private_key_t
);
444 this->public.interface
.get_type
= (key_type_t (*)(private_key_t
*this))get_type
;
445 this->public.interface
.sign
= (bool (*)(private_key_t
*this, signature_scheme_t scheme
, chunk_t data
, chunk_t
*signature
))sign
;
446 this->public.interface
.decrypt
= (bool (*)(private_key_t
*this, chunk_t crypto
, chunk_t
*plain
))decrypt
;
447 this->public.interface
.get_keysize
= (size_t (*) (private_key_t
*this))get_keysize
;
448 this->public.interface
.get_id
= (identification_t
* (*) (private_key_t
*this,id_type_t
))get_id
;
449 this->public.interface
.get_public_key
= (public_key_t
* (*)(private_key_t
*this))get_public_key
;
450 this->public.interface
.equals
= (bool (*) (private_key_t
*, private_key_t
*))equals
;
451 this->public.interface
.belongs_to
= (bool (*) (private_key_t
*this, public_key_t
*public))belongs_to
;
452 this->public.interface
.get_encoding
= (chunk_t(*)(private_key_t
*))get_encoding
;
453 this->public.interface
.get_ref
= (private_key_t
* (*)(private_key_t
*this))get_ref
;
454 this->public.interface
.destroy
= (void (*)(private_key_t
*this))destroy
;
458 this->keyid_info
= NULL
;
465 * build the keyids of a private/public key
467 bool gcrypt_rsa_build_keyids(gcry_sexp_t key
, identification_t
**keyid
,
468 identification_t
**keyid_info
)
470 chunk_t publicKeyInfo
, publicKey
, hash
;
473 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
476 DBG1("SHA1 hash algorithm not supported, unable to use RSA");
479 publicKey
= asn1_wrap(ASN1_SEQUENCE
, "mm",
480 asn1_integer("m", gcrypt_rsa_find_token(key
, "n")),
481 asn1_integer("m", gcrypt_rsa_find_token(key
, "e")));
482 hasher
->allocate_hash(hasher
, publicKey
, &hash
);
483 *keyid
= identification_create_from_encoding(ID_PUBKEY_SHA1
, hash
);
486 publicKeyInfo
= asn1_wrap(ASN1_SEQUENCE
, "cm",
487 asn1_algorithmIdentifier(OID_RSA_ENCRYPTION
),
488 asn1_bitstring("m", publicKey
));
489 hasher
->allocate_hash(hasher
, publicKeyInfo
, &hash
);
490 *keyid_info
= identification_create_from_encoding(ID_PUBKEY_INFO_SHA1
, hash
);
493 hasher
->destroy(hasher
);
494 chunk_free(&publicKeyInfo
);
500 * Generate an RSA key of specified key size
502 static gcrypt_rsa_private_key_t
*generate(size_t key_size
)
504 private_gcrypt_rsa_private_key_t
*this;
505 gcry_sexp_t param
, key
;
508 err
= gcry_sexp_build(¶m
, NULL
, "(genkey(rsa(nbits %d)))", key_size
);
511 DBG1("building S-expression failed: %s", gpg_strerror(err
));
515 err
= gcry_pk_genkey(&key
, param
);
516 gcry_sexp_release(param
);
519 DBG1("generating RSA key failed: %s", gpg_strerror(err
));
522 this = gcrypt_rsa_private_key_create_empty();
525 if (!gcrypt_rsa_build_keyids(this->key
, &this->keyid
, &this->keyid_info
))
531 return &this->public;
535 * ASN.1 definition of a PKCS#1 RSA private key
537 static const asn1Object_t privkeyObjects
[] = {
538 { 0, "RSAPrivateKey", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
539 { 1, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 1 */
540 { 1, "modulus", ASN1_INTEGER
, ASN1_BODY
}, /* 2 */
541 { 1, "publicExponent", ASN1_INTEGER
, ASN1_BODY
}, /* 3 */
542 { 1, "privateExponent", ASN1_INTEGER
, ASN1_BODY
}, /* 4 */
543 { 1, "prime1", ASN1_INTEGER
, ASN1_BODY
}, /* 5 */
544 { 1, "prime2", ASN1_INTEGER
, ASN1_BODY
}, /* 6 */
545 { 1, "exponent1", ASN1_INTEGER
, ASN1_BODY
}, /* 7 */
546 { 1, "exponent2", ASN1_INTEGER
, ASN1_BODY
}, /* 8 */
547 { 1, "coefficient", ASN1_INTEGER
, ASN1_BODY
}, /* 9 */
548 { 1, "otherPrimeInfos", ASN1_SEQUENCE
, ASN1_OPT
|
549 ASN1_LOOP
}, /* 10 */
550 { 2, "otherPrimeInfo", ASN1_SEQUENCE
, ASN1_NONE
}, /* 11 */
551 { 3, "prime", ASN1_INTEGER
, ASN1_BODY
}, /* 12 */
552 { 3, "exponent", ASN1_INTEGER
, ASN1_BODY
}, /* 13 */
553 { 3, "coefficient", ASN1_INTEGER
, ASN1_BODY
}, /* 14 */
554 { 1, "end opt or loop", ASN1_EOC
, ASN1_END
}, /* 15 */
555 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
557 #define PRIV_KEY_VERSION 1
558 #define PRIV_KEY_MODULUS 2
559 #define PRIV_KEY_PUB_EXP 3
560 #define PRIV_KEY_PRIV_EXP 4
561 #define PRIV_KEY_PRIME1 5
562 #define PRIV_KEY_PRIME2 6
563 #define PRIV_KEY_EXP1 7
564 #define PRIV_KEY_EXP2 8
565 #define PRIV_KEY_COEFF 9
568 * load private key from a ASN1 encoded blob
570 static gcrypt_rsa_private_key_t
*load(chunk_t blob
)
572 private_gcrypt_rsa_private_key_t
*this;
573 asn1_parser_t
*parser
;
576 bool success
= FALSE
;
577 chunk_t n
, e
, d
, u
, p
, q
;
580 n
= e
= d
= u
= p
= q
= chunk_empty
;
582 parser
= asn1_parser_create(privkeyObjects
, blob
);
583 parser
->set_flags(parser
, FALSE
, TRUE
);
585 while (parser
->iterate(parser
, &objectID
, &object
))
589 case PRIV_KEY_VERSION
:
590 if (object
.len
> 0 && *object
.ptr
!= 0)
595 case PRIV_KEY_MODULUS
:
598 case PRIV_KEY_PUB_EXP
:
601 case PRIV_KEY_PRIV_EXP
:
604 case PRIV_KEY_PRIME1
:
605 /* p and q are swapped, as gcrypt expects p < q */
608 case PRIV_KEY_PRIME2
:
619 success
= parser
->success(parser
);
622 parser
->destroy(parser
);
629 this = gcrypt_rsa_private_key_create_empty();
630 err
= gcry_sexp_build(&this->key
, NULL
,
631 "(private-key(rsa(n %b)(e %b)(d %b)(p %b)(q %b)(u %b)))",
632 n
.len
, n
.ptr
, e
.len
, e
.ptr
, d
.len
, d
.ptr
,
633 p
.len
, p
.ptr
, q
.len
, q
.ptr
, u
.len
, u
.ptr
);
636 DBG1("loading private key failed: %s", gpg_strerror(err
));
640 err
= gcry_pk_testkey(this->key
);
643 DBG1("private key sanity check failed: %s", gpg_strerror(err
));
647 if (!gcrypt_rsa_build_keyids(this->key
, &this->keyid
, &this->keyid_info
))
652 return &this->public;
655 typedef struct private_builder_t private_builder_t
;
658 * Builder implementation for key loading/generation
660 struct private_builder_t
{
661 /** implements the builder interface */
663 /** loaded/generated private key */
664 gcrypt_rsa_private_key_t
*key
;
668 * Implementation of builder_t.build
670 static gcrypt_rsa_private_key_t
*build(private_builder_t
*this)
672 gcrypt_rsa_private_key_t
*key
= this->key
;
679 * Implementation of builder_t.add
681 static void add(private_builder_t
*this, builder_part_t part
, ...)
689 case BUILD_BLOB_ASN1_DER
:
691 va_start(args
, part
);
692 this->key
= load(va_arg(args
, chunk_t
));
698 va_start(args
, part
);
699 this->key
= generate(va_arg(args
, u_int
));
709 destroy((private_gcrypt_rsa_private_key_t
*)this->key
);
711 builder_cancel(&this->public);
715 * Builder construction function
717 builder_t
*gcrypt_rsa_private_key_builder(key_type_t type
)
719 private_builder_t
*this;
726 this = malloc_thing(private_builder_t
);
729 this->public.add
= (void(*)(builder_t
*this, builder_part_t part
, ...))add
;
730 this->public.build
= (void*(*)(builder_t
*this))build
;
732 return &this->public;