From b12c6d163d179ad238fe920eb9f1746b96f51166 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Thu, 27 Aug 2009 09:58:38 +0200 Subject: do openssl fingerprinting/encoding directly, openssl provides all functions --- .../plugins/openssl/openssl_ec_private_key.c | 45 +++----- .../plugins/openssl/openssl_ec_public_key.c | 74 ++++++++---- src/libstrongswan/plugins/openssl/openssl_plugin.c | 5 - .../plugins/openssl/openssl_rsa_private_key.c | 42 +++---- .../plugins/openssl/openssl_rsa_public_key.c | 85 ++++++++++---- src/libstrongswan/plugins/openssl/openssl_util.c | 124 --------------------- src/libstrongswan/plugins/openssl/openssl_util.h | 10 -- 7 files changed, 148 insertions(+), 237 deletions(-) diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c index 820debe14..b256b46ca 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c @@ -98,6 +98,9 @@ static bool lookup_scheme(int scheme, int *hash, int *curve) return FALSE; } +/* from ec public key */ +bool openssl_ec_fingerprint(EC_KEY *ec, key_encoding_type_t type, chunk_t *fp); + /** * Convert an ECDSA_SIG to a chunk by concatenating r and s. * This function allocates memory for the chunk. @@ -230,21 +233,7 @@ static public_key_t* get_public_key(private_openssl_ec_private_key_t *this) static bool get_fingerprint(private_openssl_ec_private_key_t *this, key_encoding_type_t type, chunk_t *fingerprint) { - chunk_t key; - u_char *p; - bool success; - - if (lib->encoding->get_cache(lib->encoding, type, this, fingerprint)) - { - return TRUE; - } - key = chunk_alloc(i2d_EC_PUBKEY(this->ec, NULL)); - p = key.ptr; - i2d_EC_PUBKEY(this->ec, &p); - success = lib->encoding->encode(lib->encoding, type, this, fingerprint, - KEY_PART_ECDSA_PUB_ASN1_DER, key, KEY_PART_END); - free(key.ptr); - return success; + return openssl_ec_fingerprint(this->ec, type, fingerprint); } /** @@ -253,17 +242,20 @@ static bool get_fingerprint(private_openssl_ec_private_key_t *this, static bool get_encoding(private_openssl_ec_private_key_t *this, key_encoding_type_t type, chunk_t *encoding) { - chunk_t key; u_char *p; - bool success; - key = chunk_alloc(i2d_ECPrivateKey(this->ec, NULL)); - p = key.ptr; - i2d_ECPrivateKey(this->ec, &p); - success = lib->encoding->encode(lib->encoding, type, NULL, encoding, - KEY_PART_ECDSA_PRIV_ASN1_DER, key, KEY_PART_END); - free(key.ptr); - return success; + switch (type) + { + case KEY_PRIV_ASN1_DER: + { + *encoding = chunk_alloc(i2d_ECPrivateKey(this->ec, NULL)); + p = encoding->ptr; + i2d_ECPrivateKey(this->ec, &p); + return TRUE; + } + default: + return FALSE; + } } /** @@ -284,9 +276,9 @@ static void destroy(private_openssl_ec_private_key_t *this) { if (this->ec) { + lib->encoding->clear_cache(lib->encoding, this->ec); EC_KEY_free(this->ec); } - lib->encoding->clear_cache(lib->encoding, this); free(this); } } @@ -356,10 +348,9 @@ static openssl_ec_private_key_t *generate(size_t key_size) */ static openssl_ec_private_key_t *load(chunk_t blob) { - u_char *p = blob.ptr; private_openssl_ec_private_key_t *this = create_empty(); - this->ec = d2i_ECPrivateKey(NULL, (const u_char**)&p, blob.len); + this->ec = d2i_ECPrivateKey(NULL, (const u_char**)&blob.ptr, blob.len); if (!this->ec) { diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c index 4d0af04b4..a290f3d05 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c @@ -194,26 +194,53 @@ static size_t get_keysize(private_openssl_ec_public_key_t *this) } /** - * Implementation of private_key_t.get_fingerprint. + * Calculate fingerprint from a EC_KEY, also used in ec private key. */ -static bool get_fingerprint(private_openssl_ec_public_key_t *this, - key_encoding_type_t type, chunk_t *fingerprint) +bool openssl_ec_fingerprint(EC_KEY *ec, key_encoding_type_t type, chunk_t *fp) { + hasher_t *hasher; chunk_t key; u_char *p; - bool success; - if (lib->encoding->get_cache(lib->encoding, type, this, fingerprint)) + if (lib->encoding->get_cache(lib->encoding, type, ec, fp)) { return TRUE; } - key = chunk_alloc(i2d_EC_PUBKEY(this->ec, NULL)); - p = key.ptr; - i2d_EC_PUBKEY(this->ec, &p); - success = lib->encoding->encode(lib->encoding, type, this, fingerprint, - KEY_PART_ECDSA_PUB_ASN1_DER, key, KEY_PART_END); - free(key.ptr); - return success; + switch (type) + { + case KEY_ID_PUBKEY_SHA1: + key = chunk_alloc(i2o_ECPublicKey(ec, NULL)); + p = key.ptr; + i2o_ECPublicKey(ec, &p); + break; + case KEY_ID_PUBKEY_INFO_SHA1: + key = chunk_alloc(i2d_EC_PUBKEY(ec, NULL)); + p = key.ptr; + i2d_EC_PUBKEY(ec, &p); + break; + default: + return FALSE; + } + hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); + if (!hasher) + { + DBG1("SHA1 hash algorithm not supported, fingerprinting failed"); + free(key.ptr); + return FALSE; + } + hasher->allocate_hash(hasher, key, fp); + hasher->destroy(hasher); + lib->encoding->cache(lib->encoding, type, ec, *fp); + return TRUE; +} + +/** + * Implementation of private_key_t.get_fingerprint. + */ +static bool get_fingerprint(private_openssl_ec_public_key_t *this, + key_encoding_type_t type, chunk_t *fingerprint) +{ + return openssl_ec_fingerprint(this->ec, type, fingerprint); } /** @@ -222,17 +249,20 @@ static bool get_fingerprint(private_openssl_ec_public_key_t *this, static bool get_encoding(private_openssl_ec_public_key_t *this, key_encoding_type_t type, chunk_t *encoding) { - chunk_t key; u_char *p; - bool success; - key = chunk_alloc(i2d_EC_PUBKEY(this->ec, NULL)); - p = key.ptr; - i2d_EC_PUBKEY(this->ec, &p); - success = lib->encoding->encode(lib->encoding, type, NULL, encoding, - KEY_PART_ECDSA_PUB_ASN1_DER, key, KEY_PART_END); - free(key.ptr); - return success; + switch (type) + { + case KEY_PUB_SPKI_ASN1_DER: + { + *encoding = chunk_alloc(i2d_EC_PUBKEY(this->ec, NULL)); + p = encoding->ptr; + i2d_EC_PUBKEY(this->ec, &p); + return TRUE; + } + default: + return FALSE; + } } /** @@ -253,9 +283,9 @@ static void destroy(private_openssl_ec_public_key_t *this) { if (this->ec) { + lib->encoding->clear_cache(lib->encoding, this->ec); EC_KEY_free(this->ec); } - lib->encoding->clear_cache(lib->encoding, this); free(this); } } diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c index 53c3e6816..a24f88219 100644 --- a/src/libstrongswan/plugins/openssl/openssl_plugin.c +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c @@ -183,8 +183,6 @@ static void destroy(private_openssl_plugin_t *this) lib->creds->remove_builder(lib->creds, (builder_constructor_t)openssl_ec_public_key_builder); - lib->encoding->remove_encoder(lib->encoding, openssl_encode); - ENGINE_cleanup(); EVP_cleanup(); CONF_modules_free(); @@ -294,8 +292,5 @@ plugin_t *plugin_create() lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_ECDSA, (builder_constructor_t)openssl_ec_public_key_builder); - /* fingerprinting/encoding */ - lib->encoding->add_encoder(lib->encoding, openssl_encode); - return &this->public.plugin; } diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c index d371e8807..3f4e1cd74 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c @@ -55,6 +55,9 @@ struct private_openssl_rsa_private_key_t { refcount_t ref; }; +/* implemented in rsa public key */ +bool openssl_rsa_fingerprint(RSA *rsa, key_encoding_type_t type, chunk_t *fp); + /** * Build an EMPSA PKCS1 signature described in PKCS#1 */ @@ -205,21 +208,7 @@ static public_key_t* get_public_key(private_openssl_rsa_private_key_t *this) static bool get_fingerprint(private_openssl_rsa_private_key_t *this, key_encoding_type_t type, chunk_t *fingerprint) { - chunk_t enc; - bool success; - u_char *p; - - if (lib->encoding->get_cache(lib->encoding, type, this, fingerprint)) - { - return TRUE; - } - enc = chunk_alloc(i2d_RSAPublicKey(this->rsa, NULL)); - p = enc.ptr; - i2d_RSAPublicKey(this->rsa, &p); - success = lib->encoding->encode(lib->encoding, type, this, fingerprint, - KEY_PART_RSA_PUB_ASN1_DER, enc, KEY_PART_END); - free(enc.ptr); - return success; + return openssl_rsa_fingerprint(this->rsa, type, fingerprint); } /* @@ -228,21 +217,24 @@ static bool get_fingerprint(private_openssl_rsa_private_key_t *this, static bool get_encoding(private_openssl_rsa_private_key_t *this, key_encoding_type_t type, chunk_t *encoding) { - chunk_t enc; - bool success; u_char *p; if (this->engine) { return FALSE; } - enc = chunk_alloc(i2d_RSAPrivateKey(this->rsa, NULL)); - p = enc.ptr; - i2d_RSAPrivateKey(this->rsa, &p); - success = lib->encoding->encode(lib->encoding, type, NULL, encoding, - KEY_PART_RSA_PRIV_ASN1_DER, enc, KEY_PART_END); - free(enc.ptr); - return success; + switch (type) + { + case KEY_PRIV_ASN1_DER: + { + *encoding = chunk_alloc(i2d_RSAPrivateKey(this->rsa, NULL)); + p = encoding->ptr; + i2d_RSAPrivateKey(this->rsa, &p); + return TRUE; + } + default: + return FALSE; + } } /** @@ -263,9 +255,9 @@ static void destroy(private_openssl_rsa_private_key_t *this) { if (this->rsa) { + lib->encoding->clear_cache(lib->encoding, this->rsa); RSA_free(this->rsa); } - lib->encoding->clear_cache(lib->encoding, this); free(this); } } diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c index cb3e80a69..880a4613e 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c @@ -20,6 +20,7 @@ #include #include +#include typedef struct private_openssl_rsa_public_key_t private_openssl_rsa_public_key_t; @@ -169,27 +170,53 @@ static size_t get_keysize(private_openssl_rsa_public_key_t *this) } /** - * Implementation of public_key_t.get_fingerprint. + * Calculate fingerprint from a RSA key, also used in rsa private key. */ -static bool get_fingerprint(private_openssl_rsa_public_key_t *this, - key_encoding_type_t type, chunk_t *fingerprint) +bool openssl_rsa_fingerprint(RSA *rsa, key_encoding_type_t type, chunk_t *fp) { - chunk_t enc; - bool success; + hasher_t *hasher; + chunk_t key; u_char *p; - if (lib->encoding->get_cache(lib->encoding, type, this, fingerprint)) + if (lib->encoding->get_cache(lib->encoding, type, rsa, fp)) { return TRUE; } - enc = chunk_alloc(i2d_RSAPublicKey(this->rsa, NULL)); - p = enc.ptr; - i2d_RSAPublicKey(this->rsa, &p); - success = lib->encoding->encode(lib->encoding, type, this, fingerprint, - KEY_PART_RSA_PUB_ASN1_DER, enc, KEY_PART_END); - free(enc.ptr); - - return success; + switch (type) + { + case KEY_ID_PUBKEY_SHA1: + key = chunk_alloc(i2d_RSAPublicKey(rsa, NULL)); + p = key.ptr; + i2d_RSAPublicKey(rsa, &p); + break; + case KEY_ID_PUBKEY_INFO_SHA1: + key = chunk_alloc(i2d_RSA_PUBKEY(rsa, NULL)); + p = key.ptr; + i2d_RSA_PUBKEY(rsa, &p); + break; + default: + return FALSE; + } + hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); + if (!hasher) + { + DBG1("SHA1 hash algorithm not supported, fingerprinting failed"); + free(key.ptr); + return FALSE; + } + hasher->allocate_hash(hasher, key, fp); + hasher->destroy(hasher); + lib->encoding->cache(lib->encoding, type, rsa, *fp); + return TRUE; +} + +/** + * Implementation of public_key_t.get_fingerprint. + */ +static bool get_fingerprint(private_openssl_rsa_public_key_t *this, + key_encoding_type_t type, chunk_t *fingerprint) +{ + return openssl_rsa_fingerprint(this->rsa, type, fingerprint); } /* @@ -198,17 +225,27 @@ static bool get_fingerprint(private_openssl_rsa_public_key_t *this, static bool get_encoding(private_openssl_rsa_public_key_t *this, key_encoding_type_t type, chunk_t *encoding) { - chunk_t enc; - bool success; u_char *p; - enc = chunk_alloc(i2d_RSAPublicKey(this->rsa, NULL)); - p = enc.ptr; - i2d_RSAPublicKey(this->rsa, &p); - success = lib->encoding->encode(lib->encoding, type, NULL, encoding, - KEY_PART_RSA_PUB_ASN1_DER, enc, KEY_PART_END); - free(enc.ptr); - return success; + switch (type) + { + case KEY_PUB_SPKI_ASN1_DER: + { + *encoding = chunk_alloc(i2d_RSA_PUBKEY(this->rsa, NULL)); + p = encoding->ptr; + i2d_RSA_PUBKEY(this->rsa, &p); + return TRUE; + } + case KEY_PUB_ASN1_DER: + { + *encoding = chunk_alloc(i2d_RSAPublicKey(this->rsa, NULL)); + p = encoding->ptr; + i2d_RSAPublicKey(this->rsa, &p); + return TRUE; + } + default: + return FALSE; + } } /** @@ -229,9 +266,9 @@ static void destroy(private_openssl_rsa_public_key_t *this) { if (this->rsa) { + lib->encoding->clear_cache(lib->encoding, this->rsa); RSA_free(this->rsa); } - lib->encoding->clear_cache(lib->encoding, this); free(this); } } diff --git a/src/libstrongswan/plugins/openssl/openssl_util.c b/src/libstrongswan/plugins/openssl/openssl_util.c index 60b4e74e0..5caae4bdd 100644 --- a/src/libstrongswan/plugins/openssl/openssl_util.c +++ b/src/libstrongswan/plugins/openssl/openssl_util.c @@ -124,127 +124,3 @@ bool openssl_bn_split(chunk_t chunk, BIGNUM *a, BIGNUM *b) return TRUE; } -/** - * wrap publicKey in subjectPublicKeyInfo - */ -static chunk_t build_info(chunk_t key) -{ - X509_PUBKEY *pubkey; - chunk_t enc; - u_char *p; - - pubkey = X509_PUBKEY_new(); - ASN1_OBJECT_free(pubkey->algor->algorithm); - pubkey->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption); - - if (pubkey->algor->parameter == NULL || - pubkey->algor->parameter->type != V_ASN1_NULL) - { - ASN1_TYPE_free(pubkey->algor->parameter); - pubkey->algor->parameter = ASN1_TYPE_new(); - pubkey->algor->parameter->type = V_ASN1_NULL; - } - M_ASN1_BIT_STRING_set(pubkey->public_key, key.ptr, key.len); - - enc = chunk_alloc(i2d_X509_PUBKEY(pubkey, NULL)); - p = enc.ptr; - i2d_X509_PUBKEY(pubkey, &p); - X509_PUBKEY_free(pubkey); - - return enc; -} - -/** - * Build fingerprints of a private/public RSA key. - */ -static bool build_fingerprint(chunk_t key, key_encoding_type_t type, - chunk_t *fingerprint) -{ - hasher_t *hasher; - - hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); - if (!hasher) - { - DBG1("SHA1 hash algorithm not supported, fingerprinting failed"); - return FALSE; - } - if (type == KEY_ID_PUBKEY_INFO_SHA1) - { - chunk_t enc; - - enc = build_info(key); - hasher->allocate_hash(hasher, enc, fingerprint); - chunk_free(&enc); - } - else - { - hasher->allocate_hash(hasher, key, fingerprint); - } - hasher->destroy(hasher); - return TRUE; -} - -/** - * See header. - */ -bool openssl_encode(key_encoding_type_t type, chunk_t *encoding, va_list args) -{ - chunk_t key; - - switch (type) - { - case KEY_PUB_ASN1_DER: - /* this encoding is currently not supported for ECDSA keys */ - if (key_encoding_args(args, KEY_PART_RSA_PUB_ASN1_DER, &key, - KEY_PART_END)) - { - *encoding = chunk_clone(key); - return TRUE; - } - return FALSE; - case KEY_PUB_SPKI_ASN1_DER: - /* key encoding, wrapped in a subjectPublicKeyInfo field */ - if (key_encoding_args(args, KEY_PART_RSA_PUB_ASN1_DER, &key, - KEY_PART_END)) - { - *encoding = build_info(key); - return TRUE; - } - else if (key_encoding_args(args, KEY_PART_ECDSA_PUB_ASN1_DER, &key, - KEY_PART_END)) - { - /* ECDSA keys are already wrapped in the publickeyInfo field, - * they are incomplete without */ - *encoding = chunk_clone(key); - return TRUE; - } - return FALSE; - case KEY_PRIV_ASN1_DER: - if (key_encoding_args(args, KEY_PART_RSA_PRIV_ASN1_DER, &key, - KEY_PART_END) || - key_encoding_args(args, KEY_PART_ECDSA_PRIV_ASN1_DER, &key, - KEY_PART_END)) - { - *encoding = chunk_clone(key); - return TRUE; - } - return FALSE; - case KEY_ID_PUBKEY_SHA1: - case KEY_ID_PUBKEY_INFO_SHA1: - if (key_encoding_args(args, KEY_PART_RSA_PUB_ASN1_DER, &key, - KEY_PART_END)) - { - return build_fingerprint(key, type, encoding); - } - else if (key_encoding_args(args, KEY_PART_ECDSA_PUB_ASN1_DER, &key, - KEY_PART_END)) - { - /* for ECDSA the two keyids are currently the same */ - return build_fingerprint(key, KEY_ID_PUBKEY_SHA1, encoding); - } - return FALSE; - default: - return FALSE; - } -} - diff --git a/src/libstrongswan/plugins/openssl/openssl_util.h b/src/libstrongswan/plugins/openssl/openssl_util.h index 921c52612..6ba1ff07b 100644 --- a/src/libstrongswan/plugins/openssl/openssl_util.h +++ b/src/libstrongswan/plugins/openssl/openssl_util.h @@ -65,14 +65,4 @@ bool openssl_bn_cat(int len, BIGNUM *a, BIGNUM *b, chunk_t *chunk); */ bool openssl_bn_split(chunk_t chunk, BIGNUM *a, BIGNUM *b); - -/** - * Fingerprinting/encdoing of PKCS#1/ASN.1 encoded keys. - * - * @param type type of the fingerprint/encoding to create. - * @param encoding receives fingerprint/encoding, allocated - * @param args variable argument list of encoding parts - */ -bool openssl_encode(key_encoding_type_t type, chunk_t *encoding, va_list args); - #endif /** OPENSSL_UTIL_H_ @}*/ -- cgit v1.2.3