@@ -300,9 +300,23 @@ void SecureContext::Initialize(Environment* env, Handle<Object> target) {
300300  env->SetProtoMethod (t, " getTicketKeys" 
301301  env->SetProtoMethod (t, " setTicketKeys" 
302302  env->SetProtoMethod (t, " setFreeListLength" 
303+   env->SetProtoMethod (t,
304+                       " enableTicketKeyCallback" 
305+                       SecureContext::EnableTicketKeyCallback);
303306  env->SetProtoMethod (t, " getCertificate" true >);
304307  env->SetProtoMethod (t, " getIssuer" false >);
305308
309+   t->Set (FIXED_ONE_BYTE_STRING (env->isolate (), " kTicketKeyReturnIndex" 
310+          Integer::NewFromUnsigned (env->isolate (), kTicketKeyReturnIndex ));
311+   t->Set (FIXED_ONE_BYTE_STRING (env->isolate (), " kTicketKeyHMACIndex" 
312+          Integer::NewFromUnsigned (env->isolate (), kTicketKeyHMACIndex ));
313+   t->Set (FIXED_ONE_BYTE_STRING (env->isolate (), " kTicketKeyAESIndex" 
314+          Integer::NewFromUnsigned (env->isolate (), kTicketKeyAESIndex ));
315+   t->Set (FIXED_ONE_BYTE_STRING (env->isolate (), " kTicketKeyNameIndex" 
316+          Integer::NewFromUnsigned (env->isolate (), kTicketKeyNameIndex ));
317+   t->Set (FIXED_ONE_BYTE_STRING (env->isolate (), " kTicketKeyIVIndex" 
318+          Integer::NewFromUnsigned (env->isolate (), kTicketKeyIVIndex ));
319+ 
306320  t->PrototypeTemplate ()->SetAccessor (
307321      FIXED_ONE_BYTE_STRING (env->isolate (), " _external" 
308322      CtxGetter,
@@ -378,6 +392,7 @@ void SecureContext::Init(const FunctionCallbackInfo<Value>& args) {
378392  }
379393
380394  sc->ctx_  = SSL_CTX_new (method);
395+   SSL_CTX_set_app_data (sc->ctx_ , sc);
381396
382397  //  Disable SSLv2 in the case when method == SSLv23_method() and the
383398  //  cipher list contains SSLv2 ciphers (not the default, should be rare.)
@@ -982,6 +997,95 @@ void SecureContext::SetFreeListLength(const FunctionCallbackInfo<Value>& args) {
982997}
983998
984999
1000+ void  SecureContext::EnableTicketKeyCallback (
1001+     const  FunctionCallbackInfo<Value>& args) {
1002+   SecureContext* wrap = Unwrap<SecureContext>(args.Holder ());
1003+ 
1004+   SSL_CTX_set_tlsext_ticket_key_cb (wrap->ctx_ , TicketKeyCallback);
1005+ }
1006+ 
1007+ 
1008+ int  SecureContext::TicketKeyCallback (SSL* ssl,
1009+                                      unsigned  char * name,
1010+                                      unsigned  char * iv,
1011+                                      EVP_CIPHER_CTX* ectx,
1012+                                      HMAC_CTX* hctx,
1013+                                      int  enc) {
1014+   static  const  int  kTicketPartSize  = 16 ;
1015+ 
1016+   SecureContext* sc = static_cast <SecureContext*>(
1017+       SSL_CTX_get_app_data (ssl->ctx ));
1018+ 
1019+   Environment* env = sc->env ();
1020+   HandleScope handle_scope (env->isolate ());
1021+   Context::Scope context_scope (env->context ());
1022+ 
1023+   Local<Value> argv[] = {
1024+     Buffer::New (env,
1025+                 reinterpret_cast <char *>(name),
1026+                 kTicketPartSize ).ToLocalChecked (),
1027+     Buffer::New (env,
1028+                 reinterpret_cast <char *>(iv),
1029+                 kTicketPartSize ).ToLocalChecked (),
1030+     Boolean::New (env->isolate (), enc != 0 )
1031+   };
1032+   Local<Value> ret = node::MakeCallback (env,
1033+                                         sc->object (),
1034+                                         env->ticketkeycallback_string (),
1035+                                         ARRAY_SIZE (argv),
1036+                                         argv);
1037+   Local<Array> arr = ret.As <Array>();
1038+ 
1039+   int  r = arr->Get (kTicketKeyReturnIndex )->Int32Value ();
1040+   if  (r < 0 )
1041+     return  r;
1042+ 
1043+   Local<Value> hmac = arr->Get (kTicketKeyHMACIndex );
1044+   Local<Value> aes = arr->Get (kTicketKeyAESIndex );
1045+   if  (Buffer::Length (aes) != kTicketPartSize )
1046+     return  -1 ;
1047+ 
1048+   if  (enc) {
1049+     Local<Value> name_val = arr->Get (kTicketKeyNameIndex );
1050+     Local<Value> iv_val = arr->Get (kTicketKeyIVIndex );
1051+ 
1052+     if  (Buffer::Length (name_val) != kTicketPartSize  ||
1053+         Buffer::Length (iv_val) != kTicketPartSize ) {
1054+       return  -1 ;
1055+     }
1056+ 
1057+     memcpy (name, Buffer::Data (name_val), kTicketPartSize );
1058+     memcpy (iv, Buffer::Data (iv_val), kTicketPartSize );
1059+   }
1060+ 
1061+   HMAC_Init_ex (hctx,
1062+                Buffer::Data (hmac),
1063+                Buffer::Length (hmac),
1064+                EVP_sha256 (),
1065+                nullptr );
1066+ 
1067+   const  unsigned  char * aes_key =
1068+       reinterpret_cast <unsigned  char *>(Buffer::Data (aes));
1069+   if  (enc) {
1070+     EVP_EncryptInit_ex (ectx,
1071+                        EVP_aes_128_cbc (),
1072+                        nullptr ,
1073+                        aes_key,
1074+                        iv);
1075+   } else  {
1076+     EVP_DecryptInit_ex (ectx,
1077+                        EVP_aes_128_cbc (),
1078+                        nullptr ,
1079+                        aes_key,
1080+                        iv);
1081+   }
1082+ 
1083+   return  r;
1084+ }
1085+ 
1086+ 
1087+ 
1088+ 
9851089void  SecureContext::CtxGetter (Local<String> property,
9861090                              const  PropertyCallbackInfo<Value>& info) {
9871091  HandleScope scope (info.GetIsolate ());
0 commit comments