Provisional support for TLS v1.2 client authentication: client side only.

Parse certificate request message and set digests appropriately.

Generate new TLS v1.2 format certificate verify message.

Keep handshake caches around for longer as they are needed for client auth.
This commit is contained in:
Dr. Stephen Henson 2011-05-12 17:35:03 +00:00
parent 8f82912460
commit 855a54a9a5
2 changed files with 59 additions and 5 deletions

View file

@ -4,6 +4,11 @@
Changes between 1.0.1 and 1.1.0 [xx XXX xxxx] Changes between 1.0.1 and 1.1.0 [xx XXX xxxx]
*) Add TLS v1.2 client side support for client authentication. Keep cache
of handshake records longer as we don't know the hash algorithm to use
until after the certificate request message is received.
[Steve Henson]
*) Rename FIPS_mode_set and FIPS_mode to FIPS_module_mode_set and *) Rename FIPS_mode_set and FIPS_mode to FIPS_module_mode_set and
FIPS_module_mode. FIPS_mode and FIPS_mode_set will be implmeneted FIPS_module_mode. FIPS_mode and FIPS_mode_set will be implmeneted
outside the validated module in the FIPS capable OpenSSL. outside the validated module in the FIPS capable OpenSSL.

View file

@ -922,9 +922,11 @@ int ssl3_get_server_hello(SSL *s)
} }
} }
s->s3->tmp.new_cipher=c; s->s3->tmp.new_cipher=c;
if (!ssl3_digest_cached_records(s)) /* Don't digest cached records if TLS v1.2: we may need them for
* client authentication.
*/
if (s->version < TLS1_2_VERSION && !ssl3_digest_cached_records(s))
goto f_err; goto f_err;
/* lets get the compression algorithm */ /* lets get the compression algorithm */
/* COMPRESSION */ /* COMPRESSION */
#ifdef OPENSSL_NO_COMP #ifdef OPENSSL_NO_COMP
@ -1813,6 +1815,14 @@ int ssl3_get_certificate_request(SSL *s)
if (s->s3->tmp.message_type == SSL3_MT_SERVER_DONE) if (s->s3->tmp.message_type == SSL3_MT_SERVER_DONE)
{ {
s->s3->tmp.reuse_message=1; s->s3->tmp.reuse_message=1;
/* If we get here we don't need any cached handshake records
* as we wont be doing client auth.
*/
if (s->s3->handshake_buffer)
{
if (!ssl3_digest_cached_records(s))
goto err;
}
return(1); return(1);
} }
@ -2854,12 +2864,13 @@ int ssl3_send_client_verify(SSL *s)
unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH]; unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
EVP_PKEY *pkey; EVP_PKEY *pkey;
EVP_PKEY_CTX *pctx=NULL; EVP_PKEY_CTX *pctx=NULL;
#ifndef OPENSSL_NO_RSA EVP_MD_CTX mctx;
unsigned u=0; unsigned u=0;
#endif
unsigned long n; unsigned long n;
int j; int j;
EVP_MD_CTX_init(&mctx);
if (s->state == SSL3_ST_CW_CERT_VRFY_A) if (s->state == SSL3_ST_CW_CERT_VRFY_A)
{ {
d=(unsigned char *)s->init_buf->data; d=(unsigned char *)s->init_buf->data;
@ -2870,6 +2881,7 @@ int ssl3_send_client_verify(SSL *s)
EVP_PKEY_sign_init(pctx); EVP_PKEY_sign_init(pctx);
if (EVP_PKEY_CTX_set_signature_md(pctx, EVP_sha1())>0) if (EVP_PKEY_CTX_set_signature_md(pctx, EVP_sha1())>0)
{ {
if (s->version < TLS1_2_VERSION)
s->method->ssl3_enc->cert_verify_mac(s, s->method->ssl3_enc->cert_verify_mac(s,
NID_sha1, NID_sha1,
&(data[MD5_DIGEST_LENGTH])); &(data[MD5_DIGEST_LENGTH]));
@ -2878,6 +2890,41 @@ int ssl3_send_client_verify(SSL *s)
{ {
ERR_clear_error(); ERR_clear_error();
} }
/* For TLS v1.2 send signature algorithm and signature
* using agreed digest and cached handshake records.
*/
if (s->version >= TLS1_2_VERSION)
{
long hdatalen = 0;
void *hdata;
const EVP_MD *md = s->cert->key->digest;
hdatalen = BIO_get_mem_data(s->s3->handshake_buffer,
&hdata);
if (hdatalen <= 0 || !tls12_get_sigandhash(p, pkey, md))
{
SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,
ERR_R_INTERNAL_ERROR);
goto err;
}
p += 2;
#ifdef SSL_DEBUG
fprintf(stderr, "Using TLS 1.2 with client alg %s\n",
EVP_MD_name(md));
#endif
if (!EVP_SignInit_ex(&mctx, md, NULL)
|| !EVP_SignUpdate(&mctx, hdata, hdatalen)
|| !EVP_SignFinal(&mctx, p + 2, &u, pkey))
{
SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,
ERR_R_EVP_LIB);
goto err;
}
s2n(u,p);
n = u + 4;
if (!ssl3_digest_cached_records(s))
goto err;
}
else
#ifndef OPENSSL_NO_RSA #ifndef OPENSSL_NO_RSA
if (pkey->type == EVP_PKEY_RSA) if (pkey->type == EVP_PKEY_RSA)
{ {
@ -2960,9 +3007,11 @@ int ssl3_send_client_verify(SSL *s)
s->init_num=(int)n+4; s->init_num=(int)n+4;
s->init_off=0; s->init_off=0;
} }
EVP_MD_CTX_cleanup(&mctx);
EVP_PKEY_CTX_free(pctx); EVP_PKEY_CTX_free(pctx);
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
err: err:
EVP_MD_CTX_cleanup(&mctx);
EVP_PKEY_CTX_free(pctx); EVP_PKEY_CTX_free(pctx);
return(-1); return(-1);
} }