sl@0: /* ssl/t1_enc.c */ sl@0: /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) sl@0: * All rights reserved. sl@0: * sl@0: * This package is an SSL implementation written sl@0: * by Eric Young (eay@cryptsoft.com). sl@0: * The implementation was written so as to conform with Netscapes SSL. sl@0: * sl@0: * This library is free for commercial and non-commercial use as long as sl@0: * the following conditions are aheared to. The following conditions sl@0: * apply to all code found in this distribution, be it the RC4, RSA, sl@0: * lhash, DES, etc., code; not just the SSL code. The SSL documentation sl@0: * included with this distribution is covered by the same copyright terms sl@0: * except that the holder is Tim Hudson (tjh@cryptsoft.com). sl@0: * sl@0: * Copyright remains Eric Young's, and as such any Copyright notices in sl@0: * the code are not to be removed. sl@0: * If this package is used in a product, Eric Young should be given attribution sl@0: * as the author of the parts of the library used. sl@0: * This can be in the form of a textual message at program startup or sl@0: * in documentation (online or textual) provided with the package. sl@0: * sl@0: * Redistribution and use in source and binary forms, with or without sl@0: * modification, are permitted provided that the following conditions sl@0: * are met: sl@0: * 1. Redistributions of source code must retain the copyright sl@0: * notice, this list of conditions and the following disclaimer. sl@0: * 2. Redistributions in binary form must reproduce the above copyright sl@0: * notice, this list of conditions and the following disclaimer in the sl@0: * documentation and/or other materials provided with the distribution. sl@0: * 3. All advertising materials mentioning features or use of this software sl@0: * must display the following acknowledgement: sl@0: * "This product includes cryptographic software written by sl@0: * Eric Young (eay@cryptsoft.com)" sl@0: * The word 'cryptographic' can be left out if the rouines from the library sl@0: * being used are not cryptographic related :-). sl@0: * 4. If you include any Windows specific code (or a derivative thereof) from sl@0: * the apps directory (application code) you must include an acknowledgement: sl@0: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" sl@0: * sl@0: * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND sl@0: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE sl@0: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE sl@0: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE sl@0: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL sl@0: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS sl@0: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) sl@0: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT sl@0: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY sl@0: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF sl@0: * SUCH DAMAGE. sl@0: * sl@0: * The licence and distribution terms for any publically available version or sl@0: * derivative of this code cannot be changed. i.e. this code cannot simply be sl@0: * copied and put under another distribution licence sl@0: * [including the GNU Public Licence.] sl@0: */ sl@0: /* ==================================================================== sl@0: * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. sl@0: * sl@0: * Redistribution and use in source and binary forms, with or without sl@0: * modification, are permitted provided that the following conditions sl@0: * are met: sl@0: * sl@0: * 1. Redistributions of source code must retain the above copyright sl@0: * notice, this list of conditions and the following disclaimer. sl@0: * sl@0: * 2. Redistributions in binary form must reproduce the above copyright sl@0: * notice, this list of conditions and the following disclaimer in sl@0: * the documentation and/or other materials provided with the sl@0: * distribution. sl@0: * sl@0: * 3. All advertising materials mentioning features or use of this sl@0: * software must display the following acknowledgment: sl@0: * "This product includes software developed by the OpenSSL Project sl@0: * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" sl@0: * sl@0: * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to sl@0: * endorse or promote products derived from this software without sl@0: * prior written permission. For written permission, please contact sl@0: * openssl-core@openssl.org. sl@0: * sl@0: * 5. Products derived from this software may not be called "OpenSSL" sl@0: * nor may "OpenSSL" appear in their names without prior written sl@0: * permission of the OpenSSL Project. sl@0: * sl@0: * 6. Redistributions of any form whatsoever must retain the following sl@0: * acknowledgment: sl@0: * "This product includes software developed by the OpenSSL Project sl@0: * for use in the OpenSSL Toolkit (http://www.openssl.org/)" sl@0: * sl@0: * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY sl@0: * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE sl@0: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR sl@0: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR sl@0: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, sl@0: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT sl@0: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; sl@0: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) sl@0: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, sl@0: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) sl@0: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED sl@0: * OF THE POSSIBILITY OF SUCH DAMAGE. sl@0: * ==================================================================== sl@0: * sl@0: * This product includes cryptographic software written by Eric Young sl@0: * (eay@cryptsoft.com). This product includes software written by Tim sl@0: * Hudson (tjh@cryptsoft.com). sl@0: * sl@0: */ sl@0: sl@0: #include sl@0: #include "ssl_locl.h" sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: static void tls1_P_hash(const EVP_MD *md, const unsigned char *sec, sl@0: int sec_len, unsigned char *seed, int seed_len, sl@0: unsigned char *out, int olen) sl@0: { sl@0: int chunk,n; sl@0: unsigned int j; sl@0: HMAC_CTX ctx; sl@0: HMAC_CTX ctx_tmp; sl@0: unsigned char A1[EVP_MAX_MD_SIZE]; sl@0: unsigned int A1_len; sl@0: sl@0: chunk=EVP_MD_size(md); sl@0: sl@0: HMAC_CTX_init(&ctx); sl@0: HMAC_CTX_init(&ctx_tmp); sl@0: HMAC_Init_ex(&ctx,sec,sec_len,md, NULL); sl@0: HMAC_Init_ex(&ctx_tmp,sec,sec_len,md, NULL); sl@0: HMAC_Update(&ctx,seed,seed_len); sl@0: HMAC_Final(&ctx,A1,&A1_len); sl@0: sl@0: n=0; sl@0: for (;;) sl@0: { sl@0: HMAC_Init_ex(&ctx,NULL,0,NULL,NULL); /* re-init */ sl@0: HMAC_Init_ex(&ctx_tmp,NULL,0,NULL,NULL); /* re-init */ sl@0: HMAC_Update(&ctx,A1,A1_len); sl@0: HMAC_Update(&ctx_tmp,A1,A1_len); sl@0: HMAC_Update(&ctx,seed,seed_len); sl@0: sl@0: if (olen > chunk) sl@0: { sl@0: HMAC_Final(&ctx,out,&j); sl@0: out+=j; sl@0: olen-=j; sl@0: HMAC_Final(&ctx_tmp,A1,&A1_len); /* calc the next A1 value */ sl@0: } sl@0: else /* last one */ sl@0: { sl@0: HMAC_Final(&ctx,A1,&A1_len); sl@0: memcpy(out,A1,olen); sl@0: break; sl@0: } sl@0: } sl@0: HMAC_CTX_cleanup(&ctx); sl@0: HMAC_CTX_cleanup(&ctx_tmp); sl@0: OPENSSL_cleanse(A1,sizeof(A1)); sl@0: } sl@0: sl@0: static void tls1_PRF(const EVP_MD *md5, const EVP_MD *sha1, sl@0: unsigned char *label, int label_len, sl@0: const unsigned char *sec, int slen, unsigned char *out1, sl@0: unsigned char *out2, int olen) sl@0: { sl@0: int len,i; sl@0: const unsigned char *S1,*S2; sl@0: sl@0: len=slen/2; sl@0: S1=sec; sl@0: S2= &(sec[len]); sl@0: len+=(slen&1); /* add for odd, make longer */ sl@0: sl@0: sl@0: tls1_P_hash(md5 ,S1,len,label,label_len,out1,olen); sl@0: tls1_P_hash(sha1,S2,len,label,label_len,out2,olen); sl@0: sl@0: for (i=0; is3->server_random,SSL3_RANDOM_SIZE); sl@0: p+=SSL3_RANDOM_SIZE; sl@0: memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE); sl@0: p+=SSL3_RANDOM_SIZE; sl@0: sl@0: tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,(int)(p-buf), sl@0: s->session->master_key,s->session->master_key_length, sl@0: km,tmp,num); sl@0: #ifdef KSSL_DEBUG sl@0: printf("tls1_generate_key_block() ==> %d byte master_key =\n\t", sl@0: s->session->master_key_length); sl@0: { sl@0: int i; sl@0: for (i=0; i < s->session->master_key_length; i++) sl@0: { sl@0: printf("%02X", s->session->master_key[i]); sl@0: } sl@0: printf("\n"); } sl@0: #endif /* KSSL_DEBUG */ sl@0: } sl@0: sl@0: int tls1_change_cipher_state(SSL *s, int which) sl@0: { sl@0: static const unsigned char empty[]=""; sl@0: unsigned char *p,*key_block,*mac_secret; sl@0: unsigned char *exp_label,buf[TLS_MD_MAX_CONST_SIZE+ sl@0: SSL3_RANDOM_SIZE*2]; sl@0: unsigned char tmp1[EVP_MAX_KEY_LENGTH]; sl@0: unsigned char tmp2[EVP_MAX_KEY_LENGTH]; sl@0: unsigned char iv1[EVP_MAX_IV_LENGTH*2]; sl@0: unsigned char iv2[EVP_MAX_IV_LENGTH*2]; sl@0: unsigned char *ms,*key,*iv,*er1,*er2; sl@0: int client_write; sl@0: EVP_CIPHER_CTX *dd; sl@0: const EVP_CIPHER *c; sl@0: #ifndef OPENSSL_NO_COMP sl@0: const SSL_COMP *comp; sl@0: #endif sl@0: const EVP_MD *m; sl@0: int is_export,n,i,j,k,exp_label_len,cl; sl@0: int reuse_dd = 0; sl@0: sl@0: is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher); sl@0: c=s->s3->tmp.new_sym_enc; sl@0: m=s->s3->tmp.new_hash; sl@0: #ifndef OPENSSL_NO_COMP sl@0: comp=s->s3->tmp.new_compression; sl@0: #endif sl@0: key_block=s->s3->tmp.key_block; sl@0: sl@0: #ifdef KSSL_DEBUG sl@0: printf("tls1_change_cipher_state(which= %d) w/\n", which); sl@0: printf("\talg= %ld, comp= %p\n", s->s3->tmp.new_cipher->algorithms, sl@0: comp); sl@0: printf("\tevp_cipher == %p ==? &d_cbc_ede_cipher3\n", c); sl@0: printf("\tevp_cipher: nid, blksz= %d, %d, keylen=%d, ivlen=%d\n", sl@0: c->nid,c->block_size,c->key_len,c->iv_len); sl@0: printf("\tkey_block: len= %d, data= ", s->s3->tmp.key_block_length); sl@0: { sl@0: int i; sl@0: for (i=0; is3->tmp.key_block_length; i++) sl@0: printf("%02x", key_block[i]); printf("\n"); sl@0: } sl@0: #endif /* KSSL_DEBUG */ sl@0: sl@0: if (which & SSL3_CC_READ) sl@0: { sl@0: if (s->enc_read_ctx != NULL) sl@0: reuse_dd = 1; sl@0: else if ((s->enc_read_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL) sl@0: goto err; sl@0: else sl@0: /* make sure it's intialized in case we exit later with an error */ sl@0: EVP_CIPHER_CTX_init(s->enc_read_ctx); sl@0: dd= s->enc_read_ctx; sl@0: s->read_hash=m; sl@0: #ifndef OPENSSL_NO_COMP sl@0: if (s->expand != NULL) sl@0: { sl@0: COMP_CTX_free(s->expand); sl@0: s->expand=NULL; sl@0: } sl@0: if (comp != NULL) sl@0: { sl@0: s->expand=COMP_CTX_new(comp->method); sl@0: if (s->expand == NULL) sl@0: { sl@0: SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR); sl@0: goto err2; sl@0: } sl@0: if (s->s3->rrec.comp == NULL) sl@0: s->s3->rrec.comp=(unsigned char *) sl@0: OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LENGTH); sl@0: if (s->s3->rrec.comp == NULL) sl@0: goto err; sl@0: } sl@0: #endif sl@0: /* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */ sl@0: if (s->version != DTLS1_VERSION) sl@0: memset(&(s->s3->read_sequence[0]),0,8); sl@0: mac_secret= &(s->s3->read_mac_secret[0]); sl@0: } sl@0: else sl@0: { sl@0: if (s->enc_write_ctx != NULL) sl@0: reuse_dd = 1; sl@0: else if ((s->enc_write_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL) sl@0: goto err; sl@0: else sl@0: /* make sure it's intialized in case we exit later with an error */ sl@0: EVP_CIPHER_CTX_init(s->enc_write_ctx); sl@0: dd= s->enc_write_ctx; sl@0: s->write_hash=m; sl@0: #ifndef OPENSSL_NO_COMP sl@0: if (s->compress != NULL) sl@0: { sl@0: COMP_CTX_free(s->compress); sl@0: s->compress=NULL; sl@0: } sl@0: if (comp != NULL) sl@0: { sl@0: s->compress=COMP_CTX_new(comp->method); sl@0: if (s->compress == NULL) sl@0: { sl@0: SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR); sl@0: goto err2; sl@0: } sl@0: } sl@0: #endif sl@0: /* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */ sl@0: if (s->version != DTLS1_VERSION) sl@0: memset(&(s->s3->write_sequence[0]),0,8); sl@0: mac_secret= &(s->s3->write_mac_secret[0]); sl@0: } sl@0: sl@0: if (reuse_dd) sl@0: EVP_CIPHER_CTX_cleanup(dd); sl@0: sl@0: p=s->s3->tmp.key_block; sl@0: i=EVP_MD_size(m); sl@0: cl=EVP_CIPHER_key_length(c); sl@0: j=is_export ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ? sl@0: cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl; sl@0: /* Was j=(exp)?5:EVP_CIPHER_key_length(c); */ sl@0: k=EVP_CIPHER_iv_length(c); sl@0: er1= &(s->s3->client_random[0]); sl@0: er2= &(s->s3->server_random[0]); sl@0: if ( (which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) || sl@0: (which == SSL3_CHANGE_CIPHER_SERVER_READ)) sl@0: { sl@0: ms= &(p[ 0]); n=i+i; sl@0: key= &(p[ n]); n+=j+j; sl@0: iv= &(p[ n]); n+=k+k; sl@0: exp_label=(unsigned char *)TLS_MD_CLIENT_WRITE_KEY_CONST; sl@0: exp_label_len=TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE; sl@0: client_write=1; sl@0: } sl@0: else sl@0: { sl@0: n=i; sl@0: ms= &(p[ n]); n+=i+j; sl@0: key= &(p[ n]); n+=j+k; sl@0: iv= &(p[ n]); n+=k; sl@0: exp_label=(unsigned char *)TLS_MD_SERVER_WRITE_KEY_CONST; sl@0: exp_label_len=TLS_MD_SERVER_WRITE_KEY_CONST_SIZE; sl@0: client_write=0; sl@0: } sl@0: sl@0: if (n > s->s3->tmp.key_block_length) sl@0: { sl@0: SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_INTERNAL_ERROR); sl@0: goto err2; sl@0: } sl@0: sl@0: memcpy(mac_secret,ms,i); sl@0: #ifdef TLS_DEBUG sl@0: printf("which = %04X\nmac key=",which); sl@0: { int z; for (z=0; zs3->client_random,SSL3_RANDOM_SIZE); sl@0: p+=SSL3_RANDOM_SIZE; sl@0: memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE); sl@0: p+=SSL3_RANDOM_SIZE; sl@0: tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,(int)(p-buf),key,j, sl@0: tmp1,tmp2,EVP_CIPHER_key_length(c)); sl@0: key=tmp1; sl@0: sl@0: if (k > 0) sl@0: { sl@0: p=buf; sl@0: memcpy(p,TLS_MD_IV_BLOCK_CONST, sl@0: TLS_MD_IV_BLOCK_CONST_SIZE); sl@0: p+=TLS_MD_IV_BLOCK_CONST_SIZE; sl@0: memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE); sl@0: p+=SSL3_RANDOM_SIZE; sl@0: memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE); sl@0: p+=SSL3_RANDOM_SIZE; sl@0: tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,p-buf,empty,0, sl@0: iv1,iv2,k*2); sl@0: if (client_write) sl@0: iv=iv1; sl@0: else sl@0: iv= &(iv1[k]); sl@0: } sl@0: } sl@0: sl@0: s->session->key_arg_length=0; sl@0: #ifdef KSSL_DEBUG sl@0: { sl@0: int i; sl@0: printf("EVP_CipherInit_ex(dd,c,key=,iv=,which)\n"); sl@0: printf("\tkey= "); for (i=0; ikey_len; i++) printf("%02x", key[i]); sl@0: printf("\n"); sl@0: printf("\t iv= "); for (i=0; iiv_len; i++) printf("%02x", iv[i]); sl@0: printf("\n"); sl@0: } sl@0: #endif /* KSSL_DEBUG */ sl@0: sl@0: EVP_CipherInit_ex(dd,c,NULL,key,iv,(which & SSL3_CC_WRITE)); sl@0: #ifdef TLS_DEBUG sl@0: printf("which = %04X\nkey=",which); sl@0: { int z; for (z=0; zs3->tmp.key_block_length != 0) sl@0: return(1); sl@0: sl@0: if (!ssl_cipher_get_evp(s->session,&c,&hash,&comp)) sl@0: { sl@0: SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,SSL_R_CIPHER_OR_HASH_UNAVAILABLE); sl@0: return(0); sl@0: } sl@0: sl@0: s->s3->tmp.new_sym_enc=c; sl@0: s->s3->tmp.new_hash=hash; sl@0: sl@0: num=EVP_CIPHER_key_length(c)+EVP_MD_size(hash)+EVP_CIPHER_iv_length(c); sl@0: num*=2; sl@0: sl@0: ssl3_cleanup_key_block(s); sl@0: sl@0: if ((p1=(unsigned char *)OPENSSL_malloc(num)) == NULL) sl@0: goto err; sl@0: if ((p2=(unsigned char *)OPENSSL_malloc(num)) == NULL) sl@0: goto err; sl@0: sl@0: s->s3->tmp.key_block_length=num; sl@0: s->s3->tmp.key_block=p1; sl@0: sl@0: sl@0: #ifdef TLS_DEBUG sl@0: printf("client random\n"); sl@0: { int z; for (z=0; zs3->client_random[z],((z+1)%16)?' ':'\n'); } sl@0: printf("server random\n"); sl@0: { int z; for (z=0; zs3->server_random[z],((z+1)%16)?' ':'\n'); } sl@0: printf("pre-master\n"); sl@0: { int z; for (z=0; zsession->master_key_length; z++) printf("%02X%c",s->session->master_key[z],((z+1)%16)?' ':'\n'); } sl@0: #endif sl@0: tls1_generate_key_block(s,p1,p2,num); sl@0: OPENSSL_cleanse(p2,num); sl@0: OPENSSL_free(p2); sl@0: #ifdef TLS_DEBUG sl@0: printf("\nkey block\n"); sl@0: { int z; for (z=0; zoptions & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) sl@0: { sl@0: /* enable vulnerability countermeasure for CBC ciphers with sl@0: * known-IV problem (http://www.openssl.org/~bodo/tls-cbc.txt) sl@0: */ sl@0: s->s3->need_empty_fragments = 1; sl@0: sl@0: if (s->session->cipher != NULL) sl@0: { sl@0: if ((s->session->cipher->algorithms & SSL_ENC_MASK) == SSL_eNULL) sl@0: s->s3->need_empty_fragments = 0; sl@0: sl@0: #ifndef OPENSSL_NO_RC4 sl@0: if ((s->session->cipher->algorithms & SSL_ENC_MASK) == SSL_RC4) sl@0: s->s3->need_empty_fragments = 0; sl@0: #endif sl@0: } sl@0: } sl@0: sl@0: return(1); sl@0: err: sl@0: SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,ERR_R_MALLOC_FAILURE); sl@0: return(0); sl@0: } sl@0: sl@0: int tls1_enc(SSL *s, int send) sl@0: { sl@0: SSL3_RECORD *rec; sl@0: EVP_CIPHER_CTX *ds; sl@0: unsigned long l; sl@0: int bs,i,ii,j,k,n=0; sl@0: const EVP_CIPHER *enc; sl@0: sl@0: if (send) sl@0: { sl@0: if (s->write_hash != NULL) sl@0: n=EVP_MD_size(s->write_hash); sl@0: ds=s->enc_write_ctx; sl@0: rec= &(s->s3->wrec); sl@0: if (s->enc_write_ctx == NULL) sl@0: enc=NULL; sl@0: else sl@0: enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx); sl@0: } sl@0: else sl@0: { sl@0: if (s->read_hash != NULL) sl@0: n=EVP_MD_size(s->read_hash); sl@0: ds=s->enc_read_ctx; sl@0: rec= &(s->s3->rrec); sl@0: if (s->enc_read_ctx == NULL) sl@0: enc=NULL; sl@0: else sl@0: enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx); sl@0: } sl@0: sl@0: #ifdef KSSL_DEBUG sl@0: printf("tls1_enc(%d)\n", send); sl@0: #endif /* KSSL_DEBUG */ sl@0: sl@0: if ((s->session == NULL) || (ds == NULL) || sl@0: (enc == NULL)) sl@0: { sl@0: memmove(rec->data,rec->input,rec->length); sl@0: rec->input=rec->data; sl@0: } sl@0: else sl@0: { sl@0: l=rec->length; sl@0: bs=EVP_CIPHER_block_size(ds->cipher); sl@0: sl@0: if ((bs != 1) && send) sl@0: { sl@0: i=bs-((int)l%bs); sl@0: sl@0: /* Add weird padding of upto 256 bytes */ sl@0: sl@0: /* we need to add 'i' padding bytes of value j */ sl@0: j=i-1; sl@0: if (s->options & SSL_OP_TLS_BLOCK_PADDING_BUG) sl@0: { sl@0: if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) sl@0: j++; sl@0: } sl@0: for (k=(int)l; k<(int)(l+i); k++) sl@0: rec->input[k]=j; sl@0: l+=i; sl@0: rec->length+=i; sl@0: } sl@0: sl@0: #ifdef KSSL_DEBUG sl@0: { sl@0: unsigned long ui; sl@0: printf("EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n", sl@0: ds,rec->data,rec->input,l); sl@0: printf("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%d %d], %d iv_len\n", sl@0: ds->buf_len, ds->cipher->key_len, sl@0: DES_KEY_SZ, DES_SCHEDULE_SZ, sl@0: ds->cipher->iv_len); sl@0: printf("\t\tIV: "); sl@0: for (i=0; icipher->iv_len; i++) printf("%02X", ds->iv[i]); sl@0: printf("\n"); sl@0: printf("\trec->input="); sl@0: for (ui=0; uiinput[ui]); sl@0: printf("\n"); sl@0: } sl@0: #endif /* KSSL_DEBUG */ sl@0: sl@0: if (!send) sl@0: { sl@0: if (l == 0 || l%bs != 0) sl@0: { sl@0: SSLerr(SSL_F_TLS1_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); sl@0: ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED); sl@0: return 0; sl@0: } sl@0: } sl@0: sl@0: EVP_Cipher(ds,rec->data,rec->input,l); sl@0: sl@0: #ifdef KSSL_DEBUG sl@0: { sl@0: unsigned long i; sl@0: printf("\trec->data="); sl@0: for (i=0; idata[i]); printf("\n"); sl@0: } sl@0: #endif /* KSSL_DEBUG */ sl@0: sl@0: if ((bs != 1) && !send) sl@0: { sl@0: ii=i=rec->data[l-1]; /* padding_length */ sl@0: i++; sl@0: /* NB: if compression is in operation the first packet sl@0: * may not be of even length so the padding bug check sl@0: * cannot be performed. This bug workaround has been sl@0: * around since SSLeay so hopefully it is either fixed sl@0: * now or no buggy implementation supports compression sl@0: * [steve] sl@0: */ sl@0: if ( (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG) sl@0: && !s->expand) sl@0: { sl@0: /* First packet is even in size, so check */ sl@0: if ((memcmp(s->s3->read_sequence, sl@0: "\0\0\0\0\0\0\0\0",8) == 0) && !(ii & 1)) sl@0: s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG; sl@0: if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) sl@0: i--; sl@0: } sl@0: /* TLS 1.0 does not bound the number of padding bytes by the block size. sl@0: * All of them must have value 'padding_length'. */ sl@0: if (i > (int)rec->length) sl@0: { sl@0: /* Incorrect padding. SSLerr() and ssl3_alert are done sl@0: * by caller: we don't want to reveal whether this is sl@0: * a decryption error or a MAC verification failure sl@0: * (see http://www.openssl.org/~bodo/tls-cbc.txt) */ sl@0: return -1; sl@0: } sl@0: for (j=(int)(l-i); j<(int)l; j++) sl@0: { sl@0: if (rec->data[j] != ii) sl@0: { sl@0: /* Incorrect padding */ sl@0: return -1; sl@0: } sl@0: } sl@0: rec->length-=i; sl@0: } sl@0: } sl@0: return(1); sl@0: } sl@0: sl@0: int tls1_cert_verify_mac(SSL *s, EVP_MD_CTX *in_ctx, unsigned char *out) sl@0: { sl@0: unsigned int ret; sl@0: EVP_MD_CTX ctx; sl@0: sl@0: EVP_MD_CTX_init(&ctx); sl@0: EVP_MD_CTX_copy_ex(&ctx,in_ctx); sl@0: EVP_DigestFinal_ex(&ctx,out,&ret); sl@0: EVP_MD_CTX_cleanup(&ctx); sl@0: return((int)ret); sl@0: } sl@0: sl@0: int tls1_final_finish_mac(SSL *s, EVP_MD_CTX *in1_ctx, EVP_MD_CTX *in2_ctx, sl@0: const char *str, int slen, unsigned char *out) sl@0: { sl@0: unsigned int i; sl@0: EVP_MD_CTX ctx; sl@0: unsigned char buf[TLS_MD_MAX_CONST_SIZE+MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH]; sl@0: unsigned char *q,buf2[12]; sl@0: sl@0: q=buf; sl@0: memcpy(q,str,slen); sl@0: q+=slen; sl@0: sl@0: EVP_MD_CTX_init(&ctx); sl@0: EVP_MD_CTX_copy_ex(&ctx,in1_ctx); sl@0: EVP_DigestFinal_ex(&ctx,q,&i); sl@0: q+=i; sl@0: EVP_MD_CTX_copy_ex(&ctx,in2_ctx); sl@0: EVP_DigestFinal_ex(&ctx,q,&i); sl@0: q+=i; sl@0: sl@0: tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,(int)(q-buf), sl@0: s->session->master_key,s->session->master_key_length, sl@0: out,buf2,sizeof buf2); sl@0: EVP_MD_CTX_cleanup(&ctx); sl@0: sl@0: return sizeof buf2; sl@0: } sl@0: sl@0: int tls1_mac(SSL *ssl, unsigned char *md, int send) sl@0: { sl@0: SSL3_RECORD *rec; sl@0: unsigned char *mac_sec,*seq; sl@0: const EVP_MD *hash; sl@0: unsigned int md_size; sl@0: int i; sl@0: HMAC_CTX hmac; sl@0: unsigned char buf[5]; sl@0: sl@0: if (send) sl@0: { sl@0: rec= &(ssl->s3->wrec); sl@0: mac_sec= &(ssl->s3->write_mac_secret[0]); sl@0: seq= &(ssl->s3->write_sequence[0]); sl@0: hash=ssl->write_hash; sl@0: } sl@0: else sl@0: { sl@0: rec= &(ssl->s3->rrec); sl@0: mac_sec= &(ssl->s3->read_mac_secret[0]); sl@0: seq= &(ssl->s3->read_sequence[0]); sl@0: hash=ssl->read_hash; sl@0: } sl@0: sl@0: md_size=EVP_MD_size(hash); sl@0: sl@0: buf[0]=rec->type; sl@0: if (ssl->version == DTLS1_VERSION && ssl->client_version == DTLS1_BAD_VER) sl@0: { sl@0: buf[1]=TLS1_VERSION_MAJOR; sl@0: buf[2]=TLS1_VERSION_MINOR; sl@0: } sl@0: else { sl@0: buf[1]=(unsigned char)(ssl->version>>8); sl@0: buf[2]=(unsigned char)(ssl->version); sl@0: } sl@0: sl@0: buf[3]=rec->length>>8; sl@0: buf[4]=rec->length&0xff; sl@0: sl@0: /* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */ sl@0: HMAC_CTX_init(&hmac); sl@0: HMAC_Init_ex(&hmac,mac_sec,EVP_MD_size(hash),hash,NULL); sl@0: sl@0: if (ssl->version == DTLS1_VERSION && ssl->client_version != DTLS1_BAD_VER) sl@0: { sl@0: unsigned char dtlsseq[8],*p=dtlsseq; sl@0: sl@0: s2n(send?ssl->d1->w_epoch:ssl->d1->r_epoch, p); sl@0: memcpy (p,&seq[2],6); sl@0: sl@0: HMAC_Update(&hmac,dtlsseq,8); sl@0: } sl@0: else sl@0: HMAC_Update(&hmac,seq,8); sl@0: sl@0: HMAC_Update(&hmac,buf,5); sl@0: HMAC_Update(&hmac,rec->input,rec->length); sl@0: HMAC_Final(&hmac,md,&md_size); sl@0: HMAC_CTX_cleanup(&hmac); sl@0: sl@0: #ifdef TLS_DEBUG sl@0: printf("sec="); sl@0: {unsigned int z; for (z=0; z=0; i--) sl@0: { sl@0: ++seq[i]; sl@0: if (seq[i] != 0) break; sl@0: } sl@0: } sl@0: sl@0: #ifdef TLS_DEBUG sl@0: {unsigned int z; for (z=0; zs3->client_random,SSL3_RANDOM_SIZE); sl@0: memcpy(&(buf[SSL3_RANDOM_SIZE+TLS_MD_MASTER_SECRET_CONST_SIZE]), sl@0: s->s3->server_random,SSL3_RANDOM_SIZE); sl@0: tls1_PRF(s->ctx->md5,s->ctx->sha1, sl@0: buf,TLS_MD_MASTER_SECRET_CONST_SIZE+SSL3_RANDOM_SIZE*2,p,len, sl@0: s->session->master_key,buff,sizeof buff); sl@0: #ifdef KSSL_DEBUG sl@0: printf ("tls1_generate_master_secret() complete\n"); sl@0: #endif /* KSSL_DEBUG */ sl@0: return(SSL3_MASTER_SECRET_SIZE); sl@0: } sl@0: sl@0: int tls1_alert_code(int code) sl@0: { sl@0: switch (code) sl@0: { sl@0: case SSL_AD_CLOSE_NOTIFY: return(SSL3_AD_CLOSE_NOTIFY); sl@0: case SSL_AD_UNEXPECTED_MESSAGE: return(SSL3_AD_UNEXPECTED_MESSAGE); sl@0: case SSL_AD_BAD_RECORD_MAC: return(SSL3_AD_BAD_RECORD_MAC); sl@0: case SSL_AD_DECRYPTION_FAILED: return(TLS1_AD_DECRYPTION_FAILED); sl@0: case SSL_AD_RECORD_OVERFLOW: return(TLS1_AD_RECORD_OVERFLOW); sl@0: case SSL_AD_DECOMPRESSION_FAILURE:return(SSL3_AD_DECOMPRESSION_FAILURE); sl@0: case SSL_AD_HANDSHAKE_FAILURE: return(SSL3_AD_HANDSHAKE_FAILURE); sl@0: case SSL_AD_NO_CERTIFICATE: return(-1); sl@0: case SSL_AD_BAD_CERTIFICATE: return(SSL3_AD_BAD_CERTIFICATE); sl@0: case SSL_AD_UNSUPPORTED_CERTIFICATE:return(SSL3_AD_UNSUPPORTED_CERTIFICATE); sl@0: case SSL_AD_CERTIFICATE_REVOKED:return(SSL3_AD_CERTIFICATE_REVOKED); sl@0: case SSL_AD_CERTIFICATE_EXPIRED:return(SSL3_AD_CERTIFICATE_EXPIRED); sl@0: case SSL_AD_CERTIFICATE_UNKNOWN:return(SSL3_AD_CERTIFICATE_UNKNOWN); sl@0: case SSL_AD_ILLEGAL_PARAMETER: return(SSL3_AD_ILLEGAL_PARAMETER); sl@0: case SSL_AD_UNKNOWN_CA: return(TLS1_AD_UNKNOWN_CA); sl@0: case SSL_AD_ACCESS_DENIED: return(TLS1_AD_ACCESS_DENIED); sl@0: case SSL_AD_DECODE_ERROR: return(TLS1_AD_DECODE_ERROR); sl@0: case SSL_AD_DECRYPT_ERROR: return(TLS1_AD_DECRYPT_ERROR); sl@0: case SSL_AD_EXPORT_RESTRICTION: return(TLS1_AD_EXPORT_RESTRICTION); sl@0: case SSL_AD_PROTOCOL_VERSION: return(TLS1_AD_PROTOCOL_VERSION); sl@0: case SSL_AD_INSUFFICIENT_SECURITY:return(TLS1_AD_INSUFFICIENT_SECURITY); sl@0: case SSL_AD_INTERNAL_ERROR: return(TLS1_AD_INTERNAL_ERROR); sl@0: case SSL_AD_USER_CANCELLED: return(TLS1_AD_USER_CANCELLED); sl@0: case SSL_AD_NO_RENEGOTIATION: return(TLS1_AD_NO_RENEGOTIATION); sl@0: case DTLS1_AD_MISSING_HANDSHAKE_MESSAGE: return sl@0: (DTLS1_AD_MISSING_HANDSHAKE_MESSAGE); sl@0: default: return(-1); sl@0: } sl@0: } sl@0: