GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: crypto/crypto_dsa.cc Lines: 50 74 67.6 %
Date: 2022-10-02 04:22:39 Branches: 23 54 42.6 %

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
// EVP_PKEY_CTX_set_dsa_paramgen_q_bits was added in OpenSSL 1.1.1e.
16
#if OPENSSL_VERSION_NUMBER < 0x1010105fL
17
#define EVP_PKEY_CTX_set_dsa_paramgen_q_bits(ctx, qbits)                       \
18
  EVP_PKEY_CTX_ctrl((ctx),                                                     \
19
                    EVP_PKEY_DSA,                                              \
20
                    EVP_PKEY_OP_PARAMGEN,                                      \
21
                    EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS,                         \
22
                    (qbits),                                                   \
23
                    nullptr)
24
#endif
25
26
namespace node {
27
28
using v8::FunctionCallbackInfo;
29
using v8::Int32;
30
using v8::Just;
31
using v8::Local;
32
using v8::Maybe;
33
using v8::Nothing;
34
using v8::Number;
35
using v8::Object;
36
using v8::Uint32;
37
using v8::Value;
38
39
namespace crypto {
40
3
EVPKeyCtxPointer DsaKeyGenTraits::Setup(DsaKeyPairGenConfig* params) {
41
6
  EVPKeyCtxPointer param_ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, nullptr));
42
3
  EVP_PKEY* raw_params = nullptr;
43
44
6
  if (!param_ctx ||
45

6
      EVP_PKEY_paramgen_init(param_ctx.get()) <= 0 ||
46
3
      EVP_PKEY_CTX_set_dsa_paramgen_bits(
47
          param_ctx.get(),
48
3
          params->params.modulus_bits) <= 0) {
49
    return EVPKeyCtxPointer();
50
  }
51
52
3
  if (params->params.divisor_bits != -1) {
53
2
    if (EVP_PKEY_CTX_set_dsa_paramgen_q_bits(
54
2
            param_ctx.get(), params->params.divisor_bits) <= 0) {
55
      return EVPKeyCtxPointer();
56
    }
57
  }
58
59
3
  if (EVP_PKEY_paramgen(param_ctx.get(), &raw_params) <= 0)
60
    return EVPKeyCtxPointer();
61
62
6
  EVPKeyPointer key_params(raw_params);
63
6
  EVPKeyCtxPointer key_ctx(EVP_PKEY_CTX_new(key_params.get(), nullptr));
64
65

3
  if (!key_ctx || EVP_PKEY_keygen_init(key_ctx.get()) <= 0)
66
    return EVPKeyCtxPointer();
67
68
3
  return key_ctx;
69
}
70
71
// Input arguments for DsaKeyPairGenJob
72
//   1. CryptoJobMode
73
//   2. Modulus Bits
74
//   3. Divisor Bits
75
//   4. Public Format
76
//   5. Public Type
77
//   6. Private Format
78
//   7. Private Type
79
//   8. Cipher
80
//   9. Passphrase
81
3
Maybe<bool> DsaKeyGenTraits::AdditionalConfig(
82
    CryptoJobMode mode,
83
    const FunctionCallbackInfo<Value>& args,
84
    unsigned int* offset,
85
    DsaKeyPairGenConfig* params) {
86
3
  Environment* env = Environment::GetCurrent(args);
87

6
  CHECK(args[*offset]->IsUint32());  // modulus bits
88

6
  CHECK(args[*offset + 1]->IsInt32());  // divisor bits
89
90
9
  params->params.modulus_bits = args[*offset].As<Uint32>()->Value();
91
9
  params->params.divisor_bits = args[*offset + 1].As<Int32>()->Value();
92
3
  if (params->params.divisor_bits < -1) {
93
    THROW_ERR_OUT_OF_RANGE(env, "invalid value for divisor_bits");
94
    return Nothing<bool>();
95
  }
96
97
3
  *offset += 2;
98
99
3
  return Just(true);
100
}
101
102
Maybe<bool> DSAKeyExportTraits::AdditionalConfig(
103
    const FunctionCallbackInfo<Value>& args,
104
    unsigned int offset,
105
    DSAKeyExportConfig* params) {
106
  return Just(true);
107
}
108
109
WebCryptoKeyExportStatus DSAKeyExportTraits::DoExport(
110
    std::shared_ptr<KeyObjectData> key_data,
111
    WebCryptoKeyFormat format,
112
    const DSAKeyExportConfig& params,
113
    ByteSource* out) {
114
  CHECK_NE(key_data->GetKeyType(), kKeyTypeSecret);
115
116
  switch (format) {
117
    case kWebCryptoKeyFormatRaw:
118
      // Not supported for RSA keys of either type
119
      return WebCryptoKeyExportStatus::FAILED;
120
    case kWebCryptoKeyFormatPKCS8:
121
      if (key_data->GetKeyType() != kKeyTypePrivate)
122
        return WebCryptoKeyExportStatus::INVALID_KEY_TYPE;
123
      return PKEY_PKCS8_Export(key_data.get(), out);
124
    case kWebCryptoKeyFormatSPKI:
125
      if (key_data->GetKeyType() != kKeyTypePublic)
126
        return WebCryptoKeyExportStatus::INVALID_KEY_TYPE;
127
      return PKEY_SPKI_Export(key_data.get(), out);
128
    default:
129
      UNREACHABLE();
130
  }
131
}
132
133
2
Maybe<bool> GetDsaKeyDetail(
134
    Environment* env,
135
    std::shared_ptr<KeyObjectData> key,
136
    Local<Object> target) {
137
  const BIGNUM* p;  // Modulus length
138
  const BIGNUM* q;  // Divisor length
139
140
4
  ManagedEVPPKey m_pkey = key->GetAsymmetricKey();
141
4
  Mutex::ScopedLock lock(*m_pkey.mutex());
142
2
  int type = EVP_PKEY_id(m_pkey.get());
143
2
  CHECK(type == EVP_PKEY_DSA);
144
145
2
  const DSA* dsa = EVP_PKEY_get0_DSA(m_pkey.get());
146
2
  CHECK_NOT_NULL(dsa);
147
148
2
  DSA_get0_pqg(dsa, &p, &q, nullptr);
149
150
2
  size_t modulus_length = BN_num_bytes(p) * CHAR_BIT;
151
2
  size_t divisor_length = BN_num_bytes(q) * CHAR_BIT;
152
153
2
  if (target
154
2
          ->Set(
155
              env->context(),
156
              env->modulus_length_string(),
157
6
              Number::New(env->isolate(), static_cast<double>(modulus_length)))
158
4
          .IsNothing() ||
159
      target
160
2
          ->Set(
161
              env->context(),
162
              env->divisor_length_string(),
163
8
              Number::New(env->isolate(), static_cast<double>(divisor_length)))
164
2
          .IsNothing()) {
165
    return Nothing<bool>();
166
  }
167
168
2
  return Just(true);
169
}
170
171
namespace DSAAlg {
172
780
void Initialize(Environment* env, Local<Object> target) {
173
780
  DsaKeyPairGenJob::Initialize(env, target);
174
780
  DSAKeyExportJob::Initialize(env, target);
175
780
}
176
177
5531
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
178
5531
  DsaKeyPairGenJob::RegisterExternalReferences(registry);
179
5531
  DSAKeyExportJob::RegisterExternalReferences(registry);
180
5531
}
181
}  // namespace DSAAlg
182
}  // namespace crypto
183
}  // namespace node