xref: /dflybsd-src/crypto/libressl/ssl/ssl_transcript.c (revision 961e30ea7dc61d1112b778ea4981eac68129fb86)
1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: ssl_transcript.c,v 1.8 2022/07/22 19:54:46 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 <openssl/ssl.h>
1972c33676SMaxim Ag 
20*de0e0e4dSAntonio Huete Jimenez #include "ssl_locl.h"
21*de0e0e4dSAntonio Huete Jimenez #include "tls_internal.h"
22*de0e0e4dSAntonio Huete Jimenez 
2372c33676SMaxim Ag int
tls1_transcript_hash_init(SSL * s)2472c33676SMaxim Ag tls1_transcript_hash_init(SSL *s)
2572c33676SMaxim Ag {
2672c33676SMaxim Ag 	const unsigned char *data;
2772c33676SMaxim Ag 	const EVP_MD *md;
2872c33676SMaxim Ag 	size_t len;
2972c33676SMaxim Ag 
3072c33676SMaxim Ag 	tls1_transcript_hash_free(s);
3172c33676SMaxim Ag 
3272c33676SMaxim Ag 	if (!ssl_get_handshake_evp_md(s, &md)) {
3372c33676SMaxim Ag 		SSLerrorx(ERR_R_INTERNAL_ERROR);
3472c33676SMaxim Ag 		goto err;
3572c33676SMaxim Ag 	}
3672c33676SMaxim Ag 
37*de0e0e4dSAntonio Huete Jimenez 	if ((s->s3->handshake_hash = EVP_MD_CTX_new()) == NULL) {
3872c33676SMaxim Ag 		SSLerror(s, ERR_R_MALLOC_FAILURE);
3972c33676SMaxim Ag 		goto err;
4072c33676SMaxim Ag 	}
41*de0e0e4dSAntonio Huete Jimenez 	if (!EVP_DigestInit_ex(s->s3->handshake_hash, md, NULL)) {
4272c33676SMaxim Ag 		SSLerror(s, ERR_R_EVP_LIB);
4372c33676SMaxim Ag 		goto err;
4472c33676SMaxim Ag 	}
4572c33676SMaxim Ag 
4672c33676SMaxim Ag 	if (!tls1_transcript_data(s, &data, &len)) {
4772c33676SMaxim Ag 		SSLerror(s, SSL_R_BAD_HANDSHAKE_LENGTH);
4872c33676SMaxim Ag 		goto err;
4972c33676SMaxim Ag 	}
5072c33676SMaxim Ag 	if (!tls1_transcript_hash_update(s, data, len)) {
5172c33676SMaxim Ag 		SSLerror(s, ERR_R_EVP_LIB);
5272c33676SMaxim Ag 		goto err;
5372c33676SMaxim Ag 	}
5472c33676SMaxim Ag 
5572c33676SMaxim Ag 	return 1;
5672c33676SMaxim Ag 
5772c33676SMaxim Ag  err:
5872c33676SMaxim Ag 	tls1_transcript_hash_free(s);
5972c33676SMaxim Ag 
6072c33676SMaxim Ag 	return 0;
6172c33676SMaxim Ag }
6272c33676SMaxim Ag 
6372c33676SMaxim Ag int
tls1_transcript_hash_update(SSL * s,const unsigned char * buf,size_t len)6472c33676SMaxim Ag tls1_transcript_hash_update(SSL *s, const unsigned char *buf, size_t len)
6572c33676SMaxim Ag {
66*de0e0e4dSAntonio Huete Jimenez 	if (s->s3->handshake_hash == NULL)
6772c33676SMaxim Ag 		return 1;
6872c33676SMaxim Ag 
69*de0e0e4dSAntonio Huete Jimenez 	return EVP_DigestUpdate(s->s3->handshake_hash, buf, len);
7072c33676SMaxim Ag }
7172c33676SMaxim Ag 
7272c33676SMaxim Ag int
tls1_transcript_hash_value(SSL * s,unsigned char * out,size_t len,size_t * outlen)73*de0e0e4dSAntonio Huete Jimenez tls1_transcript_hash_value(SSL *s, unsigned char *out, size_t len,
7472c33676SMaxim Ag     size_t *outlen)
7572c33676SMaxim Ag {
7672c33676SMaxim Ag 	EVP_MD_CTX *mdctx = NULL;
7772c33676SMaxim Ag 	unsigned int mdlen;
7872c33676SMaxim Ag 	int ret = 0;
7972c33676SMaxim Ag 
80*de0e0e4dSAntonio Huete Jimenez 	if (s->s3->handshake_hash == NULL)
81*de0e0e4dSAntonio Huete Jimenez 		goto err;
82*de0e0e4dSAntonio Huete Jimenez 
83*de0e0e4dSAntonio Huete Jimenez 	if (EVP_MD_CTX_size(s->s3->handshake_hash) > len)
8472c33676SMaxim Ag 		goto err;
8572c33676SMaxim Ag 
8672c33676SMaxim Ag 	if ((mdctx = EVP_MD_CTX_new()) == NULL) {
8772c33676SMaxim Ag 		SSLerror(s, ERR_R_MALLOC_FAILURE);
8872c33676SMaxim Ag 		goto err;
8972c33676SMaxim Ag 	}
90*de0e0e4dSAntonio Huete Jimenez 	if (!EVP_MD_CTX_copy_ex(mdctx, s->s3->handshake_hash)) {
9172c33676SMaxim Ag 		SSLerror(s, ERR_R_EVP_LIB);
9272c33676SMaxim Ag 		goto err;
9372c33676SMaxim Ag 	}
94*de0e0e4dSAntonio Huete Jimenez 	if (!EVP_DigestFinal_ex(mdctx, out, &mdlen)) {
9572c33676SMaxim Ag 		SSLerror(s, ERR_R_EVP_LIB);
9672c33676SMaxim Ag 		goto err;
9772c33676SMaxim Ag 	}
9872c33676SMaxim Ag 	if (outlen != NULL)
9972c33676SMaxim Ag 		*outlen = mdlen;
10072c33676SMaxim Ag 
10172c33676SMaxim Ag 	ret = 1;
10272c33676SMaxim Ag 
10372c33676SMaxim Ag  err:
10472c33676SMaxim Ag 	EVP_MD_CTX_free(mdctx);
10572c33676SMaxim Ag 
10672c33676SMaxim Ag 	return (ret);
10772c33676SMaxim Ag }
10872c33676SMaxim Ag 
10972c33676SMaxim Ag void
tls1_transcript_hash_free(SSL * s)11072c33676SMaxim Ag tls1_transcript_hash_free(SSL *s)
11172c33676SMaxim Ag {
112*de0e0e4dSAntonio Huete Jimenez 	EVP_MD_CTX_free(s->s3->handshake_hash);
113*de0e0e4dSAntonio Huete Jimenez 	s->s3->handshake_hash = NULL;
11472c33676SMaxim Ag }
11572c33676SMaxim Ag 
11672c33676SMaxim Ag int
tls1_transcript_init(SSL * s)11772c33676SMaxim Ag tls1_transcript_init(SSL *s)
11872c33676SMaxim Ag {
119*de0e0e4dSAntonio Huete Jimenez 	if (s->s3->handshake_transcript != NULL)
12072c33676SMaxim Ag 		return 0;
12172c33676SMaxim Ag 
122*de0e0e4dSAntonio Huete Jimenez 	if ((s->s3->handshake_transcript = tls_buffer_new(0)) == NULL)
12372c33676SMaxim Ag 		return 0;
12472c33676SMaxim Ag 
12572c33676SMaxim Ag 	tls1_transcript_reset(s);
12672c33676SMaxim Ag 
12772c33676SMaxim Ag 	return 1;
12872c33676SMaxim Ag }
12972c33676SMaxim Ag 
13072c33676SMaxim Ag void
tls1_transcript_free(SSL * s)13172c33676SMaxim Ag tls1_transcript_free(SSL *s)
13272c33676SMaxim Ag {
133*de0e0e4dSAntonio Huete Jimenez 	tls_buffer_free(s->s3->handshake_transcript);
134*de0e0e4dSAntonio Huete Jimenez 	s->s3->handshake_transcript = NULL;
13572c33676SMaxim Ag }
13672c33676SMaxim Ag 
13772c33676SMaxim Ag void
tls1_transcript_reset(SSL * s)13872c33676SMaxim Ag tls1_transcript_reset(SSL *s)
13972c33676SMaxim Ag {
140*de0e0e4dSAntonio Huete Jimenez 	tls_buffer_clear(s->s3->handshake_transcript);
14172c33676SMaxim Ag 
142cca6fc52SDaniel Fojt 	tls1_transcript_unfreeze(s);
14372c33676SMaxim Ag }
14472c33676SMaxim Ag 
14572c33676SMaxim Ag int
tls1_transcript_append(SSL * s,const unsigned char * buf,size_t len)14672c33676SMaxim Ag tls1_transcript_append(SSL *s, const unsigned char *buf, size_t len)
14772c33676SMaxim Ag {
148*de0e0e4dSAntonio Huete Jimenez 	if (s->s3->handshake_transcript == NULL)
14972c33676SMaxim Ag 		return 1;
15072c33676SMaxim Ag 
15172c33676SMaxim Ag 	if (s->s3->flags & TLS1_FLAGS_FREEZE_TRANSCRIPT)
15272c33676SMaxim Ag 		return 1;
15372c33676SMaxim Ag 
154*de0e0e4dSAntonio Huete Jimenez 	return tls_buffer_append(s->s3->handshake_transcript, buf, len);
15572c33676SMaxim Ag }
15672c33676SMaxim Ag 
15772c33676SMaxim Ag int
tls1_transcript_data(SSL * s,const unsigned char ** data,size_t * len)15872c33676SMaxim Ag tls1_transcript_data(SSL *s, const unsigned char **data, size_t *len)
15972c33676SMaxim Ag {
160*de0e0e4dSAntonio Huete Jimenez 	CBS cbs;
161*de0e0e4dSAntonio Huete Jimenez 
162*de0e0e4dSAntonio Huete Jimenez 	if (s->s3->handshake_transcript == NULL)
16372c33676SMaxim Ag 		return 0;
16472c33676SMaxim Ag 
165*de0e0e4dSAntonio Huete Jimenez 	if (!tls_buffer_data(s->s3->handshake_transcript, &cbs))
166*de0e0e4dSAntonio Huete Jimenez 		return 0;
167*de0e0e4dSAntonio Huete Jimenez 
168*de0e0e4dSAntonio Huete Jimenez 	/* XXX - change to caller providing a CBS argument. */
169*de0e0e4dSAntonio Huete Jimenez 	*data = CBS_data(&cbs);
170*de0e0e4dSAntonio Huete Jimenez 	*len = CBS_len(&cbs);
17172c33676SMaxim Ag 
17272c33676SMaxim Ag 	return 1;
17372c33676SMaxim Ag }
17472c33676SMaxim Ag 
17572c33676SMaxim Ag void
tls1_transcript_freeze(SSL * s)17672c33676SMaxim Ag tls1_transcript_freeze(SSL *s)
17772c33676SMaxim Ag {
17872c33676SMaxim Ag 	s->s3->flags |= TLS1_FLAGS_FREEZE_TRANSCRIPT;
17972c33676SMaxim Ag }
18072c33676SMaxim Ag 
181cca6fc52SDaniel Fojt void
tls1_transcript_unfreeze(SSL * s)182cca6fc52SDaniel Fojt tls1_transcript_unfreeze(SSL *s)
183cca6fc52SDaniel Fojt {
184cca6fc52SDaniel Fojt 	s->s3->flags &= ~TLS1_FLAGS_FREEZE_TRANSCRIPT;
185cca6fc52SDaniel Fojt }
186cca6fc52SDaniel Fojt 
18772c33676SMaxim Ag int
tls1_transcript_record(SSL * s,const unsigned char * buf,size_t len)18872c33676SMaxim Ag tls1_transcript_record(SSL *s, const unsigned char *buf, size_t len)
18972c33676SMaxim Ag {
19072c33676SMaxim Ag 	if (!tls1_transcript_hash_update(s, buf, len))
19172c33676SMaxim Ag 		return 0;
19272c33676SMaxim Ag 
19372c33676SMaxim Ag 	if (!tls1_transcript_append(s, buf, len))
19472c33676SMaxim Ag 		return 0;
19572c33676SMaxim Ag 
19672c33676SMaxim Ag 	return 1;
19772c33676SMaxim Ag }
198