Skip to content

Commit d99014c

Browse files
committed
An IV should be generated for each encryption
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
1 parent 99662f8 commit d99014c

File tree

1 file changed

+91
-13
lines changed

1 file changed

+91
-13
lines changed

src/ngx_http_encrypted_session_module.c

Lines changed: 91 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "ddebug.h"
1111

1212
#include <ndk.h>
13+
#include <string.h>
1314
#include "ngx_http_encrypted_session_cipher.h"
1415

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

2021
typedef struct {
2122
u_char *key;
23+
size_t key_len;
2224
u_char *iv;
25+
size_t iv_len;
2326
time_t expires;
24-
27+
ngx_flag_t iv_in_content;
2528
} ngx_http_encrypted_session_conf_t;
2629

2730

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

48+
static char *ngx_http_encrypted_iv_in_content(ngx_conf_t *cf,
49+
ngx_command_t *cmd, void *conf);
4550

4651
static ngx_int_t ngx_http_encrypted_session_init(ngx_conf_t *cf);
4752
static void *ngx_http_encrypted_session_create_main_conf(ngx_conf_t *cf);
@@ -53,7 +58,6 @@ static void *ngx_http_encrypted_session_create_conf(ngx_conf_t *cf);
5358
static char *ngx_http_encrypted_session_merge_conf(ngx_conf_t *cf, void *parent,
5459
void *child);
5560

56-
5761
static ndk_set_var_t ngx_http_set_encode_encrypted_session_filter = {
5862
NDK_SET_VAR_VALUE,
5963
(void *) ngx_http_set_encode_encrypted_session,
@@ -115,7 +119,14 @@ static ngx_command_t ngx_http_encrypted_session_commands[] = {
115119
0,
116120
&ngx_http_set_decode_encrypted_session_filter
117121
},
118-
122+
{ ngx_string("include_iv_in_encrypted_payload"),
123+
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF
124+
|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_NOARGS,
125+
ngx_http_encrypted_iv_in_content,
126+
NGX_HTTP_LOC_CONF_OFFSET,
127+
0,
128+
NULL
129+
},
119130
ngx_null_command
120131
};
121132

@@ -151,14 +162,14 @@ ngx_module_t ngx_http_encrypted_session_module = {
151162
};
152163

153164
static ngx_str_t ngx_http_get_variable_by_name(ngx_http_request_t *r,
154-
unsigned char *name, ngx_http_encrypted_session_conf_t *conf)
165+
unsigned char *name, size_t name_len, ngx_http_encrypted_session_conf_t *conf)
155166
{
156167
ngx_http_variable_value_t *v;
157168
ngx_str_t name_str;
158169
name_str.data = name;
159-
name_str.len = strlen((const char *)name);
170+
name_str.len = name_len;
160171

161-
ngx_uint_t key = ngx_hash_strlow(name, name, name_str.len);
172+
ngx_uint_t key = ngx_hash_strlow(name, name, name_len);
162173
v = ngx_http_get_variable(r, &name_str, key);
163174

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

185+
static char*
186+
ngx_http_encrypted_session_build_payload(ngx_http_request_t *r,
187+
char *input, size_t input_len, ngx_str_t *iv)
188+
{
189+
size_t new_len = input_len + iv->len + 2;
190+
char *data = (char *)ngx_pcalloc(r->pool, new_len);
191+
data = strncat(data, input, input_len);
192+
data = strcat(data, ":");
193+
data = strncat(data, (char *)iv->data, iv->len);
194+
195+
return data;
196+
}
197+
174198
static ngx_int_t
175199
ngx_http_set_encode_encrypted_session(ngx_http_request_t *r,
176200
ngx_str_t *res, ngx_http_variable_value_t *v)
@@ -196,12 +220,19 @@ ngx_http_set_encode_encrypted_session(ngx_http_request_t *r,
196220
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
197221
"encrypted_session: expires=%T", conf->expires);
198222

199-
ngx_str_t iv = ngx_http_get_variable_by_name(r, conf->iv, conf);
200-
ngx_str_t key = ngx_http_get_variable_by_name(r, conf->key, conf);
223+
ngx_str_t iv = ngx_http_get_variable_by_name(r, conf->iv, conf->iv_len,
224+
conf);
225+
ngx_str_t key = ngx_http_get_variable_by_name(r, conf->key, conf->key_len,
226+
conf);
227+
228+
char *data = (char *)v->data;
229+
if (conf->iv_in_content) {
230+
data = ngx_http_encrypted_session_build_payload(r, data, v->len, &iv);
231+
}
201232

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

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

245+
if (conf->iv_in_content) {
246+
size_t new_len = iv.len + len + 1;
247+
char *new_content = (char*)ngx_pcalloc(r->pool, new_len);
248+
new_content = strncat(new_content, (char*)iv.data, iv.len);
249+
new_content = strcat(new_content, ":");
250+
new_content = strncat(new_content, (char*)dst, len);
251+
len = new_len;
252+
dst = (u_char*)new_content;
253+
}
254+
214255
res->data = dst;
215256
res->len = len;
216257

@@ -240,12 +281,29 @@ ngx_http_set_decode_encrypted_session(ngx_http_request_t *r,
240281
return NGX_ERROR;
241282
}
242283

243-
ngx_str_t iv = ngx_http_get_variable_by_name(r, conf->iv, conf);
244-
ngx_str_t key = ngx_http_get_variable_by_name(r, conf->key, conf);
284+
ngx_str_t iv;
285+
char *data = (char*)v->data;
286+
size_t data_len = v->len;
287+
288+
if (!conf->iv_in_content) {
289+
iv = ngx_http_get_variable_by_name(r, conf->iv, conf->iv_len, conf);
290+
} else {
291+
iv.len = strcspn(data, ":");
292+
iv.data = (u_char*)ngx_pcalloc(r->pool, iv.len + 1);
293+
294+
strncpy((char*)iv.data, (char*)v->data, iv.len);
295+
296+
data_len = v->len - iv.len - 1;
297+
data = (char*)ngx_pcalloc(r->pool, data_len);
298+
strncpy(data, (char*)(&v->data[iv.len + 1]), data_len);
299+
}
300+
301+
ngx_str_t key = ngx_http_get_variable_by_name(r, conf->key, conf->key_len,
302+
conf);
245303

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

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

275333
if (value[1].len > 1 && value[1].data[0] == '$') {
276-
llcf->key = &(value[1].data[1]);
334+
llcf->key_len = value[1].len - 1;
335+
llcf->key = (u_char*)ngx_pcalloc(cf->pool, llcf->key_len);
336+
strncpy((char*)llcf->key, (char*)&(value[1].data[1]), llcf->key_len);
277337
return NGX_CONF_OK;
278338
}
279339

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

289349
llcf->key = value[1].data;
350+
llcf->key_len = value[1].len;
290351

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

308369
if (value[1].len > 1 && value[1].data[0] == '$') {
309370
llcf->iv = &(value[1].data[1]);
371+
llcf->iv_len = value[1].len - 1;
310372
return NGX_CONF_OK;
311373
}
312374

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

322384
llcf->iv = ngx_pcalloc(cf->pool, ngx_http_encrypted_session_iv_length);
385+
llcf->iv_len = ngx_http_encrypted_session_iv_length;
323386

324387
if (llcf->iv == NULL) {
325388
return NGX_CONF_ERROR;
@@ -360,6 +423,13 @@ ngx_http_encrypted_session_expires(ngx_conf_t *cf, ngx_command_t *cmd,
360423
return NGX_CONF_OK;
361424
}
362425

426+
static char *ngx_http_encrypted_iv_in_content(ngx_conf_t *cf,
427+
ngx_command_t *cmd, void *conf)
428+
{
429+
ngx_http_encrypted_session_conf_t *llcf = conf;
430+
llcf->iv_in_content = 1;
431+
return NGX_CONF_OK;
432+
}
363433

364434
static void
365435
ngx_http_encrypted_session_free_cipher_ctx(void *data)
@@ -435,8 +505,11 @@ ngx_http_encrypted_session_create_conf(ngx_conf_t *cf)
435505
}
436506

437507
conf->key = NGX_CONF_UNSET_PTR;
508+
conf->key_len = NGX_CONF_UNSET;
438509
conf->iv = NGX_CONF_UNSET_PTR;
510+
conf->iv_len = NGX_CONF_UNSET;
439511
conf->expires = NGX_CONF_UNSET;
512+
conf->iv_in_content = NGX_CONF_UNSET;
440513

441514
return conf;
442515
}
@@ -449,12 +522,17 @@ ngx_http_encrypted_session_merge_conf(ngx_conf_t *cf, void *parent, void *child)
449522
ngx_http_encrypted_session_conf_t *conf = child;
450523

451524
ngx_conf_merge_ptr_value(conf->key, prev->key, NULL);
525+
ngx_conf_merge_size_value(conf->key_len, prev->key_len,
526+
(size_t)ngx_http_encrypted_session_key_length);
452527

453528
ngx_conf_merge_ptr_value(conf->iv, prev->iv,
454529
ngx_http_encrypted_session_default_iv);
530+
ngx_conf_merge_size_value(conf->iv_len, prev->iv_len,
531+
(size_t)ngx_http_encrypted_session_iv_length);
455532

456533
ngx_conf_merge_value(conf->expires, prev->expires,
457534
ngx_http_encrypted_session_default_expires);
535+
ngx_conf_merge_value(conf->iv_in_content, prev->iv_in_content, 0);
458536

459537
return NGX_CONF_OK;
460538
}

0 commit comments

Comments
 (0)