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_public_key.h"
22 #include <asn1/asn1.h>
23 #include <asn1/asn1_parser.h>
25 #include <crypto/hashers/hasher.h>
27 typedef struct private_gcrypt_rsa_public_key_t private_gcrypt_rsa_public_key_t
;
30 * Private data structure with signing context.
32 struct private_gcrypt_rsa_public_key_t
{
35 * Public interface for this signer.
37 gcrypt_rsa_public_key_t
public;
40 * gcrypt S-expression representing an public RSA key
45 * Keyid formed as a SHA-1 hash of a publicKey object
47 identification_t
* keyid
;
50 * Keyid formed as a SHA-1 hash of a publicKeyInfo object
52 identification_t
* keyid_info
;
61 * Implemented in gcrypt_rsa_private_key.c
63 chunk_t
gcrypt_rsa_find_token(gcry_sexp_t sexp
, char *name
);
64 bool gcrypt_rsa_build_keyids(gcry_sexp_t key
, identification_t
**keyid
,
65 identification_t
**keyid_info
);
68 * verification of a padded PKCS1 signature without an OID
70 static bool verify_raw(private_gcrypt_rsa_public_key_t
*this,
71 chunk_t data
, chunk_t signature
)
78 /* EM = 0x00 || 0x01 || PS || 0x00 || T
79 * PS = 0xFF padding, with length to fill em
82 k
= gcry_pk_get_nbits(this->key
) / 8;
88 memset(em
.ptr
, 0xFF, em
.len
);
91 em
.ptr
[em
.len
- data
.len
- 1] = 0x00;
92 memcpy(em
.ptr
+ em
.len
- data
.len
, data
.ptr
, data
.len
);
94 err
= gcry_sexp_build(&in
, NULL
, "(data(flags raw)(value %b))",
99 DBG1("building data S-expression failed: %s", gpg_strerror(err
));
102 err
= gcry_sexp_build(&sig
, NULL
, "(sig-val(rsa(s %b)))",
103 signature
.len
, signature
.ptr
);
106 DBG1("building signature S-expression failed: %s", gpg_strerror(err
));
107 gcry_sexp_release(in
);
110 err
= gcry_pk_verify(sig
, in
, this->key
);
111 gcry_sexp_release(in
);
112 gcry_sexp_release(sig
);
115 DBG1("RSA signature verification failed: %s", gpg_strerror(err
));
122 * Verification of an EMSA PKCS1 signature described in PKCS#1
124 static bool verify_pkcs1(private_gcrypt_rsa_public_key_t
*this,
125 hash_algorithm_t algorithm
, char *hash_name
,
126 chunk_t data
, chunk_t signature
)
133 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, algorithm
);
138 hasher
->allocate_hash(hasher
, data
, &hash
);
139 hasher
->destroy(hasher
);
141 err
= gcry_sexp_build(&in
, NULL
, "(data(flags pkcs1)(hash %s %b))",
142 hash_name
, hash
.len
, hash
.ptr
);
146 DBG1("building data S-expression failed: %s", gpg_strerror(err
));
150 err
= gcry_sexp_build(&sig
, NULL
, "(sig-val(rsa(s %b)))",
151 signature
.len
, signature
.ptr
);
154 DBG1("building signature S-expression failed: %s", gpg_strerror(err
));
155 gcry_sexp_release(in
);
158 err
= gcry_pk_verify(sig
, in
, this->key
);
159 gcry_sexp_release(in
);
160 gcry_sexp_release(sig
);
163 DBG1("RSA signature verification failed: %s", gpg_strerror(err
));
170 * Implementation of public_key_t.get_type.
172 static key_type_t
get_type(private_gcrypt_rsa_public_key_t
*this)
178 * Implementation of public_key_t.verify.
180 static bool verify(private_gcrypt_rsa_public_key_t
*this,
181 signature_scheme_t scheme
, chunk_t data
, chunk_t signature
)
185 case SIGN_RSA_EMSA_PKCS1_NULL
:
186 return verify_raw(this, data
, signature
);
187 case SIGN_RSA_EMSA_PKCS1_MD5
:
188 return verify_pkcs1(this, HASH_MD5
, "md5", data
, signature
);
189 case SIGN_RSA_EMSA_PKCS1_SHA1
:
190 return verify_pkcs1(this, HASH_SHA1
, "sha1", data
, signature
);
191 case SIGN_RSA_EMSA_PKCS1_SHA256
:
192 return verify_pkcs1(this, HASH_SHA256
, "sha256", data
, signature
);
193 case SIGN_RSA_EMSA_PKCS1_SHA384
:
194 return verify_pkcs1(this, HASH_SHA384
, "sha384", data
, signature
);
195 case SIGN_RSA_EMSA_PKCS1_SHA512
:
196 return verify_pkcs1(this, HASH_SHA512
, "sha512", data
, signature
);
198 DBG1("signature scheme %N not supported in RSA",
199 signature_scheme_names
, scheme
);
205 * Implementation of public_key_t.encrypt.
207 static bool encrypt_(private_gcrypt_rsa_public_key_t
*this, chunk_t plain
,
213 /* "pkcs1" uses PKCS 1.5 (section 8.1) block type 2 encryption:
214 * 00 | 02 | RANDOM | 00 | DATA */
215 err
= gcry_sexp_build(&in
, NULL
, "(data(flags pkcs1)(value %b))",
216 plain
.len
, plain
.ptr
);
219 DBG1("building encryption S-expression failed: %s", gpg_strerror(err
));
222 err
= gcry_pk_encrypt(&out
, in
, this->key
);
223 gcry_sexp_release(in
);
226 DBG1("encrypting data using pkcs1 failed: %s", gpg_strerror(err
));
229 *encrypted
= gcrypt_rsa_find_token(out
, "a");
230 gcry_sexp_release(out
);
231 return !!encrypted
->len
;
235 * Implementation of gcrypt_rsa_public_key.equals.
237 static bool equals(private_gcrypt_rsa_public_key_t
*this, public_key_t
*other
)
239 identification_t
*keyid
;
241 if (&this->public.interface
== other
)
245 if (other
->get_type(other
) != KEY_RSA
)
249 keyid
= other
->get_id(other
, ID_PUBKEY_SHA1
);
250 if (keyid
&& keyid
->equals(keyid
, this->keyid
))
254 keyid
= other
->get_id(other
, ID_PUBKEY_INFO_SHA1
);
255 if (keyid
&& keyid
->equals(keyid
, this->keyid_info
))
263 * Implementation of public_key_t.get_keysize.
265 static size_t get_keysize(private_gcrypt_rsa_public_key_t
*this)
267 return gcry_pk_get_nbits(this->key
) / 8;
271 * Implementation of public_key_t.get_id.
273 static identification_t
*get_id(private_gcrypt_rsa_public_key_t
*this,
278 case ID_PUBKEY_INFO_SHA1
:
279 return this->keyid_info
;
288 * Implementation of public_key_t.get_encoding.
290 static chunk_t
get_encoding(private_gcrypt_rsa_public_key_t
*this)
292 return asn1_wrap(ASN1_SEQUENCE
, "mm",
293 asn1_integer("m", gcrypt_rsa_find_token(this->key
, "n")),
294 asn1_integer("m", gcrypt_rsa_find_token(this->key
, "e")));
298 * Implementation of public_key_t.get_ref.
300 static public_key_t
* get_ref(private_gcrypt_rsa_public_key_t
*this)
303 return &this->public.interface
;
307 * Implementation of gcrypt_rsa_public_key.destroy.
309 static void destroy(private_gcrypt_rsa_public_key_t
*this)
311 if (ref_put(&this->ref
))
313 DESTROY_IF(this->keyid
);
314 DESTROY_IF(this->keyid_info
);
315 gcry_sexp_release(this->key
);
321 * Generic private constructor
323 static private_gcrypt_rsa_public_key_t
*gcrypt_rsa_public_key_create_empty()
325 private_gcrypt_rsa_public_key_t
*this = malloc_thing(private_gcrypt_rsa_public_key_t
);
327 this->public.interface
.get_type
= (key_type_t (*)(public_key_t
*this))get_type
;
328 this->public.interface
.verify
= (bool (*)(public_key_t
*this, signature_scheme_t scheme
, chunk_t data
, chunk_t signature
))verify
;
329 this->public.interface
.encrypt
= (bool (*)(public_key_t
*this, chunk_t crypto
, chunk_t
*plain
))encrypt_
;
330 this->public.interface
.equals
= (bool (*) (public_key_t
*, public_key_t
*))equals
;
331 this->public.interface
.get_keysize
= (size_t (*) (public_key_t
*this))get_keysize
;
332 this->public.interface
.get_id
= (identification_t
* (*) (public_key_t
*this,id_type_t
))get_id
;
333 this->public.interface
.get_encoding
= (chunk_t(*)(public_key_t
*))get_encoding
;
334 this->public.interface
.get_ref
= (public_key_t
* (*)(public_key_t
*this))get_ref
;
335 this->public.interface
.destroy
= (void (*)(public_key_t
*this))destroy
;
339 this->keyid_info
= NULL
;
346 * Create a public key from a S-expression, used in gcrypt_rsa_private_key
348 public_key_t
*gcrypt_rsa_public_key_create_from_sexp(gcry_sexp_t key
)
350 private_gcrypt_rsa_public_key_t
*this;
354 this = gcrypt_rsa_public_key_create_empty();
355 n
= gcrypt_rsa_find_token(key
, "n");
356 e
= gcrypt_rsa_find_token(key
, "e");
358 err
= gcry_sexp_build(&this->key
, NULL
, "(public-key(rsa(n %b)(e %b)))",
359 n
.len
, n
.ptr
, e
.len
, e
.ptr
);
364 DBG1("loading public key failed: %s", gpg_strerror(err
));
368 if (!gcrypt_rsa_build_keyids(this->key
, &this->keyid
, &this->keyid_info
))
373 return &this->public.interface
;
377 * ASN.1 definition of RSApublicKey
379 static const asn1Object_t pubkeyObjects
[] = {
380 { 0, "RSAPublicKey", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 0 */
381 { 1, "modulus", ASN1_INTEGER
, ASN1_BODY
}, /* 1 */
382 { 1, "publicExponent", ASN1_INTEGER
, ASN1_BODY
}, /* 2 */
383 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
385 #define PUB_KEY_RSA_PUBLIC_KEY 0
386 #define PUB_KEY_MODULUS 1
387 #define PUB_KEY_EXPONENT 2
390 * Load a public key from an ASN1 encoded blob
392 static gcrypt_rsa_public_key_t
*load(chunk_t blob
)
394 private_gcrypt_rsa_public_key_t
*this;
395 asn1_parser_t
*parser
;
396 chunk_t object
, n
, e
;
398 bool success
= FALSE
;
403 parser
= asn1_parser_create(pubkeyObjects
, blob
);
404 while (parser
->iterate(parser
, &objectID
, &object
))
408 case PUB_KEY_MODULUS
:
411 case PUB_KEY_EXPONENT
:
416 success
= parser
->success(parser
);
417 parser
->destroy(parser
);
424 this = gcrypt_rsa_public_key_create_empty();
425 err
= gcry_sexp_build(&this->key
, NULL
, "(public-key(rsa(n %b)(e %b)))",
426 n
.len
, n
.ptr
, e
.len
, e
.ptr
);
429 DBG1("loading public key failed: %s", gpg_strerror(err
));
433 if (!gcrypt_rsa_build_keyids(this->key
, &this->keyid
, &this->keyid_info
))
438 return &this->public;
441 typedef struct private_builder_t private_builder_t
;
443 * Builder implementation for key loading
445 struct private_builder_t
{
446 /** implements the builder interface */
448 /** loaded public key */
449 gcrypt_rsa_public_key_t
*key
;
453 * Implementation of builder_t.build
455 static gcrypt_rsa_public_key_t
*build(private_builder_t
*this)
457 gcrypt_rsa_public_key_t
*key
= this->key
;
464 * Implementation of builder_t.add
466 static void add(private_builder_t
*this, builder_part_t part
, ...)
474 case BUILD_BLOB_ASN1_DER
:
476 va_start(args
, part
);
477 this->key
= load(va_arg(args
, chunk_t
));
487 destroy((private_gcrypt_rsa_public_key_t
*)this->key
);
489 builder_cancel(&this->public);
493 * Builder construction function
495 builder_t
*gcrypt_rsa_public_key_builder(key_type_t type
)
497 private_builder_t
*this;
504 this = malloc_thing(private_builder_t
);
507 this->public.add
= (void(*)(builder_t
*this, builder_part_t part
, ...))add
;
508 this->public.build
= (void*(*)(builder_t
*this))build
;
510 return &this->public;