10
10
#include "ddebug.h"
11
11
12
12
#include <ndk.h>
13
+ #include <string.h>
13
14
#include "ngx_http_encrypted_session_cipher.h"
14
15
15
16
#define ngx_http_encrypted_session_default_iv (u_char *) "deadbeefdeadbeef"
19
20
20
21
typedef struct {
21
22
u_char * key ;
23
+ size_t key_len ;
22
24
u_char * iv ;
25
+ size_t iv_len ;
23
26
time_t expires ;
24
-
27
+ ngx_flag_t iv_in_content ;
25
28
} ngx_http_encrypted_session_conf_t ;
26
29
30
+ const char * PARTS_DELIMITER = ":" ;
31
+ const size_t PARTS_DELIMITER_LEN = 1 ;
32
+ const size_t NUM_OF_DELIMITERS = 2 ;
27
33
28
34
static ngx_int_t ngx_http_set_encode_encrypted_session (ngx_http_request_t * r ,
29
35
ngx_str_t * res , ngx_http_variable_value_t * v );
@@ -42,6 +48,8 @@ static char *ngx_http_encrypted_session_iv(ngx_conf_t *cf, ngx_command_t *cmd,
42
48
static char * ngx_http_encrypted_session_expires (ngx_conf_t * cf ,
43
49
ngx_command_t * cmd , void * conf );
44
50
51
+ static char * ngx_http_encrypted_iv_in_content (ngx_conf_t * cf ,
52
+ ngx_command_t * cmd , void * conf );
45
53
46
54
static ngx_int_t ngx_http_encrypted_session_init (ngx_conf_t * cf );
47
55
static void * ngx_http_encrypted_session_create_main_conf (ngx_conf_t * cf );
@@ -53,7 +61,6 @@ static void *ngx_http_encrypted_session_create_conf(ngx_conf_t *cf);
53
61
static char * ngx_http_encrypted_session_merge_conf (ngx_conf_t * cf , void * parent ,
54
62
void * child );
55
63
56
-
57
64
static ndk_set_var_t ngx_http_set_encode_encrypted_session_filter = {
58
65
NDK_SET_VAR_VALUE ,
59
66
(void * ) ngx_http_set_encode_encrypted_session ,
@@ -115,7 +122,14 @@ static ngx_command_t ngx_http_encrypted_session_commands[] = {
115
122
0 ,
116
123
& ngx_http_set_decode_encrypted_session_filter
117
124
},
118
-
125
+ { ngx_string ("include_iv_in_encrypted_payload" ),
126
+ NGX_HTTP_MAIN_CONF |NGX_HTTP_SRV_CONF |NGX_HTTP_SIF_CONF
127
+ |NGX_HTTP_LOC_CONF |NGX_HTTP_LIF_CONF |NGX_CONF_NOARGS ,
128
+ ngx_http_encrypted_iv_in_content ,
129
+ NGX_HTTP_LOC_CONF_OFFSET ,
130
+ 0 ,
131
+ NULL
132
+ },
119
133
ngx_null_command
120
134
};
121
135
@@ -151,14 +165,14 @@ ngx_module_t ngx_http_encrypted_session_module = {
151
165
};
152
166
153
167
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 )
168
+ unsigned char * name , size_t name_len , ngx_http_encrypted_session_conf_t * conf )
155
169
{
156
170
ngx_http_variable_value_t * v ;
157
171
ngx_str_t name_str ;
158
172
name_str .data = name ;
159
- name_str .len = strlen (( const char * ) name ) ;
173
+ name_str .len = name_len ;
160
174
161
- ngx_uint_t key = ngx_hash_strlow (name , name , name_str . len );
175
+ ngx_uint_t key = ngx_hash_strlow (name , name , name_len );
162
176
v = ngx_http_get_variable (r , & name_str , key );
163
177
164
178
if (v -> not_found ) {
@@ -171,6 +185,37 @@ static ngx_str_t ngx_http_get_variable_by_name(ngx_http_request_t *r,
171
185
return var_value ;
172
186
}
173
187
188
+ static char *
189
+ ngx_http_encrypted_session_build_payload (ngx_http_request_t * r ,
190
+ char * input , size_t input_len , ngx_str_t * iv )
191
+ {
192
+ size_t new_len = input_len + iv -> len + PARTS_DELIMITER_LEN ;
193
+ char * data = (char * )ngx_pcalloc (r -> pool , new_len );
194
+ data = strncat (data , input , input_len );
195
+ data = strcat (data , PARTS_DELIMITER );
196
+ data = strncat (data , (char * )iv -> data , iv -> len );
197
+
198
+ return data ;
199
+ }
200
+
201
+ static ngx_str_t *
202
+ ngx_http_session_encrypted_compute_hmac (ngx_http_request_t * r ,
203
+ ngx_str_t * key , ngx_str_t * content )
204
+ {
205
+ size_t signature_len ;
206
+ u_char * signature ;
207
+
208
+ ngx_http_encrypted_session_hmac (key -> data , key -> len ,
209
+ content -> data , content -> len ,
210
+ & signature , & signature_len );
211
+
212
+ ngx_str_t * result = (ngx_str_t * )ngx_pcalloc (r -> pool , sizeof (ngx_str_t ));
213
+ result -> len = signature_len ;
214
+ result -> data = (u_char * )ngx_pcalloc (r -> pool , signature_len + 1 );
215
+ memcpy (result -> data , signature , signature_len );
216
+ return result ;
217
+ }
218
+
174
219
static ngx_int_t
175
220
ngx_http_set_encode_encrypted_session (ngx_http_request_t * r ,
176
221
ngx_str_t * res , ngx_http_variable_value_t * v )
@@ -196,12 +241,19 @@ ngx_http_set_encode_encrypted_session(ngx_http_request_t *r,
196
241
ngx_log_debug1 (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
197
242
"encrypted_session: expires=%T" , conf -> expires );
198
243
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 );
244
+ ngx_str_t iv = ngx_http_get_variable_by_name (r , conf -> iv , conf -> iv_len ,
245
+ conf );
246
+ ngx_str_t key = ngx_http_get_variable_by_name (r , conf -> key , conf -> key_len ,
247
+ conf );
248
+
249
+ char * data = (char * )v -> data ;
250
+ if (conf -> iv_in_content ) {
251
+ data = ngx_http_encrypted_session_build_payload (r , data , v -> len , & iv );
252
+ }
201
253
202
254
rc = ngx_http_encrypted_session_aes_mac_encrypt (emcf , r -> pool ,
203
255
r -> connection -> log , iv .data , iv .len , key .data , key .len ,
204
- v -> data , v -> len , (ngx_uint_t ) conf -> expires , & dst , & len );
256
+ ( u_char * ) data , v -> len , (ngx_uint_t ) conf -> expires , & dst , & len );
205
257
206
258
if (rc != NGX_OK ) {
207
259
dst = NULL ;
@@ -211,6 +263,29 @@ ngx_http_set_encode_encrypted_session(ngx_http_request_t *r,
211
263
"encrypted_session: failed to encrypt" );
212
264
}
213
265
266
+ if (conf -> iv_in_content ) {
267
+ size_t signature_content_len = iv .len + len ;
268
+ char * signature_content = (char * )ngx_pcalloc (r -> pool , signature_content_len + 1 );
269
+ signature_content = strncat (signature_content , (char * )iv .data , iv .len );
270
+ signature_content = strncat (signature_content , (char * )dst , len );
271
+
272
+ ngx_str_t signature_input ;
273
+ signature_input .len = signature_content_len ;
274
+ signature_input .data = (u_char * )signature_content ;
275
+ ngx_str_t * signature = ngx_http_session_encrypted_compute_hmac (r , & key ,
276
+ & signature_input );
277
+
278
+ size_t new_len = iv .len + len + signature -> len + NUM_OF_DELIMITERS * PARTS_DELIMITER_LEN ;
279
+ char * new_content = (char * )ngx_pcalloc (r -> pool , new_len + 1 );
280
+ new_content = strncat (new_content , (char * )iv .data , iv .len );
281
+ new_content = strcat (new_content , PARTS_DELIMITER );
282
+ new_content = strncat (new_content , (char * )dst , len );
283
+ new_content = strcat (new_content , PARTS_DELIMITER );
284
+ new_content = strncat (new_content , (char * )signature -> data , signature -> len );
285
+ len = new_len ;
286
+ dst = (u_char * )new_content ;
287
+ }
288
+
214
289
res -> data = dst ;
215
290
res -> len = len ;
216
291
@@ -240,12 +315,55 @@ ngx_http_set_decode_encrypted_session(ngx_http_request_t *r,
240
315
return NGX_ERROR ;
241
316
}
242
317
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 );
318
+ ngx_str_t key = ngx_http_get_variable_by_name (r , conf -> key , conf -> key_len ,
319
+ conf );
320
+
321
+ ngx_str_t iv ;
322
+ char * data = (char * )v -> data ;
323
+ size_t data_len = v -> len ;
324
+
325
+
326
+ if (!conf -> iv_in_content )
327
+ {
328
+ iv = ngx_http_get_variable_by_name (r , conf -> iv , conf -> iv_len , conf );
329
+ }
330
+ else
331
+ {
332
+ iv .len = strcspn (data , PARTS_DELIMITER );
333
+ iv .data = (u_char * )ngx_pcalloc (r -> pool , iv .len + 1 );
334
+ strncpy ((char * )iv .data , (char * )v -> data , iv .len );
335
+
336
+ size_t signature_start = iv .len + strcspn (& data [iv .len + 1 ], PARTS_DELIMITER ) + NUM_OF_DELIMITERS * PARTS_DELIMITER_LEN ;
337
+ size_t signature_len = v -> len - signature_start ;
338
+
339
+ u_char * signature = (u_char * )ngx_pcalloc (r -> pool , signature_len + 1 );
340
+ strncpy ((char * )signature , & data [data_len - signature_len ], signature_len );
341
+
342
+ data_len = v -> len - iv .len - signature_len - NUM_OF_DELIMITERS * PARTS_DELIMITER_LEN ;
343
+ data = (char * )ngx_pcalloc (r -> pool , data_len + 1 );
344
+ strncpy (data , (char * )(& v -> data [iv .len + 1 ]), data_len );
345
+
346
+ ngx_str_t signature_input ;
347
+ signature_input .len = iv .len + data_len ;
348
+ signature_input .data = (u_char * )ngx_pcalloc (r -> pool , signature_input .len + 1 );
349
+ strncat ((char * )signature_input .data , (char * )iv .data , iv .len );
350
+ strncat ((char * )signature_input .data , (char * )data , data_len );
351
+
352
+ ngx_str_t * computed_signature = ngx_http_session_encrypted_compute_hmac (r ,
353
+ & key , & signature_input );
354
+ if (signature_len != computed_signature -> len ||
355
+ strncmp ((char * )computed_signature -> data , (char * )signature , signature_len ) != 0 )
356
+ {
357
+ res -> data = NULL ;
358
+ res -> len = 0 ;
359
+
360
+ return NGX_OK ;
361
+ }
362
+ }
245
363
246
364
rc = ngx_http_encrypted_session_aes_mac_decrypt (emcf , r -> pool ,
247
365
r -> connection -> log , iv .data , iv .len , key .data , key .len ,
248
- v -> data , v -> len , & dst , & len );
366
+ ( u_char * ) data , data_len , & dst , & len );
249
367
250
368
if (rc != NGX_OK ) {
251
369
dst = NULL ;
@@ -273,7 +391,9 @@ ngx_http_encrypted_session_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
273
391
value = cf -> args -> elts ;
274
392
275
393
if (value [1 ].len > 1 && value [1 ].data [0 ] == '$' ) {
276
- llcf -> key = & (value [1 ].data [1 ]);
394
+ llcf -> key_len = value [1 ].len - 1 ;
395
+ llcf -> key = (u_char * )ngx_pcalloc (cf -> pool , llcf -> key_len );
396
+ strncpy ((char * )llcf -> key , (char * )& (value [1 ].data [1 ]), llcf -> key_len );
277
397
return NGX_CONF_OK ;
278
398
}
279
399
@@ -287,6 +407,7 @@ ngx_http_encrypted_session_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
287
407
}
288
408
289
409
llcf -> key = value [1 ].data ;
410
+ llcf -> key_len = value [1 ].len ;
290
411
291
412
return NGX_CONF_OK ;
292
413
}
@@ -307,6 +428,7 @@ ngx_http_encrypted_session_iv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
307
428
308
429
if (value [1 ].len > 1 && value [1 ].data [0 ] == '$' ) {
309
430
llcf -> iv = & (value [1 ].data [1 ]);
431
+ llcf -> iv_len = value [1 ].len - 1 ;
310
432
return NGX_CONF_OK ;
311
433
}
312
434
@@ -320,6 +442,7 @@ ngx_http_encrypted_session_iv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
320
442
}
321
443
322
444
llcf -> iv = ngx_pcalloc (cf -> pool , ngx_http_encrypted_session_iv_length );
445
+ llcf -> iv_len = ngx_http_encrypted_session_iv_length ;
323
446
324
447
if (llcf -> iv == NULL ) {
325
448
return NGX_CONF_ERROR ;
@@ -360,6 +483,13 @@ ngx_http_encrypted_session_expires(ngx_conf_t *cf, ngx_command_t *cmd,
360
483
return NGX_CONF_OK ;
361
484
}
362
485
486
+ static char * ngx_http_encrypted_iv_in_content (ngx_conf_t * cf ,
487
+ ngx_command_t * cmd , void * conf )
488
+ {
489
+ ngx_http_encrypted_session_conf_t * llcf = conf ;
490
+ llcf -> iv_in_content = 1 ;
491
+ return NGX_CONF_OK ;
492
+ }
363
493
364
494
static void
365
495
ngx_http_encrypted_session_free_cipher_ctx (void * data )
@@ -435,8 +565,11 @@ ngx_http_encrypted_session_create_conf(ngx_conf_t *cf)
435
565
}
436
566
437
567
conf -> key = NGX_CONF_UNSET_PTR ;
568
+ conf -> key_len = NGX_CONF_UNSET ;
438
569
conf -> iv = NGX_CONF_UNSET_PTR ;
570
+ conf -> iv_len = NGX_CONF_UNSET ;
439
571
conf -> expires = NGX_CONF_UNSET ;
572
+ conf -> iv_in_content = NGX_CONF_UNSET ;
440
573
441
574
return conf ;
442
575
}
@@ -449,12 +582,17 @@ ngx_http_encrypted_session_merge_conf(ngx_conf_t *cf, void *parent, void *child)
449
582
ngx_http_encrypted_session_conf_t * conf = child ;
450
583
451
584
ngx_conf_merge_ptr_value (conf -> key , prev -> key , NULL );
585
+ ngx_conf_merge_size_value (conf -> key_len , prev -> key_len ,
586
+ (size_t )ngx_http_encrypted_session_key_length );
452
587
453
588
ngx_conf_merge_ptr_value (conf -> iv , prev -> iv ,
454
589
ngx_http_encrypted_session_default_iv );
590
+ ngx_conf_merge_size_value (conf -> iv_len , prev -> iv_len ,
591
+ (size_t )ngx_http_encrypted_session_iv_length );
455
592
456
593
ngx_conf_merge_value (conf -> expires , prev -> expires ,
457
594
ngx_http_encrypted_session_default_expires );
595
+ ngx_conf_merge_value (conf -> iv_in_content , prev -> iv_in_content , 0 );
458
596
459
597
return NGX_CONF_OK ;
460
598
}
0 commit comments