#include <openssl/ssl.h>
#include <openssl/ech.h>
#include "../ssl_local.h"
#include "ech_local.h"
#include "internal/ech_helpers.h"
static const char OSSL_ECH_CONTEXT_STRING[] = "\x74\x6c\x73\x20\x65\x63\x68";
int ossl_ech_make_enc_info(const unsigned char *encoding,
size_t encoding_length,
unsigned char *info, size_t *info_len)
{
WPACKET ipkt = { 0 };
if (encoding == NULL || info == NULL || info_len == NULL)
return 0;
if (!WPACKET_init_static_len(&ipkt, info, *info_len, 0)
|| !WPACKET_memcpy(&ipkt, OSSL_ECH_CONTEXT_STRING,
sizeof(OSSL_ECH_CONTEXT_STRING) - 1)
|| !WPACKET_put_bytes_u8(&ipkt, 0)
|| !WPACKET_memcpy(&ipkt, encoding, encoding_length)
|| !WPACKET_get_total_written(&ipkt, info_len)) {
WPACKET_cleanup(&ipkt);
return 0;
}
WPACKET_cleanup(&ipkt);
return 1;
}
int ossl_ech_helper_get_ch_offsets(const unsigned char *ch, size_t ch_len,
size_t *sessid_off, size_t *exts_off,
size_t *exts_len,
size_t *ech_off, uint16_t *echtype,
size_t *ech_len, size_t *sni_off,
size_t *sni_len, int *inner)
{
unsigned int elen = 0, etype = 0, pi_tmp = 0;
const unsigned char *pp_tmp = NULL, *chstart = NULL, *estart = NULL;
PACKET pkt;
int done = 0;
if (ch == NULL || ch_len == 0 || sessid_off == NULL || exts_off == NULL
|| ech_off == NULL || echtype == NULL || ech_len == NULL
|| sni_off == NULL || inner == NULL || exts_len == NULL)
return 0;
*sessid_off = *exts_off = *ech_off = *sni_off = *sni_len = *ech_len = 0;
*exts_len = 0;
*inner = OSSL_ECH_UNKNOWN_CH_TYPE;
*echtype = 0xffff;
if (!PACKET_buf_init(&pkt, ch, ch_len))
return 0;
chstart = PACKET_data(&pkt);
if (!PACKET_get_net_2(&pkt, &pi_tmp))
return 0;
if (pi_tmp != TLS1_2_VERSION)
return 1;
if (!PACKET_get_bytes(&pkt, &pp_tmp, SSL3_RANDOM_SIZE)
|| (*sessid_off = PACKET_data(&pkt) - chstart) == 0
|| !PACKET_get_1(&pkt, &pi_tmp)
|| !PACKET_get_bytes(&pkt, &pp_tmp, pi_tmp)
|| !PACKET_get_net_2(&pkt, &pi_tmp)
|| !PACKET_get_bytes(&pkt, &pp_tmp, pi_tmp)
|| !PACKET_get_1(&pkt, &pi_tmp)
|| !PACKET_get_bytes(&pkt, &pp_tmp, pi_tmp)
|| (*exts_off = PACKET_data(&pkt) - chstart) == 0
|| !PACKET_get_net_2(&pkt, &pi_tmp)
|| (*exts_len = (size_t)pi_tmp) == 0)
return 1;
if (*exts_len == 0)
return 1;
estart = PACKET_data(&pkt);
while (PACKET_remaining(&pkt) > 0
&& (size_t)(PACKET_data(&pkt) - estart) < *exts_len
&& done < 2) {
if (!PACKET_get_net_2(&pkt, &etype)
|| !PACKET_get_net_2(&pkt, &elen))
return 1;
if (etype == TLSEXT_TYPE_ech) {
if (elen == 0)
return 0;
*ech_off = PACKET_data(&pkt) - chstart - 4;
*echtype = etype;
*ech_len = elen;
done++;
}
if (etype == TLSEXT_TYPE_server_name) {
*sni_off = PACKET_data(&pkt) - chstart - 4;
*sni_len = elen;
done++;
}
if (!PACKET_get_bytes(&pkt, &pp_tmp, elen))
return 1;
if (etype == TLSEXT_TYPE_ech)
*inner = pp_tmp[0];
}
return 1;
}