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