diff options
author | Dr. Stephen Henson <steve@openssl.org> | 2007-06-04 17:04:40 +0000 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 2007-06-04 17:04:40 +0000 |
commit | b948e2c59e3a6bdbfdcc304793da4635db7ca339 (patch) | |
tree | bf2eea11b2e0b58b783aad36b956471a562fea65 | |
parent | 18096abb2939fb7d2cf24842310649908dc283ac (diff) |
Update ssl library to support EVP_PKEY MAC API. Include generic MAC support.
-rw-r--r-- | CHANGES | 5 | ||||
-rw-r--r-- | ssl/d1_enc.c | 8 | ||||
-rw-r--r-- | ssl/d1_pkt.c | 6 | ||||
-rw-r--r-- | ssl/s2_clnt.c | 2 | ||||
-rw-r--r-- | ssl/s2_enc.c | 9 | ||||
-rw-r--r-- | ssl/s2_pkt.c | 4 | ||||
-rw-r--r-- | ssl/s2_srvr.c | 2 | ||||
-rw-r--r-- | ssl/s3_enc.c | 16 | ||||
-rw-r--r-- | ssl/s3_lib.c | 42 | ||||
-rw-r--r-- | ssl/s3_pkt.c | 8 | ||||
-rw-r--r-- | ssl/ssl.h | 11 | ||||
-rw-r--r-- | ssl/ssl3.h | 4 | ||||
-rw-r--r-- | ssl/ssl_ciph.c | 73 | ||||
-rw-r--r-- | ssl/ssl_lib.c | 28 | ||||
-rw-r--r-- | ssl/ssl_locl.h | 7 | ||||
-rw-r--r-- | ssl/ssl_txt.c | 2 | ||||
-rw-r--r-- | ssl/t1_enc.c | 76 | ||||
-rw-r--r-- | ssl/tls1.h | 4 |
18 files changed, 242 insertions, 65 deletions
@@ -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. diff --git a/ssl/d1_enc.c b/ssl/d1_enc.c index cbff7495c5..ef4d880551 100644 --- a/ssl/d1_enc.c +++ b/ssl/d1_enc.c @@ -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) diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c index 8a047aeda7..bf189f11c3 100644 --- a/ssl/d1_pkt.c +++ b/ssl/d1_pkt.c @@ -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 diff --git a/ssl/s2_clnt.c b/ssl/s2_clnt.c index 6d8883fbbd..7b3b7d8eac 100644 --- a/ssl/s2_clnt.c +++ b/ssl/s2_clnt.c @@ -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); diff --git a/ssl/s2_enc.c b/ssl/s2_enc.c index 1f62acd5b1..ff3395f459 100644 --- a/ssl/s2_enc.c +++ b/ssl/s2_enc.c @@ -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); diff --git a/ssl/s2_pkt.c b/ssl/s2_pkt.c index a10929a757..e6d5d09643 100644 --- a/ssl/s2_pkt.c +++ b/ssl/s2_pkt.c @@ -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) diff --git a/ssl/s2_srvr.c b/ssl/s2_srvr.c index 45943240f0..44c1ee3527 100644 --- a/ssl/s2_srvr.c +++ b/ssl/s2_srvr.c @@ -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); diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c index 8f3ba93d61..010069bf28 100644 --- a/ssl/s3_enc.c +++ b/ssl/s3_enc.c @@ -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); diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 4ac696111f..bd0056b9fe 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -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 */ diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c index 6754e993c5..58f2845d6e 100644 --- a/ssl/s3_pkt.c +++ b/ssl/s3_pkt.c @@ -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) @@ -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 diff --git a/ssl/ssl3.h b/ssl/ssl3.h index 5ddadb2cd1..2d5db780be 100644 --- a/ssl/ssl3.h +++ b/ssl/ssl3.h @@ -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 diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c index 0a56042931..d2e648bf30 100644 --- a/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c @@ -143,6 +143,7 @@ #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, diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index d73c7ca080..ab15575eec 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -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" diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 8488a6153f..004e21ddb8 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -320,7 +320,8 @@ /* 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 diff --git a/ssl/ssl_txt.c b/ssl/ssl_txt.c index f51e48b233..22f9a403af 100644 --- a/ssl/ssl_txt.c +++ b/ssl/ssl_txt.c @@ -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; diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index 8398d271d6..7a4e2ce076 100644 --- a/ssl/t1_enc.c +++ b/ssl/t1_enc.c @@ -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"); } diff --git a/ssl/tls1.h b/ssl/tls1.h index 05d74f5416..84ab246f14 100644 --- a/ssl/tls1.h +++ b/ssl/tls1.h @@ -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 |