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_dsa.cc Lines: 94 116 81.0 %
Date: 2021-01-16 04:10:54 Branches: 66 122 54.1 %

Line Branch Exec Source
1
#include "crypto/crypto_dsa.h"
2
#include "crypto/crypto_keys.h"
3
#include "crypto/crypto_util.h"
4
#include "async_wrap-inl.h"
5
#include "env-inl.h"
6
#include "memory_tracker-inl.h"
7
#include "threadpoolwork-inl.h"
8
#include "v8.h"
9
10
#include <openssl/bn.h>
11
#include <openssl/dsa.h>
12
13
#include <cstdio>
14
15
namespace node {
16
17
using v8::FunctionCallbackInfo;
18
using v8::Int32;
19
using v8::Just;
20
using v8::Local;
21
using v8::Maybe;
22
using v8::Nothing;
23
using v8::Number;
24
using v8::Object;
25
using v8::String;
26
using v8::Uint32;
27
using v8::Value;
28
29
namespace crypto {
30
3
EVPKeyCtxPointer DsaKeyGenTraits::Setup(DsaKeyPairGenConfig* params) {
31
6
  EVPKeyCtxPointer param_ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, nullptr));
32
3
  EVP_PKEY* raw_params = nullptr;
33
34

9
  if (!param_ctx ||
35

6
      EVP_PKEY_paramgen_init(param_ctx.get()) <= 0 ||
36
3
      EVP_PKEY_CTX_set_dsa_paramgen_bits(
37
          param_ctx.get(),
38
          params->params.modulus_bits) <= 0) {
39
    return EVPKeyCtxPointer();
40
  }
41
42
3
  if (params->params.divisor_bits != -1) {
43
2
    if (EVP_PKEY_CTX_ctrl(
44
            param_ctx.get(),
45
            EVP_PKEY_DSA,
46
            EVP_PKEY_OP_PARAMGEN,
47
            EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS,
48
            params->params.divisor_bits,
49
            nullptr) <= 0) {
50
      return EVPKeyCtxPointer();
51
    }
52
  }
53
54
3
  if (EVP_PKEY_paramgen(param_ctx.get(), &raw_params) <= 0)
55
    return EVPKeyCtxPointer();
56
57
6
  EVPKeyPointer key_params(raw_params);
58
6
  EVPKeyCtxPointer key_ctx(EVP_PKEY_CTX_new(key_params.get(), nullptr));
59
60

3
  if (!key_ctx || EVP_PKEY_keygen_init(key_ctx.get()) <= 0)
61
    return EVPKeyCtxPointer();
62
63
3
  return key_ctx;
64
}
65
66
// Input arguments for DsaKeyPairGenJob
67
//   1. CryptoJobMode
68
//   2. Modulus Bits
69
//   3. Divisor Bits
70
//   4. Public Format
71
//   5. Public Type
72
//   6. Private Format
73
//   7. Private Type
74
//   8. Cipher
75
//   9. Passphrase
76
3
Maybe<bool> DsaKeyGenTraits::AdditionalConfig(
77
    CryptoJobMode mode,
78
    const FunctionCallbackInfo<Value>& args,
79
    unsigned int* offset,
80
    DsaKeyPairGenConfig* params) {
81
3
  Environment* env = Environment::GetCurrent(args);
82
9
  CHECK(args[*offset]->IsUint32());  // modulus bits
83
9
  CHECK(args[*offset + 1]->IsInt32());  // divisor bits
84
85
12
  params->params.modulus_bits = args[*offset].As<Uint32>()->Value();
86
12
  params->params.divisor_bits = args[*offset + 1].As<Int32>()->Value();
87
3
  if (params->params.divisor_bits < -1) {
88
    char msg[1024];
89
    snprintf(msg, sizeof(msg), "invalid value for divisor_bits");
90
    THROW_ERR_OUT_OF_RANGE(env, msg);
91
    return Nothing<bool>();
92
  }
93
94
3
  *offset += 2;
95
96
3
  return Just(true);
97
}
98
99
8
Maybe<bool> DSAKeyExportTraits::AdditionalConfig(
100
    const FunctionCallbackInfo<Value>& args,
101
    unsigned int offset,
102
    DSAKeyExportConfig* params) {
103
8
  return Just(true);
104
}
105
106
8
WebCryptoKeyExportStatus DSAKeyExportTraits::DoExport(
107
    std::shared_ptr<KeyObjectData> key_data,
108
    WebCryptoKeyFormat format,
109
    const DSAKeyExportConfig& params,
110
    ByteSource* out) {
111
8
  CHECK_NE(key_data->GetKeyType(), kKeyTypeSecret);
112
113

8
  switch (format) {
114
    case kWebCryptoKeyFormatRaw:
115
      // Not supported for RSA keys of either type
116
      return WebCryptoKeyExportStatus::FAILED;
117
    case kWebCryptoKeyFormatPKCS8:
118
4
      if (key_data->GetKeyType() != kKeyTypePrivate)
119
        return WebCryptoKeyExportStatus::INVALID_KEY_TYPE;
120
4
      return PKEY_PKCS8_Export(key_data.get(), out);
121
    case kWebCryptoKeyFormatSPKI:
122
4
      if (key_data->GetKeyType() != kKeyTypePublic)
123
        return WebCryptoKeyExportStatus::INVALID_KEY_TYPE;
124
4
      return PKEY_SPKI_Export(key_data.get(), out);
125
    default:
126
      UNREACHABLE();
127
  }
128
}
129
130
8
Maybe<bool> ExportJWKDsaKey(
131
    Environment* env,
132
    std::shared_ptr<KeyObjectData> key,
133
    Local<Object> target) {
134
16
  ManagedEVPPKey pkey = key->GetAsymmetricKey();
135
8
  CHECK_EQ(EVP_PKEY_id(pkey.get()), EVP_PKEY_DSA);
136
137
8
  DSA* dsa = EVP_PKEY_get0_DSA(pkey.get());
138
8
  CHECK_NOT_NULL(dsa);
139
140
  const BIGNUM* y;
141
  const BIGNUM* x;
142
  const BIGNUM* p;
143
  const BIGNUM* q;
144
  const BIGNUM* g;
145
146
8
  DSA_get0_key(dsa, &y, &x);
147
8
  DSA_get0_pqg(dsa, &p, &q, &g);
148
149
24
  if (target->Set(
150
          env->context(),
151
          env->jwk_kty_string(),
152
40
          env->jwk_dsa_string()).IsNothing()) {
153
    return Nothing<bool>();
154
  }
155
156

40
  if (SetEncodedValue(env, target, env->jwk_y_string(), y).IsNothing() ||
157
32
      SetEncodedValue(env, target, env->jwk_p_string(), p).IsNothing() ||
158

40
      SetEncodedValue(env, target, env->jwk_q_string(), q).IsNothing() ||
159
24
      SetEncodedValue(env, target, env->jwk_g_string(), g).IsNothing()) {
160
    return Nothing<bool>();
161
  }
162
163

20
  if (key->GetKeyType() == kKeyTypePrivate &&
164
16
      SetEncodedValue(env, target, env->jwk_x_string(), x).IsNothing()) {
165
    return Nothing<bool>();
166
  }
167
168
8
  return Just(true);
169
}
170
171
16
std::shared_ptr<KeyObjectData> ImportJWKDsaKey(
172
    Environment* env,
173
    Local<Object> jwk,
174
    const FunctionCallbackInfo<Value>& args,
175
    unsigned int offset) {
176
  Local<Value> y_value;
177
  Local<Value> p_value;
178
  Local<Value> q_value;
179
  Local<Value> g_value;
180
  Local<Value> x_value;
181
182

112
  if (!jwk->Get(env->context(), env->jwk_y_string()).ToLocal(&y_value) ||
183
96
      !jwk->Get(env->context(), env->jwk_p_string()).ToLocal(&p_value) ||
184
96
      !jwk->Get(env->context(), env->jwk_q_string()).ToLocal(&q_value) ||
185

112
      !jwk->Get(env->context(), env->jwk_g_string()).ToLocal(&g_value) ||
186
80
      !jwk->Get(env->context(), env->jwk_x_string()).ToLocal(&x_value)) {
187
    return std::shared_ptr<KeyObjectData>();
188
  }
189
190

64
  if (!y_value->IsString() ||
191
48
      !p_value->IsString() ||
192
48
      !q_value->IsString() ||
193

64
      !q_value->IsString() ||
194
48
      (!x_value->IsUndefined() && !x_value->IsString())) {
195
    THROW_ERR_CRYPTO_INVALID_JWK(env, "Invalid JWK DSA key");
196
    return std::shared_ptr<KeyObjectData>();
197
  }
198
199
32
  KeyType type = x_value->IsString() ? kKeyTypePrivate : kKeyTypePublic;
200
201
32
  DsaPointer dsa(DSA_new());
202
203
32
  ByteSource y = ByteSource::FromEncodedString(env, y_value.As<String>());
204
32
  ByteSource p = ByteSource::FromEncodedString(env, p_value.As<String>());
205
32
  ByteSource q = ByteSource::FromEncodedString(env, q_value.As<String>());
206
32
  ByteSource g = ByteSource::FromEncodedString(env, g_value.As<String>());
207
208


96
  if (!DSA_set0_key(dsa.get(), y.ToBN().release(), nullptr) ||
209
48
      !DSA_set0_pqg(dsa.get(),
210
32
                    p.ToBN().release(),
211
32
                    q.ToBN().release(),
212
32
                    g.ToBN().release())) {
213
    THROW_ERR_CRYPTO_INVALID_JWK(env, "Invalid JWK DSA key");
214
    return std::shared_ptr<KeyObjectData>();
215
  }
216
217
16
  if (type == kKeyTypePrivate) {
218
16
    ByteSource x = ByteSource::FromEncodedString(env, x_value.As<String>());
219
8
    if (!DSA_set0_key(dsa.get(), nullptr, x.ToBN().release())) {
220
      THROW_ERR_CRYPTO_INVALID_JWK(env, "Invalid JWK DSA key");
221
      return std::shared_ptr<KeyObjectData>();
222
    }
223
  }
224
225
32
  EVPKeyPointer pkey(EVP_PKEY_new());
226
16
  CHECK_EQ(EVP_PKEY_set1_DSA(pkey.get(), dsa.get()), 1);
227
228
16
  return KeyObjectData::CreateAsymmetric(type, ManagedEVPPKey(std::move(pkey)));
229
}
230
231
58
Maybe<bool> GetDsaKeyDetail(
232
    Environment* env,
233
    std::shared_ptr<KeyObjectData> key,
234
    Local<Object> target) {
235
  const BIGNUM* p;  // Modulus length
236
  const BIGNUM* q;  // Divisor length
237
238
116
  ManagedEVPPKey pkey = key->GetAsymmetricKey();
239
58
  int type = EVP_PKEY_id(pkey.get());
240
58
  CHECK(type == EVP_PKEY_DSA);
241
242
58
  DSA* dsa = EVP_PKEY_get0_DSA(pkey.get());
243
58
  CHECK_NOT_NULL(dsa);
244
245
58
  DSA_get0_pqg(dsa, &p, &q, nullptr);
246
247
58
  size_t modulus_length = BN_num_bytes(p) * CHAR_BIT;
248
58
  size_t divisor_length = BN_num_bytes(q) * CHAR_BIT;
249
250
232
  if (target->Set(
251
          env->context(),
252
          env->modulus_length_string(),
253

406
          Number::New(env->isolate(), modulus_length)).IsNothing() ||
254
116
      target->Set(
255
          env->context(),
256
          env->divisor_length_string(),
257
348
          Number::New(env->isolate(), divisor_length)).IsNothing()) {
258
    return Nothing<bool>();
259
  }
260
261
58
  return Just(true);
262
}
263
264
namespace DSAAlg {
265
663
void Initialize(Environment* env, Local<Object> target) {
266
663
  DsaKeyPairGenJob::Initialize(env, target);
267
663
  DSAKeyExportJob::Initialize(env, target);
268
663
}
269
}  // namespace DSAAlg
270
}  // namespace crypto
271

13995
}  // namespace node
272