summaryrefslogtreecommitdiffstats
path: root/ssl/t1_enc.c
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2007-08-31 12:42:53 +0000
committerDr. Stephen Henson <steve@openssl.org>2007-08-31 12:42:53 +0000
commit81025661a94034fef1386cb5d5137ba4ddb120f0 (patch)
treecde73075708fe40deb5c7dfcd0c03861794599cf /ssl/t1_enc.c
parent4ece7eb6f4d396008d8b4ee6beb6dca409d84882 (diff)
Update ssl code to support digests other than MD5+SHA1 in handshake.
Submitted by: Victor B. Wagner <vitus@cryptocom.ru>
Diffstat (limited to 'ssl/t1_enc.c')
-rw-r--r--ssl/t1_enc.c99
1 files changed, 68 insertions, 31 deletions
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
index 7a4e2ce076..80cfe44a02 100644
--- a/ssl/t1_enc.c
+++ b/ssl/t1_enc.c
@@ -190,27 +190,41 @@ static void tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
OPENSSL_cleanse(A1,sizeof(A1));
}
-static void tls1_PRF(const EVP_MD *md5, const EVP_MD *sha1,
+static void tls1_PRF(long digest_mask,
unsigned char *label, int label_len,
const unsigned char *sec, int slen, unsigned char *out1,
unsigned char *out2, int olen)
{
- int len,i;
- const unsigned char *S1,*S2;
-
- len=slen/2;
+ int len,i,idx,count;
+ const unsigned char *S1;
+ long m;
+ const EVP_MD *md;
+
+ /* Count number of digests and divide sec evenly */
+ count=0;
+ for (idx=0;ssl_get_handshake_digest(idx,&m,&md);idx++) {
+ if ((m<<TLS1_PRF_DGST_SHIFT) & digest_mask) count++;
+ }
+ len=slen/count;
S1=sec;
- S2= &(sec[len]);
- len+=(slen&1); /* add for odd, make longer */
-
-
- tls1_P_hash(md5 ,S1,len,label,label_len,out1,olen);
- tls1_P_hash(sha1,S2,len,label,label_len,out2,olen);
-
- for (i=0; i<olen; i++)
- out1[i]^=out2[i];
+ memset(out1,0,olen);
+ for (idx=0;ssl_get_handshake_digest(idx,&m,&md);idx++) {
+ if ((m<<TLS1_PRF_DGST_SHIFT) & digest_mask) {
+ if (!md) {
+ SSLerr(SSL_F_TLS1_PRF,
+ SSL_R_UNSUPPORTED_DIGEST_TYPE);
+ return;
+ }
+ tls1_P_hash(md ,S1,len+(slen&1),label,label_len,out2,olen);
+ S1+=len;
+ for (i=0; i<olen; i++)
+ {
+ out1[i]^=out2[i];
+ }
+ }
}
+}
static void tls1_generate_key_block(SSL *s, unsigned char *km,
unsigned char *tmp, int num)
{
@@ -227,7 +241,7 @@ static void tls1_generate_key_block(SSL *s, unsigned char *km,
memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);
p+=SSL3_RANDOM_SIZE;
- tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,(int)(p-buf),
+ tls1_PRF(s->s3->tmp.new_cipher->algorithm2,buf,(int)(p-buf),
s->session->master_key,s->session->master_key_length,
km,tmp,num);
#ifdef KSSL_DEBUG
@@ -436,7 +450,7 @@ printf("which = %04X\nmac key=",which);
p+=SSL3_RANDOM_SIZE;
memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);
p+=SSL3_RANDOM_SIZE;
- tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,(int)(p-buf),key,j,
+ tls1_PRF(s->s3->tmp.new_cipher->algorithm2,buf,(int)(p-buf),key,j,
tmp1,tmp2,EVP_CIPHER_key_length(c));
key=tmp1;
@@ -450,7 +464,7 @@ printf("which = %04X\nmac key=",which);
p+=SSL3_RANDOM_SIZE;
memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);
p+=SSL3_RANDOM_SIZE;
- tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,p-buf,empty,0,
+ tls1_PRF(s->s3->tmp.new_cipher->algorithm2,buf,p-buf,empty,0,
iv1,iv2,k*2);
if (client_write)
iv=iv1;
@@ -720,40 +734,63 @@ int tls1_enc(SSL *s, int send)
}
return(1);
}
-
-int tls1_cert_verify_mac(SSL *s, EVP_MD_CTX *in_ctx, unsigned char *out)
+int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *out)
{
unsigned int ret;
- EVP_MD_CTX ctx;
+ EVP_MD_CTX ctx, *d=NULL;
+ int i;
+
+ if (s->s3->handshake_buffer)
+ ssl3_digest_cached_records(s);
+ for (i=0;i<SSL_MAX_DIGEST;i++)
+ {
+ if (s->s3->handshake_dgst[i]&&EVP_MD_CTX_type(s->s3->handshake_dgst[i])==md_nid)
+ {
+ d=s->s3->handshake_dgst[i];
+ break;
+ }
+ }
+ if (!d) {
+ SSLerr(SSL_F_TLS1_CERT_VERIFY_MAC,SSL_R_NO_REQUIRED_DIGEST);
+ return 0;
+ }
EVP_MD_CTX_init(&ctx);
- EVP_MD_CTX_copy_ex(&ctx,in_ctx);
+ EVP_MD_CTX_copy_ex(&ctx,d);
EVP_DigestFinal_ex(&ctx,out,&ret);
EVP_MD_CTX_cleanup(&ctx);
return((int)ret);
}
-int tls1_final_finish_mac(SSL *s, EVP_MD_CTX *in1_ctx, EVP_MD_CTX *in2_ctx,
+int tls1_final_finish_mac(SSL *s,
const char *str, int slen, unsigned char *out)
{
unsigned int i;
EVP_MD_CTX ctx;
unsigned char buf[TLS_MD_MAX_CONST_SIZE+MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
unsigned char *q,buf2[12];
+ int idx;
+ long mask;
+ const EVP_MD *md;
q=buf;
memcpy(q,str,slen);
q+=slen;
EVP_MD_CTX_init(&ctx);
- EVP_MD_CTX_copy_ex(&ctx,in1_ctx);
- EVP_DigestFinal_ex(&ctx,q,&i);
- q+=i;
- EVP_MD_CTX_copy_ex(&ctx,in2_ctx);
- EVP_DigestFinal_ex(&ctx,q,&i);
- q+=i;
-
- tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,(int)(q-buf),
+
+ if (s->s3->handshake_buffer)
+ ssl3_digest_cached_records(s);
+
+ for (idx=0;ssl_get_handshake_digest(idx,&mask,&md);idx++) {
+ if (mask & s->s3->tmp.new_cipher->algorithm2) {
+ EVP_MD_CTX_copy_ex(&ctx,s->s3->handshake_dgst[idx]);
+ EVP_DigestFinal_ex(&ctx,q,&i);
+ q+=i;
+ }
+ }
+
+ tls1_PRF(s->s3->tmp.new_cipher->algorithm2,buf,(int)(q-buf),
s->session->master_key,s->session->master_key_length,
out,buf2,sizeof buf2);
EVP_MD_CTX_cleanup(&ctx);
@@ -853,7 +890,7 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
s->s3->client_random,SSL3_RANDOM_SIZE);
memcpy(&(buf[SSL3_RANDOM_SIZE+TLS_MD_MASTER_SECRET_CONST_SIZE]),
s->s3->server_random,SSL3_RANDOM_SIZE);
- tls1_PRF(s->ctx->md5,s->ctx->sha1,
+ tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
buf,TLS_MD_MASTER_SECRET_CONST_SIZE+SSL3_RANDOM_SIZE*2,p,len,
s->session->master_key,buff,sizeof buff);
#ifdef KSSL_DEBUG