QUIC: common code for crypto open and seal operations.

This commit is contained in:
Sergey Kandaurov 2023-10-20 18:05:07 +04:00
parent 80a695add8
commit 52d50714eb

View File

@ -28,6 +28,10 @@ static uint64_t ngx_quic_parse_pn(u_char **pos, ngx_int_t len, u_char *mask,
static ngx_int_t ngx_quic_crypto_open(ngx_quic_secret_t *s, ngx_str_t *out, static ngx_int_t ngx_quic_crypto_open(ngx_quic_secret_t *s, ngx_str_t *out,
u_char *nonce, ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log); u_char *nonce, ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log);
#ifndef OPENSSL_IS_BORINGSSL
static ngx_int_t ngx_quic_crypto_common(ngx_quic_secret_t *s, ngx_str_t *out,
u_char *nonce, ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log);
#endif
static ngx_int_t ngx_quic_crypto_hp(ngx_log_t *log, const EVP_CIPHER *cipher, static ngx_int_t ngx_quic_crypto_hp(ngx_log_t *log, const EVP_CIPHER *cipher,
ngx_quic_secret_t *s, u_char *out, u_char *in); ngx_quic_secret_t *s, u_char *out, u_char *in);
@ -426,65 +430,19 @@ static ngx_int_t
ngx_quic_crypto_open(ngx_quic_secret_t *s, ngx_str_t *out, u_char *nonce, ngx_quic_crypto_open(ngx_quic_secret_t *s, ngx_str_t *out, u_char *nonce,
ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log) ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log)
{ {
ngx_quic_crypto_ctx_t *ctx;
ctx = s->ctx;
#ifdef OPENSSL_IS_BORINGSSL #ifdef OPENSSL_IS_BORINGSSL
if (EVP_AEAD_CTX_open(ctx, out->data, &out->len, out->len, nonce, s->iv.len, if (EVP_AEAD_CTX_open(s->ctx, out->data, &out->len, out->len, nonce,
in->data, in->len, ad->data, ad->len) s->iv.len, in->data, in->len, ad->data, ad->len)
!= 1) != 1)
{ {
ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_AEAD_CTX_open() failed"); ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_AEAD_CTX_open() failed");
return NGX_ERROR; return NGX_ERROR;
} }
#else
int len;
if (EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, nonce) != 1) {
ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptInit_ex() failed");
return NGX_ERROR;
}
in->len -= NGX_QUIC_TAG_LEN;
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN,
in->data + in->len)
== 0)
{
ngx_ssl_error(NGX_LOG_INFO, log, 0,
"EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG) failed");
return NGX_ERROR;
}
if (EVP_CIPHER_mode(EVP_CIPHER_CTX_cipher(ctx)) == EVP_CIPH_CCM_MODE
&& EVP_DecryptUpdate(ctx, NULL, &len, NULL, in->len) != 1)
{
ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptUpdate() failed");
return NGX_ERROR;
}
if (EVP_DecryptUpdate(ctx, NULL, &len, ad->data, ad->len) != 1) {
ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptUpdate() failed");
return NGX_ERROR;
}
if (EVP_DecryptUpdate(ctx, out->data, &len, in->data, in->len) != 1) {
ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptUpdate() failed");
return NGX_ERROR;
}
out->len = len;
if (EVP_DecryptFinal_ex(ctx, out->data + out->len, &len) <= 0) {
ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptFinal_ex failed");
return NGX_ERROR;
}
out->len += len;
#endif
return NGX_OK; return NGX_OK;
#else
return ngx_quic_crypto_common(s, out, nonce, in, ad, log);
#endif
} }
@ -492,67 +450,96 @@ ngx_int_t
ngx_quic_crypto_seal(ngx_quic_secret_t *s, ngx_str_t *out, u_char *nonce, ngx_quic_crypto_seal(ngx_quic_secret_t *s, ngx_str_t *out, u_char *nonce,
ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log) ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log)
{ {
ngx_quic_crypto_ctx_t *ctx;
ctx = s->ctx;
#ifdef OPENSSL_IS_BORINGSSL #ifdef OPENSSL_IS_BORINGSSL
if (EVP_AEAD_CTX_seal(ctx, out->data, &out->len, out->len, nonce, s->iv.len, if (EVP_AEAD_CTX_seal(s->ctx, out->data, &out->len, out->len, nonce,
in->data, in->len, ad->data, ad->len) s->iv.len, in->data, in->len, ad->data, ad->len)
!= 1) != 1)
{ {
ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_AEAD_CTX_seal() failed"); ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_AEAD_CTX_seal() failed");
return NGX_ERROR; return NGX_ERROR;
} }
#else
int len;
if (EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, nonce) != 1) { return NGX_OK;
ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptInit_ex() failed"); #else
return ngx_quic_crypto_common(s, out, nonce, in, ad, log);
#endif
}
#ifndef OPENSSL_IS_BORINGSSL
static ngx_int_t
ngx_quic_crypto_common(ngx_quic_secret_t *s, ngx_str_t *out, u_char *nonce,
ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log)
{
int len, enc;
ngx_quic_crypto_ctx_t *ctx;
ctx = s->ctx;
enc = EVP_CIPHER_CTX_encrypting(ctx);
if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, nonce, enc) != 1) {
ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_CipherInit_ex() failed");
return NGX_ERROR; return NGX_ERROR;
} }
if (enc == 0) {
in->len -= NGX_QUIC_TAG_LEN;
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN,
in->data + in->len)
== 0)
{
ngx_ssl_error(NGX_LOG_INFO, log, 0,
"EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG) failed");
return NGX_ERROR;
}
}
if (EVP_CIPHER_mode(EVP_CIPHER_CTX_cipher(ctx)) == EVP_CIPH_CCM_MODE if (EVP_CIPHER_mode(EVP_CIPHER_CTX_cipher(ctx)) == EVP_CIPH_CCM_MODE
&& EVP_EncryptUpdate(ctx, NULL, &len, NULL, in->len) != 1) && EVP_CipherUpdate(ctx, NULL, &len, NULL, in->len) != 1)
{ {
ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptUpdate() failed"); ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_CipherUpdate() failed");
return NGX_ERROR; return NGX_ERROR;
} }
if (EVP_EncryptUpdate(ctx, NULL, &len, ad->data, ad->len) != 1) { if (EVP_CipherUpdate(ctx, NULL, &len, ad->data, ad->len) != 1) {
ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptUpdate() failed"); ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_CipherUpdate() failed");
return NGX_ERROR; return NGX_ERROR;
} }
if (EVP_EncryptUpdate(ctx, out->data, &len, in->data, in->len) != 1) { if (EVP_CipherUpdate(ctx, out->data, &len, in->data, in->len) != 1) {
ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptUpdate() failed"); ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_CipherUpdate() failed");
return NGX_ERROR; return NGX_ERROR;
} }
out->len = len; out->len = len;
if (EVP_EncryptFinal_ex(ctx, out->data + out->len, &len) <= 0) { if (EVP_CipherFinal_ex(ctx, out->data + out->len, &len) <= 0) {
ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptFinal_ex failed"); ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_CipherFinal_ex failed");
return NGX_ERROR; return NGX_ERROR;
} }
out->len += len; out->len += len;
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, NGX_QUIC_TAG_LEN, if (enc == 1) {
out->data + out->len) if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, NGX_QUIC_TAG_LEN,
== 0) out->data + out->len)
{ == 0)
ngx_ssl_error(NGX_LOG_INFO, log, 0, {
"EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_GET_TAG) failed"); ngx_ssl_error(NGX_LOG_INFO, log, 0,
return NGX_ERROR; "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_GET_TAG) failed");
} return NGX_ERROR;
}
out->len += NGX_QUIC_TAG_LEN; out->len += NGX_QUIC_TAG_LEN;
#endif }
return NGX_OK; return NGX_OK;
} }
#endif
void void
ngx_quic_crypto_cleanup(ngx_quic_secret_t *s) ngx_quic_crypto_cleanup(ngx_quic_secret_t *s)