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: 200 254 78.7 %
Date: 2020-12-12 04:11:07 Branches: 160 298 53.7 %

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
50
EVPKeyCtxPointer RsaKeyGenTraits::Setup(RsaKeyPairGenConfig* params) {
32
  EVPKeyCtxPointer ctx(
33
      EVP_PKEY_CTX_new_id(
34
50
          params->params.variant == kKeyVariantRSA_PSS
35
              ? EVP_PKEY_RSA_PSS
36
              : EVP_PKEY_RSA,
37
100
          nullptr));
38
39
50
  if (EVP_PKEY_keygen_init(ctx.get()) <= 0)
40
    return EVPKeyCtxPointer();
41
42
50
  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
50
  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
50
  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
50
  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
51
Maybe<bool> RsaKeyGenTraits::AdditionalConfig(
112
    CryptoJobMode mode,
113
    const FunctionCallbackInfo<Value>& args,
114
    unsigned int* offset,
115
    RsaKeyPairGenConfig* params) {
116
51
  Environment* env = Environment::GetCurrent(args);
117
118
153
  CHECK(args[*offset]->IsUint32());  // Variant
119
153
  CHECK(args[*offset + 1]->IsUint32());  // Modulus bits
120
153
  CHECK(args[*offset + 2]->IsUint32());  // Exponent
121
122
51
  params->params.variant =
123
255
      static_cast<RSAKeyVariant>(args[*offset].As<Uint32>()->Value());
124
125

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

52
  CHECK_IMPLIES(params->params.variant == kKeyVariantRSA_PSS,
128
                args.Length() == 13);
129
130
204
  params->params.modulus_bits = args[*offset + 1].As<Uint32>()->Value();
131
204
  params->params.exponent = args[*offset + 2].As<Uint32>()->Value();
132
133
51
  *offset += 3;
134
135
51
  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
51
  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
195
  EVPKeyCtxPointer ctx(
196
268
      EVP_PKEY_CTX_new(key_data->GetAsymmetricKey().get(), nullptr));
197
198



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

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



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

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

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

78
    CHECK_NOT_NULL(label);
215

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

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

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

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

152
  CHECK(type == EVP_PKEY_RSA || type == EVP_PKEY_RSA_PSS);
369
370
152
  RSA* rsa = EVP_PKEY_get0_RSA(pkey.get());
371
152
  CHECK_NOT_NULL(rsa);
372
373
  const BIGNUM* n;
374
  const BIGNUM* e;
375
  const BIGNUM* d;
376
  const BIGNUM* p;
377
  const BIGNUM* q;
378
  const BIGNUM* dp;
379
  const BIGNUM* dq;
380
  const BIGNUM* qi;
381
152
  RSA_get0_key(rsa, &n, &e, &d);
382
383
456
  if (target->Set(
384
          env->context(),
385
          env->jwk_kty_string(),
386
760
          env->jwk_rsa_string()).IsNothing()) {
387
    return Nothing<bool>();
388
  }
389
390

608
  if (SetEncodedValue(env, target, env->jwk_n_string(), n).IsNothing() ||
391
456
      SetEncodedValue(env, target, env->jwk_e_string(), e).IsNothing()) {
392
    return Nothing<bool>();
393
  }
394
395
152
  if (key->GetKeyType() == kKeyTypePrivate) {
396
70
    RSA_get0_factors(rsa, &p, &q);
397
70
    RSA_get0_crt_params(rsa, &dp, &dq, &qi);
398

350
    if (SetEncodedValue(env, target, env->jwk_d_string(), d).IsNothing() ||
399
280
        SetEncodedValue(env, target, env->jwk_p_string(), p).IsNothing() ||
400
280
        SetEncodedValue(env, target, env->jwk_q_string(), q).IsNothing() ||
401
280
        SetEncodedValue(env, target, env->jwk_dp_string(), dp).IsNothing() ||
402

350
        SetEncodedValue(env, target, env->jwk_dq_string(), dq).IsNothing() ||
403
210
        SetEncodedValue(env, target, env->jwk_qi_string(), qi).IsNothing()) {
404
      return Nothing<bool>();
405
    }
406
  }
407
408
152
  return Just(true);
409
}
410
411
170
std::shared_ptr<KeyObjectData> ImportJWKRsaKey(
412
    Environment* env,
413
    Local<Object> jwk,
414
    const FunctionCallbackInfo<Value>& args,
415
    unsigned int offset) {
416
  Local<Value> n_value;
417
  Local<Value> e_value;
418
  Local<Value> d_value;
419
420

1190
  if (!jwk->Get(env->context(), env->jwk_n_string()).ToLocal(&n_value) ||
421
1020
      !jwk->Get(env->context(), env->jwk_e_string()).ToLocal(&e_value) ||
422
1020
      !jwk->Get(env->context(), env->jwk_d_string()).ToLocal(&d_value) ||
423

680
      !n_value->IsString() ||
424
340
      !e_value->IsString()) {
425
    THROW_ERR_CRYPTO_INVALID_JWK(env, "Invalid JWK RSA key");
426
    return std::shared_ptr<KeyObjectData>();
427
  }
428
429

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

574
    if (!jwk->Get(env->context(), env->jwk_p_string()).ToLocal(&p_value) ||
458
492
        !jwk->Get(env->context(), env->jwk_q_string()).ToLocal(&q_value) ||
459
492
        !jwk->Get(env->context(), env->jwk_dp_string()).ToLocal(&dp_value) ||
460

574
        !jwk->Get(env->context(), env->jwk_dq_string()).ToLocal(&dq_value) ||
461
410
        !jwk->Get(env->context(), env->jwk_qi_string()).ToLocal(&qi_value)) {
462
      THROW_ERR_CRYPTO_INVALID_JWK(env, "Invalid JWK RSA key");
463
      return std::shared_ptr<KeyObjectData>();
464
    }
465
466

328
    if (!p_value->IsString() ||
467
246
        !q_value->IsString() ||
468
246
        !dp_value->IsString() ||
469

328
        !dq_value->IsString() ||
470
164
        !qi_value->IsString()) {
471
      THROW_ERR_CRYPTO_INVALID_JWK(env, "Invalid JWK RSA key");
472
      return std::shared_ptr<KeyObjectData>();
473
    }
474
475
164
    ByteSource d = ByteSource::FromEncodedString(env, d_value.As<String>());
476
164
    ByteSource q = ByteSource::FromEncodedString(env, q_value.As<String>());
477
164
    ByteSource p = ByteSource::FromEncodedString(env, p_value.As<String>());
478
164
    ByteSource dp = ByteSource::FromEncodedString(env, dp_value.As<String>());
479
164
    ByteSource dq = ByteSource::FromEncodedString(env, dq_value.As<String>());
480
164
    ByteSource qi = ByteSource::FromEncodedString(env, qi_value.As<String>());
481
482

574
    if (!RSA_set0_key(rsa.get(), nullptr, nullptr, d.ToBN().release()) ||
483


820
        !RSA_set0_factors(rsa.get(), p.ToBN().release(), q.ToBN().release()) ||
484
246
        !RSA_set0_crt_params(
485
            rsa.get(),
486
164
            dp.ToBN().release(),
487
164
            dq.ToBN().release(),
488
164
            qi.ToBN().release())) {
489
      THROW_ERR_CRYPTO_INVALID_JWK(env, "Invalid JWK RSA key");
490
      return std::shared_ptr<KeyObjectData>();
491
    }
492
  }
493
494
340
  EVPKeyPointer pkey(EVP_PKEY_new());
495
170
  CHECK_EQ(EVP_PKEY_set1_RSA(pkey.get(), rsa.get()), 1);
496
497
170
  return KeyObjectData::CreateAsymmetric(type, ManagedEVPPKey(std::move(pkey)));
498
}
499
500
601
Maybe<bool> GetRsaKeyDetail(
501
    Environment* env,
502
    std::shared_ptr<KeyObjectData> key,
503
    Local<Object> target) {
504
  const BIGNUM* e;  // Public Exponent
505
  const BIGNUM* n;  // Modulus
506
507
1202
  ManagedEVPPKey pkey = key->GetAsymmetricKey();
508
601
  int type = EVP_PKEY_id(pkey.get());
509

601
  CHECK(type == EVP_PKEY_RSA || type == EVP_PKEY_RSA_PSS);
510
511
601
  RSA* rsa = EVP_PKEY_get0_RSA(pkey.get());
512
601
  CHECK_NOT_NULL(rsa);
513
514
601
  RSA_get0_key(rsa, &n, &e, nullptr);
515
516
601
  size_t modulus_length = BN_num_bytes(n) * CHAR_BIT;
517
518
1803
  if (target->Set(
519
          env->context(),
520
          env->modulus_length_string(),
521
3005
          Number::New(env->isolate(), modulus_length)).IsNothing()) {
522
    return Nothing<bool>();
523
  }
524
525
601
  int len = BN_num_bytes(e);
526
1202
  AllocatedBuffer public_exponent = AllocatedBuffer::AllocateManaged(env, len);
527
  unsigned char* data =
528
601
      reinterpret_cast<unsigned char*>(public_exponent.data());
529
601
  CHECK_EQ(BN_bn2binpad(e, data, len), len);
530
531
  return target->Set(
532
      env->context(),
533
      env->public_exponent_string(),
534
2404
      public_exponent.ToArrayBuffer());
535
}
536
537
namespace RSAAlg {
538
656
void Initialize(Environment* env, Local<Object> target) {
539
656
  RSAKeyPairGenJob::Initialize(env, target);
540
656
  RSAKeyExportJob::Initialize(env, target);
541
656
  RSACipherJob::Initialize(env, target);
542
543
1312
  NODE_DEFINE_CONSTANT(target, kKeyVariantRSA_SSA_PKCS1_V1_5);
544
656
  NODE_DEFINE_CONSTANT(target, kKeyVariantRSA_PSS);
545
1968
  NODE_DEFINE_CONSTANT(target, kKeyVariantRSA_OAEP);
546
3280
}
547
4592
}  // namespace RSAAlg
548
3280
}  // namespace crypto
549

15385
}  // namespace node