mirror of
https://boringssl.googlesource.com/boringssl
synced 2026-07-21 14:43:51 +00:00
bd6f41c308
... and then run clang-format on the changed files to reflow any comment blocks that exceeded line lengths. (Which generated a bunch of noise formatting changes, but probably that reduces noise in future CLs.) No semantic change to the code. Change-Id: I455da9faaaedda3e751ac91b5eb43cbc662d68a6 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/97367 Reviewed-by: David Benjamin <davidben@google.com> Commit-Queue: Adam Langley <agl@google.com> Auto-Submit: Adam Langley <agl@google.com>
389 lines
18 KiB
C++
389 lines
18 KiB
C++
// Copyright 2025 The BoringSSL Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include <openssl/x509.h>
|
|
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <openssl/asn1.h>
|
|
#include <openssl/obj.h>
|
|
#include <openssl/span.h>
|
|
#include <openssl/x509v3.h>
|
|
|
|
#include "../test/der_trailing_data.h"
|
|
#include "../test/test_util.h"
|
|
|
|
BSSL_NAMESPACE_BEGIN
|
|
namespace {
|
|
|
|
static std::string ASN1ObjectToString(const ASN1_OBJECT *obj) {
|
|
char buf[128];
|
|
if (OBJ_obj2txt(buf, sizeof(buf), obj, /*always_return_oid=*/0) < 0) {
|
|
ADD_FAILURE() << "OBJ_obj2txt failed";
|
|
return "ERROR";
|
|
}
|
|
return buf;
|
|
}
|
|
|
|
static Span<const uint8_t> ASN1StringAsBytes(const ASN1_STRING *str) {
|
|
return Span(ASN1_STRING_get0_data(str), ASN1_STRING_length(str));
|
|
}
|
|
|
|
static std::string_view ASN1StringAsView(const ASN1_STRING *str) {
|
|
return BytesAsStringView(ASN1StringAsBytes(str));
|
|
}
|
|
|
|
static std::string ASN1StringToUTF8(const ASN1_STRING *str) {
|
|
uint8_t *utf8;
|
|
int utf8_len = ASN1_STRING_to_UTF8(&utf8, str);
|
|
if (utf8_len < 0) {
|
|
ADD_FAILURE() << "ASN1_STRING_to_UTF8 failed";
|
|
return "ERROR";
|
|
}
|
|
UniquePtr<uint8_t> free_utf8(utf8);
|
|
return std::string(utf8, utf8 + utf8_len);
|
|
}
|
|
|
|
TEST(X509ExtensionTest, ParseCertificatePolicies) {
|
|
// A sample input with a few policies and qualifiers to exercise the parser:
|
|
static const uint8_t kTestPolicies[] = {
|
|
0x30, 0x82, 0x01, 0xca, 0x30, 0x0f, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86,
|
|
0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x01, 0x30, 0x82, 0x01,
|
|
0xb5, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84,
|
|
0xb7, 0x09, 0x02, 0x02, 0x30, 0x82, 0x01, 0xa2, 0x30, 0x1f, 0x06, 0x08,
|
|
0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x13, 0x68, 0x74,
|
|
0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c,
|
|
0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x0c, 0x06, 0x08, 0x2b, 0x06, 0x01,
|
|
0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x00, 0x30, 0x27, 0x06, 0x08, 0x2b,
|
|
0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x1b, 0x30, 0x19, 0x0c,
|
|
0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f,
|
|
0x6e, 0x30, 0x09, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x03,
|
|
0x30, 0x1a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02,
|
|
0x30, 0x0e, 0x0c, 0x0c, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74,
|
|
0x54, 0x65, 0x78, 0x74, 0x30, 0x35, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
|
|
0x05, 0x07, 0x02, 0x02, 0x30, 0x29, 0x30, 0x19, 0x0c, 0x0c, 0x6f, 0x72,
|
|
0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x30, 0x09,
|
|
0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x03, 0x0c, 0x0c, 0x65,
|
|
0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x54, 0x65, 0x78, 0x74, 0x30,
|
|
0x35, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30,
|
|
0x29, 0x30, 0x19, 0x16, 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a,
|
|
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x30, 0x09, 0x02, 0x01, 0x01, 0x02, 0x01,
|
|
0x02, 0x02, 0x01, 0x03, 0x16, 0x0c, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63,
|
|
0x69, 0x74, 0x54, 0x65, 0x78, 0x74, 0x30, 0x35, 0x06, 0x08, 0x2b, 0x06,
|
|
0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x29, 0x30, 0x19, 0x1a, 0x0c,
|
|
0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
|
0x30, 0x09, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x03, 0x1a,
|
|
0x0c, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x54, 0x65, 0x78,
|
|
0x74, 0x30, 0x4d, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02,
|
|
0x02, 0x30, 0x41, 0x30, 0x25, 0x1e, 0x18, 0x00, 0x6f, 0x00, 0x72, 0x00,
|
|
0x67, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x7a, 0x00, 0x61, 0x00,
|
|
0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x30, 0x09, 0x02, 0x01, 0x01,
|
|
0x02, 0x01, 0x02, 0x02, 0x01, 0x03, 0x1e, 0x18, 0x00, 0x65, 0x00, 0x78,
|
|
0x00, 0x70, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x69, 0x00, 0x74,
|
|
0x00, 0x54, 0x00, 0x65, 0x00, 0x78, 0x00, 0x74, 0x30, 0x11, 0x06, 0x0d,
|
|
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02,
|
|
0x02, 0x16, 0x00, 0x30, 0x12, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7,
|
|
0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x02, 0x01, 0x01, 0xff, 0x30,
|
|
0x11, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84,
|
|
0xb7, 0x09, 0x02, 0x02, 0x80, 0x00};
|
|
const uint8_t *inp = kTestPolicies;
|
|
UniquePtr<CERTIFICATEPOLICIES> policies(
|
|
d2i_CERTIFICATEPOLICIES(nullptr, &inp, sizeof(kTestPolicies)));
|
|
ASSERT_TRUE(policies);
|
|
EXPECT_EQ(inp, kTestPolicies + sizeof(kTestPolicies));
|
|
|
|
ASSERT_EQ(sk_POLICYINFO_num(policies.get()), 2u);
|
|
|
|
// The first policy has no qualifiers.
|
|
const POLICYINFO *policy = sk_POLICYINFO_value(policies.get(), 0);
|
|
EXPECT_EQ(ASN1ObjectToString(policy->policyid),
|
|
"1.2.840.113554.4.1.72585.2.1");
|
|
EXPECT_EQ(policy->qualifiers, nullptr);
|
|
|
|
// The second policy has a wide range of qualifiers, to exercise the encoding.
|
|
policy = sk_POLICYINFO_value(policies.get(), 1);
|
|
EXPECT_EQ(ASN1ObjectToString(policy->policyid),
|
|
"1.2.840.113554.4.1.72585.2.2");
|
|
EXPECT_EQ(sk_POLICYQUALINFO_num(policy->qualifiers), 11u);
|
|
|
|
// Sample id-qt-cps
|
|
const POLICYQUALINFO *qualifier =
|
|
sk_POLICYQUALINFO_value(policy->qualifiers, 0);
|
|
EXPECT_EQ(ASN1ObjectToString(qualifier->pqualid), "Policy Qualifier CPS");
|
|
EXPECT_EQ(qualifier->d.cpsuri->type, V_ASN1_IA5STRING);
|
|
EXPECT_EQ(ASN1StringAsView(qualifier->d.cpsuri), "https://example.com");
|
|
|
|
// Sample id-qt-unotice with both optional fields omitted.
|
|
qualifier = sk_POLICYQUALINFO_value(policy->qualifiers, 1);
|
|
EXPECT_EQ(ASN1ObjectToString(qualifier->pqualid),
|
|
"Policy Qualifier User Notice");
|
|
EXPECT_EQ(qualifier->d.usernotice->noticeref, nullptr);
|
|
EXPECT_EQ(qualifier->d.usernotice->exptext, nullptr);
|
|
|
|
// Sample id-qt-unotice with noticeRef.
|
|
qualifier = sk_POLICYQUALINFO_value(policy->qualifiers, 2);
|
|
EXPECT_EQ(ASN1ObjectToString(qualifier->pqualid),
|
|
"Policy Qualifier User Notice");
|
|
EXPECT_EQ(qualifier->d.usernotice->noticeref->organization->type,
|
|
V_ASN1_UTF8STRING);
|
|
EXPECT_EQ(ASN1StringAsView(qualifier->d.usernotice->noticeref->organization),
|
|
"organization");
|
|
EXPECT_EQ(sk_ASN1_INTEGER_num(qualifier->d.usernotice->noticeref->noticenos),
|
|
3u);
|
|
EXPECT_EQ(qualifier->d.usernotice->exptext, nullptr);
|
|
|
|
// Sample id-qt-unotice with explicitText.
|
|
qualifier = sk_POLICYQUALINFO_value(policy->qualifiers, 3);
|
|
EXPECT_EQ(ASN1ObjectToString(qualifier->pqualid),
|
|
"Policy Qualifier User Notice");
|
|
EXPECT_EQ(qualifier->d.usernotice->noticeref, nullptr);
|
|
EXPECT_EQ(qualifier->d.usernotice->exptext->type, V_ASN1_UTF8STRING);
|
|
EXPECT_EQ(ASN1StringAsView(qualifier->d.usernotice->exptext), "explicitText");
|
|
|
|
// Sample id-qt-unotice with both.
|
|
qualifier = sk_POLICYQUALINFO_value(policy->qualifiers, 4);
|
|
EXPECT_EQ(ASN1ObjectToString(qualifier->pqualid),
|
|
"Policy Qualifier User Notice");
|
|
EXPECT_EQ(qualifier->d.usernotice->noticeref->organization->type,
|
|
V_ASN1_UTF8STRING);
|
|
EXPECT_EQ(ASN1StringAsView(qualifier->d.usernotice->noticeref->organization),
|
|
"organization");
|
|
EXPECT_EQ(sk_ASN1_INTEGER_num(qualifier->d.usernotice->noticeref->noticenos),
|
|
3u);
|
|
EXPECT_EQ(qualifier->d.usernotice->exptext->type, V_ASN1_UTF8STRING);
|
|
EXPECT_EQ(ASN1StringAsView(qualifier->d.usernotice->exptext), "explicitText");
|
|
|
|
// Variations with all the allowed DisplayText string types.
|
|
qualifier = sk_POLICYQUALINFO_value(policy->qualifiers, 5);
|
|
EXPECT_EQ(ASN1ObjectToString(qualifier->pqualid),
|
|
"Policy Qualifier User Notice");
|
|
EXPECT_EQ(qualifier->d.usernotice->noticeref->organization->type,
|
|
V_ASN1_IA5STRING);
|
|
EXPECT_EQ(ASN1StringAsView(qualifier->d.usernotice->noticeref->organization),
|
|
"organization");
|
|
EXPECT_EQ(sk_ASN1_INTEGER_num(qualifier->d.usernotice->noticeref->noticenos),
|
|
3u);
|
|
EXPECT_EQ(qualifier->d.usernotice->exptext->type, V_ASN1_IA5STRING);
|
|
EXPECT_EQ(ASN1StringAsView(qualifier->d.usernotice->exptext), "explicitText");
|
|
|
|
qualifier = sk_POLICYQUALINFO_value(policy->qualifiers, 6);
|
|
EXPECT_EQ(ASN1ObjectToString(qualifier->pqualid),
|
|
"Policy Qualifier User Notice");
|
|
EXPECT_EQ(qualifier->d.usernotice->noticeref->organization->type,
|
|
V_ASN1_VISIBLESTRING);
|
|
EXPECT_EQ(ASN1StringAsView(qualifier->d.usernotice->noticeref->organization),
|
|
"organization");
|
|
EXPECT_EQ(sk_ASN1_INTEGER_num(qualifier->d.usernotice->noticeref->noticenos),
|
|
3u);
|
|
EXPECT_EQ(qualifier->d.usernotice->exptext->type, V_ASN1_VISIBLESTRING);
|
|
EXPECT_EQ(ASN1StringAsView(qualifier->d.usernotice->exptext), "explicitText");
|
|
|
|
qualifier = sk_POLICYQUALINFO_value(policy->qualifiers, 7);
|
|
EXPECT_EQ(ASN1ObjectToString(qualifier->pqualid),
|
|
"Policy Qualifier User Notice");
|
|
EXPECT_EQ(qualifier->d.usernotice->noticeref->organization->type,
|
|
V_ASN1_BMPSTRING);
|
|
EXPECT_EQ(ASN1StringToUTF8(qualifier->d.usernotice->noticeref->organization),
|
|
"organization");
|
|
EXPECT_EQ(sk_ASN1_INTEGER_num(qualifier->d.usernotice->noticeref->noticenos),
|
|
3u);
|
|
EXPECT_EQ(qualifier->d.usernotice->exptext->type, V_ASN1_BMPSTRING);
|
|
EXPECT_EQ(ASN1StringToUTF8(qualifier->d.usernotice->exptext), "explicitText");
|
|
|
|
// A custom qualifier should be parsed as an ANY type.
|
|
qualifier = sk_POLICYQUALINFO_value(policy->qualifiers, 8);
|
|
EXPECT_EQ(ASN1ObjectToString(qualifier->pqualid),
|
|
"1.2.840.113554.4.1.72585.2.2");
|
|
EXPECT_EQ(qualifier->d.other->type, V_ASN1_IA5STRING);
|
|
EXPECT_EQ(ASN1StringAsView(qualifier->d.other->value.ia5string), "");
|
|
|
|
qualifier = sk_POLICYQUALINFO_value(policy->qualifiers, 9);
|
|
EXPECT_EQ(ASN1ObjectToString(qualifier->pqualid),
|
|
"1.2.840.113554.4.1.72585.2.2");
|
|
EXPECT_EQ(qualifier->d.other->type, V_ASN1_BOOLEAN);
|
|
EXPECT_EQ(qualifier->d.other->value.boolean, ASN1_BOOLEAN_TRUE);
|
|
|
|
qualifier = sk_POLICYQUALINFO_value(policy->qualifiers, 10);
|
|
EXPECT_EQ(ASN1ObjectToString(qualifier->pqualid),
|
|
"1.2.840.113554.4.1.72585.2.2");
|
|
EXPECT_EQ(qualifier->d.other->type, V_ASN1_OTHER);
|
|
EXPECT_EQ(Bytes(ASN1StringAsBytes(qualifier->d.other->value.asn1_string)),
|
|
Bytes(std::vector<uint8_t>{0x80, 0x00}));
|
|
|
|
// The object should roundtrip to the original input.
|
|
uint8_t *der = nullptr;
|
|
int der_len = i2d_CERTIFICATEPOLICIES(policies.get(), &der);
|
|
EXPECT_GT(der_len, 0);
|
|
UniquePtr<uint8_t> free_der(der);
|
|
EXPECT_EQ(Bytes(der, der_len), Bytes(kTestPolicies));
|
|
|
|
// Trailing data should be rejected.
|
|
TestDERTrailingData(
|
|
kTestPolicies, [](Span<const uint8_t> rewritten, size_t n) {
|
|
SCOPED_TRACE(n);
|
|
SCOPED_TRACE(EncodeHex(rewritten));
|
|
const uint8_t *p = rewritten.data();
|
|
EXPECT_FALSE(UniquePtr<CERTIFICATEPOLICIES>(
|
|
d2i_CERTIFICATEPOLICIES(nullptr, &p, rewritten.size())));
|
|
});
|
|
|
|
// Test additional invalid inputs.
|
|
const std::vector<uint8_t> kInvalidInputs[] = {
|
|
// The parser should attempt to parse the value for recognized types and
|
|
// reject if invalid:
|
|
// A qualifier of type id-qt-unotice with a UTF8String instead of
|
|
// UserNotice.
|
|
{0x30, 0x25, 0x30, 0x23, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86,
|
|
0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x01, 0x30,
|
|
0x12, 0x30, 0x10, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
|
|
0x07, 0x02, 0x02, 0x0c, 0x04, 0x6e, 0x6f, 0x70, 0x65},
|
|
// A qualifier of type id-qt-cps with a UTF8String instead of IA5String.
|
|
{0x30, 0x25, 0x30, 0x23, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86,
|
|
0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, 0x01, 0x30,
|
|
0x12, 0x30, 0x10, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
|
|
0x07, 0x02, 0x01, 0x0c, 0x04, 0x6e, 0x6f, 0x70, 0x65},
|
|
};
|
|
for (const auto &in : kInvalidInputs) {
|
|
SCOPED_TRACE(EncodeHex(in));
|
|
const uint8_t *p = in.data();
|
|
EXPECT_FALSE(UniquePtr<CERTIFICATEPOLICIES>(
|
|
d2i_CERTIFICATEPOLICIES(nullptr, &p, in.size())));
|
|
}
|
|
}
|
|
|
|
TEST(X509ExtensionTest, ParseCRLDistributionPoints) {
|
|
// CRL distribution points are very complex. This input is a sequence of
|
|
// three CRL distribution points that try to exercise various cases.
|
|
static const uint8_t kInput[] = {
|
|
0x30, 0x81, 0x87, 0x30, 0x28, 0xa0, 0x26, 0xa0, 0x24, 0x86, 0x10, 0x68,
|
|
0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x61, 0x2e, 0x65, 0x78, 0x61, 0x6d,
|
|
0x70, 0x6c, 0x65, 0x86, 0x10, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
|
|
0x62, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x30, 0x30, 0xa0,
|
|
0x0f, 0xa1, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x04,
|
|
0x54, 0x65, 0x73, 0x74, 0x81, 0x02, 0x05, 0x60, 0xa2, 0x19, 0xa4, 0x17,
|
|
0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
|
|
0x0a, 0x43, 0x52, 0x4c, 0x20, 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, 0x30,
|
|
0x29, 0xa2, 0x27, 0x86, 0x12, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
|
|
0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x82,
|
|
0x0b, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
|
|
0x87, 0x04, 0x7f, 0x00, 0x00, 0x01};
|
|
const uint8_t *inp = kInput;
|
|
UniquePtr<CRL_DIST_POINTS> crldp(
|
|
d2i_CRL_DIST_POINTS(nullptr, &inp, sizeof(kInput)));
|
|
ASSERT_TRUE(crldp);
|
|
EXPECT_EQ(inp, kInput + sizeof(kInput));
|
|
|
|
ASSERT_EQ(sk_DIST_POINT_num(crldp.get()), 3u);
|
|
|
|
// A distribution point with two URIs.
|
|
const DIST_POINT *dp1 = sk_DIST_POINT_value(crldp.get(), 0);
|
|
ASSERT_NE(dp1->distpoint, nullptr);
|
|
ASSERT_EQ(dp1->distpoint->type, 0); // fullName
|
|
ASSERT_NE(dp1->distpoint->name.fullname, nullptr);
|
|
ASSERT_EQ(sk_GENERAL_NAME_num(dp1->distpoint->name.fullname), 2u);
|
|
|
|
const GENERAL_NAME *gn1_1 =
|
|
sk_GENERAL_NAME_value(dp1->distpoint->name.fullname, 0);
|
|
ASSERT_EQ(gn1_1->type, GEN_URI);
|
|
EXPECT_EQ(ASN1StringAsView(gn1_1->d.uniformResourceIdentifier),
|
|
"http://a.example");
|
|
|
|
const GENERAL_NAME *gn1_2 =
|
|
sk_GENERAL_NAME_value(dp1->distpoint->name.fullname, 1);
|
|
ASSERT_EQ(gn1_2->type, GEN_URI);
|
|
EXPECT_EQ(ASN1StringAsView(gn1_2->d.uniformResourceIdentifier),
|
|
"http://b.example");
|
|
|
|
EXPECT_EQ(dp1->reasons, nullptr);
|
|
EXPECT_EQ(dp1->CRLissuer, nullptr);
|
|
|
|
// A distribution point relative to the CRL issuer, some reason flags, and a
|
|
// CRL issuer
|
|
const DIST_POINT *dp2 = sk_DIST_POINT_value(crldp.get(), 1);
|
|
ASSERT_NE(dp2->distpoint, nullptr);
|
|
ASSERT_EQ(dp2->distpoint->type, 1); // relativename
|
|
ASSERT_NE(dp2->distpoint->name.relativename, nullptr);
|
|
ASSERT_EQ(sk_X509_NAME_ENTRY_num(dp2->distpoint->name.relativename), 1u);
|
|
|
|
const X509_NAME_ENTRY *entry =
|
|
sk_X509_NAME_ENTRY_value(dp2->distpoint->name.relativename, 0);
|
|
EXPECT_EQ(OBJ_obj2nid(X509_NAME_ENTRY_get_object(entry)), NID_commonName);
|
|
EXPECT_EQ(ASN1StringAsView(X509_NAME_ENTRY_get_data(entry)), "Test");
|
|
|
|
ASSERT_NE(dp2->reasons, nullptr);
|
|
UniquePtr<ASN1_BIT_STRING> expected_reasons(ASN1_BIT_STRING_new());
|
|
ASSERT_TRUE(expected_reasons);
|
|
ASSERT_TRUE(ASN1_BIT_STRING_set_bit(expected_reasons.get(),
|
|
CRL_REASON_KEY_COMPROMISE, 1));
|
|
ASSERT_TRUE(ASN1_BIT_STRING_set_bit(expected_reasons.get(),
|
|
CRL_REASON_CA_COMPROMISE, 1));
|
|
EXPECT_EQ(ASN1_STRING_cmp(dp2->reasons, expected_reasons.get()), 0);
|
|
|
|
ASSERT_NE(dp2->CRLissuer, nullptr);
|
|
ASSERT_EQ(sk_GENERAL_NAME_num(dp2->CRLissuer), 1u);
|
|
const GENERAL_NAME *issuer_gn = sk_GENERAL_NAME_value(dp2->CRLissuer, 0);
|
|
ASSERT_EQ(issuer_gn->type, GEN_DIRNAME);
|
|
ASSERT_NE(issuer_gn->d.directoryName, nullptr);
|
|
ASSERT_EQ(X509_NAME_entry_count(issuer_gn->d.directoryName), 1);
|
|
const X509_NAME_ENTRY *issuer_entry =
|
|
X509_NAME_get_entry(issuer_gn->d.directoryName, 0);
|
|
EXPECT_EQ(OBJ_obj2nid(X509_NAME_ENTRY_get_object(issuer_entry)),
|
|
NID_commonName);
|
|
EXPECT_EQ(ASN1StringAsView(X509_NAME_ENTRY_get_data(issuer_entry)),
|
|
"CRL Issuer");
|
|
|
|
// Only a CRL issuer with various general names.
|
|
const DIST_POINT *dp3 = sk_DIST_POINT_value(crldp.get(), 2);
|
|
EXPECT_EQ(dp3->distpoint, nullptr);
|
|
EXPECT_EQ(dp3->reasons, nullptr);
|
|
ASSERT_NE(dp3->CRLissuer, nullptr);
|
|
ASSERT_EQ(sk_GENERAL_NAME_num(dp3->CRLissuer), 3u);
|
|
|
|
const GENERAL_NAME *gn3_1 = sk_GENERAL_NAME_value(dp3->CRLissuer, 0);
|
|
ASSERT_EQ(gn3_1->type, GEN_URI);
|
|
EXPECT_EQ(ASN1StringAsView(gn3_1->d.uniformResourceIdentifier),
|
|
"http://example.com");
|
|
|
|
const GENERAL_NAME *gn3_2 = sk_GENERAL_NAME_value(dp3->CRLissuer, 1);
|
|
ASSERT_EQ(gn3_2->type, GEN_DNS);
|
|
EXPECT_EQ(ASN1StringAsView(gn3_2->d.dNSName), "example.com");
|
|
|
|
const GENERAL_NAME *gn3_3 = sk_GENERAL_NAME_value(dp3->CRLissuer, 2);
|
|
ASSERT_EQ(gn3_3->type, GEN_IPADD);
|
|
EXPECT_EQ(Bytes(ASN1StringAsBytes(gn3_3->d.iPAddress)),
|
|
Bytes(std::vector<uint8_t>{127, 0, 0, 1}));
|
|
|
|
// The object should roundtrip to the original input.
|
|
uint8_t *der = nullptr;
|
|
int der_len = i2d_CRL_DIST_POINTS(crldp.get(), &der);
|
|
EXPECT_GT(der_len, 0);
|
|
UniquePtr<uint8_t> free_der(der);
|
|
EXPECT_EQ(Bytes(der, der_len), Bytes(kInput));
|
|
|
|
// Trailing data should be rejected.
|
|
TestDERTrailingData(kInput, [](Span<const uint8_t> rewritten, size_t n) {
|
|
SCOPED_TRACE(n);
|
|
SCOPED_TRACE(EncodeHex(rewritten));
|
|
const uint8_t *p = rewritten.data();
|
|
EXPECT_FALSE(UniquePtr<CRL_DIST_POINTS>(
|
|
d2i_CRL_DIST_POINTS(nullptr, &p, rewritten.size())));
|
|
});
|
|
}
|
|
|
|
} // namespace
|
|
BSSL_NAMESPACE_END
|