Skip to content

Commit e619133

Browse files
jasnelltargos
authored andcommittedAug 14, 2024
src: move spkac methods to ncrypto
PR-URL: #53985 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
1 parent 1e82591 commit e619133

File tree

4 files changed

+95
-68
lines changed

4 files changed

+95
-68
lines changed
 

Diff for: ‎deps/ncrypto/ncrypto.cc

+70-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <algorithm>
33
#include <cstring>
44
#include "openssl/bn.h"
5+
#include "openssl/evp.h"
56
#if OPENSSL_VERSION_MAJOR >= 3
67
#include "openssl/provider.h"
78
#endif
@@ -207,7 +208,7 @@ int NoPasswordCallback(char* buf, int size, int rwflag, void* u) {
207208
}
208209

209210
int PasswordCallback(char* buf, int size, int rwflag, void* u) {
210-
const Buffer* passphrase = static_cast<const Buffer*>(u);
211+
auto passphrase = static_cast<const Buffer<char>*>(u);
211212
if (passphrase != nullptr) {
212213
size_t buflen = static_cast<size_t>(size);
213214
size_t len = passphrase->len;
@@ -220,4 +221,72 @@ int PasswordCallback(char* buf, int size, int rwflag, void* u) {
220221
return -1;
221222
}
222223

224+
// ============================================================================
225+
// SPKAC
226+
227+
bool VerifySpkac(const char* input, size_t length) {
228+
#ifdef OPENSSL_IS_BORINGSSL
229+
// OpenSSL uses EVP_DecodeBlock, which explicitly removes trailing characters,
230+
// while BoringSSL uses EVP_DecodedLength and EVP_DecodeBase64, which do not.
231+
// As such, we trim those characters here for compatibility.
232+
//
233+
// find_last_not_of can return npos, which is the maximum value of size_t.
234+
// The + 1 will force a roll-ver to 0, which is the correct value. in that
235+
// case.
236+
length = std::string_view(input, length).find_last_not_of(" \n\r\t") + 1;
237+
#endif
238+
NetscapeSPKIPointer spki(
239+
NETSCAPE_SPKI_b64_decode(input, length));
240+
if (!spki)
241+
return false;
242+
243+
EVPKeyPointer pkey(X509_PUBKEY_get(spki->spkac->pubkey));
244+
return pkey ? NETSCAPE_SPKI_verify(spki.get(), pkey.get()) > 0 : false;
245+
}
246+
247+
BIOPointer ExportPublicKey(const char* input, size_t length) {
248+
BIOPointer bio(BIO_new(BIO_s_mem()));
249+
if (!bio) return {};
250+
251+
#ifdef OPENSSL_IS_BORINGSSL
252+
// OpenSSL uses EVP_DecodeBlock, which explicitly removes trailing characters,
253+
// while BoringSSL uses EVP_DecodedLength and EVP_DecodeBase64, which do not.
254+
// As such, we trim those characters here for compatibility.
255+
length = std::string_view(input, length).find_last_not_of(" \n\r\t") + 1;
256+
#endif
257+
NetscapeSPKIPointer spki(
258+
NETSCAPE_SPKI_b64_decode(input, length));
259+
if (!spki) return {};
260+
261+
EVPKeyPointer pkey(NETSCAPE_SPKI_get_pubkey(spki.get()));
262+
if (!pkey) return {};
263+
264+
if (PEM_write_bio_PUBKEY(bio.get(), pkey.get()) <= 0) return { };
265+
266+
return std::move(bio);
267+
}
268+
269+
Buffer<char> ExportChallenge(const char* input, size_t length) {
270+
#ifdef OPENSSL_IS_BORINGSSL
271+
// OpenSSL uses EVP_DecodeBlock, which explicitly removes trailing characters,
272+
// while BoringSSL uses EVP_DecodedLength and EVP_DecodeBase64, which do not.
273+
// As such, we trim those characters here for compatibility.
274+
length = std::string_view(input, length).find_last_not_of(" \n\r\t") + 1;
275+
#endif
276+
NetscapeSPKIPointer sp(
277+
NETSCAPE_SPKI_b64_decode(input, length));
278+
if (!sp) return {};
279+
280+
unsigned char* buf = nullptr;
281+
int buf_size = ASN1_STRING_to_UTF8(&buf, sp->spkac->challenge);
282+
if (buf_size >= 0) {
283+
return {
284+
.data = reinterpret_cast<char*>(buf),
285+
.len = static_cast<size_t>(buf_size),
286+
};
287+
}
288+
289+
return {};
290+
}
291+
223292
} // namespace ncrypto

Diff for: ‎deps/ncrypto/ncrypto.h

+12-2
Original file line numberDiff line numberDiff line change
@@ -269,9 +269,10 @@ bool testFipsEnabled();
269269
// ============================================================================
270270
// Various utilities
271271

272+
template <typename T>
272273
struct Buffer {
273-
const void* data;
274-
size_t len;
274+
T* data = nullptr;
275+
size_t len = 0;
275276
};
276277

277278
bool CSPRNG(void* buffer, size_t length) NCRYPTO_MUST_USE_RESULT;
@@ -285,6 +286,15 @@ int NoPasswordCallback(char* buf, int size, int rwflag, void* u);
285286

286287
int PasswordCallback(char* buf, int size, int rwflag, void* u);
287288

289+
// ============================================================================
290+
// SPKAC
291+
292+
bool VerifySpkac(const char* input, size_t length);
293+
BIOPointer ExportPublicKey(const char* input, size_t length);
294+
295+
// The caller takes ownership of the returned Buffer<char>
296+
Buffer<char> ExportChallenge(const char* input, size_t length);
297+
288298
// ============================================================================
289299
// Version metadata
290300
#define NCRYPTO_VERSION "0.0.1"

Diff for: ‎src/crypto/crypto_spkac.cc

+7-65
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "crypto/crypto_util.h"
44
#include "env-inl.h"
55
#include "memory_tracker-inl.h"
6+
#include "ncrypto.h"
67
#include "node.h"
78
#include "v8.h"
89

@@ -16,25 +17,6 @@ using v8::Value;
1617

1718
namespace crypto {
1819
namespace SPKAC {
19-
bool VerifySpkac(const ArrayBufferOrViewContents<char>& input) {
20-
size_t length = input.size();
21-
#ifdef OPENSSL_IS_BORINGSSL
22-
// OpenSSL uses EVP_DecodeBlock, which explicitly removes trailing characters,
23-
// while BoringSSL uses EVP_DecodedLength and EVP_DecodeBase64, which do not.
24-
// As such, we trim those characters here for compatibility.
25-
length = std::string(input.data()).find_last_not_of(" \n\r\t") + 1;
26-
#endif
27-
NetscapeSPKIPointer spki(
28-
NETSCAPE_SPKI_b64_decode(input.data(), length));
29-
if (!spki)
30-
return false;
31-
32-
EVPKeyPointer pkey(X509_PUBKEY_get(spki->spkac->pubkey));
33-
if (!pkey)
34-
return false;
35-
36-
return NETSCAPE_SPKI_verify(spki.get(), pkey.get()) > 0;
37-
}
3820

3921
void VerifySpkac(const FunctionCallbackInfo<Value>& args) {
4022
Environment* env = Environment::GetCurrent(args);
@@ -44,31 +26,7 @@ void VerifySpkac(const FunctionCallbackInfo<Value>& args) {
4426
if (UNLIKELY(!input.CheckSizeInt32()))
4527
return THROW_ERR_OUT_OF_RANGE(env, "spkac is too large");
4628

47-
args.GetReturnValue().Set(VerifySpkac(input));
48-
}
49-
50-
ByteSource ExportPublicKey(Environment* env,
51-
const ArrayBufferOrViewContents<char>& input) {
52-
BIOPointer bio(BIO_new(BIO_s_mem()));
53-
if (!bio) return ByteSource();
54-
55-
size_t length = input.size();
56-
#ifdef OPENSSL_IS_BORINGSSL
57-
// OpenSSL uses EVP_DecodeBlock, which explicitly removes trailing characters,
58-
// while BoringSSL uses EVP_DecodedLength and EVP_DecodeBase64, which do not.
59-
// As such, we trim those characters here for compatibility.
60-
length = std::string(input.data()).find_last_not_of(" \n\r\t") + 1;
61-
#endif
62-
NetscapeSPKIPointer spki(
63-
NETSCAPE_SPKI_b64_decode(input.data(), length));
64-
if (!spki) return ByteSource();
65-
66-
EVPKeyPointer pkey(NETSCAPE_SPKI_get_pubkey(spki.get()));
67-
if (!pkey) return ByteSource();
68-
69-
if (PEM_write_bio_PUBKEY(bio.get(), pkey.get()) <= 0) return ByteSource();
70-
71-
return ByteSource::FromBIO(bio);
29+
args.GetReturnValue().Set(ncrypto::VerifySpkac(input.data(), input.size()));
7230
}
7331

7432
void ExportPublicKey(const FunctionCallbackInfo<Value>& args) {
@@ -80,30 +38,13 @@ void ExportPublicKey(const FunctionCallbackInfo<Value>& args) {
8038
if (UNLIKELY(!input.CheckSizeInt32()))
8139
return THROW_ERR_OUT_OF_RANGE(env, "spkac is too large");
8240

83-
ByteSource pkey = ExportPublicKey(env, input);
84-
if (!pkey) return args.GetReturnValue().SetEmptyString();
41+
BIOPointer bio = ncrypto::ExportPublicKey(input.data(), input.size());
42+
if (!bio) return args.GetReturnValue().SetEmptyString();
8543

44+
auto pkey = ByteSource::FromBIO(bio);
8645
args.GetReturnValue().Set(pkey.ToBuffer(env).FromMaybe(Local<Value>()));
8746
}
8847

89-
ByteSource ExportChallenge(const ArrayBufferOrViewContents<char>& input) {
90-
size_t length = input.size();
91-
#ifdef OPENSSL_IS_BORINGSSL
92-
// OpenSSL uses EVP_DecodeBlock, which explicitly removes trailing characters,
93-
// while BoringSSL uses EVP_DecodedLength and EVP_DecodeBase64, which do not.
94-
// As such, we trim those characters here for compatibility.
95-
length = std::string(input.data()).find_last_not_of(" \n\r\t") + 1;
96-
#endif
97-
NetscapeSPKIPointer sp(
98-
NETSCAPE_SPKI_b64_decode(input.data(), length));
99-
if (!sp)
100-
return ByteSource();
101-
102-
unsigned char* buf = nullptr;
103-
int buf_size = ASN1_STRING_to_UTF8(&buf, sp->spkac->challenge);
104-
return (buf_size >= 0) ? ByteSource::Allocated(buf, buf_size) : ByteSource();
105-
}
106-
10748
void ExportChallenge(const FunctionCallbackInfo<Value>& args) {
10849
Environment* env = Environment::GetCurrent(args);
10950

@@ -113,7 +54,8 @@ void ExportChallenge(const FunctionCallbackInfo<Value>& args) {
11354
if (UNLIKELY(!input.CheckSizeInt32()))
11455
return THROW_ERR_OUT_OF_RANGE(env, "spkac is too large");
11556

116-
ByteSource cert = ExportChallenge(input);
57+
auto cert = ByteSource::Allocated(
58+
ncrypto::ExportChallenge(input.data(), input.size()));
11759
if (!cert)
11860
return args.GetReturnValue().SetEmptyString();
11961

Diff for: ‎src/crypto/crypto_util.h

+6
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,12 @@ class ByteSource {
275275
v8::MaybeLocal<v8::Uint8Array> ToBuffer(Environment* env);
276276

277277
static ByteSource Allocated(void* data, size_t size);
278+
279+
template <typename T>
280+
static ByteSource Allocated(const ncrypto::Buffer<T>& buffer) {
281+
return Allocated(buffer.data, buffer.len);
282+
}
283+
278284
static ByteSource Foreign(const void* data, size_t size);
279285

280286
static ByteSource FromEncodedString(Environment* env,

0 commit comments

Comments
 (0)