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 an EMPSA PKCS1 signature described in PKCS#1
70 static bool verify_pkcs1(private_gcrypt_rsa_public_key_t
*this,
71 hash_algorithm_t algorithm
, char *hash_name
,
72 chunk_t data
, chunk_t signature
)
79 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, algorithm
);
84 hasher
->allocate_hash(hasher
, data
, &hash
);
85 hasher
->destroy(hasher
);
87 err
= gcry_sexp_build(&in
, NULL
, "(data(flags pkcs1)(hash %s %b))",
88 hash_name
, hash
.len
, hash
.ptr
);
92 DBG1("building data S-expression failed: %s", gpg_strerror(err
));
96 err
= gcry_sexp_build(&sig
, NULL
, "(sig-val(rsa(s %b)))",
97 signature
.len
, signature
.ptr
);
100 DBG1("building signature S-expression failed: %s", gpg_strerror(err
));
101 gcry_sexp_release(in
);
104 err
= gcry_pk_verify(sig
, in
, this->key
);
105 gcry_sexp_release(in
);
106 gcry_sexp_release(sig
);
109 DBG1("RSA signature verification failed: %s", gpg_strerror(err
));
116 * Implementation of public_key_t.get_type.
118 static key_type_t
get_type(private_gcrypt_rsa_public_key_t
*this)
124 * Implementation of public_key_t.verify.
126 static bool verify(private_gcrypt_rsa_public_key_t
*this,
127 signature_scheme_t scheme
, chunk_t data
, chunk_t signature
)
131 case SIGN_RSA_EMSA_PKCS1_MD5
:
132 return verify_pkcs1(this, HASH_MD5
, "md5", data
, signature
);
133 case SIGN_RSA_EMSA_PKCS1_SHA1
:
134 return verify_pkcs1(this, HASH_SHA1
, "sha1", data
, signature
);
135 case SIGN_RSA_EMSA_PKCS1_SHA256
:
136 return verify_pkcs1(this, HASH_SHA256
, "sha256", data
, signature
);
137 case SIGN_RSA_EMSA_PKCS1_SHA384
:
138 return verify_pkcs1(this, HASH_SHA384
, "sha384", data
, signature
);
139 case SIGN_RSA_EMSA_PKCS1_SHA512
:
140 return verify_pkcs1(this, HASH_SHA512
, "sha512", data
, signature
);
142 /* parsing hash OID currently not supported by gcrypt, fall */
144 DBG1("signature scheme %N not supported in RSA",
145 signature_scheme_names
, scheme
);
151 * Implementation of public_key_t.get_keysize.
153 static bool encrypt_(private_gcrypt_rsa_public_key_t
*this, chunk_t crypto
,
156 DBG1("RSA public key encryption not implemented");
161 * Implementation of gcrypt_rsa_public_key.equals.
163 static bool equals(private_gcrypt_rsa_public_key_t
*this, public_key_t
*other
)
165 identification_t
*keyid
;
167 if (&this->public.interface
== other
)
171 if (other
->get_type(other
) != KEY_RSA
)
175 keyid
= other
->get_id(other
, ID_PUBKEY_SHA1
);
176 if (keyid
&& keyid
->equals(keyid
, this->keyid
))
180 keyid
= other
->get_id(other
, ID_PUBKEY_INFO_SHA1
);
181 if (keyid
&& keyid
->equals(keyid
, this->keyid_info
))
189 * Implementation of public_key_t.get_keysize.
191 static size_t get_keysize(private_gcrypt_rsa_public_key_t
*this)
193 return gcry_pk_get_nbits(this->key
) / 8;
197 * Implementation of public_key_t.get_id.
199 static identification_t
*get_id(private_gcrypt_rsa_public_key_t
*this,
204 case ID_PUBKEY_INFO_SHA1
:
205 return this->keyid_info
;
214 * Implementation of public_key_t.get_encoding.
216 static chunk_t
get_encoding(private_gcrypt_rsa_public_key_t
*this)
218 return asn1_wrap(ASN1_SEQUENCE
, "mm",
219 asn1_wrap(ASN1_INTEGER
, "m", gcrypt_rsa_find_token(this->key
, "n")),
220 asn1_wrap(ASN1_INTEGER
, "m", gcrypt_rsa_find_token(this->key
, "e")));
224 * Implementation of public_key_t.get_ref.
226 static public_key_t
* get_ref(private_gcrypt_rsa_public_key_t
*this)
229 return &this->public.interface
;
233 * Implementation of gcrypt_rsa_public_key.destroy.
235 static void destroy(private_gcrypt_rsa_public_key_t
*this)
237 if (ref_put(&this->ref
))
239 DESTROY_IF(this->keyid
);
240 DESTROY_IF(this->keyid_info
);
241 gcry_sexp_release(this->key
);
247 * Generic private constructor
249 static private_gcrypt_rsa_public_key_t
*gcrypt_rsa_public_key_create_empty()
251 private_gcrypt_rsa_public_key_t
*this = malloc_thing(private_gcrypt_rsa_public_key_t
);
253 this->public.interface
.get_type
= (key_type_t (*)(public_key_t
*this))get_type
;
254 this->public.interface
.verify
= (bool (*)(public_key_t
*this, signature_scheme_t scheme
, chunk_t data
, chunk_t signature
))verify
;
255 this->public.interface
.encrypt
= (bool (*)(public_key_t
*this, chunk_t crypto
, chunk_t
*plain
))encrypt_
;
256 this->public.interface
.equals
= (bool (*) (public_key_t
*, public_key_t
*))equals
;
257 this->public.interface
.get_keysize
= (size_t (*) (public_key_t
*this))get_keysize
;
258 this->public.interface
.get_id
= (identification_t
* (*) (public_key_t
*this,id_type_t
))get_id
;
259 this->public.interface
.get_encoding
= (chunk_t(*)(public_key_t
*))get_encoding
;
260 this->public.interface
.get_ref
= (public_key_t
* (*)(public_key_t
*this))get_ref
;
261 this->public.interface
.destroy
= (void (*)(public_key_t
*this))destroy
;
265 this->keyid_info
= NULL
;
272 * Create a public key from a S-expression, used in gcrypt_rsa_private_key
274 public_key_t
*gcrypt_rsa_public_key_create_from_sexp(gcry_sexp_t key
)
276 private_gcrypt_rsa_public_key_t
*this;
280 this = gcrypt_rsa_public_key_create_empty();
281 n
= gcrypt_rsa_find_token(key
, "n");
282 e
= gcrypt_rsa_find_token(key
, "e");
284 err
= gcry_sexp_build(&this->key
, NULL
, "(public-key(rsa(n %b)(e %b)))",
285 n
.len
, n
.ptr
, e
.len
, e
.ptr
);
290 DBG1("loading public key failed: %s", gpg_strerror(err
));
294 if (!gcrypt_rsa_build_keyids(this->key
, &this->keyid
, &this->keyid_info
))
299 return &this->public.interface
;
303 * ASN.1 definition of RSApublicKey
305 static const asn1Object_t pubkeyObjects
[] = {
306 { 0, "RSAPublicKey", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 0 */
307 { 1, "modulus", ASN1_INTEGER
, ASN1_BODY
}, /* 1 */
308 { 1, "publicExponent", ASN1_INTEGER
, ASN1_BODY
}, /* 2 */
309 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
311 #define PUB_KEY_RSA_PUBLIC_KEY 0
312 #define PUB_KEY_MODULUS 1
313 #define PUB_KEY_EXPONENT 2
316 * Load a public key from an ASN1 encoded blob
318 static gcrypt_rsa_public_key_t
*load(chunk_t blob
)
320 private_gcrypt_rsa_public_key_t
*this;
321 asn1_parser_t
*parser
;
322 chunk_t object
, n
, e
;
324 bool success
= FALSE
;
327 parser
= asn1_parser_create(pubkeyObjects
, blob
);
328 while (parser
->iterate(parser
, &objectID
, &object
))
332 case PUB_KEY_MODULUS
:
335 case PUB_KEY_EXPONENT
:
340 success
= parser
->success(parser
);
341 parser
->destroy(parser
);
348 this = gcrypt_rsa_public_key_create_empty();
349 err
= gcry_sexp_build(&this->key
, NULL
, "(public-key(rsa(n %b)(e %b)))",
350 n
.len
, n
.ptr
, e
.len
, e
.ptr
);
353 DBG1("loading public key failed: %s", gpg_strerror(err
));
357 if (!gcrypt_rsa_build_keyids(this->key
, &this->keyid
, &this->keyid_info
))
362 return &this->public;
365 typedef struct private_builder_t private_builder_t
;
367 * Builder implementation for key loading
369 struct private_builder_t
{
370 /** implements the builder interface */
372 /** loaded public key */
373 gcrypt_rsa_public_key_t
*key
;
377 * Implementation of builder_t.build
379 static gcrypt_rsa_public_key_t
*build(private_builder_t
*this)
381 gcrypt_rsa_public_key_t
*key
= this->key
;
388 * Implementation of builder_t.add
390 static void add(private_builder_t
*this, builder_part_t part
, ...)
398 case BUILD_BLOB_ASN1_DER
:
400 va_start(args
, part
);
401 this->key
= load(va_arg(args
, chunk_t
));
411 destroy((private_gcrypt_rsa_public_key_t
*)this->key
);
413 builder_cancel(&this->public);
417 * Builder construction function
419 builder_t
*gcrypt_rsa_public_key_builder(key_type_t type
)
421 private_builder_t
*this;
428 this = malloc_thing(private_builder_t
);
431 this->public.add
= (void(*)(builder_t
*this, builder_part_t part
, ...))add
;
432 this->public.build
= (void*(*)(builder_t
*this))build
;
434 return &this->public;