@@ -300,9 +300,23 @@ void SecureContext::Initialize(Environment* env, Handle<Object> target) {
300300 env->SetProtoMethod (t, " getTicketKeys" , SecureContext::GetTicketKeys);
301301 env->SetProtoMethod (t, " setTicketKeys" , SecureContext::SetTicketKeys);
302302 env->SetProtoMethod (t, " setFreeListLength" , SecureContext::SetFreeListLength);
303+ env->SetProtoMethod (t,
304+ " enableTicketKeyCallback" ,
305+ SecureContext::EnableTicketKeyCallback);
303306 env->SetProtoMethod (t, " getCertificate" , SecureContext::GetCertificate<true >);
304307 env->SetProtoMethod (t, " getIssuer" , SecureContext::GetCertificate<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