openssl: Add support for signature schemes with parameters

This commit is contained in:
Tobias Brunner
2017-11-08 16:48:10 +01:00
parent dc83bc147e
commit fb63012e0c
2 changed files with 34 additions and 47 deletions
+11 -29
View File
@@ -57,7 +57,6 @@ static inline void X509_CRL_get0_signature(const X509_CRL *crl, ASN1_BIT_STRING
#define X509_REVOKED_get0_serialNumber(r) ({ (r)->serialNumber; }) #define X509_REVOKED_get0_serialNumber(r) ({ (r)->serialNumber; })
#define X509_REVOKED_get0_revocationDate(r) ({ (r)->revocationDate; }) #define X509_REVOKED_get0_revocationDate(r) ({ (r)->revocationDate; })
#define X509_CRL_get0_extensions(c) ({ (c)->crl->extensions; }) #define X509_CRL_get0_extensions(c) ({ (c)->crl->extensions; })
#define X509_ALGOR_get0(oid, ppt, ppv, alg) ({ *(oid) = (alg)->algorithm; })
#endif #endif
typedef struct private_openssl_crl_t private_openssl_crl_t; typedef struct private_openssl_crl_t private_openssl_crl_t;
@@ -120,7 +119,7 @@ struct private_openssl_crl_t {
/** /**
* Signature scheme used in this CRL * Signature scheme used in this CRL
*/ */
signature_scheme_t scheme; signature_params_t *scheme;
/** /**
* References to this CRL * References to this CRL
@@ -321,10 +320,6 @@ METHOD(certificate_t, issued_by, bool,
return FALSE; return FALSE;
} }
} }
if (this->scheme == SIGN_UNKNOWN)
{
return FALSE;
}
/* i2d_re_X509_CRL_tbs() was added with 1.1.0 when X509_CRL became opaque */ /* i2d_re_X509_CRL_tbs() was added with 1.1.0 when X509_CRL became opaque */
#if OPENSSL_VERSION_NUMBER >= 0x10100000L #if OPENSSL_VERSION_NUMBER >= 0x10100000L
tbs = openssl_i2chunk(re_X509_CRL_tbs, this->crl); tbs = openssl_i2chunk(re_X509_CRL_tbs, this->crl);
@@ -332,15 +327,13 @@ METHOD(certificate_t, issued_by, bool,
tbs = openssl_i2chunk(X509_CRL_INFO, this->crl->crl); tbs = openssl_i2chunk(X509_CRL_INFO, this->crl->crl);
#endif #endif
X509_CRL_get0_signature(this->crl, &sig, NULL); X509_CRL_get0_signature(this->crl, &sig, NULL);
valid = key->verify(key, this->scheme, NULL, tbs, valid = key->verify(key, this->scheme->scheme, this->scheme->params, tbs,
openssl_asn1_str2chunk(sig)); openssl_asn1_str2chunk(sig));
free(tbs.ptr); free(tbs.ptr);
key->destroy(key); key->destroy(key);
if (valid && scheme) if (valid && scheme)
{ {
INIT(*scheme, *scheme = signature_params_clone(this->scheme);
.scheme = this->scheme,
);
} }
return valid; return valid;
} }
@@ -420,6 +413,7 @@ METHOD(certificate_t, destroy, void,
{ {
X509_CRL_free(this->crl); X509_CRL_free(this->crl);
} }
signature_params_destroy(this->scheme);
this->crl_uris->destroy_function(this->crl_uris, this->crl_uris->destroy_function(this->crl_uris,
(void*)x509_cdp_destroy); (void*)x509_cdp_destroy);
DESTROY_IF(this->issuer); DESTROY_IF(this->issuer);
@@ -569,7 +563,7 @@ static bool parse_extensions(private_openssl_crl_t *this)
static bool parse_crl(private_openssl_crl_t *this) static bool parse_crl(private_openssl_crl_t *this)
{ {
const unsigned char *ptr = this->encoding.ptr; const unsigned char *ptr = this->encoding.ptr;
ASN1_OBJECT *oid; chunk_t sig_scheme;
X509_ALGOR *alg; X509_ALGOR *alg;
this->crl = d2i_X509_CRL(NULL, &ptr, this->encoding.len); this->crl = d2i_X509_CRL(NULL, &ptr, this->encoding.len);
@@ -579,27 +573,15 @@ static bool parse_crl(private_openssl_crl_t *this)
} }
X509_CRL_get0_signature(this->crl, NULL, &alg); X509_CRL_get0_signature(this->crl, NULL, &alg);
X509_ALGOR_get0(&oid, NULL, NULL, alg); sig_scheme = openssl_i2chunk(X509_ALGOR, alg);
#if OPENSSL_VERSION_NUMBER < 0x10100000L INIT(this->scheme);
if (!chunk_equals( if (!signature_params_parse(sig_scheme, 0, this->scheme))
openssl_asn1_obj2chunk(this->crl->crl->sig_alg->algorithm),
openssl_asn1_obj2chunk(this->crl->sig_alg->algorithm)))
{ {
DBG1(DBG_ASN, "unable to parse signature algorithm");
free(sig_scheme.ptr);
return FALSE; return FALSE;
} }
#elif 0 free(sig_scheme.ptr);
/* FIXME: we currently can't do this if X509_CRL is opaque (>= 1.1.0) as
* X509_CRL_get0_tbs_sigalg() does not exist and there does not seem to be
* another easy way to get the algorithm from the tbsCertList of the CRL */
alg = X509_CRL_get0_tbs_sigalg(this->crl);
X509_ALGOR_get0(&oid_tbs, NULL, NULL, alg);
if (!chunk_equals(openssl_asn1_obj2chunk(oid),
openssl_asn1_obj2chunk(oid_tbs)))
{
return FALSE;
}
#endif
this->scheme = signature_scheme_from_oid(openssl_asn1_known_oid(oid));
this->issuer = openssl_x509_name2id(X509_CRL_get_issuer(this->crl)); this->issuer = openssl_x509_name2id(X509_CRL_get_issuer(this->crl));
if (!this->issuer) if (!this->issuer)
@@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2011 Tobias Brunner * Copyright (C) 2011-2017 Tobias Brunner
* Hochschule fuer Technik Rapperswil * HSR Hochschule fuer Technik Rapperswil
* *
* Copyright (C) 2010 Martin Willi * Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG * Copyright (C) 2010 revosec AG
@@ -154,7 +154,7 @@ struct private_openssl_x509_t {
/** /**
* Signature scheme of the certificate * Signature scheme of the certificate
*/ */
signature_scheme_t scheme; signature_params_t *scheme;
/** /**
* subjectAltNames * subjectAltNames
@@ -392,10 +392,6 @@ METHOD(certificate_t, issued_by, bool,
ASN1_BIT_STRING *sig; ASN1_BIT_STRING *sig;
chunk_t tbs; chunk_t tbs;
if (this->scheme == SIGN_UNKNOWN)
{
return FALSE;
}
if (&this->public.x509.interface == issuer) if (&this->public.x509.interface == issuer)
{ {
if (this->flags & X509_SELF_SIGNED) if (this->flags & X509_SELF_SIGNED)
@@ -431,7 +427,7 @@ METHOD(certificate_t, issued_by, bool,
tbs = openssl_i2chunk(X509_CINF, this->x509->cert_info); tbs = openssl_i2chunk(X509_CINF, this->x509->cert_info);
#endif #endif
X509_get0_signature(&sig, NULL, this->x509); X509_get0_signature(&sig, NULL, this->x509);
valid = key->verify(key, this->scheme, NULL, tbs, valid = key->verify(key, this->scheme->scheme, this->scheme->params, tbs,
openssl_asn1_str2chunk(sig)); openssl_asn1_str2chunk(sig));
free(tbs.ptr); free(tbs.ptr);
key->destroy(key); key->destroy(key);
@@ -439,9 +435,7 @@ METHOD(certificate_t, issued_by, bool,
out: out:
if (valid && scheme) if (valid && scheme)
{ {
INIT(*scheme, *scheme = signature_params_clone(this->scheme);
.scheme = this->scheme,
);
} }
return valid; return valid;
} }
@@ -534,6 +528,7 @@ METHOD(certificate_t, destroy, void,
{ {
X509_free(this->x509); X509_free(this->x509);
} }
signature_params_destroy(this->scheme);
DESTROY_IF(this->subject); DESTROY_IF(this->subject);
DESTROY_IF(this->issuer); DESTROY_IF(this->issuer);
DESTROY_IF(this->pubkey); DESTROY_IF(this->pubkey);
@@ -1069,8 +1064,8 @@ static bool parse_certificate(private_openssl_x509_t *this)
{ {
const unsigned char *ptr = this->encoding.ptr; const unsigned char *ptr = this->encoding.ptr;
hasher_t *hasher; hasher_t *hasher;
chunk_t chunk; chunk_t chunk, sig_scheme, sig_scheme_tbs;
ASN1_OBJECT *oid, *oid_tbs; ASN1_OBJECT *oid;
X509_ALGOR *alg; X509_ALGOR *alg;
this->x509 = d2i_X509(NULL, &ptr, this->encoding.len); this->x509 = d2i_X509(NULL, &ptr, this->encoding.len);
@@ -1125,15 +1120,25 @@ static bool parse_certificate(private_openssl_x509_t *this)
/* while X509_ALGOR_cmp() is declared in the headers of older OpenSSL /* while X509_ALGOR_cmp() is declared in the headers of older OpenSSL
* versions, at least on Ubuntu 14.04 it is not actually defined */ * versions, at least on Ubuntu 14.04 it is not actually defined */
X509_get0_signature(NULL, &alg, this->x509); X509_get0_signature(NULL, &alg, this->x509);
X509_ALGOR_get0(&oid, NULL, NULL, alg); sig_scheme = openssl_i2chunk(X509_ALGOR, alg);
alg = X509_get0_tbs_sigalg(this->x509); alg = X509_get0_tbs_sigalg(this->x509);
X509_ALGOR_get0(&oid_tbs, NULL, NULL, alg); sig_scheme_tbs = openssl_i2chunk(X509_ALGOR, alg);
if (!chunk_equals(openssl_asn1_obj2chunk(oid), if (!chunk_equals(sig_scheme, sig_scheme_tbs))
openssl_asn1_obj2chunk(oid_tbs)))
{ {
free(sig_scheme_tbs.ptr);
free(sig_scheme.ptr);
return FALSE; return FALSE;
} }
this->scheme = signature_scheme_from_oid(openssl_asn1_known_oid(oid)); free(sig_scheme_tbs.ptr);
INIT(this->scheme);
if (!signature_params_parse(sig_scheme, 0, this->scheme))
{
DBG1(DBG_ASN, "unable to parse signature algorithm");
free(sig_scheme.ptr);
return FALSE;
}
free(sig_scheme.ptr);
if (!parse_extensions(this)) if (!parse_extensions(this))
{ {