Reverse the changes made to openssl plugin for signature verification
[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 METHOD(public_key_t, get_type, key_type_t,
120 private_openssl_rsa_public_key_t *this)
121 {
122 return KEY_RSA;
123 }
124
125 METHOD(public_key_t, verify, bool,
126 private_openssl_rsa_public_key_t *this, signature_scheme_t scheme,
127 chunk_t data, chunk_t signature)
128 {
129 switch (scheme)
130 {
131 case SIGN_RSA_EMSA_PKCS1_NULL:
132 return verify_emsa_pkcs1_signature(this, NID_undef, data, signature);
133 case SIGN_RSA_EMSA_PKCS1_SHA1:
134 return verify_emsa_pkcs1_signature(this, NID_sha1, data, signature);
135 case SIGN_RSA_EMSA_PKCS1_SHA224:
136 return verify_emsa_pkcs1_signature(this, NID_sha224, data, signature);
137 case SIGN_RSA_EMSA_PKCS1_SHA256:
138 return verify_emsa_pkcs1_signature(this, NID_sha256, data, signature);
139 case SIGN_RSA_EMSA_PKCS1_SHA384:
140 return verify_emsa_pkcs1_signature(this, NID_sha384, data, signature);
141 case SIGN_RSA_EMSA_PKCS1_SHA512:
142 return verify_emsa_pkcs1_signature(this, NID_sha512, data, signature);
143 case SIGN_RSA_EMSA_PKCS1_MD5:
144 return verify_emsa_pkcs1_signature(this, NID_md5, data, signature);
145 default:
146 DBG1(DBG_LIB, "signature scheme %N not supported in RSA",
147 signature_scheme_names, scheme);
148 return FALSE;
149 }
150 }
151
152 METHOD(public_key_t, encrypt, bool,
153 private_openssl_rsa_public_key_t *this, encryption_scheme_t scheme,
154 chunk_t plain, chunk_t *crypto)
155 {
156 int padding, len;
157 char *encrypted;
158
159 switch (scheme)
160 {
161 case ENCRYPT_RSA_PKCS1:
162 padding = RSA_PKCS1_PADDING;
163 break;
164 case ENCRYPT_RSA_OAEP_SHA1:
165 padding = RSA_PKCS1_OAEP_PADDING;
166 break;
167 default:
168 DBG1(DBG_LIB, "decryption scheme %N not supported via openssl",
169 encryption_scheme_names, scheme);
170 return FALSE;
171 }
172 encrypted = malloc(RSA_size(this->rsa));
173 len = RSA_public_encrypt(plain.len, plain.ptr, encrypted,
174 this->rsa, padding);
175 if (len < 0)
176 {
177 DBG1(DBG_LIB, "RSA decryption failed");
178 free(encrypted);
179 return FALSE;
180 }
181 *crypto = chunk_create(encrypted, len);
182 return TRUE;
183 }
184
185 METHOD(public_key_t, get_keysize, int,
186 private_openssl_rsa_public_key_t *this)
187 {
188 return RSA_size(this->rsa) * 8;
189 }
190
191 /**
192 * Calculate fingerprint from a RSA key, also used in rsa private key.
193 */
194 bool openssl_rsa_fingerprint(RSA *rsa, cred_encoding_type_t type, chunk_t *fp)
195 {
196 hasher_t *hasher;
197 chunk_t key;
198 u_char *p;
199
200 if (lib->encoding->get_cache(lib->encoding, type, rsa, fp))
201 {
202 return TRUE;
203 }
204 switch (type)
205 {
206 case KEYID_PUBKEY_SHA1:
207 key = chunk_alloc(i2d_RSAPublicKey(rsa, NULL));
208 p = key.ptr;
209 i2d_RSAPublicKey(rsa, &p);
210 break;
211 case KEYID_PUBKEY_INFO_SHA1:
212 key = chunk_alloc(i2d_RSA_PUBKEY(rsa, NULL));
213 p = key.ptr;
214 i2d_RSA_PUBKEY(rsa, &p);
215 break;
216 default:
217 return FALSE;
218 }
219 hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
220 if (!hasher)
221 {
222 DBG1(DBG_LIB, "SHA1 hash algorithm not supported, fingerprinting failed");
223 free(key.ptr);
224 return FALSE;
225 }
226 hasher->allocate_hash(hasher, key, fp);
227 free(key.ptr);
228 hasher->destroy(hasher);
229 lib->encoding->cache(lib->encoding, type, rsa, *fp);
230 return TRUE;
231 }
232
233 METHOD(public_key_t, get_fingerprint, bool,
234 private_openssl_rsa_public_key_t *this, cred_encoding_type_t type,
235 chunk_t *fingerprint)
236 {
237 return openssl_rsa_fingerprint(this->rsa, type, fingerprint);
238 }
239
240 METHOD(public_key_t, get_encoding, bool,
241 private_openssl_rsa_public_key_t *this, cred_encoding_type_t type,
242 chunk_t *encoding)
243 {
244 u_char *p;
245
246 switch (type)
247 {
248 case PUBKEY_SPKI_ASN1_DER:
249 case PUBKEY_PEM:
250 {
251 bool success = TRUE;
252
253 *encoding = chunk_alloc(i2d_RSA_PUBKEY(this->rsa, NULL));
254 p = encoding->ptr;
255 i2d_RSA_PUBKEY(this->rsa, &p);
256
257 if (type == PUBKEY_PEM)
258 {
259 chunk_t asn1_encoding = *encoding;
260
261 success = lib->encoding->encode(lib->encoding, PUBKEY_PEM,
262 NULL, encoding, CRED_PART_RSA_PUB_ASN1_DER,
263 asn1_encoding, CRED_PART_END);
264 chunk_clear(&asn1_encoding);
265 }
266 return success;
267 }
268 case PUBKEY_ASN1_DER:
269 {
270 *encoding = chunk_alloc(i2d_RSAPublicKey(this->rsa, NULL));
271 p = encoding->ptr;
272 i2d_RSAPublicKey(this->rsa, &p);
273 return TRUE;
274 }
275 default:
276 return FALSE;
277 }
278 }
279
280 METHOD(public_key_t, get_ref, public_key_t*,
281 private_openssl_rsa_public_key_t *this)
282 {
283 ref_get(&this->ref);
284 return &this->public.key;
285 }
286
287 METHOD(public_key_t, destroy, void,
288 private_openssl_rsa_public_key_t *this)
289 {
290 if (ref_put(&this->ref))
291 {
292 if (this->rsa)
293 {
294 lib->encoding->clear_cache(lib->encoding, this->rsa);
295 RSA_free(this->rsa);
296 }
297 free(this);
298 }
299 }
300
301 /**
302 * Generic private constructor
303 */
304 static private_openssl_rsa_public_key_t *create_empty()
305 {
306 private_openssl_rsa_public_key_t *this;
307
308 INIT(this,
309 .public = {
310 .key = {
311 .get_type = _get_type,
312 .verify = _verify,
313 .encrypt = _encrypt,
314 .equals = public_key_equals,
315 .get_keysize = _get_keysize,
316 .get_fingerprint = _get_fingerprint,
317 .has_fingerprint = public_key_has_fingerprint,
318 .get_encoding = _get_encoding,
319 .get_ref = _get_ref,
320 .destroy = _destroy,
321 },
322 },
323 .ref = 1,
324 );
325
326 return this;
327 }
328
329 /**
330 * See header.
331 */
332 openssl_rsa_public_key_t *openssl_rsa_public_key_load(key_type_t type,
333 va_list args)
334 {
335 private_openssl_rsa_public_key_t *this;
336 chunk_t blob, n, e;
337
338 n = e = blob = chunk_empty;
339 while (TRUE)
340 {
341 switch (va_arg(args, builder_part_t))
342 {
343 case BUILD_BLOB_ASN1_DER:
344 blob = va_arg(args, chunk_t);
345 continue;
346 case BUILD_RSA_MODULUS:
347 n = va_arg(args, chunk_t);
348 continue;
349 case BUILD_RSA_PUB_EXP:
350 e = va_arg(args, chunk_t);
351 continue;
352 case BUILD_END:
353 break;
354 default:
355 return NULL;
356 }
357 break;
358 }
359
360 this = create_empty();
361 if (blob.ptr)
362 {
363 switch (type)
364 {
365 case KEY_ANY:
366 this->rsa = d2i_RSA_PUBKEY(NULL, (const u_char**)&blob.ptr,
367 blob.len);
368 break;
369 case KEY_RSA:
370 this->rsa = d2i_RSAPublicKey(NULL, (const u_char**)&blob.ptr,
371 blob.len);
372 break;
373 default:
374 break;
375 }
376 if (this->rsa)
377 {
378 return &this->public;
379 }
380 }
381 else if (n.ptr && e.ptr && type == KEY_RSA)
382 {
383 this->rsa = RSA_new();
384 this->rsa->n = BN_bin2bn((const u_char*)n.ptr, n.len, NULL);
385 this->rsa->e = BN_bin2bn((const u_char*)e.ptr, e.len, NULL);
386 return &this->public;
387 }
388 destroy(this);
389 return NULL;
390 }