@@ -21,12 +21,13 @@ const size_t IV_LENGTH = 16;
2121const size_t SIGNATURE_LENGTH = 32 ;
2222
2323typedef struct {
24- u_char * key ;
25- size_t key_len ;
26- u_char * iv ;
27- size_t iv_len ;
28- time_t expires ;
29- ngx_flag_t iv_in_content ;
24+ u_char * key ;
25+ size_t key_len ;
26+ u_char * iv ;
27+ size_t iv_len ;
28+ time_t expires ;
29+ ngx_flag_t iv_in_content ;
30+ enum ngx_http_encrypted_session_mode encryption_mode ;
3031} ngx_http_encrypted_session_conf_t ;
3132
3233static ngx_int_t ngx_http_set_encode_encrypted_session (ngx_http_request_t * r ,
@@ -43,6 +44,9 @@ static char *ngx_http_encrypted_session_key(ngx_conf_t *cf, ngx_command_t *cmd,
4344static char * ngx_http_encrypted_session_iv (ngx_conf_t * cf , ngx_command_t * cmd ,
4445 void * conf );
4546
47+ static char * ngx_http_encrypted_session_mode_set (ngx_conf_t * cf ,
48+ ngx_command_t * cmd , void * conf );
49+
4650static char * ngx_http_encrypted_session_expires (ngx_conf_t * cf ,
4751 ngx_command_t * cmd , void * conf );
4852
@@ -93,6 +97,15 @@ static ngx_command_t ngx_http_encrypted_session_commands[] = {
9397 0 ,
9498 NULL
9599 },
100+ {
101+ ngx_string ("encrypted_session_mode" ),
102+ NGX_HTTP_MAIN_CONF |NGX_HTTP_SRV_CONF |NGX_HTTP_SIF_CONF
103+ |NGX_HTTP_LOC_CONF |NGX_HTTP_LIF_CONF |NGX_CONF_TAKE1 ,
104+ ngx_http_encrypted_session_mode_set ,
105+ NGX_HTTP_LOC_CONF_OFFSET ,
106+ 0 ,
107+ NULL
108+ },
96109 {
97110 ngx_string ("encrypted_session_expires" ),
98111 NGX_HTTP_MAIN_CONF |NGX_HTTP_SRV_CONF |NGX_HTTP_SIF_CONF
@@ -216,12 +229,28 @@ ngx_http_session_encrypted_compute_hmac(ngx_http_request_t *r,
216229
217230static ngx_str_t *
218231ngx_http_session_generate_signature (ngx_http_request_t * r ,
219- ngx_str_t * iv , ngx_str_t * key , ngx_str_t * content )
232+ ngx_str_t * iv , ngx_str_t * key , ngx_str_t * content ,
233+ ngx_str_t * tag , enum ngx_http_encrypted_session_mode mode )
220234{
221235 size_t signature_content_len = iv -> len + content -> len ;
236+ if (mode == ngx_http_encrypted_session_mode_gcm )
237+ {
238+ signature_content_len += tag -> len ;
239+ }
240+
222241 u_char * signature_content = (u_char * )ngx_pcalloc (r -> pool , signature_content_len + 1 );
223242 ngx_memcpy (signature_content , iv -> data , iv -> len );
224- ngx_memcpy (signature_content + iv -> len , content -> data , content -> len );
243+
244+ if (mode == ngx_http_encrypted_session_mode_gcm )
245+ {
246+ ngx_memcpy (signature_content + iv -> len , tag -> data , tag -> len );
247+ ngx_memcpy (signature_content + iv -> len + tag -> len ,
248+ content -> data , content -> len );
249+ }
250+ else
251+ {
252+ ngx_memcpy (signature_content + iv -> len , content -> data , content -> len );
253+ }
225254
226255 ngx_log_error (NGX_LOG_DEBUG , r -> connection -> log , 0 ,
227256 "encrypted_session: signature content len=%d" ,
@@ -245,15 +274,32 @@ ngx_http_session_generate_signature(ngx_http_request_t *r,
245274
246275static ngx_str_t *
247276ngx_http_session_generate_response_with_iv (ngx_http_request_t * r ,
248- ngx_str_t * iv , ngx_str_t * key , ngx_str_t * content )
277+ ngx_str_t * iv , ngx_str_t * key , ngx_str_t * content ,
278+ ngx_str_t * tag , enum ngx_http_encrypted_session_mode mode )
249279{
250- ngx_str_t * signature = ngx_http_session_generate_signature (r , iv , key , content );
280+ ngx_str_t * signature = ngx_http_session_generate_signature (r , iv , key ,
281+ content , tag , mode );
282+
283+ size_t new_len = iv -> len + signature -> len + content -> len ;
284+
285+ if (mode == ngx_http_encrypted_session_mode_gcm )
286+ {
287+ new_len += tag -> len ;
288+ }
251289
252- size_t new_len = iv -> len + content -> len + signature -> len ;
253290 u_char * new_content = (u_char * )ngx_pcalloc (r -> pool , new_len + 1 );
254291 ngx_memcpy (new_content , iv -> data , iv -> len );
255292 ngx_memcpy (new_content + iv -> len , signature -> data , signature -> len );
256- ngx_memcpy (new_content + iv -> len + signature -> len , content -> data , content -> len );
293+
294+ if (mode == ngx_http_encrypted_session_mode_gcm )
295+ {
296+ ngx_memcpy (new_content + iv -> len + signature -> len , tag -> data , tag -> len );
297+ ngx_memcpy (new_content + iv -> len + signature -> len + tag -> len , content -> data , content -> len );
298+ }
299+ else
300+ {
301+ ngx_memcpy (new_content + iv -> len + signature -> len , content -> data , content -> len );
302+ }
257303
258304 ngx_log_error (NGX_LOG_DEBUG , r -> connection -> log , 0 ,
259305 "encrypted_session: encrypted data len=%d" , content -> len );
@@ -314,9 +360,11 @@ ngx_http_set_encode_encrypted_session(ngx_http_request_t *r,
314360 content .data );
315361 }
316362
363+ u_char * tag ;
317364 rc = ngx_http_encrypted_session_aes_mac_encrypt (emcf , r -> pool ,
318365 r -> connection -> log , iv .data , iv .len , key .data , key .len ,
319- content .data , content .len , (ngx_uint_t ) conf -> expires , & dst , & len );
366+ content .data , content .len ,
367+ (ngx_uint_t ) conf -> expires , conf -> encryption_mode , & dst , & len , & tag );
320368
321369 if (rc != NGX_OK ) {
322370 res -> data = NULL ;
@@ -332,8 +380,12 @@ ngx_http_set_encode_encrypted_session(ngx_http_request_t *r,
332380 encrypted_content .len = len ;
333381 encrypted_content .data = dst ;
334382
383+ ngx_str_t tag_content ;
384+ tag_content .len = ngx_http_encrypted_session_aes_tag_size ;
385+ tag_content .data = tag ;
386+
335387 ngx_str_t * result = ngx_http_session_generate_response_with_iv (r , & iv ,
336- & key , & encrypted_content );
388+ & key , & encrypted_content , & tag_content , conf -> encryption_mode );
337389 res -> data = result -> data ;
338390 res -> len = result -> len ;
339391
@@ -377,6 +429,8 @@ ngx_http_set_decode_encrypted_session(ngx_http_request_t *r,
377429
378430 ngx_str_t iv ;
379431 ngx_str_t content ;
432+ ngx_str_t tag ;
433+
380434 content .data = v -> data ;
381435 content .len = v -> len ;
382436
@@ -405,10 +459,28 @@ ngx_http_set_decode_encrypted_session(ngx_http_request_t *r,
405459 u_char * signature = (u_char * )ngx_pcalloc (r -> pool , SIGNATURE_LENGTH + 1 );
406460 ngx_memcpy (signature , content .data + iv .len , SIGNATURE_LENGTH );
407461
462+ if (conf -> encryption_mode == ngx_http_encrypted_session_mode_gcm )
463+ {
464+ tag .len = ngx_http_encrypted_session_aes_tag_size ;
465+ tag .data = (u_char * )ngx_pcalloc (r -> pool , tag .len );
466+ ngx_memcpy (tag .data , content .data + iv .len + SIGNATURE_LENGTH , tag .len );
467+ }
468+
408469 ngx_str_t encrypted_content ;
409- encrypted_content .len = content .len - iv .len - SIGNATURE_LENGTH ;
410- encrypted_content .data = (u_char * )ngx_pcalloc (r -> pool , encrypted_content .len + 1 );
411- ngx_memcpy (encrypted_content .data , v -> data + iv .len + SIGNATURE_LENGTH , encrypted_content .len );
470+ if (conf -> encryption_mode == ngx_http_encrypted_session_mode_gcm )
471+ {
472+ encrypted_content .len = content .len - iv .len - SIGNATURE_LENGTH - tag .len ;
473+ encrypted_content .data = (u_char * )ngx_pcalloc (r -> pool , encrypted_content .len + 1 );
474+ ngx_memcpy (encrypted_content .data ,
475+ v -> data + iv .len + SIGNATURE_LENGTH + tag .len ,
476+ encrypted_content .len );
477+ }
478+ else
479+ {
480+ encrypted_content .len = content .len - iv .len - SIGNATURE_LENGTH ;
481+ encrypted_content .data = (u_char * )ngx_pcalloc (r -> pool , encrypted_content .len + 1 );
482+ ngx_memcpy (encrypted_content .data , v -> data + iv .len + SIGNATURE_LENGTH , encrypted_content .len );
483+ }
412484
413485 content .data = encrypted_content .data ;
414486 content .len = encrypted_content .len ;
@@ -417,7 +489,7 @@ ngx_http_set_decode_encrypted_session(ngx_http_request_t *r,
417489 "encrypted_session: data len=%d" , content .len );
418490
419491 ngx_str_t * computed_signature = ngx_http_session_generate_signature (r ,
420- & iv , & key , & encrypted_content );
492+ & iv , & key , & encrypted_content , & tag , conf -> encryption_mode );
421493 if (SIGNATURE_LENGTH != computed_signature -> len ||
422494 ngx_memcmp (computed_signature -> data , signature , SIGNATURE_LENGTH ) != 0 )
423495 {
@@ -432,7 +504,8 @@ ngx_http_set_decode_encrypted_session(ngx_http_request_t *r,
432504
433505 rc = ngx_http_encrypted_session_aes_mac_decrypt (emcf , r -> pool ,
434506 r -> connection -> log , iv .data , iv .len , key .data , key .len ,
435- content .data , content .len , & dst , & len );
507+ content .data , content .len , conf -> encryption_mode , tag .data ,
508+ & dst , & len );
436509
437510 if (rc != NGX_OK ) {
438511 ngx_log_error (NGX_LOG_WARN , r -> connection -> log , 0 ,
@@ -542,6 +615,24 @@ ngx_http_encrypted_session_iv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
542615 return NGX_CONF_OK ;
543616}
544617
618+ static char *
619+ ngx_http_encrypted_session_mode_set (ngx_conf_t * cf ,
620+ ngx_command_t * cmd , void * conf )
621+ {
622+ ngx_str_t * value ;
623+ ngx_http_encrypted_session_conf_t * llcf = conf ;
624+
625+ value = cf -> args -> elts ;
626+ if (value [1 ].len == 3 && strncmp ("cbc" , (char * )value [1 ].data , 3 ) == 0 ) {
627+ llcf -> encryption_mode = ngx_http_encrypted_session_mode_cbc ;
628+ }
629+ else if (value [1 ].len == 3 && strncmp ("gcm" , (char * )value [1 ].data , 3 ) == 0 ) {
630+ llcf -> encryption_mode = ngx_http_encrypted_session_mode_gcm ;
631+ }
632+
633+ return NGX_CONF_OK ;
634+ }
635+
545636
546637static char *
547638ngx_http_encrypted_session_expires (ngx_conf_t * cf , ngx_command_t * cmd ,
@@ -654,6 +745,7 @@ ngx_http_encrypted_session_create_conf(ngx_conf_t *cf)
654745 conf -> iv_len = NGX_CONF_UNSET ;
655746 conf -> expires = NGX_CONF_UNSET ;
656747 conf -> iv_in_content = NGX_CONF_UNSET ;
748+ conf -> encryption_mode = ngx_http_encrypted_session_mode_unknown ;
657749
658750 return conf ;
659751}
@@ -678,5 +770,13 @@ ngx_http_encrypted_session_merge_conf(ngx_conf_t *cf, void *parent, void *child)
678770 ngx_http_encrypted_session_default_expires );
679771 ngx_conf_merge_value (conf -> iv_in_content , prev -> iv_in_content , 0 );
680772
773+ if (conf -> encryption_mode == ngx_http_encrypted_session_mode_unknown ) {
774+ conf -> encryption_mode = prev -> encryption_mode ;
775+ }
776+
777+ if (conf -> encryption_mode == ngx_http_encrypted_session_mode_unknown ) {
778+ conf -> encryption_mode = ngx_http_encrypted_session_mode_cbc ;
779+ }
780+
681781 return NGX_CONF_OK ;
682782}
0 commit comments