xref: /dflybsd-src/crypto/libressl/ssl/ssl_transcript.c (revision cca6fc5243d2098262ea81f83ad5b28d3b800f4a)
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