Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 75 additions & 1 deletion deps/ngtcp2/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,10 @@ NGTCP2_EXTERN int ngtcp2_crypto_generate_stateless_reset_token(
* @macro
*
* :macro:`NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN` is the maximum length
* of a token generated by `ngtcp2_crypto_generate_regular_token`.
* of a token generated by `ngtcp2_crypto_generate_regular_token`.
* `ngtcp2_crypto_generate_regular_token2` generates a token of length
* at most :macro:`NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN` bytes + the
* length of the provided opaque data.
*/
#define NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN \
(/* magic = */ 1 + sizeof(ngtcp2_tstamp) + /* aead tag = */ 16 + \
Expand Down Expand Up @@ -787,6 +790,77 @@ NGTCP2_EXTERN int ngtcp2_crypto_verify_regular_token(
size_t secretlen, const ngtcp2_sockaddr *remote_addr,
ngtcp2_socklen remote_addrlen, ngtcp2_duration timeout, ngtcp2_tstamp ts);

/**
* @function
*
* `ngtcp2_crypto_generate_regular_token2` generates a token in the
* buffer pointed by |token| that is sent with NEW_TOKEN frame. The
* buffer pointed by |token| must have at least
* :macro:`NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN` + |datalen| bytes long.
* The successfully generated token starts with
* :macro:`NGTCP2_CRYPTO_TOKEN_MAGIC_REGULAR`. |secret| of length
* |secretlen| is a keying material to generate keys to encrypt the
* token. |remote_addr| of length |remote_addrlen| is an address of
* client. |ts| is the timestamp when the token is generated. |data|
* of length |datalen| is an opaque data embedded in the token.
* |datalen| must be less than or equal to 256.
*
* Calling this function with |datalen| = 0 is equivalent to calling
* `ngtcp2_crypto_generate_regular_token`.
*
* To get the opaque data after successful verification, use
* `ngtcp2_crypto_verify_regular_token2`.
* `ngtcp2_crypto_verify_regular_token` can verify the token with
* |datalen| > 0, but it discards the opaque data.
*
* This function returns the length of generated token if it succeeds,
* or -1.
*/
NGTCP2_EXTERN ngtcp2_ssize ngtcp2_crypto_generate_regular_token2(
uint8_t *token, const uint8_t *secret, size_t secretlen,
const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen,
const void *data, size_t datalen, ngtcp2_tstamp ts);

/**
* @function
*
* `ngtcp2_crypto_verify_regular_token2` verifies a regular token
* stored in the buffer pointed by |token| of length |tokenlen|.
* |secret| of length |secretlen| is a keying material to generate
* keys to decrypt the token. |remote_addr| of length
* |remote_addrlen| is an address of client. |timeout| is the period
* during which the token is valid. |ts| is the current timestamp.
* |data| is the pointer to the buffer of length at least
* |max_datalen| bytes. If the token is verified successfully, the
* opaque data embedded in the token is copied to the buffer pointed
* by |data|.
*
* If |tokenlen| is less than
* :macro:`NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN`, this function returns
* :macro:`NGTCP2_CRYPTO_ERR_UNREADABLE_TOKEN`.
*
* If the length of opaque data is larger than |max_datalen|, the
* verification still succeeds, but nothing is written to the buffer
* pointed by |data|, and this function returns 0. In other words,
* the opaque data is discarded.
*
* This function returns the number of the opaque data written to the
* buffer pointed by |data| if it succeeds, or one of the following
* negative error codes:
*
* :macro:`NGTCP2_CRYPTO_ERR_UNREADABLE_TOKEN`
* A token is badly formatted; or verifying the integrity
* protection failed.
* :macro:`NGTCP2_CRYPTO_ERR_VERIFY_TOKEN`
* A token validity has expired.
* :macro:`NGTCP2_CRYPTO_ERR_INTERNAL`
* Internal error occurred.
*/
NGTCP2_EXTERN ngtcp2_ssize ngtcp2_crypto_verify_regular_token2(
void *data, size_t max_datalen, const uint8_t *token, size_t tokenlen,
const uint8_t *secret, size_t secretlen, const ngtcp2_sockaddr *remote_addr,
ngtcp2_socklen remote_addrlen, ngtcp2_duration timeout, ngtcp2_tstamp ts);

/**
* @function
*
Expand Down
94 changes: 41 additions & 53 deletions deps/ngtcp2/ngtcp2/crypto/ossl/ossl.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,70 +41,40 @@
#include "ngtcp2_macro.h"
#include "shared.h"

static int crypto_initialized;
#if defined(OPENSSL_NO_CHACHA) || defined(OPENSSL_NO_POLY1305)
# define NGTCP2_NO_CHACHA_POLY1305
#endif /* defined(OPENSSL_NO_CHACHA) || \
defined(OPENSSL_NO_POLY1305) */

static EVP_CIPHER *crypto_aes_128_gcm;
static EVP_CIPHER *crypto_aes_256_gcm;
static EVP_CIPHER *crypto_chacha20_poly1305;
static EVP_CIPHER *crypto_aes_128_ccm;
static EVP_CIPHER *crypto_aes_128_ctr;
static EVP_CIPHER *crypto_aes_256_ctr;
#ifndef NGTCP2_NO_CHACHA_POLY1305
static EVP_CIPHER *crypto_chacha20_poly1305;
static EVP_CIPHER *crypto_chacha20;
#endif /* !defined(NGTCP2_NO_CHACHA_POLY1305) */
static EVP_MD *crypto_sha256;
static EVP_MD *crypto_sha384;
static EVP_KDF *crypto_hkdf;

int ngtcp2_crypto_ossl_init(void) {
/* We do not care whether the pre-fetch succeeds or not. If it
fails, it returns NULL, which is still the default value, and our
code should still work with it. */
crypto_aes_128_gcm = EVP_CIPHER_fetch(NULL, "AES-128-GCM", NULL);
if (crypto_aes_128_gcm == NULL) {
return -1;
}

crypto_aes_256_gcm = EVP_CIPHER_fetch(NULL, "AES-256-GCM", NULL);
if (crypto_aes_256_gcm == NULL) {
return -1;
}

crypto_chacha20_poly1305 = EVP_CIPHER_fetch(NULL, "ChaCha20-Poly1305", NULL);
if (crypto_chacha20_poly1305 == NULL) {
return -1;
}

crypto_aes_128_ccm = EVP_CIPHER_fetch(NULL, "AES-128-CCM", NULL);
if (crypto_aes_128_ccm == NULL) {
return -1;
}

crypto_aes_128_ctr = EVP_CIPHER_fetch(NULL, "AES-128-CTR", NULL);
if (crypto_aes_128_ctr == NULL) {
return -1;
}

crypto_aes_256_ctr = EVP_CIPHER_fetch(NULL, "AES-256-CTR", NULL);
if (crypto_aes_256_ctr == NULL) {
return -1;
}

#ifndef NGTCP2_NO_CHACHA_POLY1305
crypto_chacha20_poly1305 = EVP_CIPHER_fetch(NULL, "ChaCha20-Poly1305", NULL);
crypto_chacha20 = EVP_CIPHER_fetch(NULL, "ChaCha20", NULL);
if (crypto_chacha20 == NULL) {
return -1;
}

#endif /* !defined(NGTCP2_NO_CHACHA_POLY1305) */
crypto_sha256 = EVP_MD_fetch(NULL, "sha256", NULL);
if (crypto_sha256 == NULL) {
return -1;
}

crypto_sha384 = EVP_MD_fetch(NULL, "sha384", NULL);
if (crypto_sha384 == NULL) {
return -1;
}

crypto_hkdf = EVP_KDF_fetch(NULL, "hkdf", NULL);
if (crypto_hkdf == NULL) {
return -1;
}

crypto_initialized = 1;

return 0;
}
Expand All @@ -125,13 +95,15 @@ static const EVP_CIPHER *crypto_aead_aes_256_gcm(void) {
return EVP_aes_256_gcm();
}

#ifndef NGTCP2_NO_CHACHA_POLY1305
static const EVP_CIPHER *crypto_aead_chacha20_poly1305(void) {
if (crypto_chacha20_poly1305) {
return crypto_chacha20_poly1305;
}

return EVP_chacha20_poly1305();
}
#endif /* !defined(NGTCP2_NO_CHACHA_POLY1305) */

static const EVP_CIPHER *crypto_aead_aes_128_ccm(void) {
if (crypto_aes_128_ccm) {
Expand All @@ -157,13 +129,15 @@ static const EVP_CIPHER *crypto_cipher_aes_256_ctr(void) {
return EVP_aes_256_ctr();
}

#ifndef NGTCP2_NO_CHACHA_POLY1305
static const EVP_CIPHER *crypto_cipher_chacha20(void) {
if (crypto_chacha20) {
return crypto_chacha20;
}

return EVP_chacha20();
}
#endif /* !defined(NGTCP2_NO_CHACHA_POLY1305) */

static const EVP_MD *crypto_md_sha256(void) {
if (crypto_sha256) {
Expand All @@ -189,13 +163,21 @@ static EVP_KDF *crypto_kdf_hkdf(void) {
return EVP_KDF_fetch(NULL, "hkdf", NULL);
}

static void crypto_kdf_hkdf_free(EVP_KDF *kdf) {
if (kdf && crypto_hkdf != kdf) {
EVP_KDF_free(kdf);
}
}

static size_t crypto_aead_max_overhead(const EVP_CIPHER *aead) {
switch (EVP_CIPHER_nid(aead)) {
case NID_aes_128_gcm:
case NID_aes_256_gcm:
return EVP_GCM_TLS_TAG_LEN;
#ifndef NGTCP2_NO_CHACHA_POLY1305
case NID_chacha20_poly1305:
return EVP_CHACHAPOLY_TLS_TAG_LEN;
#endif /* !defined(NGTCP2_NO_CHACHA_POLY1305) */
case NID_aes_128_ccm:
return EVP_CCM_TLS_TAG_LEN;
default:
Expand Down Expand Up @@ -239,8 +221,10 @@ static const EVP_CIPHER *crypto_cipher_id_get_aead(uint32_t cipher_id) {
return crypto_aead_aes_128_gcm();
case TLS1_3_CK_AES_256_GCM_SHA384:
return crypto_aead_aes_256_gcm();
#ifndef NGTCP2_NO_CHACHA_POLY1305
case TLS1_3_CK_CHACHA20_POLY1305_SHA256:
return crypto_aead_chacha20_poly1305();
#endif /* !defined(NGTCP2_NO_CHACHA_POLY1305) */
case TLS1_3_CK_AES_128_CCM_SHA256:
return crypto_aead_aes_128_ccm();
default:
Expand All @@ -253,8 +237,10 @@ static uint64_t crypto_cipher_id_get_aead_max_encryption(uint32_t cipher_id) {
case TLS1_3_CK_AES_128_GCM_SHA256:
case TLS1_3_CK_AES_256_GCM_SHA384:
return NGTCP2_CRYPTO_MAX_ENCRYPTION_AES_GCM;
#ifndef NGTCP2_NO_CHACHA_POLY1305
case TLS1_3_CK_CHACHA20_POLY1305_SHA256:
return NGTCP2_CRYPTO_MAX_ENCRYPTION_CHACHA20_POLY1305;
#endif /* !defined(NGTCP2_NO_CHACHA_POLY1305) */
case TLS1_3_CK_AES_128_CCM_SHA256:
return NGTCP2_CRYPTO_MAX_ENCRYPTION_AES_CCM;
default:
Expand All @@ -268,8 +254,10 @@ crypto_cipher_id_get_aead_max_decryption_failure(uint32_t cipher_id) {
case TLS1_3_CK_AES_128_GCM_SHA256:
case TLS1_3_CK_AES_256_GCM_SHA384:
return NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_AES_GCM;
#ifndef NGTCP2_NO_CHACHA_POLY1305
case TLS1_3_CK_CHACHA20_POLY1305_SHA256:
return NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_CHACHA20_POLY1305;
#endif /* !defined(NGTCP2_NO_CHACHA_POLY1305) */
case TLS1_3_CK_AES_128_CCM_SHA256:
return NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_AES_CCM;
default:
Expand All @@ -284,8 +272,10 @@ static const EVP_CIPHER *crypto_cipher_id_get_hp(uint32_t cipher_id) {
return crypto_cipher_aes_128_ctr();
case TLS1_3_CK_AES_256_GCM_SHA384:
return crypto_cipher_aes_256_ctr();
#ifndef NGTCP2_NO_CHACHA_POLY1305
case TLS1_3_CK_CHACHA20_POLY1305_SHA256:
return crypto_cipher_chacha20();
#endif /* !defined(NGTCP2_NO_CHACHA_POLY1305) */
default:
return NULL;
}
Expand All @@ -294,7 +284,9 @@ static const EVP_CIPHER *crypto_cipher_id_get_hp(uint32_t cipher_id) {
static const EVP_MD *crypto_cipher_id_get_md(uint32_t cipher_id) {
switch (cipher_id) {
case TLS1_3_CK_AES_128_GCM_SHA256:
#ifndef NGTCP2_NO_CHACHA_POLY1305
case TLS1_3_CK_CHACHA20_POLY1305_SHA256:
#endif /* !defined(NGTCP2_NO_CHACHA_POLY1305) */
case TLS1_3_CK_AES_128_CCM_SHA256:
return crypto_md_sha256();
case TLS1_3_CK_AES_256_GCM_SHA384:
Expand All @@ -308,7 +300,9 @@ static int supported_cipher_id(uint32_t cipher_id) {
switch (cipher_id) {
case TLS1_3_CK_AES_128_GCM_SHA256:
case TLS1_3_CK_AES_256_GCM_SHA384:
#ifndef NGTCP2_NO_CHACHA_POLY1305
case TLS1_3_CK_CHACHA20_POLY1305_SHA256:
#endif /* !defined(NGTCP2_NO_CHACHA_POLY1305) */
case TLS1_3_CK_AES_128_CCM_SHA256:
return 1;
default:
Expand Down Expand Up @@ -697,9 +691,7 @@ int ngtcp2_crypto_hkdf_extract(uint8_t *dest, const ngtcp2_crypto_md *md,
};
int rv = 0;

if (!crypto_initialized) {
EVP_KDF_free(kdf);
}
crypto_kdf_hkdf_free(kdf);

if (EVP_KDF_derive(kctx, dest, (size_t)EVP_MD_size(prf), params) <= 0) {
rv = -1;
Expand Down Expand Up @@ -730,9 +722,7 @@ int ngtcp2_crypto_hkdf_expand(uint8_t *dest, size_t destlen,
};
int rv = 0;

if (!crypto_initialized) {
EVP_KDF_free(kdf);
}
crypto_kdf_hkdf_free(kdf);

if (EVP_KDF_derive(kctx, dest, destlen, params) <= 0) {
rv = -1;
Expand Down Expand Up @@ -763,9 +753,7 @@ int ngtcp2_crypto_hkdf(uint8_t *dest, size_t destlen,
};
int rv = 0;

if (!crypto_initialized) {
EVP_KDF_free(kdf);
}
crypto_kdf_hkdf_free(kdf);

if (EVP_KDF_derive(kctx, dest, destlen, params) <= 0) {
rv = -1;
Expand Down
Loading
Loading