Commit 93a77f9e authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Add function tls_choose_sigalg().



New function tls_choose_sigalg(). This is a signature algorithm version
of ssl3_choose_cipher(): it picks and sets the appropriate signature
algorithm and certificate based on shared signature algorithms.

Reviewed-by: default avatarRich Salz <rsalz@openssl.org>
Reviewed-by: default avatarMatt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2339)
parent 3f4bf115
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -1287,6 +1287,10 @@ typedef struct ssl3_state_st {
        unsigned char *psk;
        size_t psklen;
# endif
        /* Signature algorithm we actually use */
        const SIGALG_LOOKUP *sigalg;
        /* Index of certificate we use */
        int cert_idx;
        /*
         * signature algorithms peer reports: e.g. supported signature
         * algorithms extension for server or as part of a certificate
@@ -2257,6 +2261,8 @@ __owur int ssl_security_cert(SSL *s, SSL_CTX *ctx, X509 *x, int vfy, int is_ee);
__owur int ssl_security_cert_chain(SSL *s, STACK_OF(X509) *sk, X509 *ex,
                                   int vfy);

int tls_choose_sigalg(SSL *s);

__owur EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash, const EVP_MD *md);
void ssl_clear_hash_ctx(EVP_MD_CTX **hash);
__owur long ssl_get_algorithm2(SSL *s);
+57 −0
Original line number Diff line number Diff line
@@ -2270,3 +2270,60 @@ int ssl_security_cert_chain(SSL *s, STACK_OF(X509) *sk, X509 *x, int vfy)
    }
    return 1;
}

/*
 * Choose an appropriate signature algorithm based on available certificates
 * Set current certificate and digest to match chosen algorithm.
 */
int tls_choose_sigalg(SSL *s)
{
    if (SSL_IS_TLS13(s)) {
        size_t i;
        int curve = -1;

        /* Look for a certificate matching shared sigaglgs */
        for (i = 0; i < s->cert->shared_sigalgslen; i++) {
            const SIGALG_LOOKUP *lu = s->cert->shared_sigalgs[i];
            int idx;
            const EVP_MD *md;
            CERT_PKEY *c;

            /* Skip RSA if not PSS */
            if (lu->sig == EVP_PKEY_RSA)
                continue;
            md = ssl_md(lu->hash_idx);
            if (md == NULL)
                continue;
            idx = lu->sig_idx;
            c = &s->cert->pkeys[idx];
            if (c->x509 == NULL || c->privatekey == NULL) {
                if (idx != SSL_PKEY_RSA_SIGN)
                    continue;
                idx = SSL_PKEY_RSA_ENC;
                c = s->cert->pkeys + idx;
                if (c->x509 == NULL || c->privatekey == NULL)
                    continue;
            }
            if (lu->sig == EVP_PKEY_EC) {
                if (curve == -1) {
                    EC_KEY *ec = EVP_PKEY_get0_EC_KEY(c->privatekey);

                    curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
                }
                if (curve != lu->curve)
                    continue;
            }
            s->s3->tmp.sigalg = lu;
            s->s3->tmp.cert_idx = idx;
            s->s3->tmp.md[idx] = md;
            s->cert->key = s->cert->pkeys + idx;
            return 1;
        }
        return 0;
    }
    /*
     * FIXME: could handle previous TLS versions in an appropriate way
     * and tidy up certificate and signature algorithm handling.
     */
    return 1;
}