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/opensslconf.h>
19 #ifndef OPENSSL_NO_RSA
21 #include "openssl_rsa_public_key.h"
23 #include <utils/debug.h>
25 #include <openssl/evp.h>
26 #include <openssl/rsa.h>
27 #include <openssl/x509.h>
29 typedef struct private_openssl_rsa_public_key_t private_openssl_rsa_public_key_t
;
32 * Private data structure with signing context.
34 struct private_openssl_rsa_public_key_t
{
36 * Public interface for this signer.
38 openssl_rsa_public_key_t
public;
41 * RSA object from OpenSSL
54 * Verification of an EMPSA PKCS1 signature described in PKCS#1
56 static bool verify_emsa_pkcs1_signature(private_openssl_rsa_public_key_t
*this,
57 int type
, chunk_t data
, chunk_t signature
)
60 int rsa_size
= RSA_size(this->rsa
);
62 /* OpenSSL expects a signature of exactly RSA size (no leading 0x00) */
63 if (signature
.len
> rsa_size
)
65 signature
= chunk_skip(signature
, signature
.len
- rsa_size
);
68 if (type
== NID_undef
)
70 chunk_t hash
= chunk_alloc(rsa_size
);
72 hash
.len
= RSA_public_decrypt(signature
.len
, signature
.ptr
, hash
.ptr
,
73 this->rsa
, RSA_PKCS1_PADDING
);
74 valid
= chunk_equals(data
, hash
);
83 hasher
= EVP_get_digestbynid(type
);
89 ctx
= EVP_MD_CTX_create();
96 if (!EVP_PKEY_set1_RSA(key
, this->rsa
))
100 if (!EVP_VerifyInit_ex(ctx
, hasher
, NULL
))
104 if (!EVP_VerifyUpdate(ctx
, data
.ptr
, data
.len
))
108 valid
= (EVP_VerifyFinal(ctx
, signature
.ptr
, signature
.len
, key
) == 1);
117 EVP_MD_CTX_destroy(ctx
);
123 METHOD(public_key_t
, get_type
, key_type_t
,
124 private_openssl_rsa_public_key_t
*this)
129 METHOD(public_key_t
, verify
, bool,
130 private_openssl_rsa_public_key_t
*this, signature_scheme_t scheme
,
131 chunk_t data
, chunk_t signature
)
135 case SIGN_RSA_EMSA_PKCS1_NULL
:
136 return verify_emsa_pkcs1_signature(this, NID_undef
, data
, signature
);
137 case SIGN_RSA_EMSA_PKCS1_SHA1
:
138 return verify_emsa_pkcs1_signature(this, NID_sha1
, data
, signature
);
139 case SIGN_RSA_EMSA_PKCS1_SHA224
:
140 return verify_emsa_pkcs1_signature(this, NID_sha224
, data
, signature
);
141 case SIGN_RSA_EMSA_PKCS1_SHA256
:
142 return verify_emsa_pkcs1_signature(this, NID_sha256
, data
, signature
);
143 case SIGN_RSA_EMSA_PKCS1_SHA384
:
144 return verify_emsa_pkcs1_signature(this, NID_sha384
, data
, signature
);
145 case SIGN_RSA_EMSA_PKCS1_SHA512
:
146 return verify_emsa_pkcs1_signature(this, NID_sha512
, data
, signature
);
147 case SIGN_RSA_EMSA_PKCS1_MD5
:
148 return verify_emsa_pkcs1_signature(this, NID_md5
, data
, signature
);
150 DBG1(DBG_LIB
, "signature scheme %N not supported in RSA",
151 signature_scheme_names
, scheme
);
156 METHOD(public_key_t
, encrypt
, bool,
157 private_openssl_rsa_public_key_t
*this, encryption_scheme_t scheme
,
158 chunk_t plain
, chunk_t
*crypto
)
165 case ENCRYPT_RSA_PKCS1
:
166 padding
= RSA_PKCS1_PADDING
;
168 case ENCRYPT_RSA_OAEP_SHA1
:
169 padding
= RSA_PKCS1_OAEP_PADDING
;
172 DBG1(DBG_LIB
, "decryption scheme %N not supported via openssl",
173 encryption_scheme_names
, scheme
);
176 encrypted
= malloc(RSA_size(this->rsa
));
177 len
= RSA_public_encrypt(plain
.len
, plain
.ptr
, encrypted
,
181 DBG1(DBG_LIB
, "RSA decryption failed");
185 *crypto
= chunk_create(encrypted
, len
);
189 METHOD(public_key_t
, get_keysize
, int,
190 private_openssl_rsa_public_key_t
*this)
192 return RSA_size(this->rsa
) * 8;
196 * Calculate fingerprint from a RSA key, also used in rsa private key.
198 bool openssl_rsa_fingerprint(RSA
*rsa
, cred_encoding_type_t type
, chunk_t
*fp
)
204 if (lib
->encoding
->get_cache(lib
->encoding
, type
, rsa
, fp
))
210 case KEYID_PUBKEY_SHA1
:
211 key
= chunk_alloc(i2d_RSAPublicKey(rsa
, NULL
));
213 i2d_RSAPublicKey(rsa
, &p
);
215 case KEYID_PUBKEY_INFO_SHA1
:
216 key
= chunk_alloc(i2d_RSA_PUBKEY(rsa
, NULL
));
218 i2d_RSA_PUBKEY(rsa
, &p
);
223 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
224 if (!hasher
|| !hasher
->allocate_hash(hasher
, key
, fp
))
226 DBG1(DBG_LIB
, "SHA1 hash algorithm not supported, fingerprinting failed");
232 hasher
->destroy(hasher
);
233 lib
->encoding
->cache(lib
->encoding
, type
, rsa
, *fp
);
237 METHOD(public_key_t
, get_fingerprint
, bool,
238 private_openssl_rsa_public_key_t
*this, cred_encoding_type_t type
,
239 chunk_t
*fingerprint
)
241 return openssl_rsa_fingerprint(this->rsa
, type
, fingerprint
);
244 METHOD(public_key_t
, get_encoding
, bool,
245 private_openssl_rsa_public_key_t
*this, cred_encoding_type_t type
,
252 case PUBKEY_SPKI_ASN1_DER
:
257 *encoding
= chunk_alloc(i2d_RSA_PUBKEY(this->rsa
, NULL
));
259 i2d_RSA_PUBKEY(this->rsa
, &p
);
261 if (type
== PUBKEY_PEM
)
263 chunk_t asn1_encoding
= *encoding
;
265 success
= lib
->encoding
->encode(lib
->encoding
, PUBKEY_PEM
,
266 NULL
, encoding
, CRED_PART_RSA_PUB_ASN1_DER
,
267 asn1_encoding
, CRED_PART_END
);
268 chunk_clear(&asn1_encoding
);
272 case PUBKEY_ASN1_DER
:
274 *encoding
= chunk_alloc(i2d_RSAPublicKey(this->rsa
, NULL
));
276 i2d_RSAPublicKey(this->rsa
, &p
);
284 METHOD(public_key_t
, get_ref
, public_key_t
*,
285 private_openssl_rsa_public_key_t
*this)
288 return &this->public.key
;
291 METHOD(public_key_t
, destroy
, void,
292 private_openssl_rsa_public_key_t
*this)
294 if (ref_put(&this->ref
))
298 lib
->encoding
->clear_cache(lib
->encoding
, this->rsa
);
306 * Generic private constructor
308 static private_openssl_rsa_public_key_t
*create_empty()
310 private_openssl_rsa_public_key_t
*this;
315 .get_type
= _get_type
,
318 .equals
= public_key_equals
,
319 .get_keysize
= _get_keysize
,
320 .get_fingerprint
= _get_fingerprint
,
321 .has_fingerprint
= public_key_has_fingerprint
,
322 .get_encoding
= _get_encoding
,
336 openssl_rsa_public_key_t
*openssl_rsa_public_key_load(key_type_t type
,
339 private_openssl_rsa_public_key_t
*this;
342 n
= e
= blob
= chunk_empty
;
345 switch (va_arg(args
, builder_part_t
))
347 case BUILD_BLOB_ASN1_DER
:
348 blob
= va_arg(args
, chunk_t
);
350 case BUILD_RSA_MODULUS
:
351 n
= va_arg(args
, chunk_t
);
353 case BUILD_RSA_PUB_EXP
:
354 e
= va_arg(args
, chunk_t
);
364 this = create_empty();
370 this->rsa
= d2i_RSA_PUBKEY(NULL
, (const u_char
**)&blob
.ptr
,
374 this->rsa
= d2i_RSAPublicKey(NULL
, (const u_char
**)&blob
.ptr
,
382 return &this->public;
385 else if (n
.ptr
&& e
.ptr
&& type
== KEY_RSA
)
387 this->rsa
= RSA_new();
388 this->rsa
->n
= BN_bin2bn((const u_char
*)n
.ptr
, n
.len
, NULL
);
389 this->rsa
->e
= BN_bin2bn((const u_char
*)e
.ptr
, e
.len
, NULL
);
390 return &this->public;
396 #endif /* OPENSSL_NO_RSA */