GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: crypto/crypto_pbkdf2.cc Lines: 50 63 79.4 %
Date: 2022-08-28 04:20:35 Branches: 23 42 54.8 %

Line Branch Exec Source
1
#include "crypto/crypto_pbkdf2.h"
2
#include "async_wrap-inl.h"
3
#include "crypto/crypto_util.h"
4
#include "env-inl.h"
5
#include "memory_tracker-inl.h"
6
#include "node_buffer.h"
7
#include "threadpoolwork-inl.h"
8
#include "v8.h"
9
10
namespace node {
11
12
using v8::FunctionCallbackInfo;
13
using v8::Int32;
14
using v8::Just;
15
using v8::Maybe;
16
using v8::Nothing;
17
using v8::Value;
18
19
namespace crypto {
20
1896
PBKDF2Config::PBKDF2Config(PBKDF2Config&& other) noexcept
21
1896
    : mode(other.mode),
22
1896
      pass(std::move(other.pass)),
23
1896
      salt(std::move(other.salt)),
24
1896
      iterations(other.iterations),
25
1896
      length(other.length),
26
1896
      digest(other.digest) {}
27
28
PBKDF2Config& PBKDF2Config::operator=(PBKDF2Config&& other) noexcept {
29
  if (&other == this) return *this;
30
  this->~PBKDF2Config();
31
  return *new (this) PBKDF2Config(std::move(other));
32
}
33
34
1
void PBKDF2Config::MemoryInfo(MemoryTracker* tracker) const {
35
  // The job is sync, the PBKDF2Config does not own the data.
36
1
  if (mode == kCryptoJobAsync) {
37
1
    tracker->TrackFieldWithSize("pass", pass.size());
38
1
    tracker->TrackFieldWithSize("salt", salt.size());
39
  }
40
1
}
41
42
1896
Maybe<bool> PBKDF2Traits::EncodeOutput(
43
    Environment* env,
44
    const PBKDF2Config& params,
45
    ByteSource* out,
46
    v8::Local<v8::Value>* result) {
47
3792
  *result = out->ToArrayBuffer(env);
48
1896
  return Just(!result->IsEmpty());
49
}
50
51
// The input arguments for the job are:
52
//   1. CryptoJobMode
53
//   2. The password
54
//   3. The salt
55
//   4. The number of iterations
56
//   5. The number of bytes to generate
57
//   6. The digest algorithm name
58
1899
Maybe<bool> PBKDF2Traits::AdditionalConfig(
59
    CryptoJobMode mode,
60
    const FunctionCallbackInfo<Value>& args,
61
    unsigned int offset,
62
    PBKDF2Config* params) {
63
1899
  Environment* env = Environment::GetCurrent(args);
64
65
1899
  params->mode = mode;
66
67
3798
  ArrayBufferOrViewContents<char> pass(args[offset]);
68
3798
  ArrayBufferOrViewContents<char> salt(args[offset + 1]);
69
70
1899
  if (UNLIKELY(!pass.CheckSizeInt32())) {
71
    THROW_ERR_OUT_OF_RANGE(env, "pass is too large");
72
    return Nothing<bool>();
73
  }
74
75
1899
  if (UNLIKELY(!salt.CheckSizeInt32())) {
76
    THROW_ERR_OUT_OF_RANGE(env, "salt is too large");
77
    return Nothing<bool>();
78
  }
79
80
  params->pass = mode == kCryptoJobAsync
81
3798
      ? pass.ToCopy()
82
1899
      : pass.ToByteSource();
83
84
  params->salt = mode == kCryptoJobAsync
85
3798
      ? salt.ToCopy()
86
1899
      : salt.ToByteSource();
87
88

3798
  CHECK(args[offset + 2]->IsInt32());  // iteration_count
89

3798
  CHECK(args[offset + 3]->IsInt32());  // length
90

5697
  CHECK(args[offset + 4]->IsString());  // digest_name
91
92
5697
  params->iterations = args[offset + 2].As<Int32>()->Value();
93
1899
  if (params->iterations < 0) {
94
    THROW_ERR_OUT_OF_RANGE(env, "iterations must be <= %d", INT_MAX);
95
    return Nothing<bool>();
96
  }
97
98
5697
  params->length = args[offset + 3].As<Int32>()->Value();
99
1899
  if (params->length < 0) {
100
    THROW_ERR_OUT_OF_RANGE(env, "length must be <= %d", INT_MAX);
101
    return Nothing<bool>();
102
  }
103
104
5697
  Utf8Value name(args.GetIsolate(), args[offset + 4]);
105
1899
  params->digest = EVP_get_digestbyname(*name);
106
1899
  if (params->digest == nullptr) {
107
3
    THROW_ERR_CRYPTO_INVALID_DIGEST(env, "Invalid digest: %s", *name);
108
3
    return Nothing<bool>();
109
  }
110
111
1896
  return Just(true);
112
}
113
114
1896
bool PBKDF2Traits::DeriveBits(
115
    Environment* env,
116
    const PBKDF2Config& params,
117
    ByteSource* out) {
118
3792
  ByteSource::Builder buf(params.length);
119
120
  // Both pass and salt may be zero length here.
121
  // The generated bytes are stored in buf, which is
122
  // assigned to out on success.
123
124
5688
  if (PKCS5_PBKDF2_HMAC(params.pass.data<char>(),
125
1896
                        params.pass.size(),
126
                        params.salt.data<unsigned char>(),
127
1896
                        params.salt.size(),
128
1896
                        params.iterations,
129
1896
                        params.digest,
130
1896
                        params.length,
131
1896
                        buf.data<unsigned char>()) <= 0) {
132
    return false;
133
  }
134
1896
  *out = std::move(buf).release();
135
1896
  return true;
136
}
137
138
}  // namespace crypto
139
}  // namespace node