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"
1920
2021typedef 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
30+ const char * PARTS_DELIMITER = ":" ;
31+ const size_t PARTS_DELIMITER_LEN = 1 ;
32+ const size_t NUM_OF_DELIMITERS = 2 ;
2733
2834static ngx_int_t ngx_http_set_encode_encrypted_session (ngx_http_request_t * r ,
2935 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,
4248static char * ngx_http_encrypted_session_expires (ngx_conf_t * cf ,
4349 ngx_command_t * cmd , void * conf );
4450
51+ static char * ngx_http_encrypted_iv_in_content (ngx_conf_t * cf ,
52+ ngx_command_t * cmd , void * conf );
4553
4654static ngx_int_t ngx_http_encrypted_session_init (ngx_conf_t * cf );
4755static 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);
5361static char * ngx_http_encrypted_session_merge_conf (ngx_conf_t * cf , void * parent ,
5462 void * child );
5563
56-
5764static ndk_set_var_t ngx_http_set_encode_encrypted_session_filter = {
5865 NDK_SET_VAR_VALUE ,
5966 (void * ) ngx_http_set_encode_encrypted_session ,
@@ -115,7 +122,14 @@ static ngx_command_t ngx_http_encrypted_session_commands[] = {
115122 0 ,
116123 & ngx_http_set_decode_encrypted_session_filter
117124 },
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+ },
119133 ngx_null_command
120134};
121135
@@ -151,14 +165,14 @@ ngx_module_t ngx_http_encrypted_session_module = {
151165};
152166
153167static 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 )
155169{
156170 ngx_http_variable_value_t * v ;
157171 ngx_str_t name_str ;
158172 name_str .data = name ;
159- name_str .len = strlen (( const char * ) name ) ;
173+ name_str .len = name_len ;
160174
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 );
162176 v = ngx_http_get_variable (r , & name_str , key );
163177
164178 if (v -> not_found ) {
@@ -171,6 +185,37 @@ static ngx_str_t ngx_http_get_variable_by_name(ngx_http_request_t *r,
171185 return var_value ;
172186}
173187
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+
174219static ngx_int_t
175220ngx_http_set_encode_encrypted_session (ngx_http_request_t * r ,
176221 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,
196241 ngx_log_debug1 (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
197242 "encrypted_session: expires=%T" , conf -> expires );
198243
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+ }
201253
202254 rc = ngx_http_encrypted_session_aes_mac_encrypt (emcf , r -> pool ,
203255 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 );
205257
206258 if (rc != NGX_OK ) {
207259 dst = NULL ;
@@ -211,6 +263,29 @@ ngx_http_set_encode_encrypted_session(ngx_http_request_t *r,
211263 "encrypted_session: failed to encrypt" );
212264 }
213265
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+
214289 res -> data = dst ;
215290 res -> len = len ;
216291
@@ -240,12 +315,55 @@ ngx_http_set_decode_encrypted_session(ngx_http_request_t *r,
240315 return NGX_ERROR ;
241316 }
242317
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+ }
245363
246364 rc = ngx_http_encrypted_session_aes_mac_decrypt (emcf , r -> pool ,
247365 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 );
249367
250368 if (rc != NGX_OK ) {
251369 dst = NULL ;
@@ -273,7 +391,9 @@ ngx_http_encrypted_session_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
273391 value = cf -> args -> elts ;
274392
275393 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 );
277397 return NGX_CONF_OK ;
278398 }
279399
@@ -287,6 +407,7 @@ ngx_http_encrypted_session_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
287407 }
288408
289409 llcf -> key = value [1 ].data ;
410+ llcf -> key_len = value [1 ].len ;
290411
291412 return NGX_CONF_OK ;
292413}
@@ -307,6 +428,7 @@ ngx_http_encrypted_session_iv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
307428
308429 if (value [1 ].len > 1 && value [1 ].data [0 ] == '$' ) {
309430 llcf -> iv = & (value [1 ].data [1 ]);
431+ llcf -> iv_len = value [1 ].len - 1 ;
310432 return NGX_CONF_OK ;
311433 }
312434
@@ -320,6 +442,7 @@ ngx_http_encrypted_session_iv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
320442 }
321443
322444 llcf -> iv = ngx_pcalloc (cf -> pool , ngx_http_encrypted_session_iv_length );
445+ llcf -> iv_len = ngx_http_encrypted_session_iv_length ;
323446
324447 if (llcf -> iv == NULL ) {
325448 return NGX_CONF_ERROR ;
@@ -360,6 +483,13 @@ ngx_http_encrypted_session_expires(ngx_conf_t *cf, ngx_command_t *cmd,
360483 return NGX_CONF_OK ;
361484}
362485
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+ }
363493
364494static void
365495ngx_http_encrypted_session_free_cipher_ctx (void * data )
@@ -435,8 +565,11 @@ ngx_http_encrypted_session_create_conf(ngx_conf_t *cf)
435565 }
436566
437567 conf -> key = NGX_CONF_UNSET_PTR ;
568+ conf -> key_len = NGX_CONF_UNSET ;
438569 conf -> iv = NGX_CONF_UNSET_PTR ;
570+ conf -> iv_len = NGX_CONF_UNSET ;
439571 conf -> expires = NGX_CONF_UNSET ;
572+ conf -> iv_in_content = NGX_CONF_UNSET ;
440573
441574 return conf ;
442575}
@@ -449,12 +582,17 @@ ngx_http_encrypted_session_merge_conf(ngx_conf_t *cf, void *parent, void *child)
449582 ngx_http_encrypted_session_conf_t * conf = child ;
450583
451584 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 );
452587
453588 ngx_conf_merge_ptr_value (conf -> iv , prev -> iv ,
454589 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 );
455592
456593 ngx_conf_merge_value (conf -> expires , prev -> expires ,
457594 ngx_http_encrypted_session_default_expires );
595+ ngx_conf_merge_value (conf -> iv_in_content , prev -> iv_in_content , 0 );
458596
459597 return NGX_CONF_OK ;
460598}
0 commit comments