Commit 786dd2c2 authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Add support for custom signature parameters



Many signature types define the digest and public key type by a single OID
such as ecdsa_with_sha256.

Some types (RSA-PSS for example) use a single OID to indicate the signature
scheme and additional parameters are encoded in the AlgorithmIdentifier.

Add an X509_SIG_INFO structure to contain details about the signature type:
specifically the digest algorithm, public key algorithm, security bits and
various flags. This supports both existing algorithms and more complex
types.

Add accessors for the structure and a special case that retrieves signature
information from a certificate.

Reviewed-by: default avatarRichard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3301)
parent 7531b3a6
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -52,6 +52,8 @@ struct evp_pkey_asn1_method_st {
    int (*item_sign) (EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
                      X509_ALGOR *alg1, X509_ALGOR *alg2,
                      ASN1_BIT_STRING *sig);
    int (*siginf_set) (X509_SIG_INFO *siginf, const X509_ALGOR *alg,
                       const ASN1_STRING *sig);
} /* EVP_PKEY_ASN1_METHOD */ ;

DEFINE_STACK_OF_CONST(EVP_PKEY_ASN1_METHOD)
+16 −0
Original line number Diff line number Diff line
@@ -37,6 +37,19 @@ struct X509_name_st {
    int canon_enclen;
} /* X509_NAME */ ;

/* Signature info structure */

struct x509_sig_info_st {
    /* NID of message digest */
    int mdnid;
    /* NID of public key algorithm */
    int pknid;
    /* Security bits */
    int secbits;
    /* Various flags */
    uint32_t flags;
};

/* PKCS#10 certificate request */

struct X509_req_info_st {
@@ -146,6 +159,7 @@ struct x509_st {
    X509_CINF cert_info;
    X509_ALGOR sig_alg;
    ASN1_BIT_STRING signature;
    X509_SIG_INFO siginf;
    CRYPTO_REF_COUNT references;
    CRYPTO_EX_DATA ex_data;
    /* These contain copies of various extension values */
@@ -267,3 +281,5 @@ struct x509_object_st {

int a2i_ipadd(unsigned char *ipout, const char *ipasc);
int x509_set1_time(ASN1_TIME **ptm, const ASN1_TIME *tm);

void x509_init_sig_info(X509 *x);
+3 −0
Original line number Diff line number Diff line
@@ -142,3 +142,6 @@ DEFINE_STACK_OF(BY_DIR_HASH)
DEFINE_STACK_OF(BY_DIR_ENTRY)
typedef STACK_OF(X509_NAME_ENTRY) STACK_OF_X509_NAME_ENTRY;
DEFINE_STACK_OF(STACK_OF_X509_NAME_ENTRY)

void x509_set_signature_info(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
                             const ASN1_STRING *sig);
+77 −0
Original line number Diff line number Diff line
@@ -13,7 +13,10 @@
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "internal/asn1_int.h"
#include "internal/x509_int.h"
#include "x509_lcl.h"

int X509_set_version(X509 *x, long version)
{
@@ -157,3 +160,77 @@ const X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x)
{
    return &x->cert_info.signature;
}

int X509_SIG_INFO_get(const X509_SIG_INFO *siginf, int *mdnid, int *pknid,
                      int *secbits, uint32_t *flags)
{
    if (mdnid != NULL)
        *mdnid = siginf->mdnid;
    if (pknid != NULL)
        *pknid = siginf->pknid;
    if (secbits != NULL)
        *secbits = siginf->secbits;
    if (flags != NULL)
        *flags = siginf->flags;
    return (siginf->flags & X509_SIG_INFO_VALID) != 0;
}

void X509_SIG_INFO_set(X509_SIG_INFO *siginf, int mdnid, int pknid,
                       int secbits, uint32_t flags)
{
    siginf->mdnid = mdnid;
    siginf->pknid = pknid;
    siginf->secbits = secbits;
    siginf->flags = flags;
}

int X509_get_signature_info(X509 *x, int *mdnid, int *pknid, int *secbits,
                            uint32_t *flags)
{
    X509_check_purpose(x, -1, -1);
    return X509_SIG_INFO_get(&x->siginf, mdnid, pknid, secbits, flags);
}

static void x509_sig_info_init(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
                               const ASN1_STRING *sig)
{
    int pknid, mdnid;
    const EVP_MD *md;

    siginf->mdnid = NID_undef;
    siginf->pknid = NID_undef;
    siginf->secbits = -1;
    siginf->flags = 0;
    if (!OBJ_find_sigid_algs(OBJ_obj2nid(alg->algorithm), &mdnid, &pknid)
            || pknid == NID_undef)
        return;
    siginf->pknid = pknid;
    if (mdnid == NID_undef) {
        /* If we have one, use a custom handler for this algorithm */
        const EVP_PKEY_ASN1_METHOD *ameth = EVP_PKEY_asn1_find(NULL, pknid);
        if (ameth == NULL || ameth->siginf_set == NULL
                || ameth->siginf_set(siginf, alg, sig) == 0)
            return;
        siginf->flags |= X509_SIG_INFO_VALID;
        return;
    }
    siginf->flags |= X509_SIG_INFO_VALID;
    siginf->mdnid = mdnid;
    md = EVP_get_digestbynid(mdnid);
    if (md == NULL)
        return;
    /* Security bits: half number of bits in digest */
    siginf->secbits = EVP_MD_size(md) * 4;
    switch (mdnid) {
        case NID_sha1:
        case NID_sha256:
        case NID_sha384:
        case NID_sha512:
        siginf->flags |= X509_SIG_INFO_TLS;
    }
}

void x509_init_sig_info(X509 *x)
{
    x509_sig_info_init(&x->siginf, &x->sig_alg, &x->signature);
}
+1 −0
Original line number Diff line number Diff line
@@ -488,6 +488,7 @@ static void x509v3_cache_extensions(X509 *x)
            break;
        }
    }
    x509_init_sig_info(x);
    x->ex_flags |= EXFLAG_SET;
}

Loading