summaryrefslogtreecommitdiff
path: root/src/libstrongswan/crypto/rsa
diff options
context:
space:
mode:
authorRene Mayrhofer <rene@mayrhofer.eu.org>2007-10-26 14:24:26 +0000
committerRene Mayrhofer <rene@mayrhofer.eu.org>2007-10-26 14:24:26 +0000
commit3168dc628f034e03bb4fab16e8a00da59a5c86e1 (patch)
tree663da4d1badc1373ec59d9bdc39f893af0cc8a75 /src/libstrongswan/crypto/rsa
parent1a144d57c8f2f08513b747078d185db688637859 (diff)
downloadvyos-strongswan-3168dc628f034e03bb4fab16e8a00da59a5c86e1.tar.gz
vyos-strongswan-3168dc628f034e03bb4fab16e8a00da59a5c86e1.zip
- Import new upstream release 4.1.8.
Diffstat (limited to 'src/libstrongswan/crypto/rsa')
-rw-r--r--src/libstrongswan/crypto/rsa/rsa_private_key.c307
-rw-r--r--src/libstrongswan/crypto/rsa/rsa_private_key.h67
-rw-r--r--src/libstrongswan/crypto/rsa/rsa_public_key.c326
-rw-r--r--src/libstrongswan/crypto/rsa/rsa_public_key.h43
4 files changed, 328 insertions, 415 deletions
diff --git a/src/libstrongswan/crypto/rsa/rsa_private_key.c b/src/libstrongswan/crypto/rsa/rsa_private_key.c
index 5b1647965..ec2f2fc74 100644
--- a/src/libstrongswan/crypto/rsa/rsa_private_key.c
+++ b/src/libstrongswan/crypto/rsa/rsa_private_key.c
@@ -19,6 +19,8 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* 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 $
*/
#include <gmp.h>
@@ -29,33 +31,21 @@
#include "rsa_public_key.h"
#include "rsa_private_key.h"
+#include <debug.h>
#include <asn1/asn1.h>
#include <asn1/pem.h>
#include <utils/randomizer.h>
/**
- * OIDs for hash algorithms are defined in rsa_public_key.c.
- */
-extern u_int8_t md2_oid[18];
-extern u_int8_t md5_oid[18];
-extern u_int8_t sha1_oid[15];
-extern u_int8_t sha256_oid[19];
-extern u_int8_t sha384_oid[19];
-extern u_int8_t sha512_oid[19];
-
-
-/**
* defined in rsa_public_key.c
*/
extern chunk_t rsa_public_key_info_to_asn1(const mpz_t n, const mpz_t e);
-
/**
* Public exponent to use for key generation.
*/
#define PUBLIC_EXPONENT 0x10001
-
typedef struct private_rsa_private_key_t private_rsa_private_key_t;
/**
@@ -153,23 +143,23 @@ struct private_rsa_private_key_t {
/* ASN.1 definition of a PKCS#1 RSA private key */
static const asn1Object_t privkey_objects[] = {
- { 0, "RSAPrivateKey", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
- { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
- { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 2 */
- { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 3 */
- { 1, "privateExponent", ASN1_INTEGER, ASN1_BODY }, /* 4 */
- { 1, "prime1", ASN1_INTEGER, ASN1_BODY }, /* 5 */
- { 1, "prime2", ASN1_INTEGER, ASN1_BODY }, /* 6 */
- { 1, "exponent1", ASN1_INTEGER, ASN1_BODY }, /* 7 */
- { 1, "exponent2", ASN1_INTEGER, ASN1_BODY }, /* 8 */
- { 1, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 9 */
- { 1, "otherPrimeInfos", ASN1_SEQUENCE, ASN1_OPT |
- ASN1_LOOP }, /* 10 */
- { 2, "otherPrimeInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */
- { 3, "prime", ASN1_INTEGER, ASN1_BODY }, /* 12 */
- { 3, "exponent", ASN1_INTEGER, ASN1_BODY }, /* 13 */
- { 3, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 14 */
- { 1, "end opt or loop", ASN1_EOC, ASN1_END } /* 15 */
+ { 0, "RSAPrivateKey", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
+ { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
+ { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 2 */
+ { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 3 */
+ { 1, "privateExponent", ASN1_INTEGER, ASN1_BODY }, /* 4 */
+ { 1, "prime1", ASN1_INTEGER, ASN1_BODY }, /* 5 */
+ { 1, "prime2", ASN1_INTEGER, ASN1_BODY }, /* 6 */
+ { 1, "exponent1", ASN1_INTEGER, ASN1_BODY }, /* 7 */
+ { 1, "exponent2", ASN1_INTEGER, ASN1_BODY }, /* 8 */
+ { 1, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 9 */
+ { 1, "otherPrimeInfos", ASN1_SEQUENCE, ASN1_OPT |
+ ASN1_LOOP }, /* 10 */
+ { 2, "otherPrimeInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */
+ { 3, "prime", ASN1_INTEGER, ASN1_BODY }, /* 12 */
+ { 3, "exponent", ASN1_INTEGER, ASN1_BODY }, /* 13 */
+ { 3, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 14 */
+ { 1, "end opt or loop", ASN1_EOC, ASN1_END } /* 15 */
};
#define PRIV_KEY_VERSION 1
@@ -186,6 +176,26 @@ static const asn1Object_t privkey_objects[] = {
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
+ */
+static void mpz_clear_randomized(mpz_t z)
+{
+ size_t len = mpz_size(z) * GMP_LIMB_BITS / BITS_PER_BYTE;
+ u_int8_t *random_bytes = alloca(len);
+
+ randomizer_t *randomizer = randomizer_create();
+
+ randomizer->get_pseudo_random_bytes(randomizer, len, random_bytes);
+
+ /* overwrite mpz_t with pseudo-random bytes before clearing it */
+ mpz_import(z, len, 1, 1, 1, 0, random_bytes);
+ mpz_clear(z);
+
+ randomizer->destroy(randomizer);
+}
+
+/**
* Implementation of private_rsa_private_key_t.compute_prime.
*/
static status_t compute_prime(private_rsa_private_key_t *this, size_t prime_size, mpz_t *prime)
@@ -216,7 +226,8 @@ static status_t compute_prime(private_rsa_private_key_t *this, size_t prime_size
/* get next prime */
mpz_nextprime (*prime, *prime);
- free(random_bytes.ptr);
+ /* free the random_bytes after overwriting them with a pseudo-random sequence */
+ chunk_free_randomized(&random_bytes);
}
/* check if it isnt too large */
while (((mpz_sizeinbase(*prime, 2) + 7) / 8) > prime_size);
@@ -251,59 +262,96 @@ static chunk_t rsadp(private_rsa_private_key_t *this, chunk_t data)
decrypted.len = this->k;
decrypted.ptr = mpz_export(NULL, NULL, 1, decrypted.len, 1, 0, t1);
- mpz_clear(t1);
- mpz_clear(t2);
+ mpz_clear_randomized(t1);
+ mpz_clear_randomized(t2);
return decrypted;
}
/**
- * Implementation of rsa_private_key.build_emsa_signature.
+ * Implementation of rsa_private_key_t.eme_pkcs1_decrypt.
*/
-static status_t build_emsa_pkcs1_signature(private_rsa_private_key_t *this, hash_algorithm_t hash_algorithm, chunk_t data, chunk_t *signature)
+static status_t pkcs1_decrypt(private_rsa_private_key_t *this,
+ chunk_t in, chunk_t *out)
+{
+ status_t status = FAILED;
+ chunk_t em, em_ori;
+
+ /* decrypt the input data */
+ em = em_ori = this->rsadp(this, in);
+
+ /* PKCS#1 v1.5 EME encryption formatting
+ * EM = 00 || 02 || PS || 00 || M
+ * PS = pseudo-random nonzero octets
+ */
+
+ /* check for magic bytes */
+ if (*(em.ptr) != 0x00 || *(em.ptr+1) != 0x02)
+ {
+ DBG1("incorrect padding - probably wrong RSA key");
+ goto end;
+ }
+ em.ptr += 2;
+ em.len -= 2;
+
+ /* the plaintext data starts after first 0x00 byte */
+ while (em.len-- > 0 && *em.ptr++ != 0x00);
+
+ if (em.len == 0)
+ {
+ DBG1("no plaintext data found");
+ goto end;
+ }
+
+ *out = chunk_clone(em);
+ status = SUCCESS;
+
+end:
+ free(em_ori.ptr);
+ return status;
+}
+
+/**
+ * Implementation of rsa_private_key_t.build_emsa_pkcs1_signature.
+ */
+static status_t build_emsa_pkcs1_signature(private_rsa_private_key_t *this,
+ hash_algorithm_t hash_algorithm,
+ chunk_t data, chunk_t *signature)
{
hasher_t *hasher;
- chunk_t hash;
- chunk_t em;
- chunk_t oid;
+ chunk_t em, digestInfo, hash_id, hash;
/* get oid string prepended to hash */
switch (hash_algorithm)
{
case HASH_MD2:
{
- oid.ptr = md2_oid;
- oid.len = sizeof(md2_oid);
+ hash_id =ASN1_md2_id;
break;
}
case HASH_MD5:
{
- oid.ptr = md5_oid;
- oid.len = sizeof(md5_oid);
+ hash_id = ASN1_md5_id;
break;
}
case HASH_SHA1:
{
- oid.ptr = sha1_oid;
- oid.len = sizeof(sha1_oid);
+ hash_id = ASN1_sha1_id;
break;
}
case HASH_SHA256:
{
- oid.ptr = sha256_oid;
- oid.len = sizeof(sha256_oid);
+ hash_id = ASN1_sha256_id;
break;
}
case HASH_SHA384:
{
- oid.ptr = sha384_oid;
- oid.len = sizeof(sha384_oid);
+ hash_id = ASN1_sha384_id;
break;
}
case HASH_SHA512:
{
- oid.ptr = sha512_oid;
- oid.len = sizeof(sha512_oid);
+ hash_id = ASN1_sha512_id;
break;
}
default:
@@ -323,10 +371,17 @@ static status_t build_emsa_pkcs1_signature(private_rsa_private_key_t *this, hash
hasher->allocate_hash(hasher, data, &hash);
hasher->destroy(hasher);
+ /* build DER-encoded digestInfo */
+ digestInfo = asn1_wrap(ASN1_SEQUENCE, "cm",
+ hash_id,
+ asn1_simple_object(ASN1_OCTET_STRING, hash)
+ );
+ chunk_free(&hash);
+
/* build chunk to rsa-decrypt:
* EM = 0x00 || 0x01 || PS || 0x00 || T.
* PS = 0xFF padding, with length to fill em
- * T = oid || hash
+ * T = encoded_hash
*/
em.len = this->k;
em.ptr = malloc(em.len);
@@ -336,78 +391,44 @@ static status_t build_emsa_pkcs1_signature(private_rsa_private_key_t *this, hash
/* set magic bytes */
*(em.ptr) = 0x00;
*(em.ptr+1) = 0x01;
- *(em.ptr + em.len - hash.len - oid.len - 1) = 0x00;
- /* set hash */
- memcpy(em.ptr + em.len - hash.len, hash.ptr, hash.len);
- /* set oid */
- memcpy(em.ptr + em.len - hash.len - oid.len, oid.ptr, oid.len);
-
+ *(em.ptr + em.len - digestInfo.len - 1) = 0x00;
+ /* set DER-encoded hash */
+ memcpy(em.ptr + em.len - digestInfo.len, digestInfo.ptr, digestInfo.len);
+
/* build signature */
*signature = this->rsasp1(this, em);
- free(hash.ptr);
+ free(digestInfo.ptr);
free(em.ptr);
return SUCCESS;
}
/**
- * Implementation of rsa_private_key.get_key.
+ * Implementation of rsa_private_key_t.pkcs1_write.
*/
-static status_t get_key(private_rsa_private_key_t *this, chunk_t *key)
-{
- chunk_t n, e, p, q, d, exp1, exp2, coeff;
-
- n.len = this->k;
- n.ptr = mpz_export(NULL, NULL, 1, n.len, 1, 0, this->n);
- e.len = this->k;
- e.ptr = mpz_export(NULL, NULL, 1, e.len, 1, 0, this->e);
- p.len = this->k;
- p.ptr = mpz_export(NULL, NULL, 1, p.len, 1, 0, this->p);
- q.len = this->k;
- q.ptr = mpz_export(NULL, NULL, 1, q.len, 1, 0, this->q);
- d.len = this->k;
- d.ptr = mpz_export(NULL, NULL, 1, d.len, 1, 0, this->d);
- exp1.len = this->k;
- exp1.ptr = mpz_export(NULL, NULL, 1, exp1.len, 1, 0, this->exp1);
- exp2.len = this->k;
- exp2.ptr = mpz_export(NULL, NULL, 1, exp2.len, 1, 0, this->exp2);
- coeff.len = this->k;
- coeff.ptr = mpz_export(NULL, NULL, 1, coeff.len, 1, 0, this->coeff);
-
- key->len = this->k * 8;
- key->ptr = malloc(key->len);
- memcpy(key->ptr + this->k * 0, n.ptr , n.len);
- memcpy(key->ptr + this->k * 1, e.ptr, e.len);
- memcpy(key->ptr + this->k * 2, p.ptr, p.len);
- memcpy(key->ptr + this->k * 3, q.ptr, q.len);
- memcpy(key->ptr + this->k * 4, d.ptr, d.len);
- memcpy(key->ptr + this->k * 5, exp1.ptr, exp1.len);
- memcpy(key->ptr + this->k * 6, exp2.ptr, exp2.len);
- memcpy(key->ptr + this->k * 7, coeff.ptr, coeff.len);
-
- free(n.ptr);
- free(e.ptr);
- free(p.ptr);
- free(q.ptr);
- free(d.ptr);
- free(exp1.ptr);
- free(exp2.ptr);
- free(coeff.ptr);
-
- return SUCCESS;
-}
-
-/**
- * Implementation of rsa_private_key.save_key.
- */
-static status_t save_key(private_rsa_private_key_t *this, char *file)
+static bool pkcs1_write(private_rsa_private_key_t *this, const char *filename, bool force)
{
- return NOT_SUPPORTED;
+ bool status;
+
+ chunk_t pkcs1 = asn1_wrap(ASN1_SEQUENCE, "cmmmmmmmm",
+ ASN1_INTEGER_0,
+ asn1_integer_from_mpz(this->n),
+ asn1_integer_from_mpz(this->e),
+ asn1_integer_from_mpz(this->d),
+ asn1_integer_from_mpz(this->p),
+ asn1_integer_from_mpz(this->q),
+ asn1_integer_from_mpz(this->exp1),
+ asn1_integer_from_mpz(this->exp2),
+ asn1_integer_from_mpz(this->coeff));
+
+ status = chunk_write(pkcs1, filename, "pkcs1", 0066, force);
+ chunk_free_randomized(&pkcs1);
+ return status;
}
/**
- * Implementation of rsa_private_key.get_public_key.
+ * Implementation of rsa_private_key_t.get_public_key.
*/
rsa_public_key_t *get_public_key(private_rsa_private_key_t *this)
{
@@ -510,47 +531,26 @@ static status_t check(private_rsa_private_key_t *this)
status = FAILED;
}
- mpz_clear(t);
- mpz_clear(u);
- mpz_clear(q1);
+ mpz_clear_randomized(t);
+ mpz_clear_randomized(u);
+ mpz_clear_randomized(q1);
return status;
}
/**
- * Implementation of rsa_private_key.clone.
- */
-static rsa_private_key_t* _clone(private_rsa_private_key_t *this)
-{
- private_rsa_private_key_t *clone = rsa_private_key_create_empty();
-
- mpz_init_set(clone->n, this->n);
- mpz_init_set(clone->e, this->e);
- mpz_init_set(clone->p, this->p);
- mpz_init_set(clone->q, this->q);
- mpz_init_set(clone->d, this->d);
- mpz_init_set(clone->exp1, this->exp1);
- mpz_init_set(clone->exp2, this->exp2);
- mpz_init_set(clone->coeff, this->coeff);
- clone->keyid = chunk_clone(this->keyid);
- clone->k = this->k;
-
- return &clone->public;
-}
-
-/**
* Implementation of rsa_private_key.destroy.
*/
static void destroy(private_rsa_private_key_t *this)
{
- mpz_clear(this->n);
- mpz_clear(this->e);
- mpz_clear(this->p);
- mpz_clear(this->q);
- mpz_clear(this->d);
- mpz_clear(this->exp1);
- mpz_clear(this->exp2);
- mpz_clear(this->coeff);
- free(this->keyid.ptr);
+ mpz_clear_randomized(this->n);
+ mpz_clear_randomized(this->e);
+ mpz_clear_randomized(this->p);
+ mpz_clear_randomized(this->q);
+ mpz_clear_randomized(this->d);
+ mpz_clear_randomized(this->exp1);
+ mpz_clear_randomized(this->exp2);
+ mpz_clear_randomized(this->coeff);
+ chunk_free_randomized(&this->keyid);
free(this);
}
@@ -562,12 +562,11 @@ static private_rsa_private_key_t *rsa_private_key_create_empty(void)
private_rsa_private_key_t *this = malloc_thing(private_rsa_private_key_t);
/* public functions */
+ this->public.pkcs1_decrypt = (status_t (*) (rsa_private_key_t*,chunk_t,chunk_t*))pkcs1_decrypt;
this->public.build_emsa_pkcs1_signature = (status_t (*) (rsa_private_key_t*,hash_algorithm_t,chunk_t,chunk_t*))build_emsa_pkcs1_signature;
- this->public.get_key = (status_t (*) (rsa_private_key_t*,chunk_t*))get_key;
- this->public.save_key = (status_t (*) (rsa_private_key_t*,char*))save_key;
- this->public.get_public_key = (rsa_public_key_t *(*) (rsa_private_key_t*))get_public_key;
+ this->public.pkcs1_write = (bool (*) (rsa_private_key_t*,const char*,bool))pkcs1_write;
+ this->public.get_public_key = (rsa_public_key_t* (*) (rsa_private_key_t*))get_public_key;
this->public.belongs_to = (bool (*) (rsa_private_key_t*,rsa_public_key_t*))belongs_to;
- this->public.clone = (rsa_private_key_t*(*)(rsa_private_key_t*))_clone;
this->public.destroy = (void (*) (rsa_private_key_t*))destroy;
/* private functions */
@@ -575,6 +574,8 @@ static private_rsa_private_key_t *rsa_private_key_create_empty(void)
this->rsasp1 = rsadp; /* same algorithm */
this->compute_prime = compute_prime;
+ this->keyid = chunk_empty;
+
return this;
}
@@ -613,9 +614,7 @@ rsa_private_key_t *rsa_private_key_create(size_t key_size)
/* Swapping Primes so p is larger then q */
if (mpz_cmp(p, q) < 0)
{
- mpz_set(t, p);
- mpz_set(p, q);
- mpz_set(q, t);
+ mpz_swap(p, q);
}
mpz_mul(n, p, q); /* n = p*q */
@@ -645,9 +644,9 @@ rsa_private_key_t *rsa_private_key_create(size_t key_size)
mpz_add(coeff, coeff, p);
}
- mpz_clear(q1);
- mpz_clear(m);
- mpz_clear(t);
+ mpz_clear_randomized(q1);
+ mpz_clear_randomized(m);
+ mpz_clear_randomized(t);
/* apply values */
*(this->p) = *p;
@@ -733,7 +732,7 @@ rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t blob)
objectID++;
}
- this->k = (mpz_sizeinbase(this->n, 2) + 7) / 8;
+ this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
/* form the keyid as a SHA-1 hash of a publicKeyInfo object */
{
@@ -769,6 +768,6 @@ rsa_private_key_t *rsa_private_key_create_from_file(char *filename, chunk_t *pas
return NULL;
key = rsa_private_key_create_from_chunk(chunk);
- free(chunk.ptr);
+ chunk_free_randomized(&chunk);
return key;
}
diff --git a/src/libstrongswan/crypto/rsa/rsa_private_key.h b/src/libstrongswan/crypto/rsa/rsa_private_key.h
index 9ec07704e..e5cf49810 100644
--- a/src/libstrongswan/crypto/rsa/rsa_private_key.h
+++ b/src/libstrongswan/crypto/rsa/rsa_private_key.h
@@ -19,6 +19,8 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* 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 $
*/
#ifndef RSA_PRIVATE_KEY_H_
@@ -42,13 +44,24 @@ typedef struct rsa_private_key_t rsa_private_key_t;
*
* @see rsa_public_key_t
*
- * @todo Implement get_key(), save_key(), get_public_key()
- *
* @ingroup rsa
*/
struct rsa_private_key_t {
/**
+ * @brief Decrypt a data block based on EME-PKCS1 encoding.
+ *
+ *
+ * @param this calling object
+ * @param data encrypted input data
+ * @param out decrypted output data
+ * @return
+ * - SUCCESS
+ * - FAILED if padding is not correct
+ */
+ status_t (*pkcs1_decrypt) (rsa_private_key_t *this, chunk_t in, chunk_t *out);
+
+ /**
* @brief Build a signature over a chunk using EMSA-PKCS1 encoding.
*
* This signature creates a hash using the specified hash algorithm, concatenates
@@ -67,45 +80,17 @@ struct rsa_private_key_t {
status_t (*build_emsa_pkcs1_signature) (rsa_private_key_t *this, hash_algorithm_t hash_algorithm, chunk_t data, chunk_t *signature);
/**
- * @brief Gets the key.
- *
- * UNIMPLEMENTED!
- *
+ * @brief Writes an RSA private key to a file in PKCS#1 format.
+ *
* @param this calling object
- * @param key key (in a propriarity format)
- * @return
- * - SUCCESS
- * - INVALID_STATE, if key not set
+ * @param filename file to which the key should be written.
+ * @param force if TRUE overwrite existing file
+ * @return TRUE if successful - FALSE otherwise
*/
- status_t (*get_key) (rsa_private_key_t *this, chunk_t *key);
+ bool (*pkcs1_write) (rsa_private_key_t *this, const char *filename, bool force);
/**
- * @brief Saves a key to a file.
- *
- * Not implemented!
- *
- * @param this calling object
- * @param file file to which the key should be written.
- * @return NOT_SUPPORTED
- */
- status_t (*save_key) (rsa_private_key_t *this, char *file);
-
- /**
- * @brief Generate a new key.
- *
- * Generates a new private_key with specified key size
- *
- * @param this calling object
- * @param key_size size of the key in bits
- * @return
- * - SUCCESS
- * - INVALID_ARG if key_size invalid
- */
- status_t (*generate_key) (rsa_private_key_t *this, size_t key_size);
-
- /**
- * @brief Create a rsa_public_key_t with the public
- * parts of the key.
+ * @brief Create a rsa_public_key_t with the public part of the key.
*
* @param this calling object
* @return public_key
@@ -125,14 +110,6 @@ struct rsa_private_key_t {
bool (*belongs_to) (rsa_private_key_t *this, rsa_public_key_t *public);
/**
- * @brief Clone the private key.
- *
- * @param this private key to clone
- * @return clone of this
- */
- rsa_private_key_t *(*clone) (rsa_private_key_t *this);
-
- /**
* @brief Destroys the private key.
*
* @param this private key to destroy
diff --git a/src/libstrongswan/crypto/rsa/rsa_public_key.c b/src/libstrongswan/crypto/rsa/rsa_public_key.c
index 38899670f..6f2158d2b 100644
--- a/src/libstrongswan/crypto/rsa/rsa_public_key.c
+++ b/src/libstrongswan/crypto/rsa/rsa_public_key.c
@@ -19,6 +19,8 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* 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 $
*/
#include <gmp.h>
@@ -29,74 +31,13 @@
#include "rsa_public_key.h"
+#include <debug.h>
#include <crypto/hashers/hasher.h>
#include <asn1/asn1.h>
#include <asn1/pem.h>
-/*
- * For simplicity, we use these predefined values for hash algorithm OIDs
- * These also contain the length of the appended hash
- * These values are also used in rsa_private_key.c.
- */
-
-const u_int8_t md2_oid[] = {
- 0x30,0x20,
- 0x30,0x0c,
- 0x06,0x08,
- 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x02,
- 0x05,0x00,
- 0x04,0x10
-};
-
-const u_int8_t md5_oid[] = {
- 0x30,0x20,
- 0x30,0x0c,
- 0x06,0x08,
- 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,
- 0x05,0x00,
- 0x04,0x10
-};
-
-const u_int8_t sha1_oid[] = {
- 0x30,0x21,
- 0x30,0x09,
- 0x06,0x05,
- 0x2b,0x0e,0x03,0x02,0x1a,
- 0x05,0x00,
- 0x04,0x14
-};
-
-const u_int8_t sha256_oid[] = {
- 0x30,0x31,
- 0x30,0x0d,
- 0x06,0x09,
- 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,
- 0x05,0x00,
- 0x04,0x20
-};
-
-const u_int8_t sha384_oid[] = {
- 0x30,0x41,
- 0x30,0x0d,
- 0x06,0x09,
- 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,
- 0x05,0x00,
- 0x04,0x30
-};
-
-const u_int8_t sha512_oid[] = {
- 0x30,0x51,
- 0x30,0x0d,
- 0x06,0x09,
- 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,
- 0x05,0x00,
- 0x04,0x40
-};
-
-#define LARGEST_HASH_OID_SIZE sizeof(sha512_oid)
-
-/* ASN.1 definition public key */
-static const asn1Object_t pubkey_objects[] = {
+/* ASN.1 definition of RSApublicKey */
+static const asn1Object_t pubkeyObjects[] = {
{ 0, "RSAPublicKey", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
{ 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 1 */
{ 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 2 */
@@ -107,6 +48,18 @@ static const asn1Object_t pubkey_objects[] = {
#define PUB_KEY_EXPONENT 2
#define PUB_KEY_ROOF 3
+/* ASN.1 definition of digestInfo */
+static const asn1Object_t digestInfoObjects[] = {
+ { 0, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
+ { 1, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 1 */
+ { 1, "digest", ASN1_OCTET_STRING, ASN1_BODY }, /* 2 */
+};
+
+#define DIGEST_INFO 0
+#define DIGEST_INFO_ALGORITHM 1
+#define DIGEST_INFO_DIGEST 2
+#define DIGEST_INFO_ROOF 3
+
typedef struct private_rsa_public_key_t private_rsa_public_key_t;
/**
@@ -186,12 +139,11 @@ static chunk_t rsaep(const private_rsa_public_key_t *this, chunk_t data)
/**
* Implementation of rsa_public_key.verify_emsa_pkcs1_signature.
*/
-static status_t verify_emsa_pkcs1_signature(const private_rsa_public_key_t *this, chunk_t data, chunk_t signature)
+static status_t verify_emsa_pkcs1_signature(const private_rsa_public_key_t *this,
+ hash_algorithm_t algorithm,
+ chunk_t data, chunk_t signature)
{
- hasher_t *hasher = NULL;
- chunk_t hash;
- chunk_t em;
- u_int8_t *pos;
+ chunk_t em_ori, em;
status_t res = FAILED;
/* remove any preceding 0-bytes from signature */
@@ -207,7 +159,7 @@ static status_t verify_emsa_pkcs1_signature(const private_rsa_public_key_t *this
}
/* unpack signature */
- em = this->rsavp1(this, signature);
+ em_ori = em = this->rsavp1(this, signature);
/* result should look like this:
* EM = 0x00 || 0x01 || PS || 0x00 || T.
@@ -216,141 +168,160 @@ static status_t verify_emsa_pkcs1_signature(const private_rsa_public_key_t *this
*/
/* check magic bytes */
- if ((*(em.ptr) != 0x00) || (*(em.ptr+1) != 0x01))
+ if (*(em.ptr) != 0x00 || *(em.ptr+1) != 0x01)
{
+ DBG2("incorrect padding - probably wrong RSA key");
goto end;
}
+ em.ptr += 2;
+ em.len -= 2;
/* find magic 0x00 */
- pos = em.ptr + 2;
- while (pos <= em.ptr + em.len)
+ while (em.len > 0)
{
- if (*pos == 0x00)
+ if (*em.ptr == 0x00)
{
/* found magic byte, stop */
- pos++;
+ em.ptr++;
+ em.len--;
break;
}
- else if (*pos != 0xFF)
+ else if (*em.ptr != 0xFF)
{
/* bad padding, decryption failed ?!*/
goto end;
}
- pos++;
+ em.ptr++;
+ em.len--;
}
- if (pos + LARGEST_HASH_OID_SIZE > em.ptr + em.len)
- {
- /* not enought room for oid compare */
- goto end;
- }
-
- if (memeq(md2_oid, pos, sizeof(md2_oid)))
- {
- hasher = hasher_create(HASH_MD2);
- pos += sizeof(md2_oid);
- }
- else if (memeq(md5_oid, pos, sizeof(md5_oid)))
+ if (em.len == 0)
{
- hasher = hasher_create(HASH_MD5);
- pos += sizeof(md5_oid);
- }
- else if (memeq(sha1_oid, pos, sizeof(sha1_oid)))
- {
- hasher = hasher_create(HASH_SHA1);
- pos += sizeof(sha1_oid);
- }
- else if (memeq(sha256_oid, pos, sizeof(sha256_oid)))
- {
- hasher = hasher_create(HASH_SHA256);
- pos += sizeof(sha256_oid);
- }
- else if (memeq(sha384_oid, pos, sizeof(sha384_oid)))
- {
- hasher = hasher_create(HASH_SHA384);
- pos += sizeof(sha384_oid);
- }
- else if (memeq(sha512_oid, pos, sizeof(sha512_oid)))
- {
- hasher = hasher_create(HASH_SHA512);
- pos += sizeof(sha512_oid);
- }
-
- if (hasher == NULL)
- {
- /* unsupported hash algorithm */
- res = NOT_SUPPORTED;;
+ /* no digestInfo found */
goto end;
}
-
- if (pos + hasher->get_hash_size(hasher) != em.ptr + em.len)
+
+ /* parse ASN.1-based digestInfo */
{
- /* bad length */
- hasher->destroy(hasher);
- goto end;
+ asn1_ctx_t ctx;
+ chunk_t object;
+ u_int level;
+ int objectID = 0;
+ hash_algorithm_t hash_algorithm = HASH_UNKNOWN;
+
+ asn1_init(&ctx, em, 0, FALSE, FALSE);
+
+ while (objectID < DIGEST_INFO_ROOF)
+ {
+ if (!extract_object(digestInfoObjects, &objectID, &object, &level, &ctx))
+ {
+ goto end;
+ }
+ switch (objectID)
+ {
+ case DIGEST_INFO:
+ if (em.len > object.len)
+ {
+ DBG1("digestInfo field in signature is followed by %u surplus bytes",
+ em.len - object.len);
+ goto end;
+ }
+ break;
+ case DIGEST_INFO_ALGORITHM:
+ {
+ int hash_oid = parse_algorithmIdentifier(object, level+1, NULL);
+
+ hash_algorithm = hasher_algorithm_from_oid(hash_oid);
+ if (hash_algorithm == HASH_UNKNOWN
+ || (algorithm != HASH_UNKNOWN && hash_algorithm != algorithm))
+ {
+ DBG1("wrong hash algorithm used in signature");
+ goto end;
+ }
+ }
+ break;
+ case DIGEST_INFO_DIGEST:
+ {
+ chunk_t hash;
+ hasher_t *hasher = hasher_create(hash_algorithm);
+
+ if (object.len != hasher->get_hash_size(hasher))
+ {
+ DBG1("hash size in signature is %u bytes instead of %u bytes",
+ object.len, hasher->get_hash_size(hasher));
+ hasher->destroy(hasher);
+ goto end;
+ }
+
+ /* build our own hash */
+ hasher->allocate_hash(hasher, data, &hash);
+ hasher->destroy(hasher);
+
+ /* compare the hashes */
+ res = memeq(object.ptr, hash.ptr, hash.len) ? SUCCESS : FAILED;
+ free(hash.ptr);
+ }
+ break;
+ default:
+ break;
+ }
+ objectID++;
+ }
}
-
- /* build our own hash */
- hasher->allocate_hash(hasher, data, &hash);
- hasher->destroy(hasher);
-
- /* compare the hashes */
- res = memeq(hash.ptr, pos, hash.len) ? SUCCESS : FAILED;
- free(hash.ptr);
end:
- free(em.ptr);
+ free(em_ori.ptr);
return res;
}
-
+
+
/**
- * Implementation of rsa_public_key.get_key.
+ * Implementation of rsa_public_key_t.get_modulus.
*/
-static status_t get_key(const private_rsa_public_key_t *this, chunk_t *key)
-{
- chunk_t n, e;
-
- n.len = this->k;
- n.ptr = mpz_export(NULL, NULL, 1, n.len, 1, 0, this->n);
- e.len = this->k;
- e.ptr = mpz_export(NULL, NULL, 1, e.len, 1, 0, this->e);
-
- key->len = this->k * 2;
- key->ptr = malloc(key->len);
- memcpy(key->ptr, n.ptr, n.len);
- memcpy(key->ptr + n.len, e.ptr, e.len);
- free(n.ptr);
- free(e.ptr);
-
- return SUCCESS;
+static mpz_t *get_modulus(const private_rsa_public_key_t *this)
+{
+ return (mpz_t*)&this->n;
}
/**
- * Implementation of rsa_public_key.save_key.
+ * Implementation of rsa_public_key_t.get_keysize.
*/
-static status_t save_key(const private_rsa_public_key_t *this, char *file)
+static size_t get_keysize(const private_rsa_public_key_t *this)
{
- return NOT_SUPPORTED;
+ return this->k;
}
/**
- * Implementation of rsa_public_key.get_modulus.
+ * Build a DER-encoded publicKeyInfo object from an RSA public key.
+ * Also used in rsa_private_key.c.
*/
-static mpz_t *get_modulus(const private_rsa_public_key_t *this)
+chunk_t rsa_public_key_info_to_asn1(const mpz_t n, const mpz_t e)
{
- return (mpz_t*)&this->n;
+ chunk_t rawKey = 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);
+
+ *pos++ = 0x00;
+ memcpy(pos, rawKey.ptr, rawKey.len);
+ free(rawKey.ptr);
+
+ return asn1_wrap(ASN1_SEQUENCE, "cm", ASN1_rsaEncryption_id,
+ publicKey);
}
/**
- * Implementation of rsa_public_key.get_keysize.
+ * Implementation of rsa_public_key_t.get_publicKeyInfo.
*/
-static size_t get_keysize(const private_rsa_public_key_t *this)
+static chunk_t get_publicKeyInfo(const private_rsa_public_key_t *this)
{
- return this->k;
+ return rsa_public_key_info_to_asn1(this->n, this->e);
}
/**
- * Implementation of rsa_public_key.get_keyid.
+ * Implementation of rsa_public_key_t.get_keyid.
*/
static chunk_t get_keyid(const private_rsa_public_key_t *this)
{
@@ -358,7 +329,7 @@ static chunk_t get_keyid(const private_rsa_public_key_t *this)
}
/**
- * Implementation of rsa_public_key.clone.
+ * Implementation of rsa_public_key_t.clone.
*/
static rsa_public_key_t* _clone(const private_rsa_public_key_t *this)
{
@@ -373,7 +344,7 @@ static rsa_public_key_t* _clone(const private_rsa_public_key_t *this)
}
/**
- * Implementation of rsa_public_key.destroy.
+ * Implementation of rsa_public_key_t.destroy.
*/
static void destroy(private_rsa_public_key_t *this)
{
@@ -391,11 +362,10 @@ 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.verify_emsa_pkcs1_signature = (status_t (*) (const rsa_public_key_t*,chunk_t,chunk_t))verify_emsa_pkcs1_signature;
- this->public.get_key = (status_t (*) (const rsa_public_key_t*,chunk_t*))get_key;
- this->public.save_key = (status_t (*) (const rsa_public_key_t*,char*))save_key;
+ 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;
+ this->public.get_publicKeyInfo = (chunk_t (*) (const rsa_public_key_t*))get_publicKeyInfo;
this->public.get_keyid = (chunk_t (*) (const rsa_public_key_t*))get_keyid;
this->public.clone = (rsa_public_key_t* (*) (const rsa_public_key_t*))_clone;
this->public.destroy = (void (*) (rsa_public_key_t*))destroy;
@@ -407,27 +377,6 @@ private_rsa_public_key_t *rsa_public_key_create_empty(void)
return this;
}
-/**
- * Build a DER-encoded publicKeyInfo object from an RSA public key.
- * Also used in rsa_private_key.c.
- */
-chunk_t rsa_public_key_info_to_asn1(const mpz_t n, const mpz_t e)
-{
- chunk_t rawKey = 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);
-
- *pos++ = 0x00;
- memcpy(pos, rawKey.ptr, rawKey.len);
- free(rawKey.ptr);
-
- return asn1_wrap(ASN1_SEQUENCE, "cm", ASN1_rsaEncryption_id,
- publicKey);
-}
-
/*
* See header
*/
@@ -447,7 +396,7 @@ rsa_public_key_t *rsa_public_key_create_from_chunk(chunk_t blob)
while (objectID < PUB_KEY_ROOF)
{
- if (!extract_object(pubkey_objects, &objectID, &object, &level, &ctx))
+ if (!extract_object(pubkeyObjects, &objectID, &object, &level, &ctx))
{
destroy(this);
return FALSE;
@@ -489,8 +438,9 @@ rsa_public_key_t *rsa_public_key_create_from_file(char *filename)
rsa_public_key_t *pubkey = NULL;
if (!pem_asn1_load_file(filename, NULL, "public key", &chunk, &pgp))
+ {
return NULL;
-
+ }
pubkey = rsa_public_key_create_from_chunk(chunk);
free(chunk.ptr);
return pubkey;
diff --git a/src/libstrongswan/crypto/rsa/rsa_public_key.h b/src/libstrongswan/crypto/rsa/rsa_public_key.h
index 1ee54dcc3..0a40c2204 100644
--- a/src/libstrongswan/crypto/rsa/rsa_public_key.h
+++ b/src/libstrongswan/crypto/rsa/rsa_public_key.h
@@ -19,6 +19,8 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* 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 $
*/
#ifndef RSA_PUBLIC_KEY_H_
@@ -29,6 +31,7 @@ typedef struct rsa_public_key_t rsa_public_key_t;
#include <gmp.h>
#include <library.h>
+#include <crypto/hashers/hasher.h>
/**
* @brief RSA public key with associated functions.
@@ -58,6 +61,7 @@ struct rsa_public_key_t {
*
* @param this rsa_public_key to use
* @param data data to sign
+ # @param algorithm hash algorithm the signature is based on
* @param signature signature to verify
* @return
* - SUCCESS, if signature ok
@@ -66,34 +70,9 @@ struct rsa_public_key_t {
* - INVALID_ARG, if signature is not a signature
* - FAILED if signature invalid or unable to verify
*/
- status_t (*verify_emsa_pkcs1_signature) (const rsa_public_key_t *this, chunk_t data, chunk_t signature);
-
- /**
- * @brief Gets the key.
- *
- * Currently uses a proprietary format which is only inteded
- * for testing. This should be replaced with a proper
- * ASN1 encoded key format, when charon gets the ASN1
- * capabilities.
- *
- * @param this calling object
- * @param key key (in a propriarity format)
- * @return
- * - SUCCESS
- * - INVALID_STATE, if key not set
- */
- status_t (*get_key) (const rsa_public_key_t *this, chunk_t *key);
-
- /**
- * @brief Saves a key to a file.
- *
- * Not implemented!
- *
- * @param this calling object
- * @param file file to which the key should be written.
- * @return NOT_SUPPORTED
- */
- status_t (*save_key) (const rsa_public_key_t *this, char *file);
+ status_t (*verify_emsa_pkcs1_signature) (const rsa_public_key_t *this,
+ hash_algorithm_t algorithm,
+ chunk_t data, chunk_t signature);
/**
* @brief Get the modulus of the key.
@@ -112,6 +91,14 @@ struct rsa_public_key_t {
size_t (*get_keysize) (const rsa_public_key_t *this);
/**
+ * @brief Get the DER encoded publicKeyInfo object.
+ *
+ * @param this calling object
+ * @return DER encoded publicKeyInfo object
+ */
+ chunk_t (*get_publicKeyInfo) (const rsa_public_key_t *this);
+
+ /**
* @brief Get the keyid formed as the SHA-1 hash of a publicKeyInfo object.
*
* @param this calling object