1*cca6fc52SDaniel Fojt /* $OpenBSD: ssl_transcript.c,v 1.2 2020/02/05 16:47:34 jsing Exp $ */ 272c33676SMaxim Ag /* 372c33676SMaxim Ag * Copyright (c) 2017 Joel Sing <jsing@openbsd.org> 472c33676SMaxim Ag * 572c33676SMaxim Ag * Permission to use, copy, modify, and distribute this software for any 672c33676SMaxim Ag * purpose with or without fee is hereby granted, provided that the above 772c33676SMaxim Ag * copyright notice and this permission notice appear in all copies. 872c33676SMaxim Ag * 972c33676SMaxim Ag * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1072c33676SMaxim Ag * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1172c33676SMaxim Ag * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1272c33676SMaxim Ag * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1372c33676SMaxim Ag * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1472c33676SMaxim Ag * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1572c33676SMaxim Ag * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1672c33676SMaxim Ag */ 1772c33676SMaxim Ag 1872c33676SMaxim Ag #include "ssl_locl.h" 1972c33676SMaxim Ag 2072c33676SMaxim Ag #include <openssl/ssl.h> 2172c33676SMaxim Ag 2272c33676SMaxim Ag int 2372c33676SMaxim Ag tls1_transcript_hash_init(SSL *s) 2472c33676SMaxim Ag { 2572c33676SMaxim Ag const unsigned char *data; 2672c33676SMaxim Ag const EVP_MD *md; 2772c33676SMaxim Ag size_t len; 2872c33676SMaxim Ag 2972c33676SMaxim Ag tls1_transcript_hash_free(s); 3072c33676SMaxim Ag 3172c33676SMaxim Ag if (!ssl_get_handshake_evp_md(s, &md)) { 3272c33676SMaxim Ag SSLerrorx(ERR_R_INTERNAL_ERROR); 3372c33676SMaxim Ag goto err; 3472c33676SMaxim Ag } 3572c33676SMaxim Ag 3672c33676SMaxim Ag if ((S3I(s)->handshake_hash = EVP_MD_CTX_new()) == NULL) { 3772c33676SMaxim Ag SSLerror(s, ERR_R_MALLOC_FAILURE); 3872c33676SMaxim Ag goto err; 3972c33676SMaxim Ag } 4072c33676SMaxim Ag if (!EVP_DigestInit_ex(S3I(s)->handshake_hash, md, NULL)) { 4172c33676SMaxim Ag SSLerror(s, ERR_R_EVP_LIB); 4272c33676SMaxim Ag goto err; 4372c33676SMaxim Ag } 4472c33676SMaxim Ag 4572c33676SMaxim Ag if (!tls1_transcript_data(s, &data, &len)) { 4672c33676SMaxim Ag SSLerror(s, SSL_R_BAD_HANDSHAKE_LENGTH); 4772c33676SMaxim Ag goto err; 4872c33676SMaxim Ag } 4972c33676SMaxim Ag if (!tls1_transcript_hash_update(s, data, len)) { 5072c33676SMaxim Ag SSLerror(s, ERR_R_EVP_LIB); 5172c33676SMaxim Ag goto err; 5272c33676SMaxim Ag } 5372c33676SMaxim Ag 5472c33676SMaxim Ag return 1; 5572c33676SMaxim Ag 5672c33676SMaxim Ag err: 5772c33676SMaxim Ag tls1_transcript_hash_free(s); 5872c33676SMaxim Ag 5972c33676SMaxim Ag return 0; 6072c33676SMaxim Ag } 6172c33676SMaxim Ag 6272c33676SMaxim Ag int 6372c33676SMaxim Ag tls1_transcript_hash_update(SSL *s, const unsigned char *buf, size_t len) 6472c33676SMaxim Ag { 6572c33676SMaxim Ag if (S3I(s)->handshake_hash == NULL) 6672c33676SMaxim Ag return 1; 6772c33676SMaxim Ag 6872c33676SMaxim Ag return EVP_DigestUpdate(S3I(s)->handshake_hash, buf, len); 6972c33676SMaxim Ag } 7072c33676SMaxim Ag 7172c33676SMaxim Ag int 7272c33676SMaxim Ag tls1_transcript_hash_value(SSL *s, const unsigned char *out, size_t len, 7372c33676SMaxim Ag size_t *outlen) 7472c33676SMaxim Ag { 7572c33676SMaxim Ag EVP_MD_CTX *mdctx = NULL; 7672c33676SMaxim Ag unsigned int mdlen; 7772c33676SMaxim Ag int ret = 0; 7872c33676SMaxim Ag 7972c33676SMaxim Ag if (EVP_MD_CTX_size(S3I(s)->handshake_hash) > len) 8072c33676SMaxim Ag goto err; 8172c33676SMaxim Ag 8272c33676SMaxim Ag if ((mdctx = EVP_MD_CTX_new()) == NULL) { 8372c33676SMaxim Ag SSLerror(s, ERR_R_MALLOC_FAILURE); 8472c33676SMaxim Ag goto err; 8572c33676SMaxim Ag } 8672c33676SMaxim Ag if (!EVP_MD_CTX_copy_ex(mdctx, S3I(s)->handshake_hash)) { 8772c33676SMaxim Ag SSLerror(s, ERR_R_EVP_LIB); 8872c33676SMaxim Ag goto err; 8972c33676SMaxim Ag } 9072c33676SMaxim Ag if (!EVP_DigestFinal_ex(mdctx, (unsigned char *)out, &mdlen)) { 9172c33676SMaxim Ag SSLerror(s, ERR_R_EVP_LIB); 9272c33676SMaxim Ag goto err; 9372c33676SMaxim Ag } 9472c33676SMaxim Ag if (outlen != NULL) 9572c33676SMaxim Ag *outlen = mdlen; 9672c33676SMaxim Ag 9772c33676SMaxim Ag ret = 1; 9872c33676SMaxim Ag 9972c33676SMaxim Ag err: 10072c33676SMaxim Ag EVP_MD_CTX_free(mdctx); 10172c33676SMaxim Ag 10272c33676SMaxim Ag return (ret); 10372c33676SMaxim Ag } 10472c33676SMaxim Ag 10572c33676SMaxim Ag void 10672c33676SMaxim Ag tls1_transcript_hash_free(SSL *s) 10772c33676SMaxim Ag { 10872c33676SMaxim Ag EVP_MD_CTX_free(S3I(s)->handshake_hash); 10972c33676SMaxim Ag S3I(s)->handshake_hash = NULL; 11072c33676SMaxim Ag } 11172c33676SMaxim Ag 11272c33676SMaxim Ag int 11372c33676SMaxim Ag tls1_transcript_init(SSL *s) 11472c33676SMaxim Ag { 11572c33676SMaxim Ag if (S3I(s)->handshake_transcript != NULL) 11672c33676SMaxim Ag return 0; 11772c33676SMaxim Ag 11872c33676SMaxim Ag if ((S3I(s)->handshake_transcript = BUF_MEM_new()) == NULL) 11972c33676SMaxim Ag return 0; 12072c33676SMaxim Ag 12172c33676SMaxim Ag tls1_transcript_reset(s); 12272c33676SMaxim Ag 12372c33676SMaxim Ag return 1; 12472c33676SMaxim Ag } 12572c33676SMaxim Ag 12672c33676SMaxim Ag void 12772c33676SMaxim Ag tls1_transcript_free(SSL *s) 12872c33676SMaxim Ag { 12972c33676SMaxim Ag BUF_MEM_free(S3I(s)->handshake_transcript); 13072c33676SMaxim Ag S3I(s)->handshake_transcript = NULL; 13172c33676SMaxim Ag } 13272c33676SMaxim Ag 13372c33676SMaxim Ag void 13472c33676SMaxim Ag tls1_transcript_reset(SSL *s) 13572c33676SMaxim Ag { 13672c33676SMaxim Ag /* 13772c33676SMaxim Ag * We should check the return value of BUF_MEM_grow_clean(), however 13872c33676SMaxim Ag * due to yet another bad API design, when called with a length of zero 13972c33676SMaxim Ag * it is impossible to tell if it succeeded (returning a length of zero) 14072c33676SMaxim Ag * or if it failed (and returned zero)... our implementation never 14172c33676SMaxim Ag * fails with a length of zero, so we trust all is okay... 14272c33676SMaxim Ag */ 14372c33676SMaxim Ag (void)BUF_MEM_grow_clean(S3I(s)->handshake_transcript, 0); 14472c33676SMaxim Ag 145*cca6fc52SDaniel Fojt tls1_transcript_unfreeze(s); 14672c33676SMaxim Ag } 14772c33676SMaxim Ag 14872c33676SMaxim Ag int 14972c33676SMaxim Ag tls1_transcript_append(SSL *s, const unsigned char *buf, size_t len) 15072c33676SMaxim Ag { 15172c33676SMaxim Ag size_t olen, nlen; 15272c33676SMaxim Ag 15372c33676SMaxim Ag if (S3I(s)->handshake_transcript == NULL) 15472c33676SMaxim Ag return 1; 15572c33676SMaxim Ag 15672c33676SMaxim Ag if (s->s3->flags & TLS1_FLAGS_FREEZE_TRANSCRIPT) 15772c33676SMaxim Ag return 1; 15872c33676SMaxim Ag 15972c33676SMaxim Ag olen = S3I(s)->handshake_transcript->length; 16072c33676SMaxim Ag nlen = olen + len; 16172c33676SMaxim Ag 16272c33676SMaxim Ag if (nlen < olen) 16372c33676SMaxim Ag return 0; 16472c33676SMaxim Ag 16572c33676SMaxim Ag if (BUF_MEM_grow(S3I(s)->handshake_transcript, nlen) == 0) 16672c33676SMaxim Ag return 0; 16772c33676SMaxim Ag 16872c33676SMaxim Ag memcpy(S3I(s)->handshake_transcript->data + olen, buf, len); 16972c33676SMaxim Ag 17072c33676SMaxim Ag return 1; 17172c33676SMaxim Ag } 17272c33676SMaxim Ag 17372c33676SMaxim Ag int 17472c33676SMaxim Ag tls1_transcript_data(SSL *s, const unsigned char **data, size_t *len) 17572c33676SMaxim Ag { 17672c33676SMaxim Ag if (S3I(s)->handshake_transcript == NULL) 17772c33676SMaxim Ag return 0; 17872c33676SMaxim Ag 17972c33676SMaxim Ag *data = S3I(s)->handshake_transcript->data; 18072c33676SMaxim Ag *len = S3I(s)->handshake_transcript->length; 18172c33676SMaxim Ag 18272c33676SMaxim Ag return 1; 18372c33676SMaxim Ag } 18472c33676SMaxim Ag 18572c33676SMaxim Ag void 18672c33676SMaxim Ag tls1_transcript_freeze(SSL *s) 18772c33676SMaxim Ag { 18872c33676SMaxim Ag s->s3->flags |= TLS1_FLAGS_FREEZE_TRANSCRIPT; 18972c33676SMaxim Ag } 19072c33676SMaxim Ag 191*cca6fc52SDaniel Fojt void 192*cca6fc52SDaniel Fojt tls1_transcript_unfreeze(SSL *s) 193*cca6fc52SDaniel Fojt { 194*cca6fc52SDaniel Fojt s->s3->flags &= ~TLS1_FLAGS_FREEZE_TRANSCRIPT; 195*cca6fc52SDaniel Fojt } 196*cca6fc52SDaniel Fojt 19772c33676SMaxim Ag int 19872c33676SMaxim Ag tls1_transcript_record(SSL *s, const unsigned char *buf, size_t len) 19972c33676SMaxim Ag { 20072c33676SMaxim Ag if (!tls1_transcript_hash_update(s, buf, len)) 20172c33676SMaxim Ag return 0; 20272c33676SMaxim Ag 20372c33676SMaxim Ag if (!tls1_transcript_append(s, buf, len)) 20472c33676SMaxim Ag return 0; 20572c33676SMaxim Ag 20672c33676SMaxim Ag return 1; 20772c33676SMaxim Ag } 208