Skip to content

Commit 3175080

Browse files
Make callback more useful, flag adjustment and naming
1 parent 8f6960e commit 3175080

File tree

4 files changed

+65
-27
lines changed

4 files changed

+65
-27
lines changed

crypto/x509/internal.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,8 @@ struct x509_store_ctx_st {
344344
X509_STORE_CTX_verify_cb verify_cb; // error callback
345345
X509_STORE_CTX_get_crl_fn get_crl; // retrieve CRL
346346
X509_STORE_CTX_check_crl_fn check_crl; // Check CRL validity
347-
X509_STORE_CTX_verify_crit_oids
348-
verify_crit_oids; // Check custom critical oids
347+
X509_STORE_CTX_verify_crit_oids_cb
348+
verify_custom_crit_oids; // Check custom critical oids
349349

350350
// The following is built up
351351

@@ -361,7 +361,7 @@ struct x509_store_ctx_st {
361361

362362
int current_crl_score; // score of current CRL
363363

364-
// Array of allowed custom critical extension oids.
364+
// Stack of allowed custom critical extension oids.
365365
STACK_OF(ASN1_OBJECT) *custom_crit_oids;
366366

367367
CRYPTO_EX_DATA ex_data;

crypto/x509/x509_test.cc

+11-1
Original file line numberDiff line numberDiff line change
@@ -8314,6 +8314,9 @@ TEST(X509Test, X509CustomExtensions) {
83148314
bssl::UniquePtr<X509> ca(CertFromPEM(kX509CustomExtensionsCA));
83158315
ASSERT_TRUE(ca);
83168316

8317+
// Check that the cert has been marked as |EXFLAG_CRITICAL|.
8318+
EXPECT_TRUE(X509_get_extension_flags(cert.get()) & EXFLAG_CRITICAL);
8319+
83178320
bssl::UniquePtr<ASN1_OBJECT> custom_oid(OBJ_txt2obj("1.3.187.25204.5", 1));
83188321
ASSERT_TRUE(custom_oid);
83198322

@@ -8344,14 +8347,16 @@ TEST(X509Test, X509CustomExtensions) {
83448347
Verify(cert.get(), {ca.get()}, {}, {},
83458348
/*flags=*/0, set_no_custom_ext_with_callback));
83468349

8347-
// This correctly sets up |ctx| with a customcritical extension and the
8350+
// This correctly sets up |ctx| with a custom critical extension and the
83488351
// |verify_crit_oids| callback.
83498352
auto set_custom_ext_with_callback = [&](X509_STORE_CTX *ctx) {
83508353
SetupVerificationContext(ctx, {custom_oid.get()}, true);
83518354
};
83528355
EXPECT_EQ(X509_V_OK,
83538356
Verify(cert.get(), {ca.get()}, {}, {}, /*flags=*/0,
83548357
set_custom_ext_with_callback));
8358+
// Check that |EXFLAG_CRITICAL| has been removed after validation.
8359+
EXPECT_FALSE(X509_get_extension_flags(cert.get()) & EXFLAG_CRITICAL);
83558360
}
83568361

83578362
TEST(X509Test, X509MultipleCustomExtensions) {
@@ -8360,6 +8365,9 @@ TEST(X509Test, X509MultipleCustomExtensions) {
83608365
bssl::UniquePtr<X509> ca(CertFromPEM(kX509MultipleCustomExtensionsCA));
83618366
ASSERT_TRUE(ca);
83628367

8368+
// Check that the cert has been marked as |EXFLAG_CRITICAL|.
8369+
EXPECT_TRUE(X509_get_extension_flags(cert.get()) & EXFLAG_CRITICAL);
8370+
83638371
bssl::UniquePtr<ASN1_OBJECT> custom_oid(OBJ_txt2obj("1.3.187.25204.5", 1));
83648372
ASSERT_TRUE(custom_oid);
83658373
bssl::UniquePtr<ASN1_OBJECT> custom_oid2(OBJ_txt2obj("1.3.187.25204.6", 1));
@@ -8397,4 +8405,6 @@ TEST(X509Test, X509MultipleCustomExtensions) {
83978405
};
83988406
EXPECT_EQ(X509_V_OK, Verify(cert.get(), {ca.get()}, {}, {},
83998407
/*flags=*/0, set_custom_exts_with_callback));
8408+
// Check that |EXFLAG_CRITICAL| has been removed after validation.
8409+
EXPECT_FALSE(X509_get_extension_flags(cert.get()) & EXFLAG_CRITICAL);
84008410
}

crypto/x509/x509_vfy.c

+38-13
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,11 @@ static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x);
122122
static int internal_verify(X509_STORE_CTX *ctx);
123123

124124
static int null_callback(int ok, X509_STORE_CTX *e) { return ok; }
125-
static int null_verify_crit_oids_callback(X509_STORE_CTX *ctx, X509 *x509,
126-
STACK_OF(ASN1_OBJECT) *oids) {
125+
static int null_verify_custom_crit_oids_callback(X509_STORE_CTX *ctx,
126+
X509 *x509,
127+
STACK_OF(ASN1_OBJECT) *oids) {
128+
// This returns 0 by default, so that the callback must be configured by the
129+
// user when enabling the custom critical extensions feature.
127130
return 0;
128131
}
129132

@@ -565,7 +568,7 @@ static int get_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) {
565568
return X509_STORE_CTX_get1_issuer(issuer, ctx, x);
566569
}
567570

568-
static int check_custom_known_critical_extension(X509_STORE_CTX *ctx, X509 *x) {
571+
static int check_custom_critical_extensions(X509_STORE_CTX *ctx, X509 *x) {
569572
if (ctx->custom_crit_oids == NULL) {
570573
// Fail if custom critical extensions are enabled, but none were set.
571574
return 0;
@@ -575,6 +578,12 @@ static int check_custom_known_critical_extension(X509_STORE_CTX *ctx, X509 *x) {
575578
return 0;
576579
}
577580

581+
// Allocate |found_exts| to pass to the callback.
582+
STACK_OF(ASN1_OBJECT) *found_exts = sk_ASN1_OBJECT_new_null();
583+
if (found_exts == NULL) {
584+
return 0;
585+
}
586+
578587
// Iterate through all critical extensions of |x| and validate against the
579588
// ones that aren't recognized by |X509_supported_extension|.
580589
int last_pos = X509_get_ext_by_critical(x, 1, -1);
@@ -585,10 +594,12 @@ static int check_custom_known_critical_extension(X509_STORE_CTX *ctx, X509 *x) {
585594

586595
// Iterate through all set |custom_crit_oids|.
587596
for (size_t i = 0; i < known_oid_count; i++) {
588-
ASN1_OBJECT *known_ext =
589-
sk_ASN1_OBJECT_value(ctx->custom_crit_oids, i);
597+
ASN1_OBJECT *known_ext = sk_ASN1_OBJECT_value(ctx->custom_crit_oids, i);
590598
if (OBJ_cmp(ext->object, known_ext) == 0) {
591599
found = 1;
600+
if (!sk_ASN1_OBJECT_push(found_exts, known_ext)) {
601+
return 0;
602+
}
592603
break;
593604
}
594605
}
@@ -600,7 +611,17 @@ static int check_custom_known_critical_extension(X509_STORE_CTX *ctx, X509 *x) {
600611
}
601612
last_pos = X509_get_ext_by_critical(x, 1, last_pos);
602613
}
603-
// If we get here, all unknown critical extensions were found
614+
615+
// If we get here, all unknown critical extensions in |x| were
616+
// properly handled and we pass the ones that were found to the caller.
617+
if (!ctx->verify_custom_crit_oids(ctx, x, found_exts)) {
618+
return 0;
619+
}
620+
621+
// Remove the |EXFLAG_CRITICAL| flag from |x|, now that all unknown
622+
// critical extensions have been handled.
623+
x->ex_flags &= ~EXFLAG_CRITICAL;
624+
604625
return 1;
605626
}
606627

@@ -614,11 +635,14 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) {
614635
// Check all untrusted certificates
615636
for (int i = 0; i < ctx->last_untrusted; i++) {
616637
X509 *x = sk_X509_value(ctx->chain, i);
617-
if ((!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) &&
638+
if ( // OpenSSL's historic check for unknown critical extensions.
639+
// |EXFLAG_CRITICAL| indicates an unsupported critical extension was
640+
// found in |x| during the initial parsing of the certificate.
641+
(!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) &&
618642
(x->ex_flags & EXFLAG_CRITICAL)) &&
619-
// Do check for enabling custom unknown critical extensions.
620-
(!check_custom_known_critical_extension(ctx, x) ||
621-
!ctx->verify_crit_oids(ctx, x, ctx->custom_crit_oids))) {
643+
// AWS-LC specific logic for enabling custom unknown critical
644+
// extensions.
645+
!check_custom_critical_extensions(ctx, x)) {
622646
ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION;
623647
ctx->error_depth = i;
624648
ctx->current_cert = x;
@@ -1728,7 +1752,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
17281752
ctx->check_crl = check_crl;
17291753
}
17301754

1731-
ctx->verify_crit_oids = null_verify_crit_oids_callback;
1755+
ctx->verify_custom_crit_oids = null_verify_custom_crit_oids_callback;
17321756

17331757
return 1;
17341758

@@ -1830,6 +1854,7 @@ int X509_STORE_CTX_add_custom_crit_oid(X509_STORE_CTX *ctx, ASN1_OBJECT *oid) {
18301854
}
18311855

18321856
void X509_STORE_CTX_set_verify_crit_oids(
1833-
X509_STORE_CTX *ctx, X509_STORE_CTX_verify_crit_oids verify_crit_oids) {
1834-
ctx->verify_crit_oids = verify_crit_oids;
1857+
X509_STORE_CTX *ctx,
1858+
X509_STORE_CTX_verify_crit_oids_cb verify_custom_crit_oids) {
1859+
ctx->verify_custom_crit_oids = verify_custom_crit_oids;
18351860
}

include/openssl/x509.h

+13-10
Original file line numberDiff line numberDiff line change
@@ -2903,12 +2903,12 @@ OPENSSL_EXPORT int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
29032903
// difference.
29042904
OPENSSL_EXPORT int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust);
29052905

2906-
// X509_STORE_CTX_add_custom_crit_oid adds |oid| to the list of "known"
2907-
// critical extension OIDs in |ctx|. Typical OpenSSL/AWS-LC behavior returns
2908-
// an error if there are any unknown critical extensions present within the
2909-
// certificates being validated. This function lets users to specify custom
2910-
// OIDs of any critical extensions that are within the certificates being
2911-
// validated, that they wish to allow.
2906+
// X509_STORE_CTX_add_custom_crit_oid adds |oid| to the list of "known" critical
2907+
// extension OIDs in |ctx|. Typical OpenSSL/AWS-LC behavior returns an error if
2908+
// there are any unknown critical extensions present within the certificates
2909+
// being validated. This function lets users specify custom OIDs of any critical
2910+
// extensions that are within the certificates being validated, that they wish
2911+
// to allow.
29122912
//
29132913
// To properly consume this feature, the callback mechanism with
29142914
// |X509_STORE_CTX_set_verify_crit_oids| must be set. See its specific
@@ -2919,18 +2919,21 @@ OPENSSL_EXPORT int X509_STORE_CTX_add_custom_crit_oid(X509_STORE_CTX *ctx,
29192919
// X509_STORE_CTX_verify_crit_oids is the callback signature for
29202920
// |X509_STORE_CTX_set_verify_crit_oids|. |ctx| is the context being used,
29212921
// |x509| represents the current certificate being validated, and |oids|
2922-
// represents the stack of custom OIDs that have been set by
2922+
// is a stack of |ASN1_OBJECT|s representing unknown critical extension
2923+
// OIDs that were found in |x509| and match those previously registered via
29232924
// |X509_STORE_CTX_add_custom_crit_oid|.
2924-
typedef int (*X509_STORE_CTX_verify_crit_oids)(X509_STORE_CTX *ctx, X509 *x509,
2925-
STACK_OF(ASN1_OBJECT) *oids);
2925+
typedef int (*X509_STORE_CTX_verify_crit_oids_cb)(X509_STORE_CTX *ctx,
2926+
X509 *x509,
2927+
STACK_OF(ASN1_OBJECT) *oids);
29262928

29272929
// X509_STORE_CTX_set_verify_crit_oids sets the |verify_crit_oids| callback
29282930
// function for |ctx|. Consumers should be performing additional validation
29292931
// against the custom extension oids after or during the handshake with
29302932
// |X509_STORE_CTX_set_verify_crit_oids|. This callback forces users to validate
29312933
// their custom OIDs when processing unknown custom critical extensions.
29322934
OPENSSL_EXPORT void X509_STORE_CTX_set_verify_crit_oids(
2933-
X509_STORE_CTX *ctx, X509_STORE_CTX_verify_crit_oids verify_crit_oids);
2935+
X509_STORE_CTX *ctx,
2936+
X509_STORE_CTX_verify_crit_oids_cb verify_custom_crit_oids);
29342937

29352938

29362939
// Verification parameters

0 commit comments

Comments
 (0)