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 crypto
, chunk_t
*plain
)
219 DBG1("RSA private key decryption not implemented");
224 * Implementation of gcrypt_rsa_private_key.get_keysize.
226 static size_t get_keysize(private_gcrypt_rsa_private_key_t
*this)
228 return gcry_pk_get_nbits(this->key
) / 8;
232 * Implementation of gcrypt_rsa_private_key.destroy.
234 static identification_t
* get_id(private_gcrypt_rsa_private_key_t
*this,
239 case ID_PUBKEY_INFO_SHA1
:
240 return this->keyid_info
;
249 * Implementation of gcrypt_rsa_private_key.get_public_key.
251 static public_key_t
* get_public_key(private_gcrypt_rsa_private_key_t
*this)
253 return gcrypt_rsa_public_key_create_from_sexp(this->key
);
257 * Implementation of gcrypt_rsa_private_key.equals.
259 static bool equals(private_gcrypt_rsa_private_key_t
*this, private_key_t
*other
)
261 identification_t
*keyid
;
263 if (&this->public.interface
== other
)
267 if (other
->get_type(other
) != KEY_RSA
)
271 keyid
= other
->get_id(other
, ID_PUBKEY_SHA1
);
272 if (keyid
&& keyid
->equals(keyid
, this->keyid
))
276 keyid
= other
->get_id(other
, ID_PUBKEY_INFO_SHA1
);
277 if (keyid
&& keyid
->equals(keyid
, this->keyid_info
))
285 * Implementation of gcrypt_rsa_private_key.belongs_to.
287 static bool belongs_to(private_gcrypt_rsa_private_key_t
*this,
288 public_key_t
*public)
290 identification_t
*keyid
;
292 if (public->get_type(public) != KEY_RSA
)
296 keyid
= public->get_id(public, ID_PUBKEY_SHA1
);
297 if (keyid
&& keyid
->equals(keyid
, this->keyid
))
301 keyid
= public->get_id(public, ID_PUBKEY_INFO_SHA1
);
302 if (keyid
&& keyid
->equals(keyid
, this->keyid_info
))
310 * Implementation of private_key_t.get_encoding.
312 static chunk_t
get_encoding(private_gcrypt_rsa_private_key_t
*this)
314 chunk_t cp
, cq
, cd
, cexp1
= chunk_empty
, cexp2
= chunk_empty
;
315 gcry_mpi_t p
= NULL
, q
= NULL
, d
= NULL
, exp1
, exp2
;
318 /* p and q are swapped, gcrypt expects p < q */
319 cp
= gcrypt_rsa_find_token(this->key
, "q");
320 cq
= gcrypt_rsa_find_token(this->key
, "p");
321 cd
= gcrypt_rsa_find_token(this->key
, "d");
323 err
= gcry_mpi_scan(&p
, GCRYMPI_FMT_USG
, cp
.ptr
, cp
.len
, NULL
)
324 | gcry_mpi_scan(&q
, GCRYMPI_FMT_USG
, cq
.ptr
, cq
.len
, NULL
)
325 | gcry_mpi_scan(&d
, GCRYMPI_FMT_USG
, cd
.ptr
, cd
.len
, NULL
);
334 DBG1("scanning mpi for export failed: %s", gpg_strerror(err
));
338 gcry_mpi_sub_ui(p
, p
, 1);
339 exp1
= gcry_mpi_new(gcry_pk_get_nbits(this->key
));
340 gcry_mpi_mod(exp1
, d
, p
);
343 gcry_mpi_sub_ui(q
, q
, 1);
344 exp2
= gcry_mpi_new(gcry_pk_get_nbits(this->key
));
345 gcry_mpi_mod(exp1
, d
, q
);
348 err
= gcry_mpi_aprint(GCRYMPI_FMT_USG
, &cexp1
.ptr
, &cexp1
.len
, exp1
)
349 | gcry_mpi_aprint(GCRYMPI_FMT_USG
, &cexp2
.ptr
, &cexp2
.len
, exp2
);
352 gcry_mpi_release(exp1
);
353 gcry_mpi_release(exp2
);
357 DBG1("printing mpi for export failed: %s", gpg_strerror(err
));
366 return asn1_wrap(ASN1_SEQUENCE
, "cmmmmmmmm", ASN1_INTEGER_0
,
367 asn1_integer("m", gcrypt_rsa_find_token(this->key
, "n")),
368 asn1_integer("m", gcrypt_rsa_find_token(this->key
, "e")),
369 asn1_integer("m", cd
),
370 asn1_integer("m", cp
),
371 asn1_integer("m", cq
),
372 asn1_integer("m", cexp1
),
373 asn1_integer("m", cexp2
),
374 asn1_integer("m", gcrypt_rsa_find_token(this->key
, "u")));
378 * Implementation of gcrypt_rsa_private_key.get_ref.
380 static private_key_t
* get_ref(private_gcrypt_rsa_private_key_t
*this)
383 return &this->public.interface
;
387 * Implementation of gcrypt_rsa_private_key.destroy.
389 static void destroy(private_gcrypt_rsa_private_key_t
*this)
391 if (ref_put(&this->ref
))
393 DESTROY_IF(this->keyid
);
394 DESTROY_IF(this->keyid_info
);
395 gcry_sexp_release(this->key
);
401 * Internal generic constructor
403 static private_gcrypt_rsa_private_key_t
*gcrypt_rsa_private_key_create_empty()
405 private_gcrypt_rsa_private_key_t
*this = malloc_thing(private_gcrypt_rsa_private_key_t
);
407 this->public.interface
.get_type
= (key_type_t (*)(private_key_t
*this))get_type
;
408 this->public.interface
.sign
= (bool (*)(private_key_t
*this, signature_scheme_t scheme
, chunk_t data
, chunk_t
*signature
))sign
;
409 this->public.interface
.decrypt
= (bool (*)(private_key_t
*this, chunk_t crypto
, chunk_t
*plain
))decrypt
;
410 this->public.interface
.get_keysize
= (size_t (*) (private_key_t
*this))get_keysize
;
411 this->public.interface
.get_id
= (identification_t
* (*) (private_key_t
*this,id_type_t
))get_id
;
412 this->public.interface
.get_public_key
= (public_key_t
* (*)(private_key_t
*this))get_public_key
;
413 this->public.interface
.equals
= (bool (*) (private_key_t
*, private_key_t
*))equals
;
414 this->public.interface
.belongs_to
= (bool (*) (private_key_t
*this, public_key_t
*public))belongs_to
;
415 this->public.interface
.get_encoding
= (chunk_t(*)(private_key_t
*))get_encoding
;
416 this->public.interface
.get_ref
= (private_key_t
* (*)(private_key_t
*this))get_ref
;
417 this->public.interface
.destroy
= (void (*)(private_key_t
*this))destroy
;
421 this->keyid_info
= NULL
;
428 * build the keyids of a private/public key
430 bool gcrypt_rsa_build_keyids(gcry_sexp_t key
, identification_t
**keyid
,
431 identification_t
**keyid_info
)
433 chunk_t publicKeyInfo
, publicKey
, hash
;
436 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
439 DBG1("SHA1 hash algorithm not supported, unable to use RSA");
442 publicKey
= asn1_wrap(ASN1_SEQUENCE
, "mm",
443 asn1_integer("m", gcrypt_rsa_find_token(key
, "n")),
444 asn1_integer("m", gcrypt_rsa_find_token(key
, "e")));
445 hasher
->allocate_hash(hasher
, publicKey
, &hash
);
446 *keyid
= identification_create_from_encoding(ID_PUBKEY_SHA1
, hash
);
449 publicKeyInfo
= asn1_wrap(ASN1_SEQUENCE
, "cm",
450 asn1_algorithmIdentifier(OID_RSA_ENCRYPTION
),
451 asn1_bitstring("m", publicKey
));
452 hasher
->allocate_hash(hasher
, publicKeyInfo
, &hash
);
453 *keyid_info
= identification_create_from_encoding(ID_PUBKEY_INFO_SHA1
, hash
);
456 hasher
->destroy(hasher
);
457 chunk_free(&publicKeyInfo
);
463 * Generate an RSA key of specified key size
465 static gcrypt_rsa_private_key_t
*generate(size_t key_size
)
467 private_gcrypt_rsa_private_key_t
*this;
468 gcry_sexp_t param
, key
;
471 err
= gcry_sexp_build(¶m
, NULL
, "(genkey(rsa(nbits %d)))", key_size
);
474 DBG1("building S-expression failed: %s", gpg_strerror(err
));
478 err
= gcry_pk_genkey(&key
, param
);
479 gcry_sexp_release(param
);
482 DBG1("generating RSA key failed: %s", gpg_strerror(err
));
485 this = gcrypt_rsa_private_key_create_empty();
488 if (!gcrypt_rsa_build_keyids(this->key
, &this->keyid
, &this->keyid_info
))
494 return &this->public;
498 * ASN.1 definition of a PKCS#1 RSA private key
500 static const asn1Object_t privkeyObjects
[] = {
501 { 0, "RSAPrivateKey", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
502 { 1, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 1 */
503 { 1, "modulus", ASN1_INTEGER
, ASN1_BODY
}, /* 2 */
504 { 1, "publicExponent", ASN1_INTEGER
, ASN1_BODY
}, /* 3 */
505 { 1, "privateExponent", ASN1_INTEGER
, ASN1_BODY
}, /* 4 */
506 { 1, "prime1", ASN1_INTEGER
, ASN1_BODY
}, /* 5 */
507 { 1, "prime2", ASN1_INTEGER
, ASN1_BODY
}, /* 6 */
508 { 1, "exponent1", ASN1_INTEGER
, ASN1_BODY
}, /* 7 */
509 { 1, "exponent2", ASN1_INTEGER
, ASN1_BODY
}, /* 8 */
510 { 1, "coefficient", ASN1_INTEGER
, ASN1_BODY
}, /* 9 */
511 { 1, "otherPrimeInfos", ASN1_SEQUENCE
, ASN1_OPT
|
512 ASN1_LOOP
}, /* 10 */
513 { 2, "otherPrimeInfo", ASN1_SEQUENCE
, ASN1_NONE
}, /* 11 */
514 { 3, "prime", ASN1_INTEGER
, ASN1_BODY
}, /* 12 */
515 { 3, "exponent", ASN1_INTEGER
, ASN1_BODY
}, /* 13 */
516 { 3, "coefficient", ASN1_INTEGER
, ASN1_BODY
}, /* 14 */
517 { 1, "end opt or loop", ASN1_EOC
, ASN1_END
}, /* 15 */
518 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
520 #define PRIV_KEY_VERSION 1
521 #define PRIV_KEY_MODULUS 2
522 #define PRIV_KEY_PUB_EXP 3
523 #define PRIV_KEY_PRIV_EXP 4
524 #define PRIV_KEY_PRIME1 5
525 #define PRIV_KEY_PRIME2 6
526 #define PRIV_KEY_EXP1 7
527 #define PRIV_KEY_EXP2 8
528 #define PRIV_KEY_COEFF 9
531 * load private key from a ASN1 encoded blob
533 static gcrypt_rsa_private_key_t
*load(chunk_t blob
)
535 private_gcrypt_rsa_private_key_t
*this;
536 asn1_parser_t
*parser
;
539 bool success
= FALSE
;
540 chunk_t n
, e
, d
, u
, p
, q
;
543 parser
= asn1_parser_create(privkeyObjects
, blob
);
544 parser
->set_flags(parser
, FALSE
, TRUE
);
546 while (parser
->iterate(parser
, &objectID
, &object
))
550 case PRIV_KEY_VERSION
:
551 if (object
.len
> 0 && *object
.ptr
!= 0)
556 case PRIV_KEY_MODULUS
:
559 case PRIV_KEY_PUB_EXP
:
562 case PRIV_KEY_PRIV_EXP
:
565 case PRIV_KEY_PRIME1
:
566 /* p and q are swapped, as gcrypt expects p < q */
569 case PRIV_KEY_PRIME2
:
580 success
= parser
->success(parser
);
583 parser
->destroy(parser
);
590 this = gcrypt_rsa_private_key_create_empty();
591 err
= gcry_sexp_build(&this->key
, NULL
,
592 "(private-key(rsa(n %b)(e %b)(d %b)(p %b)(q %b)(u %b)))",
593 n
.len
, n
.ptr
, e
.len
, e
.ptr
, d
.len
, d
.ptr
,
594 p
.len
, p
.ptr
, q
.len
, q
.ptr
, u
.len
, u
.ptr
);
597 DBG1("loading private key failed: %s", gpg_strerror(err
));
601 err
= gcry_pk_testkey(this->key
);
604 DBG1("private key sanity check failed: %s", gpg_strerror(err
));
608 if (!gcrypt_rsa_build_keyids(this->key
, &this->keyid
, &this->keyid_info
))
613 return &this->public;
616 typedef struct private_builder_t private_builder_t
;
619 * Builder implementation for key loading/generation
621 struct private_builder_t
{
622 /** implements the builder interface */
624 /** loaded/generated private key */
625 gcrypt_rsa_private_key_t
*key
;
629 * Implementation of builder_t.build
631 static gcrypt_rsa_private_key_t
*build(private_builder_t
*this)
633 gcrypt_rsa_private_key_t
*key
= this->key
;
640 * Implementation of builder_t.add
642 static void add(private_builder_t
*this, builder_part_t part
, ...)
650 case BUILD_BLOB_ASN1_DER
:
652 va_start(args
, part
);
653 this->key
= load(va_arg(args
, chunk_t
));
659 va_start(args
, part
);
660 this->key
= generate(va_arg(args
, u_int
));
670 destroy((private_gcrypt_rsa_private_key_t
*)this->key
);
672 builder_cancel(&this->public);
676 * Builder construction function
678 builder_t
*gcrypt_rsa_private_key_builder(key_type_t type
)
680 private_builder_t
*this;
687 this = malloc_thing(private_builder_t
);
690 this->public.add
= (void(*)(builder_t
*this, builder_part_t part
, ...))add
;
691 this->public.build
= (void*(*)(builder_t
*this))build
;
693 return &this->public;