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_pbkdf2.cc Lines: 53 68 77.9 %
Date: 2021-04-17 04:11:57 Branches: 17 32 53.1 %

Line Branch Exec Source
1
#include "crypto/crypto_pbkdf2.h"
2
#include "crypto/crypto_util.h"
3
#include "allocated_buffer-inl.h"
4
#include "async_wrap-inl.h"
5
#include "env-inl.h"
6
#include "memory_tracker-inl.h"
7
#include "node_buffer.h"
8
#include "threadpoolwork-inl.h"
9
#include "v8.h"
10
11
namespace node {
12
13
using v8::FunctionCallbackInfo;
14
using v8::Int32;
15
using v8::Just;
16
using v8::Maybe;
17
using v8::Nothing;
18
using v8::Value;
19
20
namespace crypto {
21
1109
PBKDF2Config::PBKDF2Config(PBKDF2Config&& other) noexcept
22
1109
    : mode(other.mode),
23
1109
      pass(std::move(other.pass)),
24
1109
      salt(std::move(other.salt)),
25
1109
      iterations(other.iterations),
26
1109
      length(other.length),
27
6654
      digest(other.digest) {}
28
29
PBKDF2Config& PBKDF2Config::operator=(PBKDF2Config&& other) noexcept {
30
  if (&other == this) return *this;
31
  this->~PBKDF2Config();
32
  return *new (this) PBKDF2Config(std::move(other));
33
}
34
35
1
void PBKDF2Config::MemoryInfo(MemoryTracker* tracker) const {
36
  // The job is sync, the PBKDF2Config does not own the data.
37
1
  if (mode == kCryptoJobAsync) {
38
1
    tracker->TrackFieldWithSize("pass", pass.size());
39
1
    tracker->TrackFieldWithSize("salt", salt.size());
40
  }
41
1
}
42
43
1109
Maybe<bool> PBKDF2Traits::EncodeOutput(
44
    Environment* env,
45
    const PBKDF2Config& params,
46
    ByteSource* out,
47
    v8::Local<v8::Value>* result) {
48
2218
  *result = out->ToArrayBuffer(env);
49
1109
  return Just(!result->IsEmpty());
50
}
51
52
// The input arguments for the job are:
53
//   1. CryptoJobMode
54
//   2. The password
55
//   3. The salt
56
//   4. The number of iterations
57
//   5. The number of bytes to generate
58
//   6. The digest algorithm name
59
1111
Maybe<bool> PBKDF2Traits::AdditionalConfig(
60
    CryptoJobMode mode,
61
    const FunctionCallbackInfo<Value>& args,
62
    unsigned int offset,
63
    PBKDF2Config* params) {
64
1111
  Environment* env = Environment::GetCurrent(args);
65
66
1111
  params->mode = mode;
67
68
3333
  ArrayBufferOrViewContents<char> pass(args[offset]);
69
3333
  ArrayBufferOrViewContents<char> salt(args[offset + 1]);
70
71
1111
  if (UNLIKELY(!pass.CheckSizeInt32())) {
72
    THROW_ERR_OUT_OF_RANGE(env, "pass is too large");
73
    return Nothing<bool>();
74
  }
75
76
1111
  if (UNLIKELY(!salt.CheckSizeInt32())) {
77
    THROW_ERR_OUT_OF_RANGE(env, "salt is too large");
78
    return Nothing<bool>();
79
  }
80
81
  params->pass = mode == kCryptoJobAsync
82
2222
      ? pass.ToCopy()
83
1111
      : pass.ToByteSource();
84
85
  params->salt = mode == kCryptoJobAsync
86
2222
      ? salt.ToCopy()
87
1111
      : salt.ToByteSource();
88
89
3333
  CHECK(args[offset + 2]->IsInt32());  // iteration_count
90
3333
  CHECK(args[offset + 3]->IsInt32());  // length
91
4444
  CHECK(args[offset + 4]->IsString());  // digest_name
92
93
4444
  params->iterations = args[offset + 2].As<Int32>()->Value();
94
1111
  if (params->iterations < 0) {
95
    char msg[1024];
96
    snprintf(msg, sizeof(msg), "iterations must be <= %d", INT_MAX);
97
    THROW_ERR_OUT_OF_RANGE(env, msg);
98
    return Nothing<bool>();
99
  }
100
101
4444
  params->length = args[offset + 3].As<Int32>()->Value();
102
1111
  if (params->length < 0) {
103
    char msg[1024];
104
    snprintf(msg, sizeof(msg), "length must be <= %d", INT_MAX);
105
    THROW_ERR_OUT_OF_RANGE(env, msg);
106
    return Nothing<bool>();
107
  }
108
109
3333
  Utf8Value name(args.GetIsolate(), args[offset + 4]);
110
1111
  params->digest = EVP_get_digestbyname(*name);
111
1111
  if (params->digest == nullptr) {
112
    char errmsg[1024];
113
2
    snprintf(errmsg, sizeof(errmsg), "Invalid digest: %s", *name);
114
2
    THROW_ERR_CRYPTO_INVALID_DIGEST(env, errmsg);
115
2
    return Nothing<bool>();
116
  }
117
118
1109
  return Just(true);
119
}
120
121
1109
bool PBKDF2Traits::DeriveBits(
122
    Environment* env,
123
    const PBKDF2Config& params,
124
    ByteSource* out) {
125
1109
  char* data = MallocOpenSSL<char>(params.length);
126
2217
  ByteSource buf = ByteSource::Allocated(data, params.length);
127
1109
  unsigned char* ptr = reinterpret_cast<unsigned char*>(data);
128
129
  // Both pass and salt may be zero length here.
130
  // The generated bytes are stored in buf, which is
131
  // assigned to out on success.
132
133
2218
  if (PKCS5_PBKDF2_HMAC(
134
          params.pass.get(),
135
1109
          params.pass.size(),
136
          params.salt.data<unsigned char>(),
137
1109
          params.salt.size(),
138
1109
          params.iterations,
139
1109
          params.digest,
140
1109
          params.length,
141
          ptr) <= 0) {
142
    return false;
143
  }
144
1108
  *out = std::move(buf);
145
1108
  return true;
146
}
147
148
}  // namespace crypto
149

14310
}  // namespace node