Fix sign-compare warnings.
[openssl.git] / ssl / t1_enc.c
index 4baea2dc672464f1be7192b9347bf85f1952d9ce..d9b93f585714553a0f50137596cb4dc7fc0a34cf 100644 (file)
@@ -56,7 +56,7 @@
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
- * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #include <stdio.h>
 #include "ssl_locl.h"
+#ifndef OPENSSL_NO_COMP
 #include <openssl/comp.h>
+#endif
 #include <openssl/evp.h>
 #include <openssl/hmac.h>
 #include <openssl/md5.h>
+#ifdef KSSL_DEBUG
+#include <openssl/des.h>
+#endif
 
+/* seed1 through seed5 are virtually concatenated */
 static void tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
-                       int sec_len, unsigned char *seed, int seed_len,
+                       int sec_len,
+                       const void *seed1, int seed1_len,
+                       const void *seed2, int seed2_len,
+                       const void *seed3, int seed3_len,
+                       const void *seed4, int seed4_len,
+                       const void *seed5, int seed5_len,
                        unsigned char *out, int olen)
        {
        int chunk,n;
@@ -154,12 +165,17 @@ static void tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
        unsigned int A1_len;
        
        chunk=EVP_MD_size(md);
+       OPENSSL_assert(chunk >= 0);
 
        HMAC_CTX_init(&ctx);
        HMAC_CTX_init(&ctx_tmp);
        HMAC_Init_ex(&ctx,sec,sec_len,md, NULL);
        HMAC_Init_ex(&ctx_tmp,sec,sec_len,md, NULL);
-       HMAC_Update(&ctx,seed,seed_len);
+       if (seed1 != NULL) HMAC_Update(&ctx,seed1,seed1_len);
+       if (seed2 != NULL) HMAC_Update(&ctx,seed2,seed2_len);
+       if (seed3 != NULL) HMAC_Update(&ctx,seed3,seed3_len);
+       if (seed4 != NULL) HMAC_Update(&ctx,seed4,seed4_len);
+       if (seed5 != NULL) HMAC_Update(&ctx,seed5,seed5_len);
        HMAC_Final(&ctx,A1,&A1_len);
 
        n=0;
@@ -169,7 +185,11 @@ static void tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
                HMAC_Init_ex(&ctx_tmp,NULL,0,NULL,NULL); /* re-init */
                HMAC_Update(&ctx,A1,A1_len);
                HMAC_Update(&ctx_tmp,A1,A1_len);
-               HMAC_Update(&ctx,seed,seed_len);
+               if (seed1 != NULL) HMAC_Update(&ctx,seed1,seed1_len);
+               if (seed2 != NULL) HMAC_Update(&ctx,seed2,seed2_len);
+               if (seed3 != NULL) HMAC_Update(&ctx,seed3,seed3_len);
+               if (seed4 != NULL) HMAC_Update(&ctx,seed4,seed4_len);
+               if (seed5 != NULL) HMAC_Update(&ctx,seed5,seed5_len);
 
                if (olen > chunk)
                        {
@@ -190,44 +210,57 @@ 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,
-                    unsigned char *label, int label_len,
-                    const unsigned char *sec, int slen, unsigned char *out1,
+/* seed1 through seed5 are virtually concatenated */
+static void tls1_PRF(long digest_mask,
+                    const void *seed1, int seed1_len,
+                    const void *seed2, int seed2_len,
+                    const void *seed3, int seed3_len,
+                    const void *seed4, int seed4_len,
+                    const void *seed5, int seed5_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 partition 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),
+                                   seed1,seed1_len,seed2,seed2_len,seed3,seed3_len,seed4,seed4_len,seed5,seed5_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)
        {
-       unsigned char *p;
-       unsigned char buf[SSL3_RANDOM_SIZE*2+
-               TLS_MD_MAX_CONST_SIZE];
-       p=buf;
-
-       memcpy(p,TLS_MD_KEY_EXPANSION_CONST,
-               TLS_MD_KEY_EXPANSION_CONST_SIZE);
-       p+=TLS_MD_KEY_EXPANSION_CONST_SIZE;
-       memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);
-       p+=SSL3_RANDOM_SIZE;
-       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,
+                TLS_MD_KEY_EXPANSION_CONST,TLS_MD_KEY_EXPANSION_CONST_SIZE,
+                s->s3->server_random,SSL3_RANDOM_SIZE,
+                s->s3->client_random,SSL3_RANDOM_SIZE,
+                NULL,0,NULL,0,
                 s->session->master_key,s->session->master_key_length,
                 km,tmp,num);
 #ifdef KSSL_DEBUG
@@ -247,8 +280,7 @@ int tls1_change_cipher_state(SSL *s, int which)
        {
        static const unsigned char empty[]="";
        unsigned char *p,*key_block,*mac_secret;
-       unsigned char *exp_label,buf[TLS_MD_MAX_CONST_SIZE+
-               SSL3_RANDOM_SIZE*2];
+       unsigned char *exp_label;
        unsigned char tmp1[EVP_MAX_KEY_LENGTH];
        unsigned char tmp2[EVP_MAX_KEY_LENGTH];
        unsigned char iv1[EVP_MAX_IV_LENGTH*2];
@@ -261,12 +293,17 @@ int tls1_change_cipher_state(SSL *s, int which)
        const SSL_COMP *comp;
 #endif
        const EVP_MD *m;
+       int mac_type;
+       int *mac_secret_size;
+       EVP_MD_CTX *mac_ctx;
+       EVP_PKEY *mac_key;
        int is_export,n,i,j,k,exp_label_len,cl;
        int reuse_dd = 0;
 
        is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher);
        c=s->s3->tmp.new_sym_enc;
        m=s->s3->tmp.new_hash;
+       mac_type = s->s3->tmp.new_mac_pkey_type;
 #ifndef OPENSSL_NO_COMP
        comp=s->s3->tmp.new_compression;
 #endif
@@ -274,8 +311,10 @@ int tls1_change_cipher_state(SSL *s, int which)
 
 #ifdef KSSL_DEBUG
        printf("tls1_change_cipher_state(which= %d) w/\n", which);
-       printf("\talg= %ld, comp= %p\n", s->s3->tmp.new_cipher->algorithms,
-                comp);
+       printf("\talg= %ld/%ld, comp= %p\n",
+              s->s3->tmp.new_cipher->algorithm_mkey,
+              s->s3->tmp.new_cipher->algorithm_auth,
+              comp);
        printf("\tevp_cipher == %p ==? &d_cbc_ede_cipher3\n", c);
        printf("\tevp_cipher: nid, blksz= %d, %d, keylen=%d, ivlen=%d\n",
                 c->nid,c->block_size,c->key_len,c->iv_len);
@@ -289,12 +328,20 @@ int tls1_change_cipher_state(SSL *s, int which)
 
        if (which & SSL3_CC_READ)
                {
+               if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC)
+                       s->mac_flags |= SSL_MAC_FLAG_READ_MAC_STREAM;
+                       else
+                       s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM;
+
                if (s->enc_read_ctx != NULL)
                        reuse_dd = 1;
                else if ((s->enc_read_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)
                        goto err;
+               else
+                       /* make sure it's intialized in case we exit later with an error */
+                       EVP_CIPHER_CTX_init(s->enc_read_ctx);
                dd= s->enc_read_ctx;
-               s->read_hash=m;
+               mac_ctx=ssl_replace_hash(&s->read_hash,NULL);
 #ifndef OPENSSL_NO_COMP
                if (s->expand != NULL)
                        {
@@ -320,19 +367,23 @@ int tls1_change_cipher_state(SSL *s, int which)
                if (s->version != DTLS1_VERSION)
                        memset(&(s->s3->read_sequence[0]),0,8);
                mac_secret= &(s->s3->read_mac_secret[0]);
+               mac_secret_size=&(s->s3->read_mac_secret_size);
                }
        else
                {
+               if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC)
+                       s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM;
+                       else
+                       s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_STREAM;
                if (s->enc_write_ctx != NULL)
                        reuse_dd = 1;
                else if ((s->enc_write_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)
                        goto err;
-               if ((s->enc_write_ctx == NULL) &&
-                       ((s->enc_write_ctx=(EVP_CIPHER_CTX *)
-                       OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL))
-                       goto err;
+               else
+                       /* make sure it's intialized in case we exit later with an error */
+                       EVP_CIPHER_CTX_init(s->enc_write_ctx);
                dd= s->enc_write_ctx;
-               s->write_hash=m;
+               mac_ctx = ssl_replace_hash(&s->write_hash,NULL);
 #ifndef OPENSSL_NO_COMP
                if (s->compress != NULL)
                        {
@@ -353,14 +404,15 @@ int tls1_change_cipher_state(SSL *s, int which)
                if (s->version != DTLS1_VERSION)
                        memset(&(s->s3->write_sequence[0]),0,8);
                mac_secret= &(s->s3->write_mac_secret[0]);
+               mac_secret_size = &(s->s3->write_mac_secret_size);
                }
 
        if (reuse_dd)
                EVP_CIPHER_CTX_cleanup(dd);
-       EVP_CIPHER_CTX_init(dd);
 
        p=s->s3->tmp.key_block;
-       i=EVP_MD_size(m);
+       i=*mac_secret_size=s->s3->tmp.new_mac_secret_size;
+
        cl=EVP_CIPHER_key_length(c);
        j=is_export ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ?
                       cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl;
@@ -396,6 +448,10 @@ int tls1_change_cipher_state(SSL *s, int which)
                }
 
        memcpy(mac_secret,ms,i);
+       mac_key = EVP_PKEY_new_mac_key(mac_type, NULL,
+                       mac_secret,*mac_secret_size);
+       EVP_DigestSignInit(mac_ctx,NULL,m,NULL,mac_key);
+       EVP_PKEY_free(mac_key);
 #ifdef TLS_DEBUG
 printf("which = %04X\nmac key=",which);
 { int z; for (z=0; z<i; z++) printf("%02X%c",ms[z],((z+1)%16)?' ':'\n'); }
@@ -405,29 +461,22 @@ printf("which = %04X\nmac key=",which);
                /* In here I set both the read and write key/iv to the
                 * same value since only the correct one will be used :-).
                 */
-               p=buf;
-               memcpy(p,exp_label,exp_label_len);
-               p+=exp_label_len;
-               memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);
-               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,
-                        tmp1,tmp2,EVP_CIPHER_key_length(c));
+               tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
+                        exp_label,exp_label_len,
+                        s->s3->client_random,SSL3_RANDOM_SIZE,
+                        s->s3->server_random,SSL3_RANDOM_SIZE,
+                        NULL,0,NULL,0,
+                        key,j,tmp1,tmp2,EVP_CIPHER_key_length(c));
                key=tmp1;
 
                if (k > 0)
                        {
-                       p=buf;
-                       memcpy(p,TLS_MD_IV_BLOCK_CONST,
-                               TLS_MD_IV_BLOCK_CONST_SIZE);
-                       p+=TLS_MD_IV_BLOCK_CONST_SIZE;
-                       memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);
-                       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,
-                                iv1,iv2,k*2);
+                       tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
+                                TLS_MD_IV_BLOCK_CONST,TLS_MD_IV_BLOCK_CONST_SIZE,
+                                s->s3->client_random,SSL3_RANDOM_SIZE,
+                                s->s3->server_random,SSL3_RANDOM_SIZE,
+                                NULL,0,NULL,0,
+                                empty,0,iv1,iv2,k*2);
                        if (client_write)
                                iv=iv1;
                        else
@@ -474,6 +523,7 @@ int tls1_setup_key_block(SSL *s)
        const EVP_MD *hash;
        int num;
        SSL_COMP *comp;
+       int mac_type= NID_undef,mac_secret_size=0;
 
 #ifdef KSSL_DEBUG
        printf ("tls1_setup_key_block()\n");
@@ -482,7 +532,7 @@ int tls1_setup_key_block(SSL *s)
        if (s->s3->tmp.key_block_length != 0)
                return(1);
 
-       if (!ssl_cipher_get_evp(s->session,&c,&hash,&comp))
+       if (!ssl_cipher_get_evp(s->session,&c,&hash,&mac_type,&mac_secret_size,&comp))
                {
                SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
                return(0);
@@ -490,8 +540,9 @@ int tls1_setup_key_block(SSL *s)
 
        s->s3->tmp.new_sym_enc=c;
        s->s3->tmp.new_hash=hash;
-
-       num=EVP_CIPHER_key_length(c)+EVP_MD_size(hash)+EVP_CIPHER_iv_length(c);
+       s->s3->tmp.new_mac_pkey_type = mac_type;
+       s->s3->tmp.new_mac_secret_size = mac_secret_size;
+       num=EVP_CIPHER_key_length(c)+mac_secret_size+EVP_CIPHER_iv_length(c);
        num*=2;
 
        ssl3_cleanup_key_block(s);
@@ -530,11 +581,11 @@ printf("\nkey block\n");
 
                if (s->session->cipher != NULL)
                        {
-                       if ((s->session->cipher->algorithms & SSL_ENC_MASK) == SSL_eNULL)
+                       if (s->session->cipher->algorithm_enc == SSL_eNULL)
                                s->s3->need_empty_fragments = 0;
                        
 #ifndef OPENSSL_NO_RC4
-                       if ((s->session->cipher->algorithms & SSL_ENC_MASK) == SSL_RC4)
+                       if (s->session->cipher->algorithm_enc == SSL_RC4)
                                s->s3->need_empty_fragments = 0;
 #endif
                        }
@@ -556,8 +607,11 @@ int tls1_enc(SSL *s, int send)
 
        if (send)
                {
-               if (s->write_hash != NULL)
-                       n=EVP_MD_size(s->write_hash);
+               if (EVP_MD_CTX_md(s->write_hash))
+                       {
+                       n=EVP_MD_CTX_size(s->write_hash);
+                       OPENSSL_assert(n >= 0);
+                       }
                ds=s->enc_write_ctx;
                rec= &(s->s3->wrec);
                if (s->enc_write_ctx == NULL)
@@ -567,8 +621,11 @@ int tls1_enc(SSL *s, int send)
                }
        else
                {
-               if (s->read_hash != NULL)
-                       n=EVP_MD_size(s->read_hash);
+               if (EVP_MD_CTX_md(s->read_hash))
+                       {
+                       n=EVP_MD_CTX_size(s->read_hash);
+                       OPENSSL_assert(n >= 0);
+                       }
                ds=s->enc_read_ctx;
                rec= &(s->s3->rrec);
                if (s->enc_read_ctx == NULL)
@@ -694,56 +751,100 @@ 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) 
+               if (!ssl3_digest_cached_records(s))
+                       return 0;
+
+       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 buf[2*EVP_MAX_MD_SIZE];
        unsigned char *q,buf2[12];
+       int idx;
+       long mask;
+       int err=0;
+       const EVP_MD *md; 
 
        q=buf;
-       memcpy(q,str,slen);
-       q+=slen;
+
+       if (s->s3->handshake_buffer) 
+               if (!ssl3_digest_cached_records(s))
+                       return 0;
 
        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),
-               s->session->master_key,s->session->master_key_length,
-               out,buf2,sizeof buf2);
+
+       for (idx=0;ssl_get_handshake_digest(idx,&mask,&md);idx++)
+               {
+               if (mask & s->s3->tmp.new_cipher->algorithm2)
+                       {
+                       unsigned int hashsize = EVP_MD_size(md);
+                       if (hashsize < 0 || hashsize > (sizeof buf - (size_t)(q-buf)))
+                               {
+                               /* internal error: 'buf' is too small for this cipersuite! */
+                               err = 1;
+                               }
+                       else
+                               {
+                               EVP_MD_CTX_copy_ex(&ctx,s->s3->handshake_dgst[idx]);
+                               EVP_DigestFinal_ex(&ctx,q,&i);
+                               if (i != hashsize) /* can't really happen */
+                                       err = 1;
+                               q+=i;
+                               }
+                       }
+               }
+               
+       tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
+                str,slen, buf,(int)(q-buf), NULL,0, NULL,0, NULL,0,
+                s->session->master_key,s->session->master_key_length,
+                out,buf2,sizeof buf2);
        EVP_MD_CTX_cleanup(&ctx);
 
-       return sizeof buf2;
+       if (err)
+               return 0;
+       else
+               return sizeof buf2;
        }
 
 int tls1_mac(SSL *ssl, unsigned char *md, int send)
        {
        SSL3_RECORD *rec;
        unsigned char *mac_sec,*seq;
-       const EVP_MD *hash;
-       unsigned int md_size;
+       EVP_MD_CTX *hash;
+       size_t md_size;
        int i;
-       HMAC_CTX hmac;
+       EVP_MD_CTX hmac, *mac_ctx;
        unsigned char buf[5]; 
+       int stream_mac = (send?(ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM):(ssl->mac_flags&SSL_MAC_FLAG_READ_MAC_STREAM));
+       int t;
 
        if (send)
                {
@@ -760,23 +861,45 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send)
                hash=ssl->read_hash;
                }
 
-       md_size=EVP_MD_size(hash);
+       t=EVP_MD_CTX_size(hash);
+       OPENSSL_assert(t >= 0);
+       md_size=t;
 
        buf[0]=rec->type;
-       buf[1]=TLS1_VERSION_MAJOR;
-       buf[2]=TLS1_VERSION_MINOR;
+       buf[1]=(unsigned char)(ssl->version>>8);
+       buf[2]=(unsigned char)(ssl->version);
        buf[3]=rec->length>>8;
        buf[4]=rec->length&0xff;
 
        /* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */
-       HMAC_CTX_init(&hmac);
-       HMAC_Init_ex(&hmac,mac_sec,EVP_MD_size(hash),hash,NULL);
-       HMAC_Update(&hmac,seq,8);
-       HMAC_Update(&hmac,buf,5);
-       HMAC_Update(&hmac,rec->input,rec->length);
-       HMAC_Final(&hmac,md,&md_size);
-       HMAC_CTX_cleanup(&hmac);
+       if (stream_mac) 
+               {
+                       mac_ctx = hash;
+               }
+               else
+               {
+                       EVP_MD_CTX_copy(&hmac,hash);
+                       mac_ctx = &hmac;
+               }
+
+       if (ssl->version == DTLS1_VERSION)
+               {
+               unsigned char dtlsseq[8],*p=dtlsseq;
+
+               s2n(send?ssl->d1->w_epoch:ssl->d1->r_epoch, p);
+               memcpy (p,&seq[2],6);
+
+               EVP_DigestSignUpdate(mac_ctx,dtlsseq,8);
+               }
+       else
+               EVP_DigestSignUpdate(mac_ctx,seq,8);
 
+       EVP_DigestSignUpdate(mac_ctx,buf,5);
+       EVP_DigestSignUpdate(mac_ctx,rec->input,rec->length);
+       t=EVP_DigestSignFinal(mac_ctx,md,&md_size);
+       OPENSSL_assert(t > 0);
+               
+       if (!stream_mac) EVP_MD_CTX_cleanup(&hmac);
 #ifdef TLS_DEBUG
 printf("sec=");
 {unsigned int z; for (z=0; z<md_size; z++) printf("%02X ",mac_sec[z]); printf("\n"); }
@@ -788,8 +911,8 @@ printf("rec=");
 {unsigned int z; for (z=0; z<rec->length; z++) printf("%02X ",buf[z]); printf("\n"); }
 #endif
 
-    if ( SSL_version(ssl) != DTLS1_VERSION)
-           {
+       if (ssl->version != DTLS1_VERSION)
+               {
                for (i=7; i>=0; i--)
                        {
                        ++seq[i];
@@ -806,23 +929,35 @@ printf("rec=");
 int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
             int len)
        {
-       unsigned char buf[SSL3_RANDOM_SIZE*2+TLS_MD_MASTER_SECRET_CONST_SIZE];
        unsigned char buff[SSL_MAX_MASTER_KEY_LENGTH];
+       const void *co = NULL, *so = NULL;
+       int col = 0, sol = 0;
 
 #ifdef KSSL_DEBUG
        printf ("tls1_generate_master_secret(%p,%p, %p, %d)\n", s,out, p,len);
 #endif /* KSSL_DEBUG */
 
-       /* Setup the stuff to munge */
-       memcpy(buf,TLS_MD_MASTER_SECRET_CONST,
-               TLS_MD_MASTER_SECRET_CONST_SIZE);
-       memcpy(&(buf[TLS_MD_MASTER_SECRET_CONST_SIZE]),
-               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,
-               buf,TLS_MD_MASTER_SECRET_CONST_SIZE+SSL3_RANDOM_SIZE*2,p,len,
+#ifdef TLSEXT_TYPE_opaque_prf_input
+       if (s->s3->client_opaque_prf_input != NULL && s->s3->server_opaque_prf_input != NULL &&
+           s->s3->client_opaque_prf_input_len > 0 &&
+           s->s3->client_opaque_prf_input_len == s->s3->server_opaque_prf_input_len)
+               {
+               co = s->s3->client_opaque_prf_input;
+               col = s->s3->server_opaque_prf_input_len;
+               so = s->s3->server_opaque_prf_input;
+               sol = s->s3->client_opaque_prf_input_len; /* must be same as col (see draft-rescorla-tls-opaque-prf-input-00.txt, section 3.1) */
+               }
+#endif
+
+       tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
+               TLS_MD_MASTER_SECRET_CONST,TLS_MD_MASTER_SECRET_CONST_SIZE,
+               s->s3->client_random,SSL3_RANDOM_SIZE,
+               co, col,
+               s->s3->server_random,SSL3_RANDOM_SIZE,
+               so, sol,
+               p,len,
                s->session->master_key,buff,sizeof buff);
+
 #ifdef KSSL_DEBUG
        printf ("tls1_generate_master_secret() complete\n");
 #endif /* KSSL_DEBUG */