Skip to content

Commit

Permalink
An IV should be generated for each encryption
Browse files Browse the repository at this point in the history
We now have the ability to decide if the IV is communicated to the client in a non forgeable manner or we only keep it on the server side.

Closes openresty#2
  • Loading branch information
rcosnita committed Oct 29, 2020
1 parent 99662f8 commit d99014c
Showing 1 changed file with 91 additions and 13 deletions.
104 changes: 91 additions & 13 deletions src/ngx_http_encrypted_session_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "ddebug.h"

#include <ndk.h>
#include <string.h>
#include "ngx_http_encrypted_session_cipher.h"

#define ngx_http_encrypted_session_default_iv (u_char *) "deadbeefdeadbeef"
Expand All @@ -19,9 +20,11 @@

typedef struct {
u_char *key;
size_t key_len;
u_char *iv;
size_t iv_len;
time_t expires;

ngx_flag_t iv_in_content;
} ngx_http_encrypted_session_conf_t;


Expand All @@ -42,6 +45,8 @@ static char *ngx_http_encrypted_session_iv(ngx_conf_t *cf, ngx_command_t *cmd,
static char *ngx_http_encrypted_session_expires(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf);

static char *ngx_http_encrypted_iv_in_content(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf);

static ngx_int_t ngx_http_encrypted_session_init(ngx_conf_t *cf);
static void *ngx_http_encrypted_session_create_main_conf(ngx_conf_t *cf);
Expand All @@ -53,7 +58,6 @@ static void *ngx_http_encrypted_session_create_conf(ngx_conf_t *cf);
static char *ngx_http_encrypted_session_merge_conf(ngx_conf_t *cf, void *parent,
void *child);


static ndk_set_var_t ngx_http_set_encode_encrypted_session_filter = {
NDK_SET_VAR_VALUE,
(void *) ngx_http_set_encode_encrypted_session,
Expand Down Expand Up @@ -115,7 +119,14 @@ static ngx_command_t ngx_http_encrypted_session_commands[] = {
0,
&ngx_http_set_decode_encrypted_session_filter
},

{ ngx_string("include_iv_in_encrypted_payload"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF
|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_NOARGS,
ngx_http_encrypted_iv_in_content,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL
},
ngx_null_command
};

Expand Down Expand Up @@ -151,14 +162,14 @@ ngx_module_t ngx_http_encrypted_session_module = {
};

static ngx_str_t ngx_http_get_variable_by_name(ngx_http_request_t *r,
unsigned char *name, ngx_http_encrypted_session_conf_t *conf)
unsigned char *name, size_t name_len, ngx_http_encrypted_session_conf_t *conf)
{
ngx_http_variable_value_t *v;
ngx_str_t name_str;
name_str.data = name;
name_str.len = strlen((const char *)name);
name_str.len = name_len;

ngx_uint_t key = ngx_hash_strlow(name, name, name_str.len);
ngx_uint_t key = ngx_hash_strlow(name, name, name_len);
v = ngx_http_get_variable(r, &name_str, key);

if (v->not_found) {
Expand All @@ -171,6 +182,19 @@ static ngx_str_t ngx_http_get_variable_by_name(ngx_http_request_t *r,
return var_value;
}

static char*
ngx_http_encrypted_session_build_payload(ngx_http_request_t *r,
char *input, size_t input_len, ngx_str_t *iv)
{
size_t new_len = input_len + iv->len + 2;
char *data = (char *)ngx_pcalloc(r->pool, new_len);
data = strncat(data, input, input_len);
data = strcat(data, ":");
data = strncat(data, (char *)iv->data, iv->len);

return data;
}

static ngx_int_t
ngx_http_set_encode_encrypted_session(ngx_http_request_t *r,
ngx_str_t *res, ngx_http_variable_value_t *v)
Expand All @@ -196,12 +220,19 @@ ngx_http_set_encode_encrypted_session(ngx_http_request_t *r,
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"encrypted_session: expires=%T", conf->expires);

ngx_str_t iv = ngx_http_get_variable_by_name(r, conf->iv, conf);
ngx_str_t key = ngx_http_get_variable_by_name(r, conf->key, conf);
ngx_str_t iv = ngx_http_get_variable_by_name(r, conf->iv, conf->iv_len,
conf);
ngx_str_t key = ngx_http_get_variable_by_name(r, conf->key, conf->key_len,
conf);

char *data = (char *)v->data;
if (conf->iv_in_content) {
data = ngx_http_encrypted_session_build_payload(r, data, v->len, &iv);
}

rc = ngx_http_encrypted_session_aes_mac_encrypt(emcf, r->pool,
r->connection->log, iv.data, iv.len, key.data, key.len,
v->data, v->len, (ngx_uint_t) conf->expires, &dst, &len);
(u_char*)data, v->len, (ngx_uint_t) conf->expires, &dst, &len);

if (rc != NGX_OK) {
dst = NULL;
Expand All @@ -211,6 +242,16 @@ ngx_http_set_encode_encrypted_session(ngx_http_request_t *r,
"encrypted_session: failed to encrypt");
}

if (conf->iv_in_content) {
size_t new_len = iv.len + len + 1;
char *new_content = (char*)ngx_pcalloc(r->pool, new_len);
new_content = strncat(new_content, (char*)iv.data, iv.len);
new_content = strcat(new_content, ":");
new_content = strncat(new_content, (char*)dst, len);
len = new_len;
dst = (u_char*)new_content;
}

res->data = dst;
res->len = len;

Expand Down Expand Up @@ -240,12 +281,29 @@ ngx_http_set_decode_encrypted_session(ngx_http_request_t *r,
return NGX_ERROR;
}

ngx_str_t iv = ngx_http_get_variable_by_name(r, conf->iv, conf);
ngx_str_t key = ngx_http_get_variable_by_name(r, conf->key, conf);
ngx_str_t iv;
char *data = (char*)v->data;
size_t data_len = v->len;

if (!conf->iv_in_content) {
iv = ngx_http_get_variable_by_name(r, conf->iv, conf->iv_len, conf);
} else {
iv.len = strcspn(data, ":");
iv.data = (u_char*)ngx_pcalloc(r->pool, iv.len + 1);

strncpy((char*)iv.data, (char*)v->data, iv.len);

data_len = v->len - iv.len - 1;
data = (char*)ngx_pcalloc(r->pool, data_len);
strncpy(data, (char*)(&v->data[iv.len + 1]), data_len);
}

ngx_str_t key = ngx_http_get_variable_by_name(r, conf->key, conf->key_len,
conf);

rc = ngx_http_encrypted_session_aes_mac_decrypt(emcf, r->pool,
r->connection->log, iv.data, iv.len, key.data, key.len,
v->data, v->len, &dst, &len);
(u_char*)data, data_len, &dst, &len);

if (rc != NGX_OK) {
dst = NULL;
Expand Down Expand Up @@ -273,7 +331,9 @@ ngx_http_encrypted_session_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
value = cf->args->elts;

if (value[1].len > 1 && value[1].data[0] == '$') {
llcf->key = &(value[1].data[1]);
llcf->key_len = value[1].len - 1;
llcf->key = (u_char*)ngx_pcalloc(cf->pool, llcf->key_len);
strncpy((char*)llcf->key, (char*)&(value[1].data[1]), llcf->key_len);
return NGX_CONF_OK;
}

Expand All @@ -287,6 +347,7 @@ ngx_http_encrypted_session_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}

llcf->key = value[1].data;
llcf->key_len = value[1].len;

return NGX_CONF_OK;
}
Expand All @@ -307,6 +368,7 @@ ngx_http_encrypted_session_iv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)

if (value[1].len > 1 && value[1].data[0] == '$') {
llcf->iv = &(value[1].data[1]);
llcf->iv_len = value[1].len - 1;
return NGX_CONF_OK;
}

Expand All @@ -320,6 +382,7 @@ ngx_http_encrypted_session_iv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}

llcf->iv = ngx_pcalloc(cf->pool, ngx_http_encrypted_session_iv_length);
llcf->iv_len = ngx_http_encrypted_session_iv_length;

if (llcf->iv == NULL) {
return NGX_CONF_ERROR;
Expand Down Expand Up @@ -360,6 +423,13 @@ ngx_http_encrypted_session_expires(ngx_conf_t *cf, ngx_command_t *cmd,
return NGX_CONF_OK;
}

static char *ngx_http_encrypted_iv_in_content(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf)
{
ngx_http_encrypted_session_conf_t *llcf = conf;
llcf->iv_in_content = 1;
return NGX_CONF_OK;
}

static void
ngx_http_encrypted_session_free_cipher_ctx(void *data)
Expand Down Expand Up @@ -435,8 +505,11 @@ ngx_http_encrypted_session_create_conf(ngx_conf_t *cf)
}

conf->key = NGX_CONF_UNSET_PTR;
conf->key_len = NGX_CONF_UNSET;
conf->iv = NGX_CONF_UNSET_PTR;
conf->iv_len = NGX_CONF_UNSET;
conf->expires = NGX_CONF_UNSET;
conf->iv_in_content = NGX_CONF_UNSET;

return conf;
}
Expand All @@ -449,12 +522,17 @@ ngx_http_encrypted_session_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_encrypted_session_conf_t *conf = child;

ngx_conf_merge_ptr_value(conf->key, prev->key, NULL);
ngx_conf_merge_size_value(conf->key_len, prev->key_len,
(size_t)ngx_http_encrypted_session_key_length);

ngx_conf_merge_ptr_value(conf->iv, prev->iv,
ngx_http_encrypted_session_default_iv);
ngx_conf_merge_size_value(conf->iv_len, prev->iv_len,
(size_t)ngx_http_encrypted_session_iv_length);

ngx_conf_merge_value(conf->expires, prev->expires,
ngx_http_encrypted_session_default_expires);
ngx_conf_merge_value(conf->iv_in_content, prev->iv_in_content, 0);

return NGX_CONF_OK;
}

0 comments on commit d99014c

Please sign in to comment.