MINOR: quic: implement Retry TLS AEAD tag generation

Implement a new QUIC TLS related function
quic_tls_generate_retry_integrity_tag(). This function can be used to
calculate the AEAD tag of a Retry packet.
This commit is contained in:
Amaury Denoyelle 2022-01-11 11:57:00 +01:00
parent c8b4ce4a47
commit 6efec292ef
2 changed files with 59 additions and 0 deletions

View File

@ -69,6 +69,9 @@ int quic_tls_decrypt(unsigned char *buf, size_t len,
const EVP_CIPHER *aead,
const unsigned char *key, const unsigned char *iv);
int quic_tls_generate_retry_integrity_tag(unsigned char *odcid, size_t odcid_len,
unsigned char *buf, size_t len);
int quic_tls_derive_keys(const EVP_CIPHER *aead, const EVP_CIPHER *hp,
const EVP_MD *md,
unsigned char *key, size_t keylen,

View File

@ -396,3 +396,59 @@ int quic_tls_decrypt(unsigned char *buf, size_t len,
EVP_CIPHER_CTX_free(ctx);
return ret;
}
/* Generate the AEAD tag for the Retry packet <pkt> of <pkt_len> bytes and
* write it to <tag>. The tag is written just after the <pkt> area. It should
* be at least 16 bytes longs. <odcid> is the CID of the Initial packet
* received which triggers the Retry.
*
* Returns non-zero on success else zero.
*/
int quic_tls_generate_retry_integrity_tag(unsigned char *odcid,
unsigned char odcid_len,
unsigned char *pkt, size_t pkt_len)
{
const EVP_CIPHER *evp = EVP_aes_128_gcm();
EVP_CIPHER_CTX *ctx;
/* key/nonce from rfc9001 5.8. Retry Packet Integrity */
const unsigned char key[] = {
0xbe, 0x0c, 0x69, 0x0b, 0x9f, 0x66, 0x57, 0x5a,
0x1d, 0x76, 0x6b, 0x54, 0xe3, 0x68, 0xc8, 0x4e,
};
const unsigned char nonce[] = {
0x46, 0x15, 0x99, 0xd3, 0x5d, 0x63, 0x2b, 0xf2, 0x23, 0x98, 0x25, 0xbb,
};
/* encryption buffer - not used as only AEAD tag generation is proceed */
unsigned char *out = NULL;
/* address to store the AEAD tag */
unsigned char *tag = pkt + pkt_len;
int outlen, ret = 0;
ctx = EVP_CIPHER_CTX_new();
if (!ctx)
return 0;
/* rfc9001 5.8. Retry Packet Integrity
*
* AEAD is proceed over a pseudo-Retry packet used as AAD. It contains
* the ODCID len + data and the Retry packet itself.
*/
if (!EVP_EncryptInit_ex(ctx, evp, NULL, key, nonce) ||
/* specify pseudo-Retry as AAD */
!EVP_EncryptUpdate(ctx, NULL, &outlen, &odcid_len, sizeof(odcid_len)) ||
!EVP_EncryptUpdate(ctx, NULL, &outlen, odcid, odcid_len) ||
!EVP_EncryptUpdate(ctx, NULL, &outlen, pkt, pkt_len) ||
/* finalize */
!EVP_EncryptFinal_ex(ctx, out, &outlen) ||
/* store the tag */
!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, QUIC_TLS_TAG_LEN, tag)) {
goto out;
}
ret = 1;
out:
EVP_CIPHER_CTX_free(ctx);
return ret;
}