mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-22 07:57:30 +00:00
d83a3d71bc
Merge in RedPhone // FREEBIE
412 lines
11 KiB
Diff
412 lines
11 KiB
Diff
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
|
|
|