* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
+/* ====================================================================
+ * Copyright (c) 1998-2002 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
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
#include <stdio.h>
+#include "ssl_locl.h"
#include <openssl/comp.h>
-#include <openssl/md5.h>
-#include <openssl/sha.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
-#include "ssl_locl.h"
+#include <openssl/md5.h>
static void tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
int sec_len, unsigned char *seed, int seed_len,
unsigned int j;
HMAC_CTX ctx;
HMAC_CTX ctx_tmp;
- unsigned char A1[HMAC_MAX_MD_CBLOCK];
+ unsigned char A1[EVP_MAX_MD_SIZE];
unsigned int A1_len;
chunk=EVP_MD_size(md);
- HMAC_Init(&ctx,sec,sec_len,md);
+ 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);
HMAC_Final(&ctx,A1,&A1_len);
n=0;
for (;;)
{
- HMAC_Init(&ctx,NULL,0,NULL); /* re-init */
+ HMAC_Init_ex(&ctx,NULL,0,NULL,NULL); /* re-init */
+ HMAC_Init_ex(&ctx_tmp,NULL,0,NULL,NULL); /* re-init */
HMAC_Update(&ctx,A1,A1_len);
- memcpy(&ctx_tmp,&ctx,sizeof(ctx)); /* Copy for A2 */ /* not needed for last one */
+ HMAC_Update(&ctx_tmp,A1,A1_len);
HMAC_Update(&ctx,seed,seed_len);
if (olen > chunk)
break;
}
}
- HMAC_cleanup(&ctx);
- HMAC_cleanup(&ctx_tmp);
- memset(A1,0,sizeof(A1));
+ HMAC_CTX_cleanup(&ctx);
+ HMAC_CTX_cleanup(&ctx_tmp);
+ OPENSSL_cleanse(A1,sizeof(A1));
}
static void tls1_PRF(const EVP_MD *md5, const EVP_MD *sha1,
tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,(int)(p-buf),
s->session->master_key,s->session->master_key_length,
km,tmp,num);
+#ifdef KSSL_DEBUG
+ printf("tls1_generate_key_block() ==> %d byte master_key =\n\t",
+ s->session->master_key_length);
+ {
+ int i;
+ for (i=0; i < s->session->master_key_length; i++)
+ {
+ printf("%02X", s->session->master_key[i]);
+ }
+ printf("\n"); }
+#endif /* KSSL_DEBUG */
}
int tls1_change_cipher_state(SSL *s, int which)
int client_write;
EVP_CIPHER_CTX *dd;
const EVP_CIPHER *c;
+#ifndef OPENSSL_NO_COMP
const SSL_COMP *comp;
+#endif
const EVP_MD *m;
- int _exp,n,i,j,k,exp_label_len,cl;
+ int is_export,n,i,j,k,exp_label_len,cl;
+ int reuse_dd = 0;
- _exp=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher);
+ is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher);
c=s->s3->tmp.new_sym_enc;
m=s->s3->tmp.new_hash;
+#ifndef OPENSSL_NO_COMP
comp=s->s3->tmp.new_compression;
+#endif
key_block=s->s3->tmp.key_block;
+#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("\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);
+ printf("\tkey_block: len= %d, data= ", s->s3->tmp.key_block_length);
+ {
+ int i;
+ for (i=0; i<s->s3->tmp.key_block_length; i++)
+ printf("%02x", key_block[i]); printf("\n");
+ }
+#endif /* KSSL_DEBUG */
+
if (which & SSL3_CC_READ)
{
- if ((s->enc_read_ctx == NULL) &&
- ((s->enc_read_ctx=(EVP_CIPHER_CTX *)
- OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL))
+ if (s->enc_read_ctx != NULL)
+ reuse_dd = 1;
+ else if ((s->enc_read_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)
goto err;
dd= s->enc_read_ctx;
s->read_hash=m;
+#ifndef OPENSSL_NO_COMP
if (s->expand != NULL)
{
COMP_CTX_free(s->expand);
if (s->s3->rrec.comp == NULL)
goto err;
}
- memset(&(s->s3->read_sequence[0]),0,8);
+#endif
+ /* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */
+ if (s->version != DTLS1_VERSION)
+ memset(&(s->s3->read_sequence[0]),0,8);
mac_secret= &(s->s3->read_mac_secret[0]);
}
else
{
+ 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;
dd= s->enc_write_ctx;
s->write_hash=m;
+#ifndef OPENSSL_NO_COMP
if (s->compress != NULL)
{
COMP_CTX_free(s->compress);
goto err2;
}
}
- memset(&(s->s3->write_sequence[0]),0,8);
+#endif
+ /* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */
+ if (s->version != DTLS1_VERSION)
+ memset(&(s->s3->write_sequence[0]),0,8);
mac_secret= &(s->s3->write_mac_secret[0]);
}
+ if (reuse_dd)
+ EVP_CIPHER_CTX_cleanup(dd);
EVP_CIPHER_CTX_init(dd);
p=s->s3->tmp.key_block;
i=EVP_MD_size(m);
cl=EVP_CIPHER_key_length(c);
- j=_exp ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ?
- cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl;
+ j=is_export ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ?
+ cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl;
/* Was j=(exp)?5:EVP_CIPHER_key_length(c); */
k=EVP_CIPHER_iv_length(c);
er1= &(s->s3->client_random[0]);
if (n > s->s3->tmp.key_block_length)
{
- SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_INTERNAL_ERROR);
goto err2;
}
printf("which = %04X\nmac key=",which);
{ int z; for (z=0; z<i; z++) printf("%02X%c",ms[z],((z+1)%16)?' ':'\n'); }
#endif
- if (_exp)
+ if (is_export)
{
/* In here I set both the read and write key/iv to the
* same value since only the correct one will be used :-).
}
s->session->key_arg_length=0;
+#ifdef KSSL_DEBUG
+ {
+ int i;
+ printf("EVP_CipherInit_ex(dd,c,key=,iv=,which)\n");
+ printf("\tkey= "); for (i=0; i<c->key_len; i++) printf("%02x", key[i]);
+ printf("\n");
+ printf("\t iv= "); for (i=0; i<c->iv_len; i++) printf("%02x", iv[i]);
+ printf("\n");
+ }
+#endif /* KSSL_DEBUG */
- EVP_CipherInit(dd,c,key,iv,(which & SSL3_CC_WRITE));
+ EVP_CipherInit_ex(dd,c,NULL,key,iv,(which & SSL3_CC_WRITE));
#ifdef TLS_DEBUG
printf("which = %04X\nkey=",which);
{ int z; for (z=0; z<EVP_CIPHER_key_length(c); z++) printf("%02X%c",key[z],((z+1)%16)?' ':'\n'); }
printf("\n");
#endif
- memset(tmp1,0,sizeof(tmp1));
- memset(tmp2,0,sizeof(tmp1));
- memset(iv1,0,sizeof(iv1));
- memset(iv2,0,sizeof(iv2));
+ OPENSSL_cleanse(tmp1,sizeof(tmp1));
+ OPENSSL_cleanse(tmp2,sizeof(tmp1));
+ OPENSSL_cleanse(iv1,sizeof(iv1));
+ OPENSSL_cleanse(iv2,sizeof(iv2));
return(1);
err:
SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_MALLOC_FAILURE);
int num;
SSL_COMP *comp;
+#ifdef KSSL_DEBUG
+ printf ("tls1_setup_key_block()\n");
+#endif /* KSSL_DEBUG */
+
if (s->s3->tmp.key_block_length != 0)
return(1);
{ int z; for (z=0; z<s->session->master_key_length; z++) printf("%02X%c",s->session->master_key[z],((z+1)%16)?' ':'\n'); }
#endif
tls1_generate_key_block(s,p1,p2,num);
- memset(p2,0,num);
+ OPENSSL_cleanse(p2,num);
OPENSSL_free(p2);
#ifdef TLS_DEBUG
printf("\nkey block\n");
{ int z; for (z=0; z<num; z++) printf("%02X%c",p1[z],((z+1)%16)?' ':'\n'); }
#endif
+ if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS))
+ {
+ /* enable vulnerability countermeasure for CBC ciphers with
+ * known-IV problem (http://www.openssl.org/~bodo/tls-cbc.txt)
+ */
+ s->s3->need_empty_fragments = 1;
+
+ if (s->session->cipher != NULL)
+ {
+ if ((s->session->cipher->algorithms & SSL_ENC_MASK) == SSL_eNULL)
+ s->s3->need_empty_fragments = 0;
+
+#ifndef OPENSSL_NO_RC4
+ if ((s->session->cipher->algorithms & SSL_ENC_MASK) == SSL_RC4)
+ s->s3->need_empty_fragments = 0;
+#endif
+ }
+ }
+
return(1);
err:
SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,ERR_R_MALLOC_FAILURE);
enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
}
+#ifdef KSSL_DEBUG
+ printf("tls1_enc(%d)\n", send);
+#endif /* KSSL_DEBUG */
+
if ((s->session == NULL) || (ds == NULL) ||
(enc == NULL))
{
- memcpy(rec->data,rec->input,rec->length);
+ memmove(rec->data,rec->input,rec->length);
rec->input=rec->data;
}
else
rec->length+=i;
}
+#ifdef KSSL_DEBUG
+ {
+ unsigned long ui;
+ printf("EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n",
+ ds,rec->data,rec->input,l);
+ printf("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%d %d], %d iv_len\n",
+ ds->buf_len, ds->cipher->key_len,
+ DES_KEY_SZ, DES_SCHEDULE_SZ,
+ ds->cipher->iv_len);
+ printf("\t\tIV: ");
+ for (i=0; i<ds->cipher->iv_len; i++) printf("%02X", ds->iv[i]);
+ printf("\n");
+ printf("\trec->input=");
+ for (ui=0; ui<l; ui++) printf(" %02x", rec->input[ui]);
+ printf("\n");
+ }
+#endif /* KSSL_DEBUG */
+
+ if (!send)
+ {
+ if (l == 0 || l%bs != 0)
+ {
+ SSLerr(SSL_F_TLS1_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
+ ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED);
+ return 0;
+ }
+ }
+
EVP_Cipher(ds,rec->data,rec->input,l);
+#ifdef KSSL_DEBUG
+ {
+ unsigned long i;
+ printf("\trec->data=");
+ for (i=0; i<l; i++)
+ printf(" %02x", rec->data[i]); printf("\n");
+ }
+#endif /* KSSL_DEBUG */
+
if ((bs != 1) && !send)
{
- ii=i=rec->data[l-1];
+ ii=i=rec->data[l-1]; /* padding_length */
i++;
if (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG)
{
if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG)
i--;
}
+ /* TLS 1.0 does not bound the number of padding bytes by the block size.
+ * All of them must have value 'padding_length'. */
if (i > (int)rec->length)
{
- SSLerr(SSL_F_TLS1_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
- ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED);
- return(0);
+ /* Incorrect padding. SSLerr() and ssl3_alert are done
+ * by caller: we don't want to reveal whether this is
+ * a decryption error or a MAC verification failure
+ * (see http://www.openssl.org/~bodo/tls-cbc.txt) */
+ return -1;
}
for (j=(int)(l-i); j<(int)l; j++)
{
if (rec->data[j] != ii)
{
- SSLerr(SSL_F_TLS1_ENC,SSL_R_DECRYPTION_FAILED);
- ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED);
- return(0);
+ /* Incorrect padding */
+ return -1;
}
}
rec->length-=i;
unsigned int ret;
EVP_MD_CTX ctx;
- EVP_MD_CTX_copy(&ctx,in_ctx);
- EVP_DigestFinal(&ctx,out,&ret);
+ EVP_MD_CTX_init(&ctx);
+ EVP_MD_CTX_copy_ex(&ctx,in_ctx);
+ EVP_DigestFinal_ex(&ctx,out,&ret);
+ EVP_MD_CTX_cleanup(&ctx);
return((int)ret);
}
memcpy(q,str,slen);
q+=slen;
- EVP_MD_CTX_copy(&ctx,in1_ctx);
- EVP_DigestFinal(&ctx,q,&i);
+ 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(&ctx,in2_ctx);
- EVP_DigestFinal(&ctx,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,12);
- memset(&ctx,0,sizeof(EVP_MD_CTX));
+ out,buf2,sizeof buf2);
+ EVP_MD_CTX_cleanup(&ctx);
- return((int)12);
+ return sizeof buf2;
}
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_Init(&hmac,mac_sec,EVP_MD_size(hash),hash);
+ 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);
#ifdef TLS_DEBUG
printf("sec=");
{unsigned int z; for (z=0; z<rec->length; z++) printf("%02X ",buf[z]); printf("\n"); }
#endif
- for (i=7; i>=0; i--)
- if (++seq[i]) break;
+ if ( SSL_version(ssl) != DTLS1_VERSION)
+ {
+ for (i=7; i>=0; i--)
+ {
+ ++seq[i];
+ if (seq[i] != 0) break;
+ }
+ }
#ifdef TLS_DEBUG
{unsigned int z; for (z=0; z<md_size; z++) printf("%02X ",md[z]); printf("\n"); }
unsigned char buf[SSL3_RANDOM_SIZE*2+TLS_MD_MASTER_SECRET_CONST_SIZE];
unsigned char buff[SSL_MAX_MASTER_KEY_LENGTH];
+#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);
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,
- s->session->master_key,buff,SSL3_MASTER_SECRET_SIZE);
+ s->session->master_key,buff,sizeof buff);
+#ifdef KSSL_DEBUG
+ printf ("tls1_generate_master_secret() complete\n");
+#endif /* KSSL_DEBUG */
return(SSL3_MASTER_SECRET_SIZE);
}
case SSL_AD_INTERNAL_ERROR: return(TLS1_AD_INTERNAL_ERROR);
case SSL_AD_USER_CANCELLED: return(TLS1_AD_USER_CANCELLED);
case SSL_AD_NO_RENEGOTIATION: return(TLS1_AD_NO_RENEGOTIATION);
+ case DTLS1_AD_MISSING_HANDSHAKE_MESSAGE: return
+ (DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
default: return(-1);
}
}