/**
* EC key object
*/
- EC_KEY *ec;
+ EVP_PKEY *key;
/**
* TRUE if the key is from an OpenSSL ENGINE and might not be readable
refcount_t ref;
};
-/* from ec public key */
-bool openssl_ec_fingerprint(EC_KEY *ec, cred_encoding_type_t type, chunk_t *fp);
+/* from openssl_ec_public_key */
+bool openssl_check_ec_key_curve(EVP_PKEY *key, int nid_curve);
+
+/**
+ * Build a DER encoded signature as in RFC 3279
+ */
+static bool build_der_signature(private_openssl_ec_private_key_t *this,
+ int nid_hash, chunk_t data, chunk_t *signature)
+{
+ EVP_MD_CTX *ctx;
+ const EVP_MD *md;
+
+ md = EVP_get_digestbynid(nid_hash);
+ if (!md)
+ {
+ return FALSE;
+ }
+ *signature = chunk_alloc(EVP_PKEY_size(this->key));
+ ctx = EVP_MD_CTX_create();
+ if (!ctx ||
+ EVP_DigestSignInit(ctx, NULL, md, NULL, this->key) <= 0 ||
+ EVP_DigestSignUpdate(ctx, data.ptr, data.len) <= 0 ||
+ EVP_DigestSignFinal(ctx, signature->ptr, &signature->len) != 1)
+ {
+ chunk_free(signature);
+ EVP_MD_CTX_destroy(ctx);
+ return FALSE;
+ }
+ EVP_MD_CTX_destroy(ctx);
+ return TRUE;
+}
/**
* Build a signature as in RFC 4754
*/
static bool build_signature(private_openssl_ec_private_key_t *this,
- chunk_t hash, chunk_t *signature)
+ int nid_hash, chunk_t data, chunk_t *signature)
{
- const BIGNUM *r, *s;
+ EVP_PKEY_CTX *ctx;
ECDSA_SIG *sig;
+ const BIGNUM *r, *s;
+ const u_char *p;
+ chunk_t der_sig;
bool built = FALSE;
- sig = ECDSA_do_sign(hash.ptr, hash.len, this->ec);
+ if (!nid_hash)
+ { /* EVP_DigestSign*() has issues with NULL EVP_MD */
+ der_sig = chunk_alloc(EVP_PKEY_size(this->key));
+ ctx = EVP_PKEY_CTX_new(this->key, NULL);
+ if (!ctx ||
+ EVP_PKEY_sign_init(ctx) <= 0 ||
+ EVP_PKEY_sign(ctx, der_sig.ptr, &der_sig.len, data.ptr, data.len) <= 0)
+ {
+ chunk_free(&der_sig);
+ EVP_PKEY_CTX_free(ctx);
+ return FALSE;
+ }
+ EVP_PKEY_CTX_free(ctx);
+ }
+ else if (!build_der_signature(this, nid_hash, data, &der_sig))
+ {
+ return FALSE;
+ }
+ /* extract r and s from the DER-encoded signature */
+ p = der_sig.ptr;
+ sig = d2i_ECDSA_SIG(NULL, &p, der_sig.len);
+ chunk_free(&der_sig);
if (sig)
{
ECDSA_SIG_get0(sig, &r, &s);
/* concatenate BNs r/s to a signature chunk */
- built = openssl_bn_cat(EC_FIELD_ELEMENT_LEN(EC_KEY_get0_group(this->ec)),
+ built = openssl_bn_cat((EVP_PKEY_bits(this->key) + 7) / 8,
r, s, signature);
ECDSA_SIG_free(sig);
}
signature_scheme_t scheme, int nid_hash,
int nid_curve, chunk_t data, chunk_t *signature)
{
- const EC_GROUP *my_group;
- EC_GROUP *req_group;
- chunk_t hash;
- bool built;
-
- req_group = EC_GROUP_new_by_curve_name(nid_curve);
- if (!req_group)
- {
- DBG1(DBG_LIB, "signature scheme %N not supported in EC (required curve "
- "not supported)", signature_scheme_names, scheme);
- return FALSE;
- }
- my_group = EC_KEY_get0_group(this->ec);
- if (EC_GROUP_cmp(my_group, req_group, NULL) != 0)
+ if (!openssl_check_ec_key_curve(this->key, nid_curve))
{
- DBG1(DBG_LIB, "signature scheme %N not supported by private key",
+ DBG1(DBG_LIB, "signature scheme %N not supported by key",
signature_scheme_names, scheme);
return FALSE;
}
- EC_GROUP_free(req_group);
- if (!openssl_hash_chunk(nid_hash, data, &hash))
- {
- return FALSE;
- }
- built = build_signature(this, hash, signature);
- chunk_free(&hash);
- return built;
-}
-
-/**
- * Build a DER encoded signature as in RFC 3279
- */
-static bool build_der_signature(private_openssl_ec_private_key_t *this,
- int hash_nid, chunk_t data, chunk_t *signature)
-{
- chunk_t hash, sig;
- int siglen = 0;
- bool built;
-
- if (!openssl_hash_chunk(hash_nid, data, &hash))
- {
- return FALSE;
- }
- sig = chunk_alloc(ECDSA_size(this->ec));
- built = ECDSA_sign(0, hash.ptr, hash.len, sig.ptr, &siglen, this->ec) == 1;
- sig.len = siglen;
- if (built)
- {
- *signature = sig;
- }
- else
- {
- free(sig.ptr);
- }
- free(hash.ptr);
- return built;
+ return build_signature(this, nid_hash, data, signature);
}
METHOD(private_key_t, sign, bool,
switch (scheme)
{
case SIGN_ECDSA_WITH_NULL:
- return build_signature(this, data, signature);
+ return build_signature(this, 0, data, signature);
case SIGN_ECDSA_WITH_SHA1_DER:
return build_der_signature(this, NID_sha1, data, signature);
case SIGN_ECDSA_WITH_SHA256_DER:
METHOD(private_key_t, get_keysize, int,
private_openssl_ec_private_key_t *this)
{
- return EC_GROUP_get_degree(EC_KEY_get0_group(this->ec));
+ return EVP_PKEY_bits(this->key);
}
METHOD(private_key_t, get_type, key_type_t,
{
public_key_t *public;
chunk_t key;
- u_char *p;
-
- key = chunk_alloc(i2d_EC_PUBKEY(this->ec, NULL));
- p = key.ptr;
- i2d_EC_PUBKEY(this->ec, &p);
+ key = openssl_i2chunk(PUBKEY, this->key);
public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ECDSA,
BUILD_BLOB_ASN1_DER, key, BUILD_END);
free(key.ptr);
private_openssl_ec_private_key_t *this, cred_encoding_type_t type,
chunk_t *fingerprint)
{
- return openssl_ec_fingerprint(this->ec, type, fingerprint);
+ return openssl_fingerprint(this->key, type, fingerprint);
}
METHOD(private_key_t, get_encoding, bool,
private_openssl_ec_private_key_t *this, cred_encoding_type_t type,
chunk_t *encoding)
{
- u_char *p;
-
if (this->engine)
{
return FALSE;
}
-
switch (type)
{
case PRIVKEY_ASN1_DER:
{
bool success = TRUE;
- *encoding = chunk_alloc(i2d_ECPrivateKey(this->ec, NULL));
- p = encoding->ptr;
- i2d_ECPrivateKey(this->ec, &p);
+ *encoding = openssl_i2chunk(PrivateKey, this->key);
if (type == PRIVKEY_PEM)
{
{
if (ref_put(&this->ref))
{
- if (this->ec)
+ if (this->key)
{
- lib->encoding->clear_cache(lib->encoding, this->ec);
- EC_KEY_free(this->ec);
+ lib->encoding->clear_cache(lib->encoding, this->key);
+ EVP_PKEY_free(this->key);
}
free(this);
}
/**
* Internal generic constructor
*/
-static private_openssl_ec_private_key_t *create_empty(void)
+static private_openssl_ec_private_key_t *create_internal(EVP_PKEY *key)
{
private_openssl_ec_private_key_t *this;
},
},
.ref = 1,
+ .key = key,
);
return this;
private_key_t *openssl_ec_private_key_create(EVP_PKEY *key, bool engine)
{
private_openssl_ec_private_key_t *this;
- EC_KEY *ec;
- ec = EVP_PKEY_get1_EC_KEY(key);
- EVP_PKEY_free(key);
- if (!ec)
+ if (EVP_PKEY_base_id(key) != EVP_PKEY_EC)
{
+ EVP_PKEY_free(key);
return NULL;
}
- this = create_empty();
- this->ec = ec;
+ this = create_internal(key);
this->engine = engine;
return &this->public.key;
}
va_list args)
{
private_openssl_ec_private_key_t *this;
+ EVP_PKEY *key = NULL;
u_int key_size = 0;
while (TRUE)
{
return NULL;
}
- this = create_empty();
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
switch (key_size)
{
case 256:
- this->ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+ key = EVP_EC_gen("P-256");
break;
case 384:
- this->ec = EC_KEY_new_by_curve_name(NID_secp384r1);
+ key = EVP_EC_gen("P-384");
break;
case 521:
- this->ec = EC_KEY_new_by_curve_name(NID_secp521r1);
+ key = EVP_EC_gen("P-521");
break;
default:
DBG1(DBG_LIB, "EC private key size %d not supported", key_size);
- destroy(this);
return NULL;
}
- if (EC_KEY_generate_key(this->ec) != 1)
+#else /* OPENSSL_VERSION_NUMBER */
+ EC_KEY *ec;
+
+ switch (key_size)
+ {
+ case 256:
+ ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+ break;
+ case 384:
+ ec = EC_KEY_new_by_curve_name(NID_secp384r1);
+ break;
+ case 521:
+ ec = EC_KEY_new_by_curve_name(NID_secp521r1);
+ break;
+ default:
+ DBG1(DBG_LIB, "EC private key size %d not supported", key_size);
+ return NULL;
+ }
+ if (ec && EC_KEY_generate_key(ec) == 1)
+ {
+ key = EVP_PKEY_new();
+ if (!EVP_PKEY_assign_EC_KEY(key, ec))
+ {
+ EC_KEY_free(ec);
+ EVP_PKEY_free(key);
+ key = NULL;
+ }
+ }
+#endif /* OPENSSL_VERSION_NUMBER */
+
+ if (!key)
{
- DBG1(DBG_LIB, "EC private key generation failed", key_size);
- destroy(this);
return NULL;
}
- /* encode as a named curve key (no parameters), uncompressed public key */
- EC_KEY_set_asn1_flag(this->ec, OPENSSL_EC_NAMED_CURVE);
- EC_KEY_set_conv_form(this->ec, POINT_CONVERSION_UNCOMPRESSED);
+ this = create_internal(key);
return &this->public;
}
va_list args)
{
private_openssl_ec_private_key_t *this;
- chunk_t par = chunk_empty, key = chunk_empty;
+ chunk_t par = chunk_empty, blob = chunk_empty;
+ EVP_PKEY *key = NULL;
while (TRUE)
{
par = va_arg(args, chunk_t);
continue;
case BUILD_BLOB_ASN1_DER:
- key = va_arg(args, chunk_t);
+ blob = va_arg(args, chunk_t);
continue;
case BUILD_END:
break;
break;
}
- this = create_empty();
-
if (par.ptr)
{
- this->ec = d2i_ECParameters(NULL, (const u_char**)&par.ptr, par.len);
- if (!this->ec)
+ /* for OpenSSL 3, the combination of d2i_KeyParams/d2i_PrivateKey, which
+ * are intended to replace the functions below, does currently not work
+ * because OpenSSL does not pass the internal EC_KEY that stores the
+ * parameters from the first call to the call that parses the private
+ * key. however, since parsing PKCS#8 is the only use case for this and
+ * OpenSSL 3 parses this format directly, there isn't really any need
+ * for it anyway */
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
+ EC_KEY *ec;
+
+ ec = d2i_ECParameters(NULL, (const u_char**)&par.ptr, par.len);
+ if (ec && d2i_ECPrivateKey(&ec, (const u_char**)&blob.ptr, blob.len))
{
- goto error;
+ key = EVP_PKEY_new();
+ if (!EVP_PKEY_assign_EC_KEY(key, ec))
+ {
+ EC_KEY_free(ec);
+ EVP_PKEY_free(key);
+ key = NULL;
+ }
}
- if (!d2i_ECPrivateKey(&this->ec, (const u_char**)&key.ptr, key.len))
+ else
{
- goto error;
+ EC_KEY_free(ec);
}
+#endif
}
else
{
- this->ec = d2i_ECPrivateKey(NULL, (const u_char**)&key.ptr, key.len);
- if (!this->ec)
- {
- goto error;
- }
+ key = d2i_PrivateKey(EVP_PKEY_EC, NULL, (const u_char**)&blob.ptr,
+ blob.len);
}
- if (!EC_KEY_check_key(this->ec))
+
+ if (!key)
{
- goto error;
+ return NULL;
}
+ this = create_internal(key);
return &this->public;
-
-error:
- destroy(this);
- return NULL;
}
#endif /* OPENSSL_NO_ECDSA */
#include <openssl/ecdsa.h>
#include <openssl/x509.h>
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/core_names.h>
+#endif
+
#if OPENSSL_VERSION_NUMBER < 0x10100000L
OPENSSL_KEY_FALLBACK(ECDSA_SIG, r, s)
#endif
/**
* EC key object
*/
- EC_KEY *ec;
+ EVP_PKEY *key;
/**
* reference counter
refcount_t ref;
};
+/**
+ * Verification of a DER encoded signature as in RFC 3279
+ */
+static bool verify_der_signature(private_openssl_ec_public_key_t *this,
+ int nid_hash, chunk_t data, chunk_t signature)
+{
+ EVP_MD_CTX *ctx;
+ const EVP_MD *md;
+
+ /* remove any preceding 0-bytes from signature */
+ while (signature.len && signature.ptr[0] == 0x00)
+ {
+ signature = chunk_skip(signature, 1);
+ }
+ md = EVP_get_digestbynid(nid_hash);
+ if (!md)
+ {
+ return FALSE;
+ }
+ ctx = EVP_MD_CTX_create();
+ if (!ctx ||
+ EVP_DigestVerifyInit(ctx, NULL, md, NULL, this->key) <= 0 ||
+ EVP_DigestVerifyUpdate(ctx, data.ptr, data.len) <= 0 ||
+ EVP_DigestVerifyFinal(ctx, signature.ptr, signature.len) != 1)
+ {
+ EVP_MD_CTX_destroy(ctx);
+ return FALSE;
+ }
+ EVP_MD_CTX_destroy(ctx);
+ return TRUE;
+}
+
/**
* Verification of a signature as in RFC 4754
*/
static bool verify_signature(private_openssl_ec_public_key_t *this,
- chunk_t hash, chunk_t signature)
+ int nid_hash, chunk_t data, chunk_t signature)
{
+ EVP_PKEY_CTX *ctx;
BIGNUM *r, *s;
ECDSA_SIG *sig;
+ chunk_t der_sig;
bool valid = FALSE;
sig = ECDSA_SIG_new();
}
if (ECDSA_SIG_set0(sig, r, s))
{
- valid = (ECDSA_do_verify(hash.ptr, hash.len, sig, this->ec) == 1);
+ der_sig = openssl_i2chunk(ECDSA_SIG, sig);
+ if (!nid_hash)
+ { /* EVP_DigestVerify*() has issues with NULL EVP_MD */
+ ctx = EVP_PKEY_CTX_new(this->key, NULL);
+ valid = ctx && EVP_PKEY_verify_init(ctx) > 0 &&
+ EVP_PKEY_verify(ctx, der_sig.ptr, der_sig.len,
+ data.ptr, data.len) > 0;
+ EVP_PKEY_CTX_free(ctx);
+ }
+ else
+ {
+ valid = verify_der_signature(this, nid_hash, data, der_sig);
+ }
+ chunk_free(&der_sig);
}
ECDSA_SIG_free(sig);
}
}
/**
- * Verify a RFC 4754 signature for a specified curve and hash algorithm
+ * Check that the given key's curve matches a specific one. Also used by
+ * private key.
*/
-static bool verify_curve_signature(private_openssl_ec_public_key_t *this,
- signature_scheme_t scheme, int nid_hash,
- int nid_curve, chunk_t data, chunk_t signature)
+bool openssl_check_ec_key_curve(EVP_PKEY *key, int nid_curve)
{
- const EC_GROUP *my_group;
- EC_GROUP *req_group;
- chunk_t hash;
- bool valid;
+ EC_GROUP *req_group, *my_group = NULL;
+ bool matches = FALSE;
req_group = EC_GROUP_new_by_curve_name(nid_curve);
if (!req_group)
{
- DBG1(DBG_LIB, "signature scheme %N not supported in EC (required curve "
- "not supported)", signature_scheme_names, scheme);
- return FALSE;
+ goto error;
}
- my_group = EC_KEY_get0_group(this->ec);
- if (EC_GROUP_cmp(my_group, req_group, NULL) != 0)
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ char name[BUF_LEN];
+ OSSL_PARAM params[] = {
+ OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, name, sizeof(name)),
+ OSSL_PARAM_END,
+ };
+
+ if (!EVP_PKEY_get_group_name(key, name, sizeof(name), NULL))
{
- DBG1(DBG_LIB, "signature scheme %N not supported by private key",
- signature_scheme_names, scheme);
- return FALSE;
+ goto error;
}
- EC_GROUP_free(req_group);
- if (!openssl_hash_chunk(nid_hash, data, &hash))
+ my_group = EC_GROUP_new_from_params(params, NULL, NULL);
+#elif OPENSSL_VERSION_NUMBER >= 0x1010000fL
+ EC_KEY *ec = EVP_PKEY_get0_EC_KEY(key);
+ my_group = EC_GROUP_dup(EC_KEY_get0_group(ec));
+#else
+ EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key);
+ my_group = EC_GROUP_dup(EC_KEY_get0_group(ec));
+ EC_KEY_free(ec);
+#endif
+
+ if (EC_GROUP_cmp(my_group, req_group, NULL) == 0)
{
- return FALSE;
+ matches = TRUE;
}
- valid = verify_signature(this, hash, signature);
- chunk_free(&hash);
- return valid;
+
+error:
+ EC_GROUP_free(my_group);
+ EC_GROUP_free(req_group);
+ return matches;
}
/**
- * Verification of a DER encoded signature as in RFC 3279
+ * Verify a RFC 4754 signature for a specified curve and hash algorithm
*/
-static bool verify_der_signature(private_openssl_ec_public_key_t *this,
- int nid_hash, chunk_t data, chunk_t signature)
+static bool verify_curve_signature(private_openssl_ec_public_key_t *this,
+ signature_scheme_t scheme, int nid_hash,
+ int nid_curve, chunk_t data, chunk_t signature)
{
- chunk_t hash;
- bool valid = FALSE;
-
- /* remove any preceding 0-bytes from signature */
- while (signature.len && signature.ptr[0] == 0x00)
+ if (!openssl_check_ec_key_curve(this->key, nid_curve))
{
- signature = chunk_skip(signature, 1);
- }
- if (openssl_hash_chunk(nid_hash, data, &hash))
- {
- valid = ECDSA_verify(0, hash.ptr, hash.len,
- signature.ptr, signature.len, this->ec) == 1;
- free(hash.ptr);
+ DBG1(DBG_LIB, "signature scheme %N not supported by key",
+ signature_scheme_names, scheme);
+ return FALSE;
}
- return valid;
+ return verify_signature(this, nid_hash, data, signature);
}
METHOD(public_key_t, get_type, key_type_t,
case SIGN_ECDSA_WITH_SHA512_DER:
return verify_der_signature(this, NID_sha512, data, signature);
case SIGN_ECDSA_WITH_NULL:
- return verify_signature(this, data, signature);
+ return verify_signature(this, 0, data, signature);
case SIGN_ECDSA_256:
return verify_curve_signature(this, scheme, NID_sha256,
NID_X9_62_prime256v1, data, signature);
METHOD(public_key_t, get_keysize, int,
private_openssl_ec_public_key_t *this)
{
- return EC_GROUP_get_degree(EC_KEY_get0_group(this->ec));
-}
-
-/**
- * Calculate fingerprint from a EC_KEY, also used in ec private key.
- */
-bool openssl_ec_fingerprint(EC_KEY *ec, cred_encoding_type_t type, chunk_t *fp)
-{
- hasher_t *hasher;
- chunk_t key;
- u_char *p;
-
- if (lib->encoding->get_cache(lib->encoding, type, ec, fp))
- {
- return TRUE;
- }
- switch (type)
- {
- case KEYID_PUBKEY_SHA1:
- key = chunk_alloc(i2o_ECPublicKey(ec, NULL));
- p = key.ptr;
- i2o_ECPublicKey(ec, &p);
- break;
- case KEYID_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 || !hasher->allocate_hash(hasher, key, fp))
- {
- DBG1(DBG_LIB, "SHA1 hash algorithm not supported, fingerprinting failed");
- DESTROY_IF(hasher);
- free(key.ptr);
- return FALSE;
- }
- hasher->destroy(hasher);
- free(key.ptr);
- lib->encoding->cache(lib->encoding, type, ec, *fp);
- return TRUE;
+ return EVP_PKEY_bits(this->key);
}
METHOD(public_key_t, get_fingerprint, bool,
private_openssl_ec_public_key_t *this, cred_encoding_type_t type,
chunk_t *fingerprint)
{
- return openssl_ec_fingerprint(this->ec, type, fingerprint);
+ return openssl_fingerprint(this->key, type, fingerprint);
}
METHOD(public_key_t, get_encoding, bool,
chunk_t *encoding)
{
bool success = TRUE;
- u_char *p;
- *encoding = chunk_alloc(i2d_EC_PUBKEY(this->ec, NULL));
- p = encoding->ptr;
- i2d_EC_PUBKEY(this->ec, &p);
+ *encoding = openssl_i2chunk(PUBKEY, this->key);
if (type != PUBKEY_SPKI_ASN1_DER)
{
{
if (ref_put(&this->ref))
{
- if (this->ec)
+ if (this->key)
{
- lib->encoding->clear_cache(lib->encoding, this->ec);
- EC_KEY_free(this->ec);
+ lib->encoding->clear_cache(lib->encoding, this->key);
+ EVP_PKEY_free(this->key);
}
free(this);
}
}
-/**
- * Generic private constructor
- */
-static private_openssl_ec_public_key_t *create_empty()
-{
- private_openssl_ec_public_key_t *this;
-
- INIT(this,
- .public = {
- .key = {
- .get_type = _get_type,
- .verify = _verify,
- .encrypt = _encrypt,
- .get_keysize = _get_keysize,
- .equals = public_key_equals,
- .get_fingerprint = _get_fingerprint,
- .has_fingerprint = public_key_has_fingerprint,
- .get_encoding = _get_encoding,
- .get_ref = _get_ref,
- .destroy = _destroy,
- },
- },
- .ref = 1,
- );
-
- return this;
-}
-
/**
* See header.
*/
{
private_openssl_ec_public_key_t *this;
chunk_t blob = chunk_empty;
-
- if (type != KEY_ECDSA)
- {
- return NULL;
- }
+ EVP_PKEY *key;
while (TRUE)
{
}
break;
}
- this = create_empty();
- this->ec = d2i_EC_PUBKEY(NULL, (const u_char**)&blob.ptr, blob.len);
- if (!this->ec)
+ key = d2i_PUBKEY(NULL, (const u_char**)&blob.ptr, blob.len);
+ if (!key || EVP_PKEY_base_id(key) != EVP_PKEY_EC)
{
- destroy(this);
+ EVP_PKEY_free(key);
return NULL;
}
+
+ INIT(this,
+ .public = {
+ .key = {
+ .get_type = _get_type,
+ .verify = _verify,
+ .encrypt = _encrypt,
+ .get_keysize = _get_keysize,
+ .equals = public_key_equals,
+ .get_fingerprint = _get_fingerprint,
+ .has_fingerprint = public_key_has_fingerprint,
+ .get_encoding = _get_encoding,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ },
+ .ref = 1,
+ .key = key,
+ );
return &this->public;
}
-#endif /* OPENSSL_NO_ECDSA */
+#endif /* OPENSSL_NO_ECDSA */
*/
bool openssl_rsa_fingerprint(EVP_PKEY *key, cred_encoding_type_t type, chunk_t *fp)
{
- hasher_t *hasher;
- chunk_t enc;
- u_char *p;
-
- if (lib->encoding->get_cache(lib->encoding, type, key, fp))
+ if (!openssl_fingerprint(key, type, fp))
{
- return TRUE;
- }
- switch (type)
- {
- case KEYID_PUBKEY_SHA1:
- enc = chunk_alloc(i2d_PublicKey(key, NULL));
- p = enc.ptr;
- i2d_PublicKey(key, &p);
- break;
- case KEYID_PUBKEY_INFO_SHA1:
- enc = chunk_alloc(i2d_PUBKEY(key, NULL));
- p = enc.ptr;
- i2d_PUBKEY(key, &p);
- break;
- default:
- {
- chunk_t n = chunk_empty, e = chunk_empty;
- bool success = FALSE;
+ chunk_t n = chunk_empty, e = chunk_empty;
+ bool success = FALSE;
- if (get_n_and_e(key, &n, &e))
- {
- success = lib->encoding->encode(lib->encoding, type, key, fp,
+ if (get_n_and_e(key, &n, &e))
+ {
+ success = lib->encoding->encode(lib->encoding, type, key, fp,
CRED_PART_RSA_MODULUS, n,
CRED_PART_RSA_PUB_EXP, e, CRED_PART_END);
- }
- chunk_free(&n);
- chunk_free(&e);
- return success;
}
+ chunk_free(&n);
+ chunk_free(&e);
+ return success;
}
- hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
- if (!hasher || !hasher->allocate_hash(hasher, enc, fp))
- {
- DBG1(DBG_LIB, "SHA1 hash algorithm not supported, fingerprinting failed");
- DESTROY_IF(hasher);
- free(enc.ptr);
- return FALSE;
- }
- free(enc.ptr);
- hasher->destroy(hasher);
- lib->encoding->cache(lib->encoding, type, key, *fp);
return TRUE;
}
return success;
}
+/*
+ * Described in header
+ */
+bool openssl_fingerprint(EVP_PKEY *key, cred_encoding_type_t type, chunk_t *fp)
+{
+ hasher_t *hasher;
+ chunk_t enc;
+ u_char *p;
+
+ if (lib->encoding->get_cache(lib->encoding, type, key, fp))
+ {
+ return TRUE;
+ }
+ switch (type)
+ {
+ case KEYID_PUBKEY_SHA1:
+ enc = chunk_alloc(i2d_PublicKey(key, NULL));
+ p = enc.ptr;
+ i2d_PublicKey(key, &p);
+ break;
+ case KEYID_PUBKEY_INFO_SHA1:
+ enc = chunk_alloc(i2d_PUBKEY(key, NULL));
+ p = enc.ptr;
+ i2d_PUBKEY(key, &p);
+ break;
+ default:
+ return FALSE;
+ }
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (!hasher || !hasher->allocate_hash(hasher, enc, fp))
+ {
+ DBG1(DBG_LIB, "SHA1 not supported, fingerprinting failed");
+ DESTROY_IF(hasher);
+ free(enc.ptr);
+ return FALSE;
+ }
+ free(enc.ptr);
+ hasher->destroy(hasher);
+ lib->encoding->cache(lib->encoding, type, key, *fp);
+ return TRUE;
+}
+
/**
* Described in header.
*/
*/
bool openssl_compute_shared_key(EVP_PKEY *priv, EVP_PKEY *pub, chunk_t *shared);
+/**
+ * Calculate a fingerprint from the given key (cached under it).
+ *
+ * @param key key object
+ * @param type encoding type
+ * @param fp allocated fingerprint
+ * @return TRUE on success, FALSE otherwise
+ */
+bool openssl_fingerprint(EVP_PKEY *key, cred_encoding_type_t type, chunk_t *fp);
+
/**
* Creates a hash of a given type of a chunk of data.
*