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>
24 #include <crypto/hashers/hasher.h>
26 typedef struct private_gcrypt_rsa_public_key_t private_gcrypt_rsa_public_key_t
;
29 * Private data structure with signing context.
31 struct private_gcrypt_rsa_public_key_t
{
34 * Public interface for this signer.
36 gcrypt_rsa_public_key_t
public;
39 * gcrypt S-expression representing an public RSA key
44 * Keyid formed as a SHA-1 hash of a publicKey object
46 identification_t
* keyid
;
49 * Keyid formed as a SHA-1 hash of a publicKeyInfo object
51 identification_t
* keyid_info
;
60 * Implemented in gcrypt_rsa_private_key.c
62 chunk_t
gcrypt_rsa_find_token(gcry_sexp_t sexp
, char *name
, gcry_sexp_t key
);
63 bool gcrypt_rsa_build_keyids(gcry_sexp_t key
, identification_t
**keyid
,
64 identification_t
**keyid_info
);
67 * verification of a padded PKCS1 signature without an OID
69 static bool verify_raw(private_gcrypt_rsa_public_key_t
*this,
70 chunk_t data
, chunk_t signature
)
77 /* EM = 0x00 || 0x01 || PS || 0x00 || T
78 * PS = 0xFF padding, with length to fill em
81 k
= gcry_pk_get_nbits(this->key
) / 8;
87 memset(em
.ptr
, 0xFF, em
.len
);
90 em
.ptr
[em
.len
- data
.len
- 1] = 0x00;
91 memcpy(em
.ptr
+ em
.len
- data
.len
, data
.ptr
, data
.len
);
93 err
= gcry_sexp_build(&in
, NULL
, "(data(flags raw)(value %b))",
98 DBG1("building data S-expression failed: %s", gpg_strerror(err
));
101 err
= gcry_sexp_build(&sig
, NULL
, "(sig-val(rsa(s %b)))",
102 signature
.len
, signature
.ptr
);
105 DBG1("building signature S-expression failed: %s", gpg_strerror(err
));
106 gcry_sexp_release(in
);
109 err
= gcry_pk_verify(sig
, in
, this->key
);
110 gcry_sexp_release(in
);
111 gcry_sexp_release(sig
);
114 DBG1("RSA signature verification failed: %s", gpg_strerror(err
));
121 * Verification of an EMSA PKCS1 signature described in PKCS#1
123 static bool verify_pkcs1(private_gcrypt_rsa_public_key_t
*this,
124 hash_algorithm_t algorithm
, char *hash_name
,
125 chunk_t data
, chunk_t signature
)
132 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, algorithm
);
137 hasher
->allocate_hash(hasher
, data
, &hash
);
138 hasher
->destroy(hasher
);
140 err
= gcry_sexp_build(&in
, NULL
, "(data(flags pkcs1)(hash %s %b))",
141 hash_name
, hash
.len
, hash
.ptr
);
145 DBG1("building data S-expression failed: %s", gpg_strerror(err
));
149 err
= gcry_sexp_build(&sig
, NULL
, "(sig-val(rsa(s %b)))",
150 signature
.len
, signature
.ptr
);
153 DBG1("building signature S-expression failed: %s", gpg_strerror(err
));
154 gcry_sexp_release(in
);
157 err
= gcry_pk_verify(sig
, in
, this->key
);
158 gcry_sexp_release(in
);
159 gcry_sexp_release(sig
);
162 DBG1("RSA signature verification failed: %s", gpg_strerror(err
));
169 * Implementation of public_key_t.get_type.
171 static key_type_t
get_type(private_gcrypt_rsa_public_key_t
*this)
177 * Implementation of public_key_t.verify.
179 static bool verify(private_gcrypt_rsa_public_key_t
*this,
180 signature_scheme_t scheme
, chunk_t data
, chunk_t signature
)
184 case SIGN_RSA_EMSA_PKCS1_NULL
:
185 return verify_raw(this, data
, signature
);
186 case SIGN_RSA_EMSA_PKCS1_MD5
:
187 return verify_pkcs1(this, HASH_MD5
, "md5", data
, signature
);
188 case SIGN_RSA_EMSA_PKCS1_SHA1
:
189 return verify_pkcs1(this, HASH_SHA1
, "sha1", data
, signature
);
190 case SIGN_RSA_EMSA_PKCS1_SHA224
:
191 return verify_pkcs1(this, HASH_SHA224
, "sha224", data
, signature
);
192 case SIGN_RSA_EMSA_PKCS1_SHA256
:
193 return verify_pkcs1(this, HASH_SHA256
, "sha256", data
, signature
);
194 case SIGN_RSA_EMSA_PKCS1_SHA384
:
195 return verify_pkcs1(this, HASH_SHA384
, "sha384", data
, signature
);
196 case SIGN_RSA_EMSA_PKCS1_SHA512
:
197 return verify_pkcs1(this, HASH_SHA512
, "sha512", data
, signature
);
199 DBG1("signature scheme %N not supported in RSA",
200 signature_scheme_names
, scheme
);
206 * Implementation of public_key_t.encrypt.
208 static bool encrypt_(private_gcrypt_rsa_public_key_t
*this, chunk_t plain
,
214 /* "pkcs1" uses PKCS 1.5 (section 8.1) block type 2 encryption:
215 * 00 | 02 | RANDOM | 00 | DATA */
216 err
= gcry_sexp_build(&in
, NULL
, "(data(flags pkcs1)(value %b))",
217 plain
.len
, plain
.ptr
);
220 DBG1("building encryption S-expression failed: %s", gpg_strerror(err
));
223 err
= gcry_pk_encrypt(&out
, in
, this->key
);
224 gcry_sexp_release(in
);
227 DBG1("encrypting data using pkcs1 failed: %s", gpg_strerror(err
));
230 *encrypted
= gcrypt_rsa_find_token(out
, "a", this->key
);
231 gcry_sexp_release(out
);
232 return !!encrypted
->len
;
236 * Implementation of gcrypt_rsa_public_key.equals.
238 static bool equals(private_gcrypt_rsa_public_key_t
*this, public_key_t
*other
)
240 identification_t
*keyid
;
242 if (&this->public.interface
== other
)
246 if (other
->get_type(other
) != KEY_RSA
)
250 keyid
= other
->get_id(other
, ID_PUBKEY_SHA1
);
251 if (keyid
&& keyid
->equals(keyid
, this->keyid
))
255 keyid
= other
->get_id(other
, ID_PUBKEY_INFO_SHA1
);
256 if (keyid
&& keyid
->equals(keyid
, this->keyid_info
))
264 * Implementation of public_key_t.get_keysize.
266 static size_t get_keysize(private_gcrypt_rsa_public_key_t
*this)
268 return gcry_pk_get_nbits(this->key
) / 8;
272 * Implementation of public_key_t.get_id.
274 static identification_t
*get_id(private_gcrypt_rsa_public_key_t
*this,
279 case ID_PUBKEY_INFO_SHA1
:
280 return this->keyid_info
;
289 * Implementation of public_key_t.get_encoding.
291 static chunk_t
get_encoding(private_gcrypt_rsa_public_key_t
*this)
293 return asn1_wrap(ASN1_SEQUENCE
, "mm",
294 asn1_integer("m", gcrypt_rsa_find_token(this->key
, "n", NULL
)),
295 asn1_integer("m", gcrypt_rsa_find_token(this->key
, "e", NULL
)));
299 * Implementation of public_key_t.get_ref.
301 static public_key_t
* get_ref(private_gcrypt_rsa_public_key_t
*this)
304 return &this->public.interface
;
308 * Implementation of gcrypt_rsa_public_key.destroy.
310 static void destroy(private_gcrypt_rsa_public_key_t
*this)
312 if (ref_put(&this->ref
))
314 DESTROY_IF(this->keyid
);
315 DESTROY_IF(this->keyid_info
);
316 gcry_sexp_release(this->key
);
322 * Generic private constructor
324 static private_gcrypt_rsa_public_key_t
*gcrypt_rsa_public_key_create_empty()
326 private_gcrypt_rsa_public_key_t
*this = malloc_thing(private_gcrypt_rsa_public_key_t
);
328 this->public.interface
.get_type
= (key_type_t (*)(public_key_t
*this))get_type
;
329 this->public.interface
.verify
= (bool (*)(public_key_t
*this, signature_scheme_t scheme
, chunk_t data
, chunk_t signature
))verify
;
330 this->public.interface
.encrypt
= (bool (*)(public_key_t
*this, chunk_t crypto
, chunk_t
*plain
))encrypt_
;
331 this->public.interface
.equals
= (bool (*) (public_key_t
*, public_key_t
*))equals
;
332 this->public.interface
.get_keysize
= (size_t (*) (public_key_t
*this))get_keysize
;
333 this->public.interface
.get_id
= (identification_t
* (*) (public_key_t
*this,id_type_t
))get_id
;
334 this->public.interface
.get_encoding
= (chunk_t(*)(public_key_t
*))get_encoding
;
335 this->public.interface
.get_ref
= (public_key_t
* (*)(public_key_t
*this))get_ref
;
336 this->public.interface
.destroy
= (void (*)(public_key_t
*this))destroy
;
340 this->keyid_info
= NULL
;
347 * Create a public key from a S-expression, used in gcrypt_rsa_private_key
349 public_key_t
*gcrypt_rsa_public_key_create_from_sexp(gcry_sexp_t key
)
351 private_gcrypt_rsa_public_key_t
*this;
355 this = gcrypt_rsa_public_key_create_empty();
356 n
= gcrypt_rsa_find_token(key
, "n", NULL
);
357 e
= gcrypt_rsa_find_token(key
, "e", NULL
);
359 err
= gcry_sexp_build(&this->key
, NULL
, "(public-key(rsa(n %b)(e %b)))",
360 n
.len
, n
.ptr
, e
.len
, e
.ptr
);
365 DBG1("loading public key failed: %s", gpg_strerror(err
));
369 if (!gcrypt_rsa_build_keyids(this->key
, &this->keyid
, &this->keyid_info
))
374 return &this->public.interface
;
378 * Load a public key from components
380 static gcrypt_rsa_public_key_t
*load(chunk_t n
, chunk_t e
)
382 private_gcrypt_rsa_public_key_t
*this;
385 this = gcrypt_rsa_public_key_create_empty();
386 err
= gcry_sexp_build(&this->key
, NULL
, "(public-key(rsa(n %b)(e %b)))",
387 n
.len
, n
.ptr
, e
.len
, e
.ptr
);
390 DBG1("loading public key failed: %s", gpg_strerror(err
));
394 if (!gcrypt_rsa_build_keyids(this->key
, &this->keyid
, &this->keyid_info
))
399 return &this->public;
402 typedef struct private_builder_t private_builder_t
;
404 * Builder implementation for key loading
406 struct private_builder_t
{
407 /** implements the builder interface */
409 /** rsa key parameters */
414 * Implementation of builder_t.build
416 static gcrypt_rsa_public_key_t
*build(private_builder_t
*this)
418 gcrypt_rsa_public_key_t
*key
;
420 key
= load(this->n
, this->e
);
426 * Implementation of builder_t.add
428 static void add(private_builder_t
*this, builder_part_t part
, ...)
432 va_start(args
, part
);
435 case BUILD_RSA_MODULUS
:
436 this->n
= va_arg(args
, chunk_t
);
438 case BUILD_RSA_PUB_EXP
:
439 this->e
= va_arg(args
, chunk_t
);
442 builder_cancel(&this->public);
449 * Builder construction function
451 builder_t
*gcrypt_rsa_public_key_builder(key_type_t type
)
453 private_builder_t
*this;
460 this = malloc_thing(private_builder_t
);
462 this->n
= this->e
= chunk_empty
;
463 this->public.add
= (void(*)(builder_t
*this, builder_part_t part
, ...))add
;
464 this->public.build
= (void*(*)(builder_t
*this))build
;
466 return &this->public;