aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstrongswan/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/plugins')
-rw-r--r--src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c281
-rw-r--r--src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c253
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c66
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c30
-rw-r--r--src/libstrongswan/plugins/x509/x509_cert.c29
5 files changed, 546 insertions, 113 deletions
diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
index e3244ccbf..bfe9d3cdd 100644
--- a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
+++ b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
@@ -26,6 +26,7 @@
#include <asn1/oid.h>
#include <asn1/asn1.h>
#include <asn1/asn1_parser.h>
+#include <pgp/pgp.h>
/**
* Public exponent to use for key generation.
@@ -110,11 +111,12 @@ struct private_gmp_rsa_private_key_t {
};
/**
- * shared functions, implemented in gmp_rsa_public_key.c
+ * Shared functions defined in gmp_rsa_public_key.c
*/
-bool gmp_rsa_public_key_build_id(mpz_t n, mpz_t e, identification_t **keyid,
- identification_t **keyid_info);
-gmp_rsa_public_key_t *gmp_rsa_public_key_create_from_n_e(mpz_t n, mpz_t e);
+extern bool gmp_rsa_public_key_build_id(mpz_t n, mpz_t e,
+ identification_t **keyid,
+ identification_t **keyid_info);
+extern gmp_rsa_public_key_t *gmp_rsa_public_key_create_from_n_e(mpz_t n, mpz_t e);
/**
* Auxiliary function overwriting private key material with zero bytes
@@ -215,32 +217,36 @@ static bool build_emsa_pkcs1_signature(private_gmp_rsa_private_key_t *this,
hash_algorithm_t hash_algorithm,
chunk_t data, chunk_t *signature)
{
- hasher_t *hasher;
- chunk_t em, digestInfo, hash;
- int hash_oid = hasher_algorithm_to_oid(hash_algorithm);
-
- if (hash_oid == OID_UNKNOWN)
- {
- return FALSE;
- }
+ chunk_t digestInfo = chunk_empty;
+ chunk_t em;
- /* get hasher */
- hasher = lib->crypto->create_hasher(lib->crypto, hash_algorithm);
- if (hasher == NULL)
+ if (hash_algorithm != HASH_UNKNOWN)
{
- return FALSE;
- }
+ hasher_t *hasher;
+ chunk_t hash;
+ int hash_oid = hasher_algorithm_to_oid(hash_algorithm);
- /* build hash */
- hasher->allocate_hash(hasher, data, &hash);
- hasher->destroy(hasher);
+ if (hash_oid == OID_UNKNOWN)
+ {
+ return FALSE;
+ }
+
+ hasher = lib->crypto->create_hasher(lib->crypto, hash_algorithm);
+ if (hasher == NULL)
+ {
+ return FALSE;
+ }
+ hasher->allocate_hash(hasher, data, &hash);
+ hasher->destroy(hasher);
- /* build DER-encoded digestInfo */
- digestInfo = asn1_wrap(ASN1_SEQUENCE, "cm",
- asn1_algorithmIdentifier(hash_oid),
- asn1_simple_object(ASN1_OCTET_STRING, hash)
- );
- chunk_free(&hash);
+ /* build DER-encoded digestInfo */
+ digestInfo = asn1_wrap(ASN1_SEQUENCE, "cm",
+ asn1_algorithmIdentifier(hash_oid),
+ asn1_simple_object(ASN1_OCTET_STRING, hash)
+ );
+ chunk_free(&hash);
+ data = digestInfo;
+ }
/* build chunk to rsa-decrypt:
* EM = 0x00 || 0x01 || PS || 0x00 || T.
@@ -255,9 +261,9 @@ static bool build_emsa_pkcs1_signature(private_gmp_rsa_private_key_t *this,
/* set magic bytes */
*(em.ptr) = 0x00;
*(em.ptr+1) = 0x01;
- *(em.ptr + em.len - digestInfo.len - 1) = 0x00;
+ *(em.ptr + em.len - data.len - 1) = 0x00;
/* set DER-encoded hash */
- memcpy(em.ptr + em.len - digestInfo.len, digestInfo.ptr, digestInfo.len);
+ memcpy(em.ptr + em.len - data.len, data.ptr, data.len);
/* build signature */
*signature = rsasp1(this, em);
@@ -269,7 +275,7 @@ static bool build_emsa_pkcs1_signature(private_gmp_rsa_private_key_t *this,
}
/**
- * Implementation of gmp_rsa_private_key.destroy.
+ * Implementation of gmp_rsa_private_key.get_type.
*/
static key_type_t get_type(private_gmp_rsa_private_key_t *this)
{
@@ -277,15 +283,16 @@ static key_type_t get_type(private_gmp_rsa_private_key_t *this)
}
/**
- * Implementation of gmp_rsa_private_key.destroy.
+ * Implementation of gmp_rsa_private_key.sign.
*/
static bool sign(private_gmp_rsa_private_key_t *this, signature_scheme_t scheme,
chunk_t data, chunk_t *signature)
{
switch (scheme)
{
+ case SIGN_RSA_EMSA_PKCS1_NULL:
+ return build_emsa_pkcs1_signature(this, HASH_UNKNOWN, data, signature);
case SIGN_DEFAULT:
- /* default is EMSA-PKCS1 using SHA1 */
case SIGN_RSA_EMSA_PKCS1_SHA1:
return build_emsa_pkcs1_signature(this, HASH_SHA1, data, signature);
case SIGN_RSA_EMSA_PKCS1_SHA256:
@@ -304,7 +311,7 @@ static bool sign(private_gmp_rsa_private_key_t *this, signature_scheme_t scheme,
}
/**
- * Implementation of gmp_rsa_private_key.destroy.
+ * Implementation of gmp_rsa_private_key.decrypt.
*/
static bool decrypt(private_gmp_rsa_private_key_t *this,
chunk_t crypto, chunk_t *plain)
@@ -314,7 +321,7 @@ static bool decrypt(private_gmp_rsa_private_key_t *this,
}
/**
- * Implementation of gmp_rsa_private_key.destroy.
+ * Implementation of gmp_rsa_private_key.get_keysize.
*/
static size_t get_keysize(private_gmp_rsa_private_key_t *this)
{
@@ -322,7 +329,7 @@ static size_t get_keysize(private_gmp_rsa_private_key_t *this)
}
/**
- * Implementation of gmp_rsa_private_key.destroy.
+ * Implementation of gmp_rsa_private_key.get_id.
*/
static identification_t* get_id(private_gmp_rsa_private_key_t *this,
id_type_t type)
@@ -347,7 +354,35 @@ static gmp_rsa_public_key_t* get_public_key(private_gmp_rsa_private_key_t *this)
}
/**
- * Implementation of gmp_rsa_private_key.destroy.
+ * Implementation of gmp_rsa_private_key.equals.
+ */
+static bool equals(private_gmp_rsa_private_key_t *this, private_key_t *other)
+{
+ identification_t *keyid;
+
+ if (&this->public.interface == other)
+ {
+ return TRUE;
+ }
+ if (other->get_type(other) != KEY_RSA)
+ {
+ return FALSE;
+ }
+ keyid = other->get_id(other, ID_PUBKEY_SHA1);
+ if (keyid && keyid->equals(keyid, this->keyid))
+ {
+ return TRUE;
+ }
+ keyid = other->get_id(other, ID_PUBKEY_INFO_SHA1);
+ if (keyid && keyid->equals(keyid, this->keyid_info))
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Implementation of gmp_rsa_private_key.belongs_to.
*/
static bool belongs_to(private_gmp_rsa_private_key_t *this, public_key_t *public)
{
@@ -371,19 +406,27 @@ static bool belongs_to(private_gmp_rsa_private_key_t *this, public_key_t *public
}
/**
- * convert a MP integer into a DER coded ASN.1 object
+ * Convert a MP integer into a chunk_t
*/
-chunk_t gmp_mpz_to_asn1(const mpz_t value)
+chunk_t gmp_mpz_to_chunk(const mpz_t value)
{
chunk_t n;
- n.len = 1 + mpz_sizeinbase(value, 2) / 8; /* size in bytes */
+ n.len = 1 + mpz_sizeinbase(value, 2) / BITS_PER_BYTE;
n.ptr = mpz_export(NULL, NULL, 1, n.len, 1, 0, value);
if (n.ptr == NULL)
{ /* if we have zero in "value", gmp returns NULL */
n.len = 0;
}
- return asn1_wrap(ASN1_INTEGER, "m", n);
+ return n;
+}
+
+/**
+ * Convert a MP integer into a DER coded ASN.1 object
+ */
+chunk_t gmp_mpz_to_asn1(const mpz_t value)
+{
+ return asn1_wrap(ASN1_INTEGER, "m", gmp_mpz_to_chunk(value));
}
/**
@@ -404,7 +447,7 @@ static chunk_t get_encoding(private_gmp_rsa_private_key_t *this)
}
/**
- * Implementation of gmp_rsa_private_key.destroy.
+ * Implementation of gmp_rsa_private_key.get_ref.
*/
static private_gmp_rsa_private_key_t* get_ref(private_gmp_rsa_private_key_t *this)
{
@@ -445,14 +488,14 @@ static status_t check(private_gmp_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)
{
DBG1("key shorter than 512 bits");
return FAILED;
}
/* we picked a max modulus size to simplify buffer allocation */
- if (this->k > 8192/8)
+ if (this->k > 8192 / BITS_PER_BYTE)
{
DBG1("key larger than 8192 bits");
return FAILED;
@@ -540,16 +583,17 @@ static private_gmp_rsa_private_key_t *gmp_rsa_private_key_create_empty(void)
{
private_gmp_rsa_private_key_t *this = malloc_thing(private_gmp_rsa_private_key_t);
- this->public.interface.get_type = (key_type_t (*)(private_key_t *this))get_type;
- this->public.interface.sign = (bool (*)(private_key_t *this, signature_scheme_t scheme, chunk_t data, chunk_t *signature))sign;
- this->public.interface.decrypt = (bool (*)(private_key_t *this, chunk_t crypto, chunk_t *plain))decrypt;
- this->public.interface.get_keysize = (size_t (*) (private_key_t *this))get_keysize;
- this->public.interface.get_id = (identification_t* (*) (private_key_t *this,id_type_t))get_id;
- this->public.interface.get_public_key = (public_key_t* (*)(private_key_t *this))get_public_key;
- this->public.interface.belongs_to = (bool (*) (private_key_t *this, public_key_t *public))belongs_to;
- this->public.interface.get_encoding = (chunk_t(*)(private_key_t*))get_encoding;
- this->public.interface.get_ref = (private_key_t* (*)(private_key_t *this))get_ref;
- this->public.interface.destroy = (void (*)(private_key_t *this))destroy;
+ this->public.interface.get_type = (key_type_t (*) (private_key_t*))get_type;
+ this->public.interface.sign = (bool (*) (private_key_t*, signature_scheme_t, chunk_t, chunk_t*))sign;
+ this->public.interface.decrypt = (bool (*) (private_key_t*, chunk_t, chunk_t*))decrypt;
+ this->public.interface.get_keysize = (size_t (*) (private_key_t*))get_keysize;
+ this->public.interface.get_id = (identification_t* (*) (private_key_t*, id_type_t))get_id;
+ this->public.interface.get_public_key = (public_key_t* (*) (private_key_t*))get_public_key;
+ this->public.interface.equals = (bool (*) (private_key_t*, private_key_t*))equals;
+ this->public.interface.belongs_to = (bool (*) (private_key_t*, public_key_t*))belongs_to;
+ this->public.interface.get_encoding = (chunk_t (*) (private_key_t*))get_encoding;
+ this->public.interface.get_ref = (private_key_t* (*) (private_key_t*))get_ref;
+ this->public.interface.destroy = (void (*) (private_key_t*))destroy;
this->keyid = NULL;
this->keyid_info = NULL;
@@ -567,7 +611,7 @@ static gmp_rsa_private_key_t *generate(size_t key_size)
mpz_t m, q1, t;
private_gmp_rsa_private_key_t *this = gmp_rsa_private_key_create_empty();
- key_size = key_size / 8;
+ key_size = key_size / BITS_PER_BYTE;
/* Get values of primes p and q */
if (compute_prime(this, key_size/2, &p) != SUCCESS)
@@ -678,7 +722,7 @@ static const asn1Object_t privkeyObjects[] = {
/**
* load private key from a ASN1 encoded blob
*/
-static gmp_rsa_private_key_t *load(chunk_t blob)
+static gmp_rsa_private_key_t *load_asn1_der(chunk_t blob)
{
asn1_parser_t *parser;
chunk_t object;
@@ -706,6 +750,7 @@ static gmp_rsa_private_key_t *load(chunk_t blob)
case PRIV_KEY_VERSION:
if (object.len > 0 && *object.ptr != 0)
{
+ DBG1("PKCS#1 private key format is not version 1");
goto end;
}
break;
@@ -755,13 +800,131 @@ end:
destroy(this);
return NULL;
}
+ if (check(this) != SUCCESS)
+ {
+ destroy(this);
+ return NULL;
+ }
+ return &this->public;
+}
+/**
+ * load private key from an OpenPGP blob coded according to section
+ */
+static gmp_rsa_private_key_t *load_pgp(chunk_t blob)
+{
+ mpz_t u;
+ int objectID;
+ pgp_sym_alg_t s2k;
+ chunk_t packet = blob;
+ private_gmp_rsa_private_key_t *this = gmp_rsa_private_key_create_empty();
+
+ mpz_init(this->n);
+ mpz_init(this->e);
+ mpz_init(this->p);
+ mpz_init(this->q);
+ mpz_init(this->d);
+ mpz_init(this->exp1);
+ mpz_init(this->exp2);
+ mpz_init(this->coeff);
+
+ /* string-to-key usage */
+ s2k = pgp_length(&packet, 1);
+ DBG2("L3 - string-to-key: %d", s2k);
+
+ if (s2k == 255 || s2k == 254)
+ {
+ DBG1("string-to-key specifiers not supported");
+ goto end;
+ }
+ DBG2(" %N", pgp_sym_alg_names, s2k);
+
+ if (s2k != PGP_SYM_ALG_PLAIN)
+ {
+ DBG1("%N encryption not supported", pgp_sym_alg_names, s2k);
+ goto end;
+ }
+
+ for (objectID = PRIV_KEY_MODULUS; objectID <= PRIV_KEY_PRIME2; objectID++)
+ {
+ chunk_t object;
+
+ object.len = pgp_length(&packet, 2);
+
+ if (object.len == PGP_INVALID_LENGTH)
+ {
+ DBG1("OpenPGP length is invalid");
+ goto end;
+ }
+ object.len = (object.len + 7) / BITS_PER_BYTE;
+ if (object.len > packet.len)
+ {
+ DBG1("OpenPGP field is too short");
+ goto end;
+ }
+ object.ptr = packet.ptr;
+ packet.ptr += object.len;
+ packet.len -= object.len;
+
+ switch (objectID)
+ {
+ case PRIV_KEY_MODULUS:
+ mpz_import(this->n, object.len, 1, 1, 1, 0, object.ptr);
+ break;
+ case PRIV_KEY_PUB_EXP:
+ mpz_import(this->e, object.len, 1, 1, 1, 0, object.ptr);
+ break;
+ case PRIV_KEY_PRIV_EXP:
+ mpz_import(this->d, object.len, 1, 1, 1, 0, object.ptr);
+ break;
+ case PRIV_KEY_PRIME1:
+ mpz_import(this->p, object.len, 1, 1, 1, 0, object.ptr);
+ break;
+ case PRIV_KEY_PRIME2:
+ mpz_import(this->q, object.len, 1, 1, 1, 0, object.ptr);
+ break;
+ }
+ }
+
+ /* auxiliary variable */
+ mpz_init(u);
+
+ /* exp1 = d mod (p-1) */
+ mpz_sub_ui(u, this->p, 1);
+ mpz_mod(this->exp1, this->d, u);
+
+ /* exp2 = d mod (q-1) */
+ mpz_sub_ui(u, this->q, 1);
+ mpz_mod(this->exp2, this->d, u);
+
+ /* coeff = (q^-1) mod p */
+ mpz_invert(this->coeff, this->q, this->p);
+ if (mpz_cmp_ui(this->coeff, 0) < 0)
+ {
+ mpz_add(this->coeff, this->coeff, this->p);
+ }
+ mpz_clear(u);
+ chunk_clear(&blob);
+
+ this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
+
+ if (!gmp_rsa_public_key_build_id(this->n, this->e,
+ &this->keyid, &this->keyid_info))
+ {
+ destroy(this);
+ return NULL;
+ }
if (check(this) != SUCCESS)
{
destroy(this);
return NULL;
}
return &this->public;
+
+end:
+ chunk_clear(&blob);
+ destroy(this);
+ return NULL;
}
typedef struct private_builder_t private_builder_t;
@@ -802,7 +965,15 @@ static void add(private_builder_t *this, builder_part_t part, ...)
{
va_start(args, part);
chunk = va_arg(args, chunk_t);
- this->key = load(chunk_clone(chunk));
+ this->key = load_asn1_der(chunk_clone(chunk));
+ va_end(args);
+ return;
+ }
+ case BUILD_BLOB_PGP:
+ {
+ va_start(args, part);
+ chunk = va_arg(args, chunk_t);
+ this->key = load_pgp(chunk_clone(chunk));
va_end(args);
return;
}
diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c
index acb44a110..4c779703b 100644
--- a/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c
+++ b/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c
@@ -28,11 +28,7 @@
#include <asn1/asn1_parser.h>
#include <asn1/pem.h>
#include <crypto/hashers/hasher.h>
-
-/**
- * defined in gmp_rsa_private_key.c
- */
-extern chunk_t gmp_mpz_to_asn1(const mpz_t value);
+#include <pgp/pgp.h>
typedef struct private_gmp_rsa_public_key_t private_gmp_rsa_public_key_t;
@@ -77,6 +73,12 @@ struct private_gmp_rsa_public_key_t {
};
/**
+ * Shared functions defined in gmp_rsa_private_key.c
+ */
+extern chunk_t gmp_mpz_to_chunk(const mpz_t value);
+extern chunk_t gmp_mpz_to_asn1(const mpz_t value);
+
+/**
* RSAEP algorithm specified in PKCS#1.
*/
static chunk_t rsaep(private_gmp_rsa_public_key_t *this, chunk_t data)
@@ -189,13 +191,24 @@ static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
goto end;
}
- /* parse ASN.1-based digestInfo */
- {
+ if (algorithm == HASH_UNKNOWN)
+ { /* IKEv1 signatures without digestInfo */
+ if (em.len != data.len)
+ {
+ DBG1("hash size in signature is %u bytes instead of %u bytes",
+ em.len, data.len);
+ goto end;
+ }
+ success = memeq(em.ptr, data.ptr, data.len);
+ }
+ else
+ { /* IKEv2 and X.509 certificate signatures */
asn1_parser_t *parser;
chunk_t object;
int objectID;
hash_algorithm_t hash_algorithm = HASH_UNKNOWN;
+ DBG2("signature verification:");
parser = asn1_parser_create(digestInfoObjects, em);
while (parser->iterate(parser, &objectID, &object))
@@ -218,8 +231,7 @@ static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
parser->get_level(parser)+1, NULL);
hash_algorithm = hasher_algorithm_from_oid(hash_oid);
- if (hash_algorithm == HASH_UNKNOWN ||
- (algorithm != HASH_UNKNOWN && hash_algorithm != algorithm))
+ if (hash_algorithm == HASH_UNKNOWN || hash_algorithm != algorithm)
{
DBG1("expected hash algorithm %N, but found %N (OID: %#B)",
hash_algorithm_names, algorithm,
@@ -287,7 +299,8 @@ static bool verify(private_gmp_rsa_public_key_t *this, signature_scheme_t scheme
{
switch (scheme)
{
- case SIGN_DEFAULT: /* default is EMSA-PKCS1 using included OID */
+ case SIGN_DEFAULT:
+ case SIGN_RSA_EMSA_PKCS1_NULL:
return verify_emsa_pkcs1_signature(this, HASH_UNKNOWN, data, signature);
case SIGN_RSA_EMSA_PKCS1_MD5:
return verify_emsa_pkcs1_signature(this, HASH_MD5, data, signature);
@@ -316,6 +329,34 @@ static bool encrypt_(private_gmp_rsa_public_key_t *this, chunk_t crypto, chunk_t
}
/**
+ * Implementation of gmp_rsa_public_key.equals.
+ */
+static bool equals(private_gmp_rsa_public_key_t *this, public_key_t *other)
+{
+ identification_t *keyid;
+
+ if (&this->public.interface == other)
+ {
+ return TRUE;
+ }
+ if (other->get_type(other) != KEY_RSA)
+ {
+ return FALSE;
+ }
+ keyid = other->get_id(other, ID_PUBKEY_SHA1);
+ if (keyid && keyid->equals(keyid, this->keyid))
+ {
+ return TRUE;
+ }
+ keyid = other->get_id(other, ID_PUBKEY_INFO_SHA1);
+ if (keyid && keyid->equals(keyid, this->keyid_info))
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
* Implementation of public_key_t.get_keysize.
*/
static size_t get_keysize(private_gmp_rsa_public_key_t *this)
@@ -324,6 +365,34 @@ static size_t get_keysize(private_gmp_rsa_public_key_t *this)
}
/**
+ * Build the PGP version 3 RSA key identifier from n and e using
+ * MD5 hashed modulus and exponent. Also used in rsa_private_key.c.
+ */
+static identification_t* gmp_rsa_build_pgp_v3_keyid(mpz_t n, mpz_t e)
+{
+ identification_t *keyid;
+ chunk_t modulus, exponent, hash;
+ hasher_t *hasher;
+
+ hasher= lib->crypto->create_hasher(lib->crypto, HASH_MD5);
+ if (hasher == NULL)
+ {
+ DBG1("computation of PGP V3 key ID failed, no MD5 hasher is available");
+ return NULL;
+ }
+ modulus = gmp_mpz_to_chunk(n);
+ exponent = gmp_mpz_to_chunk(e);
+ hasher->allocate_hash(hasher, modulus, NULL);
+ hasher->allocate_hash(hasher, exponent, &hash);
+ hasher->destroy(hasher);
+ keyid = identification_create_from_encoding(ID_PUBKEY_SHA1, hash);
+ free(hash.ptr);
+ free(modulus.ptr);
+ free(exponent.ptr);
+ return keyid;
+}
+
+/**
* Implementation of public_key_t.get_id.
*/
static identification_t *get_id(private_gmp_rsa_public_key_t *this,
@@ -335,6 +404,8 @@ static identification_t *get_id(private_gmp_rsa_public_key_t *this,
return this->keyid_info;
case ID_PUBKEY_SHA1:
return this->keyid;
+ case ID_KEY_ID:
+ return gmp_rsa_build_pgp_v3_keyid(this->n, this->e);
default:
return NULL;
}
@@ -381,14 +452,15 @@ static private_gmp_rsa_public_key_t *gmp_rsa_public_key_create_empty()
{
private_gmp_rsa_public_key_t *this = malloc_thing(private_gmp_rsa_public_key_t);
- this->public.interface.get_type = (key_type_t (*)(public_key_t *this))get_type;
- this->public.interface.verify = (bool (*)(public_key_t *this, signature_scheme_t scheme, chunk_t data, chunk_t signature))verify;
- this->public.interface.encrypt = (bool (*)(public_key_t *this, chunk_t crypto, chunk_t *plain))encrypt_;
- this->public.interface.get_keysize = (size_t (*) (public_key_t *this))get_keysize;
- this->public.interface.get_id = (identification_t* (*) (public_key_t *this,id_type_t))get_id;
- this->public.interface.get_encoding = (chunk_t(*)(public_key_t*))get_encoding;
- this->public.interface.get_ref = (public_key_t* (*)(public_key_t *this))get_ref;
- this->public.interface.destroy = (void (*)(public_key_t *this))destroy;
+ this->public.interface.get_type = (key_type_t (*) (public_key_t*))get_type;
+ this->public.interface.verify = (bool (*) (public_key_t*, signature_scheme_t, chunk_t, chunk_t))verify;
+ this->public.interface.encrypt = (bool (*) (public_key_t*, chunk_t, chunk_t*))encrypt_;
+ this->public.interface.equals = (bool (*) (public_key_t*, public_key_t*))equals;
+ this->public.interface.get_keysize = (size_t (*) (public_key_t*))get_keysize;
+ this->public.interface.get_id = (identification_t* (*) (public_key_t*, id_type_t))get_id;
+ this->public.interface.get_encoding = (chunk_t(*) (public_key_t*))get_encoding;
+ this->public.interface.get_ref = (public_key_t* (*) (public_key_t *this))get_ref;
+ this->public.interface.destroy = (void (*) (public_key_t *this))destroy;
this->keyid = NULL;
this->keyid_info = NULL;
@@ -443,7 +515,7 @@ gmp_rsa_public_key_t *gmp_rsa_public_key_create_from_n_e(mpz_t n, mpz_t e)
mpz_init_set(this->n, n);
mpz_init_set(this->e, e);
- this->k = (mpz_sizeinbase(this->n, 2) + 7) / 8;
+ this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
if (!gmp_rsa_public_key_build_id(this->n, this->e,
&this->keyid, &this->keyid_info))
{
@@ -467,9 +539,9 @@ static const asn1Object_t pubkeyObjects[] = {
#define PUB_KEY_EXPONENT 2
/**
- * Load a public key from an ASN1 encoded blob
+ * Load a public key from an ASN.1 encoded blob
*/
-static gmp_rsa_public_key_t *load(chunk_t blob)
+static gmp_rsa_public_key_t *load_asn1_der(chunk_t blob)
{
asn1_parser_t *parser;
chunk_t object;
@@ -505,7 +577,121 @@ static gmp_rsa_public_key_t *load(chunk_t blob)
return NULL;
}
- this->k = (mpz_sizeinbase(this->n, 2) + 7) / 8;
+ this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
+
+ if (!gmp_rsa_public_key_build_id(this->n, this->e,
+ &this->keyid, &this->keyid_info))
+ {
+ destroy(this);
+ return NULL;
+ }
+ return &this->public;
+}
+
+/**
+ * Load a public key from an OpenPGP blob
+ */
+static gmp_rsa_public_key_t* load_pgp(chunk_t blob)
+{
+ chunk_t exponent, modulus;
+ chunk_t packet = blob;
+ private_gmp_rsa_public_key_t *this = gmp_rsa_public_key_create_empty();
+
+ mpz_init(this->n);
+ mpz_init(this->e);
+
+ /* modulus n */
+ modulus.len = (pgp_length(&packet, 2) + 7) / BITS_PER_BYTE;
+ modulus.ptr = packet.ptr;
+ if (modulus.len > packet.len)
+ {
+ DBG1("OpenPGP public key blob too short for modulus");
+ goto end;
+ }
+ packet.ptr += modulus.len;
+ packet.len -= modulus.len;
+ DBG2("L3 - modulus:");
+ DBG3("%B", &modulus);
+
+ /* public exponent e */
+ exponent.len = (pgp_length(&packet, 2) + 7) / BITS_PER_BYTE;
+ exponent.ptr = packet.ptr;
+ if (exponent.len > packet.len)
+ {
+ DBG1("OpenPGP public key blob too short for exponent");
+ goto end;
+ }
+ DBG2("L3 - public exponent:");
+ DBG3("%B", &exponent);
+
+ mpz_import(this->n, modulus.len, 1, 1, 1, 0, modulus.ptr);
+ mpz_import(this->e, exponent.len, 1, 1, 1, 0, exponent.ptr);
+ this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
+ free(blob.ptr);
+
+ if (!gmp_rsa_public_key_build_id(this->n, this->e,
+ &this->keyid, &this->keyid_info))
+ {
+ destroy(this);
+ return NULL;
+ }
+ return &this->public;
+
+end:
+ free(blob.ptr);
+ destroy(this);
+ return NULL;
+}
+
+/**
+ * Load a public key from an RFC 3110 encoded blob
+ */
+static gmp_rsa_public_key_t *load_rfc_3110(chunk_t blob)
+{
+ chunk_t exponent, modulus;
+ u_char *pos = blob.ptr;
+ size_t len = blob.len;
+ private_gmp_rsa_public_key_t *this = gmp_rsa_public_key_create_empty();
+
+ mpz_init(this->n);
+ mpz_init(this->e);
+
+ if (blob.len < 3)
+ {
+ DBG1("RFC 3110 public key blob too short for exponent length");
+ goto end;
+ }
+ if (pos[0] != 0x00)
+ {
+ exponent = chunk_create(pos + 1, pos[0]);
+ pos++;
+ len--;
+ }
+ else
+ {
+ exponent = chunk_create(pos + 3, 256*pos[1] + pos[2]);
+ pos += 3;
+ len -= 3;
+ }
+ if (exponent.len > len)
+ {
+ DBG1("RFC 3110 public key blob too short for exponent");
+ goto end;
+ }
+ pos += exponent.len;
+ len -= exponent.len;
+
+ if (len == 0)
+ {
+ DBG1("RFC 3110 public key blob has zero length modulus");
+ goto end;
+ }
+ modulus = chunk_create(pos, len);
+
+ mpz_import(this->n, modulus.len, 1, 1, 1, 0, modulus.ptr);
+ mpz_import(this->e, exponent.len, 1, 1, 1, 0, exponent.ptr);
+ this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
+ free(blob.ptr);
if (!gmp_rsa_public_key_build_id(this->n, this->e,
&this->keyid, &this->keyid_info))
@@ -514,6 +700,11 @@ static gmp_rsa_public_key_t *load(chunk_t blob)
return NULL;
}
return &this->public;
+
+end:
+ free(blob.ptr);
+ destroy(this);
+ return NULL;
}
typedef struct private_builder_t private_builder_t;
@@ -554,7 +745,23 @@ static void add(private_builder_t *this, builder_part_t part, ...)
{
va_start(args, part);
chunk = va_arg(args, chunk_t);
- this->key = load(chunk_clone(chunk));
+ this->key = load_asn1_der(chunk_clone(chunk));
+ va_end(args);
+ return;
+ }
+ case BUILD_BLOB_PGP:
+ {
+ va_start(args, part);
+ chunk = va_arg(args, chunk_t);
+ this->key = load_pgp(chunk_clone(chunk));
+ va_end(args);
+ return;
+ }
+ case BUILD_BLOB_RFC_3110:
+ {
+ va_start(args, part);
+ chunk = va_arg(args, chunk_t);
+ this->key = load_rfc_3110(chunk_clone(chunk));
va_end(args);
return;
}
diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c
index 4004e0949..12040f229 100644
--- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c
@@ -136,7 +136,7 @@ error:
}
/**
- * Implementation of openssl_rsa_private_key.destroy.
+ * Implementation of openssl_rsa_private_key.get_type.
*/
static key_type_t get_type(private_openssl_rsa_private_key_t *this)
{
@@ -144,7 +144,7 @@ static key_type_t get_type(private_openssl_rsa_private_key_t *this)
}
/**
- * Implementation of openssl_rsa_private_key.destroy.
+ * Implementation of openssl_rsa_private_key.sign.
*/
static bool sign(private_openssl_rsa_private_key_t *this, signature_scheme_t scheme,
chunk_t data, chunk_t *signature)
@@ -152,7 +152,6 @@ static bool sign(private_openssl_rsa_private_key_t *this, signature_scheme_t sch
switch (scheme)
{
case SIGN_DEFAULT:
- /* default is EMSA-PKCS1 using SHA1 */
case SIGN_RSA_EMSA_PKCS1_SHA1:
return build_emsa_pkcs1_signature(this, NID_sha1, data, signature);
case SIGN_RSA_EMSA_PKCS1_SHA256:
@@ -171,7 +170,7 @@ static bool sign(private_openssl_rsa_private_key_t *this, signature_scheme_t sch
}
/**
- * Implementation of openssl_rsa_private_key.destroy.
+ * Implementation of openssl_rsa_private_key.decrypt.
*/
static bool decrypt(private_openssl_rsa_private_key_t *this,
chunk_t crypto, chunk_t *plain)
@@ -181,7 +180,7 @@ static bool decrypt(private_openssl_rsa_private_key_t *this,
}
/**
- * Implementation of openssl_rsa_private_key.destroy.
+ * Implementation of openssl_rsa_private_key.get_keysize.
*/
static size_t get_keysize(private_openssl_rsa_private_key_t *this)
{
@@ -189,7 +188,7 @@ static size_t get_keysize(private_openssl_rsa_private_key_t *this)
}
/**
- * Implementation of openssl_rsa_private_key.destroy.
+ * Implementation of openssl_rsa_private_key.get_id.
*/
static identification_t* get_id(private_openssl_rsa_private_key_t *this,
id_type_t type)
@@ -206,7 +205,7 @@ static identification_t* get_id(private_openssl_rsa_private_key_t *this,
}
/**
- * Implementation of openssl_rsa_private_key.destroy.
+ * Implementation of openssl_rsa_private_key.get_public_key.
*/
static openssl_rsa_public_key_t* get_public_key(private_openssl_rsa_private_key_t *this)
{
@@ -214,7 +213,35 @@ static openssl_rsa_public_key_t* get_public_key(private_openssl_rsa_private_key_
}
/**
- * Implementation of openssl_rsa_private_key.destroy.
+ * Implementation of openssl_rsa_private_key.equals.
+ */
+static bool equals(private_openssl_rsa_private_key_t *this, private_key_t *other)
+{
+ identification_t *keyid;
+
+ if (&this->public.interface == other)
+ {
+ return TRUE;
+ }
+ if (other->get_type(other) != KEY_RSA)
+ {
+ return FALSE;
+ }
+ keyid = other->get_id(other, ID_PUBKEY_SHA1);
+ if (keyid && keyid->equals(keyid, this->keyid))
+ {
+ return TRUE;
+ }
+ keyid = other->get_id(other, ID_PUBKEY_INFO_SHA1);
+ if (keyid && keyid->equals(keyid, this->keyid_info))
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Implementation of openssl_rsa_private_key.belongs_to.
*/
static bool belongs_to(private_openssl_rsa_private_key_t *this, public_key_t *public)
{
@@ -253,7 +280,7 @@ static chunk_t get_encoding(private_openssl_rsa_private_key_t *this)
}
/**
- * Implementation of openssl_rsa_private_key.destroy.
+ * Implementation of openssl_rsa_private_key.get_ref.
*/
static private_openssl_rsa_private_key_t* get_ref(private_openssl_rsa_private_key_t *this)
{
@@ -286,16 +313,17 @@ static private_openssl_rsa_private_key_t *openssl_rsa_private_key_create_empty(v
{
private_openssl_rsa_private_key_t *this = malloc_thing(private_openssl_rsa_private_key_t);
- this->public.interface.get_type = (key_type_t (*)(private_key_t *this))get_type;
- this->public.interface.sign = (bool (*)(private_key_t *this, signature_scheme_t scheme, chunk_t data, chunk_t *signature))sign;
- this->public.interface.decrypt = (bool (*)(private_key_t *this, chunk_t crypto, chunk_t *plain))decrypt;
- this->public.interface.get_keysize = (size_t (*) (private_key_t *this))get_keysize;
- this->public.interface.get_id = (identification_t* (*) (private_key_t *this,id_type_t))get_id;
- this->public.interface.get_public_key = (public_key_t* (*)(private_key_t *this))get_public_key;
- this->public.interface.belongs_to = (bool (*) (private_key_t *this, public_key_t *public))belongs_to;
- this->public.interface.get_encoding = (chunk_t(*)(private_key_t*))get_encoding;
- this->public.interface.get_ref = (private_key_t* (*)(private_key_t *this))get_ref;
- this->public.interface.destroy = (void (*)(private_key_t *this))destroy;
+ this->public.interface.get_type = (key_type_t (*) (private_key_t*))get_type;
+ this->public.interface.sign = (bool (*) (private_key_t*, signature_scheme_t, chunk_t, chunk_t*))sign;
+ this->public.interface.decrypt = (bool (*) (private_key_t*, chunk_t, chunk_t*))decrypt;
+ this->public.interface.get_keysize = (size_t (*) (private_key_t*))get_keysize;
+ this->public.interface.get_id = (identification_t* (*) (private_key_t*, id_type_t))get_id;
+ this->public.interface.get_public_key = (public_key_t* (*) (private_key_t*))get_public_key;
+ this->public.interface.equals = (bool (*) (private_key_t*, private_key_t*))equals;
+ this->public.interface.belongs_to = (bool (*) (private_key_t*, public_key_t*))belongs_to;
+ this->public.interface.get_encoding = (chunk_t(*) (private_key_t*))get_encoding;
+ this->public.interface.get_ref = (private_key_t* (*) (private_key_t*))get_ref;
+ this->public.interface.destroy = (void (*) (private_key_t*))destroy;
this->engine = FALSE;
this->keyid = NULL;
diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
index 8803b7960..d0fd562af 100644
--- a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
@@ -124,7 +124,6 @@ static bool verify(private_openssl_rsa_public_key_t *this, signature_scheme_t sc
switch (scheme)
{
case SIGN_DEFAULT:
- /* default is EMSA-PKCS1 using SHA1 */
case SIGN_RSA_EMSA_PKCS1_SHA1:
return verify_emsa_pkcs1_signature(this, NID_sha1, data, signature);
case SIGN_RSA_EMSA_PKCS1_SHA256:
@@ -152,6 +151,34 @@ static bool encrypt_(private_openssl_rsa_public_key_t *this, chunk_t crypto, chu
}
/**
+ * Implementation of public_key_t.equals.
+ */
+static bool equals(private_openssl_rsa_public_key_t *this, public_key_t *other)
+{
+ identification_t *keyid;
+
+ if (&this->public.interface == other)
+ {
+ return TRUE;
+ }
+ if (other->get_type(other) != KEY_RSA)
+ {
+ return FALSE;
+ }
+ keyid = other->get_id(other, ID_PUBKEY_SHA1);
+ if (keyid && keyid->equals(keyid, this->keyid))
+ {
+ return TRUE;
+ }
+ keyid = other->get_id(other, ID_PUBKEY_INFO_SHA1);
+ if (keyid && keyid->equals(keyid, this->keyid_info))
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
* Implementation of public_key_t.get_keysize.
*/
static size_t get_keysize(private_openssl_rsa_public_key_t *this)
@@ -262,6 +289,7 @@ static private_openssl_rsa_public_key_t *openssl_rsa_public_key_create_empty()
this->public.interface.get_type = (key_type_t (*)(public_key_t *this))get_type;
this->public.interface.verify = (bool (*)(public_key_t *this, signature_scheme_t scheme, chunk_t data, chunk_t signature))verify;
this->public.interface.encrypt = (bool (*)(public_key_t *this, chunk_t crypto, chunk_t *plain))encrypt_;
+ this->public.interface.equals = (bool (*) (public_key_t*, public_key_t*))equals;
this->public.interface.get_keysize = (size_t (*) (public_key_t *this))get_keysize;
this->public.interface.get_id = (identification_t* (*) (public_key_t *this,id_type_t))get_id;
this->public.interface.get_encoding = (chunk_t(*)(public_key_t*))get_encoding;
diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c
index 57fef9496..34c121d7b 100644
--- a/src/libstrongswan/plugins/x509/x509_cert.c
+++ b/src/libstrongswan/plugins/x509/x509_cert.c
@@ -730,7 +730,6 @@ static bool parse_certificate(private_x509_cert_t *this)
KEY_ANY, BUILD_BLOB_ASN1_DER, object, BUILD_END);
if (this->public_key == NULL)
{
- DBG1("could not create public key");
goto end;
}
break;
@@ -1123,19 +1122,19 @@ static private_x509_cert_t* create_empty(void)
{
private_x509_cert_t *this = malloc_thing(private_x509_cert_t);
- this->public.interface.interface.get_type = (certificate_type_t (*)(certificate_t *this))get_type;
- this->public.interface.interface.get_subject = (identification_t* (*)(certificate_t *this))get_subject;
- this->public.interface.interface.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer;
- this->public.interface.interface.has_subject = (id_match_t (*)(certificate_t*, identification_t *subject))has_subject;
- this->public.interface.interface.has_issuer = (id_match_t (*)(certificate_t*, identification_t *issuer))has_issuer;
- this->public.interface.interface.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer))issued_by;
- this->public.interface.interface.get_public_key = (public_key_t* (*)(certificate_t *this))get_public_key;
- this->public.interface.interface.get_validity = (bool (*)(certificate_t*, time_t *when, time_t *, time_t*))get_validity;
- this->public.interface.interface.is_newer = (bool (*)(certificate_t*,certificate_t*))is_newer;
- this->public.interface.interface.get_encoding = (chunk_t (*)(certificate_t*))get_encoding;
- this->public.interface.interface.equals = (bool (*)(certificate_t*, certificate_t *other))equals;
- this->public.interface.interface.get_ref = (certificate_t* (*)(certificate_t *this))get_ref;
- this->public.interface.interface.destroy = (void (*)(certificate_t *this))destroy;
+ this->public.interface.interface.get_type = (certificate_type_t (*) (certificate_t*))get_type;
+ this->public.interface.interface.get_subject = (identification_t* (*) (certificate_t*))get_subject;
+ this->public.interface.interface.get_issuer = (identification_t* (*) (certificate_t*))get_issuer;
+ this->public.interface.interface.has_subject = (id_match_t (*) (certificate_t*, identification_t*))has_subject;
+ this->public.interface.interface.has_issuer = (id_match_t (*) (certificate_t*, identification_t*))has_issuer;
+ this->public.interface.interface.issued_by = (bool (*) (certificate_t*, certificate_t*))issued_by;
+ this->public.interface.interface.get_public_key = (public_key_t* (*) (certificate_t*))get_public_key;
+ this->public.interface.interface.get_validity = (bool (*) (certificate_t*, time_t*, time_t*, time_t*))get_validity;
+ this->public.interface.interface.is_newer = (bool (*) (certificate_t*,certificate_t*))is_newer;
+ this->public.interface.interface.get_encoding = (chunk_t (*) (certificate_t*))get_encoding;
+ this->public.interface.interface.equals = (bool (*)(certificate_t*, certificate_t*))equals;
+ this->public.interface.interface.get_ref = (certificate_t* (*)(certificate_t*))get_ref;
+ this->public.interface.interface.destroy = (void (*)(certificate_t*))destroy;
this->public.interface.get_flags = (x509_flag_t (*)(x509_t*))get_flags;
this->public.interface.get_serial = (chunk_t (*)(x509_t*))get_serial;
this->public.interface.get_authKeyIdentifier = (identification_t* (*)(x509_t*))get_authKeyIdentifier;
@@ -1314,7 +1313,7 @@ static bool generate(private_builder_t *this)
this->cert->tbsCertificate = asn1_wrap(ASN1_SEQUENCE, "mmccmcmm",
asn1_simple_object(ASN1_CONTEXT_C_0, ASN1_INTEGER_2),
- asn1_simple_object(ASN1_INTEGER, this->cert->serialNumber),
+ asn1_integer("c", this->cert->serialNumber),
asn1_algorithmIdentifier(this->cert->algorithm),
issuer->get_encoding(issuer),
asn1_wrap(ASN1_SEQUENCE, "mm",