GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: crypto/crypto_hkdf.cc Lines: 58 73 79.5 %
Date: 2021-10-04 04:12:38 Branches: 35 66 53.0 %

Line Branch Exec Source
1
#include "crypto/crypto_hkdf.h"
2
#include "crypto/crypto_keys.h"
3
#include "allocated_buffer-inl.h"
4
#include "async_wrap-inl.h"
5
#include "base_object-inl.h"
6
#include "env-inl.h"
7
#include "memory_tracker-inl.h"
8
#include "threadpoolwork-inl.h"
9
#include "v8.h"
10
11
namespace node {
12
13
using v8::FunctionCallbackInfo;
14
using v8::Just;
15
using v8::Maybe;
16
using v8::Nothing;
17
using v8::Uint32;
18
using v8::Value;
19
20
namespace crypto {
21
513
HKDFConfig::HKDFConfig(HKDFConfig&& other) noexcept
22
513
    : mode(other.mode),
23
513
      length(other.length),
24
513
      digest(other.digest),
25
513
      key(other.key),
26
513
      salt(std::move(other.salt)),
27
513
      info(std::move(other.info)) {}
28
29
HKDFConfig& HKDFConfig::operator=(HKDFConfig&& other) noexcept {
30
  if (&other == this) return *this;
31
  this->~HKDFConfig();
32
  return *new (this) HKDFConfig(std::move(other));
33
}
34
35
513
Maybe<bool> HKDFTraits::EncodeOutput(
36
    Environment* env,
37
    const HKDFConfig& params,
38
    ByteSource* out,
39
    v8::Local<v8::Value>* result) {
40
1026
  *result = out->ToArrayBuffer(env);
41
513
  return Just(!result->IsEmpty());
42
}
43
44
517
Maybe<bool> HKDFTraits::AdditionalConfig(
45
    CryptoJobMode mode,
46
    const FunctionCallbackInfo<Value>& args,
47
    unsigned int offset,
48
    HKDFConfig* params) {
49
517
  Environment* env = Environment::GetCurrent(args);
50
51
517
  params->mode = mode;
52
53

1551
  CHECK(args[offset]->IsString());  // Hash
54

1034
  CHECK(args[offset + 1]->IsObject());  // Key
55

1034
  CHECK(IsAnyByteSource(args[offset + 2]));  // Salt
56

1034
  CHECK(IsAnyByteSource(args[offset + 3]));  // Info
57

1034
  CHECK(args[offset + 4]->IsUint32());  // Length
58
59
1551
  Utf8Value hash(env->isolate(), args[offset]);
60
517
  params->digest = EVP_get_digestbyname(*hash);
61
517
  if (params->digest == nullptr) {
62
2
    THROW_ERR_CRYPTO_INVALID_DIGEST(env);
63
2
    return Nothing<bool>();
64
  }
65
66
  KeyObjectHandle* key;
67

1030
  ASSIGN_OR_RETURN_UNWRAP(&key, args[offset + 1], Nothing<bool>());
68
515
  params->key = key->Data();
69
70
1545
  ArrayBufferOrViewContents<char> salt(args[offset + 2]);
71
1545
  ArrayBufferOrViewContents<char> info(args[offset + 3]);
72
73
515
  if (UNLIKELY(!salt.CheckSizeInt32())) {
74
    THROW_ERR_OUT_OF_RANGE(env, "salt is too big");
75
    return Nothing<bool>();
76
  }
77
515
  if (UNLIKELY(!info.CheckSizeInt32())) {
78
    THROW_ERR_OUT_OF_RANGE(env, "info is too big");
79
    return Nothing<bool>();
80
  }
81
82
  params->salt = mode == kCryptoJobAsync
83
1030
      ? salt.ToCopy()
84
515
      : salt.ToByteSource();
85
86
  params->info = mode == kCryptoJobAsync
87
1030
      ? info.ToCopy()
88
515
      : info.ToByteSource();
89
90
1545
  params->length = args[offset + 4].As<Uint32>()->Value();
91
515
  size_t max_length = EVP_MD_size(params->digest) * kMaxDigestMultiplier;
92
515
  if (params->length > max_length) {
93
2
    THROW_ERR_CRYPTO_INVALID_KEYLEN(env);
94
2
    return Nothing<bool>();
95
  }
96
97
513
  return Just(true);
98
}
99
100
513
bool HKDFTraits::DeriveBits(
101
    Environment* env,
102
    const HKDFConfig& params,
103
    ByteSource* out) {
104
  EVPKeyCtxPointer ctx =
105
1026
      EVPKeyCtxPointer(EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr));
106
1026
  if (!ctx ||
107
1026
      !EVP_PKEY_derive_init(ctx.get()) ||
108
513
      !EVP_PKEY_CTX_hkdf_mode(
109
513
        ctx.get(), EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND) ||
110
1026
      !EVP_PKEY_CTX_set_hkdf_md(ctx.get(), params.digest) ||
111
513
      !EVP_PKEY_CTX_set1_hkdf_salt(
112
        ctx.get(),
113
        reinterpret_cast<const unsigned char*>(params.salt.get()),
114
513
        params.salt.size()) ||
115
513
      !EVP_PKEY_CTX_set1_hkdf_key(
116
        ctx.get(),
117
        reinterpret_cast<const unsigned char*>(params.key->GetSymmetricKey()),
118

1026
        params.key->GetSymmetricKeySize()) ||
119
513
      !EVP_PKEY_CTX_add1_hkdf_info(
120
        ctx.get(),
121
        reinterpret_cast<const unsigned char*>(params.info.get()),
122
        params.info.size())) {
123
    return false;
124
  }
125
126
513
  size_t length = params.length;
127
513
  char* data = MallocOpenSSL<char>(length);
128
1026
  ByteSource buf = ByteSource::Allocated(data, length);
129
513
  unsigned char* ptr = reinterpret_cast<unsigned char*>(data);
130
513
  if (EVP_PKEY_derive(ctx.get(), ptr, &length) <= 0)
131
    return false;
132
133
513
  *out = std::move(buf);
134
513
  return true;
135
}
136
137
void HKDFConfig::MemoryInfo(MemoryTracker* tracker) const {
138
  tracker->TrackField("key", key);
139
  // If the job is sync, then the HKDFConfig does not own the data
140
  if (mode == kCryptoJobAsync) {
141
    tracker->TrackFieldWithSize("salt", salt.size());
142
    tracker->TrackFieldWithSize("info", info.size());
143
  }
144
}
145
146
}  // namespace crypto
147
}  // namespace node