diff options
author | Martin Willi <martin@strongswan.org> | 2009-08-27 17:36:17 +0200 |
---|---|---|
committer | Martin Willi <martin@strongswan.org> | 2009-08-27 17:37:42 +0200 |
commit | 472cb4ce77295feebc6deff49d863ea1917576cb (patch) | |
tree | 177a006d5652b3eee048500d83ba2526041886e7 /src/libstrongswan/plugins | |
parent | 78aa4ebd6296d8447914cdd0b9e53cc1f4343806 (diff) | |
download | strongswan-472cb4ce77295feebc6deff49d863ea1917576cb.tar.bz2 strongswan-472cb4ce77295feebc6deff49d863ea1917576cb.tar.xz |
distinguish between RFC 4754 (concatenated) and RFC 3279 (DER encoded) ECDSA signatures
Diffstat (limited to 'src/libstrongswan/plugins')
4 files changed, 130 insertions, 179 deletions
diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c index f333bd32d..576eaf5c5 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c @@ -43,153 +43,129 @@ struct private_openssl_ec_private_key_t { /** * reference count */ - refcount_t ref; + refcount_t ref; }; -/** - * Mapping from the signature scheme defined in (RFC 4754) to the elliptic - * curve and the hash algorithm - */ -typedef struct { - /** - * Scheme specified in RFC 4754 - */ - int scheme; - - /** - * NID of the hash - */ - int hash; - - /** - * NID of the curve - */ - int curve; -} openssl_ecdsa_scheme_t; - -#define END_OF_LIST -1 - -/** - * Signature schemes - */ -static openssl_ecdsa_scheme_t ecdsa_schemes[] = { - {SIGN_ECDSA_WITH_SHA1, NID_sha1, -1}, - {SIGN_ECDSA_256, NID_sha256, NID_X9_62_prime256v1}, - {SIGN_ECDSA_384, NID_sha384, NID_secp384r1}, - {SIGN_ECDSA_521, NID_sha512, NID_secp521r1}, - {END_OF_LIST, 0, 0}, -}; - -/** - * Look up the hash and curve of a signature scheme - */ -static bool lookup_scheme(int scheme, int *hash, int *curve) -{ - openssl_ecdsa_scheme_t *ecdsa_scheme = ecdsa_schemes; - while (ecdsa_scheme->scheme != END_OF_LIST) - { - if (scheme == ecdsa_scheme->scheme) - { - *hash = ecdsa_scheme->hash; - *curve = ecdsa_scheme->curve; - return TRUE; - } - ecdsa_scheme++; - } - 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. - */ -static bool sig2chunk(const EC_GROUP *group, ECDSA_SIG *sig, chunk_t *chunk) -{ - return openssl_bn_cat(EC_FIELD_ELEMENT_LEN(group), sig->r, sig->s, chunk); -} - -/** - * Build the signature + * Build a signature as in RFC 4754 */ static bool build_signature(private_openssl_ec_private_key_t *this, chunk_t hash, chunk_t *signature) { + bool built = FALSE; ECDSA_SIG *sig; - bool success; sig = ECDSA_do_sign(hash.ptr, hash.len, this->ec); - if (!sig) + if (sig) { - return FALSE; + /* concatenate BNs r/s to a signature chunk */ + built = openssl_bn_cat(EC_FIELD_ELEMENT_LEN(EC_KEY_get0_group(this->ec)), + sig->r, sig->s, signature); + ECDSA_SIG_free(sig); } - success = sig2chunk(EC_KEY_get0_group(this->ec), sig, signature); - ECDSA_SIG_free(sig); - return success; + return built; } /** - * Implementation of private_key_t.get_type. + * Build a RFC 4754 signature for a specified curve and hash algorithm */ -static key_type_t get_type(private_openssl_ec_private_key_t *this) +static bool build_curve_signature(private_openssl_ec_private_key_t *this, + signature_scheme_t scheme, int nid_hash, + int nid_curve, chunk_t data, chunk_t *signature) { - return KEY_ECDSA; + 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("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) + { + DBG1("signature scheme %N not supported by private 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, data, signature); + chunk_free(&hash); + return built; } /** - * Implementation of private_key_t.sign. + * Build a DER encoded signature as in RFC 3279 */ -static bool sign(private_openssl_ec_private_key_t *this, signature_scheme_t scheme, - chunk_t data, chunk_t *signature) +static bool build_der_signature(private_openssl_ec_private_key_t *this, + int hash_nid, chunk_t data, chunk_t *signature) { - bool success; + chunk_t hash, sig; + int siglen = 0; + bool built; - if (scheme == SIGN_ECDSA_WITH_NULL) + if (!openssl_hash_chunk(hash_nid, data, &hash)) { - success = build_signature(this, data, signature); + 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 { - EC_GROUP *req_group; - const EC_GROUP *my_group; - chunk_t hash = chunk_empty; - int hash_type, curve; - - if (!lookup_scheme(scheme, &hash_type, &curve)) - { - DBG1("signature scheme %N not supported in EC", - signature_scheme_names, scheme); - return FALSE; - } - - if (curve != -1) - { - req_group = EC_GROUP_new_by_curve_name(curve); - if (!req_group) - { - DBG1("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) - { - DBG1("signature scheme %N not supported by private key", - signature_scheme_names, scheme); - return FALSE; - } - EC_GROUP_free(req_group); - } - if (!openssl_hash_chunk(hash_type, data, &hash)) - { + free(sig.ptr); + } + free(hash.ptr); + return built; +} + +/** + * Implementation of private_key_t.sign. + */ +static bool sign(private_openssl_ec_private_key_t *this, + signature_scheme_t scheme, chunk_t data, chunk_t *signature) +{ + switch (scheme) + { + case SIGN_ECDSA_WITH_NULL: + return build_signature(this, data, signature); + case SIGN_ECDSA_WITH_SHA1_DER: + return build_der_signature(this, NID_sha1, data, signature); + case SIGN_ECDSA_WITH_SHA256_DER: + return build_der_signature(this, NID_sha256, data, signature); + case SIGN_ECDSA_WITH_SHA384_DER: + return build_der_signature(this, NID_sha384, data, signature); + case SIGN_ECDSA_WITH_SHA512_DER: + return build_der_signature(this, NID_sha512, data, signature); + case SIGN_ECDSA_256: + return build_curve_signature(this, scheme, NID_X9_62_prime256v1, + NID_sha256, data, signature); + case SIGN_ECDSA_384: + return build_curve_signature(this, scheme, NID_secp384r1, + NID_sha384, data, signature); + case SIGN_ECDSA_521: + return build_curve_signature(this, scheme, NID_secp521r1, + NID_sha512, data, signature); + default: + DBG1("signature scheme %N not supported", + signature_scheme_names, scheme); return FALSE; - } - success = build_signature(this, hash, signature); - chunk_free(&hash); - } - return success; + } } /** @@ -211,6 +187,14 @@ static size_t get_keysize(private_openssl_ec_private_key_t *this) } /** + * Implementation of private_key_t.get_type. + */ +static key_type_t get_type(private_openssl_ec_private_key_t *this) +{ + return KEY_ECDSA; +} + +/** * Implementation of private_key_t.get_public_key. */ static public_key_t* get_public_key(private_openssl_ec_private_key_t *this) diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c index d1b3a4e39..b351067de 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c @@ -46,51 +46,31 @@ struct private_openssl_ec_public_key_t { }; /** - * Convert a chunk to an ECDSA_SIG (which must already exist). r and s - * of the signature have to be concatenated in the chunk. - */ -static bool chunk2sig(const EC_GROUP *group, chunk_t chunk, ECDSA_SIG *sig) -{ - return openssl_bn_split(chunk, sig->r, sig->s); -} - -/** * Verification of a signature as in RFC 4754 */ static bool verify_signature(private_openssl_ec_public_key_t *this, - int hash_type, chunk_t data, chunk_t signature) + int hash_type, chunk_t data, chunk_t signature) { - chunk_t hash = chunk_empty; - ECDSA_SIG *sig; bool valid = FALSE; + ECDSA_SIG *sig; + chunk_t hash; - if (hash_type == NID_undef) - { - hash = data; - } - else + hash = data; + if (hash_type != NID_undef) { if (!openssl_hash_chunk(hash_type, data, &hash)) { return FALSE; } } - sig = ECDSA_SIG_new(); - if (!sig) - { - goto error; - } - - if (!chunk2sig(EC_KEY_get0_group(this->ec), signature, sig)) - { - goto error; - } - valid = (ECDSA_do_verify(hash.ptr, hash.len, sig, this->ec) == 1); - -error: if (sig) { + /* split the signature chunk in r and s */ + if (openssl_bn_split(signature, sig->r, sig->s)) + { + valid = (ECDSA_do_verify(hash.ptr, hash.len, sig, this->ec) == 1); + } ECDSA_SIG_free(sig); } if (hash_type != NID_undef) @@ -100,45 +80,26 @@ error: return valid; } - /** - * Verification of the default signature using SHA-1 + * Verification of a DER encoded signature as in RFC 3279 */ -static bool verify_default_signature(private_openssl_ec_public_key_t *this, - chunk_t data, chunk_t signature) +static bool verify_der_signature(private_openssl_ec_public_key_t *this, + int nid, chunk_t data, chunk_t signature) { + chunk_t hash; bool valid = FALSE; - chunk_t hash = chunk_empty; - u_char *p; - ECDSA_SIG *sig; /* remove any preceding 0-bytes from signature */ - while (signature.len && *(signature.ptr) == 0x00) - { - signature.len -= 1; - signature.ptr++; - } - - p = signature.ptr; - sig = d2i_ECDSA_SIG(NULL, (const u_char**)&p, signature.len); - if (!sig) + while (signature.len && signature.ptr[0] == 0x00) { - return FALSE; - } - - if (!openssl_hash_chunk(NID_sha1, data, &hash)) - { - goto error; + signature = chunk_skip(signature, 1); } - - valid = (ECDSA_do_verify(hash.ptr, hash.len, sig, this->ec) == 1); - -error: - if (sig) + if (openssl_hash_chunk(nid, data, &hash)) { - ECDSA_SIG_free(sig); + valid = ECDSA_verify(0, hash.ptr, hash.len, + signature.ptr, signature.len, this->ec); + free(hash.ptr); } - chunk_free(&hash); return valid; } @@ -158,10 +119,16 @@ static bool verify(private_openssl_ec_public_key_t *this, signature_scheme_t sch { switch (scheme) { + case SIGN_ECDSA_WITH_SHA1_DER: + return verify_der_signature(this, NID_sha1, data, signature); + case SIGN_ECDSA_WITH_SHA256_DER: + return verify_der_signature(this, NID_sha256, data, signature); + case SIGN_ECDSA_WITH_SHA384_DER: + return verify_der_signature(this, NID_sha384, data, signature); + case SIGN_ECDSA_WITH_SHA512_DER: + return verify_der_signature(this, NID_sha512, data, signature); case SIGN_ECDSA_WITH_NULL: return verify_signature(this, NID_undef, data, signature); - case SIGN_ECDSA_WITH_SHA1: - return verify_default_signature(this, data, signature); case SIGN_ECDSA_256: return verify_signature(this, NID_sha256, data, signature); case SIGN_ECDSA_384: diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c index 8a68e9df0..c8d0dabc0 100644 --- a/src/libstrongswan/plugins/x509/x509_cert.c +++ b/src/libstrongswan/plugins/x509/x509_cert.c @@ -1249,7 +1249,7 @@ static bool generate(private_builder_t *this) scheme = SIGN_RSA_EMSA_PKCS1_SHA1; break; case KEY_ECDSA: - scheme = SIGN_ECDSA_WITH_SHA1; + scheme = SIGN_ECDSA_WITH_SHA1_DER; this->cert->algorithm = OID_ECDSA_WITH_SHA1; break; default: diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_request.c b/src/libstrongswan/plugins/x509/x509_ocsp_request.c index f65fa6d12..e772b9720 100644 --- a/src/libstrongswan/plugins/x509/x509_ocsp_request.c +++ b/src/libstrongswan/plugins/x509/x509_ocsp_request.c @@ -266,7 +266,7 @@ static chunk_t build_optionalSignature(private_x509_ocsp_request_t *this, break; case KEY_ECDSA: oid = OID_ECDSA_WITH_SHA1; - scheme = SIGN_ECDSA_WITH_SHA1; + scheme = SIGN_ECDSA_WITH_SHA1_DER; break; default: DBG1("unable to sign OCSP request, %N signature not supported", |