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