- }
- }
-
- ret = 1;
-err:
- if (p2)
- {
- OPENSSL_cleanse(p2,num);
- OPENSSL_free(p2);
- }
- return(ret);
- }
-
-/* tls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively.
- *
- * Returns:
- * 0: (in non-constant time) if the record is publically invalid (i.e. too
- * short etc).
- * 1: if the record's padding is valid / the encryption was successful.
- * -1: if the record's padding/AEAD-authenticator is invalid or, if sending,
- * an internal error occured.
- */
-int tls1_enc(SSL *s, int send)
- {
- SSL3_RECORD *rec;
- EVP_CIPHER_CTX *ds;
- unsigned long l;
- int bs,i,j,k,pad=0,ret,mac_size=0;
- const EVP_CIPHER *enc;
-
- if (send)
- {
- if (EVP_MD_CTX_md(s->write_hash))
- {
- int n=EVP_MD_CTX_size(s->write_hash);
- OPENSSL_assert(n >= 0);
- }
- ds=s->enc_write_ctx;
- rec= &(s->s3->wrec);
- if (s->enc_write_ctx == NULL)
- enc=NULL;
- else
- {
- int ivlen;
- enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
- /* For TLSv1.1 and later explicit IV */
- if (s->version >= TLS1_1_VERSION
- && EVP_CIPHER_mode(enc) == EVP_CIPH_CBC_MODE)
- ivlen = EVP_CIPHER_iv_length(enc);
- else
- ivlen = 0;
- if (ivlen > 1)
- {
- if ( rec->data != rec->input)
- /* we can't write into the input stream:
- * Can this ever happen?? (steve)
- */
- fprintf(stderr,
- "%s:%d: rec->data != rec->input\n",
- __FILE__, __LINE__);
- else if (RAND_bytes(rec->input, ivlen) <= 0)
- return -1;
- }
- }
- }
- else
- {
- if (EVP_MD_CTX_md(s->read_hash))
- {
- int n=EVP_MD_CTX_size(s->read_hash);
- OPENSSL_assert(n >= 0);
- }
- ds=s->enc_read_ctx;
- rec= &(s->s3->rrec);
- if (s->enc_read_ctx == NULL)
- enc=NULL;
- else
- 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))
- {
- memmove(rec->data,rec->input,rec->length);
- rec->input=rec->data;
- ret = 1;
- }
- else
- {
- l=rec->length;
- bs=EVP_CIPHER_block_size(ds->cipher);
-
- if (EVP_CIPHER_flags(ds->cipher)&EVP_CIPH_FLAG_AEAD_CIPHER)
- {
- unsigned char buf[13],*seq;
-
- seq = send?s->s3->write_sequence:s->s3->read_sequence;
-
- if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER)
- {
- unsigned char dtlsseq[9],*p=dtlsseq;
-
- s2n(send?s->d1->w_epoch:s->d1->r_epoch,p);
- memcpy(p,&seq[2],6);
- memcpy(buf,dtlsseq,8);
- }
- else
- {
- memcpy(buf,seq,8);
- for (i=7; i>=0; i--) /* increment */
- {
- ++seq[i];
- if (seq[i] != 0) break;
- }
- }
-
- buf[8]=rec->type;
- buf[9]=(unsigned char)(s->version>>8);
- buf[10]=(unsigned char)(s->version);
- buf[11]=rec->length>>8;
- buf[12]=rec->length&0xff;
- pad=EVP_CIPHER_CTX_ctrl(ds,EVP_CTRL_AEAD_TLS1_AAD,13,buf);
- if (send)
- {
- l+=pad;
- rec->length+=pad;
- }
- }
- else if ((bs != 1) && send)
- {
- i=bs-((int)l%bs);
-
- /* Add weird padding of upto 256 bytes */
-
- /* we need to add 'i' padding bytes of value j */
- j=i-1;
- if (s->options & SSL_OP_TLS_BLOCK_PADDING_BUG)
- {
- if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG)
- j++;
- }
- for (k=(int)l; k<(int)(l+i); k++)
- rec->input[k]=j;
- l+=i;
- 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)
- return 0;
- }
-
- i = EVP_Cipher(ds,rec->data,rec->input,l);
- if ((EVP_CIPHER_flags(ds->cipher)&EVP_CIPH_FLAG_CUSTOM_CIPHER)
- ?(i<0)
- :(i==0))
- return -1; /* AEAD can fail to verify MAC */
- if (EVP_CIPHER_mode(enc) == EVP_CIPH_GCM_MODE && !send)
- {
- rec->data += EVP_GCM_TLS_EXPLICIT_IV_LEN;
- rec->input += EVP_GCM_TLS_EXPLICIT_IV_LEN;
- rec->length -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
- }
-
-#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 */
-
- ret = 1;
- if (EVP_MD_CTX_md(s->read_hash) != NULL)
- mac_size = EVP_MD_CTX_size(s->read_hash);
- if ((bs != 1) && !send)
- ret = tls1_cbc_remove_padding(s, rec, bs, mac_size);
- if (pad && !send)
- rec->length -= pad;
- }
- return ret;
- }
-
-int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *out)
- {
- unsigned int ret;
- EVP_MD_CTX ctx, *d=NULL;
- int i;
-
- if (s->s3->handshake_buffer)
- if (!ssl3_digest_cached_records(s))
- return 0;
-
- 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_TLS1_CERT_VERIFY_MAC,SSL_R_NO_REQUIRED_DIGEST);
- return 0;
- }
-
- EVP_MD_CTX_init(&ctx);
- EVP_MD_CTX_copy_ex(&ctx,d);
- EVP_DigestFinal_ex(&ctx,out,&ret);
- EVP_MD_CTX_cleanup(&ctx);
- return((int)ret);
- }
-
-int tls1_final_finish_mac(SSL *s,
- const char *str, int slen, unsigned char *out)
- {
- unsigned int i;
- EVP_MD_CTX ctx;
- unsigned char buf[2*EVP_MAX_MD_SIZE];
- unsigned char *q,buf2[12];
- int idx;
- long mask;
- int err=0;
- const EVP_MD *md;
-
- q=buf;
-
- if (s->s3->handshake_buffer)
- if (!ssl3_digest_cached_records(s))
- return 0;
-
- EVP_MD_CTX_init(&ctx);
-
- for (idx=0;ssl_get_handshake_digest(idx,&mask,&md);idx++)
- {
- if (mask & ssl_get_algorithm2(s))
- {
- int hashsize = EVP_MD_size(md);
- if (hashsize < 0 || hashsize > (int)(sizeof buf - (size_t)(q-buf)))
- {
- /* internal error: 'buf' is too small for this cipersuite! */
- err = 1;
- }
- else
- {
- EVP_MD_CTX_copy_ex(&ctx,s->s3->handshake_dgst[idx]);
- EVP_DigestFinal_ex(&ctx,q,&i);
- if (i != (unsigned int)hashsize) /* can't really happen */
- err = 1;
- q+=i;
- }
- }
- }
-
- if (!tls1_PRF(ssl_get_algorithm2(s),
- str,slen, buf,(int)(q-buf), NULL,0, NULL,0, NULL,0,
- s->session->master_key,s->session->master_key_length,
- out,buf2,sizeof buf2))
- err = 1;
- EVP_MD_CTX_cleanup(&ctx);
-
- if (err)
- return 0;
- else
- return sizeof buf2;
- }
-
-int tls1_mac(SSL *ssl, unsigned char *md, int send)
- {
- SSL3_RECORD *rec;
- unsigned char *seq;
- EVP_MD_CTX *hash;
- size_t md_size, orig_len;
- int i;
- EVP_MD_CTX hmac, *mac_ctx;
- unsigned char header[13];
- int stream_mac = (send?(ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM):(ssl->mac_flags&SSL_MAC_FLAG_READ_MAC_STREAM));
- int t;
-
- if (send)
- {
- rec= &(ssl->s3->wrec);
- seq= &(ssl->s3->write_sequence[0]);
- hash=ssl->write_hash;
- }
- else
- {
- rec= &(ssl->s3->rrec);
- seq= &(ssl->s3->read_sequence[0]);
- hash=ssl->read_hash;
- }
-
- t=EVP_MD_CTX_size(hash);
- OPENSSL_assert(t >= 0);
- md_size=t;
-
- /* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */
- if (stream_mac)
- {
- mac_ctx = hash;
- }
- else
- {
- EVP_MD_CTX_copy(&hmac,hash);
- mac_ctx = &hmac;
- }
-
- if (ssl->version == DTLS1_VERSION || ssl->version == DTLS1_BAD_VER)
- {
- unsigned char dtlsseq[8],*p=dtlsseq;
-
- s2n(send?ssl->d1->w_epoch:ssl->d1->r_epoch, p);
- memcpy (p,&seq[2],6);