| Index: runtime/bin/secure_socket.cc
|
| diff --git a/runtime/bin/secure_socket.cc b/runtime/bin/secure_socket.cc
|
| index b1be87c5a65b043f7e791af240e70a03619535ad..f8dd77625991447ba16912c08f065a612915cb49 100644
|
| --- a/runtime/bin/secure_socket.cc
|
| +++ b/runtime/bin/secure_socket.cc
|
| @@ -376,16 +376,17 @@ void CheckStatus(int status,
|
| }
|
|
|
|
|
| -void FUNCTION_NAME(SecurityContext_UsePrivateKey)(Dart_NativeArguments args) {
|
| +void FUNCTION_NAME(SecurityContext_UsePrivateKeyAsBytes)(
|
| + Dart_NativeArguments args) {
|
| SSL_CTX* context = GetSecurityContext(args);
|
| - Dart_Handle filename_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
|
| - const char* filename = NULL;
|
| - if (Dart_IsString(filename_object)) {
|
| - ThrowIfError(Dart_StringToCString(filename_object, &filename));
|
| - } else {
|
| +
|
| + Dart_Handle key_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
|
| + if (!Dart_IsTypedData(key_object) && !Dart_IsList(key_object)) {
|
| Dart_ThrowException(DartUtils::NewDartArgumentError(
|
| - "File argument to SecurityContext.usePrivateKey is not a String"));
|
| + "keyBytes argument to SecurityContext.usePrivateKey "
|
| + "is not a List<int>"));
|
| }
|
| +
|
| Dart_Handle password_object = ThrowIfError(Dart_GetNativeArgument(args, 2));
|
| const char* password = NULL;
|
| if (Dart_IsString(password_object)) {
|
| @@ -402,16 +403,45 @@ void FUNCTION_NAME(SecurityContext_UsePrivateKey)(Dart_NativeArguments args) {
|
| "SecurityContext.usePrivateKey password is not a String or null"));
|
| }
|
|
|
| - SSL_CTX_set_default_passwd_cb(context, PasswordCallback);
|
| - SSL_CTX_set_default_passwd_cb_userdata(context, const_cast<char*>(password));
|
| - int status = SSL_CTX_use_PrivateKey_file(context,
|
| - filename,
|
| - SSL_FILETYPE_PEM);
|
| + uint8_t* key_bytes = NULL;
|
| + intptr_t key_bytes_len = 0;
|
| + bool is_typed_data = false;
|
| + if (Dart_IsTypedData(key_object)) {
|
| + is_typed_data = true;
|
| + Dart_TypedData_Type typ;
|
| + ThrowIfError(Dart_TypedDataAcquireData(
|
| + key_object,
|
| + &typ,
|
| + reinterpret_cast<void**>(&key_bytes),
|
| + &key_bytes_len));
|
| + } else {
|
| + ASSERT(Dart_IsList(key_object));
|
| + ThrowIfError(Dart_ListLength(key_object, &key_bytes_len));
|
| + key_bytes = new uint8_t[key_bytes_len];
|
| + Dart_Handle err =
|
| + Dart_ListGetAsBytes(key_object, 0, key_bytes, key_bytes_len);
|
| + if (Dart_IsError(err)) {
|
| + delete[] key_bytes;
|
| + Dart_PropagateError(err);
|
| + }
|
| + }
|
| + ASSERT(key_bytes != NULL);
|
| +
|
| + BIO* bio = BIO_new_mem_buf(key_bytes, key_bytes_len);
|
| + EVP_PKEY *key = PEM_read_bio_PrivateKey(
|
| + bio, NULL, PasswordCallback, const_cast<char*>(password));
|
| + int status = SSL_CTX_use_PrivateKey(context, key);
|
| + BIO_free(bio);
|
| + if (is_typed_data) {
|
| + ThrowIfError(Dart_TypedDataReleaseData(key_object));
|
| + } else {
|
| + delete[] key_bytes;
|
| + }
|
| +
|
| // TODO(24184): Handle different expected errors here - file missing,
|
| // incorrect password, file not a PEM, and throw exceptions.
|
| // CheckStatus should also throw an exception in uncaught cases.
|
| CheckStatus(status, "TlsException", "Failure in usePrivateKey");
|
| - SSL_CTX_set_default_passwd_cb_userdata(context, NULL);
|
| }
|
|
|
|
|
|
|