updated openssl plugin to new private/public key API, use encoder framework
[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
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 * reference counter
42 */
43 refcount_t ref;
44 };
45
46 /**
47 * Verification of an EMPSA PKCS1 signature described in PKCS#1
48 */
49 static bool verify_emsa_pkcs1_signature(private_openssl_rsa_public_key_t *this,
50 int type, chunk_t data, chunk_t signature)
51 {
52 bool valid = FALSE;
53 int rsa_size = RSA_size(this->rsa);
54
55 /* OpenSSL expects a signature of exactly RSA size (no leading 0x00) */
56 if (signature.len > rsa_size)
57 {
58 signature = chunk_skip(signature, signature.len - rsa_size);
59 }
60
61 if (type == NID_undef)
62 {
63 chunk_t hash = chunk_alloc(rsa_size);
64
65 hash.len = RSA_public_decrypt(signature.len, signature.ptr, hash.ptr,
66 this->rsa, RSA_PKCS1_PADDING);
67 valid = chunk_equals(data, hash);
68 free(hash.ptr);
69 }
70 else
71 {
72 EVP_MD_CTX *ctx;
73 EVP_PKEY *key;
74 const EVP_MD *hasher;
75
76 hasher = EVP_get_digestbynid(type);
77 if (!hasher)
78 {
79 return FALSE;
80 }
81
82 ctx = EVP_MD_CTX_create();
83 key = EVP_PKEY_new();
84
85 if (!ctx || !key)
86 {
87 goto error;
88 }
89 if (!EVP_PKEY_set1_RSA(key, this->rsa))
90 {
91 goto error;
92 }
93 if (!EVP_VerifyInit_ex(ctx, hasher, NULL))
94 {
95 goto error;
96 }
97 if (!EVP_VerifyUpdate(ctx, data.ptr, data.len))
98 {
99 goto error;
100 }
101 valid = (EVP_VerifyFinal(ctx, signature.ptr, signature.len, key) == 1);
102
103 error:
104 if (key)
105 {
106 EVP_PKEY_free(key);
107 }
108 if (ctx)
109 {
110 EVP_MD_CTX_destroy(ctx);
111 }
112 }
113 return valid;
114 }
115
116 /**
117 * Implementation of public_key_t.get_type.
118 */
119 static key_type_t get_type(private_openssl_rsa_public_key_t *this)
120 {
121 return KEY_RSA;
122 }
123
124 /**
125 * Implementation of public_key_t.verify.
126 */
127 static bool verify(private_openssl_rsa_public_key_t *this, signature_scheme_t scheme,
128 chunk_t data, chunk_t signature)
129 {
130 switch (scheme)
131 {
132 case SIGN_RSA_EMSA_PKCS1_NULL:
133 return verify_emsa_pkcs1_signature(this, NID_undef, data, signature);
134 case SIGN_RSA_EMSA_PKCS1_SHA1:
135 return verify_emsa_pkcs1_signature(this, NID_sha1, data, signature);
136 case SIGN_RSA_EMSA_PKCS1_SHA224:
137 return verify_emsa_pkcs1_signature(this, NID_sha224, data, signature);
138 case SIGN_RSA_EMSA_PKCS1_SHA256:
139 return verify_emsa_pkcs1_signature(this, NID_sha256, data, signature);
140 case SIGN_RSA_EMSA_PKCS1_SHA384:
141 return verify_emsa_pkcs1_signature(this, NID_sha384, data, signature);
142 case SIGN_RSA_EMSA_PKCS1_SHA512:
143 return verify_emsa_pkcs1_signature(this, NID_sha512, data, signature);
144 case SIGN_RSA_EMSA_PKCS1_MD5:
145 return verify_emsa_pkcs1_signature(this, NID_md5, data, signature);
146 default:
147 DBG1("signature scheme %N not supported in RSA",
148 signature_scheme_names, scheme);
149 return FALSE;
150 }
151 }
152
153 /**
154 * Implementation of public_key_t.get_keysize.
155 */
156 static bool encrypt_(private_openssl_rsa_public_key_t *this,
157 chunk_t crypto, chunk_t *plain)
158 {
159 DBG1("RSA public key encryption not implemented");
160 return FALSE;
161 }
162
163 /**
164 * Implementation of public_key_t.get_keysize.
165 */
166 static size_t get_keysize(private_openssl_rsa_public_key_t *this)
167 {
168 return RSA_size(this->rsa);
169 }
170
171 /**
172 * Implementation of public_key_t.get_fingerprint.
173 */
174 static bool get_fingerprint(private_openssl_rsa_public_key_t *this,
175 key_encoding_type_t type, chunk_t *fingerprint)
176 {
177 chunk_t enc;
178 bool success;
179 u_char *p;
180
181 if (lib->encoding->get_cache(lib->encoding, type, this, fingerprint))
182 {
183 return TRUE;
184 }
185 enc = chunk_alloc(i2d_RSAPublicKey(this->rsa, NULL));
186 p = enc.ptr;
187 i2d_RSAPublicKey(this->rsa, &p);
188 success = lib->encoding->encode(lib->encoding, type, this, fingerprint,
189 KEY_PART_RSA_PUB_ASN1_DER, enc, KEY_PART_END);
190 free(enc.ptr);
191
192 return success;
193 }
194
195 /*
196 * Implementation of public_key_t.get_encoding.
197 */
198 static bool get_encoding(private_openssl_rsa_public_key_t *this,
199 key_encoding_type_t type, chunk_t *encoding)
200 {
201 chunk_t enc;
202 bool success;
203 u_char *p;
204
205 enc = chunk_alloc(i2d_RSAPublicKey(this->rsa, NULL));
206 p = enc.ptr;
207 i2d_RSAPublicKey(this->rsa, &p);
208 success = lib->encoding->encode(lib->encoding, type, NULL, encoding,
209 KEY_PART_RSA_PUB_ASN1_DER, enc, KEY_PART_END);
210 free(enc.ptr);
211 return success;
212 }
213
214 /**
215 * Implementation of public_key_t.get_ref.
216 */
217 static public_key_t* get_ref(private_openssl_rsa_public_key_t *this)
218 {
219 ref_get(&this->ref);
220 return &this->public.interface;
221 }
222
223 /**
224 * Implementation of openssl_rsa_public_key.destroy.
225 */
226 static void destroy(private_openssl_rsa_public_key_t *this)
227 {
228 if (ref_put(&this->ref))
229 {
230 if (this->rsa)
231 {
232 RSA_free(this->rsa);
233 }
234 lib->encoding->clear_cache(lib->encoding, this);
235 free(this);
236 }
237 }
238
239 /**
240 * Generic private constructor
241 */
242 static private_openssl_rsa_public_key_t *create_empty()
243 {
244 private_openssl_rsa_public_key_t *this = malloc_thing(private_openssl_rsa_public_key_t);
245
246 this->public.interface.get_type = (key_type_t (*)(public_key_t *this))get_type;
247 this->public.interface.verify = (bool (*)(public_key_t *this, signature_scheme_t scheme, chunk_t data, chunk_t signature))verify;
248 this->public.interface.encrypt = (bool (*)(public_key_t *this, chunk_t crypto, chunk_t *plain))encrypt_;
249 this->public.interface.equals = public_key_equals;
250 this->public.interface.get_keysize = (size_t (*) (public_key_t *this))get_keysize;
251 this->public.interface.get_fingerprint = (bool(*)(public_key_t*, key_encoding_type_t type, chunk_t *fp))get_fingerprint;
252 this->public.interface.get_encoding = (bool(*)(public_key_t*, key_encoding_type_t type, chunk_t *encoding))get_encoding;
253 this->public.interface.get_ref = (public_key_t* (*)(public_key_t *this))get_ref;
254 this->public.interface.destroy = (void (*)(public_key_t *this))destroy;
255
256 this->rsa = NULL;
257 this->ref = 1;
258
259 return this;
260 }
261
262 /**
263 * Load a public key from an ASN1 encoded blob
264 */
265 static openssl_rsa_public_key_t *load(chunk_t blob)
266 {
267 u_char *p = blob.ptr;
268 private_openssl_rsa_public_key_t *this = create_empty();
269
270 this->rsa = d2i_RSAPublicKey(NULL, (const u_char**)&p, blob.len);
271 if (!this->rsa)
272 {
273 destroy(this);
274 return NULL;
275 }
276
277 return &this->public;
278 }
279
280 typedef struct private_builder_t private_builder_t;
281
282 /**
283 * Builder implementation for key loading
284 */
285 struct private_builder_t {
286 /** implements the builder interface */
287 builder_t public;
288 /** loaded public key */
289 openssl_rsa_public_key_t *key;
290 };
291
292 /**
293 * Implementation of builder_t.build
294 */
295 static openssl_rsa_public_key_t *build(private_builder_t *this)
296 {
297 openssl_rsa_public_key_t *key = this->key;
298
299 free(this);
300 return key;
301 }
302
303 /**
304 * Implementation of builder_t.add
305 */
306 static void add(private_builder_t *this, builder_part_t part, ...)
307 {
308 if (!this->key)
309 {
310 va_list args;
311
312 switch (part)
313 {
314 case BUILD_BLOB_ASN1_DER:
315 {
316 va_start(args, part);
317 this->key = load(va_arg(args, chunk_t));
318 va_end(args);
319 return;
320 }
321 default:
322 break;
323 }
324 }
325 if (this->key)
326 {
327 destroy((private_openssl_rsa_public_key_t*)this->key);
328 }
329 builder_cancel(&this->public);
330 }
331
332 /**
333 * Builder construction function
334 */
335 builder_t *openssl_rsa_public_key_builder(key_type_t type)
336 {
337 private_builder_t *this;
338
339 if (type != KEY_RSA)
340 {
341 return NULL;
342 }
343
344 this = malloc_thing(private_builder_t);
345
346 this->key = NULL;
347 this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
348 this->public.build = (void*(*)(builder_t *this))build;
349
350 return &this->public;
351 }
352