mirror of
https://github.com/openssl/openssl.git
synced 2024-11-28 04:25:31 +08:00
Continuing TLS v1.2 support: add support for server parsing of
signature algorithms extension and correct signature format for server key exchange. All ciphersuites should now work on the server but no client support and no client certificate support yet.
This commit is contained in:
parent
c184711124
commit
6b7be581e5
6
CHANGES
6
CHANGES
@ -4,6 +4,12 @@
|
||||
|
||||
Changes between 1.0.1 and 1.1.0 [xx XXX xxxx]
|
||||
|
||||
*) Add server support for TLS v1.2 signature algorithms extension. Switch
|
||||
to new signature format when needed using client digest preference.
|
||||
All server ciphersuites should now work correctly in TLS v1.2. No client
|
||||
support yet and no support for client certificates.
|
||||
[Steve Henson]
|
||||
|
||||
*) Initial TLS v1.2 support. Add new SHA256 digest to ssl code, switch
|
||||
to SHA256 for PRF when using TLS v1.2 and later. Add new SHA256 based
|
||||
ciphersuites. At present only RSA key exchange ciphersuites work with
|
||||
|
@ -1526,6 +1526,9 @@ bad:
|
||||
SSL_CTX_set_quiet_shutdown(ctx,1);
|
||||
if (bugs) SSL_CTX_set_options(ctx,SSL_OP_ALL);
|
||||
if (hack) SSL_CTX_set_options(ctx,SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG);
|
||||
/* HACK while TLS v1.2 is disabled by default */
|
||||
if (!(off & SSL_OP_NO_TLSv1_2))
|
||||
SSL_CTX_clear_options(ctx, SSL_OP_NO_TLSv1_2);
|
||||
SSL_CTX_set_options(ctx,off);
|
||||
/* DTLS: partial reads end up discarding unread UDP bytes :-(
|
||||
* Setting read ahead solves this problem.
|
||||
|
@ -1139,7 +1139,7 @@ int dtls1_send_server_key_exchange(SSL *s)
|
||||
if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
|
||||
&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
|
||||
{
|
||||
if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher))
|
||||
if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher, NULL))
|
||||
== NULL)
|
||||
{
|
||||
al=SSL_AD_DECODE_ERROR;
|
||||
|
@ -1530,6 +1530,7 @@ int ssl3_send_server_key_exchange(SSL *s)
|
||||
BN_CTX *bn_ctx = NULL;
|
||||
#endif
|
||||
EVP_PKEY *pkey;
|
||||
const EVP_MD *md = NULL;
|
||||
unsigned char *p,*d;
|
||||
int al,i;
|
||||
unsigned long type;
|
||||
@ -1810,7 +1811,7 @@ int ssl3_send_server_key_exchange(SSL *s)
|
||||
if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
|
||||
&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
|
||||
{
|
||||
if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher))
|
||||
if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher,&md))
|
||||
== NULL)
|
||||
{
|
||||
al=SSL_AD_DECODE_ERROR;
|
||||
@ -1888,7 +1889,8 @@ int ssl3_send_server_key_exchange(SSL *s)
|
||||
/* n is the length of the params, they start at &(d[4])
|
||||
* and p points to the space at the end. */
|
||||
#ifndef OPENSSL_NO_RSA
|
||||
if (pkey->type == EVP_PKEY_RSA)
|
||||
if (pkey->type == EVP_PKEY_RSA
|
||||
&& s->version < TLS1_2_VERSION)
|
||||
{
|
||||
q=md_buf;
|
||||
j=0;
|
||||
@ -1915,44 +1917,37 @@ int ssl3_send_server_key_exchange(SSL *s)
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if !defined(OPENSSL_NO_DSA)
|
||||
if (pkey->type == EVP_PKEY_DSA)
|
||||
if (md)
|
||||
{
|
||||
/* lets do DSS */
|
||||
EVP_SignInit_ex(&md_ctx,EVP_dss1(), NULL);
|
||||
/* For TLS1.2 and later send signature
|
||||
* algorithm */
|
||||
if (s->version >= TLS1_2_VERSION)
|
||||
{
|
||||
if (!tls12_get_sigandhash(p, pkey, md))
|
||||
{
|
||||
/* Should never happen */
|
||||
al=SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
|
||||
goto f_err;
|
||||
}
|
||||
p+=2;
|
||||
}
|
||||
EVP_SignInit_ex(&md_ctx, md, NULL);
|
||||
EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
|
||||
EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
|
||||
EVP_SignUpdate(&md_ctx,&(d[4]),n);
|
||||
if (!EVP_SignFinal(&md_ctx,&(p[2]),
|
||||
(unsigned int *)&i,pkey))
|
||||
{
|
||||
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_DSA);
|
||||
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_EVP);
|
||||
goto err;
|
||||
}
|
||||
s2n(i,p);
|
||||
n+=i+2;
|
||||
if (s->version >= TLS1_2_VERSION)
|
||||
n+= 2;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if !defined(OPENSSL_NO_ECDSA)
|
||||
if (pkey->type == EVP_PKEY_EC)
|
||||
{
|
||||
/* let's do ECDSA */
|
||||
EVP_SignInit_ex(&md_ctx,EVP_ecdsa(), NULL);
|
||||
EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
|
||||
EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
|
||||
EVP_SignUpdate(&md_ctx,&(d[4]),n);
|
||||
if (!EVP_SignFinal(&md_ctx,&(p[2]),
|
||||
(unsigned int *)&i,pkey))
|
||||
{
|
||||
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_ECDSA);
|
||||
goto err;
|
||||
}
|
||||
s2n(i,p);
|
||||
n+=i+2;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Is this error check actually needed? */
|
||||
al=SSL_AD_HANDSHAKE_FAILURE;
|
||||
|
@ -160,6 +160,21 @@ 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_dss1();
|
||||
#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_ecdsa();
|
||||
#endif
|
||||
}
|
||||
|
||||
CERT *ssl_cert_new(void)
|
||||
{
|
||||
CERT *ret;
|
||||
@ -174,7 +189,7 @@ CERT *ssl_cert_new(void)
|
||||
|
||||
ret->key= &(ret->pkeys[SSL_PKEY_RSA_ENC]);
|
||||
ret->references=1;
|
||||
|
||||
ssl_cert_set_default_md(ret);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
@ -307,6 +322,10 @@ 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);
|
||||
|
||||
|
@ -2322,34 +2322,36 @@ X509 *ssl_get_server_send_cert(SSL *s)
|
||||
return(c->pkeys[i].x509);
|
||||
}
|
||||
|
||||
EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher)
|
||||
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;
|
||||
|
||||
if ((alg_a & SSL_aDSS) &&
|
||||
(c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))
|
||||
return(c->pkeys[SSL_PKEY_DSA_SIGN].privatekey);
|
||||
idx = SSL_PKEY_DSA_SIGN;
|
||||
else if (alg_a & SSL_aRSA)
|
||||
{
|
||||
if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL)
|
||||
return(c->pkeys[SSL_PKEY_RSA_SIGN].privatekey);
|
||||
idx = SSL_PKEY_RSA_SIGN;
|
||||
else if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL)
|
||||
return(c->pkeys[SSL_PKEY_RSA_ENC].privatekey);
|
||||
else
|
||||
return(NULL);
|
||||
idx = SSL_PKEY_RSA_ENC;
|
||||
}
|
||||
else if ((alg_a & SSL_aECDSA) &&
|
||||
(c->pkeys[SSL_PKEY_ECC].privatekey != NULL))
|
||||
return(c->pkeys[SSL_PKEY_ECC].privatekey);
|
||||
else /* if (alg_a & SSL_aNULL) */
|
||||
idx = SSL_PKEY_ECC;
|
||||
if (idx == -1)
|
||||
{
|
||||
SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR);
|
||||
return(NULL);
|
||||
}
|
||||
if (pmd)
|
||||
*pmd = c->pkeys[idx].digest;
|
||||
return c->pkeys[idx].privatekey;
|
||||
}
|
||||
|
||||
void ssl_update_cache(SSL *s,int mode)
|
||||
|
@ -461,6 +461,8 @@ 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
|
||||
@ -814,7 +816,7 @@ int ssl_undefined_function(SSL *s);
|
||||
int ssl_undefined_void_function(void);
|
||||
int ssl_undefined_const_function(const SSL *s);
|
||||
X509 *ssl_get_server_send_cert(SSL *);
|
||||
EVP_PKEY *ssl_get_sign_pkey(SSL *,const SSL_CIPHER *);
|
||||
EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *c, const EVP_MD **pmd);
|
||||
int ssl_cert_type(X509 *x,EVP_PKEY *pkey);
|
||||
void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher);
|
||||
STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s);
|
||||
@ -1088,3 +1090,4 @@ int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
|
||||
int *al);
|
||||
long ssl_get_algorithm2(SSL *s);
|
||||
#endif
|
||||
int tls12_get_sigandhash(unsigned char *p, EVP_PKEY *pk, const EVP_MD *md);
|
||||
|
205
ssl/t1_lib.c
205
ssl/t1_lib.c
@ -122,6 +122,7 @@ const char tls1_version_str[]="TLSv1" OPENSSL_VERSION_PTEXT;
|
||||
static int tls_decrypt_ticket(SSL *s, const unsigned char *tick, int ticklen,
|
||||
const unsigned char *sess_id, int sesslen,
|
||||
SSL_SESSION **psess);
|
||||
static int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize);
|
||||
#endif
|
||||
|
||||
SSL3_ENC_METHOD TLSv1_enc_data={
|
||||
@ -693,6 +694,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
|
||||
unsigned short len;
|
||||
unsigned char *data = *p;
|
||||
int renegotiate_seen = 0;
|
||||
int sigalg_seen = 0;
|
||||
|
||||
s->servername_done = 0;
|
||||
s->tlsext_status_type = -1;
|
||||
@ -956,6 +958,28 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
|
||||
return 0;
|
||||
renegotiate_seen = 1;
|
||||
}
|
||||
else if (type == TLSEXT_TYPE_signature_algorithms)
|
||||
{
|
||||
int dsize;
|
||||
if (sigalg_seen || size < 2)
|
||||
{
|
||||
*al = SSL_AD_DECODE_ERROR;
|
||||
return 0;
|
||||
}
|
||||
sigalg_seen = 1;
|
||||
n2s(data,dsize);
|
||||
size -= 2;
|
||||
if (dsize != size || dsize & 1)
|
||||
{
|
||||
*al = SSL_AD_DECODE_ERROR;
|
||||
return 0;
|
||||
}
|
||||
if (!tls1_process_sigalgs(s, data, dsize))
|
||||
{
|
||||
*al = SSL_AD_DECODE_ERROR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (type == TLSEXT_TYPE_status_request &&
|
||||
s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb)
|
||||
{
|
||||
@ -1893,4 +1917,185 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Tables to translate from NIDs to TLS v1.2 ids */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int nid;
|
||||
int id;
|
||||
} tls12_lookup;
|
||||
|
||||
static tls12_lookup tls12_md[] = {
|
||||
#ifndef OPENSSL_NO_MD5
|
||||
{NID_md5, TLSEXT_hash_md5},
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_SHA
|
||||
{NID_sha1, TLSEXT_hash_sha1},
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_SHA256
|
||||
{NID_sha224, TLSEXT_hash_sha224},
|
||||
{NID_sha256, TLSEXT_hash_sha256},
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_SHA512
|
||||
{NID_sha384, TLSEXT_hash_sha384},
|
||||
{NID_sha512, TLSEXT_hash_sha512}
|
||||
#endif
|
||||
};
|
||||
|
||||
static tls12_lookup tls12_sig[] = {
|
||||
#ifndef OPENSSL_NO_RSA
|
||||
{EVP_PKEY_RSA, TLSEXT_signature_rsa},
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_RSA
|
||||
{EVP_PKEY_DSA, TLSEXT_signature_dsa},
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_ECDSA
|
||||
{EVP_PKEY_EC, TLSEXT_signature_ecdsa}
|
||||
#endif
|
||||
};
|
||||
|
||||
static int tls12_find_id(int nid, tls12_lookup *table, size_t tlen)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < tlen; i++)
|
||||
{
|
||||
if (table[i].nid == nid)
|
||||
return table[i].id;
|
||||
}
|
||||
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, EVP_PKEY *pk, const EVP_MD *md)
|
||||
{
|
||||
int sig_id, md_id;
|
||||
md_id = tls12_find_id(EVP_MD_type(md), tls12_md,
|
||||
sizeof(tls12_md)/sizeof(tls12_lookup));
|
||||
if (md_id == -1)
|
||||
return 0;
|
||||
sig_id = tls12_find_id(pk->type, tls12_sig,
|
||||
sizeof(tls12_sig)/sizeof(tls12_lookup));
|
||||
if (sig_id == -1)
|
||||
return 0;
|
||||
p[0] = (unsigned char)md_id;
|
||||
p[1] = (unsigned char)sig_id;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Set preferred digest for each key type */
|
||||
|
||||
int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
|
||||
{
|
||||
int i, idx;
|
||||
const EVP_MD *md;
|
||||
CERT *c = s->cert;
|
||||
/* Extension ignored for TLS versions below 1.2 */
|
||||
if (s->version < TLS1_2_VERSION)
|
||||
return 1;
|
||||
|
||||
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;
|
||||
|
||||
for (i = 0; i < dsize; i += 2)
|
||||
{
|
||||
unsigned char hash_alg = data[i], sig_alg = data[i+1];
|
||||
|
||||
switch(sig_alg)
|
||||
{
|
||||
#ifndef OPENSSL_NO_RSA
|
||||
case TLSEXT_signature_rsa:
|
||||
idx = SSL_PKEY_RSA_SIGN;
|
||||
break;
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_DSA
|
||||
case TLSEXT_signature_dsa:
|
||||
idx = SSL_PKEY_DSA_SIGN;
|
||||
break;
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_ECDSA
|
||||
case TLSEXT_signature_ecdsa:
|
||||
idx = SSL_PKEY_ECC;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c->pkeys[idx].digest)
|
||||
continue;
|
||||
|
||||
switch(hash_alg)
|
||||
{
|
||||
#ifndef OPENSSL_NO_MD5
|
||||
case TLSEXT_hash_md5:
|
||||
md = EVP_md5();
|
||||
break;
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_SHA
|
||||
case TLSEXT_hash_sha1:
|
||||
md = EVP_sha1();
|
||||
break;
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_SHA256
|
||||
case TLSEXT_hash_sha224:
|
||||
md = EVP_sha224();
|
||||
break;
|
||||
|
||||
case TLSEXT_hash_sha256:
|
||||
md = EVP_sha256();
|
||||
break;
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_SHA512
|
||||
case TLSEXT_hash_sha384:
|
||||
md = EVP_sha384();
|
||||
break;
|
||||
|
||||
case TLSEXT_hash_sha512:
|
||||
md = EVP_sha512();
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
c->pkeys[idx].digest = md;
|
||||
if (idx == SSL_PKEY_RSA_SIGN)
|
||||
c->pkeys[SSL_PKEY_RSA_ENC].digest = 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_dss1();
|
||||
#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_ecdsa();
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
15
ssl/tls1.h
15
ssl/tls1.h
@ -234,6 +234,21 @@ extern "C" {
|
||||
#define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2 2
|
||||
#define TLSEXT_ECPOINTFORMAT_last 2
|
||||
|
||||
/* Signature and hash algorithms from RFC 5246 */
|
||||
|
||||
#define TLSEXT_signature_anonymous 0
|
||||
#define TLSEXT_signature_rsa 1
|
||||
#define TLSEXT_signature_dsa 2
|
||||
#define TLSEXT_signature_ecdsa 3
|
||||
|
||||
#define TLSEXT_hash_none 0
|
||||
#define TLSEXT_hash_md5 1
|
||||
#define TLSEXT_hash_sha1 2
|
||||
#define TLSEXT_hash_sha224 3
|
||||
#define TLSEXT_hash_sha256 4
|
||||
#define TLSEXT_hash_sha384 5
|
||||
#define TLSEXT_hash_sha512 6
|
||||
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
|
||||
#define TLSEXT_MAXLEN_host_name 255
|
||||
|
Loading…
Reference in New Issue
Block a user