react-native-quick-crypto 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +23 -6
  2. package/cpp/Cipher/MGLCipherHostObject.cpp +64 -48
  3. package/cpp/Cipher/MGLCipherKeys.cpp +1469 -0
  4. package/cpp/Cipher/MGLCipherKeys.h +124 -0
  5. package/cpp/Cipher/MGLCreateCipherInstaller.cpp +56 -53
  6. package/cpp/Cipher/MGLCreateCipherInstaller.h +5 -0
  7. package/cpp/Cipher/MGLCreateDecipherInstaller.cpp +56 -53
  8. package/cpp/Cipher/MGLGenerateKeyPairInstaller.cpp +107 -0
  9. package/cpp/Cipher/MGLGenerateKeyPairInstaller.h +32 -0
  10. package/cpp/Cipher/MGLGenerateKeyPairSyncInstaller.cpp +60 -0
  11. package/cpp/Cipher/MGLGenerateKeyPairSyncInstaller.h +35 -0
  12. package/cpp/Cipher/MGLPublicCipher.h +120 -0
  13. package/cpp/Cipher/MGLPublicCipherInstaller.h +113 -0
  14. package/cpp/Cipher/MGLRsa.cpp +188 -0
  15. package/cpp/Cipher/MGLRsa.h +61 -0
  16. package/cpp/JSIUtils/MGLJSIUtils.h +24 -0
  17. package/cpp/JSIUtils/MGLThreadAwareHostObject.h +1 -1
  18. package/cpp/MGLQuickCryptoHostObject.cpp +42 -3
  19. package/cpp/Utils/MGLUtils.cpp +156 -0
  20. package/cpp/Utils/MGLUtils.h +254 -0
  21. package/lib/commonjs/Cipher.js +307 -0
  22. package/lib/commonjs/Cipher.js.map +1 -1
  23. package/lib/commonjs/NativeQuickCrypto/Cipher.js +11 -0
  24. package/lib/commonjs/NativeQuickCrypto/Cipher.js.map +1 -1
  25. package/lib/commonjs/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -1
  26. package/lib/commonjs/QuickCrypto.js +8 -0
  27. package/lib/commonjs/QuickCrypto.js.map +1 -1
  28. package/lib/commonjs/Utils.js +82 -1
  29. package/lib/commonjs/Utils.js.map +1 -1
  30. package/lib/commonjs/constants.js +86 -0
  31. package/lib/commonjs/constants.js.map +1 -0
  32. package/lib/commonjs/index.js +5 -0
  33. package/lib/commonjs/index.js.map +1 -1
  34. package/lib/commonjs/keys.js +207 -0
  35. package/lib/commonjs/keys.js.map +1 -0
  36. package/lib/module/Cipher.js +296 -3
  37. package/lib/module/Cipher.js.map +1 -1
  38. package/lib/module/NativeQuickCrypto/Cipher.js +9 -1
  39. package/lib/module/NativeQuickCrypto/Cipher.js.map +1 -1
  40. package/lib/module/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -1
  41. package/lib/module/QuickCrypto.js +8 -1
  42. package/lib/module/QuickCrypto.js.map +1 -1
  43. package/lib/module/Utils.js +67 -1
  44. package/lib/module/Utils.js.map +1 -1
  45. package/lib/module/constants.js +79 -0
  46. package/lib/module/constants.js.map +1 -0
  47. package/lib/module/index.js +2 -0
  48. package/lib/module/index.js.map +1 -1
  49. package/lib/module/keys.js +193 -0
  50. package/lib/module/keys.js.map +1 -0
  51. package/lib/typescript/Cipher.d.ts +58 -1
  52. package/lib/typescript/NativeQuickCrypto/Cipher.d.ts +10 -0
  53. package/lib/typescript/NativeQuickCrypto/NativeQuickCrypto.d.ts +6 -1
  54. package/lib/typescript/QuickCrypto.d.ts +105 -1
  55. package/lib/typescript/Utils.d.ts +11 -0
  56. package/lib/typescript/constants.d.ts +75 -0
  57. package/lib/typescript/index.d.ts +2 -0
  58. package/lib/typescript/keys.d.ts +60 -0
  59. package/package.json +5 -5
  60. package/react-native-quick-crypto.podspec +1 -1
  61. package/src/.DS_Store +0 -0
  62. package/src/Cipher.ts +444 -3
  63. package/src/NativeQuickCrypto/Cipher.ts +44 -0
  64. package/src/NativeQuickCrypto/NativeQuickCrypto.ts +13 -1
  65. package/src/QuickCrypto.ts +12 -0
  66. package/src/Utils.ts +91 -0
  67. package/src/constants.ts +79 -0
  68. package/src/index.ts +4 -0
  69. package/src/keys.ts +297 -0
@@ -0,0 +1,1469 @@
1
+ //
2
+ // MGLCipherKeys.cpp
3
+ // react-native-fast-crypto
4
+ //
5
+ // Created by Oscar on 20.06.22.
6
+ //
7
+
8
+ #include "MGLCipherKeys.h"
9
+
10
+ #include <jsi/jsi.h>
11
+ #include <openssl/bio.h>
12
+
13
+ #include <algorithm>
14
+ #include <optional>
15
+ #include <utility>
16
+ #include <vector>
17
+
18
+ #include "MGLJSIUtils.h"
19
+ #include "MGLTypedArray.h"
20
+ #include "MGLUtils.h"
21
+ #ifdef ANDROID
22
+ #else
23
+ #include "logs.h"
24
+ #endif
25
+
26
+ namespace margelo {
27
+ namespace jsi = facebook::jsi;
28
+
29
+ void GetKeyFormatAndTypeFromJs(AsymmetricKeyEncodingConfig* config,
30
+ jsi::Runtime& runtime, const jsi::Value* args,
31
+ unsigned int* offset,
32
+ KeyEncodingContext context) {
33
+ // During key pair generation, it is possible not to specify a key encoding,
34
+ // which will lead to a key object being returned.
35
+ if (args[*offset].isUndefined()) {
36
+ // CHECK_EQ(context, kKeyContextGenerate);
37
+ // CHECK(args[*offset + 1].IsUndefined());
38
+ config->output_key_object_ = true;
39
+ } else {
40
+ config->output_key_object_ = false;
41
+
42
+ // TODO(osp) implement check
43
+ // CHECK(args[*offset]->IsInt32());
44
+ config->format_ = static_cast<PKFormatType>((int)args[*offset].getNumber());
45
+
46
+ if (args[*offset + 1].isNumber()) {
47
+ config->type_ = std::optional<PKEncodingType>(
48
+ static_cast<PKEncodingType>((int)args[*offset + 1].getNumber()));
49
+ } else {
50
+ // TODO(osp) implement checks
51
+ // CHECK(
52
+ // (context == kKeyContextInput &&
53
+ // config->format_ == kKeyFormatPEM) ||
54
+ // (context == kKeyContextGenerate &&
55
+ // config->format_ == kKeyFormatJWK));
56
+ // CHECK(args[*offset + 1]->IsNullOrUndefined());
57
+ config->type_ = std::nullopt;
58
+ }
59
+ }
60
+
61
+ *offset += 2;
62
+ }
63
+
64
+ ParseKeyResult TryParsePublicKey(
65
+ EVPKeyPointer* pkey, const BIOPointer& bp, const char* name,
66
+ const std::function<EVP_PKEY*(const unsigned char** p, long l)>& parse) {
67
+ unsigned char* der_data;
68
+ long der_len;
69
+
70
+ // This skips surrounding data and decodes PEM to DER.
71
+ if (PEM_bytes_read_bio(&der_data, &der_len, nullptr, name, bp.get(), nullptr,
72
+ nullptr) != 1) {
73
+ return ParseKeyResult::kParseKeyNotRecognized;
74
+ }
75
+
76
+ // OpenSSL might modify the pointer, so we need to make a copy before parsing.
77
+ const unsigned char* p = der_data;
78
+ pkey->reset(parse(&p, der_len));
79
+ OPENSSL_clear_free(der_data, der_len);
80
+
81
+ return *pkey ? ParseKeyResult::kParseKeyOk : ParseKeyResult::kParseKeyFailed;
82
+ }
83
+
84
+ ParseKeyResult ParsePublicKeyPEM(EVPKeyPointer* pkey, const char* key_pem,
85
+ int key_pem_len) {
86
+ BIOPointer bp(BIO_new_mem_buf(const_cast<char*>(key_pem), key_pem_len));
87
+ if (!bp) return ParseKeyResult::kParseKeyFailed;
88
+
89
+ ParseKeyResult ret;
90
+
91
+ // Try parsing as a SubjectPublicKeyInfo first.
92
+ ret = TryParsePublicKey(pkey, bp, "PUBLIC KEY",
93
+ [](const unsigned char** p, long l) {
94
+ return d2i_PUBKEY(nullptr, p, l);
95
+ });
96
+
97
+ if (ret != ParseKeyResult::kParseKeyNotRecognized) return ret;
98
+
99
+ // Maybe it is PKCS#1.
100
+ BIO_reset(bp.get());
101
+ ret = TryParsePublicKey(pkey, bp, "RSA PUBLIC KEY",
102
+ [](const unsigned char** p, long l) {
103
+ return d2i_PublicKey(EVP_PKEY_RSA, nullptr, p, l);
104
+ });
105
+ if (ret != ParseKeyResult::kParseKeyNotRecognized) return ret;
106
+
107
+ // X.509 fallback.
108
+ BIO_reset(bp.get());
109
+ return TryParsePublicKey(
110
+ pkey, bp, "CERTIFICATE", [](const unsigned char** p, long l) {
111
+ X509Pointer x509(d2i_X509(nullptr, p, l));
112
+ return x509 ? X509_get_pubkey(x509.get()) : nullptr;
113
+ });
114
+ }
115
+
116
+ ParseKeyResult ParsePublicKey(EVPKeyPointer* pkey,
117
+ const PublicKeyEncodingConfig& config,
118
+ const char* key, size_t key_len) {
119
+ if (config.format_ == kKeyFormatPEM) {
120
+ return ParsePublicKeyPEM(pkey, key, key_len);
121
+ } else {
122
+ // CHECK_EQ(config.format_, kKeyFormatDER);
123
+
124
+ const unsigned char* p = reinterpret_cast<const unsigned char*>(key);
125
+ if (config.type_.value() == kKeyEncodingPKCS1) {
126
+ pkey->reset(d2i_PublicKey(EVP_PKEY_RSA, nullptr, &p, key_len));
127
+ } else {
128
+ // CHECK_EQ(config.type_.ToChecked(), kKeyEncodingSPKI);
129
+ pkey->reset(d2i_PUBKEY(nullptr, &p, key_len));
130
+ }
131
+
132
+ return *pkey ? ParseKeyResult::kParseKeyOk
133
+ : ParseKeyResult::kParseKeyFailed;
134
+ }
135
+ }
136
+
137
+ bool IsASN1Sequence(const unsigned char* data, size_t size, size_t* data_offset,
138
+ size_t* data_size) {
139
+ if (size < 2 || data[0] != 0x30) return false;
140
+
141
+ if (data[1] & 0x80) {
142
+ // Long form.
143
+ size_t n_bytes = data[1] & ~0x80;
144
+ if (n_bytes + 2 > size || n_bytes > sizeof(size_t)) return false;
145
+ size_t length = 0;
146
+ for (size_t i = 0; i < n_bytes; i++) length = (length << 8) | data[i + 2];
147
+ *data_offset = 2 + n_bytes;
148
+ *data_size = std::min(size - 2 - n_bytes, length);
149
+ } else {
150
+ // Short form.
151
+ *data_offset = 2;
152
+ *data_size = std::min<size_t>(size - 2, data[1]);
153
+ }
154
+
155
+ return true;
156
+ }
157
+
158
+ bool IsRSAPrivateKey(const unsigned char* data, size_t size) {
159
+ // Both RSAPrivateKey and RSAPublicKey structures start with a SEQUENCE.
160
+ size_t offset, len;
161
+ if (!IsASN1Sequence(data, size, &offset, &len)) return false;
162
+
163
+ // An RSAPrivateKey sequence always starts with a single-byte integer whose
164
+ // value is either 0 or 1, whereas an RSAPublicKey starts with the modulus
165
+ // (which is the product of two primes and therefore at least 4), so we can
166
+ // decide the type of the structure based on the first three bytes of the
167
+ // sequence.
168
+ return len >= 3 && data[offset] == 2 && data[offset + 1] == 1 &&
169
+ !(data[offset + 2] & 0xfe);
170
+ }
171
+
172
+ bool IsEncryptedPrivateKeyInfo(const unsigned char* data, size_t size) {
173
+ // Both PrivateKeyInfo and EncryptedPrivateKeyInfo start with a SEQUENCE.
174
+ size_t offset, len;
175
+ if (!IsASN1Sequence(data, size, &offset, &len)) return false;
176
+
177
+ // A PrivateKeyInfo sequence always starts with an integer whereas an
178
+ // EncryptedPrivateKeyInfo starts with an AlgorithmIdentifier.
179
+ return len >= 1 && data[offset] != 2;
180
+ }
181
+
182
+ ParseKeyResult ParsePrivateKey(EVPKeyPointer* pkey,
183
+ const PrivateKeyEncodingConfig& config,
184
+ const char* key, size_t key_len) {
185
+ const ByteSource* passphrase = config.passphrase_.get();
186
+
187
+ if (config.format_ == kKeyFormatPEM) {
188
+ BIOPointer bio(BIO_new_mem_buf(key, (int)key_len));
189
+ if (!bio) {
190
+ return ParseKeyResult::kParseKeyFailed;
191
+ }
192
+
193
+ pkey->reset(PEM_read_bio_PrivateKey(bio.get(), nullptr, PasswordCallback,
194
+ &passphrase));
195
+ } else {
196
+ // CHECK_EQ(config.format_, kKeyFormatDER);
197
+
198
+ if (!config.type_.has_value()) {
199
+ // TODO(osp) need to implement end of the world exception
200
+ // throw new crashing exception
201
+ }
202
+
203
+ if (config.type_.value() == kKeyEncodingPKCS1) {
204
+ const unsigned char* p = reinterpret_cast<const unsigned char*>(key);
205
+ pkey->reset(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &p, key_len));
206
+ } else if (config.type_.value() == kKeyEncodingPKCS8) {
207
+ BIOPointer bio(BIO_new_mem_buf(key, (int)key_len));
208
+ if (!bio) return ParseKeyResult::kParseKeyFailed;
209
+
210
+ if (IsEncryptedPrivateKeyInfo(reinterpret_cast<const unsigned char*>(key),
211
+ key_len)) {
212
+ pkey->reset(d2i_PKCS8PrivateKey_bio(bio.get(), nullptr,
213
+ PasswordCallback, &passphrase));
214
+ } else {
215
+ PKCS8Pointer p8inf(d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), nullptr));
216
+ if (p8inf) pkey->reset(EVP_PKCS82PKEY(p8inf.get()));
217
+ }
218
+ } else {
219
+ // CHECK_EQ(config.type_.ToChecked(), kKeyEncodingSEC1);
220
+ const unsigned char* p = reinterpret_cast<const unsigned char*>(key);
221
+ pkey->reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &p, key_len));
222
+ }
223
+ }
224
+
225
+ // OpenSSL can fail to parse the key but still return a non-null pointer.
226
+ unsigned long err = ERR_peek_error(); // NOLINT(runtime/int)
227
+ auto reason = ERR_GET_REASON(err);
228
+ // Per OpenSSL documentation PEM_R_NO_START_LINE signals all PEM certs have
229
+ // been consumed and is a harmless error
230
+ if (reason == PEM_R_NO_START_LINE && *pkey) {
231
+ return ParseKeyResult::kParseKeyOk;
232
+ }
233
+
234
+ if (err != 0) pkey->reset();
235
+
236
+ if (*pkey) {
237
+ return ParseKeyResult::kParseKeyOk;
238
+ }
239
+
240
+ if (ERR_GET_LIB(err) == ERR_LIB_PEM) {
241
+ if (reason == PEM_R_BAD_PASSWORD_READ && config.passphrase_.IsEmpty()) {
242
+ return ParseKeyResult::kParseKeyNeedPassphrase;
243
+ }
244
+ }
245
+ return ParseKeyResult::kParseKeyFailed;
246
+ }
247
+
248
+ std::optional<StringOrBuffer> BIOToStringOrBuffer(BIO* bio,
249
+ PKFormatType format) {
250
+ BUF_MEM* bptr;
251
+ BIO_get_mem_ptr(bio, &bptr);
252
+ if (format == kKeyFormatPEM) {
253
+ // PEM is an ASCII format, so we will return it as a string.
254
+ return StringOrBuffer{
255
+ .isString = true,
256
+ .stringValue = std::string(bptr->data, bptr->length),
257
+ };
258
+ } else {
259
+ // CHECK_EQ(format, kKeyFormatDER);
260
+ // DER is binary, return it as a buffer.
261
+ std::vector<unsigned char> vec(bptr->data, bptr->data + bptr->length);
262
+ return StringOrBuffer{
263
+ .isString = false,
264
+ .vectorValue = vec,
265
+ };
266
+ }
267
+ }
268
+
269
+ std::optional<StringOrBuffer> WritePrivateKey(
270
+ jsi::Runtime& runtime, EVP_PKEY* pkey,
271
+ const PrivateKeyEncodingConfig& config) {
272
+ BIOPointer bio(BIO_new(BIO_s_mem()));
273
+ // CHECK(bio);
274
+
275
+ // If an empty string was passed as the passphrase, the ByteSource might
276
+ // contain a null pointer, which OpenSSL will ignore, causing it to invoke its
277
+ // default passphrase callback, which would block the thread until the user
278
+ // manually enters a passphrase. We could supply our own passphrase callback
279
+ // to handle this special case, but it is easier to avoid passing a null
280
+ // pointer to OpenSSL.
281
+ char* pass = nullptr;
282
+ size_t pass_len = 0;
283
+ if (!config.passphrase_.IsEmpty()) {
284
+ pass = const_cast<char*>(config.passphrase_->data<char>());
285
+ pass_len = config.passphrase_->size();
286
+ if (pass == nullptr) {
287
+ // OpenSSL will not actually dereference this pointer, so it can be any
288
+ // non-null pointer. We cannot assert that directly, which is why we
289
+ // intentionally use a pointer that will likely cause a segmentation fault
290
+ // when dereferenced.
291
+ // CHECK_EQ(pass_len, 0);
292
+ pass = reinterpret_cast<char*>(-1);
293
+ // CHECK_NE(pass, nullptr);
294
+ }
295
+ }
296
+
297
+ bool err;
298
+
299
+ PKEncodingType encoding_type = config.type_.value();
300
+ if (encoding_type == kKeyEncodingPKCS1) {
301
+ // PKCS#1 is only permitted for RSA keys.
302
+ // CHECK_EQ(EVP_PKEY_id(pkey), EVP_PKEY_RSA);
303
+
304
+ RSAPointer rsa(EVP_PKEY_get1_RSA(pkey));
305
+ if (config.format_ == kKeyFormatPEM) {
306
+ // Encode PKCS#1 as PEM.
307
+ err = PEM_write_bio_RSAPrivateKey(bio.get(), rsa.get(), config.cipher_,
308
+ reinterpret_cast<unsigned char*>(pass),
309
+ pass_len, nullptr, nullptr) != 1;
310
+ } else {
311
+ // Encode PKCS#1 as DER. This does not permit encryption.
312
+ // CHECK_EQ(config.format_, kKeyFormatDER);
313
+ // CHECK_NULL(config.cipher_);
314
+ err = i2d_RSAPrivateKey_bio(bio.get(), rsa.get()) != 1;
315
+ }
316
+ } else if (encoding_type == kKeyEncodingPKCS8) {
317
+ if (config.format_ == kKeyFormatPEM) {
318
+ // Encode PKCS#8 as PEM.
319
+ err = PEM_write_bio_PKCS8PrivateKey(bio.get(), pkey, config.cipher_, pass,
320
+ pass_len, nullptr, nullptr) != 1;
321
+ } else {
322
+ // Encode PKCS#8 as DER.
323
+ // CHECK_EQ(config.format_, kKeyFormatDER);
324
+ err = i2d_PKCS8PrivateKey_bio(bio.get(), pkey, config.cipher_, pass,
325
+ pass_len, nullptr, nullptr) != 1;
326
+ }
327
+ } else {
328
+ // CHECK_EQ(encoding_type, kKeyEncodingSEC1);
329
+
330
+ // SEC1 is only permitted for EC keys.
331
+ // CHECK_EQ(EVP_PKEY_id(pkey), EVP_PKEY_EC);
332
+
333
+ // ECKeyPointer ec_key(EVP_PKEY_get1_EC_KEY(pkey));
334
+ // if (config.format_ == kKeyFormatPEM) {
335
+ // // Encode SEC1 as PEM.
336
+ // err = PEM_write_bio_ECPrivateKey(
337
+ // bio.get(), ec_key.get(),
338
+ // config.cipher_,
339
+ // reinterpret_cast<unsigned
340
+ // char*>(pass), pass_len, nullptr,
341
+ // nullptr) != 1;
342
+ // } else {
343
+ // // Encode SEC1 as DER. This does not permit encryption.
344
+ // CHECK_EQ(config.format_, kKeyFormatDER);
345
+ // CHECK_NULL(config.cipher_);
346
+ // err = i2d_ECPrivateKey_bio(bio.get(), ec_key.get()) != 1;
347
+ // }
348
+ }
349
+
350
+ if (err) {
351
+ jsi::detail::throwJSError(runtime, "Failed to encode private key");
352
+ return {};
353
+ }
354
+
355
+ return BIOToStringOrBuffer(bio.get(), config.format_);
356
+ }
357
+
358
+ bool WritePublicKeyInner(EVP_PKEY* pkey, const BIOPointer& bio,
359
+ const PublicKeyEncodingConfig& config) {
360
+ if (config.type_.value() == kKeyEncodingPKCS1) {
361
+ // PKCS#1 is only valid for RSA keys.
362
+ // CHECK_EQ(EVP_PKEY_id(pkey), EVP_PKEY_RSA);
363
+ RSAPointer rsa(EVP_PKEY_get1_RSA(pkey));
364
+ if (config.format_ == kKeyFormatPEM) {
365
+ // Encode PKCS#1 as PEM.
366
+ return PEM_write_bio_RSAPublicKey(bio.get(), rsa.get()) == 1;
367
+ } else {
368
+ // Encode PKCS#1 as DER.
369
+ // CHECK_EQ(config.format_, kKeyFormatDER);
370
+ return i2d_RSAPublicKey_bio(bio.get(), rsa.get()) == 1;
371
+ }
372
+ } else {
373
+ // CHECK_EQ(config.type_.ToChecked(), kKeyEncodingSPKI);
374
+ if (config.format_ == kKeyFormatPEM) {
375
+ // Encode SPKI as PEM.
376
+ return PEM_write_bio_PUBKEY(bio.get(), pkey) == 1;
377
+ } else {
378
+ // Encode SPKI as DER.
379
+ // CHECK_EQ(config.format_, kKeyFormatDER);
380
+ return i2d_PUBKEY_bio(bio.get(), pkey) == 1;
381
+ }
382
+ }
383
+ }
384
+
385
+ std::optional<StringOrBuffer> WritePublicKey(
386
+ jsi::Runtime& runtime, EVP_PKEY* pkey,
387
+ const PublicKeyEncodingConfig& config) {
388
+ BIOPointer bio(BIO_new(BIO_s_mem()));
389
+ // CHECK(bio);
390
+
391
+ if (!WritePublicKeyInner(pkey, bio, config)) {
392
+ jsi::detail::throwJSError(runtime, "Failed to encode public key");
393
+ return std::nullopt;
394
+ }
395
+
396
+ return BIOToStringOrBuffer(bio.get(), config.format_);
397
+ }
398
+
399
+ // Maybe<bool> ExportJWKSecretKey(
400
+ // Environment* env,
401
+ // std::shared_ptr<KeyObjectData> key,
402
+ // Local<Object> target) {
403
+ // CHECK_EQ(key->GetKeyType(), kKeyTypeSecret);
404
+ //
405
+ // Local<Value> error;
406
+ // Local<Value> raw;
407
+ // MaybeLocal<Value> key_data =
408
+ // StringBytes::Encode(
409
+ // env->isolate(),
410
+ // key->GetSymmetricKey(),
411
+ // key->GetSymmetricKeySize(),
412
+ // BASE64URL,
413
+ // &error);
414
+ // if (key_data.IsEmpty()) {
415
+ // CHECK(!error.IsEmpty());
416
+ // env->isolate()->ThrowException(error);
417
+ // return Nothing<bool>();
418
+ // }
419
+ // if (!key_data.ToLocal(&raw))
420
+ // return Nothing<bool>();
421
+ //
422
+ // if (target->Set(
423
+ // env->context(),
424
+ // env->jwk_kty_string(),
425
+ // env->jwk_oct_string()).IsNothing() ||
426
+ // target->Set(
427
+ // env->context(),
428
+ // env->jwk_k_string(),
429
+ // raw).IsNothing()) {
430
+ // return Nothing<bool>();
431
+ // }
432
+ //
433
+ // return Just(true);
434
+ //}
435
+ //
436
+ // std::shared_ptr<KeyObjectData> ImportJWKSecretKey(
437
+ // Environment* env,
438
+ // Local<Object> jwk) {
439
+ // Local<Value> key;
440
+ // if (!jwk->Get(env->context(), env->jwk_k_string()).ToLocal(&key) ||
441
+ // !key->IsString()) {
442
+ // THROW_ERR_CRYPTO_INVALID_JWK(env, "Invalid JWK secret key format");
443
+ // return std::shared_ptr<KeyObjectData>();
444
+ // }
445
+ //
446
+ // ByteSource key_data = ByteSource::FromEncodedString(env,
447
+ // key.As<String>()); if (key_data.size() > INT_MAX) {
448
+ // THROW_ERR_CRYPTO_INVALID_KEYLEN(env);
449
+ // return std::shared_ptr<KeyObjectData>();
450
+ // }
451
+ //
452
+ // return KeyObjectData::CreateSecret(std::move(key_data));
453
+ //}
454
+ //
455
+ // Maybe<bool> ExportJWKAsymmetricKey(
456
+ // Environment* env,
457
+ // std::shared_ptr<KeyObjectData> key,
458
+ // Local<Object> target,
459
+ // bool handleRsaPss) {
460
+ // switch (EVP_PKEY_id(key->GetAsymmetricKey().get())) {
461
+ // case EVP_PKEY_RSA_PSS: {
462
+ // if (handleRsaPss) return ExportJWKRsaKey(env, key, target);
463
+ // break;
464
+ // }
465
+ // case EVP_PKEY_RSA: return ExportJWKRsaKey(env, key, target);
466
+ // case EVP_PKEY_EC: return ExportJWKEcKey(env, key, target).IsJust() ?
467
+ // Just(true) : Nothing<bool>();
468
+ // case EVP_PKEY_ED25519:
469
+ // // Fall through
470
+ // case EVP_PKEY_ED448:
471
+ // // Fall through
472
+ // case EVP_PKEY_X25519:
473
+ // // Fall through
474
+ // case EVP_PKEY_X448: return ExportJWKEdKey(env, key, target);
475
+ // }
476
+ // THROW_ERR_CRYPTO_JWK_UNSUPPORTED_KEY_TYPE(env);
477
+ // return Just(false);
478
+ //}
479
+ //
480
+ // std::shared_ptr<KeyObjectData> ImportJWKAsymmetricKey(
481
+ // Environment* env,
482
+ // Local<Object> jwk,
483
+ // const char* kty,
484
+ // const
485
+ // FunctionCallbackInfo<Value>&
486
+ // args, unsigned int
487
+ // offset) {
488
+ // if (strcmp(kty, "RSA") == 0) {
489
+ // return ImportJWKRsaKey(env, jwk, args, offset);
490
+ // } else if (strcmp(kty, "EC") == 0) {
491
+ // return ImportJWKEcKey(env, jwk, args, offset);
492
+ // }
493
+ //
494
+ // THROW_ERR_CRYPTO_INVALID_JWK(env, "%s is not a supported JWK key type",
495
+ // kty); return std::shared_ptr<KeyObjectData>();
496
+ //}
497
+ //
498
+ // Maybe<bool> GetSecretKeyDetail(
499
+ // Environment* env,
500
+ // std::shared_ptr<KeyObjectData> key,
501
+ // Local<Object> target) {
502
+ // // For the secret key detail, all we care about is the length,
503
+ // // converted to bits.
504
+ //
505
+ // size_t length = key->GetSymmetricKeySize() * CHAR_BIT;
506
+ // return target->Set(env->context(),
507
+ // env->length_string(),
508
+ // Number::New(env->isolate(),
509
+ // static_cast<double>(length)));
510
+ //}
511
+ //
512
+ // Maybe<bool> GetAsymmetricKeyDetail(
513
+ // Environment* env,
514
+ // std::shared_ptr<KeyObjectData> key,
515
+ // Local<Object> target) {
516
+ // switch (EVP_PKEY_id(key->GetAsymmetricKey().get())) {
517
+ // case EVP_PKEY_RSA:
518
+ // // Fall through
519
+ // case EVP_PKEY_RSA_PSS: return GetRsaKeyDetail(env, key, target);
520
+ // case EVP_PKEY_DSA: return GetDsaKeyDetail(env, key, target);
521
+ // case EVP_PKEY_EC: return GetEcKeyDetail(env, key, target);
522
+ // case EVP_PKEY_DH: return GetDhKeyDetail(env, key, target);
523
+ // }
524
+ // THROW_ERR_CRYPTO_INVALID_KEYTYPE(env);
525
+ // return Nothing<bool>();
526
+ //}
527
+ //} // namespace
528
+
529
+ ManagedEVPPKey::ManagedEVPPKey(EVPKeyPointer&& pkey) : pkey_(std::move(pkey)) {}
530
+
531
+ ManagedEVPPKey::ManagedEVPPKey(const ManagedEVPPKey& that) { *this = that; }
532
+
533
+ ManagedEVPPKey& ManagedEVPPKey::operator=(const ManagedEVPPKey& that) {
534
+ // Mutex::ScopedLock lock(*that.mutex_);
535
+
536
+ pkey_.reset(that.get());
537
+
538
+ if (pkey_) EVP_PKEY_up_ref(pkey_.get());
539
+
540
+ // mutex_ = that.mutex_;
541
+
542
+ return *this;
543
+ }
544
+
545
+ ManagedEVPPKey::operator bool() const { return !!pkey_; }
546
+
547
+ EVP_PKEY* ManagedEVPPKey::get() const { return pkey_.get(); }
548
+
549
+ // Mutex* ManagedEVPPKey::mutex() const {
550
+ // return mutex_.get();
551
+ //}
552
+ //
553
+ // void ManagedEVPPKey::MemoryInfo(MemoryTracker* tracker) const {
554
+ // tracker->TrackFieldWithSize("pkey",
555
+ // !pkey_ ? 0 : kSizeOf_EVP_PKEY +
556
+ // size_of_private_key() +
557
+ // size_of_public_key());
558
+ //}
559
+ //
560
+ // size_t ManagedEVPPKey::size_of_private_key() const {
561
+ // size_t len = 0;
562
+ // return (pkey_ && EVP_PKEY_get_raw_private_key(
563
+ // pkey_.get(), nullptr, &len)
564
+ // == 1) ? len : 0;
565
+ //}
566
+ //
567
+ // size_t ManagedEVPPKey::size_of_public_key() const {
568
+ // size_t len = 0;
569
+ // return (pkey_ && EVP_PKEY_get_raw_public_key(
570
+ // pkey_.get(), nullptr, &len)
571
+ // == 1) ? len : 0;
572
+ //}
573
+ //
574
+ // Maybe<bool> ExportJWKInner(Environment* env,
575
+ // std::shared_ptr<KeyObjectData> key,
576
+ // Local<Value> result,
577
+ // bool handleRsaPss) {
578
+ // switch (key->GetKeyType()) {
579
+ // case kKeyTypeSecret:
580
+ // return ExportJWKSecretKey(env, key, result.As<Object>());
581
+ // case kKeyTypePublic:
582
+ // // Fall through
583
+ // case kKeyTypePrivate:
584
+ // return ExportJWKAsymmetricKey(
585
+ // env, key, result.As<Object>(),
586
+ // handleRsaPss);
587
+ // default:
588
+ // UNREACHABLE();
589
+ // }
590
+ // }
591
+ //
592
+
593
+ std::optional<StringOrBuffer> ManagedEVPPKey::ToEncodedPublicKey(
594
+ jsi::Runtime& runtime, ManagedEVPPKey key,
595
+ const PublicKeyEncodingConfig& config) {
596
+ if (!key) return {};
597
+ // TODO(osp) ignore all this for now
598
+ // if (config.output_key_object_) {
599
+ // // Note that this has the downside of containing sensitive data of the
600
+ // // private key.
601
+ // std::shared_ptr<KeyObjectData> data =
602
+ // KeyObjectData::CreateAsymmetric(kKeyTypePublic, std::move(key));
603
+ // TODO(osp) Replaced tristate for std::optional
604
+ // return Tristate(KeyObjectHandle::Create(env, data).ToLocal(out));
605
+ // } else if (config.format_ == kKeyFormatJWK) {
606
+ // std::shared_ptr<KeyObjectData> data =
607
+ // KeyObjectData::CreateAsymmetric(kKeyTypePublic, std::move(key));
608
+ // *out = Object::New(env->isolate());
609
+ // return ExportJWKInner(env, data, *out, false);
610
+ // }
611
+
612
+ return WritePublicKey(runtime, key.get(), config);
613
+ }
614
+
615
+ std::optional<StringOrBuffer> ManagedEVPPKey::ToEncodedPrivateKey(
616
+ jsi::Runtime& runtime, ManagedEVPPKey key,
617
+ const PrivateKeyEncodingConfig& config) {
618
+ if (!key) return {};
619
+ // if (config.output_key_object_) {
620
+ // std::shared_ptr<KeyObjectData> data =
621
+ // KeyObjectData::CreateAsymmetric(kKeyTypePrivate, std::move(key));
622
+ // TODO(osp) replaced tristate for std::optional
623
+ // return Tristate(KeyObjectHandle::Create(env, data).ToLocal(out));
624
+ // } else if (config.format_ == kKeyFormatJWK) {
625
+ // std::shared_ptr<KeyObjectData> data =
626
+ // KeyObjectData::CreateAsymmetric(kKeyTypePrivate, std::move(key));
627
+ // *out = Object::New(env->isolate());
628
+ // return ExportJWKInner(env, data, *out, false);
629
+ // }
630
+
631
+ return WritePrivateKey(runtime, key.get(), config);
632
+ }
633
+
634
+ NonCopyableMaybe<PrivateKeyEncodingConfig>
635
+ ManagedEVPPKey::GetPrivateKeyEncodingFromJs(jsi::Runtime& runtime,
636
+ const jsi::Value* arguments,
637
+ unsigned int* offset,
638
+ KeyEncodingContext context) {
639
+ PrivateKeyEncodingConfig result;
640
+ GetKeyFormatAndTypeFromJs(&result, runtime, arguments, offset, context);
641
+
642
+ if (result.output_key_object_) {
643
+ if (context != kKeyContextInput) (*offset)++;
644
+ } else {
645
+ bool needs_passphrase = false;
646
+ if (context != kKeyContextInput) {
647
+ if (arguments[*offset].isString()) {
648
+ auto cipher_name = arguments[*offset].getString(runtime).utf8(runtime);
649
+ result.cipher_ = EVP_get_cipherbyname(cipher_name.c_str());
650
+ if (result.cipher_ == nullptr) {
651
+ jsi::detail::throwJSError(runtime, "Unknown cipher");
652
+ return NonCopyableMaybe<PrivateKeyEncodingConfig>();
653
+ }
654
+ needs_passphrase = true;
655
+ } else {
656
+ // CHECK(args[*offset]->IsNullOrUndefined());
657
+ result.cipher_ = nullptr;
658
+ }
659
+ (*offset)++;
660
+ }
661
+
662
+ if (CheckIsArrayBuffer(runtime, arguments[*offset])) {
663
+ // CHECK_IMPLIES(context != kKeyContextInput, result.cipher_ !=
664
+ // nullptr); ArrayBufferOrViewContents<char>
665
+ // passphrase(arguments[*offset]);
666
+ jsi::ArrayBuffer passphrase =
667
+ arguments[*offset].asObject(runtime).getArrayBuffer(runtime);
668
+ if (!CheckSizeInt32(runtime, passphrase)) {
669
+ jsi::detail::throwJSError(runtime, "passphrase is too long");
670
+ }
671
+
672
+ result.passphrase_ = NonCopyableMaybe<ByteSource>(
673
+ ToNullTerminatedByteSource(runtime, passphrase));
674
+ } else {
675
+ if (needs_passphrase &&
676
+ (arguments[*offset].isNull() || arguments[*offset].isUndefined())) {
677
+ jsi::detail::throwJSError(
678
+ runtime, "passphrase is null or unfedined but it is required");
679
+ }
680
+ }
681
+ }
682
+
683
+ (*offset)++;
684
+ return NonCopyableMaybe<PrivateKeyEncodingConfig>(std::move(result));
685
+ }
686
+
687
+ PublicKeyEncodingConfig ManagedEVPPKey::GetPublicKeyEncodingFromJs(
688
+ jsi::Runtime& runtime, const jsi::Value* arguments, unsigned int* offset,
689
+ KeyEncodingContext context) {
690
+ PublicKeyEncodingConfig result;
691
+ GetKeyFormatAndTypeFromJs(&result, runtime, arguments, offset, context);
692
+ return result;
693
+ }
694
+
695
+ // TODO(osp) I never quite manage to figure out whether this is really necessary
696
+ // maybe is other crypto function, leaving it for future uncommenting
697
+ // ManagedEVPPKey ManagedEVPPKey::GetPrivateKeyFromJs(
698
+ // const
699
+ // FunctionCallbackInfo<Value>&
700
+ // args, unsigned int*
701
+ // offset, bool
702
+ // allow_key_object) {
703
+ // if (args[*offset]->IsString() || IsAnyByteSource(args[*offset])) {
704
+ // Environment* env = Environment::GetCurrent(args);
705
+ // ByteSource key = ByteSource::FromStringOrBuffer(env, args[(*offset)++]);
706
+ // NonCopyableMaybe<PrivateKeyEncodingConfig> config =
707
+ // GetPrivateKeyEncodingFromJs(args, offset, kKeyContextInput);
708
+ // if (config.IsEmpty())
709
+ // return ManagedEVPPKey();
710
+ //
711
+ // EVPKeyPointer pkey;
712
+ // ParseKeyResult ret =
713
+ // ParsePrivateKey(&pkey, config.Release(), key.data<char>(), key.size());
714
+ // return GetParsedKey(env, std::move(pkey), ret,
715
+ // "Failed to read private key");
716
+ // } else {
717
+ // CHECK(args[*offset]->IsObject() && allow_key_object);
718
+ // KeyObjectHandle* key;
719
+ // ASSIGN_OR_RETURN_UNWRAP(&key, args[*offset].As<Object>(),
720
+ // ManagedEVPPKey()); CHECK_EQ(key->Data()->GetKeyType(), kKeyTypePrivate);
721
+ // (*offset) += 4;
722
+ // return key->Data()->GetAsymmetricKey();
723
+ // }
724
+ //}
725
+
726
+ ManagedEVPPKey ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(
727
+ jsi::Runtime& runtime, const jsi::Value* args, unsigned int* offset) {
728
+ if (args[*offset].asObject(runtime).isArrayBuffer(runtime)) {
729
+ auto dataArrayBuffer =
730
+ args[(*offset)++].asObject(runtime).getArrayBuffer(runtime);
731
+
732
+ if (!CheckSizeInt32(runtime, dataArrayBuffer)) {
733
+ jsi::detail::throwJSError(runtime, "data is too big");
734
+ }
735
+
736
+ NonCopyableMaybe<PrivateKeyEncodingConfig> config_ =
737
+ GetPrivateKeyEncodingFromJs(runtime, args, offset, kKeyContextInput);
738
+ if (config_.IsEmpty()) return ManagedEVPPKey();
739
+
740
+ ParseKeyResult ret;
741
+ PrivateKeyEncodingConfig config = config_.Release();
742
+ EVPKeyPointer pkey;
743
+ if (config.format_ == kKeyFormatPEM) {
744
+ // For PEM, we can easily determine whether it is a public or private
745
+ // key by looking for the respective PEM tags.
746
+ ret = ParsePublicKeyPEM(&pkey, (const char*)dataArrayBuffer.data(runtime),
747
+ (int)dataArrayBuffer.size(runtime));
748
+ if (ret == ParseKeyResult::kParseKeyNotRecognized) {
749
+ ret = ParsePrivateKey(&pkey, config,
750
+ (const char*)dataArrayBuffer.data(runtime),
751
+ (int)dataArrayBuffer.size(runtime));
752
+ }
753
+ } else {
754
+ // For DER, the type determines how to parse it. SPKI, PKCS#8 and SEC1
755
+ // are easy, but PKCS#1 can be a public key or a private key.
756
+ bool is_public;
757
+ switch (config.type_.value()) {
758
+ case kKeyEncodingPKCS1:
759
+ is_public = !IsRSAPrivateKey(reinterpret_cast<const unsigned char*>(
760
+ dataArrayBuffer.data(runtime)),
761
+ dataArrayBuffer.size(runtime));
762
+ break;
763
+ case kKeyEncodingSPKI:
764
+ is_public = true;
765
+ break;
766
+ case kKeyEncodingPKCS8:
767
+ case kKeyEncodingSEC1:
768
+ is_public = false;
769
+ break;
770
+ default:
771
+ jsi::detail::throwJSError(runtime, "Invalid key encoding type");
772
+ throw new jsi::JSError(runtime, "Invalid key encoding type");
773
+ }
774
+
775
+ if (is_public) {
776
+ ret = ParsePublicKey(&pkey, config,
777
+ (const char*)dataArrayBuffer.data(runtime),
778
+ dataArrayBuffer.size(runtime));
779
+ } else {
780
+ ret = ParsePrivateKey(&pkey, config,
781
+ (const char*)dataArrayBuffer.data(runtime),
782
+ dataArrayBuffer.size(runtime));
783
+ }
784
+ }
785
+
786
+ return ManagedEVPPKey::GetParsedKey(runtime, std::move(pkey), ret,
787
+ "Failed to read asymmetric key");
788
+ } else {
789
+ jsi::detail::throwJSError(runtime,
790
+ "publicEncrypt api only supports ArrayBuffer keys"
791
+ "for now");
792
+ throw new jsi::JSError(
793
+ runtime, "public encrypt only supports ArrayBuffer at the moment");
794
+ // CHECK(args[*offset]->IsObject());
795
+ // KeyObjectHandle* key =
796
+ // Unwrap<KeyObjectHandle>(args[*offset].As<Object>());
797
+ // CHECK_NOT_NULL(key);
798
+ // CHECK_NE(key->Data()->GetKeyType(), kKeyTypeSecret);
799
+ // (*offset) += 4;
800
+ // return key->Data()->GetAsymmetricKey();
801
+ }
802
+ }
803
+
804
+ ManagedEVPPKey ManagedEVPPKey::GetParsedKey(jsi::Runtime& runtime,
805
+ EVPKeyPointer&& pkey,
806
+ ParseKeyResult ret,
807
+ const char* default_msg) {
808
+ switch (ret) {
809
+ case ParseKeyResult::kParseKeyOk:
810
+ // CHECK(pkey);
811
+ break;
812
+ case ParseKeyResult::kParseKeyNeedPassphrase:
813
+ jsi::detail::throwJSError(runtime,
814
+ "Passphrase required for encrypted key");
815
+ break;
816
+ default:
817
+ jsi::detail::throwJSError(runtime, default_msg);
818
+ throw new jsi::JSError(runtime, default_msg);
819
+ }
820
+
821
+ return ManagedEVPPKey(std::move(pkey));
822
+ }
823
+ //
824
+ // KeyObjectData::KeyObjectData(
825
+ // ByteSource symmetric_key)
826
+ //: key_type_(KeyType::kKeyTypeSecret),
827
+ // symmetric_key_(std::move(symmetric_key)),
828
+ // symmetric_key_len_(symmetric_key_.size()),
829
+ // asymmetric_key_() {}
830
+ //
831
+ // KeyObjectData::KeyObjectData(
832
+ // KeyType type,
833
+ // const ManagedEVPPKey& pkey)
834
+ //: key_type_(type),
835
+ // symmetric_key_(),
836
+ // symmetric_key_len_(0),
837
+ // asymmetric_key_{pkey} {}
838
+ //
839
+ // void KeyObjectData::MemoryInfo(MemoryTracker* tracker) const {
840
+ // switch (GetKeyType()) {
841
+ // case kKeyTypeSecret:
842
+ // tracker->TrackFieldWithSize("symmetric_key", symmetric_key_.size());
843
+ // break;
844
+ // case kKeyTypePrivate:
845
+ // // Fall through
846
+ // case kKeyTypePublic:
847
+ // tracker->TrackFieldWithSize("key", asymmetric_key_);
848
+ // break;
849
+ // default:
850
+ // UNREACHABLE();
851
+ // }
852
+ // }
853
+ //
854
+ // std::shared_ptr<KeyObjectData> KeyObjectData::CreateSecret(ByteSource key)
855
+ // {
856
+ // CHECK(key);
857
+ // return std::shared_ptr<KeyObjectData>(new KeyObjectData(std::move(key)));
858
+ // }
859
+ //
860
+ // std::shared_ptr<KeyObjectData> KeyObjectData::CreateAsymmetric(
861
+ // KeyType
862
+ // key_type,
863
+ // const
864
+ // ManagedEVPPKey&
865
+ // pkey) {
866
+ // CHECK(pkey);
867
+ // return std::shared_ptr<KeyObjectData>(new KeyObjectData(key_type, pkey));
868
+ // }
869
+ //
870
+ // KeyType KeyObjectData::GetKeyType() const {
871
+ // return key_type_;
872
+ // }
873
+ //
874
+ // ManagedEVPPKey KeyObjectData::GetAsymmetricKey() const {
875
+ // CHECK_NE(key_type_, kKeyTypeSecret);
876
+ // return asymmetric_key_;
877
+ // }
878
+ //
879
+ // const char* KeyObjectData::GetSymmetricKey() const {
880
+ // CHECK_EQ(key_type_, kKeyTypeSecret);
881
+ // return symmetric_key_.data<char>();
882
+ // }
883
+ //
884
+ // size_t KeyObjectData::GetSymmetricKeySize() const {
885
+ // CHECK_EQ(key_type_, kKeyTypeSecret);
886
+ // return symmetric_key_len_;
887
+ // }
888
+ //
889
+ // v8::Local<v8::Function> KeyObjectHandle::Initialize(Environment* env) {
890
+ // Local<Function> templ = env->crypto_key_object_handle_constructor();
891
+ // if (!templ.IsEmpty()) {
892
+ // return templ;
893
+ // }
894
+ // Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
895
+ // t->InstanceTemplate()->SetInternalFieldCount(
896
+ // KeyObjectHandle::kInternalFieldCount);
897
+ // t->Inherit(BaseObject::GetConstructorTemplate(env));
898
+ //
899
+ // env->SetProtoMethod(t, "init", Init);
900
+ // env->SetProtoMethodNoSideEffect(t, "getSymmetricKeySize",
901
+ // GetSymmetricKeySize);
902
+ // env->SetProtoMethodNoSideEffect(t, "getAsymmetricKeyType",
903
+ // GetAsymmetricKeyType);
904
+ // env->SetProtoMethod(t, "export", Export);
905
+ // env->SetProtoMethod(t, "exportJwk", ExportJWK);
906
+ // env->SetProtoMethod(t, "initECRaw", InitECRaw);
907
+ // env->SetProtoMethod(t, "initEDRaw", InitEDRaw);
908
+ // env->SetProtoMethod(t, "initJwk", InitJWK);
909
+ // env->SetProtoMethod(t, "keyDetail", GetKeyDetail);
910
+ // env->SetProtoMethod(t, "equals", Equals);
911
+ //
912
+ // auto function = t->GetFunction(env->context()).ToLocalChecked();
913
+ // env->set_crypto_key_object_handle_constructor(function);
914
+ // return function;
915
+ // }
916
+ //
917
+ // void KeyObjectHandle::RegisterExternalReferences(
918
+ // ExternalReferenceRegistry*
919
+ // registry) {
920
+ // registry->Register(New);
921
+ // registry->Register(Init);
922
+ // registry->Register(GetSymmetricKeySize);
923
+ // registry->Register(GetAsymmetricKeyType);
924
+ // registry->Register(Export);
925
+ // registry->Register(ExportJWK);
926
+ // registry->Register(InitECRaw);
927
+ // registry->Register(InitEDRaw);
928
+ // registry->Register(InitJWK);
929
+ // registry->Register(GetKeyDetail);
930
+ // registry->Register(Equals);
931
+ // }
932
+ //
933
+ // MaybeLocal<Object> KeyObjectHandle::Create(
934
+ // Environment* env,
935
+ // std::shared_ptr<KeyObjectData>
936
+ // data) {
937
+ // Local<Object> obj;
938
+ // Local<Function> ctor = KeyObjectHandle::Initialize(env);
939
+ // CHECK(!env->crypto_key_object_handle_constructor().IsEmpty());
940
+ // if (!ctor->NewInstance(env->context(), 0, nullptr).ToLocal(&obj))
941
+ // return MaybeLocal<Object>();
942
+ //
943
+ // KeyObjectHandle* key = Unwrap<KeyObjectHandle>(obj);
944
+ // CHECK_NOT_NULL(key);
945
+ // key->data_ = data;
946
+ // return obj;
947
+ // }
948
+ //
949
+ // const std::shared_ptr<KeyObjectData>& KeyObjectHandle::Data() {
950
+ // return data_;
951
+ // }
952
+ //
953
+ // void KeyObjectHandle::New(const FunctionCallbackInfo<Value>& args) {
954
+ // CHECK(args.IsConstructCall());
955
+ // Environment* env = Environment::GetCurrent(args);
956
+ // new KeyObjectHandle(env, args.This());
957
+ // }
958
+ //
959
+ // KeyObjectHandle::KeyObjectHandle(Environment* env,
960
+ // Local<Object> wrap)
961
+ //: BaseObject(env, wrap) {
962
+ // MakeWeak();
963
+ //}
964
+ //
965
+ // void KeyObjectHandle::Init(const FunctionCallbackInfo<Value>& args) {
966
+ // KeyObjectHandle* key;
967
+ // ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
968
+ // MarkPopErrorOnReturn mark_pop_error_on_return;
969
+ //
970
+ // CHECK(args[0]->IsInt32());
971
+ // KeyType type = static_cast<KeyType>(args[0].As<Uint32>()->Value());
972
+ //
973
+ // unsigned int offset;
974
+ // ManagedEVPPKey pkey;
975
+ //
976
+ // switch (type) {
977
+ // case kKeyTypeSecret: {
978
+ // CHECK_EQ(args.Length(), 2);
979
+ // ArrayBufferOrViewContents<char> buf(args[1]);
980
+ // key->data_ = KeyObjectData::CreateSecret(buf.ToCopy());
981
+ // break;
982
+ // }
983
+ // case kKeyTypePublic: {
984
+ // CHECK_EQ(args.Length(), 5);
985
+ //
986
+ // offset = 1;
987
+ // pkey = ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(args, &offset);
988
+ // if (!pkey)
989
+ // return;
990
+ // key->data_ = KeyObjectData::CreateAsymmetric(type, pkey);
991
+ // break;
992
+ // }
993
+ // case kKeyTypePrivate: {
994
+ // CHECK_EQ(args.Length(), 5);
995
+ //
996
+ // offset = 1;
997
+ // pkey = ManagedEVPPKey::GetPrivateKeyFromJs(args, &offset, false);
998
+ // if (!pkey)
999
+ // return;
1000
+ // key->data_ = KeyObjectData::CreateAsymmetric(type, pkey);
1001
+ // break;
1002
+ // }
1003
+ // default:
1004
+ // UNREACHABLE();
1005
+ // }
1006
+ //}
1007
+ //
1008
+ // void KeyObjectHandle::InitJWK(const FunctionCallbackInfo<Value>& args) {
1009
+ // Environment* env = Environment::GetCurrent(args);
1010
+ // KeyObjectHandle* key;
1011
+ // ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1012
+ // MarkPopErrorOnReturn mark_pop_error_on_return;
1013
+ //
1014
+ // // The argument must be a JavaScript object that we will inspect
1015
+ // // to get the JWK properties from.
1016
+ // CHECK(args[0]->IsObject());
1017
+ //
1018
+ // // Step one, Secret key or not?
1019
+ // Local<Object> input = args[0].As<Object>();
1020
+ //
1021
+ // Local<Value> kty;
1022
+ // if (!input->Get(env->context(), env->jwk_kty_string()).ToLocal(&kty) ||
1023
+ // !kty->IsString()) {
1024
+ // return THROW_ERR_CRYPTO_INVALID_JWK(env);
1025
+ // }
1026
+ //
1027
+ // Utf8Value kty_string(env->isolate(), kty);
1028
+ //
1029
+ // if (strcmp(*kty_string, "oct") == 0) {
1030
+ // // Secret key
1031
+ // key->data_ = ImportJWKSecretKey(env, input);
1032
+ // if (!key->data_) {
1033
+ // // ImportJWKSecretKey is responsible for throwing an appropriate error
1034
+ // return;
1035
+ // }
1036
+ // } else {
1037
+ // key->data_ = ImportJWKAsymmetricKey(env, input, *kty_string, args, 1);
1038
+ // if (!key->data_) {
1039
+ // // ImportJWKAsymmetricKey is responsible for throwing an appropriate
1040
+ // error return;
1041
+ // }
1042
+ // }
1043
+ //
1044
+ // args.GetReturnValue().Set(key->data_->GetKeyType());
1045
+ //}
1046
+ //
1047
+ // void KeyObjectHandle::InitECRaw(const FunctionCallbackInfo<Value>& args) {
1048
+ // Environment* env = Environment::GetCurrent(args);
1049
+ // KeyObjectHandle* key;
1050
+ // ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1051
+ //
1052
+ // CHECK(args[0]->IsString());
1053
+ // Utf8Value name(env->isolate(), args[0]);
1054
+ //
1055
+ // MarkPopErrorOnReturn mark_pop_error_on_return;
1056
+ //
1057
+ // int id = OBJ_txt2nid(*name);
1058
+ // ECKeyPointer eckey(EC_KEY_new_by_curve_name(id));
1059
+ // if (!eckey)
1060
+ // return args.GetReturnValue().Set(false);
1061
+ //
1062
+ // const EC_GROUP* group = EC_KEY_get0_group(eckey.get());
1063
+ // ECPointPointer pub(ECDH::BufferToPoint(env, group, args[1]));
1064
+ //
1065
+ // if (!pub ||
1066
+ // !eckey ||
1067
+ // !EC_KEY_set_public_key(eckey.get(), pub.get())) {
1068
+ // return args.GetReturnValue().Set(false);
1069
+ // }
1070
+ //
1071
+ // EVPKeyPointer pkey(EVP_PKEY_new());
1072
+ // if (!EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()))
1073
+ // args.GetReturnValue().Set(false);
1074
+ //
1075
+ // eckey.release(); // Release ownership of the key
1076
+ //
1077
+ // key->data_ =
1078
+ // KeyObjectData::CreateAsymmetric(
1079
+ // kKeyTypePublic,
1080
+ // ManagedEVPPKey(std::move(pkey)));
1081
+ //
1082
+ // args.GetReturnValue().Set(true);
1083
+ //}
1084
+ //
1085
+ // void KeyObjectHandle::InitEDRaw(const FunctionCallbackInfo<Value>& args) {
1086
+ // Environment* env = Environment::GetCurrent(args);
1087
+ // KeyObjectHandle* key;
1088
+ // ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1089
+ //
1090
+ // CHECK(args[0]->IsString());
1091
+ // Utf8Value name(env->isolate(), args[0]);
1092
+ //
1093
+ // ArrayBufferOrViewContents<unsigned char> key_data(args[1]);
1094
+ // KeyType type = static_cast<KeyType>(args[2].As<Int32>()->Value());
1095
+ //
1096
+ // MarkPopErrorOnReturn mark_pop_error_on_return;
1097
+ //
1098
+ // typedef EVP_PKEY* (*new_key_fn)(int, ENGINE*, const unsigned char*,
1099
+ // size_t); new_key_fn fn = type == kKeyTypePrivate ?
1100
+ // EVP_PKEY_new_raw_private_key : EVP_PKEY_new_raw_public_key;
1101
+ //
1102
+ // int id = GetOKPCurveFromName(*name);
1103
+ //
1104
+ // switch (id) {
1105
+ // case EVP_PKEY_X25519:
1106
+ // case EVP_PKEY_X448:
1107
+ // case EVP_PKEY_ED25519:
1108
+ // case EVP_PKEY_ED448: {
1109
+ // EVPKeyPointer pkey(fn(id, nullptr, key_data.data(), key_data.size()));
1110
+ // if (!pkey)
1111
+ // return args.GetReturnValue().Set(false);
1112
+ // key->data_ =
1113
+ // KeyObjectData::CreateAsymmetric(
1114
+ // type,
1115
+ // ManagedEVPPKey(std::move(pkey)));
1116
+ // CHECK(key->data_);
1117
+ // break;
1118
+ // }
1119
+ // default:
1120
+ // UNREACHABLE();
1121
+ // }
1122
+ //
1123
+ // args.GetReturnValue().Set(true);
1124
+ //}
1125
+ //
1126
+ // void KeyObjectHandle::Equals(const FunctionCallbackInfo<Value>& args) {
1127
+ // KeyObjectHandle* self_handle;
1128
+ // KeyObjectHandle* arg_handle;
1129
+ // ASSIGN_OR_RETURN_UNWRAP(&self_handle, args.Holder());
1130
+ // ASSIGN_OR_RETURN_UNWRAP(&arg_handle, args[0].As<Object>());
1131
+ // std::shared_ptr<KeyObjectData> key = self_handle->Data();
1132
+ // std::shared_ptr<KeyObjectData> key2 = arg_handle->Data();
1133
+ //
1134
+ // KeyType key_type = key->GetKeyType();
1135
+ // CHECK_EQ(key_type, key2->GetKeyType());
1136
+ //
1137
+ // bool ret;
1138
+ // switch (key_type) {
1139
+ // case kKeyTypeSecret: {
1140
+ // size_t size = key->GetSymmetricKeySize();
1141
+ // if (size == key2->GetSymmetricKeySize()) {
1142
+ // ret = CRYPTO_memcmp(
1143
+ // key->GetSymmetricKey(),
1144
+ // key2->GetSymmetricKey(),
1145
+ // size) == 0;
1146
+ // } else {
1147
+ // ret = false;
1148
+ // }
1149
+ // break;
1150
+ // }
1151
+ // case kKeyTypePublic:
1152
+ // case kKeyTypePrivate: {
1153
+ // EVP_PKEY* pkey = key->GetAsymmetricKey().get();
1154
+ // EVP_PKEY* pkey2 = key2->GetAsymmetricKey().get();
1155
+ //#if OPENSSL_VERSION_MAJOR >= 3
1156
+ // int ok = EVP_PKEY_eq(pkey, pkey2);
1157
+ //#else
1158
+ // int ok = EVP_PKEY_cmp(pkey, pkey2);
1159
+ //#endif
1160
+ // if (ok == -2) {
1161
+ // Environment* env = Environment::GetCurrent(args);
1162
+ // return THROW_ERR_CRYPTO_UNSUPPORTED_OPERATION(env);
1163
+ // }
1164
+ // ret = ok == 1;
1165
+ // break;
1166
+ // }
1167
+ // default:
1168
+ // UNREACHABLE("unsupported key type");
1169
+ // }
1170
+ //
1171
+ // args.GetReturnValue().Set(ret);
1172
+ //}
1173
+ //
1174
+ // void KeyObjectHandle::GetKeyDetail(const FunctionCallbackInfo<Value>& args)
1175
+ // {
1176
+ // Environment* env = Environment::GetCurrent(args);
1177
+ // KeyObjectHandle* key;
1178
+ // ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1179
+ //
1180
+ // CHECK(args[0]->IsObject());
1181
+ //
1182
+ // std::shared_ptr<KeyObjectData> data = key->Data();
1183
+ //
1184
+ // switch (data->GetKeyType()) {
1185
+ // case kKeyTypeSecret:
1186
+ // if (GetSecretKeyDetail(env, data, args[0].As<Object>()).IsNothing())
1187
+ // return;
1188
+ // break;
1189
+ // case kKeyTypePublic:
1190
+ // // Fall through
1191
+ // case kKeyTypePrivate:
1192
+ // if (GetAsymmetricKeyDetail(env, data,
1193
+ // args[0].As<Object>()).IsNothing())
1194
+ // return;
1195
+ // break;
1196
+ // default:
1197
+ // UNREACHABLE();
1198
+ // }
1199
+ //
1200
+ // args.GetReturnValue().Set(args[0]);
1201
+ //}
1202
+ //
1203
+ // Local<Value> KeyObjectHandle::GetAsymmetricKeyType() const {
1204
+ // const ManagedEVPPKey& key = data_->GetAsymmetricKey();
1205
+ // switch (EVP_PKEY_id(key.get())) {
1206
+ // case EVP_PKEY_RSA:
1207
+ // return env()->crypto_rsa_string();
1208
+ // case EVP_PKEY_RSA_PSS:
1209
+ // return env()->crypto_rsa_pss_string();
1210
+ // case EVP_PKEY_DSA:
1211
+ // return env()->crypto_dsa_string();
1212
+ // case EVP_PKEY_DH:
1213
+ // return env()->crypto_dh_string();
1214
+ // case EVP_PKEY_EC:
1215
+ // return env()->crypto_ec_string();
1216
+ // case EVP_PKEY_ED25519:
1217
+ // return env()->crypto_ed25519_string();
1218
+ // case EVP_PKEY_ED448:
1219
+ // return env()->crypto_ed448_string();
1220
+ // case EVP_PKEY_X25519:
1221
+ // return env()->crypto_x25519_string();
1222
+ // case EVP_PKEY_X448:
1223
+ // return env()->crypto_x448_string();
1224
+ // default:
1225
+ // return Undefined(env()->isolate());
1226
+ // }
1227
+ //}
1228
+ //
1229
+ // void KeyObjectHandle::GetAsymmetricKeyType(
1230
+ // const
1231
+ // FunctionCallbackInfo<Value>&
1232
+ // args) {
1233
+ // KeyObjectHandle* key;
1234
+ // ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1235
+ //
1236
+ // args.GetReturnValue().Set(key->GetAsymmetricKeyType());
1237
+ //}
1238
+ //
1239
+ // void KeyObjectHandle::GetSymmetricKeySize(
1240
+ // const FunctionCallbackInfo<Value>&
1241
+ // args) {
1242
+ // KeyObjectHandle* key;
1243
+ // ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1244
+ // args.GetReturnValue().Set(
1245
+ // static_cast<uint32_t>(key->Data()->GetSymmetricKeySize()));
1246
+ //}
1247
+ //
1248
+ // void KeyObjectHandle::Export(const FunctionCallbackInfo<Value>& args) {
1249
+ // KeyObjectHandle* key;
1250
+ // ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1251
+ //
1252
+ // KeyType type = key->Data()->GetKeyType();
1253
+ //
1254
+ // MaybeLocal<Value> result;
1255
+ // if (type == kKeyTypeSecret) {
1256
+ // result = key->ExportSecretKey();
1257
+ // } else if (type == kKeyTypePublic) {
1258
+ // unsigned int offset = 0;
1259
+ // PublicKeyEncodingConfig config =
1260
+ // ManagedEVPPKey::GetPublicKeyEncodingFromJs(
1261
+ // args, &offset,
1262
+ // kKeyContextExport);
1263
+ // CHECK_EQ(offset, static_cast<unsigned int>(args.Length()));
1264
+ // result = key->ExportPublicKey(config);
1265
+ // } else {
1266
+ // CHECK_EQ(type, kKeyTypePrivate);
1267
+ // unsigned int offset = 0;
1268
+ // NonCopyableMaybe<PrivateKeyEncodingConfig> config =
1269
+ // ManagedEVPPKey::GetPrivateKeyEncodingFromJs(
1270
+ // args, &offset,
1271
+ // kKeyContextExport);
1272
+ // if (config.IsEmpty())
1273
+ // return;
1274
+ // CHECK_EQ(offset, static_cast<unsigned int>(args.Length()));
1275
+ // result = key->ExportPrivateKey(config.Release());
1276
+ // }
1277
+ //
1278
+ // if (!result.IsEmpty())
1279
+ // args.GetReturnValue().Set(result.FromMaybe(Local<Value>()));
1280
+ //}
1281
+ //
1282
+ // MaybeLocal<Value> KeyObjectHandle::ExportSecretKey() const {
1283
+ // const char* buf = data_->GetSymmetricKey();
1284
+ // unsigned int len = data_->GetSymmetricKeySize();
1285
+ // return Buffer::Copy(env(), buf, len).FromMaybe(Local<Value>());
1286
+ //}
1287
+ //
1288
+ // MaybeLocal<Value> KeyObjectHandle::ExportPublicKey(
1289
+ // const
1290
+ // PublicKeyEncodingConfig&
1291
+ // config) const {
1292
+ // return
1293
+ // WritePublicKey(env(),
1294
+ // data_->GetAsymmetricKey().get(),
1295
+ // config);
1296
+ // }
1297
+ //
1298
+ // MaybeLocal<Value> KeyObjectHandle::ExportPrivateKey(
1299
+ // const
1300
+ // PrivateKeyEncodingConfig&
1301
+ // config) const {
1302
+ // return
1303
+ // WritePrivateKey(env(),
1304
+ // data_->GetAsymmetricKey().get(),
1305
+ // config);
1306
+ // }
1307
+ //
1308
+ // void KeyObjectHandle::ExportJWK(
1309
+ // const v8::FunctionCallbackInfo<v8::Value>&
1310
+ // args) {
1311
+ // Environment* env = Environment::GetCurrent(args);
1312
+ // KeyObjectHandle* key;
1313
+ // ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1314
+ //
1315
+ // CHECK(args[0]->IsObject());
1316
+ // CHECK(args[1]->IsBoolean());
1317
+ //
1318
+ // ExportJWKInner(env, key->Data(), args[0], args[1]->IsTrue());
1319
+ //
1320
+ // args.GetReturnValue().Set(args[0]);
1321
+ //}
1322
+ //
1323
+ // void NativeKeyObject::Initialize(Environment* env, Local<Object> target) {
1324
+ // env->SetMethod(target, "createNativeKeyObjectClass",
1325
+ // NativeKeyObject::CreateNativeKeyObjectClass);
1326
+ //}
1327
+ //
1328
+ // void NativeKeyObject::RegisterExternalReferences(
1329
+ // ExternalReferenceRegistry*
1330
+ // registry) {
1331
+ // registry->Register(NativeKeyObject::CreateNativeKeyObjectClass);
1332
+ // registry->Register(NativeKeyObject::New);
1333
+ //}
1334
+ //
1335
+ // void NativeKeyObject::New(const FunctionCallbackInfo<Value>& args) {
1336
+ // Environment* env = Environment::GetCurrent(args);
1337
+ // CHECK_EQ(args.Length(), 1);
1338
+ // CHECK(args[0]->IsObject());
1339
+ // KeyObjectHandle* handle = Unwrap<KeyObjectHandle>(args[0].As<Object>());
1340
+ // new NativeKeyObject(env, args.This(), handle->Data());
1341
+ //}
1342
+ //
1343
+ // void NativeKeyObject::CreateNativeKeyObjectClass(
1344
+ // const
1345
+ // FunctionCallbackInfo<Value>&
1346
+ // args) {
1347
+ // Environment* env = Environment::GetCurrent(args);
1348
+ //
1349
+ // CHECK_EQ(args.Length(), 1);
1350
+ // Local<Value> callback = args[0];
1351
+ // CHECK(callback->IsFunction());
1352
+ //
1353
+ // Local<FunctionTemplate> t =
1354
+ // env->NewFunctionTemplate(NativeKeyObject::New);
1355
+ // t->InstanceTemplate()->SetInternalFieldCount(
1356
+ // KeyObjectHandle::kInternalFieldCount);
1357
+ // t->Inherit(BaseObject::GetConstructorTemplate(env));
1358
+ //
1359
+ // Local<Value> ctor;
1360
+ // if (!t->GetFunction(env->context()).ToLocal(&ctor))
1361
+ // return;
1362
+ //
1363
+ // Local<Value> recv = Undefined(env->isolate());
1364
+ // Local<Value> ret_v;
1365
+ // if (!callback.As<Function>()->Call(
1366
+ // env->context(), recv, 1,
1367
+ // &ctor).ToLocal(&ret_v)) {
1368
+ // return;
1369
+ // }
1370
+ // Local<Array> ret = ret_v.As<Array>();
1371
+ // if (!ret->Get(env->context(), 1).ToLocal(&ctor)) return;
1372
+ // env->set_crypto_key_object_secret_constructor(ctor.As<Function>());
1373
+ // if (!ret->Get(env->context(), 2).ToLocal(&ctor)) return;
1374
+ // env->set_crypto_key_object_public_constructor(ctor.As<Function>());
1375
+ // if (!ret->Get(env->context(), 3).ToLocal(&ctor)) return;
1376
+ // env->set_crypto_key_object_private_constructor(ctor.As<Function>());
1377
+ // args.GetReturnValue().Set(ret);
1378
+ //}
1379
+ //
1380
+ // BaseObjectPtr<BaseObject>
1381
+ // NativeKeyObject::KeyObjectTransferData::Deserialize(
1382
+ // Environment* env,
1383
+ // Local<Context>
1384
+ // context,
1385
+ // std::unique_ptr<worker::TransferData>
1386
+ // self) {
1387
+ // if (context != env->context()) {
1388
+ // THROW_ERR_MESSAGE_TARGET_CONTEXT_UNAVAILABLE(env);
1389
+ // return {};
1390
+ // }
1391
+ //
1392
+ // Local<Value> handle;
1393
+ // if (!KeyObjectHandle::Create(env, data_).ToLocal(&handle))
1394
+ // return {};
1395
+ //
1396
+ // Local<Function> key_ctor;
1397
+ // Local<Value> arg = FIXED_ONE_BYTE_STRING(env->isolate(),
1398
+ // "internal/crypto/keys");
1399
+ // if (env->native_module_require()->
1400
+ // Call(context, Null(env->isolate()), 1, &arg).IsEmpty()) {
1401
+ // return {};
1402
+ // }
1403
+ // switch (data_->GetKeyType()) {
1404
+ // case kKeyTypeSecret:
1405
+ // key_ctor = env->crypto_key_object_secret_constructor();
1406
+ // break;
1407
+ // case kKeyTypePublic:
1408
+ // key_ctor = env->crypto_key_object_public_constructor();
1409
+ // break;
1410
+ // case kKeyTypePrivate:
1411
+ // key_ctor = env->crypto_key_object_private_constructor();
1412
+ // break;
1413
+ // default:
1414
+ // CHECK(false);
1415
+ // }
1416
+ //
1417
+ // Local<Value> key;
1418
+ // if (!key_ctor->NewInstance(context, 1, &handle).ToLocal(&key))
1419
+ // return {};
1420
+ //
1421
+ // return
1422
+ // BaseObjectPtr<BaseObject>(Unwrap<KeyObjectHandle>(key.As<Object>()));
1423
+ //}
1424
+ //
1425
+ // BaseObject::TransferMode NativeKeyObject::GetTransferMode() const {
1426
+ // return BaseObject::TransferMode::kCloneable;
1427
+ //}
1428
+ //
1429
+ // std::unique_ptr<worker::TransferData> NativeKeyObject::CloneForMessaging()
1430
+ // const {
1431
+ // return std::make_unique<KeyObjectTransferData>(handle_data_);
1432
+ //}
1433
+ //
1434
+ // WebCryptoKeyExportStatus PKEY_SPKI_Export(
1435
+ // KeyObjectData* key_data,
1436
+ // ByteSource* out) {
1437
+ // CHECK_EQ(key_data->GetKeyType(), kKeyTypePublic);
1438
+ // ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey();
1439
+ // Mutex::ScopedLock lock(*m_pkey.mutex());
1440
+ // BIOPointer bio(BIO_new(BIO_s_mem()));
1441
+ // CHECK(bio);
1442
+ // if (!i2d_PUBKEY_bio(bio.get(), m_pkey.get()))
1443
+ // return WebCryptoKeyExportStatus::FAILED;
1444
+ //
1445
+ // *out = ByteSource::FromBIO(bio);
1446
+ // return WebCryptoKeyExportStatus::OK;
1447
+ //}
1448
+ //
1449
+ // WebCryptoKeyExportStatus PKEY_PKCS8_Export(
1450
+ // KeyObjectData* key_data,
1451
+ // ByteSource* out) {
1452
+ // CHECK_EQ(key_data->GetKeyType(), kKeyTypePrivate);
1453
+ // ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey();
1454
+ // Mutex::ScopedLock lock(*m_pkey.mutex());
1455
+ //
1456
+ // BIOPointer bio(BIO_new(BIO_s_mem()));
1457
+ // CHECK(bio);
1458
+ // PKCS8Pointer p8inf(EVP_PKEY2PKCS8(m_pkey.get()));
1459
+ // if (!i2d_PKCS8_PRIV_KEY_INFO_bio(bio.get(), p8inf.get()))
1460
+ // return WebCryptoKeyExportStatus::FAILED;
1461
+ //
1462
+ // *out = ByteSource::FromBIO(bio);
1463
+ // return WebCryptoKeyExportStatus::OK;
1464
+ //}
1465
+
1466
+ // void RegisterExternalReferences(ExternalReferenceRegistry * registry) {
1467
+ // KeyObjectHandle::RegisterExternalReferences(registry);
1468
+ // }
1469
+ } // namespace margelo