aboutsummaryrefslogtreecommitdiff
path: root/src/event/ngx_event_quic.c
diff options
context:
space:
mode:
authorSergey Kandaurov <pluknet@nginx.com>2020-02-28 13:09:52 +0300
committerSergey Kandaurov <pluknet@nginx.com>2020-02-28 13:09:52 +0300
commit56eead6176d2d63392fc82668b2233dfadbae33e (patch)
tree6d0e2c0b580695c62883b7005d7561d1e71ec09a /src/event/ngx_event_quic.c
parent8c90e6f440f432908ad70002bb6acb1f9aec1758 (diff)
downloadnginx-56eead6176d2d63392fc82668b2233dfadbae33e.tar.gz
nginx-56eead6176d2d63392fc82668b2233dfadbae33e.zip
AEAD routines, introduced ngx_quic_tls_open()/ngx_quic_tls_seal().
Diffstat (limited to 'src/event/ngx_event_quic.c')
-rw-r--r--src/event/ngx_event_quic.c208
1 files changed, 208 insertions, 0 deletions
diff --git a/src/event/ngx_event_quic.c b/src/event/ngx_event_quic.c
index a655e7ddc..106ca0d34 100644
--- a/src/event/ngx_event_quic.c
+++ b/src/event/ngx_event_quic.c
@@ -163,3 +163,211 @@ ngx_hkdf_expand(u_char *out_key, size_t out_len, const EVP_MD *digest,
return NGX_OK;
}
+
+
+ngx_int_t
+ngx_quic_tls_open(ngx_connection_t *c, const ngx_aead_cipher_t *cipher,
+ ngx_quic_secret_t *s, ngx_str_t *out, u_char *nonce, ngx_str_t *in,
+ ngx_str_t *ad)
+{
+ out->len = in->len - EVP_GCM_TLS_TAG_LEN;
+ out->data = ngx_pnalloc(c->pool, out->len);
+ if (out->data == NULL) {
+ return NGX_ERROR;
+ }
+
+#ifdef OPENSSL_IS_BORINGSSL
+ EVP_AEAD_CTX *ctx;
+
+ ctx = EVP_AEAD_CTX_new(cipher, s->key.data, s->key.len,
+ EVP_AEAD_DEFAULT_TAG_LENGTH);
+ if (ctx == NULL) {
+ ngx_ssl_error(NGX_LOG_INFO, c->log, 0, "EVP_AEAD_CTX_new() failed");
+ return NGX_ERROR;
+ }
+
+ if (EVP_AEAD_CTX_open(ctx, out->data, &out->len, out->len, nonce, s->iv.len,
+ in->data, in->len, ad->data, ad->len)
+ != 1)
+ {
+ EVP_AEAD_CTX_free(ctx);
+ ngx_ssl_error(NGX_LOG_INFO, c->log, 0, "EVP_AEAD_CTX_open() failed");
+ return NGX_ERROR;
+ }
+
+ EVP_AEAD_CTX_free(ctx);
+#else
+ int len;
+ u_char *tag;
+ EVP_CIPHER_CTX *ctx;
+
+ ctx = EVP_CIPHER_CTX_new();
+ if (ctx == NULL) {
+ ngx_ssl_error(NGX_LOG_INFO, c->log, 0, "EVP_CIPHER_CTX_new() failed");
+ return NGX_ERROR;
+ }
+
+ if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) {
+ EVP_CIPHER_CTX_free(ctx);
+ ngx_ssl_error(NGX_LOG_INFO, c->log, 0, "EVP_DecryptInit_ex() failed");
+ return NGX_ERROR;
+ }
+
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, s->iv.len, NULL)
+ == 0)
+ {
+ EVP_CIPHER_CTX_free(ctx);
+ ngx_ssl_error(NGX_LOG_INFO, c->log, 0,
+ "EVP_CIPHER_CTX_ctrl(EVP_CTRL_GCM_SET_IVLEN) failed");
+ return NGX_ERROR;
+ }
+
+ if (EVP_DecryptInit_ex(ctx, NULL, NULL, s->key.data, nonce) != 1) {
+ EVP_CIPHER_CTX_free(ctx);
+ ngx_ssl_error(NGX_LOG_INFO, c->log, 0, "EVP_DecryptInit_ex() failed");
+ return NGX_ERROR;
+ }
+
+ if (EVP_DecryptUpdate(ctx, NULL, &len, ad->data, ad->len) != 1) {
+ EVP_CIPHER_CTX_free(ctx);
+ ngx_ssl_error(NGX_LOG_INFO, c->log, 0, "EVP_DecryptUpdate() failed");
+ return NGX_ERROR;
+ }
+
+ if (EVP_DecryptUpdate(ctx, out->data, &len, in->data,
+ in->len - EVP_GCM_TLS_TAG_LEN)
+ != 1)
+ {
+ EVP_CIPHER_CTX_free(ctx);
+ ngx_ssl_error(NGX_LOG_INFO, c->log, 0, "EVP_DecryptUpdate() failed");
+ return NGX_ERROR;
+ }
+
+ out->len = len;
+ tag = in->data + in->len - EVP_GCM_TLS_TAG_LEN;
+
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, EVP_GCM_TLS_TAG_LEN, tag)
+ == 0)
+ {
+ EVP_CIPHER_CTX_free(ctx);
+ ngx_ssl_error(NGX_LOG_INFO, c->log, 0,
+ "EVP_CIPHER_CTX_ctrl(EVP_CTRL_GCM_SET_TAG) failed");
+ return NGX_ERROR;
+ }
+
+ if (EVP_DecryptFinal_ex(ctx, out->data + len, &len) <= 0) {
+ EVP_CIPHER_CTX_free(ctx);
+ ngx_ssl_error(NGX_LOG_INFO, c->log, 0, "EVP_DecryptFinal_ex failed");
+ return NGX_ERROR;
+ }
+
+ out->len += len;
+
+ EVP_CIPHER_CTX_free(ctx);
+#endif
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
+ngx_quic_tls_seal(ngx_connection_t *c, const ngx_aead_cipher_t *cipher,
+ ngx_quic_secret_t *s, ngx_str_t *out, u_char *nonce, ngx_str_t *in,
+ ngx_str_t *ad)
+{
+ out->len = in->len + EVP_GCM_TLS_TAG_LEN;
+ out->data = ngx_pnalloc(c->pool, out->len);
+ if (out->data == NULL) {
+ return NGX_ERROR;
+ }
+
+#ifdef OPENSSL_IS_BORINGSSL
+ EVP_AEAD_CTX *ctx;
+
+ ctx = EVP_AEAD_CTX_new(cipher, s->key.data, s->key.len,
+ EVP_AEAD_DEFAULT_TAG_LENGTH);
+ if (ctx == NULL) {
+ ngx_ssl_error(NGX_LOG_INFO, c->log, 0, "EVP_AEAD_CTX_new() failed");
+ return NGX_ERROR;
+ }
+
+ if (EVP_AEAD_CTX_seal(ctx, out->data, &out->len, out->len, nonce, s->iv.len,
+ in->data, in->len, ad->data, ad->len)
+ != 1)
+ {
+ EVP_AEAD_CTX_free(ctx);
+ ngx_ssl_error(NGX_LOG_INFO, c->log, 0, "EVP_AEAD_CTX_seal() failed");
+ return NGX_ERROR;
+ }
+
+ EVP_AEAD_CTX_free(ctx);
+#else
+ int len;
+ EVP_CIPHER_CTX *ctx;
+
+ ctx = EVP_CIPHER_CTX_new();
+ if (ctx == NULL) {
+ ngx_ssl_error(NGX_LOG_INFO, c->log, 0, "EVP_CIPHER_CTX_new() failed");
+ return NGX_ERROR;
+ }
+
+ if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) {
+ EVP_CIPHER_CTX_free(ctx);
+ ngx_ssl_error(NGX_LOG_INFO, c->log, 0, "EVP_EncryptInit_ex() failed");
+ return NGX_ERROR;
+ }
+
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, s->iv.len, NULL)
+ == 0)
+ {
+ EVP_CIPHER_CTX_free(ctx);
+ ngx_ssl_error(NGX_LOG_INFO, c->log, 0,
+ "EVP_CIPHER_CTX_ctrl(EVP_CTRL_GCM_SET_IVLEN) failed");
+ return NGX_ERROR;
+ }
+
+ if (EVP_EncryptInit_ex(ctx, NULL, NULL, s->key.data, nonce) != 1) {
+ EVP_CIPHER_CTX_free(ctx);
+ ngx_ssl_error(NGX_LOG_INFO, c->log, 0, "EVP_EncryptInit_ex() failed");
+ return NGX_ERROR;
+ }
+
+ if (EVP_EncryptUpdate(ctx, NULL, &len, ad->data, ad->len) != 1) {
+ EVP_CIPHER_CTX_free(ctx);
+ ngx_ssl_error(NGX_LOG_INFO, c->log, 0, "EVP_EncryptUpdate() failed");
+ return NGX_ERROR;
+ }
+
+ if (EVP_EncryptUpdate(ctx, out->data, &len, in->data, in->len) != 1) {
+ EVP_CIPHER_CTX_free(ctx);
+ ngx_ssl_error(NGX_LOG_INFO, c->log, 0, "EVP_EncryptUpdate() failed");
+ return NGX_ERROR;
+ }
+
+ out->len = len;
+
+ if (EVP_EncryptFinal_ex(ctx, out->data + out->len, &len) <= 0) {
+ EVP_CIPHER_CTX_free(ctx);
+ ngx_ssl_error(NGX_LOG_INFO, c->log, 0, "EVP_EncryptFinal_ex failed");
+ return NGX_ERROR;
+ }
+
+ out->len += len;
+
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, EVP_GCM_TLS_TAG_LEN,
+ out->data + in->len)
+ == 0)
+ {
+ EVP_CIPHER_CTX_free(ctx);
+ ngx_ssl_error(NGX_LOG_INFO, c->log, 0,
+ "EVP_CIPHER_CTX_ctrl(EVP_CTRL_GCM_GET_TAG) failed");
+ return NGX_ERROR;
+ }
+
+ EVP_CIPHER_CTX_free(ctx);
+
+ out->len += EVP_GCM_TLS_TAG_LEN;
+#endif
+
+ return NGX_OK;
+}