diff options
Diffstat (limited to 'src/libstrongswan/plugins/x509/x509_ac.c')
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_ac.c | 91 |
1 files changed, 61 insertions, 30 deletions
diff --git a/src/libstrongswan/plugins/x509/x509_ac.c b/src/libstrongswan/plugins/x509/x509_ac.c index c0a64fc5d..8e2b4c1e3 100644 --- a/src/libstrongswan/plugins/x509/x509_ac.c +++ b/src/libstrongswan/plugins/x509/x509_ac.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2017 Tobias Brunner * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler * Copyright (C) 2003 Martin Berner, Lukas Suter * Copyright (C) 2002-2017 Andreas Steffen @@ -116,9 +117,9 @@ struct private_x509_ac_t { bool noRevAvail; /** - * Signature algorithm + * Signature scheme */ - int algorithm; + signature_params_t *scheme; /** * Signature @@ -425,7 +426,7 @@ static bool parse_certificate(private_x509_ac_t *this) int objectID; int type = OID_UNKNOWN; int extn_oid = OID_UNKNOWN; - int sig_alg = OID_UNKNOWN; + signature_params_t sig_alg; bool success = FALSE; bool critical; @@ -476,7 +477,11 @@ static bool parse_certificate(private_x509_ac_t *this) } break; case AC_OBJ_SIG_ALG: - sig_alg = asn1_parse_algorithmIdentifier(object, level, NULL); + if (!signature_params_parse(object, level, &sig_alg)) + { + DBG1(DBG_ASN, " unable to parse signature algorithm"); + goto end; + } break; case AC_OBJ_SERIAL_NUMBER: this->serialNumber = chunk_clone(object); @@ -550,12 +555,15 @@ static bool parse_certificate(private_x509_ac_t *this) break; } case AC_OBJ_ALGORITHM: - this->algorithm = asn1_parse_algorithmIdentifier(object, level, - NULL); - if (this->algorithm != sig_alg) + INIT(this->scheme); + if (!signature_params_parse(object, level, this->scheme)) + { + DBG1(DBG_ASN, " unable to parse signature algorithm"); + goto end; + } + if (!signature_params_equal(this->scheme, &sig_alg)) { DBG1(DBG_ASN, " signature algorithms do not agree"); - success = FALSE; goto end; } break; @@ -570,6 +578,7 @@ static bool parse_certificate(private_x509_ac_t *this) end: parser->destroy(parser); + signature_params_clear(&sig_alg); return success; } @@ -742,13 +751,13 @@ static chunk_t build_extensions(private_x509_ac_t *this) /** * build attributeCertificateInfo */ -static chunk_t build_attr_cert_info(private_x509_ac_t *this) +static chunk_t build_attr_cert_info(private_x509_ac_t *this, chunk_t sig_scheme) { - return asn1_wrap(ASN1_SEQUENCE, "cmmmmmmm", + return asn1_wrap(ASN1_SEQUENCE, "cmmcmmmm", ASN1_INTEGER_1, build_holder(this), build_v2_form(this), - asn1_algorithmIdentifier(OID_SHA1_WITH_RSA), + sig_scheme, asn1_simple_object(ASN1_INTEGER, this->serialNumber), build_attr_cert_validity(this), build_attributes(this), @@ -758,20 +767,39 @@ static chunk_t build_attr_cert_info(private_x509_ac_t *this) /** * build an X.509 attribute certificate */ -static bool build_ac(private_x509_ac_t *this) +static bool build_ac(private_x509_ac_t *this, hash_algorithm_t digest_alg) { - chunk_t signatureValue, attributeCertificateInfo; + chunk_t signatureValue, attributeCertificateInfo, sig_scheme; + private_key_t *key = this->signerKey; + + if (!this->scheme) + { + INIT(this->scheme, + .scheme = signature_scheme_from_oid( + hasher_signature_algorithm_to_oid(digest_alg, + key->get_type(key))), + ); + } + if (this->scheme->scheme == SIGN_UNKNOWN) + { + return FALSE; + } + if (!signature_params_build(this->scheme, &sig_scheme)) + { + return FALSE; + } - attributeCertificateInfo = build_attr_cert_info(this); - if (!this->signerKey->sign(this->signerKey, SIGN_RSA_EMSA_PKCS1_SHA1, NULL, - attributeCertificateInfo, &signatureValue)) + attributeCertificateInfo = build_attr_cert_info(this, sig_scheme); + if (!key->sign(key, this->scheme->scheme, this->scheme->params, + attributeCertificateInfo, &signatureValue)) { free(attributeCertificateInfo.ptr); + free(sig_scheme.ptr); return FALSE; } this->encoding = asn1_wrap(ASN1_SEQUENCE, "mmm", attributeCertificateInfo, - asn1_algorithmIdentifier(OID_SHA1_WITH_RSA), + sig_scheme, asn1_bitstring("m", signatureValue)); return TRUE; } @@ -887,10 +915,9 @@ METHOD(certificate_t, has_issuer, id_match_t, METHOD(certificate_t, issued_by, bool, private_x509_ac_t *this, certificate_t *issuer, - signature_params_t **schemep) + signature_params_t **scheme) { public_key_t *key; - signature_scheme_t scheme; bool valid; x509_t *x509 = (x509_t*)issuer; @@ -927,21 +954,16 @@ METHOD(certificate_t, issued_by, bool, } } - /* determine signature scheme */ - scheme = signature_scheme_from_oid(this->algorithm); - - if (scheme == SIGN_UNKNOWN || key == NULL) + if (!key) { return FALSE; } - valid = key->verify(key, scheme, NULL, this->certificateInfo, - this->signature); + valid = key->verify(key, this->scheme->scheme, this->scheme->params, + this->certificateInfo, this->signature); key->destroy(key); - if (valid && schemep) + if (valid && scheme) { - INIT(*schemep, - .scheme = scheme, - ); + *scheme = signature_params_clone(this->scheme); } return valid; } @@ -1024,6 +1046,7 @@ METHOD(certificate_t, destroy, void, DESTROY_IF(this->signerCert); DESTROY_IF(this->signerKey); this->groups->destroy_function(this->groups, (void*)group_destroy); + signature_params_destroy(this->scheme); free(this->serialNumber.ptr); free(this->authKeyIdentifier.ptr); free(this->encoding.ptr); @@ -1130,6 +1153,7 @@ static void add_groups_from_list(private_x509_ac_t *this, linked_list_t *list) */ x509_ac_t *x509_ac_gen(certificate_type_t type, va_list args) { + hash_algorithm_t digest_alg = HASH_SHA1; private_x509_ac_t *ac; ac = create_empty(); @@ -1161,6 +1185,13 @@ x509_ac_t *x509_ac_gen(certificate_type_t type, va_list args) ac->signerKey = va_arg(args, private_key_t*); ac->signerKey->get_ref(ac->signerKey); continue; + case BUILD_SIGNATURE_SCHEME: + ac->scheme = va_arg(args, signature_params_t*); + ac->scheme = signature_params_clone(ac->scheme); + continue; + case BUILD_DIGEST_ALG: + digest_alg = va_arg(args, int); + continue; case BUILD_END: break; default: @@ -1174,7 +1205,7 @@ x509_ac_t *x509_ac_gen(certificate_type_t type, va_list args) ac->holderCert->get_type(ac->holderCert) == CERT_X509 && ac->signerCert->get_type(ac->signerCert) == CERT_X509) { - if (build_ac(ac)) + if (build_ac(ac, digest_alg)) { return &ac->public; } |