x509: Add support for signature schemes with parameters
Also adds support for specifying the hash algorithm for attribute certificate signatures.
This commit is contained in:
@@ -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;
|
||||
|
||||
attributeCertificateInfo = build_attr_cert_info(this);
|
||||
if (!this->signerKey->sign(this->signerKey, SIGN_RSA_EMSA_PKCS1_SHA1, NULL,
|
||||
attributeCertificateInfo, &signatureValue))
|
||||
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, 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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user