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