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_private_key.h"
18 #include "openssl_rsa_public_key.h"
22 #include <openssl/evp.h>
23 #include <openssl/rsa.h>
24 #ifndef OPENSSL_NO_ENGINE
25 #include <openssl/engine.h>
26 #endif /* OPENSSL_NO_ENGINE */
29 * Public exponent to use for key generation.
31 #define PUBLIC_EXPONENT 0x10001
33 typedef struct private_openssl_rsa_private_key_t private_openssl_rsa_private_key_t
;
36 * Private data of a openssl_rsa_private_key_t object.
38 struct private_openssl_rsa_private_key_t
{
40 * Public interface for this signer.
42 openssl_rsa_private_key_t
public;
45 * RSA object from OpenSSL
50 * TRUE if the key is from an OpenSSL ENGINE and might not be readable
60 /* implemented in rsa public key */
61 bool openssl_rsa_fingerprint(RSA
*rsa
, cred_encoding_type_t type
, chunk_t
*fp
);
64 * Build an EMPSA PKCS1 signature described in PKCS#1
66 static bool build_emsa_pkcs1_signature(private_openssl_rsa_private_key_t
*this,
67 int type
, chunk_t data
, chunk_t
*sig
)
71 *sig
= chunk_alloc(RSA_size(this->rsa
));
73 if (type
== NID_undef
)
75 if (RSA_private_encrypt(data
.len
, data
.ptr
, sig
->ptr
, this->rsa
,
76 RSA_PKCS1_PADDING
) == sig
->len
)
88 hasher
= EVP_get_digestbynid(type
);
94 ctx
= EVP_MD_CTX_create();
100 if (!EVP_PKEY_set1_RSA(key
, this->rsa
))
104 if (!EVP_SignInit_ex(ctx
, hasher
, NULL
))
108 if (!EVP_SignUpdate(ctx
, data
.ptr
, data
.len
))
112 if (EVP_SignFinal(ctx
, sig
->ptr
, &len
, key
))
124 EVP_MD_CTX_destroy(ctx
);
135 * Implementation of openssl_rsa_private_key.get_type.
137 static key_type_t
get_type(private_openssl_rsa_private_key_t
*this)
143 * Implementation of openssl_rsa_private_key.sign.
145 static bool sign(private_openssl_rsa_private_key_t
*this, signature_scheme_t scheme
,
146 chunk_t data
, chunk_t
*signature
)
150 case SIGN_RSA_EMSA_PKCS1_NULL
:
151 return build_emsa_pkcs1_signature(this, NID_undef
, data
, signature
);
152 case SIGN_RSA_EMSA_PKCS1_SHA1
:
153 return build_emsa_pkcs1_signature(this, NID_sha1
, data
, signature
);
154 case SIGN_RSA_EMSA_PKCS1_SHA224
:
155 return build_emsa_pkcs1_signature(this, NID_sha224
, data
, signature
);
156 case SIGN_RSA_EMSA_PKCS1_SHA256
:
157 return build_emsa_pkcs1_signature(this, NID_sha256
, data
, signature
);
158 case SIGN_RSA_EMSA_PKCS1_SHA384
:
159 return build_emsa_pkcs1_signature(this, NID_sha384
, data
, signature
);
160 case SIGN_RSA_EMSA_PKCS1_SHA512
:
161 return build_emsa_pkcs1_signature(this, NID_sha512
, data
, signature
);
162 case SIGN_RSA_EMSA_PKCS1_MD5
:
163 return build_emsa_pkcs1_signature(this, NID_md5
, data
, signature
);
165 DBG1(DBG_LIB
, "signature scheme %N not supported in RSA",
166 signature_scheme_names
, scheme
);
172 * Implementation of openssl_rsa_private_key.decrypt.
174 static bool decrypt(private_openssl_rsa_private_key_t
*this,
175 chunk_t crypto
, chunk_t
*plain
)
177 DBG1(DBG_LIB
, "RSA private key decryption not implemented");
182 * Implementation of openssl_rsa_private_key.get_keysize.
184 static size_t get_keysize(private_openssl_rsa_private_key_t
*this)
186 return RSA_size(this->rsa
);
190 * Implementation of openssl_rsa_private_key.get_public_key.
192 static public_key_t
* get_public_key(private_openssl_rsa_private_key_t
*this)
198 enc
= chunk_alloc(i2d_RSAPublicKey(this->rsa
, NULL
));
200 i2d_RSAPublicKey(this->rsa
, &p
);
201 key
= lib
->creds
->create(lib
->creds
, CRED_PUBLIC_KEY
, KEY_RSA
,
202 BUILD_BLOB_ASN1_DER
, enc
, BUILD_END
);
208 * Implementation of public_key_t.get_fingerprint.
210 static bool get_fingerprint(private_openssl_rsa_private_key_t
*this,
211 cred_encoding_type_t type
, chunk_t
*fingerprint
)
213 return openssl_rsa_fingerprint(this->rsa
, type
, fingerprint
);
217 * Implementation of public_key_t.get_encoding.
219 static bool get_encoding(private_openssl_rsa_private_key_t
*this,
220 cred_encoding_type_t type
, chunk_t
*encoding
)
230 case PRIVKEY_ASN1_DER
:
235 *encoding
= chunk_alloc(i2d_RSAPrivateKey(this->rsa
, NULL
));
237 i2d_RSAPrivateKey(this->rsa
, &p
);
239 if (type
== PRIVKEY_PEM
)
241 chunk_t asn1_encoding
= *encoding
;
243 success
= lib
->encoding
->encode(lib
->encoding
, PRIVKEY_PEM
,
244 NULL
, encoding
, CRED_PART_RSA_PRIV_ASN1_DER
,
245 asn1_encoding
, CRED_PART_END
);
246 chunk_clear(&asn1_encoding
);
256 * Implementation of openssl_rsa_private_key.get_ref.
258 static private_openssl_rsa_private_key_t
* get_ref(private_openssl_rsa_private_key_t
*this)
265 * Implementation of openssl_rsa_private_key.destroy.
267 static void destroy(private_openssl_rsa_private_key_t
*this)
269 if (ref_put(&this->ref
))
273 lib
->encoding
->clear_cache(lib
->encoding
, this->rsa
);
281 * Internal generic constructor
283 static private_openssl_rsa_private_key_t
*create_empty(void)
285 private_openssl_rsa_private_key_t
*this = malloc_thing(private_openssl_rsa_private_key_t
);
287 this->public.interface
.get_type
= (key_type_t (*) (private_key_t
*))get_type
;
288 this->public.interface
.sign
= (bool (*) (private_key_t
*, signature_scheme_t
, chunk_t
, chunk_t
*))sign
;
289 this->public.interface
.decrypt
= (bool (*) (private_key_t
*, chunk_t
, chunk_t
*))decrypt
;
290 this->public.interface
.get_keysize
= (size_t (*) (private_key_t
*))get_keysize
;
291 this->public.interface
.get_public_key
= (public_key_t
* (*) (private_key_t
*))get_public_key
;
292 this->public.interface
.equals
= private_key_equals
;
293 this->public.interface
.belongs_to
= private_key_belongs_to
;
294 this->public.interface
.get_fingerprint
= (bool(*)(private_key_t
*, cred_encoding_type_t type
, chunk_t
*fp
))get_fingerprint
;
295 this->public.interface
.has_fingerprint
= (bool(*)(private_key_t
*, chunk_t fp
))private_key_has_fingerprint
;
296 this->public.interface
.get_encoding
= (bool(*)(private_key_t
*, cred_encoding_type_t type
, chunk_t
*encoding
))get_encoding
;
297 this->public.interface
.get_ref
= (private_key_t
* (*) (private_key_t
*))get_ref
;
298 this->public.interface
.destroy
= (void (*) (private_key_t
*))destroy
;
300 this->engine
= FALSE
;
309 openssl_rsa_private_key_t
*openssl_rsa_private_key_gen(key_type_t type
,
312 private_openssl_rsa_private_key_t
*this;
319 switch (va_arg(args
, builder_part_t
))
322 key_size
= va_arg(args
, u_int
);
336 if (!e
|| !BN_set_word(e
, PUBLIC_EXPONENT
))
341 if (!rsa
|| !RSA_generate_key_ex(rsa
, key_size
, e
, NULL
))
345 this = create_empty();
348 return &this->public;
365 openssl_rsa_private_key_t
*openssl_rsa_private_key_load(key_type_t type
,
368 private_openssl_rsa_private_key_t
*this;
369 chunk_t blob
, n
, e
, d
, p
, q
, exp1
, exp2
, coeff
;
371 blob
= n
= e
= d
= p
= q
= exp1
= exp2
= coeff
= chunk_empty
;
374 switch (va_arg(args
, builder_part_t
))
376 case BUILD_BLOB_ASN1_DER
:
377 blob
= va_arg(args
, chunk_t
);
379 case BUILD_RSA_MODULUS
:
380 n
= va_arg(args
, chunk_t
);
382 case BUILD_RSA_PUB_EXP
:
383 e
= va_arg(args
, chunk_t
);
385 case BUILD_RSA_PRIV_EXP
:
386 d
= va_arg(args
, chunk_t
);
388 case BUILD_RSA_PRIME1
:
389 p
= va_arg(args
, chunk_t
);
391 case BUILD_RSA_PRIME2
:
392 q
= va_arg(args
, chunk_t
);
395 exp1
= va_arg(args
, chunk_t
);
398 exp2
= va_arg(args
, chunk_t
);
400 case BUILD_RSA_COEFF
:
401 coeff
= va_arg(args
, chunk_t
);
411 this = create_empty();
414 this->rsa
= d2i_RSAPrivateKey(NULL
, (const u_char
**)&blob
.ptr
, blob
.len
);
415 if (this->rsa
&& RSA_check_key(this->rsa
))
417 return &this->public;
420 else if (n
.ptr
&& e
.ptr
&& d
.ptr
&& p
.ptr
&& q
.ptr
&& coeff
.ptr
)
422 this->rsa
= RSA_new();
423 this->rsa
->n
= BN_bin2bn((const u_char
*)n
.ptr
, n
.len
, NULL
);
424 this->rsa
->e
= BN_bin2bn((const u_char
*)e
.ptr
, e
.len
, NULL
);
425 this->rsa
->d
= BN_bin2bn((const u_char
*)d
.ptr
, d
.len
, NULL
);
426 this->rsa
->p
= BN_bin2bn((const u_char
*)p
.ptr
, p
.len
, NULL
);
427 this->rsa
->q
= BN_bin2bn((const u_char
*)q
.ptr
, q
.len
, NULL
);
430 this->rsa
->dmp1
= BN_bin2bn((const u_char
*)exp1
.ptr
, exp1
.len
, NULL
);
434 this->rsa
->dmq1
= BN_bin2bn((const u_char
*)exp2
.ptr
, exp2
.len
, NULL
);
436 this->rsa
->iqmp
= BN_bin2bn((const u_char
*)coeff
.ptr
, coeff
.len
, NULL
);
437 if (RSA_check_key(this->rsa
))
439 return &this->public;
449 openssl_rsa_private_key_t
*openssl_rsa_private_key_connect(key_type_t type
,
452 #ifndef OPENSSL_NO_ENGINE
453 private_openssl_rsa_private_key_t
*this;
454 char *keyid
= NULL
, *engine_id
= NULL
;
455 char keyname
[64], pin
[32];;
456 chunk_t secret
= chunk_empty
;
463 switch (va_arg(args
, builder_part_t
))
465 case BUILD_PKCS11_KEYID
:
466 keyid
= va_arg(args
, char*);
468 case BUILD_PASSPHRASE
:
469 secret
= va_arg(args
, chunk_t
);
471 case BUILD_PKCS11_SLOT
:
472 slot
= va_arg(args
, int);
474 case BUILD_PKCS11_MODULE
:
475 engine_id
= va_arg(args
, char*);
484 if (!keyid
|| !secret
.len
|| !secret
.ptr
)
491 snprintf(keyname
, sizeof(keyname
), "%s", keyid
);
495 snprintf(keyname
, sizeof(keyname
), "%d:%s", slot
, keyid
);
497 snprintf(pin
, sizeof(pin
), "%.*s", secret
.len
, secret
.ptr
);
501 engine_id
= lib
->settings
->get_str(lib
->settings
,
502 "libstrongswan.plugins.openssl.engine_id", "pkcs11");
504 engine
= ENGINE_by_id(engine_id
);
507 DBG1(DBG_LIB
, "engine '%s' is not available", engine_id
);
510 if (!ENGINE_init(engine
))
512 DBG1(DBG_LIB
, "failed to initialize engine '%s'", engine_id
);
516 if (!ENGINE_ctrl_cmd_string(engine
, "PIN", pin
, 0))
518 DBG1(DBG_LIB
, "failed to set PIN on engine '%s'", engine_id
);
523 key
= ENGINE_load_private_key(engine
, keyname
, NULL
, NULL
);
526 DBG1(DBG_LIB
, "failed to load private key with ID '%s' from "
527 "engine '%s'", keyname
, engine_id
);
533 this = create_empty();
534 this->rsa
= EVP_PKEY_get1_RSA(key
);
542 return &this->public;
543 #else /* OPENSSL_NO_ENGINE */
545 #endif /* OPENSSL_NO_ENGINE */