00f131423e4a0ec505f029955547e07827060235
[strongswan.git] / src / libstrongswan / plugins / openssl / openssl_rsa_public_key.c
1 /*
2 * Copyright (C) 2009 Martin Willi
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.
15 */
16
17 #include "openssl_rsa_public_key.h"
18
19 #include <debug.h>
20
21 #include <openssl/evp.h>
22 #include <openssl/rsa.h>
23 #include <openssl/x509.h>
24
25 typedef struct private_openssl_rsa_public_key_t private_openssl_rsa_public_key_t;
26
27 /**
28 * Private data structure with signing context.
29 */
30 struct private_openssl_rsa_public_key_t {
31 /**
32 * Public interface for this signer.
33 */
34 openssl_rsa_public_key_t public;
35
36 /**
37 * RSA object from OpenSSL
38 */
39 RSA *rsa;
40
41 /**
42 * reference counter
43 */
44 refcount_t ref;
45 };
46
47
48
49 /**
50 * Verification of an EMPSA PKCS1 signature described in PKCS#1
51 */
52 static bool verify_emsa_pkcs1_signature(private_openssl_rsa_public_key_t *this,
53 int type, chunk_t data, chunk_t signature)
54 {
55 bool valid = FALSE;
56 int rsa_size = RSA_size(this->rsa);
57
58 /* OpenSSL expects a signature of exactly RSA size (no leading 0x00) */
59 if (signature.len > rsa_size)
60 {
61 signature = chunk_skip(signature, signature.len - rsa_size);
62 }
63
64 if (type == NID_undef)
65 {
66 chunk_t hash = chunk_alloc(rsa_size);
67
68 hash.len = RSA_public_decrypt(signature.len, signature.ptr, hash.ptr,
69 this->rsa, RSA_PKCS1_PADDING);
70 valid = chunk_equals(data, hash);
71 free(hash.ptr);
72 }
73 else
74 {
75 EVP_MD_CTX *ctx;
76 EVP_PKEY *key;
77 const EVP_MD *hasher;
78
79 hasher = EVP_get_digestbynid(type);
80 if (!hasher)
81 {
82 return FALSE;
83 }
84
85 ctx = EVP_MD_CTX_create();
86 key = EVP_PKEY_new();
87
88 if (!ctx || !key)
89 {
90 goto error;
91 }
92 if (!EVP_PKEY_set1_RSA(key, this->rsa))
93 {
94 goto error;
95 }
96 if (!EVP_VerifyInit_ex(ctx, hasher, NULL))
97 {
98 goto error;
99 }
100 if (!EVP_VerifyUpdate(ctx, data.ptr, data.len))
101 {
102 goto error;
103 }
104 valid = (EVP_VerifyFinal(ctx, signature.ptr, signature.len, key) == 1);
105
106 error:
107 if (key)
108 {
109 EVP_PKEY_free(key);
110 }
111 if (ctx)
112 {
113 EVP_MD_CTX_destroy(ctx);
114 }
115 }
116 return valid;
117 }
118
119 /**
120 * Verification of an EMPSA PKCS1 signature described in PKCS#1
121 */
122 static bool verify_signature(private_openssl_rsa_public_key_t *this,
123 int type, chunk_t data, chunk_t signature)
124 {
125 bool valid = FALSE;
126 int rsa_size = RSA_size(this->rsa);
127
128 /* OpenSSL expects a signature of exactly RSA size (no leading 0x00) */
129 if (signature.len > rsa_size)
130 {
131 signature = chunk_skip(signature, signature.len - rsa_size);
132 }
133
134 if (type == NID_undef)
135 {
136 chunk_t hash = chunk_alloc(rsa_size);
137
138 hash.len = RSA_public_decrypt(signature.len, signature.ptr, hash.ptr,
139 this->rsa, RSA_PKCS1_PADDING);
140 valid = chunk_equals(data, hash);
141 free(hash.ptr);
142 }
143 else
144 {
145 EVP_PKEY *key;
146 RSA *rsa = NULL;
147
148 key = EVP_PKEY_new();
149 if (!EVP_PKEY_set1_RSA(key, this->rsa))
150 {
151 goto error;
152 }
153 rsa = EVP_PKEY_get1_RSA(key);
154 if (!rsa)
155 {
156 goto error;
157 }
158
159 valid = (RSA_verify(type, data.ptr, data.len,
160 signature.ptr, signature.len, rsa) == 1);
161
162 error:
163 if (key)
164 {
165 EVP_PKEY_free(key);
166 }
167 if (rsa)
168 {
169 RSA_free(rsa);
170 }
171 }
172
173 return valid;
174 }
175
176
177 METHOD(public_key_t, get_type, key_type_t,
178 private_openssl_rsa_public_key_t *this)
179 {
180 return KEY_RSA;
181 }
182
183 METHOD(public_key_t, verify, bool,
184 private_openssl_rsa_public_key_t *this, signature_scheme_t scheme,
185 chunk_t data, chunk_t signature)
186 {
187 switch (scheme)
188 {
189 case SIGN_RSA_SHA1:
190 return verify_signature(this, NID_sha1, data, signature);
191 case SIGN_RSA_EMSA_PKCS1_NULL:
192 return verify_emsa_pkcs1_signature(this, NID_undef, data, signature);
193 case SIGN_RSA_EMSA_PKCS1_SHA1:
194 return verify_emsa_pkcs1_signature(this, NID_sha1, data, signature);
195 case SIGN_RSA_EMSA_PKCS1_SHA224:
196 return verify_emsa_pkcs1_signature(this, NID_sha224, data, signature);
197 case SIGN_RSA_EMSA_PKCS1_SHA256:
198 return verify_emsa_pkcs1_signature(this, NID_sha256, data, signature);
199 case SIGN_RSA_EMSA_PKCS1_SHA384:
200 return verify_emsa_pkcs1_signature(this, NID_sha384, data, signature);
201 case SIGN_RSA_EMSA_PKCS1_SHA512:
202 return verify_emsa_pkcs1_signature(this, NID_sha512, data, signature);
203 case SIGN_RSA_EMSA_PKCS1_MD5:
204 return verify_emsa_pkcs1_signature(this, NID_md5, data, signature);
205 default:
206 DBG1(DBG_LIB, "signature scheme %N not supported in RSA",
207 signature_scheme_names, scheme);
208 return FALSE;
209 }
210 }
211
212 METHOD(public_key_t, encrypt, bool,
213 private_openssl_rsa_public_key_t *this, encryption_scheme_t scheme,
214 chunk_t plain, chunk_t *crypto)
215 {
216 int padding, len;
217 char *encrypted;
218
219 switch (scheme)
220 {
221 case ENCRYPT_RSA_PKCS1:
222 padding = RSA_PKCS1_PADDING;
223 break;
224 case ENCRYPT_RSA_OAEP_SHA1:
225 padding = RSA_PKCS1_OAEP_PADDING;
226 break;
227 default:
228 DBG1(DBG_LIB, "decryption scheme %N not supported via openssl",
229 encryption_scheme_names, scheme);
230 return FALSE;
231 }
232 encrypted = malloc(RSA_size(this->rsa));
233 len = RSA_public_encrypt(plain.len, plain.ptr, encrypted,
234 this->rsa, padding);
235 if (len < 0)
236 {
237 DBG1(DBG_LIB, "RSA decryption failed");
238 free(encrypted);
239 return FALSE;
240 }
241 *crypto = chunk_create(encrypted, len);
242 return TRUE;
243 }
244
245 METHOD(public_key_t, get_keysize, int,
246 private_openssl_rsa_public_key_t *this)
247 {
248 return RSA_size(this->rsa) * 8;
249 }
250
251 /**
252 * Calculate fingerprint from a RSA key, also used in rsa private key.
253 */
254 bool openssl_rsa_fingerprint(RSA *rsa, cred_encoding_type_t type, chunk_t *fp)
255 {
256 hasher_t *hasher;
257 chunk_t key;
258 u_char *p;
259
260 if (lib->encoding->get_cache(lib->encoding, type, rsa, fp))
261 {
262 return TRUE;
263 }
264 switch (type)
265 {
266 case KEYID_PUBKEY_SHA1:
267 key = chunk_alloc(i2d_RSAPublicKey(rsa, NULL));
268 p = key.ptr;
269 i2d_RSAPublicKey(rsa, &p);
270 break;
271 case KEYID_PUBKEY_INFO_SHA1:
272 key = chunk_alloc(i2d_RSA_PUBKEY(rsa, NULL));
273 p = key.ptr;
274 i2d_RSA_PUBKEY(rsa, &p);
275 break;
276 default:
277 return FALSE;
278 }
279 hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
280 if (!hasher)
281 {
282 DBG1(DBG_LIB, "SHA1 hash algorithm not supported, fingerprinting failed");
283 free(key.ptr);
284 return FALSE;
285 }
286 hasher->allocate_hash(hasher, key, fp);
287 free(key.ptr);
288 hasher->destroy(hasher);
289 lib->encoding->cache(lib->encoding, type, rsa, *fp);
290 return TRUE;
291 }
292
293 METHOD(public_key_t, get_fingerprint, bool,
294 private_openssl_rsa_public_key_t *this, cred_encoding_type_t type,
295 chunk_t *fingerprint)
296 {
297 return openssl_rsa_fingerprint(this->rsa, type, fingerprint);
298 }
299
300 METHOD(public_key_t, get_encoding, bool,
301 private_openssl_rsa_public_key_t *this, cred_encoding_type_t type,
302 chunk_t *encoding)
303 {
304 u_char *p;
305
306 switch (type)
307 {
308 case PUBKEY_SPKI_ASN1_DER:
309 case PUBKEY_PEM:
310 {
311 bool success = TRUE;
312
313 *encoding = chunk_alloc(i2d_RSA_PUBKEY(this->rsa, NULL));
314 p = encoding->ptr;
315 i2d_RSA_PUBKEY(this->rsa, &p);
316
317 if (type == PUBKEY_PEM)
318 {
319 chunk_t asn1_encoding = *encoding;
320
321 success = lib->encoding->encode(lib->encoding, PUBKEY_PEM,
322 NULL, encoding, CRED_PART_RSA_PUB_ASN1_DER,
323 asn1_encoding, CRED_PART_END);
324 chunk_clear(&asn1_encoding);
325 }
326 return success;
327 }
328 case PUBKEY_ASN1_DER:
329 {
330 *encoding = chunk_alloc(i2d_RSAPublicKey(this->rsa, NULL));
331 p = encoding->ptr;
332 i2d_RSAPublicKey(this->rsa, &p);
333 return TRUE;
334 }
335 default:
336 return FALSE;
337 }
338 }
339
340 METHOD(public_key_t, get_ref, public_key_t*,
341 private_openssl_rsa_public_key_t *this)
342 {
343 ref_get(&this->ref);
344 return &this->public.key;
345 }
346
347 METHOD(public_key_t, destroy, void,
348 private_openssl_rsa_public_key_t *this)
349 {
350 if (ref_put(&this->ref))
351 {
352 if (this->rsa)
353 {
354 lib->encoding->clear_cache(lib->encoding, this->rsa);
355 RSA_free(this->rsa);
356 }
357 free(this);
358 }
359 }
360
361 /**
362 * Generic private constructor
363 */
364 static private_openssl_rsa_public_key_t *create_empty()
365 {
366 private_openssl_rsa_public_key_t *this;
367
368 INIT(this,
369 .public = {
370 .key = {
371 .get_type = _get_type,
372 .verify = _verify,
373 .encrypt = _encrypt,
374 .equals = public_key_equals,
375 .get_keysize = _get_keysize,
376 .get_fingerprint = _get_fingerprint,
377 .has_fingerprint = public_key_has_fingerprint,
378 .get_encoding = _get_encoding,
379 .get_ref = _get_ref,
380 .destroy = _destroy,
381 },
382 },
383 .ref = 1,
384 );
385
386 return this;
387 }
388
389 /**
390 * See header.
391 */
392 openssl_rsa_public_key_t *openssl_rsa_public_key_load(key_type_t type,
393 va_list args)
394 {
395 private_openssl_rsa_public_key_t *this;
396 chunk_t blob, n, e;
397
398 n = e = blob = chunk_empty;
399 while (TRUE)
400 {
401 switch (va_arg(args, builder_part_t))
402 {
403 case BUILD_BLOB_ASN1_DER:
404 blob = va_arg(args, chunk_t);
405 continue;
406 case BUILD_RSA_MODULUS:
407 n = va_arg(args, chunk_t);
408 continue;
409 case BUILD_RSA_PUB_EXP:
410 e = va_arg(args, chunk_t);
411 continue;
412 case BUILD_END:
413 break;
414 default:
415 return NULL;
416 }
417 break;
418 }
419
420 this = create_empty();
421 if (blob.ptr)
422 {
423 switch (type)
424 {
425 case KEY_ANY:
426 this->rsa = d2i_RSA_PUBKEY(NULL, (const u_char**)&blob.ptr,
427 blob.len);
428 break;
429 case KEY_RSA:
430 this->rsa = d2i_RSAPublicKey(NULL, (const u_char**)&blob.ptr,
431 blob.len);
432 break;
433 default:
434 break;
435 }
436 if (this->rsa)
437 {
438 return &this->public;
439 }
440 }
441 else if (n.ptr && e.ptr && type == KEY_RSA)
442 {
443 this->rsa = RSA_new();
444 this->rsa->n = BN_bin2bn((const u_char*)n.ptr, n.len, NULL);
445 this->rsa->e = BN_bin2bn((const u_char*)e.ptr, e.len, NULL);
446 return &this->public;
447 }
448 destroy(this);
449 return NULL;
450 }