summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenny Root <kroot@google.com>2013-06-24 12:03:19 -0700
committerKenny Root <kroot@google.com>2013-06-26 08:48:28 -0700
commit9296b4bb0e04a10b561da2996d3c9575872f1fa4 (patch)
tree9bcb9d17db9ae249c3000b2bcec950e54c33a344
parenta417d05adc329e0cda1768aed67f207bc4168998 (diff)
downloadreplicant_openssl-9296b4bb0e04a10b561da2996d3c9575872f1fa4.zip
replicant_openssl-9296b4bb0e04a10b561da2996d3c9575872f1fa4.tar.gz
replicant_openssl-9296b4bb0e04a10b561da2996d3c9575872f1fa4.tar.bz2
Add TLS 1.2 digests patch
Fixes a bug with handling TLS 1.2 and digest functions for DSA and ECDSA keys. Patch from Adam Langley <agl@chromium.org> Change-Id: I11b74472c0df16eca8de3aa36413686603814243
-rw-r--r--include/openssl/ssl3.h11
-rw-r--r--openssl.config9
-rw-r--r--patches/README5
-rw-r--r--patches/tls12_digests.patch411
-rw-r--r--ssl/s3_clnt.c26
-rw-r--r--ssl/ssl3.h11
-rw-r--r--ssl/ssl_cert.c20
-rw-r--r--ssl/ssl_lib.c35
-rw-r--r--ssl/ssl_locl.h4
-rw-r--r--ssl/t1_lib.c104
10 files changed, 529 insertions, 107 deletions
diff --git a/include/openssl/ssl3.h b/include/openssl/ssl3.h
index fee9671..215b985 100644
--- a/include/openssl/ssl3.h
+++ b/include/openssl/ssl3.h
@@ -550,6 +550,16 @@ typedef struct ssl3_state_st
* verified Channel ID from the client: a P256 point, (x,y), where
* each are big-endian values. */
unsigned char tlsext_channel_id[64];
+
+ /* These point to the digest function to use for signatures made with
+ * each type of public key. A NULL value indicates that the default
+ * digest should be used, which is SHA1 as of TLS 1.2.
+ *
+ * (These should be in the tmp member, but we have to put them here to
+ * ensure binary compatibility with earlier OpenSSL 1.0.* releases.) */
+ const EVP_MD *digest_rsa;
+ const EVP_MD *digest_dsa;
+ const EVP_MD *digest_ecdsa;
} SSL3_STATE;
#endif
@@ -699,4 +709,3 @@ typedef struct ssl3_state_st
}
#endif
#endif
-
diff --git a/openssl.config b/openssl.config
index d5c0aa4..e5a71bd 100644
--- a/openssl.config
+++ b/openssl.config
@@ -991,6 +991,7 @@ jsse.patch \
channelid.patch \
eng_dyn_dirs.patch \
fix_clang_build.patch \
+tls12_digests.patch \
"
OPENSSL_PATCHES_progs_SOURCES="\
@@ -1047,3 +1048,11 @@ crypto/bio/b_sock.c \
crypto/x509v3/v3_utl.c \
"
+OPENSSL_PATCHES_tls12_digests_SOURCES="\
+ssl/s3_clnt.c \
+ssl/ssl3.h \
+ssl/ssl_cert.c \
+ssl/ssl_lib.c \
+ssl/ssl_locl.h \
+ssl/t1_lib.c \
+"
diff --git a/patches/README b/patches/README
index 5d9ef03..85f0a4a 100644
--- a/patches/README
+++ b/patches/README
@@ -26,3 +26,8 @@ Fixes the case of having multiple DIR_ADD commands sent to eng_dyn
fix_clang_build.patch
Fixes the Clang based build.
+
+tls12_digests.patch
+
+Fixes a bug with handling TLS 1.2 and digest functions for DSA and ECDSA
+keys.
diff --git a/patches/tls12_digests.patch b/patches/tls12_digests.patch
new file mode 100644
index 0000000..11f7c27
--- /dev/null
+++ b/patches/tls12_digests.patch
@@ -0,0 +1,411 @@
+From 3a8c7b1a08b2766a7f8a388eee14442281b4e295 Mon Sep 17 00:00:00 2001
+From: Adam Langley <agl@chromium.org>
+Date: Thu, 24 Jan 2013 16:27:14 -0500
+Subject: [PATCH 19/36] tls12_digests
+
+Fixes a bug with handling TLS 1.2 and digest functions for DSA and ECDSA
+keys.
+---
+ ssl/s3_clnt.c | 26 +++++++++++++--
+ ssl/ssl3.h | 11 +++++-
+ ssl/ssl_cert.c | 20 -----------
+ ssl/ssl_lib.c | 35 +++++++++++--------
+ ssl/ssl_locl.h | 4 +--
+ ssl/t1_lib.c | 104 ++++++++++++++++++++-------------------------------------
+ 6 files changed, 94 insertions(+), 106 deletions(-)
+
+diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
+index c9196b3..1f3b376 100644
+--- a/ssl/s3_clnt.c
++++ b/ssl/s3_clnt.c
+@@ -1990,12 +1990,13 @@ int ssl3_get_certificate_request(SSL *s)
+ SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_DATA_LENGTH_TOO_LONG);
+ goto err;
+ }
+- if ((llen & 1) || !tls1_process_sigalgs(s, p, llen))
++ if (llen & 1)
+ {
+ ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
+ SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_SIGNATURE_ALGORITHMS_ERROR);
+ goto err;
+ }
++ tls1_process_sigalgs(s, p, llen);
+ p += llen;
+ }
+
+@@ -3017,7 +3018,28 @@ int ssl3_send_client_verify(SSL *s)
+ {
+ long hdatalen = 0;
+ void *hdata;
+- const EVP_MD *md = s->cert->key->digest;
++ const EVP_MD *md;
++ switch (ssl_cert_type(NULL, pkey))
++ {
++ case SSL_PKEY_RSA_ENC:
++ md = s->s3->digest_rsa;
++ break;
++ case SSL_PKEY_DSA_SIGN:
++ md = s->s3->digest_dsa;
++ break;
++ case SSL_PKEY_ECC:
++ md = s->s3->digest_ecdsa;
++ break;
++ default:
++ md = NULL;
++ }
++ if (!md)
++ /* Unlike with the SignatureAlgorithm extension (sent by clients),
++ * there are no default algorithms for the CertificateRequest message
++ * (sent by servers). However, now that we've sent a certificate
++ * for which we don't really know what hash to use for signing, the
++ * best we can do is try a default algorithm. */
++ md = EVP_sha1();
+ hdatalen = BIO_get_mem_data(s->s3->handshake_buffer,
+ &hdata);
+ if (hdatalen <= 0 || !tls12_get_sigandhash(p, pkey, md))
+diff --git a/ssl/ssl3.h b/ssl/ssl3.h
+index 29098e4..3229995 100644
+--- a/ssl/ssl3.h
++++ b/ssl/ssl3.h
+@@ -550,6 +550,16 @@ typedef struct ssl3_state_st
+ * verified Channel ID from the client: a P256 point, (x,y), where
+ * each are big-endian values. */
+ unsigned char tlsext_channel_id[64];
++
++ /* These point to the digest function to use for signatures made with
++ * each type of public key. A NULL value indicates that the default
++ * digest should be used, which is SHA1 as of TLS 1.2.
++ *
++ * (These should be in the tmp member, but we have to put them here to
++ * ensure binary compatibility with earlier OpenSSL 1.0.* releases.) */
++ const EVP_MD *digest_rsa;
++ const EVP_MD *digest_dsa;
++ const EVP_MD *digest_ecdsa;
+ } SSL3_STATE;
+
+ #endif
+@@ -700,4 +710,3 @@ typedef struct ssl3_state_st
+ }
+ #endif
+ #endif
+-
+diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
+index 5123a89..bc4150b 100644
+--- a/ssl/ssl_cert.c
++++ b/ssl/ssl_cert.c
+@@ -160,21 +160,6 @@ int SSL_get_ex_data_X509_STORE_CTX_idx(void)
+ return ssl_x509_store_ctx_idx;
+ }
+
+-static void ssl_cert_set_default_md(CERT *cert)
+- {
+- /* Set digest values to defaults */
+-#ifndef OPENSSL_NO_DSA
+- cert->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1();
+-#endif
+-#ifndef OPENSSL_NO_RSA
+- cert->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1();
+- cert->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1();
+-#endif
+-#ifndef OPENSSL_NO_ECDSA
+- cert->pkeys[SSL_PKEY_ECC].digest = EVP_sha1();
+-#endif
+- }
+-
+ CERT *ssl_cert_new(void)
+ {
+ CERT *ret;
+@@ -189,7 +174,6 @@ CERT *ssl_cert_new(void)
+
+ ret->key= &(ret->pkeys[SSL_PKEY_RSA_ENC]);
+ ret->references=1;
+- ssl_cert_set_default_md(ret);
+ return(ret);
+ }
+
+@@ -322,10 +306,6 @@ CERT *ssl_cert_dup(CERT *cert)
+ * chain is held inside SSL_CTX */
+
+ ret->references=1;
+- /* Set digests to defaults. NB: we don't copy existing values as they
+- * will be set during handshake.
+- */
+- ssl_cert_set_default_md(ret);
+
+ return(ret);
+
+diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
+index 5f8b0b0..e360550 100644
+--- a/ssl/ssl_lib.c
++++ b/ssl/ssl_lib.c
+@@ -2345,32 +2345,41 @@ EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher, const EVP_MD **pmd)
+ {
+ unsigned long alg_a;
+ CERT *c;
+- int idx = -1;
+
+ alg_a = cipher->algorithm_auth;
+ c=s->cert;
+
++ /* SHA1 is the default for all signature algorithms up to TLS 1.2,
++ * except RSA which is handled specially in s3_srvr.c */
++ if (pmd)
++ *pmd = EVP_sha1();
++
+ if ((alg_a & SSL_aDSS) &&
+- (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))
+- idx = SSL_PKEY_DSA_SIGN;
++ (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))
++ {
++ if (pmd && s->s3 && s->s3->digest_dsa)
++ *pmd = s->s3->digest_dsa;
++ return c->pkeys[SSL_PKEY_DSA_SIGN].privatekey;
++ }
+ else if (alg_a & SSL_aRSA)
+ {
++ if (pmd && s->s3 && s->s3->digest_rsa)
++ *pmd = s->s3->digest_rsa;
+ if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL)
+- idx = SSL_PKEY_RSA_SIGN;
+- else if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL)
+- idx = SSL_PKEY_RSA_ENC;
++ return c->pkeys[SSL_PKEY_RSA_SIGN].privatekey;
++ if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL)
++ return c->pkeys[SSL_PKEY_RSA_ENC].privatekey;
+ }
+ else if ((alg_a & SSL_aECDSA) &&
+ (c->pkeys[SSL_PKEY_ECC].privatekey != NULL))
+- idx = SSL_PKEY_ECC;
+- if (idx == -1)
+ {
+- SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR);
+- return(NULL);
++ if (pmd && s->s3 && s->s3->digest_ecdsa)
++ *pmd = s->s3->digest_ecdsa;
++ return c->pkeys[SSL_PKEY_ECC].privatekey;
+ }
+- if (pmd)
+- *pmd = c->pkeys[idx].digest;
+- return c->pkeys[idx].privatekey;
++
++ SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR);
++ return(NULL);
+ }
+
+ void ssl_update_cache(SSL *s,int mode)
+diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
+index 6d38f0f..3e89fcb 100644
+--- a/ssl/ssl_locl.h
++++ b/ssl/ssl_locl.h
+@@ -485,8 +485,6 @@ typedef struct cert_pkey_st
+ {
+ X509 *x509;
+ EVP_PKEY *privatekey;
+- /* Digest to use when signing */
+- const EVP_MD *digest;
+ } CERT_PKEY;
+
+ typedef struct cert_st
+@@ -1142,7 +1140,7 @@ int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
+ int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
+ int *al);
+ long ssl_get_algorithm2(SSL *s);
+-int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize);
++void tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize);
+ int tls12_get_req_sig_algs(SSL *s, unsigned char *p);
+
+ int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int maxlen);
+diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
+index 26805e4..6af51a9 100644
+--- a/ssl/t1_lib.c
++++ b/ssl/t1_lib.c
+@@ -897,6 +897,13 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
+
+ s->servername_done = 0;
+ s->tlsext_status_type = -1;
++
++ /* Reset TLS 1.2 digest functions to defaults because they don't carry
++ * over to a renegotiation. */
++ s->s3->digest_rsa = NULL;
++ s->s3->digest_dsa = NULL;
++ s->s3->digest_ecdsa = NULL;
++
+ #ifndef OPENSSL_NO_NEXTPROTONEG
+ s->s3->next_proto_neg_seen = 0;
+ #endif
+@@ -1198,11 +1205,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+- if (!tls1_process_sigalgs(s, data, dsize))
+- {
+- *al = SSL_AD_DECODE_ERROR;
+- return 0;
+- }
++ tls1_process_sigalgs(s, data, dsize);
+ }
+ else if (type == TLSEXT_TYPE_status_request &&
+ s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb)
+@@ -2354,18 +2357,6 @@ static int tls12_find_id(int nid, tls12_lookup *table, size_t tlen)
+ }
+ return -1;
+ }
+-#if 0
+-static int tls12_find_nid(int id, tls12_lookup *table, size_t tlen)
+- {
+- size_t i;
+- for (i = 0; i < tlen; i++)
+- {
+- if (table[i].id == id)
+- return table[i].nid;
+- }
+- return -1;
+- }
+-#endif
+
+ int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk, const EVP_MD *md)
+ {
+@@ -2384,6 +2375,8 @@ int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk, const EVP_MD *md)
+ return 1;
+ }
+
++/* tls12_get_sigid returns the TLS 1.2 SignatureAlgorithm value corresponding
++ * to the given public key, or -1 if not known. */
+ int tls12_get_sigid(const EVP_PKEY *pk)
+ {
+ return tls12_find_id(pk->type, tls12_sig,
+@@ -2403,47 +2396,49 @@ const EVP_MD *tls12_get_hash(unsigned char hash_alg)
+ return EVP_md5();
+ #endif
+ #ifndef OPENSSL_NO_SHA
+- case TLSEXT_hash_sha1:
++ case TLSEXT_hash_sha1:
+ return EVP_sha1();
+ #endif
+ #ifndef OPENSSL_NO_SHA256
+- case TLSEXT_hash_sha224:
++ case TLSEXT_hash_sha224:
+ return EVP_sha224();
+
+- case TLSEXT_hash_sha256:
++ case TLSEXT_hash_sha256:
+ return EVP_sha256();
+ #endif
+ #ifndef OPENSSL_NO_SHA512
+- case TLSEXT_hash_sha384:
++ case TLSEXT_hash_sha384:
+ return EVP_sha384();
+
+- case TLSEXT_hash_sha512:
++ case TLSEXT_hash_sha512:
+ return EVP_sha512();
+ #endif
+- default:
++ default:
+ return NULL;
+
+ }
+ }
+
+-/* Set preferred digest for each key type */
+-
+-int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
++/* tls1_process_sigalgs processes a signature_algorithms extension and sets the
++ * digest functions accordingly for each key type.
++ *
++ * See RFC 5246, section 7.4.1.4.1.
++ *
++ * data: points to the content of the extension, not including type and length
++ * headers.
++ * dsize: the number of bytes of |data|. Must be even.
++ */
++void tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
+ {
+- int i, idx;
+- const EVP_MD *md;
+- CERT *c = s->cert;
++ int i;
++ const EVP_MD *md, **digest_ptr;
+ /* Extension ignored for TLS versions below 1.2 */
+ if (TLS1_get_version(s) < TLS1_2_VERSION)
+- return 1;
+- /* Should never happen */
+- if (!c)
+- return 0;
++ return;
+
+- c->pkeys[SSL_PKEY_DSA_SIGN].digest = NULL;
+- c->pkeys[SSL_PKEY_RSA_SIGN].digest = NULL;
+- c->pkeys[SSL_PKEY_RSA_ENC].digest = NULL;
+- c->pkeys[SSL_PKEY_ECC].digest = NULL;
++ s->s3->digest_rsa = NULL;
++ s->s3->digest_dsa = NULL;
++ s->s3->digest_ecdsa = NULL;
+
+ for (i = 0; i < dsize; i += 2)
+ {
+@@ -2453,56 +2448,31 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
+ {
+ #ifndef OPENSSL_NO_RSA
+ case TLSEXT_signature_rsa:
+- idx = SSL_PKEY_RSA_SIGN;
++ digest_ptr = &s->s3->digest_rsa;
+ break;
+ #endif
+ #ifndef OPENSSL_NO_DSA
+ case TLSEXT_signature_dsa:
+- idx = SSL_PKEY_DSA_SIGN;
++ digest_ptr = &s->s3->digest_dsa;
+ break;
+ #endif
+ #ifndef OPENSSL_NO_ECDSA
+ case TLSEXT_signature_ecdsa:
+- idx = SSL_PKEY_ECC;
++ digest_ptr = &s->s3->digest_ecdsa;
+ break;
+ #endif
+ default:
+ continue;
+ }
+
+- if (c->pkeys[idx].digest == NULL)
++ if (*digest_ptr == NULL)
+ {
+ md = tls12_get_hash(hash_alg);
+ if (md)
+- {
+- c->pkeys[idx].digest = md;
+- if (idx == SSL_PKEY_RSA_SIGN)
+- c->pkeys[SSL_PKEY_RSA_ENC].digest = md;
+- }
++ *digest_ptr = md;
+ }
+
+ }
+-
+-
+- /* Set any remaining keys to default values. NOTE: if alg is not
+- * supported it stays as NULL.
+- */
+-#ifndef OPENSSL_NO_DSA
+- if (!c->pkeys[SSL_PKEY_DSA_SIGN].digest)
+- c->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1();
+-#endif
+-#ifndef OPENSSL_NO_RSA
+- if (!c->pkeys[SSL_PKEY_RSA_SIGN].digest)
+- {
+- c->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1();
+- c->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1();
+- }
+-#endif
+-#ifndef OPENSSL_NO_ECDSA
+- if (!c->pkeys[SSL_PKEY_ECC].digest)
+- c->pkeys[SSL_PKEY_ECC].digest = EVP_sha1();
+-#endif
+- return 1;
+ }
+
+ #endif
+--
+1.8.2.1
+
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 1d40a2e..88077ea 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -2014,12 +2014,13 @@ int ssl3_get_certificate_request(SSL *s)
SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_DATA_LENGTH_TOO_LONG);
goto err;
}
- if ((llen & 1) || !tls1_process_sigalgs(s, p, llen))
+ if (llen & 1)
{
ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_SIGNATURE_ALGORITHMS_ERROR);
goto err;
}
+ tls1_process_sigalgs(s, p, llen);
p += llen;
}
@@ -3041,7 +3042,28 @@ int ssl3_send_client_verify(SSL *s)
{
long hdatalen = 0;
void *hdata;
- const EVP_MD *md = s->cert->key->digest;
+ const EVP_MD *md;
+ switch (ssl_cert_type(NULL, pkey))
+ {
+ case SSL_PKEY_RSA_ENC:
+ md = s->s3->digest_rsa;
+ break;
+ case SSL_PKEY_DSA_SIGN:
+ md = s->s3->digest_dsa;
+ break;
+ case SSL_PKEY_ECC:
+ md = s->s3->digest_ecdsa;
+ break;
+ default:
+ md = NULL;
+ }
+ if (!md)
+ /* Unlike with the SignatureAlgorithm extension (sent by clients),
+ * there are no default algorithms for the CertificateRequest message
+ * (sent by servers). However, now that we've sent a certificate
+ * for which we don't really know what hash to use for signing, the
+ * best we can do is try a default algorithm. */
+ md = EVP_sha1();
hdatalen = BIO_get_mem_data(s->s3->handshake_buffer,
&hdata);
if (hdatalen <= 0 || !tls12_get_sigandhash(p, pkey, md))
diff --git a/ssl/ssl3.h b/ssl/ssl3.h
index fee9671..215b985 100644
--- a/ssl/ssl3.h
+++ b/ssl/ssl3.h
@@ -550,6 +550,16 @@ typedef struct ssl3_state_st
* verified Channel ID from the client: a P256 point, (x,y), where
* each are big-endian values. */
unsigned char tlsext_channel_id[64];
+
+ /* These point to the digest function to use for signatures made with
+ * each type of public key. A NULL value indicates that the default
+ * digest should be used, which is SHA1 as of TLS 1.2.
+ *
+ * (These should be in the tmp member, but we have to put them here to
+ * ensure binary compatibility with earlier OpenSSL 1.0.* releases.) */
+ const EVP_MD *digest_rsa;
+ const EVP_MD *digest_dsa;
+ const EVP_MD *digest_ecdsa;
} SSL3_STATE;
#endif
@@ -699,4 +709,3 @@ typedef struct ssl3_state_st
}
#endif
#endif
-
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 5123a89..bc4150b 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -160,21 +160,6 @@ int SSL_get_ex_data_X509_STORE_CTX_idx(void)
return ssl_x509_store_ctx_idx;
}
-static void ssl_cert_set_default_md(CERT *cert)
- {
- /* Set digest values to defaults */
-#ifndef OPENSSL_NO_DSA
- cert->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1();
-#endif
-#ifndef OPENSSL_NO_RSA
- cert->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1();
- cert->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1();
-#endif
-#ifndef OPENSSL_NO_ECDSA
- cert->pkeys[SSL_PKEY_ECC].digest = EVP_sha1();
-#endif
- }
-
CERT *ssl_cert_new(void)
{
CERT *ret;
@@ -189,7 +174,6 @@ CERT *ssl_cert_new(void)
ret->key= &(ret->pkeys[SSL_PKEY_RSA_ENC]);
ret->references=1;
- ssl_cert_set_default_md(ret);
return(ret);
}
@@ -322,10 +306,6 @@ CERT *ssl_cert_dup(CERT *cert)
* chain is held inside SSL_CTX */
ret->references=1;
- /* Set digests to defaults. NB: we don't copy existing values as they
- * will be set during handshake.
- */
- ssl_cert_set_default_md(ret);
return(ret);
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 65b2ef8..6382325 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2400,32 +2400,41 @@ EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher, const EVP_MD **pmd)
{
unsigned long alg_a;
CERT *c;
- int idx = -1;
alg_a = cipher->algorithm_auth;
c=s->cert;
+ /* SHA1 is the default for all signature algorithms up to TLS 1.2,
+ * except RSA which is handled specially in s3_srvr.c */
+ if (pmd)
+ *pmd = EVP_sha1();
+
if ((alg_a & SSL_aDSS) &&
- (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))
- idx = SSL_PKEY_DSA_SIGN;
+ (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))
+ {
+ if (pmd && s->s3 && s->s3->digest_dsa)
+ *pmd = s->s3->digest_dsa;
+ return c->pkeys[SSL_PKEY_DSA_SIGN].privatekey;
+ }
else if (alg_a & SSL_aRSA)
{
+ if (pmd && s->s3 && s->s3->digest_rsa)
+ *pmd = s->s3->digest_rsa;
if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL)
- idx = SSL_PKEY_RSA_SIGN;
- else if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL)
- idx = SSL_PKEY_RSA_ENC;
+ return c->pkeys[SSL_PKEY_RSA_SIGN].privatekey;
+ if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL)
+ return c->pkeys[SSL_PKEY_RSA_ENC].privatekey;
}
else if ((alg_a & SSL_aECDSA) &&
(c->pkeys[SSL_PKEY_ECC].privatekey != NULL))
- idx = SSL_PKEY_ECC;
- if (idx == -1)
{
- SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR);
- return(NULL);
+ if (pmd && s->s3 && s->s3->digest_ecdsa)
+ *pmd = s->s3->digest_ecdsa;
+ return c->pkeys[SSL_PKEY_ECC].privatekey;
}
- if (pmd)
- *pmd = c->pkeys[idx].digest;
- return c->pkeys[idx].privatekey;
+
+ SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR);
+ return(NULL);
}
void ssl_update_cache(SSL *s,int mode)
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 5f21726..917c9f3 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -483,8 +483,6 @@ typedef struct cert_pkey_st
X509 *x509;
STACK_OF(X509) *cert_chain;
EVP_PKEY *privatekey;
- /* Digest to use when signing */
- const EVP_MD *digest;
} CERT_PKEY;
typedef struct cert_st
@@ -1140,7 +1138,7 @@ int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
int *al);
long ssl_get_algorithm2(SSL *s);
-int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize);
+void tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize);
int tls12_get_req_sig_algs(SSL *s, unsigned char *p);
int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int maxlen);
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 28d45b3..53b805f 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -897,6 +897,13 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
s->servername_done = 0;
s->tlsext_status_type = -1;
+
+ /* Reset TLS 1.2 digest functions to defaults because they don't carry
+ * over to a renegotiation. */
+ s->s3->digest_rsa = NULL;
+ s->s3->digest_dsa = NULL;
+ s->s3->digest_ecdsa = NULL;
+
#ifndef OPENSSL_NO_NEXTPROTONEG
s->s3->next_proto_neg_seen = 0;
#endif
@@ -1194,11 +1201,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
*al = SSL_AD_DECODE_ERROR;
return 0;
}
- if (!tls1_process_sigalgs(s, data, dsize))
- {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ tls1_process_sigalgs(s, data, dsize);
}
else if (type == TLSEXT_TYPE_status_request &&
s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb)
@@ -2350,18 +2353,6 @@ static int tls12_find_id(int nid, tls12_lookup *table, size_t tlen)
}
return -1;
}
-#if 0
-static int tls12_find_nid(int id, tls12_lookup *table, size_t tlen)
- {
- size_t i;
- for (i = 0; i < tlen; i++)
- {
- if (table[i].id == id)
- return table[i].nid;
- }
- return -1;
- }
-#endif
int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk, const EVP_MD *md)
{
@@ -2380,6 +2371,8 @@ int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk, const EVP_MD *md)
return 1;
}
+/* tls12_get_sigid returns the TLS 1.2 SignatureAlgorithm value corresponding
+ * to the given public key, or -1 if not known. */
int tls12_get_sigid(const EVP_PKEY *pk)
{
return tls12_find_id(pk->type, tls12_sig,
@@ -2399,47 +2392,49 @@ const EVP_MD *tls12_get_hash(unsigned char hash_alg)
return EVP_md5();
#endif
#ifndef OPENSSL_NO_SHA
- case TLSEXT_hash_sha1:
+ case TLSEXT_hash_sha1:
return EVP_sha1();
#endif
#ifndef OPENSSL_NO_SHA256
- case TLSEXT_hash_sha224:
+ case TLSEXT_hash_sha224:
return EVP_sha224();
- case TLSEXT_hash_sha256:
+ case TLSEXT_hash_sha256:
return EVP_sha256();
#endif
#ifndef OPENSSL_NO_SHA512
- case TLSEXT_hash_sha384:
+ case TLSEXT_hash_sha384:
return EVP_sha384();
- case TLSEXT_hash_sha512:
+ case TLSEXT_hash_sha512:
return EVP_sha512();
#endif
- default:
+ default:
return NULL;
}
}
-/* Set preferred digest for each key type */
-
-int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
+/* tls1_process_sigalgs processes a signature_algorithms extension and sets the
+ * digest functions accordingly for each key type.
+ *
+ * See RFC 5246, section 7.4.1.4.1.
+ *
+ * data: points to the content of the extension, not including type and length
+ * headers.
+ * dsize: the number of bytes of |data|. Must be even.
+ */
+void tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
{
- int i, idx;
- const EVP_MD *md;
- CERT *c = s->cert;
+ int i;
+ const EVP_MD *md, **digest_ptr;
/* Extension ignored for TLS versions below 1.2 */
if (TLS1_get_version(s) < TLS1_2_VERSION)
- return 1;
- /* Should never happen */
- if (!c)
- return 0;
+ return;
- c->pkeys[SSL_PKEY_DSA_SIGN].digest = NULL;
- c->pkeys[SSL_PKEY_RSA_SIGN].digest = NULL;
- c->pkeys[SSL_PKEY_RSA_ENC].digest = NULL;
- c->pkeys[SSL_PKEY_ECC].digest = NULL;
+ s->s3->digest_rsa = NULL;
+ s->s3->digest_dsa = NULL;
+ s->s3->digest_ecdsa = NULL;
for (i = 0; i < dsize; i += 2)
{
@@ -2449,56 +2444,31 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
{
#ifndef OPENSSL_NO_RSA
case TLSEXT_signature_rsa:
- idx = SSL_PKEY_RSA_SIGN;
+ digest_ptr = &s->s3->digest_rsa;
break;
#endif
#ifndef OPENSSL_NO_DSA
case TLSEXT_signature_dsa:
- idx = SSL_PKEY_DSA_SIGN;
+ digest_ptr = &s->s3->digest_dsa;
break;
#endif
#ifndef OPENSSL_NO_ECDSA
case TLSEXT_signature_ecdsa:
- idx = SSL_PKEY_ECC;
+ digest_ptr = &s->s3->digest_ecdsa;
break;
#endif
default:
continue;
}
- if (c->pkeys[idx].digest == NULL)
+ if (*digest_ptr == NULL)
{
md = tls12_get_hash(hash_alg);
if (md)
- {
- c->pkeys[idx].digest = md;
- if (idx == SSL_PKEY_RSA_SIGN)
- c->pkeys[SSL_PKEY_RSA_ENC].digest = md;
- }
+ *digest_ptr = md;
}
}
-
-
- /* Set any remaining keys to default values. NOTE: if alg is not
- * supported it stays as NULL.
- */
-#ifndef OPENSSL_NO_DSA
- if (!c->pkeys[SSL_PKEY_DSA_SIGN].digest)
- c->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1();
-#endif
-#ifndef OPENSSL_NO_RSA
- if (!c->pkeys[SSL_PKEY_RSA_SIGN].digest)
- {
- c->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1();
- c->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1();
- }
-#endif
-#ifndef OPENSSL_NO_ECDSA
- if (!c->pkeys[SSL_PKEY_ECC].digest)
- c->pkeys[SSL_PKEY_ECC].digest = EVP_sha1();
-#endif
- return 1;
}
#endif