Skip to content

Commit 126fcd7

Browse files
jasnellnpaun
authored andcommitted
src: move spkac methods to ncrypto
PR-URL: nodejs/node#53985 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
1 parent 3eb26ed commit 126fcd7

2 files changed

Lines changed: 82 additions & 3 deletions

File tree

ncrypto.cc

Lines changed: 70 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,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

ncrypto.h

Lines changed: 12 additions & 2 deletions
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"

0 commit comments

Comments
 (0)