diff options
Diffstat (limited to 'src/libstrongswan/crypto/rsa')
-rw-r--r-- | src/libstrongswan/crypto/rsa/rsa_private_key.c | 123 | ||||
-rw-r--r-- | src/libstrongswan/crypto/rsa/rsa_private_key.h | 6 | ||||
-rw-r--r-- | src/libstrongswan/crypto/rsa/rsa_public_key.c | 117 | ||||
-rw-r--r-- | src/libstrongswan/crypto/rsa/rsa_public_key.h | 40 |
4 files changed, 164 insertions, 122 deletions
diff --git a/src/libstrongswan/crypto/rsa/rsa_private_key.c b/src/libstrongswan/crypto/rsa/rsa_private_key.c index ec2f2fc74..1b1499887 100644 --- a/src/libstrongswan/crypto/rsa/rsa_private_key.c +++ b/src/libstrongswan/crypto/rsa/rsa_private_key.c @@ -6,8 +6,10 @@ */ /* - * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2007-2008 Andreas Steffen + * * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -20,7 +22,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: rsa_private_key.c 3306 2007-10-17 02:55:53Z andreas $ + * RCSID $Id: rsa_private_key.c 3429 2008-01-27 20:59:22Z andreas $ */ #include <gmp.h> @@ -40,6 +42,7 @@ * defined in rsa_public_key.c */ extern chunk_t rsa_public_key_info_to_asn1(const mpz_t n, const mpz_t e); +extern chunk_t rsa_public_key_id_create(const mpz_t n, const mpz_t e); /** * Public exponent to use for key generation. @@ -111,7 +114,6 @@ struct private_rsa_private_key_t { * Keyid formed as a SHA-1 hash of a publicKeyInfo object */ chunk_t keyid; - /** * @brief Implements the RSADP algorithm specified in PKCS#1. @@ -129,16 +131,6 @@ struct private_rsa_private_key_t { * @return processed data */ chunk_t (*rsasp1) (private_rsa_private_key_t *this, chunk_t data); - - /** - * @brief Generate a prime value. - * - * @param this calling object - * @param prime_size size of the prime, in bytes - * @param[out] prime uninitialized mpz - */ - status_t (*compute_prime) (private_rsa_private_key_t *this, size_t prime_size, mpz_t *prime); - }; /* ASN.1 definition of a PKCS#1 RSA private key */ @@ -173,8 +165,6 @@ static const asn1Object_t privkey_objects[] = { #define PRIV_KEY_COEFF 9 #define PRIV_KEY_ROOF 16 -static private_rsa_private_key_t *rsa_private_key_create_empty(void); - /** * Auxiliary function overwriting private key material with * pseudo-random bytes before releasing it @@ -196,9 +186,9 @@ static void mpz_clear_randomized(mpz_t z) } /** - * Implementation of private_rsa_private_key_t.compute_prime. + * Generate a random prime number with prime_len bytes */ -static status_t compute_prime(private_rsa_private_key_t *this, size_t prime_size, mpz_t *prime) +static status_t compute_prime(private_rsa_private_key_t *this, size_t prime_len, mpz_t *prime) { randomizer_t *randomizer; chunk_t random_bytes; @@ -209,7 +199,8 @@ static status_t compute_prime(private_rsa_private_key_t *this, size_t prime_size do { - status = randomizer->allocate_random_bytes(randomizer, prime_size, &random_bytes); + DBG1(" generating %d bit prime from %s ...", BITS_PER_BYTE * prime_len, DEV_RANDOM); + status = randomizer->allocate_random_bytes(randomizer, prime_len, &random_bytes); if (status != SUCCESS) { randomizer->destroy(randomizer); @@ -230,7 +221,7 @@ static status_t compute_prime(private_rsa_private_key_t *this, size_t prime_size chunk_free_randomized(&random_bytes); } /* check if it isnt too large */ - while (((mpz_sizeinbase(*prime, 2) + 7) / 8) > prime_size); + while (((mpz_sizeinbase(*prime, 2) + 7) / BITS_PER_BYTE) > prime_len); randomizer->destroy(randomizer); return SUCCESS; @@ -269,7 +260,7 @@ static chunk_t rsadp(private_rsa_private_key_t *this, chunk_t data) } /** - * Implementation of rsa_private_key_t.eme_pkcs1_decrypt. + * Implementation of rsa_private_key_t.pkcs1_decrypt. */ static status_t pkcs1_decrypt(private_rsa_private_key_t *this, chunk_t in, chunk_t *out) @@ -319,47 +310,14 @@ static status_t build_emsa_pkcs1_signature(private_rsa_private_key_t *this, chunk_t data, chunk_t *signature) { hasher_t *hasher; - chunk_t em, digestInfo, hash_id, hash; - - /* get oid string prepended to hash */ - switch (hash_algorithm) - { - case HASH_MD2: - { - hash_id =ASN1_md2_id; - break; - } - case HASH_MD5: - { - hash_id = ASN1_md5_id; - break; - } - case HASH_SHA1: - { - hash_id = ASN1_sha1_id; - break; - } - case HASH_SHA256: - { - hash_id = ASN1_sha256_id; - break; - } - case HASH_SHA384: - { - hash_id = ASN1_sha384_id; - break; - } - case HASH_SHA512: - { - hash_id = ASN1_sha512_id; - break; - } - default: - { - return NOT_SUPPORTED; - } + chunk_t em, digestInfo, hash; + int hash_oid = hasher_algorithm_to_oid(hash_algorithm); + + if (hash_oid == OID_UNKNOWN) + { + return NOT_SUPPORTED; } - + /* get hasher */ hasher = hasher_create(hash_algorithm); if (hasher == NULL) @@ -373,7 +331,7 @@ static status_t build_emsa_pkcs1_signature(private_rsa_private_key_t *this, /* build DER-encoded digestInfo */ digestInfo = asn1_wrap(ASN1_SEQUENCE, "cm", - hash_id, + asn1_algorithmIdentifier(hash_oid), asn1_simple_object(ASN1_OCTET_STRING, hash) ); chunk_free(&hash); @@ -432,7 +390,7 @@ static bool pkcs1_write(private_rsa_private_key_t *this, const char *filename, b */ rsa_public_key_t *get_public_key(private_rsa_private_key_t *this) { - return NULL; + return rsa_public_key_create(this->n, this->e); } /** @@ -455,13 +413,13 @@ static status_t check(private_rsa_private_key_t *this) /* PKCS#1 1.5 section 6 requires modulus to have at least 12 octets. * We actually require more (for security). */ - if (this->k < 512/8) + if (this->k < 512 / BITS_PER_BYTE) { return FAILED; } /* we picked a max modulus size to simplify buffer allocation */ - if (this->k > 8192/8) + if (this->k > 8192 / BITS_PER_BYTE) { return FAILED; } @@ -572,7 +530,6 @@ static private_rsa_private_key_t *rsa_private_key_create_empty(void) /* private functions */ this->rsadp = rsadp; this->rsasp1 = rsadp; /* same algorithm */ - this->compute_prime = compute_prime; this->keyid = chunk_empty; @@ -587,20 +544,17 @@ rsa_private_key_t *rsa_private_key_create(size_t key_size) mpz_t p, q, n, e, d, exp1, exp2, coeff; mpz_t m, q1, t; private_rsa_private_key_t *this; - - this = rsa_private_key_create_empty(); - key_size = key_size / 8; + size_t key_len = key_size / BITS_PER_BYTE; + size_t prime_len = key_len / 2; /* Get values of primes p and q */ - if (this->compute_prime(this, key_size/2, &p) != SUCCESS) + if (compute_prime(this, prime_len, &p) != SUCCESS) { - free(this); return NULL; } - if (this->compute_prime(this, key_size/2, &q) != SUCCESS) + if (compute_prime(this, prime_len, &q) != SUCCESS) { mpz_clear(p); - free(this); return NULL; } @@ -648,7 +602,13 @@ rsa_private_key_t *rsa_private_key_create(size_t key_size) mpz_clear_randomized(m); mpz_clear_randomized(t); - /* apply values */ + /* determine exact the modulus size in bits */ + key_size = mpz_sizeinbase(n, 2); + + /* create and fill in rsa_private_key_t object */ + this = rsa_private_key_create_empty(); + this->k = (key_size + 7) / BITS_PER_BYTE; + this->keyid = rsa_public_key_id_create(n, e); *(this->p) = *p; *(this->q) = *q; *(this->n) = *n; @@ -657,10 +617,8 @@ rsa_private_key_t *rsa_private_key_create(size_t key_size) *(this->exp1) = *exp1; *(this->exp2) = *exp2; *(this->coeff) = *coeff; - - /* set key size in bytes */ - this->k = key_size; - + DBG1("generated %d bit RSA key with keyid: %#B", key_size, &this->keyid); + return &this->public; } @@ -733,17 +691,8 @@ rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t blob) } this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE; + this->keyid = rsa_public_key_id_create(this->n, this->e); - /* form the keyid as a SHA-1 hash of a publicKeyInfo object */ - { - chunk_t publicKeyInfo = rsa_public_key_info_to_asn1(this->n, this->e); - hasher_t *hasher = hasher_create(HASH_SHA1); - - hasher->allocate_hash(hasher, publicKeyInfo, &this->keyid); - hasher->destroy(hasher); - free(publicKeyInfo.ptr); - } - if (check(this) != SUCCESS) { destroy(this); diff --git a/src/libstrongswan/crypto/rsa/rsa_private_key.h b/src/libstrongswan/crypto/rsa/rsa_private_key.h index e5cf49810..8013f03c2 100644 --- a/src/libstrongswan/crypto/rsa/rsa_private_key.h +++ b/src/libstrongswan/crypto/rsa/rsa_private_key.h @@ -6,8 +6,10 @@ */ /* - * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2007-2008 Andreas Steffen + * * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -20,7 +22,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: rsa_private_key.h 3296 2007-10-12 15:23:29Z andreas $ + * RCSID $Id: rsa_private_key.h 3423 2008-01-22 10:32:37Z andreas $ */ #ifndef RSA_PRIVATE_KEY_H_ diff --git a/src/libstrongswan/crypto/rsa/rsa_public_key.c b/src/libstrongswan/crypto/rsa/rsa_public_key.c index 6f2158d2b..10af0527e 100644 --- a/src/libstrongswan/crypto/rsa/rsa_public_key.c +++ b/src/libstrongswan/crypto/rsa/rsa_public_key.c @@ -6,8 +6,10 @@ */ /* - * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2007-2008 Andreas Steffen + * * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -20,7 +22,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: rsa_public_key.c 3303 2007-10-12 22:49:39Z andreas $ + * RCSID $Id: rsa_public_key.c 3428 2008-01-27 20:58:52Z andreas $ */ #include <gmp.h> @@ -32,6 +34,7 @@ #include "rsa_public_key.h" #include <debug.h> +#include <utils/randomizer.h> #include <crypto/hashers/hasher.h> #include <asn1/asn1.h> #include <asn1/pem.h> @@ -110,8 +113,6 @@ struct private_rsa_public_key_t { chunk_t (*rsavp1) (const private_rsa_public_key_t *this, chunk_t data); }; -private_rsa_public_key_t *rsa_public_key_create_empty(void); - /** * Implementation of private_rsa_public_key_t.rsaep and private_rsa_public_key_t.rsavp1 */ @@ -137,6 +138,55 @@ static chunk_t rsaep(const private_rsa_public_key_t *this, chunk_t data) } /** + * Implementation of rsa_public_key_t.eme_pkcs1_encrypt. + */ +static status_t pkcs1_encrypt(private_rsa_public_key_t *this, + chunk_t in, chunk_t *out) +{ + chunk_t em; + u_char *pos; + int padding = this->k - in.len - 3; + + if (padding < 8) + { + DBG1("rsa padding of %d bytes is too small", padding); + return FAILED; + } + em.len = this->k; + em.ptr = pos = malloc(em.len); + + /* add padding according to PKCS#1 7.2.1 1.+2. */ + *pos++ = 0x00; + *pos++ = 0x02; + + /* pad with pseudo random bytes unequal to zero */ + { + randomizer_t *randomizer = randomizer_create(); + + /* pad with pseudo random bytes unequal to zero */ + while (padding--) + { + randomizer->get_pseudo_random_bytes(randomizer, 1, pos); + while (!*pos) + { + randomizer->get_pseudo_random_bytes(randomizer, 1, pos); + } + pos++; + } + randomizer->destroy(randomizer); + } + + /* append the padding terminator */ + *pos++ = 0x00; + + /* now add the data */ + memcpy(pos, in.ptr, in.len); + *out = this->rsaep(this, em); + free(em.ptr); + return SUCCESS; +} + +/** * Implementation of rsa_public_key.verify_emsa_pkcs1_signature. */ static status_t verify_emsa_pkcs1_signature(const private_rsa_public_key_t *this, @@ -297,19 +347,30 @@ static size_t get_keysize(const private_rsa_public_key_t *this) */ chunk_t rsa_public_key_info_to_asn1(const mpz_t n, const mpz_t e) { - chunk_t rawKey = asn1_wrap(ASN1_SEQUENCE, "mm", + chunk_t publicKey = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_integer_from_mpz(n), asn1_integer_from_mpz(e)); - chunk_t publicKey; - u_char *pos = build_asn1_object(&publicKey, ASN1_BIT_STRING, 1 + rawKey.len); + return asn1_wrap(ASN1_SEQUENCE, "cm", + asn1_algorithmIdentifier(OID_RSA_ENCRYPTION), + asn1_bitstring("m", publicKey)); +} - *pos++ = 0x00; - memcpy(pos, rawKey.ptr, rawKey.len); - free(rawKey.ptr); +/** + * Form the RSA keyid as a SHA-1 hash of a publicKeyInfo object + * Also used in rsa_private_key.c. + */ +chunk_t rsa_public_key_id_create(mpz_t n, mpz_t e) +{ + chunk_t keyid; + chunk_t publicKeyInfo = rsa_public_key_info_to_asn1(n, e); + hasher_t *hasher = hasher_create(HASH_SHA1); + + hasher->allocate_hash(hasher, publicKeyInfo, &keyid); + hasher->destroy(hasher); + free(publicKeyInfo.ptr); - return asn1_wrap(ASN1_SEQUENCE, "cm", ASN1_rsaEncryption_id, - publicKey); + return keyid; } /** @@ -328,6 +389,9 @@ static chunk_t get_keyid(const private_rsa_public_key_t *this) return this->keyid; } +/* forward declaration used by rsa_public_key_t.clone */ +private_rsa_public_key_t *rsa_public_key_create_empty(void); + /** * Implementation of rsa_public_key_t.clone. */ @@ -362,6 +426,7 @@ private_rsa_public_key_t *rsa_public_key_create_empty(void) private_rsa_public_key_t *this = malloc_thing(private_rsa_public_key_t); /* public functions */ + this->public.pkcs1_encrypt = (status_t (*) (rsa_public_key_t*,chunk_t,chunk_t*))pkcs1_encrypt; this->public.verify_emsa_pkcs1_signature = (status_t (*) (const rsa_public_key_t*,hash_algorithm_t,chunk_t,chunk_t))verify_emsa_pkcs1_signature; this->public.get_modulus = (mpz_t *(*) (const rsa_public_key_t*))get_modulus; this->public.get_keysize = (size_t (*) (const rsa_public_key_t*))get_keysize; @@ -380,6 +445,20 @@ private_rsa_public_key_t *rsa_public_key_create_empty(void) /* * See header */ +rsa_public_key_t *rsa_public_key_create(mpz_t n, mpz_t e) +{ + private_rsa_public_key_t *this = rsa_public_key_create_empty(); + + mpz_init_set(this->n, n); + mpz_init_set(this->e, e); + + this->k = (mpz_sizeinbase(n, 2) + 7) / BITS_PER_BYTE; + this->keyid = rsa_public_key_id_create(n, e); + return &this->public; +} +/* + * See header + */ rsa_public_key_t *rsa_public_key_create_from_chunk(chunk_t blob) { asn1_ctx_t ctx; @@ -412,19 +491,9 @@ rsa_public_key_t *rsa_public_key_create_from_chunk(chunk_t blob) } objectID++; } - - this->k = (mpz_sizeinbase(this->n, 2) + 7) / 8; - - /* form the keyid as a SHA-1 hash of a publicKeyInfo object */ - { - chunk_t publicKeyInfo = rsa_public_key_info_to_asn1(this->n, this->e); - hasher_t *hasher = hasher_create(HASH_SHA1); - - hasher->allocate_hash(hasher, publicKeyInfo, &this->keyid); - hasher->destroy(hasher); - free(publicKeyInfo.ptr); - } + this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE; + this->keyid = rsa_public_key_id_create(this->n, this->e); return &this->public; } diff --git a/src/libstrongswan/crypto/rsa/rsa_public_key.h b/src/libstrongswan/crypto/rsa/rsa_public_key.h index 0a40c2204..c0bd3e351 100644 --- a/src/libstrongswan/crypto/rsa/rsa_public_key.h +++ b/src/libstrongswan/crypto/rsa/rsa_public_key.h @@ -6,8 +6,10 @@ */ /* - * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2007-2008 Andreas Steffen + * * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -20,7 +22,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: rsa_public_key.h 3303 2007-10-12 22:49:39Z andreas $ + * RCSID $Id: rsa_public_key.h 3423 2008-01-22 10:32:37Z andreas $ */ #ifndef RSA_PUBLIC_KEY_H_ @@ -40,20 +42,29 @@ typedef struct rsa_public_key_t rsa_public_key_t; * the EMSA encoding (see PKCS1) * * @b Constructors: + * - rsa_public_key_create() * - rsa_public_key_create_from_chunk() * - rsa_public_key_create_from_file() - * - rsa_private_key_t.get_public_key() - * - * @see rsa_private_key_t - * - * @todo Implement getkey() and savekey() - * + * * @ingroup rsa */ struct rsa_public_key_t { /** - * @brief Verify a EMSA-PKCS1 encodined signature. + * @brief Encrypt a data block using EME-PKCS1 encoding. + * + * + * @param this calling object + * @param data plaintext input data + * @param out encrypted output data + * @return + * - SUCCESS + * - FAILED if data block is too large + */ + status_t (*pkcs1_encrypt) (rsa_public_key_t *this, chunk_t in, chunk_t *out); + + /** + * @brief Verify an EMSA-PKCS1 encoded signature. * * Processes the supplied signature with the RSAVP1 function, * selects the hash algorithm form the resultign ASN1-OID and @@ -123,6 +134,17 @@ struct rsa_public_key_t { }; /** + * @brief Create a RSA public key from modulus and public exponent. + * + * @param n modulus + * @param e public exponent + * @return created rsa_public_key_t + * + * @ingroup rsa + */ +rsa_public_key_t *rsa_public_key_create(mpz_t n, mpz_t e); + +/** * @brief Load an RSA public key from a chunk. * * Load a key from a chunk, encoded in the more frequently |