GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: crypto/crypto_dsa.cc Lines: 50 74 67.6 %
Date: 2022-08-28 04:20:35 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
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::Uint32;
26
using v8::Value;
27
28
namespace crypto {
29
3
EVPKeyCtxPointer DsaKeyGenTraits::Setup(DsaKeyPairGenConfig* params) {
30
6
  EVPKeyCtxPointer param_ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, nullptr));
31
3
  EVP_PKEY* raw_params = nullptr;
32
33
6
  if (!param_ctx ||
34

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

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

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

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