2105d8ffe32ff9dfeb86575ae513cb00f60bf849
[strongswan.git] / src / libstrongswan / crypto / rsa / rsa_public_key.c
1 /**
2 * @file rsa_public_key.c
3 *
4 * @brief Implementation of rsa_public_key_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005 Jan Hutter
10 * Copyright (C) 2005-2006 Martin Willi
11 * Copyright (C) 2007-2008 Andreas Steffen
12 *
13 * Hochschule fuer Technik Rapperswil
14 *
15 * This program is free software; you can redistribute it and/or modify it
16 * under the terms of the GNU General Public License as published by the
17 * Free Software Foundation; either version 2 of the License, or (at your
18 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
19 *
20 * This program is distributed in the hope that it will be useful, but
21 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 * for more details.
24 *
25 * RCSID $Id$
26 */
27
28 #include <gmp.h>
29 #include <sys/stat.h>
30 #include <unistd.h>
31 #include <stdio.h>
32 #include <string.h>
33
34 #include "rsa_public_key.h"
35
36 #include <debug.h>
37 #include <crypto/hashers/hasher.h>
38 #include <asn1/asn1.h>
39 #include <asn1/pem.h>
40
41 /* ASN.1 definition of RSApublicKey */
42 static const asn1Object_t pubkeyObjects[] = {
43 { 0, "RSAPublicKey", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
44 { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 1 */
45 { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 2 */
46 };
47
48 #define PUB_KEY_RSA_PUBLIC_KEY 0
49 #define PUB_KEY_MODULUS 1
50 #define PUB_KEY_EXPONENT 2
51 #define PUB_KEY_ROOF 3
52
53 /* ASN.1 definition of digestInfo */
54 static const asn1Object_t digestInfoObjects[] = {
55 { 0, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
56 { 1, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 1 */
57 { 1, "digest", ASN1_OCTET_STRING, ASN1_BODY }, /* 2 */
58 };
59
60 #define DIGEST_INFO 0
61 #define DIGEST_INFO_ALGORITHM 1
62 #define DIGEST_INFO_DIGEST 2
63 #define DIGEST_INFO_ROOF 3
64
65 typedef struct private_rsa_public_key_t private_rsa_public_key_t;
66
67 /**
68 * Private data structure with signing context.
69 */
70 struct private_rsa_public_key_t {
71 /**
72 * Public interface for this signer.
73 */
74 rsa_public_key_t public;
75
76 /**
77 * Public modulus.
78 */
79 mpz_t n;
80
81 /**
82 * Public exponent.
83 */
84 mpz_t e;
85
86 /**
87 * Keysize in bytes.
88 */
89 size_t k;
90
91 /**
92 * Keyid formed as a SHA-1 hash of a publicKeyInfo object
93 */
94 chunk_t keyid;
95
96 /**
97 * @brief Implements the RSAEP algorithm specified in PKCS#1.
98 *
99 * @param this calling object
100 * @param data data to process
101 * @return processed data
102 */
103 chunk_t (*rsaep) (const private_rsa_public_key_t *this, chunk_t data);
104
105 /**
106 * @brief Implements the RSASVP1 algorithm specified in PKCS#1.
107 *
108 * @param this calling object
109 * @param data data to process
110 * @return processed data
111 */
112 chunk_t (*rsavp1) (const private_rsa_public_key_t *this, chunk_t data);
113 };
114
115 /**
116 * Implementation of private_rsa_public_key_t.rsaep and private_rsa_public_key_t.rsavp1
117 */
118 static chunk_t rsaep(const private_rsa_public_key_t *this, chunk_t data)
119 {
120 mpz_t m, c;
121 chunk_t encrypted;
122
123 mpz_init(c);
124 mpz_init(m);
125
126 mpz_import(m, data.len, 1, 1, 1, 0, data.ptr);
127
128 mpz_powm(c, m, this->e, this->n);
129
130 encrypted.len = this->k;
131 encrypted.ptr = mpz_export(NULL, NULL, 1, encrypted.len, 1, 0, c);
132
133 mpz_clear(c);
134 mpz_clear(m);
135
136 return encrypted;
137 }
138
139 /**
140 * Implementation of rsa_public_key.verify_emsa_pkcs1_signature.
141 */
142 static status_t verify_emsa_pkcs1_signature(const private_rsa_public_key_t *this,
143 hash_algorithm_t algorithm,
144 chunk_t data, chunk_t signature)
145 {
146 chunk_t em_ori, em;
147 status_t res = FAILED;
148
149 /* remove any preceding 0-bytes from signature */
150 while (signature.len && *(signature.ptr) == 0x00)
151 {
152 signature.len -= 1;
153 signature.ptr++;
154 }
155
156 if (signature.len > this->k)
157 {
158 return INVALID_ARG;
159 }
160
161 /* unpack signature */
162 em_ori = em = this->rsavp1(this, signature);
163
164 /* result should look like this:
165 * EM = 0x00 || 0x01 || PS || 0x00 || T.
166 * PS = 0xFF padding, with length to fill em
167 * T = oid || hash
168 */
169
170 /* check magic bytes */
171 if (*(em.ptr) != 0x00 || *(em.ptr+1) != 0x01)
172 {
173 DBG2("incorrect padding - probably wrong RSA key");
174 goto end;
175 }
176 em.ptr += 2;
177 em.len -= 2;
178
179 /* find magic 0x00 */
180 while (em.len > 0)
181 {
182 if (*em.ptr == 0x00)
183 {
184 /* found magic byte, stop */
185 em.ptr++;
186 em.len--;
187 break;
188 }
189 else if (*em.ptr != 0xFF)
190 {
191 /* bad padding, decryption failed ?!*/
192 goto end;
193 }
194 em.ptr++;
195 em.len--;
196 }
197
198 if (em.len == 0)
199 {
200 /* no digestInfo found */
201 goto end;
202 }
203
204 /* parse ASN.1-based digestInfo */
205 {
206 asn1_ctx_t ctx;
207 chunk_t object;
208 u_int level;
209 int objectID = 0;
210 hash_algorithm_t hash_algorithm = HASH_UNKNOWN;
211
212 asn1_init(&ctx, em, 0, FALSE, FALSE);
213
214 while (objectID < DIGEST_INFO_ROOF)
215 {
216 if (!extract_object(digestInfoObjects, &objectID, &object, &level, &ctx))
217 {
218 goto end;
219 }
220 switch (objectID)
221 {
222 case DIGEST_INFO:
223 if (em.len > object.len)
224 {
225 DBG1("digestInfo field in signature is followed by %u surplus bytes",
226 em.len - object.len);
227 goto end;
228 }
229 break;
230 case DIGEST_INFO_ALGORITHM:
231 {
232 int hash_oid = parse_algorithmIdentifier(object, level+1, NULL);
233
234 hash_algorithm = hasher_algorithm_from_oid(hash_oid);
235 if (hash_algorithm == HASH_UNKNOWN
236 || (algorithm != HASH_UNKNOWN && hash_algorithm != algorithm))
237 {
238 DBG1("wrong hash algorithm used in signature");
239 goto end;
240 }
241 }
242 break;
243 case DIGEST_INFO_DIGEST:
244 {
245 chunk_t hash;
246 hasher_t *hasher = hasher_create(hash_algorithm);
247
248 if (object.len != hasher->get_hash_size(hasher))
249 {
250 DBG1("hash size in signature is %u bytes instead of %u bytes",
251 object.len, hasher->get_hash_size(hasher));
252 hasher->destroy(hasher);
253 goto end;
254 }
255
256 /* build our own hash */
257 hasher->allocate_hash(hasher, data, &hash);
258 hasher->destroy(hasher);
259
260 /* compare the hashes */
261 res = memeq(object.ptr, hash.ptr, hash.len) ? SUCCESS : FAILED;
262 free(hash.ptr);
263 }
264 break;
265 default:
266 break;
267 }
268 objectID++;
269 }
270 }
271
272 end:
273 free(em_ori.ptr);
274 return res;
275 }
276
277
278 /**
279 * Implementation of rsa_public_key_t.get_modulus.
280 */
281 static mpz_t *get_modulus(const private_rsa_public_key_t *this)
282 {
283 return (mpz_t*)&this->n;
284 }
285
286 /**
287 * Implementation of rsa_public_key_t.get_keysize.
288 */
289 static size_t get_keysize(const private_rsa_public_key_t *this)
290 {
291 return this->k;
292 }
293
294 /**
295 * Build a DER-encoded publicKeyInfo object from an RSA public key.
296 * Also used in rsa_private_key.c.
297 */
298 chunk_t rsa_public_key_info_to_asn1(const mpz_t n, const mpz_t e)
299 {
300 chunk_t publicKey = asn1_wrap(ASN1_SEQUENCE, "mm",
301 asn1_integer_from_mpz(n),
302 asn1_integer_from_mpz(e));
303
304 return asn1_wrap(ASN1_SEQUENCE, "cm",
305 asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
306 asn1_bitstring("m", publicKey));
307 }
308
309 /**
310 * Form the RSA keyid as a SHA-1 hash of a publicKeyInfo object
311 * Also used in rsa_private_key.c.
312 */
313 chunk_t rsa_public_key_id_create(mpz_t n, mpz_t e)
314 {
315 chunk_t keyid;
316 chunk_t publicKeyInfo = rsa_public_key_info_to_asn1(n, e);
317 hasher_t *hasher = hasher_create(HASH_SHA1);
318
319 hasher->allocate_hash(hasher, publicKeyInfo, &keyid);
320 hasher->destroy(hasher);
321 free(publicKeyInfo.ptr);
322
323 return keyid;
324 }
325
326 /**
327 * Implementation of rsa_public_key_t.get_publicKeyInfo.
328 */
329 static chunk_t get_publicKeyInfo(const private_rsa_public_key_t *this)
330 {
331 return rsa_public_key_info_to_asn1(this->n, this->e);
332 }
333
334 /**
335 * Implementation of rsa_public_key_t.get_keyid.
336 */
337 static chunk_t get_keyid(const private_rsa_public_key_t *this)
338 {
339 return this->keyid;
340 }
341
342 /* forward declaration used by rsa_public_key_t.clone */
343 private_rsa_public_key_t *rsa_public_key_create_empty(void);
344
345 /**
346 * Implementation of rsa_public_key_t.clone.
347 */
348 static rsa_public_key_t* _clone(const private_rsa_public_key_t *this)
349 {
350 private_rsa_public_key_t *clone = rsa_public_key_create_empty();
351
352 mpz_init_set(clone->n, this->n);
353 mpz_init_set(clone->e, this->e);
354 clone->keyid = chunk_clone(this->keyid);
355 clone->k = this->k;
356
357 return &clone->public;
358 }
359
360 /**
361 * Implementation of rsa_public_key_t.destroy.
362 */
363 static void destroy(private_rsa_public_key_t *this)
364 {
365 mpz_clear(this->n);
366 mpz_clear(this->e);
367 free(this->keyid.ptr);
368 free(this);
369 }
370
371 /**
372 * Generic private constructor
373 */
374 private_rsa_public_key_t *rsa_public_key_create_empty(void)
375 {
376 private_rsa_public_key_t *this = malloc_thing(private_rsa_public_key_t);
377
378 /* public functions */
379 this->public.verify_emsa_pkcs1_signature = (status_t (*) (const rsa_public_key_t*,hash_algorithm_t,chunk_t,chunk_t))verify_emsa_pkcs1_signature;
380 this->public.get_modulus = (mpz_t *(*) (const rsa_public_key_t*))get_modulus;
381 this->public.get_keysize = (size_t (*) (const rsa_public_key_t*))get_keysize;
382 this->public.get_publicKeyInfo = (chunk_t (*) (const rsa_public_key_t*))get_publicKeyInfo;
383 this->public.get_keyid = (chunk_t (*) (const rsa_public_key_t*))get_keyid;
384 this->public.clone = (rsa_public_key_t* (*) (const rsa_public_key_t*))_clone;
385 this->public.destroy = (void (*) (rsa_public_key_t*))destroy;
386
387 /* private functions */
388 this->rsaep = rsaep;
389 this->rsavp1 = rsaep; /* same algorithm */
390
391 return this;
392 }
393
394 /*
395 * See header
396 */
397 rsa_public_key_t *rsa_public_key_create(mpz_t n, mpz_t e)
398 {
399 private_rsa_public_key_t *this = rsa_public_key_create_empty();
400
401 mpz_init_set(this->n, n);
402 mpz_init_set(this->e, e);
403
404 this->k = (mpz_sizeinbase(n, 2) + 7) / BITS_PER_BYTE;
405 this->keyid = rsa_public_key_id_create(n, e);
406 return &this->public;
407 }
408 /*
409 * See header
410 */
411 rsa_public_key_t *rsa_public_key_create_from_chunk(chunk_t blob)
412 {
413 asn1_ctx_t ctx;
414 chunk_t object;
415 u_int level;
416 int objectID = 0;
417
418 private_rsa_public_key_t *this = rsa_public_key_create_empty();
419
420 mpz_init(this->n);
421 mpz_init(this->e);
422
423 asn1_init(&ctx, blob, 0, FALSE, FALSE);
424
425 while (objectID < PUB_KEY_ROOF)
426 {
427 if (!extract_object(pubkeyObjects, &objectID, &object, &level, &ctx))
428 {
429 destroy(this);
430 return FALSE;
431 }
432 switch (objectID)
433 {
434 case PUB_KEY_MODULUS:
435 mpz_import(this->n, object.len, 1, 1, 1, 0, object.ptr);
436 break;
437 case PUB_KEY_EXPONENT:
438 mpz_import(this->e, object.len, 1, 1, 1, 0, object.ptr);
439 break;
440 }
441 objectID++;
442 }
443
444 this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
445 this->keyid = rsa_public_key_id_create(this->n, this->e);
446 return &this->public;
447 }
448
449 /*
450 * See header
451 */
452 rsa_public_key_t *rsa_public_key_create_from_file(char *filename)
453 {
454 bool pgp = FALSE;
455 chunk_t chunk = chunk_empty;
456 rsa_public_key_t *pubkey = NULL;
457
458 if (!pem_asn1_load_file(filename, NULL, "public key", &chunk, &pgp))
459 {
460 return NULL;
461 }
462 pubkey = rsa_public_key_create_from_chunk(chunk);
463 free(chunk.ptr);
464 return pubkey;
465 }