removed 0-byte truncation, fixes random Openssl RSA signature verification failures
[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 * $Id$
16 */
17
18 #include "openssl_rsa_public_key.h"
19
20 #include <debug.h>
21
22 #include <openssl/evp.h>
23 #include <openssl/rsa.h>
24 #include <openssl/x509.h>
25
26 typedef struct private_openssl_rsa_public_key_t private_openssl_rsa_public_key_t;
27
28 /**
29 * Private data structure with signing context.
30 */
31 struct private_openssl_rsa_public_key_t {
32 /**
33 * Public interface for this signer.
34 */
35 openssl_rsa_public_key_t public;
36
37 /**
38 * RSA object from OpenSSL
39 */
40 RSA *rsa;
41
42 /**
43 * Keyid formed as a SHA-1 hash of a publicKeyInfo object
44 */
45 identification_t *keyid_info;
46
47 /**
48 * Keyid formed as a SHA-1 hash of a publicKey object
49 */
50 identification_t *keyid;
51
52 /**
53 * reference counter
54 */
55 refcount_t ref;
56 };
57
58 /**
59 * Verification of an EMPSA PKCS1 signature described in PKCS#1
60 */
61 static bool verify_emsa_pkcs1_signature(private_openssl_rsa_public_key_t *this,
62 int type, chunk_t data, chunk_t signature)
63 {
64 bool valid = FALSE;
65 const EVP_MD *hasher = EVP_get_digestbynid(type);
66 if (!hasher)
67 {
68 return FALSE;
69 }
70
71 EVP_MD_CTX *ctx = EVP_MD_CTX_create();
72 EVP_PKEY *key = EVP_PKEY_new();
73 if (!ctx || !key)
74 {
75 goto error;
76 }
77
78 if (!EVP_PKEY_set1_RSA(key, this->rsa))
79 {
80 goto error;
81 }
82
83 if (!EVP_VerifyInit_ex(ctx, hasher, NULL))
84 {
85 goto error;
86 }
87
88 if (!EVP_VerifyUpdate(ctx, data.ptr, data.len))
89 {
90 goto error;
91 }
92
93 valid = (EVP_VerifyFinal(ctx, signature.ptr, signature.len, key) == 1);
94
95 error:
96 if (key)
97 {
98 EVP_PKEY_free(key);
99 }
100 if (ctx)
101 {
102 EVP_MD_CTX_destroy(ctx);
103 }
104 return valid;
105 }
106
107 /**
108 * Implementation of public_key_t.get_type.
109 */
110 static key_type_t get_type(private_openssl_rsa_public_key_t *this)
111 {
112 return KEY_RSA;
113 }
114
115 /**
116 * Implementation of public_key_t.verify.
117 */
118 static bool verify(private_openssl_rsa_public_key_t *this, signature_scheme_t scheme,
119 chunk_t data, chunk_t signature)
120 {
121 switch (scheme)
122 {
123 case SIGN_DEFAULT:
124 /* default is EMSA-PKCS1 using SHA1 */
125 case SIGN_RSA_EMSA_PKCS1_SHA1:
126 return verify_emsa_pkcs1_signature(this, NID_sha1, data, signature);
127 case SIGN_RSA_EMSA_PKCS1_SHA256:
128 return verify_emsa_pkcs1_signature(this, NID_sha256, data, signature);
129 case SIGN_RSA_EMSA_PKCS1_SHA384:
130 return verify_emsa_pkcs1_signature(this, NID_sha384, data, signature);
131 case SIGN_RSA_EMSA_PKCS1_SHA512:
132 return verify_emsa_pkcs1_signature(this, NID_sha512, data, signature);
133 case SIGN_RSA_EMSA_PKCS1_MD5:
134 return verify_emsa_pkcs1_signature(this, NID_md5, data, signature);
135 default:
136 DBG1("signature scheme %N not supported in RSA",
137 signature_scheme_names, scheme);
138 return FALSE;
139 }
140 }
141
142 /**
143 * Implementation of public_key_t.get_keysize.
144 */
145 static bool encrypt(private_openssl_rsa_public_key_t *this, chunk_t crypto, chunk_t *plain)
146 {
147 DBG1("RSA public key encryption not implemented");
148 return FALSE;
149 }
150
151 /**
152 * Implementation of public_key_t.get_keysize.
153 */
154 static size_t get_keysize(private_openssl_rsa_public_key_t *this)
155 {
156 return RSA_size(this->rsa);
157 }
158
159 /**
160 * Implementation of public_key_t.get_id.
161 */
162 static identification_t *get_id(private_openssl_rsa_public_key_t *this,
163 id_type_t type)
164 {
165 switch (type)
166 {
167 case ID_PUBKEY_INFO_SHA1:
168 return this->keyid_info;
169 case ID_PUBKEY_SHA1:
170 return this->keyid;
171 default:
172 return NULL;
173 }
174 }
175
176 /**
177 * Encodes the public key
178 */
179 static chunk_t get_encoding_raw(RSA *rsa)
180 {
181 chunk_t enc = chunk_alloc(i2d_RSAPublicKey(rsa, NULL));
182 u_char *p = enc.ptr;
183 i2d_RSAPublicKey(rsa, &p);
184 return enc;
185 }
186
187 /**
188 * Encodes the public key with the algorithm used
189 */
190 static chunk_t get_encoding_with_algo(RSA *rsa)
191 {
192 u_char *p;
193 chunk_t enc;
194 X509_PUBKEY *pubkey = X509_PUBKEY_new();
195
196 ASN1_OBJECT_free(pubkey->algor->algorithm);
197 pubkey->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
198
199 if (pubkey->algor->parameter == NULL ||
200 pubkey->algor->parameter->type != V_ASN1_NULL)
201 {
202 ASN1_TYPE_free(pubkey->algor->parameter);
203 pubkey->algor->parameter = ASN1_TYPE_new();
204 pubkey->algor->parameter->type = V_ASN1_NULL;
205 }
206
207 enc = get_encoding_raw(rsa);
208 M_ASN1_BIT_STRING_set(pubkey->public_key, enc.ptr, enc.len);
209 chunk_free(&enc);
210
211 enc = chunk_alloc(i2d_X509_PUBKEY(pubkey, NULL));
212 p = enc.ptr;
213 i2d_X509_PUBKEY(pubkey, &p);
214 X509_PUBKEY_free(pubkey);
215 return enc;
216 }
217
218 /*
219 * Implementation of public_key_t.get_encoding.
220 */
221 static chunk_t get_encoding(private_openssl_rsa_public_key_t *this)
222 {
223 return get_encoding_raw(this->rsa);
224 }
225
226 /**
227 * Implementation of public_key_t.get_ref.
228 */
229 static private_openssl_rsa_public_key_t* get_ref(private_openssl_rsa_public_key_t *this)
230 {
231 ref_get(&this->ref);
232 return this;
233 }
234
235 /**
236 * Implementation of openssl_rsa_public_key.destroy.
237 */
238 static void destroy(private_openssl_rsa_public_key_t *this)
239 {
240 if (ref_put(&this->ref))
241 {
242 if (this->rsa)
243 {
244 RSA_free(this->rsa);
245 }
246 DESTROY_IF(this->keyid);
247 DESTROY_IF(this->keyid_info);
248 free(this);
249 }
250 }
251
252 /**
253 * Generic private constructor
254 */
255 static private_openssl_rsa_public_key_t *openssl_rsa_public_key_create_empty()
256 {
257 private_openssl_rsa_public_key_t *this = malloc_thing(private_openssl_rsa_public_key_t);
258
259 this->public.interface.get_type = (key_type_t (*)(public_key_t *this))get_type;
260 this->public.interface.verify = (bool (*)(public_key_t *this, signature_scheme_t scheme, chunk_t data, chunk_t signature))verify;
261 this->public.interface.encrypt = (bool (*)(public_key_t *this, chunk_t crypto, chunk_t *plain))encrypt;
262 this->public.interface.get_keysize = (size_t (*) (public_key_t *this))get_keysize;
263 this->public.interface.get_id = (identification_t* (*) (public_key_t *this,id_type_t))get_id;
264 this->public.interface.get_encoding = (chunk_t(*)(public_key_t*))get_encoding;
265 this->public.interface.get_ref = (public_key_t* (*)(public_key_t *this))get_ref;
266 this->public.interface.destroy = (void (*)(public_key_t *this))destroy;
267
268 this->keyid = NULL;
269 this->keyid_info = NULL;
270 this->ref = 1;
271
272 return this;
273 }
274
275 /**
276 * Build the RSA key identifier from n and e using SHA1 hashed publicKey(Info).
277 * Also used in openssl_rsa_private_key.c.
278 */
279 bool openssl_rsa_public_key_build_id(RSA *rsa, identification_t **keyid,
280 identification_t **keyid_info)
281 {
282 chunk_t publicKeyInfo, publicKey, hash;
283 hasher_t *hasher;
284
285 hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
286 if (hasher == NULL)
287 {
288 DBG1("SHA1 hash algorithm not supported, unable to use RSA");
289 return FALSE;
290 }
291
292 publicKey = get_encoding_raw(rsa);
293
294 hasher->allocate_hash(hasher, publicKey, &hash);
295 *keyid = identification_create_from_encoding(ID_PUBKEY_SHA1, hash);
296 chunk_free(&hash);
297
298 publicKeyInfo = get_encoding_with_algo(rsa);
299
300 hasher->allocate_hash(hasher, publicKeyInfo, &hash);
301 *keyid_info = identification_create_from_encoding(ID_PUBKEY_INFO_SHA1, hash);
302 chunk_free(&hash);
303
304 hasher->destroy(hasher);
305 chunk_free(&publicKeyInfo);
306 chunk_free(&publicKey);
307
308 return TRUE;
309 }
310
311 /**
312 * Create a public key from BIGNUM values, used in openssl_rsa_private_key.c
313 */
314 openssl_rsa_public_key_t *openssl_rsa_public_key_create_from_n_e(BIGNUM *n, BIGNUM *e)
315 {
316 private_openssl_rsa_public_key_t *this = openssl_rsa_public_key_create_empty();
317
318 this->rsa = RSA_new();
319 this->rsa->n = BN_dup(n);
320 this->rsa->e = BN_dup(e);
321
322 if (!openssl_rsa_public_key_build_id(this->rsa, &this->keyid, &this->keyid_info))
323 {
324 destroy(this);
325 return NULL;
326 }
327 return &this->public;
328 }
329
330 /**
331 * Load a public key from an ASN1 encoded blob
332 */
333 static openssl_rsa_public_key_t *load(chunk_t blob)
334 {
335 u_char *p = blob.ptr;
336 private_openssl_rsa_public_key_t *this = openssl_rsa_public_key_create_empty();
337
338 this->rsa = d2i_RSAPublicKey(NULL, (const u_char**)&p, blob.len);
339
340 chunk_clear(&blob);
341
342 if (!this->rsa)
343 {
344 destroy(this);
345 return NULL;
346 }
347
348 if (!openssl_rsa_public_key_build_id(this->rsa, &this->keyid, &this->keyid_info))
349 {
350 destroy(this);
351 return NULL;
352 }
353 return &this->public;
354 }
355
356 typedef struct private_builder_t private_builder_t;
357 /**
358 * Builder implementation for key loading
359 */
360 struct private_builder_t {
361 /** implements the builder interface */
362 builder_t public;
363 /** loaded public key */
364 openssl_rsa_public_key_t *key;
365 };
366
367 /**
368 * Implementation of builder_t.build
369 */
370 static openssl_rsa_public_key_t *build(private_builder_t *this)
371 {
372 openssl_rsa_public_key_t *key = this->key;
373
374 free(this);
375 return key;
376 }
377
378 /**
379 * Implementation of builder_t.add
380 */
381 static void add(private_builder_t *this, builder_part_t part, ...)
382 {
383 if (!this->key)
384 {
385 va_list args;
386 chunk_t chunk;
387
388 switch (part)
389 {
390 case BUILD_BLOB_ASN1_DER:
391 {
392 va_start(args, part);
393 chunk = va_arg(args, chunk_t);
394 this->key = load(chunk_clone(chunk));
395 va_end(args);
396 return;
397 }
398 default:
399 break;
400 }
401 }
402 if (this->key)
403 {
404 destroy((private_openssl_rsa_public_key_t*)this->key);
405 }
406 builder_cancel(&this->public);
407 }
408
409 /**
410 * Builder construction function
411 */
412 builder_t *openssl_rsa_public_key_builder(key_type_t type)
413 {
414 private_builder_t *this;
415
416 if (type != KEY_RSA)
417 {
418 return NULL;
419 }
420
421 this = malloc_thing(private_builder_t);
422
423 this->key = NULL;
424 this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
425 this->public.build = (void*(*)(builder_t *this))build;
426
427 return &this->public;
428 }
429