diff options
author | Tobias Brunner <tobias@strongswan.org> | 2011-11-02 19:04:43 +0100 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2011-11-02 20:27:55 +0100 |
commit | 9e3b1e14955a2e9a2b71eed1bcc9076ae7019279 (patch) | |
tree | bf8df8420d0e5c3b31d74730c003dd67162ea10c /src/libstrongswan | |
parent | 36d1627f6e43c9f4787907a58ab3e28ed323a6d5 (diff) | |
download | strongswan-9e3b1e14955a2e9a2b71eed1bcc9076ae7019279.tar.bz2 strongswan-9e3b1e14955a2e9a2b71eed1bcc9076ae7019279.tar.xz |
pkcs11: Added support to encode ECDSA public keys.
Diffstat (limited to 'src/libstrongswan')
-rw-r--r-- | src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c b/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c index d878c8f7a..8be4a2b2f 100644 --- a/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c @@ -286,6 +286,91 @@ METHOD(public_key_t, encrypt, bool, } /** + * Encode ECDSA key using a given encoding type + */ +static bool encode_ecdsa(private_pkcs11_public_key_t *this, + cred_encoding_type_t type, chunk_t *encoding) +{ + enumerator_t *enumerator; + bool success = FALSE; + CK_ATTRIBUTE attr[] = { + {CKA_EC_PARAMS, NULL, 0}, + {CKA_EC_POINT, NULL, 0}, + }; + + if (type != PUBKEY_SPKI_ASN1_DER && type != PUBKEY_PEM) + { + return FALSE; + } + + enumerator = this->lib->create_object_attr_enumerator(this->lib, + this->session, this->object, attr, countof(attr)); + if (enumerator && enumerator->enumerate(enumerator, NULL) && + attr[0].ulValueLen > 0 && attr[1].ulValueLen > 0) + { + chunk_t ecparams, ecpoint; + ecparams = chunk_create(attr[0].pValue, attr[0].ulValueLen); + ecpoint = chunk_create(attr[1].pValue, attr[1].ulValueLen); + /* encode as subjectPublicKeyInfo */ + *encoding = asn1_wrap(ASN1_SEQUENCE, "mm", + asn1_wrap(ASN1_SEQUENCE, "mc", + asn1_build_known_oid(OID_EC_PUBLICKEY), ecparams), + asn1_bitstring("c", ecpoint)); + success = TRUE; + if (type == PUBKEY_PEM) + { + chunk_t asn1 = *encoding; + success = lib->encoding->encode(lib->encoding, PUBKEY_PEM, + NULL, encoding, CRED_PART_ECDSA_PUB_ASN1_DER, + asn1, CRED_PART_END); + chunk_clear(&asn1); + } + } + DESTROY_IF(enumerator); + return success; +} + +/** + * Compute fingerprint of an ECDSA key + */ +static bool fingerprint_ecdsa(private_pkcs11_public_key_t *this, + cred_encoding_type_t type, chunk_t *fp) +{ + hasher_t *hasher; + chunk_t asn1; + + switch (type) + { + case KEYID_PUBKEY_SHA1: + if (!this->lib->get_ck_attribute(this->lib, this->session, + this->object, CKA_EC_POINT, &asn1)) + { + return FALSE; + } + break; + case KEYID_PUBKEY_INFO_SHA1: + if (!encode_ecdsa(this, PUBKEY_SPKI_ASN1_DER, &asn1)) + { + return FALSE; + } + break; + default: + return FALSE; + } + hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); + if (!hasher) + { + chunk_clear(&asn1); + return FALSE; + } + hasher->allocate_hash(hasher, asn1, fp); + hasher->destroy(hasher); + chunk_clear(&asn1); + lib->encoding->cache(lib->encoding, type, this, *fp); + return TRUE; +} + +/** * Encode RSA key using a given encoding type */ static bool encode_rsa(private_pkcs11_public_key_t *this, @@ -325,6 +410,8 @@ METHOD(public_key_t, get_encoding, bool, { case KEY_RSA: return encode_rsa(this, type, NULL, encoding); + case KEY_ECDSA: + return encode_ecdsa(this, type, encoding); default: return FALSE; } @@ -341,6 +428,8 @@ METHOD(public_key_t, get_fingerprint, bool, { case KEY_RSA: return encode_rsa(this, type, this, fp); + case KEY_ECDSA: + return fingerprint_ecdsa(this, type, fp); default: return FALSE; } |