react-native-quick-crypto 0.3.2 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -6
- package/android/CMakeLists.txt +10 -2
- package/android/gradle.properties +1 -1
- package/android/src/main/cpp/cpp-adapter.cpp +1 -1
- package/cpp/Cipher/MGLCipherHostObject.cpp +4 -5
- package/cpp/Cipher/MGLCreateCipherInstaller.cpp +1 -3
- package/cpp/Cipher/MGLGenerateKeyPairInstaller.h +6 -3
- package/cpp/Cipher/MGLGenerateKeyPairSyncInstaller.h +5 -3
- package/cpp/Cipher/MGLPublicCipher.h +1 -1
- package/cpp/Cipher/MGLPublicCipherInstaller.h +1 -1
- package/cpp/Cipher/MGLRsa.h +5 -1
- package/cpp/JSIUtils/MGLJSIMacros.h +69 -6
- package/cpp/{Cipher/MGLCipherKeys.cpp → MGLKeys.cpp} +47 -49
- package/cpp/{Cipher/MGLCipherKeys.h → MGLKeys.h} +29 -30
- package/cpp/MGLQuickCryptoHostObject.cpp +12 -0
- package/cpp/Sig/MGLSignHostObjects.cpp +889 -0
- package/cpp/Sig/MGLSignHostObjects.h +88 -0
- package/cpp/Sig/MGLSignInstaller.cpp +24 -0
- package/cpp/Sig/MGLSignInstaller.h +29 -0
- package/cpp/Sig/MGLVerifyInstaller.cpp +24 -0
- package/cpp/Sig/MGLVerifyInstaller.h +22 -0
- package/cpp/Utils/MGLUtils.cpp +67 -29
- package/cpp/Utils/MGLUtils.h +17 -17
- package/lib/commonjs/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -1
- package/lib/commonjs/NativeQuickCrypto/sig.js +2 -0
- package/lib/commonjs/NativeQuickCrypto/sig.js.map +1 -0
- package/lib/commonjs/QuickCrypto.js +4 -0
- package/lib/commonjs/QuickCrypto.js.map +1 -1
- package/lib/commonjs/keys.js +1 -4
- package/lib/commonjs/keys.js.map +1 -1
- package/lib/commonjs/sig.js +170 -0
- package/lib/commonjs/sig.js.map +1 -0
- package/lib/module/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -1
- package/lib/module/NativeQuickCrypto/sig.js +2 -0
- package/lib/module/NativeQuickCrypto/sig.js.map +1 -0
- package/lib/module/QuickCrypto.js +3 -0
- package/lib/module/QuickCrypto.js.map +1 -1
- package/lib/module/keys.js +1 -4
- package/lib/module/keys.js.map +1 -1
- package/lib/module/sig.js +155 -0
- package/lib/module/sig.js.map +1 -0
- package/lib/typescript/NativeQuickCrypto/NativeQuickCrypto.d.ts +3 -0
- package/lib/typescript/NativeQuickCrypto/sig.d.ts +12 -0
- package/lib/typescript/QuickCrypto.d.ts +3 -0
- package/lib/typescript/index.d.ts +2 -3
- package/lib/typescript/sig.d.ts +35 -0
- package/package.json +3 -3
- package/src/NativeQuickCrypto/NativeQuickCrypto.ts +3 -0
- package/src/NativeQuickCrypto/sig.ts +17 -0
- package/src/QuickCrypto.ts +3 -0
- package/src/keys.ts +18 -13
- package/src/sig.ts +179 -0
|
@@ -0,0 +1,889 @@
|
|
|
1
|
+
#include "MGLSignHostObjects.h"
|
|
2
|
+
|
|
3
|
+
#include <openssl/evp.h>
|
|
4
|
+
|
|
5
|
+
#include <optional>
|
|
6
|
+
|
|
7
|
+
#include "MGLKeys.h"
|
|
8
|
+
#ifdef ANDROID
|
|
9
|
+
#include "JSIUtils/MGLJSIUtils.h"
|
|
10
|
+
#include "JSIUtils/MGLTypedArray.h"
|
|
11
|
+
#include "Utils/MGLUtils.h"
|
|
12
|
+
#else
|
|
13
|
+
#include "MGLJSIUtils.h"
|
|
14
|
+
#include "MGLTypedArray.h"
|
|
15
|
+
#include "MGLUtils.h"
|
|
16
|
+
#endif
|
|
17
|
+
|
|
18
|
+
namespace margelo {
|
|
19
|
+
|
|
20
|
+
bool ValidateDSAParameters(EVP_PKEY* key) {
|
|
21
|
+
/* Validate DSA2 parameters from FIPS 186-4 */
|
|
22
|
+
#if OPENSSL_VERSION_MAJOR >= 3
|
|
23
|
+
if (EVP_default_properties_is_fips_enabled(nullptr) &&
|
|
24
|
+
EVP_PKEY_DSA == EVP_PKEY_base_id(key)) {
|
|
25
|
+
#else
|
|
26
|
+
if (FIPS_mode() && EVP_PKEY_DSA == EVP_PKEY_base_id(key)) {
|
|
27
|
+
#endif
|
|
28
|
+
const DSA* dsa = EVP_PKEY_get0_DSA(key);
|
|
29
|
+
const BIGNUM* p;
|
|
30
|
+
DSA_get0_pqg(dsa, &p, nullptr, nullptr);
|
|
31
|
+
size_t L = BN_num_bits(p);
|
|
32
|
+
const BIGNUM* q;
|
|
33
|
+
DSA_get0_pqg(dsa, nullptr, &q, nullptr);
|
|
34
|
+
size_t N = BN_num_bits(q);
|
|
35
|
+
|
|
36
|
+
return (L == 1024 && N == 160) || (L == 2048 && N == 224) ||
|
|
37
|
+
(L == 2048 && N == 256) || (L == 3072 && N == 256);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
bool ApplyRSAOptions(const ManagedEVPPKey& pkey, EVP_PKEY_CTX* pkctx,
|
|
44
|
+
int padding, std::optional<int> salt_len) {
|
|
45
|
+
if (EVP_PKEY_id(pkey.get()) == EVP_PKEY_RSA ||
|
|
46
|
+
EVP_PKEY_id(pkey.get()) == EVP_PKEY_RSA2 ||
|
|
47
|
+
EVP_PKEY_id(pkey.get()) == EVP_PKEY_RSA_PSS) {
|
|
48
|
+
if (EVP_PKEY_CTX_set_rsa_padding(pkctx, padding) <= 0) return false;
|
|
49
|
+
if (padding == RSA_PKCS1_PSS_PADDING && salt_len.has_value()) {
|
|
50
|
+
if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, salt_len.value()) <= 0)
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
std::optional<jsi::Value> Node_SignFinal(jsi::Runtime& runtime,
|
|
59
|
+
EVPMDPointer&& mdctx,
|
|
60
|
+
const ManagedEVPPKey& pkey,
|
|
61
|
+
int padding,
|
|
62
|
+
std::optional<int> pss_salt_len) {
|
|
63
|
+
unsigned char m[EVP_MAX_MD_SIZE];
|
|
64
|
+
unsigned int m_len;
|
|
65
|
+
|
|
66
|
+
if (!EVP_DigestFinal_ex(mdctx.get(), m, &m_len)) return {};
|
|
67
|
+
|
|
68
|
+
int signed_sig_len = EVP_PKEY_size(pkey.get());
|
|
69
|
+
CHECK_GE(signed_sig_len, 0);
|
|
70
|
+
size_t sig_len = static_cast<size_t>(signed_sig_len);
|
|
71
|
+
|
|
72
|
+
MGLTypedArray<MGLTypedArrayKind::Uint8Array> sig(runtime, sig_len);
|
|
73
|
+
|
|
74
|
+
EVPKeyCtxPointer pkctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
|
|
75
|
+
if (pkctx && EVP_PKEY_sign_init(pkctx.get()) &&
|
|
76
|
+
ApplyRSAOptions(pkey, pkctx.get(), padding, pss_salt_len) &&
|
|
77
|
+
EVP_PKEY_CTX_set_signature_md(pkctx.get(), EVP_MD_CTX_md(mdctx.get())) &&
|
|
78
|
+
EVP_PKEY_sign(
|
|
79
|
+
pkctx.get(),
|
|
80
|
+
static_cast<unsigned char*>(sig.getBuffer(runtime).data(runtime)),
|
|
81
|
+
&sig_len, m, m_len)) {
|
|
82
|
+
CHECK_LE(sig_len, sig.size(runtime));
|
|
83
|
+
|
|
84
|
+
// do this bits need to be trimmed? I think so
|
|
85
|
+
// if (sig_len == 0)
|
|
86
|
+
// sig = ArrayBuffer::NewBackingStore(env->isolate(), 0);
|
|
87
|
+
// else
|
|
88
|
+
// sig = BackingStore::Reallocate(env->isolate(), std::move(sig),
|
|
89
|
+
// sig_len);
|
|
90
|
+
return sig;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return {};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// int GetDefaultSignPadding(const ManagedEVPPKey& m_pkey) {
|
|
97
|
+
// return EVP_PKEY_id(m_pkey.get()) == EVP_PKEY_RSA_PSS ?
|
|
98
|
+
// RSA_PKCS1_PSS_PADDING : RSA_PKCS1_PADDING;
|
|
99
|
+
// }
|
|
100
|
+
//
|
|
101
|
+
unsigned int GetBytesOfRS(const ManagedEVPPKey& pkey) {
|
|
102
|
+
int bits, base_id = EVP_PKEY_base_id(pkey.get());
|
|
103
|
+
|
|
104
|
+
if (base_id == EVP_PKEY_DSA) {
|
|
105
|
+
const DSA* dsa_key = EVP_PKEY_get0_DSA(pkey.get());
|
|
106
|
+
// Both r and s are computed mod q, so their width is limited by that of
|
|
107
|
+
bits = BN_num_bits(DSA_get0_q(dsa_key));
|
|
108
|
+
} else if (base_id == EVP_PKEY_EC) {
|
|
109
|
+
const EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(pkey.get());
|
|
110
|
+
const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key);
|
|
111
|
+
bits = EC_GROUP_order_bits(ec_group);
|
|
112
|
+
} else {
|
|
113
|
+
return kNoDsaSignature;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return (bits + 7) / 8;
|
|
117
|
+
}
|
|
118
|
+
//
|
|
119
|
+
// bool ExtractP1363(
|
|
120
|
+
// const unsigned char* sig_data,
|
|
121
|
+
// unsigned char* out,
|
|
122
|
+
// size_t len,
|
|
123
|
+
// size_t n) {
|
|
124
|
+
// ECDSASigPointer asn1_sig(d2i_ECDSA_SIG(nullptr,
|
|
125
|
+
// &sig_data, len)); if (!asn1_sig)
|
|
126
|
+
// return false;
|
|
127
|
+
//
|
|
128
|
+
// const BIGNUM* pr = ECDSA_SIG_get0_r(asn1_sig.get());
|
|
129
|
+
// const BIGNUM* ps = ECDSA_SIG_get0_s(asn1_sig.get());
|
|
130
|
+
//
|
|
131
|
+
// return BN_bn2binpad(pr, out, n) > 0 && BN_bn2binpad(ps,
|
|
132
|
+
// out + n, n) > 0;
|
|
133
|
+
// }
|
|
134
|
+
//
|
|
135
|
+
// // Returns the maximum size of each of the integers (r, s) of the DSA
|
|
136
|
+
// signature. std::unique_ptr<BackingStore>
|
|
137
|
+
// ConvertSignatureToP1363(Environment* env,
|
|
138
|
+
// const ManagedEVPPKey&
|
|
139
|
+
// pkey,
|
|
140
|
+
// std::unique_ptr<BackingStore>&&
|
|
141
|
+
// signature) {
|
|
142
|
+
// unsigned int n = GetBytesOfRS(pkey);
|
|
143
|
+
// if (n == kNoDsaSignature)
|
|
144
|
+
// return std::move(signature);
|
|
145
|
+
//
|
|
146
|
+
// std::unique_ptr<BackingStore> buf;
|
|
147
|
+
// {
|
|
148
|
+
// NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
|
|
149
|
+
// buf = ArrayBuffer::NewBackingStore(env->isolate(), 2 * n);
|
|
150
|
+
// }
|
|
151
|
+
// if (!ExtractP1363(static_cast<unsigned char*>(signature->Data()),
|
|
152
|
+
// static_cast<unsigned char*>(buf->Data()),
|
|
153
|
+
// signature->ByteLength(), n))
|
|
154
|
+
// return std::move(signature);
|
|
155
|
+
//
|
|
156
|
+
// return buf;
|
|
157
|
+
// }
|
|
158
|
+
//
|
|
159
|
+
// // Returns the maximum size of each of the integers (r, s) of the DSA
|
|
160
|
+
// signature. ByteSource ConvertSignatureToP1363(
|
|
161
|
+
// Environment* env,
|
|
162
|
+
// const ManagedEVPPKey& pkey,
|
|
163
|
+
// const ByteSource& signature) {
|
|
164
|
+
// unsigned int n = GetBytesOfRS(pkey);
|
|
165
|
+
// if (n == kNoDsaSignature)
|
|
166
|
+
// return ByteSource();
|
|
167
|
+
//
|
|
168
|
+
// const unsigned char* sig_data =
|
|
169
|
+
// signature.data<unsigned char>();
|
|
170
|
+
//
|
|
171
|
+
// ByteSource::Builder out(n * 2);
|
|
172
|
+
// memset(out.data<void>(), 0, n * 2);
|
|
173
|
+
//
|
|
174
|
+
// if (!ExtractP1363(sig_data,
|
|
175
|
+
// out.data<unsigned char>(),
|
|
176
|
+
// signature.size(), n))
|
|
177
|
+
// return ByteSource();
|
|
178
|
+
//
|
|
179
|
+
// return std::move(out).release();
|
|
180
|
+
// }
|
|
181
|
+
//
|
|
182
|
+
ByteSource ConvertSignatureToDER(const ManagedEVPPKey& pkey, ByteSource&& out) {
|
|
183
|
+
unsigned int n = GetBytesOfRS(pkey);
|
|
184
|
+
if (n == kNoDsaSignature) return std::move(out);
|
|
185
|
+
|
|
186
|
+
const unsigned char* sig_data = out.data<unsigned char>();
|
|
187
|
+
|
|
188
|
+
if (out.size() != 2 * n) return ByteSource();
|
|
189
|
+
|
|
190
|
+
ECDSASigPointer asn1_sig(ECDSA_SIG_new());
|
|
191
|
+
CHECK(asn1_sig);
|
|
192
|
+
BIGNUM* r = BN_new();
|
|
193
|
+
CHECK_NOT_NULL(r);
|
|
194
|
+
BIGNUM* s = BN_new();
|
|
195
|
+
CHECK_NOT_NULL(s);
|
|
196
|
+
CHECK_EQ(r, BN_bin2bn(sig_data, n, r));
|
|
197
|
+
CHECK_EQ(s, BN_bin2bn(sig_data + n, n, s));
|
|
198
|
+
CHECK_EQ(1, ECDSA_SIG_set0(asn1_sig.get(), r, s));
|
|
199
|
+
|
|
200
|
+
unsigned char* data = nullptr;
|
|
201
|
+
int len = i2d_ECDSA_SIG(asn1_sig.get(), &data);
|
|
202
|
+
|
|
203
|
+
if (len <= 0) return ByteSource();
|
|
204
|
+
|
|
205
|
+
CHECK_NOT_NULL(data);
|
|
206
|
+
|
|
207
|
+
return ByteSource::Allocated(reinterpret_cast<char*>(data), len);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// void CheckThrow(Environment* env, SignBase::Error error) {
|
|
211
|
+
// HandleScope scope(env->isolate());
|
|
212
|
+
//
|
|
213
|
+
// switch (error) {
|
|
214
|
+
// case SignBase::Error::kSignUnknownDigest:
|
|
215
|
+
// return THROW_ERR_CRYPTO_INVALID_DIGEST(env);
|
|
216
|
+
//
|
|
217
|
+
// case SignBase::Error::kSignNotInitialised:
|
|
218
|
+
// return THROW_ERR_CRYPTO_INVALID_STATE(env, "Not initialised");
|
|
219
|
+
//
|
|
220
|
+
// case SignBase::Error::kSignMalformedSignature:
|
|
221
|
+
// return THROW_ERR_CRYPTO_OPERATION_FAILED(env, "Malformed signature");
|
|
222
|
+
//
|
|
223
|
+
// case SignBase::Error::kSignInit:
|
|
224
|
+
// case SignBase::Error::kSignUpdate:
|
|
225
|
+
// case SignBase::Error::kSignPrivateKey:
|
|
226
|
+
// case SignBase::Error::kSignPublicKey:
|
|
227
|
+
// {
|
|
228
|
+
// unsigned long err = ERR_get_error(); // NOLINT(runtime/int)
|
|
229
|
+
// if (err)
|
|
230
|
+
// return ThrowCryptoError(env, err);
|
|
231
|
+
// switch (error) {
|
|
232
|
+
// case SignBase::Error::kSignInit:
|
|
233
|
+
// return THROW_ERR_CRYPTO_OPERATION_FAILED(env,
|
|
234
|
+
// "EVP_SignInit_ex
|
|
235
|
+
// failed");
|
|
236
|
+
// case SignBase::Error::kSignUpdate:
|
|
237
|
+
// return THROW_ERR_CRYPTO_OPERATION_FAILED(env,
|
|
238
|
+
// "EVP_SignUpdate failed");
|
|
239
|
+
// case SignBase::Error::kSignPrivateKey:
|
|
240
|
+
// return THROW_ERR_CRYPTO_OPERATION_FAILED(env,
|
|
241
|
+
// "PEM_read_bio_PrivateKey
|
|
242
|
+
// failed");
|
|
243
|
+
// case SignBase::Error::kSignPublicKey:
|
|
244
|
+
// return THROW_ERR_CRYPTO_OPERATION_FAILED(env,
|
|
245
|
+
// "PEM_read_bio_PUBKEY
|
|
246
|
+
// failed");
|
|
247
|
+
// default:
|
|
248
|
+
// ABORT();
|
|
249
|
+
// }
|
|
250
|
+
// }
|
|
251
|
+
//
|
|
252
|
+
// case SignBase::Error::kSignOk:
|
|
253
|
+
// return;
|
|
254
|
+
// }
|
|
255
|
+
// }
|
|
256
|
+
//
|
|
257
|
+
// bool IsOneShot(const ManagedEVPPKey& key) {
|
|
258
|
+
// switch (EVP_PKEY_id(key.get())) {
|
|
259
|
+
// case EVP_PKEY_ED25519:
|
|
260
|
+
// case EVP_PKEY_ED448:
|
|
261
|
+
// return true;
|
|
262
|
+
// default:
|
|
263
|
+
// return false;
|
|
264
|
+
// }
|
|
265
|
+
// }
|
|
266
|
+
//
|
|
267
|
+
// bool UseP1363Encoding(const ManagedEVPPKey& key,
|
|
268
|
+
// const DSASigEnc& dsa_encoding) {
|
|
269
|
+
// switch (EVP_PKEY_id(key.get())) {
|
|
270
|
+
// case EVP_PKEY_EC:
|
|
271
|
+
// case EVP_PKEY_DSA:
|
|
272
|
+
// return dsa_encoding == kSigEncP1363;
|
|
273
|
+
// default:
|
|
274
|
+
// return false;
|
|
275
|
+
// }
|
|
276
|
+
// }
|
|
277
|
+
|
|
278
|
+
SignBase::SignResult SignBase::SignFinal(jsi::Runtime& runtime,
|
|
279
|
+
const ManagedEVPPKey& pkey,
|
|
280
|
+
int padding,
|
|
281
|
+
std::optional<int>& salt_len,
|
|
282
|
+
DSASigEnc dsa_sig_enc) {
|
|
283
|
+
if (!mdctx_) return SignResult(kSignNotInitialised);
|
|
284
|
+
|
|
285
|
+
EVPMDPointer mdctx = std::move(mdctx_);
|
|
286
|
+
|
|
287
|
+
if (!ValidateDSAParameters(pkey.get())) return SignResult(kSignPrivateKey);
|
|
288
|
+
|
|
289
|
+
std::optional<jsi::Value> buffer =
|
|
290
|
+
Node_SignFinal(runtime, std::move(mdctx), pkey, padding, salt_len);
|
|
291
|
+
Error error = buffer.has_value() ? kSignOk : kSignPrivateKey;
|
|
292
|
+
// TODO(osp) enable this
|
|
293
|
+
// if (error == kSignOk && dsa_sig_enc == kSigEncP1363) {
|
|
294
|
+
// buffer = ConvertSignatureToP1363(env(), pkey, std::move(buffer));
|
|
295
|
+
// CHECK_NOT_NULL(buffer->Data());
|
|
296
|
+
// }
|
|
297
|
+
return SignResult(error, std::move(buffer.value()));
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
SignBase::Error SignBase::VerifyFinal(const ManagedEVPPKey& pkey,
|
|
301
|
+
const ByteSource& sig, int padding,
|
|
302
|
+
std::optional<int>& saltlen,
|
|
303
|
+
bool* verify_result) {
|
|
304
|
+
if (!mdctx_) return kSignNotInitialised;
|
|
305
|
+
|
|
306
|
+
unsigned char m[EVP_MAX_MD_SIZE];
|
|
307
|
+
unsigned int m_len;
|
|
308
|
+
*verify_result = false;
|
|
309
|
+
EVPMDPointer mdctx = std::move(mdctx_);
|
|
310
|
+
|
|
311
|
+
if (!EVP_DigestFinal_ex(mdctx.get(), m, &m_len)) return kSignPublicKey;
|
|
312
|
+
|
|
313
|
+
EVPKeyCtxPointer pkctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
|
|
314
|
+
if (pkctx && EVP_PKEY_verify_init(pkctx.get()) > 0 &&
|
|
315
|
+
ApplyRSAOptions(pkey, pkctx.get(), padding, saltlen) &&
|
|
316
|
+
EVP_PKEY_CTX_set_signature_md(pkctx.get(), EVP_MD_CTX_md(mdctx.get())) >
|
|
317
|
+
0) {
|
|
318
|
+
const unsigned char* s = sig.data<unsigned char>();
|
|
319
|
+
const int r = EVP_PKEY_verify(pkctx.get(), s, sig.size(), m, m_len);
|
|
320
|
+
*verify_result = r == 1;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
return kSignOk;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
SignBase::SignBase(std::shared_ptr<react::CallInvoker> jsCallInvoker,
|
|
327
|
+
std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue)
|
|
328
|
+
: MGLSmartHostObject(jsCallInvoker, workerQueue) {}
|
|
329
|
+
|
|
330
|
+
MGLSignHostObject::MGLSignHostObject(
|
|
331
|
+
std::shared_ptr<react::CallInvoker> jsCallInvoker,
|
|
332
|
+
std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue)
|
|
333
|
+
: SignBase(jsCallInvoker, workerQueue) {
|
|
334
|
+
InstallMethods(kModeSign);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
MGLVerifyHostObject::MGLVerifyHostObject(
|
|
338
|
+
std::shared_ptr<react::CallInvoker> jsCallInvoker,
|
|
339
|
+
std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue)
|
|
340
|
+
: SignBase(jsCallInvoker, workerQueue) {
|
|
341
|
+
InstallMethods(kModeVerify);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
int GetDefaultSignPadding(const ManagedEVPPKey& m_pkey) {
|
|
345
|
+
return EVP_PKEY_id(m_pkey.get()) == EVP_PKEY_RSA_PSS ? RSA_PKCS1_PSS_PADDING
|
|
346
|
+
: RSA_PKCS1_PADDING;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
void SignBase::InstallMethods(mode mode) {
|
|
350
|
+
this->fields.push_back(buildPair(
|
|
351
|
+
"init", JSIF([=]) {
|
|
352
|
+
if (count != 1 || !arguments[0].isString()) {
|
|
353
|
+
jsi::detail::throwJSError(runtime, "init requires algorithm param");
|
|
354
|
+
return {};
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
std::string sign_type = arguments[0].asString(runtime).utf8(runtime);
|
|
358
|
+
CHECK_NULL(mdctx_);
|
|
359
|
+
|
|
360
|
+
// Historically, "dss1" and "DSS1" were DSA aliases for SHA-1
|
|
361
|
+
// exposed through the public API.
|
|
362
|
+
if (sign_type.compare("dss1") == 0 || sign_type.compare("DSS1") == 0) {
|
|
363
|
+
sign_type = "SHA1";
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const EVP_MD* md = EVP_get_digestbyname(sign_type.c_str());
|
|
367
|
+
if (md == nullptr) return jsi::Value((int)kSignUnknownDigest);
|
|
368
|
+
|
|
369
|
+
mdctx_.reset(EVP_MD_CTX_new());
|
|
370
|
+
if (!mdctx_ || !EVP_DigestInit_ex(mdctx_.get(), md, nullptr)) {
|
|
371
|
+
mdctx_.reset();
|
|
372
|
+
return jsi::Value((int)kSignInit);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return jsi::Value((int)kSignOk);
|
|
376
|
+
}));
|
|
377
|
+
|
|
378
|
+
this->fields.push_back(buildPair(
|
|
379
|
+
"update", JSIF([=]) {
|
|
380
|
+
if (count != 1) {
|
|
381
|
+
jsi::detail::throwJSError(runtime, "update requires 2 arguments");
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (!arguments[0].isObject() ||
|
|
385
|
+
!arguments[0].asObject(runtime).isArrayBuffer(runtime)) {
|
|
386
|
+
jsi::detail::throwJSError(
|
|
387
|
+
runtime, "First argument (data) needs to be an array buffer");
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
auto data = arguments[0].asObject(runtime).getArrayBuffer(runtime);
|
|
391
|
+
|
|
392
|
+
if (!CheckSizeInt32(runtime, data)) {
|
|
393
|
+
jsi::detail::throwJSError(runtime, "data is too large");
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
if (mdctx_ == nullptr) return (int)kSignNotInitialised;
|
|
397
|
+
if (!EVP_DigestUpdate(mdctx_.get(), data.data(runtime),
|
|
398
|
+
data.size(runtime)))
|
|
399
|
+
return (int)kSignUpdate;
|
|
400
|
+
return (int)kSignOk;
|
|
401
|
+
}));
|
|
402
|
+
|
|
403
|
+
if (mode == kModeSign) {
|
|
404
|
+
this->fields.push_back(buildPair(
|
|
405
|
+
"sign", JSIF([=]) {
|
|
406
|
+
unsigned int offset = 0;
|
|
407
|
+
ManagedEVPPKey key = ManagedEVPPKey::GetPrivateKeyFromJs(
|
|
408
|
+
runtime, arguments, &offset, true);
|
|
409
|
+
if (!key) {
|
|
410
|
+
return {};
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
int padding = GetDefaultSignPadding(key);
|
|
414
|
+
if (!arguments[offset].isUndefined()) {
|
|
415
|
+
// TODO(osp) need to add a check for int32
|
|
416
|
+
CHECK(arguments[offset].isNumber());
|
|
417
|
+
padding = static_cast<int>(arguments[offset].asNumber());
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
std::optional<int> salt_len;
|
|
421
|
+
if (!arguments[offset + 1].isUndefined()) {
|
|
422
|
+
// TODO(osp) add check for int32
|
|
423
|
+
CHECK(arguments[offset + 1].isNumber());
|
|
424
|
+
salt_len = static_cast<int>(arguments[offset + 1].asNumber());
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// TODO(osp) add check for int32
|
|
428
|
+
CHECK(arguments[offset + 2].isNumber());
|
|
429
|
+
DSASigEnc dsa_sig_enc = static_cast<DSASigEnc>(
|
|
430
|
+
static_cast<int>(arguments[offset + 2].asNumber()));
|
|
431
|
+
|
|
432
|
+
SignResult ret =
|
|
433
|
+
this->SignFinal(runtime, key, padding, salt_len, dsa_sig_enc);
|
|
434
|
+
|
|
435
|
+
if (ret.error != kSignOk) {
|
|
436
|
+
jsi::detail::throwJSError(runtime, "Error signing");
|
|
437
|
+
throw new jsi::JSError(runtime, "Error signing");
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
return std::move(ret.signature.value());
|
|
441
|
+
}));
|
|
442
|
+
} else {
|
|
443
|
+
this->fields.push_back(buildPair(
|
|
444
|
+
"verify", JSIF([=]) {
|
|
445
|
+
// Verify* verify;
|
|
446
|
+
// ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder());
|
|
447
|
+
|
|
448
|
+
unsigned int offset = 0;
|
|
449
|
+
ManagedEVPPKey pkey = ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(
|
|
450
|
+
runtime, arguments, &offset);
|
|
451
|
+
if (!pkey) {
|
|
452
|
+
return {};
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
jsi::ArrayBuffer hbuf =
|
|
456
|
+
arguments[offset].asObject(runtime).getArrayBuffer(runtime);
|
|
457
|
+
if (!CheckSizeInt32(runtime, hbuf)) {
|
|
458
|
+
jsi::detail::throwJSError(runtime, "buffer is too big");
|
|
459
|
+
throw jsi::JSError(runtime, "buffer is too big");
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
int padding = GetDefaultSignPadding(pkey);
|
|
463
|
+
if (!arguments[offset + 1].isUndefined()) {
|
|
464
|
+
CHECK(arguments[offset + 1].isNumber());
|
|
465
|
+
padding = static_cast<int>(arguments[offset + 1].asNumber());
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
std::optional<int> salt_len;
|
|
469
|
+
if (!arguments[offset + 2].isUndefined()) {
|
|
470
|
+
// TODO(osp) add check for int32
|
|
471
|
+
CHECK(arguments[offset + 2].isNumber());
|
|
472
|
+
salt_len = static_cast<int>(arguments[offset + 2].asNumber());
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// TODO(osp) add check for int32
|
|
476
|
+
CHECK(arguments[offset + 3].isNumber());
|
|
477
|
+
DSASigEnc dsa_sig_enc = static_cast<DSASigEnc>(
|
|
478
|
+
static_cast<int>(arguments[offset + 3].asNumber()));
|
|
479
|
+
|
|
480
|
+
ByteSource signature = ArrayBufferToByteSource(runtime, hbuf);
|
|
481
|
+
if (dsa_sig_enc == kSigEncP1363) {
|
|
482
|
+
signature = ConvertSignatureToDER(
|
|
483
|
+
pkey, ArrayBufferToByteSource(runtime, hbuf));
|
|
484
|
+
if (signature.data() == nullptr) {
|
|
485
|
+
jsi::detail::throwJSError(runtime, "kSignMalformedSignature");
|
|
486
|
+
}
|
|
487
|
+
// return crypto::CheckThrow(env,
|
|
488
|
+
// Error::kSignMalformedSignature);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
bool verify_result;
|
|
492
|
+
Error err = this->VerifyFinal(pkey, signature, padding, salt_len,
|
|
493
|
+
&verify_result);
|
|
494
|
+
if (err != kSignOk) {
|
|
495
|
+
jsi::detail::throwJSError(runtime, "Error on verify");
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
return verify_result;
|
|
499
|
+
}));
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// Verify::Verify(Environment* env, Local<Object> wrap)
|
|
504
|
+
//: SignBase(env, wrap) {
|
|
505
|
+
// MakeWeak();
|
|
506
|
+
//}
|
|
507
|
+
//
|
|
508
|
+
// void Verify::Initialize(Environment* env, Local<Object> target) {
|
|
509
|
+
// Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
|
|
510
|
+
//
|
|
511
|
+
// t->InstanceTemplate()->SetInternalFieldCount(
|
|
512
|
+
// SignBase::kInternalFieldCount);
|
|
513
|
+
// t->Inherit(BaseObject::GetConstructorTemplate(env));
|
|
514
|
+
//
|
|
515
|
+
// env->SetProtoMethod(t, "init", VerifyInit);
|
|
516
|
+
// env->SetProtoMethod(t, "update", VerifyUpdate);
|
|
517
|
+
// env->SetProtoMethod(t, "verify", VerifyFinal);
|
|
518
|
+
//
|
|
519
|
+
// env->SetConstructorFunction(target, "Verify", t);
|
|
520
|
+
//}
|
|
521
|
+
//
|
|
522
|
+
// void Verify::RegisterExternalReferences(ExternalReferenceRegistry* registry)
|
|
523
|
+
// {
|
|
524
|
+
// registry->Register(New);
|
|
525
|
+
// registry->Register(VerifyInit);
|
|
526
|
+
// registry->Register(VerifyUpdate);
|
|
527
|
+
// registry->Register(VerifyFinal);
|
|
528
|
+
//}
|
|
529
|
+
//
|
|
530
|
+
// void Verify::New(const FunctionCallbackInfo<Value>& args) {
|
|
531
|
+
// Environment* env = Environment::GetCurrent(args);
|
|
532
|
+
// new Verify(env, args.This());
|
|
533
|
+
//}
|
|
534
|
+
//
|
|
535
|
+
// void Verify::VerifyInit(const FunctionCallbackInfo<Value>& args) {
|
|
536
|
+
// Environment* env = Environment::GetCurrent(args);
|
|
537
|
+
// Verify* verify;
|
|
538
|
+
// ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder());
|
|
539
|
+
//
|
|
540
|
+
// const node::Utf8Value verify_type(args.GetIsolate(), args[0]);
|
|
541
|
+
// crypto::CheckThrow(env, verify->Init(*verify_type));
|
|
542
|
+
//}
|
|
543
|
+
//
|
|
544
|
+
// void Verify::VerifyUpdate(const FunctionCallbackInfo<Value>& args) {
|
|
545
|
+
// Decode<Verify>(args, [](Verify* verify,
|
|
546
|
+
// const FunctionCallbackInfo<Value>& args,
|
|
547
|
+
// const char* data, size_t size) {
|
|
548
|
+
// Environment* env = Environment::GetCurrent(args);
|
|
549
|
+
// if (UNLIKELY(size > INT_MAX))
|
|
550
|
+
// return THROW_ERR_OUT_OF_RANGE(env, "data is too long");
|
|
551
|
+
// Error err = verify->Update(data, size);
|
|
552
|
+
// crypto::CheckThrow(verify->env(), err);
|
|
553
|
+
// });
|
|
554
|
+
//}
|
|
555
|
+
//
|
|
556
|
+
// SignBase::Error Verify::VerifyFinal(const ManagedEVPPKey& pkey,
|
|
557
|
+
// const ByteSource& sig,
|
|
558
|
+
// int padding,
|
|
559
|
+
// const Maybe<int>& saltlen,
|
|
560
|
+
// bool* verify_result) {
|
|
561
|
+
// if (!mdctx_)
|
|
562
|
+
// return kSignNotInitialised;
|
|
563
|
+
//
|
|
564
|
+
// unsigned char m[EVP_MAX_MD_SIZE];
|
|
565
|
+
// unsigned int m_len;
|
|
566
|
+
// *verify_result = false;
|
|
567
|
+
// EVPMDPointer mdctx = std::move(mdctx_);
|
|
568
|
+
//
|
|
569
|
+
// if (!EVP_DigestFinal_ex(mdctx.get(), m, &m_len))
|
|
570
|
+
// return kSignPublicKey;
|
|
571
|
+
//
|
|
572
|
+
// EVPKeyCtxPointer pkctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
|
|
573
|
+
// if (pkctx &&
|
|
574
|
+
// EVP_PKEY_verify_init(pkctx.get()) > 0 &&
|
|
575
|
+
// ApplyRSAOptions(pkey, pkctx.get(), padding, saltlen) &&
|
|
576
|
+
// EVP_PKEY_CTX_set_signature_md(pkctx.get(),
|
|
577
|
+
// EVP_MD_CTX_md(mdctx.get())) > 0) {
|
|
578
|
+
// const unsigned char* s = sig.data<unsigned char>();
|
|
579
|
+
// const int r = EVP_PKEY_verify(pkctx.get(), s, sig.size(), m, m_len);
|
|
580
|
+
// *verify_result = r == 1;
|
|
581
|
+
// }
|
|
582
|
+
//
|
|
583
|
+
// return kSignOk;
|
|
584
|
+
//}
|
|
585
|
+
//
|
|
586
|
+
// void Verify::VerifyFinal(const FunctionCallbackInfo<Value>& args) {
|
|
587
|
+
// Environment* env = Environment::GetCurrent(args);
|
|
588
|
+
// ClearErrorOnReturn clear_error_on_return;
|
|
589
|
+
//
|
|
590
|
+
// Verify* verify;
|
|
591
|
+
// ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder());
|
|
592
|
+
//
|
|
593
|
+
// unsigned int offset = 0;
|
|
594
|
+
// ManagedEVPPKey pkey =
|
|
595
|
+
// ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(args, &offset);
|
|
596
|
+
// if (!pkey)
|
|
597
|
+
// return;
|
|
598
|
+
//
|
|
599
|
+
// ArrayBufferOrViewContents<char> hbuf(args[offset]);
|
|
600
|
+
// if (UNLIKELY(!hbuf.CheckSizeInt32()))
|
|
601
|
+
// return THROW_ERR_OUT_OF_RANGE(env, "buffer is too big");
|
|
602
|
+
//
|
|
603
|
+
// int padding = GetDefaultSignPadding(pkey);
|
|
604
|
+
// if (!args[offset + 1]->IsUndefined()) {
|
|
605
|
+
// CHECK(args[offset + 1]->IsInt32());
|
|
606
|
+
// padding = args[offset + 1].As<Int32>()->Value();
|
|
607
|
+
// }
|
|
608
|
+
//
|
|
609
|
+
// Maybe<int> salt_len = Nothing<int>();
|
|
610
|
+
// if (!args[offset + 2]->IsUndefined()) {
|
|
611
|
+
// CHECK(args[offset + 2]->IsInt32());
|
|
612
|
+
// salt_len = Just<int>(args[offset + 2].As<Int32>()->Value());
|
|
613
|
+
// }
|
|
614
|
+
//
|
|
615
|
+
// CHECK(args[offset + 3]->IsInt32());
|
|
616
|
+
// DSASigEnc dsa_sig_enc =
|
|
617
|
+
// static_cast<DSASigEnc>(args[offset + 3].As<Int32>()->Value());
|
|
618
|
+
//
|
|
619
|
+
// ByteSource signature = hbuf.ToByteSource();
|
|
620
|
+
// if (dsa_sig_enc == kSigEncP1363) {
|
|
621
|
+
// signature = ConvertSignatureToDER(pkey, hbuf.ToByteSource());
|
|
622
|
+
// if (signature.data() == nullptr)
|
|
623
|
+
// return crypto::CheckThrow(env, Error::kSignMalformedSignature);
|
|
624
|
+
// }
|
|
625
|
+
//
|
|
626
|
+
// bool verify_result;
|
|
627
|
+
// Error err = verify->VerifyFinal(pkey, signature, padding,
|
|
628
|
+
// salt_len, &verify_result);
|
|
629
|
+
// if (err != kSignOk)
|
|
630
|
+
// return crypto::CheckThrow(env, err);
|
|
631
|
+
// args.GetReturnValue().Set(verify_result);
|
|
632
|
+
//}
|
|
633
|
+
//
|
|
634
|
+
// SignConfiguration::SignConfiguration(SignConfiguration&& other) noexcept
|
|
635
|
+
//: job_mode(other.job_mode),
|
|
636
|
+
// mode(other.mode),
|
|
637
|
+
// key(std::move(other.key)),
|
|
638
|
+
// data(std::move(other.data)),
|
|
639
|
+
// signature(std::move(other.signature)),
|
|
640
|
+
// digest(other.digest),
|
|
641
|
+
// flags(other.flags),
|
|
642
|
+
// padding(other.padding),
|
|
643
|
+
// salt_length(other.salt_length),
|
|
644
|
+
// dsa_encoding(other.dsa_encoding) {}
|
|
645
|
+
//
|
|
646
|
+
// SignConfiguration& SignConfiguration::operator=(
|
|
647
|
+
// SignConfiguration&& other)
|
|
648
|
+
// noexcept {
|
|
649
|
+
// if (&other == this) return
|
|
650
|
+
// *this;
|
|
651
|
+
// this->~SignConfiguration();
|
|
652
|
+
// return *new (this)
|
|
653
|
+
// SignConfiguration(std::move(other));
|
|
654
|
+
// }
|
|
655
|
+
//
|
|
656
|
+
// void SignConfiguration::MemoryInfo(MemoryTracker* tracker) const {
|
|
657
|
+
// tracker->TrackField("key", key);
|
|
658
|
+
// if (job_mode == kCryptoJobAsync) {
|
|
659
|
+
// tracker->TrackFieldWithSize("data", data.size());
|
|
660
|
+
// tracker->TrackFieldWithSize("signature", signature.size());
|
|
661
|
+
// }
|
|
662
|
+
// }
|
|
663
|
+
//
|
|
664
|
+
// Maybe<bool> SignTraits::AdditionalConfig(
|
|
665
|
+
// CryptoJobMode mode,
|
|
666
|
+
// const FunctionCallbackInfo<Value>&
|
|
667
|
+
// args, unsigned int offset,
|
|
668
|
+
// SignConfiguration* params) {
|
|
669
|
+
// ClearErrorOnReturn clear_error_on_return;
|
|
670
|
+
// Environment* env = Environment::GetCurrent(args);
|
|
671
|
+
//
|
|
672
|
+
// params->job_mode = mode;
|
|
673
|
+
//
|
|
674
|
+
// CHECK(args[offset]->IsUint32()); // Sign Mode
|
|
675
|
+
//
|
|
676
|
+
// params->mode =
|
|
677
|
+
// static_cast<SignConfiguration::Mode>(args[offset].As<Uint32>()->Value());
|
|
678
|
+
//
|
|
679
|
+
// ManagedEVPPKey key;
|
|
680
|
+
// unsigned int keyParamOffset = offset + 1;
|
|
681
|
+
// if (params->mode == SignConfiguration::kVerify) {
|
|
682
|
+
// key = ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(args, &keyParamOffset);
|
|
683
|
+
// } else {
|
|
684
|
+
// key = ManagedEVPPKey::GetPrivateKeyFromJs(args, &keyParamOffset, true);
|
|
685
|
+
// }
|
|
686
|
+
// if (!key)
|
|
687
|
+
// return Nothing<bool>();
|
|
688
|
+
// params->key = key;
|
|
689
|
+
//
|
|
690
|
+
// ArrayBufferOrViewContents<char> data(args[offset + 5]);
|
|
691
|
+
// if (UNLIKELY(!data.CheckSizeInt32())) {
|
|
692
|
+
// THROW_ERR_OUT_OF_RANGE(env, "data is too big");
|
|
693
|
+
// return Nothing<bool>();
|
|
694
|
+
// }
|
|
695
|
+
// params->data = mode == kCryptoJobAsync
|
|
696
|
+
// ? data.ToCopy()
|
|
697
|
+
// : data.ToByteSource();
|
|
698
|
+
//
|
|
699
|
+
// if (args[offset + 6]->IsString()) {
|
|
700
|
+
// Utf8Value digest(env->isolate(), args[offset + 6]);
|
|
701
|
+
// params->digest = EVP_get_digestbyname(*digest);
|
|
702
|
+
// if (params->digest == nullptr) {
|
|
703
|
+
// THROW_ERR_CRYPTO_INVALID_DIGEST(env);
|
|
704
|
+
// return Nothing<bool>();
|
|
705
|
+
// }
|
|
706
|
+
// }
|
|
707
|
+
//
|
|
708
|
+
// if (args[offset + 7]->IsInt32()) { // Salt length
|
|
709
|
+
// params->flags |= SignConfiguration::kHasSaltLength;
|
|
710
|
+
// params->salt_length = args[offset + 7].As<Int32>()->Value();
|
|
711
|
+
// }
|
|
712
|
+
// if (args[offset + 8]->IsUint32()) { // Padding
|
|
713
|
+
// params->flags |= SignConfiguration::kHasPadding;
|
|
714
|
+
// params->padding = args[offset + 8].As<Uint32>()->Value();
|
|
715
|
+
// }
|
|
716
|
+
//
|
|
717
|
+
// if (args[offset + 9]->IsUint32()) { // DSA Encoding
|
|
718
|
+
// params->dsa_encoding =
|
|
719
|
+
// static_cast<DSASigEnc>(args[offset + 9].As<Uint32>()->Value());
|
|
720
|
+
// if (params->dsa_encoding != kSigEncDER &&
|
|
721
|
+
// params->dsa_encoding != kSigEncP1363) {
|
|
722
|
+
// THROW_ERR_OUT_OF_RANGE(env, "invalid signature encoding");
|
|
723
|
+
// return Nothing<bool>();
|
|
724
|
+
// }
|
|
725
|
+
// }
|
|
726
|
+
//
|
|
727
|
+
// if (params->mode == SignConfiguration::kVerify) {
|
|
728
|
+
// ArrayBufferOrViewContents<char> signature(args[offset + 10]);
|
|
729
|
+
// if (UNLIKELY(!signature.CheckSizeInt32())) {
|
|
730
|
+
// THROW_ERR_OUT_OF_RANGE(env, "signature is too big");
|
|
731
|
+
// return Nothing<bool>();
|
|
732
|
+
// }
|
|
733
|
+
// // If this is an EC key (assuming ECDSA) we need to convert the
|
|
734
|
+
// // the signature from WebCrypto format into DER format...
|
|
735
|
+
// ManagedEVPPKey m_pkey = params->key;
|
|
736
|
+
// Mutex::ScopedLock lock(*m_pkey.mutex());
|
|
737
|
+
// if (UseP1363Encoding(m_pkey, params->dsa_encoding)) {
|
|
738
|
+
// params->signature =
|
|
739
|
+
// ConvertSignatureToDER(m_pkey, signature.ToByteSource());
|
|
740
|
+
// } else {
|
|
741
|
+
// params->signature = mode == kCryptoJobAsync
|
|
742
|
+
// ? signature.ToCopy()
|
|
743
|
+
// : signature.ToByteSource();
|
|
744
|
+
// }
|
|
745
|
+
// }
|
|
746
|
+
//
|
|
747
|
+
// return Just(true);
|
|
748
|
+
// }
|
|
749
|
+
//
|
|
750
|
+
// bool SignTraits::DeriveBits(
|
|
751
|
+
// Environment* env,
|
|
752
|
+
// const SignConfiguration& params,
|
|
753
|
+
// ByteSource* out) {
|
|
754
|
+
// ClearErrorOnReturn clear_error_on_return;
|
|
755
|
+
// EVPMDPointer context(EVP_MD_CTX_new());
|
|
756
|
+
// EVP_PKEY_CTX* ctx = nullptr;
|
|
757
|
+
//
|
|
758
|
+
// switch (params.mode) {
|
|
759
|
+
// case SignConfiguration::kSign:
|
|
760
|
+
// if (!EVP_DigestSignInit(
|
|
761
|
+
// context.get(),
|
|
762
|
+
// &ctx,
|
|
763
|
+
// params.digest,
|
|
764
|
+
// nullptr,
|
|
765
|
+
// params.key.get())) {
|
|
766
|
+
// crypto::CheckThrow(env,
|
|
767
|
+
// SignBase::Error::kSignInit); return false;
|
|
768
|
+
// }
|
|
769
|
+
// break;
|
|
770
|
+
// case SignConfiguration::kVerify:
|
|
771
|
+
// if (!EVP_DigestVerifyInit(
|
|
772
|
+
// context.get(),
|
|
773
|
+
// &ctx,
|
|
774
|
+
// params.digest,
|
|
775
|
+
// nullptr,
|
|
776
|
+
// params.key.get())) {
|
|
777
|
+
// crypto::CheckThrow(env,
|
|
778
|
+
// SignBase::Error::kSignInit); return false;
|
|
779
|
+
// }
|
|
780
|
+
// break;
|
|
781
|
+
// }
|
|
782
|
+
//
|
|
783
|
+
// int padding = params.flags & SignConfiguration::kHasPadding
|
|
784
|
+
// ? params.padding
|
|
785
|
+
// : GetDefaultSignPadding(params.key);
|
|
786
|
+
//
|
|
787
|
+
// Maybe<int> salt_length = params.flags & SignConfiguration::kHasSaltLength
|
|
788
|
+
// ? Just<int>(params.salt_length) : Nothing<int>();
|
|
789
|
+
//
|
|
790
|
+
// if (!ApplyRSAOptions(
|
|
791
|
+
// params.key,
|
|
792
|
+
// ctx,
|
|
793
|
+
// padding,
|
|
794
|
+
// salt_length)) {
|
|
795
|
+
// crypto::CheckThrow(env,
|
|
796
|
+
// SignBase::Error::kSignPrivateKey); return false;
|
|
797
|
+
// }
|
|
798
|
+
//
|
|
799
|
+
// switch (params.mode) {
|
|
800
|
+
// case SignConfiguration::kSign: {
|
|
801
|
+
// if (IsOneShot(params.key)) {
|
|
802
|
+
// size_t len;
|
|
803
|
+
// if (!EVP_DigestSign(
|
|
804
|
+
// context.get(),
|
|
805
|
+
// nullptr,
|
|
806
|
+
// &len,
|
|
807
|
+
// params.data.data<unsigned char>(),
|
|
808
|
+
// params.data.size())) {
|
|
809
|
+
// crypto::CheckThrow(env,
|
|
810
|
+
// SignBase::Error::kSignPrivateKey); return
|
|
811
|
+
// false;
|
|
812
|
+
// }
|
|
813
|
+
// ByteSource::Builder buf(len);
|
|
814
|
+
// if (!EVP_DigestSign(context.get(),
|
|
815
|
+
// buf.data<unsigned char>(),
|
|
816
|
+
// &len,
|
|
817
|
+
// params.data.data<unsigned char>(),
|
|
818
|
+
// params.data.size())) {
|
|
819
|
+
// crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey);
|
|
820
|
+
// return false;
|
|
821
|
+
// }
|
|
822
|
+
// *out = std::move(buf).release(len);
|
|
823
|
+
// } else {
|
|
824
|
+
// size_t len;
|
|
825
|
+
// if (!EVP_DigestSignUpdate(
|
|
826
|
+
// context.get(),
|
|
827
|
+
// params.data.data<unsigned char>(),
|
|
828
|
+
// params.data.size()) ||
|
|
829
|
+
// !EVP_DigestSignFinal(context.get(), nullptr, &len)) {
|
|
830
|
+
// crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey);
|
|
831
|
+
// return false;
|
|
832
|
+
// }
|
|
833
|
+
// ByteSource::Builder buf(len);
|
|
834
|
+
// if (!EVP_DigestSignFinal(
|
|
835
|
+
// context.get(), buf.data<unsigned char>(),
|
|
836
|
+
// &len)) {
|
|
837
|
+
// crypto::CheckThrow(env,
|
|
838
|
+
// SignBase::Error::kSignPrivateKey); return
|
|
839
|
+
// false;
|
|
840
|
+
// }
|
|
841
|
+
//
|
|
842
|
+
// if (UseP1363Encoding(params.key, params.dsa_encoding)) {
|
|
843
|
+
// *out = ConvertSignatureToP1363(
|
|
844
|
+
// env, params.key,
|
|
845
|
+
// std::move(buf).release());
|
|
846
|
+
// } else {
|
|
847
|
+
// *out = std::move(buf).release(len);
|
|
848
|
+
// }
|
|
849
|
+
// }
|
|
850
|
+
// break;
|
|
851
|
+
// }
|
|
852
|
+
// case SignConfiguration::kVerify: {
|
|
853
|
+
// ByteSource::Builder buf(1);
|
|
854
|
+
// buf.data<char>()[0] = 0;
|
|
855
|
+
// if (EVP_DigestVerify(
|
|
856
|
+
// context.get(),
|
|
857
|
+
// params.signature.data<unsigned char>(),
|
|
858
|
+
// params.signature.size(),
|
|
859
|
+
// params.data.data<unsigned char>(),
|
|
860
|
+
// params.data.size()) == 1) {
|
|
861
|
+
// buf.data<char>()[0] = 1;
|
|
862
|
+
// }
|
|
863
|
+
// *out = std::move(buf).release();
|
|
864
|
+
// }
|
|
865
|
+
// }
|
|
866
|
+
//
|
|
867
|
+
// return true;
|
|
868
|
+
// }
|
|
869
|
+
//
|
|
870
|
+
// Maybe<bool> SignTraits::EncodeOutput(
|
|
871
|
+
// Environment* env,
|
|
872
|
+
// const SignConfiguration& params,
|
|
873
|
+
// ByteSource* out,
|
|
874
|
+
// Local<Value>* result) {
|
|
875
|
+
// switch (params.mode) {
|
|
876
|
+
// case SignConfiguration::kSign:
|
|
877
|
+
// *result = out->ToArrayBuffer(env);
|
|
878
|
+
// break;
|
|
879
|
+
// case SignConfiguration::kVerify:
|
|
880
|
+
// *result = out->data<char>()[0] == 1 ? v8::True(env->isolate())
|
|
881
|
+
// : v8::False(env->isolate());
|
|
882
|
+
// break;
|
|
883
|
+
// default:
|
|
884
|
+
// UNREACHABLE();
|
|
885
|
+
// }
|
|
886
|
+
// return Just(!result->IsEmpty());
|
|
887
|
+
// }
|
|
888
|
+
|
|
889
|
+
} // namespace margelo
|