support of SHA224-based certificate signatures
[strongswan.git] / src / libstrongswan / plugins / gcrypt / gcrypt_rsa_public_key.c
1 /*
2 * Copyright (C) 2005-2009 Martin Willi
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
16 #include <gcrypt.h>
17
18 #include "gcrypt_rsa_public_key.h"
19
20 #include <debug.h>
21 #include <asn1/oid.h>
22 #include <asn1/asn1.h>
23 #include <asn1/asn1_parser.h>
24 #include <asn1/pem.h>
25 #include <crypto/hashers/hasher.h>
26
27 typedef struct private_gcrypt_rsa_public_key_t private_gcrypt_rsa_public_key_t;
28
29 /**
30 * Private data structure with signing context.
31 */
32 struct private_gcrypt_rsa_public_key_t {
33
34 /**
35 * Public interface for this signer.
36 */
37 gcrypt_rsa_public_key_t public;
38
39 /**
40 * gcrypt S-expression representing an public RSA key
41 */
42 gcry_sexp_t key;
43
44 /**
45 * Keyid formed as a SHA-1 hash of a publicKey object
46 */
47 identification_t* keyid;
48
49 /**
50 * Keyid formed as a SHA-1 hash of a publicKeyInfo object
51 */
52 identification_t* keyid_info;
53
54 /**
55 * reference counter
56 */
57 refcount_t ref;
58 };
59
60 /**
61 * Implemented in gcrypt_rsa_private_key.c
62 */
63 chunk_t gcrypt_rsa_find_token(gcry_sexp_t sexp, char *name, gcry_sexp_t key);
64 bool gcrypt_rsa_build_keyids(gcry_sexp_t key, identification_t **keyid,
65 identification_t **keyid_info);
66
67 /**
68 * verification of a padded PKCS1 signature without an OID
69 */
70 static bool verify_raw(private_gcrypt_rsa_public_key_t *this,
71 chunk_t data, chunk_t signature)
72 {
73 gcry_sexp_t in, sig;
74 gcry_error_t err;
75 chunk_t em;
76 size_t k;
77
78 /* EM = 0x00 || 0x01 || PS || 0x00 || T
79 * PS = 0xFF padding, with length to fill em
80 * T = data
81 */
82 k = gcry_pk_get_nbits(this->key) / 8;
83 if (data.len > k - 3)
84 {
85 return FALSE;
86 }
87 em = chunk_alloc(k);
88 memset(em.ptr, 0xFF, em.len);
89 em.ptr[0] = 0x00;
90 em.ptr[1] = 0x01;
91 em.ptr[em.len - data.len - 1] = 0x00;
92 memcpy(em.ptr + em.len - data.len, data.ptr, data.len);
93
94 err = gcry_sexp_build(&in, NULL, "(data(flags raw)(value %b))",
95 em.len, em.ptr);
96 chunk_free(&em);
97 if (err)
98 {
99 DBG1("building data S-expression failed: %s", gpg_strerror(err));
100 return FALSE;
101 }
102 err = gcry_sexp_build(&sig, NULL, "(sig-val(rsa(s %b)))",
103 signature.len, signature.ptr);
104 if (err)
105 {
106 DBG1("building signature S-expression failed: %s", gpg_strerror(err));
107 gcry_sexp_release(in);
108 return FALSE;
109 }
110 err = gcry_pk_verify(sig, in, this->key);
111 gcry_sexp_release(in);
112 gcry_sexp_release(sig);
113 if (err)
114 {
115 DBG1("RSA signature verification failed: %s", gpg_strerror(err));
116 return FALSE;
117 }
118 return TRUE;
119 }
120
121 /**
122 * Verification of an EMSA PKCS1 signature described in PKCS#1
123 */
124 static bool verify_pkcs1(private_gcrypt_rsa_public_key_t *this,
125 hash_algorithm_t algorithm, char *hash_name,
126 chunk_t data, chunk_t signature)
127 {
128 hasher_t *hasher;
129 chunk_t hash;
130 gcry_error_t err;
131 gcry_sexp_t in, sig;
132
133 hasher = lib->crypto->create_hasher(lib->crypto, algorithm);
134 if (!hasher)
135 {
136 return FALSE;
137 }
138 hasher->allocate_hash(hasher, data, &hash);
139 hasher->destroy(hasher);
140
141 err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(hash %s %b))",
142 hash_name, hash.len, hash.ptr);
143 chunk_free(&hash);
144 if (err)
145 {
146 DBG1("building data S-expression failed: %s", gpg_strerror(err));
147 return FALSE;
148 }
149
150 err = gcry_sexp_build(&sig, NULL, "(sig-val(rsa(s %b)))",
151 signature.len, signature.ptr);
152 if (err)
153 {
154 DBG1("building signature S-expression failed: %s", gpg_strerror(err));
155 gcry_sexp_release(in);
156 return FALSE;
157 }
158 err = gcry_pk_verify(sig, in, this->key);
159 gcry_sexp_release(in);
160 gcry_sexp_release(sig);
161 if (err)
162 {
163 DBG1("RSA signature verification failed: %s", gpg_strerror(err));
164 return FALSE;
165 }
166 return TRUE;
167 }
168
169 /**
170 * Implementation of public_key_t.get_type.
171 */
172 static key_type_t get_type(private_gcrypt_rsa_public_key_t *this)
173 {
174 return KEY_RSA;
175 }
176
177 /**
178 * Implementation of public_key_t.verify.
179 */
180 static bool verify(private_gcrypt_rsa_public_key_t *this,
181 signature_scheme_t scheme, chunk_t data, chunk_t signature)
182 {
183 switch (scheme)
184 {
185 case SIGN_RSA_EMSA_PKCS1_NULL:
186 return verify_raw(this, data, signature);
187 case SIGN_RSA_EMSA_PKCS1_MD5:
188 return verify_pkcs1(this, HASH_MD5, "md5", data, signature);
189 case SIGN_RSA_EMSA_PKCS1_SHA1:
190 return verify_pkcs1(this, HASH_SHA1, "sha1", data, signature);
191 case SIGN_RSA_EMSA_PKCS1_SHA224:
192 return verify_pkcs1(this, HASH_SHA224, "sha224", data, signature);
193 case SIGN_RSA_EMSA_PKCS1_SHA256:
194 return verify_pkcs1(this, HASH_SHA256, "sha256", data, signature);
195 case SIGN_RSA_EMSA_PKCS1_SHA384:
196 return verify_pkcs1(this, HASH_SHA384, "sha384", data, signature);
197 case SIGN_RSA_EMSA_PKCS1_SHA512:
198 return verify_pkcs1(this, HASH_SHA512, "sha512", data, signature);
199 default:
200 DBG1("signature scheme %N not supported in RSA",
201 signature_scheme_names, scheme);
202 return FALSE;
203 }
204 }
205
206 /**
207 * Implementation of public_key_t.encrypt.
208 */
209 static bool encrypt_(private_gcrypt_rsa_public_key_t *this, chunk_t plain,
210 chunk_t *encrypted)
211 {
212 gcry_sexp_t in, out;
213 gcry_error_t err;
214
215 /* "pkcs1" uses PKCS 1.5 (section 8.1) block type 2 encryption:
216 * 00 | 02 | RANDOM | 00 | DATA */
217 err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(value %b))",
218 plain.len, plain.ptr);
219 if (err)
220 {
221 DBG1("building encryption S-expression failed: %s", gpg_strerror(err));
222 return FALSE;
223 }
224 err = gcry_pk_encrypt(&out, in, this->key);
225 gcry_sexp_release(in);
226 if (err)
227 {
228 DBG1("encrypting data using pkcs1 failed: %s", gpg_strerror(err));
229 return FALSE;
230 }
231 *encrypted = gcrypt_rsa_find_token(out, "a", this->key);
232 gcry_sexp_release(out);
233 return !!encrypted->len;
234 }
235
236 /**
237 * Implementation of gcrypt_rsa_public_key.equals.
238 */
239 static bool equals(private_gcrypt_rsa_public_key_t *this, public_key_t *other)
240 {
241 identification_t *keyid;
242
243 if (&this->public.interface == other)
244 {
245 return TRUE;
246 }
247 if (other->get_type(other) != KEY_RSA)
248 {
249 return FALSE;
250 }
251 keyid = other->get_id(other, ID_PUBKEY_SHA1);
252 if (keyid && keyid->equals(keyid, this->keyid))
253 {
254 return TRUE;
255 }
256 keyid = other->get_id(other, ID_PUBKEY_INFO_SHA1);
257 if (keyid && keyid->equals(keyid, this->keyid_info))
258 {
259 return TRUE;
260 }
261 return FALSE;
262 }
263
264 /**
265 * Implementation of public_key_t.get_keysize.
266 */
267 static size_t get_keysize(private_gcrypt_rsa_public_key_t *this)
268 {
269 return gcry_pk_get_nbits(this->key) / 8;
270 }
271
272 /**
273 * Implementation of public_key_t.get_id.
274 */
275 static identification_t *get_id(private_gcrypt_rsa_public_key_t *this,
276 id_type_t type)
277 {
278 switch (type)
279 {
280 case ID_PUBKEY_INFO_SHA1:
281 return this->keyid_info;
282 case ID_PUBKEY_SHA1:
283 return this->keyid;
284 default:
285 return NULL;
286 }
287 }
288
289 /*
290 * Implementation of public_key_t.get_encoding.
291 */
292 static chunk_t get_encoding(private_gcrypt_rsa_public_key_t *this)
293 {
294 return asn1_wrap(ASN1_SEQUENCE, "mm",
295 asn1_integer("m", gcrypt_rsa_find_token(this->key, "n", NULL)),
296 asn1_integer("m", gcrypt_rsa_find_token(this->key, "e", NULL)));
297 }
298
299 /**
300 * Implementation of public_key_t.get_ref.
301 */
302 static public_key_t* get_ref(private_gcrypt_rsa_public_key_t *this)
303 {
304 ref_get(&this->ref);
305 return &this->public.interface;
306 }
307
308 /**
309 * Implementation of gcrypt_rsa_public_key.destroy.
310 */
311 static void destroy(private_gcrypt_rsa_public_key_t *this)
312 {
313 if (ref_put(&this->ref))
314 {
315 DESTROY_IF(this->keyid);
316 DESTROY_IF(this->keyid_info);
317 gcry_sexp_release(this->key);
318 free(this);
319 }
320 }
321
322 /**
323 * Generic private constructor
324 */
325 static private_gcrypt_rsa_public_key_t *gcrypt_rsa_public_key_create_empty()
326 {
327 private_gcrypt_rsa_public_key_t *this = malloc_thing(private_gcrypt_rsa_public_key_t);
328
329 this->public.interface.get_type = (key_type_t (*)(public_key_t *this))get_type;
330 this->public.interface.verify = (bool (*)(public_key_t *this, signature_scheme_t scheme, chunk_t data, chunk_t signature))verify;
331 this->public.interface.encrypt = (bool (*)(public_key_t *this, chunk_t crypto, chunk_t *plain))encrypt_;
332 this->public.interface.equals = (bool (*) (public_key_t*, public_key_t*))equals;
333 this->public.interface.get_keysize = (size_t (*) (public_key_t *this))get_keysize;
334 this->public.interface.get_id = (identification_t* (*) (public_key_t *this,id_type_t))get_id;
335 this->public.interface.get_encoding = (chunk_t(*)(public_key_t*))get_encoding;
336 this->public.interface.get_ref = (public_key_t* (*)(public_key_t *this))get_ref;
337 this->public.interface.destroy = (void (*)(public_key_t *this))destroy;
338
339 this->key = NULL;
340 this->keyid = NULL;
341 this->keyid_info = NULL;
342 this->ref = 1;
343
344 return this;
345 }
346
347 /**
348 * Create a public key from a S-expression, used in gcrypt_rsa_private_key
349 */
350 public_key_t *gcrypt_rsa_public_key_create_from_sexp(gcry_sexp_t key)
351 {
352 private_gcrypt_rsa_public_key_t *this;
353 gcry_error_t err;
354 chunk_t n, e;
355
356 this = gcrypt_rsa_public_key_create_empty();
357 n = gcrypt_rsa_find_token(key, "n", NULL);
358 e = gcrypt_rsa_find_token(key, "e", NULL);
359
360 err = gcry_sexp_build(&this->key, NULL, "(public-key(rsa(n %b)(e %b)))",
361 n.len, n.ptr, e.len, e.ptr);
362 chunk_free(&n);
363 chunk_free(&e);
364 if (err)
365 {
366 DBG1("loading public key failed: %s", gpg_strerror(err));
367 free(this);
368 return NULL;
369 }
370 if (!gcrypt_rsa_build_keyids(this->key, &this->keyid, &this->keyid_info))
371 {
372 destroy(this);
373 return NULL;
374 }
375 return &this->public.interface;
376 }
377
378 /**
379 * ASN.1 definition of RSApublicKey
380 */
381 static const asn1Object_t pubkeyObjects[] = {
382 { 0, "RSAPublicKey", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
383 { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 1 */
384 { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 2 */
385 { 0, "exit", ASN1_EOC, ASN1_EXIT }
386 };
387 #define PUB_KEY_RSA_PUBLIC_KEY 0
388 #define PUB_KEY_MODULUS 1
389 #define PUB_KEY_EXPONENT 2
390
391 /**
392 * Load a public key from an ASN1 encoded blob
393 */
394 static gcrypt_rsa_public_key_t *load(chunk_t blob)
395 {
396 private_gcrypt_rsa_public_key_t *this;
397 asn1_parser_t *parser;
398 chunk_t object, n, e;
399 int objectID;
400 bool success = FALSE;
401 gcry_error_t err;
402
403 n = e = chunk_empty;
404
405 parser = asn1_parser_create(pubkeyObjects, blob);
406 while (parser->iterate(parser, &objectID, &object))
407 {
408 switch (objectID)
409 {
410 case PUB_KEY_MODULUS:
411 n = object;
412 break;
413 case PUB_KEY_EXPONENT:
414 e = object;
415 break;
416 }
417 }
418 success = parser->success(parser);
419 parser->destroy(parser);
420
421 if (!success)
422 {
423 return NULL;
424 }
425
426 this = gcrypt_rsa_public_key_create_empty();
427 err = gcry_sexp_build(&this->key, NULL, "(public-key(rsa(n %b)(e %b)))",
428 n.len, n.ptr, e.len, e.ptr);
429 if (err)
430 {
431 DBG1("loading public key failed: %s", gpg_strerror(err));
432 free(this);
433 return NULL;
434 }
435 if (!gcrypt_rsa_build_keyids(this->key, &this->keyid, &this->keyid_info))
436 {
437 destroy(this);
438 return NULL;
439 }
440 return &this->public;
441 }
442
443 typedef struct private_builder_t private_builder_t;
444 /**
445 * Builder implementation for key loading
446 */
447 struct private_builder_t {
448 /** implements the builder interface */
449 builder_t public;
450 /** loaded public key */
451 gcrypt_rsa_public_key_t *key;
452 };
453
454 /**
455 * Implementation of builder_t.build
456 */
457 static gcrypt_rsa_public_key_t *build(private_builder_t *this)
458 {
459 gcrypt_rsa_public_key_t *key = this->key;
460
461 free(this);
462 return key;
463 }
464
465 /**
466 * Implementation of builder_t.add
467 */
468 static void add(private_builder_t *this, builder_part_t part, ...)
469 {
470 if (!this->key)
471 {
472 va_list args;
473
474 switch (part)
475 {
476 case BUILD_BLOB_ASN1_DER:
477 {
478 va_start(args, part);
479 this->key = load(va_arg(args, chunk_t));
480 va_end(args);
481 return;
482 }
483 default:
484 break;
485 }
486 }
487 if (this->key)
488 {
489 destroy((private_gcrypt_rsa_public_key_t*)this->key);
490 }
491 builder_cancel(&this->public);
492 }
493
494 /**
495 * Builder construction function
496 */
497 builder_t *gcrypt_rsa_public_key_builder(key_type_t type)
498 {
499 private_builder_t *this;
500
501 if (type != KEY_RSA)
502 {
503 return NULL;
504 }
505
506 this = malloc_thing(private_builder_t);
507
508 this->key = NULL;
509 this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
510 this->public.build = (void*(*)(builder_t *this))build;
511
512 return &this->public;
513 }
514