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. If a key is given, its length is used to
65 * pad the output to a given length.
67 chunk_t
gcrypt_rsa_find_token(gcry_sexp_t sexp
, char *name
, gcry_sexp_t key
)
70 chunk_t data
= chunk_empty
, tmp
;
73 token
= gcry_sexp_find_token(sexp
, name
, 1);
76 data
.ptr
= (char*)gcry_sexp_nth_data(token
, 1, &data
.len
);
85 /* gcrypt might return more bytes than necessary. Truncate
86 * to key lenght if key given, or prepend zeros if needed */
87 len
= gcry_pk_get_nbits(key
);
88 len
= len
/ 8 + (len
% 8 ? 1 : 0);
91 tmp
= chunk_alloc(len
);
93 memset(tmp
.ptr
, 0, tmp
.len
- len
);
94 memcpy(tmp
.ptr
+ len
, data
.ptr
, data
.len
);
97 else if (len
< data
.len
)
99 data
= chunk_clone(chunk_skip(data
, data
.len
- len
));
103 data
= chunk_clone(data
);
108 data
= chunk_clone(data
);
111 gcry_sexp_release(token
);
117 * Sign a chunk of data with direct PKCS#1 encoding, no hash OID
119 static bool sign_raw(private_gcrypt_rsa_private_key_t
*this,
120 chunk_t data
, chunk_t
*signature
)
127 /* EM = 0x00 || 0x01 || PS || 0x00 || T
128 * PS = 0xFF padding, with length to fill em
131 k
= gcry_pk_get_nbits(this->key
) / 8;
132 if (data
.len
> k
- 3)
137 memset(em
.ptr
, 0xFF, em
.len
);
140 em
.ptr
[em
.len
- data
.len
- 1] = 0x00;
141 memcpy(em
.ptr
+ em
.len
- data
.len
, data
.ptr
, data
.len
);
143 err
= gcry_sexp_build(&in
, NULL
, "(data(flags raw)(value %b))",
148 DBG1("building signature S-expression failed: %s", gpg_strerror(err
));
151 err
= gcry_pk_sign(&out
, in
, this->key
);
152 gcry_sexp_release(in
);
155 DBG1("creating pkcs1 signature failed: %s", gpg_strerror(err
));
158 *signature
= gcrypt_rsa_find_token(out
, "s", this->key
);
159 gcry_sexp_release(out
);
160 return !!signature
->len
;
164 * Sign a chunk of data using hashing and PKCS#1 encoding
166 static bool sign_pkcs1(private_gcrypt_rsa_private_key_t
*this,
167 hash_algorithm_t hash_algorithm
, char *hash_name
,
168 chunk_t data
, chunk_t
*signature
)
176 hash_oid
= hasher_algorithm_to_oid(hash_algorithm
);
177 if (hash_oid
== OID_UNKNOWN
)
181 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, hash_algorithm
);
186 hasher
->allocate_hash(hasher
, data
, &hash
);
187 hasher
->destroy(hasher
);
189 err
= gcry_sexp_build(&in
, NULL
, "(data(flags pkcs1)(hash %s %b))",
190 hash_name
, hash
.len
, hash
.ptr
);
194 DBG1("building signature S-expression failed: %s", gpg_strerror(err
));
197 err
= gcry_pk_sign(&out
, in
, this->key
);
198 gcry_sexp_release(in
);
201 DBG1("creating pkcs1 signature failed: %s", gpg_strerror(err
));
204 *signature
= gcrypt_rsa_find_token(out
, "s", this->key
);
205 gcry_sexp_release(out
);
206 return !!signature
->len
;
210 * Implementation of gcrypt_rsa_private_key.destroy.
212 static key_type_t
get_type(private_gcrypt_rsa_private_key_t
*this)
218 * Implementation of gcrypt_rsa_private_key.destroy.
220 static bool sign(private_gcrypt_rsa_private_key_t
*this, signature_scheme_t scheme
,
221 chunk_t data
, chunk_t
*sig
)
225 case SIGN_RSA_EMSA_PKCS1_NULL
:
226 return sign_raw(this, data
, sig
);
227 case SIGN_RSA_EMSA_PKCS1_SHA1
:
228 return sign_pkcs1(this, HASH_SHA1
, "sha1", data
, sig
);
229 case SIGN_RSA_EMSA_PKCS1_SHA224
:
230 return sign_pkcs1(this, HASH_SHA224
, "sha224", data
, sig
);
231 case SIGN_RSA_EMSA_PKCS1_SHA256
:
232 return sign_pkcs1(this, HASH_SHA256
, "sha256", data
, sig
);
233 case SIGN_RSA_EMSA_PKCS1_SHA384
:
234 return sign_pkcs1(this, HASH_SHA384
, "sha384", data
, sig
);
235 case SIGN_RSA_EMSA_PKCS1_SHA512
:
236 return sign_pkcs1(this, HASH_SHA512
, "sha512", data
, sig
);
237 case SIGN_RSA_EMSA_PKCS1_MD5
:
238 return sign_pkcs1(this, HASH_MD5
, "md5", data
, sig
);
240 DBG1("signature scheme %N not supported in RSA",
241 signature_scheme_names
, scheme
);
247 * Implementation of gcrypt_rsa_private_key.destroy.
249 static bool decrypt(private_gcrypt_rsa_private_key_t
*this,
250 chunk_t encrypted
, chunk_t
*plain
)
257 err
= gcry_sexp_build(&in
, NULL
, "(enc-val(flags)(rsa(a %b)))",
258 encrypted
.len
, encrypted
.ptr
);
261 DBG1("building decryption S-expression failed: %s", gpg_strerror(err
));
264 err
= gcry_pk_decrypt(&out
, in
, this->key
);
265 gcry_sexp_release(in
);
268 DBG1("decrypting pkcs1 data failed: %s", gpg_strerror(err
));
271 padded
.ptr
= (u_char
*)gcry_sexp_nth_data(out
, 1, &padded
.len
);
272 /* result is padded, but gcrypt strips leading zero:
273 * 00 | 02 | RANDOM | 00 | DATA */
274 if (padded
.ptr
&& padded
.len
> 2 && padded
.ptr
[0] == 0x02)
276 pos
= memchr(padded
.ptr
, 0x00, padded
.len
- 1);
280 *plain
= chunk_clone(chunk_create(
281 pos
, padded
.len
- (pos
- padded
.ptr
)));
284 gcry_sexp_release(out
);
287 DBG1("decrypted data has invalid pkcs1 padding");
294 * Implementation of gcrypt_rsa_private_key.get_keysize.
296 static size_t get_keysize(private_gcrypt_rsa_private_key_t
*this)
298 return gcry_pk_get_nbits(this->key
) / 8;
302 * Implementation of gcrypt_rsa_private_key.destroy.
304 static identification_t
* get_id(private_gcrypt_rsa_private_key_t
*this,
309 case ID_PUBKEY_INFO_SHA1
:
310 return this->keyid_info
;
319 * Implementation of gcrypt_rsa_private_key.get_public_key.
321 static public_key_t
* get_public_key(private_gcrypt_rsa_private_key_t
*this)
323 return gcrypt_rsa_public_key_create_from_sexp(this->key
);
327 * Implementation of gcrypt_rsa_private_key.equals.
329 static bool equals(private_gcrypt_rsa_private_key_t
*this, private_key_t
*other
)
331 identification_t
*keyid
;
333 if (&this->public.interface
== other
)
337 if (other
->get_type(other
) != KEY_RSA
)
341 keyid
= other
->get_id(other
, ID_PUBKEY_SHA1
);
342 if (keyid
&& keyid
->equals(keyid
, this->keyid
))
346 keyid
= other
->get_id(other
, ID_PUBKEY_INFO_SHA1
);
347 if (keyid
&& keyid
->equals(keyid
, this->keyid_info
))
355 * Implementation of gcrypt_rsa_private_key.belongs_to.
357 static bool belongs_to(private_gcrypt_rsa_private_key_t
*this,
358 public_key_t
*public)
360 identification_t
*keyid
;
362 if (public->get_type(public) != KEY_RSA
)
366 keyid
= public->get_id(public, ID_PUBKEY_SHA1
);
367 if (keyid
&& keyid
->equals(keyid
, this->keyid
))
371 keyid
= public->get_id(public, ID_PUBKEY_INFO_SHA1
);
372 if (keyid
&& keyid
->equals(keyid
, this->keyid_info
))
380 * Implementation of private_key_t.get_encoding.
382 static chunk_t
get_encoding(private_gcrypt_rsa_private_key_t
*this)
384 chunk_t cp
, cq
, cd
, cexp1
= chunk_empty
, cexp2
= chunk_empty
;
385 gcry_mpi_t p
= NULL
, q
= NULL
, d
= NULL
, exp1
, exp2
;
388 /* p and q are swapped, gcrypt expects p < q */
389 cp
= gcrypt_rsa_find_token(this->key
, "q", NULL
);
390 cq
= gcrypt_rsa_find_token(this->key
, "p", NULL
);
391 cd
= gcrypt_rsa_find_token(this->key
, "d", NULL
);
393 err
= gcry_mpi_scan(&p
, GCRYMPI_FMT_USG
, cp
.ptr
, cp
.len
, NULL
)
394 | gcry_mpi_scan(&q
, GCRYMPI_FMT_USG
, cq
.ptr
, cq
.len
, NULL
)
395 | gcry_mpi_scan(&d
, GCRYMPI_FMT_USG
, cd
.ptr
, cd
.len
, NULL
);
404 DBG1("scanning mpi for export failed: %s", gpg_strerror(err
));
408 gcry_mpi_sub_ui(p
, p
, 1);
409 exp1
= gcry_mpi_new(gcry_pk_get_nbits(this->key
));
410 gcry_mpi_mod(exp1
, d
, p
);
413 gcry_mpi_sub_ui(q
, q
, 1);
414 exp2
= gcry_mpi_new(gcry_pk_get_nbits(this->key
));
415 gcry_mpi_mod(exp1
, d
, q
);
418 err
= gcry_mpi_aprint(GCRYMPI_FMT_USG
, &cexp1
.ptr
, &cexp1
.len
, exp1
)
419 | gcry_mpi_aprint(GCRYMPI_FMT_USG
, &cexp2
.ptr
, &cexp2
.len
, exp2
);
422 gcry_mpi_release(exp1
);
423 gcry_mpi_release(exp2
);
427 DBG1("printing mpi for export failed: %s", gpg_strerror(err
));
436 return asn1_wrap(ASN1_SEQUENCE
, "cmmmmmmmm", ASN1_INTEGER_0
,
437 asn1_integer("m", gcrypt_rsa_find_token(this->key
, "n", NULL
)),
438 asn1_integer("m", gcrypt_rsa_find_token(this->key
, "e", NULL
)),
439 asn1_integer("m", cd
),
440 asn1_integer("m", cp
),
441 asn1_integer("m", cq
),
442 asn1_integer("m", cexp1
),
443 asn1_integer("m", cexp2
),
444 asn1_integer("m", gcrypt_rsa_find_token(this->key
, "u", NULL
)));
448 * Implementation of gcrypt_rsa_private_key.get_ref.
450 static private_key_t
* get_ref(private_gcrypt_rsa_private_key_t
*this)
453 return &this->public.interface
;
457 * Implementation of gcrypt_rsa_private_key.destroy.
459 static void destroy(private_gcrypt_rsa_private_key_t
*this)
461 if (ref_put(&this->ref
))
463 DESTROY_IF(this->keyid
);
464 DESTROY_IF(this->keyid_info
);
465 gcry_sexp_release(this->key
);
471 * Internal generic constructor
473 static private_gcrypt_rsa_private_key_t
*gcrypt_rsa_private_key_create_empty()
475 private_gcrypt_rsa_private_key_t
*this = malloc_thing(private_gcrypt_rsa_private_key_t
);
477 this->public.interface
.get_type
= (key_type_t (*)(private_key_t
*this))get_type
;
478 this->public.interface
.sign
= (bool (*)(private_key_t
*this, signature_scheme_t scheme
, chunk_t data
, chunk_t
*signature
))sign
;
479 this->public.interface
.decrypt
= (bool (*)(private_key_t
*this, chunk_t crypto
, chunk_t
*plain
))decrypt
;
480 this->public.interface
.get_keysize
= (size_t (*) (private_key_t
*this))get_keysize
;
481 this->public.interface
.get_id
= (identification_t
* (*) (private_key_t
*this,id_type_t
))get_id
;
482 this->public.interface
.get_public_key
= (public_key_t
* (*)(private_key_t
*this))get_public_key
;
483 this->public.interface
.equals
= (bool (*) (private_key_t
*, private_key_t
*))equals
;
484 this->public.interface
.belongs_to
= (bool (*) (private_key_t
*this, public_key_t
*public))belongs_to
;
485 this->public.interface
.get_encoding
= (chunk_t(*)(private_key_t
*))get_encoding
;
486 this->public.interface
.get_ref
= (private_key_t
* (*)(private_key_t
*this))get_ref
;
487 this->public.interface
.destroy
= (void (*)(private_key_t
*this))destroy
;
491 this->keyid_info
= NULL
;
498 * build the keyids of a private/public key
500 bool gcrypt_rsa_build_keyids(gcry_sexp_t key
, identification_t
**keyid
,
501 identification_t
**keyid_info
)
503 chunk_t publicKeyInfo
, publicKey
, hash
;
506 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
509 DBG1("SHA1 hash algorithm not supported, unable to use RSA");
512 publicKey
= asn1_wrap(ASN1_SEQUENCE
, "mm",
513 asn1_integer("m", gcrypt_rsa_find_token(key
, "n", NULL
)),
514 asn1_integer("m", gcrypt_rsa_find_token(key
, "e", NULL
)));
515 hasher
->allocate_hash(hasher
, publicKey
, &hash
);
516 *keyid
= identification_create_from_encoding(ID_PUBKEY_SHA1
, hash
);
519 publicKeyInfo
= asn1_wrap(ASN1_SEQUENCE
, "cm",
520 asn1_algorithmIdentifier(OID_RSA_ENCRYPTION
),
521 asn1_bitstring("m", publicKey
));
522 hasher
->allocate_hash(hasher
, publicKeyInfo
, &hash
);
523 *keyid_info
= identification_create_from_encoding(ID_PUBKEY_INFO_SHA1
, hash
);
526 hasher
->destroy(hasher
);
527 chunk_free(&publicKeyInfo
);
533 * Generate an RSA key of specified key size
535 static gcrypt_rsa_private_key_t
*generate(size_t key_size
)
537 private_gcrypt_rsa_private_key_t
*this;
538 gcry_sexp_t param
, key
;
541 err
= gcry_sexp_build(¶m
, NULL
, "(genkey(rsa(nbits %d)))", key_size
);
544 DBG1("building S-expression failed: %s", gpg_strerror(err
));
548 err
= gcry_pk_genkey(&key
, param
);
549 gcry_sexp_release(param
);
552 DBG1("generating RSA key failed: %s", gpg_strerror(err
));
555 this = gcrypt_rsa_private_key_create_empty();
558 if (!gcrypt_rsa_build_keyids(this->key
, &this->keyid
, &this->keyid_info
))
564 return &this->public;
568 * Load a private key from components
570 static gcrypt_rsa_private_key_t
*load(chunk_t n
, chunk_t e
, chunk_t d
,
571 chunk_t p
, chunk_t q
, chunk_t u
)
574 private_gcrypt_rsa_private_key_t
*this = gcrypt_rsa_private_key_create_empty();
576 err
= gcry_sexp_build(&this->key
, NULL
,
577 "(private-key(rsa(n %b)(e %b)(d %b)(p %b)(q %b)(u %b)))",
578 n
.len
, n
.ptr
, e
.len
, e
.ptr
, d
.len
, d
.ptr
,
579 p
.len
, p
.ptr
, q
.len
, q
.ptr
, u
.len
, u
.ptr
);
582 DBG1("loading private key failed: %s", gpg_strerror(err
));
586 err
= gcry_pk_testkey(this->key
);
589 DBG1("private key sanity check failed: %s", gpg_strerror(err
));
593 if (!gcrypt_rsa_build_keyids(this->key
, &this->keyid
, &this->keyid_info
))
598 return &this->public;
601 typedef struct private_builder_t private_builder_t
;
604 * Builder implementation for key loading/generation
606 struct private_builder_t
{
607 /** implements the builder interface */
609 /** key size, if generating */
611 /** rsa key parameters */
612 chunk_t n
, e
, d
, p
, q
, u
;
616 * Implementation of builder_t.build
618 static gcrypt_rsa_private_key_t
*build(private_builder_t
*this)
620 gcrypt_rsa_private_key_t
*key
= NULL
;
624 key
= generate(this->key_size
);
628 key
= load(this->n
, this->e
, this->d
, this->p
, this->q
, this->u
);
635 * Implementation of builder_t.add
637 static void add(private_builder_t
*this, builder_part_t part
, ...)
641 va_start(args
, part
);
645 this->key_size
= va_arg(args
, u_int
);
647 case BUILD_RSA_MODULUS
:
648 this->n
= va_arg(args
, chunk_t
);
650 case BUILD_RSA_PUB_EXP
:
651 this->e
= va_arg(args
, chunk_t
);
653 case BUILD_RSA_PRIV_EXP
:
654 this->d
= va_arg(args
, chunk_t
);
656 case BUILD_RSA_PRIME1
:
657 /* swap p and q, gcrypt expects p < q */
658 this->q
= va_arg(args
, chunk_t
);
660 case BUILD_RSA_PRIME2
:
661 this->p
= va_arg(args
, chunk_t
);
665 /* not required for gcrypt */
667 case BUILD_RSA_COEFF
:
668 this->u
= va_arg(args
, chunk_t
);
671 builder_cancel(&this->public);
678 * Builder construction function
680 builder_t
*gcrypt_rsa_private_key_builder(key_type_t type
)
682 private_builder_t
*this;
689 this = malloc_thing(private_builder_t
);
692 this->n
= this->e
= this->d
= this->p
= this->q
= this->u
= chunk_empty
;
693 this->public.add
= (void(*)(builder_t
*this, builder_part_t part
, ...))add
;
694 this->public.build
= (void*(*)(builder_t
*this))build
;
696 return &this->public;