Skip to content

Commit 5843486

Browse files
committed
src: move more x509 to ncrypto
Signed-off-by: James M Snell <[email protected]>
1 parent a2ec037 commit 5843486

File tree

3 files changed

+123
-62
lines changed

3 files changed

+123
-62
lines changed

deps/ncrypto/ncrypto.cc

+71
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,18 @@ BIOPointer X509View::toDER() const {
915915
return bio;
916916
}
917917

918+
const X509Name X509View::getSubjectName() const {
919+
ClearErrorOnReturn clearErrorOnReturn;
920+
if (cert_ == nullptr) return {};
921+
return X509Name(X509_get_subject_name(cert_));
922+
}
923+
924+
const X509Name X509View::getIssuerName() const {
925+
ClearErrorOnReturn clearErrorOnReturn;
926+
if (cert_ == nullptr) return {};
927+
return X509Name(X509_get_issuer_name(cert_));
928+
}
929+
918930
BIOPointer X509View::getSubject() const {
919931
ClearErrorOnReturn clearErrorOnReturn;
920932
if (cert_ == nullptr) return {};
@@ -3831,4 +3843,63 @@ DataPointer hashDigest(const Buffer<const unsigned char>& buf,
38313843
return data.resize(result_size);
38323844
}
38333845

3846+
// ============================================================================
3847+
3848+
X509Name::X509Name() : name_(nullptr), total_(0) {}
3849+
3850+
X509Name::X509Name(const X509_NAME* name)
3851+
: name_(name), total_(X509_NAME_entry_count(name)) {}
3852+
3853+
X509Name::Iterator::Iterator(const X509Name& name, int pos)
3854+
: name_(name), loc_(pos) {}
3855+
3856+
X509Name::Iterator& X509Name::Iterator::operator++() {
3857+
++loc_;
3858+
return *this;
3859+
}
3860+
3861+
X509Name::Iterator::operator bool() const {
3862+
return loc_ < name_.total_;
3863+
}
3864+
3865+
bool X509Name::Iterator::operator==(const Iterator& other) const {
3866+
return loc_ == other.loc_;
3867+
}
3868+
3869+
bool X509Name::Iterator::operator!=(const Iterator& other) const {
3870+
return loc_ != other.loc_;
3871+
}
3872+
3873+
std::pair<std::string, std::string> X509Name::Iterator::operator*() const {
3874+
if (loc_ == name_.total_) return {{}, {}};
3875+
3876+
X509_NAME_ENTRY* entry = X509_NAME_get_entry(name_, loc_);
3877+
if (entry == nullptr) [[unlikely]]
3878+
return {{}, {}};
3879+
3880+
ASN1_OBJECT* name = X509_NAME_ENTRY_get_object(entry);
3881+
ASN1_STRING* value = X509_NAME_ENTRY_get_data(entry);
3882+
3883+
if (name == nullptr || value == nullptr) [[unlikely]] {
3884+
return {{}, {}};
3885+
}
3886+
3887+
int nid = OBJ_obj2nid(name);
3888+
std::string name_str;
3889+
if (nid != NID_undef) {
3890+
name_str = std::string(OBJ_nid2sn(nid));
3891+
} else {
3892+
char buf[80];
3893+
OBJ_obj2txt(buf, sizeof(buf), name, 0);
3894+
name_str = std::string(buf);
3895+
}
3896+
3897+
unsigned char* value_str;
3898+
int value_str_size = ASN1_STRING_to_UTF8(&value_str, value);
3899+
3900+
return {
3901+
std::move(name_str),
3902+
std::string(reinterpret_cast<const char*>(value_str), value_str_size)};
3903+
}
3904+
38343905
} // namespace ncrypto

deps/ncrypto/ncrypto.h

+39
Original file line numberDiff line numberDiff line change
@@ -934,6 +934,43 @@ class SSLPointer final {
934934
DeleteFnPtr<SSL, SSL_free> ssl_;
935935
};
936936

937+
class X509Name final {
938+
public:
939+
X509Name();
940+
explicit X509Name(const X509_NAME* name);
941+
NCRYPTO_DISALLOW_COPY_AND_MOVE(X509Name)
942+
943+
inline operator const X509_NAME*() const { return name_; }
944+
inline operator bool() const { return name_ != nullptr; }
945+
inline const X509_NAME* get() const { return name_; }
946+
inline size_t size() const { return total_; }
947+
948+
class Iterator final {
949+
public:
950+
Iterator(const X509Name& name, int pos);
951+
Iterator(const Iterator& other) = default;
952+
Iterator(Iterator&& other) = default;
953+
Iterator& operator=(const Iterator& other) = delete;
954+
Iterator& operator=(Iterator&& other) = delete;
955+
Iterator& operator++();
956+
operator bool() const;
957+
bool operator==(const Iterator& other) const;
958+
bool operator!=(const Iterator& other) const;
959+
std::pair<std::string, std::string> operator*() const;
960+
961+
private:
962+
const X509Name& name_;
963+
int loc_;
964+
};
965+
966+
inline Iterator begin() const { return Iterator(*this, 0); }
967+
inline Iterator end() const { return Iterator(*this, total_); }
968+
969+
private:
970+
const X509_NAME* name_;
971+
int total_;
972+
};
973+
937974
class X509View final {
938975
public:
939976
static X509View From(const SSLPointer& ssl);
@@ -955,6 +992,8 @@ class X509View final {
955992
BIOPointer toPEM() const;
956993
BIOPointer toDER() const;
957994

995+
const X509Name getSubjectName() const;
996+
const X509Name getIssuerName() const;
958997
BIOPointer getSubject() const;
959998
BIOPointer getSubjectAltName() const;
960999
BIOPointer getIssuer() const;

src/crypto/crypto_x509.cc

+13-62
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ using ncrypto::ClearErrorOnReturn;
2121
using ncrypto::DataPointer;
2222
using ncrypto::ECKeyPointer;
2323
using ncrypto::SSLPointer;
24+
using ncrypto::X509Name;
2425
using ncrypto::X509Pointer;
2526
using ncrypto::X509View;
2627
using v8::Array;
@@ -92,6 +93,11 @@ void Fingerprint(const FunctionCallbackInfo<Value>& args) {
9293
}
9394
}
9495

96+
MaybeLocal<String> ToV8Value(Environment* env, std::string_view val) {
97+
return String::NewFromUtf8(
98+
env->isolate(), val.data(), NewStringType::kNormal, val.size());
99+
}
100+
95101
MaybeLocal<Value> ToV8Value(Local<Context> context, BIOPointer&& bio) {
96102
if (!bio) [[unlikely]]
97103
return {};
@@ -106,51 +112,6 @@ MaybeLocal<Value> ToV8Value(Local<Context> context, BIOPointer&& bio) {
106112
return ret;
107113
}
108114

109-
MaybeLocal<Value> ToV8Value(Local<Context> context, const ASN1_OBJECT* obj) {
110-
// If OpenSSL knows the type, use the short name of the type as the key, and
111-
// the numeric representation of the type's OID otherwise.
112-
int nid = OBJ_obj2nid(obj);
113-
char buf[80];
114-
const char* str;
115-
if (nid != NID_undef) {
116-
str = OBJ_nid2sn(nid);
117-
CHECK_NOT_NULL(str);
118-
} else {
119-
OBJ_obj2txt(buf, sizeof(buf), obj, true);
120-
str = buf;
121-
}
122-
123-
Local<Value> result;
124-
if (!String::NewFromUtf8(context->GetIsolate(), str).ToLocal(&result)) {
125-
return {};
126-
}
127-
return result;
128-
}
129-
130-
MaybeLocal<Value> ToV8Value(Local<Context> context, const ASN1_STRING* str) {
131-
// The previous implementation used X509_NAME_print_ex, which escapes some
132-
// characters in the value. The old implementation did not decode/unescape
133-
// values correctly though, leading to ambiguous and incorrect
134-
// representations. The new implementation only converts to Unicode and does
135-
// not escape anything.
136-
unsigned char* value_str;
137-
int value_str_size = ASN1_STRING_to_UTF8(&value_str, str);
138-
if (value_str_size < 0) [[unlikely]] {
139-
return Undefined(context->GetIsolate());
140-
}
141-
DataPointer free_value_str(value_str, value_str_size);
142-
143-
Local<Value> result;
144-
if (!String::NewFromUtf8(context->GetIsolate(),
145-
reinterpret_cast<const char*>(value_str),
146-
NewStringType::kNormal,
147-
value_str_size)
148-
.ToLocal(&result)) {
149-
return {};
150-
}
151-
return result;
152-
}
153-
154115
MaybeLocal<Value> ToV8Value(Local<Context> context, const BIOPointer& bio) {
155116
if (!bio) [[unlikely]]
156117
return {};
@@ -594,14 +555,9 @@ bool Set(Environment* env,
594555
// Convert an X509_NAME* into a JavaScript object.
595556
// Each entry of the name is converted into a property of the object.
596557
// The property value may be a single string or an array of strings.
597-
template <X509_NAME* get_name(const X509*)>
598558
static MaybeLocal<Value> GetX509NameObject(Environment* env,
599-
const X509View& cert) {
600-
X509_NAME* name = get_name(cert.get());
601-
CHECK_NOT_NULL(name);
602-
603-
int cnt = X509_NAME_entry_count(name);
604-
CHECK_GE(cnt, 0);
559+
const X509Name& name) {
560+
if (!name) return {};
605561

606562
Local<Value> v8_name;
607563
Local<Value> v8_value;
@@ -610,14 +566,9 @@ static MaybeLocal<Value> GetX509NameObject(Environment* env,
610566
Object::New(env->isolate(), Null(env->isolate()), nullptr, nullptr, 0);
611567
if (result.IsEmpty()) return {};
612568

613-
for (int i = 0; i < cnt; i++) {
614-
X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, i);
615-
CHECK_NOT_NULL(entry);
616-
617-
if (!ToV8Value(env->context(), X509_NAME_ENTRY_get_object(entry))
618-
.ToLocal(&v8_name) ||
619-
!ToV8Value(env->context(), X509_NAME_ENTRY_get_data(entry))
620-
.ToLocal(&v8_value)) {
569+
for (auto i : name) {
570+
if (!ToV8Value(env, i.first).ToLocal(&v8_name) ||
571+
!ToV8Value(env, i.second).ToLocal(&v8_value)) {
621572
return {};
622573
}
623574

@@ -727,11 +678,11 @@ MaybeLocal<Object> X509ToObject(Environment* env, const X509View& cert) {
727678
if (!Set<Value>(env,
728679
info,
729680
env->subject_string(),
730-
GetX509NameObject<X509_get_subject_name>(env, cert)) ||
681+
GetX509NameObject(env, cert.getSubjectName())) ||
731682
!Set<Value>(env,
732683
info,
733684
env->issuer_string(),
734-
GetX509NameObject<X509_get_issuer_name>(env, cert)) ||
685+
GetX509NameObject(env, cert.getIssuerName())) ||
735686
!Set<Value>(env,
736687
info,
737688
env->subjectaltname_string(),

0 commit comments

Comments
 (0)