Skip to content

Commit 9afde2d

Browse files
committed
src: move spkac methods to ncrypto
1 parent 1fb23f1 commit 9afde2d

File tree

4 files changed

+97
-67
lines changed

4 files changed

+97
-67
lines changed

deps/ncrypto/ncrypto.cc

Lines changed: 73 additions & 1 deletion
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,75 @@ 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+
length = std::string(input.data()).find_last_not_of(" \n\r\t") + 1;
233+
#endif
234+
NetscapeSPKIPointer spki(
235+
NETSCAPE_SPKI_b64_decode(input, length));
236+
if (!spki)
237+
return false;
238+
239+
EVPKeyPointer pkey(X509_PUBKEY_get(spki->spkac->pubkey));
240+
return pkey ? NETSCAPE_SPKI_verify(spki.get(), pkey.get()) > 0 : false;
241+
}
242+
243+
BIOPointer ExportPublicKey(const char* input, size_t length) {
244+
BIOPointer bio(BIO_new(BIO_s_mem()));
245+
if (!bio) return BIOPointer();
246+
247+
#ifdef OPENSSL_IS_BORINGSSL
248+
// OpenSSL uses EVP_DecodeBlock, which explicitly removes trailing characters,
249+
// while BoringSSL uses EVP_DecodedLength and EVP_DecodeBase64, which do not.
250+
// As such, we trim those characters here for compatibility.
251+
length = std::string(input).find_last_not_of(" \n\r\t") + 1;
252+
#endif
253+
NetscapeSPKIPointer spki(
254+
NETSCAPE_SPKI_b64_decode(input, length));
255+
if (!spki) return BIOPointer();
256+
257+
EVPKeyPointer pkey(NETSCAPE_SPKI_get_pubkey(spki.get()));
258+
if (!pkey) return BIOPointer();
259+
260+
if (PEM_write_bio_PUBKEY(bio.get(), pkey.get()) <= 0) return BIOPointer();
261+
262+
return std::move(bio);
263+
}
264+
265+
Buffer<char> ExportChallenge(const char* input, size_t length) {
266+
#ifdef OPENSSL_IS_BORINGSSL
267+
// OpenSSL uses EVP_DecodeBlock, which explicitly removes trailing characters,
268+
// while BoringSSL uses EVP_DecodedLength and EVP_DecodeBase64, which do not.
269+
// As such, we trim those characters here for compatibility.
270+
length = std::string(input).find_last_not_of(" \n\r\t") + 1;
271+
#endif
272+
NetscapeSPKIPointer sp(
273+
NETSCAPE_SPKI_b64_decode(input, length));
274+
if (!sp) {
275+
return Buffer<char> {
276+
.data = nullptr,
277+
.len = 0,
278+
};
279+
}
280+
281+
unsigned char* buf = nullptr;
282+
int buf_size = ASN1_STRING_to_UTF8(&buf, sp->spkac->challenge);
283+
if (buf_size >= 0) {
284+
return Buffer<char> {
285+
.data = reinterpret_cast<char*>(buf),
286+
.len = static_cast<size_t>(buf_size),
287+
};
288+
}
289+
return Buffer<char> {
290+
.data = nullptr,
291+
.len = 0,
292+
};
293+
}
294+
223295
} // namespace ncrypto

deps/ncrypto/ncrypto.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,8 +269,9 @@ bool testFipsEnabled();
269269
// ============================================================================
270270
// Various utilities
271271

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

@@ -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"

src/crypto/crypto_spkac.cc

Lines changed: 7 additions & 65 deletions
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

src/crypto/crypto_util.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,12 @@ class ByteSource {
289289
v8::MaybeLocal<v8::Uint8Array> ToBuffer(Environment* env);
290290

291291
static ByteSource Allocated(void* data, size_t size);
292+
293+
template <typename T>
294+
static ByteSource Allocated(const ncrypto::Buffer<T>& buffer) {
295+
return Allocated(buffer.data, buffer.len);
296+
}
297+
292298
static ByteSource Foreign(const void* data, size_t size);
293299

294300
static ByteSource FromEncodedString(Environment* env,

0 commit comments

Comments
 (0)