]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
Moved debug.[ch] to utils folder
[thirdparty/strongswan.git] / src / libstrongswan / plugins / openssl / openssl_rsa_public_key.c
CommitLineData
84770ded 1/*
e35c3e2a 2 * Copyright (C) 2009 Martin Willi
84770ded
TB
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.
84770ded
TB
15 */
16
17#include "openssl_rsa_public_key.h"
18
f05b4272 19#include <utils/debug.h>
84770ded
TB
20
21#include <openssl/evp.h>
22#include <openssl/rsa.h>
b12c6d16 23#include <openssl/x509.h>
84770ded
TB
24
25typedef struct private_openssl_rsa_public_key_t private_openssl_rsa_public_key_t;
26
27/**
28 * Private data structure with signing context.
29 */
30struct private_openssl_rsa_public_key_t {
31 /**
32 * Public interface for this signer.
33 */
34 openssl_rsa_public_key_t public;
7daf5226 35
84770ded
TB
36 /**
37 * RSA object from OpenSSL
38 */
39 RSA *rsa;
7daf5226 40
84770ded
TB
41 /**
42 * reference counter
43 */
44 refcount_t ref;
45};
46
3cd6077b
SC
47
48
84770ded
TB
49/**
50 * Verification of an EMPSA PKCS1 signature described in PKCS#1
51 */
52static 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;
29bbfc11
AS
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)
84770ded 60 {
29bbfc11 61 signature = chunk_skip(signature, signature.len - rsa_size);
84770ded 62 }
29bbfc11
AS
63
64 if (type == NID_undef)
84770ded 65 {
29bbfc11
AS
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);
84770ded 72 }
29bbfc11 73 else
d6dc9db5 74 {
29bbfc11
AS
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);
7daf5226 105
84770ded 106error:
29bbfc11
AS
107 if (key)
108 {
109 EVP_PKEY_free(key);
110 }
111 if (ctx)
112 {
113 EVP_MD_CTX_destroy(ctx);
114 }
84770ded
TB
115 }
116 return valid;
117}
118
57202484
MW
119METHOD(public_key_t, get_type, key_type_t,
120 private_openssl_rsa_public_key_t *this)
84770ded
TB
121{
122 return KEY_RSA;
123}
124
57202484
MW
125METHOD(public_key_t, verify, bool,
126 private_openssl_rsa_public_key_t *this, signature_scheme_t scheme,
127 chunk_t data, chunk_t signature)
84770ded
TB
128{
129 switch (scheme)
130 {
29bbfc11
AS
131 case SIGN_RSA_EMSA_PKCS1_NULL:
132 return verify_emsa_pkcs1_signature(this, NID_undef, data, signature);
84770ded
TB
133 case SIGN_RSA_EMSA_PKCS1_SHA1:
134 return verify_emsa_pkcs1_signature(this, NID_sha1, data, signature);
b6f739c1
AS
135 case SIGN_RSA_EMSA_PKCS1_SHA224:
136 return verify_emsa_pkcs1_signature(this, NID_sha224, data, signature);
84770ded
TB
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:
8b0e0910 146 DBG1(DBG_LIB, "signature scheme %N not supported in RSA",
84770ded
TB
147 signature_scheme_names, scheme);
148 return FALSE;
149 }
150}
151
57202484 152METHOD(public_key_t, encrypt, bool,
33ddaaab 153 private_openssl_rsa_public_key_t *this, encryption_scheme_t scheme,
d775af9d 154 chunk_t plain, chunk_t *crypto)
84770ded 155{
d775af9d
MW
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;
84770ded
TB
183}
184
a944d209 185METHOD(public_key_t, get_keysize, int,
57202484 186 private_openssl_rsa_public_key_t *this)
84770ded 187{
a944d209 188 return RSA_size(this->rsa) * 8;
84770ded
TB
189}
190
191/**
b12c6d16 192 * Calculate fingerprint from a RSA key, also used in rsa private key.
84770ded 193 */
da9724e6 194bool openssl_rsa_fingerprint(RSA *rsa, cred_encoding_type_t type, chunk_t *fp)
84770ded 195{
b12c6d16
MW
196 hasher_t *hasher;
197 chunk_t key;
e35c3e2a 198 u_char *p;
7daf5226 199
b12c6d16 200 if (lib->encoding->get_cache(lib->encoding, type, rsa, fp))
84770ded 201 {
e35c3e2a 202 return TRUE;
84770ded 203 }
b12c6d16
MW
204 switch (type)
205 {
da9724e6 206 case KEYID_PUBKEY_SHA1:
b12c6d16
MW
207 key = chunk_alloc(i2d_RSAPublicKey(rsa, NULL));
208 p = key.ptr;
209 i2d_RSAPublicKey(rsa, &p);
210 break;
da9724e6 211 case KEYID_PUBKEY_INFO_SHA1:
b12c6d16
MW
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);
87dd205b 220 if (!hasher || !hasher->allocate_hash(hasher, key, fp))
b12c6d16 221 {
8b0e0910 222 DBG1(DBG_LIB, "SHA1 hash algorithm not supported, fingerprinting failed");
87dd205b 223 DESTROY_IF(hasher);
b12c6d16
MW
224 free(key.ptr);
225 return FALSE;
226 }
1a8ef8aa 227 free(key.ptr);
b12c6d16
MW
228 hasher->destroy(hasher);
229 lib->encoding->cache(lib->encoding, type, rsa, *fp);
230 return TRUE;
231}
232
57202484
MW
233METHOD(public_key_t, get_fingerprint, bool,
234 private_openssl_rsa_public_key_t *this, cred_encoding_type_t type,
235 chunk_t *fingerprint)
b12c6d16
MW
236{
237 return openssl_rsa_fingerprint(this->rsa, type, fingerprint);
84770ded
TB
238}
239
57202484
MW
240METHOD(public_key_t, get_encoding, bool,
241 private_openssl_rsa_public_key_t *this, cred_encoding_type_t type,
242 chunk_t *encoding)
84770ded 243{
e35c3e2a 244 u_char *p;
7daf5226 245
b12c6d16
MW
246 switch (type)
247 {
da9724e6
MW
248 case PUBKEY_SPKI_ASN1_DER:
249 case PUBKEY_PEM:
b12c6d16 250 {
29cf15a9
AS
251 bool success = TRUE;
252
b12c6d16
MW
253 *encoding = chunk_alloc(i2d_RSA_PUBKEY(this->rsa, NULL));
254 p = encoding->ptr;
255 i2d_RSA_PUBKEY(this->rsa, &p);
29cf15a9 256
da9724e6 257 if (type == PUBKEY_PEM)
29cf15a9
AS
258 {
259 chunk_t asn1_encoding = *encoding;
260
da9724e6
MW
261 success = lib->encoding->encode(lib->encoding, PUBKEY_PEM,
262 NULL, encoding, CRED_PART_RSA_PUB_ASN1_DER,
263 asn1_encoding, CRED_PART_END);
29cf15a9 264 chunk_clear(&asn1_encoding);
0a4dc787 265 }
29cf15a9 266 return success;
b12c6d16 267 }
da9724e6 268 case PUBKEY_ASN1_DER:
b12c6d16
MW
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 }
84770ded
TB
278}
279
57202484
MW
280METHOD(public_key_t, get_ref, public_key_t*,
281 private_openssl_rsa_public_key_t *this)
84770ded
TB
282{
283 ref_get(&this->ref);
57202484 284 return &this->public.key;
84770ded
TB
285}
286
57202484
MW
287METHOD(public_key_t, destroy, void,
288 private_openssl_rsa_public_key_t *this)
84770ded
TB
289{
290 if (ref_put(&this->ref))
291 {
292 if (this->rsa)
293 {
b12c6d16 294 lib->encoding->clear_cache(lib->encoding, this->rsa);
84770ded
TB
295 RSA_free(this->rsa);
296 }
84770ded
TB
297 free(this);
298 }
299}
300
301/**
302 * Generic private constructor
303 */
e35c3e2a 304static private_openssl_rsa_public_key_t *create_empty()
84770ded 305{
57202484
MW
306 private_openssl_rsa_public_key_t *this;
307
308 INIT(this,
ba31fe1f
MW
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 },
57202484
MW
322 },
323 .ref = 1,
324 );
7daf5226 325
84770ded
TB
326 return this;
327}
328
84770ded 329/**
30c06407 330 * See header.
84770ded 331 */
30c06407
MW
332openssl_rsa_public_key_t *openssl_rsa_public_key_load(key_type_t type,
333 va_list args)
84770ded 334{
30c06407 335 private_openssl_rsa_public_key_t *this;
b9fbd665 336 chunk_t blob, n, e;
7daf5226 337
b9fbd665 338 n = e = blob = chunk_empty;
30c06407 339 while (TRUE)
84770ded 340 {
30c06407 341 switch (va_arg(args, builder_part_t))
84770ded 342 {
f7c17aa1 343 case BUILD_BLOB_ASN1_DER:
30c06407
MW
344 blob = va_arg(args, chunk_t);
345 continue;
b9fbd665
MW
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;
30c06407 352 case BUILD_END:
f7c17aa1 353 break;
30c06407
MW
354 default:
355 return NULL;
84770ded 356 }
30c06407 357 break;
84770ded 358 }
84770ded 359
30c06407 360 this = create_empty();
b9fbd665
MW
361 if (blob.ptr)
362 {
026b0058
MW
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 }
b9fbd665
MW
376 if (this->rsa)
377 {
378 return &this->public;
379 }
380 }
026b0058 381 else if (n.ptr && e.ptr && type == KEY_RSA)
84770ded 382 {
b9fbd665
MW
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;
84770ded 387 }
b9fbd665
MW
388 destroy(this);
389 return NULL;
84770ded 390}