2 * Copyright (C) 2009 Martin Willi
3 * Copyright (C) 2008 Tobias Brunner
4 * Hochschule fuer Technik Rapperswil
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 #include "openssl_rsa_public_key.h"
21 #include <openssl/evp.h>
22 #include <openssl/rsa.h>
23 #include <openssl/x509.h>
25 typedef struct private_openssl_rsa_public_key_t private_openssl_rsa_public_key_t
;
28 * Private data structure with signing context.
30 struct private_openssl_rsa_public_key_t
{
32 * Public interface for this signer.
34 openssl_rsa_public_key_t
public;
37 * RSA object from OpenSSL
48 * Verification of an EMPSA PKCS1 signature described in PKCS#1
50 static bool verify_emsa_pkcs1_signature(private_openssl_rsa_public_key_t
*this,
51 int type
, chunk_t data
, chunk_t signature
)
54 int rsa_size
= RSA_size(this->rsa
);
56 /* OpenSSL expects a signature of exactly RSA size (no leading 0x00) */
57 if (signature
.len
> rsa_size
)
59 signature
= chunk_skip(signature
, signature
.len
- rsa_size
);
62 if (type
== NID_undef
)
64 chunk_t hash
= chunk_alloc(rsa_size
);
66 hash
.len
= RSA_public_decrypt(signature
.len
, signature
.ptr
, hash
.ptr
,
67 this->rsa
, RSA_PKCS1_PADDING
);
68 valid
= chunk_equals(data
, hash
);
77 hasher
= EVP_get_digestbynid(type
);
83 ctx
= EVP_MD_CTX_create();
90 if (!EVP_PKEY_set1_RSA(key
, this->rsa
))
94 if (!EVP_VerifyInit_ex(ctx
, hasher
, NULL
))
98 if (!EVP_VerifyUpdate(ctx
, data
.ptr
, data
.len
))
102 valid
= (EVP_VerifyFinal(ctx
, signature
.ptr
, signature
.len
, key
) == 1);
111 EVP_MD_CTX_destroy(ctx
);
118 * Implementation of public_key_t.get_type.
120 static key_type_t
get_type(private_openssl_rsa_public_key_t
*this)
126 * Implementation of public_key_t.verify.
128 static bool verify(private_openssl_rsa_public_key_t
*this, signature_scheme_t scheme
,
129 chunk_t data
, chunk_t signature
)
133 case SIGN_RSA_EMSA_PKCS1_NULL
:
134 return verify_emsa_pkcs1_signature(this, NID_undef
, data
, signature
);
135 case SIGN_RSA_EMSA_PKCS1_SHA1
:
136 return verify_emsa_pkcs1_signature(this, NID_sha1
, data
, signature
);
137 case SIGN_RSA_EMSA_PKCS1_SHA224
:
138 return verify_emsa_pkcs1_signature(this, NID_sha224
, data
, signature
);
139 case SIGN_RSA_EMSA_PKCS1_SHA256
:
140 return verify_emsa_pkcs1_signature(this, NID_sha256
, data
, signature
);
141 case SIGN_RSA_EMSA_PKCS1_SHA384
:
142 return verify_emsa_pkcs1_signature(this, NID_sha384
, data
, signature
);
143 case SIGN_RSA_EMSA_PKCS1_SHA512
:
144 return verify_emsa_pkcs1_signature(this, NID_sha512
, data
, signature
);
145 case SIGN_RSA_EMSA_PKCS1_MD5
:
146 return verify_emsa_pkcs1_signature(this, NID_md5
, data
, signature
);
148 DBG1(DBG_LIB
, "signature scheme %N not supported in RSA",
149 signature_scheme_names
, scheme
);
155 * Implementation of public_key_t.get_keysize.
157 static bool encrypt_(private_openssl_rsa_public_key_t
*this,
158 chunk_t crypto
, chunk_t
*plain
)
160 DBG1(DBG_LIB
, "RSA public key encryption not implemented");
165 * Implementation of public_key_t.get_keysize.
167 static size_t get_keysize(private_openssl_rsa_public_key_t
*this)
169 return RSA_size(this->rsa
);
173 * Calculate fingerprint from a RSA key, also used in rsa private key.
175 bool openssl_rsa_fingerprint(RSA
*rsa
, key_encoding_type_t type
, chunk_t
*fp
)
181 if (lib
->encoding
->get_cache(lib
->encoding
, type
, rsa
, fp
))
187 case KEY_ID_PUBKEY_SHA1
:
188 key
= chunk_alloc(i2d_RSAPublicKey(rsa
, NULL
));
190 i2d_RSAPublicKey(rsa
, &p
);
192 case KEY_ID_PUBKEY_INFO_SHA1
:
193 key
= chunk_alloc(i2d_RSA_PUBKEY(rsa
, NULL
));
195 i2d_RSA_PUBKEY(rsa
, &p
);
200 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
203 DBG1(DBG_LIB
, "SHA1 hash algorithm not supported, fingerprinting failed");
207 hasher
->allocate_hash(hasher
, key
, fp
);
209 hasher
->destroy(hasher
);
210 lib
->encoding
->cache(lib
->encoding
, type
, rsa
, *fp
);
215 * Implementation of public_key_t.get_fingerprint.
217 static bool get_fingerprint(private_openssl_rsa_public_key_t
*this,
218 key_encoding_type_t type
, chunk_t
*fingerprint
)
220 return openssl_rsa_fingerprint(this->rsa
, type
, fingerprint
);
224 * Implementation of public_key_t.get_encoding.
226 static bool get_encoding(private_openssl_rsa_public_key_t
*this,
227 key_encoding_type_t type
, chunk_t
*encoding
)
233 case KEY_PUB_SPKI_ASN1_DER
:
238 *encoding
= chunk_alloc(i2d_RSA_PUBKEY(this->rsa
, NULL
));
240 i2d_RSA_PUBKEY(this->rsa
, &p
);
242 if (type
== KEY_PUB_PEM
)
244 chunk_t asn1_encoding
= *encoding
;
246 success
= lib
->encoding
->encode(lib
->encoding
, KEY_PUB_PEM
,
247 NULL
, encoding
, KEY_PART_RSA_PUB_ASN1_DER
,
248 asn1_encoding
, KEY_PART_END
);
249 chunk_clear(&asn1_encoding
);
253 case KEY_PUB_ASN1_DER
:
255 *encoding
= chunk_alloc(i2d_RSAPublicKey(this->rsa
, NULL
));
257 i2d_RSAPublicKey(this->rsa
, &p
);
266 * Implementation of public_key_t.get_ref.
268 static public_key_t
* get_ref(private_openssl_rsa_public_key_t
*this)
271 return &this->public.interface
;
275 * Implementation of openssl_rsa_public_key.destroy.
277 static void destroy(private_openssl_rsa_public_key_t
*this)
279 if (ref_put(&this->ref
))
283 lib
->encoding
->clear_cache(lib
->encoding
, this->rsa
);
291 * Generic private constructor
293 static private_openssl_rsa_public_key_t
*create_empty()
295 private_openssl_rsa_public_key_t
*this = malloc_thing(private_openssl_rsa_public_key_t
);
297 this->public.interface
.get_type
= (key_type_t (*)(public_key_t
*this))get_type
;
298 this->public.interface
.verify
= (bool (*)(public_key_t
*this, signature_scheme_t scheme
, chunk_t data
, chunk_t signature
))verify
;
299 this->public.interface
.encrypt
= (bool (*)(public_key_t
*this, chunk_t crypto
, chunk_t
*plain
))encrypt_
;
300 this->public.interface
.equals
= public_key_equals
;
301 this->public.interface
.get_keysize
= (size_t (*) (public_key_t
*this))get_keysize
;
302 this->public.interface
.get_fingerprint
= (bool(*)(public_key_t
*, key_encoding_type_t type
, chunk_t
*fp
))get_fingerprint
;
303 this->public.interface
.has_fingerprint
= (bool(*)(public_key_t
*, chunk_t fp
))public_key_has_fingerprint
;
304 this->public.interface
.get_encoding
= (bool(*)(public_key_t
*, key_encoding_type_t type
, chunk_t
*encoding
))get_encoding
;
305 this->public.interface
.get_ref
= (public_key_t
* (*)(public_key_t
*this))get_ref
;
306 this->public.interface
.destroy
= (void (*)(public_key_t
*this))destroy
;
317 openssl_rsa_public_key_t
*openssl_rsa_public_key_load(key_type_t type
,
320 private_openssl_rsa_public_key_t
*this;
323 n
= e
= blob
= chunk_empty
;
326 switch (va_arg(args
, builder_part_t
))
328 case BUILD_BLOB_ASN1_DER
:
329 blob
= va_arg(args
, chunk_t
);
331 case BUILD_RSA_MODULUS
:
332 n
= va_arg(args
, chunk_t
);
334 case BUILD_RSA_PUB_EXP
:
335 e
= va_arg(args
, chunk_t
);
345 this = create_empty();
348 this->rsa
= d2i_RSAPublicKey(NULL
, (const u_char
**)&blob
.ptr
, blob
.len
);
351 return &this->public;
354 else if (n
.ptr
&& e
.ptr
)
356 this->rsa
= RSA_new();
357 this->rsa
->n
= BN_bin2bn((const u_char
*)n
.ptr
, n
.len
, NULL
);
358 this->rsa
->e
= BN_bin2bn((const u_char
*)e
.ptr
, e
.len
, NULL
);
359 return &this->public;