GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/crypto/crypto_rsa.cc Lines: 207 263 78.7 %
Date: 2021-04-23 04:11:39 Branches: 164 302 54.3 %

Line Branch Exec Source
1
#include "crypto/crypto_rsa.h"
2
#include "crypto/crypto_bio.h"
3
#include "crypto/crypto_keys.h"
4
#include "crypto/crypto_util.h"
5
#include "allocated_buffer-inl.h"
6
#include "async_wrap-inl.h"
7
#include "base_object-inl.h"
8
#include "env-inl.h"
9
#include "memory_tracker-inl.h"
10
#include "threadpoolwork-inl.h"
11
#include "v8.h"
12
13
#include <openssl/bn.h>
14
#include <openssl/rsa.h>
15
16
namespace node {
17
18
using v8::FunctionCallbackInfo;
19
using v8::Int32;
20
using v8::Just;
21
using v8::Local;
22
using v8::Maybe;
23
using v8::Nothing;
24
using v8::Number;
25
using v8::Object;
26
using v8::String;
27
using v8::Uint32;
28
using v8::Value;
29
30
namespace crypto {
31
51
EVPKeyCtxPointer RsaKeyGenTraits::Setup(RsaKeyPairGenConfig* params) {
32
  EVPKeyCtxPointer ctx(
33
      EVP_PKEY_CTX_new_id(
34
51
          params->params.variant == kKeyVariantRSA_PSS
35
              ? EVP_PKEY_RSA_PSS
36
              : EVP_PKEY_RSA,
37
102
          nullptr));
38
39
51
  if (EVP_PKEY_keygen_init(ctx.get()) <= 0)
40
    return EVPKeyCtxPointer();
41
42
51
  if (EVP_PKEY_CTX_set_rsa_keygen_bits(
43
          ctx.get(),
44
          params->params.modulus_bits) <= 0) {
45
    return EVPKeyCtxPointer();
46
  }
47
48
  // 0x10001 is the default RSA exponent.
49
51
  if (params->params.exponent != 0x10001) {
50
4
    BignumPointer bn(BN_new());
51
2
    CHECK_NOT_NULL(bn.get());
52
2
    CHECK(BN_set_word(bn.get(), params->params.exponent));
53
    // EVP_CTX accepts ownership of bn on success.
54
2
    if (EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx.get(), bn.get()) <= 0)
55
      return EVPKeyCtxPointer();
56
57
2
    bn.release();
58
  }
59
60
51
  if (params->params.variant == kKeyVariantRSA_PSS) {
61

2
    if (params->params.md != nullptr &&
62
1
        EVP_PKEY_CTX_set_rsa_pss_keygen_md(ctx.get(), params->params.md) <= 0) {
63
      return EVPKeyCtxPointer();
64
    }
65
66

2
    if (params->params.mgf1_md != nullptr &&
67
1
        EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(
68
            ctx.get(),
69
            params->params.mgf1_md) <= 0) {
70
      return EVPKeyCtxPointer();
71
    }
72
73

2
    if (params->params.saltlen >= 0 &&
74
1
        EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(
75
            ctx.get(),
76
            params->params.saltlen) <= 0) {
77
      return EVPKeyCtxPointer();
78
    }
79
  }
80
81
51
  return ctx;
82
}
83
84
// Input parameters to the RsaKeyGenJob:
85
// For key variants RSA-OAEP and RSA-SSA-PKCS1-v1_5
86
//   1. CryptoJobMode
87
//   2. Key Variant
88
//   3. Modulus Bits
89
//   4. Public Exponent
90
//   5. Public Format
91
//   6. Public Type
92
//   7. Private Format
93
//   8. Private Type
94
//   9. Cipher
95
//   10. Passphrase
96
//
97
// For RSA-PSS variant
98
//   1. CryptoJobMode
99
//   2. Key Variant
100
//   3. Modulus Bits
101
//   4. Public Exponent
102
//   5. Digest
103
//   6. mgf1 Digest
104
//   7. Salt length
105
//   8. Public Format
106
//   9. Public Type
107
//   10. Private Format
108
//   11. Private Type
109
//   12. Cipher
110
//   13. Passphrase
111
52
Maybe<bool> RsaKeyGenTraits::AdditionalConfig(
112
    CryptoJobMode mode,
113
    const FunctionCallbackInfo<Value>& args,
114
    unsigned int* offset,
115
    RsaKeyPairGenConfig* params) {
116
52
  Environment* env = Environment::GetCurrent(args);
117
118
156
  CHECK(args[*offset]->IsUint32());  // Variant
119
156
  CHECK(args[*offset + 1]->IsUint32());  // Modulus bits
120
156
  CHECK(args[*offset + 2]->IsUint32());  // Exponent
121
122
52
  params->params.variant =
123
260
      static_cast<RSAKeyVariant>(args[*offset].As<Uint32>()->Value());
124
125

103
  CHECK_IMPLIES(params->params.variant != kKeyVariantRSA_PSS,
126
                args.Length() == 10);
127

53
  CHECK_IMPLIES(params->params.variant == kKeyVariantRSA_PSS,
128
                args.Length() == 13);
129
130
208
  params->params.modulus_bits = args[*offset + 1].As<Uint32>()->Value();
131
208
  params->params.exponent = args[*offset + 2].As<Uint32>()->Value();
132
133
52
  *offset += 3;
134
135
52
  if (params->params.variant == kKeyVariantRSA_PSS) {
136
4
    if (!args[*offset]->IsUndefined()) {
137
4
      CHECK(args[*offset]->IsString());
138
3
      Utf8Value digest(env->isolate(), args[*offset]);
139
1
      params->params.md = EVP_get_digestbyname(*digest);
140
1
      if (params->params.md == nullptr) {
141
        char msg[1024];
142
        snprintf(msg, sizeof(msg), "md specifies an invalid digest");
143
        THROW_ERR_CRYPTO_INVALID_DIGEST(env, msg);
144
        return Nothing<bool>();
145
      }
146
    }
147
148
4
    if (!args[*offset + 1]->IsUndefined()) {
149
4
      CHECK(args[*offset + 1]->IsString());
150
3
      Utf8Value digest(env->isolate(), args[*offset + 1]);
151
1
      params->params.mgf1_md = EVP_get_digestbyname(*digest);
152
1
      if (params->params.mgf1_md == nullptr) {
153
        char msg[1024];
154
        snprintf(msg, sizeof(msg), "mgf1_md specifies an invalid digest");
155
        THROW_ERR_CRYPTO_INVALID_DIGEST(env, msg);
156
        return Nothing<bool>();
157
      }
158
    }
159
160
4
    if (!args[*offset + 2]->IsUndefined()) {
161
3
      CHECK(args[*offset + 2]->IsInt32());
162
4
      params->params.saltlen = args[*offset + 2].As<Int32>()->Value();
163
1
      if (params->params.saltlen < 0) {
164
        char msg[1024];
165
        snprintf(msg, sizeof(msg), "salt length is out of range");
166
        THROW_ERR_OUT_OF_RANGE(env, msg);
167
        return Nothing<bool>();
168
      }
169
    }
170
171
1
    *offset += 3;
172
  }
173
174
52
  return Just(true);
175
}
176
177
namespace {
178
WebCryptoKeyExportStatus RSA_JWK_Export(
179
    KeyObjectData* key_data,
180
    const RSAKeyExportConfig& params,
181
    ByteSource* out) {
182
  return WebCryptoKeyExportStatus::FAILED;
183
}
184
185
template <PublicKeyCipher::EVP_PKEY_cipher_init_t init,
186
          PublicKeyCipher::EVP_PKEY_cipher_t cipher>
187
134
WebCryptoCipherStatus RSA_Cipher(
188
    Environment* env,
189
    KeyObjectData* key_data,
190
    const RSACipherConfig& params,
191
    const ByteSource& in,
192
    ByteSource* out) {
193

134
  CHECK_NE(key_data->GetKeyType(), kKeyTypeSecret);
194
268
  ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey();
195
268
  Mutex::ScopedLock lock(*m_pkey.mutex());
196
197
268
  EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new(m_pkey.get(), nullptr));
198
199



134
  if (!ctx || init(ctx.get()) <= 0)
200
    return WebCryptoCipherStatus::FAILED;
201
202

134
  if (EVP_PKEY_CTX_set_rsa_padding(ctx.get(), params.padding) <= 0) {
203
    return WebCryptoCipherStatus::FAILED;
204
  }
205
206



268
  if (params.digest != nullptr &&
207

268
      (EVP_PKEY_CTX_set_rsa_oaep_md(ctx.get(), params.digest) <= 0 ||
208
134
       EVP_PKEY_CTX_set_rsa_mgf1_md(ctx.get(), params.digest) <= 0)) {
209
    return WebCryptoCipherStatus::FAILED;
210
  }
211
212
134
  size_t label_len = params.label.size();
213

134
  if (label_len > 0) {
214
78
    void* label = OPENSSL_memdup(params.label.get(), label_len);
215

78
    CHECK_NOT_NULL(label);
216

78
    if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx.get(), label, label_len) <= 0) {
217
      OPENSSL_free(label);
218
      return WebCryptoCipherStatus::FAILED;
219
    }
220
  }
221
222
134
  size_t out_len = 0;
223

134
  if (cipher(
224
          ctx.get(),
225
          nullptr,
226
          &out_len,
227
          in.data<unsigned char>(),
228
          in.size()) <= 0) {
229
    return WebCryptoCipherStatus::FAILED;
230
  }
231
232
134
  char* data = MallocOpenSSL<char>(out_len);
233
268
  ByteSource buf = ByteSource::Allocated(data, out_len);
234
134
  unsigned char* ptr = reinterpret_cast<unsigned char*>(data);
235
236

134
  if (cipher(
237
          ctx.get(),
238
          ptr,
239
          &out_len,
240
          in.data<unsigned char>(),
241
          in.size()) <= 0) {
242
12
    return WebCryptoCipherStatus::FAILED;
243
  }
244
245
122
  buf.Resize(out_len);
246
247
122
  *out = std::move(buf);
248
122
  return WebCryptoCipherStatus::OK;
249
}
250
}  // namespace
251
252
146
Maybe<bool> RSAKeyExportTraits::AdditionalConfig(
253
    const FunctionCallbackInfo<Value>& args,
254
    unsigned int offset,
255
    RSAKeyExportConfig* params) {
256
438
  CHECK(args[offset]->IsUint32());  // RSAKeyVariant
257
146
  params->variant =
258
730
      static_cast<RSAKeyVariant>(args[offset].As<Uint32>()->Value());
259
146
  return Just(true);
260
}
261
262
146
WebCryptoKeyExportStatus RSAKeyExportTraits::DoExport(
263
    std::shared_ptr<KeyObjectData> key_data,
264
    WebCryptoKeyFormat format,
265
    const RSAKeyExportConfig& params,
266
    ByteSource* out) {
267
146
  CHECK_NE(key_data->GetKeyType(), kKeyTypeSecret);
268
269

146
  switch (format) {
270
    case kWebCryptoKeyFormatRaw:
271
      // Not supported for RSA keys of either type
272
      return WebCryptoKeyExportStatus::FAILED;
273
    case kWebCryptoKeyFormatJWK:
274
      return RSA_JWK_Export(key_data.get(), params, out);
275
    case kWebCryptoKeyFormatPKCS8:
276
70
      if (key_data->GetKeyType() != kKeyTypePrivate)
277
        return WebCryptoKeyExportStatus::INVALID_KEY_TYPE;
278
70
      return PKEY_PKCS8_Export(key_data.get(), out);
279
    case kWebCryptoKeyFormatSPKI:
280
76
      if (key_data->GetKeyType() != kKeyTypePublic)
281
        return WebCryptoKeyExportStatus::INVALID_KEY_TYPE;
282
76
      return PKEY_SPKI_Export(key_data.get(), out);
283
    default:
284
      UNREACHABLE();
285
  }
286
}
287
288
134
RSACipherConfig::RSACipherConfig(RSACipherConfig&& other) noexcept
289
134
    : mode(other.mode),
290
134
      label(std::move(other.label)),
291
134
      padding(other.padding),
292
536
      digest(other.digest) {}
293
294
void RSACipherConfig::MemoryInfo(MemoryTracker* tracker) const {
295
  if (mode == kCryptoJobAsync)
296
    tracker->TrackFieldWithSize("label", label.size());
297
}
298
299
134
Maybe<bool> RSACipherTraits::AdditionalConfig(
300
    CryptoJobMode mode,
301
    const FunctionCallbackInfo<Value>& args,
302
    unsigned int offset,
303
    WebCryptoCipherMode cipher_mode,
304
    RSACipherConfig* params) {
305
134
  Environment* env = Environment::GetCurrent(args);
306
307
134
  params->mode = mode;
308
134
  params->padding = RSA_PKCS1_OAEP_PADDING;
309
310
402
  CHECK(args[offset]->IsUint32());
311
  RSAKeyVariant variant =
312
536
      static_cast<RSAKeyVariant>(args[offset].As<Uint32>()->Value());
313
314
134
  switch (variant) {
315
    case kKeyVariantRSA_OAEP: {
316
536
      CHECK(args[offset + 1]->IsString());  // digest
317
268
      Utf8Value digest(env->isolate(), args[offset + 1]);
318
319
134
      params->digest = EVP_get_digestbyname(*digest);
320
134
      if (params->digest == nullptr) {
321
        THROW_ERR_CRYPTO_INVALID_DIGEST(env);
322
        return Nothing<bool>();
323
      }
324
325
268
      if (IsAnyByteSource(args[offset + 2])) {
326
318
        ArrayBufferOrViewContents<char> label(args[offset + 2]);
327
106
        if (UNLIKELY(!label.CheckSizeInt32())) {
328
          THROW_ERR_OUT_OF_RANGE(env, "label is too big");
329
          return Nothing<bool>();
330
        }
331
106
        params->label = label.ToCopy();
332
      }
333
134
      break;
334
    }
335
    default:
336
      THROW_ERR_CRYPTO_INVALID_KEYTYPE(env);
337
      return Nothing<bool>();
338
  }
339
340
134
  return Just(true);
341
}
342
343
134
WebCryptoCipherStatus RSACipherTraits::DoCipher(
344
    Environment* env,
345
    std::shared_ptr<KeyObjectData> key_data,
346
    WebCryptoCipherMode cipher_mode,
347
    const RSACipherConfig& params,
348
    const ByteSource& in,
349
    ByteSource* out) {
350
134
  switch (cipher_mode) {
351
    case kWebCryptoCipherEncrypt:
352
61
      CHECK_EQ(key_data->GetKeyType(), kKeyTypePublic);
353
61
      return RSA_Cipher<EVP_PKEY_encrypt_init, EVP_PKEY_encrypt>(
354
61
          env, key_data.get(), params, in, out);
355
    case kWebCryptoCipherDecrypt:
356
73
      CHECK_EQ(key_data->GetKeyType(), kKeyTypePrivate);
357
73
      return RSA_Cipher<EVP_PKEY_decrypt_init, EVP_PKEY_decrypt>(
358
73
          env, key_data.get(), params, in, out);
359
  }
360
  return WebCryptoCipherStatus::FAILED;
361
}
362
363
157
Maybe<bool> ExportJWKRsaKey(
364
    Environment* env,
365
    std::shared_ptr<KeyObjectData> key,
366
    Local<Object> target) {
367
314
  ManagedEVPPKey m_pkey = key->GetAsymmetricKey();
368
314
  Mutex::ScopedLock lock(*m_pkey.mutex());
369
157
  int type = EVP_PKEY_id(m_pkey.get());
370

157
  CHECK(type == EVP_PKEY_RSA || type == EVP_PKEY_RSA_PSS);
371
372
  // TODO(tniessen): Remove the "else" branch once we drop support for OpenSSL
373
  // versions older than 1.1.1e via FIPS / dynamic linking.
374
  const RSA* rsa;
375
157
  if (OpenSSL_version_num() >= 0x1010105fL) {
376
157
    rsa = EVP_PKEY_get0_RSA(m_pkey.get());
377
  } else {
378
    rsa = static_cast<const RSA*>(EVP_PKEY_get0(m_pkey.get()));
379
  }
380
157
  CHECK_NOT_NULL(rsa);
381
382
  const BIGNUM* n;
383
  const BIGNUM* e;
384
  const BIGNUM* d;
385
  const BIGNUM* p;
386
  const BIGNUM* q;
387
  const BIGNUM* dp;
388
  const BIGNUM* dq;
389
  const BIGNUM* qi;
390
157
  RSA_get0_key(rsa, &n, &e, &d);
391
392
471
  if (target->Set(
393
          env->context(),
394
          env->jwk_kty_string(),
395
785
          env->jwk_rsa_string()).IsNothing()) {
396
    return Nothing<bool>();
397
  }
398
399

628
  if (SetEncodedValue(env, target, env->jwk_n_string(), n).IsNothing() ||
400
471
      SetEncodedValue(env, target, env->jwk_e_string(), e).IsNothing()) {
401
    return Nothing<bool>();
402
  }
403
404
157
  if (key->GetKeyType() == kKeyTypePrivate) {
405
72
    RSA_get0_factors(rsa, &p, &q);
406
72
    RSA_get0_crt_params(rsa, &dp, &dq, &qi);
407

360
    if (SetEncodedValue(env, target, env->jwk_d_string(), d).IsNothing() ||
408
288
        SetEncodedValue(env, target, env->jwk_p_string(), p).IsNothing() ||
409
288
        SetEncodedValue(env, target, env->jwk_q_string(), q).IsNothing() ||
410
288
        SetEncodedValue(env, target, env->jwk_dp_string(), dp).IsNothing() ||
411

360
        SetEncodedValue(env, target, env->jwk_dq_string(), dq).IsNothing() ||
412
216
        SetEncodedValue(env, target, env->jwk_qi_string(), qi).IsNothing()) {
413
      return Nothing<bool>();
414
    }
415
  }
416
417
157
  return Just(true);
418
}
419
420
186
std::shared_ptr<KeyObjectData> ImportJWKRsaKey(
421
    Environment* env,
422
    Local<Object> jwk,
423
    const FunctionCallbackInfo<Value>& args,
424
    unsigned int offset) {
425
  Local<Value> n_value;
426
  Local<Value> e_value;
427
  Local<Value> d_value;
428
429

1302
  if (!jwk->Get(env->context(), env->jwk_n_string()).ToLocal(&n_value) ||
430
1116
      !jwk->Get(env->context(), env->jwk_e_string()).ToLocal(&e_value) ||
431
1116
      !jwk->Get(env->context(), env->jwk_d_string()).ToLocal(&d_value) ||
432

744
      !n_value->IsString() ||
433
372
      !e_value->IsString()) {
434
    THROW_ERR_CRYPTO_INVALID_JWK(env, "Invalid JWK RSA key");
435
    return std::shared_ptr<KeyObjectData>();
436
  }
437
438

558
  if (!d_value->IsUndefined() && !d_value->IsString()) {
439
    THROW_ERR_CRYPTO_INVALID_JWK(env, "Invalid JWK RSA key");
440
    return std::shared_ptr<KeyObjectData>();
441
  }
442
443
372
  KeyType type = d_value->IsString() ? kKeyTypePrivate : kKeyTypePublic;
444
445
372
  RsaPointer rsa(RSA_new());
446
447
372
  ByteSource n = ByteSource::FromEncodedString(env, n_value.As<String>());
448
372
  ByteSource e = ByteSource::FromEncodedString(env, e_value.As<String>());
449
450
558
  if (!RSA_set0_key(
451
          rsa.get(),
452
372
          n.ToBN().release(),
453
372
          e.ToBN().release(),
454
          nullptr)) {
455
    THROW_ERR_CRYPTO_INVALID_JWK(env, "Invalid JWK RSA key");
456
    return std::shared_ptr<KeyObjectData>();
457
  }
458
459
186
  if (type == kKeyTypePrivate) {
460
    Local<Value> p_value;
461
    Local<Value> q_value;
462
    Local<Value> dp_value;
463
    Local<Value> dq_value;
464
    Local<Value> qi_value;
465
466

651
    if (!jwk->Get(env->context(), env->jwk_p_string()).ToLocal(&p_value) ||
467
558
        !jwk->Get(env->context(), env->jwk_q_string()).ToLocal(&q_value) ||
468
558
        !jwk->Get(env->context(), env->jwk_dp_string()).ToLocal(&dp_value) ||
469

651
        !jwk->Get(env->context(), env->jwk_dq_string()).ToLocal(&dq_value) ||
470
465
        !jwk->Get(env->context(), env->jwk_qi_string()).ToLocal(&qi_value)) {
471
      THROW_ERR_CRYPTO_INVALID_JWK(env, "Invalid JWK RSA key");
472
      return std::shared_ptr<KeyObjectData>();
473
    }
474
475

372
    if (!p_value->IsString() ||
476
279
        !q_value->IsString() ||
477
279
        !dp_value->IsString() ||
478

372
        !dq_value->IsString() ||
479
186
        !qi_value->IsString()) {
480
      THROW_ERR_CRYPTO_INVALID_JWK(env, "Invalid JWK RSA key");
481
      return std::shared_ptr<KeyObjectData>();
482
    }
483
484
186
    ByteSource d = ByteSource::FromEncodedString(env, d_value.As<String>());
485
186
    ByteSource q = ByteSource::FromEncodedString(env, q_value.As<String>());
486
186
    ByteSource p = ByteSource::FromEncodedString(env, p_value.As<String>());
487
186
    ByteSource dp = ByteSource::FromEncodedString(env, dp_value.As<String>());
488
186
    ByteSource dq = ByteSource::FromEncodedString(env, dq_value.As<String>());
489
186
    ByteSource qi = ByteSource::FromEncodedString(env, qi_value.As<String>());
490
491

651
    if (!RSA_set0_key(rsa.get(), nullptr, nullptr, d.ToBN().release()) ||
492


930
        !RSA_set0_factors(rsa.get(), p.ToBN().release(), q.ToBN().release()) ||
493
279
        !RSA_set0_crt_params(
494
            rsa.get(),
495
186
            dp.ToBN().release(),
496
186
            dq.ToBN().release(),
497
186
            qi.ToBN().release())) {
498
      THROW_ERR_CRYPTO_INVALID_JWK(env, "Invalid JWK RSA key");
499
      return std::shared_ptr<KeyObjectData>();
500
    }
501
  }
502
503
372
  EVPKeyPointer pkey(EVP_PKEY_new());
504
186
  CHECK_EQ(EVP_PKEY_set1_RSA(pkey.get(), rsa.get()), 1);
505
506
186
  return KeyObjectData::CreateAsymmetric(type, ManagedEVPPKey(std::move(pkey)));
507
}
508
509
615
Maybe<bool> GetRsaKeyDetail(
510
    Environment* env,
511
    std::shared_ptr<KeyObjectData> key,
512
    Local<Object> target) {
513
  const BIGNUM* e;  // Public Exponent
514
  const BIGNUM* n;  // Modulus
515
516
1230
  ManagedEVPPKey m_pkey = key->GetAsymmetricKey();
517
1230
  Mutex::ScopedLock lock(*m_pkey.mutex());
518
615
  int type = EVP_PKEY_id(m_pkey.get());
519

615
  CHECK(type == EVP_PKEY_RSA || type == EVP_PKEY_RSA_PSS);
520
521
  // TODO(tniessen): Remove the "else" branch once we drop support for OpenSSL
522
  // versions older than 1.1.1e via FIPS / dynamic linking.
523
  const RSA* rsa;
524
615
  if (OpenSSL_version_num() >= 0x1010105fL) {
525
615
    rsa = EVP_PKEY_get0_RSA(m_pkey.get());
526
  } else {
527
    rsa = static_cast<const RSA*>(EVP_PKEY_get0(m_pkey.get()));
528
  }
529
615
  CHECK_NOT_NULL(rsa);
530
531
615
  RSA_get0_key(rsa, &n, &e, nullptr);
532
533
615
  size_t modulus_length = BN_num_bytes(n) * CHAR_BIT;
534
535
1230
  if (target
536
1230
          ->Set(
537
              env->context(),
538
              env->modulus_length_string(),
539
3075
              Number::New(env->isolate(), static_cast<double>(modulus_length)))
540
          .IsNothing()) {
541
    return Nothing<bool>();
542
  }
543
544
615
  int len = BN_num_bytes(e);
545
1230
  AllocatedBuffer public_exponent = AllocatedBuffer::AllocateManaged(env, len);
546
  unsigned char* data =
547
615
      reinterpret_cast<unsigned char*>(public_exponent.data());
548
615
  CHECK_EQ(BN_bn2binpad(e, data, len), len);
549
550
  return target->Set(
551
      env->context(),
552
      env->public_exponent_string(),
553
2460
      public_exponent.ToArrayBuffer());
554
}
555
556
namespace RSAAlg {
557
4099
void Initialize(Environment* env, Local<Object> target) {
558
4099
  RSAKeyPairGenJob::Initialize(env, target);
559
4099
  RSAKeyExportJob::Initialize(env, target);
560
4099
  RSACipherJob::Initialize(env, target);
561
562
8198
  NODE_DEFINE_CONSTANT(target, kKeyVariantRSA_SSA_PKCS1_v1_5);
563
4099
  NODE_DEFINE_CONSTANT(target, kKeyVariantRSA_PSS);
564
12297
  NODE_DEFINE_CONSTANT(target, kKeyVariantRSA_OAEP);
565
20495
}
566
28693
}  // namespace RSAAlg
567
20495
}  // namespace crypto
568

22511
}  // namespace node