]>
Commit | Line | Data |
---|---|---|
84770ded | 1 | /* |
e35c3e2a | 2 | * Copyright (C) 2009 Martin Willi |
84770ded TB |
3 | * Copyright (C) 2008 Tobias Brunner |
4 | * Hochschule fuer Technik Rapperswil | |
5 | * | |
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>. | |
10 | * | |
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 | |
14 | * for more details. | |
84770ded TB |
15 | */ |
16 | ||
17 | #include "openssl_rsa_private_key.h" | |
18 | #include "openssl_rsa_public_key.h" | |
19 | ||
20 | #include <debug.h> | |
21 | ||
22 | #include <openssl/evp.h> | |
23 | #include <openssl/rsa.h> | |
1e3d66f8 | 24 | #ifndef OPENSSL_NO_ENGINE |
83c42156 | 25 | #include <openssl/engine.h> |
1e3d66f8 | 26 | #endif /* OPENSSL_NO_ENGINE */ |
84770ded TB |
27 | |
28 | /** | |
29 | * Public exponent to use for key generation. | |
30 | */ | |
31 | #define PUBLIC_EXPONENT 0x10001 | |
32 | ||
33 | typedef struct private_openssl_rsa_private_key_t private_openssl_rsa_private_key_t; | |
34 | ||
35 | /** | |
36 | * Private data of a openssl_rsa_private_key_t object. | |
37 | */ | |
38 | struct private_openssl_rsa_private_key_t { | |
39 | /** | |
40 | * Public interface for this signer. | |
41 | */ | |
42 | openssl_rsa_private_key_t public; | |
7daf5226 | 43 | |
84770ded TB |
44 | /** |
45 | * RSA object from OpenSSL | |
46 | */ | |
47 | RSA *rsa; | |
7daf5226 | 48 | |
83c42156 TB |
49 | /** |
50 | * TRUE if the key is from an OpenSSL ENGINE and might not be readable | |
51 | */ | |
52 | bool engine; | |
7daf5226 | 53 | |
84770ded TB |
54 | /** |
55 | * reference count | |
56 | */ | |
e35c3e2a | 57 | refcount_t ref; |
84770ded TB |
58 | }; |
59 | ||
b12c6d16 | 60 | /* implemented in rsa public key */ |
da9724e6 | 61 | bool openssl_rsa_fingerprint(RSA *rsa, cred_encoding_type_t type, chunk_t *fp); |
b12c6d16 | 62 | |
84770ded TB |
63 | /** |
64 | * Build an EMPSA PKCS1 signature described in PKCS#1 | |
65 | */ | |
66 | static bool build_emsa_pkcs1_signature(private_openssl_rsa_private_key_t *this, | |
dfa5fb03 | 67 | int type, chunk_t data, chunk_t *sig) |
84770ded TB |
68 | { |
69 | bool success = FALSE; | |
dfa5fb03 AS |
70 | |
71 | *sig = chunk_alloc(RSA_size(this->rsa)); | |
72 | ||
73 | if (type == NID_undef) | |
84770ded | 74 | { |
dfa5fb03 AS |
75 | if (RSA_private_encrypt(data.len, data.ptr, sig->ptr, this->rsa, |
76 | RSA_PKCS1_PADDING) == sig->len) | |
77 | { | |
78 | success = TRUE; | |
79 | } | |
dcbea444 MW |
80 | } |
81 | else | |
82 | { | |
dfa5fb03 AS |
83 | EVP_MD_CTX *ctx; |
84 | EVP_PKEY *key; | |
85 | const EVP_MD *hasher; | |
942127a6 | 86 | u_int len; |
7daf5226 | 87 | |
dfa5fb03 AS |
88 | hasher = EVP_get_digestbynid(type); |
89 | if (!hasher) | |
90 | { | |
91 | return FALSE; | |
92 | } | |
7daf5226 | 93 | |
dfa5fb03 AS |
94 | ctx = EVP_MD_CTX_create(); |
95 | key = EVP_PKEY_new(); | |
96 | if (!ctx || !key) | |
97 | { | |
98 | goto error; | |
99 | } | |
100 | if (!EVP_PKEY_set1_RSA(key, this->rsa)) | |
101 | { | |
102 | goto error; | |
103 | } | |
104 | if (!EVP_SignInit_ex(ctx, hasher, NULL)) | |
105 | { | |
106 | goto error; | |
107 | } | |
108 | if (!EVP_SignUpdate(ctx, data.ptr, data.len)) | |
109 | { | |
110 | goto error; | |
111 | } | |
942127a6 | 112 | if (EVP_SignFinal(ctx, sig->ptr, &len, key)) |
dfa5fb03 AS |
113 | { |
114 | success = TRUE; | |
115 | } | |
7daf5226 | 116 | |
84770ded | 117 | error: |
dfa5fb03 AS |
118 | if (key) |
119 | { | |
120 | EVP_PKEY_free(key); | |
121 | } | |
122 | if (ctx) | |
123 | { | |
124 | EVP_MD_CTX_destroy(ctx); | |
125 | } | |
84770ded | 126 | } |
dfa5fb03 | 127 | if (!success) |
84770ded | 128 | { |
dfa5fb03 | 129 | free(sig->ptr); |
84770ded TB |
130 | } |
131 | return success; | |
132 | } | |
133 | ||
57202484 MW |
134 | |
135 | METHOD(private_key_t, get_type, key_type_t, | |
136 | private_openssl_rsa_private_key_t *this) | |
84770ded TB |
137 | { |
138 | return KEY_RSA; | |
139 | } | |
140 | ||
57202484 MW |
141 | METHOD(private_key_t, sign, bool, |
142 | private_openssl_rsa_private_key_t *this, signature_scheme_t scheme, | |
143 | chunk_t data, chunk_t *signature) | |
84770ded TB |
144 | { |
145 | switch (scheme) | |
146 | { | |
dfa5fb03 AS |
147 | case SIGN_RSA_EMSA_PKCS1_NULL: |
148 | return build_emsa_pkcs1_signature(this, NID_undef, data, signature); | |
84770ded TB |
149 | case SIGN_RSA_EMSA_PKCS1_SHA1: |
150 | return build_emsa_pkcs1_signature(this, NID_sha1, data, signature); | |
b6f739c1 AS |
151 | case SIGN_RSA_EMSA_PKCS1_SHA224: |
152 | return build_emsa_pkcs1_signature(this, NID_sha224, data, signature); | |
84770ded TB |
153 | case SIGN_RSA_EMSA_PKCS1_SHA256: |
154 | return build_emsa_pkcs1_signature(this, NID_sha256, data, signature); | |
155 | case SIGN_RSA_EMSA_PKCS1_SHA384: | |
156 | return build_emsa_pkcs1_signature(this, NID_sha384, data, signature); | |
157 | case SIGN_RSA_EMSA_PKCS1_SHA512: | |
158 | return build_emsa_pkcs1_signature(this, NID_sha512, data, signature); | |
159 | case SIGN_RSA_EMSA_PKCS1_MD5: | |
160 | return build_emsa_pkcs1_signature(this, NID_md5, data, signature); | |
161 | default: | |
8b0e0910 | 162 | DBG1(DBG_LIB, "signature scheme %N not supported in RSA", |
84770ded TB |
163 | signature_scheme_names, scheme); |
164 | return FALSE; | |
165 | } | |
166 | } | |
167 | ||
57202484 | 168 | METHOD(private_key_t, decrypt, bool, |
33ddaaab MW |
169 | private_openssl_rsa_private_key_t *this, encryption_scheme_t scheme, |
170 | chunk_t crypto, chunk_t *plain) | |
84770ded | 171 | { |
d775af9d MW |
172 | int padding, len; |
173 | char *decrypted; | |
174 | ||
175 | switch (scheme) | |
176 | { | |
177 | case ENCRYPT_RSA_PKCS1: | |
178 | padding = RSA_PKCS1_PADDING; | |
179 | break; | |
180 | case ENCRYPT_RSA_OAEP_SHA1: | |
181 | padding = RSA_PKCS1_OAEP_PADDING; | |
182 | break; | |
183 | default: | |
184 | DBG1(DBG_LIB, "encryption scheme %N not supported via openssl", | |
185 | encryption_scheme_names, scheme); | |
186 | return FALSE; | |
187 | } | |
188 | decrypted = malloc(RSA_size(this->rsa)); | |
189 | len = RSA_private_decrypt(crypto.len, crypto.ptr, decrypted, | |
190 | this->rsa, padding); | |
191 | if (len < 0) | |
192 | { | |
193 | DBG1(DBG_LIB, "RSA decryption failed"); | |
194 | free(decrypted); | |
195 | return FALSE; | |
196 | } | |
197 | *plain = chunk_create(decrypted, len); | |
198 | return TRUE; | |
84770ded TB |
199 | } |
200 | ||
a944d209 | 201 | METHOD(private_key_t, get_keysize, int, |
57202484 | 202 | private_openssl_rsa_private_key_t *this) |
84770ded | 203 | { |
a944d209 | 204 | return RSA_size(this->rsa) * 8; |
84770ded TB |
205 | } |
206 | ||
57202484 MW |
207 | METHOD(private_key_t, get_public_key, public_key_t*, |
208 | private_openssl_rsa_private_key_t *this) | |
8b799d55 | 209 | { |
e35c3e2a MW |
210 | chunk_t enc; |
211 | public_key_t *key; | |
212 | u_char *p; | |
7daf5226 | 213 | |
e35c3e2a MW |
214 | enc = chunk_alloc(i2d_RSAPublicKey(this->rsa, NULL)); |
215 | p = enc.ptr; | |
216 | i2d_RSAPublicKey(this->rsa, &p); | |
217 | key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, | |
218 | BUILD_BLOB_ASN1_DER, enc, BUILD_END); | |
219 | free(enc.ptr); | |
220 | return key; | |
8b799d55 AS |
221 | } |
222 | ||
57202484 MW |
223 | METHOD(private_key_t, get_fingerprint, bool, |
224 | private_openssl_rsa_private_key_t *this, cred_encoding_type_t type, | |
225 | chunk_t *fingerprint) | |
84770ded | 226 | { |
b12c6d16 | 227 | return openssl_rsa_fingerprint(this->rsa, type, fingerprint); |
84770ded TB |
228 | } |
229 | ||
57202484 MW |
230 | METHOD(private_key_t, get_encoding, bool, |
231 | private_openssl_rsa_private_key_t *this, cred_encoding_type_t type, | |
232 | chunk_t *encoding) | |
84770ded | 233 | { |
e35c3e2a | 234 | u_char *p; |
7daf5226 | 235 | |
a0b85045 | 236 | if (this->engine) |
83c42156 | 237 | { |
e35c3e2a | 238 | return FALSE; |
83c42156 | 239 | } |
b12c6d16 MW |
240 | switch (type) |
241 | { | |
da9724e6 MW |
242 | case PRIVKEY_ASN1_DER: |
243 | case PRIVKEY_PEM: | |
b12c6d16 | 244 | { |
29cf15a9 AS |
245 | bool success = TRUE; |
246 | ||
b12c6d16 MW |
247 | *encoding = chunk_alloc(i2d_RSAPrivateKey(this->rsa, NULL)); |
248 | p = encoding->ptr; | |
249 | i2d_RSAPrivateKey(this->rsa, &p); | |
29cf15a9 | 250 | |
da9724e6 | 251 | if (type == PRIVKEY_PEM) |
29cf15a9 AS |
252 | { |
253 | chunk_t asn1_encoding = *encoding; | |
254 | ||
da9724e6 MW |
255 | success = lib->encoding->encode(lib->encoding, PRIVKEY_PEM, |
256 | NULL, encoding, CRED_PART_RSA_PRIV_ASN1_DER, | |
257 | asn1_encoding, CRED_PART_END); | |
29cf15a9 | 258 | chunk_clear(&asn1_encoding); |
0a4dc787 | 259 | } |
29cf15a9 | 260 | return success; |
b12c6d16 MW |
261 | } |
262 | default: | |
263 | return FALSE; | |
264 | } | |
84770ded TB |
265 | } |
266 | ||
57202484 MW |
267 | METHOD(private_key_t, get_ref, private_key_t*, |
268 | private_openssl_rsa_private_key_t *this) | |
84770ded TB |
269 | { |
270 | ref_get(&this->ref); | |
57202484 | 271 | return &this->public.key; |
84770ded TB |
272 | } |
273 | ||
57202484 MW |
274 | METHOD(private_key_t, destroy, void, |
275 | private_openssl_rsa_private_key_t *this) | |
84770ded TB |
276 | { |
277 | if (ref_put(&this->ref)) | |
278 | { | |
279 | if (this->rsa) | |
280 | { | |
b12c6d16 | 281 | lib->encoding->clear_cache(lib->encoding, this->rsa); |
84770ded TB |
282 | RSA_free(this->rsa); |
283 | } | |
84770ded TB |
284 | free(this); |
285 | } | |
286 | } | |
287 | ||
288 | /** | |
289 | * Internal generic constructor | |
290 | */ | |
57202484 | 291 | static private_openssl_rsa_private_key_t *create_empty() |
84770ded | 292 | { |
57202484 MW |
293 | private_openssl_rsa_private_key_t *this; |
294 | ||
295 | INIT(this, | |
ba31fe1f MW |
296 | .public = { |
297 | .key = { | |
298 | .get_type = _get_type, | |
299 | .sign = _sign, | |
300 | .decrypt = _decrypt, | |
301 | .get_keysize = _get_keysize, | |
302 | .get_public_key = _get_public_key, | |
303 | .equals = private_key_equals, | |
304 | .belongs_to = private_key_belongs_to, | |
305 | .get_fingerprint = _get_fingerprint, | |
306 | .has_fingerprint = private_key_has_fingerprint, | |
307 | .get_encoding = _get_encoding, | |
308 | .get_ref = _get_ref, | |
309 | .destroy = _destroy, | |
310 | }, | |
57202484 MW |
311 | }, |
312 | .ref = 1, | |
313 | ); | |
7daf5226 | 314 | |
84770ded TB |
315 | return this; |
316 | } | |
317 | ||
318 | /** | |
30c06407 | 319 | * See header. |
84770ded | 320 | */ |
30c06407 MW |
321 | openssl_rsa_private_key_t *openssl_rsa_private_key_gen(key_type_t type, |
322 | va_list args) | |
84770ded | 323 | { |
30c06407 MW |
324 | private_openssl_rsa_private_key_t *this; |
325 | u_int key_size = 0; | |
d14203b0 TB |
326 | RSA *rsa = NULL; |
327 | BIGNUM *e = NULL; | |
7daf5226 | 328 | |
30c06407 MW |
329 | while (TRUE) |
330 | { | |
331 | switch (va_arg(args, builder_part_t)) | |
332 | { | |
333 | case BUILD_KEY_SIZE: | |
334 | key_size = va_arg(args, u_int); | |
335 | continue; | |
336 | case BUILD_END: | |
337 | break; | |
338 | default: | |
339 | return NULL; | |
340 | } | |
341 | break; | |
342 | } | |
343 | if (!key_size) | |
344 | { | |
345 | return NULL; | |
346 | } | |
d14203b0 TB |
347 | e = BN_new(); |
348 | if (!e || !BN_set_word(e, PUBLIC_EXPONENT)) | |
349 | { | |
350 | goto error; | |
351 | } | |
352 | rsa = RSA_new(); | |
353 | if (!rsa || !RSA_generate_key_ex(rsa, key_size, e, NULL)) | |
354 | { | |
355 | goto error; | |
356 | } | |
30c06407 | 357 | this = create_empty(); |
d14203b0 TB |
358 | this->rsa = rsa; |
359 | BN_free(e); | |
84770ded | 360 | return &this->public; |
d14203b0 TB |
361 | |
362 | error: | |
363 | if (e) | |
364 | { | |
365 | BN_free(e); | |
366 | } | |
367 | if (rsa) | |
368 | { | |
369 | RSA_free(rsa); | |
370 | } | |
371 | return NULL; | |
84770ded TB |
372 | } |
373 | ||
374 | /** | |
30c06407 | 375 | * See header |
84770ded | 376 | */ |
30c06407 MW |
377 | openssl_rsa_private_key_t *openssl_rsa_private_key_load(key_type_t type, |
378 | va_list args) | |
84770ded | 379 | { |
30c06407 | 380 | private_openssl_rsa_private_key_t *this; |
b9fbd665 | 381 | chunk_t blob, n, e, d, p, q, exp1, exp2, coeff; |
7daf5226 | 382 | |
b9fbd665 | 383 | blob = n = e = d = p = q = exp1 = exp2 = coeff = chunk_empty; |
30c06407 MW |
384 | while (TRUE) |
385 | { | |
386 | switch (va_arg(args, builder_part_t)) | |
387 | { | |
388 | case BUILD_BLOB_ASN1_DER: | |
389 | blob = va_arg(args, chunk_t); | |
390 | continue; | |
b9fbd665 MW |
391 | case BUILD_RSA_MODULUS: |
392 | n = va_arg(args, chunk_t); | |
393 | continue; | |
394 | case BUILD_RSA_PUB_EXP: | |
395 | e = va_arg(args, chunk_t); | |
396 | continue; | |
397 | case BUILD_RSA_PRIV_EXP: | |
398 | d = va_arg(args, chunk_t); | |
399 | continue; | |
400 | case BUILD_RSA_PRIME1: | |
401 | p = va_arg(args, chunk_t); | |
402 | continue; | |
403 | case BUILD_RSA_PRIME2: | |
404 | q = va_arg(args, chunk_t); | |
405 | continue; | |
406 | case BUILD_RSA_EXP1: | |
407 | exp1 = va_arg(args, chunk_t); | |
408 | continue; | |
409 | case BUILD_RSA_EXP2: | |
410 | exp2 = va_arg(args, chunk_t); | |
411 | continue; | |
412 | case BUILD_RSA_COEFF: | |
413 | coeff = va_arg(args, chunk_t); | |
414 | continue; | |
30c06407 MW |
415 | case BUILD_END: |
416 | break; | |
417 | default: | |
418 | return NULL; | |
419 | } | |
420 | break; | |
421 | } | |
422 | ||
423 | this = create_empty(); | |
b9fbd665 | 424 | if (blob.ptr) |
84770ded | 425 | { |
b9fbd665 MW |
426 | this->rsa = d2i_RSAPrivateKey(NULL, (const u_char**)&blob.ptr, blob.len); |
427 | if (this->rsa && RSA_check_key(this->rsa)) | |
428 | { | |
429 | return &this->public; | |
430 | } | |
84770ded | 431 | } |
012f62a8 | 432 | else if (n.ptr && e.ptr && d.ptr && p.ptr && q.ptr && coeff.ptr) |
84770ded | 433 | { |
b9fbd665 MW |
434 | this->rsa = RSA_new(); |
435 | this->rsa->n = BN_bin2bn((const u_char*)n.ptr, n.len, NULL); | |
436 | this->rsa->e = BN_bin2bn((const u_char*)e.ptr, e.len, NULL); | |
437 | this->rsa->d = BN_bin2bn((const u_char*)d.ptr, d.len, NULL); | |
438 | this->rsa->p = BN_bin2bn((const u_char*)p.ptr, p.len, NULL); | |
439 | this->rsa->q = BN_bin2bn((const u_char*)q.ptr, q.len, NULL); | |
012f62a8 MW |
440 | if (exp1.ptr) |
441 | { | |
442 | this->rsa->dmp1 = BN_bin2bn((const u_char*)exp1.ptr, exp1.len, NULL); | |
443 | } | |
444 | if (exp2.ptr) | |
445 | { | |
446 | this->rsa->dmq1 = BN_bin2bn((const u_char*)exp2.ptr, exp2.len, NULL); | |
447 | } | |
b9fbd665 MW |
448 | this->rsa->iqmp = BN_bin2bn((const u_char*)coeff.ptr, coeff.len, NULL); |
449 | if (RSA_check_key(this->rsa)) | |
450 | { | |
451 | return &this->public; | |
452 | } | |
84770ded | 453 | } |
b9fbd665 MW |
454 | destroy(this); |
455 | return NULL; | |
84770ded TB |
456 | } |
457 | ||
0556667d MW |
458 | /** |
459 | * Login to engine with a PIN specified for a keyid | |
460 | */ | |
461 | static bool login(ENGINE *engine, chunk_t keyid) | |
462 | { | |
463 | enumerator_t *enumerator; | |
464 | shared_key_t *shared; | |
465 | identification_t *id; | |
466 | chunk_t key; | |
467 | char pin[64]; | |
468 | bool found = FALSE, success = FALSE; | |
469 | ||
470 | id = identification_create_from_encoding(ID_KEY_ID, keyid); | |
471 | enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr, | |
472 | SHARED_PIN, id, NULL); | |
473 | while (enumerator->enumerate(enumerator, &shared, NULL, NULL)) | |
474 | { | |
475 | found = TRUE; | |
476 | key = shared->get_key(shared); | |
477 | if (snprintf(pin, sizeof(pin), "%.*s", key.len, key.ptr) >= sizeof(pin)) | |
478 | { | |
479 | continue; | |
480 | } | |
481 | if (ENGINE_ctrl_cmd_string(engine, "PIN", pin, 0)) | |
482 | { | |
483 | success = TRUE; | |
484 | break; | |
485 | } | |
486 | else | |
487 | { | |
488 | DBG1(DBG_CFG, "setting PIN on engine failed"); | |
489 | } | |
490 | } | |
491 | enumerator->destroy(enumerator); | |
492 | id->destroy(id); | |
493 | if (!found) | |
494 | { | |
495 | DBG1(DBG_CFG, "no PIN found for %#B", &keyid); | |
496 | } | |
497 | return success; | |
498 | } | |
499 | ||
83c42156 | 500 | /** |
30c06407 | 501 | * See header. |
83c42156 | 502 | */ |
30c06407 MW |
503 | openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type, |
504 | va_list args) | |
83c42156 | 505 | { |
1e3d66f8 | 506 | #ifndef OPENSSL_NO_ENGINE |
30c06407 | 507 | private_openssl_rsa_private_key_t *this; |
0b8b6640 | 508 | char *engine_id = NULL; |
0556667d MW |
509 | char keyname[64]; |
510 | chunk_t keyid = chunk_empty;; | |
83c42156 | 511 | EVP_PKEY *key; |
30c06407 | 512 | ENGINE *engine; |
3479c279 | 513 | int slot = -1; |
30c06407 MW |
514 | |
515 | while (TRUE) | |
516 | { | |
517 | switch (va_arg(args, builder_part_t)) | |
518 | { | |
3479c279 | 519 | case BUILD_PKCS11_KEYID: |
0b8b6640 | 520 | keyid = va_arg(args, chunk_t); |
30c06407 | 521 | continue; |
3479c279 MW |
522 | case BUILD_PKCS11_SLOT: |
523 | slot = va_arg(args, int); | |
524 | continue; | |
525 | case BUILD_PKCS11_MODULE: | |
526 | engine_id = va_arg(args, char*); | |
527 | continue; | |
30c06407 MW |
528 | case BUILD_END: |
529 | break; | |
530 | default: | |
531 | return NULL; | |
532 | } | |
533 | break; | |
534 | } | |
0556667d | 535 | if (!keyid.len || keyid.len > 40) |
30c06407 MW |
536 | { |
537 | return NULL; | |
538 | } | |
7daf5226 | 539 | |
0b8b6640 MW |
540 | memset(keyname, 0, sizeof(keyname)); |
541 | if (slot != -1) | |
3479c279 | 542 | { |
0b8b6640 | 543 | snprintf(keyname, sizeof(keyname), "%d:", slot); |
3479c279 | 544 | } |
0b8b6640 | 545 | if (sizeof(keyname) - strlen(keyname) <= keyid.len * 4 / 3 + 1) |
3479c279 | 546 | { |
0b8b6640 | 547 | return NULL; |
3479c279 | 548 | } |
0b8b6640 MW |
549 | chunk_to_hex(keyid, keyname + strlen(keyname), FALSE); |
550 | ||
3479c279 MW |
551 | if (!engine_id) |
552 | { | |
3e2419eb | 553 | engine_id = lib->settings->alloc_str(lib->settings, |
9f4b02e3 | 554 | "libstrongswan.plugins.openssl.engine_id", "pkcs11"); |
3479c279 | 555 | } |
30c06407 | 556 | engine = ENGINE_by_id(engine_id); |
83c42156 TB |
557 | if (!engine) |
558 | { | |
0b8b6640 | 559 | DBG2(DBG_LIB, "engine '%s' is not available", engine_id); |
3e2419eb | 560 | goto engine_failed; |
83c42156 | 561 | } |
83c42156 TB |
562 | if (!ENGINE_init(engine)) |
563 | { | |
8b0e0910 | 564 | DBG1(DBG_LIB, "failed to initialize engine '%s'", engine_id); |
3e2419eb | 565 | goto engine_failed; |
83c42156 | 566 | } |
0556667d | 567 | if (!login(engine, keyid)) |
83c42156 | 568 | { |
0556667d | 569 | DBG1(DBG_LIB, "login to engine '%s' failed", engine_id); |
3e2419eb | 570 | goto engine_failed; |
83c42156 | 571 | } |
3479c279 | 572 | key = ENGINE_load_private_key(engine, keyname, NULL, NULL); |
83c42156 TB |
573 | if (!key) |
574 | { | |
8b0e0910 | 575 | DBG1(DBG_LIB, "failed to load private key with ID '%s' from " |
3479c279 | 576 | "engine '%s'", keyname, engine_id); |
3e2419eb | 577 | goto engine_failed; |
83c42156 TB |
578 | } |
579 | ENGINE_free(engine); | |
3e2419eb | 580 | free(engine_id); |
7daf5226 | 581 | |
e35c3e2a | 582 | this = create_empty(); |
83c42156 TB |
583 | this->rsa = EVP_PKEY_get1_RSA(key); |
584 | this->engine = TRUE; | |
3479c279 MW |
585 | if (!this->rsa) |
586 | { | |
587 | destroy(this); | |
588 | return NULL; | |
589 | } | |
7daf5226 | 590 | |
84770ded | 591 | return &this->public; |
1e3d66f8 TB |
592 | #else /* OPENSSL_NO_ENGINE */ |
593 | return NULL; | |
594 | #endif /* OPENSSL_NO_ENGINE */ | |
3e2419eb MW |
595 | engine_failed: |
596 | if (engine) | |
597 | { | |
598 | ENGINE_free(engine); | |
599 | } | |
600 | free(engine_id); | |
601 | return NULL; | |
84770ded TB |
602 | } |
603 |