aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libstrongswan/Makefile.am3
-rw-r--r--src/libstrongswan/asn1/asn1.c39
-rw-r--r--src/libstrongswan/asn1/asn1.h11
-rw-r--r--src/libstrongswan/credentials/builder.c2
-rw-r--r--src/libstrongswan/credentials/builder.h10
-rw-r--r--src/libstrongswan/credentials/credential_factory.c2
-rw-r--r--src/libstrongswan/credentials/keys/private_key.h8
-rw-r--r--src/libstrongswan/credentials/keys/public_key.c6
-rw-r--r--src/libstrongswan/credentials/keys/public_key.h52
-rw-r--r--src/libstrongswan/pgp/pgp.c (renamed from src/scepclient/rsakey.h)49
-rw-r--r--src/libstrongswan/pgp/pgp.h64
-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
-rw-r--r--src/pluto/Makefile.am3
-rw-r--r--src/pluto/ac.c4
-rw-r--r--src/pluto/ca.c4
-rw-r--r--src/pluto/certs.c36
-rw-r--r--src/pluto/certs.h17
-rw-r--r--src/pluto/connections.c54
-rw-r--r--src/pluto/crl.c8
-rw-r--r--src/pluto/dnskey.c107
-rw-r--r--src/pluto/ipsec_doi.c364
-rw-r--r--src/pluto/kernel.c5
-rw-r--r--src/pluto/keys.c633
-rw-r--r--src/pluto/keys.h35
-rw-r--r--src/pluto/ocsp.c138
-rw-r--r--src/pluto/pgpcert.c (renamed from src/pluto/pgp.c)282
-rw-r--r--src/pluto/pgpcert.h (renamed from src/pluto/pgp.h)34
-rw-r--r--src/pluto/pkcs1.c602
-rw-r--r--src/pluto/pkcs1.h86
-rw-r--r--src/pluto/pkcs7.c83
-rw-r--r--src/pluto/pkcs7.h10
-rw-r--r--src/pluto/rcv_whack.c9
-rw-r--r--src/pluto/x509.c350
-rw-r--r--src/pluto/x509.h104
-rw-r--r--src/scepclient/Makefile.am9
-rw-r--r--src/scepclient/pkcs10.c38
-rw-r--r--src/scepclient/pkcs10.h25
-rw-r--r--src/scepclient/rsakey.c313
-rw-r--r--src/scepclient/scep.c47
-rw-r--r--src/scepclient/scep.h26
-rw-r--r--src/scepclient/scepclient.c49
-rw-r--r--src/strongswan.conf18
46 files changed, 1802 insertions, 2596 deletions
diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am
index 089d089f5..c2a1a5a4f 100644
--- a/src/libstrongswan/Makefile.am
+++ b/src/libstrongswan/Makefile.am
@@ -41,8 +41,9 @@ credentials/certificates/ac.h \
credentials/certificates/crl.h credentials/certificates/crl.c \
credentials/certificates/ocsp_request.h \
credentials/certificates/ocsp_response.h credentials/certificates/ocsp_response.c \
-fetcher/fetcher.h fetcher/fetcher_manager.h fetcher/fetcher_manager.c \
database/database.h database/database_factory.h database/database_factory.c \
+fetcher/fetcher.h fetcher/fetcher_manager.h fetcher/fetcher_manager.c \
+pgp/pgp.c pgp/pgp.h \
utils.h utils.c \
utils/host.c utils/host.h \
utils/identification.c utils/identification.h \
diff --git a/src/libstrongswan/asn1/asn1.c b/src/libstrongswan/asn1/asn1.c
index 85f906caa..d57444d67 100644
--- a/src/libstrongswan/asn1/asn1.c
+++ b/src/libstrongswan/asn1/asn1.c
@@ -255,7 +255,7 @@ chunk_t asn1_build_known_oid(int n)
/*
* Defined in header.
*/
-u_int asn1_length(chunk_t *blob)
+size_t asn1_length(chunk_t *blob)
{
u_char n;
size_t len;
@@ -675,7 +675,7 @@ chunk_t asn1_simple_object(asn1_t tag, chunk_t content)
}
/**
- * Build an ASN.1 BITSTRING object
+ * Build an ASN.1 BIT_STRING object
*/
chunk_t asn1_bitstring(const char *mode, chunk_t content)
{
@@ -692,6 +692,41 @@ chunk_t asn1_bitstring(const char *mode, chunk_t content)
}
/**
+ * Build an ASN.1 INTEGER object
+ */
+chunk_t asn1_integer(const char *mode, chunk_t content)
+{
+ chunk_t object;
+ size_t len;
+ u_char *pos;
+
+ if (content.len == 0 || (content.len == 1 && *content.ptr == 0x00))
+ {
+ /* a zero ASN.1 integer does not have a value field */
+ len = 0;
+ }
+ else
+ {
+ /* ASN.1 integers must be positive numbers in two's complement */
+ len = content.len + ((*content.ptr & 0x80) ? 1 : 0);
+ }
+ pos = asn1_build_object(&object, ASN1_INTEGER, len);
+ if (len > content.len)
+ {
+ *pos++ = 0x00;
+ }
+ if (len)
+ {
+ memcpy(pos, content.ptr, content.len);
+ }
+ if (*mode == 'm')
+ {
+ free(content.ptr);
+ }
+ return object;
+}
+
+/**
* Build an ASN.1 object from a variable number of individual chunks.
* Depending on the mode, chunks either are moved ('m') or copied ('c').
*/
diff --git a/src/libstrongswan/asn1/asn1.h b/src/libstrongswan/asn1/asn1.h
index 12390596a..6a2b594c0 100644
--- a/src/libstrongswan/asn1/asn1.h
+++ b/src/libstrongswan/asn1/asn1.h
@@ -120,7 +120,7 @@ chunk_t asn1_build_known_oid(int n);
* @param blob pointer to an ASN.1 coded blob
* @return length of ASN.1 object
*/
-u_int asn1_length(chunk_t *blob);
+size_t asn1_length(chunk_t *blob);
/**
* Parses an ASN.1 algorithmIdentifier object
@@ -228,6 +228,15 @@ chunk_t asn1_simple_object(asn1_t tag, chunk_t content);
chunk_t asn1_bitstring(const char *mode, chunk_t content);
/**
+ * Build an ASN.1 INTEGER object
+ *
+ * @param mode 'c' for copy or 'm' for move
+ * @param content content of the INTEGER
+ * @return chunk containing the ASN.1 coded INTEGER
+ */
+chunk_t asn1_integer(const char *mode, chunk_t content);
+
+/**
* Build an ASN.1 object from a variable number of individual chunks
*
* @param type ASN.1 type to be created
diff --git a/src/libstrongswan/credentials/builder.c b/src/libstrongswan/credentials/builder.c
index 0bca198f1..701cbcde3 100644
--- a/src/libstrongswan/credentials/builder.c
+++ b/src/libstrongswan/credentials/builder.c
@@ -20,6 +20,8 @@ ENUM(builder_part_names, BUILD_FROM_FILE, BUILD_END,
"BUILD_AGENT_SOCKET",
"BUILD_BLOB_ASN1_DER",
"BUILD_BLOB_ASN1_PEM",
+ "BUILD_BLOB_PGP",
+ "BUILD_BLOB_RFC_3110",
"BUILD_KEY_SIZE",
"BUILD_SIGNING_KEY",
"BUILD_SIGNING_CERT",
diff --git a/src/libstrongswan/credentials/builder.h b/src/libstrongswan/credentials/builder.h
index 4b3fb1ae4..01ccf2a5c 100644
--- a/src/libstrongswan/credentials/builder.h
+++ b/src/libstrongswan/credentials/builder.h
@@ -38,14 +38,18 @@ typedef builder_t* (*builder_constructor_t)(int subtype);
* Parts to build credentials from.
*/
enum builder_part_t {
- /** path to a file containing an ASN1 blob, char* */
+ /** path to a file containing an ASN.1 blob, char* */
BUILD_FROM_FILE,
/** unix socket of a ssh/pgp agent, char* */
BUILD_AGENT_SOCKET,
- /** DER encoded ASN1 blob, chunk_t */
+ /** DER encoded ASN.1 blob, chunk_t */
BUILD_BLOB_ASN1_DER,
- /** PEM encoded ASN1 blob, null terminated char* */
+ /** PEM encoded ASN.1 blob, null terminated char* */
BUILD_BLOB_ASN1_PEM,
+ /** OpenPGP key blob, chunk_t */
+ BUILD_BLOB_PGP,
+ /** RFC 3110 DNS public key blob, chunk_t */
+ BUILD_BLOB_RFC_3110,
/** key size in bits, as used for key generation, u_int */
BUILD_KEY_SIZE,
/** private key to use for signing, private_key_t* */
diff --git a/src/libstrongswan/credentials/credential_factory.c b/src/libstrongswan/credentials/credential_factory.c
index 76438a56c..2e9a541d4 100644
--- a/src/libstrongswan/credentials/credential_factory.c
+++ b/src/libstrongswan/credentials/credential_factory.c
@@ -156,6 +156,8 @@ static void* create(private_credential_factory_t *this, credential_type_t type,
case BUILD_END:
break;
case BUILD_BLOB_ASN1_DER:
+ case BUILD_BLOB_PGP:
+ case BUILD_BLOB_RFC_3110:
case BUILD_SERIAL:
builder->add(builder, part, va_arg(args, chunk_t));
continue;
diff --git a/src/libstrongswan/credentials/keys/private_key.h b/src/libstrongswan/credentials/keys/private_key.h
index 62f1167c4..f38af8ff4 100644
--- a/src/libstrongswan/credentials/keys/private_key.h
+++ b/src/libstrongswan/credentials/keys/private_key.h
@@ -80,6 +80,14 @@ struct private_key_t {
public_key_t* (*get_public_key)(private_key_t *this);
/**
+ * Check if two private keys are equal.
+ *
+ * @param other other private key
+ * @return TRUE, if equality
+ */
+ bool (*equals) (private_key_t *this, private_key_t *other);
+
+ /**
* Check if a private key belongs to a public key.
*
* @param public public key
diff --git a/src/libstrongswan/credentials/keys/public_key.c b/src/libstrongswan/credentials/keys/public_key.c
index f08b2dcce..c5b5d6f9a 100644
--- a/src/libstrongswan/credentials/keys/public_key.c
+++ b/src/libstrongswan/credentials/keys/public_key.c
@@ -15,13 +15,15 @@
#include "public_key.h"
-ENUM(key_type_names, KEY_RSA, KEY_ECDSA,
+ENUM(key_type_names, KEY_RSA, KEY_DSA,
"RSA",
- "ECDSA"
+ "ECDSA",
+ "DSA"
);
ENUM(signature_scheme_names, SIGN_DEFAULT, SIGN_ECDSA_521,
"DEFAULT",
+ "RSA_EMSA_PKCS1_NULL",
"RSA_EMSA_PKCS1_MD5",
"RSA_EMSA_PKCS1_SHA1",
"RSA_EMSA_PKCS1_SHA256",
diff --git a/src/libstrongswan/credentials/keys/public_key.h b/src/libstrongswan/credentials/keys/public_key.h
index 86571b013..d78791aeb 100644
--- a/src/libstrongswan/credentials/keys/public_key.h
+++ b/src/libstrongswan/credentials/keys/public_key.h
@@ -34,12 +34,14 @@ typedef enum signature_scheme_t signature_scheme_t;
*/
enum key_type_t {
/** key type wildcard */
- KEY_ANY,
+ KEY_ANY = 0,
/** RSA crypto system as in PKCS#1 */
- KEY_RSA,
+ KEY_RSA = 1,
/** ECDSA as in ANSI X9.62 */
- KEY_ECDSA,
- /** DSS, ElGamal, ... */
+ KEY_ECDSA = 2,
+ /** DSA */
+ KEY_DSA = 3,
+ /** ElGamal, ... */
};
/**
@@ -50,29 +52,33 @@ extern enum_name_t *key_type_names;
/**
* Signature scheme for signature creation
*
- * EMSA-PKCS1 signatures are from the PKCS#1 standard. They include
- * the ASN1-OID of the used hash algorithm.
+ * EMSA-PKCS1 signatures are defined in PKCS#1 standard.
+ * A prepended ASN.1 encoded digestInfo field contains the
+ * OID of the used hash algorithm. The ASN.1 type of the PKCS#7
+ * variants is OCTET_STRING instead of the default BIT_STRING.
*/
enum signature_scheme_t {
- /** default scheme of that underlying crypto system */
+ /** Default scheme of the underlying crypto system */
SIGN_DEFAULT,
- /** EMSA-PKCS1 with MD5 */
+ /** EMSA-PKCS1_v1.5 signature over digest without digestInfo */
+ SIGN_RSA_EMSA_PKCS1_NULL,
+ /** EMSA-PKCS1_v1.5 signature as in PKCS#1 using RSA and MD5 */
SIGN_RSA_EMSA_PKCS1_MD5,
- /** EMSA-PKCS1 signature as in PKCS#1 standard using SHA1 as hash. */
+ /** EMSA-PKCS1_v1.5 signature as in PKCS#1 using RSA and SHA-1 */
SIGN_RSA_EMSA_PKCS1_SHA1,
- /** EMSA-PKCS1 signature as in PKCS#1 standard using SHA256 as hash. */
+ /** EMSA-PKCS1_v1.5 signature as in PKCS#1 using RSA and SHA-256 */
SIGN_RSA_EMSA_PKCS1_SHA256,
- /** EMSA-PKCS1 signature as in PKCS#1 standard using SHA384 as hash. */
+ /** EMSA-PKCS1_v1.5 signature as in PKCS#1 using RSA and SHA-384 */
SIGN_RSA_EMSA_PKCS1_SHA384,
- /** EMSA-PKCS1 signature as in PKCS#1 standard using SHA512 as hash. */
+ /** EMSA-PKCS1_v1.5 signature as in PKCS#1 using RSA and SHA-512 */
SIGN_RSA_EMSA_PKCS1_SHA512,
- /** ECDSA using SHA-1 as hash. */
+ /** ECDSA with SHA-1 */
SIGN_ECDSA_WITH_SHA1,
- /** ECDSA with SHA-256 on the P-256 curve as in RFC 4754 */
+ /** ECDSA on the P-256 curve with SHA-256 as in RFC 4754 */
SIGN_ECDSA_256,
- /** ECDSA with SHA-384 on the P-384 curve as in RFC 4754 */
+ /** ECDSA on the P-384 curve with SHA-384 as in RFC 4754 */
SIGN_ECDSA_384,
- /** ECDSA with SHA-512 on the P-521 curve as in RFC 4754 */
+ /** ECDSA on the P-521 curve with SHA-512 as in RFC 4754 */
SIGN_ECDSA_521,
};
@@ -107,13 +113,21 @@ struct public_key_t {
/**
* Encrypt a chunk of data.
*
- * @param crypto chunk containing plaintext data
- * @param plain where to allocate encrypted data
+ * @param plain chunk containing plaintext data
+ * @param crypto where to allocate encrypted data
* @return TRUE if data successfully encrypted
*/
- bool (*encrypt)(public_key_t *this, chunk_t crypto, chunk_t *plain);
+ bool (*encrypt)(public_key_t *this, chunk_t plain, chunk_t *crypto);
/**
+ * Check if two public keys are equal.
+ *
+ * @param other other public key
+ * @return TRUE, if equality
+ */
+ bool (*equals)(public_key_t *this, public_key_t *other);
+
+ /**
* Get the strength of the key in bytes.
*
* @return strength of the key in bytes
diff --git a/src/scepclient/rsakey.h b/src/libstrongswan/pgp/pgp.c
index f9245d25b..f1f924774 100644
--- a/src/scepclient/rsakey.h
+++ b/src/libstrongswan/pgp/pgp.c
@@ -1,11 +1,6 @@
-/**
- * @file rsakey.h
- * @brief Functions for RSA key generation
- */
-
-/*
- * Copyright (C) 1999, 2000, 2001 Henry Spencer.
- * Copyright (C) 2005 Jan Hutter, Martin Willi
+/*
+ * Copyright (C) 2002-2009 Andreas Steffen
+ *
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -18,12 +13,40 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
+
+#include "pgp.h"
-#ifndef RSAKEY_H_
-#define RSAKEY_H_
+ENUM(pgp_sym_alg_names, PGP_SYM_ALG_PLAIN, PGP_SYM_ALG_TWOFISH,
+ "PLAINTEXT",
+ "IDEA",
+ "3DES",
+ "CAST5",
+ "BLOWFISH",
+ "SAFER",
+ "DES",
+ "AES_128",
+ "AES_192",
+ "AES_256",
+ "TWOFISH"
+);
+
+/*
+ * Defined in header.
+ */
+size_t pgp_length(chunk_t *blob, size_t len)
+{
+ size_t size = 0;
-#include "../pluto/pkcs1.h"
+ if (len > blob->len)
+ {
+ return PGP_INVALID_LENGTH;
+ }
+ blob->len -= len;
-extern err_t generate_rsa_private_key(int nbits, RSA_private_key_t *key);
+ while (len-- > 0)
+ {
+ size = 256*size + *blob->ptr++;
+ }
+ return size;
+}
-#endif // RSAKEY_H_
diff --git a/src/libstrongswan/pgp/pgp.h b/src/libstrongswan/pgp/pgp.h
new file mode 100644
index 000000000..b12031970
--- /dev/null
+++ b/src/libstrongswan/pgp/pgp.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2002-2009 Andreas Steffen
+ *
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * 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.
+ */
+
+/**
+ * @defgroup pgpi pgp
+ * @{ @ingroup pgp
+ */
+
+#ifndef PGP_H_
+#define PGP_H_
+
+typedef enum pgp_sym_alg_t pgp_sym_alg_t;
+
+#include <chunk.h>
+#include <enum.h>
+
+/**
+ * OpenPGP symmetric key algorithms defined in section 9.2 of RFC 4880
+ */
+enum pgp_sym_alg_t {
+ PGP_SYM_ALG_PLAIN = 0,
+ PGP_SYM_ALG_IDEA = 1,
+ PGP_SYM_ALG_3DES = 2,
+ PGP_SYM_ALG_CAST5 = 3,
+ PGP_SYM_ALG_BLOWFISH = 4,
+ PGP_SYM_ALG_SAFER = 5,
+ PGP_SYM_ALG_DES = 6,
+ PGP_SYM_ALG_AES_128 = 7,
+ PGP_SYM_ALG_AES_192 = 8,
+ PGP_SYM_ALG_AES_256 = 9,
+ PGP_SYM_ALG_TWOFISH = 10
+};
+
+/**
+ * Enum names for pgp_sym_alg_t
+ */
+extern enum_name_t *pgp_sym_alg_names;
+
+#define PGP_INVALID_LENGTH 0xffffffff
+
+/**
+ * Returns the length of an OpenPGP (RFC 4880) packet
+ * The blob pointer is advanced past the length field
+ *
+ * @param blob pointer to an OpenPGP blob
+ * @param len size of the length field
+ * @return length of the next OpenPGP packet
+ */
+size_t pgp_length(chunk_t *blob, size_t len);
+
+#endif /** PGP_H_ @}*/
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",
diff --git a/src/pluto/Makefile.am b/src/pluto/Makefile.am
index 2c91c3d84..269401121 100644
--- a/src/pluto/Makefile.am
+++ b/src/pluto/Makefile.am
@@ -38,8 +38,7 @@ nat_traversal.c nat_traversal.h \
ocsp.c ocsp.h \
packet.c packet.h \
pem.c pem.h \
-pgp.c pgp.h \
-pkcs1.c pkcs1.h \
+pgpcert.c pgpcert.h \
pkcs7.c pkcs7.h \
plutomain.c \
rcv_whack.c rcv_whack.h \
diff --git a/src/pluto/ac.c b/src/pluto/ac.c
index 3c886f973..3b5df9738 100644
--- a/src/pluto/ac.c
+++ b/src/pluto/ac.c
@@ -783,8 +783,8 @@ bool verify_x509acert(x509acert_t *ac, bool strict)
DBG_log("issuer aacert found")
)
- if (!check_signature(ac->certificateInfo, ac->signature
- , ac->algorithm, ac->algorithm, aacert))
+ if (!x509_check_signature(ac->certificateInfo, ac->signature, ac->algorithm,
+ aacert))
{
plog("attribute certificate signature is invalid");
return FALSE;
diff --git a/src/pluto/ca.c b/src/pluto/ca.c
index 363a78b92..4fdb8cfe7 100644
--- a/src/pluto/ca.c
+++ b/src/pluto/ca.c
@@ -385,8 +385,8 @@ trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain)
}
}
- if (!check_signature(cert->tbsCertificate, cert->signature
- , cert->algorithm, cert->algorithm, authcert))
+ if (!x509_check_signature(cert->tbsCertificate, cert->signature,
+ cert->algorithm, authcert))
{
plog("certificate signature is invalid");
unlock_authcert_list("trust_authcert_candidate");
diff --git a/src/pluto/certs.c b/src/pluto/certs.c
index 7d78f229a..29e7dbfa4 100644
--- a/src/pluto/certs.c
+++ b/src/pluto/certs.c
@@ -1,5 +1,7 @@
/* Certificate support for IKE authentication
- * Copyright (C) 2002-2004 Andreas Steffen, Zuercher Hochschule Winterthur
+ * Copyright (C) 2002-2009 Andreas Steffen
+ *
+ * HSR - Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -18,17 +20,15 @@
#include <freeswan.h>
+#include "library.h"
#include "asn1/asn1.h"
#include "constants.h"
#include "defs.h"
#include "log.h"
#include "id.h"
-#include "x509.h"
-#include "pgp.h"
#include "pem.h"
#include "certs.h"
-#include "pkcs1.h"
/**
* used for initializatin of certs
@@ -118,14 +118,14 @@ bool load_coded_file(char *filename, prompt_pass_t *pass, const char *type,
}
/**
- * Loads a PKCS#1 or PGP private RSA key file
+ * Loads a PKCS#1 or PGP privatekey file
*/
-err_t load_rsa_private_key(char* filename, prompt_pass_t *pass,
- RSA_private_key_t *key)
+private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
+ key_type_t type)
{
- err_t ugh = NULL;
- bool pgp = FALSE;
+ private_key_t *key = NULL;
chunk_t blob = chunk_empty;
+ bool pgp = FALSE;
char *path = concatenate_paths(PRIVATE_KEY_PATH, filename);
@@ -133,20 +133,24 @@ err_t load_rsa_private_key(char* filename, prompt_pass_t *pass,
{
if (pgp)
{
- if (!parse_pgp(blob, NULL, key))
- ugh = "syntax error in PGP private key file";
+ parse_pgp(blob, NULL, &key);
}
else
{
- if (!pkcs1_parse_private_key(blob, key))
- ugh = "syntax error in PKCS#1 private key file";
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
+ BUILD_BLOB_ASN1_DER, blob, BUILD_END);
}
+ if (key == NULL)
+ {
+ plog("syntax error in %s private key file", pgp ? "PGP":"PKCS#");
+ }
free(blob.ptr);
}
else
- ugh = "error loading RSA private key file";
-
- return ugh;
+ {
+ plog("error loading RSA private key file");
+ }
+ return key;
}
/**
diff --git a/src/pluto/certs.h b/src/pluto/certs.h
index 1d9e984e9..a88fc152e 100644
--- a/src/pluto/certs.h
+++ b/src/pluto/certs.h
@@ -1,5 +1,7 @@
/* Certificate support for IKE authentication
- * Copyright (C) 2002-2004 Andreas Steffen, Zuercher Hochschule Winterthur
+ * Copyright (C) 2002-2009 Andreas Steffen
+ *
+ * HSR - Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -15,9 +17,10 @@
#ifndef _CERTS_H
#define _CERTS_H
-#include "pkcs1.h"
+#include <credentials/keys/private_key.h>
+
#include "x509.h"
-#include "pgp.h"
+#include "pgpcert.h"
/* path definitions for private keys, end certs,
* cacerts, attribute certs and crls
@@ -59,11 +62,11 @@ extern const cert_t empty_cert;
*/
extern bool no_cr_send;
-extern err_t load_rsa_private_key(char* filename, prompt_pass_t *pass
- , RSA_private_key_t *key);
+extern private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
+ key_type_t type);
extern chunk_t get_mycert(cert_t cert);
-extern bool load_coded_file(char *filename, prompt_pass_t *pass
- , const char *type, chunk_t *blob, bool *pgp);
+extern bool load_coded_file(char *filename, prompt_pass_t *pass,
+ const char *type, chunk_t *blob, bool *pgp);
extern bool load_cert(char *filename, const char *label, cert_t *cert);
extern bool load_host_cert(char *filename, cert_t *cert);
extern bool load_ca_cert(char *filename, cert_t *cert);
diff --git a/src/pluto/connections.c b/src/pluto/connections.c
index 960884e84..bdfdc10a0 100644
--- a/src/pluto/connections.c
+++ b/src/pluto/connections.c
@@ -29,13 +29,15 @@
#include <freeswan.h>
#include "kameipsec.h"
+#include <credentials/keys/private_key.h>
+
#include "constants.h"
#include "defs.h"
#include "id.h"
#include "x509.h"
#include "ca.h"
#include "crl.h"
-#include "pgp.h"
+#include "pgpcert.h"
#include "certs.h"
#include "ac.h"
#include "smartcard.h"
@@ -2155,17 +2157,16 @@ check_key_recs(enum myid_state try_state
* If so, treat as a kind of failure.
*/
enum myid_state old_myid_state = myid_state;
- const struct RSA_private_key *our_RSA_pri;
+ private_key_t *private;
err_t ugh = NULL;
myid_state = try_state;
- if (old_myid_state != myid_state
- && old_myid_state == MYID_SPECIFIED)
+ if (old_myid_state != myid_state && old_myid_state == MYID_SPECIFIED)
{
ugh = "%myid was specified while we were guessing";
}
- else if ((our_RSA_pri = get_RSA_private_key(c)) == NULL)
+ else if ((private = get_private_key(c)) == NULL)
{
ugh = "we don't know our own RSA key";
}
@@ -2185,7 +2186,7 @@ check_key_recs(enum myid_state try_state
{
ugh = "all our KEY RRs have the wrong public key";
if (kr->key->alg == PUBKEY_ALG_RSA
- && same_RSA_public_key(&our_RSA_pri->pub, &kr->key->u.rsa))
+ && private->belongs_to(private, &kr->key->public_key))
{
ugh = NULL; /* good! */
break;
@@ -2198,10 +2199,9 @@ check_key_recs(enum myid_state try_state
}
#endif /* USE_KEYRR */
-static err_t
-check_txt_recs(enum myid_state try_state
-, const struct connection *c
-, struct adns_continuation *ac)
+static err_t check_txt_recs(enum myid_state try_state,
+ const struct connection *c,
+ struct adns_continuation *ac)
{
/* Check if TXT lookup yielded good results.
* Looking up based on our ID. Used if
@@ -2211,7 +2211,7 @@ check_txt_recs(enum myid_state try_state
* If so, treat as a kind of failure.
*/
enum myid_state old_myid_state = myid_state;
- const struct RSA_private_key *our_RSA_pri;
+ private_key_t *private;
err_t ugh = NULL;
myid_state = try_state;
@@ -2221,7 +2221,7 @@ check_txt_recs(enum myid_state try_state
{
ugh = "%myid was specified while we were guessing";
}
- else if ((our_RSA_pri = get_RSA_private_key(c)) == NULL)
+ else if ((private = get_private_key(c)) == NULL)
{
ugh = "we don't know our own RSA key";
}
@@ -2239,9 +2239,11 @@ check_txt_recs(enum myid_state try_state
ugh = "no TXT RR found for us";
for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
{
+ public_key_t *pub_key = gwp->key->public_key;
+
ugh = "all our TXT RRs have the wrong public key";
- if (gwp->key->alg == PUBKEY_ALG_RSA
- && same_RSA_public_key(&our_RSA_pri->pub, &gwp->key->u.rsa))
+ if (pub_key->get_type(pub_key) == KEY_RSA &&
+ private->belongs_to(private, pub_key))
{
ugh = NULL; /* good! */
break;
@@ -2249,7 +2251,9 @@ check_txt_recs(enum myid_state try_state
}
}
if (ugh != NULL)
+ {
myid_state = old_myid_state;
+ }
return ugh;
}
@@ -2513,13 +2517,13 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
* a chance that we did the wrong query.
* If so, treat as a kind of failure.
*/
- const struct RSA_private_key *our_RSA_pri = get_RSA_private_key(c);
+ private_key_t *private = get_private_key(c);
next_step = fos_his_client; /* normal situation */
passert(sr != NULL);
- if (our_RSA_pri == NULL)
+ if (private == NULL)
{
ugh = "we don't know our own RSA key";
}
@@ -2560,7 +2564,7 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
ugh = NULL; /* good! */
break;
}
- if (same_RSA_public_key(&our_RSA_pri->pub, &gwp->key->u.rsa))
+ if (private->belongs_to(private, gwp->key->public_key))
{
ugh = NULL; /* good! */
break;
@@ -2579,11 +2583,11 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
* a chance that we did the wrong query.
* If so, treat as a kind of failure.
*/
- const struct RSA_private_key *our_RSA_pri = get_RSA_private_key(c);
+ private_key_t *private = get_private_key(c);
next_step = fos_his_client; /* unless we decide to look for KEY RR */
- if (our_RSA_pri == NULL)
+ if (private == NULL)
{
ugh = "we don't know our own RSA key";
}
@@ -2604,8 +2608,8 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
passert(same_id(&gwp->gw_id, &sr->this.id));
ugh = "TXT RR for us has wrong key";
- if (gwp->gw_key_present
- && same_RSA_public_key(&our_RSA_pri->pub, &gwp->key->u.rsa))
+ if (gwp->gw_key_present &&
+ private->belongs_to(private, gwp->key->public_key))
{
DBG(DBG_CONTROL,
DBG_log("initiate on demand found TXT with right public key at: %s"
@@ -2639,11 +2643,11 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
* a chance that we did the wrong query.
* If so, treat as a kind of failure.
*/
- const struct RSA_private_key *our_RSA_pri = get_RSA_private_key(c);
+ private_key_t *private = get_private_key(c);
next_step = fos_his_client; /* always */
- if (our_RSA_pri == NULL)
+ if (private == NULL)
{
ugh = "we don't know our own RSA key";
}
@@ -2663,7 +2667,7 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
{
ugh = "all our KEY RRs have the wrong public key (and no good TXT RR)";
if (kr->key->alg == PUBKEY_ALG_RSA
- && same_RSA_public_key(&our_RSA_pri->pub, &kr->key->u.rsa))
+ && private->belongs_to(private, kr->key->public_key))
{
/* do this only once a day */
if (!logged_txt_warning)
@@ -3399,7 +3403,7 @@ refine_host_connection(const struct state *st, const struct id *peer_id
* We must at least be able to find our private key
.*/
if (d->spd.this.sc == NULL /* no smartcard */
- && get_RSA_private_key(d) == NULL) /* no private key */
+ && get_private_key(d) == NULL) /* no private key */
continue;
break;
diff --git a/src/pluto/crl.c b/src/pluto/crl.c
index 1d9b5445e..c800f2acc 100644
--- a/src/pluto/crl.c
+++ b/src/pluto/crl.c
@@ -238,8 +238,8 @@ bool insert_crl(chunk_t blob, chunk_t crl_uri, bool cache_crl)
)
/* check the issuer's signature of the crl */
- valid_sig = check_signature(crl->tbsCertList, crl->signature
- , crl->algorithm, crl->algorithm, issuer_cert);
+ valid_sig = x509_check_signature(crl->tbsCertList, crl->signature,
+ crl->algorithm, issuer_cert);
unlock_authcert_list("insert_crl");
if (!valid_sig)
@@ -656,8 +656,8 @@ verify_by_crl(const x509cert_t *cert, time_t *until, time_t *revocationDate
issuer_cert = get_authcert(crl->issuer, crl->authKeySerialNumber
, crl->authKeyID, AUTH_CA);
- valid = check_signature(crl->tbsCertList, crl->signature
- , crl->algorithm, crl->algorithm, issuer_cert);
+ valid = x509_check_signature(crl->tbsCertList, crl->signature,
+ crl->algorithm, issuer_cert);
unlock_authcert_list("verify_by_crl");
diff --git a/src/pluto/dnskey.c b/src/pluto/dnskey.c
index bd190530c..ed901ade5 100644
--- a/src/pluto/dnskey.c
+++ b/src/pluto/dnskey.c
@@ -29,6 +29,9 @@
#include <freeswan.h>
+#include <utils/identification.h>
+#include <credentials/keys/public_key.h>
+
#include "constants.h"
#include "adns.h" /* needs <resolv.h> */
#include "defs.h"
@@ -83,7 +86,9 @@ init_adns(void)
{
strcpy(adns_path_space, helper_bin_dir);
if (n > 0 && adns_path_space[n -1] != '/')
+ {
adns_path_space[n++] = '/';
+ }
}
}
else
@@ -95,25 +100,33 @@ init_adns(void)
n = readlink("/proc/self/exe", adns_path_space, sizeof(adns_path_space));
if (n < 0)
+ {
exit_log_errno((e
, "readlink(\"/proc/self/exe\") failed in init_adns()"));
-
+ }
}
if ((size_t)n > sizeof(adns_path_space) - sizeof(adns_name))
+ {
exit_log("path to %s is too long", adns_name);
+ }
while (n > 0 && adns_path_space[n - 1] != '/')
+ {
n--;
-
+ }
strcpy(adns_path_space + n, adns_name);
adns_path = adns_path_space;
}
if (access(adns_path, X_OK) < 0)
+ {
exit_log_errno((e, "%s missing or not executable", adns_path));
+ }
if (pipe(qfds) != 0 || pipe(afds) != 0)
+ {
exit_log_errno((e, "pipe(2) failed in init_adns()"));
+ }
adns_pid = fork();
switch (adns_pid)
@@ -128,7 +141,9 @@ init_adns(void)
* Take care to handle case where pipes already use these fds.
*/
if (afds[1] == 0)
+ {
afds[1] = dup(afds[1]); /* avoid being overwritten */
+ }
if (qfds[0] != 0)
{
dup2(qfds[0], 0);
@@ -140,16 +155,18 @@ init_adns(void)
close(qfds[1]);
}
if (afds[0] > 1)
+ {
close(afds[0]);
+ }
if (afds[1] > 1)
+ {
close(afds[1]);
-
+ }
DBG(DBG_DNS, execlp(adns_path, adns_name, "-d", NULL));
execlp(adns_path, adns_name, NULL);
exit_log_errno((e, "execlp of %s failed", adns_path));
}
-
default:
/* parent */
close(qfds[0]);
@@ -183,8 +200,10 @@ stop_adns(void)
else if (WIFEXITED(status))
{
if (WEXITSTATUS(status) != 0)
+ {
plog("ADNS process exited with status %d"
, (int) WEXITSTATUS(status));
+ }
}
else if (WIFSIGNALED(status))
{
@@ -227,8 +246,9 @@ decode_iii(u_char **pp, struct id *gw_id)
u_char under = *e;
if (p == e)
+ {
return "TXT " our_TXT_attr_string " badly formed (no gateway specified)";
-
+ }
*e = '\0';
if (*p == '@')
{
@@ -236,8 +256,10 @@ decode_iii(u_char **pp, struct id *gw_id)
err_t ugh = atoid(p, gw_id, FALSE);
if (ugh != NULL)
+ {
return builddiag("malformed FQDN in TXT " our_TXT_attr_string ": %s"
, ugh);
+ }
}
else
{
@@ -248,12 +270,14 @@ decode_iii(u_char **pp, struct id *gw_id)
, &ip);
if (ugh != NULL)
+ {
return builddiag("malformed IP address in TXT " our_TXT_attr_string ": %s"
, ugh);
-
+ }
if (isanyaddr(&ip))
+ {
return "gateway address must not be 0.0.0.0 or 0::0";
-
+ }
iptoid(&ip, gw_id);
}
@@ -278,14 +302,18 @@ process_txt_rr_body(u_char *str
/* is this for us? */
if (strncasecmp(p, our_TXT_attr, sizeof(our_TXT_attr)-1) != 0)
+ {
return NULL; /* neither interesting nor bad */
+ }
p += sizeof(our_TXT_attr) - 1; /* ignore our attribute name */
p += strspn(p, " \t"); /* ignore leading whitespace */
/* decode '(' nnn ')' */
if (*p != '(')
+ {
return "X-IPsec-Server missing '('";
+ }
{
char *e;
@@ -293,25 +321,30 @@ process_txt_rr_body(u_char *str
p++;
pref = strtoul(p, &e, 0);
if ((u_char *)e == p)
+ {
return "malformed X-IPsec-Server priority";
-
+ }
p = e + strspn(e, " \t");
if (*p != ')')
+ {
return "X-IPsec-Server priority missing ')'";
-
+ }
p++;
p += strspn(p, " \t");
if (pref > 0xFFFF)
+ {
return "X-IPsec-Server priority larger than 0xFFFF";
+ }
}
/* time for '=' */
if (*p != '=')
+ {
return "X-IPsec-Server priority missing '='";
-
+ }
p++;
p += strspn(p, " \t");
@@ -384,29 +417,34 @@ process_txt_rr_body(u_char *str
/* Decode base 64 encoding of key.
* Similar code is in process_lwdnsq_key.
*/
- u_char kb[RSA_MAX_ENCODING_BYTES]; /* plenty of space for binary form of public key */
- chunk_t kbc;
- struct RSA_public_key r;
-
- err_t ugh = ttodatav(p, 0, 64, kb, sizeof(kb), &kbc.len
- , diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS);
-
- if (ugh != NULL)
+ u_char buf[RSA_MAX_ENCODING_BYTES]; /* plenty of space for binary form of public key */
+ size_t sz;
+ err_t ugh;
+ chunk_t rfc3110_chunk;
+ public_key_t *key;
+
+ ugh = ttodatav(p, 0, 64, buf, sizeof(buf), &sz,
+ diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS);
+ if (ugh)
+ {
return builddiag("malformed key data: %s", ugh);
-
- if (kbc.len > sizeof(kb))
- return builddiag("key data larger than %lu bytes"
- , (unsigned long) sizeof(kb));
-
- kbc.ptr = kb;
- ugh = unpack_RSA_public_key(&r, &kbc);
- if (ugh != NULL)
- return builddiag("invalid key data: %s", ugh);
+ }
+ if (sz > sizeof(buf))
+ {
+ return builddiag("key data larger than %lu bytes",
+ (unsigned long) sizeof(buf));
+ }
+ rfc3110_chunk = chunk_create(buf, sz);
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_BLOB_RFC_3110, rfc3110_chunk,
+ BUILD_END);
+ if (key == NULL)
+ {
+ return builddiag("invalid key data");
+ }
/* now find a key entry to put it in */
- gi.key = public_key_from_rsa(&r);
-
- free_RSA_public_content(&r);
+ gi.key = public_key_from_rsa(key);
unreference_key(&cr->last_info);
cr->last_info = reference_key(gi.key);
@@ -426,13 +464,18 @@ process_txt_rr_body(u_char *str
{
char cidb[BUF_LEN];
char gwidb[BUF_LEN];
+ identification_t *keyid;
+ public_key_t *pub_key;
idtoa(client_id, cidb, sizeof(cidb));
idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
+ pub_key = gi.key->public_key;
+ keyid = pub_key->get_id(pub_key, ID_PUBKEY_SHA1);
+
if (gi.gw_key_present)
{
- DBG_log("gateway for %s is %s with key %s"
- , cidb, gwidb, gi.key->u.rsa.keyid);
+ DBG_log("gateway for %s is %s with key %Y"
+ , cidb, gwidb, keyid);
}
else
{
diff --git a/src/pluto/ipsec_doi.c b/src/pluto/ipsec_doi.c
index 52f5553f0..49f40e38d 100644
--- a/src/pluto/ipsec_doi.c
+++ b/src/pluto/ipsec_doi.c
@@ -34,6 +34,8 @@
#include <crypto/hashers/hasher.h>
#include <crypto/prfs/prf.h>
#include <crypto/rngs/rng.h>
+#include <credentials/keys/private_key.h>
+#include <credentials/keys/public_key.h>
#include "constants.h"
#include "defs.h"
@@ -1402,35 +1404,44 @@ static bool generate_skeyids_iv(struct state *st)
return prf_block_size;
}
-/* Create an RSA signature of a hash.
+/* Create a public key signature of a hash.
* Poorly specified in draft-ietf-ipsec-ike-01.txt 6.1.1.2.
* Use PKCS#1 version 1.5 encryption of hash (called
* RSAES-PKCS1-V1_5) in PKCS#2.
*/
-static size_t RSA_sign_hash(struct connection *c, u_char sig_val[RSA_MAX_OCTETS],
- const u_char *hash_val, size_t hash_len)
+static size_t sign_hash(struct connection *c, u_char sig_val[RSA_MAX_OCTETS],
+ u_char *hash_val, size_t hash_len)
{
size_t sz = 0;
smartcard_t *sc = c->spd.this.sc;
if (sc == NULL) /* no smartcard */
{
- const struct RSA_private_key *k = get_RSA_private_key(c);
+ chunk_t hash, sig;
+ private_key_t *private = get_private_key(c);
- if (k == NULL)
+ if (private == NULL)
+ {
return 0; /* failure: no key to use */
-
- sz = k->pub.k;
+ }
+ sz = private->get_keysize(private);
passert(RSA_MIN_OCTETS <= sz && 4 + hash_len < sz && sz <= RSA_MAX_OCTETS);
- sign_hash(k, hash_val, hash_len, sig_val, sz);
+ hash = chunk_create(hash_val, hash_len);
+ sig = chunk_create(sig_val, sz);
+ if (!private->sign(private, SIGN_RSA_EMSA_PKCS1_NULL, hash, &sig))
+ {
+ return 0;
+ }
+ memcpy(sig_val, sig.ptr, sz);
+ free(sig.ptr);
}
else if (sc->valid) /* if valid pin then sign hash on the smartcard */
{
- lock_certs_and_keys("RSA_sign_hash");
+ lock_certs_and_keys("sign_hash");
if (!scx_establish_context(sc) || !scx_login(sc))
{
scx_release_context(sc);
- unlock_certs_and_keys("RSA_sign_hash");
+ unlock_certs_and_keys("sign_hash");
return 0;
}
@@ -1439,7 +1450,7 @@ static size_t RSA_sign_hash(struct connection *c, u_char sig_val[RSA_MAX_OCTETS]
{
plog("failed to get keylength from smartcard");
scx_release_context(sc);
- unlock_certs_and_keys("RSA_sign_hash");
+ unlock_certs_and_keys("sign_hash");
return 0;
}
@@ -1450,142 +1461,11 @@ static size_t RSA_sign_hash(struct connection *c, u_char sig_val[RSA_MAX_OCTETS]
sz = scx_sign_hash(sc, hash_val, hash_len, sig_val, sz) ? sz : 0;
if (!pkcs11_keep_state)
scx_release_context(sc);
- unlock_certs_and_keys("RSA_sign_hash");
+ unlock_certs_and_keys("sign_hash");
}
return sz;
}
-/* Check a Main Mode RSA Signature against computed hash using RSA public key k.
- *
- * As a side effect, on success, the public key is copied into the
- * state object to record the authenticator.
- *
- * Can fail because wrong public key is used or because hash disagrees.
- * We distinguish because diagnostics should also.
- *
- * The result is NULL if the Signature checked out.
- * Otherwise, the first character of the result indicates
- * how far along failure occurred. A greater character signifies
- * greater progress.
- *
- * Classes:
- * 0 reserved for caller
- * 1 SIG length doesn't match key length -- wrong key
- * 2-8 malformed ECB after decryption -- probably wrong key
- * 9 decrypted hash != computed hash -- probably correct key
- *
- * Although the math should be the same for generating and checking signatures,
- * it is not: the knowledge of the private key allows more efficient (i.e.
- * different) computation for encryption.
- */
-static err_t try_RSA_signature(const u_char hash_val[MAX_DIGEST_LEN],
- size_t hash_len, const pb_stream *sig_pbs,
- pubkey_t *kr, struct state *st)
-{
- const u_char *sig_val = sig_pbs->cur;
- size_t sig_len = pbs_left(sig_pbs);
- u_char s[RSA_MAX_OCTETS]; /* for decrypted sig_val */
- u_char *hash_in_s = &s[sig_len - hash_len];
- const struct RSA_public_key *k = &kr->u.rsa;
-
- /* decrypt the signature -- reversing RSA_sign_hash */
- if (sig_len != k->k)
- {
- /* XXX notification: INVALID_KEY_INFORMATION */
- return "1" "SIG length does not match public key length";
- }
-
- /* actual exponentiation; see PKCS#1 v2.0 5.1 */
- {
- chunk_t temp_s;
- mpz_t c;
-
- n_to_mpz(c, sig_val, sig_len);
- mpz_powm(c, c, &k->e, &k->n);
-
- temp_s = mpz_to_n(c, sig_len); /* back to octets */
- memcpy(s, temp_s.ptr, sig_len);
- free(temp_s.ptr);
- mpz_clear(c);
- }
-
- /* sanity check on signature: see if it matches
- * PKCS#1 v1.5 8.1 encryption-block formatting
- */
- {
- err_t ugh = NULL;
-
- if (s[0] != 0x00)
- ugh = "2" "no leading 00";
- else if (hash_in_s[-1] != 0x00)
- ugh = "3" "00 separator not present";
- else if (s[1] == 0x01)
- {
- const u_char *p;
-
- for (p = &s[2]; p != hash_in_s - 1; p++)
- {
- if (*p != 0xFF)
- {
- ugh = "4" "invalid Padding String";
- break;
- }
- }
- }
- else if (s[1] == 0x02)
- {
- const u_char *p;
-
- for (p = &s[2]; p != hash_in_s - 1; p++)
- {
- if (*p == 0x00)
- {
- ugh = "5" "invalid Padding String";
- break;
- }
- }
- }
- else
- ugh = "6" "Block Type not 01 or 02";
-
- if (ugh != NULL)
- {
- /* note: it might be a good idea to make sure that
- * an observer cannot tell what kind of failure happened.
- * I don't know what this means in practice.
- */
- /* We probably selected the wrong public key for peer:
- * SIG Payload decrypted into malformed ECB
- */
- /* XXX notification: INVALID_KEY_INFORMATION */
- return ugh;
- }
- }
-
- /* We have the decoded hash: see if it matches. */
- if (memcmp(hash_val, hash_in_s, hash_len) != 0)
- {
- /* good: header, hash, signature, and other payloads well-formed
- * good: we could find an RSA Sig key for the peer.
- * bad: hash doesn't match
- * Guess: sides disagree about key to be used.
- */
- DBG_cond_dump(DBG_CRYPT, "decrypted SIG", s, sig_len);
- DBG_cond_dump(DBG_CRYPT, "computed HASH", hash_val, hash_len);
- /* XXX notification: INVALID_HASH_INFORMATION */
- return "9" "authentication failure: received SIG does not match computed HASH, but message is well-formed";
- }
-
- /* Success: copy successful key into state.
- * There might be an old one if we previously aborted this
- * state transition.
- */
- unreference_key(&st->st_peer_pubkey);
- st->st_peer_pubkey = reference_key(kr);
-
- return NULL; /* happy happy */
-}
-
/* Check signature against all RSA public keys we can find.
* If we need keys from DNS KEY records, and they haven't been fetched,
* return STF_SUSPEND to ask for asynch DNS lookup.
@@ -1597,54 +1477,39 @@ static err_t try_RSA_signature(const u_char hash_val[MAX_DIGEST_LEN],
* If only we had coroutines.
*/
struct tac_state {
- /* RSA_check_signature's args that take_a_crack needs */
struct state *st;
- const u_char *hash_val;
- size_t hash_len;
- const pb_stream *sig_pbs;
-
- /* state carried between calls */
- err_t best_ugh; /* most successful failure */
+ chunk_t hash;
+ chunk_t sig;
int tried_cnt; /* number of keys tried */
- char tried[50]; /* keyids of tried public keys */
- char *tn; /* roof of tried[] */
};
-static bool take_a_crack(struct tac_state *s, pubkey_t *kr,
- const char *story USED_BY_DEBUG)
+static bool take_a_crack(struct tac_state *s, pubkey_t *kr)
{
- err_t ugh = try_RSA_signature(s->hash_val, s->hash_len, s->sig_pbs
- , kr, s->st);
- const struct RSA_public_key *k = &kr->u.rsa;
+ public_key_t *pub_key = kr->public_key;
+ identification_t *keyid = pub_key->get_id(pub_key, ID_PUBKEY_SHA1);
s->tried_cnt++;
- if (ugh == NULL)
+
+ if (pub_key->verify(pub_key, SIGN_RSA_EMSA_PKCS1_NULL, s->hash, s->sig))
{
- DBG(DBG_CRYPT | DBG_CONTROL
- , DBG_log("an RSA Sig check passed with *%s [%s]"
- , k->keyid, story));
+ DBG(DBG_CRYPT | DBG_CONTROL,
+ DBG_log("signature check passed with keyid %Y", keyid)
+ )
+ unreference_key(&s->st->st_peer_pubkey);
+ s->st->st_peer_pubkey = reference_key(kr);
return TRUE;
}
else
{
- DBG(DBG_CRYPT
- , DBG_log("an RSA Sig check failure %s with *%s [%s]"
- , ugh + 1, k->keyid, story));
- if (s->best_ugh == NULL || s->best_ugh[0] < ugh[0])
- s->best_ugh = ugh;
- if (ugh[0] > '0'
- && s->tn - s->tried + KEYID_BUF + 2 < (ptrdiff_t)sizeof(s->tried))
- {
- strcpy(s->tn, " *");
- strcpy(s->tn + 2, k->keyid);
- s->tn += strlen(s->tn);
- }
+ DBG(DBG_CRYPT,
+ DBG_log("signature check failed with keyid %Y", keyid)
+ )
return FALSE;
}
}
static stf_status RSA_check_signature(const struct id* peer, struct state *st,
- const u_char hash_val[MAX_DIGEST_LEN],
+ u_char hash_val[MAX_DIGEST_LEN],
size_t hash_len, const pb_stream *sig_pbs,
#ifdef USE_KEYRR
const pubkey_list_t *keys_from_dns,
@@ -1653,16 +1518,11 @@ static stf_status RSA_check_signature(const struct id* peer, struct state *st,
{
const struct connection *c = st->st_connection;
struct tac_state s;
- err_t dns_ugh = NULL;
s.st = st;
- s.hash_val = hash_val;
- s.hash_len = hash_len;
- s.sig_pbs = sig_pbs;
-
- s.best_ugh = NULL;
+ s.hash = chunk_create(hash_val, hash_len);
+ s.sig = chunk_create(sig_pbs->cur, pbs_left(sig_pbs));
s.tried_cnt = 0;
- s.tn = s.tried;
/* try all gateway records hung off c */
if (c->policy & POLICY_OPPO)
@@ -1672,10 +1532,11 @@ static stf_status RSA_check_signature(const struct id* peer, struct state *st,
for (gw = c->gw_info; gw != NULL; gw = gw->next)
{
/* only consider entries that have a key and are for our peer */
- if (gw->gw_key_present
- && same_id(&gw->gw_id, &c->spd.that.id)
- && take_a_crack(&s, gw->key, "key saved from DNS TXT"))
+ if (gw->gw_key_present && same_id(&gw->gw_id, &c->spd.that.id)&&
+ take_a_crack(&s, gw->key))
+ {
return STF_OK;
+ }
}
}
@@ -1688,8 +1549,9 @@ static stf_status RSA_check_signature(const struct id* peer, struct state *st,
for (p = pubkeys; p != NULL; p = *pp)
{
pubkey_t *key = p->key;
+ key_type_t type = key->public_key->get_type(key->public_key);
- if (key->alg == PUBKEY_ALG_RSA && same_id(peer, &key->id))
+ if (type == KEY_RSA && same_id(peer, &key->id))
{
time_t now = time(NULL);
@@ -1702,18 +1564,19 @@ static stf_status RSA_check_signature(const struct id* peer, struct state *st,
continue; /* continue with next public key */
}
- if (take_a_crack(&s, key, "preloaded key"))
- return STF_OK;
+ if (take_a_crack(&s, key))
+ {
+ return STF_OK;
+ }
}
pp = &p->next;
}
}
- /* if no key was found (evidenced by best_ugh == NULL)
- * and that side of connection is key_from_DNS_on_demand
- * then go search DNS for keys for peer.
+ /* if no key was found and that side of connection is
+ * key_from_DNS_on_demand then go search DNS for keys for peer.
*/
- if (s.best_ugh == NULL && c->spd.that.key_from_DNS_on_demand)
+ if (s.tried_cnt == 0 && c->spd.that.key_from_DNS_on_demand)
{
if (gateways_from_dns != NULL)
{
@@ -1721,9 +1584,12 @@ static stf_status RSA_check_signature(const struct id* peer, struct state *st,
const struct gw_info *gwp;
for (gwp = gateways_from_dns; gwp != NULL; gwp = gwp->next)
- if (gwp->gw_key_present
- && take_a_crack(&s, gwp->key, "key from DNS TXT"))
+ {
+ if (gwp->gw_key_present && take_a_crack(&s, gwp->key))
+ {
return STF_OK;
+ }
+ }
}
#ifdef USE_KEYRR
else if (keys_from_dns != NULL)
@@ -1732,9 +1598,12 @@ static stf_status RSA_check_signature(const struct id* peer, struct state *st,
const pubkey_list_t *kr;
for (kr = keys_from_dns; kr != NULL; kr = kr->next)
- if (kr->key->alg == PUBKEY_ALG_RSA
- && take_a_crack(&s, kr->key, "key from DNS KEY"))
+ {
+ if (kr->key->alg == PUBKEY_ALG_RSA && take_a_crack(&s, kr->key))
+ {
return STF_OK;
+ }
+ }
}
#endif /* USE_KEYRR */
else
@@ -1748,53 +1617,32 @@ static stf_status RSA_check_signature(const struct id* peer, struct state *st,
{
char id_buf[BUF_LEN]; /* arbitrary limit on length of ID reported */
- (void) idtoa(peer, id_buf, sizeof(id_buf));
+ idtoa(peer, id_buf, sizeof(id_buf));
- if (s.best_ugh == NULL)
+ if (s.tried_cnt == 0)
{
- if (dns_ugh == NULL)
- loglog(RC_LOG_SERIOUS, "no RSA public key known for '%s'"
- , id_buf);
- else
- loglog(RC_LOG_SERIOUS, "no RSA public key known for '%s'"
- "; DNS search for KEY failed (%s)"
- , id_buf, dns_ugh);
-
- /* ??? is this the best code there is? */
- return STF_FAIL + INVALID_KEY_INFORMATION;
+ loglog(RC_LOG_SERIOUS, "no public key known for '%s'", id_buf);
}
-
- if (s.best_ugh[0] == '9')
+ else if (s.tried_cnt == 1)
{
- loglog(RC_LOG_SERIOUS, "%s", s.best_ugh + 1);
- /* XXX Could send notification back */
- return STF_FAIL + INVALID_HASH_INFORMATION;
+ loglog(RC_LOG_SERIOUS, "signature check for '%s' failed: "
+ " wrong key?; tried %d", id_buf, s.tried_cnt);
+ DBG(DBG_CONTROL,
+ DBG_log("public key for '%s' failed: "
+ "decrypted SIG payload into a malformed ECB", id_buf)
+ )
}
else
{
- if (s.tried_cnt == 1)
- {
- loglog(RC_LOG_SERIOUS
- , "Signature check (on %s) failed (wrong key?); tried%s"
- , id_buf, s.tried);
- DBG(DBG_CONTROL,
- DBG_log("public key for %s failed:"
- " decrypted SIG payload into a malformed ECB (%s)"
- , id_buf, s.best_ugh + 1));
- }
- else
- {
- loglog(RC_LOG_SERIOUS
- , "Signature check (on %s) failed:"
- " tried%s keys but none worked."
- , id_buf, s.tried);
- DBG(DBG_CONTROL,
- DBG_log("all %d public keys for %s failed:"
- " best decrypted SIG payload into a malformed ECB (%s)"
- , s.tried_cnt, id_buf, s.best_ugh + 1));
- }
- return STF_FAIL + INVALID_KEY_INFORMATION;
+ loglog(RC_LOG_SERIOUS, "signature check for '%s' failed: "
+ "tried %d keys but none worked.", id_buf, s.tried_cnt);
+ DBG(DBG_CONTROL,
+ DBG_log("all %d public keys for '%s' failed: "
+ "best decrypted SIG payload into a malformed ECB",
+ s.tried_cnt, id_buf)
+ )
}
+ return STF_FAIL + INVALID_KEY_INFORMATION;
}
}
@@ -2245,6 +2093,7 @@ static void decode_cert(struct msg_digest *md)
{
plog("X.509 certificate rejected");
}
+ DESTROY_IF(cert.public_key);
free_generalNames(cert.subjectAltName, FALSE);
free_generalNames(cert.crlDistributionPoints, FALSE);
}
@@ -2749,9 +2598,9 @@ static bool has_preloaded_public_key(struct state *st)
for (p = pubkeys; p != NULL; p = p->next)
{
pubkey_t *key = p->key;
+ key_type_t type = key->public_key->get_type(key->public_key);
- if (key->alg == PUBKEY_ALG_RSA &&
- same_id(&c->spd.that.id, &key->id) &&
+ if (type == KEY_RSA && same_id(&c->spd.that.id, &key->id) &&
key->until_time == UNDEFINED_TIME)
{
/* found a preloaded public key */
@@ -3595,12 +3444,12 @@ stf_status main_inR2_outI3(struct msg_digest *md)
{
/* SIG_I out */
u_char sig_val[RSA_MAX_OCTETS];
- size_t sig_len = RSA_sign_hash(st->st_connection
- , sig_val, hash_val, hash_len);
+ size_t sig_len = sign_hash(st->st_connection, sig_val, hash_val,
+ hash_len);
if (sig_len == 0)
{
- loglog(RC_LOG_SERIOUS, "unable to locate my private key for RSA Signature");
+ loglog(RC_LOG_SERIOUS, "unable to locate my private key for signature");
return STF_FAIL + AUTHENTICATION_FAILED;
}
@@ -3997,12 +3846,12 @@ main_inI3_outR3_tail(struct msg_digest *md
{
/* SIG_R out */
u_char sig_val[RSA_MAX_OCTETS];
- size_t sig_len = RSA_sign_hash(st->st_connection
- , sig_val, hash_val, hash_len);
+ size_t sig_len = sign_hash(st->st_connection, sig_val, hash_val,
+ hash_len);
if (sig_len == 0)
{
- loglog(RC_LOG_SERIOUS, "unable to locate my private key for RSA Signature");
+ loglog(RC_LOG_SERIOUS, "unable to locate my private key for signature");
return STF_FAIL + AUTHENTICATION_FAILED;
}
@@ -4479,10 +4328,10 @@ static enum verify_oppo_step quick_inI1_outR1_process_answer(
case vos_our_client:
next_step = vos_his_client;
{
- const struct RSA_private_key *pri = get_RSA_private_key(c);
+ private_key_t *private = get_private_key(c);
struct gw_info *gwp;
- if (pri == NULL)
+ if (private == NULL)
{
ugh = "we don't know our own key";
break;
@@ -4503,7 +4352,7 @@ static enum verify_oppo_step quick_inI1_outR1_process_answer(
ugh = NULL; /* good! */
break;
}
- else if (same_RSA_public_key(&pri->pub, &gwp->key->u.rsa))
+ else if (private->belongs_to(private, gwp->key->public_key))
{
ugh = NULL; /* good! */
break;
@@ -4515,9 +4364,9 @@ static enum verify_oppo_step quick_inI1_outR1_process_answer(
case vos_our_txt:
next_step = vos_his_client;
{
- const struct RSA_private_key *pri = get_RSA_private_key(c);
+ private_key_t *private = get_private_key(c);
- if (pri == NULL)
+ if (private == NULL)
{
ugh = "we don't know our own key";
break;
@@ -4534,7 +4383,7 @@ static enum verify_oppo_step quick_inI1_outR1_process_answer(
ugh = "our client delegation depends on our " RRNAME " record, but it has the wrong public key";
#endif
if (gwp->gw_key_present
- && same_RSA_public_key(&pri->pub, &gwp->key->u.rsa))
+ && private->belongs_to(private, gwp->key->public_key))
{
ugh = NULL; /* good! */
break;
@@ -4551,9 +4400,9 @@ static enum verify_oppo_step quick_inI1_outR1_process_answer(
case vos_our_key:
next_step = vos_his_client;
{
- const struct RSA_private_key *pri = get_RSA_private_key(c);
+ private_key_t *private = get_private_key(c);
- if (pri == NULL)
+ if (private == NULL)
{
ugh = "we don't know our own key";
break;
@@ -4565,7 +4414,7 @@ static enum verify_oppo_step quick_inI1_outR1_process_answer(
for (kp = ac->keys_from_dns; kp != NULL; kp = kp->next)
{
ugh = "our client delegation depends on our " RRNAME " record, but it has the wrong public key";
- if (same_RSA_public_key(&pri->pub, &kp->key->u.rsa))
+ if (private->belongs_to(private, kp->key->public_key))
{
/* do this only once a day */
if (!logged_txt_warning)
@@ -4585,11 +4434,15 @@ static enum verify_oppo_step quick_inI1_outR1_process_answer(
case vos_his_client:
next_step = vos_done;
{
+ public_key_t *pub_key;
+ identification_t *p1st_keyid;
struct gw_info *gwp;
-
+
/* check that the public key that authenticated
* the ISAKMP SA (p1st) will do for this gateway.
*/
+ pub_key = p1st->st_peer_pubkey->public_key;
+ p1st_keyid = pub_key->get_id(pub_key, ID_PUBKEY_INFO_SHA1);
ugh = "peer's client does not delegate to peer";
for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
@@ -4601,9 +4454,10 @@ static enum verify_oppo_step quick_inI1_outR1_process_answer(
* it implies fetching a KEY from the same
* place we must have gotten it.
*/
- if (!gwp->gw_key_present
- || same_RSA_public_key(&p1st->st_peer_pubkey->u.rsa
- , &gwp->key->u.rsa))
+ if (!gwp->gw_key_present || p1st_keyid->equals(p1st_keyid,
+ gwp->key->public_key->get_id(gwp->key->public_key,
+ ID_PUBKEY_INFO_SHA1))
+ )
{
ugh = NULL; /* good! */
break;
diff --git a/src/pluto/kernel.c b/src/pluto/kernel.c
index fdc2c4c3c..f698de2c8 100644
--- a/src/pluto/kernel.c
+++ b/src/pluto/kernel.c
@@ -488,10 +488,11 @@ static bool do_command(struct connection *c, struct spd_route *sr,
for (p = pubkeys; p != NULL; p = p->next)
{
pubkey_t *key = p->key;
+ key_type_t type = key->public_key->get_type(key->public_key);
int pathlen;
- if (key->alg == PUBKEY_ALG_RSA && same_id(&sr->that.id, &key->id)
- && trusted_ca(key->issuer, sr->that.ca, &pathlen))
+ if (type == KEY_RSA && same_id(&sr->that.id, &key->id) &&
+ trusted_ca(key->issuer, sr->that.ca, &pathlen))
{
dntoa_or_null(peerca_str, BUF_LEN, key->issuer, "");
escape_metachar(peerca_str, secure_peerca_str, sizeof(secure_peerca_str));
diff --git a/src/pluto/keys.c b/src/pluto/keys.c
index 031d00a46..c0eb6ae74 100644
--- a/src/pluto/keys.c
+++ b/src/pluto/keys.c
@@ -33,12 +33,15 @@
#include <freeswan.h>
+#include <library.h>
+#include <asn1/asn1.h>
+
#include "constants.h"
#include "defs.h"
#include "mp_defs.h"
#include "id.h"
#include "x509.h"
-#include "pgp.h"
+#include "pgpcert.h"
#include "certs.h"
#include "smartcard.h"
#include "connections.h"
@@ -69,66 +72,42 @@ struct secret {
enum PrivateKeyKind kind;
union {
chunk_t preshared_secret;
- RSA_private_key_t RSA_private_key;
xauth_t xauth_secret;
+ private_key_t *private_key;
smartcard_t *smartcard;
} u;
secret_t *next;
};
-static pubkey_t*
-allocate_RSA_public_key(const cert_t cert)
+static public_key_t* get_public_key(const cert_t cert)
{
- pubkey_t *pk = malloc_thing(pubkey_t);
- chunk_t e = chunk_empty, n = chunk_empty;
-
switch (cert.type)
{
- case CERT_PGP:
- e = cert.u.pgp->publicExponent;
- n = cert.u.pgp->modulus;
- break;
- case CERT_X509_SIGNATURE:
- e = cert.u.x509->publicExponent;
- n = cert.u.x509->modulus;
- break;
- default:
- plog("RSA public key allocation error");
+ case CERT_PGP:
+ /*
+ e = cert.u.pgp->publicExponent;
+ n = cert.u.pgp->modulus;
+ init_RSA_public_key(&pk->public_key, e, n);
+ */
+ return NULL;
+ break;
+ case CERT_X509_SIGNATURE:
+ return cert.u.x509->public_key;
+ break;
+ default:
+ return NULL;
}
-
- zero(pk);
- init_RSA_public_key(&pk->u.rsa, e, n);
- DBG(DBG_RAW,
- RSA_show_public_key(&pk->u.rsa)
- )
-
- pk->alg = PUBKEY_ALG_RSA;
- pk->id = empty_id;
- pk->issuer = chunk_empty;
- pk->serial = chunk_empty;
-
- return pk;
}
/*
* free a public key struct
*/
-static void
-free_public_key(pubkey_t *pk)
+static void free_public_key(pubkey_t *pk)
{
+ DESTROY_IF(pk->public_key);
free_id_content(&pk->id);
free(pk->issuer.ptr);
free(pk->serial.ptr);
-
- /* algorithm-specific freeing */
- switch (pk->alg)
- {
- case PUBKEY_ALG_RSA:
- free_RSA_public_content(&pk->u.rsa);
- break;
- default:
- bad_case(pk->alg);
- }
free(pk);
}
@@ -138,8 +117,8 @@ secret_t *secrets = NULL;
* me and the peer. We match the Id (if none, the IP address).
* Failure is indicated by a NULL.
*/
-static const secret_t *
-get_secret(const struct connection *c, enum PrivateKeyKind kind, bool asym)
+static const secret_t* get_secret(const struct connection *c,
+ enum PrivateKeyKind kind, bool asym)
{
enum { /* bits */
match_default = 01,
@@ -155,20 +134,19 @@ get_secret(const struct connection *c, enum PrivateKeyKind kind, bool asym)
struct id rw_id;
/* is there a certificate assigned to this connection? */
- if (kind == PPK_RSA && c->spd.this.cert.type != CERT_NONE)
+ if (kind == PPK_PUBKEY && c->spd.this.cert.type != CERT_NONE)
{
- pubkey_t *my_public_key = allocate_RSA_public_key(c->spd.this.cert);
+ public_key_t *pub_key = get_public_key(c->spd.this.cert);
for (s = secrets; s != NULL; s = s->next)
{
if (s->kind == kind &&
- same_RSA_public_key(&s->u.RSA_private_key.pub, &my_public_key->u.rsa))
+ s->u.private_key->belongs_to(s->u.private_key, pub_key))
{
best = s;
break; /* we have found the private key - no sense in searching further */
}
}
- free_public_key(my_public_key);
return best;
}
@@ -222,9 +200,10 @@ get_secret(const struct connection *c, enum PrivateKeyKind kind, bool asym)
* default to matching any peer.
* A more specific match will trump this.
*/
- if (match == match_me
- && s->ids->next == NULL)
+ if (match == match_me && s->ids->next == NULL)
+ {
match |= match_default;
+ }
}
switch (match)
@@ -251,16 +230,10 @@ get_secret(const struct connection *c, enum PrivateKeyKind kind, bool asym)
{
case PPK_PSK:
same = s->u.preshared_secret.len == best->u.preshared_secret.len
- && memeq(s->u.preshared_secret.ptr, best->u.preshared_secret.ptr, s->u.preshared_secret.len);
+ && memeq(s->u.preshared_secret.ptr, best->u.preshared_secret.ptr, s->u.preshared_secret.len);
break;
- case PPK_RSA:
- /* Dirty trick: since we have code to compare
- * RSA public keys, but not private keys, we
- * make the assumption that equal public keys
- * mean equal private keys. This ought to work.
- */
- same = same_RSA_public_key(&s->u.RSA_private_key.pub
- , &best->u.RSA_private_key.pub);
+ case PPK_PUBKEY:
+ same = s->u.private_key->equals(s->u.private_key, best->u.private_key);
break;
default:
bad_case(kind);
@@ -288,8 +261,7 @@ get_secret(const struct connection *c, enum PrivateKeyKind kind, bool asym)
* Failure is indicated by a NULL pointer.
* Note: the result is not to be freed by the caller.
*/
-const chunk_t *
-get_preshared_secret(const struct connection *c)
+const chunk_t* get_preshared_secret(const struct connection *c)
{
const secret_t *s = get_secret(c, PPK_PSK, FALSE);
@@ -305,60 +277,50 @@ get_preshared_secret(const struct connection *c)
/* check the existence of an RSA private key matching an RSA public
* key contained in an X.509 or OpenPGP certificate
*/
-bool
-has_private_key(cert_t cert)
+bool has_private_key(cert_t cert)
{
secret_t *s;
bool has_key = FALSE;
- pubkey_t *pubkey = allocate_RSA_public_key(cert);
+ public_key_t *pub_key = get_public_key(cert);
for (s = secrets; s != NULL; s = s->next)
{
- if (s->kind == PPK_RSA &&
- same_RSA_public_key(&s->u.RSA_private_key.pub, &pubkey->u.rsa))
+ if (s->kind == PPK_PUBKEY &&
+ s->u.private_key->belongs_to(s->u.private_key, pub_key))
{
has_key = TRUE;
break;
}
}
- free_public_key(pubkey);
return has_key;
}
/*
* get the matching RSA private key belonging to a given X.509 certificate
*/
-const RSA_private_key_t*
-get_x509_private_key(const x509cert_t *cert)
+private_key_t* get_x509_private_key(const x509cert_t *cert)
{
secret_t *s;
- const RSA_private_key_t *pri = NULL;
- const cert_t c = {CERT_X509_SIGNATURE, {(x509cert_t*)cert}};
-
- pubkey_t *pubkey = allocate_RSA_public_key(c);
for (s = secrets; s != NULL; s = s->next)
{
- if (s->kind == PPK_RSA &&
- same_RSA_public_key(&s->u.RSA_private_key.pub, &pubkey->u.rsa))
+ if (s->kind == PPK_PUBKEY &&
+ s->u.private_key->belongs_to(s->u.private_key, cert->public_key))
{
- pri = &s->u.RSA_private_key;
- break;
+ return s->u.private_key;
}
}
- free_public_key(pubkey);
- return pri;
+ return NULL;
}
/* find the appropriate RSA private key (see get_secret).
* Failure is indicated by a NULL pointer.
*/
-const RSA_private_key_t *
-get_RSA_private_key(const struct connection *c)
+private_key_t* get_private_key(const struct connection *c)
{
- const secret_t *s = get_secret(c, PPK_RSA, TRUE);
+ const secret_t *s = get_secret(c, PPK_PUBKEY, TRUE);
- return s == NULL? NULL : &s->u.RSA_private_key;
+ return s == NULL? NULL : s->u.private_key;
}
/* digest a secrets file
@@ -401,8 +363,7 @@ get_RSA_private_key(const struct connection *c)
*/
/* parse PSK from file */
-static err_t
-process_psk_secret(chunk_t *psk)
+static err_t process_psk_secret(chunk_t *psk)
{
err_t ugh = NULL;
@@ -435,109 +396,113 @@ process_psk_secret(chunk_t *psk)
return ugh;
}
-/* Parse fields of RSA private key.
- * A braced list of keyword and value pairs.
- * At the moment, each field is required, in order.
- * The fields come from BIND 8.2's representation
+const char *rsa_private_keywords[] = {
+ "Modulus",
+ "PublicExponent",
+ "PrivateExponent",
+ "Prime1",
+ "Prime2",
+ "Exponent1",
+ "Exponent2",
+ "Coefficient"
+};
+
+/**
+ * Parse fields of an RSA private key in BIND 8.2's representation
+ * consistiong of a braced list of keyword and value pairs in required order.
+ * Conversion into ASN.1 DER encoded PKCS#1 representation.
*/
-static err_t
-process_rsa_secret(RSA_private_key_t *rsak)
+static err_t process_rsa_secret(private_key_t **key)
{
- char buf[RSA_MAX_ENCODING_BYTES]; /* limit on size of binary representation of key */
- const struct fld *p;
-
- /* save bytes of Modulus and PublicExponent for keyid calculation */
- unsigned char ebytes[sizeof(buf)];
- unsigned char *eb_next = ebytes;
- chunk_t pub_bytes[2];
- chunk_t *pb_next = &pub_bytes[0];
-
- for (p = RSA_private_field; p < &RSA_private_field[RSA_PRIVATE_FIELD_ELEMENTS]; p++)
+ chunk_t asn1_chunks[countof(rsa_private_keywords)];
+ chunk_t pkcs1_chunk;
+ u_char buf[RSA_MAX_ENCODING_BYTES]; /* limit on size of binary representation of key */
+ err_t ugh;
+ int i, j;
+ size_t sz, len = 0;
+
+ for (i = 0; i < countof(rsa_private_keywords); i++)
{
- size_t sz;
- err_t ugh;
+ chunk_t rsa_private_key_chunk;
+ const char *keyword = rsa_private_keywords[i];
if (!shift())
{
- return "premature end of RSA key";
+ ugh = "premature end of RSA key";
+ goto end;
}
- else if (!tokeqword(p->name))
+ if (!tokeqword(keyword))
{
- return builddiag("%s keyword not found where expected in RSA key"
- , p->name);
+ ugh = builddiag("%s keyword not found where expected in RSA key"
+ , keyword);
+ goto end;
}
- else if (!(shift()
- && (!tokeq(":") || shift()))) /* ignore optional ":" */
+ if (!(shift() && (!tokeq(":") || shift()))) /* ignore optional ":" */
{
- return "premature end of RSA key";
+ ugh = "premature end of RSA key";
+ goto end;
}
- else if (NULL != (ugh = ttodatav(tok, flp->cur - tok
- , 0, buf, sizeof(buf), &sz, diag_space, sizeof(diag_space)
- , TTODATAV_SPACECOUNTS)))
+ ugh = ttodatav(tok, flp->cur - tok, 0, buf, sizeof(buf), &sz,
+ diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS);
+ if (ugh)
{
- /* in RSA key, ttodata didn't like */
- return builddiag("RSA data malformed (%s): %s", ugh, tok);
- }
- else
- {
- MP_INT *n = (MP_INT *) ((char *)rsak + p->offset);
-
- n_to_mpz(n, buf, sz);
- if (pb_next < &pub_bytes[countof(pub_bytes)])
- {
- if (eb_next - ebytes + sz > sizeof(ebytes))
- return "public key takes too many bytes";
-
- *pb_next = chunk_create(eb_next, sz);
- memcpy(eb_next, buf, sz);
- eb_next += sz;
- pb_next++;
- }
-#if 0 /* debugging info that compromises security */
- {
- size_t sz = mpz_sizeinbase(n, 16);
- char buf[RSA_MAX_OCTETS * 2 + 2]; /* ought to be big enough */
-
- passert(sz <= sizeof(buf));
- mpz_get_str(buf, 16, n);
-
- loglog(RC_LOG_SERIOUS, "%s: %s", p->name, buf);
- }
-#endif
+ ugh = builddiag("RSA data malformed (%s): %s", ugh, tok);
+ i++;
+ goto end;
}
+ rsa_private_key_chunk = chunk_create(buf, sz);
+ asn1_chunks[i] = asn1_integer("c", rsa_private_key_chunk);
+ len += asn1_chunks[i].len;
}
/* We require an (indented) '}' and the end of the record.
- * We break down the test so that the diagnostic will be
- * more helpful. Some people don't seem to wish to indent
- * the brace!
+ * We break down the test so that the diagnostic will be more helpful.
+ * Some people don't seem to wish to indent the brace!
*/
if (!shift() || !tokeq("}"))
{
- return "malformed end of RSA private key -- indented '}' required";
+ ugh = "malformed end of RSA private key -- indented '}' required";
+ goto end;
}
- else if (shift())
+ if (shift())
{
- return "malformed end of RSA private key -- unexpected token after '}'";
+ ugh = "malformed end of RSA private key -- unexpected token after '}'";
+ goto end;
}
- else
+
+ pkcs1_chunk = asn1_wrap(ASN1_SEQUENCE, "ccccccccc",
+ ASN1_INTEGER_0,
+ asn1_chunks[0],
+ asn1_chunks[1],
+ asn1_chunks[2],
+ asn1_chunks[3],
+ asn1_chunks[4],
+ asn1_chunks[5],
+ asn1_chunks[6],
+ asn1_chunks[7]);
+
+ *key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_BLOB_ASN1_DER, pkcs1_chunk,
+ BUILD_END);
+ free(pkcs1_chunk.ptr);
+ if (*key == NULL)
{
- unsigned bits = mpz_sizeinbase(&rsak->pub.n, 2);
-
- rsak->pub.k = (bits + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
- rsak->pub.keyid[0] = '\0'; /* in case of splitkeytoid failure */
- splitkeytoid(pub_bytes[1].ptr, pub_bytes[1].len
- , pub_bytes[0].ptr, pub_bytes[0].len
- , rsak->pub.keyid, sizeof(rsak->pub.keyid));
- return RSA_private_key_sanity(rsak);
+ ugh = "parsing of RSA private key failed";
}
+
+end:
+ for (j = 0 ; j < i; j++)
+ {
+ free(asn1_chunks[j].ptr);
+ }
+ return ugh;
}
-/* process rsa key file protected with optional passphrase which can either be
+/**
+ * process a key file protected with optional passphrase which can either be
* read from ipsec.secrets or prompted for by using whack
*/
-static err_t
-process_rsa_keyfile(RSA_private_key_t *rsak, int whackfd)
+static err_t process_keyfile(private_key_t **key, key_type_t type, int whackfd)
{
char filename[BUF_LEN];
prompt_pass_t pass;
@@ -560,7 +525,9 @@ process_rsa_keyfile(RSA_private_key_t *rsak, int whackfd)
if (tokeqword("%prompt"))
{
if (pass.fd == NULL_FD)
- return "RSA private key file -- enter passphrase using 'ipsec secrets'";
+ {
+ return "Private key file -- enter passphrase using 'ipsec secrets'";
+ }
pass.prompt = TRUE;
}
else
@@ -574,21 +541,25 @@ process_rsa_keyfile(RSA_private_key_t *rsak, int whackfd)
len -= 2;
}
if (len > PROMPT_PASS_LEN)
- return "RSA private key file -- passphrase exceeds 64 characters";
-
+ {
+ return "Private key file -- passphrase exceeds 64 characters";
+ }
memcpy(pass.secret, passphrase, len);
}
if (shift())
- return "RSA private key file -- unexpected token after passphrase";
+ {
+ return "Private key file -- unexpected token after passphrase";
+ }
}
- return load_rsa_private_key(filename, &pass, rsak);
+ *key = load_private_key(filename, &pass, type);
+
+ return key ? NULL : "Private key file -- could not be loaded";
}
-/*
- * process xauth secret read from ipsec.secrets
+/**
+ * Process xauth secret read from ipsec.secrets
*/
-static err_t
-process_xauth(secret_t *s)
+static err_t process_xauth(secret_t *s)
{
chunk_t user_name;
@@ -616,11 +587,11 @@ process_xauth(secret_t *s)
return process_psk_secret(&s->u.xauth_secret.user_password);
}
-/* get XAUTH secret from chained secrets lists
+/**
+ * Get XAUTH secret from chained secrets lists
* only one entry is currently supported
*/
-static bool
-xauth_get_secret(xauth_t *xauth_secret)
+static bool xauth_get_secret(xauth_t *xauth_secret)
{
secret_t *s;
bool found = FALSE;
@@ -643,11 +614,11 @@ xauth_get_secret(xauth_t *xauth_secret)
return found;
}
-/*
+/**
* find a matching secret
*/
-static bool
-xauth_verify_secret(const xauth_peer_t *peer, const xauth_t *xauth_secret)
+static bool xauth_verify_secret(const xauth_peer_t *peer,
+ const xauth_t *xauth_secret)
{
bool found = FALSE;
secret_t *s;
@@ -657,10 +628,14 @@ xauth_verify_secret(const xauth_peer_t *peer, const xauth_t *xauth_secret)
if (s->kind == PPK_XAUTH)
{
if (!chunk_equals(xauth_secret->user_name, s->u.xauth_secret.user_name))
+ {
continue;
+ }
found = TRUE;
if (chunk_equals(xauth_secret->user_password, s->u.xauth_secret.user_password))
+ {
return TRUE;
+ }
}
}
plog("xauth user '%.*s' %s"
@@ -669,16 +644,15 @@ xauth_verify_secret(const xauth_peer_t *peer, const xauth_t *xauth_secret)
return FALSE;
}
-/*
+/**
* the global xauth_module struct is defined here
*/
xauth_module_t xauth_module;
-/*
- * assign the default xauth functions to any null function pointers
+/**
+ * Assign the default xauth functions to any null function pointers
*/
-void
-xauth_defaults(void)
+void xauth_defaults(void)
{
if (xauth_module.get_secret == NULL)
{
@@ -696,11 +670,10 @@ xauth_defaults(void)
}
};
-/*
- * process pin read from ipsec.secrets or prompted for it using whack
+/**
+ * Process pin read from ipsec.secrets or prompted for it using whack
*/
-static err_t
-process_pin(secret_t *s, int whackfd)
+static err_t process_pin(secret_t *s, int whackfd)
{
smartcard_t *sc;
const char *pin_status = "no pin";
@@ -776,8 +749,7 @@ process_pin(secret_t *s, int whackfd)
return NULL;
}
-static void
-log_psk(secret_t *s)
+static void log_psk(secret_t *s)
{
int n = 0;
char buf[BUF_LEN];
@@ -808,8 +780,7 @@ log_psk(secret_t *s)
plog(" loaded shared key for %.*s", n, buf);
}
-static void
-process_secret(secret_t *s, int whackfd)
+static void process_secret(secret_t *s, int whackfd)
{
err_t ugh = NULL;
@@ -832,18 +803,30 @@ process_secret(secret_t *s, int whackfd)
/* RSA key: the fun begins.
* A braced list of keyword and value pairs.
*/
- s->kind = PPK_RSA;
+ s->kind = PPK_PUBKEY;
if (!shift())
{
ugh = "bad RSA key syntax";
}
else if (tokeq("{"))
{
- ugh = process_rsa_secret(&s->u.RSA_private_key);
+ ugh = process_rsa_secret(&s->u.private_key);
+ }
+ else
+ {
+ ugh = process_keyfile(&s->u.private_key, KEY_RSA, whackfd);
+ }
+ }
+ else if (tokeqword("ecdsa"))
+ {
+ s->kind = PPK_PUBKEY;
+ if (!shift())
+ {
+ ugh = "bad ECDSA key syntax";
}
else
{
- ugh = process_rsa_keyfile(&s->u.RSA_private_key, whackfd);
+ ugh = process_keyfile(&s->u.private_key, KEY_ECDSA, whackfd);
}
}
else if (tokeqword("xauth"))
@@ -877,8 +860,7 @@ process_secret(secret_t *s, int whackfd)
static void process_secrets_file(const char *file_pat, int whackfd); /* forward declaration */
-static void
-process_secret_records(int whackfd)
+static void process_secret_records(int whackfd)
{
/* read records from ipsec.secrets and load them into our table */
for (;;)
@@ -1013,15 +995,13 @@ process_secret_records(int whackfd)
}
}
-static int
-globugh(const char *epath, int eerrno)
+static int globugh(const char *epath, int eerrno)
{
log_errno_routine(eerrno, "problem with secrets file \"%s\"", epath);
return 1; /* stop glob */
}
-static void
-process_secrets_file(const char *file_pat, int whackfd)
+static void process_secrets_file(const char *file_pat, int whackfd)
{
struct file_lex_position pos;
char **fnp;
@@ -1075,8 +1055,7 @@ process_secrets_file(const char *file_pat, int whackfd)
globfree(&globbuf);
}
-void
-free_preshared_secrets(void)
+void free_preshared_secrets(void)
{
lock_certs_and_keys("free_preshared_secrets");
@@ -1102,8 +1081,8 @@ free_preshared_secrets(void)
case PPK_PSK:
free(s->u.preshared_secret.ptr);
break;
- case PPK_RSA:
- free_RSA_private_content(&s->u.RSA_private_key);
+ case PPK_PUBKEY:
+ DESTROY_IF(s->u.private_key);
break;
case PPK_XAUTH:
free(s->u.xauth_secret.user_name.ptr);
@@ -1123,8 +1102,7 @@ free_preshared_secrets(void)
unlock_certs_and_keys("free_preshard_secrets");
}
-void
-load_preshared_secrets(int whackfd)
+void load_preshared_secrets(int whackfd)
{
free_preshared_secrets();
(void) process_secrets_file(shared_secrets_file, whackfd);
@@ -1134,8 +1112,7 @@ load_preshared_secrets(int whackfd)
* Note: caller must set dns_auth_level.
*/
-pubkey_t *
-public_key_from_rsa(const RSA_public_key_t *k)
+pubkey_t* public_key_from_rsa(public_key_t *key)
{
pubkey_t *p = malloc_thing(pubkey_t);
@@ -1143,12 +1120,7 @@ public_key_from_rsa(const RSA_public_key_t *k)
p->id = empty_id; /* don't know, doesn't matter */
p->issuer = chunk_empty;
p->serial = chunk_empty;
- p->alg = PUBKEY_ALG_RSA;
-
- memcpy(p->u.rsa.keyid, k->keyid, sizeof(p->u.rsa.keyid));
- p->u.rsa.k = k->k;
- mpz_init_set(&p->u.rsa.e, &k->e);
- mpz_init_set(&p->u.rsa.n, &k->n);
+ p->public_key = key;
/* note that we return a 1 reference count upon creation:
* invariant: recount > 0.
@@ -1161,8 +1133,7 @@ public_key_from_rsa(const RSA_public_key_t *k)
/* Free a public key record.
* As a convenience, this returns a pointer to next.
*/
-pubkey_list_t *
-free_public_keyentry(pubkey_list_t *p)
+pubkey_list_t* free_public_keyentry(pubkey_list_t *p)
{
pubkey_list_t *nxt = p->next;
@@ -1172,8 +1143,7 @@ free_public_keyentry(pubkey_list_t *p)
return nxt;
}
-void
-free_public_keys(pubkey_list_t **keys)
+void free_public_keys(pubkey_list_t **keys)
{
while (*keys != NULL)
*keys = free_public_keyentry(*keys);
@@ -1183,15 +1153,15 @@ free_public_keys(pubkey_list_t **keys)
pubkey_list_t *pubkeys = NULL; /* keys from ipsec.conf */
-void
-free_remembered_public_keys(void)
+void free_remembered_public_keys(void)
{
free_public_keys(&pubkeys);
}
-/* transfer public keys from *keys list to front of pubkeys list */
-void
-transfer_to_public_keys(struct gw_info *gateways_from_dns
+/**
+ * Transfer public keys from *keys list to front of pubkeys list
+ */
+void transfer_to_public_keys(struct gw_info *gateways_from_dns
#ifdef USE_KEYRR
, pubkey_list_t **keys
#endif /* USE_KEYRR */
@@ -1224,66 +1194,8 @@ transfer_to_public_keys(struct gw_info *gateways_from_dns
#endif /* USE_KEYRR */
}
-/* decode of RSA pubkey chunk
- * - format specified in RFC 2537 RSA/MD5 Keys and SIGs in the DNS
- * - exponent length in bytes (1 or 3 octets)
- * + 1 byte if in [1, 255]
- * + otherwise 0x00 followed by 2 bytes of length
- * - exponent
- * - modulus
- */
-err_t
-unpack_RSA_public_key(RSA_public_key_t *rsa, const chunk_t *pubkey)
-{
- chunk_t exp;
- chunk_t mod;
-
- if (pubkey->len < 3)
- return "RSA public key blob way to short"; /* not even room for length! */
-
- if (pubkey->ptr[0] != 0x00)
- {
- exp = chunk_create(pubkey->ptr + 1, pubkey->ptr[0]);
- }
- else
- {
- exp = chunk_create(pubkey->ptr + 3,
- (pubkey->ptr[1] << BITS_PER_BYTE) + pubkey->ptr[2]);
- }
-
- if (pubkey->len - (exp.ptr - pubkey->ptr) < exp.len + RSA_MIN_OCTETS_RFC)
- {
- return "RSA public key blob too short";
- }
-
- mod.ptr = exp.ptr + exp.len;
- mod.len = &pubkey->ptr[pubkey->len] - mod.ptr;
-
- if (mod.len < RSA_MIN_OCTETS)
- return RSA_MIN_OCTETS_UGH;
-
- if (mod.len > RSA_MAX_OCTETS)
- return RSA_MAX_OCTETS_UGH;
-
- init_RSA_public_key(rsa, exp, mod);
- rsa->k = mpz_sizeinbase(&rsa->n, 2); /* size in bits, for a start */
- rsa->k = (rsa->k + BITS_PER_BYTE - 1) / BITS_PER_BYTE; /* now octets */
- DBG(DBG_RAW,
- RSA_show_public_key(rsa)
- )
-
- if (rsa->k != mod.len)
- {
- mpz_clear(&rsa->e);
- mpz_clear(&rsa->n);
- return "RSA modulus shorter than specified";
- }
-
- return NULL;
-}
-static void
-install_public_key(pubkey_t *pk, pubkey_list_t **head)
+static void install_public_key(pubkey_t *pk, pubkey_list_t **head)
{
pubkey_list_t *p = malloc_thing(pubkey_list_t);
@@ -1304,30 +1216,33 @@ install_public_key(pubkey_t *pk, pubkey_list_t **head)
*head = p;
}
-
-void
-delete_public_keys(const struct id *id, enum pubkey_alg alg
-, chunk_t issuer, chunk_t serial)
+void delete_public_keys(const struct id *id, key_type_t type,
+ chunk_t issuer, chunk_t serial)
{
pubkey_list_t **pp, *p;
pubkey_t *pk;
+ key_type_t pk_type;
for (pp = &pubkeys; (p = *pp) != NULL; )
{
pk = p->key;
+ pk_type = pk->public_key->get_type(pk->public_key);
- if (same_id(id, &pk->id) && pk->alg == alg
+ if (same_id(id, &pk->id) && pk_type == type
&& (issuer.ptr == NULL || pk->issuer.ptr == NULL
|| same_dn(issuer, pk->issuer))
&& same_serial(serial, pk->serial))
+ {
*pp = free_public_keyentry(p);
+ }
else
+ {
pp = &p->next;
+ }
}
}
-pubkey_t *
-reference_key(pubkey_t *pk)
+pubkey_t* reference_key(pubkey_t *pk)
{
pk->refcnt++;
return pk;
@@ -1357,67 +1272,63 @@ unreference_key(pubkey_t **pkp)
free_public_key(pk);
}
-err_t
-add_public_key(const struct id *id, enum dns_auth_level dns_auth_level,
- enum pubkey_alg alg, const chunk_t *key, pubkey_list_t **head)
+bool add_public_key(const struct id *id, enum dns_auth_level dns_auth_level,
+ enum pubkey_alg alg, chunk_t rfc3110_key,
+ pubkey_list_t **head)
{
+ public_key_t *key = NULL;
pubkey_t *pk;
- pk = malloc_thing(pubkey_t); zero(pk);
-
/* first: algorithm-specific decoding of key chunk */
switch (alg)
{
- case PUBKEY_ALG_RSA:
- {
- err_t ugh = unpack_RSA_public_key(&pk->u.rsa, key);
-
- if (ugh != NULL)
+ case PUBKEY_ALG_RSA:
+ key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
+ BUILD_BLOB_RFC_3110, rfc3110_key,
+ BUILD_END);
+ if (key == NULL)
{
- free(pk);
- return ugh;
+ return FALSE;
}
- }
- break;
- default:
- bad_case(alg);
+ break;
+ default:
+ bad_case(alg);
}
+ pk = malloc_thing(pubkey_t);
+ zero(pk);
+ pk->public_key = key;
pk->id = *id;
pk->dns_auth_level = dns_auth_level;
- pk->alg = alg;
pk->until_time = UNDEFINED_TIME;
pk->issuer = chunk_empty;
pk->serial = chunk_empty;
-
install_public_key(pk, head);
- return NULL;
+ return TRUE;
}
/* extract id and public key from x.509 certificate and
* insert it into a pubkeyrec
*/
-void
-add_x509_public_key(x509cert_t *cert , time_t until
- , enum dns_auth_level dns_auth_level)
+void add_x509_public_key(x509cert_t *cert , time_t until,
+ enum dns_auth_level dns_auth_level)
{
generalName_t *gn;
pubkey_t *pk;
- cert_t c = { CERT_X509_SIGNATURE, {cert} };
-
- /* we support RSA only */
- if (cert->subjectPublicKeyAlgorithm != PUBKEY_ALG_RSA)
- return;
+ key_type_t pk_type;
/* ID type: ID_DER_ASN1_DN (X.509 subject field) */
- pk = allocate_RSA_public_key(c);
+ pk = malloc_thing(pubkey_t);
+ zero(pk);
+ pk->public_key = cert->public_key->get_ref(cert->public_key);
pk->id.kind = ID_DER_ASN1_DN;
pk->id.name = cert->subject;
pk->dns_auth_level = dns_auth_level;
pk->until_time = until;
pk->issuer = cert->issuer;
pk->serial = cert->serialNumber;
- delete_public_keys(&pk->id, pk->alg, pk->issuer, pk->serial);
+ pk_type = pk->public_key->get_type(pk->public_key);
+ delete_public_keys(&pk->id, pk_type, pk->issuer, pk->serial);
install_public_key(pk, &pubkeys);
gn = cert->subjectAltName;
@@ -1429,13 +1340,15 @@ add_x509_public_key(x509cert_t *cert , time_t until
gntoid(&id, gn);
if (id.kind != ID_ANY)
{
- pk = allocate_RSA_public_key(c);
+ pk = malloc_thing(pubkey_t);
+ zero(pk);
+ pk->public_key = cert->public_key->get_ref(cert->public_key);
pk->id = id;
pk->dns_auth_level = dns_auth_level;
pk->until_time = until;
pk->issuer = cert->issuer;
pk->serial = cert->serialNumber;
- delete_public_keys(&pk->id, pk->alg, pk->issuer, pk->serial);
+ delete_public_keys(&pk->id, pk_type, pk->issuer, pk->serial);
install_public_key(pk, &pubkeys);
}
gn = gn->next;
@@ -1445,50 +1358,39 @@ add_x509_public_key(x509cert_t *cert , time_t until
/* extract id and public key from OpenPGP certificate and
* insert it into a pubkeyrec
*/
-void
-add_pgp_public_key(pgpcert_t *cert , time_t until
- , enum dns_auth_level dns_auth_level)
+void add_pgp_public_key(pgpcert_t *cert , time_t until,
+ enum dns_auth_level dns_auth_level)
{
pubkey_t *pk;
- cert_t c;
-
- c.type = CERT_PGP;
- c.u.pgp = cert;
-
- /* we support RSA only */
- if (cert->pubkeyAlg != PUBKEY_ALG_RSA)
- {
- plog(" RSA public keys supported only");
- return;
- }
+ key_type_t pk_type;
- pk = allocate_RSA_public_key(c);
+ pk = malloc_thing(pubkey_t);
+ zero(pk);
+ pk->public_key = cert->public_key->get_ref(cert->public_key);
pk->id.kind = ID_KEY_ID;
- pk->id.name.ptr = cert->fingerprint;
- pk->id.name.len = PGP_FINGERPRINT_SIZE;
+ pk->id.name = cert->fingerprint->get_encoding(cert->fingerprint);
+ pk->id.name = chunk_clone(pk->id.name);
pk->dns_auth_level = dns_auth_level;
pk->until_time = until;
- delete_public_keys(&pk->id, pk->alg, chunk_empty, chunk_empty);
+ pk_type = pk->public_key->get_type(pk->public_key);
+ delete_public_keys(&pk->id, pk_type, chunk_empty, chunk_empty);
install_public_key(pk, &pubkeys);
}
/* when a X.509 certificate gets revoked, all instances of
* the corresponding public key must be removed
*/
-void
-remove_x509_public_key(const x509cert_t *cert)
+void remove_x509_public_key(const x509cert_t *cert)
{
- const cert_t c = {CERT_X509_SIGNATURE, {(x509cert_t*)cert}};
+ public_key_t *revoked_key = cert->public_key;
pubkey_list_t *p, **pp;
- pubkey_t *revoked_pk;
- revoked_pk = allocate_RSA_public_key(c);
- p = pubkeys;
- pp = &pubkeys;
+ p = pubkeys;
+ pp = &pubkeys;
while(p != NULL)
- {
- if (same_RSA_public_key(&p->key->u.rsa, &revoked_pk->u.rsa))
+ {
+ if (revoked_key->equals(revoked_key, p->key->public_key))
{
/* remove p from list and free memory */
*pp = free_public_keyentry(p);
@@ -1501,7 +1403,6 @@ remove_x509_public_key(const x509cert_t *cert)
}
p =*pp;
}
- free_public_key(revoked_pk);
}
/*
@@ -1521,30 +1422,28 @@ void list_public_keys(bool utc)
while (p != NULL)
{
pubkey_t *key = p->key;
+ public_key_t *public = key->public_key;
+ identification_t *keyid = public->get_id(public, ID_PUBKEY_INFO_SHA1);
+ char buf[BUF_LEN];
- if (key->alg == PUBKEY_ALG_RSA)
+ idtoa(&key->id, buf, BUF_LEN);
+ whack_log(RC_COMMENT,"%T, '%s'", &key->installed_time, utc, buf);
+ whack_log(RC_COMMENT, " pubkey: %N %4d bits, until %T %s",
+ key_type_names, public->get_type(public),
+ public->get_keysize(public) * BITS_PER_BYTE,
+ &key->until_time, utc,
+ check_expiry(key->until_time, PUBKEY_WARNING_INTERVAL, TRUE));
+ whack_log(RC_COMMENT," keyid: %Y", keyid);
+ if (key->issuer.len > 0)
{
- char buf[BUF_LEN];
-
- idtoa(&key->id, buf, BUF_LEN);
- whack_log(RC_COMMENT, "%T, %4d RSA Key %s, until %T %s",
- &key->installed_time, utc,
- 8*key->u.rsa.k, key->u.rsa.keyid,
- &key->until_time, utc,
- check_expiry(key->until_time, PUBKEY_WARNING_INTERVAL, TRUE));
- whack_log(RC_COMMENT," %s '%s'",
- enum_show(&ident_names, key->id.kind), buf);
- if (key->issuer.len > 0)
- {
- dntoa(buf, BUF_LEN, key->issuer);
- whack_log(RC_COMMENT," issuer: '%s'", buf);
- }
- if (key->serial.len > 0)
- {
- datatot(key->serial.ptr, key->serial.len, ':'
- , buf, BUF_LEN);
- whack_log(RC_COMMENT," serial: %s", buf);
- }
+ dntoa(buf, BUF_LEN, key->issuer);
+ whack_log(RC_COMMENT," issuer: '%s'", buf);
+ }
+ if (key->serial.len > 0)
+ {
+ datatot(key->serial.ptr, key->serial.len, ':'
+ , buf, BUF_LEN);
+ whack_log(RC_COMMENT," serial: %s", buf);
}
p = p->next;
}
diff --git a/src/pluto/keys.h b/src/pluto/keys.h
index 84d941fe8..8bc94d839 100644
--- a/src/pluto/keys.h
+++ b/src/pluto/keys.h
@@ -1,5 +1,6 @@
/* mechanisms for preshared keys (public, private, and preshared secrets)
* Copyright (C) 1998-2002 D. Hugh Redelmeier.
+ * Copyright (C) 2009 Andreas Steffen, Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -15,9 +16,9 @@
#ifndef _KEYS_H
#define _KEYS_H
-#include <gmp.h> /* GNU Multi-Precision library */
+#include <credentials/keys/private_key.h>
+#include <credentials/keys/public_key.h>
-#include "pkcs1.h"
#include "certs.h"
#ifndef SHARED_SECRETS_FILE
@@ -31,8 +32,7 @@ extern void free_preshared_secrets(void);
enum PrivateKeyKind {
PPK_PSK,
- /* PPK_DSS, */ /* not implemented */
- PPK_RSA,
+ PPK_PUBKEY,
PPK_XAUTH,
PPK_PIN
};
@@ -43,9 +43,8 @@ extern void xauth_defaults(void);
struct connection;
extern const chunk_t *get_preshared_secret(const struct connection *c);
-extern err_t unpack_RSA_public_key(RSA_public_key_t *rsa, const chunk_t *pubkey);
-extern const RSA_private_key_t *get_RSA_private_key(const struct connection *c);
-extern const RSA_private_key_t *get_x509_private_key(const x509cert_t *cert);
+extern private_key_t *get_private_key(const struct connection *c);
+extern private_key_t *get_x509_private_key(const x509cert_t *cert);
/* public key machinery */
@@ -62,10 +61,7 @@ struct pubkey {
, until_time;
chunk_t issuer;
chunk_t serial;
- enum pubkey_alg alg;
- union {
- RSA_public_key_t rsa;
- } u;
+ public_key_t *public_key;
};
typedef struct pubkey_list pubkey_list_t;
@@ -77,21 +73,20 @@ struct pubkey_list {
extern pubkey_list_t *pubkeys; /* keys from ipsec.conf or from certs */
-extern pubkey_t *public_key_from_rsa(const RSA_public_key_t *k);
+extern pubkey_t *public_key_from_rsa(public_key_t *key);
extern pubkey_list_t *free_public_keyentry(pubkey_list_t *p);
extern void free_public_keys(pubkey_list_t **keys);
extern void free_remembered_public_keys(void);
-extern void delete_public_keys(const struct id *id, enum pubkey_alg alg
- , chunk_t issuer, chunk_t serial);
-
+extern void delete_public_keys(const struct id *id, key_type_t type,
+ chunk_t issuer, chunk_t serial);
extern pubkey_t *reference_key(pubkey_t *pk);
extern void unreference_key(pubkey_t **pkp);
-extern err_t add_public_key(const struct id *id
- , enum dns_auth_level dns_auth_level
- , enum pubkey_alg alg
- , const chunk_t *key
- , pubkey_list_t **head);
+extern bool add_public_key(const struct id *id,
+ enum dns_auth_level dns_auth_level,
+ enum pubkey_alg alg,
+ chunk_t rfc3110_key,
+ pubkey_list_t **head);
extern bool has_private_key(cert_t cert);
extern void add_x509_public_key(x509cert_t *cert, time_t until
diff --git a/src/pluto/ocsp.c b/src/pluto/ocsp.c
index 1445f4b8e..80164fa1d 100644
--- a/src/pluto/ocsp.c
+++ b/src/pluto/ocsp.c
@@ -39,7 +39,6 @@
#include "certs.h"
#include "smartcard.h"
#include "whack.h"
-#include "pkcs1.h"
#include "keys.h"
#include "fetch.h"
#include "ocsp.h"
@@ -159,7 +158,7 @@ static x509cert_t *ocsp_requestor_cert = NULL;
static smartcard_t *ocsp_requestor_sc = NULL;
-static const struct RSA_private_key *ocsp_requestor_pri = NULL;
+static private_key_t *ocsp_requestor_key = NULL;
/**
* ASN.1 definition of ocspResponse
@@ -293,8 +292,9 @@ static const asn1Object_t singleResponseObjects[] = {
*/
static bool build_ocsp_location(const x509cert_t *cert, ocsp_location_t *location)
{
+ hasher_t *hasher;
static u_char digest[HASH_SIZE_SHA1]; /* temporary storage */
-
+
location->uri = cert->accessLocation;
if (location->uri.ptr == NULL)
@@ -311,8 +311,15 @@ static bool build_ocsp_location(const x509cert_t *cert, ocsp_location_t *locatio
}
}
+ /* compute authNameID from as SHA-1 hash of issuer DN */
location->authNameID = chunk_create(digest, HASH_SIZE_SHA1);
- compute_digest(cert->issuer, OID_SHA1, &location->authNameID);
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (hasher == NULL)
+ {
+ return FALSE;
+ }
+ hasher->get_hash(hasher, cert->issuer, digest);
+ hasher->destroy(hasher);
location->next = NULL;
location->issuer = cert->issuer;
@@ -660,7 +667,7 @@ static bool get_ocsp_requestor_cert(ocsp_location_t *location)
/* initialize temporary static storage */
ocsp_requestor_cert = NULL;
ocsp_requestor_sc = NULL;
- ocsp_requestor_pri = NULL;
+ ocsp_requestor_key = NULL;
for (;;)
{
@@ -699,15 +706,15 @@ static bool get_ocsp_requestor_cert(ocsp_location_t *location)
else
{
/* look for a matching private key in the chained list */
- const struct RSA_private_key *pri = get_x509_private_key(cert);
+ private_key_t *private = get_x509_private_key(cert);
- if (pri != NULL)
+ if (private != NULL)
{
DBG(DBG_CONTROL,
DBG_log("matching private key found")
)
ocsp_requestor_cert = cert;
- ocsp_requestor_pri = pri;
+ ocsp_requestor_key = private;
return TRUE;
}
}
@@ -715,50 +722,58 @@ static bool get_ocsp_requestor_cert(ocsp_location_t *location)
return FALSE;
}
-static chunk_t generate_signature(chunk_t digest, smartcard_t *sc,
- const RSA_private_key_t *pri)
+static chunk_t sc_build_sha1_signature(chunk_t tbs, smartcard_t *sc)
{
- chunk_t sigdata;
+ hasher_t *hasher;
u_char *pos;
+ u_char digest_buf[HASH_SIZE_SHA1];
+ chunk_t digest = chunk_from_buf(digest_buf);
+ chunk_t digest_info, sigdata;
size_t siglen = 0;
- if (sc != NULL)
+ if (!scx_establish_context(sc) || !scx_login(sc))
{
- /* RSA signature is done on smartcard */
-
- if (!scx_establish_context(sc) || !scx_login(sc))
- {
- scx_release_context(sc);
- return chunk_empty;
- }
+ scx_release_context(sc);
+ return chunk_empty;
+ }
- siglen = scx_get_keylength(sc);
+ siglen = scx_get_keylength(sc);
- if (siglen == 0)
- {
- plog("failed to get keylength from smartcard");
- scx_release_context(sc);
- return chunk_empty;
- }
+ if (siglen == 0)
+ {
+ plog("failed to get keylength from smartcard");
+ scx_release_context(sc);
+ return chunk_empty;
+ }
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("signing hash with RSA key from smartcard (slot: %d, id: %s)"
- , (int)sc->slot, sc->id)
- )
+ DBG(DBG_CONTROL | DBG_CRYPT,
+ DBG_log("signing hash with RSA key from smartcard (slot: %d, id: %s)"
+ , (int)sc->slot, sc->id)
+ )
- pos = asn1_build_object(&sigdata, ASN1_BIT_STRING, 1 + siglen);
- *pos++ = 0x00;
- scx_sign_hash(sc, digest.ptr, digest.len, pos, siglen);
- if (!pkcs11_keep_state)
- scx_release_context(sc);
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (hasher == NULL)
+ {
+ return chunk_empty;
}
- else
+ hasher->get_hash(hasher, tbs, digest_buf);
+ hasher->destroy(hasher);
+
+ /* according to PKCS#1 v2.1 digest must be packaged into
+ * an ASN.1 structure for encryption
+ */
+ digest_info = asn1_wrap(ASN1_SEQUENCE, "cm"
+ , asn1_algorithmIdentifier(OID_SHA1)
+ , asn1_simple_object(ASN1_OCTET_STRING, digest));
+
+ pos = asn1_build_object(&sigdata, ASN1_BIT_STRING, 1 + siglen);
+ *pos++ = 0x00;
+ scx_sign_hash(sc, digest_info.ptr, digest_info.len, pos, siglen);
+ free(digest_info.ptr);
+
+ if (!pkcs11_keep_state)
{
- /* RSA signature is done in software */
- siglen = pri->pub.k;
- pos = asn1_build_object(&sigdata, ASN1_BIT_STRING, 1 + siglen);
- *pos++ = 0x00;
- sign_hash(pri, digest.ptr, digest.len, pos, siglen);
+ scx_release_context(sc);
}
return sigdata;
}
@@ -770,30 +785,22 @@ static chunk_t generate_signature(chunk_t digest, smartcard_t *sc,
static chunk_t build_signature(chunk_t tbsRequest)
{
chunk_t sigdata, certs;
- chunk_t digest_info;
-
- u_char digest_buf[MAX_DIGEST_LEN];
- chunk_t digest_raw = { digest_buf, MAX_DIGEST_LEN };
- if (!compute_digest(tbsRequest, OID_SHA1, &digest_raw))
- return chunk_empty;
-
- /* according to PKCS#1 v2.1 digest must be packaged into
- * an ASN.1 structure for encryption
- */
- digest_info = asn1_wrap(ASN1_SEQUENCE, "cm"
- , asn1_algorithmIdentifier(OID_SHA1)
- , asn1_simple_object(ASN1_OCTET_STRING, digest_raw));
-
- /* generate the RSA signature */
- sigdata = generate_signature(digest_info
- , ocsp_requestor_sc
- , ocsp_requestor_pri);
- free(digest_info.ptr);
-
- /* has the RSA signature generation been successful? */
+ if (ocsp_requestor_sc != NULL)
+ {
+ /* RSA signature is done on smartcard */
+ sigdata = sc_build_sha1_signature(tbsRequest, ocsp_requestor_sc);
+ }
+ else
+ {
+ /* RSA signature is done in software */
+ sigdata = x509_build_signature(tbsRequest, OID_SHA1, ocsp_requestor_key,
+ TRUE);
+ }
if (sigdata.ptr == NULL)
+ {
return chunk_empty;
+ }
/* include our certificate */
certs = asn1_wrap(ASN1_CONTEXT_C_0, "m"
@@ -992,8 +999,7 @@ static bool valid_ocsp_response(response_t *res)
DBG_log("ocsp signer cert found")
)
- if (!check_signature(res->tbs, res->signature, res->algorithm
- , res->algorithm, authcert))
+ if (!x509_check_signature(res->tbs, res->signature, res->algorithm, authcert))
{
plog("signature of ocsp response is invalid");
unlock_authcert_list("valid_ocsp_response");
@@ -1051,8 +1057,8 @@ static bool valid_ocsp_response(response_t *res)
DBG_log("issuer cacert found")
)
- if (!check_signature(cert->tbsCertificate, cert->signature
- , cert->algorithm, cert->algorithm, authcert))
+ if (!x509_check_signature(cert->tbsCertificate, cert->signature,
+ cert->algorithm, authcert))
{
plog("certificate signature is invalid");
unlock_authcert_list("valid_ocsp_response");
diff --git a/src/pluto/pgp.c b/src/pluto/pgpcert.c
index e80b2cc5b..bfa048265 100644
--- a/src/pluto/pgp.c
+++ b/src/pluto/pgpcert.c
@@ -1,5 +1,7 @@
/* Support of OpenPGP certificates
- * Copyright (C) 2002-2004 Andreas Steffen, Zuercher Hochschule Winterthur
+ * Copyright (C) 2002-2009 Andreas Steffen
+ *
+ * HSR - Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -19,6 +21,7 @@
#include <freeswan.h>
#include <library.h>
+#include <pgp/pgp.h>
#include <crypto/hashers/hasher.h>
#include "constants.h"
@@ -26,10 +29,9 @@
#include "mp_defs.h"
#include "log.h"
#include "id.h"
-#include "pgp.h"
+#include "pgpcert.h"
#include "certs.h"
#include "whack.h"
-#include "pkcs1.h"
#include "keys.h"
/*
@@ -88,36 +90,6 @@ static const char *const pgp_packet_type_name[] = {
#define PGP_PUBKEY_ALG_ELGAMAL 20
/*
- * OpenPGP symmetric key algorithms defined in section 9.2 of RFC 2440
- */
-#define PGP_SYM_ALG_PLAIN 0
-#define PGP_SYM_ALG_IDEA 1
-#define PGP_SYM_ALG_3DES 2
-#define PGP_SYM_ALG_CAST5 3
-#define PGP_SYM_ALG_BLOWFISH 4
-#define PGP_SYM_ALG_SAFER 5
-#define PGP_SYM_ALG_DES 6
-#define PGP_SYM_ALG_AES 7
-#define PGP_SYM_ALG_AES_192 8
-#define PGP_SYM_ALG_AES_256 9
-#define PGP_SYM_ALG_TWOFISH 10
-#define PGP_SYM_ALG_ROOF 11
-
-static const char *const pgp_sym_alg_name[] = {
- "Plaintext",
- "IDEA",
- "3DES",
- "CAST5",
- "Blowfish",
- "SAFER",
- "DES",
- "AES",
- "AES-192",
- "AES-256",
- "Twofish"
-};
-
-/*
* Size of PGP Key ID
*/
#define PGP_KEYID_SIZE 8
@@ -129,28 +101,15 @@ const pgpcert_t empty_pgpcert = {
{ NULL, 0 }, /* certificate */
0 , /* created */
0 , /* until */
- 0 , /* pubkeyAlgorithm */
- { NULL, 0 }, /* modulus */
- { NULL, 0 }, /* publicExponent */
- "" /* fingerprint */
+ NULL , /* public key */
+ NULL /* fingerprint */
};
-static size_t
-pgp_size(chunk_t *blob, int len)
-{
- size_t size = 0;
-
- blob->len -= len;
- while (len-- > 0)
- size = 256*size + *blob->ptr++;
- return size;
-}
/*
* extracts the length of a PGP packet
*/
-static size_t
-pgp_old_packet_length(chunk_t *blob)
+static size_t pgp_old_packet_length(chunk_t *blob)
{
/* bits 0 and 1 define the packet length type */
int len_type = 0x03 & *blob->ptr++;
@@ -158,14 +117,13 @@ pgp_old_packet_length(chunk_t *blob)
blob->len--;
/* len_type: 0 -> 1 byte, 1 -> 2 bytes, 2 -> 4 bytes */
- return pgp_size(blob, (len_type == 0)? 1: len_type << 1);
+ return pgp_length(blob, (len_type == 0)? 1: len_type << 1);
}
/*
* extracts PGP packet version (V3 or V4)
*/
-static u_char
-pgp_version(chunk_t *blob)
+static u_char pgp_version(chunk_t *blob)
{
u_char version = *blob->ptr++;
blob->len--;
@@ -179,10 +137,10 @@ pgp_version(chunk_t *blob)
/*
* Parse OpenPGP public key packet defined in section 5.5.2 of RFC 2440
*/
-static bool
-parse_pgp_pubkey_packet(chunk_t *packet, pgpcert_t *cert)
+static bool parse_pgp_pubkey_packet(chunk_t *packet, pgpcert_t *cert)
{
u_char version = pgp_version(packet);
+ public_key_t *key;
if (version < 3 || version > 4)
{
@@ -191,7 +149,7 @@ parse_pgp_pubkey_packet(chunk_t *packet, pgpcert_t *cert)
}
/* creation date - 4 bytes */
- cert->created = (time_t)pgp_size(packet, 4);
+ cert->created = (time_t)pgp_length(packet, 4);
DBG(DBG_PARSING,
DBG_log("L3 - created:");
DBG_log(" %T", &cert->created, TRUE)
@@ -200,12 +158,13 @@ parse_pgp_pubkey_packet(chunk_t *packet, pgpcert_t *cert)
if (version == 3)
{
/* validity in days - 2 bytes */
- cert->until = (time_t)pgp_size(packet, 2);
+ cert->until = (time_t)pgp_length(packet, 2);
/* validity of 0 days means that the key never expires */
if (cert->until > 0)
+ {
cert->until = cert->created + 24*3600*cert->until;
-
+ }
DBG(DBG_PARSING,
DBG_log("L3 - until:");
DBG_log(" %T", &cert->until, TRUE);
@@ -217,49 +176,29 @@ parse_pgp_pubkey_packet(chunk_t *packet, pgpcert_t *cert)
DBG_log("L3 - public key algorithm:")
)
- switch (pgp_size(packet, 1))
+ switch (pgp_length(packet, 1))
{
case PGP_PUBKEY_ALG_RSA:
case PGP_PUBKEY_ALG_RSA_SIGN_ONLY:
- cert->pubkeyAlg = PUBKEY_ALG_RSA;
DBG(DBG_PARSING,
DBG_log(" RSA")
)
- /* modulus n */
- cert->modulus.len = (pgp_size(packet, 2)+7) / BITS_PER_BYTE;
- cert->modulus.ptr = packet->ptr;
- packet->ptr += cert->modulus.len;
- packet->len -= cert->modulus.len;
- DBG(DBG_PARSING,
- DBG_log("L3 - modulus:")
- )
- DBG_cond_dump_chunk(DBG_RAW, "", cert->modulus);
-
- /* public exponent e */
- cert->publicExponent.len = (pgp_size(packet, 2)+7) / BITS_PER_BYTE;
- cert->publicExponent.ptr = packet->ptr;
- packet->ptr += cert->publicExponent.len;
- packet->len -= cert->publicExponent.len;
- DBG(DBG_PARSING,
- DBG_log("L3 - public exponent:")
- )
- DBG_cond_dump_chunk(DBG_RAW, "", cert->publicExponent);
+ key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
+ BUILD_BLOB_PGP, *packet,
+ BUILD_END);
+ if (key == NULL)
+ {
+ return FALSE;
+ }
+ cert->public_key = key;
if (version == 3)
{
- hasher_t *hasher;
-
- /* a V3 fingerprint is the MD5 hash of modulus and public exponent */
-
- hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
- if (hasher == NULL)
+ cert->fingerprint = key->get_id(key, ID_KEY_ID);
+ if (cert->fingerprint == NULL)
{
- plog(" computation of V3 key ID failed, no MD5 hasher is available");
return FALSE;
}
- hasher->get_hash(hasher, cert->modulus, NULL);
- hasher->get_hash(hasher, cert->publicExponent, cert->fingerprint);
- hasher->destroy(hasher);
}
else
{
@@ -267,14 +206,12 @@ parse_pgp_pubkey_packet(chunk_t *packet, pgpcert_t *cert)
}
break;
case PGP_PUBKEY_ALG_DSA:
- cert->pubkeyAlg = PUBKEY_ALG_DSA;
DBG(DBG_PARSING,
DBG_log(" DSA")
)
plog(" DSA public keys not supported");
return FALSE;
default:
- cert->pubkeyAlg = 0;
DBG(DBG_PARSING,
DBG_log(" other")
)
@@ -285,103 +222,9 @@ parse_pgp_pubkey_packet(chunk_t *packet, pgpcert_t *cert)
}
/*
- * Parse OpenPGP secret key packet defined in section 5.5.3 of RFC 2440
- */
-static bool
-parse_pgp_secretkey_packet(chunk_t *packet, RSA_private_key_t *key)
-{
- int i, s2k;
- pgpcert_t cert = empty_pgpcert;
-
- if (!parse_pgp_pubkey_packet(packet, &cert))
- return FALSE;
-
- init_RSA_public_key((RSA_public_key_t *)key, cert.publicExponent
- , cert.modulus);
-
- /* string-to-key usage */
- s2k = pgp_size(packet, 1);
-
- DBG(DBG_PARSING,
- DBG_log("L3 - string-to-key: %d", s2k)
- )
-
- if (s2k == 255)
- {
- plog(" string-to-key specifiers not supported");
- return FALSE;
- }
-
- if (s2k >= PGP_SYM_ALG_ROOF)
- {
- plog(" undefined symmetric key algorithm");
- return FALSE;
- }
-
- /* a known symmetric key algorithm is specified*/
- DBG(DBG_PARSING,
- DBG_log(" %s", pgp_sym_alg_name[s2k])
- )
-
- /* private key is unencrypted */
- if (s2k == PGP_SYM_ALG_PLAIN)
- {
- for (i = 2; i < RSA_PRIVATE_FIELD_ELEMENTS; i++)
- {
- mpz_t u; /* auxiliary variable */
-
- /* compute offset to private key component i*/
- MP_INT *n = (MP_INT*)((char *)key + RSA_private_field[i].offset);
-
- switch (i)
- {
- case 2:
- case 3:
- case 4:
- {
- size_t len = (pgp_size(packet, 2)+7) / BITS_PER_BYTE;
-
- n_to_mpz(n, packet->ptr, len);
- DBG(DBG_PARSING,
- DBG_log("L3 - %s:", RSA_private_field[i].name)
- )
- DBG_cond_dump(DBG_PRIVATE, "", packet->ptr, len);
- packet->ptr += len;
- packet->len -= len;
- }
- break;
- case 5: /* dP = d mod (p-1) */
- mpz_init(u);
- mpz_sub_ui(u, &key->p, 1);
- mpz_mod(n, &key->d, u);
- mpz_clear(u);
- break;
- case 6: /* dQ = d mod (q-1) */
- mpz_init(u);
- mpz_sub_ui(u, &key->q, 1);
- mpz_mod(n, &key->d, u);
- mpz_clear(u);
- break;
- case 7: /* qInv = (q^-1) mod p */
- mpz_invert(n, &key->q, &key->p);
- if (mpz_cmp_ui(n, 0) < 0)
- mpz_add(n, n, &key->p);
- passert(mpz_cmp(n, &key->p) < 0);
- break;
- }
- }
- return TRUE;
- }
-
- plog(" %s encryption not supported", pgp_sym_alg_name[s2k]);
- return FALSE;
-}
-
-/*
* Parse OpenPGP signature packet defined in section 5.2.2 of RFC 2440
*/
-static bool
-parse_pgp_signature_packet(chunk_t *packet, pgpcert_t *cert)
+static bool parse_pgp_signature_packet(chunk_t *packet, pgpcert_t *cert)
{
time_t created;
chunk_t keyid;
@@ -393,20 +236,20 @@ parse_pgp_signature_packet(chunk_t *packet, pgpcert_t *cert)
return TRUE;
/* size byte must have the value 5 */
- if (pgp_size(packet, 1) != 5)
+ if (pgp_length(packet, 1) != 5)
{
plog(" size must be 5");
return FALSE;
}
/* signature type - 1 byte */
- sig_type = (u_char)pgp_size(packet, 1);
+ sig_type = (u_char)pgp_length(packet, 1);
DBG(DBG_PARSING,
DBG_log("L3 - signature type: 0x%2x", sig_type)
)
/* creation date - 4 bytes */
- created = (time_t)pgp_size(packet, 4);
+ created = (time_t)pgp_length(packet, 4);
DBG(DBG_PARSING,
DBG_log("L3 - created:");
DBG_log(" %T", &cert->created, TRUE)
@@ -420,8 +263,7 @@ parse_pgp_signature_packet(chunk_t *packet, pgpcert_t *cert)
return TRUE;
}
-bool
-parse_pgp(chunk_t blob, pgpcert_t *cert, RSA_private_key_t *key)
+bool parse_pgp(chunk_t blob, pgpcert_t *cert, private_key_t **key)
{
DBG(DBG_PARSING,
DBG_log("L0 - PGP file:")
@@ -486,11 +328,15 @@ parse_pgp(chunk_t blob, pgpcert_t *cert, RSA_private_key_t *key)
{
case PGP_PKT_PUBLIC_KEY:
if (!parse_pgp_pubkey_packet(&packet, cert))
+ {
return FALSE;
+ }
break;
case PGP_PKT_SIGNATURE:
if (!parse_pgp_signature_packet(&packet, cert))
+ {
return FALSE;
+ }
break;
case PGP_PKT_USER_ID:
DBG(DBG_PARSING,
@@ -508,12 +354,18 @@ parse_pgp(chunk_t blob, pgpcert_t *cert, RSA_private_key_t *key)
switch (packet_type)
{
case PGP_PKT_SECRET_KEY:
- if (!parse_pgp_secretkey_packet(&packet, key))
- return FALSE;
+ *key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_BLOB_PGP, packet,
+ BUILD_END);
break;
default:
break;
}
+ if (*key == NULL)
+ {
+ return FALSE;
+ }
+
}
}
}
@@ -523,8 +375,7 @@ parse_pgp(chunk_t blob, pgpcert_t *cert, RSA_private_key_t *key)
/*
* compare two OpenPGP certificates
*/
-static bool
-same_pgpcert(pgpcert_t *a, pgpcert_t *b)
+static bool same_pgpcert(pgpcert_t *a, pgpcert_t *b)
{
return a->certificate.len == b->certificate.len &&
memeq(a->certificate.ptr, b->certificate.ptr, b->certificate.len);
@@ -533,8 +384,7 @@ same_pgpcert(pgpcert_t *a, pgpcert_t *b)
/*
* for each link pointing to the certificate increase the count by one
*/
-void
-share_pgpcert(pgpcert_t *cert)
+void share_pgpcert(pgpcert_t *cert)
{
if (cert != NULL)
{
@@ -545,21 +395,17 @@ share_pgpcert(pgpcert_t *cert)
/*
* select the OpenPGP keyid as ID
*/
-void
-select_pgpcert_id(pgpcert_t *cert, struct id *end_id)
+void select_pgpcert_id(pgpcert_t *cert, struct id *end_id)
{
end_id->kind = ID_KEY_ID;
- end_id->name.len = PGP_FINGERPRINT_SIZE;
- end_id->name.ptr = cert->fingerprint;
- end_id->name.ptr = temporary_cyclic_buffer();
- memcpy(end_id->name.ptr, cert->fingerprint, PGP_FINGERPRINT_SIZE);
+ end_id->name = cert->fingerprint->get_encoding(cert->fingerprint);
+ end_id->name = chunk_clone(end_id->name);
}
/*
* add an OpenPGP user/host certificate to the chained list
*/
-pgpcert_t*
-add_pgpcert(pgpcert_t *cert)
+pgpcert_t* add_pgpcert(pgpcert_t *cert)
{
pgpcert_t *c = pgpcerts;
@@ -585,14 +431,15 @@ add_pgpcert(pgpcert_t *cert)
/* release of a certificate decreases the count by one
" the certificate is freed when the counter reaches zero
*/
-void
-release_pgpcert(pgpcert_t *cert)
+void release_pgpcert(pgpcert_t *cert)
{
if (cert != NULL && --cert->count == 0)
{
pgpcert_t **pp = &pgpcerts;
while (*pp != cert)
+ {
pp = &(*pp)->next;
+ }
*pp = cert->next;
free_pgpcert(cert);
}
@@ -601,11 +448,12 @@ release_pgpcert(pgpcert_t *cert)
/*
* free a PGP certificate
*/
-void
-free_pgpcert(pgpcert_t *cert)
+void free_pgpcert(pgpcert_t *cert)
{
if (cert != NULL)
{
+ DESTROY_IF(cert->public_key);
+ DESTROY_IF(cert->fingerprint);
free(cert->certificate.ptr);
free(cert);
}
@@ -614,8 +462,7 @@ free_pgpcert(pgpcert_t *cert)
/*
* list all PGP end certificates in a chained list
*/
-void
-list_pgp_end_certs(bool utc)
+void list_pgp_end_certs(bool utc)
{
pgpcert_t *cert = pgpcerts;
time_t now;
@@ -632,19 +479,20 @@ list_pgp_end_certs(bool utc)
while (cert != NULL)
{
- unsigned keysize;
- char buf[BUF_LEN];
+ public_key_t *key = cert->public_key;
cert_t c;
c.type = CERT_PGP;
c.u.pgp = cert;
whack_log(RC_COMMENT, "%T, count: %d", &cert->installed, utc, cert->count);
- datatot(cert->fingerprint, PGP_FINGERPRINT_SIZE, 'x', buf, BUF_LEN);
- whack_log(RC_COMMENT, " fingerprint: %s", buf);
- form_keyid(cert->publicExponent, cert->modulus, buf, &keysize);
- whack_log(RC_COMMENT, " pubkey: %4d RSA Key %s%s", 8*keysize, buf,
- (has_private_key(c))? ", has private key" : "");
+ whack_log(RC_COMMENT, " fingerprint: %Y", cert->fingerprint);
+ whack_log(RC_COMMENT, " pubkey: %N %4d bits%s",
+ key_type_names, key->get_type(key),
+ key->get_keysize(key) * BITS_PER_BYTE,
+ has_private_key(c)? ", has private key" : "");
+ whack_log(RC_COMMENT, " keyid: %Y",
+ key->get_id(key, ID_PUBKEY_INFO_SHA1));
whack_log(RC_COMMENT, " created: %T", &cert->created, utc);
whack_log(RC_COMMENT, " until: %T %s", &cert->until, utc,
check_expiry(cert->until, CA_CERT_WARNING_INTERVAL, TRUE));
diff --git a/src/pluto/pgp.h b/src/pluto/pgpcert.h
index 4519022e4..9d8912ec5 100644
--- a/src/pluto/pgp.h
+++ b/src/pluto/pgpcert.h
@@ -1,5 +1,7 @@
/* Support of OpenPGP certificates
- * Copyright (C) 2002-2004 Andreas Steffen, Zuercher Hochschule Winterthur
+ * Copyright (C) 2002-2009 Andreas Steffen
+ *
+ * HSR - Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -12,12 +14,12 @@
* for more details.
*/
-#ifndef _PGP_H
-#define _PGP_H
+#ifndef _PGPCERT_H
+#define _PGPCERT_H
#include <crypto/hashers/hasher.h>
-
-#include "pkcs1.h"
+#include <credentials/keys/private_key.h>
+#include <credentials/keys/public_key.h>
/*
* Length of PGP V3 fingerprint
@@ -31,20 +33,18 @@ typedef char fingerprint_t[PGP_FINGERPRINT_SIZE];
typedef struct pgpcert pgpcert_t;
struct pgpcert {
- pgpcert_t *next;
- time_t installed;
- int count;
- chunk_t certificate;
- time_t created;
- time_t until;
- enum pubkey_alg pubkeyAlg;
- chunk_t modulus;
- chunk_t publicExponent;
- fingerprint_t fingerprint;
+ pgpcert_t *next;
+ time_t installed;
+ int count;
+ chunk_t certificate;
+ time_t created;
+ time_t until;
+ public_key_t *public_key;
+ identification_t *fingerprint;
};
extern const pgpcert_t empty_pgpcert;
-extern bool parse_pgp(chunk_t blob, pgpcert_t *cert, RSA_private_key_t *key);
+extern bool parse_pgp(chunk_t blob, pgpcert_t *cert, private_key_t **key);
extern void share_pgpcert(pgpcert_t *cert);
extern void select_pgpcert_id(pgpcert_t *cert, struct id *end_id);
extern pgpcert_t* add_pgpcert(pgpcert_t *cert);
@@ -52,4 +52,4 @@ extern void list_pgp_end_certs(bool utc);
extern void release_pgpcert(pgpcert_t *cert);
extern void free_pgpcert(pgpcert_t *cert);
-#endif /* _PGP_H */
+#endif /* _PGPCERT_H */
diff --git a/src/pluto/pkcs1.c b/src/pluto/pkcs1.c
deleted file mode 100644
index 51c90a2e2..000000000
--- a/src/pluto/pkcs1.c
+++ /dev/null
@@ -1,602 +0,0 @@
-/* Support of PKCS#1 private key data structures
- * Copyright (C) 2005 Jan Hutter, Martin Willi
- * Copyright (C) 2002-2009 Andreas Steffen
- *
- * HSR Hochschule fuer Technik Rapperswil, Switzerland
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * 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.
- */
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <freeswan.h>
-
-#include <library.h>
-#include <asn1/asn1.h>
-#include <asn1/asn1_parser.h>
-#include <asn1/oid.h>
-#include <crypto/rngs/rng.h>
-#include <crypto/hashers/hasher.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "mp_defs.h"
-#include "log.h"
-#include "pkcs1.h"
-
-const struct fld RSA_private_field[] =
-{
- { "Modulus", offsetof(RSA_private_key_t, pub.n) },
- { "PublicExponent", offsetof(RSA_private_key_t, pub.e) },
-
- { "PrivateExponent", offsetof(RSA_private_key_t, d) },
- { "Prime1", offsetof(RSA_private_key_t, p) },
- { "Prime2", offsetof(RSA_private_key_t, q) },
- { "Exponent1", offsetof(RSA_private_key_t, dP) },
- { "Exponent2", offsetof(RSA_private_key_t, dQ) },
- { "Coefficient", offsetof(RSA_private_key_t, qInv) },
-};
-
-/**
- * ASN.1 definition of a PKCS#1 RSA private key
- */
-static const asn1Object_t privkeyObjects[] = {
- { 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, "exit", ASN1_EOC, ASN1_EXIT }
-};
-#define PKCS1_PRIV_KEY_VERSION 1
-#define PKCS1_PRIV_KEY_MODULUS 2
-#define PKCS1_PRIV_KEY_PUB_EXP 3
-#define PKCS1_PRIV_KEY_COEFF 9
-
-/**
- * Forms the FreeS/WAN keyid from the public exponent e and modulus n
- */
-void form_keyid(chunk_t e, chunk_t n, char* keyid, unsigned *keysize)
-{
- /* eliminate leading zero bytes in modulus from ASN.1 coding */
- while (n.len > 1 && *n.ptr == 0x00)
- {
- n.ptr++; n.len--;
- }
-
- /* form the FreeS/WAN keyid */
- keyid[0] = '\0'; /* in case of splitkeytoid failure */
- splitkeytoid(e.ptr, e.len, n.ptr, n.len, keyid, KEYID_BUF);
-
- /* return the RSA modulus size in octets */
- *keysize = n.len;
-}
-
-/**
- * Initialize an RSA_public_key_t object
- */
-void init_RSA_public_key(RSA_public_key_t *rsa, chunk_t e, chunk_t n)
-{
- n_to_mpz(&rsa->e, e.ptr, e.len);
- n_to_mpz(&rsa->n, n.ptr, n.len);
-
- form_keyid(e, n, rsa->keyid, &rsa->k);
-}
-
-#ifdef DEBUG
-static void RSA_show_key_fields(RSA_private_key_t *k, int fieldcnt)
-{
- const struct fld *p;
-
- DBG_log(" keyid: *%s", k->pub.keyid);
-
- for (p = RSA_private_field; p < &RSA_private_field[fieldcnt]; p++)
- {
- MP_INT *n = (MP_INT *) ((char *)k + p->offset);
- size_t sz = mpz_sizeinbase(n, 16);
- char buf[RSA_MAX_OCTETS * 2 + 2]; /* ought to be big enough */
-
- passert(sz <= sizeof(buf));
- mpz_get_str(buf, 16, n);
-
- DBG_log(" %s: 0x%s", p->name, buf);
- }
-}
-
-/**
- * debugging info that compromises security!
- */
-void RSA_show_private_key(RSA_private_key_t *k)
-{
- RSA_show_key_fields(k, countof(RSA_private_field));
-}
-
-void RSA_show_public_key(RSA_public_key_t *k)
-{
- /* Kludge: pretend that it is a private key, but only display the
- * first two fields (which are the public key).
- */
- passert(offsetof(RSA_private_key_t, pub) == 0);
- RSA_show_key_fields((RSA_private_key_t *)k, 2);
-}
-#endif
-
-err_t RSA_private_key_sanity(RSA_private_key_t *k)
-{
- /* note that the *last* error found is reported */
- err_t ugh = NULL;
- mpz_t t, u, q1;
-
-#ifdef DEBUG /* debugging info that compromises security */
- DBG(DBG_PRIVATE, RSA_show_private_key(k));
-#endif
-
- /* PKCS#1 1.5 section 6 requires modulus to have at least 12 octets.
- * We actually require more (for security).
- */
- if (k->pub.k < RSA_MIN_OCTETS)
- return RSA_MIN_OCTETS_UGH;
-
- /* we picked a max modulus size to simplify buffer allocation */
- if (k->pub.k > RSA_MAX_OCTETS)
- return RSA_MAX_OCTETS_UGH;
-
- mpz_init(t);
- mpz_init(u);
- mpz_init(q1);
-
- /* check that n == p * q */
- mpz_mul(u, &k->p, &k->q);
- if (mpz_cmp(u, &k->pub.n) != 0)
- ugh = "n != p * q";
-
- /* check that e divides neither p-1 nor q-1 */
- mpz_sub_ui(t, &k->p, 1);
- mpz_mod(t, t, &k->pub.e);
- if (mpz_cmp_ui(t, 0) == 0)
- ugh = "e divides p-1";
-
- mpz_sub_ui(t, &k->q, 1);
- mpz_mod(t, t, &k->pub.e);
- if (mpz_cmp_ui(t, 0) == 0)
- ugh = "e divides q-1";
-
- /* check that d is e^-1 (mod lcm(p-1, q-1)) */
- /* see PKCS#1v2, aka RFC 2437, for the "lcm" */
- mpz_sub_ui(q1, &k->q, 1);
- mpz_sub_ui(u, &k->p, 1);
- mpz_gcd(t, u, q1); /* t := gcd(p-1, q-1) */
- mpz_mul(u, u, q1); /* u := (p-1) * (q-1) */
- mpz_divexact(u, u, t); /* u := lcm(p-1, q-1) */
-
- mpz_mul(t, &k->d, &k->pub.e);
- mpz_mod(t, t, u);
- if (mpz_cmp_ui(t, 1) != 0)
- ugh = "(d * e) mod (lcm(p-1, q-1)) != 1";
-
- /* check that dP is d mod (p-1) */
- mpz_sub_ui(u, &k->p, 1);
- mpz_mod(t, &k->d, u);
- if (mpz_cmp(t, &k->dP) != 0)
- ugh = "dP is not congruent to d mod (p-1)";
-
- /* check that dQ is d mod (q-1) */
- mpz_sub_ui(u, &k->q, 1);
- mpz_mod(t, &k->d, u);
- if (mpz_cmp(t, &k->dQ) != 0)
- ugh = "dQ is not congruent to d mod (q-1)";
-
- /* check that qInv is (q^-1) mod p */
- mpz_mul(t, &k->qInv, &k->q);
- mpz_mod(t, t, &k->p);
- if (mpz_cmp_ui(t, 1) != 0)
- ugh = "qInv is not conguent ot (q^-1) mod p";
-
- mpz_clear(t);
- mpz_clear(u);
- mpz_clear(q1);
- return ugh;
-}
-
-/**
- * Check the equality of two RSA public keys
- */
-bool same_RSA_public_key(const RSA_public_key_t *a, const RSA_public_key_t *b)
-{
- return a == b
- || (a->k == b->k && mpz_cmp(&a->n, &b->n) == 0 && mpz_cmp(&a->e, &b->e) == 0);
-}
-
-/**
- * Parses a PKCS#1 private key
- */
-bool pkcs1_parse_private_key(chunk_t blob, RSA_private_key_t *key)
-{
- asn1_parser_t *parser;
- chunk_t object, modulus, exp;
- int objectID;
- bool success = FALSE;
-
- parser = asn1_parser_create(privkeyObjects, blob);
- parser->set_flags(parser, FALSE, TRUE);
-
- while (parser->iterate(parser, &objectID, &object))
- {
- if (objectID == PKCS1_PRIV_KEY_VERSION)
- {
- if (object.len > 0 && *object.ptr != 0)
- {
- plog(" wrong PKCS#1 private key version");
- goto end;
- }
- }
- else if (objectID >= PKCS1_PRIV_KEY_MODULUS &&
- objectID <= PKCS1_PRIV_KEY_COEFF)
- {
- MP_INT *u = (MP_INT *) ((char *)key
- + RSA_private_field[objectID - PKCS1_PRIV_KEY_MODULUS].offset);
-
- n_to_mpz(u, object.ptr, object.len);
-
- if (objectID == PKCS1_PRIV_KEY_MODULUS)
- modulus = object;
- else if (objectID == PKCS1_PRIV_KEY_PUB_EXP)
- exp = object;
- }
- }
- success = parser->success(parser);
-
-end:
- parser->destroy(parser);
-
- if (success)
- {
- err_t ugh;
-
- form_keyid(exp, modulus, key->pub.keyid, &key->pub.k);
- ugh = RSA_private_key_sanity(key);
- success = (ugh == NULL);
- }
- return success;
-}
-
-/**
- * Compute a digest over a binary blob
- */
-bool compute_digest(chunk_t tbs, int oid, chunk_t *digest)
-{
- hasher_t *hasher;
- hash_algorithm_t alg = hasher_algorithm_from_oid(oid);
-
- if (alg == HASH_UNKNOWN)
- {
- digest->len = 0;
- return FALSE;
- }
-
- hasher = lib->crypto->create_hasher(lib->crypto, alg);
- if (hasher == NULL)
- {
- digest->len = 0;
- return FALSE;
- }
- digest->len = hasher->get_hash_size(hasher);
- hasher->get_hash(hasher, tbs, digest->ptr);
- hasher->destroy(hasher);
- return TRUE;
-}
-
-/**
- * Compute an RSA signature with PKCS#1 padding
- */
-void sign_hash(const RSA_private_key_t *k, const u_char *hash_val,
- size_t hash_len, u_char *sig_val, size_t sig_len)
-{
- chunk_t ch;
- mpz_t t1, t2;
- size_t padlen;
- u_char *p = sig_val;
-
- DBG(DBG_CONTROL | DBG_CRYPT,
- DBG_log("signing hash with RSA Key *%s", k->pub.keyid)
- )
- /* PKCS#1 v1.5 8.1 encryption-block formatting */
- *p++ = 0x00;
- *p++ = 0x01; /* BT (block type) 01 */
- padlen = sig_len - 3 - hash_len;
- memset(p, 0xFF, padlen);
- p += padlen;
- *p++ = 0x00;
- memcpy(p, hash_val, hash_len);
- passert(p + hash_len - sig_val == (ptrdiff_t)sig_len);
-
- /* PKCS#1 v1.5 8.2 octet-string-to-integer conversion */
- n_to_mpz(t1, sig_val, sig_len); /* (could skip leading 0x00) */
-
- /* PKCS#1 v1.5 8.3 RSA computation y = x^c mod n
- * Better described in PKCS#1 v2.0 5.1 RSADP.
- * There are two methods, depending on the form of the private key.
- * We use the one based on the Chinese Remainder Theorem.
- */
- mpz_init(t2);
-
- mpz_powm(t2, t1, &k->dP, &k->p); /* m1 = c^dP mod p */
-
- mpz_powm(t1, t1, &k->dQ, &k->q); /* m2 = c^dQ mod Q */
-
- mpz_sub(t2, t2, t1); /* h = qInv (m1 - m2) mod p */
- mpz_mod(t2, t2, &k->p);
- mpz_mul(t2, t2, &k->qInv);
- mpz_mod(t2, t2, &k->p);
-
- mpz_mul(t2, t2, &k->q); /* m = m2 + h q */
- mpz_add(t1, t1, t2);
-
- /* PKCS#1 v1.5 8.4 integer-to-octet-string conversion */
- ch = mpz_to_n(t1, sig_len);
- memcpy(sig_val, ch.ptr, sig_len);
- free(ch.ptr);
-
- mpz_clear(t1);
- mpz_clear(t2);
-}
-
-/**
- * Encrypt data with an RSA public key after padding
- */
-chunk_t RSA_encrypt(const RSA_public_key_t *key, chunk_t in)
-{
- u_char padded[RSA_MAX_OCTETS];
- u_char *pos = padded;
- int padding = key->k - in.len - 3;
- int i;
- rng_t *rng;
-
- if (padding < 8 || key->k > RSA_MAX_OCTETS)
- return chunk_empty;
-
- /* add padding according to PKCS#1 7.2.1 1.+2. */
- *pos++ = 0x00;
- *pos++ = 0x02;
-
- /* pad with pseudo random bytes unequal to zero */
- rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- for (i = 0; i < padding; i++)
- {
- rng->get_bytes(rng, padding, pos);
- while (!*pos)
- {
- rng->get_bytes(rng, 1, pos);
- }
- pos++;
- }
- rng->destroy(rng);
-
- /* append the padding terminator */
- *pos++ = 0x00;
-
- /* now add the data */
- memcpy(pos, in.ptr, in.len);
- DBG(DBG_RAW,
- DBG_dump_chunk("data for rsa encryption:\n", in);
- DBG_dump("padded data for rsa encryption:\n", padded, key->k)
- )
-
- /* convert chunk to integer (PKCS#1 7.2.1 3.a) */
- {
- chunk_t out;
- mpz_t m, c;
-
- mpz_init(c);
- n_to_mpz(m, padded, key->k);
-
- /* encrypt(PKCS#1 7.2.1 3.b) */
- mpz_powm(c, m, &key->e, &key->n);
-
- /* convert integer back to a chunk (PKCS#1 7.2.1 3.c) */
- out = mpz_to_n(c, key->k);
- mpz_clear(c);
- mpz_clear(m);
-
- DBG(DBG_RAW,
- DBG_dump_chunk("rsa encrypted data:\n", out)
- )
- return out;
- }
-}
-
-/**
- * Decrypt data with an RSA private key and remove padding
- */
-bool RSA_decrypt(const RSA_private_key_t *key, chunk_t in, chunk_t *out)
-{
- chunk_t padded, plaintext;
- u_char *pos;
- mpz_t t1, t2;
-
- n_to_mpz(t1, in.ptr,in.len);
-
- /* PKCS#1 v1.5 8.3 RSA computation y = x^c mod n
- * Better described in PKCS#1 v2.0 5.1 RSADP.
- * There are two methods, depending on the form of the private key.
- * We use the one based on the Chinese Remainder Theorem.
- */
- mpz_init(t2);
-
- mpz_powm(t2, t1, &key->dP, &key->p); /* m1 = c^dP mod p */
- mpz_powm(t1, t1, &key->dQ, &key->q); /* m2 = c^dQ mod Q */
-
- mpz_sub(t2, t2, t1); /* h = qInv (m1 - m2) mod p */
- mpz_mod(t2, t2, &key->p);
- mpz_mul(t2, t2, &key->qInv);
- mpz_mod(t2, t2, &key->p);
-
- mpz_mul(t2, t2, &key->q); /* m = m2 + h q */
- mpz_add(t1, t1, t2);
-
- padded = mpz_to_n(t1, key->pub.k);
- mpz_clear(t1);
- mpz_clear(t2);
-
- DBG(DBG_PRIVATE,
- DBG_dump_chunk("rsa decrypted data with padding:\n", padded)
- )
- pos = padded.ptr;
-
- /* PKCS#1 v1.5 8.1 encryption-block formatting (EB = 00 || 02 || PS || 00 || D) */
-
- /* check for hex pattern 00 02 in decrypted message */
- if ((*pos++ != 0x00) || (*(pos++) != 0x02))
- {
- plog("incorrect padding - probably wrong RSA key");
- chunk_clear(&padded);
- return FALSE;
- }
- padded.len -= 2;
-
- /* the plaintext data starts after first 0x00 byte */
- while (padded.len-- > 0 && *pos++ != 0x00)
-
- if (padded.len == 0)
- {
- plog("no plaintext data");
- free(padded.ptr);
- return FALSE;
- }
-
- plaintext = chunk_create(pos, padded.len);
- *out = chunk_clone(plaintext);
- chunk_clear(&padded);
- return TRUE;
-}
-
-/**
- * Build signatureValue
- */
-chunk_t pkcs1_build_signature(chunk_t tbs, int hash_alg,
- const RSA_private_key_t *key, bool bit_string)
-{
-
- size_t siglen = key->pub.k;
-
- u_char digest_buf[MAX_DIGEST_LEN];
- chunk_t digest = { digest_buf, MAX_DIGEST_LEN };
- chunk_t digestInfo, signatureValue;
- u_char *pos;
-
- if (!compute_digest(tbs, hash_alg, &digest))
- {
- return chunk_empty;
- }
-
- /* according to PKCS#1 v2.1 digest must be packaged into
- * an ASN.1 structure for encryption
- */
- digestInfo = asn1_wrap(ASN1_SEQUENCE, "cm"
- , asn1_algorithmIdentifier(hash_alg)
- , asn1_simple_object(ASN1_OCTET_STRING, digest));
-
- /* generate the RSA signature */
- if (bit_string)
- {
- pos = asn1_build_object(&signatureValue, ASN1_BIT_STRING, 1 + siglen);
- *pos++ = 0x00;
- }
- else
- {
- pos = asn1_build_object(&signatureValue, ASN1_OCTET_STRING, siglen);
- }
- sign_hash(key, digestInfo.ptr, digestInfo.len, pos, siglen);
- free(digestInfo.ptr);
-
- return signatureValue;
-}
-
-/**
- * Build a DER-encoded PKCS#1 private key object
- */
-chunk_t pkcs1_build_private_key(const RSA_private_key_t *key)
-{
- chunk_t pkcs1 = asn1_wrap(ASN1_SEQUENCE, "cmmmmmmmm"
- , ASN1_INTEGER_0
- , asn1_integer_from_mpz(&key->pub.n)
- , asn1_integer_from_mpz(&key->pub.e)
- , asn1_integer_from_mpz(&key->d)
- , asn1_integer_from_mpz(&key->p)
- , asn1_integer_from_mpz(&key->q)
- , asn1_integer_from_mpz(&key->dP)
- , asn1_integer_from_mpz(&key->dQ)
- , asn1_integer_from_mpz(&key->qInv));
-
- DBG(DBG_PRIVATE,
- DBG_dump_chunk("PKCS#1 encoded private key:", pkcs1)
- )
- return pkcs1;
-}
-
-/**
- * Build a DER-encoded PKCS#1 public key object
- */
-chunk_t pkcs1_build_public_key(const RSA_public_key_t *rsa)
-{
- return asn1_wrap(ASN1_SEQUENCE, "mm"
- , asn1_integer_from_mpz(&rsa->n)
- , asn1_integer_from_mpz(&rsa->e));
-}
-
-/**
- * Build a DER-encoded publicKeyInfo object
- */
-chunk_t pkcs1_build_publicKeyInfo(const RSA_public_key_t *rsa)
-{
- chunk_t publicKey;
- chunk_t rawKey = pkcs1_build_public_key(rsa);
- u_char *pos;
-
- pos = asn1_build_object(&publicKey, ASN1_BIT_STRING, 1 + rawKey.len);
- *pos++ = 0x00;
- mv_chunk(&pos, rawKey);
-
- return asn1_wrap(ASN1_SEQUENCE, "cm"
- , asn1_algorithmIdentifier(OID_RSA_ENCRYPTION)
- , publicKey);
-}
-
-void free_RSA_public_content(RSA_public_key_t *rsa)
-{
- mpz_clear(&rsa->n);
- mpz_clear(&rsa->e);
-}
-
-void free_RSA_private_content(RSA_private_key_t *rsak)
-{
- free_RSA_public_content(&rsak->pub);
- mpz_clear(&rsak->d);
- mpz_clear(&rsak->p);
- mpz_clear(&rsak->q);
- mpz_clear(&rsak->dP);
- mpz_clear(&rsak->dQ);
- mpz_clear(&rsak->qInv);
-}
diff --git a/src/pluto/pkcs1.h b/src/pluto/pkcs1.h
deleted file mode 100644
index 4aaa8c409..000000000
--- a/src/pluto/pkcs1.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/* Support of PKCS#1 private key data structures
- * Copyright (C) 2005 Jan Hutter, Martin Willi
- * Copyright (C) 2002-2005 Andreas Steffen
- * Hochschule fuer Technik Rapperswil, Switzerland
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * 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.
- */
-
-#ifndef _PKCS1_H
-#define _PKCS1_H
-
-#include <gmp.h> /* GNU Multi Precision library */
-
-#include "defs.h"
-
-typedef struct RSA_public_key RSA_public_key_t;
-
-struct RSA_public_key
-{
- char keyid[KEYID_BUF]; /* see ipsec_keyblobtoid(3) */
-
- /* length of modulus n in octets: [RSA_MIN_OCTETS, RSA_MAX_OCTETS] */
- unsigned k;
-
- /* public: */
- MP_INT
- n, /* modulus: p * q */
- e; /* exponent: relatively prime to (p-1) * (q-1) [probably small] */
-};
-
-typedef struct RSA_private_key RSA_private_key_t;
-
-struct RSA_private_key {
- struct RSA_public_key pub; /* must be at start for RSA_show_public_key */
-
- MP_INT
- d, /* private exponent: (e^-1) mod ((p-1) * (q-1)) */
- /* help for Chinese Remainder Theorem speedup: */
- p, /* first secret prime */
- q, /* second secret prime */
- dP, /* first factor's exponent: (e^-1) mod (p-1) == d mod (p-1) */
- dQ, /* second factor's exponent: (e^-1) mod (q-1) == d mod (q-1) */
- qInv; /* (q^-1) mod p */
-};
-
-struct fld {
- const char *name;
- size_t offset;
-};
-
-extern const struct fld RSA_private_field[];
-#define RSA_PRIVATE_FIELD_ELEMENTS 8
-
-extern void init_RSA_public_key(RSA_public_key_t *rsa, chunk_t e, chunk_t n);
-extern bool pkcs1_parse_private_key(chunk_t blob, RSA_private_key_t *key);
-extern chunk_t pkcs1_build_private_key(const RSA_private_key_t *key);
-extern chunk_t pkcs1_build_public_key(const RSA_public_key_t *rsa);
-extern chunk_t pkcs1_build_publicKeyInfo(const RSA_public_key_t *rsa);
-extern chunk_t pkcs1_build_signature(chunk_t tbs, int hash_alg
- , const RSA_private_key_t *key, bool bit_string);
-extern bool compute_digest(chunk_t tbs, int alg, chunk_t *digest);
-extern void sign_hash(const RSA_private_key_t *k, const u_char *hash_val
- , size_t hash_len, u_char *sig_val, size_t sig_len);
-extern chunk_t RSA_encrypt(const RSA_public_key_t *key, chunk_t in);
-extern bool RSA_decrypt(const RSA_private_key_t *key, chunk_t in
- , chunk_t *out);
-extern bool same_RSA_public_key(const RSA_public_key_t *a
- , const RSA_public_key_t *b);
-extern void form_keyid(chunk_t e, chunk_t n, char* keyid, unsigned *keysize);
-extern err_t RSA_private_key_sanity(RSA_private_key_t *k);
-#ifdef DEBUG
-extern void RSA_show_public_key(RSA_public_key_t *k);
-extern void RSA_show_private_key(RSA_private_key_t *k);
-#endif
-extern void free_RSA_public_content(RSA_public_key_t *rsa);
-extern void free_RSA_private_content(RSA_private_key_t *rsak);
-
-#endif /* _PKCS1_H */
diff --git a/src/pluto/pkcs7.c b/src/pluto/pkcs7.c
index c793d28df..ab4362c73 100644
--- a/src/pluto/pkcs7.c
+++ b/src/pluto/pkcs7.c
@@ -340,6 +340,9 @@ bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert
/* check the signature only if a cacert is available */
if (cacert != NULL)
{
+ public_key_t *key = cacert->public_key;
+ signature_scheme_t scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
+
if (signerInfos == 0)
{
DBG1("no signerInfo object found");
@@ -355,16 +358,40 @@ bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert
DBG1("no authenticatedAttributes object found");
return FALSE;
}
- if (!check_signature(*attributes, encrypted_digest, digest_alg,
- enc_alg, cacert))
+ if (enc_alg != OID_RSA_ENCRYPTION)
{
- DBG1("invalid signature");
+ DBG1("only RSA digest encryption supported");
return FALSE;
}
- else
+ switch (digest_alg)
+ {
+ case OID_MD5:
+ scheme = SIGN_RSA_EMSA_PKCS1_MD5;
+ break;
+ case OID_SHA1:
+ scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
+ break;
+ case OID_SHA256:
+ scheme = SIGN_RSA_EMSA_PKCS1_SHA256;
+ break;
+ case OID_SHA384:
+ scheme = SIGN_RSA_EMSA_PKCS1_SHA384;
+ break;
+ case OID_SHA512:
+ scheme = SIGN_RSA_EMSA_PKCS1_SHA512;
+ break;
+ default:
+ return FALSE;
+ }
+ if (key->verify(key, scheme, *attributes, encrypted_digest))
{
DBG2("signature is valid");
}
+ else
+ {
+ DBG1("invalid signature");
+ return FALSE;
+ }
}
return TRUE;
}
@@ -374,7 +401,7 @@ bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert
*/
bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data,
chunk_t serialNumber,
- const RSA_private_key_t *key)
+ private_key_t *key)
{
asn1_parser_t *parser;
chunk_t object;
@@ -446,7 +473,7 @@ bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data,
}
break;
case PKCS7_ENCRYPTED_KEY:
- if (!RSA_decrypt(key, object, &symmetric_key))
+ if (!key->decrypt(key, object, &symmetric_key))
{
DBG1("symmetric key could not be decrypted with rsa");
goto end;
@@ -579,17 +606,20 @@ chunk_t pkcs7_contentType_attribute(void)
*/
chunk_t pkcs7_messageDigest_attribute(chunk_t content, int digest_alg)
{
- u_char digest_buf[MAX_DIGEST_LEN];
- chunk_t digest = { digest_buf, MAX_DIGEST_LEN };
-
- compute_digest(content, digest_alg, &digest);
-
- return asn1_wrap(ASN1_SEQUENCE, "cm"
- , ASN1_messageDigest_oid
- , asn1_wrap(ASN1_SET, "m"
- , asn1_simple_object(ASN1_OCTET_STRING, digest)
- )
- );
+ chunk_t digest;
+ hash_algorithm_t hash_alg;
+ hasher_t *hasher;
+
+ hash_alg = hasher_algorithm_from_oid(digest_alg);
+ hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
+ hasher->allocate_hash(hasher, content, &digest);
+
+ return asn1_wrap(ASN1_SEQUENCE, "cm",
+ ASN1_messageDigest_oid,
+ asn1_wrap(ASN1_SET, "m",
+ asn1_wrap(ASN1_OCTET_STRING, "m", digest)
+ )
+ );
}
/**
@@ -649,7 +679,7 @@ chunk_t pkcs7_build_issuerAndSerialNumber(const x509cert_t *cert)
*/
chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes,
const x509cert_t *cert, int digest_alg,
- const RSA_private_key_t *key)
+ private_key_t *key)
{
contentInfo_t pkcs7Data, signedData;
chunk_t authenticatedAttributes, encryptedDigest, signerInfo, cInfo;
@@ -658,15 +688,15 @@ chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes,
if (attributes.ptr != NULL)
{
- encryptedDigest = pkcs1_build_signature(attributes, digest_alg
- , key, FALSE);
+ encryptedDigest = x509_build_signature(attributes, digest_alg, key,
+ FALSE);
authenticatedAttributes = chunk_clone(attributes);
*authenticatedAttributes.ptr = ASN1_CONTEXT_C_0;
}
else
{
encryptedDigest = (data.ptr == NULL)? chunk_empty
- : pkcs1_build_signature(data, digest_alg, key, FALSE);
+ : x509_build_signature(data, digest_alg, key, FALSE);
authenticatedAttributes = chunk_empty;
}
@@ -705,8 +735,7 @@ chunk_t pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert, int enc_
{
encryption_algorithm_t alg;
size_t alg_key_size;
- RSA_public_key_t public_key;
- chunk_t symmetricKey, iv, in, out;
+ chunk_t symmetricKey, protectedKey, iv, in, out;
crypter_t *crypter;
alg = encryption_algorithm_from_oid(enc_alg, &alg_key_size);
@@ -759,10 +788,11 @@ chunk_t pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert, int enc_
free(in.ptr);
free(iv.ptr);
- init_RSA_public_key(&public_key, cert->publicExponent, cert->modulus);
-
+ cert->public_key->encrypt(cert->public_key, symmetricKey, &protectedKey);
+
/* build pkcs7 enveloped data object */
{
+
chunk_t contentEncryptionAlgorithm = asn1_wrap(ASN1_SEQUENCE, "mm"
, asn1_build_known_oid(enc_alg)
, asn1_simple_object(ASN1_OCTET_STRING, iv));
@@ -773,7 +803,7 @@ chunk_t pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert, int enc_
, asn1_wrap(ASN1_CONTEXT_S_0, "m", out));
chunk_t encryptedKey = asn1_wrap(ASN1_OCTET_STRING, "m"
- , RSA_encrypt(&public_key, symmetricKey));
+ , protectedKey);
chunk_t recipientInfo = asn1_wrap(ASN1_SEQUENCE, "cmcm"
, ASN1_INTEGER_0
@@ -793,7 +823,6 @@ chunk_t pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert, int enc_
cInfo = pkcs7_build_contentInfo(&envelopedData);
DBG3("envelopedData %B", &cInfo);
- free_RSA_public_content(&public_key);
free(envelopedData.content.ptr);
free(symmetricKey.ptr);
return cInfo;
diff --git a/src/pluto/pkcs7.h b/src/pluto/pkcs7.h
index 09ffd65d5..028822dfe 100644
--- a/src/pluto/pkcs7.h
+++ b/src/pluto/pkcs7.h
@@ -1,6 +1,7 @@
/* Support of PKCS#7 data structures
* Copyright (C) 2005 Jan Hutter, Martin Willi
- * Copyright (C) 2002-2005 Andreas Steffen
+ * Copyright (C) 2002-2009 Andreas Steffen
+ *
* Hochschule fuer Technik Rapperswil, Switzerland
*
* This program is free software; you can redistribute it and/or modify it
@@ -18,9 +19,8 @@
#define _PKCS7_H
#include <crypto/crypters/crypter.h>
-
+#include <credentials/keys/private_key.h>
#include "defs.h"
-#include "pkcs1.h"
#include "x509.h"
/* Access structure for a PKCS#7 ContentInfo object */
@@ -39,12 +39,12 @@ extern bool pkcs7_parse_contentInfo(chunk_t blob, u_int level0,
extern bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data,
x509cert_t **cert, chunk_t *attributes, const x509cert_t *cacert);
extern bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data,
- chunk_t serialNumber, const RSA_private_key_t *key);
+ chunk_t serialNumber, private_key_t *key);
extern chunk_t pkcs7_contentType_attribute(void);
extern chunk_t pkcs7_messageDigest_attribute(chunk_t content, int digest_alg);
extern chunk_t pkcs7_build_issuerAndSerialNumber(const x509cert_t *cert);
extern chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes,
- const x509cert_t *cert, int digest_alg, const RSA_private_key_t *key);
+ const x509cert_t *cert, int digest_alg, private_key_t *key);
extern chunk_t pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert,
int enc_alg);
diff --git a/src/pluto/rcv_whack.c b/src/pluto/rcv_whack.c
index d40a4e28a..01f721ee9 100644
--- a/src/pluto/rcv_whack.c
+++ b/src/pluto/rcv_whack.c
@@ -234,10 +234,11 @@ key_add_request(const whack_message_t *msg)
}
else
{
- ugh = add_public_key(&keyid, DAL_LOCAL, msg->pubkey_alg
- , &msg->keyval, &pubkeys);
- if (ugh != NULL)
- loglog(RC_LOG_SERIOUS, "%s", ugh);
+ if (!add_public_key(&keyid, DAL_LOCAL, msg->pubkey_alg, msg->keyval,
+ &pubkeys))
+ {
+ loglog(RC_LOG_SERIOUS, "failed to add public key");
+ }
}
}
}
diff --git a/src/pluto/x509.c b/src/pluto/x509.c
index 9a5714bc9..ca926a9b8 100644
--- a/src/pluto/x509.c
+++ b/src/pluto/x509.c
@@ -35,7 +35,6 @@
#include "mp_defs.h"
#include "log.h"
#include "id.h"
-#include "pkcs1.h"
#include "x509.h"
#include "crl.h"
#include "ca.h"
@@ -198,36 +197,33 @@ static const asn1Object_t pubkeyObjects[] = {
* ASN.1 definition of an X.509v3 x509_cert
*/
static const asn1Object_t certObjects[] = {
- { 0, "certificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
- { 1, "tbsCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
- { 2, "DEFAULT v1", ASN1_CONTEXT_C_0, ASN1_DEF }, /* 2 */
- { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */
- { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 4 */
- { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 5 */
- { 2, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */
- { 2, "validity", ASN1_SEQUENCE, ASN1_NONE }, /* 7 */
- { 3, "notBefore", ASN1_EOC, ASN1_RAW }, /* 8 */
- { 3, "notAfter", ASN1_EOC, ASN1_RAW }, /* 9 */
- { 2, "subject", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */
- { 2, "subjectPublicKeyInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */
- { 3, "algorithm", ASN1_EOC, ASN1_RAW }, /* 12 */
- { 3, "subjectPublicKey", ASN1_BIT_STRING, ASN1_BODY }, /* 13 */
- { 2, "issuerUniqueID", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 14 */
- { 2, "end opt", ASN1_EOC, ASN1_END }, /* 15 */
- { 2, "subjectUniqueID", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 16 */
- { 2, "end opt", ASN1_EOC, ASN1_END }, /* 17 */
- { 2, "optional extensions", ASN1_CONTEXT_C_3, ASN1_OPT }, /* 18 */
- { 3, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 19 */
- { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 20 */
- { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 21 */
- { 5, "critical", ASN1_BOOLEAN, ASN1_DEF |
- ASN1_BODY }, /* 22 */
- { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 23 */
- { 3, "end loop", ASN1_EOC, ASN1_END }, /* 24 */
- { 2, "end opt", ASN1_EOC, ASN1_END }, /* 25 */
- { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 26 */
- { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY }, /* 27 */
- { 0, "exit", ASN1_EOC, ASN1_EXIT }
+ { 0, "x509", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
+ { 1, "tbsCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
+ { 2, "DEFAULT v1", ASN1_CONTEXT_C_0, ASN1_DEF }, /* 2 */
+ { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */
+ { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 4 */
+ { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 5 */
+ { 2, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */
+ { 2, "validity", ASN1_SEQUENCE, ASN1_NONE }, /* 7 */
+ { 3, "notBefore", ASN1_EOC, ASN1_RAW }, /* 8 */
+ { 3, "notAfter", ASN1_EOC, ASN1_RAW }, /* 9 */
+ { 2, "subject", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */
+ { 2, "subjectPublicKeyInfo",ASN1_SEQUENCE, ASN1_RAW }, /* 11 */
+ { 2, "issuerUniqueID", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 12 */
+ { 2, "end opt", ASN1_EOC, ASN1_END }, /* 13 */
+ { 2, "subjectUniqueID", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 14 */
+ { 2, "end opt", ASN1_EOC, ASN1_END }, /* 15 */
+ { 2, "optional extensions", ASN1_CONTEXT_C_3, ASN1_OPT }, /* 16 */
+ { 3, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 17 */
+ { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 18 */
+ { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 19 */
+ { 5, "critical", ASN1_BOOLEAN, ASN1_DEF|ASN1_BODY }, /* 20 */
+ { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 21 */
+ { 3, "end loop", ASN1_EOC, ASN1_END }, /* 22 */
+ { 2, "end opt", ASN1_EOC, ASN1_END }, /* 23 */
+ { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 24 */
+ { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY }, /* 25 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
};
#define X509_OBJ_CERTIFICATE 0
#define X509_OBJ_TBS_CERTIFICATE 1
@@ -238,13 +234,12 @@ static const asn1Object_t certObjects[] = {
#define X509_OBJ_NOT_BEFORE 8
#define X509_OBJ_NOT_AFTER 9
#define X509_OBJ_SUBJECT 10
-#define X509_OBJ_SUBJECT_PUBLIC_KEY_ALGORITHM 12
-#define X509_OBJ_SUBJECT_PUBLIC_KEY 13
-#define X509_OBJ_EXTN_ID 21
-#define X509_OBJ_CRITICAL 22
-#define X509_OBJ_EXTN_VALUE 23
-#define X509_OBJ_ALGORITHM 26
-#define X509_OBJ_SIGNATURE 27
+#define X509_OBJ_SUBJECT_PUBLIC_KEY_INFO 11
+#define X509_OBJ_EXTN_ID 19
+#define X509_OBJ_CRITICAL 20
+#define X509_OBJ_EXTN_VALUE 21
+#define X509_OBJ_ALGORITHM 24
+#define X509_OBJ_SIGNATURE 25
const x509cert_t empty_x509cert = {
NULL , /* *next */
@@ -262,11 +257,7 @@ const x509cert_t empty_x509cert = {
0 , /* notBefore */
0 , /* notAfter */
{ NULL, 0 } , /* subject */
- /* subjectPublicKeyInfo */
- OID_UNKNOWN , /* subjectPublicKeyAlgorithm */
- { NULL, 0 } , /* subjectPublicKey */
- { NULL, 0 } , /* modulus */
- { NULL, 0 } , /* publicExponent */
+ NULL , /* public_key */
/* issuerUniqueID */
/* subjectUniqueID */
/* extensions */
@@ -1140,13 +1131,19 @@ chunk_t build_subjectAltNames(generalName_t *subjectAltNames)
/**
* Build a to-be-signed X.509 certificate body
*/
-static chunk_t build_tbs_x509cert(x509cert_t *cert, const RSA_public_key_t *rsa)
+static chunk_t build_tbs_x509cert(x509cert_t *cert, public_key_t *rsa)
{
/* version is always X.509v3 */
chunk_t version = asn1_simple_object(ASN1_CONTEXT_C_0, ASN1_INTEGER_2);
chunk_t extensions = chunk_empty;
+ chunk_t key = rsa->get_encoding(rsa);
+
+ chunk_t keyInfo = asn1_wrap(ASN1_SEQUENCE, "cm",
+ asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
+ asn1_bitstring("m", key));
+
if (cert->subjectAltName != NULL)
{
extensions = asn1_wrap(ASN1_CONTEXT_C_3, "m"
@@ -1156,7 +1153,7 @@ static chunk_t build_tbs_x509cert(x509cert_t *cert, const RSA_public_key_t *rsa)
return asn1_wrap(ASN1_SEQUENCE, "mmccmcmm"
, version
- , asn1_simple_object(ASN1_INTEGER, cert->serialNumber)
+ , asn1_integer("c", cert->serialNumber)
, asn1_algorithmIdentifier(cert->sigAlg)
, cert->issuer
, asn1_wrap(ASN1_SEQUENCE, "mm"
@@ -1164,7 +1161,7 @@ static chunk_t build_tbs_x509cert(x509cert_t *cert, const RSA_public_key_t *rsa)
, asn1_from_time(&cert->notAfter, ASN1_UTCTIME)
)
, cert->subject
- , pkcs1_build_publicKeyInfo(rsa)
+ , keyInfo
, extensions
);
}
@@ -1172,13 +1169,13 @@ static chunk_t build_tbs_x509cert(x509cert_t *cert, const RSA_public_key_t *rsa)
/**
* Build a DER-encoded X.509 certificate
*/
-void build_x509cert(x509cert_t *cert, const RSA_public_key_t *cert_key,
- const RSA_private_key_t *signer_key)
+void build_x509cert(x509cert_t *cert, public_key_t *cert_key,
+ private_key_t *signer_key)
{
chunk_t tbs_cert = build_tbs_x509cert(cert, cert_key);
- chunk_t signature = pkcs1_build_signature(tbs_cert, cert->sigAlg
- , signer_key, TRUE);
+ chunk_t signature = x509_build_signature(tbs_cert, cert->sigAlg
+ , signer_key, TRUE);
cert->certificate = asn1_wrap(ASN1_SEQUENCE, "mcm"
, tbs_cert
@@ -1210,6 +1207,7 @@ void free_x509cert(x509cert_t *cert)
{
if (cert != NULL)
{
+ DESTROY_IF(cert->public_key);
free_generalNames(cert->subjectAltName, FALSE);
free_generalNames(cert->crlDistributionPoints, FALSE);
free(cert->certificate.ptr);
@@ -1318,111 +1316,75 @@ void store_x509certs(x509cert_t **firstcert, bool strict)
}
/**
- * Decrypts an RSA signature using the issuer's certificate
+ * Check if a signature over binary blob is genuine
*/
-static bool decrypt_sig(chunk_t sig, int alg, const x509cert_t *issuer_cert,
- chunk_t *digest)
+bool x509_check_signature(chunk_t tbs, chunk_t sig, int algorithm,
+ const x509cert_t *issuer_cert)
{
- switch (alg)
- {
- chunk_t decrypted;
+ public_key_t *key = issuer_cert->public_key;
+ signature_scheme_t scheme = SIGN_DEFAULT;
- case OID_RSA_ENCRYPTION:
- case OID_MD2_WITH_RSA:
+ switch (algorithm)
+ {
case OID_MD5_WITH_RSA:
+ scheme = SIGN_RSA_EMSA_PKCS1_MD5;
+ break;
case OID_SHA1_WITH_RSA:
- case OID_SHA1_WITH_RSA_OIW:
+ scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
+ break;
case OID_SHA256_WITH_RSA:
+ scheme = SIGN_RSA_EMSA_PKCS1_SHA256;
+ break;
case OID_SHA384_WITH_RSA:
+ scheme = SIGN_RSA_EMSA_PKCS1_SHA384;
+ break;
case OID_SHA512_WITH_RSA:
- {
- mpz_t s;
- RSA_public_key_t rsa;
-
- init_RSA_public_key(&rsa, issuer_cert->publicExponent
- , issuer_cert->modulus);
-
- /* decrypt the signature s = s^e mod n */
- n_to_mpz(s, sig.ptr, sig.len);
- mpz_powm(s, s, &rsa.e, &rsa.n);
-
- /* convert back to bytes */
- decrypted = mpz_to_n(s, rsa.k);
- DBG(DBG_PARSING,
- DBG_dump_chunk(" decrypted signature: ", decrypted)
- )
-
- /* copy the least significant bits of decrypted signature
- * into the digest string
- */
- memcpy(digest->ptr, decrypted.ptr + decrypted.len - digest->len,
- digest->len);
-
- /* free memory */
- free_RSA_public_content(&rsa);
- free(decrypted.ptr);
- mpz_clear(s);
- return TRUE;
- }
+ scheme = SIGN_RSA_EMSA_PKCS1_SHA512;
+ break;
+ case OID_ECDSA_WITH_SHA1:
+ scheme = SIGN_ECDSA_WITH_SHA1;
+ break;
default:
- digest->len = 0;
return FALSE;
}
+ return key->verify(key, scheme, tbs, sig);
}
/**
- * Check if a signature over binary blob is genuine
+ * Build an ASN.1 encoded PKCS#1 signature over a binary blob
*/
-bool check_signature(chunk_t tbs, chunk_t sig, int digest_alg, int enc_alg,
- const x509cert_t *issuer_cert)
+chunk_t x509_build_signature(chunk_t tbs, int hash_alg, private_key_t *key,
+ bool bit_string)
{
- u_char digest_buf[MAX_DIGEST_LEN];
- u_char decrypted_buf[MAX_DIGEST_LEN];
- chunk_t digest = {digest_buf, MAX_DIGEST_LEN};
- chunk_t decrypted = {decrypted_buf, MAX_DIGEST_LEN};
-
- DBG(DBG_PARSING,
- if (digest_alg != OID_UNKNOWN)
- {
- DBG_log("signature digest algorithm: '%s'",oid_names[digest_alg].name);
- }
- else
- {
- DBG_log("unknown signature digest algorithm");
- }
- )
+ signature_scheme_t scheme = SIGN_DEFAULT;
+ chunk_t signature;
- if (!compute_digest(tbs, digest_alg, &digest))
+ switch (hash_alg)
{
- plog(" digest algorithm not supported");
- return FALSE;
+ case OID_MD5:
+ scheme = SIGN_RSA_EMSA_PKCS1_MD5;
+ break;
+ case OID_SHA1:
+ scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
+ break;
+ case OID_SHA256:
+ scheme = SIGN_RSA_EMSA_PKCS1_SHA256;
+ break;
+ case OID_SHA384:
+ scheme = SIGN_RSA_EMSA_PKCS1_SHA384;
+ break;
+ case OID_SHA512:
+ scheme = SIGN_RSA_EMSA_PKCS1_SHA512;
+ break;
+ default:
+ return chunk_empty;
}
-
- DBG(DBG_PARSING,
- DBG_dump_chunk(" digest:", digest)
- )
-
- decrypted.len = digest.len; /* we want the same digest length */
-
- DBG(DBG_PARSING,
- if (enc_alg != OID_UNKNOWN)
- {
- DBG_log("signature encryption algorithm: '%s'",oid_names[enc_alg].name);
- }
- else
- {
- DBG_log("unknown signature encryption algorithm");
- }
- )
-
- if (!decrypt_sig(sig, enc_alg, issuer_cert, &decrypted))
+ if (!key->sign(key, scheme, tbs, &signature))
{
- plog(" decryption algorithm not supported");
- return FALSE;
- }
-
- /* check if digests are equal */
- return memeq(decrypted.ptr, digest.ptr, digest.len);
+ return chunk_empty;
+ }
+ return (bit_string) ? asn1_bitstring("m", signature)
+ : asn1_wrap(ASN1_OCTET_STRING, "m", signature);
}
/**
@@ -1489,15 +1451,17 @@ void gntoid(struct id *id, const generalName_t *gn)
*/
bool compute_subjectKeyID(x509cert_t *cert, chunk_t subjectKeyID)
{
- hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ identification_t *keyid;
+ chunk_t encoding;
- if (hasher == NULL)
+ keyid = cert->public_key->get_id(cert->public_key, ID_PUBKEY_SHA1);
+ if (keyid == NULL)
{
- plog(" no SHA-1 hasher available to compute subjectKeyID");
+ plog(" unable to compute subjectKeyID");
return FALSE;
}
- hasher->get_hash(hasher, cert->subjectPublicKey, subjectKeyID.ptr);
- hasher->destroy(hasher);
+ encoding = keyid->get_encoding(keyid);
+ memcpy(subjectKeyID.ptr, encoding.ptr, subjectKeyID.len);
return TRUE;
}
@@ -1825,50 +1789,6 @@ static generalName_t* parse_crlDistributionPoints(chunk_t blob, int level0)
}
/**
- * Parses an RSA public key
- */
-bool parse_RSA_public_key(chunk_t blob, u_int level0, x509cert_t *cert)
-{
- asn1_parser_t *parser;
- chunk_t object;
- int objectID;
- bool success = FALSE;
-
- parser = asn1_parser_create(pubkeyObjects, blob);
- parser->set_top_level(parser, level0);
-
- while (parser->iterate(parser, &objectID, &object))
- {
- switch (objectID) {
- case PUB_KEY_RSA_PUBLIC_KEY:
- cert->subjectPublicKey = object;
- break;
- case PUB_KEY_MODULUS:
- if (object.len < RSA_MIN_OCTETS + 1)
- {
- plog(" " RSA_MIN_OCTETS_UGH);
- goto end;
- }
- if (object.len > RSA_MAX_OCTETS + (size_t)(*object.ptr == 0x00))
- {
- plog(" " RSA_MAX_OCTETS_UGH);
- goto end;
- }
- cert->modulus = object;
- break;
- case PUB_KEY_EXPONENT:
- cert->publicExponent = object;
- break;
- }
- }
- success = parser->success(parser);
-
-end:
- parser->destroy(parser);
- return success;
-}
-
-/**
* Parses an X.509v3 certificate
*/
bool parse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert)
@@ -1927,30 +1847,11 @@ bool parse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert)
DBG_log(" '%s'",buf)
)
break;
- case X509_OBJ_SUBJECT_PUBLIC_KEY_ALGORITHM:
- if (asn1_parse_algorithmIdentifier(object, level, NULL) == OID_RSA_ENCRYPTION)
- {
- cert->subjectPublicKeyAlgorithm = PUBKEY_ALG_RSA;
- }
- else
- {
- plog(" unsupported public key algorithm");
- goto end;
- }
- break;
- case X509_OBJ_SUBJECT_PUBLIC_KEY:
- if (object.len > 0 && *object.ptr == 0x00)
- {
- /* skip initial bit string octet defining 0 unused bits */
- object = chunk_skip(object, 1);
- if (!parse_RSA_public_key(object, level, cert))
- {
- goto end;
- }
- }
- else
+ case X509_OBJ_SUBJECT_PUBLIC_KEY_INFO:
+ cert->public_key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
+ KEY_ANY, BUILD_BLOB_ASN1_DER, object, BUILD_END);
+ if (cert->public_key == NULL)
{
- plog(" invalid RSA public key format");
goto end;
}
break;
@@ -2116,8 +2017,8 @@ bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
DBG_log("issuer cacert found")
)
- if (!check_signature(cert->tbsCertificate, cert->signature
- , cert->algorithm, cert->algorithm, issuer_cert))
+ if (!x509_check_signature(cert->tbsCertificate, cert->signature,
+ cert->algorithm, issuer_cert))
{
plog("certificate signature is invalid");
unlock_authcert_list("verify_x509cert");
@@ -2220,9 +2121,8 @@ void list_x509cert_chain(const char *caption, x509cert_t* cert,
{
if (auth_flags == AUTH_NONE || (auth_flags & cert->authority_flags))
{
- unsigned keysize;
- char keyid[KEYID_BUF];
u_char buf[BUF_LEN];
+ public_key_t *key = cert->public_key;
cert_t c;
c.type = CERT_X509_SIGNATURE;
@@ -2242,36 +2142,38 @@ void list_x509cert_chain(const char *caption, x509cert_t* cert,
whack_log(RC_COMMENT, " subject: '%s'", buf);
dntoa(buf, BUF_LEN, cert->issuer);
whack_log(RC_COMMENT, " issuer: '%s'", buf);
- datatot(cert->serialNumber.ptr, cert->serialNumber.len, ':'
- , buf, BUF_LEN);
+ datatot(cert->serialNumber.ptr, cert->serialNumber.len, ':',
+ buf, BUF_LEN);
whack_log(RC_COMMENT, " serial: %s", buf);
- form_keyid(cert->publicExponent, cert->modulus, keyid, &keysize);
- whack_log(RC_COMMENT, " pubkey: %4d RSA Key %s%s"
- , 8*keysize, keyid
- , cert->smartcard ? ", on smartcard" :
- (has_private_key(c)? ", has private key" : ""));
whack_log(RC_COMMENT, " validity: not before %T %s",
&cert->notBefore, utc,
(cert->notBefore < now)?"ok":"fatal (not valid yet)");
whack_log(RC_COMMENT, " not after %T %s",
&cert->notAfter, utc,
check_expiry(cert->notAfter, CA_CERT_WARNING_INTERVAL, TRUE));
+ whack_log(RC_COMMENT, " pubkey: %N %4d bits%s",
+ key_type_names, key->get_type(key),
+ key->get_keysize(key) * BITS_PER_BYTE,
+ cert->smartcard ? ", on smartcard" :
+ (has_private_key(c)? ", has private key" : ""));
+ whack_log(RC_COMMENT, " keyid: %Y",
+ key->get_id(key, ID_PUBKEY_INFO_SHA1));
if (cert->subjectKeyID.ptr != NULL)
{
- datatot(cert->subjectKeyID.ptr, cert->subjectKeyID.len, ':'
- , buf, BUF_LEN);
+ datatot(cert->subjectKeyID.ptr, cert->subjectKeyID.len, ':',
+ buf, BUF_LEN);
whack_log(RC_COMMENT, " subjkey: %s", buf);
}
if (cert->authKeyID.ptr != NULL)
{
- datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':'
- , buf, BUF_LEN);
+ datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':',
+ buf, BUF_LEN);
whack_log(RC_COMMENT, " authkey: %s", buf);
}
if (cert->authKeySerialNumber.ptr != NULL)
{
- datatot(cert->authKeySerialNumber.ptr, cert->authKeySerialNumber.len
- , ':', buf, BUF_LEN);
+ datatot(cert->authKeySerialNumber.ptr,
+ cert->authKeySerialNumber.len, ':', buf, BUF_LEN);
whack_log(RC_COMMENT, " aserial: %s", buf);
}
}
diff --git a/src/pluto/x509.h b/src/pluto/x509.h
index ec3203d74..1810cad06 100644
--- a/src/pluto/x509.h
+++ b/src/pluto/x509.h
@@ -2,7 +2,7 @@
* Copyright (C) 2000 Andreas Hess, Patric Lichtsteiner, Roger Wegmann
* Copyright (C) 2001 Marco Bertossa, Andreas Schleiss
* Copyright (C) 2002 Mario Strasser
- * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur
+ * Copyright (C) 2000-2009 Andreas Steffen, Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -18,8 +18,10 @@
#ifndef _X509_H
#define _X509_H
+#include <credentials/keys/public_key.h>
+#include <credentials/keys/private_key.h>
+
#include "constants.h"
-#include "pkcs1.h"
#include "id.h"
/* Definition of generalNames kinds */
@@ -51,46 +53,42 @@ struct generalName {
typedef struct x509cert x509cert_t;
struct x509cert {
- x509cert_t *next;
- time_t installed;
- int count;
- bool smartcard;
- u_char authority_flags;
- chunk_t certificate;
- chunk_t tbsCertificate;
- u_int version;
- chunk_t serialNumber;
- /* signature */
- int sigAlg;
- chunk_t issuer;
- /* validity */
- time_t notBefore;
- time_t notAfter;
- chunk_t subject;
- /* subjectPublicKeyInfo */
- enum pubkey_alg subjectPublicKeyAlgorithm;
- chunk_t subjectPublicKey;
- chunk_t modulus;
- chunk_t publicExponent;
- /* issuerUniqueID */
- /* subjectUniqueID */
- /* v3 extensions */
- /* extension */
- /* extension */
- /* extnID */
- /* critical */
- /* extnValue */
- bool isCA;
- bool isOcspSigner; /* ocsp */
- chunk_t subjectKeyID;
- chunk_t authKeyID;
- chunk_t authKeySerialNumber;
- chunk_t accessLocation; /* ocsp */
- generalName_t *subjectAltName;
- generalName_t *crlDistributionPoints;
- /* signatureAlgorithm */
- int algorithm;
- chunk_t signature;
+ x509cert_t *next;
+ time_t installed;
+ int count;
+ bool smartcard;
+ u_char authority_flags;
+ chunk_t certificate;
+ chunk_t tbsCertificate;
+ u_int version;
+ chunk_t serialNumber;
+ /* signature */
+ int sigAlg;
+ chunk_t issuer;
+ /* validity */
+ time_t notBefore;
+ time_t notAfter;
+ chunk_t subject;
+ public_key_t *public_key;
+ /* issuerUniqueID */
+ /* subjectUniqueID */
+ /* v3 extensions */
+ /* extension */
+ /* extension */
+ /* extnID */
+ /* critical */
+ /* extnValue */
+ bool isCA;
+ bool isOcspSigner; /* ocsp */
+ chunk_t subjectKeyID;
+ chunk_t authKeyID;
+ chunk_t authKeySerialNumber;
+ chunk_t accessLocation; /* ocsp */
+ generalName_t *subjectAltName;
+ generalName_t *crlDistributionPoints;
+ /* signatureAlgorithm */
+ int algorithm;
+ chunk_t signature;
};
/* used for initialization */
@@ -104,8 +102,8 @@ extern bool same_x509cert(const x509cert_t *a, const x509cert_t *b);
extern void hex_str(chunk_t bin, chunk_t *str);
extern int dn_count_wildcards(chunk_t dn);
extern int dntoa(char *dst, size_t dstlen, chunk_t dn);
-extern int dntoa_or_null(char *dst, size_t dstlen, chunk_t dn
- , const char* null_dn);
+extern int dntoa_or_null(char *dst, size_t dstlen, chunk_t dn,
+ const char* null_dn);
extern err_t atodn(char *src, chunk_t *dn);
extern void gntoid(struct id *id, const generalName_t *gn);
extern bool compute_subjectKeyID(x509cert_t *cert, chunk_t subjectKeyID);
@@ -116,21 +114,23 @@ extern void parse_authorityKeyIdentifier(chunk_t blob, int level0
, chunk_t *authKeyID, chunk_t *authKeySerialNumber);
extern chunk_t get_directoryName(chunk_t blob, int level, bool implicit);
extern err_t check_validity(const x509cert_t *cert, time_t *until);
-extern bool check_signature(chunk_t tbs, chunk_t sig, int digest_alg
- , int enc_alg, const x509cert_t *issuer_cert);
+extern bool x509_check_signature(chunk_t tbs, chunk_t sig, int algorithm,
+ const x509cert_t *issuer_cert);
+extern chunk_t x509_build_signature(chunk_t tbs, int hash_alg, private_key_t *key,
+ bool bit_string);
extern bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until);
extern x509cert_t* add_x509cert(x509cert_t *cert);
-extern x509cert_t* get_x509cert(chunk_t issuer, chunk_t serial, chunk_t keyid
- , x509cert_t* chain);
-extern void build_x509cert(x509cert_t *cert, const RSA_public_key_t *cert_key
- , const RSA_private_key_t *signer_key);
+extern x509cert_t* get_x509cert(chunk_t issuer, chunk_t serial, chunk_t keyid,
+ x509cert_t* chain);
+extern void build_x509cert(x509cert_t *cert, public_key_t *cert_key,
+ private_key_t *signer_key);
extern chunk_t build_subjectAltNames(generalName_t *subjectAltNames);
extern void share_x509cert(x509cert_t *cert);
extern void release_x509cert(x509cert_t *cert);
extern void free_x509cert(x509cert_t *cert);
extern void store_x509certs(x509cert_t **firstcert, bool strict);
-extern void list_x509cert_chain(const char *caption, x509cert_t* cert
- , u_char auth_flags, bool utc);
+extern void list_x509cert_chain(const char *caption, x509cert_t* cert,
+ u_char auth_flags, bool utc);
extern void list_x509_end_certs(bool utc);
extern void free_generalNames(generalName_t* gn, bool free_name);
diff --git a/src/scepclient/Makefile.am b/src/scepclient/Makefile.am
index f7cfc7355..a6e43a4f1 100644
--- a/src/scepclient/Makefile.am
+++ b/src/scepclient/Makefile.am
@@ -1,5 +1,5 @@
ipsec_PROGRAMS = scepclient
-scepclient_SOURCES = scepclient.c rsakey.c rsakey.h pkcs10.c pkcs10.h scep.c scep.h loglite.c
+scepclient_SOURCES = scepclient.c pkcs10.c pkcs10.h scep.c scep.h loglite.c
PLUTODIR=$(top_srcdir)/src/pluto
OPENACDIR=$(top_srcdir)/src/openac
@@ -28,7 +28,7 @@ LIBCRYPTOBUILDDIR=$(top_builddir)/src/libcrypto
scepclient_LDADD = \
ca.o crl.o certs.o constants.o defs.o fetch.o id.o keys.o lex.o \
-mp_defs.o ocsp.o pem.o pgp.o pkcs1.o pkcs7.o smartcard.o x509.o \
+mp_defs.o ocsp.o pem.o pgpcert.o pkcs7.o smartcard.o x509.o \
$(LIBSTRONGSWANBUILDDIR)/libstrongswan.la \
$(LIBFREESWANBUILDDIR)/libfreeswan.a \
-lgmp
@@ -77,10 +77,7 @@ ocsp.o : $(PLUTODIR)/ocsp.c $(PLUTODIR)/ocsp.h
pem.o : $(PLUTODIR)/pem.c $(PLUTODIR)/pem.h
$(COMPILE) $(INCLUDES) -c -o $@ $<
-pgp.o : $(PLUTODIR)/pgp.c $(PLUTODIR)/pgp.h
- $(COMPILE) $(INCLUDES) -c -o $@ $<
-
-pkcs1.o : $(PLUTODIR)/pkcs1.c $(PLUTODIR)/pkcs1.h
+pgpcert.o : $(PLUTODIR)/pgpcert.c $(PLUTODIR)/pgpcert.h
$(COMPILE) $(INCLUDES) -c -o $@ $<
pkcs7.o : $(PLUTODIR)/pkcs7.c $(PLUTODIR)/pkcs7.h
diff --git a/src/scepclient/pkcs10.c b/src/scepclient/pkcs10.c
index 6933adaf8..cdd68431e 100644
--- a/src/scepclient/pkcs10.c
+++ b/src/scepclient/pkcs10.c
@@ -31,7 +31,6 @@
#include "../pluto/constants.h"
#include "../pluto/defs.h"
-#include "../pluto/pkcs1.h"
#include "../pluto/log.h"
#include "../pluto/x509.h"
@@ -158,21 +157,25 @@ build_req_info_attributes(pkcs10_t* pkcs10)
static chunk_t
pkcs10_build_request(pkcs10_t *pkcs10, int signature_alg)
{
- RSA_public_key_t *rsak = (RSA_public_key_t *) pkcs10->private_key;
+ chunk_t key = pkcs10->public_key->get_encoding(pkcs10->public_key);
- chunk_t cert_req_info = asn1_wrap(ASN1_SEQUENCE, "ccmm"
- , ASN1_INTEGER_0
- , pkcs10->subject
- , pkcs1_build_publicKeyInfo(rsak)
- , build_req_info_attributes(pkcs10));
+ chunk_t keyInfo = asn1_wrap(ASN1_SEQUENCE, "cm",
+ asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
+ asn1_bitstring("m", key));
- chunk_t signature = pkcs1_build_signature(cert_req_info
- , signature_alg, pkcs10->private_key, TRUE);
+ chunk_t cert_req_info = asn1_wrap(ASN1_SEQUENCE, "ccmm",
+ ASN1_INTEGER_0,
+ pkcs10->subject,
+ keyInfo,
+ build_req_info_attributes(pkcs10));
- return asn1_wrap(ASN1_SEQUENCE, "mcm"
- , cert_req_info
- , asn1_algorithmIdentifier(signature_alg)
- , signature);
+ chunk_t signature = x509_build_signature(cert_req_info, signature_alg,
+ pkcs10->private_key, TRUE);
+
+ return asn1_wrap(ASN1_SEQUENCE, "mcm",
+ cert_req_info,
+ asn1_algorithmIdentifier(signature_alg),
+ signature);
}
/**
@@ -189,14 +192,15 @@ pkcs10_build_request(pkcs10_t *pkcs10, int signature_alg)
* @param[in] subjectAltNames linked list of subjectAltNames or NULL
* @return pointer to a #pkcs10_t object
*/
-pkcs10_t*
-pkcs10_build(RSA_private_key_t *key, chunk_t subject, chunk_t challengePassword
-, generalName_t *subjectAltNames, int signature_alg)
+pkcs10_t* pkcs10_build(private_key_t *private, public_key_t *public,
+ chunk_t subject, chunk_t challengePassword,
+ generalName_t *subjectAltNames, int signature_alg)
{
pkcs10_t *pkcs10 = malloc_thing(pkcs10_t);
pkcs10->subject = subject;
- pkcs10->private_key = key;
+ pkcs10->private_key = private;
+ pkcs10->public_key = public;
pkcs10->challengePassword = challengePassword;
pkcs10->subjectAltNames = subjectAltNames;
diff --git a/src/scepclient/pkcs10.h b/src/scepclient/pkcs10.h
index a48dd7c2e..3f29f019a 100644
--- a/src/scepclient/pkcs10.h
+++ b/src/scepclient/pkcs10.h
@@ -23,8 +23,10 @@
#ifndef _PKCS10_H
#define _PKCS10_H
+#include <credentials/keys/private_key.h>
+#include <credentials/keys/public_key.h>
+
#include "../pluto/defs.h"
-#include "../pluto/pkcs1.h"
#include "../pluto/x509.h"
typedef struct pkcs10_struct pkcs10_t;
@@ -38,20 +40,21 @@ typedef struct pkcs10_struct pkcs10_t;
* The RSA private key is needed to compute the signature of the given request
*/
struct pkcs10_struct {
- RSA_private_key_t *private_key;
- chunk_t request;
- chunk_t subject;
- chunk_t challengePassword;
- generalName_t *subjectAltNames;
+ private_key_t *private_key;
+ public_key_t *public_key;
+ chunk_t request;
+ chunk_t subject;
+ chunk_t challengePassword;
+ generalName_t *subjectAltNames;
};
extern const pkcs10_t empty_pkcs10;
-extern void pkcs10_add_subjectAltName(generalName_t **subjectAltNames
- , generalNames_t kind, char *value);
-extern pkcs10_t* pkcs10_build(RSA_private_key_t *key, chunk_t subject
- , chunk_t challengePassword, generalName_t *subjectAltNames
- , int signature_alg);
+extern void pkcs10_add_subjectAltName(generalName_t **subjectAltNames,
+ generalNames_t kind, char *value);
+extern pkcs10_t* pkcs10_build(private_key_t *private, public_key_t *public,
+ chunk_t subject, chunk_t challengePassword,
+ generalName_t *subjectAltNames, int signature_alg);
extern void pkcs10_free(pkcs10_t *pkcs10);
#endif /* _PKCS10_H */
diff --git a/src/scepclient/rsakey.c b/src/scepclient/rsakey.c
deleted file mode 100644
index e7e4a47f5..000000000
--- a/src/scepclient/rsakey.c
+++ /dev/null
@@ -1,313 +0,0 @@
-/**
- * @file rsakey.c
- * @brief Functions for RSA key generation
- */
-
-/*
- * Copyright (C) 1999, 2000, 2001 Henry Spencer.
- * Copyright (C) 2005 Jan Hutter, Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * 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.
- */
-
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <assert.h>
-#include <gmp.h>
-
-#include <freeswan.h>
-
-#include <library.h>
-#include <crypto/rngs/rng.h>
-
-#include "../pluto/constants.h"
-#include "../pluto/defs.h"
-#include "../pluto/mp_defs.h"
-#include "../pluto/log.h"
-#include "../pluto/pkcs1.h"
-
-#include "rsakey.h"
-
-/* Number of times the probabilistic primality test is applied */
-#define PRIMECHECK_ROUNDS 30
-
-/* Public exponent used for signature key generation */
-#define PUBLIC_EXPONENT 0x10001
-
-#ifndef DEV_RANDOM
-#define DEV_RANDOM "/dev/random"
-#endif
-
-
-/**
- * @brief Reads a specific number of bytes from a given device/file
- *
- * @param[in] nbytes number of bytes to read from random device
- * @param[out] buf pointer to buffer where to write the data in.
- * size of buffer has to be at least nbytes.
- * @return TRUE, if succeeded, FALSE otherwise
- */
-
-/**
- * @brief initialize an mpz_t to a random number, specified bit count
- *
- * Converting the random value in a value of type mpz_t is done
- * by creating a hexbuffer.
- * Converting via hex is a bit weird, but it's the best route GMP gives us.
- * Note that highmost and lowmost bits are forced on -- highmost to give a
- * number of exactly the specified length, lowmost so it is an odd number.
- *
- * @param[out] var uninitialized mpz_t to store th random number in
- * @param[in] nbits length of var in bits (known to be a multiple of BITS_PER_BYTE)
- * @return TRUE on success, FALSE otherwise
- */
-static bool init_random(mpz_t var, int nbits)
-{
- size_t nbytes = (size_t)(nbits/BITS_PER_BYTE);
- char random_buf[RSA_MAX_OCTETS/2];
- rng_t *rng = lib->crypto->create_rng(lib->crypto, RNG_TRUE);
-
- if (!rng)
- {
- return FALSE;
- }
- assert(nbytes <= sizeof(random_buf));
- rng->get_bytes(rng, nbytes, random_buf);
- rng->destroy(rng);
-
- random_buf[0] |= 01 << (BITS_PER_BYTE-1); /* force high bit on */
- random_buf[nbytes-1] |= 01; /* force low bit on */
- n_to_mpz(var, random_buf, nbytes);
- return TRUE;
-}
-
-/**
- * @brief initialize an mpz_t to a random prime of specified size
- *
- * Efficiency tweak: we reject candidates that are 1 higher than a multiple
- * of e, since they will make the internal modulus not relatively prime to e.
- *
- * @param[out] var mpz_t variable to initialize
- * @param[in] nbits length of given prime in bits (known to be a multiple of BITS_PER_BYTE)
- * @param[in] eval E-Value, 0 means don't bother w. tweak
- * @return 1 on success, 0 otherwise
- */
-static bool init_prime(mpz_t var, int nbits, int eval)
-{
- unsigned long tries;
- size_t len;
-
- /* get a random value of nbits length */
- if (!init_random(var, nbits))
- return FALSE;
-
- /* check if odd number */
- assert(mpz_fdiv_ui(var, 2) == 1);
- DBG(DBG_CONTROLMORE,
- DBG_log("looking for a prime starting there (can take a while)...")
- )
-
- tries = 1;
- while (mpz_fdiv_ui(var, eval) == 1
- || !mpz_probab_prime_p(var, PRIMECHECK_ROUNDS))
- {
- /* not a prime, increase by 2 */
- mpz_add_ui(var, var, 2);
- tries++;
- }
-
- len = mpz_sizeinbase(var, 2);
-
- /* check bit length of primee */
- assert(len == (size_t)nbits || len == (size_t)(nbits+1));
-
- if (len == (size_t)(nbits+1))
- {
- DBG(DBG_CONTROLMORE,
- DBG_log("carry out occurred (!), retrying...")
- )
- mpz_clear(var);
- /* recursive call */
- return init_prime(var, nbits, eval);
- }
- DBG(DBG_CONTROLMORE,
- DBG_log("found it after %lu tries.",tries)
- )
- return TRUE;
-}
-
-/**
- * @brief Generate a RSA key usable for encryption
- *
- * Generate an RSA key usable for encryption. All the
- * values of the RSA key are filled into mpz_t parameters.
- * These mpz_t parameters must not be initialized and have
- * to be cleared with mpz_clear after using.
- *
- * @param[in] nbits size of rsa key in bits
- * @return RSA_public_key_t containing the generated RSA key
- */
-err_t generate_rsa_private_key(int nbits, RSA_private_key_t *key)
-{
- mpz_t p, q, n, e, d, exp1, exp2, coeff;
- mpz_t m, q1, t; /* temporary variables*/
-
- DBG(DBG_CONTROL,
- DBG_log("generating %d bit RSA key:", nbits)
- )
-
- if (nbits <= 0)
- return "negative rsa key length!";
-
- /* Get values of primes p and q */
- DBG(DBG_CONTROLMORE,
- DBG_log("initialize prime p")
- )
- if (!init_prime(p, nbits/2, PUBLIC_EXPONENT))
- return "could not generate prime p";
-
- DBG(DBG_CONTROLMORE,
- DBG_log("initialize prime q")
- )
- if (!init_prime(q, nbits/2, PUBLIC_EXPONENT))
- return "could not generate prime q";
-
- mpz_init(t);
-
- /* Swapping primes so p is larger then q */
- if (mpz_cmp(p, q) < 0)
- {
- DBG(DBG_CONTROLMORE,
- DBG_log("swapping primes so p is the larger...")
- );
- mpz_set(t, p);
- mpz_set(p, q);
- mpz_set(q, t);
- }
-
- DBG(DBG_CONTROLMORE,
- DBG_log("computing modulus...")
- )
- mpz_init(n);
- /* n = p*q */
- mpz_mul(n, p, q);
-
- /* Assign e the value of defined PUBLIC_EXPONENT */
- mpz_init_set_ui(e, PUBLIC_EXPONENT);
-
- DBG(DBG_CONTROLMORE,
- DBG_log("computing lcm(p-1, q-1)...")
- )
- /* m = p */
- mpz_init_set(m, p);
- /* m = m-1 */
- mpz_sub_ui(m, m, 1);
- /* q1 = q */
- mpz_init_set(q1, q);
- /* q1 = q1-1 */
- mpz_sub_ui(q1, q1, 1);
- /* t = gcd(p-1, q-1) */
- mpz_gcd(t, m, q1);
- /* m = (p-1)*(q-1) */
- mpz_mul(m, m, q1);
- /* m = m / t */
- mpz_divexact(m, m, t);
- /* t = gcd(m, e) (greatest common divisor) */
- mpz_gcd(t, m, e);
- /* m and e relatively prime */
- assert(mpz_cmp_ui(t, 1) == 0);
-
- /* decryption key */
- DBG(DBG_CONTROLMORE,
- DBG_log("computing d...")
- )
- mpz_init(d);
- /* e has an inverse mod m */
- assert(mpz_invert(d, e, m));
-
- /* make sure d is positive */
- if (mpz_cmp_ui(d, 0) < 0)
- mpz_add(d, d, m);
-
- /* d has to be positive */
- assert(mpz_cmp(d, m) < 0);
-
- /* the speedup hacks */
- DBG(DBG_CONTROLMORE,
- DBG_log("computing exp1, exp1, coeff...")
- )
- mpz_init(exp1);
- /* t = p-1 */
- mpz_sub_ui(t, p, 1);
- /* exp1 = d mod p-1 */
- mpz_mod(exp1, d, t);
-
- mpz_init(exp2);
- /* t = q-1 */
- mpz_sub_ui(t, q, 1);
- /* exp2 = d mod q-1 */
- mpz_mod(exp2, d, t);
-
- mpz_init(coeff);
- /* coeff = q^-1 mod p */
- mpz_invert(coeff, q, p);
-
- /* make sure coeff is positive */
- if (mpz_cmp_ui(coeff, 0) < 0)
- mpz_add(coeff, coeff, p);
-
- /* coeff has to be positive */
- assert(mpz_cmp(coeff, p) < 0);
-
- /* Clear temporary variables */
- mpz_clear(q1);
- mpz_clear(m);
- mpz_clear(t);
-
- /* form FreeS/WAN keyid */
- {
- size_t e_len = (mpz_sizeinbase(e,2)+BITS_PER_BYTE-1)/BITS_PER_BYTE;
- size_t n_len = (mpz_sizeinbase(n,2)+BITS_PER_BYTE-1)/BITS_PER_BYTE;
- chunk_t e_ch = mpz_to_n(e, e_len);
- chunk_t n_ch = mpz_to_n(n, n_len);
-
- form_keyid(e_ch, n_ch, key->pub.keyid, &key->pub.k);
- free(e_ch.ptr);
- free(n_ch.ptr);
- }
-
- /* fill in the elements of the RSA private key */
- key->p = *p;
- key->q = *q;
- key->pub.n = *n;
- key->pub.e = *e;
- key->d = *d;
- key->dP = *exp1;
- key->dQ = *exp2;
- key->qInv = *coeff;
-
- DBG(DBG_CONTROL,
- DBG_log("RSA key *%s generated with %d bits", key->pub.keyid
- , (int)mpz_sizeinbase(n,2))
- )
-
-#ifdef DEBUG
- DBG(DBG_PRIVATE,
- RSA_show_private_key(key)
- )
-#endif
- return NULL;
-}
diff --git a/src/scepclient/scep.c b/src/scepclient/scep.c
index dd16dff1b..a788c6f41 100644
--- a/src/scepclient/scep.c
+++ b/src/scepclient/scep.c
@@ -34,7 +34,6 @@
#include "../pluto/constants.h"
#include "../pluto/defs.h"
-#include "../pluto/pkcs1.h"
#include "../pluto/fetch.h"
#include "../pluto/log.h"
@@ -266,35 +265,43 @@ end:
* Generates a unique fingerprint of the pkcs10 request
* by computing an MD5 hash over it
*/
-void scep_generate_pkcs10_fingerprint(chunk_t pkcs10, chunk_t *fingerprint)
+chunk_t scep_generate_pkcs10_fingerprint(chunk_t pkcs10)
{
- char buf[HASH_SIZE_MD5];
- chunk_t digest = { buf, sizeof(buf) };
-
- /* the fingerprint is the MD5 hash in hexadecimal format */
- compute_digest(pkcs10, OID_MD5, &digest);
- fingerprint->len = 2*digest.len;
- fingerprint->ptr = malloc(fingerprint->len + 1);
- datatot(digest.ptr, digest.len, 16, fingerprint->ptr, fingerprint->len + 1);
+ char digest_buf[HASH_SIZE_MD5];
+ chunk_t digest = chunk_from_buf(digest_buf);
+ hasher_t *hasher;
+
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
+ hasher->get_hash(hasher, pkcs10, digest_buf);
+ hasher->destroy(hasher);
+
+ return chunk_to_hex(digest, NULL, FALSE);
}
/**
* Generate a transaction id as the MD5 hash of an public key
* the transaction id is also used as a unique serial number
*/
-void scep_generate_transaction_id(const RSA_public_key_t *rsak,
- chunk_t *transID, chunk_t *serialNumber)
+void scep_generate_transaction_id(public_key_t *key, chunk_t *transID,
+ chunk_t *serialNumber)
{
- char buf[HASH_SIZE_MD5];
-
- chunk_t digest = { buf, sizeof(buf) };
- chunk_t public_key = pkcs1_build_publicKeyInfo(rsak);
-
+ char digest_buf[HASH_SIZE_MD5];
+ chunk_t digest = chunk_from_buf(digest_buf);
+ chunk_t keyEncoding, keyInfo;
+ hasher_t *hasher;
bool msb_set;
u_char *pos;
+
+ keyEncoding = key->get_encoding(key);
+
+ keyInfo = asn1_wrap(ASN1_SEQUENCE, "cm",
+ asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
+ asn1_bitstring("m", keyEncoding));
- compute_digest(public_key, OID_MD5, &digest);
- free(public_key.ptr);
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
+ hasher->get_hash(hasher, keyInfo, digest_buf);
+ hasher->destroy(hasher);
+ free(keyInfo.ptr);
/* is the most significant bit of the digest set? */
msb_set = (*digest.ptr & 0x80) == 0x80;
@@ -376,7 +383,7 @@ chunk_t scep_senderNonce_attribute(void)
chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg,
const x509cert_t *enc_cert, int enc_alg,
const x509cert_t *signer_cert, int digest_alg,
- const RSA_private_key_t *private_key)
+ private_key_t *private_key)
{
chunk_t envelopedData, attributes, request;
diff --git a/src/scepclient/scep.h b/src/scepclient/scep.h
index 2a11a246e..e8dc87591 100644
--- a/src/scepclient/scep.h
+++ b/src/scepclient/scep.h
@@ -24,7 +24,6 @@
#define _SCEP_H
#include "../pluto/defs.h"
-#include "../pluto/pkcs1.h"
#include "../pluto/pkcs7.h"
/* supported SCEP operation types */
@@ -74,20 +73,21 @@ typedef struct {
extern const scep_attributes_t empty_scep_attributes;
extern bool parse_attributes(chunk_t blob, scep_attributes_t *attrs);
-extern void scep_generate_pkcs10_fingerprint(chunk_t pkcs10
- , chunk_t *fingerprint);
-extern void scep_generate_transaction_id(const RSA_public_key_t *rsak
- , chunk_t *transID, chunk_t *serialNumber);
+extern void scep_generate_transaction_id(public_key_t *key,
+ chunk_t *transID,
+ chunk_t *serialNumber);
+extern chunk_t scep_generate_pkcs10_fingerprint(chunk_t pkcs10);
extern chunk_t scep_transId_attribute(chunk_t transaction_id);
extern chunk_t scep_messageType_attribute(scep_msg_t m);
extern chunk_t scep_senderNonce_attribute(void);
-extern chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg
- , const x509cert_t *enc_cert, int enc_alg
- , const x509cert_t *signer_cert, int digest_alg
- , const RSA_private_key_t *private_key);
-extern bool scep_http_request(const char *url, chunk_t pkcs7, scep_op_t op
- , bool http_get_request, chunk_t *response);
-extern err_t scep_parse_response(chunk_t response, chunk_t transID
- , contentInfo_t *data, scep_attributes_t *attrs, x509cert_t *signer_cert);
+extern chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg,
+ const x509cert_t *enc_cert, int enc_alg,
+ const x509cert_t *signer_cert, int digest_alg,
+ private_key_t *private_key);
+extern bool scep_http_request(const char *url, chunk_t pkcs7, scep_op_t op,
+ bool http_get_request, chunk_t *response);
+extern err_t scep_parse_response(chunk_t response, chunk_t transID,
+ contentInfo_t *data, scep_attributes_t *attrs,
+ x509cert_t *signer_cert);
#endif /* _SCEP_H */
diff --git a/src/scepclient/scepclient.c b/src/scepclient/scepclient.c
index 96853e948..eb3197689 100644
--- a/src/scepclient/scepclient.c
+++ b/src/scepclient/scepclient.c
@@ -42,15 +42,15 @@
#include <asn1/oid.h>
#include <utils/optionsfrom.h>
#include <utils/enumerator.h>
+#include <credentials/keys/private_key.h>
+#include <credentials/keys/public_key.h>
#include "../pluto/constants.h"
#include "../pluto/defs.h"
#include "../pluto/log.h"
-#include "../pluto/pkcs1.h"
#include "../pluto/pkcs7.h"
#include "../pluto/certs.h"
-#include "rsakey.h"
#include "pkcs10.h"
#include "scep.h"
@@ -120,7 +120,8 @@ options_t *options;
* Global variables
*/
-RSA_private_key_t *private_key = NULL;
+private_key_t *private_key = NULL;
+public_key_t *public_key = NULL;
chunk_t pkcs1;
chunk_t pkcs7;
@@ -150,11 +151,8 @@ exit_scepclient(err_t message, ...)
{
int status = 0;
- if (private_key != NULL)
- {
- free_RSA_private_content(private_key);
- free(private_key);
- }
+ DESTROY_IF(private_key);
+ DESTROY_IF(public_key);
free(pkcs1.ptr);
free(pkcs7.ptr);
free(subject.ptr);
@@ -784,24 +782,27 @@ int main(int argc, char **argv)
/*
* input of PKCS#1 file
*/
- private_key = malloc_thing(RSA_private_key_t);
-
if (filetype_in & PKCS1) /* load an RSA key pair from file */
{
prompt_pass_t pass = { "", FALSE, STDIN_FILENO };
char *path = concatenate_paths(PRIVATE_KEY_PATH, file_in_pkcs1);
- ugh = load_rsa_private_key(path, &pass, private_key);
+ private_key = load_private_key(path, &pass, KEY_RSA);
}
else /* generate an RSA key pair */
{
- ugh = generate_rsa_private_key(rsa_keylength, private_key);
+ private_key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_KEY_SIZE, rsa_keylength,
+ BUILD_END);
}
- if (ugh != NULL)
- exit_scepclient(ugh);
+ if (private_key == NULL)
+ {
+ exit_scepclient("no RSA private key available");
+ }
+ public_key = private_key->get_public_key(private_key);
/* check for minimum key length */
- if ((private_key->pub.k) < RSA_MIN_OCTETS)
+ if (private_key->get_keysize(private_key) < RSA_MIN_OCTETS)
{
exit_scepclient("length of RSA key has to be at least %d bits"
,RSA_MIN_OCTETS * BITS_PER_BYTE);
@@ -855,10 +856,11 @@ int main(int argc, char **argv)
DBG(DBG_CONTROL,
DBG_log("building pkcs10 object:")
)
- pkcs10 = pkcs10_build(private_key, subject, challengePassword
- , subjectAltNames, pkcs10_signature_alg);
- scep_generate_pkcs10_fingerprint(pkcs10->request, &fingerprint);
- plog(" fingerprint: %.*s", (int)fingerprint.len, fingerprint.ptr);
+ pkcs10 = pkcs10_build(private_key, public_key, subject,
+ challengePassword, subjectAltNames,
+ pkcs10_signature_alg);
+ fingerprint = scep_generate_pkcs10_fingerprint(pkcs10->request);
+ plog(" fingerprint: %s", fingerprint.ptr);
}
/*
@@ -889,7 +891,7 @@ int main(int argc, char **argv)
DBG(DBG_CONTROL,
DBG_log("building pkcs1 object:")
)
- pkcs1 = pkcs1_build_private_key(private_key);
+ pkcs1 = private_key->get_encoding(private_key);
if (!chunk_write(pkcs1, path, "pkcs1", 0066, force))
exit_scepclient("could not write pkcs1 file '%s'", path);
@@ -902,8 +904,7 @@ int main(int argc, char **argv)
exit_scepclient(NULL); /* no further output required */
}
- scep_generate_transaction_id((const RSA_public_key_t *)private_key
- , &transID, &serialNumber);
+ scep_generate_transaction_id(public_key, &transID, &serialNumber);
plog(" transaction ID: %.*s", (int)transID.len, transID.ptr);
/* generate a self-signed X.509 certificate */
@@ -918,9 +919,7 @@ int main(int argc, char **argv)
: x509_signer->notBefore + validity;
x509_signer->subject = subject;
x509_signer->subjectAltName = subjectAltNames;
-
- build_x509cert(x509_signer, (const RSA_public_key_t *)private_key
- , private_key);
+ build_x509cert(x509_signer, public_key, private_key);
/*
* output of self-signed X.509 certificate file
diff --git a/src/strongswan.conf b/src/strongswan.conf
index 661792a67..0ec4ae9ef 100644
--- a/src/strongswan.conf
+++ b/src/strongswan.conf
@@ -6,12 +6,11 @@ charon {
threads = 16
# plugins to load in charon
- # load = aes des gmp hmac md5 random sha1 sha2 pubkey xcbc x509 stroke
+ # load = aes des sha1 md5 sha2 hmac gmp random pubkey xcbc x509 stroke
plugins {
-
+
sql {
-
# loglevel to log into sql database
loglevel = -1
@@ -23,3 +22,16 @@ charon {
# ...
}
+
+pluto {
+
+ # plugins to load in pluto
+ # load = aes des sha1 md5 sha2 hmac gmp random pubkey
+
+}
+
+libstrongswan {
+
+ # set to no, the DH exponent size is optimized
+ # dh_exponent_ansi_x9_42 = no
+}