Update ssl library to support EVP_PKEY MAC API. Include generic MAC support.
authorDr. Stephen Henson <steve@openssl.org>
Mon, 4 Jun 2007 17:04:40 +0000 (17:04 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Mon, 4 Jun 2007 17:04:40 +0000 (17:04 +0000)
18 files changed:
CHANGES
ssl/d1_enc.c
ssl/d1_pkt.c
ssl/s2_clnt.c
ssl/s2_enc.c
ssl/s2_pkt.c
ssl/s2_srvr.c
ssl/s3_enc.c
ssl/s3_lib.c
ssl/s3_pkt.c
ssl/ssl.h
ssl/ssl3.h
ssl/ssl_ciph.c
ssl/ssl_lib.c
ssl/ssl_locl.h
ssl/ssl_txt.c
ssl/t1_enc.c
ssl/tls1.h

diff --git a/CHANGES b/CHANGES
index 0a383b4..6af082f 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,11 @@
 
  Changes between 0.9.8f and 0.9.9  [xx XXX xxxx]
 
+  *) Update SSL library to use new EVP_PKEY MAC API. Include generic MAC
+     support including streaming MAC support: this is required for GOST
+     ciphersuite support.
+     [Victor B. Wagner <vitus@cryptocom.ru>, Steve Henson]
+
   *) Add option -stream to use PKCS#7 streaming in smime utility. New
      function i2d_PKCS7_bio_stream() and PEM_write_PKCS7_bio_stream()
      to output in BER and PEM format.
index cbff749..ef4d880 100644 (file)
@@ -132,8 +132,8 @@ int dtls1_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);
                ds=s->enc_write_ctx;
                rec= &(s->s3->wrec);
                if (s->enc_write_ctx == NULL)
@@ -154,8 +154,8 @@ int dtls1_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);
                ds=s->enc_read_ctx;
                rec= &(s->s3->rrec);
                if (s->enc_read_ctx == NULL)
index 8a047ae..bf189f1 100644 (file)
@@ -426,7 +426,7 @@ printf("\n");
 
        if (!clear)
                {
-               mac_size=EVP_MD_size(s->read_hash);
+               mac_size=EVP_MD_CTX_size(s->read_hash);
 
                if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+mac_size)
                        {
@@ -1335,13 +1335,13 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len,
 
        if (    (sess == NULL) ||
                (s->enc_write_ctx == NULL) ||
-               (s->write_hash == NULL))
+               (EVP_MD_CTX_md(s->write_hash) == NULL))
                clear=1;
 
        if (clear)
                mac_size=0;
        else
-               mac_size=EVP_MD_size(s->write_hash);
+               mac_size=EVP_MD_CTX_size(s->write_hash);
 
        /* DTLS implements explicit IV, so no need for empty fragments */
 #if 0
index 6d8883f..7b3b7d8 100644 (file)
@@ -621,7 +621,7 @@ static int client_master_key(SSL *s)
        if (s->state == SSL2_ST_SEND_CLIENT_MASTER_KEY_A)
                {
 
-               if (!ssl_cipher_get_evp(s->session,&c,&md,NULL))
+               if (!ssl_cipher_get_evp(s->session,&c,&md,NULL,NULL,NULL))
                        {
                        ssl2_return_error(s,SSL2_PE_NO_CIPHER);
                        SSLerr(SSL_F_CLIENT_MASTER_KEY,SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS);
index 1f62acd..ff3395f 100644 (file)
@@ -68,15 +68,14 @@ int ssl2_enc_init(SSL *s, int client)
        const EVP_MD *md;
        int num;
 
-       if (!ssl_cipher_get_evp(s->session,&c,&md,NULL))
+       if (!ssl_cipher_get_evp(s->session,&c,&md,NULL,NULL,NULL))
                {
                ssl2_return_error(s,SSL2_PE_NO_CIPHER);
                SSLerr(SSL_F_SSL2_ENC_INIT,SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS);
                return(0);
                }
-
-       s->read_hash=md;
-       s->write_hash=md;
+       ssl_replace_hash(&s->read_hash,md);
+       ssl_replace_hash(&s->write_hash,md);
 
        if ((s->enc_read_ctx == NULL) &&
                ((s->enc_read_ctx=(EVP_CIPHER_CTX *)
@@ -176,7 +175,7 @@ void ssl2_mac(SSL *s, unsigned char *md, int send)
 
        /* There has to be a MAC algorithm. */
        EVP_MD_CTX_init(&c);
-       EVP_DigestInit_ex(&c, s->read_hash, NULL);
+       EVP_MD_CTX_copy(&c, s->read_hash);
        EVP_DigestUpdate(&c,sec,
                EVP_CIPHER_CTX_key_length(s->enc_read_ctx));
        EVP_DigestUpdate(&c,act,len); 
index a10929a..e6d5d09 100644 (file)
@@ -246,7 +246,7 @@ static int ssl2_read_internal(SSL *s, void *buf, int len, int peek)
                        }
                else
                        {
-                       mac_size=EVP_MD_size(s->read_hash);
+                       mac_size=EVP_MD_CTX_size(s->read_hash);
                        OPENSSL_assert(mac_size <= MAX_MAC_SIZE);
                        s->s2->mac_data=p;
                        s->s2->ract_data= &p[mac_size];
@@ -529,7 +529,7 @@ static int do_ssl_write(SSL *s, const unsigned char *buf, unsigned int len)
        if (s->s2->clear_text)
                mac_size=0;
        else
-               mac_size=EVP_MD_size(s->write_hash);
+               mac_size=EVP_MD_CTX_size(s->write_hash);
 
        /* lets set the pad p */
        if (s->s2->clear_text)
index 4594324..44c1ee3 100644 (file)
@@ -451,7 +451,7 @@ static int get_client_master_key(SSL *s)
 
        is_export=SSL_C_IS_EXPORT(s->session->cipher);
        
-       if (!ssl_cipher_get_evp(s->session,&c,&md,NULL))
+       if (!ssl_cipher_get_evp(s->session,&c,&md,NULL,NULL,NULL))
                {
                ssl2_return_error(s,SSL2_PE_NO_CIPHER);
                SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS);
index 8f3ba93..010069b 100644 (file)
@@ -251,7 +251,8 @@ int ssl3_change_cipher_state(SSL *s, int which)
                        /* 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;
+
+               ssl_replace_hash(&s->read_hash,m);
 #ifndef OPENSSL_NO_COMP
                /* COMPRESS */
                if (s->expand != NULL)
@@ -287,7 +288,7 @@ int ssl3_change_cipher_state(SSL *s, int which)
                        /* 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;
+               ssl_replace_hash(&s->write_hash,m);
 #ifndef OPENSSL_NO_COMP
                /* COMPRESS */
                if (s->compress != NULL)
@@ -394,7 +395,7 @@ int ssl3_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,NULL,NULL,&comp))
                {
                SSLerr(SSL_F_SSL3_SETUP_KEY_BLOCK,SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
                return(0);
@@ -581,7 +582,6 @@ static int ssl3_handshake_mac(SSL *s, EVP_MD_CTX *in_ctx,
 
        EVP_MD_CTX_init(&ctx);
        EVP_MD_CTX_copy_ex(&ctx,in_ctx);
-
        n=EVP_MD_CTX_size(&ctx);
        npad=(48/n)*n;
 
@@ -609,7 +609,7 @@ int ssl3_mac(SSL *ssl, unsigned char *md, int send)
        SSL3_RECORD *rec;
        unsigned char *mac_sec,*seq;
        EVP_MD_CTX md_ctx;
-       const EVP_MD *hash;
+       const EVP_MD_CTX *hash;
        unsigned char *p,rec_char;
        unsigned int md_size;
        int npad;
@@ -629,13 +629,13 @@ int ssl3_mac(SSL *ssl, unsigned char *md, int send)
                hash=ssl->read_hash;
                }
 
-       md_size=EVP_MD_size(hash);
+       md_size=EVP_MD_CTX_size(hash);
        npad=(48/md_size)*md_size;
 
        /* Chop the digest off the end :-) */
        EVP_MD_CTX_init(&md_ctx);
 
-       EVP_DigestInit_ex(  &md_ctx,hash, NULL);
+       EVP_MD_CTX_copy_ex( &md_ctx,hash);
        EVP_DigestUpdate(&md_ctx,mac_sec,md_size);
        EVP_DigestUpdate(&md_ctx,ssl3_pad_1,npad);
        EVP_DigestUpdate(&md_ctx,seq,8);
@@ -647,7 +647,7 @@ int ssl3_mac(SSL *ssl, unsigned char *md, int send)
        EVP_DigestUpdate(&md_ctx,rec->input,rec->length);
        EVP_DigestFinal_ex( &md_ctx,md,NULL);
 
-       EVP_DigestInit_ex(  &md_ctx,hash, NULL);
+       EVP_MD_CTX_copy_ex( &md_ctx,hash);
        EVP_DigestUpdate(&md_ctx,mac_sec,md_size);
        EVP_DigestUpdate(&md_ctx,ssl3_pad_2,npad);
        EVP_DigestUpdate(&md_ctx,md,md_size);
index 4ac6961..bd0056b 100644 (file)
@@ -1972,6 +1972,48 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
        256,
        256,
        },
+       {
+       1,
+       "GOST-GOST94",
+       0x0300ff01,
+       SSL_kRSA,
+       SSL_aRSA,
+       SSL_eGOST2814789CNT,
+       SSL_GOST94,
+       SSL_TLSV1,
+       SSL_NOT_EXP|SSL_HIGH,
+       0,
+       256,
+       256
+       },
+       {
+       1,
+       "GOST-GOST89MAC",
+       0x0300ff02,
+       SSL_kRSA,
+       SSL_aRSA,
+       SSL_eGOST2814789CNT,
+       SSL_GOST89MAC,
+       SSL_TLSV1,
+       SSL_NOT_EXP|SSL_HIGH,
+       0,
+       256,
+       256
+       },
+       {
+       1,
+       "GOST-GOST89STREAM",
+       0x0300ff03,
+       SSL_kRSA,
+       SSL_aRSA,
+       SSL_eGOST2814789CNT,
+       SSL_GOST89MAC,
+       SSL_TLSV1,
+       SSL_NOT_EXP|SSL_HIGH,
+       TLS1_STREAM_MAC,
+       256,
+       256
+       },
 #endif
 
 /* end of list */
index 6754e99..58f2845 100644 (file)
@@ -399,12 +399,12 @@ printf("\n");
        /* r->length is now the compressed data plus mac */
        if (    (sess == NULL) ||
                (s->enc_read_ctx == NULL) ||
-               (s->read_hash == NULL))
+               (EVP_MD_CTX_md(s->read_hash) == NULL))
                clear=1;
 
        if (!clear)
                {
-               mac_size=EVP_MD_size(s->read_hash);
+               mac_size=EVP_MD_CTX_size(s->read_hash);
 
                if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size)
                        {
@@ -629,13 +629,13 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
 
        if (    (sess == NULL) ||
                (s->enc_write_ctx == NULL) ||
-               (s->write_hash == NULL))
+               (EVP_MD_CTX_md(s->write_hash) == NULL))
                clear=1;
 
        if (clear)
                mac_size=0;
        else
-               mac_size=EVP_MD_size(s->write_hash);
+               mac_size=EVP_MD_CTX_size(s->write_hash);
 
        /* 'create_empty_fragment' is true only when this function calls itself */
        if (!clear && !create_empty_fragment && !s->s3->empty_fragment_done)
index abc3342..5702464 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -286,6 +286,8 @@ extern "C" {
 #define SSL_TXT_MD5            "MD5"
 #define SSL_TXT_SHA1           "SHA1"
 #define SSL_TXT_SHA            "SHA" /* same as "SHA1" */
+#define SSL_TXT_GOST94         "GOST94" 
+#define SSL_TXT_GOST89MAC              "GOST89MAC" 
 
 #define SSL_TXT_SSLV2          "SSLv2"
 #define SSL_TXT_SSLV3          "SSLv3"
@@ -884,6 +886,9 @@ const char *SSL_get_psk_identity(const SSL *s);
 #define SSL_want_write(s)      (SSL_want(s) == SSL_WRITING)
 #define SSL_want_x509_lookup(s)        (SSL_want(s) == SSL_X509_LOOKUP)
 
+#define SSL_MAC_FLAG_READ_MAC_STREAM 1
+#define SSL_MAC_FLAG_WRITE_MAC_STREAM 2
+
 struct ssl_st
        {
        /* protocol version
@@ -975,9 +980,9 @@ struct ssl_st
 
        /* These are the ones being used, the ones in SSL_SESSION are
         * the ones to be 'copied' into these ones */
-
+       int mac_flags; 
        EVP_CIPHER_CTX *enc_read_ctx;           /* cryptographic state */
-       const EVP_MD *read_hash;                /* used for mac generation */
+       EVP_MD_CTX *read_hash;          /* used for mac generation */
 #ifndef OPENSSL_NO_COMP
        COMP_CTX *expand;                       /* uncompress */
 #else
@@ -985,7 +990,7 @@ struct ssl_st
 #endif
 
        EVP_CIPHER_CTX *enc_write_ctx;          /* cryptographic state */
-       const EVP_MD *write_hash;               /* used for mac generation */
+       EVP_MD_CTX *write_hash;         /* used for mac generation */
 #ifndef OPENSSL_NO_COMP
        COMP_CTX *compress;                     /* compression */
 #else
index 5ddadb2..2d5db78 100644 (file)
@@ -382,8 +382,10 @@ typedef struct ssl3_state_st
        int delay_buf_pop_ret;
 
        unsigned char read_sequence[8];
+       int read_mac_secret_size;
        unsigned char read_mac_secret[EVP_MAX_MD_SIZE];
        unsigned char write_sequence[8];
+       int write_mac_secret_size;
        unsigned char write_mac_secret[EVP_MAX_MD_SIZE];
 
        unsigned char server_random[SSL3_RANDOM_SIZE];
@@ -480,6 +482,8 @@ typedef struct ssl3_state_st
 
                const EVP_CIPHER *new_sym_enc;
                const EVP_MD *new_hash;
+               int new_mac_pkey_type;
+               int new_mac_secret_size;
 #ifndef OPENSSL_NO_COMP
                const SSL_COMP *new_compression;
 #else
index 0a56042..d2e648b 100644 (file)
 #include <stdio.h>
 #include <openssl/objects.h>
 #include <openssl/comp.h>
+#include <openssl/engine.h>
 #include "ssl_locl.h"
 
 #define SSL_ENC_DES_IDX                0
@@ -172,9 +173,22 @@ static STACK_OF(SSL_COMP) *ssl_comp_methods=NULL;
 
 #define SSL_MD_MD5_IDX 0
 #define SSL_MD_SHA1_IDX        1
-#define SSL_MD_NUM_IDX 2
+#define SSL_MD_GOST94_IDX 2
+#define SSL_MD_GOST89MAC_IDX 3
+#define SSL_MD_NUM_IDX 4
 static const EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX]={
-       NULL,NULL,
+       NULL,NULL,NULL,NULL
+       };
+/* PKEY_TYPE for GOST89MAC is known in advance, but, because
+ * implementation is engine-provided, we'll fill it only if
+ * corresponding EVP_PKEY_METHOD is found 
+ */
+static int  ssl_mac_pkey_id[SSL_MD_NUM_IDX]={
+       EVP_PKEY_HMAC,EVP_PKEY_HMAC,EVP_PKEY_HMAC,NID_undef
+       };
+
+static int ssl_mac_secret_size[SSL_MD_NUM_IDX]={
+       0,0,0,0
        };
 
 #define CIPHER_ADD     1
@@ -266,6 +280,8 @@ static const SSL_CIPHER cipher_aliases[]={
        {0,SSL_TXT_MD5,0,     0,0,0,SSL_MD5,   0,0,0,0,0},
        {0,SSL_TXT_SHA1,0,    0,0,0,SSL_SHA1,  0,0,0,0,0},
        {0,SSL_TXT_SHA,0,     0,0,0,SSL_SHA1,  0,0,0,0,0},
+       {0,SSL_TXT_GOST94,0,     0,0,0,SSL_GOST94,  0,0,0,0,0},
+       {0,SSL_TXT_GOST89MAC,0,     0,0,0,SSL_GOST89MAC,  0,0,0,0,0},
 
        /* protocol version aliases */
        {0,SSL_TXT_SSLV2,0,   0,0,0,0,SSL_SSLV2, 0,0,0,0},
@@ -315,11 +331,36 @@ void ssl_load_ciphers(void)
 
        ssl_digest_methods[SSL_MD_MD5_IDX]=
                EVP_get_digestbyname(SN_md5);
+       ssl_mac_secret_size[SSL_MD_MD5_IDX]=
+               EVP_MD_size(ssl_digest_methods[SSL_MD_MD5_IDX]);
        ssl_digest_methods[SSL_MD_SHA1_IDX]=
                EVP_get_digestbyname(SN_sha1);
-       }
-
+       ssl_mac_secret_size[SSL_MD_SHA1_IDX]=
+               EVP_MD_size(ssl_digest_methods[SSL_MD_SHA1_IDX]);
+       ssl_digest_methods[SSL_MD_GOST94_IDX]=
+               EVP_get_digestbyname(SN_id_GostR3411_94);
+       if (ssl_digest_methods[SSL_MD_GOST94_IDX])
+               {       
+               ssl_mac_secret_size[SSL_MD_GOST94_IDX]=
+                       EVP_MD_size(ssl_digest_methods[SSL_MD_GOST94_IDX]);
+               }
+       ssl_digest_methods[SSL_MD_GOST89MAC_IDX]=
+               EVP_get_digestbyname(SN_id_Gost28147_89_MAC);
+               {
+               const EVP_PKEY_ASN1_METHOD *ameth;
+               ENGINE *tmpeng = NULL;
+               int pkey_id;
+               ameth = EVP_PKEY_asn1_find_str(&tmpeng,"gost-mac",-1);
+               if (ameth) 
+                       {
+                       EVP_PKEY_asn1_get0_info(&pkey_id, NULL,NULL,NULL,NULL,ameth);
+                       ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX]= pkey_id;
+                       ssl_mac_secret_size[SSL_MD_GOST89MAC_IDX]=32;
+                       }               
+               if (tmpeng) ENGINE_finish(tmpeng);      
+               }
 
+       }
 #ifndef OPENSSL_NO_COMP
 
 static int sk_comp_cmp(const SSL_COMP * const *a,
@@ -374,7 +415,7 @@ static void load_builtin_compressions(void)
 #endif
 
 int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
-            const EVP_MD **md, SSL_COMP **comp)
+            const EVP_MD **md, int *mac_pkey_type, int *mac_secret_size,SSL_COMP **comp)
        {
        int i;
        SSL_CIPHER *c;
@@ -463,16 +504,31 @@ int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
        case SSL_SHA1:
                i=SSL_MD_SHA1_IDX;
                break;
+       case SSL_GOST94:
+               i = SSL_MD_GOST94_IDX;
+               break;
+       case SSL_GOST89MAC:
+               i = SSL_MD_GOST89MAC_IDX;
+               break;
        default:
                i= -1;
                break;
                }
        if ((i < 0) || (i > SSL_MD_NUM_IDX))
-               *md=NULL;
+       {
+               *md=NULL; 
+               if (mac_pkey_type!=NULL) *mac_pkey_type = NID_undef;
+               if (mac_secret_size!=NULL) *mac_secret_size = 0;
+
+       }
        else
+       {
                *md=ssl_digest_methods[i];
+               if (mac_pkey_type!=NULL) *mac_pkey_type = ssl_mac_pkey_id[i];
+               if (mac_secret_size!=NULL) *mac_secret_size = ssl_mac_secret_size[i];
+       }       
 
-       if ((*enc != NULL) && (*md != NULL))
+       if ((*enc != NULL) && (*md != NULL) && (!mac_pkey_type||*mac_pkey_type != NID_undef))
                return(1);
        else
                return(0);
@@ -567,6 +623,9 @@ static void ssl_cipher_get_disabled(unsigned long *mkey, unsigned long *auth, un
 
        *mac |= (ssl_digest_methods[SSL_MD_MD5_IDX ] == NULL) ? SSL_MD5 :0;
        *mac |= (ssl_digest_methods[SSL_MD_SHA1_IDX] == NULL) ? SSL_SHA1:0;
+       *mac |= (ssl_digest_methods[SSL_MD_GOST94_IDX] == NULL) ? SSL_GOST94:0;
+       *mac |= (ssl_digest_methods[SSL_MD_GOST89MAC_IDX] == NULL || ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX]==NID_undef)? SSL_GOST89MAC:0;
+
        }
 
 static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method,
index d73c7ca..ab15575 100644 (file)
@@ -225,6 +225,8 @@ int SSL_clear(SSL *s)
                }
 
        ssl_clear_cipher_ctx(s);
+       ssl_clear_hash_ctx(&s->read_hash);
+       ssl_clear_hash_ctx(&s->write_hash);
 
        s->first_packet=0;
 
@@ -523,6 +525,8 @@ void SSL_free(SSL *s)
                }
 
        ssl_clear_cipher_ctx(s);
+       ssl_clear_hash_ctx(&s->read_hash);
+       ssl_clear_hash_ctx(&s->write_hash);
 
        if (s->cert != NULL) ssl_cert_free(s->cert);
        /* Free up if allocated */
@@ -2203,6 +2207,8 @@ void SSL_set_accept_state(SSL *s)
        s->handshake_func=s->method->ssl_accept;
        /* clear the current cipher */
        ssl_clear_cipher_ctx(s);
+       ssl_clear_hash_ctx(&s->read_hash);
+       ssl_clear_hash_ctx(&s->write_hash);
        }
 
 void SSL_set_connect_state(SSL *s)
@@ -2213,6 +2219,8 @@ void SSL_set_connect_state(SSL *s)
        s->handshake_func=s->method->ssl_connect;
        /* clear the current cipher */
        ssl_clear_cipher_ctx(s);
+       ssl_clear_hash_ctx(&s->read_hash);
+       ssl_clear_hash_ctx(&s->write_hash);
        }
 
 int ssl_undefined_function(SSL *s)
@@ -2836,7 +2844,25 @@ void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int con
        SSL_callback_ctrl(ssl, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb);
        }
 
-
+/* Allocates new EVP_MD_CTX and sets pointer to it into given pointer
+ * vairable, freeing  EVP_MD_CTX previously stored in that variable, if
+ * any. If EVP_MD pointer is passed, initializes ctx with this md
+ * Returns newly allocated ctx;
+ */ 
+
+EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md) 
+{
+       ssl_clear_hash_ctx(hash);
+       *hash = EVP_MD_CTX_create();
+       if (md) EVP_DigestInit_ex(*hash,md,NULL);
+       return *hash;
+}
+void ssl_clear_hash_ctx(EVP_MD_CTX **hash) 
+{
+
+       if (*hash) EVP_MD_CTX_destroy(*hash);
+       *hash=NULL;
+}
 
 #if defined(_WINDLL) && defined(OPENSSL_SYS_WIN16)
 #include "../crypto/bio/bss_file.c"
index 8488a61..004e21d 100644 (file)
 /* Bits for algorithm_mac (symmetric authentication) */
 #define SSL_MD5                        0x00000001L
 #define SSL_SHA1               0x00000002L
-
+#define SSL_GOST94      0x00000004L
+#define SSL_GOST89MAC   0x00000008L
 
 /* Bits for algorithm_ssl (protocol version) */
 #define SSL_SSLV2              0x00000001L
@@ -753,7 +754,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *meth,
                                             const char *rule_str);
 void ssl_update_cache(SSL *s, int mode);
 int ssl_cipher_get_evp(const SSL_SESSION *s,const EVP_CIPHER **enc,
-                      const EVP_MD **md,SSL_COMP **comp);
+                      const EVP_MD **md,int *mac_pkey_type,int *mac_secret_size, SSL_COMP **comp);
 int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk);
 int ssl_undefined_function(SSL *s);
 int ssl_undefined_void_function(void);
@@ -984,5 +985,7 @@ int ssl_prepare_clienthello_tlsext(SSL *s);
 int ssl_prepare_serverhello_tlsext(SSL *s);
 int ssl_check_clienthello_tlsext(SSL *s);
 int ssl_check_serverhello_tlsext(SSL *s);
+EVP_MD_CTX* ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md) ;
+void ssl_clear_hash_ctx(EVP_MD_CTX **hash);
 #endif
 #endif
index f51e48b..22f9a40 100644 (file)
@@ -188,7 +188,7 @@ int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x)
                {
                SSL_COMP *comp = NULL;
 
-               ssl_cipher_get_evp(x,NULL,NULL,&comp);
+               ssl_cipher_get_evp(x,NULL,NULL,NULL,NULL,&comp);
                if (comp == NULL)
                        {
                        if (BIO_printf(bp,"\n   Compression: %d",x->compress_meth) <= 0) goto err;
index 8398d27..7a4e2ce 100644 (file)
@@ -261,12 +261,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
@@ -291,6 +296,11 @@ 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)
@@ -299,7 +309,7 @@ int tls1_change_cipher_state(SSL *s, int which)
                        /* 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)
                        {
@@ -325,9 +335,14 @@ 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)
@@ -336,7 +351,7 @@ int tls1_change_cipher_state(SSL *s, int which)
                        /* 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)
                        {
@@ -357,13 +372,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);
 
        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;
@@ -399,6 +416,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'); }
@@ -477,6 +498,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");
@@ -485,7 +507,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);
@@ -493,8 +515,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);
@@ -559,8 +582,8 @@ 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);
                ds=s->enc_write_ctx;
                rec= &(s->s3->wrec);
                if (s->enc_write_ctx == NULL)
@@ -570,8 +593,8 @@ 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);
                ds=s->enc_read_ctx;
                rec= &(s->s3->rrec);
                if (s->enc_read_ctx == NULL)
@@ -742,12 +765,12 @@ 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));
        if (send)
                {
                rec= &(ssl->s3->wrec);
@@ -763,7 +786,7 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send)
                hash=ssl->read_hash;
                }
 
-       md_size=EVP_MD_size(hash);
+       md_size=EVP_MD_CTX_size(hash);
 
        buf[0]=rec->type;
        buf[1]=TLS1_VERSION_MAJOR;
@@ -772,14 +795,21 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send)
        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;
+               }       
+       EVP_DigestSignUpdate(mac_ctx,seq,8);
+       EVP_DigestSignUpdate(mac_ctx,buf,5);
+       EVP_DigestSignUpdate(mac_ctx,rec->input,rec->length);
+       if (stream_mac) EVP_MD_CTX_copy(&hmac,hash);
+       EVP_DigestSignFinal(&hmac,md,&md_size);
+       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"); }
index 05d74f5..84ab246 100644 (file)
@@ -404,6 +404,10 @@ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG,0, (void *)arg)
 #define TLS1_TXT_DHE_RSA_WITH_SEED_SHA                  "DHE-RSA-SEED-SHA"
 #define TLS1_TXT_ADH_WITH_SEED_SHA                      "ADH-SEED-SHA"
 
+/* Flags for SSL_CIPHER.algorithm2 field */
+/* Stream MAC for GOST ciphersuites from cryptopro draft */
+#define TLS1_STREAM_MAC 0x04
+
 #define TLS_CT_RSA_SIGN                        1
 #define TLS_CT_DSS_SIGN                        2
 #define TLS_CT_RSA_FIXED_DH            3