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