- {
- 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);
- EVP_MD_CTX *hdgst = s->s3->handshake_dgst[idx];
- if (!hdgst || hashsize < 0 || hashsize > (int)(sizeof buf - (size_t)(q-buf)))
- {
- /* internal error: 'buf' is too small for this cipersuite! */
- err = 1;
- }
- else
- {
- if (!EVP_MD_CTX_copy_ex(&ctx, hdgst) ||
- !EVP_DigestFinal_ex(&ctx,q,&i) ||
- (i != (unsigned int)hashsize))
- err = 1;
- q+=hashsize;
- }
- }
- }
-
- 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;
- 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
- {
- if (!EVP_MD_CTX_copy(&hmac,hash))
- return -1;
- mac_ctx = &hmac;
- }
-
- if (SSL_IS_DTLS(ssl))
- {
- unsigned char dtlsseq[8],*p=dtlsseq;
-
- s2n(send?ssl->d1->w_epoch:ssl->d1->r_epoch, p);
- memcpy (p,&seq[2],6);
-
- memcpy(header, dtlsseq, 8);
- }
- else
- memcpy(header, seq, 8);
-
- header[8]=rec->type;
- header[9]=(unsigned char)(ssl->version>>8);
- header[10]=(unsigned char)(ssl->version);
- header[11]=(rec->length)>>8;
- header[12]=(rec->length)&0xff;
-
- if (!send && !SSL_USE_ETM(ssl) &&
- EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
- ssl3_cbc_record_digest_supported(mac_ctx))
- {
- /* This is a CBC-encrypted record. We must avoid leaking any
- * timing-side channel information about how many blocks of
- * data we are hashing because that gives an attacker a
- * timing-oracle. */
- ssl3_cbc_digest_record(
- mac_ctx,
- md, &md_size,
- header, rec->input,
- rec->length + md_size, rec->orig_len,
- ssl->s3->read_mac_secret,
- ssl->s3->read_mac_secret_size,
- 0 /* not SSLv3 */);
- }
- else
- {
- EVP_DigestSignUpdate(mac_ctx,header,sizeof(header));
- EVP_DigestSignUpdate(mac_ctx,rec->input,rec->length);
- t=EVP_DigestSignFinal(mac_ctx,md,&md_size);
- OPENSSL_assert(t > 0);
-#ifdef OPENSSL_FIPS
- if (!send && !SSL_USE_ETM(ssl) && FIPS_mode())
- tls_fips_digest_extra(
- ssl->enc_read_ctx,
- mac_ctx, rec->input,
- rec->length, rec->orig_len);
-#endif
- }
-
- if (!stream_mac)
- 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"); }
-printf("seq=");
-{int z; for (z=0; z<8; z++) printf("%02X ",seq[z]); printf("\n"); }
-printf("buf=");
-{int z; for (z=0; z<5; z++) printf("%02X ",buf[z]); printf("\n"); }
-printf("rec=");
-{unsigned int z; for (z=0; z<rec->length; z++) printf("%02X ",buf[z]); printf("\n"); }
-#endif
-
- if (!SSL_IS_DTLS(ssl))
- {
- for (i=7; i>=0; i--)
- {
- ++seq[i];
- if (seq[i] != 0) break;
- }
- }