Merge branch 'main' into api-summary-dependencies
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index d533149..b93c3f9 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS
@@ -10,7 +10,7 @@ tool/update-yaml-test-suite.sh @dart-lang/dart-pub-team pkgs/api_summary @kevmoo -pkgs/bazel_worker @dart-lang/dart-bat +pkgs/bazel_worker @dart-lang/dart-ecosystem-team pkgs/benchmark_harness @dart-lang/dart-native-runtime-team pkgs/boolean_selector @dart-lang/dart-ecosystem-team pkgs/boring @dart-lang/dart-ecosystem-team @@ -26,8 +26,8 @@ pkgs/file_testing @dart-lang/dart-ecosystem-team pkgs/glob @dart-lang/dart-ecosystem-team pkgs/graphs @natebosch -pkgs/html @HosseinYousefi -pkgs/io @dart-lang/dart-bat +pkgs/html @dart-lang/dart-ecosystem-team +pkgs/io @dart-lang/dart-ecosystem-team pkgs/json_rpc_2 @dart-lang/dart-ecosystem-team pkgs/markdown @srawlins pkgs/mime @lrhn @@ -36,7 +36,7 @@ pkgs/pool @dart-lang/dart-ecosystem-team pkgs/process @dart-lang/dart-ecosystem-team pkgs/pub_semver @dart-lang/dart-pub-team -pkgs/pubspec_parse @dart-lang/dart-bat +pkgs/pubspec_parse @dart-lang/dart-ecosystem-team pkgs/source_maps @dart-lang/dart-ecosystem-team pkgs/source_map_stack_trace @dart-lang/dart-ecosystem-team pkgs/source_span @dart-lang/dart-ecosystem-team @@ -45,9 +45,9 @@ pkgs/stream_channel @natebosch pkgs/stream_transform @natebosch pkgs/string_scanner @dart-lang/dart-ecosystem-team -pkgs/term_glyph @dart-lang/dart-bat +pkgs/term_glyph @dart-lang/dart-ecosystem-team pkgs/test_reflective_loader @scheglov -pkgs/timing @dart-lang/dart-bat +pkgs/timing @dart-lang/dart-ecosystem-team pkgs/unified_analytics @dart-lang/analyzer-team pkgs/watcher @davidmorgan @dart-lang/dart-model-team pkgs/yaml @dart-lang/dart-pub-team
diff --git a/pkgs/api_summary/CHANGELOG.md b/pkgs/api_summary/CHANGELOG.md index 4e98f17..daac9c8 100644 --- a/pkgs/api_summary/CHANGELOG.md +++ b/pkgs/api_summary/CHANGELOG.md
@@ -1,5 +1,7 @@ ## 1.3.0-wip +- Add `includeImplicitNonPublicMembers` and `includeReferencedTypes` optional + named constructor parameters to `ApiSummaryCustomizer`. - Track `pubspec.yaml` runtime `dependencies` constraints for external packages referenced in the public API on `ApiSummary.dependencies`, and render them inline on referenced `package:...` library headers in `api.txt`
diff --git a/pkgs/api_summary/README.md b/pkgs/api_summary/README.md index d81dae7..81a95aa 100644 --- a/pkgs/api_summary/README.md +++ b/pkgs/api_summary/README.md
@@ -108,9 +108,26 @@ ### Customizing the Summary -Extend the `ApiSummaryCustomizer` class to customize what is displayed in the -API summary. For example, to exclude specific public classes or only display -details of certain elements: +Pass `ApiSummaryCustomizer` with optional flags, or extend it to customize what +is displayed in the API summary. For example, to include member details for +implicitly exposed non-public types or referenced external types: + +```dart +import 'package:api_summary/api_summary.dart'; + +void main() async { + final summary = await apiSummary( + '/path/to/package', + customizer: const ApiSummaryCustomizer( + includeImplicitNonPublicMembers: true, + includeReferencedTypes: true, + ), + ); + print(summary); +} +``` + +Or extend `ApiSummaryCustomizer` for custom element filtering: ```dart import 'package:api_summary/api_summary.dart';
diff --git a/pkgs/api_summary/api.json b/pkgs/api_summary/api.json index 21e910d..0357a2f 100644 --- a/pkgs/api_summary/api.json +++ b/pkgs/api_summary/api.json
@@ -3271,6 +3271,26 @@ "name": "ApiSummaryCustomizer", "libraryUri": "package:api_summary/src/api_summary_customizer.dart" }, + "parameters": [ + { + "name": "includeImplicitNonPublicMembers", + "type": { + "kind": "interface", + "name": "bool", + "libraryUri": "dart:core" + }, + "isNamed": true + }, + { + "name": "includeReferencedTypes", + "type": { + "kind": "interface", + "name": "bool", + "libraryUri": "dart:core" + }, + "isNamed": true + } + ], "isConst": true } ],
diff --git a/pkgs/api_summary/api.txt b/pkgs/api_summary/api.txt index cec4ef5..41db736 100644 --- a/pkgs/api_summary/api.txt +++ b/pkgs/api_summary/api.txt
@@ -152,7 +152,7 @@ publicApiLibraries (getter: List<LibraryElement>) topLevelPublicElements (getter: Set<Element>) ApiSummaryCustomizer (class extends Object, base): - new (const constructor: ApiSummaryCustomizer Function()) + new (const constructor: ApiSummaryCustomizer Function({bool includeImplicitNonPublicMembers, bool includeReferencedTypes})) includeImplicitNonPublicMembers (getter: bool) includeReferencedTypes (getter: bool) initialScanComplete (method: Future<void> Function(ApiSummaryContext))
diff --git a/pkgs/api_summary/api.yaml b/pkgs/api_summary/api.yaml index b50ebc0..09dd3c6 100644 --- a/pkgs/api_summary/api.yaml +++ b/pkgs/api_summary/api.yaml
@@ -2127,6 +2127,19 @@ kind: interface name: ApiSummaryCustomizer libraryUri: package:api_summary/src/api_summary_customizer.dart + parameters: + - name: includeImplicitNonPublicMembers + type: + kind: interface + name: bool + libraryUri: dart:core + isNamed: true + - name: includeReferencedTypes + type: + kind: interface + name: bool + libraryUri: dart:core + isNamed: true isConst: true methods: - name: includeImplicitNonPublicMembers
diff --git a/pkgs/api_summary/lib/src/api_summary_customizer.dart b/pkgs/api_summary/lib/src/api_summary_customizer.dart index 17fa9bd..a4139d1 100644 --- a/pkgs/api_summary/lib/src/api_summary_customizer.dart +++ b/pkgs/api_summary/lib/src/api_summary_customizer.dart
@@ -44,7 +44,21 @@ /// Clients should not *implement* this class, however, because additional /// methods may be added in the future. base class ApiSummaryCustomizer { - const ApiSummaryCustomizer(); + /// Whether to include full member signatures (constructors, methods) for + /// non-public declarations that are implicitly exposed via public signatures. + final bool includeImplicitNonPublicMembers; + + /// Whether to include declarations of referenced types from external packages + /// or SDK libraries. + /// + /// If true, referenced types will be included in the summary with a status of + /// [ApiDeclarationStatus.referenced] and without their members. + final bool includeReferencedTypes; + + const ApiSummaryCustomizer({ + this.includeImplicitNonPublicMembers = false, + this.includeReferencedTypes = false, + }); /// Called after [ApiSummaryContext.packageName] and /// [ApiSummaryContext.analysisContext] have been set, but before any analysis @@ -60,17 +74,6 @@ /// Further analysis won't be performed until the returned Future completes. Future<void> initialScanComplete(ApiSummaryContext context) async {} - /// Whether to include full member signatures (constructors, methods) for - /// non-public declarations that are implicitly exposed via public signatures. - bool get includeImplicitNonPublicMembers => false; - - /// Whether to include declarations of referenced types from external packages - /// or SDK libraries. - /// - /// If true, referenced types will be included in the summary with a status of - /// [ApiDeclarationStatus.referenced] and without their members. - bool get includeReferencedTypes => false; - /// Called after [initialScanComplete] to determine if details about an /// element should be shown in the API summary. ///
diff --git a/pkgs/api_summary/test/api_builder_test.dart b/pkgs/api_summary/test/api_builder_test.dart index a1498be..a066cea 100644 --- a/pkgs/api_summary/test/api_builder_test.dart +++ b/pkgs/api_summary/test/api_builder_test.dart
@@ -258,7 +258,7 @@ '$testPackageLibPath/src/private.dart': ''' class PrivateInterface {} ''', - }, customizer: _IncludeReferencedTypesCustomizer()); + }, customizer: const ApiSummaryCustomizer(includeReferencedTypes: true)); final decodedMap = jsonDecode(summary) as Map<String, dynamic>; final rehydrated = ApiSummary.fromJson(decodedMap); @@ -380,6 +380,53 @@ expect(enumValues.isEnumConstant, isFalse); } + Future<void> test_customizerConstructorFlags() async { + final summary = await _build( + { + '$testPackageLibPath/file.dart': ''' +import 'src/private.dart'; + +class PublicClass extends LeakedBase {} +''', + '$testPackageLibPath/src/private.dart': ''' +class LeakedBase { + void leakedMethod(TransitiveLeak arg) {} +} +class TransitiveLeak { + int get count => 0; +} +''', + }, + customizer: const ApiSummaryCustomizer( + includeImplicitNonPublicMembers: true, + ), + ); + + final decodedMap = jsonDecode(summary) as Map<String, dynamic>; + final rehydrated = ApiSummary.fromJson(decodedMap); + + final privateLib = rehydrated.libraries.firstWhere( + (l) => l.uri == 'package:test/src/private.dart', + ); + expect(privateLib.isPublicEntryPoint, isFalse); + expect( + privateLib.classes.map((c) => c.name), + containsAll(['LeakedBase', 'TransitiveLeak']), + ); + + final leakedBase = privateLib.classes.firstWhere( + (c) => c.name == 'LeakedBase', + ); + expect(leakedBase.status, ApiDeclarationStatus.nonPublic); + expect(leakedBase.methods.map((m) => m.name), contains('leakedMethod')); + + final transitiveLeak = privateLib.classes.firstWhere( + (c) => c.name == 'TransitiveLeak', + ); + expect(transitiveLeak.status, ApiDeclarationStatus.nonPublic); + expect(transitiveLeak.methods.map((m) => m.name), contains('count')); + } + Future<String> _build( Map<String, String> files, { ApiSummaryCustomizer? customizer, @@ -401,8 +448,3 @@ return jsonEncode(package.toJson()); } } - -base class _IncludeReferencedTypesCustomizer extends ApiSummaryCustomizer { - @override - bool get includeReferencedTypes => true; -}
diff --git a/pkgs/boring/CHANGELOG.md b/pkgs/boring/CHANGELOG.md index d539dda..020e1e7 100644 --- a/pkgs/boring/CHANGELOG.md +++ b/pkgs/boring/CHANGELOG.md
@@ -6,6 +6,7 @@ - The package is now licensed under the BSD 3-Clause license used by other Dart packages. - Update BoringSSL to 3fed4f20. +- Update BoringSSL to 64188f17. ## 0.4.1
diff --git a/pkgs/boring/lib/src/bindings/boringssl.g.dart b/pkgs/boring/lib/src/bindings/boringssl.g.dart index dd7d95b..40c777d 100644 --- a/pkgs/boring/lib/src/bindings/boringssl.g.dart +++ b/pkgs/boring/lib/src/bindings/boringssl.g.dart
@@ -1011,7 +1011,7 @@ /// representation that does not always correspond to the DER encoding of the /// type. See the documentation for `ASN1_STRING` for details. /// -/// Prefer `ASN1_STRING_get0_data`. +/// Prefer `ASN1_STRING_get0_data`. See crbug.com/574019297. @meta.RecordUse() @ffi.Native<ffi.Pointer<ffi.UnsignedChar> Function(ffi.Pointer<ASN1_STRING>)>( symbol: 'bssl_dart_ASN1_STRING_data', @@ -1060,7 +1060,21 @@ ) external int ASN1_STRING_get_default_mask(); -/// ASN1_STRING_length returns the length of `str`, in bytes. +/// ASN1_STRING_get_length returns the length of `str`, in bytes. +/// +/// The contents of an `ASN1_STRING` encode the value in some type-specific +/// representation that does not always correspond to the DER encoding of the +/// type. See the documentation for `ASN1_STRING` for details. +@meta.RecordUse() +@ffi.Native<ffi.Size Function(ffi.Pointer<ASN1_STRING>)>( + symbol: 'bssl_dart_ASN1_STRING_get_length', +) +external int ASN1_STRING_get_length( + ffi.Pointer<ASN1_STRING> str, +); + +/// ASN1_STRING_length returns the length of `str`, in bytes. Prefer +/// `ASN1_STRING_get_length`. /// /// The contents of an `ASN1_STRING` encode the value in some type-specific /// representation that does not always correspond to the DER encoding of the @@ -2384,6 +2398,16 @@ ffi.Pointer<BIO> bio, ); +/// BIO_dup_ref increments the reference count of `bio` and returns the same +/// handle. +@meta.RecordUse() +@ffi.Native<ffi.Pointer<BIO> Function(ffi.Pointer<BIO>)>( + symbol: 'bssl_dart_BIO_dup_ref', +) +external ffi.Pointer<BIO> BIO_dup_ref( + ffi.Pointer<BIO> bio, +); + /// BIO_eof returns non-zero when `bio` has reached end-of-file. The precise /// meaning of which depends on the concrete type of `bio`. Note that in the /// case of BIO_pair this always returns non-zero. @@ -8208,6 +8232,17 @@ ffi.Pointer<DH> dh, ); +/// DH_dup_ref increments the reference count of `dh` and returns the same +/// handle. It does not mutate `dh` for thread-safety purposes and may be used +/// concurrently. +@meta.RecordUse() +@ffi.Native<ffi.Pointer<DH> Function(ffi.Pointer<DH>)>( + symbol: 'bssl_dart_DH_dup_ref', +) +external ffi.Pointer<DH> DH_dup_ref( + ffi.Pointer<DH> dh, +); + /// DH_free decrements the reference count of `dh` and frees it if the reference /// count drops to zero. @meta.RecordUse() @@ -13059,9 +13094,6 @@ /// Ed25519, `type` should be NULL. The `EVP_MD_CTX` itself is unused but is /// present so the API is uniform. See `EVP_DigestSign`. /// -/// This function does not mutate `pkey` for thread-safety purposes and may be -/// used concurrently with other non-mutating functions on `pkey`. -/// /// It returns one on success, or zero on error. @meta.RecordUse() @ffi.Native< @@ -13156,9 +13188,6 @@ /// Ed25519, `type` should be NULL. The `EVP_MD_CTX` itself is unused but is /// present so the API is uniform. See `EVP_DigestVerify`. /// -/// This function does not mutate `pkey` for thread-safety purposes and may be -/// used concurrently with other non-mutating functions on `pkey`. -/// /// It returns one on success, or zero on error. @meta.RecordUse() @ffi.Native< @@ -15671,11 +15700,6 @@ /// actual size of the signature is written to `*out_sig_len`. /// /// It returns one on success and zero otherwise. -/// -/// It does not modify `ctx`, thus it's possible to continue to use `ctx` in -/// order to sign a longer message. It also does not mutate `pkey` for -/// thread-safety purposes and may be used concurrently with other non-mutating -/// functions on `pkey`. @meta.RecordUse() @ffi.Native< ffi.Int Function( @@ -15741,11 +15765,6 @@ /// calls to `EVP_VerifyUpdate`. /// /// It returns one on success and zero otherwise. -/// -/// It does not modify `ctx`, thus it's possible to continue to use `ctx` in -/// order to verify a longer message. It also does not mutate `pkey` for -/// thread-safety purposes and may be used concurrently with other non-mutating -/// functions on `pkey`. @meta.RecordUse() @ffi.Native< ffi.Int Function( @@ -16731,6 +16750,23 @@ @ffi.Native<ffi.Pointer<EVP_MD> Function()>(symbol: 'bssl_dart_EVP_sha384') external ffi.Pointer<EVP_MD> EVP_sha384(); +/// SHA-3 family of digest functions. +/// +/// WARNING: Prefer to use SHA-2 (e.g. `EVP_sha256`) over SHA-3. Despite being a +/// newer hash function, SHA-3 performs poorly and should only be used when +/// necessary for interoperability with existing systems. +@meta.RecordUse() +@ffi.Native<ffi.Pointer<EVP_MD> Function()>(symbol: 'bssl_dart_EVP_sha3_256') +external ffi.Pointer<EVP_MD> EVP_sha3_256(); + +@meta.RecordUse() +@ffi.Native<ffi.Pointer<EVP_MD> Function()>(symbol: 'bssl_dart_EVP_sha3_384') +external ffi.Pointer<EVP_MD> EVP_sha3_384(); + +@meta.RecordUse() +@ffi.Native<ffi.Pointer<EVP_MD> Function()>(symbol: 'bssl_dart_EVP_sha3_512') +external ffi.Pointer<EVP_MD> EVP_sha3_512(); + @meta.RecordUse() @ffi.Native<ffi.Pointer<EVP_MD> Function()>(symbol: 'bssl_dart_EVP_sha512') external ffi.Pointer<EVP_MD> EVP_sha512(); @@ -23213,6 +23249,16 @@ ffi.Pointer<X509_CRL> crl, ); +/// X509_CRL_dup_ref adds one to the reference count of `crl` and returns the +/// same. +@meta.RecordUse() +@ffi.Native<ffi.Pointer<X509_CRL> Function(ffi.Pointer<X509_CRL>)>( + symbol: 'bssl_dart_X509_CRL_dup_ref', +) +external ffi.Pointer<X509_CRL> X509_CRL_dup_ref( + ffi.Pointer<X509_CRL> crl, +); + /// X509_CRL_free decrements `crl`'s reference count and, if zero, releases /// memory associated with `crl`. @meta.RecordUse() @@ -25546,16 +25592,6 @@ ffi.Pointer<X509_STORE_CTX> ctx, ); -/// X509_STORE_CTX_get0_current_crl returns the CRL which caused the error -/// returned by `X509_STORE_CTX_get_error`. -@meta.RecordUse() -@ffi.Native<ffi.Pointer<X509_CRL> Function(ffi.Pointer<X509_STORE_CTX>)>( - symbol: 'bssl_dart_X509_STORE_CTX_get0_current_crl', -) -external ffi.Pointer<X509_CRL> X509_STORE_CTX_get0_current_crl( - ffi.Pointer<X509_STORE_CTX> ctx, -); - /// X509_STORE_CTX_get0_param returns `ctx`'s verification parameters. This /// object is mutable and may be modified by the caller. @meta.RecordUse() @@ -28088,8 +28124,7 @@ ); /// X509_set_pubkey sets `x509`'s public key to `pkey`. It returns one on success -/// and zero on error. This function does not take ownership of `pkey` and -/// internally copies and updates reference counts as needed. +/// and zero on error. @meta.RecordUse() @ffi.Native<ffi.Int Function(ffi.Pointer<X509>, ffi.Pointer<EVP_PKEY>)>( symbol: 'bssl_dart_X509_set_pubkey', @@ -32975,9 +33010,9 @@ const int EVP_MAX_KEY_LENGTH = 64; -const int EVP_MAX_MD_BLOCK_SIZE = 128; +const int EVP_MAX_MD_BLOCK_SIZE = 136; -const int EVP_MAX_MD_DATA_SIZE = 208; +const int EVP_MAX_MD_DATA_SIZE = 240; const int EVP_MAX_MD_SIZE = 64; @@ -33276,11 +33311,11 @@ const int NID_Private = 385; -const int NID_SLH_DSA_SHA2_128s = 979; +const int NID_SLH_DSA_SHA2_128s = 973; -const int NID_SLH_DSA_SHA2_128s_WITH_SHA256 = 981; +const int NID_SLH_DSA_SHA2_128s_WITH_SHA256 = 975; -const int NID_SLH_DSA_SHAKE_256f = 980; +const int NID_SLH_DSA_SHAKE_256f = 974; const int NID_SMIME = 188; @@ -33462,7 +33497,7 @@ const int NID_aes_256_xts = 914; -const int NID_alg_mtcProof_draft = 976; +const int NID_alg_mtcProof = 976; const int NID_algorithm = 376; @@ -34532,7 +34567,7 @@ const int NID_pbmac1 = 162; -const int NID_pe_mtcCertificationAuthority_draft = 978; +const int NID_pe_mtcCertificationAuthority_SHA256 = 978; const int NID_personalSignature = 499; @@ -34662,7 +34697,7 @@ const int NID_rc5_ofb64 = 123; -const int NID_rdna_trustAnchorID_draft = 977; +const int NID_rdna_trustAnchorID = 977; const int NID_registeredAddress = 870; @@ -35771,7 +35806,7 @@ /// md_data contains the hash-specific context. final class UnnamedUnion$2 extends ffi.Union { - @ffi.Array.multi([208]) + @ffi.Array.multi([240]) external ffi.Array<ffi.Uint8> md_data; @ffi.Uint64() @@ -36367,7 +36402,7 @@ const int X509_V_FLAG_CB_ISSUER_CHECK = 1; -const int X509_V_FLAG_CHECK_SS_SIGNATURE = 16384; +const int X509_V_FLAG_CHECK_SS_SIGNATURE = 0; const int X509_V_FLAG_CRL_CHECK = 4; @@ -36399,7 +36434,7 @@ const int X509_V_FLAG_USE_DELTAS = 8192; -const int X509_V_FLAG_USE_MTC_DRAFT_PLANTS_05 = 4194304; +const int X509_V_FLAG_USE_MTC_DRAFT_PLANTS_07 = 4194304; const int X509_V_FLAG_X509_STRICT = 0;
diff --git a/pkgs/boring/lib/src/bindings/record_use_mapping.g.dart b/pkgs/boring/lib/src/bindings/record_use_mapping.g.dart index f61e022..5aa218a 100644 --- a/pkgs/boring/lib/src/bindings/record_use_mapping.g.dart +++ b/pkgs/boring/lib/src/bindings/record_use_mapping.g.dart
@@ -94,6 +94,7 @@ 'ASN1_STRING_free': 'bssl_dart_ASN1_STRING_free', 'ASN1_STRING_get0_data': 'bssl_dart_ASN1_STRING_get0_data', 'ASN1_STRING_get_default_mask': 'bssl_dart_ASN1_STRING_get_default_mask', + 'ASN1_STRING_get_length': 'bssl_dart_ASN1_STRING_get_length', 'ASN1_STRING_length': 'bssl_dart_ASN1_STRING_length', 'ASN1_STRING_new': 'bssl_dart_ASN1_STRING_new', 'ASN1_STRING_print': 'bssl_dart_ASN1_STRING_print', @@ -183,6 +184,7 @@ 'BIO_ctrl_get_write_guarantee': 'bssl_dart_BIO_ctrl_get_write_guarantee', 'BIO_ctrl_pending': 'bssl_dart_BIO_ctrl_pending', 'BIO_do_connect': 'bssl_dart_BIO_do_connect', + 'BIO_dup_ref': 'bssl_dart_BIO_dup_ref', 'BIO_eof': 'bssl_dart_BIO_eof', 'BIO_find_type': 'bssl_dart_BIO_find_type', 'BIO_flush': 'bssl_dart_BIO_flush', @@ -608,6 +610,7 @@ 'DH_compute_key': 'bssl_dart_DH_compute_key', 'DH_compute_key_hashed': 'bssl_dart_DH_compute_key_hashed', 'DH_compute_key_padded': 'bssl_dart_DH_compute_key_padded', + 'DH_dup_ref': 'bssl_dart_DH_dup_ref', 'DH_free': 'bssl_dart_DH_free', 'DH_generate_key': 'bssl_dart_DH_generate_key', 'DH_generate_parameters_ex': 'bssl_dart_DH_generate_parameters_ex', @@ -1249,6 +1252,9 @@ 'EVP_sha224': 'bssl_dart_EVP_sha224', 'EVP_sha256': 'bssl_dart_EVP_sha256', 'EVP_sha384': 'bssl_dart_EVP_sha384', + 'EVP_sha3_256': 'bssl_dart_EVP_sha3_256', + 'EVP_sha3_384': 'bssl_dart_EVP_sha3_384', + 'EVP_sha3_512': 'bssl_dart_EVP_sha3_512', 'EVP_sha512': 'bssl_dart_EVP_sha512', 'EVP_sha512_256': 'bssl_dart_EVP_sha512_256', 'EXTENDED_KEY_USAGE_free': 'bssl_dart_EXTENDED_KEY_USAGE_free', @@ -1702,6 +1708,7 @@ 'X509_CRL_delete_ext': 'bssl_dart_X509_CRL_delete_ext', 'X509_CRL_digest': 'bssl_dart_X509_CRL_digest', 'X509_CRL_dup': 'bssl_dart_X509_CRL_dup', + 'X509_CRL_dup_ref': 'bssl_dart_X509_CRL_dup_ref', 'X509_CRL_free': 'bssl_dart_X509_CRL_free', 'X509_CRL_get0_by_cert': 'bssl_dart_X509_CRL_get0_by_cert', 'X509_CRL_get0_by_serial': 'bssl_dart_X509_CRL_get0_by_serial', @@ -1869,8 +1876,6 @@ 'X509_STORE_CTX_free': 'bssl_dart_X509_STORE_CTX_free', 'X509_STORE_CTX_get0_cert': 'bssl_dart_X509_STORE_CTX_get0_cert', 'X509_STORE_CTX_get0_chain': 'bssl_dart_X509_STORE_CTX_get0_chain', - 'X509_STORE_CTX_get0_current_crl': - 'bssl_dart_X509_STORE_CTX_get0_current_crl', 'X509_STORE_CTX_get0_param': 'bssl_dart_X509_STORE_CTX_get0_param', 'X509_STORE_CTX_get0_parent_ctx': 'bssl_dart_X509_STORE_CTX_get0_parent_ctx', 'X509_STORE_CTX_get0_store': 'bssl_dart_X509_STORE_CTX_get0_store',
diff --git a/pkgs/boring/third_party/boringssl/sources.cmake b/pkgs/boring/third_party/boringssl/sources.cmake index 2d97387..fcf752d 100644 --- a/pkgs/boring/third_party/boringssl/sources.cmake +++ b/pkgs/boring/third_party/boringssl/sources.cmake
@@ -112,6 +112,7 @@ ${BORINGSSL_ROOT}src/crypto/evp/p_ec.cc ${BORINGSSL_ROOT}src/crypto/evp/p_ed25519.cc ${BORINGSSL_ROOT}src/crypto/evp/p_hkdf.cc + ${BORINGSSL_ROOT}src/crypto/evp/p_keccak.cc ${BORINGSSL_ROOT}src/crypto/evp/p_mldsa.cc ${BORINGSSL_ROOT}src/crypto/evp/p_mlkem.cc ${BORINGSSL_ROOT}src/crypto/evp/p_rsa.cc
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/asn1/asn1_lib.cc b/pkgs/boring/third_party/boringssl/src/crypto/asn1/asn1_lib.cc index e41e43e..960cabb 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/asn1/asn1_lib.cc +++ b/pkgs/boring/third_party/boringssl/src/crypto/asn1/asn1_lib.cc
@@ -280,6 +280,7 @@ } void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len) { + BSSL_CHECK(len >= 0); OPENSSL_free(str->data); str->data = reinterpret_cast<uint8_t *>(data); str->length = len; @@ -361,6 +362,8 @@ int ASN1_STRING_length(const ASN1_STRING *str) { return str->length; } +size_t ASN1_STRING_get_length(const ASN1_STRING *str) { return str->length; } + int ASN1_STRING_type(const ASN1_STRING *str) { return str->type; } unsigned char *ASN1_STRING_data(ASN1_STRING *str) { return str->data; }
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/bio/bio.cc b/pkgs/boring/third_party/boringssl/src/crypto/bio/bio.cc index aabf06d..28c3f4b 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/bio/bio.cc +++ b/pkgs/boring/third_party/boringssl/src/crypto/bio/bio.cc
@@ -74,6 +74,13 @@ return 1; } +BIO *BIO_dup_ref(const BIO *bio) { + if (bio == nullptr) { + return nullptr; + } + return FromOpaque(bio)->DupRefInternal(); +} + void BIO_vfree(BIO *bio) { BIO_free(bio); } void BIO_free_all(BIO *bio) { BIO_free(bio); } @@ -291,9 +298,7 @@ impl->retry_reason = 0; } -int BIO_method_type(const BIO *bio) { - return FromOpaque(bio)->method->type; -} +int BIO_method_type(const BIO *bio) { return FromOpaque(bio)->method->type; } void BIO_copy_next_retry(BIO *bio) { auto *impl = FromOpaque(bio);
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/cms/cms.cc b/pkgs/boring/third_party/boringssl/src/crypto/cms/cms.cc index e8ba962..ddd9d60 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/cms/cms.cc +++ b/pkgs/boring/third_party/boringssl/src/crypto/cms/cms.cc
@@ -56,8 +56,9 @@ BSSL_NAMESPACE_END -CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, - BIO *data, uint32_t flags) { +CMS_ContentInfo *CMS_sign(const X509 *signcert, const EVP_PKEY *pkey, + const STACK_OF(X509) *certs, BIO *data, + uint32_t flags) { // We only support external signatures and do not support embedding // certificates in SignedData. if ((flags & CMS_DETACHED) == 0 || sk_X509_num(certs) != 0) { @@ -88,8 +89,8 @@ void CMS_ContentInfo_free(CMS_ContentInfo *cms) { Delete(FromOpaque(cms)); } -CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, X509 *signcert, - EVP_PKEY *pkey, const EVP_MD *md, +CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, const X509 *signcert, + const EVP_PKEY *pkey, const EVP_MD *md, uint32_t flags) { auto *impl = FromOpaque(cms); if ( // Already finalized.
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/dsa/dsa.cc b/pkgs/boring/third_party/boringssl/src/crypto/dsa/dsa.cc index 2048c44..9bb2df1 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/dsa/dsa.cc +++ b/pkgs/boring/third_party/boringssl/src/crypto/dsa/dsa.cc
@@ -76,9 +76,7 @@ if (dsa == nullptr) { return nullptr; } - auto *ptr = const_cast<DSA *>(dsa); - DSA_up_ref(ptr); - return ptr; + return FromOpaque(dsa)->DupRefInternal(); } unsigned DSA_bits(const DSA *dsa) {
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/evp/evp.cc b/pkgs/boring/third_party/boringssl/src/crypto/evp/evp.cc index f99ee15..f52a967 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/evp/evp.cc +++ b/pkgs/boring/third_party/boringssl/src/crypto/evp/evp.cc
@@ -63,10 +63,7 @@ if (pkey == nullptr) { return nullptr; } - auto pkey_ref = const_cast<EVP_PKEY *>(pkey); - // We know that this call always returns one. - EVP_PKEY_up_ref(pkey_ref); - return pkey_ref; + return FromOpaque(pkey)->DupRefInternal(); } int EVP_PKEY_is_opaque(const EVP_PKEY *pkey) {
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/evp/evp_ctx.cc b/pkgs/boring/third_party/boringssl/src/crypto/evp/evp_ctx.cc index a0d7810..e01e92a 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/evp/evp_ctx.cc +++ b/pkgs/boring/third_party/boringssl/src/crypto/evp/evp_ctx.cc
@@ -30,7 +30,8 @@ using namespace bssl; static UniquePtr<EvpPkeyCtx> evp_pkey_ctx_new( - EvpPkey *pkey, const EVP_PKEY_ALG *alg, const EVP_PKEY_CTX_METHOD *pmeth) { + const EvpPkey *pkey, const EVP_PKEY_ALG *alg, + const EVP_PKEY_CTX_METHOD *pmeth) { assert(pkey != nullptr || alg != nullptr); UniquePtr<EvpPkeyCtx> ret = MakeUnique<EvpPkeyCtx>(); if (!ret) { @@ -49,7 +50,7 @@ return ret; } -EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e) { +EVP_PKEY_CTX *EVP_PKEY_CTX_new(const EVP_PKEY *pkey, ENGINE *e) { auto *pkey_impl = FromOpaque(pkey); if (pkey_impl == nullptr || pkey_impl->ameth == nullptr) { OPENSSL_PUT_ERROR(EVP, ERR_R_PASSED_NULL_PARAMETER); @@ -151,7 +152,7 @@ return ret.release(); } -EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx) { +EVP_PKEY *EVP_PKEY_CTX_get0_pkey(const EVP_PKEY_CTX *ctx) { auto *impl = FromOpaque(ctx); return impl->pkey.get(); } @@ -315,7 +316,7 @@ return 1; } -int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer) { +int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, const EVP_PKEY *peer) { auto *impl = FromOpaque(ctx); if (!impl || !impl->pmeth || !(impl->pmeth->derive || impl->pmeth->encrypt || impl->pmeth->decrypt) || @@ -330,7 +331,8 @@ return 0; } - int ret = impl->pmeth->ctrl(impl, EVP_PKEY_CTRL_PEER_KEY, 0, peer); + int ret = impl->pmeth->ctrl(impl, EVP_PKEY_CTRL_PEER_KEY, 0, + const_cast<EVP_PKEY *>(peer)); if (ret <= 0) { return 0; @@ -357,7 +359,7 @@ } impl->peerkey = UpRef(FromOpaque(peer)); - ret = impl->pmeth->ctrl(impl, EVP_PKEY_CTRL_PEER_KEY, 1, peer); + ret = impl->pmeth->ctrl(impl, EVP_PKEY_CTRL_PEER_KEY, 1, impl->peerkey.get()); if (ret <= 0) { impl->peerkey = nullptr; return 0;
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/evp/p_keccak.cc b/pkgs/boring/third_party/boringssl/src/crypto/evp/p_keccak.cc new file mode 100644 index 0000000..99731c0 --- /dev/null +++ b/pkgs/boring/third_party/boringssl/src/crypto/evp/p_keccak.cc
@@ -0,0 +1,84 @@ +// Copyright 2026 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. + +// Family of Keccak-derived hash functions including: +// - SHA3-256 +// - SHA3-512 + +#include <openssl/evp.h> + +#include "../fipsmodule/digest/internal.h" // IWYU pragma: keep +#include "../fipsmodule/keccak/internal.h" + +BSSL_NAMESPACE_BEGIN +namespace { +template <boringssl_keccak_config_t Config> +void keccak_init(EVP_MD_CTX *ctx) { + BORINGSSL_keccak_init(reinterpret_cast<BORINGSSL_keccak_st *>(ctx->md_data), + Config); +} + +void keccak_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + BORINGSSL_keccak_absorb(reinterpret_cast<BORINGSSL_keccak_st *>(ctx->md_data), + static_cast<const uint8_t *>(data), count); +} + +template <size_t Size> +void keccak_final(EVP_MD_CTX *ctx, uint8_t *out) { + BORINGSSL_keccak_squeeze( + reinterpret_cast<BORINGSSL_keccak_st *>(ctx->md_data), + static_cast<uint8_t *>(out), Size); +} + +constexpr EVP_MD evp_md_sha3_256 = { + /*type=*/NID_undef, + /*md_size=*/SHA3_256_DIGEST_LENGTH, + /*flags=*/0, + /*init=*/keccak_init<boringssl_sha3_256>, + /*update=*/keccak_update, + /*final=*/keccak_final<SHA3_256_DIGEST_LENGTH>, + /*block_size=*/SHA3_256_CBLOCK, + /*ctx_size=*/sizeof(BORINGSSL_keccak_st), +}; + +constexpr EVP_MD evp_md_sha3_384 = { + /*type=*/NID_undef, + /*md_size=*/SHA3_384_DIGEST_LENGTH, + /*flags=*/0, + /*init=*/keccak_init<boringssl_sha3_384>, + /*update=*/keccak_update, + /*final=*/keccak_final<SHA3_384_DIGEST_LENGTH>, + /*block_size=*/SHA3_384_CBLOCK, + /*ctx_size=*/sizeof(BORINGSSL_keccak_st), +}; + +constexpr EVP_MD evp_md_sha3_512 = { + /*type=*/NID_undef, + /*md_size=*/SHA3_512_DIGEST_LENGTH, + /*flags=*/0, + /*init=*/keccak_init<boringssl_sha3_512>, + /*update=*/keccak_update, + /*final=*/keccak_final<SHA3_512_DIGEST_LENGTH>, + /*block_size=*/SHA3_512_CBLOCK, + /*ctx_size=*/sizeof(BORINGSSL_keccak_st), +}; + +static_assert(sizeof(BORINGSSL_keccak_st) <= EVP_MAX_MD_DATA_SIZE); +static_assert(SHA3_256_CBLOCK <= EVP_MAX_MD_BLOCK_SIZE); +} // namespace +BSSL_NAMESPACE_END + +const EVP_MD *EVP_sha3_256() { return &bssl::evp_md_sha3_256; } +const EVP_MD *EVP_sha3_384() { return &bssl::evp_md_sha3_384; } +const EVP_MD *EVP_sha3_512() { return &bssl::evp_md_sha3_512; }
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/evp/sign.cc b/pkgs/boring/third_party/boringssl/src/crypto/evp/sign.cc index afccef5..3503c40 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/evp/sign.cc +++ b/pkgs/boring/third_party/boringssl/src/crypto/evp/sign.cc
@@ -19,8 +19,6 @@ #include <openssl/digest.h> #include <openssl/err.h> -#include "internal.h" - int EVP_SignInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) { return EVP_DigestInit_ex(ctx, type, impl); @@ -35,7 +33,7 @@ } int EVP_SignFinal(const EVP_MD_CTX *ctx, uint8_t *sig, unsigned *out_sig_len, - EVP_PKEY *pkey) { + const EVP_PKEY *pkey) { // Ensure the final result will fit in `unsigned`. size_t sig_len = EVP_PKEY_size(pkey); if (sig_len > UINT_MAX) { @@ -75,7 +73,7 @@ } int EVP_VerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig, size_t sig_len, - EVP_PKEY *pkey) { + const EVP_PKEY *pkey) { uint8_t m[EVP_MAX_MD_SIZE]; unsigned m_len; bssl::ScopedEVP_MD_CTX tmp_ctx; @@ -85,11 +83,9 @@ } bssl::UniquePtr<EVP_PKEY_CTX> pkctx(EVP_PKEY_CTX_new(pkey, nullptr)); - if (!pkctx || - !EVP_PKEY_verify_init(pkctx.get()) || + if (!pkctx || !EVP_PKEY_verify_init(pkctx.get()) || !EVP_PKEY_CTX_set_signature_md(pkctx.get(), ctx->digest)) { return 0; } return EVP_PKEY_verify(pkctx.get(), sig, sig_len, m, m_len); } -
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/dh/dh.cc.inc b/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/dh/dh.cc.inc index d018f76..8dfcdee 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/dh/dh.cc.inc +++ b/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/dh/dh.cc.inc
@@ -353,6 +353,13 @@ return 1; } +DH *DH_dup_ref(const DH *dh) { + if (dh == nullptr) { + return nullptr; + } + return FromOpaque(dh)->DupRefInternal(); +} + DH *DH_get_rfc7919_2048() { // This is the prime from https://tools.ietf.org/html/rfc7919#appendix-A.1, // which is specifically approved for FIPS in appendix D of SP 800-56Ar3.
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/digestsign/digestsign.cc.inc b/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/digestsign/digestsign.cc.inc index 8920546..a886d46 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/digestsign/digestsign.cc.inc +++ b/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/digestsign/digestsign.cc.inc
@@ -41,7 +41,7 @@ } static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **out_pctx, - const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey, + const EVP_MD *type, ENGINE *e, const EVP_PKEY *pkey, enum evp_sign_verify_t op) { UniquePtr<EVP_PKEY_CTX> pctx(EVP_PKEY_CTX_new(pkey, e)); if (pctx == nullptr) { @@ -84,12 +84,12 @@ } int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, - ENGINE *e, EVP_PKEY *pkey) { + ENGINE *e, const EVP_PKEY *pkey) { return do_sigver_init(ctx, pctx, type, e, pkey, evp_sign); } int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, - const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey) { + const EVP_MD *type, ENGINE *e, const EVP_PKEY *pkey) { return do_sigver_init(ctx, pctx, type, e, pkey, evp_verify); } @@ -143,8 +143,7 @@ } } -int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig, - size_t sig_len) { +int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig, size_t sig_len) { if (!uses_prehash(ctx->pctx, evp_verify)) { OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); return 0;
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/ec/ec_key.cc.inc b/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/ec/ec_key.cc.inc index e1e4e4b..078e541 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/ec/ec_key.cc.inc +++ b/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/ec/ec_key.cc.inc
@@ -150,9 +150,7 @@ if (key == nullptr) { return nullptr; } - auto *ptr = const_cast<EC_KEY *>(key); - EC_KEY_up_ref(ptr); - return ptr; + return FromOpaque(key)->DupRefInternal(); } int EC_KEY_is_opaque(const EC_KEY *key) {
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/keccak/internal.h b/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/keccak/internal.h index e7d79b0..fa1e2e8 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/keccak/internal.h +++ b/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/keccak/internal.h
@@ -22,8 +22,18 @@ BSSL_NAMESPACE_BEGIN +#define BITS_TO_BYTES(BITS) ((BITS) / 8) +#define SHA3_256_DIGEST_LENGTH BITS_TO_BYTES(256) +#define SHA3_384_DIGEST_LENGTH BITS_TO_BYTES(384) +#define SHA3_512_DIGEST_LENGTH BITS_TO_BYTES(512) +#define SHA3_BLOCK_SIZE(BITS) BITS_TO_BYTES(1600 - 2 * (BITS)) +#define SHA3_256_CBLOCK SHA3_BLOCK_SIZE(256) +#define SHA3_384_CBLOCK SHA3_BLOCK_SIZE(384) +#define SHA3_512_CBLOCK SHA3_BLOCK_SIZE(512) + enum boringssl_keccak_config_t : int32_t { boringssl_sha3_256, + boringssl_sha3_384, boringssl_sha3_512, boringssl_shake128, boringssl_shake256,
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/keccak/keccak.cc.inc b/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/keccak/keccak.cc.inc index adb09a2..e808dd5 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/keccak/keccak.cc.inc +++ b/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/keccak/keccak.cc.inc
@@ -205,6 +205,10 @@ capacity_bytes = 512 / 8; required_out_len = 32; break; + case boringssl_sha3_384: + capacity_bytes = 768 / 8; + required_out_len = 48; + break; case boringssl_sha3_512: capacity_bytes = 1024 / 8; required_out_len = 64; @@ -235,8 +239,9 @@ [[maybe_unused]] static bool keccak_can_parallel( enum boringssl_keccak_config_t config) { - return config == boringssl_sha3_256 || config == boringssl_sha3_512 || - config == boringssl_shake128 || config == boringssl_shake256; + return config == boringssl_sha3_256 || config == boringssl_sha3_384 || + config == boringssl_sha3_512 || config == boringssl_shake128 || + config == boringssl_shake256; } static bool keccak_is_cshake(enum boringssl_keccak_config_t config) { @@ -430,6 +435,7 @@ static uint8_t keccak_terminator(struct BORINGSSL_keccak_st *ctx) { switch (ctx->config) { case boringssl_sha3_256: + case boringssl_sha3_384: case boringssl_sha3_512: return 0x06; case boringssl_shake128:
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/rsa/rsa.cc.inc b/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/rsa/rsa.cc.inc index 34a219f..cf406b2 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/rsa/rsa.cc.inc +++ b/pkgs/boring/third_party/boringssl/src/crypto/fipsmodule/rsa/rsa.cc.inc
@@ -225,9 +225,7 @@ if (rsa == nullptr) { return nullptr; } - auto *ptr = const_cast<RSA *>(rsa); - RSA_up_ref(ptr); - return ptr; + return FromOpaque(rsa)->DupRefInternal(); } unsigned RSA_bits(const RSA *rsa) {
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/mem_internal.h b/pkgs/boring/third_party/boringssl/src/crypto/mem_internal.h index 59927e1..488052f 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/mem_internal.h +++ b/pkgs/boring/third_party/boringssl/src/crypto/mem_internal.h
@@ -135,6 +135,13 @@ // ref-count variable. CRYPTO_refcount_inc(&references_); } + + // Only the implementations of `FOO_dup_ref` should call these. + Derived *DupRefInternal() const { + UpRefInternal(); + return const_cast<Derived *>(static_cast<const Derived *>(this)); + } + bool DecRefInternal() { if (CRYPTO_refcount_dec_and_test_zero(&references_)) { Derived *d = static_cast<Derived *>(this);
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/obj/obj_dat.h b/pkgs/boring/third_party/boringssl/src/crypto/obj/obj_dat.h index ced3582..0e7d4c2 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/obj/obj_dat.h +++ b/pkgs/boring/third_party/boringssl/src/crypto/obj/obj_dat.h
@@ -16,7 +16,7 @@ BSSL_NAMESPACE_BEGIN -#define NUM_NID 982 +#define NUM_NID 979 static const uint8_t kObjectData[] = { /* NID_rsadsi */ @@ -7146,39 +7146,6 @@ 0x04, 0x04, 0x02, - /* NID_alg_mtcProof_draft */ - 0x2b, - 0x06, - 0x01, - 0x04, - 0x01, - 0x82, - 0xda, - 0x4b, - 0x2f, - 0x00, - /* NID_rdna_trustAnchorID_draft */ - 0x2b, - 0x06, - 0x01, - 0x04, - 0x01, - 0x82, - 0xda, - 0x4b, - 0x2f, - 0x01, - /* NID_pe_mtcCertificationAuthority_draft */ - 0x2b, - 0x06, - 0x01, - 0x04, - 0x01, - 0x82, - 0xda, - 0x4b, - 0x2f, - 0x02, /* NID_SLH_DSA_SHA2_128s */ 0x60, 0x86, @@ -7209,6 +7176,33 @@ 0x04, 0x03, 0x23, + /* NID_alg_mtcProof */ + 0x2b, + 0x06, + 0x01, + 0x05, + 0x05, + 0x07, + 0x06, + 0x43, + /* NID_rdna_trustAnchorID */ + 0x2b, + 0x06, + 0x01, + 0x05, + 0x05, + 0x07, + 0x19, + 0x03, + /* NID_pe_mtcCertificationAuthority_SHA256 */ + 0x2b, + 0x06, + 0x01, + 0x05, + 0x05, + 0x07, + 0x01, + 0x26, }; static const ASN1_OBJECT kObjects[NUM_NID] = { @@ -8865,21 +8859,19 @@ 0}, {NULL, NULL, NID_undef, 0, NULL, 0}, {"X-Wing", "X-Wing", NID_X_Wing, 0, NULL, 0}, - {NULL, NULL, NID_undef, 0, NULL, 0}, - {NULL, NULL, NID_undef, 0, NULL, 0}, - {NULL, NULL, NID_undef, 0, NULL, 0}, - {"alg-mtcProof-draft", "alg-mtcProof-draft", NID_alg_mtcProof_draft, 10, - &kObjectData[6241], 0}, - {"rdna-trustAnchorID-draft", "rdna-trustAnchorID-draft", - NID_rdna_trustAnchorID_draft, 10, &kObjectData[6251], 0}, - {"pe-mtcCertificationAuthority-draft", "pe-mtcCertificationAuthority-draft", - NID_pe_mtcCertificationAuthority_draft, 10, &kObjectData[6261], 0}, {"id-slh-dsa-sha2-128s", "SLH-DSA-SHA2-128s", NID_SLH_DSA_SHA2_128s, 9, - &kObjectData[6271], 0}, + &kObjectData[6241], 0}, {"id-slh-dsa-shake-256f", "SLH-DSA-SHAKE-256f", NID_SLH_DSA_SHAKE_256f, 9, - &kObjectData[6280], 0}, + &kObjectData[6250], 0}, {"id-hash-slh-dsa-sha2-128s-with-sha256", "SLH-DSA-SHA2-128s-WITH-SHA256", - NID_SLH_DSA_SHA2_128s_WITH_SHA256, 9, &kObjectData[6289], 0}, + NID_SLH_DSA_SHA2_128s_WITH_SHA256, 9, &kObjectData[6259], 0}, + {"alg-mtcProof", "alg-mtcProof", NID_alg_mtcProof, 8, &kObjectData[6268], + 0}, + {"rdna-trustAnchorID", "rdna-trustAnchorID", NID_rdna_trustAnchorID, 8, + &kObjectData[6276], 0}, + {"pe-mtcCertificationAuthority-SHA256", + "pe-mtcCertificationAuthority-SHA256", + NID_pe_mtcCertificationAuthority_SHA256, 8, &kObjectData[6284], 0}, }; static const uint16_t kNIDsInShortNameOrder[] = { @@ -9095,7 +9087,7 @@ 368 /* acceptableResponses */, 446 /* account */, 363 /* ad_timestamping */, - 976 /* alg-mtcProof-draft */, + 976 /* alg-mtcProof */, 376 /* algorithm */, 405 /* ansi-X9-62 */, 910 /* anyExtendedKeyUsage */, @@ -9354,7 +9346,7 @@ 331 /* id-cmc-transactionId */, 787 /* id-ct-asciiTextWithCRLF */, 408 /* id-ecPublicKey */, - 981 /* id-hash-slh-dsa-sha2-128s-with-sha256 */, + 975 /* id-hash-slh-dsa-sha2-128s-with-sha256 */, 508 /* id-hex-multipart-message */, 507 /* id-hex-partial-message */, 260 /* id-it */, @@ -9426,8 +9418,8 @@ 322 /* id-regInfo-certReq */, 321 /* id-regInfo-utf8Pairs */, 512 /* id-set */, - 979 /* id-slh-dsa-sha2-128s */, - 980 /* id-slh-dsa-shake-256f */, + 973 /* id-slh-dsa-sha2-128s */, + 974 /* id-slh-dsa-shake-256f */, 191 /* id-smime-aa */, 215 /* id-smime-aa-contentHint */, 218 /* id-smime-aa-contentIdentifier */, @@ -9560,7 +9552,7 @@ 489 /* pagerTelephoneNumber */, 374 /* path */, 112 /* pbeWithMD5AndCast5CBC */, - 978 /* pe-mtcCertificationAuthority-draft */, + 978 /* pe-mtcCertificationAuthority-SHA256 */, 499 /* personalSignature */, 487 /* personalTitle */, 464 /* photo */, @@ -9614,7 +9606,7 @@ 286 /* qcStatements */, 457 /* qualityLabelledData */, 450 /* rFC822localPart */, - 977 /* rdna-trustAnchorID-draft */, + 977 /* rdna-trustAnchorID */, 870 /* registeredAddress */, 400 /* role */, 877 /* roleOccupant */, @@ -9955,9 +9947,9 @@ 2 /* RSA Data Security, Inc. PKCS */, 188 /* S/MIME */, 167 /* S/MIME Capabilities */, - 979 /* SLH-DSA-SHA2-128s */, - 981 /* SLH-DSA-SHA2-128s-WITH-SHA256 */, - 980 /* SLH-DSA-SHAKE-256f */, + 973 /* SLH-DSA-SHA2-128s */, + 975 /* SLH-DSA-SHA2-128s-WITH-SHA256 */, + 974 /* SLH-DSA-SHAKE-256f */, 387 /* SNMPv2 */, 512 /* Secure Electronic Transactions */, 386 /* Security */, @@ -10041,7 +10033,7 @@ 901 /* aes-256-gcm */, 428 /* aes-256-ofb */, 914 /* aes-256-xts */, - 976 /* alg-mtcProof-draft */, + 976 /* alg-mtcProof */, 376 /* algorithm */, 484 /* associatedDomain */, 485 /* associatedName */, @@ -10520,7 +10512,7 @@ 145 /* pbeWithSHA1And40BitRC4 */, 170 /* pbeWithSHA1AndDES-CBC */, 68 /* pbeWithSHA1AndRC2-CBC */, - 978 /* pe-mtcCertificationAuthority-draft */, + 978 /* pe-mtcCertificationAuthority-SHA256 */, 499 /* personalSignature */, 487 /* personalTitle */, 464 /* photo */, @@ -10580,7 +10572,7 @@ 122 /* rc5-cfb */, 121 /* rc5-ecb */, 123 /* rc5-ofb */, - 977 /* rdna-trustAnchorID-draft */, + 977 /* rdna-trustAnchorID */, 870 /* registeredAddress */, 460 /* rfc822Mailbox */, 117 /* ripemd160 */, @@ -11322,6 +11314,7 @@ 397 /* 1.3.6.1.5.5.7.1.10 (OBJ_ac_proxying) */, 398 /* 1.3.6.1.5.5.7.1.11 (OBJ_sinfo_access) */, 663 /* 1.3.6.1.5.5.7.1.14 (OBJ_proxyCertInfo) */, + 978 /* 1.3.6.1.5.5.7.1.38 (OBJ_pe_mtcCertificationAuthority_SHA256) */, 164 /* 1.3.6.1.5.5.7.2.1 (OBJ_id_qt_cps) */, 165 /* 1.3.6.1.5.5.7.2.2 (OBJ_id_qt_unotice) */, 293 /* 1.3.6.1.5.5.7.2.3 (OBJ_textNotice) */, @@ -11357,6 +11350,7 @@ 324 /* 1.3.6.1.5.5.7.6.2 (OBJ_id_alg_noSignature) */, 325 /* 1.3.6.1.5.5.7.6.3 (OBJ_id_alg_dh_sig_hmac_sha1) */, 326 /* 1.3.6.1.5.5.7.6.4 (OBJ_id_alg_dh_pop) */, + 976 /* 1.3.6.1.5.5.7.6.67 (OBJ_alg_mtcProof) */, 327 /* 1.3.6.1.5.5.7.7.1 (OBJ_id_cmc_statusInfo) */, 328 /* 1.3.6.1.5.5.7.7.2 (OBJ_id_cmc_identification) */, 329 /* 1.3.6.1.5.5.7.7.3 (OBJ_id_cmc_identityProof) */, @@ -11397,6 +11391,7 @@ 664 /* 1.3.6.1.5.5.7.21.0 (OBJ_id_ppl_anyLanguage) */, 665 /* 1.3.6.1.5.5.7.21.1 (OBJ_id_ppl_inheritAll) */, 667 /* 1.3.6.1.5.5.7.21.2 (OBJ_Independent) */, + 977 /* 1.3.6.1.5.5.7.25.3 (OBJ_rdna_trustAnchorID) */, 178 /* 1.3.6.1.5.5.7.48.1 (OBJ_ad_OCSP) */, 179 /* 1.3.6.1.5.5.7.48.2 (OBJ_ad_ca_issuers) */, 363 /* 1.3.6.1.5.5.7.48.3 (OBJ_ad_timeStamping) */, @@ -11535,9 +11530,9 @@ 967 /* 2.16.840.1.101.3.4.3.17 (OBJ_ML_DSA_44) */, 968 /* 2.16.840.1.101.3.4.3.18 (OBJ_ML_DSA_65) */, 969 /* 2.16.840.1.101.3.4.3.19 (OBJ_ML_DSA_87) */, - 979 /* 2.16.840.1.101.3.4.3.20 (OBJ_SLH_DSA_SHA2_128s) */, - 980 /* 2.16.840.1.101.3.4.3.31 (OBJ_SLH_DSA_SHAKE_256f) */, - 981 /* 2.16.840.1.101.3.4.3.35 (OBJ_SLH_DSA_SHA2_128s_WITH_SHA256) */, + 973 /* 2.16.840.1.101.3.4.3.20 (OBJ_SLH_DSA_SHA2_128s) */, + 974 /* 2.16.840.1.101.3.4.3.31 (OBJ_SLH_DSA_SHAKE_256f) */, + 975 /* 2.16.840.1.101.3.4.3.35 (OBJ_SLH_DSA_SHA2_128s_WITH_SHA256) */, 970 /* 2.16.840.1.101.3.4.4.2 (OBJ_ML_KEM_768) */, 966 /* 2.16.840.1.101.3.4.4.3 (OBJ_ML_KEM_1024) */, 71 /* 2.16.840.1.113730.1.1 (OBJ_netscape_cert_type) */, @@ -11637,9 +11632,6 @@ 138 /* 1.3.6.1.4.1.311.10.3.4 (OBJ_ms_efs) */, 648 /* 1.3.6.1.4.1.311.20.2.2 (OBJ_ms_smartcard_login) */, 649 /* 1.3.6.1.4.1.311.20.2.3 (OBJ_ms_upn) */, - 976 /* 1.3.6.1.4.1.44363.47.0 (OBJ_alg_mtcProof_draft) */, - 977 /* 1.3.6.1.4.1.44363.47.1 (OBJ_rdna_trustAnchorID_draft) */, - 978 /* 1.3.6.1.4.1.44363.47.2 (OBJ_pe_mtcCertificationAuthority_draft) */, 751 /* 1.2.392.200011.61.1.1.1.2 (OBJ_camellia_128_cbc) */, 752 /* 1.2.392.200011.61.1.1.1.3 (OBJ_camellia_192_cbc) */, 753 /* 1.2.392.200011.61.1.1.1.4 (OBJ_camellia_256_cbc) */,
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/pkcs7/internal.h b/pkgs/boring/third_party/boringssl/src/crypto/pkcs7/internal.h index a6ab04e..66f8955 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/pkcs7/internal.h +++ b/pkgs/boring/third_party/boringssl/src/crypto/pkcs7/internal.h
@@ -59,7 +59,7 @@ // // Note: CMS v1 and PKCS#7 v1.5 are not completely compatible, but they overlap // in all cases implemented by this function. -int pkcs7_add_external_signature(CBB *out, X509 *sign_cert, EVP_PKEY *key, +int pkcs7_add_external_signature(CBB *out, X509 *sign_cert, const EVP_PKEY *key, const EVP_MD *md, BIO *data, bool use_key_id); BSSL_NAMESPACE_END
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/pkcs7/pkcs7_x509.cc b/pkgs/boring/third_party/boringssl/src/crypto/pkcs7/pkcs7_x509.cc index cb9a725..c179e3a 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/pkcs7/pkcs7_x509.cc +++ b/pkgs/boring/third_party/boringssl/src/crypto/pkcs7/pkcs7_x509.cc
@@ -472,9 +472,9 @@ return 1; } -int bssl::pkcs7_add_external_signature(CBB *out, X509 *sign_cert, EVP_PKEY *key, - const EVP_MD *md, BIO *data, - bool use_key_id) { +int bssl::pkcs7_add_external_signature(CBB *out, X509 *sign_cert, + const EVP_PKEY *key, const EVP_MD *md, + BIO *data, bool use_key_id) { signer_info_data si_data; si_data.use_key_id = use_key_id; si_data.sign_cert = sign_cert; @@ -494,7 +494,7 @@ /*cert_crl_cb=*/nullptr, write_signer_info, &si_data); } -PKCS7 *PKCS7_sign(X509 *sign_cert, EVP_PKEY *pkey, STACK_OF(X509) *certs, +PKCS7 *PKCS7_sign(X509 *sign_cert, const EVP_PKEY *pkey, STACK_OF(X509) *certs, BIO *data, int flags) { ScopedCBB cbb; if (!CBB_init(cbb.get(), 2048)) {
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/pool/pool.cc b/pkgs/boring/third_party/boringssl/src/crypto/pool/pool.cc index 4bc3a19..21e2203 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/pool/pool.cc +++ b/pkgs/boring/third_party/boringssl/src/crypto/pool/pool.cc
@@ -99,9 +99,7 @@ if (pool == nullptr) { return nullptr; } - auto *ptr = const_cast<CRYPTO_BUFFER_POOL *>(pool); - CRYPTO_BUFFER_POOL_up_ref(ptr); - return ptr; + return FromOpaque(pool)->DupRefInternal(); } void CryptoBuffer::UpRefInternal() const { @@ -273,6 +271,9 @@ } CRYPTO_BUFFER *CRYPTO_BUFFER_dup_ref(const CRYPTO_BUFFER *buf) { + if (buf == nullptr) { + return nullptr; + } auto *buf_ = const_cast<CRYPTO_BUFFER *>(buf); FromOpaque(buf_)->UpRefInternal(); return buf_;
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/trust_token/trust_token.cc b/pkgs/boring/third_party/boringssl/src/crypto/trust_token/trust_token.cc index d0e5c24..b295a6b 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/trust_token/trust_token.cc +++ b/pkgs/boring/third_party/boringssl/src/crypto/trust_token/trust_token.cc
@@ -279,13 +279,13 @@ return 1; } -int TRUST_TOKEN_CLIENT_set_srr_key(TRUST_TOKEN_CLIENT *ctx, EVP_PKEY *key) { +int TRUST_TOKEN_CLIENT_set_srr_key(TRUST_TOKEN_CLIENT *ctx, + const EVP_PKEY *key) { if (!ctx->method->has_srr) { return 1; } EVP_PKEY_free(ctx->srr_key); - EVP_PKEY_up_ref(key); - ctx->srr_key = key; + ctx->srr_key = EVP_PKEY_dup_ref(key); return 1; } @@ -515,10 +515,10 @@ return 1; } -int TRUST_TOKEN_ISSUER_set_srr_key(TRUST_TOKEN_ISSUER *ctx, EVP_PKEY *key) { +int TRUST_TOKEN_ISSUER_set_srr_key(TRUST_TOKEN_ISSUER *ctx, + const EVP_PKEY *key) { EVP_PKEY_free(ctx->srr_key); - EVP_PKEY_up_ref(key); - ctx->srr_key = key; + ctx->srr_key = EVP_PKEY_dup_ref(key); return 1; }
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/x509/a_sign.cc b/pkgs/boring/third_party/boringssl/src/crypto/x509/a_sign.cc index 3e313d4..f09e80a 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/x509/a_sign.cc +++ b/pkgs/boring/third_party/boringssl/src/crypto/x509/a_sign.cc
@@ -31,7 +31,7 @@ using namespace bssl; int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2, - ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey, + ASN1_BIT_STRING *signature, void *asn, const EVP_PKEY *pkey, const EVP_MD *type) { if (signature->type != V_ASN1_BIT_STRING) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE);
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/x509/internal.h b/pkgs/boring/third_party/boringssl/src/crypto/x509/internal.h index ab07fec..238a2e8 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/x509/internal.h +++ b/pkgs/boring/third_party/boringssl/src/crypto/x509/internal.h
@@ -61,7 +61,7 @@ int x509_parse_public_key(CBS *cbs, X509_PUBKEY *out, Span<const EVP_PKEY_ALG *const> algs); int x509_marshal_public_key(CBB *cbb, const X509_PUBKEY *in); -int x509_pubkey_set1(X509_PUBKEY *key, EVP_PKEY *pkey); +int x509_pubkey_set1(X509_PUBKEY *key, const EVP_PKEY *pkey); // X509_PUBKEY is an `ASN1_ITEM` whose ASN.1 type is SubjectPublicKeyInfo and C // type is `X509_PUBKEY*`. @@ -170,18 +170,18 @@ UniquePtr<CRYPTO_BUFFER> buf; CRYPTO_EX_DATA ex_data; // These contain copies of various extension values - long ex_pathlen = -1; - uint32_t ex_flags = 0; - uint32_t ex_kusage = 0; - uint32_t ex_xkusage = 0; - UniquePtr<ASN1_OCTET_STRING> skid; - UniquePtr<AUTHORITY_KEYID> akid; - UniquePtr<STACK_OF(DIST_POINT)> crldp; - UniquePtr<STACK_OF(GENERAL_NAME)> altname; - UniquePtr<NAME_CONSTRAINTS> nc; - unsigned char cert_hash[SHA256_DIGEST_LENGTH] = {}; + mutable long ex_pathlen = -1; + mutable uint32_t ex_flags = 0; + mutable uint32_t ex_kusage = 0; + mutable uint32_t ex_xkusage = 0; + mutable UniquePtr<ASN1_OCTET_STRING> skid; + mutable UniquePtr<AUTHORITY_KEYID> akid; + mutable UniquePtr<STACK_OF(DIST_POINT)> crldp; + mutable UniquePtr<STACK_OF(GENERAL_NAME)> altname; + mutable UniquePtr<NAME_CONSTRAINTS> nc; + mutable unsigned char cert_hash[SHA256_DIGEST_LENGTH] = {}; bssl::X509_CERT_AUX *aux = nullptr; - Mutex lock; + mutable Mutex lock; private: friend RefCounted; @@ -406,10 +406,6 @@ int error_depth; int error; X509 *current_cert; - X509_CRL *current_crl; // current CRL - - X509 *current_crl_issuer; // issuer of current CRL - int current_crl_score; // score of current CRL CRYPTO_EX_DATA ex_data; } /* X509_STORE_CTX */; @@ -481,12 +477,11 @@ // the user-initial-policy-set. If `user_policies` is NULL or empty, it is // interpreted as anyPolicy. `flags` is a set of `X509_V_FLAG_*` values to // apply. It returns `X509_V_OK` on success and `X509_V_ERR_*` on error. It -// additionally sets `*out_current_cert` to the certificate where the error -// occurred. If the function succeeded, or the error applies to the entire -// chain, it sets `*out_current_cert` to NULL. +// additionally sets `*out_error_depth` to the index of certificate where the +// error occurred. int X509_policy_check(const STACK_OF(X509) *certs, const STACK_OF(ASN1_OBJECT) *user_policies, - unsigned long flags, X509 **out_current_cert); + unsigned long flags, int *out_error_depth); // x509_check_issued_with_callback calls `X509_check_issued`, but allows the // verify callback to override the result. It returns one on success and zero on @@ -527,7 +522,7 @@ // x509v3_cache_extensions fills in a number of fields relating to X.509 // extensions in `x`. It returns one on success and zero if some extensions were // invalid. -OPENSSL_EXPORT int x509v3_cache_extensions(X509 *x); +OPENSSL_EXPORT int x509v3_cache_extensions(const X509 *x); // x509v3_a2i_ipadd decodes `ipasc` as an IPv4 or IPv6 address. IPv6 addresses // use colon-separated syntax while IPv4 addresses use dotted decimal syntax. If @@ -646,7 +641,7 @@ // Merkle Tree Certificate (MTC) verification functions. // x509_is_merkle_tree_ca returns whether `x509` contains an extension of type -// id-pe-mtcCertificationAuthority. +// id-pe-mtcCertificationAuthority-SHA256. bool x509_is_merkle_tree_ca(const X509 *x509); // x509_evaluate_mtc_subtree_inclusion_proof carries out the procedure in
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/x509/policy.cc b/pkgs/boring/third_party/boringssl/src/crypto/x509/policy.cc index b2c5fba..194b0b5 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/x509/policy.cc +++ b/pkgs/boring/third_party/boringssl/src/crypto/x509/policy.cc
@@ -571,8 +571,8 @@ int X509_policy_check(const STACK_OF(X509) *certs, const STACK_OF(ASN1_OBJECT) *user_policies, - unsigned long flags, X509 **out_current_cert) { - *out_current_cert = nullptr; + unsigned long flags, int *out_error_depth) { + *out_error_depth = 0; // Skip policy checking if the chain is just the trust anchor. const size_t num_certs = sk_X509_num(certs); @@ -593,6 +593,7 @@ X509 *cert = sk_X509_value(certs, i); uint32_t ex_flags = X509_get_extension_flags(cert); if (ex_flags & EXFLAG_INVALID) { + *out_error_depth = static_cast<int>(i); return X509_V_ERR_OUT_OF_MEM; } const bool is_self_issued = (ex_flags & EXFLAG_SI) != 0; @@ -610,17 +611,19 @@ const int any_policy_allowed = inhibit_any_policy > 0 || (i > 0 && is_self_issued); if (!process_certificate_policies(cert, &*level, any_policy_allowed)) { - *out_current_cert = cert; + *out_error_depth = static_cast<int>(i); return X509_V_ERR_INVALID_POLICY_EXTENSION; } // RFC 5280, section 6.1.3, step (f). if (explicit_policy == 0 && level->is_empty()) { + *out_error_depth = static_cast<int>(i); return X509_V_ERR_NO_EXPLICIT_POLICY; } // Insert the completed level into the list. if (!levels.Push(*std::exchange(level, std::nullopt))) { + *out_error_depth = static_cast<int>(i); return X509_V_ERR_OUT_OF_MEM; } level = std::nullopt; @@ -631,7 +634,7 @@ // RFC 5280, section 6.1.4, steps (a) and (b). level = process_policy_mappings(cert, &levels.back(), policy_mapping > 0); if (!level.has_value()) { - *out_current_cert = cert; + *out_error_depth = static_cast<int>(i); return X509_V_ERR_INVALID_POLICY_EXTENSION; } } @@ -653,7 +656,7 @@ } if (!process_policy_constraints(cert, &explicit_policy, &policy_mapping, &inhibit_any_policy)) { - *out_current_cert = cert; + *out_error_depth = static_cast<int>(i); return X509_V_ERR_INVALID_POLICY_EXTENSION; } }
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/x509/v3_purp.cc b/pkgs/boring/third_party/boringssl/src/crypto/x509/v3_purp.cc index 86f23b8..2dba0d0 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/x509/v3_purp.cc +++ b/pkgs/boring/third_party/boringssl/src/crypto/x509/v3_purp.cc
@@ -18,6 +18,7 @@ #include <openssl/digest.h> #include <openssl/err.h> #include <openssl/mem.h> +#include <openssl/nid.h> #include <openssl/obj.h> #include <openssl/stack.h> #include <openssl/x509.h> @@ -142,11 +143,11 @@ nid == NID_policy_constraints || // nid == NID_name_constraints || // nid == NID_policy_mappings || // - nid == NID_inhibit_any_policy || - nid == NID_pe_mtcCertificationAuthority_draft; + nid == NID_inhibit_any_policy || // + nid == NID_pe_mtcCertificationAuthority_SHA256; } -static int setup_crldp(X509 *x) { +static int setup_crldp(const X509 *x) { int j; auto *impl = FromOpaque(x); impl->crldp.reset(reinterpret_cast<STACK_OF(DIST_POINT) *>( @@ -157,7 +158,7 @@ return 1; } -int bssl::x509v3_cache_extensions(X509 *x) { +int bssl::x509v3_cache_extensions(const X509 *x) { BASIC_CONSTRAINTS *bs; ASN1_BIT_STRING *usage; EXTENDED_KEY_USAGE *extusage; @@ -341,7 +342,7 @@ } int X509_check_ca(const X509 *x) { - if (!x509v3_cache_extensions(const_cast<X509*>(x))) { + if (!x509v3_cache_extensions(x)) { return 0; } return check_ca(x); @@ -450,8 +451,8 @@ X509_get_issuer_name(subject))) { return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; } - if (!x509v3_cache_extensions(const_cast<X509 *>(issuer)) || - !x509v3_cache_extensions(const_cast<X509 *>(subject))) { + if (!x509v3_cache_extensions(issuer) || + !x509v3_cache_extensions(subject)) { return X509_V_ERR_UNSPECIFIED; }
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/x509/x509_cmp.cc b/pkgs/boring/third_party/boringssl/src/crypto/x509/x509_cmp.cc index 4dea236..5c78399 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/x509/x509_cmp.cc +++ b/pkgs/boring/third_party/boringssl/src/crypto/x509/x509_cmp.cc
@@ -107,8 +107,8 @@ // comparison and may cause misbehaving sorts by transitivity. For now, we // retain the old OpenSSL behavior, which was to ignore the error. See // https://crbug.com/boringssl/355. - x509v3_cache_extensions((X509Impl *)a_impl); - x509v3_cache_extensions((X509Impl *)b_impl); + x509v3_cache_extensions(a_impl); + x509v3_cache_extensions(b_impl); return OPENSSL_memcmp(a_impl->cert_hash, b_impl->cert_hash, SHA256_DIGEST_LENGTH);
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/x509/x509_lu.cc b/pkgs/boring/third_party/boringssl/src/crypto/x509/x509_lu.cc index 91c3b2d..5b60327 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/x509/x509_lu.cc +++ b/pkgs/boring/third_party/boringssl/src/crypto/x509/x509_lu.cc
@@ -153,9 +153,7 @@ if (store == nullptr) { return nullptr; } - auto *ptr = const_cast<X509_STORE *>(store); - X509_STORE_up_ref(ptr); - return ptr; + return FromOpaque(store)->DupRefInternal(); } void X509_STORE_free(X509_STORE *vfy) { @@ -213,7 +211,7 @@ return 1; } -static int x509_store_add(X509Store *ctx, void *x, int is_crl) { +static int x509_store_add(X509Store *ctx, const void *x, int is_crl) { if (x == nullptr) { return 0; } @@ -225,12 +223,11 @@ if (is_crl) { obj->type = X509_LU_CRL; - obj->data.crl = (X509_CRL *)x; + obj->data.crl = X509_CRL_dup_ref(static_cast<const X509_CRL *>(x)); } else { obj->type = X509_LU_X509; - obj->data.x509 = (X509 *)x; + obj->data.x509 = X509_dup_ref(static_cast<const X509 *>(x)); } - X509_OBJECT_up_ref_count(obj); ctx->objs_lock.LockWrite(); @@ -250,11 +247,11 @@ return ret; } -int X509_STORE_add_cert(X509_STORE *ctx, X509 *x) { +int X509_STORE_add_cert(X509_STORE *ctx, const X509 *x) { return x509_store_add(FromOpaque(ctx), x, /*is_crl=*/0); } -int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x) { +int X509_STORE_add_crl(X509_STORE *ctx, const X509_CRL *x) { return x509_store_add(FromOpaque(ctx), x, /*is_crl=*/1); }
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/x509/x509_mtc.cc b/pkgs/boring/third_party/boringssl/src/crypto/x509/x509_mtc.cc index abbbbb4..1b4a8ae 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/x509/x509_mtc.cc +++ b/pkgs/boring/third_party/boringssl/src/crypto/x509/x509_mtc.cc
@@ -38,17 +38,16 @@ // Prefix for domain separation to denote a Merkle Tree leaf or interior node. constexpr uint8_t kMTCLeafDomainSeparator[] = {0x00}; constexpr uint8_t kMTCNodeDomainSeparator[] = {0x01}; -// DER encoding of AlgorithmIdentifier for alg-mtcProof-draft with absent -// parameters. -// SEQUENCE (12 bytes) { -// OBJECT IDENTIFIER 1.3.6.1.4.1.44363.47.0 (10 bytes) +// DER encoding of AlgorithmIdentifier for alg-mtcProof with absent parameters. +// SEQUENCE (10 bytes) { +// OBJECT IDENTIFIER 1.3.6.1.5.5.7.6.67 (8 bytes) // } constexpr uint8_t kMTCAlgorithmIdentifier[] = { 0x30, // SEQUENCE tag - 12, // tag + len + OID bytes + 10, // tag + len + OID bytes 0x06, // OBJECT tag - 10, // OID length - OBJ_ENC_alg_mtcProof_draft, + 8, // OID length + OBJ_ENC_alg_mtcProof, }; // MTCLogEntryType enum value for tbs_cert_entry. constexpr uint8_t kMTCLogEntryTypeTBSCertEntry[] = {0x00, 0x01}; @@ -64,6 +63,8 @@ '4', '.', '1', '.'}; // DER encoded OID component found in trust anchor IDs for issuance logs. constexpr uint8_t kEncOIDLogs = 0x00; +// draft-ietf-tls-trust-anchor-ids-06 limits trust anchor IDs to 32 bytes. +constexpr size_t kMaxTrustAnchorIdBytes = 32; constexpr CBS_ASN1_TAG kTBSVersionTag = CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0; @@ -88,10 +89,18 @@ // is_mtc_proof returns whether `algor` is an mtcProof AlgorithmIdentifier. bool is_mtc_proof(const X509_ALGOR *algor) { - return OBJ_obj2nid(algor->algorithm) == NID_alg_mtcProof_draft && + return OBJ_obj2nid(algor->algorithm) == NID_alg_mtcProof && algor->parameter == nullptr; } +// is_mtc_serial_valid returns whether `serial` is within +// (mtcMinSerial..mtcMaxSerial), which implies the log number is > 0. +bool is_mtc_serial_valid(uint64_t serial) { + // mtcMinSerial is 2^48. mtcMaxSerial is 2^64-1, the largest number + // representable as uint64_t, so is not checked explicitly. + return serial >> 48; +} + // Returns the first hash value (of size `log_hash_size`) remaining in // `inclusion_proof` and advances `inclusion_proof` past the returned value. // Returns an empty span if there are no more hash values of the appropriate @@ -137,6 +146,7 @@ // MTCCACosigner represents a Merkle Tree CA and its corresponding CA cosigner // (see draft-ietf-plants-merkle-tree-certs, section 5.5). +// Only id-pe-mtcCertificationAuthority-SHA256 is supported. class MTCCACosigner { public: MTCCACosigner() = default; @@ -150,63 +160,59 @@ bool Init(const X509 *x509, const EVP_PKEY *pkey) { // Get and parse the MTCCertificationAuthority extension (see section 5.5). int ext_index = - X509_get_ext_by_NID(x509, NID_pe_mtcCertificationAuthority_draft, -1); + X509_get_ext_by_NID(x509, NID_pe_mtcCertificationAuthority_SHA256, -1); const X509_EXTENSION *ext = X509_get_ext(x509, ext_index); if (ext == nullptr || !X509_EXTENSION_get_critical(ext)) { OPENSSL_PUT_ERROR(X509, X509_R_INVALID_MTC_CA); return false; } const ASN1_STRING *value = X509_EXTENSION_get_data(ext); - CBS ext_value; + CBS ext_value, seq; CBS_init(&ext_value, ASN1_STRING_get0_data(value), ASN1_STRING_length(value)); - - CBS seq, log_hash; - if (!CBS_get_asn1(&ext_value, &seq, CBS_ASN1_SEQUENCE) || // - CBS_len(&ext_value) != 0 || // - !CBS_get_asn1_element(&seq, &log_hash, CBS_ASN1_SEQUENCE) || // - !x509_parse_algorithm(&seq, cosign_sigalg_.get()) || // - !CBS_get_asn1_uint64(&seq, &min_serial_) || // - !CBS_get_asn1_uint64(&seq, &max_serial_) || // + if (!CBS_get_asn1(&ext_value, &seq, CBS_ASN1_SEQUENCE) || // + CBS_len(&ext_value) != 0 || // + !x509_parse_algorithm(&seq, cosign_sigalg_.get()) || // + !CBS_get_asn1_uint64(&seq, &min_serial_) || // + !CBS_get_asn1_uint64(&seq, &max_serial_) || // CBS_len(&seq) != 0) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); return false; } - log_hash_ = EVP_parse_digest_algorithm(&log_hash); - if (log_hash_ == nullptr) { + if (!is_mtc_serial_valid(min_serial_) || + !is_mtc_serial_valid(max_serial_)) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_MTC_CA); return false; } - if (CBS_len(&log_hash) != 0) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); - return false; - } - // Extract the CA ID from the subject (see section 5.1). const X509_NAME *subject = X509_get_subject_name(x509); int tai_index = - X509_NAME_get_index_by_NID(subject, NID_rdna_trustAnchorID_draft, -1); + X509_NAME_get_index_by_NID(subject, NID_rdna_trustAnchorID, -1); if (tai_index < 0 || X509_NAME_entry_count(subject) != 1) { OPENSSL_PUT_ERROR(X509, X509_R_INVALID_MTC_CA); return false; } - // For initial experimentation, the attribute's value is a UTF8String - // containing the trust anchor ID's ASCII representation. - const ASN1_STRING *tai_ascii = + const ASN1_STRING *tai = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject, tai_index)); - if (ASN1_STRING_type(tai_ascii) != V_ASN1_UTF8STRING) { + // RELATIVE-OID has no dedicated ASN1_STRING representation, so the value + // is stored as V_ASN1_OTHER containing the entire element. + if (ASN1_STRING_type(tai) != V_ASN1_OTHER) { OPENSSL_PUT_ERROR(X509, X509_R_WRONG_TYPE); return false; } - std::string_view tai_ascii_str = BytesAsStringView( - Span(ASN1_STRING_get0_data(tai_ascii), ASN1_STRING_length(tai_ascii))); - ScopedCBB ca_id_enc; - if (!CBB_init(ca_id_enc.get(), 64) || - !CBB_add_asn1_relative_oid_from_text( - ca_id_enc.get(), tai_ascii_str.data(), tai_ascii_str.size())) { + CBS tai_elem, tai_relative_oid; + CBS_init(&tai_elem, ASN1_STRING_get0_data(tai), ASN1_STRING_length(tai)); + if (!CBS_get_asn1(&tai_elem, &tai_relative_oid, CBS_ASN1_RELATIVE_OID) || + CBS_len(&tai_elem) != 0 || + !CBS_is_valid_asn1_relative_oid(&tai_relative_oid)) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING); return false; } - if (!CBBFinishArray(ca_id_enc.get(), &ca_id_enc_oid_)) { + if (CBS_len(&tai_relative_oid) > kMaxTrustAnchorIdBytes) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_MTC_CA); + return false; + } + if (!ca_id_enc_oid_.CopyFrom(tai_relative_oid)) { OPENSSL_PUT_ERROR(X509, ERR_R_INTERNAL_ERROR); return false; } @@ -216,7 +222,9 @@ } bool IsSerialInRange(uint64_t serial) const { - return min_serial_ <= serial && serial <= max_serial_; + bool ok = min_serial_ <= serial && serial <= max_serial_; + assert(!ok || is_mtc_serial_valid(serial)); + return ok; } // Constructs CosignedMessage and computes signature. @@ -249,7 +257,7 @@ return trust_anchor_id == ca_id_enc_oid_; } - const EVP_MD *log_hash() const { return log_hash_; } + const EVP_MD *log_hash() const { return EVP_sha256(); } private: // WriteTaiAscii concatenates the trust anchor ID prefix with the CA ID as a @@ -257,9 +265,9 @@ // OID components from `oid_suffix`, and writes the ASCII string // representation of the full trust anchor ID to `out`. bool WriteTaiAscii(CBB *out, Span<const uint64_t> oid_suffix = {}) const { - // Trust anchor IDs are constrained to 256 bytes by spec (and are typically - // much shorter). - uint8_t id[256]; + // Trust anchor IDs such as the CA ID are limited to 32 bytes by spec, but + // `oid_suffix` may add additional bytes. + uint8_t id[2 * kMaxTrustAnchorIdBytes]; CBB id_cbb; if (!CBB_init_fixed(&id_cbb, id, sizeof(id)) || !CBB_add_bytes(&id_cbb, ca_id_enc_oid_.data(), ca_id_enc_oid_.size())) { @@ -302,21 +310,20 @@ // 5.1 and 5.4), in the form of a DER-encoded relative OID. This does not // include any framing, only the element's contents. Array<uint8_t> ca_id_enc_oid_; - // Log hash algorithm. - const EVP_MD *log_hash_ = nullptr; // Public key of the CA cosigner. UniquePtr<EVP_PKEY> cosign_pubkey_; // Signature algorithm for CA cosigner signatures. ScopedX509Algor cosign_sigalg_; - // Min and max allowed serial number, (0..2^64-1). + // Min and max allowed serial number, both (2^48 .. 2^64-1). uint64_t min_serial_ = 0u; uint64_t max_serial_ = 0u; }; } // namespace +// Only id-pe-mtcCertificationAuthority-SHA256 is supported. bool x509_is_merkle_tree_ca(const X509 *x509) { - return X509_get_ext_by_NID(x509, NID_pe_mtcCertificationAuthority_draft, + return X509_get_ext_by_NID(x509, NID_pe_mtcCertificationAuthority_SHA256, -1) >= 0; } @@ -421,7 +428,7 @@ !CBS_get_u48(&mtc_proof, &subtree_start) || !CBS_get_u48(&mtc_proof, &subtree_end) || !CBS_get_u16_length_prefixed(&mtc_proof, &inclusion_proof) || - !CBS_get_u16_length_prefixed(&mtc_proof, &signatures) || + !CBS_get_u24_length_prefixed(&mtc_proof, &signatures) || CBS_len(&mtc_proof) != 0) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); return 0; @@ -497,12 +504,9 @@ return 0; } // `index` is the least significant 48 bits of `serial`. - uint64_t index = serial & ((uint64_t{1} << 48) - 1); - uint64_t log_number = serial >> 48; - if (log_number == 0) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PARAMETER); - return 0; - } + const uint64_t index = serial & ((uint64_t{1} << 48) - 1); + const uint64_t log_number = serial >> 48; + assert(is_mtc_serial_valid(serial)); // The TBSCertificate's `signature` field must match the expected MTC // signature algorithm identifier.
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/x509/x509_set.cc b/pkgs/boring/third_party/boringssl/src/crypto/x509/x509_set.cc index ae45063..2ede541 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/x509/x509_set.cc +++ b/pkgs/boring/third_party/boringssl/src/crypto/x509/x509_set.cc
@@ -143,7 +143,7 @@ } } -int X509_set_pubkey(X509 *x, EVP_PKEY *pkey) { +int X509_set_pubkey(X509 *x, const EVP_PKEY *pkey) { if (x == nullptr) { return 0; }
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/x509/x509_vfy.cc b/pkgs/boring/third_party/boringssl/src/crypto/x509/x509_vfy.cc index 6ceaed3..d291f54 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/x509/x509_vfy.cc +++ b/pkgs/boring/third_party/boringssl/src/crypto/x509/x509_vfy.cc
@@ -59,6 +59,14 @@ // CRL issuer matches CRL AKID #define CRL_SCORE_AKID 0x004 +namespace { +struct CRLInfo { + UniquePtr<X509_CRL> crl; + X509 *issuer = nullptr; + int score = 0; +}; +} // namespace + static int null_callback(int ok, X509_STORE_CTX *e); static X509 *find_issuer(X509_STORE_CTX *ctx, const STACK_OF(X509) *sk, const X509 *x); @@ -67,20 +75,22 @@ static int check_id(X509_STORE_CTX *ctx); static int check_trust(X509_STORE_CTX *ctx); static int check_revocation(X509_STORE_CTX *ctx); -static int check_cert(X509_STORE_CTX *ctx); +static int check_revocation_for_cert(X509_STORE_CTX *ctx, int depth); static int check_policy(X509_STORE_CTX *ctx); static UniquePtr<X509> get_trusted_issuer(X509_STORE_CTX *ctx, const X509 *x); -static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer, X509_CRL *crl, - X509 *x); -static int get_crl(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509 *x); -static int crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, X509 **pissuer, - int *pcrl_score); -static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score); -static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl); -static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); +static int get_crl_score(X509_STORE_CTX *ctx, X509 **out_issuer, + const X509_CRL *crl, const X509 *x, int depth); +static int get_crl(X509_STORE_CTX *ctx, CRLInfo *out_crl_info, const X509 *x, + int depth); +static int crl_akid_check(X509_STORE_CTX *ctx, const X509_CRL *crl, + X509 **out_issuer, int *out_crl_score, int depth); +static int crl_crldp_check(const X509 *x, const X509_CRL *crl, int crl_score); +static int check_crl(X509_STORE_CTX *ctx, const CRLInfo &crl_info, int depth); +static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, const X509 *x, + int depth); -static int internal_verify(X509_STORE_CTX *ctx); +static int check_chain_signatures_and_time(X509_STORE_CTX *ctx); static int null_callback(int ok, X509_STORE_CTX *e) { return ok; } @@ -107,6 +117,14 @@ return ok; } +// TODO(crbug.com/42290549): Switch remaining `call_verify_cb` calls to this +// function. +static int call_verify_cb_at_depth(int ok, X509_STORE_CTX *ctx, int depth) { + ctx->current_cert = sk_X509_value(ctx->chain, depth); + ctx->error_depth = depth; + return call_verify_cb(ok, ctx); +} + // Given a certificate try and find an exact match in the store static UniquePtr<X509> lookup_cert_match(X509_STORE_CTX *ctx, const X509 *x) { // Lookup all certs with matching subject name @@ -253,10 +271,8 @@ UniquePtr<X509> issuer = get_trusted_issuer(ctx, last); if (issuer == nullptr || X509_cmp(last, issuer.get()) != 0) { ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; - ctx->current_cert = last; - ctx->error_depth = num - 1; bad_chain = 1; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, num - 1)) { return 0; } } else { @@ -322,7 +338,6 @@ } else { ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT; } - ctx->current_cert = last; } else { if (!PushToStack(ctx->chain, std::move(chain_ss))) { ctx->error = X509_V_ERR_OUT_OF_MEM; @@ -330,13 +345,11 @@ } num++; ctx->last_untrusted = num; - ctx->current_cert = sk_X509_last(ctx->chain); ctx->error = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN; } - ctx->error_depth = num - 1; bad_chain = 1; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, num - 1)) { return 0; } } @@ -346,8 +359,8 @@ !check_id(ctx) || // We check revocation status after copying parameters because they may // be needed for CRL signature verification. - !check_revocation(ctx) || // - !internal_verify(ctx) || // + !check_revocation(ctx) || // + !check_chain_signatures_and_time(ctx) || // !check_name_constraints(ctx) || // TODO(davidben): Does `check_policy` still need to be conditioned on // |!bad_chain|? DoS concerns have been resolved. @@ -414,9 +427,7 @@ if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) && (x->ex_flags & EXFLAG_CRITICAL)) { ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION; - ctx->error_depth = i; - ctx->current_cert = x; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, i)) { return 0; } } @@ -424,18 +435,14 @@ int must_be_ca = i > 0; if (must_be_ca && !X509_check_ca(x)) { ctx->error = X509_V_ERR_INVALID_CA; - ctx->error_depth = i; - ctx->current_cert = x; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, i)) { return 0; } } if (ctx->param->purpose > 0 && X509_check_purpose(x, purpose, must_be_ca) != 1) { ctx->error = X509_V_ERR_INVALID_PURPOSE; - ctx->error_depth = i; - ctx->current_cert = x; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, i)) { return 0; } } @@ -450,9 +457,7 @@ // considered - they are just not counted as part of the path length! if (i > 1 && x->ex_pathlen != -1 && plen > x->ex_pathlen + 1) { ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED; - ctx->error_depth = i; - ctx->current_cert = x; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, i)) { return 0; } } @@ -521,9 +526,7 @@ return 0; default: ctx->error = rv; - ctx->error_depth = i; - ctx->current_cert = x; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, i)) { return 0; } break; @@ -553,9 +556,7 @@ return 0; default: ctx->error = rv; - ctx->error_depth = 0; - ctx->current_cert = leaf; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, /*depth=*/0)) { return 0; } break; @@ -567,9 +568,7 @@ static int check_id_error(X509_STORE_CTX *ctx, int errcode) { ctx->error = errcode; - ctx->current_cert = ctx->cert; - ctx->error_depth = 0; - return call_verify_cb(0, ctx); + return call_verify_cb_at_depth(0, ctx, /*depth=*/0); } static int check_hosts(X509 *x, X509_VERIFY_PARAM *param) { @@ -624,10 +623,8 @@ // If explicitly rejected notify callback and reject if not // overridden. if (trust == X509_TRUST_REJECTED) { - ctx->error_depth = (int)i; - ctx->current_cert = x; ctx->error = X509_V_ERR_CERT_REJECTED; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, static_cast<int>(i))) { return X509_TRUST_REJECTED; } } @@ -664,58 +661,36 @@ last = 0; } for (int i = 0; i <= last; i++) { - ctx->error_depth = i; - if (!check_cert(ctx)) { + if (!check_revocation_for_cert(ctx, i)) { return 0; } } return 1; } -static int check_cert(X509_STORE_CTX *ctx) { - X509_CRL *crl = nullptr; - int ok = 0, cnum = ctx->error_depth; - X509 *x = sk_X509_value(ctx->chain, cnum); - ctx->current_cert = x; - ctx->current_crl_issuer = nullptr; - ctx->current_crl_score = 0; - - // Try to retrieve the relevant CRL. Note that `get_crl` sets - // `current_crl_issuer` and `current_crl_score`, which `check_crl` then reads. - // - // TODO(davidben): The awkward internal calling convention is a historical - // artifact of when these functions were user-overridable callbacks, even - // though there was no way to set them correctly. These callbacks have since - // been removed, so we can pass input and output parameters more directly. - if (!get_crl(ctx, &crl, x)) { +static int check_revocation_for_cert(X509_STORE_CTX *ctx, int depth) { + X509 *x = sk_X509_value(ctx->chain, depth); + CRLInfo crl_info; + if (!get_crl(ctx, &crl_info, x, depth)) { ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL; - ok = call_verify_cb(0, ctx); - goto err; + return call_verify_cb_at_depth(0, ctx, depth); } - ctx->current_crl = crl; - if (!check_crl(ctx, crl) || // - !cert_crl(ctx, crl, x)) { - goto err; + if (!check_crl(ctx, crl_info, depth) || // + !cert_crl(ctx, crl_info.crl.get(), x, depth)) { + return 0; } - ok = 1; - -err: - X509_CRL_free(crl); - ctx->current_crl = nullptr; - return ok; + return 1; } // Check CRL times against values in X509_STORE_CTX -static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify) { +static int check_crl_time(X509_STORE_CTX *ctx, const X509_CRL *crl, bool notify, + int depth) { if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) { return 1; } - if (notify) { - ctx->current_crl = crl; - } int64_t ptime; if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) { ptime = ctx->param->check_time; @@ -729,7 +704,7 @@ return 0; } ctx->error = X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, depth)) { return 0; } } @@ -739,7 +714,7 @@ return 0; } ctx->error = X509_V_ERR_CRL_NOT_YET_VALID; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, depth)) { return 0; } } @@ -752,7 +727,7 @@ return 0; } ctx->error = X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, depth)) { return 0; } } @@ -761,36 +736,27 @@ return 0; } ctx->error = X509_V_ERR_CRL_HAS_EXPIRED; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, depth)) { return 0; } } } - if (notify) { - ctx->current_crl = nullptr; - } - return 1; } -static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509 **pissuer, - int *pscore, STACK_OF(X509_CRL) *crls) { - int crl_score, best_score = *pscore; - X509 *x = ctx->current_cert; - X509_CRL *best_crl = nullptr; - X509 *crl_issuer = nullptr, *best_crl_issuer = nullptr; - - for (size_t i = 0; i < sk_X509_CRL_num(crls); i++) { - X509_CRL *crl = sk_X509_CRL_value(crls, i); - crl_score = get_crl_score(ctx, &crl_issuer, crl, x); - if (crl_score < best_score || crl_score == 0) { +static int get_crl_sk(X509_STORE_CTX *ctx, CRLInfo *best, + STACK_OF(X509_CRL) *crls, const X509 *x, int depth) { + for (X509_CRL *crl : crls) { + X509 *crl_issuer = nullptr; + int crl_score = get_crl_score(ctx, &crl_issuer, crl, x, depth); + if (crl_score < best->score || crl_score == 0) { continue; } // If current CRL is equivalent use it if it is newer - if (crl_score == best_score && best_crl != nullptr) { + if (crl_score == best->score && best->crl != nullptr) { int day, sec; - if (ASN1_TIME_diff(&day, &sec, X509_CRL_get0_lastUpdate(best_crl), + if (ASN1_TIME_diff(&day, &sec, X509_CRL_get0_lastUpdate(best->crl.get()), X509_CRL_get0_lastUpdate(crl)) == 0) { continue; } @@ -800,33 +766,19 @@ continue; } } - best_crl = crl; - best_crl_issuer = crl_issuer; - best_score = crl_score; + best->crl = UpRef(crl); + best->issuer = crl_issuer; + best->score = crl_score; } - if (best_crl) { - if (*pcrl) { - X509_CRL_free(*pcrl); - } - *pcrl = best_crl; - *pissuer = best_crl_issuer; - *pscore = best_score; - X509_CRL_up_ref(best_crl); - } - - if (best_score >= CRL_SCORE_VALID) { - return 1; - } - - return 0; + return best->score >= CRL_SCORE_VALID; } // For a given CRL return how suitable it is for the supplied certificate // 'x'. The return value is a mask of several criteria. If the issuer is not // the certificate issuer this is returned in *pissuer. -static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer, X509_CRL *crl, - X509 *x) { +static int get_crl_score(X509_STORE_CTX *ctx, X509 **out_issuer, + const X509_CRL *crl, const X509 *x, int depth) { if (crl->idp) { // Per RFC 5280, section 5.2.5, at most one of onlyContainsUserCerts, // onlyContainsCACerts, and onlyContainsAttributeCerts may be true. @@ -854,12 +806,12 @@ } // Check expiry - if (check_crl_time(ctx, crl, 0)) { + if (check_crl_time(ctx, crl, /*notify=*/false, depth)) { crl_score |= CRL_SCORE_TIME; } // Check authority key ID and locate certificate issuer - if (!crl_akid_check(ctx, crl, pissuer, &crl_score)) { + if (!crl_akid_check(ctx, crl, out_issuer, &crl_score, depth)) { // If we can't locate certificate issuer at this point forget it return 0; } @@ -872,32 +824,28 @@ return crl_score; } -static int crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, X509 **pissuer, - int *pcrl_score) { - X509 *crl_issuer = nullptr; - X509_NAME *cnm = X509_CRL_get_issuer(crl); - int cidx = ctx->error_depth; - - if ((size_t)cidx != sk_X509_num(ctx->chain) - 1) { - cidx++; +static int crl_akid_check(X509_STORE_CTX *ctx, const X509_CRL *crl, + X509 **out_issuer, int *out_crl_score, int depth) { + const X509_NAME *cnm = X509_CRL_get_issuer(crl); + if ((size_t)depth != sk_X509_num(ctx->chain) - 1) { + depth++; } - crl_issuer = sk_X509_value(ctx->chain, cidx); - + X509 *crl_issuer = sk_X509_value(ctx->chain, depth); if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) { - *pcrl_score |= CRL_SCORE_AKID | CRL_SCORE_ISSUER_CERT; - *pissuer = crl_issuer; + *out_crl_score |= CRL_SCORE_AKID | CRL_SCORE_ISSUER_CERT; + *out_issuer = crl_issuer; return 1; } - for (cidx++; cidx < (int)sk_X509_num(ctx->chain); cidx++) { - crl_issuer = sk_X509_value(ctx->chain, cidx); + for (depth++; depth < (int)sk_X509_num(ctx->chain); depth++) { + crl_issuer = sk_X509_value(ctx->chain, depth); if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm)) { continue; } if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) { - *pcrl_score |= CRL_SCORE_AKID | CRL_SCORE_SAME_PATH; - *pissuer = crl_issuer; + *out_crl_score |= CRL_SCORE_AKID | CRL_SCORE_SAME_PATH; + *out_issuer = crl_issuer; return 1; } } @@ -939,7 +887,7 @@ } // Check CRLDP and IDP -static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score) { +static int crl_crldp_check(const X509 *x, const X509_CRL *crl, int crl_score) { auto *impl = FromOpaque(x); if (impl->ex_flags & EXFLAG_CA) { if (crl->idp && crl->idp->onlyuser) { @@ -979,33 +927,22 @@ } // Retrieve CRL corresponding to current certificate. -static int get_crl(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509 *x) { - X509 *issuer = nullptr; - int crl_score = 0; - X509_CRL *crl = nullptr; - STACK_OF(X509_CRL) *skcrl = nullptr; - if (get_crl_sk(ctx, &crl, &issuer, &crl_score, ctx->crls)) { - goto done; +static int get_crl(X509_STORE_CTX *ctx, CRLInfo *out_crl_info, const X509 *x, + int depth) { + CRLInfo best; + if (!get_crl_sk(ctx, &best, ctx->crls, x, depth)) { + // If we haven't yet found a CRL with sufficiently high score, lookup CRLs + // from the store. + UniquePtr<STACK_OF(X509_CRL)> skcrl( + X509_STORE_CTX_get1_crls(ctx, X509_get_issuer_name(x))); + if (skcrl) { + get_crl_sk(ctx, &best, skcrl.get(), x, depth); + } } - // Lookup CRLs from store - skcrl = X509_STORE_CTX_get1_crls(ctx, X509_get_issuer_name(x)); - - // If no CRLs found and a near match from get_crl_sk use that - if (!skcrl && crl) { - goto done; - } - - get_crl_sk(ctx, &crl, &issuer, &crl_score, skcrl); - - sk_X509_CRL_pop_free(skcrl, X509_CRL_free); - -done: // If we got any kind of CRL use it and return success - if (crl) { - ctx->current_crl_issuer = issuer; - ctx->current_crl_score = crl_score; - *pcrl = crl; + if (best.crl) { + *out_crl_info = std::move(best); return 1; } @@ -1013,22 +950,22 @@ } // Check CRL validity -static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) { - X509Impl *issuer = nullptr; - int cnum = ctx->error_depth; - int chnum = (int)sk_X509_num(ctx->chain) - 1; +static int check_crl(X509_STORE_CTX *ctx, const CRLInfo &crl_info, int depth) { + X509_CRL *crl = crl_info.crl.get(); + int root_depth = (int)sk_X509_num(ctx->chain) - 1; // If we have an alternative CRL issuer cert use that. Otherwise, it is the // issuer of the current certificate. - if (ctx->current_crl_issuer) { - issuer = FromOpaque(ctx->current_crl_issuer); - } else if (cnum < chnum) { - issuer = FromOpaque(sk_X509_value(ctx->chain, cnum + 1)); + X509Impl *issuer = nullptr; + if (crl_info.issuer) { + issuer = FromOpaque(crl_info.issuer); + } else if (depth < root_depth) { + issuer = FromOpaque(sk_X509_value(ctx->chain, depth + 1)); } else { - issuer = FromOpaque(sk_X509_value(ctx->chain, chnum)); + issuer = FromOpaque(sk_X509_value(ctx->chain, root_depth)); // If not self signed, can't check signature if (!x509_check_issued_with_callback(ctx, issuer, issuer)) { ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, depth)) { return 0; } } @@ -1039,20 +976,20 @@ if ((issuer->ex_flags & EXFLAG_KUSAGE) && !(issuer->ex_kusage & X509v3_KU_CRL_SIGN)) { ctx->error = X509_V_ERR_KEYUSAGE_NO_CRL_SIGN; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, depth)) { return 0; } } - if (!(ctx->current_crl_score & CRL_SCORE_SCOPE)) { + if (!(crl_info.score & CRL_SCORE_SCOPE)) { ctx->error = X509_V_ERR_DIFFERENT_CRL_SCOPE; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, depth)) { return 0; } } - if (!(ctx->current_crl_score & CRL_SCORE_TIME)) { - if (!check_crl_time(ctx, crl, 1)) { + if (!(crl_info.score & CRL_SCORE_TIME)) { + if (!check_crl_time(ctx, crl, /*notify=*/true, depth)) { return 0; } } @@ -1061,14 +998,14 @@ EVP_PKEY *ikey = X509_get0_pubkey(issuer); if (!ikey) { ctx->error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, depth)) { return 0; } } else { // Verify CRL signature if (X509_CRL_verify(crl, ikey) <= 0) { ctx->error = X509_V_ERR_CRL_SIGNATURE_FAILURE; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, depth)) { return 0; } } @@ -1079,7 +1016,8 @@ } // Check certificate against CRL -static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x) { +static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, const X509 *x, + int depth) { // The rules changed for this... previously if a CRL contained unhandled // critical extensions it could still be used to indicate a certificate // was revoked. This has since been changed since critical extension can @@ -1087,7 +1025,7 @@ if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) && (crl->flags & EXFLAG_CRITICAL)) { ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, depth)) { return 0; } } @@ -1095,7 +1033,7 @@ X509_REVOKED *rev; if (X509_CRL_get0_by_cert(crl, &rev, x)) { ctx->error = X509_V_ERR_CERT_REVOKED; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, depth)) { return 0; } } @@ -1104,22 +1042,21 @@ } static int check_policy(X509_STORE_CTX *ctx) { - X509 *current_cert = nullptr; + int error_depth; int ret = X509_policy_check(ctx->chain, ctx->param->policies, - ctx->param->flags, ¤t_cert); + ctx->param->flags, &error_depth); if (ret != X509_V_OK) { - ctx->current_cert = current_cert; ctx->error = ret; if (ret == X509_V_ERR_OUT_OF_MEM) { return 0; } - return call_verify_cb(0, ctx); + return call_verify_cb_at_depth(0, ctx, error_depth); } return 1; } -static int check_cert_time(X509_STORE_CTX *ctx, X509 *x) { +static int check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth) { if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) { return 1; } @@ -1136,16 +1073,14 @@ : X509_cmp_time_posix(X509_get_notBefore(x), ptime); if (i == 0) { ctx->error = X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD; - ctx->current_cert = x; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, depth)) { return 0; } } if (i > 0) { ctx->error = X509_V_ERR_CERT_NOT_YET_VALID; - ctx->current_cert = x; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, depth)) { return 0; } } @@ -1155,16 +1090,14 @@ : X509_cmp_time_posix(X509_get_notAfter(x), ptime); if (i == 0) { ctx->error = X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD; - ctx->current_cert = x; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, depth)) { return 0; } } if (i < 0) { ctx->error = X509_V_ERR_CERT_HAS_EXPIRED; - ctx->current_cert = x; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, depth)) { return 0; } } @@ -1173,9 +1106,14 @@ } static int verify_signature(X509_STORE_CTX *ctx, const X509 *x509, - const X509 *issuer, EVP_PKEY *pkey) { + const X509 *issuer) { + EVP_PKEY *pkey = X509_get0_pubkey(issuer); + if (pkey == nullptr) { + return X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY; + } + int ret; - if ((ctx->param->flags & X509_V_FLAG_USE_MTC_DRAFT_PLANTS_05) && + if ((ctx->param->flags & X509_V_FLAG_USE_MTC_DRAFT_PLANTS_07) && x509_is_merkle_tree_ca(issuer)) { ret = x509_verify_mtc(x509, pkey, issuer); } else { @@ -1184,73 +1122,28 @@ return ret ? X509_V_OK : X509_V_ERR_CERT_SIGNATURE_FAILURE; } -static int internal_verify(X509_STORE_CTX *ctx) { - // TODO(davidben): This logic is incredibly confusing. Rewrite this: - // - // First, don't allow the verify callback to suppress - // X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY, which will simplify the - // signature check. Then replace jumping into the middle of the loop. It's - // trying to ensure that all certificates see `check_cert_time`, then checking - // the root's self signature when requested, but not breaking partial chains - // in the process. - int n = (int)sk_X509_num(ctx->chain); - ctx->error_depth = n - 1; - n--; - X509 *xi = sk_X509_value(ctx->chain, n); - X509 *xs; - if (x509_check_issued_with_callback(ctx, xi, xi)) { - xs = xi; - } else { - if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) { - xs = xi; - goto check_cert; - } - if (n <= 0) { - ctx->error = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; - ctx->current_cert = xi; - return call_verify_cb(0, ctx); - } - n--; - ctx->error_depth = n; - xs = sk_X509_value(ctx->chain, n); - } - - // ctx->error=0; not needed - while (n >= 0) { - ctx->error_depth = n; - - // Skip signature check for self signed certificates unless - // explicitly asked for. It doesn't add any security and just wastes - // time. - if (xs != xi || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE)) { - EVP_PKEY *pkey = X509_get0_pubkey(xi); - int err = pkey == nullptr ? X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY - : verify_signature(ctx, xs, xi, pkey); - if (err != X509_V_OK) { +static int check_chain_signatures_and_time(X509_STORE_CTX *ctx) { + size_t num = sk_X509_num(ctx->chain); + for (size_t i = num - 1; i < num; i--) { + X509 *x509 = sk_X509_value(ctx->chain, i); + if (i < num - 1) { + X509 *issuer = sk_X509_value(ctx->chain, i + 1); + if (int err = verify_signature(ctx, x509, issuer); err != X509_V_OK) { ctx->error = err; - ctx->current_cert = xs; - if (!call_verify_cb(0, ctx)) { + if (!call_verify_cb_at_depth(0, ctx, static_cast<int>(i))) { return 0; } } } - check_cert: - if (!check_cert_time(ctx, xs)) { + if (!check_cert_time(ctx, x509, static_cast<int>(i))) { return 0; } // The last error (if any) is still in the error value - ctx->current_cert = xs; - if (!call_verify_cb(1, ctx)) { + if (!call_verify_cb_at_depth(1, ctx, static_cast<int>(i))) { return 0; } - - n--; - if (n >= 0) { - xi = xs; - xs = sk_X509_value(ctx->chain, n); - } } return 1; @@ -1348,10 +1241,6 @@ return X509_chain_up_ref(ctx->chain); } -X509_CRL *X509_STORE_CTX_get0_current_crl(const X509_STORE_CTX *ctx) { - return ctx->current_crl; -} - X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(const X509_STORE_CTX *ctx) { // In OpenSSL, an `X509_STORE_CTX` sometimes has a parent context during CRL // path validation for indirect CRLs. We require the CRL to be issued
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/x509/x509cset.cc b/pkgs/boring/third_party/boringssl/src/crypto/x509/x509cset.cc index 19e938a..5ece53d 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/x509/x509cset.cc +++ b/pkgs/boring/third_party/boringssl/src/crypto/x509/x509cset.cc
@@ -103,6 +103,15 @@ return 1; } +X509_CRL *X509_CRL_dup_ref(const X509_CRL *crl) { + if (crl == nullptr) { + return nullptr; + } + auto *ptr = const_cast<X509_CRL *>(crl); + CRYPTO_refcount_inc(&ptr->references); + return ptr; +} + long X509_CRL_get_version(const X509_CRL *crl) { return ASN1_INTEGER_get(crl->crl->version); }
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/x509/x_pubkey.cc b/pkgs/boring/third_party/boringssl/src/crypto/x509/x_pubkey.cc index 4862f1f..3d59a1e 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/x509/x_pubkey.cc +++ b/pkgs/boring/third_party/boringssl/src/crypto/x509/x_pubkey.cc
@@ -118,7 +118,7 @@ BSSL_NAMESPACE_END -int bssl::x509_pubkey_set1(X509_PUBKEY *key, EVP_PKEY *pkey) { +int bssl::x509_pubkey_set1(X509_PUBKEY *key, const EVP_PKEY *pkey) { ScopedCBB cbb; if (!CBB_init(cbb.get(), 64) || !EVP_marshal_public_key(cbb.get(), pkey)) { OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_ENCODE_ERROR);
diff --git a/pkgs/boring/third_party/boringssl/src/crypto/x509/x_x509.cc b/pkgs/boring/third_party/boringssl/src/crypto/x509/x_x509.cc index 413c40f..a2f1f1d 100644 --- a/pkgs/boring/third_party/boringssl/src/crypto/x509/x_x509.cc +++ b/pkgs/boring/third_party/boringssl/src/crypto/x509/x_x509.cc
@@ -328,10 +328,10 @@ } X509 *X509_dup_ref(const X509 *x) { - auto *x_ref = const_cast<X509 *>(x); - // We know that this call always returns one. - X509_up_ref(x_ref); - return x_ref; + if (x == nullptr) { + return nullptr; + } + return FromOpaque(x)->DupRefInternal(); } int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused,
diff --git a/pkgs/boring/third_party/boringssl/src/include/openssl/asn1.h b/pkgs/boring/third_party/boringssl/src/include/openssl/asn1.h index f92153d..2882a25 100644 --- a/pkgs/boring/third_party/boringssl/src/include/openssl/asn1.h +++ b/pkgs/boring/third_party/boringssl/src/include/openssl/asn1.h
@@ -517,23 +517,12 @@ OPENSSL_EXPORT const unsigned char *ASN1_STRING_get0_data( const ASN1_STRING *str); -// ASN1_STRING_data returns a mutable pointer to `str`'s contents. Callers -// should use `ASN1_STRING_length` to determine the length of the string. The -// string may have embedded NUL bytes and may not be NUL-terminated. +// ASN1_STRING_get_length returns the length of `str`, in bytes. // // The contents of an `ASN1_STRING` encode the value in some type-specific // representation that does not always correspond to the DER encoding of the // type. See the documentation for `ASN1_STRING` for details. -// -// Prefer `ASN1_STRING_get0_data`. -OPENSSL_EXPORT unsigned char *ASN1_STRING_data(ASN1_STRING *str); - -// ASN1_STRING_length returns the length of `str`, in bytes. -// -// The contents of an `ASN1_STRING` encode the value in some type-specific -// representation that does not always correspond to the DER encoding of the -// type. See the documentation for `ASN1_STRING` for details. -OPENSSL_EXPORT int ASN1_STRING_length(const ASN1_STRING *str); +OPENSSL_EXPORT size_t ASN1_STRING_get_length(const ASN1_STRING *str); // ASN1_STRING_cmp compares `a` and `b`'s type and contents. It returns an // integer equal to, less than, or greater than zero if `a` is equal to, less @@ -1810,6 +1799,25 @@ // ASN1_STRING_TABLE_cleanup does nothing. OPENSSL_EXPORT void ASN1_STRING_TABLE_cleanup(void); +// ASN1_STRING_data returns a mutable pointer to `str`'s contents. Callers +// should use `ASN1_STRING_length` to determine the length of the string. The +// string may have embedded NUL bytes and may not be NUL-terminated. +// +// The contents of an `ASN1_STRING` encode the value in some type-specific +// representation that does not always correspond to the DER encoding of the +// type. See the documentation for `ASN1_STRING` for details. +// +// Prefer `ASN1_STRING_get0_data`. See crbug.com/574019297. +OPENSSL_EXPORT unsigned char *ASN1_STRING_data(ASN1_STRING *str); + +// ASN1_STRING_length returns the length of `str`, in bytes. Prefer +// `ASN1_STRING_get_length`. +// +// The contents of an `ASN1_STRING` encode the value in some type-specific +// representation that does not always correspond to the DER encoding of the +// type. See the documentation for `ASN1_STRING` for details. +OPENSSL_EXPORT int ASN1_STRING_length(const ASN1_STRING *str); + // M_ASN1_* are legacy aliases for various `ASN1_STRING` functions. Use the // functions themselves. #define M_ASN1_STRING_length(x) ASN1_STRING_length(x)
diff --git a/pkgs/boring/third_party/boringssl/src/include/openssl/base.h b/pkgs/boring/third_party/boringssl/src/include/openssl/base.h index cb63423..e2741eb 100644 --- a/pkgs/boring/third_party/boringssl/src/include/openssl/base.h +++ b/pkgs/boring/third_party/boringssl/src/include/openssl/base.h
@@ -73,7 +73,7 @@ // A consumer may use this symbol in the preprocessor to temporarily build // against multiple revisions of BoringSSL at the same time. It is not // recommended to do so for longer than is necessary. -#define BORINGSSL_API_VERSION 43 +#define BORINGSSL_API_VERSION 44 #if defined(BORINGSSL_SHARED_LIBRARY) @@ -395,7 +395,7 @@ #if defined(BORINGSSL_NO_CXX) #define BORINGSSL_MAKE_DELETER(type, deleter) -#define BORINGSSL_MAKE_UP_REF(type, up_ref_func) +#define BORINGSSL_MAKE_UP_REF(type, dup_ref_func) #define BORINGSSL_MAKE_STACK_TRAITS(type, init_func, cleanup_func) #define BORINGSSL_MAKE_STACK_TRAITS_MOVABLE(type, init_func, cleanup_func, \ move_func) @@ -527,12 +527,9 @@ template <typename T> using UniquePtr = std::unique_ptr<T, internal::Deleter>; -#define BORINGSSL_MAKE_UP_REF(type, up_ref_func) \ - inline UniquePtr<type> UpRef(type *v) { \ - if (v != nullptr) { \ - up_ref_func(v); \ - } \ - return UniquePtr<type>(v); \ +#define BORINGSSL_MAKE_UP_REF(type, dup_ref_func) \ + inline UniquePtr<type> UpRef(const type *v) { \ + return UniquePtr<type>(dup_ref_func(v)); \ } \ \ inline UniquePtr<type> UpRef(const UniquePtr<type> &ptr) { \
diff --git a/pkgs/boring/third_party/boringssl/src/include/openssl/bio.h b/pkgs/boring/third_party/boringssl/src/include/openssl/bio.h index 630be3e..48ee4ae 100644 --- a/pkgs/boring/third_party/boringssl/src/include/openssl/bio.h +++ b/pkgs/boring/third_party/boringssl/src/include/openssl/bio.h
@@ -15,7 +15,7 @@ #ifndef OPENSSL_HEADER_BIO_H #define OPENSSL_HEADER_BIO_H -#include <openssl/base.h> // IWYU pragma: export +#include <openssl/base.h> // IWYU pragma: export #include <stdio.h> // For FILE @@ -65,6 +65,10 @@ // BIO_up_ref increments the reference count of `bio` and returns one. OPENSSL_EXPORT int BIO_up_ref(BIO *bio); +// BIO_dup_ref increments the reference count of `bio` and returns the same +// handle. +OPENSSL_EXPORT BIO *BIO_dup_ref(const BIO *bio); + // Basic I/O. @@ -613,18 +617,20 @@ #define BIO_CTRL_DGRAM_QUERY_MTU 40 // as kernel for current MTU -#define BIO_CTRL_DGRAM_SET_MTU 42 /* set cached value for MTU. want to use - this if asking the kernel fails */ +#define BIO_CTRL_DGRAM_SET_MTU \ + 42 /* set cached value for MTU. want to use \ + this if asking the kernel fails */ -#define BIO_CTRL_DGRAM_MTU_EXCEEDED 43 /* check whether the MTU was exceed in - the previous write operation. */ +#define BIO_CTRL_DGRAM_MTU_EXCEEDED \ + 43 /* check whether the MTU was exceed in \ + the previous write operation. */ // BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT is unsupported as it is unused by consumers // and depends on `timeval`, which is not 2038-clean on all platforms. -#define BIO_CTRL_DGRAM_GET_PEER 46 +#define BIO_CTRL_DGRAM_GET_PEER 46 -#define BIO_CTRL_DGRAM_GET_FALLBACK_MTU 47 +#define BIO_CTRL_DGRAM_GET_FALLBACK_MTU 47 // BIO Pairs. @@ -1031,7 +1037,7 @@ BSSL_NAMESPACE_BEGIN BORINGSSL_MAKE_DELETER(BIO, BIO_free) -BORINGSSL_MAKE_UP_REF(BIO, BIO_up_ref) +BORINGSSL_MAKE_UP_REF(BIO, BIO_dup_ref) BORINGSSL_MAKE_DELETER(BIO_METHOD, BIO_meth_free) BSSL_NAMESPACE_END
diff --git a/pkgs/boring/third_party/boringssl/src/include/openssl/cms.h b/pkgs/boring/third_party/boringssl/src/include/openssl/cms.h index d365a46..5a44517 100644 --- a/pkgs/boring/third_party/boringssl/src/include/openssl/cms.h +++ b/pkgs/boring/third_party/boringssl/src/include/openssl/cms.h
@@ -15,7 +15,7 @@ #ifndef OPENSSL_HEADER_CMS_H #define OPENSSL_HEADER_CMS_H -#include <openssl/base.h> // IWYU pragma: export +#include <openssl/base.h> // IWYU pragma: export #include <openssl/stack.h> @@ -69,8 +69,9 @@ // incomplete. `data` will then be ignored and should be NULL. The caller can // then continue configuring it and finalizing it with `CMS_final`. Otherwise, // the object will be finalized with `data` and `flags` passed to `CMS_final`. -OPENSSL_EXPORT CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, - STACK_OF(X509) *certs, BIO *data, +OPENSSL_EXPORT CMS_ContentInfo *CMS_sign(const X509 *signcert, + const EVP_PKEY *pkey, + const STACK_OF(X509) *certs, BIO *data, uint32_t flags); // CMS_ContentInfo_free releases memory associated with `cms`. @@ -102,7 +103,8 @@ // Subsequent calls will fail. Additionally, only RSA keys are currently // supported for `pkey`. OPENSSL_EXPORT CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, - X509 *signcert, EVP_PKEY *pkey, + const X509 *signcert, + const EVP_PKEY *pkey, const EVP_MD *md, uint32_t flags);
diff --git a/pkgs/boring/third_party/boringssl/src/include/openssl/dh.h b/pkgs/boring/third_party/boringssl/src/include/openssl/dh.h index 59e8c9c..6cb5d9e 100644 --- a/pkgs/boring/third_party/boringssl/src/include/openssl/dh.h +++ b/pkgs/boring/third_party/boringssl/src/include/openssl/dh.h
@@ -15,7 +15,7 @@ #ifndef OPENSSL_HEADER_DH_H #define OPENSSL_HEADER_DH_H -#include <openssl/base.h> // IWYU pragma: export +#include <openssl/base.h> // IWYU pragma: export #if defined(__cplusplus) extern "C" { @@ -49,6 +49,11 @@ // mutate `dh` for thread-safety purposes and may be used concurrently. OPENSSL_EXPORT int DH_up_ref(DH *dh); +// DH_dup_ref increments the reference count of `dh` and returns the same +// handle. It does not mutate `dh` for thread-safety purposes and may be used +// concurrently. +OPENSSL_EXPORT DH *DH_dup_ref(const DH *dh); + // Properties. @@ -317,7 +322,7 @@ BSSL_NAMESPACE_BEGIN BORINGSSL_MAKE_DELETER(DH, DH_free) -BORINGSSL_MAKE_UP_REF(DH, DH_up_ref) +BORINGSSL_MAKE_UP_REF(DH, DH_dup_ref) BSSL_NAMESPACE_END
diff --git a/pkgs/boring/third_party/boringssl/src/include/openssl/digest.h b/pkgs/boring/third_party/boringssl/src/include/openssl/digest.h index 8a81bc1..73270de 100644 --- a/pkgs/boring/third_party/boringssl/src/include/openssl/digest.h +++ b/pkgs/boring/third_party/boringssl/src/include/openssl/digest.h
@@ -44,6 +44,16 @@ OPENSSL_EXPORT const EVP_MD *EVP_sha512_256(void); OPENSSL_EXPORT const EVP_MD *EVP_blake2b256(void); +// SHA-3 family of digest functions. +// +// WARNING: Prefer to use SHA-2 (e.g. `EVP_sha256`) over SHA-3. Despite being a +// newer hash function, SHA-3 performs poorly and should only be used when +// necessary for interoperability with existing systems. + +OPENSSL_EXPORT const EVP_MD *EVP_sha3_256(void); +OPENSSL_EXPORT const EVP_MD *EVP_sha3_384(void); +OPENSSL_EXPORT const EVP_MD *EVP_sha3_512(void); + // EVP_md5_sha1 is a TLS-specific `EVP_MD` which computes the concatenation of // MD5 and SHA-1, as used in TLS 1.1 and below. OPENSSL_EXPORT const EVP_MD *EVP_md5_sha1(void); @@ -127,7 +137,7 @@ // EVP_MAX_MD_BLOCK_SIZE is the largest digest block size supported, in // bytes. -#define EVP_MAX_MD_BLOCK_SIZE 128 // SHA-512 is the longest so far. +#define EVP_MAX_MD_BLOCK_SIZE 136 // SHA3-256 is the longest so far. // EVP_DigestFinal_ex finishes the digest in `ctx` and writes the output to // `md_out`. `EVP_MD_CTX_size` bytes are written, which is at most @@ -344,9 +354,9 @@ struct evp_md_pctx_ops; // EVP_MAX_MD_DATA_SIZE is a private constant which specifies the size of the -// largest digest state. SHA-512 and BLAKE2b are joint-largest. Consuming code -// only uses this via the `EVP_MD_CTX` type. -#define EVP_MAX_MD_DATA_SIZE 208 +// largest digest state. SHA3-256 is the largest. Consuming code only uses this +// via the `EVP_MD_CTX` type. +#define EVP_MAX_MD_DATA_SIZE 240 // env_md_ctx_st is typoed ("evp" -> "env"), but the typo comes from OpenSSL // and some consumers forward-declare these structures so we're leaving it
diff --git a/pkgs/boring/third_party/boringssl/src/include/openssl/dsa.h b/pkgs/boring/third_party/boringssl/src/include/openssl/dsa.h index 3ae4d11..a77bf91 100644 --- a/pkgs/boring/third_party/boringssl/src/include/openssl/dsa.h +++ b/pkgs/boring/third_party/boringssl/src/include/openssl/dsa.h
@@ -375,7 +375,7 @@ BSSL_NAMESPACE_BEGIN BORINGSSL_MAKE_DELETER(DSA, DSA_free) -BORINGSSL_MAKE_UP_REF(DSA, DSA_up_ref) +BORINGSSL_MAKE_UP_REF(DSA, DSA_dup_ref) BORINGSSL_MAKE_DELETER(DSA_SIG, DSA_SIG_free) BSSL_NAMESPACE_END
diff --git a/pkgs/boring/third_party/boringssl/src/include/openssl/ec_key.h b/pkgs/boring/third_party/boringssl/src/include/openssl/ec_key.h index d894a67..296b7c0 100644 --- a/pkgs/boring/third_party/boringssl/src/include/openssl/ec_key.h +++ b/pkgs/boring/third_party/boringssl/src/include/openssl/ec_key.h
@@ -352,7 +352,7 @@ BSSL_NAMESPACE_BEGIN BORINGSSL_MAKE_DELETER(EC_KEY, EC_KEY_free) -BORINGSSL_MAKE_UP_REF(EC_KEY, EC_KEY_up_ref) +BORINGSSL_MAKE_UP_REF(EC_KEY, EC_KEY_dup_ref) BSSL_NAMESPACE_END
diff --git a/pkgs/boring/third_party/boringssl/src/include/openssl/evp.h b/pkgs/boring/third_party/boringssl/src/include/openssl/evp.h index 8a767ca..4af1726 100644 --- a/pkgs/boring/third_party/boringssl/src/include/openssl/evp.h +++ b/pkgs/boring/third_party/boringssl/src/include/openssl/evp.h
@@ -498,13 +498,10 @@ // Ed25519, `type` should be NULL. The `EVP_MD_CTX` itself is unused but is // present so the API is uniform. See `EVP_DigestSign`. // -// This function does not mutate `pkey` for thread-safety purposes and may be -// used concurrently with other non-mutating functions on `pkey`. -// // It returns one on success, or zero on error. OPENSSL_EXPORT int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, ENGINE *e, - EVP_PKEY *pkey); + const EVP_PKEY *pkey); // EVP_DigestSignUpdate appends `len` bytes from `data` to the data which will // be signed in `EVP_DigestSignFinal`. It returns one. @@ -554,13 +551,10 @@ // Ed25519, `type` should be NULL. The `EVP_MD_CTX` itself is unused but is // present so the API is uniform. See `EVP_DigestVerify`. // -// This function does not mutate `pkey` for thread-safety purposes and may be -// used concurrently with other non-mutating functions on `pkey`. -// // It returns one on success, or zero on error. OPENSSL_EXPORT int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, ENGINE *e, - EVP_PKEY *pkey); + const EVP_PKEY *pkey); // EVP_DigestVerifyUpdate appends `len` bytes from `data` to the data which // will be verified by `EVP_DigestVerifyFinal`. It returns one. @@ -615,13 +609,9 @@ // actual size of the signature is written to `*out_sig_len`. // // It returns one on success and zero otherwise. -// -// It does not modify `ctx`, thus it's possible to continue to use `ctx` in -// order to sign a longer message. It also does not mutate `pkey` for -// thread-safety purposes and may be used concurrently with other non-mutating -// functions on `pkey`. OPENSSL_EXPORT int EVP_SignFinal(const EVP_MD_CTX *ctx, uint8_t *sig, - unsigned int *out_sig_len, EVP_PKEY *pkey); + unsigned int *out_sig_len, + const EVP_PKEY *pkey); // Verifying (old functions) @@ -650,13 +640,8 @@ // calls to `EVP_VerifyUpdate`. // // It returns one on success and zero otherwise. -// -// It does not modify `ctx`, thus it's possible to continue to use `ctx` in -// order to verify a longer message. It also does not mutate `pkey` for -// thread-safety purposes and may be used concurrently with other non-mutating -// functions on `pkey`. OPENSSL_EXPORT int EVP_VerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig, - size_t sig_len, EVP_PKEY *pkey); + size_t sig_len, const EVP_PKEY *pkey); // Printing @@ -752,7 +737,7 @@ // EVP_PKEY_CTX_new allocates a fresh `EVP_PKEY_CTX` for use with `pkey`. It // returns the context or NULL on error. -OPENSSL_EXPORT EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e); +OPENSSL_EXPORT EVP_PKEY_CTX *EVP_PKEY_CTX_new(const EVP_PKEY *pkey, ENGINE *e); // EVP_PKEY_CTX_new_id allocates a fresh `EVP_PKEY_CTX` for a key of type `id` // (e.g. `EVP_PKEY_HMAC`). This can be used for key generation where @@ -770,7 +755,7 @@ OPENSSL_EXPORT EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *ctx); // EVP_PKEY_CTX_get0_pkey returns the `EVP_PKEY` associated with `ctx`. -OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx); +OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_CTX_get0_pkey(const EVP_PKEY_CTX *ctx); // EVP_PKEY_sign_init initialises an `EVP_PKEY_CTX` for a signing operation. It // should be called before `EVP_PKEY_sign`. @@ -897,7 +882,8 @@ // by `ctx` to `peer`. It should be called after `EVP_PKEY_derive_init`. (For // example, this is used to set the peer's key in (EC)DH.) It returns one on // success and zero on error. -OPENSSL_EXPORT int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer); +OPENSSL_EXPORT int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, + const EVP_PKEY *peer); // EVP_PKEY_derive derives a shared key from `ctx`. If `key` is non-NULL then, // on entry, `out_key_len` must contain the amount of space at `key`. If @@ -1633,7 +1619,7 @@ BSSL_NAMESPACE_BEGIN BORINGSSL_MAKE_DELETER(EVP_PKEY, EVP_PKEY_free) -BORINGSSL_MAKE_UP_REF(EVP_PKEY, EVP_PKEY_up_ref) +BORINGSSL_MAKE_UP_REF(EVP_PKEY, EVP_PKEY_dup_ref) BORINGSSL_MAKE_DELETER(EVP_PKEY_CTX, EVP_PKEY_CTX_free) BSSL_NAMESPACE_END
diff --git a/pkgs/boring/third_party/boringssl/src/include/openssl/nid.h b/pkgs/boring/third_party/boringssl/src/include/openssl/nid.h index 9ca8e67..38e5dc8 100644 --- a/pkgs/boring/third_party/boringssl/src/include/openssl/nid.h +++ b/pkgs/boring/third_party/boringssl/src/include/openssl/nid.h
@@ -5511,48 +5511,47 @@ #define SN_X_Wing "X-Wing" #define NID_X_Wing 972 -#define SN_alg_mtcProof_draft "alg-mtcProof-draft" -#define NID_alg_mtcProof_draft 976 -#define OBJ_alg_mtcProof_draft 1L, 3L, 6L, 1L, 4L, 1L, 44363L, 47L, 0L -#define OBJ_ENC_alg_mtcProof_draft \ - 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xda, 0x4b, 0x2f, 0x00 - -#define SN_rdna_trustAnchorID_draft "rdna-trustAnchorID-draft" -#define NID_rdna_trustAnchorID_draft 977 -#define OBJ_rdna_trustAnchorID_draft 1L, 3L, 6L, 1L, 4L, 1L, 44363L, 47L, 1L -#define OBJ_ENC_rdna_trustAnchorID_draft \ - 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xda, 0x4b, 0x2f, 0x01 - -#define SN_pe_mtcCertificationAuthority_draft \ - "pe-mtcCertificationAuthority-draft" -#define NID_pe_mtcCertificationAuthority_draft 978 -#define OBJ_pe_mtcCertificationAuthority_draft \ - 1L, 3L, 6L, 1L, 4L, 1L, 44363L, 47L, 2L -#define OBJ_ENC_pe_mtcCertificationAuthority_draft \ - 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xda, 0x4b, 0x2f, 0x02 - #define SN_SLH_DSA_SHA2_128s "id-slh-dsa-sha2-128s" #define LN_SLH_DSA_SHA2_128s "SLH-DSA-SHA2-128s" -#define NID_SLH_DSA_SHA2_128s 979 +#define NID_SLH_DSA_SHA2_128s 973 #define OBJ_SLH_DSA_SHA2_128s 2L, 16L, 840L, 1L, 101L, 3L, 4L, 3L, 20L #define OBJ_ENC_SLH_DSA_SHA2_128s \ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x14 #define SN_SLH_DSA_SHAKE_256f "id-slh-dsa-shake-256f" #define LN_SLH_DSA_SHAKE_256f "SLH-DSA-SHAKE-256f" -#define NID_SLH_DSA_SHAKE_256f 980 +#define NID_SLH_DSA_SHAKE_256f 974 #define OBJ_SLH_DSA_SHAKE_256f 2L, 16L, 840L, 1L, 101L, 3L, 4L, 3L, 31L #define OBJ_ENC_SLH_DSA_SHAKE_256f \ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x1f #define SN_SLH_DSA_SHA2_128s_WITH_SHA256 "id-hash-slh-dsa-sha2-128s-with-sha256" #define LN_SLH_DSA_SHA2_128s_WITH_SHA256 "SLH-DSA-SHA2-128s-WITH-SHA256" -#define NID_SLH_DSA_SHA2_128s_WITH_SHA256 981 +#define NID_SLH_DSA_SHA2_128s_WITH_SHA256 975 #define OBJ_SLH_DSA_SHA2_128s_WITH_SHA256 \ 2L, 16L, 840L, 1L, 101L, 3L, 4L, 3L, 35L #define OBJ_ENC_SLH_DSA_SHA2_128s_WITH_SHA256 \ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x23 +#define SN_alg_mtcProof "alg-mtcProof" +#define NID_alg_mtcProof 976 +#define OBJ_alg_mtcProof 1L, 3L, 6L, 1L, 5L, 5L, 7L, 6L, 67L +#define OBJ_ENC_alg_mtcProof 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x06, 0x43 + +#define SN_rdna_trustAnchorID "rdna-trustAnchorID" +#define NID_rdna_trustAnchorID 977 +#define OBJ_rdna_trustAnchorID 1L, 3L, 6L, 1L, 5L, 5L, 7L, 25L, 3L +#define OBJ_ENC_rdna_trustAnchorID \ + 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x19, 0x03 + +#define SN_pe_mtcCertificationAuthority_SHA256 \ + "pe-mtcCertificationAuthority-SHA256" +#define NID_pe_mtcCertificationAuthority_SHA256 978 +#define OBJ_pe_mtcCertificationAuthority_SHA256 \ + 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 38L +#define OBJ_ENC_pe_mtcCertificationAuthority_SHA256 \ + 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x26 + #if defined(__cplusplus) } /* extern C */
diff --git a/pkgs/boring/third_party/boringssl/src/include/openssl/pkcs7.h b/pkgs/boring/third_party/boringssl/src/include/openssl/pkcs7.h index 85c851e..b8f5b2b 100644 --- a/pkgs/boring/third_party/boringssl/src/include/openssl/pkcs7.h +++ b/pkgs/boring/third_party/boringssl/src/include/openssl/pkcs7.h
@@ -15,7 +15,7 @@ #ifndef OPENSSL_HEADER_PKCS7_H #define OPENSSL_HEADER_PKCS7_H -#include <openssl/base.h> // IWYU pragma: export +#include <openssl/base.h> // IWYU pragma: export #include <openssl/stack.h> @@ -59,8 +59,8 @@ // PKCS7_bundle_certificates behaves like `PKCS7_bundle_raw_certificates` but // takes `X509` objects as input. -OPENSSL_EXPORT int PKCS7_bundle_certificates( - CBB *out, const STACK_OF(X509) *certs); +OPENSSL_EXPORT int PKCS7_bundle_certificates(CBB *out, + const STACK_OF(X509) *certs); // PKCS7_get_CRLs parses a PKCS#7, SignedData structure from `cbs` and appends // the included CRLs to `out_crls`. It returns one on success and zero on error. @@ -144,8 +144,7 @@ // d2i_PKCS7 parses a BER-encoded, PKCS#7 signed data ContentInfo structure from // `len` bytes at `*inp`, as described in `d2i_SAMPLE`. -OPENSSL_EXPORT PKCS7 *d2i_PKCS7(PKCS7 **out, const uint8_t **inp, - size_t len); +OPENSSL_EXPORT PKCS7 *d2i_PKCS7(PKCS7 **out, const uint8_t **inp, size_t len); // d2i_PKCS7_bio behaves like `d2i_PKCS7` but reads the input from `bio`. If // the length of the object is indefinite the full contents of `bio` are read. @@ -215,7 +214,7 @@ // // Note this function only implements a subset of the corresponding OpenSSL // function. It is provided for backwards compatibility only. -OPENSSL_EXPORT PKCS7 *PKCS7_sign(X509 *sign_cert, EVP_PKEY *pkey, +OPENSSL_EXPORT PKCS7 *PKCS7_sign(X509 *sign_cert, const EVP_PKEY *pkey, STACK_OF(X509) *certs, BIO *data, int flags);
diff --git a/pkgs/boring/third_party/boringssl/src/include/openssl/pool.h b/pkgs/boring/third_party/boringssl/src/include/openssl/pool.h index 6eb759c..2c3855b 100644 --- a/pkgs/boring/third_party/boringssl/src/include/openssl/pool.h +++ b/pkgs/boring/third_party/boringssl/src/include/openssl/pool.h
@@ -130,9 +130,9 @@ BSSL_NAMESPACE_BEGIN BORINGSSL_MAKE_DELETER(CRYPTO_BUFFER_POOL, CRYPTO_BUFFER_POOL_free) -BORINGSSL_MAKE_UP_REF(CRYPTO_BUFFER_POOL, CRYPTO_BUFFER_POOL_up_ref) +BORINGSSL_MAKE_UP_REF(CRYPTO_BUFFER_POOL, CRYPTO_BUFFER_POOL_dup_ref) BORINGSSL_MAKE_DELETER(CRYPTO_BUFFER, CRYPTO_BUFFER_free) -BORINGSSL_MAKE_UP_REF(CRYPTO_BUFFER, CRYPTO_BUFFER_up_ref) +BORINGSSL_MAKE_UP_REF(CRYPTO_BUFFER, CRYPTO_BUFFER_dup_ref) BSSL_NAMESPACE_END
diff --git a/pkgs/boring/third_party/boringssl/src/include/openssl/prefix_symbols.h b/pkgs/boring/third_party/boringssl/src/include/openssl/prefix_symbols.h index 58f1fa8..47df60c 100644 --- a/pkgs/boring/third_party/boringssl/src/include/openssl/prefix_symbols.h +++ b/pkgs/boring/third_party/boringssl/src/include/openssl/prefix_symbols.h
@@ -130,6 +130,7 @@ #pragma redefine_extname ASN1_STRING_free BORINGSSL_ADD_USER_LABEL_AND_PREFIX(ASN1_STRING_free) #pragma redefine_extname ASN1_STRING_get0_data BORINGSSL_ADD_USER_LABEL_AND_PREFIX(ASN1_STRING_get0_data) #pragma redefine_extname ASN1_STRING_get_default_mask BORINGSSL_ADD_USER_LABEL_AND_PREFIX(ASN1_STRING_get_default_mask) +#pragma redefine_extname ASN1_STRING_get_length BORINGSSL_ADD_USER_LABEL_AND_PREFIX(ASN1_STRING_get_length) #pragma redefine_extname ASN1_STRING_length BORINGSSL_ADD_USER_LABEL_AND_PREFIX(ASN1_STRING_length) #pragma redefine_extname ASN1_STRING_new BORINGSSL_ADD_USER_LABEL_AND_PREFIX(ASN1_STRING_new) #pragma redefine_extname ASN1_STRING_print BORINGSSL_ADD_USER_LABEL_AND_PREFIX(ASN1_STRING_print) @@ -232,6 +233,7 @@ #pragma redefine_extname BIO_ctrl_get_write_guarantee BORINGSSL_ADD_USER_LABEL_AND_PREFIX(BIO_ctrl_get_write_guarantee) #pragma redefine_extname BIO_ctrl_pending BORINGSSL_ADD_USER_LABEL_AND_PREFIX(BIO_ctrl_pending) #pragma redefine_extname BIO_do_connect BORINGSSL_ADD_USER_LABEL_AND_PREFIX(BIO_do_connect) +#pragma redefine_extname BIO_dup_ref BORINGSSL_ADD_USER_LABEL_AND_PREFIX(BIO_dup_ref) #pragma redefine_extname BIO_eof BORINGSSL_ADD_USER_LABEL_AND_PREFIX(BIO_eof) #pragma redefine_extname BIO_f_base64 BORINGSSL_ADD_USER_LABEL_AND_PREFIX(BIO_f_base64) #pragma redefine_extname BIO_f_ssl BORINGSSL_ADD_USER_LABEL_AND_PREFIX(BIO_f_ssl) @@ -697,6 +699,7 @@ #pragma redefine_extname DH_compute_key BORINGSSL_ADD_USER_LABEL_AND_PREFIX(DH_compute_key) #pragma redefine_extname DH_compute_key_hashed BORINGSSL_ADD_USER_LABEL_AND_PREFIX(DH_compute_key_hashed) #pragma redefine_extname DH_compute_key_padded BORINGSSL_ADD_USER_LABEL_AND_PREFIX(DH_compute_key_padded) +#pragma redefine_extname DH_dup_ref BORINGSSL_ADD_USER_LABEL_AND_PREFIX(DH_dup_ref) #pragma redefine_extname DH_free BORINGSSL_ADD_USER_LABEL_AND_PREFIX(DH_free) #pragma redefine_extname DH_generate_key BORINGSSL_ADD_USER_LABEL_AND_PREFIX(DH_generate_key) #pragma redefine_extname DH_generate_parameters BORINGSSL_ADD_USER_LABEL_AND_PREFIX(DH_generate_parameters) @@ -1378,6 +1381,9 @@ #pragma redefine_extname EVP_sha224 BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_sha224) #pragma redefine_extname EVP_sha256 BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_sha256) #pragma redefine_extname EVP_sha384 BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_sha384) +#pragma redefine_extname EVP_sha3_256 BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_sha3_256) +#pragma redefine_extname EVP_sha3_384 BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_sha3_384) +#pragma redefine_extname EVP_sha3_512 BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_sha3_512) #pragma redefine_extname EVP_sha512 BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_sha512) #pragma redefine_extname EVP_sha512_256 BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_sha512_256) #pragma redefine_extname EXTENDED_KEY_USAGE_free BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EXTENDED_KEY_USAGE_free) @@ -2055,7 +2061,6 @@ #pragma redefine_extname SSL_CTX_set_ex_data BORINGSSL_ADD_USER_LABEL_AND_PREFIX(SSL_CTX_set_ex_data) #pragma redefine_extname SSL_CTX_set_false_start_allowed_without_alpn BORINGSSL_ADD_USER_LABEL_AND_PREFIX(SSL_CTX_set_false_start_allowed_without_alpn) #pragma redefine_extname SSL_CTX_set_grease_enabled BORINGSSL_ADD_USER_LABEL_AND_PREFIX(SSL_CTX_set_grease_enabled) -#pragma redefine_extname SSL_CTX_set_grease_sigalgs_enabled BORINGSSL_ADD_USER_LABEL_AND_PREFIX(SSL_CTX_set_grease_sigalgs_enabled) #pragma redefine_extname SSL_CTX_set_info_callback BORINGSSL_ADD_USER_LABEL_AND_PREFIX(SSL_CTX_set_info_callback) #pragma redefine_extname SSL_CTX_set_keylog_callback BORINGSSL_ADD_USER_LABEL_AND_PREFIX(SSL_CTX_set_keylog_callback) #pragma redefine_extname SSL_CTX_set_max_cert_list BORINGSSL_ADD_USER_LABEL_AND_PREFIX(SSL_CTX_set_max_cert_list) @@ -2580,6 +2585,7 @@ #pragma redefine_extname X509_CRL_delete_ext BORINGSSL_ADD_USER_LABEL_AND_PREFIX(X509_CRL_delete_ext) #pragma redefine_extname X509_CRL_digest BORINGSSL_ADD_USER_LABEL_AND_PREFIX(X509_CRL_digest) #pragma redefine_extname X509_CRL_dup BORINGSSL_ADD_USER_LABEL_AND_PREFIX(X509_CRL_dup) +#pragma redefine_extname X509_CRL_dup_ref BORINGSSL_ADD_USER_LABEL_AND_PREFIX(X509_CRL_dup_ref) #pragma redefine_extname X509_CRL_free BORINGSSL_ADD_USER_LABEL_AND_PREFIX(X509_CRL_free) #pragma redefine_extname X509_CRL_get0_by_cert BORINGSSL_ADD_USER_LABEL_AND_PREFIX(X509_CRL_get0_by_cert) #pragma redefine_extname X509_CRL_get0_by_serial BORINGSSL_ADD_USER_LABEL_AND_PREFIX(X509_CRL_get0_by_serial) @@ -2746,7 +2752,6 @@ #pragma redefine_extname X509_STORE_CTX_free BORINGSSL_ADD_USER_LABEL_AND_PREFIX(X509_STORE_CTX_free) #pragma redefine_extname X509_STORE_CTX_get0_cert BORINGSSL_ADD_USER_LABEL_AND_PREFIX(X509_STORE_CTX_get0_cert) #pragma redefine_extname X509_STORE_CTX_get0_chain BORINGSSL_ADD_USER_LABEL_AND_PREFIX(X509_STORE_CTX_get0_chain) -#pragma redefine_extname X509_STORE_CTX_get0_current_crl BORINGSSL_ADD_USER_LABEL_AND_PREFIX(X509_STORE_CTX_get0_current_crl) #pragma redefine_extname X509_STORE_CTX_get0_param BORINGSSL_ADD_USER_LABEL_AND_PREFIX(X509_STORE_CTX_get0_param) #pragma redefine_extname X509_STORE_CTX_get0_parent_ctx BORINGSSL_ADD_USER_LABEL_AND_PREFIX(X509_STORE_CTX_get0_parent_ctx) #pragma redefine_extname X509_STORE_CTX_get0_store BORINGSSL_ADD_USER_LABEL_AND_PREFIX(X509_STORE_CTX_get0_store) @@ -3294,6 +3299,7 @@ #define ASN1_STRING_free BORINGSSL_ADD_PREFIX(ASN1_STRING_free) #define ASN1_STRING_get0_data BORINGSSL_ADD_PREFIX(ASN1_STRING_get0_data) #define ASN1_STRING_get_default_mask BORINGSSL_ADD_PREFIX(ASN1_STRING_get_default_mask) +#define ASN1_STRING_get_length BORINGSSL_ADD_PREFIX(ASN1_STRING_get_length) #define ASN1_STRING_length BORINGSSL_ADD_PREFIX(ASN1_STRING_length) #define ASN1_STRING_new BORINGSSL_ADD_PREFIX(ASN1_STRING_new) #define ASN1_STRING_print BORINGSSL_ADD_PREFIX(ASN1_STRING_print) @@ -3396,6 +3402,7 @@ #define BIO_ctrl_get_write_guarantee BORINGSSL_ADD_PREFIX(BIO_ctrl_get_write_guarantee) #define BIO_ctrl_pending BORINGSSL_ADD_PREFIX(BIO_ctrl_pending) #define BIO_do_connect BORINGSSL_ADD_PREFIX(BIO_do_connect) +#define BIO_dup_ref BORINGSSL_ADD_PREFIX(BIO_dup_ref) #define BIO_eof BORINGSSL_ADD_PREFIX(BIO_eof) #define BIO_f_base64 BORINGSSL_ADD_PREFIX(BIO_f_base64) #define BIO_f_ssl BORINGSSL_ADD_PREFIX(BIO_f_ssl) @@ -3861,6 +3868,7 @@ #define DH_compute_key BORINGSSL_ADD_PREFIX(DH_compute_key) #define DH_compute_key_hashed BORINGSSL_ADD_PREFIX(DH_compute_key_hashed) #define DH_compute_key_padded BORINGSSL_ADD_PREFIX(DH_compute_key_padded) +#define DH_dup_ref BORINGSSL_ADD_PREFIX(DH_dup_ref) #define DH_free BORINGSSL_ADD_PREFIX(DH_free) #define DH_generate_key BORINGSSL_ADD_PREFIX(DH_generate_key) #define DH_generate_parameters BORINGSSL_ADD_PREFIX(DH_generate_parameters) @@ -4542,6 +4550,9 @@ #define EVP_sha224 BORINGSSL_ADD_PREFIX(EVP_sha224) #define EVP_sha256 BORINGSSL_ADD_PREFIX(EVP_sha256) #define EVP_sha384 BORINGSSL_ADD_PREFIX(EVP_sha384) +#define EVP_sha3_256 BORINGSSL_ADD_PREFIX(EVP_sha3_256) +#define EVP_sha3_384 BORINGSSL_ADD_PREFIX(EVP_sha3_384) +#define EVP_sha3_512 BORINGSSL_ADD_PREFIX(EVP_sha3_512) #define EVP_sha512 BORINGSSL_ADD_PREFIX(EVP_sha512) #define EVP_sha512_256 BORINGSSL_ADD_PREFIX(EVP_sha512_256) #define EXTENDED_KEY_USAGE_free BORINGSSL_ADD_PREFIX(EXTENDED_KEY_USAGE_free) @@ -5219,7 +5230,6 @@ #define SSL_CTX_set_ex_data BORINGSSL_ADD_PREFIX(SSL_CTX_set_ex_data) #define SSL_CTX_set_false_start_allowed_without_alpn BORINGSSL_ADD_PREFIX(SSL_CTX_set_false_start_allowed_without_alpn) #define SSL_CTX_set_grease_enabled BORINGSSL_ADD_PREFIX(SSL_CTX_set_grease_enabled) -#define SSL_CTX_set_grease_sigalgs_enabled BORINGSSL_ADD_PREFIX(SSL_CTX_set_grease_sigalgs_enabled) #define SSL_CTX_set_info_callback BORINGSSL_ADD_PREFIX(SSL_CTX_set_info_callback) #define SSL_CTX_set_keylog_callback BORINGSSL_ADD_PREFIX(SSL_CTX_set_keylog_callback) #define SSL_CTX_set_max_cert_list BORINGSSL_ADD_PREFIX(SSL_CTX_set_max_cert_list) @@ -5744,6 +5754,7 @@ #define X509_CRL_delete_ext BORINGSSL_ADD_PREFIX(X509_CRL_delete_ext) #define X509_CRL_digest BORINGSSL_ADD_PREFIX(X509_CRL_digest) #define X509_CRL_dup BORINGSSL_ADD_PREFIX(X509_CRL_dup) +#define X509_CRL_dup_ref BORINGSSL_ADD_PREFIX(X509_CRL_dup_ref) #define X509_CRL_free BORINGSSL_ADD_PREFIX(X509_CRL_free) #define X509_CRL_get0_by_cert BORINGSSL_ADD_PREFIX(X509_CRL_get0_by_cert) #define X509_CRL_get0_by_serial BORINGSSL_ADD_PREFIX(X509_CRL_get0_by_serial) @@ -5910,7 +5921,6 @@ #define X509_STORE_CTX_free BORINGSSL_ADD_PREFIX(X509_STORE_CTX_free) #define X509_STORE_CTX_get0_cert BORINGSSL_ADD_PREFIX(X509_STORE_CTX_get0_cert) #define X509_STORE_CTX_get0_chain BORINGSSL_ADD_PREFIX(X509_STORE_CTX_get0_chain) -#define X509_STORE_CTX_get0_current_crl BORINGSSL_ADD_PREFIX(X509_STORE_CTX_get0_current_crl) #define X509_STORE_CTX_get0_param BORINGSSL_ADD_PREFIX(X509_STORE_CTX_get0_param) #define X509_STORE_CTX_get0_parent_ctx BORINGSSL_ADD_PREFIX(X509_STORE_CTX_get0_parent_ctx) #define X509_STORE_CTX_get0_store BORINGSSL_ADD_PREFIX(X509_STORE_CTX_get0_store)
diff --git a/pkgs/boring/third_party/boringssl/src/include/openssl/rsa.h b/pkgs/boring/third_party/boringssl/src/include/openssl/rsa.h index 1abc611..f7c6cfa 100644 --- a/pkgs/boring/third_party/boringssl/src/include/openssl/rsa.h +++ b/pkgs/boring/third_party/boringssl/src/include/openssl/rsa.h
@@ -837,7 +837,7 @@ BSSL_NAMESPACE_BEGIN BORINGSSL_MAKE_DELETER(RSA, RSA_free) -BORINGSSL_MAKE_UP_REF(RSA, RSA_up_ref) +BORINGSSL_MAKE_UP_REF(RSA, RSA_dup_ref) BSSL_NAMESPACE_END
diff --git a/pkgs/boring/third_party/boringssl/src/include/openssl/trust_token.h b/pkgs/boring/third_party/boringssl/src/include/openssl/trust_token.h index cf909ae..e0fbcea 100644 --- a/pkgs/boring/third_party/boringssl/src/include/openssl/trust_token.h +++ b/pkgs/boring/third_party/boringssl/src/include/openssl/trust_token.h
@@ -15,7 +15,7 @@ #ifndef OPENSSL_HEADER_TRUST_TOKEN_H #define OPENSSL_HEADER_TRUST_TOKEN_H -#include <openssl/base.h> // IWYU pragma: export +#include <openssl/base.h> // IWYU pragma: export #include <openssl/stack.h> #if defined(__cplusplus) @@ -152,7 +152,7 @@ // TRUST_TOKEN_CLIENT_set_srr_key sets the public key used to verify the SRR. It // returns one on success and zero on error. OPENSSL_EXPORT int TRUST_TOKEN_CLIENT_set_srr_key(TRUST_TOKEN_CLIENT *ctx, - EVP_PKEY *key); + const EVP_PKEY *key); // TRUST_TOKEN_CLIENT_begin_issuance produces a request for `count` trust tokens // and serializes the request into a newly-allocated buffer, setting `*out` to @@ -180,11 +180,9 @@ // arrives without the specified key present. The caller takes ownership of the // list and must call `sk_TRUST_TOKEN_pop_free` when done. The list is empty if // issuance fails. -OPENSSL_EXPORT STACK_OF(TRUST_TOKEN) * - TRUST_TOKEN_CLIENT_finish_issuance(TRUST_TOKEN_CLIENT *ctx, - size_t *out_key_index, - const uint8_t *response, - size_t response_len); +OPENSSL_EXPORT STACK_OF(TRUST_TOKEN) *TRUST_TOKEN_CLIENT_finish_issuance( + TRUST_TOKEN_CLIENT *ctx, size_t *out_key_index, const uint8_t *response, + size_t response_len); // TRUST_TOKEN_CLIENT_begin_redemption produces a request to redeem a token @@ -243,7 +241,7 @@ // TRUST_TOKEN_ISSUER_set_srr_key sets the private key used to sign the SRR. It // returns one on success and zero on error. OPENSSL_EXPORT int TRUST_TOKEN_ISSUER_set_srr_key(TRUST_TOKEN_ISSUER *ctx, - EVP_PKEY *key); + const EVP_PKEY *key); // TRUST_TOKEN_ISSUER_issue ingests `request` for token issuance // and generates up to `max_issuance` valid tokens, producing a list of blinded
diff --git a/pkgs/boring/third_party/boringssl/src/include/openssl/x509.h b/pkgs/boring/third_party/boringssl/src/include/openssl/x509.h index 7e70ca2..6e2fa75 100644 --- a/pkgs/boring/third_party/boringssl/src/include/openssl/x509.h +++ b/pkgs/boring/third_party/boringssl/src/include/openssl/x509.h
@@ -486,9 +486,8 @@ OPENSSL_EXPORT int X509_set_subject_name(X509 *x509, const X509_NAME *name); // X509_set_pubkey sets `x509`'s public key to `pkey`. It returns one on success -// and zero on error. This function does not take ownership of `pkey` and -// internally copies and updates reference counts as needed. -OPENSSL_EXPORT int X509_set_pubkey(X509 *x509, EVP_PKEY *pkey); +// and zero on error. +OPENSSL_EXPORT int X509_set_pubkey(X509 *x509, const EVP_PKEY *pkey); // X509_delete_ext removes the extension in `x` at index `loc` and returns the // removed extension, or NULL if `loc` was out of bounds. If non-NULL, the @@ -682,6 +681,10 @@ // X509_CRL_up_ref adds one to the reference count of `crl` and returns one. OPENSSL_EXPORT int X509_CRL_up_ref(X509_CRL *crl); +// X509_CRL_dup_ref adds one to the reference count of `crl` and returns the +// same. +OPENSSL_EXPORT X509_CRL *X509_CRL_dup_ref(const X509_CRL *crl); + // X509_CRL_dup returns a newly-allocated copy of `crl`, or NULL on error. This // function works by serializing the structure, so if `crl` is incomplete, it // may fail. @@ -2819,7 +2822,7 @@ // is a race condition whether `x509` is available for issuer lookups. // Moreover, the result may differ for each issuer lookup performed by a single // `X509_verify_cert` call. -OPENSSL_EXPORT int X509_STORE_add_cert(X509_STORE *store, X509 *x509); +OPENSSL_EXPORT int X509_STORE_add_cert(X509_STORE *store, const X509 *x509); // X509_STORE_add_crl adds `crl` to `store`. It returns one on success and zero // on error. This function internally increments `crl`'s reference count, so the @@ -2836,7 +2839,7 @@ // To vary the set of CRLs over time, callers should either create a new // `X509_STORE` or configure CRLs on a per-verification basis with // `X509_STORE_CTX_set0_crls`. -OPENSSL_EXPORT int X509_STORE_add_crl(X509_STORE *store, X509_CRL *crl); +OPENSSL_EXPORT int X509_STORE_add_crl(X509_STORE *store, const X509_CRL *crl); // X509_STORE_get0_param returns `store`'s verification parameters. This object // is mutable and may be modified by the caller. For an individual certificate @@ -3068,11 +3071,6 @@ // error returned by `X509_STORE_CTX_get_error`. OPENSSL_EXPORT X509 *X509_STORE_CTX_get_current_cert(const X509_STORE_CTX *ctx); -// X509_STORE_CTX_get0_current_crl returns the CRL which caused the error -// returned by `X509_STORE_CTX_get_error`. -OPENSSL_EXPORT X509_CRL *X509_STORE_CTX_get0_current_crl( - const X509_STORE_CTX *ctx); - // X509_STORE_CTX_get0_store returns the `X509_STORE` that `ctx` uses. OPENSSL_EXPORT X509_STORE *X509_STORE_CTX_get0_store(const X509_STORE_CTX *ctx); @@ -3274,9 +3272,10 @@ // X509_V_FLAG_USE_DELTAS causes all verifications to fail. Delta CRL support // has been removed. #define X509_V_FLAG_USE_DELTAS 0x2000 -// X509_V_FLAG_CHECK_SS_SIGNATURE checks the redundant signature on self-signed -// trust anchors. This check provides no security benefit and only wastes CPU. -#define X509_V_FLAG_CHECK_SS_SIGNATURE 0x4000 +// X509_V_FLAG_CHECK_SS_SIGNATURE does nothing. Historically it would check the +// redundant signature on self-signed trust anchors. This check provided no +// security benefit and only wasted CPU. +#define X509_V_FLAG_CHECK_SS_SIGNATURE 0x0 // X509_V_FLAG_TRUSTED_FIRST does nothing. The behavior it controls is always // enabled. #define X509_V_FLAG_TRUSTED_FIRST 0x0 @@ -3291,9 +3290,9 @@ // X509_V_FLAG_ALLOW_TIMEZONE_OFFSET allows `notBefore` and `notAfter` fields // to contain a time zone offset. #define X509_V_FLAG_ALLOW_TIMEZONE_OFFSET 0x1000000 -// X509_V_FLAG_USE_MTC_DRAFT_PLANTS_05 enables the verification of Merkle Tree -// Certificates as specified in draft-ietf-plants-merkle-tree-certs-05. -#define X509_V_FLAG_USE_MTC_DRAFT_PLANTS_05 0x400000 +// X509_V_FLAG_USE_MTC_DRAFT_PLANTS_07 enables the verification of Merkle Tree +// Certificates as specified in draft-ietf-plants-merkle-tree-certs-07. +#define X509_V_FLAG_USE_MTC_DRAFT_PLANTS_07 0x400000 // X509_VERIFY_PARAM_set_flags enables all values in `flags` in `param`'s // verification flags and returns one. `flags` should be a combination of @@ -4518,7 +4517,7 @@ OPENSSL_EXPORT int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2, ASN1_BIT_STRING *signature, void *data, - EVP_PKEY *pkey, const EVP_MD *type); + const EVP_PKEY *pkey, const EVP_MD *type); // ASN1_item_sign_ctx behaves like `ASN1_item_sign` except the signature is // signed with `ctx`, `ctx`, which must have been initialized with @@ -5332,11 +5331,11 @@ BORINGSSL_MAKE_DELETER(RSA_PSS_PARAMS, RSA_PSS_PARAMS_free) BORINGSSL_MAKE_DELETER(USERNOTICE, USERNOTICE_free) BORINGSSL_MAKE_DELETER(X509, X509_free) -BORINGSSL_MAKE_UP_REF(X509, X509_up_ref) +BORINGSSL_MAKE_UP_REF(X509, X509_dup_ref) BORINGSSL_MAKE_DELETER(X509_ALGOR, X509_ALGOR_free) BORINGSSL_MAKE_DELETER(X509_ATTRIBUTE, X509_ATTRIBUTE_free) BORINGSSL_MAKE_DELETER(X509_CRL, X509_CRL_free) -BORINGSSL_MAKE_UP_REF(X509_CRL, X509_CRL_up_ref) +BORINGSSL_MAKE_UP_REF(X509_CRL, X509_CRL_dup_ref) BORINGSSL_MAKE_DELETER(X509_EXTENSION, X509_EXTENSION_free) BORINGSSL_MAKE_DELETER(X509_INFO, X509_INFO_free) BORINGSSL_MAKE_DELETER(X509_LOOKUP, X509_LOOKUP_free) @@ -5348,7 +5347,7 @@ BORINGSSL_MAKE_DELETER(X509_REVOKED, X509_REVOKED_free) BORINGSSL_MAKE_DELETER(X509_SIG, X509_SIG_free) BORINGSSL_MAKE_DELETER(X509_STORE, X509_STORE_free) -BORINGSSL_MAKE_UP_REF(X509_STORE, X509_STORE_up_ref) +BORINGSSL_MAKE_UP_REF(X509_STORE, X509_STORE_dup_ref) BORINGSSL_MAKE_DELETER(X509_STORE_CTX, X509_STORE_CTX_free) BORINGSSL_MAKE_DELETER(X509_VERIFY_PARAM, X509_VERIFY_PARAM_free)
diff --git a/pkgs/boring/tool/REVISION b/pkgs/boring/tool/REVISION index a2074dd..0678169 100644 --- a/pkgs/boring/tool/REVISION +++ b/pkgs/boring/tool/REVISION
@@ -1 +1 @@ -3fed4f207543470b3d639db6ed40737e30308b51 +64188f173d4bd19873db8a9d247470e9e1580ec2
diff --git a/pkgs/markdown/CHANGELOG.md b/pkgs/markdown/CHANGELOG.md index 3724066..166fce7 100644 --- a/pkgs/markdown/CHANGELOG.md +++ b/pkgs/markdown/CHANGELOG.md
@@ -1,5 +1,9 @@ ## 7.4.1-wip +* Skip the regular expression in `EmojiSyntax`, `AutolinkSyntax`, + `CodeSyntax`, and `ColorSwatchSyntax` when the character at the current + position cannot start a match. This makes inline parsing faster, mostly on + text with many spaces, punctuation marks, or CJK characters. * Fix quadratic parsing time on blocks of consecutive link reference definitions by only consuming lines from `BlockParser` as needed for a single definition rather than joining and re-splitting the remainder of the
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/autolink_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/autolink_syntax.dart index 01efd0c..3663c4d 100644 --- a/pkgs/markdown/lib/src/inline_syntaxes/autolink_syntax.dart +++ b/pkgs/markdown/lib/src/inline_syntaxes/autolink_syntax.dart
@@ -3,13 +3,18 @@ // BSD-style license that can be found in the LICENSE file. import '../ast.dart'; +import '../charcode.dart'; import '../inline_parser.dart'; import '../util.dart'; import 'inline_syntax.dart'; /// Matches autolinks like `<http://foo.com>`. class AutolinkSyntax extends InlineSyntax { - AutolinkSyntax() : super(r'<(([a-zA-Z][a-zA-Z\-\+\.]+):(?://)?[^\s>]*)>'); + AutolinkSyntax() + : super( + r'<(([a-zA-Z][a-zA-Z\-\+\.]+):(?://)?[^\s>]*)>', + startCharacter: $lt, + ); @override bool onMatch(InlineParser parser, Match match) {
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/code_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/code_syntax.dart index 35783d3..e69ede4 100644 --- a/pkgs/markdown/lib/src/inline_syntaxes/code_syntax.dart +++ b/pkgs/markdown/lib/src/inline_syntaxes/code_syntax.dart
@@ -26,6 +26,7 @@ @override bool tryMatch(InlineParser parser, [int? startMatchPos]) { + if (parser.charAt(parser.pos) != $backquote) return false; if (parser.pos > 0 && parser.charAt(parser.pos - 1) == $backquote) { // Not really a match! We can't just sneak past one backtick to try the // next character. An example of this situation would be:
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/color_swatch_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/color_swatch_syntax.dart index 5955cd7..2c84c3d 100644 --- a/pkgs/markdown/lib/src/inline_syntaxes/color_swatch_syntax.dart +++ b/pkgs/markdown/lib/src/inline_syntaxes/color_swatch_syntax.dart
@@ -44,6 +44,7 @@ @override bool tryMatch(InlineParser parser, [int? startMatchPos]) { + if (parser.charAt(parser.pos) != $backquote) return false; if (parser.pos > 0 && parser.charAt(parser.pos - 1) == $backquote) { // Not really a match! We can't just sneak past one backtick to try the // next character. An example of this situation would be:
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/emoji_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/emoji_syntax.dart index a068c6b..2501efc 100644 --- a/pkgs/markdown/lib/src/inline_syntaxes/emoji_syntax.dart +++ b/pkgs/markdown/lib/src/inline_syntaxes/emoji_syntax.dart
@@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import '../ast.dart'; +import '../charcode.dart'; import '../emojis.dart'; import '../inline_parser.dart'; import 'inline_syntax.dart'; @@ -15,7 +16,7 @@ class EmojiSyntax extends InlineSyntax { // Emoji "aliases" are mostly limited to lower-case letters, numbers, and // underscores, but GitHub also supports `:+1:` and `:-1:`. - EmojiSyntax() : super(':([a-z0-9_+-]+):'); + EmojiSyntax() : super(':([a-z0-9_+-]+):', startCharacter: $colon); @override bool onMatch(InlineParser parser, Match match) {
diff --git a/pkgs/markdown/test/regression_test.dart b/pkgs/markdown/test/regression_test.dart index 6ae65b9..eb4eb2f 100644 --- a/pkgs/markdown/test/regression_test.dart +++ b/pkgs/markdown/test/regression_test.dart
@@ -188,6 +188,50 @@ } }, ); + + group('inline syntaxes that check their first character', () { + // These syntaxes skip the regex when the first character cannot match. + // They must still match after CJK text and punctuation, and leave a lone + // first character as text. + test('EmojiSyntax', () { + expect( + markdownToHtml( + '中文:smile: a: b, (:+1:)', + inlineSyntaxes: [EmojiSyntax()], + ), + '<p>中文😄 a: b, (👍)</p>\n', + ); + }); + + test('AutolinkSyntax', () { + expect( + markdownToHtml('中文<http://a.b>, (<mailto:x@y.z>) a < b'), + '<p>中文<a href="http://a.b">http://a.b</a>, ' + '(<a href="mailto:x@y.z">mailto:x@y.z</a>) a < b</p>\n', + ); + }); + + test('CodeSyntax', () { + expect( + markdownToHtml('中文`code`, (``a`b``) a ` b'), + '<p>中文<code>code</code>, (<code>a`b</code>) a ` b</p>\n', + ); + }); + + test('ColorSwatchSyntax', () { + expect( + markdownToHtml( + '中文`#f00`, (`rgb(0,255,0)`) `#ba`', + inlineSyntaxes: [ColorSwatchSyntax()], + ), + '<p>中文<code class="gfm-color_chip">#f00<span ' + 'style="background-color:#f00;"></span></code>, ' + '(<code class="gfm-color_chip">rgb(0,255,0)<span ' + 'style="background-color:rgb(0,255,0);"></span></code>) ' + '<code>#ba</code></p>\n', + ); + }); + }); } class _CountingLine extends Line {
diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 41f52a0..6971f50 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md
@@ -1,8 +1,16 @@ -## 1.7.0-wip +## 1.7.0 - Added `tagPattern` and `version` fields to `GitDependency`, to support the `tag_pattern` key for git dependencies introduced in Dart 3.9. - Added a usage example. +- Fix `Pubspec.fromJson` with `lenient: true` to preserve the input `Map` + (`YamlMap`) when `name` is invalid or missing. +- Preserve nested `Map` (`YamlMap`) keys and spans when `git` or `hosted` + dependency shorthands fail to parse or when `Pubspec.fromJson` is called with + a non-`YamlMap` `Map`. +- Added fields to `Pubspec`: `falseSecrets`, `hooks`, `platforms`. +- Added `version` to `PathDependency`, exposing the constraint from an + accompanying `version` key instead of silently discarding it. ## 1.6.0
diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index 6fd01ac..2585368 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart
@@ -16,7 +16,7 @@ try { value = _fromJson(v, k); } on CheckedFromJsonException catch (e) { - if (e.map is! YamlMap) { + if (v is! Map || (source is YamlMap && e.map is! YamlMap)) { // This is likely a "synthetic" map created from a String value // Use `source` to throw this exception with an actual YamlMap and // extract the associated error information. @@ -83,9 +83,12 @@ return switch (key) { 'git' => GitDependency.fromData( data[key], - version: _optionalConstraintFromData(data), + version: _optionalConstraintFromData(data, 'GitDependency'), ), - 'path' => PathDependency.fromData(data[key]), + 'path' => PathDependency.fromData( + data[key], + version: _optionalConstraintFromData(data, 'PathDependency'), + ), 'sdk' => _$SdkDependencyFromJson(data), 'hosted' => _$HostedDependencyFromJson( data, @@ -153,7 +156,11 @@ factory GitDependency.fromData(Object? data, {VersionConstraint? version}) { if (data is String) { - data = {'url': data}; + try { + return GitDependency(parseGitUri(data), version: version); + } on FormatException catch (e) { + throw ArgumentError.value(data, 'git', e.message); + } } if (data is Map) { @@ -261,27 +268,37 @@ class PathDependency extends Dependency { final String path; - PathDependency(this.path); + /// The version constraint specified next to the `path` source. + /// + /// `null` if no constraint is specified, which pub treats as any version. + /// This isn't used to select the dependency, but pub's solver still + /// validates it against the resolved package's version. + final VersionConstraint? version; - factory PathDependency.fromData(Object? data) { + PathDependency(this.path, {this.version}); + + factory PathDependency.fromData(Object? data, {VersionConstraint? version}) { if (data is String) { - return PathDependency(data); + return PathDependency(data, version: version); } throw ArgumentError.value(data, 'path', 'Must be a String.'); } @override bool operator ==(Object other) => - other is PathDependency && other.path == path; + other is PathDependency && other.path == path && other.version == version; @override - int get hashCode => path.hashCode; + int get hashCode => Object.hash(path, version); @override String toString() => 'PathDependency: path@$path'; @override - Map<String, dynamic> toJson() => {'path': path}; + Map<String, dynamic> toJson() => { + 'path': path, + 'version': ?version?.toString(), + }; } @JsonSerializable(disallowUnrecognizedKeys: true) @@ -339,7 +356,7 @@ factory HostedDetails.fromJson(Object data) { if (data is String) { - data = {'url': data}; + return HostedDetails(null, _parseUriOrNull(data)); } if (data is Map) { @@ -366,7 +383,7 @@ VersionConstraint _constraintFromString(String? input) => input == null ? VersionConstraint.any : VersionConstraint.parse(input); -VersionConstraint? _optionalConstraintFromData(Map data) { +VersionConstraint? _optionalConstraintFromData(Map data, String className) { final value = data['version']; if (value == null) { return null; @@ -375,13 +392,13 @@ throw CheckedFromJsonException( data, 'version', - 'GitDependency', + className, '`$value` is not a String.', ); } try { return VersionConstraint.parse(value); } on FormatException catch (e) { - throw CheckedFromJsonException(data, 'version', 'GitDependency', e.message); + throw CheckedFromJsonException(data, 'version', className, e.message); } }
diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index dd51fe5..a2a8ac4 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart
@@ -99,6 +99,27 @@ /// Specifies how to resolve dependencies with the surrounding Pub Workspace. final String? resolution; + /// The platforms this package explicitly declares support for. + /// + /// Keys are platform names, such as `android`, `ios`, `linux`, `macos`, + /// `web` and `windows`. Values are currently always `null`. + /// + /// See https://dart.dev/tools/pub/pubspec#platforms. + final Map<String, Object?>? platforms; + + /// Gitignore style patterns for files that pub should not search for + /// leaked secrets when publishing. + /// + /// See https://dart.dev/tools/pub/pubspec#false_secrets. + final List<String>? falseSecrets; + + /// Configuration for hooks, such as native build or link hooks. + /// + /// May include `user_defines` and other settings. + /// + /// See https://dart.dev/tools/pub/pubspec#hooks. + final Map<String, Object?>? hooks; + /// If [author] and [authors] are both provided, their values are combined /// with duplicates eliminated. Pubspec( @@ -121,6 +142,9 @@ this.description, this.workspace, this.resolution, + this.platforms, + this.falseSecrets, + this.hooks, Map<String, Dependency>? dependencies, Map<String, Dependency>? devDependencies, Map<String, Dependency>? dependencyOverrides, @@ -154,14 +178,26 @@ factory Pubspec.fromJson(Map json, {bool lenient = false}) { if (lenient) { - while (json.isNotEmpty) { + var currentJson = json; + while (currentJson.isNotEmpty) { // Attempting to remove top-level properties that cause parsing errors. try { - return _$PubspecFromJson(json); + return _$PubspecFromJson(currentJson); } on CheckedFromJsonException catch (e) { - if (e.map == json && json.containsKey(e.key)) { - json = Map.from(json)..remove(e.key); - continue; + if (e.map == currentJson) { + if (e.key != 'name' && currentJson.containsKey(e.key)) { + currentJson = Map.from(currentJson)..remove(e.key); + continue; + } + if (currentJson != json) { + throw CheckedFromJsonException( + json, + e.key, + e.className!, + e.message, + badKey: e.badKey, + ); + } } rethrow; }
diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index cfbab51..0c0d738 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart
@@ -61,6 +61,18 @@ (v) => (v as List<dynamic>?)?.map((e) => e as String).toList(), ), resolution: $checkedConvert('resolution', (v) => v as String?), + platforms: $checkedConvert( + 'platforms', + (v) => (v as Map?)?.map((k, e) => MapEntry(k as String, e)), + ), + falseSecrets: $checkedConvert( + 'false_secrets', + (v) => (v as List<dynamic>?)?.map((e) => e as String).toList(), + ), + hooks: $checkedConvert( + 'hooks', + (v) => (v as Map?)?.map((k, e) => MapEntry(k as String, e)), + ), dependencies: $checkedConvert( 'dependencies', (v) => parseDeps(v as Map?), @@ -88,6 +100,7 @@ 'publishTo': 'publish_to', 'issueTracker': 'issue_tracker', 'ignoredAdvisories': 'ignored_advisories', + 'falseSecrets': 'false_secrets', 'devDependencies': 'dev_dependencies', 'dependencyOverrides': 'dependency_overrides', }, @@ -116,4 +129,7 @@ 'executables': _serializeExecutables(instance.executables), 'workspace': instance.workspace, 'resolution': instance.resolution, + 'platforms': instance.platforms, + 'false_secrets': instance.falseSecrets, + 'hooks': instance.hooks, };
diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 67b56a6..bacf663 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml
@@ -1,5 +1,5 @@ name: pubspec_parse -version: 1.7.0-wip +version: 1.7.0 description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting.
diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index 104f1ad..784ff89 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart
@@ -4,6 +4,7 @@ import 'dart:io'; +import 'package:json_annotation/json_annotation.dart'; import 'package:pub_semver/pub_semver.dart'; import 'package:pubspec_parse/pubspec_parse.dart'; import 'package:test/test.dart'; @@ -65,6 +66,23 @@ ╵''', ); }); + + test('plain Map in Pubspec.fromJson preserves nested key and map', () { + final gitMap = {'url': 42}; + expect( + () => Pubspec.fromJson({ + 'name': 'sample', + 'dependencies': { + 'dep': {'git': gitMap}, + }, + }), + throwsA( + isA<CheckedFromJsonException>() + .having((e) => e.key, 'key', 'url') + .having((e) => e.map, 'map', same(gitMap)), + ), + ); + }); }); } @@ -204,6 +222,18 @@ ); }); + test('map w/ invalid hosted String should error on hosted key', () { + _expectThrows( + {'hosted': '://bad_uri'}, + r''' +line 5, column 14: Unsupported value for "hosted". Invalid empty scheme at offset 0. + ╷ +5 │ "hosted": "://bad_uri" + │ ^^^^^^^^^^^^ + ╵''', + ); + }); + test('map w/ null version is fine', () async { final dep = await _dependency<HostedDependency>({'version': null}); expect(dep.version, VersionConstraint.any); @@ -465,6 +495,18 @@ 'git': {'url': 42}, }, r"type 'int' is not a subtype of type 'String'"); }); + + test('git - invalid string url', () { + _expectThrows( + {'git': '://bad_uri'}, + r''' +line 5, column 11: Unsupported value for "git". Invalid empty scheme + ╷ +5 │ "git": "://bad_uri" + │ ^^^^^^^^^^^^ + ╵''', + ); + }); } void _pathDependency() { @@ -474,15 +516,47 @@ expect(dep.toString(), 'PathDependency: path@../path'); }); - test('valid with version key is ignored', () async { + test('valid with version key exposes the constraint', () async { final dep = await _dependency<PathDependency>({ 'path': '../path', 'version': '^1.2.3', }); expect(dep.path, '../path'); + expect(dep.version, VersionConstraint.parse('^1.2.3')); expect(dep.toString(), 'PathDependency: path@../path'); }); + test('without a version key defaults to null', () async { + final dep = await _dependency<PathDependency>({'path': '../path'}); + expect(dep.version, isNull); + }); + + test('invalid version key fails', () { + _expectThrows( + {'path': '../path', 'version': 'not a version'}, + r''' +line 6, column 15: Unsupported value for "version". Could not parse version "not a version". Unknown text at "not a version". + ╷ +6 │ "version": "not a version" + │ ^^^^^^^^^^^^^^^ + ╵''', + ); + }); + + test('non-String version key fails', () { + _expectThrows( + {'path': '../path', 'version': 42}, + r''' +line 6, column 15: Unsupported value for "version". `42` is not a String. + ╷ +6 │ "version": 42 + │ ┌───────────────^ +7 │ │ } + │ └──^ + ╵''', + ); + }); + test('valid with random extra key fails', () { _expectThrows( {'path': '../path', 'bob': '^1.2.3'},
diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index f700b4e..64573b8 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart
@@ -34,6 +34,9 @@ expect(value.workspace, isNull); expect(value.resolution, isNull); expect(value.executables, isEmpty); + expect(value.platforms, isNull); + expect(value.falseSecrets, isNull); + expect(value.hooks, isNull); }); test('all fields set', () async { @@ -58,6 +61,13 @@ ], 'workspace': ['pkg1', 'pkg2'], 'resolution': 'workspace', + 'platforms': {'android': null, 'web': null}, + 'false_secrets': ['/lib/src/hardcoded_api_key.dart', '/test/*.pem'], + 'hooks': { + 'user_defines': { + 'my_package': {'enable_experimental': true}, + }, + }, 'executables': { 'my_script': 'bin/my_script.dart', 'my_script2': 'bin/my_script2.dart', @@ -101,6 +111,16 @@ expect(value.workspace!.first, 'pkg1'); expect(value.workspace!.last, 'pkg2'); expect(value.resolution, 'workspace'); + expect(value.platforms, {'android': null, 'web': null}); + expect(value.falseSecrets, [ + '/lib/src/hardcoded_api_key.dart', + '/test/*.pem', + ]); + expect(value.hooks, { + 'user_defines': { + 'my_package': {'enable_experimental': true}, + }, + }); }); test('environment values can be null', () async { @@ -398,6 +418,118 @@ }); }); + group('platforms', () { + test('map with null values', () async { + final value = await parse({ + ...defaultPubspec, + 'platforms': {'android': null, 'ios': null, 'web': null}, + }); + expect(value.platforms, {'android': null, 'ios': null, 'web': null}); + }); + + test('not a map', () { + expectParseThrowsContaining( + {...defaultPubspec, 'platforms': 1}, + "Unsupported value for \"platforms\". type 'int' is not a subtype of type 'Map<dynamic, dynamic>?'", + skipTryPub: true, + ); + }); + + test('invalid data - lenient', () async { + final value = await parse( + {...defaultPubspec, 'platforms': 1}, + skipTryPub: true, + lenient: true, + ); + expect(value.name, 'sample'); + expect(value.platforms, isNull); + }); + }); + + group('false_secrets', () { + test('list of patterns', () async { + final value = await parse({ + ...defaultPubspec, + 'false_secrets': [ + '/lib/src/hardcoded_api_key.dart', + '/test/localhost_certificates/*.pem', + ], + }); + expect(value.falseSecrets, [ + '/lib/src/hardcoded_api_key.dart', + '/test/localhost_certificates/*.pem', + ]); + }); + + test('not a list', () { + expectParseThrowsContaining( + {...defaultPubspec, 'false_secrets': 1}, + "Unsupported value for \"false_secrets\". type 'int' is not a subtype of type 'List<dynamic>?'", + skipTryPub: true, + ); + }); + + test('not a string', () { + expectParseThrowsContaining( + { + ...defaultPubspec, + 'false_secrets': [1], + }, + "Unsupported value for \"false_secrets\". type 'int' is not a subtype of type 'String'", + skipTryPub: true, + ); + }); + + test('invalid data - lenient', () async { + final value = await parse( + { + ...defaultPubspec, + 'false_secrets': [1], + }, + skipTryPub: true, + lenient: true, + ); + expect(value.name, 'sample'); + expect(value.falseSecrets, isNull); + }); + }); + + group('hooks', () { + test('map', () async { + final value = await parse({ + ...defaultPubspec, + 'hooks': { + 'user_defines': { + 'my_package': {'enable_experimental': true}, + }, + }, + }); + expect(value.hooks, { + 'user_defines': { + 'my_package': {'enable_experimental': true}, + }, + }); + }); + + test('not a map', () { + expectParseThrowsContaining( + {...defaultPubspec, 'hooks': 1}, + "Unsupported value for \"hooks\". type 'int' is not a subtype of type 'Map<dynamic, dynamic>?'", + skipTryPub: true, + ); + }); + + test('invalid data - lenient', () async { + final value = await parse( + {...defaultPubspec, 'hooks': 1}, + skipTryPub: true, + lenient: true, + ); + expect(value.name, 'sample'); + expect(value.hooks, isNull); + }); + }); + group('funding', () { test('not a list', () { expectParseThrowsContaining( @@ -676,6 +808,28 @@ ); }); + test('name cannot be null', () { + expectParseThrowsContaining( + {...defaultPubspec, 'name': null}, + "Unsupported value for \"name\". type 'Null' is not a subtype of type 'String'", + lenient: true, + ); + }); + + test('name cannot be empty string with invalid other property', () { + expectParseThrows( + {'name': '', 'version': 'invalid'}, + r''' +line 2, column 10: Unsupported value for "name". "name" cannot be empty. + ╷ +2 │ "name": "", + │ ^^ + ╵''', + lenient: true, + skipTryPub: true, + ); + }); + test('bad repository url', () async { final value = await parse({ ...defaultPubspec,
diff --git a/pkgs/pubspec_parse/test/tojson_test.dart b/pkgs/pubspec_parse/test/tojson_test.dart index 60d320f..c19ffef 100644 --- a/pkgs/pubspec_parse/test/tojson_test.dart +++ b/pkgs/pubspec_parse/test/tojson_test.dart
@@ -39,6 +39,9 @@ 'funding': null, 'topics': null, 'ignored_advisories': null, + 'platforms': null, + 'false_secrets': null, + 'hooks': null, }); }); @@ -65,6 +68,13 @@ ], 'workspace': ['pkg1', 'pkg2'], 'resolution': 'workspace', + 'platforms': {'android': null, 'web': null}, + 'false_secrets': ['/lib/src/hardcoded_api_key.dart', '/test/*.pem'], + 'hooks': { + 'user_defines': { + 'my_package': {'enable_experimental': true}, + }, + }, 'executables': { 'my_script': 'bin/my_script.dart', 'my_script2': 'bin/my_script2.dart', @@ -106,6 +116,13 @@ 'ignored_advisories': ['111', '222'], 'workspace': ['pkg1', 'pkg2'], 'resolution': 'workspace', + 'platforms': {'android': null, 'web': null}, + 'false_secrets': ['/lib/src/hardcoded_api_key.dart', '/test/*.pem'], + 'hooks': { + 'user_defines': { + 'my_package': {'enable_experimental': true}, + }, + }, 'executables': { 'my_script': 'bin/my_script.dart', 'my_script2': 'bin/my_script2.dart', @@ -139,6 +156,9 @@ expect(newValue.workspace, value.workspace); expect(newValue.resolution, value.resolution); expect(newValue.executables, value.executables); + expect(newValue.platforms, value.platforms); + expect(newValue.falseSecrets, value.falseSecrets); + expect(newValue.hooks, value.hooks); }); test('all fields set', () async { @@ -163,6 +183,13 @@ ], 'workspace': ['pkg1', 'pkg2'], 'resolution': 'workspace', + 'platforms': {'android': null, 'web': null}, + 'false_secrets': ['/lib/src/hardcoded_api_key.dart', '/test/*.pem'], + 'hooks': { + 'user_defines': { + 'my_package': {'enable_experimental': true}, + }, + }, 'executables': { 'my_script': 'bin/my_script.dart', 'my_script2': 'bin/my_script2.dart', @@ -200,6 +227,9 @@ expect(newValue.workspace, value.workspace); expect(newValue.resolution, value.resolution); expect(newValue.executables, value.executables); + expect(newValue.platforms, value.platforms); + expect(newValue.falseSecrets, value.falseSecrets); + expect(newValue.hooks, value.hooks); }); test('dependencies', () async { @@ -230,6 +260,10 @@ 'version': '^2.0.1', }, 'local_utils': {'path': '../local_utils'}, + 'versioned_local': { + 'path': '../versioned_local', + 'version': '^1.2.3', + }, }, }, skipTryPub: true); @@ -237,7 +271,7 @@ final newValue = await parse(jsonValue, skipTryPub: true); - expect(value.dependencies, hasLength(9)); + expect(value.dependencies, hasLength(10)); expect(value.dependencies, { 'flutter': isA<SdkDependency>(), 'http': isA<HostedDependency>(), @@ -248,6 +282,7 @@ 'shared_preferences': isA<GitDependency>(), 'kittens': isA<GitDependency>(), 'local_utils': isA<PathDependency>(), + 'versioned_local': isA<PathDependency>(), }); expect( @@ -293,6 +328,14 @@ value.dependencies['local_utils']?.toJson(), newValue.dependencies['local_utils']?.toJson(), ); + expect(value.dependencies['versioned_local']?.toJson(), { + 'path': '../versioned_local', + 'version': '^1.2.3', + }); + expect( + value.dependencies['versioned_local']?.toJson(), + newValue.dependencies['versioned_local']?.toJson(), + ); }); }); }
diff --git a/pkgs/unified_analytics/CHANGELOG.md b/pkgs/unified_analytics/CHANGELOG.md index 23bf450..5efe77e 100644 --- a/pkgs/unified_analytics/CHANGELOG.md +++ b/pkgs/unified_analytics/CHANGELOG.md
@@ -1,4 +1,14 @@ -## 8.1.0-wip +## 8.2.0 + +- Default `agent` in `Analytics` and `Analytics.development` to + `AiAgent.detectAgentName(Platform.environment)` when omitted. +- Tightened `AiAgent.cursor` detection in `AiAgent.detectAgentName` to check + `CURSOR_AGENT` and `CURSOR_EXTENSION_HOST_ROLE=agent-exec` rather than + `TERM_PROGRAM=cursor` or any `CURSOR_*` environment variable. +- Added `Analytics.isBot` to detect CI and bot environments from environment + variables. + +## 8.1.0 - Added optional `isExternal` parameter to `Analytics.fake` to allow overriding the build configuration during testing.
diff --git a/pkgs/unified_analytics/lib/src/analytics.dart b/pkgs/unified_analytics/lib/src/analytics.dart index 5a8722d..7f51869 100644 --- a/pkgs/unified_analytics/lib/src/analytics.dart +++ b/pkgs/unified_analytics/lib/src/analytics.dart
@@ -44,7 +44,8 @@ /// /// [agent] is an optional parameter to capture the name of any AI coding /// assistant/agent executing the tool. Examples include "Claude Code", - /// "Cursor", or "Copilot". + /// "Cursor", or "Copilot". If omitted, defaults to + /// `AiAgent.detectAgentName(io.Platform.environment)`. factory Analytics({ required DashTool tool, required String dartVersion, @@ -103,7 +104,7 @@ enableAsserts: enableAsserts, clientIde: clientIde, enabledFeatures: enabledFeatures, - agent: agent, + agent: agent ?? AiAgent.detectAgentName(io.Platform.environment), firstRun: firstRun, ); } @@ -120,7 +121,8 @@ /// /// [agent] is an optional parameter to capture the name of any AI coding /// assistant/agent executing the tool. Examples include "Claude Code", - /// "Cursor", or "Copilot". + /// "Cursor", or "Copilot". If omitted, defaults to + /// `AiAgent.detectAgentName(io.Platform.environment)`. factory Analytics.development({ required DashTool tool, required String dartVersion, @@ -188,11 +190,41 @@ enableAsserts: enableAsserts, clientIde: clientIde, enabledFeatures: enabledFeatures, - agent: agent, + agent: agent ?? AiAgent.detectAgentName(io.Platform.environment), firstRun: firstRun, ); } + /// Returns `true` if [environment] indicates that the tool is running in an + /// automated CI or bot environment. + static bool isBot(Map<String, String> environment) { + final bot = environment['BOT']?.trim().toLowerCase(); + if (bot == 'false' || + bot == '0' || + environment.containsKey('FLUTTER_HOST') || + environment.containsKey('FLUTTER_ANALYTICS_LOG_FILE')) { + return false; + } + + final ci = environment['CI']?.trim().toLowerCase(); + return (bot != null && bot.isNotEmpty) || + (ci != null && ci.isNotEmpty && ci != 'false' && ci != '0') || + environment['TRAVIS'] == 'true' || + environment['CONTINUOUS_INTEGRATION'] == 'true' || + environment.containsKey('APPVEYOR') || + environment.containsKey('CIRRUS_CI') || + (environment.containsKey('AWS_REGION') && + environment.containsKey('CODEBUILD_INITIATOR')) || + environment.containsKey('JENKINS_URL') || + environment.containsKey('GITHUB_ACTIONS') || + environment['CHROME_HEADLESS'] == '1' || + environment.containsKey('BUILDBOT_BUILDERNAME') || + environment.containsKey('SWARMING_TASK_ID') || + environment.containsKey('BORG_ALLOC_DIR') || + environment.containsKey('TF_BUILD') || + environment.containsKey('AZURE_HTTP_USER_AGENT'); + } + /// The shared identifier for Flutter and Dart related tooling using /// package:unified_analytics. String get clientId; @@ -311,12 +343,12 @@ /// Returns an instance of [FakeAnalytics] which can be used in tests to check /// for certain [Event] instances within [FakeAnalytics.sentEvents]. /// - /// The returned instance checks `DASH__SUPPRESS_ANALYTICS` in [environment] - /// rather than in the process environment. [environment] defaults to an - /// empty map, so tests aren't affected by the shell they run in. Pass - /// `Platform.environment` to follow the real environment. The production - /// [Analytics] factories don't offer this, and always respect the real - /// environment. + /// The returned instance checks `DASH__SUPPRESS_ANALYTICS` and AI agent + /// variables in [environment] rather than in the process environment. + /// [environment] defaults to an empty map, so tests aren't affected by the + /// shell they run in. Pass `Platform.environment` to follow the real + /// environment. The production [Analytics] factories don't offer this, and + /// always respect the real environment. @visibleForTesting static FakeAnalytics fake({ required DashTool tool, @@ -362,7 +394,7 @@ gaClient: gaClient ?? const FakeGAClient(), clientIde: clientIde, enabledFeatures: enabledFeatures, - agent: agent, + agent: agent ?? AiAgent.detectAgentName(environment), firstRun: firstRun, enableAsserts: enableAsserts, isExternal: isExternal,
diff --git a/pkgs/unified_analytics/lib/src/constants.dart b/pkgs/unified_analytics/lib/src/constants.dart index c3fa98b..3adeab4 100644 --- a/pkgs/unified_analytics/lib/src/constants.dart +++ b/pkgs/unified_analytics/lib/src/constants.dart
@@ -99,7 +99,7 @@ const String kLogFileName = 'dart-flutter-telemetry.log'; /// The current version of the package, should be in line with pubspec version. -const String kPackageVersion = '8.1.0-wip'; +const String kPackageVersion = '8.2.0'; /// The minimum length for a session. const int kSessionDurationMinutes = 30;
diff --git a/pkgs/unified_analytics/lib/src/enums.dart b/pkgs/unified_analytics/lib/src/enums.dart index 218598c..b789c60 100644 --- a/pkgs/unified_analytics/lib/src/enums.dart +++ b/pkgs/unified_analytics/lib/src/enums.dart
@@ -328,8 +328,12 @@ return gemini.label; } - if (environment['TERM_PROGRAM'] == 'cursor' || - environment.keys.any((String key) => key.startsWith('CURSOR_'))) { + final cursorAgent = environment['CURSOR_AGENT']?.trim(); + if ((cursorAgent != null && + cursorAgent.isNotEmpty && + cursorAgent != '0' && + cursorAgent.toLowerCase() != 'false') || + environment['CURSOR_EXTENSION_HOST_ROLE'] == 'agent-exec') { return cursor.label; }
diff --git a/pkgs/unified_analytics/pubspec.yaml b/pkgs/unified_analytics/pubspec.yaml index 53ae6ca..3246b2d 100644 --- a/pkgs/unified_analytics/pubspec.yaml +++ b/pkgs/unified_analytics/pubspec.yaml
@@ -5,7 +5,7 @@ # LINT.IfChange # When updating this, keep the version consistent with the changelog and the # value in lib/src/constants.dart. -version: 8.1.0-wip +version: 8.2.0 # LINT.ThenChange(lib/src/constants.dart) repository: https://github.com/dart-lang/tools/tree/main/pkgs/unified_analytics issue_tracker: https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aunified_analytics
diff --git a/pkgs/unified_analytics/test/unified_analytics_test.dart b/pkgs/unified_analytics/test/unified_analytics_test.dart index 4b31e24..0e70686 100644 --- a/pkgs/unified_analytics/test/unified_analytics_test.dart +++ b/pkgs/unified_analytics/test/unified_analytics_test.dart
@@ -902,6 +902,14 @@ test( 'The UserProperty class correctly sets and exposes the ai_agent value', () { + expect( + analytics.userPropertyMap['ai_agent']?['value'], + isNull, + reason: + 'The ai_agent user property should default to null when agent and ' + 'environment are omitted', + ); + final secondAnalytics = Analytics.fake( tool: initialTool, homeDirectory: home, @@ -926,6 +934,45 @@ 'CursorIDE', reason: 'The client_ide user property should be set to CursorIDE', ); + + final envDetectedAnalytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + environment: const {'CURSOR_AGENT': '1'}, + ); + expect( + envDetectedAnalytics.userPropertyMap['ai_agent']?['value'], + 'Cursor', + reason: + 'The ai_agent user property should be detected from environment ' + 'when agent is omitted', + ); + + final overrideAgentAnalytics = Analytics.fake( + tool: initialTool, + homeDirectory: home, + flutterChannel: flutterChannel, + toolsMessageVersion: toolsMessageVersion, + toolsMessage: toolsMessage, + flutterVersion: flutterVersion, + dartVersion: dartVersion, + fs: fs, + platform: platform, + agent: 'CustomAgent', + environment: const {'CURSOR_AGENT': '1'}, + ); + expect( + overrideAgentAnalytics.userPropertyMap['ai_agent']?['value'], + 'CustomAgent', + reason: 'An explicit agent argument should override environment', + ); }, ); @@ -987,10 +1034,44 @@ ); expect( AiAgent.detectAgentName(<String, String>{'TERM_PROGRAM': 'cursor'}), - 'Cursor', + isNull, + ); + expect( + AiAgent.detectAgentName(<String, String>{'CURSOR_TRACE_ID': 'abc'}), + isNull, ); expect( AiAgent.detectAgentName(<String, String>{'CURSOR_APP_VERSION': '1'}), + isNull, + ); + expect( + AiAgent.detectAgentName(<String, String>{'CURSOR_AGENT': ''}), + isNull, + ); + expect( + AiAgent.detectAgentName(<String, String>{'CURSOR_AGENT': '0'}), + isNull, + ); + expect( + AiAgent.detectAgentName(<String, String>{'CURSOR_AGENT': 'false'}), + isNull, + ); + expect( + AiAgent.detectAgentName(<String, String>{'CURSOR_AGENT': 'FALSE'}), + isNull, + ); + expect( + AiAgent.detectAgentName(<String, String>{'CURSOR_AGENT': '1'}), + 'Cursor', + ); + expect( + AiAgent.detectAgentName(<String, String>{'CURSOR_AGENT': 'true'}), + 'Cursor', + ); + expect( + AiAgent.detectAgentName(<String, String>{ + 'CURSOR_EXTENSION_HOST_ROLE': 'agent-exec', + }), 'Cursor', ); expect( @@ -1051,6 +1132,130 @@ ); }); + group('Analytics.isBot', () { + test('returns false for empty environment', () { + expect(Analytics.isBot(<String, String>{}), isFalse); + }); + + test('returns false for non-bot overrides even when CI vars are set', () { + expect( + Analytics.isBot(<String, String>{'BOT': 'false', 'CI': 'true'}), + isFalse, + ); + expect( + Analytics.isBot(<String, String>{'BOT': 'FALSE', 'CI': 'true'}), + isFalse, + ); + expect( + Analytics.isBot(<String, String>{'BOT': '0', 'GITHUB_ACTIONS': 'true'}), + isFalse, + ); + expect( + Analytics.isBot(<String, String>{ + 'FLUTTER_HOST': '1', + 'CI': 'true', + 'BOT': 'true', + }), + isFalse, + ); + expect( + Analytics.isBot(<String, String>{ + 'FLUTTER_ANALYTICS_LOG_FILE': '/tmp/analytics.log', + 'CI': 'true', + 'BOT': 'true', + }), + isFalse, + ); + }); + + test('returns false for falsy or empty CI and BOT values', () { + expect(Analytics.isBot(<String, String>{'CI': ''}), isFalse); + expect(Analytics.isBot(<String, String>{'CI': ' '}), isFalse); + expect(Analytics.isBot(<String, String>{'CI': 'false'}), isFalse); + expect(Analytics.isBot(<String, String>{'CI': 'FALSE'}), isFalse); + expect(Analytics.isBot(<String, String>{'CI': '0'}), isFalse); + expect(Analytics.isBot(<String, String>{'BOT': ''}), isFalse); + expect(Analytics.isBot(<String, String>{'BOT': ' '}), isFalse); + }); + + test('returns true for truthy CI and BOT values', () { + expect(Analytics.isBot(<String, String>{'CI': 'true'}), isTrue); + expect(Analytics.isBot(<String, String>{'CI': 'TRUE'}), isTrue); + expect(Analytics.isBot(<String, String>{'CI': '1'}), isTrue); + expect(Analytics.isBot(<String, String>{'BOT': 'true'}), isTrue); + expect(Analytics.isBot(<String, String>{'BOT': 'TRUE'}), isTrue); + expect(Analytics.isBot(<String, String>{'BOT': '1'}), isTrue); + }); + + test('returns true for known CI provider environment variables', () { + expect(Analytics.isBot(<String, String>{'TRAVIS': 'true'}), isTrue); + expect(Analytics.isBot(<String, String>{'TRAVIS': 'false'}), isFalse); + expect( + Analytics.isBot(<String, String>{'CONTINUOUS_INTEGRATION': 'true'}), + isTrue, + ); + expect( + Analytics.isBot(<String, String>{'CONTINUOUS_INTEGRATION': 'false'}), + isFalse, + ); + expect(Analytics.isBot(<String, String>{'APPVEYOR': 'True'}), isTrue); + expect(Analytics.isBot(<String, String>{'CIRRUS_CI': 'true'}), isTrue); + expect( + Analytics.isBot(<String, String>{ + 'AWS_REGION': 'us-east-1', + 'CODEBUILD_INITIATOR': 'codepipeline/my-pipeline', + }), + isTrue, + ); + expect( + Analytics.isBot(<String, String>{'AWS_REGION': 'us-east-1'}), + isFalse, + ); + expect( + Analytics.isBot(<String, String>{ + 'CODEBUILD_INITIATOR': 'codepipeline/my-pipeline', + }), + isFalse, + ); + expect( + Analytics.isBot(<String, String>{ + 'JENKINS_URL': 'https://jenkins.example.com/', + }), + isTrue, + ); + expect( + Analytics.isBot(<String, String>{'GITHUB_ACTIONS': 'true'}), + isTrue, + ); + expect(Analytics.isBot(<String, String>{'CHROME_HEADLESS': '1'}), isTrue); + expect( + Analytics.isBot(<String, String>{'CHROME_HEADLESS': '0'}), + isFalse, + ); + expect( + Analytics.isBot(<String, String>{ + 'BUILDBOT_BUILDERNAME': 'Linux Engine', + }), + isTrue, + ); + expect( + Analytics.isBot(<String, String>{'SWARMING_TASK_ID': '12345'}), + isTrue, + ); + expect( + Analytics.isBot(<String, String>{'BORG_ALLOC_DIR': '/borg/alloc'}), + isTrue, + ); + expect(Analytics.isBot(<String, String>{'TF_BUILD': 'True'}), isTrue); + expect( + Analytics.isBot(<String, String>{ + 'AZURE_HTTP_USER_AGENT': 'VSTS_12345', + }), + isTrue, + ); + }); + }); + test('The minimum session duration should be at least 30 minutes', () { expect( kSessionDurationMinutes < 30,
diff --git a/pkgs/yaml/CHANGELOG.md b/pkgs/yaml/CHANGELOG.md index e00e04c..e91c317 100644 --- a/pkgs/yaml/CHANGELOG.md +++ b/pkgs/yaml/CHANGELOG.md
@@ -2,6 +2,13 @@ * Export `ErrorListener` and `ErrorCollector` from `package:yaml/yaml.dart`. * Improve error messages when mixing list and key-value syntax. +* Preserve scanned local tag names and throw `YamlException` on malformed or + non-UTF-8 percent-encoded tag URIs. +* Support single-digit `!!float` scalars and throw `YamlException` instead of + `RangeError` on empty or invalid single-character `!!int` and `!!float` + scalars. +* Speed up scanning deeply nested flow collections: the scanner no longer + walks every open flow level for each token. ## 3.1.4
diff --git a/pkgs/yaml/lib/src/loader.dart b/pkgs/yaml/lib/src/loader.dart index 4f57f7f..771257c 100644 --- a/pkgs/yaml/lib/src/loader.dart +++ b/pkgs/yaml/lib/src/loader.dart
@@ -284,13 +284,16 @@ {bool allowInt = true, bool allowFloat = true}) { assert(allowInt || allowFloat); - var firstChar = contents.codeUnitAt(0); var length = contents.length; + if (length == 0) return null; - // Quick check for single digit integers. - if (allowInt && length == 1) { + var firstChar = contents.codeUnitAt(0); + + // Quick check for single digit numbers. + if (length == 1) { var value = firstChar - $0; - return value >= 0 && value <= 9 ? value : null; + if (value < 0 || value > 9) return null; + return allowInt ? value : value.toDouble(); } var secondChar = contents.codeUnitAt(1);
diff --git a/pkgs/yaml/lib/src/parser.dart b/pkgs/yaml/lib/src/parser.dart index 5141a19..c89a956 100644 --- a/pkgs/yaml/lib/src/parser.dart +++ b/pkgs/yaml/lib/src/parser.dart
@@ -78,10 +78,6 @@ return _parseDocumentEnd(); case _State.BLOCK_NODE: return _parseNode(block: true); - case _State.BLOCK_NODE_OR_INDENTLESS_SEQUENCE: - return _parseNode(block: true, indentlessSequence: true); - case _State.FLOW_NODE: - return _parseNode(); case _State.BLOCK_SEQUENCE_FIRST_ENTRY: // Scan past the `BLOCK-SEQUENCE-FIRST-ENTRY` token to the // `BLOCK-SEQUENCE-ENTRY` token. @@ -299,7 +295,7 @@ throw YamlException('Undefined tag handle.', tagToken!.span); } - tag = tagDirective.prefix + (tagToken?.suffix ?? ''); + tag = tagDirective.prefix + tagToken!.suffix; } } @@ -757,13 +753,6 @@ /// Expect a block node. static const BLOCK_NODE = _State('BLOCK_NODE'); - /// Expect a block node or indentless sequence. - static const BLOCK_NODE_OR_INDENTLESS_SEQUENCE = - _State('BLOCK_NODE_OR_INDENTLESS_SEQUENCE'); - - /// Expect a flow node. - static const FLOW_NODE = _State('FLOW_NODE'); - /// Expect the first entry of a block sequence. static const BLOCK_SEQUENCE_FIRST_ENTRY = _State('BLOCK_SEQUENCE_FIRST_ENTRY');
diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart index 2f7055e..197ac01 100644 --- a/pkgs/yaml/lib/src/scanner.dart +++ b/pkgs/yaml/lib/src/scanner.dart
@@ -157,6 +157,13 @@ /// parser to tell that the key is intended to be a mapping key. final _simpleKeys = <_SimpleKey?>[null]; + /// The first live key in [_simpleKeys], or `null` if there is none. + /// + /// Keys are saved in increasing token order by flow level, so this is the + /// live key with the smallest token number. Tracking it avoids walking every + /// open flow level for each token. + _SimpleKey? _earliestSimpleKey; + /// The current indentation level. int get _indent => _indentLevels.last.column; @@ -234,13 +241,13 @@ /// Whether the character at the current position is a hexidecimal /// digit. - bool get _isHex { - var char = _scanner.peekChar(); - if (char == null) return false; - return (char >= NUMBER_0 && char <= NUMBER_9) || - (char >= LETTER_A && char <= LETTER_F) || - (char >= LETTER_CAP_A && char <= LETTER_CAP_F); - } + bool get _isHex => _isHexChar(_scanner.peekChar()); + + bool _isHexChar(int? char) => + char != null && + ((char >= NUMBER_0 && char <= NUMBER_9) || + (char >= LETTER_A && char <= LETTER_F) || + (char >= LETTER_CAP_A && char <= LETTER_CAP_F)); /// Whether the character at the current position is a plain character. /// @@ -328,10 +335,7 @@ // If the current token could be a simple key, we need to scan more // tokens until we determine whether it is or not. Otherwise we might // not emit the `KEY` token before we emit the value of the key. - if (!_simpleKeys - .any((key) => key != null && key.tokenNumber == _tokensParsed)) { - break; - } + if (_earliestSimpleKey?.tokenNumber != _tokensParsed) break; } _fetchNextToken(); @@ -470,61 +474,53 @@ /// Checks the list of potential simple keys and remove the positions that /// cannot contain simple keys anymore. void _staleSimpleKeys() { - for (var i = 0; i < _simpleKeys.length; i++) { - var key = _simpleKeys[i]; - if (key == null) continue; + // Simple keys are only staled in the block context, where there is a + // single level. + if (!_inBlockContext) return; + var key = _simpleKeys.single; + if (key == null) return; - // libyaml requires that all simple keys be a single line and no longer - // than 1024 characters. However, in section 7.4.2 of the spec - // (http://yaml.org/spec/1.2/spec.html#id2790832), these restrictions are - // only applied when the curly braces are omitted. It's difficult to - // retain enough context to know which keys need to have the restriction - // placed on them, so for now we go the other direction and allow - // everything but multiline simple keys in a block context. - if (!_inBlockContext) continue; + // libyaml requires that all simple keys be a single line and no longer + // than 1024 characters. However, in section 7.4.2 of the spec + // (http://yaml.org/spec/1.2/spec.html#id2790832), these restrictions are + // only applied when the curly braces are omitted. It's difficult to + // retain enough context to know which keys need to have the restriction + // placed on them, so for now we go the other direction and allow + // everything but multiline simple keys in a block context. + if (key.line == _scanner.line) return; - if (key.line == _scanner.line) continue; - - if (key.required) { - final keyIndentIdx = _indentLevels - .lastIndexWhere((indent) => indent.column == key.column); - final inBlockSequence = keyIndentIdx >= 0 && - _indentLevels[keyIndentIdx].type == TokenType.blockSequenceStart; - final message = StringBuffer("Expected ':'."); - if (inBlockSequence) { - message.write(" If this is a list entry, it must start with '- '."); - } - _reportError(YamlException(message.toString(), _scanner.emptySpan)); - _tokens.insert(key.tokenNumber - _tokensParsed, - Token(TokenType.key, key.location.pointSpan() as FileSpan)); + if (key.required) { + final inBlockSequence = + _indentLevels.last.type == TokenType.blockSequenceStart; + final message = StringBuffer("Expected ':'."); + if (inBlockSequence) { + message.write(" If this is a list entry, it must start with '- '."); } - - _simpleKeys[i] = null; + _reportError(YamlException(message.toString(), _scanner.emptySpan)); + _tokens.insert(key.tokenNumber - _tokensParsed, + Token(TokenType.key, key.location.pointSpan() as FileSpan)); } + + _clearLastSimpleKey(); } /// Checks if a simple key may start at the current position and saves it if /// so. void _saveSimpleKey() { + if (!_simpleKeyAllowed) return; + // A simple key is required at the current position if the scanner is in the // block context and the current column coincides with the indentation // level. var required = _inBlockContext && _indent == _scanner.column; - // A simple key is required only when it is the first token in the current - // line. Therefore it is always allowed. But we add a check anyway. - assert(_simpleKeyAllowed || !required); - - if (!_simpleKeyAllowed) return; - // If the current position may start a simple key, save it. _removeSimpleKey(); - _simpleKeys[_simpleKeys.length - 1] = _SimpleKey( - _tokensParsed + _tokens.length, - _scanner.line, - _scanner.column, - _scanner.location, + final key = _SimpleKey(_tokensParsed + _tokens.length, _scanner.line, + _scanner.column, _scanner.location, required: required); + _simpleKeys[_simpleKeys.length - 1] = key; + _earliestSimpleKey ??= key; } /// Removes a potential simple key at the current flow level. @@ -535,6 +531,14 @@ key.location.pointSpan()); } + _clearLastSimpleKey(); + } + + /// Clears the key at the current flow level. + void _clearLastSimpleKey() { + if (identical(_simpleKeys.last, _earliestSimpleKey)) { + _earliestSimpleKey = null; + } _simpleKeys[_simpleKeys.length - 1] = null; } @@ -546,6 +550,9 @@ /// Decreases the flow level. void _decreaseFlowLevel() { if (_inBlockContext) return; + if (identical(_simpleKeys.last, _earliestSimpleKey)) { + _earliestSimpleKey = null; + } _simpleKeys.removeLast(); } @@ -712,7 +719,7 @@ tokenNumber: simpleKey.tokenNumber); // Remove the simple key. - _simpleKeys[_simpleKeys.length - 1] = null; + _clearLastSimpleKey(); // A simple key cannot follow another simple key. _simpleKeyAllowed = false; @@ -966,14 +973,9 @@ var next = _scanner.peekChar(); if (name.isEmpty || (!_isBlankOrEnd && - next != QUESTION && - next != COLON && next != COMMA && next != RIGHT_SQUARE && - next != RIGHT_CURLY && - next != PERCENT && - next != AT && - next != GRAVE_ACCENT)) { + next != RIGHT_CURLY)) { throw YamlException( 'Expected alphanumeric character.', _scanner.emptySpan); } @@ -1010,7 +1012,8 @@ if (handle.length > 1 && handle.startsWith('!') && handle.endsWith('!')) { suffix = _scanTagUri(flowSeparators: false); } else { - suffix = _scanTagUri(head: handle, flowSeparators: false); + suffix = + _scanTagUri(head: handle, headStart: start, flowSeparators: false); // There was no explicit handle. if (suffix.isEmpty) { @@ -1060,7 +1063,8 @@ /// [head] is the initial portion of the tag that's already been scanned. /// [flowSeparators] indicates whether the tag URI can contain flow /// separators. - String _scanTagUri({String? head, bool flowSeparators = true}) { + String _scanTagUri( + {String? head, LineScannerState? headStart, bool flowSeparators = true}) { var length = head == null ? 0 : head.length; var buffer = StringBuffer(); @@ -1077,6 +1081,7 @@ // // In a shorthand tag annotation, the flow separators ',', '[', and ']' are // disallowed. + var startState = headStart ?? _scanner.state; var start = _scanner.position; var char = _scanner.peekChar(); while (_isTagChar || @@ -1086,8 +1091,31 @@ char = _scanner.peekChar(); } + buffer.write(_scanner.substring(start)); + // libyaml manually decodes the URL, but we don't have to do that. - return Uri.decodeFull(_scanner.substring(start)); + return _decodeTagUri(buffer.toString(), _scanner.spanFrom(startState)); + } + + /// Decodes a percent-encoded tag [uri], throwing a [YamlException] at [span] + /// if it contains malformed percent-encoding or invalid UTF-8 bytes. + String _decodeTagUri(String uri, FileSpan span) { + for (var i = 0; i < uri.length; i++) { + if (uri.codeUnitAt(i) == PERCENT) { + if (i + 2 >= uri.length || + !_isHexChar(uri.codeUnitAt(i + 1)) || + !_isHexChar(uri.codeUnitAt(i + 2))) { + throw YamlException('Expected 2-digit hexadecimal number.', span); + } + i += 2; + } + } + + try { + return Uri.decodeFull(uri); + } on FormatException catch (error) { + throw YamlException(error.message, span); + } } /// Scans a block scalar. @@ -1608,8 +1636,7 @@ } bool _isStandardCharacterAt(int offset) { - var first = _scanner.peekChar(offset); - if (first == null) return false; + var first = _scanner.peekChar(offset)!; if (isHighSurrogate(first)) { var next = _scanner.peekChar(offset + 1);
diff --git a/pkgs/yaml/test/flow_nesting_performance_test.dart b/pkgs/yaml/test/flow_nesting_performance_test.dart new file mode 100644 index 0000000..60943f8 --- /dev/null +++ b/pkgs/yaml/test/flow_nesting_performance_test.dart
@@ -0,0 +1,67 @@ +// Copyright (c) 2026, the Dart project authors. +// Copyright (c) 2006, Kirill Simonov. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. + +@TestOn('vm') +library; + +import 'package:test/test.dart'; +import 'package:yaml/yaml.dart'; + +void main() { + const items = 100000; + + /// The fastest of a few loads, which is not thrown off by a GC pause or a + /// busy machine, after a warm-up load so the JIT has optimized the scanner. + int millisecondsToLoad(String text) { + loadYaml(text); + var fastest = 1 << 30; + for (var i = 0; i < 3; i++) { + final stopwatch = Stopwatch()..start(); + loadYaml(text); + final elapsed = stopwatch.elapsedMilliseconds; + if (elapsed < fastest) fastest = elapsed; + } + return fastest; + } + + // Before the fix the scanner walked every open flow level for each token, so + // the document nested 1000 levels deep took about 6 times longer to scan + // than the same scalars at depth 1; now the two take about the same time. + void expectDepthDoesNotMatter(String Function(int depth) document) { + final shallow = millisecondsToLoad(document(1)); + final deep = millisecondsToLoad(document(1000)); + expect(deep, lessThan(shallow * 3 + 50)); + } + + test('scanning flow sequences does not depend on nesting depth', () { + final scalars = List.filled(items, '1').join(','); + expectDepthDoesNotMatter( + (depth) => '${'[' * depth}$scalars${']' * depth}', + ); + }); + + test('scanning flow mapping values does not depend on nesting depth', () { + final pairs = List.generate(items, (i) => 'k$i: 1').join(','); + expectDepthDoesNotMatter( + (depth) => '${'{a: ' * depth}{$pairs}${'}' * depth}', + ); + }); + + test('nested flow collections still load as the same structure', () { + expect(loadYaml('[[a, {b: [c]}], {d: [e, f]}]'), [ + [ + 'a', + { + 'b': ['c'] + } + ], + { + 'd': ['e', 'f'] + }, + ]); + }); +}
diff --git a/pkgs/yaml/test/yaml_test.dart b/pkgs/yaml/test/yaml_test.dart index 4f512c1..e987290 100644 --- a/pkgs/yaml/test/yaml_test.dart +++ b/pkgs/yaml/test/yaml_test.dart
@@ -1154,6 +1154,71 @@ First occurrence: &anchor Value Second occurrence: *anchor'''); }); + + test('rejects malformed percent-encoding in tag URIs with YamlException', + () { + for (var input in [ + '!<%> foo', + '!a!% foo', + '%TAG ! tag:%\n---\n!foo bar', + '!% foo', + '!<%GG> foo', + ]) { + expect(() => loadYaml(input), throwsYamlException); + expect(() => loadYamlNode(input), throwsYamlException); + } + }); + + test( + 'rejects invalid UTF-8 percent-encoding in tag URIs with YamlException', + () { + for (var input in [ + '!<%C3%28> foo', + '!%C3%28 foo', + ]) { + expect(() => loadYaml(input), throwsYamlException); + expect(() => loadYamlNode(input), throwsYamlException); + } + }); + + test('rejects undefined local tags with YamlException', () { + for (var input in [ + '!custom 123', + '!<custom> 123', + ]) { + expect(() => loadYaml(input), throwsYamlException); + expect(() => loadYamlNode(input), throwsYamlException); + } + + // When %TAG ! is mapped to the standard YAML tag prefix, shorthand !str + // and !int tags resolve through the primary handle. + expectYamlLoads(['12', 12], ''' + %TAG ! tag:yaml.org,2002: + --- + - !str 12 + - !int "12"'''); + }); + + test('handles block sequence, simple key, and CRLF edge cases cleanly', () { + for (var input in [ + '- :?\t-\r:', + 'a: "\r\n:', + ]) { + expect(() => loadYaml(input), throwsYamlException); + expect(() => loadYamlNode(input), throwsYamlException); + } + + expect( + loadYaml('?\r-'), + deepEquals(deepEqualsMap({ + [null]: null + }))); + expect(loadYamlNode('?\r-'), isA<YamlMap>()); + expect(loadYaml('-\n...'), equals([null])); + expect(loadYamlNode('-\n...'), isA<YamlList>()); + expect(loadYaml(':?\t'), equals(':?')); + expect(loadYamlNode(':?\t'), isA<YamlScalar>()); + }); }); // Chapter 7: Flow Styles @@ -1941,7 +2006,36 @@ positive: !!float 2.3e4 infinity: !!float .inf not a number: !!float .nan'''); - }, skip: 'Fails for single digit float'); + }); + + test('rejects empty and invalid 1-character !!int and !!float scalars', () { + for (var input in [ + '!!int', + '!!int ""', + '- !!int\n', + '!!float', + '!!float ""', + '- !!float\n', + '!!float a', + '!!float .', + '!!float -', + ]) { + expect(() => loadYaml(input), throwsYamlException); + expect(() => loadYamlNode(input), throwsYamlException); + } + }); + + test( + 'rejects unseparated content after a multiline quoted scalar at block ' + 'indent', () { + for (var input in [ + ' a: "\n"b', + " a: '\n'b", + ]) { + expect(() => loadYaml(input), throwsYamlException); + expect(() => loadYamlNode(input), throwsYamlException); + } + }); test('[Example 10.8]', () { expectYamlStreamLoads([
diff --git a/pkgs/yaml/test/yaml_test_suite_test.dart b/pkgs/yaml/test/yaml_test_suite_test.dart index a538d22..1debbae 100644 --- a/pkgs/yaml/test/yaml_test_suite_test.dart +++ b/pkgs/yaml/test/yaml_test_suite_test.dart
@@ -59,7 +59,6 @@ 'DK95-0', 'DK95-1', 'DK95-4', - 'LHL4-0', 'ZXT5-0', 'P76L-0', '9JBA-0', @@ -72,9 +71,24 @@ 'ZYU8-2', 'RHX7-0', '2XXW-0', - '9HCY-0', 'KS4U-0', 'Z9M4-0', 'EB22-0', '3HFZ-0', + // These cases use custom local or %TAG-mapped tags (!foo, !local, !shape, + // etc.), which Loader intentionally rejects as undefined tags (see + // yaml_test.dart Examples 2.24, 5.6, 6.18, and 8.21). They previously passed + // only because Scanner._scanTagUri dropped the scanned tag head and rewrote + // shorthand '!tag' tokens to the non-specific '!' tag. + // Note: LHL4-0 ('!invalid{}tag scalar') and 9HCY-0 (missing '...' before + // '%TAG' after '!foo "bar"') were removed from _expectedFailures for the + // same reason: their 'fail: true' expectation is now satisfied by Loader + // rejecting '!invalid' / '!foo', even though the scanner/parser still does + // not reject the underlying syntax error. + '6WLZ-0', + '9WXW-0', + 'C4HZ-0', + 'CUP7-0', + 'M5C3-0', + 'Z67P-0', ];