support of SHA224-based certificate signatures
[strongswan.git] / src / libstrongswan / plugins / openssl / openssl_rsa_public_key.c
1 /*
2 * Copyright (C) 2008 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "openssl_rsa_public_key.h"
17
18 #include <debug.h>
19
20 #include <openssl/evp.h>
21 #include <openssl/rsa.h>
22 #include <openssl/x509.h>
23
24 typedef struct private_openssl_rsa_public_key_t private_openssl_rsa_public_key_t;
25
26 /**
27 * Private data structure with signing context.
28 */
29 struct private_openssl_rsa_public_key_t {
30 /**
31 * Public interface for this signer.
32 */
33 openssl_rsa_public_key_t public;
34
35 /**
36 * RSA object from OpenSSL
37 */
38 RSA *rsa;
39
40 /**
41 * Keyid formed as a SHA-1 hash of a publicKeyInfo object
42 */
43 identification_t *keyid_info;
44
45 /**
46 * Keyid formed as a SHA-1 hash of a publicKey object
47 */
48 identification_t *keyid;
49
50 /**
51 * reference counter
52 */
53 refcount_t ref;
54 };
55
56 /**
57 * Verification of an EMPSA PKCS1 signature described in PKCS#1
58 */
59 static bool verify_emsa_pkcs1_signature(private_openssl_rsa_public_key_t *this,
60 int type, chunk_t data, chunk_t signature)
61 {
62 bool valid = FALSE;
63 int rsa_size = RSA_size(this->rsa);
64
65 /* OpenSSL expects a signature of exactly RSA size (no leading 0x00) */
66 if (signature.len > rsa_size)
67 {
68 signature = chunk_skip(signature, signature.len - rsa_size);
69 }
70
71 if (type == NID_undef)
72 {
73 chunk_t hash = chunk_alloc(rsa_size);
74
75 hash.len = RSA_public_decrypt(signature.len, signature.ptr, hash.ptr,
76 this->rsa, RSA_PKCS1_PADDING);
77 valid = chunk_equals(data, hash);
78 free(hash.ptr);
79 }
80 else
81 {
82 EVP_MD_CTX *ctx;
83 EVP_PKEY *key;
84 const EVP_MD *hasher;
85
86 hasher = EVP_get_digestbynid(type);
87 if (!hasher)
88 {
89 return FALSE;
90 }
91
92 ctx = EVP_MD_CTX_create();
93 key = EVP_PKEY_new();
94
95 if (!ctx || !key)
96 {
97 goto error;
98 }
99 if (!EVP_PKEY_set1_RSA(key, this->rsa))
100 {
101 goto error;
102 }
103 if (!EVP_VerifyInit_ex(ctx, hasher, NULL))
104 {
105 goto error;
106 }
107 if (!EVP_VerifyUpdate(ctx, data.ptr, data.len))
108 {
109 goto error;
110 }
111 valid = (EVP_VerifyFinal(ctx, signature.ptr, signature.len, key) == 1);
112
113 error:
114 if (key)
115 {
116 EVP_PKEY_free(key);
117 }
118 if (ctx)
119 {
120 EVP_MD_CTX_destroy(ctx);
121 }
122 }
123 return valid;
124 }
125
126 /**
127 * Implementation of public_key_t.get_type.
128 */
129 static key_type_t get_type(private_openssl_rsa_public_key_t *this)
130 {
131 return KEY_RSA;
132 }
133
134 /**
135 * Implementation of public_key_t.verify.
136 */
137 static bool verify(private_openssl_rsa_public_key_t *this, signature_scheme_t scheme,
138 chunk_t data, chunk_t signature)
139 {
140 switch (scheme)
141 {
142 case SIGN_RSA_EMSA_PKCS1_NULL:
143 return verify_emsa_pkcs1_signature(this, NID_undef, data, signature);
144 case SIGN_RSA_EMSA_PKCS1_SHA1:
145 return verify_emsa_pkcs1_signature(this, NID_sha1, data, signature);
146 case SIGN_RSA_EMSA_PKCS1_SHA224:
147 return verify_emsa_pkcs1_signature(this, NID_sha224, data, signature);
148 case SIGN_RSA_EMSA_PKCS1_SHA256:
149 return verify_emsa_pkcs1_signature(this, NID_sha256, data, signature);
150 case SIGN_RSA_EMSA_PKCS1_SHA384:
151 return verify_emsa_pkcs1_signature(this, NID_sha384, data, signature);
152 case SIGN_RSA_EMSA_PKCS1_SHA512:
153 return verify_emsa_pkcs1_signature(this, NID_sha512, data, signature);
154 case SIGN_RSA_EMSA_PKCS1_MD5:
155 return verify_emsa_pkcs1_signature(this, NID_md5, data, signature);
156 default:
157 DBG1("signature scheme %N not supported in RSA",
158 signature_scheme_names, scheme);
159 return FALSE;
160 }
161 }
162
163 /**
164 * Implementation of public_key_t.get_keysize.
165 */
166 static bool encrypt_(private_openssl_rsa_public_key_t *this, chunk_t crypto, chunk_t *plain)
167 {
168 DBG1("RSA public key encryption not implemented");
169 return FALSE;
170 }
171
172 /**
173 * Implementation of public_key_t.equals.
174 */
175 static bool equals(private_openssl_rsa_public_key_t *this, public_key_t *other)
176 {
177 identification_t *keyid;
178
179 if (&this->public.interface == other)
180 {
181 return TRUE;
182 }
183 if (other->get_type(other) != KEY_RSA)
184 {
185 return FALSE;
186 }
187 keyid = other->get_id(other, ID_PUBKEY_SHA1);
188 if (keyid && keyid->equals(keyid, this->keyid))
189 {
190 return TRUE;
191 }
192 keyid = other->get_id(other, ID_PUBKEY_INFO_SHA1);
193 if (keyid && keyid->equals(keyid, this->keyid_info))
194 {
195 return TRUE;
196 }
197 return FALSE;
198 }
199
200 /**
201 * Implementation of public_key_t.get_keysize.
202 */
203 static size_t get_keysize(private_openssl_rsa_public_key_t *this)
204 {
205 return RSA_size(this->rsa);
206 }
207
208 /**
209 * Implementation of public_key_t.get_id.
210 */
211 static identification_t *get_id(private_openssl_rsa_public_key_t *this,
212 id_type_t type)
213 {
214 switch (type)
215 {
216 case ID_PUBKEY_INFO_SHA1:
217 return this->keyid_info;
218 case ID_PUBKEY_SHA1:
219 return this->keyid;
220 default:
221 return NULL;
222 }
223 }
224
225 /**
226 * Encodes the public key
227 */
228 static chunk_t get_encoding_raw(RSA *rsa)
229 {
230 chunk_t enc = chunk_alloc(i2d_RSAPublicKey(rsa, NULL));
231 u_char *p = enc.ptr;
232 i2d_RSAPublicKey(rsa, &p);
233 return enc;
234 }
235
236 /**
237 * Encodes the public key with the algorithm used
238 */
239 static chunk_t get_encoding_with_algo(RSA *rsa)
240 {
241 u_char *p;
242 chunk_t enc;
243 X509_PUBKEY *pubkey = X509_PUBKEY_new();
244
245 ASN1_OBJECT_free(pubkey->algor->algorithm);
246 pubkey->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
247
248 if (pubkey->algor->parameter == NULL ||
249 pubkey->algor->parameter->type != V_ASN1_NULL)
250 {
251 ASN1_TYPE_free(pubkey->algor->parameter);
252 pubkey->algor->parameter = ASN1_TYPE_new();
253 pubkey->algor->parameter->type = V_ASN1_NULL;
254 }
255
256 enc = get_encoding_raw(rsa);
257 M_ASN1_BIT_STRING_set(pubkey->public_key, enc.ptr, enc.len);
258 chunk_free(&enc);
259
260 enc = chunk_alloc(i2d_X509_PUBKEY(pubkey, NULL));
261 p = enc.ptr;
262 i2d_X509_PUBKEY(pubkey, &p);
263 X509_PUBKEY_free(pubkey);
264 return enc;
265 }
266
267 /*
268 * Implementation of public_key_t.get_encoding.
269 */
270 static chunk_t get_encoding(private_openssl_rsa_public_key_t *this)
271 {
272 return get_encoding_raw(this->rsa);
273 }
274
275 /**
276 * Implementation of public_key_t.get_ref.
277 */
278 static private_openssl_rsa_public_key_t* get_ref(private_openssl_rsa_public_key_t *this)
279 {
280 ref_get(&this->ref);
281 return this;
282 }
283
284 /**
285 * Implementation of openssl_rsa_public_key.destroy.
286 */
287 static void destroy(private_openssl_rsa_public_key_t *this)
288 {
289 if (ref_put(&this->ref))
290 {
291 if (this->rsa)
292 {
293 RSA_free(this->rsa);
294 }
295 DESTROY_IF(this->keyid);
296 DESTROY_IF(this->keyid_info);
297 free(this);
298 }
299 }
300
301 /**
302 * Generic private constructor
303 */
304 static private_openssl_rsa_public_key_t *openssl_rsa_public_key_create_empty()
305 {
306 private_openssl_rsa_public_key_t *this = malloc_thing(private_openssl_rsa_public_key_t);
307
308 this->public.interface.get_type = (key_type_t (*)(public_key_t *this))get_type;
309 this->public.interface.verify = (bool (*)(public_key_t *this, signature_scheme_t scheme, chunk_t data, chunk_t signature))verify;
310 this->public.interface.encrypt = (bool (*)(public_key_t *this, chunk_t crypto, chunk_t *plain))encrypt_;
311 this->public.interface.equals = (bool (*) (public_key_t*, public_key_t*))equals;
312 this->public.interface.get_keysize = (size_t (*) (public_key_t *this))get_keysize;
313 this->public.interface.get_id = (identification_t* (*) (public_key_t *this,id_type_t))get_id;
314 this->public.interface.get_encoding = (chunk_t(*)(public_key_t*))get_encoding;
315 this->public.interface.get_ref = (public_key_t* (*)(public_key_t *this))get_ref;
316 this->public.interface.destroy = (void (*)(public_key_t *this))destroy;
317
318 this->keyid = NULL;
319 this->keyid_info = NULL;
320 this->ref = 1;
321
322 return this;
323 }
324
325 /**
326 * Build the RSA key identifier from n and e using SHA1 hashed publicKey(Info).
327 * Also used in openssl_rsa_private_key.c.
328 */
329 bool openssl_rsa_public_key_build_id(RSA *rsa, identification_t **keyid,
330 identification_t **keyid_info)
331 {
332 chunk_t publicKeyInfo, publicKey, hash;
333 hasher_t *hasher;
334
335 hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
336 if (hasher == NULL)
337 {
338 DBG1("SHA1 hash algorithm not supported, unable to use RSA");
339 return FALSE;
340 }
341
342 publicKey = get_encoding_raw(rsa);
343
344 hasher->allocate_hash(hasher, publicKey, &hash);
345 *keyid = identification_create_from_encoding(ID_PUBKEY_SHA1, hash);
346 chunk_free(&hash);
347
348 publicKeyInfo = get_encoding_with_algo(rsa);
349
350 hasher->allocate_hash(hasher, publicKeyInfo, &hash);
351 *keyid_info = identification_create_from_encoding(ID_PUBKEY_INFO_SHA1, hash);
352 chunk_free(&hash);
353
354 hasher->destroy(hasher);
355 chunk_free(&publicKeyInfo);
356 chunk_free(&publicKey);
357
358 return TRUE;
359 }
360
361 /**
362 * Create a public key from BIGNUM values, used in openssl_rsa_private_key.c
363 */
364 openssl_rsa_public_key_t *openssl_rsa_public_key_create_from_n_e(BIGNUM *n, BIGNUM *e)
365 {
366 private_openssl_rsa_public_key_t *this = openssl_rsa_public_key_create_empty();
367
368 this->rsa = RSA_new();
369 this->rsa->n = BN_dup(n);
370 this->rsa->e = BN_dup(e);
371
372 if (!openssl_rsa_public_key_build_id(this->rsa, &this->keyid, &this->keyid_info))
373 {
374 destroy(this);
375 return NULL;
376 }
377 return &this->public;
378 }
379
380 /**
381 * Load a public key from an ASN1 encoded blob
382 */
383 static openssl_rsa_public_key_t *load(chunk_t blob)
384 {
385 u_char *p = blob.ptr;
386 private_openssl_rsa_public_key_t *this = openssl_rsa_public_key_create_empty();
387
388 this->rsa = d2i_RSAPublicKey(NULL, (const u_char**)&p, blob.len);
389
390 chunk_clear(&blob);
391
392 if (!this->rsa)
393 {
394 destroy(this);
395 return NULL;
396 }
397
398 if (!openssl_rsa_public_key_build_id(this->rsa, &this->keyid, &this->keyid_info))
399 {
400 destroy(this);
401 return NULL;
402 }
403 return &this->public;
404 }
405
406 typedef struct private_builder_t private_builder_t;
407 /**
408 * Builder implementation for key loading
409 */
410 struct private_builder_t {
411 /** implements the builder interface */
412 builder_t public;
413 /** loaded public key */
414 openssl_rsa_public_key_t *key;
415 };
416
417 /**
418 * Implementation of builder_t.build
419 */
420 static openssl_rsa_public_key_t *build(private_builder_t *this)
421 {
422 openssl_rsa_public_key_t *key = this->key;
423
424 free(this);
425 return key;
426 }
427
428 /**
429 * Implementation of builder_t.add
430 */
431 static void add(private_builder_t *this, builder_part_t part, ...)
432 {
433 if (!this->key)
434 {
435 va_list args;
436 chunk_t chunk;
437
438 switch (part)
439 {
440 case BUILD_BLOB_ASN1_DER:
441 {
442 va_start(args, part);
443 chunk = va_arg(args, chunk_t);
444 this->key = load(chunk_clone(chunk));
445 va_end(args);
446 return;
447 }
448 default:
449 break;
450 }
451 }
452 if (this->key)
453 {
454 destroy((private_openssl_rsa_public_key_t*)this->key);
455 }
456 builder_cancel(&this->public);
457 }
458
459 /**
460 * Builder construction function
461 */
462 builder_t *openssl_rsa_public_key_builder(key_type_t type)
463 {
464 private_builder_t *this;
465
466 if (type != KEY_RSA)
467 {
468 return NULL;
469 }
470
471 this = malloc_thing(private_builder_t);
472
473 this->key = NULL;
474 this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
475 this->public.build = (void*(*)(builder_t *this))build;
476
477 return &this->public;
478 }
479