Index: openssl/ssl/s3_enc.c |
=================================================================== |
--- openssl/ssl/s3_enc.c (revision 105093) |
+++ openssl/ssl/s3_enc.c (working copy) |
@@ -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 |
@@ -108,10 +108,35 @@ |
* Hudson (tjh@cryptsoft.com). |
* |
*/ |
+/* ==================================================================== |
+ * Copyright 2005 Nokia. All rights reserved. |
+ * |
+ * The portions of the attached software ("Contribution") is developed by |
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source |
+ * license. |
+ * |
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of |
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites |
+ * support (see RFC 4279) to OpenSSL. |
+ * |
+ * No patent licenses or other rights except those expressly stated in |
+ * the OpenSSL open source license shall be deemed granted or received |
+ * expressly, by implication, estoppel, or otherwise. |
+ * |
+ * No assurances are provided by Nokia that the Contribution does not |
+ * infringe the patent or other intellectual property rights of any third |
+ * party or that the license provides you with all the necessary rights |
+ * to make use of the Contribution. |
+ * |
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN |
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA |
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY |
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR |
+ * OTHERWISE. |
+ */ |
#include <stdio.h> |
#include "ssl_locl.h" |
-#include "fnv1a64.h" |
#include <openssl/evp.h> |
#include <openssl/md5.h> |
@@ -130,10 +155,8 @@ |
0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c, |
0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c, |
0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c }; |
- |
-static int ssl3_handshake_mac(SSL *s, EVP_MD_CTX *in_ctx, |
+static int ssl3_handshake_mac(SSL *s, int md_nid, |
const char *sender, int len, unsigned char *p); |
- |
static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num) |
{ |
EVP_MD_CTX m5; |
@@ -147,7 +170,6 @@ |
#endif |
k=0; |
EVP_MD_CTX_init(&m5); |
- EVP_MD_CTX_set_flags(&m5, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); |
EVP_MD_CTX_init(&s1); |
for (i=0; (int)i<num; i+=MD5_DIGEST_LENGTH) |
{ |
@@ -192,7 +214,7 @@ |
int ssl3_change_cipher_state(SSL *s, int which) |
{ |
- unsigned char *p,*key_block,*mac_secret; |
+ unsigned char *p,*mac_secret; |
unsigned char exp_key[EVP_MAX_KEY_LENGTH]; |
unsigned char exp_iv[EVP_MAX_IV_LENGTH]; |
unsigned char *ms,*key,*iv,*er1,*er2; |
@@ -209,13 +231,14 @@ |
is_exp=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher); |
c=s->s3->tmp.new_sym_enc; |
m=s->s3->tmp.new_hash; |
+ /* m == NULL will lead to a crash later */ |
+ OPENSSL_assert(m); |
#ifndef OPENSSL_NO_COMP |
if (s->s3->tmp.new_compression == NULL) |
comp=NULL; |
else |
comp=s->s3->tmp.new_compression->method; |
#endif |
- key_block=s->s3->tmp.key_block; |
if (which & SSL3_CC_READ) |
{ |
@@ -227,7 +250,8 @@ |
/* 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) |
@@ -263,7 +287,7 @@ |
/* 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) |
@@ -290,6 +314,8 @@ |
p=s->s3->tmp.key_block; |
i=EVP_MD_size(m); |
+ if (i < 0) |
+ goto err2; |
cl=EVP_CIPHER_key_length(c); |
j=is_exp ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ? |
cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl; |
@@ -370,7 +396,7 @@ |
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); |
@@ -384,7 +410,11 @@ |
s->s3->tmp.new_compression=comp; |
#endif |
- num=EVP_CIPHER_key_length(c)+EVP_MD_size(hash)+EVP_CIPHER_iv_length(c); |
+ num=EVP_MD_size(hash); |
+ if (num < 0) |
+ return 0; |
+ |
+ num=EVP_CIPHER_key_length(c)+num+EVP_CIPHER_iv_length(c); |
num*=2; |
ssl3_cleanup_key_block(s); |
@@ -406,11 +436,11 @@ |
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 |
} |
@@ -481,6 +511,9 @@ |
/* we need to add 'i-1' padding bytes */ |
l+=i; |
+ /* the last of these zero bytes will be overwritten |
+ * with the padding length. */ |
+ memset(&rec->input[rec->length], 0, i); |
rec->length+=i; |
rec->input[l-1]=(i-1); |
} |
@@ -520,55 +553,131 @@ |
void ssl3_init_finished_mac(SSL *s) |
{ |
- EVP_MD_CTX_set_flags(&(s->s3->finish_dgst1), |
- EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); |
- EVP_DigestInit_ex(&(s->s3->finish_dgst1),s->ctx->md5, NULL); |
- EVP_DigestInit_ex(&(s->s3->finish_dgst2),s->ctx->sha1, NULL); |
+ if (s->s3->handshake_buffer) BIO_free(s->s3->handshake_buffer); |
+ if (s->s3->handshake_dgst) ssl3_free_digest_list(s); |
+ s->s3->handshake_buffer=BIO_new(BIO_s_mem()); |
+ (void)BIO_set_close(s->s3->handshake_buffer,BIO_CLOSE); |
} |
+void ssl3_free_digest_list(SSL *s) |
+ { |
+ int i; |
+ if (!s->s3->handshake_dgst) return; |
+ for (i=0;i<SSL_MAX_DIGEST;i++) |
+ { |
+ if (s->s3->handshake_dgst[i]) |
+ EVP_MD_CTX_destroy(s->s3->handshake_dgst[i]); |
+ } |
+ OPENSSL_free(s->s3->handshake_dgst); |
+ s->s3->handshake_dgst=NULL; |
+ } |
+ |
+ |
+ |
void ssl3_finish_mac(SSL *s, const unsigned char *buf, int len) |
{ |
- EVP_DigestUpdate(&(s->s3->finish_dgst1),buf,len); |
- EVP_DigestUpdate(&(s->s3->finish_dgst2),buf,len); |
- if (s->s3->snap_start_requested) |
+ if (s->s3->handshake_buffer) |
{ |
- /* Compute Fowler-Noll-Vo (FNV) hash for Snap Start handshake */ |
- fnv1a64_update((FNV1A64*) s->s3->response_hash, buf, len); |
+ BIO_write (s->s3->handshake_buffer,(void *)buf,len); |
+ } |
+ else |
+ { |
+ int i; |
+ for (i=0;i< SSL_MAX_DIGEST;i++) |
+ { |
+ if (s->s3->handshake_dgst[i]!= NULL) |
+ EVP_DigestUpdate(s->s3->handshake_dgst[i],buf,len); |
+ } |
+ } |
+ } |
+ |
+int ssl3_digest_cached_records(SSL *s) |
+ { |
+ int i; |
+ long mask; |
+ const EVP_MD *md; |
+ long hdatalen; |
+ void *hdata; |
+ |
+ /* Allocate handshake_dgst array */ |
+ ssl3_free_digest_list(s); |
+ s->s3->handshake_dgst = OPENSSL_malloc(SSL_MAX_DIGEST * sizeof(EVP_MD_CTX *)); |
+ memset(s->s3->handshake_dgst,0,SSL_MAX_DIGEST *sizeof(EVP_MD_CTX *)); |
+ hdatalen = BIO_get_mem_data(s->s3->handshake_buffer,&hdata); |
+ if (hdatalen <= 0) |
+ { |
+ SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, SSL_R_BAD_HANDSHAKE_LENGTH); |
+ return 0; |
} |
+ |
+ /* Loop through bitso of algorithm2 field and create MD_CTX-es */ |
+ for (i=0;ssl_get_handshake_digest(i,&mask,&md); i++) |
+ { |
+ if ((mask & s->s3->tmp.new_cipher->algorithm2) && md) |
+ { |
+ s->s3->handshake_dgst[i]=EVP_MD_CTX_create(); |
+ EVP_DigestInit_ex(s->s3->handshake_dgst[i],md,NULL); |
+ EVP_DigestUpdate(s->s3->handshake_dgst[i],hdata,hdatalen); |
+ } |
+ else |
+ { |
+ s->s3->handshake_dgst[i]=NULL; |
+ } |
+ } |
+ /* Free handshake_buffer BIO */ |
+ BIO_free(s->s3->handshake_buffer); |
+ s->s3->handshake_buffer = NULL; |
+ |
+ return 1; |
} |
-int ssl3_cert_verify_mac(SSL *s, EVP_MD_CTX *ctx, unsigned char *p) |
+int ssl3_cert_verify_mac(SSL *s, int md_nid, unsigned char *p) |
{ |
- return(ssl3_handshake_mac(s,ctx,NULL,0,p)); |
+ return(ssl3_handshake_mac(s,md_nid,NULL,0,p)); |
} |
- |
-int ssl3_final_finish_mac(SSL *s, EVP_MD_CTX *ctx1, EVP_MD_CTX *ctx2, |
+int ssl3_final_finish_mac(SSL *s, |
const char *sender, int len, unsigned char *p) |
{ |
int ret; |
- |
- ret=ssl3_handshake_mac(s,ctx1,sender,len,p); |
+ ret=ssl3_handshake_mac(s,NID_md5,sender,len,p); |
p+=ret; |
- ret+=ssl3_handshake_mac(s,ctx2,sender,len,p); |
+ ret+=ssl3_handshake_mac(s,NID_sha1,sender,len,p); |
return(ret); |
} |
- |
-static int ssl3_handshake_mac(SSL *s, EVP_MD_CTX *in_ctx, |
+static int ssl3_handshake_mac(SSL *s, int md_nid, |
const char *sender, int len, unsigned char *p) |
{ |
unsigned int ret; |
int npad,n; |
unsigned int i; |
unsigned char md_buf[EVP_MAX_MD_SIZE]; |
- EVP_MD_CTX ctx; |
+ EVP_MD_CTX ctx,*d=NULL; |
+ if (s->s3->handshake_buffer) |
+ if (!ssl3_digest_cached_records(s)) |
+ return 0; |
+ |
+ /* Search for digest of specified type in the handshake_dgst |
+ * array*/ |
+ 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_SSL3_HANDSHAKE_MAC,SSL_R_NO_REQUIRED_DIGEST); |
+ return 0; |
+ } |
EVP_MD_CTX_init(&ctx); |
- EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); |
- EVP_MD_CTX_copy_ex(&ctx,in_ctx); |
+ EVP_MD_CTX_copy_ex(&ctx,d); |
+ n=EVP_MD_CTX_size(&ctx); |
+ if (n < 0) |
+ return 0; |
- n=EVP_MD_CTX_size(&ctx); |
npad=(48/n)*n; |
- |
if (sender != NULL) |
EVP_DigestUpdate(&ctx,sender,len); |
EVP_DigestUpdate(&ctx,s->session->master_key, |
@@ -588,15 +697,16 @@ |
return((int)ret); |
} |
-int ssl3_mac(SSL *ssl, unsigned char *md, int send) |
+int n_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; |
+ int t; |
if (send) |
{ |
@@ -613,13 +723,16 @@ |
hash=ssl->read_hash; |
} |
- md_size=EVP_MD_size(hash); |
+ t=EVP_MD_CTX_size(hash); |
+ if (t < 0) |
+ return -1; |
+ md_size=t; |
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); |
@@ -631,7 +744,7 @@ |
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); |
@@ -724,6 +837,12 @@ |
case SSL_AD_INTERNAL_ERROR: return(SSL3_AD_HANDSHAKE_FAILURE); |
case SSL_AD_USER_CANCELLED: return(SSL3_AD_HANDSHAKE_FAILURE); |
case SSL_AD_NO_RENEGOTIATION: return(-1); /* Don't send it :-) */ |
+ case SSL_AD_UNSUPPORTED_EXTENSION: return(SSL3_AD_HANDSHAKE_FAILURE); |
+ case SSL_AD_CERTIFICATE_UNOBTAINABLE: return(SSL3_AD_HANDSHAKE_FAILURE); |
+ case SSL_AD_UNRECOGNIZED_NAME: return(SSL3_AD_HANDSHAKE_FAILURE); |
+ case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: return(SSL3_AD_HANDSHAKE_FAILURE); |
+ case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: return(SSL3_AD_HANDSHAKE_FAILURE); |
+ case SSL_AD_UNKNOWN_PSK_IDENTITY:return(TLS1_AD_UNKNOWN_PSK_IDENTITY); |
default: return(-1); |
} |
} |