• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
Setup(DsaKeyPairGenConfig * params)40 EVPKeyCtxPointer DsaKeyGenTraits::Setup(DsaKeyPairGenConfig* params) {
41   EVPKeyCtxPointer param_ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, nullptr));
42   EVP_PKEY* raw_params = nullptr;
43 
44   if (!param_ctx ||
45       EVP_PKEY_paramgen_init(param_ctx.get()) <= 0 ||
46       EVP_PKEY_CTX_set_dsa_paramgen_bits(
47           param_ctx.get(),
48           params->params.modulus_bits) <= 0) {
49     return EVPKeyCtxPointer();
50   }
51 
52   if (params->params.divisor_bits != -1) {
53     if (EVP_PKEY_CTX_set_dsa_paramgen_q_bits(
54             param_ctx.get(), params->params.divisor_bits) <= 0) {
55       return EVPKeyCtxPointer();
56     }
57   }
58 
59   if (EVP_PKEY_paramgen(param_ctx.get(), &raw_params) <= 0)
60     return EVPKeyCtxPointer();
61 
62   EVPKeyPointer key_params(raw_params);
63   EVPKeyCtxPointer key_ctx(EVP_PKEY_CTX_new(key_params.get(), nullptr));
64 
65   if (!key_ctx || EVP_PKEY_keygen_init(key_ctx.get()) <= 0)
66     return EVPKeyCtxPointer();
67 
68   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
AdditionalConfig(CryptoJobMode mode,const FunctionCallbackInfo<Value> & args,unsigned int * offset,DsaKeyPairGenConfig * params)81 Maybe<bool> DsaKeyGenTraits::AdditionalConfig(
82     CryptoJobMode mode,
83     const FunctionCallbackInfo<Value>& args,
84     unsigned int* offset,
85     DsaKeyPairGenConfig* params) {
86   CHECK(args[*offset]->IsUint32());  // modulus bits
87   CHECK(args[*offset + 1]->IsInt32());  // divisor bits
88 
89   params->params.modulus_bits = args[*offset].As<Uint32>()->Value();
90   params->params.divisor_bits = args[*offset + 1].As<Int32>()->Value();
91   CHECK_GE(params->params.divisor_bits, -1);
92 
93   *offset += 2;
94 
95   return Just(true);
96 }
97 
AdditionalConfig(const FunctionCallbackInfo<Value> & args,unsigned int offset,DSAKeyExportConfig * params)98 Maybe<bool> DSAKeyExportTraits::AdditionalConfig(
99     const FunctionCallbackInfo<Value>& args,
100     unsigned int offset,
101     DSAKeyExportConfig* params) {
102   return Just(true);
103 }
104 
DoExport(std::shared_ptr<KeyObjectData> key_data,WebCryptoKeyFormat format,const DSAKeyExportConfig & params,ByteSource * out)105 WebCryptoKeyExportStatus DSAKeyExportTraits::DoExport(
106     std::shared_ptr<KeyObjectData> key_data,
107     WebCryptoKeyFormat format,
108     const DSAKeyExportConfig& params,
109     ByteSource* out) {
110   CHECK_NE(key_data->GetKeyType(), kKeyTypeSecret);
111 
112   switch (format) {
113     case kWebCryptoKeyFormatRaw:
114       // Not supported for RSA keys of either type
115       return WebCryptoKeyExportStatus::FAILED;
116     case kWebCryptoKeyFormatPKCS8:
117       if (key_data->GetKeyType() != kKeyTypePrivate)
118         return WebCryptoKeyExportStatus::INVALID_KEY_TYPE;
119       return PKEY_PKCS8_Export(key_data.get(), out);
120     case kWebCryptoKeyFormatSPKI:
121       if (key_data->GetKeyType() != kKeyTypePublic)
122         return WebCryptoKeyExportStatus::INVALID_KEY_TYPE;
123       return PKEY_SPKI_Export(key_data.get(), out);
124     default:
125       UNREACHABLE();
126   }
127 }
128 
GetDsaKeyDetail(Environment * env,std::shared_ptr<KeyObjectData> key,Local<Object> target)129 Maybe<bool> GetDsaKeyDetail(
130     Environment* env,
131     std::shared_ptr<KeyObjectData> key,
132     Local<Object> target) {
133   const BIGNUM* p;  // Modulus length
134   const BIGNUM* q;  // Divisor length
135 
136   ManagedEVPPKey m_pkey = key->GetAsymmetricKey();
137   Mutex::ScopedLock lock(*m_pkey.mutex());
138   int type = EVP_PKEY_id(m_pkey.get());
139   CHECK(type == EVP_PKEY_DSA);
140 
141   const DSA* dsa = EVP_PKEY_get0_DSA(m_pkey.get());
142   CHECK_NOT_NULL(dsa);
143 
144   DSA_get0_pqg(dsa, &p, &q, nullptr);
145 
146   size_t modulus_length = BN_num_bits(p);
147   size_t divisor_length = BN_num_bits(q);
148 
149   if (target
150           ->Set(
151               env->context(),
152               env->modulus_length_string(),
153               Number::New(env->isolate(), static_cast<double>(modulus_length)))
154           .IsNothing() ||
155       target
156           ->Set(
157               env->context(),
158               env->divisor_length_string(),
159               Number::New(env->isolate(), static_cast<double>(divisor_length)))
160           .IsNothing()) {
161     return Nothing<bool>();
162   }
163 
164   return Just(true);
165 }
166 
167 namespace DSAAlg {
Initialize(Environment * env,Local<Object> target)168 void Initialize(Environment* env, Local<Object> target) {
169   DsaKeyPairGenJob::Initialize(env, target);
170   DSAKeyExportJob::Initialize(env, target);
171 }
172 
RegisterExternalReferences(ExternalReferenceRegistry * registry)173 void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
174   DsaKeyPairGenJob::RegisterExternalReferences(registry);
175   DSAKeyExportJob::RegisterExternalReferences(registry);
176 }
177 }  // namespace DSAAlg
178 }  // namespace crypto
179 }  // namespace node
180