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.get_keysize.
207 static bool encrypt_(private_gcrypt_rsa_public_key_t
*this, chunk_t crypto
,
210 DBG1("RSA public key encryption not implemented");
215 * Implementation of gcrypt_rsa_public_key.equals.
217 static bool equals(private_gcrypt_rsa_public_key_t
*this, public_key_t
*other
)
219 identification_t
*keyid
;
221 if (&this->public.interface
== other
)
225 if (other
->get_type(other
) != KEY_RSA
)
229 keyid
= other
->get_id(other
, ID_PUBKEY_SHA1
);
230 if (keyid
&& keyid
->equals(keyid
, this->keyid
))
234 keyid
= other
->get_id(other
, ID_PUBKEY_INFO_SHA1
);
235 if (keyid
&& keyid
->equals(keyid
, this->keyid_info
))
243 * Implementation of public_key_t.get_keysize.
245 static size_t get_keysize(private_gcrypt_rsa_public_key_t
*this)
247 return gcry_pk_get_nbits(this->key
) / 8;
251 * Implementation of public_key_t.get_id.
253 static identification_t
*get_id(private_gcrypt_rsa_public_key_t
*this,
258 case ID_PUBKEY_INFO_SHA1
:
259 return this->keyid_info
;
268 * Implementation of public_key_t.get_encoding.
270 static chunk_t
get_encoding(private_gcrypt_rsa_public_key_t
*this)
272 return asn1_wrap(ASN1_SEQUENCE
, "mm",
273 asn1_integer("m", gcrypt_rsa_find_token(this->key
, "n")),
274 asn1_integer("m", gcrypt_rsa_find_token(this->key
, "e")));
278 * Implementation of public_key_t.get_ref.
280 static public_key_t
* get_ref(private_gcrypt_rsa_public_key_t
*this)
283 return &this->public.interface
;
287 * Implementation of gcrypt_rsa_public_key.destroy.
289 static void destroy(private_gcrypt_rsa_public_key_t
*this)
291 if (ref_put(&this->ref
))
293 DESTROY_IF(this->keyid
);
294 DESTROY_IF(this->keyid_info
);
295 gcry_sexp_release(this->key
);
301 * Generic private constructor
303 static private_gcrypt_rsa_public_key_t
*gcrypt_rsa_public_key_create_empty()
305 private_gcrypt_rsa_public_key_t
*this = malloc_thing(private_gcrypt_rsa_public_key_t
);
307 this->public.interface
.get_type
= (key_type_t (*)(public_key_t
*this))get_type
;
308 this->public.interface
.verify
= (bool (*)(public_key_t
*this, signature_scheme_t scheme
, chunk_t data
, chunk_t signature
))verify
;
309 this->public.interface
.encrypt
= (bool (*)(public_key_t
*this, chunk_t crypto
, chunk_t
*plain
))encrypt_
;
310 this->public.interface
.equals
= (bool (*) (public_key_t
*, public_key_t
*))equals
;
311 this->public.interface
.get_keysize
= (size_t (*) (public_key_t
*this))get_keysize
;
312 this->public.interface
.get_id
= (identification_t
* (*) (public_key_t
*this,id_type_t
))get_id
;
313 this->public.interface
.get_encoding
= (chunk_t(*)(public_key_t
*))get_encoding
;
314 this->public.interface
.get_ref
= (public_key_t
* (*)(public_key_t
*this))get_ref
;
315 this->public.interface
.destroy
= (void (*)(public_key_t
*this))destroy
;
319 this->keyid_info
= NULL
;
326 * Create a public key from a S-expression, used in gcrypt_rsa_private_key
328 public_key_t
*gcrypt_rsa_public_key_create_from_sexp(gcry_sexp_t key
)
330 private_gcrypt_rsa_public_key_t
*this;
334 this = gcrypt_rsa_public_key_create_empty();
335 n
= gcrypt_rsa_find_token(key
, "n");
336 e
= gcrypt_rsa_find_token(key
, "e");
338 err
= gcry_sexp_build(&this->key
, NULL
, "(public-key(rsa(n %b)(e %b)))",
339 n
.len
, n
.ptr
, e
.len
, e
.ptr
);
344 DBG1("loading public key failed: %s", gpg_strerror(err
));
348 if (!gcrypt_rsa_build_keyids(this->key
, &this->keyid
, &this->keyid_info
))
353 return &this->public.interface
;
357 * ASN.1 definition of RSApublicKey
359 static const asn1Object_t pubkeyObjects
[] = {
360 { 0, "RSAPublicKey", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 0 */
361 { 1, "modulus", ASN1_INTEGER
, ASN1_BODY
}, /* 1 */
362 { 1, "publicExponent", ASN1_INTEGER
, ASN1_BODY
}, /* 2 */
363 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
365 #define PUB_KEY_RSA_PUBLIC_KEY 0
366 #define PUB_KEY_MODULUS 1
367 #define PUB_KEY_EXPONENT 2
370 * Load a public key from an ASN1 encoded blob
372 static gcrypt_rsa_public_key_t
*load(chunk_t blob
)
374 private_gcrypt_rsa_public_key_t
*this;
375 asn1_parser_t
*parser
;
376 chunk_t object
, n
, e
;
378 bool success
= FALSE
;
381 parser
= asn1_parser_create(pubkeyObjects
, blob
);
382 while (parser
->iterate(parser
, &objectID
, &object
))
386 case PUB_KEY_MODULUS
:
389 case PUB_KEY_EXPONENT
:
394 success
= parser
->success(parser
);
395 parser
->destroy(parser
);
402 this = gcrypt_rsa_public_key_create_empty();
403 err
= gcry_sexp_build(&this->key
, NULL
, "(public-key(rsa(n %b)(e %b)))",
404 n
.len
, n
.ptr
, e
.len
, e
.ptr
);
407 DBG1("loading public key failed: %s", gpg_strerror(err
));
411 if (!gcrypt_rsa_build_keyids(this->key
, &this->keyid
, &this->keyid_info
))
416 return &this->public;
419 typedef struct private_builder_t private_builder_t
;
421 * Builder implementation for key loading
423 struct private_builder_t
{
424 /** implements the builder interface */
426 /** loaded public key */
427 gcrypt_rsa_public_key_t
*key
;
431 * Implementation of builder_t.build
433 static gcrypt_rsa_public_key_t
*build(private_builder_t
*this)
435 gcrypt_rsa_public_key_t
*key
= this->key
;
442 * Implementation of builder_t.add
444 static void add(private_builder_t
*this, builder_part_t part
, ...)
452 case BUILD_BLOB_ASN1_DER
:
454 va_start(args
, part
);
455 this->key
= load(va_arg(args
, chunk_t
));
465 destroy((private_gcrypt_rsa_public_key_t
*)this->key
);
467 builder_cancel(&this->public);
471 * Builder construction function
473 builder_t
*gcrypt_rsa_public_key_builder(key_type_t type
)
475 private_builder_t
*this;
482 this = malloc_thing(private_builder_t
);
485 this->public.add
= (void(*)(builder_t
*this, builder_part_t part
, ...))add
;
486 this->public.build
= (void*(*)(builder_t
*this))build
;
488 return &this->public;