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 260 79.6 %
Date: 2021-06-04 04:12:13 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
        THROW_ERR_CRYPTO_INVALID_DIGEST(env, "md specifies an invalid digest");
142
        return Nothing<bool>();
143
      }
144
    }
145
146
4
    if (!args[*offset + 1]->IsUndefined()) {
147
4
      CHECK(args[*offset + 1]->IsString());
148
3
      Utf8Value digest(env->isolate(), args[*offset + 1]);
149
1
      params->params.mgf1_md = EVP_get_digestbyname(*digest);
150
1
      if (params->params.mgf1_md == nullptr) {
151
        THROW_ERR_CRYPTO_INVALID_DIGEST(env,
152
          "mgf1_md specifies an invalid digest");
153
        return Nothing<bool>();
154
      }
155
    }
156
157
4
    if (!args[*offset + 2]->IsUndefined()) {
158
3
      CHECK(args[*offset + 2]->IsInt32());
159
4
      params->params.saltlen = args[*offset + 2].As<Int32>()->Value();
160
1
      if (params->params.saltlen < 0) {
161
        THROW_ERR_OUT_OF_RANGE(
162
          env,
163
          "salt length is out of range");
164
        return Nothing<bool>();
165
      }
166
    }
167
168
1
    *offset += 3;
169
  }
170
171
52
  return Just(true);
172
}
173
174
namespace {
175
WebCryptoKeyExportStatus RSA_JWK_Export(
176
    KeyObjectData* key_data,
177
    const RSAKeyExportConfig& params,
178
    ByteSource* out) {
179
  return WebCryptoKeyExportStatus::FAILED;
180
}
181
182
template <PublicKeyCipher::EVP_PKEY_cipher_init_t init,
183
          PublicKeyCipher::EVP_PKEY_cipher_t cipher>
184
134
WebCryptoCipherStatus RSA_Cipher(
185
    Environment* env,
186
    KeyObjectData* key_data,
187
    const RSACipherConfig& params,
188
    const ByteSource& in,
189
    ByteSource* out) {
190

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



134
  if (!ctx || init(ctx.get()) <= 0)
197
    return WebCryptoCipherStatus::FAILED;
198
199

134
  if (EVP_PKEY_CTX_set_rsa_padding(ctx.get(), params.padding) <= 0) {
200
    return WebCryptoCipherStatus::FAILED;
201
  }
202
203



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

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

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

78
    CHECK_NOT_NULL(label);
213

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

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

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

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

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

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

360
    if (SetEncodedValue(env, target, env->jwk_d_string(), d).IsNothing() ||
405
288
        SetEncodedValue(env, target, env->jwk_p_string(), p).IsNothing() ||
406
288
        SetEncodedValue(env, target, env->jwk_q_string(), q).IsNothing() ||
407
288
        SetEncodedValue(env, target, env->jwk_dp_string(), dp).IsNothing() ||
408

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

1302
  if (!jwk->Get(env->context(), env->jwk_n_string()).ToLocal(&n_value) ||
427
1116
      !jwk->Get(env->context(), env->jwk_e_string()).ToLocal(&e_value) ||
428
1116
      !jwk->Get(env->context(), env->jwk_d_string()).ToLocal(&d_value) ||
429

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

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

651
    if (!jwk->Get(env->context(), env->jwk_p_string()).ToLocal(&p_value) ||
464
558
        !jwk->Get(env->context(), env->jwk_q_string()).ToLocal(&q_value) ||
465
558
        !jwk->Get(env->context(), env->jwk_dp_string()).ToLocal(&dp_value) ||
466

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

372
    if (!p_value->IsString() ||
473
279
        !q_value->IsString() ||
474
279
        !dp_value->IsString() ||
475

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

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


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

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

22870
}  // namespace node