xref: /openbsd-src/lib/libssl/ssl_transcript.c (revision c9675a23de50ec5aa20be3956f170f2eccffb293)
1*c9675a23Stb /* $OpenBSD: ssl_transcript.c,v 1.9 2022/11/26 16:08:56 tb Exp $ */
21c0e4449Sjsing /*
31c0e4449Sjsing  * Copyright (c) 2017 Joel Sing <jsing@openbsd.org>
41c0e4449Sjsing  *
51c0e4449Sjsing  * Permission to use, copy, modify, and distribute this software for any
61c0e4449Sjsing  * purpose with or without fee is hereby granted, provided that the above
71c0e4449Sjsing  * copyright notice and this permission notice appear in all copies.
81c0e4449Sjsing  *
91c0e4449Sjsing  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
101c0e4449Sjsing  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
111c0e4449Sjsing  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
121c0e4449Sjsing  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
131c0e4449Sjsing  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
141c0e4449Sjsing  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
151c0e4449Sjsing  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
161c0e4449Sjsing  */
171c0e4449Sjsing 
181c0e4449Sjsing #include <openssl/ssl.h>
191c0e4449Sjsing 
20*c9675a23Stb #include "ssl_local.h"
21c92b62f1Sjsing #include "tls_internal.h"
2210e340b2Sjsing 
231c0e4449Sjsing int
tls1_transcript_hash_init(SSL * s)241c0e4449Sjsing tls1_transcript_hash_init(SSL *s)
251c0e4449Sjsing {
261c0e4449Sjsing 	const unsigned char *data;
271c0e4449Sjsing 	const EVP_MD *md;
281c0e4449Sjsing 	size_t len;
291c0e4449Sjsing 
301c0e4449Sjsing 	tls1_transcript_hash_free(s);
311c0e4449Sjsing 
321c0e4449Sjsing 	if (!ssl_get_handshake_evp_md(s, &md)) {
331c0e4449Sjsing 		SSLerrorx(ERR_R_INTERNAL_ERROR);
341c0e4449Sjsing 		goto err;
351c0e4449Sjsing 	}
361c0e4449Sjsing 
3702876cc3Sjsing 	if ((s->s3->handshake_hash = EVP_MD_CTX_new()) == NULL) {
381c0e4449Sjsing 		SSLerror(s, ERR_R_MALLOC_FAILURE);
391c0e4449Sjsing 		goto err;
401c0e4449Sjsing 	}
4102876cc3Sjsing 	if (!EVP_DigestInit_ex(s->s3->handshake_hash, md, NULL)) {
421c0e4449Sjsing 		SSLerror(s, ERR_R_EVP_LIB);
431c0e4449Sjsing 		goto err;
441c0e4449Sjsing 	}
451c0e4449Sjsing 
461c0e4449Sjsing 	if (!tls1_transcript_data(s, &data, &len)) {
471c0e4449Sjsing 		SSLerror(s, SSL_R_BAD_HANDSHAKE_LENGTH);
481c0e4449Sjsing 		goto err;
491c0e4449Sjsing 	}
501c0e4449Sjsing 	if (!tls1_transcript_hash_update(s, data, len)) {
511c0e4449Sjsing 		SSLerror(s, ERR_R_EVP_LIB);
521c0e4449Sjsing 		goto err;
531c0e4449Sjsing 	}
541c0e4449Sjsing 
551c0e4449Sjsing 	return 1;
561c0e4449Sjsing 
571c0e4449Sjsing  err:
581c0e4449Sjsing 	tls1_transcript_hash_free(s);
591c0e4449Sjsing 
601c0e4449Sjsing 	return 0;
611c0e4449Sjsing }
621c0e4449Sjsing 
631c0e4449Sjsing int
tls1_transcript_hash_update(SSL * s,const unsigned char * buf,size_t len)641c0e4449Sjsing tls1_transcript_hash_update(SSL *s, const unsigned char *buf, size_t len)
651c0e4449Sjsing {
6602876cc3Sjsing 	if (s->s3->handshake_hash == NULL)
671c0e4449Sjsing 		return 1;
681c0e4449Sjsing 
6902876cc3Sjsing 	return EVP_DigestUpdate(s->s3->handshake_hash, buf, len);
701c0e4449Sjsing }
711c0e4449Sjsing 
721c0e4449Sjsing int
tls1_transcript_hash_value(SSL * s,unsigned char * out,size_t len,size_t * outlen)73f4578efdSjsing tls1_transcript_hash_value(SSL *s, unsigned char *out, size_t len,
741c0e4449Sjsing     size_t *outlen)
751c0e4449Sjsing {
761c0e4449Sjsing 	EVP_MD_CTX *mdctx = NULL;
771c0e4449Sjsing 	unsigned int mdlen;
781c0e4449Sjsing 	int ret = 0;
791c0e4449Sjsing 
8002876cc3Sjsing 	if (s->s3->handshake_hash == NULL)
81eda45bbcSjsing 		goto err;
82eda45bbcSjsing 
8302876cc3Sjsing 	if (EVP_MD_CTX_size(s->s3->handshake_hash) > len)
841c0e4449Sjsing 		goto err;
851c0e4449Sjsing 
861c0e4449Sjsing 	if ((mdctx = EVP_MD_CTX_new()) == NULL) {
871c0e4449Sjsing 		SSLerror(s, ERR_R_MALLOC_FAILURE);
881c0e4449Sjsing 		goto err;
891c0e4449Sjsing 	}
9002876cc3Sjsing 	if (!EVP_MD_CTX_copy_ex(mdctx, s->s3->handshake_hash)) {
911c0e4449Sjsing 		SSLerror(s, ERR_R_EVP_LIB);
921c0e4449Sjsing 		goto err;
931c0e4449Sjsing 	}
94f4578efdSjsing 	if (!EVP_DigestFinal_ex(mdctx, out, &mdlen)) {
951c0e4449Sjsing 		SSLerror(s, ERR_R_EVP_LIB);
961c0e4449Sjsing 		goto err;
971c0e4449Sjsing 	}
981c0e4449Sjsing 	if (outlen != NULL)
991c0e4449Sjsing 		*outlen = mdlen;
1001c0e4449Sjsing 
1011c0e4449Sjsing 	ret = 1;
1021c0e4449Sjsing 
1031c0e4449Sjsing  err:
1041c0e4449Sjsing 	EVP_MD_CTX_free(mdctx);
1051c0e4449Sjsing 
1061c0e4449Sjsing 	return (ret);
1071c0e4449Sjsing }
1081c0e4449Sjsing 
1091c0e4449Sjsing void
tls1_transcript_hash_free(SSL * s)1101c0e4449Sjsing tls1_transcript_hash_free(SSL *s)
1111c0e4449Sjsing {
11202876cc3Sjsing 	EVP_MD_CTX_free(s->s3->handshake_hash);
11302876cc3Sjsing 	s->s3->handshake_hash = NULL;
1141c0e4449Sjsing }
1151c0e4449Sjsing 
1161c0e4449Sjsing int
tls1_transcript_init(SSL * s)1171c0e4449Sjsing tls1_transcript_init(SSL *s)
1181c0e4449Sjsing {
11902876cc3Sjsing 	if (s->s3->handshake_transcript != NULL)
1201c0e4449Sjsing 		return 0;
1211c0e4449Sjsing 
122c92b62f1Sjsing 	if ((s->s3->handshake_transcript = tls_buffer_new(0)) == NULL)
1231c0e4449Sjsing 		return 0;
1241c0e4449Sjsing 
1251c0e4449Sjsing 	tls1_transcript_reset(s);
1261c0e4449Sjsing 
1271c0e4449Sjsing 	return 1;
1281c0e4449Sjsing }
1291c0e4449Sjsing 
1301c0e4449Sjsing void
tls1_transcript_free(SSL * s)1311c0e4449Sjsing tls1_transcript_free(SSL *s)
1321c0e4449Sjsing {
133c92b62f1Sjsing 	tls_buffer_free(s->s3->handshake_transcript);
13402876cc3Sjsing 	s->s3->handshake_transcript = NULL;
1351c0e4449Sjsing }
1361c0e4449Sjsing 
1371c0e4449Sjsing void
tls1_transcript_reset(SSL * s)1381c0e4449Sjsing tls1_transcript_reset(SSL *s)
1391c0e4449Sjsing {
140c92b62f1Sjsing 	tls_buffer_clear(s->s3->handshake_transcript);
1411c0e4449Sjsing 
1423213f5abSjsing 	tls1_transcript_unfreeze(s);
1431c0e4449Sjsing }
1441c0e4449Sjsing 
1451c0e4449Sjsing int
tls1_transcript_append(SSL * s,const unsigned char * buf,size_t len)1461c0e4449Sjsing tls1_transcript_append(SSL *s, const unsigned char *buf, size_t len)
1471c0e4449Sjsing {
14802876cc3Sjsing 	if (s->s3->handshake_transcript == NULL)
1491c0e4449Sjsing 		return 1;
1501c0e4449Sjsing 
1511c0e4449Sjsing 	if (s->s3->flags & TLS1_FLAGS_FREEZE_TRANSCRIPT)
1521c0e4449Sjsing 		return 1;
1531c0e4449Sjsing 
154c92b62f1Sjsing 	return tls_buffer_append(s->s3->handshake_transcript, buf, len);
1551c0e4449Sjsing }
1561c0e4449Sjsing 
1571c0e4449Sjsing int
tls1_transcript_data(SSL * s,const unsigned char ** data,size_t * len)1581c0e4449Sjsing tls1_transcript_data(SSL *s, const unsigned char **data, size_t *len)
1591c0e4449Sjsing {
160c92b62f1Sjsing 	CBS cbs;
161c92b62f1Sjsing 
16202876cc3Sjsing 	if (s->s3->handshake_transcript == NULL)
1631c0e4449Sjsing 		return 0;
1641c0e4449Sjsing 
165c92b62f1Sjsing 	if (!tls_buffer_data(s->s3->handshake_transcript, &cbs))
166c92b62f1Sjsing 		return 0;
167c92b62f1Sjsing 
168c92b62f1Sjsing 	/* XXX - change to caller providing a CBS argument. */
169c92b62f1Sjsing 	*data = CBS_data(&cbs);
170c92b62f1Sjsing 	*len = CBS_len(&cbs);
1711c0e4449Sjsing 
1721c0e4449Sjsing 	return 1;
1731c0e4449Sjsing }
1741c0e4449Sjsing 
1751c0e4449Sjsing void
tls1_transcript_freeze(SSL * s)1761c0e4449Sjsing tls1_transcript_freeze(SSL *s)
1771c0e4449Sjsing {
1781c0e4449Sjsing 	s->s3->flags |= TLS1_FLAGS_FREEZE_TRANSCRIPT;
1791c0e4449Sjsing }
1801c0e4449Sjsing 
1813213f5abSjsing void
tls1_transcript_unfreeze(SSL * s)1823213f5abSjsing tls1_transcript_unfreeze(SSL *s)
1833213f5abSjsing {
1843213f5abSjsing 	s->s3->flags &= ~TLS1_FLAGS_FREEZE_TRANSCRIPT;
1853213f5abSjsing }
1863213f5abSjsing 
1871c0e4449Sjsing int
tls1_transcript_record(SSL * s,const unsigned char * buf,size_t len)1881c0e4449Sjsing tls1_transcript_record(SSL *s, const unsigned char *buf, size_t len)
1891c0e4449Sjsing {
1901c0e4449Sjsing 	if (!tls1_transcript_hash_update(s, buf, len))
1911c0e4449Sjsing 		return 0;
1921c0e4449Sjsing 
1931c0e4449Sjsing 	if (!tls1_transcript_append(s, buf, len))
1941c0e4449Sjsing 		return 0;
1951c0e4449Sjsing 
1961c0e4449Sjsing 	return 1;
1971c0e4449Sjsing }
198