2 * @file rsa_public_key.c
4 * @brief Implementation of rsa_public_key_t.
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 #include "rsa_public_key.h"
28 #include <utils/allocator.h>
29 #include <transforms/hashers/hasher.h>
31 /* since we don't have an ASN1 parser/generator,
32 * we use these predefined values for
33 * hash algorithm oids. These also contain
34 * the length of the following hash.
35 * These values are also used in rsa_private_key.c
38 u_int8_t md2_oid
[18] = {
39 0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,
40 0x48,0x86,0xf7,0x0d,0x02,0x02,0x05,0x00,
44 u_int8_t md5_oid
[] = {
45 0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,
46 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,
50 u_int8_t sha1_oid
[] = {
51 0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,
52 0x03,0x02,0x1a,0x05,0x00,0x04,0x14
55 u_int8_t sha256_oid
[] = {
56 0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,
57 0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,
61 u_int8_t sha384_oid
[] = {
62 0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,
63 0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,
67 u_int8_t sha512_oid
[] = {
68 0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,
69 0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,
74 typedef struct private_rsa_public_key_t private_rsa_public_key_t
;
77 * private data structure with signing context.
79 struct private_rsa_public_key_t
{
81 * Public interface for this signer.
83 rsa_public_key_t
public;
86 * is the key already set ?
105 * @brief Implements the RSAEP algorithm specified in PKCS#1.
107 chunk_t (*rsaep
) (private_rsa_public_key_t
*this, chunk_t data
);
110 * @brief Implements the RSASVP1 algorithm specified in PKCS#1.
112 chunk_t (*rsavp1
) (private_rsa_public_key_t
*this, chunk_t data
);
116 * Implements private_rsa_public_key_t.rsadp
117 * Implements private_rsa_public_key_t.rsavp1
119 static chunk_t
rsaep(private_rsa_public_key_t
*this, chunk_t data
)
127 mpz_import(m
, data
.len
, 1, 1, 1, 0, data
.ptr
);
129 mpz_powm(c
, m
, this->e
, this->n
);
131 encrypted
.len
= this->k
;
132 encrypted
.ptr
= mpz_export(NULL
, NULL
, 1, encrypted
.len
, 1, 0, c
);
141 * implementation of rsa_public_key.verify_emsa_signature.
143 static status_t
verify_emsa_pkcs1_signature(private_rsa_public_key_t
*this, chunk_t data
, chunk_t signature
)
145 hasher_t
*hasher
= NULL
;
150 if(!this->is_key_set
)
152 return INVALID_STATE
;
155 if (signature
.len
> this->k
)
160 /* unpack signature */
161 em
= this->rsavp1(this, signature
);
163 /* result should look like this:
164 * EM = 0x00 || 0x01 || PS || 0x00 || T.
165 * PS = 0xFF padding, with length to fill em
169 /* check magic bytes */
170 if ((*(em
.ptr
) != 0x00) ||
171 (*(em
.ptr
+1) != 0x01))
173 allocator_free(em
.ptr
);
177 /* find magic 0x00 */
179 while (pos
<= em
.ptr
+ em
.len
)
183 /* found magic byte, stop */
187 else if (*pos
!= 0xFF)
189 /* bad padding, decryption failed ?!*/
190 allocator_free(em
.ptr
);
196 if (pos
+ 20 > em
.ptr
+ em
.len
)
198 /* not enought room for oid compare */
199 allocator_free(em
.ptr
);
203 if (memcmp(md2_oid
, pos
, sizeof(md2_oid
)) == 0)
205 hasher
= hasher_create(HASH_MD2
);
206 pos
+= sizeof(md2_oid
);
208 else if (memcmp(md5_oid
, pos
, sizeof(md5_oid
)) == 0)
210 hasher
= hasher_create(HASH_MD5
);
211 pos
+= sizeof(md5_oid
);
213 else if (memcmp(sha1_oid
, pos
, sizeof(sha1_oid
)) == 0)
215 hasher
= hasher_create(HASH_SHA1
);
216 pos
+= sizeof(sha1_oid
);
218 else if (memcmp(sha256_oid
, pos
, sizeof(sha256_oid
)) == 0)
220 hasher
= hasher_create(HASH_SHA256
);
221 pos
+= sizeof(sha256_oid
);
223 else if (memcmp(sha384_oid
, pos
, sizeof(sha384_oid
)) == 0)
225 hasher
= hasher_create(HASH_SHA384
);
226 pos
+= sizeof(sha384_oid
);
228 else if (memcmp(sha512_oid
, pos
, sizeof(sha512_oid
)) == 0)
230 hasher
= hasher_create(HASH_SHA512
);
231 pos
+= sizeof(sha512_oid
);
236 /* not supported hash algorithm */
237 allocator_free(em
.ptr
);
238 return NOT_SUPPORTED
;
241 if (pos
+ hasher
->get_block_size(hasher
) != em
.ptr
+ em
.len
)
244 allocator_free(em
.ptr
);
245 hasher
->destroy(hasher
);
249 /* build own hash for a compare */
250 hasher
->allocate_hash(hasher
, data
, &hash
);
251 hasher
->destroy(hasher
);
253 if (memcmp(hash
.ptr
, pos
, hash
.len
) != 0)
255 /* hash does not equal */
256 allocator_free(hash
.ptr
);
257 allocator_free(em
.ptr
);
263 allocator_free(hash
.ptr
);
264 allocator_free(em
.ptr
);
269 * implementation of rsa_public_key.set_key.
271 static status_t
set_key(private_rsa_public_key_t
*this, chunk_t key
)
278 e
.ptr
= key
.ptr
+ n
.len
;
280 mpz_import(this->n
, n
.len
, 1, 1, 1, 0, n
.ptr
);
281 mpz_import(this->e
, n
.len
, 1, 1, 1, 0, e
.ptr
);
285 this->is_key_set
= TRUE
;
292 * implementation of rsa_public_key.get_key.
294 static status_t
get_key(private_rsa_public_key_t
*this, chunk_t
*key
)
296 if (!this->is_key_set
)
298 return INVALID_STATE
;
304 n
.ptr
= mpz_export(NULL
, NULL
, 1, n
.len
, 1, 0, this->n
);
306 e
.ptr
= mpz_export(NULL
, NULL
, 1, e
.len
, 1, 0, this->e
);
308 key
->len
= this->k
* 2;
309 key
->ptr
= allocator_alloc(key
->len
);
310 memcpy(key
->ptr
, n
.ptr
, n
.len
);
311 memcpy(key
->ptr
+ n
.len
, e
.ptr
, e
.len
);
312 allocator_free(n
.ptr
);
313 allocator_free(e
.ptr
);
319 * implementation of rsa_public_key.load_key.
321 static status_t
load_key(private_rsa_public_key_t
*this, char *file
)
323 return NOT_SUPPORTED
;
327 * implementation of rsa_public_key.save_key.
329 static status_t
save_key(private_rsa_public_key_t
*this, char *file
)
331 return NOT_SUPPORTED
;
335 * implementation of rsa_public_key.destroy.
337 static void destroy(private_rsa_public_key_t
*this)
339 if (this->is_key_set
)
344 allocator_free(this);
348 * Described in header
350 rsa_public_key_t
*rsa_public_key_create()
352 private_rsa_public_key_t
*this = allocator_alloc_thing(private_rsa_public_key_t
);
354 /* public functions */
355 this->public.verify_emsa_pkcs1_signature
= (status_t (*) (rsa_public_key_t
*,chunk_t
,chunk_t
))verify_emsa_pkcs1_signature
;
356 this->public.set_key
= (status_t (*) (rsa_public_key_t
*,chunk_t
))set_key
;
357 this->public.get_key
= (status_t (*) (rsa_public_key_t
*,chunk_t
*))get_key
;
358 this->public.load_key
= (status_t (*) (rsa_public_key_t
*,char*))load_key
;
359 this->public.save_key
= (status_t (*) (rsa_public_key_t
*,char*))save_key
;
360 this->public.destroy
= (void (*) (rsa_public_key_t
*))destroy
;
362 /* private functions */
364 this->rsavp1
= rsaep
; /* same algorithm */
366 this->is_key_set
= FALSE
;
368 return &(this->public);