From 453fc2059e297dda01017900bbe302ab2aed1e12 Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Fri, 4 Sep 2026 07:54:11 +0900 Subject: [PATCH 01/10] ssl: read the OID table out of OpenSSL's object database `txt2obj` and `nid2obj` have to answer with OpenSSL's own numbers, and the table behind them was 39 entries transcribed by hand, so every object outside that set was reported unknown. Read OpenSSL's own files instead: `obj_mac.num` carries each object's NID and `objects.txt` carries its OID, short name and description, and the identifier `objects.pl` derives per object -- the `!Cname` override, else the description, else the short name, each qualified by the enclosing `!module` with `-` spelled `_` -- joins the two. `OidEntry`, `OidTable` and the `find_by_*` functions keep their shape, so `ssl.rs` only changes where an object has no OID to report. Three details the object database settles that a curated table did not have to: - an object written with one name carries it as both, so `nid2obj(48)` is `('emailAddress', 'emailAddress', ...)`; - an object need not have an OID at all -- `DES-EDE3` and 139 other algorithm names have a NID and nothing to encode -- so the fourth field of the tuple is None for those, as it is on OpenSSL; - one arc does not encode, since DER packs the first two into a byte, so the bare roots `iso` and `itu-t` are OID-less too, while two arcs such as X500's `2.5` are a real object. Checked against `_ssl.nid2obj` on CPython built with OpenSSL, over every NID it answers: 1387 of its 1390 present, with no disagreement on any of them, up from 39. The three absent are OpenSSL's unnamed placeholder slots, which it reports as ('NULL', 'NULL', None). The data files come from openssl/openssl `crypto/objects/`, via the rustls integration rewrite in #8007. Co-authored-by: Ivan Mironov Assisted-by: Claude --- crates/stdlib/rustls-data/obj_mac.num | 1501 ++++++++++++++++++ crates/stdlib/rustls-data/objects.txt | 2069 +++++++++++++++++++++++++ crates/stdlib/src/ssl.rs | 12 +- crates/stdlib/src/ssl/oid.rs | 506 +++--- 4 files changed, 3794 insertions(+), 294 deletions(-) create mode 100644 crates/stdlib/rustls-data/obj_mac.num create mode 100644 crates/stdlib/rustls-data/objects.txt diff --git a/crates/stdlib/rustls-data/obj_mac.num b/crates/stdlib/rustls-data/obj_mac.num new file mode 100644 index 00000000000..e72170b47f7 --- /dev/null +++ b/crates/stdlib/rustls-data/obj_mac.num @@ -0,0 +1,1501 @@ +undef 0 +rsadsi 1 +pkcs 2 +md2 3 +md5 4 +rc4 5 +rsaEncryption 6 +md2WithRSAEncryption 7 +md5WithRSAEncryption 8 +pbeWithMD2AndDES_CBC 9 +pbeWithMD5AndDES_CBC 10 +X500 11 +X509 12 +commonName 13 +countryName 14 +localityName 15 +stateOrProvinceName 16 +organizationName 17 +organizationalUnitName 18 +rsa 19 +pkcs7 20 +pkcs7_data 21 +pkcs7_signed 22 +pkcs7_enveloped 23 +pkcs7_signedAndEnveloped 24 +pkcs7_digest 25 +pkcs7_encrypted 26 +pkcs3 27 +dhKeyAgreement 28 +des_ecb 29 +des_cfb64 30 +des_cbc 31 +des_ede_ecb 32 +des_ede3_ecb 33 +idea_cbc 34 +idea_cfb64 35 +idea_ecb 36 +rc2_cbc 37 +rc2_ecb 38 +rc2_cfb64 39 +rc2_ofb64 40 +sha 41 +shaWithRSAEncryption 42 +des_ede_cbc 43 +des_ede3_cbc 44 +des_ofb64 45 +idea_ofb64 46 +pkcs9 47 +pkcs9_emailAddress 48 +pkcs9_unstructuredName 49 +pkcs9_contentType 50 +pkcs9_messageDigest 51 +pkcs9_signingTime 52 +pkcs9_countersignature 53 +pkcs9_challengePassword 54 +pkcs9_unstructuredAddress 55 +pkcs9_extCertAttributes 56 +netscape 57 +netscape_cert_extension 58 +netscape_data_type 59 +des_ede_cfb64 60 +des_ede3_cfb64 61 +des_ede_ofb64 62 +des_ede3_ofb64 63 +sha1 64 +sha1WithRSAEncryption 65 +dsaWithSHA 66 +dsa_2 67 +pbeWithSHA1AndRC2_CBC 68 +id_pbkdf2 69 +dsaWithSHA1_2 70 +netscape_cert_type 71 +netscape_base_url 72 +netscape_revocation_url 73 +netscape_ca_revocation_url 74 +netscape_renewal_url 75 +netscape_ca_policy_url 76 +netscape_ssl_server_name 77 +netscape_comment 78 +netscape_cert_sequence 79 +desx_cbc 80 +id_ce 81 +subject_key_identifier 82 +key_usage 83 +private_key_usage_period 84 +subject_alt_name 85 +issuer_alt_name 86 +basic_constraints 87 +crl_number 88 +certificate_policies 89 +authority_key_identifier 90 +bf_cbc 91 +bf_ecb 92 +bf_cfb64 93 +bf_ofb64 94 +mdc2 95 +mdc2WithRSA 96 +rc4_40 97 +rc2_40_cbc 98 +givenName 99 +surname 100 +initials 101 +uniqueIdentifier 102 +crl_distribution_points 103 +md5WithRSA 104 +serialNumber 105 +title 106 +description 107 +cast5_cbc 108 +cast5_ecb 109 +cast5_cfb64 110 +cast5_ofb64 111 +pbeWithMD5AndCast5_CBC 112 +dsaWithSHA1 113 +md5_sha1 114 +sha1WithRSA 115 +dsa 116 +ripemd160 117 +ripemd160WithRSA 119 +rc5_cbc 120 +rc5_ecb 121 +rc5_cfb64 122 +rc5_ofb64 123 +rle_compression 124 +zlib_compression 125 +ext_key_usage 126 +id_pkix 127 +id_kp 128 +server_auth 129 +client_auth 130 +code_sign 131 +email_protect 132 +time_stamp 133 +ms_code_ind 134 +ms_code_com 135 +ms_ctl_sign 136 +ms_sgc 137 +ms_efs 138 +ns_sgc 139 +delta_crl 140 +crl_reason 141 +invalidity_date 142 +sxnet 143 +pbe_WithSHA1And128BitRC4 144 +pbe_WithSHA1And40BitRC4 145 +pbe_WithSHA1And3_Key_TripleDES_CBC 146 +pbe_WithSHA1And2_Key_TripleDES_CBC 147 +pbe_WithSHA1And128BitRC2_CBC 148 +pbe_WithSHA1And40BitRC2_CBC 149 +keyBag 150 +pkcs8ShroudedKeyBag 151 +certBag 152 +crlBag 153 +secretBag 154 +safeContentsBag 155 +friendlyName 156 +localKeyID 157 +x509Certificate 158 +sdsiCertificate 159 +x509Crl 160 +pbes2 161 +pbmac1 162 +hmacWithSHA1 163 +id_qt_cps 164 +id_qt_unotice 165 +rc2_64_cbc 166 +SMIMECapabilities 167 +pbeWithMD2AndRC2_CBC 168 +pbeWithMD5AndRC2_CBC 169 +pbeWithSHA1AndDES_CBC 170 +ms_ext_req 171 +ext_req 172 +name 173 +dnQualifier 174 +id_pe 175 +id_ad 176 +info_access 177 +ad_OCSP 178 +ad_ca_issuers 179 +OCSP_sign 180 +iso 181 +member_body 182 +ISO_US 183 +X9_57 184 +X9cm 185 +pkcs1 186 +pkcs5 187 +SMIME 188 +id_smime_mod 189 +id_smime_ct 190 +id_smime_aa 191 +id_smime_alg 192 +id_smime_cd 193 +id_smime_spq 194 +id_smime_cti 195 +id_smime_mod_cms 196 +id_smime_mod_ess 197 +id_smime_mod_oid 198 +id_smime_mod_msg_v3 199 +id_smime_mod_ets_eSignature_88 200 +id_smime_mod_ets_eSignature_97 201 +id_smime_mod_ets_eSigPolicy_88 202 +id_smime_mod_ets_eSigPolicy_97 203 +id_smime_ct_receipt 204 +id_smime_ct_authData 205 +id_smime_ct_publishCert 206 +id_smime_ct_TSTInfo 207 +id_smime_ct_TDTInfo 208 +id_smime_ct_contentInfo 209 +id_smime_ct_DVCSRequestData 210 +id_smime_ct_DVCSResponseData 211 +id_smime_aa_receiptRequest 212 +id_smime_aa_securityLabel 213 +id_smime_aa_mlExpandHistory 214 +id_smime_aa_contentHint 215 +id_smime_aa_msgSigDigest 216 +id_smime_aa_encapContentType 217 +id_smime_aa_contentIdentifier 218 +id_smime_aa_macValue 219 +id_smime_aa_equivalentLabels 220 +id_smime_aa_contentReference 221 +id_smime_aa_encrypKeyPref 222 +id_smime_aa_signingCertificate 223 +id_smime_aa_smimeEncryptCerts 224 +id_smime_aa_timeStampToken 225 +id_smime_aa_ets_sigPolicyId 226 +id_smime_aa_ets_commitmentType 227 +id_smime_aa_ets_signerLocation 228 +id_smime_aa_ets_signerAttr 229 +id_smime_aa_ets_otherSigCert 230 +id_smime_aa_ets_contentTimestamp 231 +id_smime_aa_ets_CertificateRefs 232 +id_smime_aa_ets_RevocationRefs 233 +id_smime_aa_ets_certValues 234 +id_smime_aa_ets_revocationValues 235 +id_smime_aa_ets_escTimeStamp 236 +id_smime_aa_ets_certCRLTimestamp 237 +id_smime_aa_ets_archiveTimeStamp 238 +id_smime_aa_signatureType 239 +id_smime_aa_dvcs_dvc 240 +id_smime_alg_ESDHwith3DES 241 +id_smime_alg_ESDHwithRC2 242 +id_smime_alg_3DESwrap 243 +id_smime_alg_RC2wrap 244 +id_smime_alg_ESDH 245 +id_smime_alg_CMS3DESwrap 246 +id_smime_alg_CMSRC2wrap 247 +id_smime_cd_ldap 248 +id_smime_spq_ets_sqt_uri 249 +id_smime_spq_ets_sqt_unotice 250 +id_smime_cti_ets_proofOfOrigin 251 +id_smime_cti_ets_proofOfReceipt 252 +id_smime_cti_ets_proofOfDelivery 253 +id_smime_cti_ets_proofOfSender 254 +id_smime_cti_ets_proofOfApproval 255 +id_smime_cti_ets_proofOfCreation 256 +md4 257 +id_pkix_mod 258 +id_qt 259 +id_it 260 +id_pkip 261 +id_alg 262 +id_cmc 263 +id_on 264 +id_pda 265 +id_aca 266 +id_qcs 267 +id_cct 268 +id_pkix1_explicit_88 269 +id_pkix1_implicit_88 270 +id_pkix1_explicit_93 271 +id_pkix1_implicit_93 272 +id_mod_crmf 273 +id_mod_cmc 274 +id_mod_kea_profile_88 275 +id_mod_kea_profile_93 276 +id_mod_cmp 277 +id_mod_qualified_cert_88 278 +id_mod_qualified_cert_93 279 +id_mod_attribute_cert 280 +id_mod_timestamp_protocol 281 +id_mod_ocsp 282 +id_mod_dvcs 283 +id_mod_cmp2000 284 +biometricInfo 285 +qcStatements 286 +ac_auditIdentity 287 +ac_targeting 288 +aaControls 289 +sbgp_ipAddrBlock 290 +sbgp_autonomousSysNum 291 +sbgp_routerIdentifier 292 +textNotice 293 +ipsecEndSystem 294 +ipsecTunnel 295 +ipsecUser 296 +dvcs 297 +id_it_caProtEncCert 298 +id_it_signKeyPairTypes 299 +id_it_encKeyPairTypes 300 +id_it_preferredSymmAlg 301 +id_it_caKeyUpdateInfo 302 +id_it_currentCRL 303 +id_it_unsupportedOIDs 304 +id_it_subscriptionRequest 305 +id_it_subscriptionResponse 306 +id_it_keyPairParamReq 307 +id_it_keyPairParamRep 308 +id_it_revPassphrase 309 +id_it_implicitConfirm 310 +id_it_confirmWaitTime 311 +id_it_origPKIMessage 312 +id_regCtrl 313 +id_regInfo 314 +id_regCtrl_regToken 315 +id_regCtrl_authenticator 316 +id_regCtrl_pkiPublicationInfo 317 +id_regCtrl_pkiArchiveOptions 318 +id_regCtrl_oldCertID 319 +id_regCtrl_protocolEncrKey 320 +id_regInfo_utf8Pairs 321 +id_regInfo_certReq 322 +id_alg_des40 323 +id_alg_noSignature 324 +id_alg_dh_sig_hmac_sha1 325 +id_alg_dh_pop 326 +id_cmc_statusInfo 327 +id_cmc_identification 328 +id_cmc_identityProof 329 +id_cmc_dataReturn 330 +id_cmc_transactionId 331 +id_cmc_senderNonce 332 +id_cmc_recipientNonce 333 +id_cmc_addExtensions 334 +id_cmc_encryptedPOP 335 +id_cmc_decryptedPOP 336 +id_cmc_lraPOPWitness 337 +id_cmc_getCert 338 +id_cmc_getCRL 339 +id_cmc_revokeRequest 340 +id_cmc_regInfo 341 +id_cmc_responseInfo 342 +id_cmc_queryPending 343 +id_cmc_popLinkRandom 344 +id_cmc_popLinkWitness 345 +id_cmc_confirmCertAcceptance 346 +id_on_personalData 347 +id_pda_dateOfBirth 348 +id_pda_placeOfBirth 349 +id_pda_pseudonym 350 +id_pda_gender 351 +id_pda_countryOfCitizenship 352 +id_pda_countryOfResidence 353 +id_aca_authenticationInfo 354 +id_aca_accessIdentity 355 +id_aca_chargingIdentity 356 +id_aca_group 357 +id_aca_role 358 +id_qcs_pkixQCSyntax_v1 359 +id_cct_crs 360 +id_cct_PKIData 361 +id_cct_PKIResponse 362 +ad_timeStamping 363 +ad_dvcs 364 +id_pkix_OCSP_basic 365 +id_pkix_OCSP_Nonce 366 +id_pkix_OCSP_CrlID 367 +id_pkix_OCSP_acceptableResponses 368 +id_pkix_OCSP_noCheck 369 +id_pkix_OCSP_archiveCutoff 370 +id_pkix_OCSP_serviceLocator 371 +id_pkix_OCSP_extendedStatus 372 +id_pkix_OCSP_valid 373 +id_pkix_OCSP_path 374 +id_pkix_OCSP_trustRoot 375 +algorithm 376 +rsaSignature 377 +X500algorithms 378 +org 379 +dod 380 +iana 381 +Directory 382 +Management 383 +Experimental 384 +Private 385 +Security 386 +SNMPv2 387 +Mail 388 +Enterprises 389 +dcObject 390 +domainComponent 391 +Domain 392 +joint_iso_ccitt 393 +selected_attribute_types 394 +clearance 395 +md4WithRSAEncryption 396 +ac_proxying 397 +sinfo_access 398 +id_aca_encAttrs 399 +role 400 +policy_constraints 401 +target_information 402 +no_rev_avail 403 +ccitt 404 +ansi_X9_62 405 +X9_62_prime_field 406 +X9_62_characteristic_two_field 407 +X9_62_id_ecPublicKey 408 +X9_62_prime192v1 409 +X9_62_prime192v2 410 +X9_62_prime192v3 411 +X9_62_prime239v1 412 +X9_62_prime239v2 413 +X9_62_prime239v3 414 +X9_62_prime256v1 415 +ecdsa_with_SHA1 416 +ms_csp_name 417 +aes_128_ecb 418 +aes_128_cbc 419 +aes_128_ofb128 420 +aes_128_cfb128 421 +aes_192_ecb 422 +aes_192_cbc 423 +aes_192_ofb128 424 +aes_192_cfb128 425 +aes_256_ecb 426 +aes_256_cbc 427 +aes_256_ofb128 428 +aes_256_cfb128 429 +hold_instruction_code 430 +hold_instruction_none 431 +hold_instruction_call_issuer 432 +hold_instruction_reject 433 +data 434 +pss 435 +ucl 436 +pilot 437 +pilotAttributeType 438 +pilotAttributeSyntax 439 +pilotObjectClass 440 +pilotGroups 441 +iA5StringSyntax 442 +caseIgnoreIA5StringSyntax 443 +pilotObject 444 +pilotPerson 445 +account 446 +document 447 +room 448 +documentSeries 449 +rFC822localPart 450 +dNSDomain 451 +domainRelatedObject 452 +friendlyCountry 453 +simpleSecurityObject 454 +pilotOrganization 455 +pilotDSA 456 +qualityLabelledData 457 +userId 458 +textEncodedORAddress 459 +rfc822Mailbox 460 +info 461 +favouriteDrink 462 +roomNumber 463 +photo 464 +userClass 465 +host 466 +manager 467 +documentIdentifier 468 +documentTitle 469 +documentVersion 470 +documentAuthor 471 +documentLocation 472 +homeTelephoneNumber 473 +secretary 474 +otherMailbox 475 +lastModifiedTime 476 +lastModifiedBy 477 +aRecord 478 +pilotAttributeType27 479 +mXRecord 480 +nSRecord 481 +sOARecord 482 +cNAMERecord 483 +associatedDomain 484 +associatedName 485 +homePostalAddress 486 +personalTitle 487 +mobileTelephoneNumber 488 +pagerTelephoneNumber 489 +friendlyCountryName 490 +organizationalStatus 491 +janetMailbox 492 +mailPreferenceOption 493 +buildingName 494 +dSAQuality 495 +singleLevelQuality 496 +subtreeMinimumQuality 497 +subtreeMaximumQuality 498 +personalSignature 499 +dITRedirect 500 +audio 501 +documentPublisher 502 +x500UniqueIdentifier 503 +mime_mhs 504 +mime_mhs_headings 505 +mime_mhs_bodies 506 +id_hex_partial_message 507 +id_hex_multipart_message 508 +generationQualifier 509 +pseudonym 510 +InternationalRA 511 +id_set 512 +set_ctype 513 +set_msgExt 514 +set_attr 515 +set_policy 516 +set_certExt 517 +set_brand 518 +setct_PANData 519 +setct_PANToken 520 +setct_PANOnly 521 +setct_OIData 522 +setct_PI 523 +setct_PIData 524 +setct_PIDataUnsigned 525 +setct_HODInput 526 +setct_AuthResBaggage 527 +setct_AuthRevReqBaggage 528 +setct_AuthRevResBaggage 529 +setct_CapTokenSeq 530 +setct_PInitResData 531 +setct_PI_TBS 532 +setct_PResData 533 +setct_AuthReqTBS 534 +setct_AuthResTBS 535 +setct_AuthResTBSX 536 +setct_AuthTokenTBS 537 +setct_CapTokenData 538 +setct_CapTokenTBS 539 +setct_AcqCardCodeMsg 540 +setct_AuthRevReqTBS 541 +setct_AuthRevResData 542 +setct_AuthRevResTBS 543 +setct_CapReqTBS 544 +setct_CapReqTBSX 545 +setct_CapResData 546 +setct_CapRevReqTBS 547 +setct_CapRevReqTBSX 548 +setct_CapRevResData 549 +setct_CredReqTBS 550 +setct_CredReqTBSX 551 +setct_CredResData 552 +setct_CredRevReqTBS 553 +setct_CredRevReqTBSX 554 +setct_CredRevResData 555 +setct_PCertReqData 556 +setct_PCertResTBS 557 +setct_BatchAdminReqData 558 +setct_BatchAdminResData 559 +setct_CardCInitResTBS 560 +setct_MeAqCInitResTBS 561 +setct_RegFormResTBS 562 +setct_CertReqData 563 +setct_CertReqTBS 564 +setct_CertResData 565 +setct_CertInqReqTBS 566 +setct_ErrorTBS 567 +setct_PIDualSignedTBE 568 +setct_PIUnsignedTBE 569 +setct_AuthReqTBE 570 +setct_AuthResTBE 571 +setct_AuthResTBEX 572 +setct_AuthTokenTBE 573 +setct_CapTokenTBE 574 +setct_CapTokenTBEX 575 +setct_AcqCardCodeMsgTBE 576 +setct_AuthRevReqTBE 577 +setct_AuthRevResTBE 578 +setct_AuthRevResTBEB 579 +setct_CapReqTBE 580 +setct_CapReqTBEX 581 +setct_CapResTBE 582 +setct_CapRevReqTBE 583 +setct_CapRevReqTBEX 584 +setct_CapRevResTBE 585 +setct_CredReqTBE 586 +setct_CredReqTBEX 587 +setct_CredResTBE 588 +setct_CredRevReqTBE 589 +setct_CredRevReqTBEX 590 +setct_CredRevResTBE 591 +setct_BatchAdminReqTBE 592 +setct_BatchAdminResTBE 593 +setct_RegFormReqTBE 594 +setct_CertReqTBE 595 +setct_CertReqTBEX 596 +setct_CertResTBE 597 +setct_CRLNotificationTBS 598 +setct_CRLNotificationResTBS 599 +setct_BCIDistributionTBS 600 +setext_genCrypt 601 +setext_miAuth 602 +setext_pinSecure 603 +setext_pinAny 604 +setext_track2 605 +setext_cv 606 +set_policy_root 607 +setCext_hashedRoot 608 +setCext_certType 609 +setCext_merchData 610 +setCext_cCertRequired 611 +setCext_tunneling 612 +setCext_setExt 613 +setCext_setQualf 614 +setCext_PGWYcapabilities 615 +setCext_TokenIdentifier 616 +setCext_Track2Data 617 +setCext_TokenType 618 +setCext_IssuerCapabilities 619 +setAttr_Cert 620 +setAttr_PGWYcap 621 +setAttr_TokenType 622 +setAttr_IssCap 623 +set_rootKeyThumb 624 +set_addPolicy 625 +setAttr_Token_EMV 626 +setAttr_Token_B0Prime 627 +setAttr_IssCap_CVM 628 +setAttr_IssCap_T2 629 +setAttr_IssCap_Sig 630 +setAttr_GenCryptgrm 631 +setAttr_T2Enc 632 +setAttr_T2cleartxt 633 +setAttr_TokICCsig 634 +setAttr_SecDevSig 635 +set_brand_IATA_ATA 636 +set_brand_Diners 637 +set_brand_AmericanExpress 638 +set_brand_JCB 639 +set_brand_Visa 640 +set_brand_MasterCard 641 +set_brand_Novus 642 +des_cdmf 643 +rsaOAEPEncryptionSET 644 +itu_t 645 +joint_iso_itu_t 646 +international_organizations 647 +ms_smartcard_login 648 +ms_upn 649 +aes_128_cfb1 650 +aes_192_cfb1 651 +aes_256_cfb1 652 +aes_128_cfb8 653 +aes_192_cfb8 654 +aes_256_cfb8 655 +des_cfb1 656 +des_cfb8 657 +des_ede3_cfb1 658 +des_ede3_cfb8 659 +streetAddress 660 +postalCode 661 +id_ppl 662 +proxyCertInfo 663 +id_ppl_anyLanguage 664 +id_ppl_inheritAll 665 +name_constraints 666 +Independent 667 +sha256WithRSAEncryption 668 +sha384WithRSAEncryption 669 +sha512WithRSAEncryption 670 +sha224WithRSAEncryption 671 +sha256 672 +sha384 673 +sha512 674 +sha224 675 +identified_organization 676 +certicom_arc 677 +wap 678 +wap_wsg 679 +X9_62_id_characteristic_two_basis 680 +X9_62_onBasis 681 +X9_62_tpBasis 682 +X9_62_ppBasis 683 +X9_62_c2pnb163v1 684 +X9_62_c2pnb163v2 685 +X9_62_c2pnb163v3 686 +X9_62_c2pnb176v1 687 +X9_62_c2tnb191v1 688 +X9_62_c2tnb191v2 689 +X9_62_c2tnb191v3 690 +X9_62_c2onb191v4 691 +X9_62_c2onb191v5 692 +X9_62_c2pnb208w1 693 +X9_62_c2tnb239v1 694 +X9_62_c2tnb239v2 695 +X9_62_c2tnb239v3 696 +X9_62_c2onb239v4 697 +X9_62_c2onb239v5 698 +X9_62_c2pnb272w1 699 +X9_62_c2pnb304w1 700 +X9_62_c2tnb359v1 701 +X9_62_c2pnb368w1 702 +X9_62_c2tnb431r1 703 +secp112r1 704 +secp112r2 705 +secp128r1 706 +secp128r2 707 +secp160k1 708 +secp160r1 709 +secp160r2 710 +secp192k1 711 +secp224k1 712 +secp224r1 713 +secp256k1 714 +secp384r1 715 +secp521r1 716 +sect113r1 717 +sect113r2 718 +sect131r1 719 +sect131r2 720 +sect163k1 721 +sect163r1 722 +sect163r2 723 +sect193r1 724 +sect193r2 725 +sect233k1 726 +sect233r1 727 +sect239k1 728 +sect283k1 729 +sect283r1 730 +sect409k1 731 +sect409r1 732 +sect571k1 733 +sect571r1 734 +wap_wsg_idm_ecid_wtls1 735 +wap_wsg_idm_ecid_wtls3 736 +wap_wsg_idm_ecid_wtls4 737 +wap_wsg_idm_ecid_wtls5 738 +wap_wsg_idm_ecid_wtls6 739 +wap_wsg_idm_ecid_wtls7 740 +wap_wsg_idm_ecid_wtls8 741 +wap_wsg_idm_ecid_wtls9 742 +wap_wsg_idm_ecid_wtls10 743 +wap_wsg_idm_ecid_wtls11 744 +wap_wsg_idm_ecid_wtls12 745 +any_policy 746 +policy_mappings 747 +inhibit_any_policy 748 +ipsec3 749 +ipsec4 750 +camellia_128_cbc 751 +camellia_192_cbc 752 +camellia_256_cbc 753 +camellia_128_ecb 754 +camellia_192_ecb 755 +camellia_256_ecb 756 +camellia_128_cfb128 757 +camellia_192_cfb128 758 +camellia_256_cfb128 759 +camellia_128_cfb1 760 +camellia_192_cfb1 761 +camellia_256_cfb1 762 +camellia_128_cfb8 763 +camellia_192_cfb8 764 +camellia_256_cfb8 765 +camellia_128_ofb128 766 +camellia_192_ofb128 767 +camellia_256_ofb128 768 +subject_directory_attributes 769 +issuing_distribution_point 770 +certificate_issuer 771 +korea 772 +kisa 773 +kftc 774 +npki_alg 775 +seed_ecb 776 +seed_cbc 777 +seed_ofb128 778 +seed_cfb128 779 +hmac_md5 780 +hmac_sha1 781 +id_PasswordBasedMAC 782 +id_DHBasedMac 783 +id_it_suppLangTags 784 +caRepository 785 +id_smime_ct_compressedData 786 +id_ct_asciiTextWithCRLF 787 +id_aes128_wrap 788 +id_aes192_wrap 789 +id_aes256_wrap 790 +ecdsa_with_Recommended 791 +ecdsa_with_Specified 792 +ecdsa_with_SHA224 793 +ecdsa_with_SHA256 794 +ecdsa_with_SHA384 795 +ecdsa_with_SHA512 796 +hmacWithMD5 797 +hmacWithSHA224 798 +hmacWithSHA256 799 +hmacWithSHA384 800 +hmacWithSHA512 801 +dsa_with_SHA224 802 +dsa_with_SHA256 803 +whirlpool 804 +cryptopro 805 +cryptocom 806 +id_GostR3411_94_with_GostR3410_2001 807 +id_GostR3411_94_with_GostR3410_94 808 +id_GostR3411_94 809 +id_HMACGostR3411_94 810 +id_GostR3410_2001 811 +id_GostR3410_94 812 +id_Gost28147_89 813 +gost89_cnt 814 +id_Gost28147_89_MAC 815 +id_GostR3411_94_prf 816 +id_GostR3410_2001DH 817 +id_GostR3410_94DH 818 +id_Gost28147_89_CryptoPro_KeyMeshing 819 +id_Gost28147_89_None_KeyMeshing 820 +id_GostR3411_94_TestParamSet 821 +id_GostR3411_94_CryptoProParamSet 822 +id_Gost28147_89_TestParamSet 823 +id_Gost28147_89_CryptoPro_A_ParamSet 824 +id_Gost28147_89_CryptoPro_B_ParamSet 825 +id_Gost28147_89_CryptoPro_C_ParamSet 826 +id_Gost28147_89_CryptoPro_D_ParamSet 827 +id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet 828 +id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet 829 +id_Gost28147_89_CryptoPro_RIC_1_ParamSet 830 +id_GostR3410_94_TestParamSet 831 +id_GostR3410_94_CryptoPro_A_ParamSet 832 +id_GostR3410_94_CryptoPro_B_ParamSet 833 +id_GostR3410_94_CryptoPro_C_ParamSet 834 +id_GostR3410_94_CryptoPro_D_ParamSet 835 +id_GostR3410_94_CryptoPro_XchA_ParamSet 836 +id_GostR3410_94_CryptoPro_XchB_ParamSet 837 +id_GostR3410_94_CryptoPro_XchC_ParamSet 838 +id_GostR3410_2001_TestParamSet 839 +id_GostR3410_2001_CryptoPro_A_ParamSet 840 +id_GostR3410_2001_CryptoPro_B_ParamSet 841 +id_GostR3410_2001_CryptoPro_C_ParamSet 842 +id_GostR3410_2001_CryptoPro_XchA_ParamSet 843 +id_GostR3410_2001_CryptoPro_XchB_ParamSet 844 +id_GostR3410_94_a 845 +id_GostR3410_94_aBis 846 +id_GostR3410_94_b 847 +id_GostR3410_94_bBis 848 +id_Gost28147_89_cc 849 +id_GostR3410_94_cc 850 +id_GostR3410_2001_cc 851 +id_GostR3411_94_with_GostR3410_94_cc 852 +id_GostR3411_94_with_GostR3410_2001_cc 853 +id_GostR3410_2001_ParamSet_cc 854 +hmac 855 +LocalKeySet 856 +freshest_crl 857 +id_on_permanentIdentifier 858 +searchGuide 859 +businessCategory 860 +postalAddress 861 +postOfficeBox 862 +physicalDeliveryOfficeName 863 +telephoneNumber 864 +telexNumber 865 +teletexTerminalIdentifier 866 +facsimileTelephoneNumber 867 +x121Address 868 +internationaliSDNNumber 869 +registeredAddress 870 +destinationIndicator 871 +preferredDeliveryMethod 872 +presentationAddress 873 +supportedApplicationContext 874 +member 875 +owner 876 +roleOccupant 877 +seeAlso 878 +userPassword 879 +userCertificate 880 +cACertificate 881 +authorityRevocationList 882 +certificateRevocationList 883 +crossCertificatePair 884 +enhancedSearchGuide 885 +protocolInformation 886 +distinguishedName 887 +uniqueMember 888 +houseIdentifier 889 +supportedAlgorithms 890 +deltaRevocationList 891 +dmdName 892 +id_alg_PWRI_KEK 893 +cmac 894 +aes_128_gcm 895 +aes_128_ccm 896 +id_aes128_wrap_pad 897 +aes_192_gcm 898 +aes_192_ccm 899 +id_aes192_wrap_pad 900 +aes_256_gcm 901 +aes_256_ccm 902 +id_aes256_wrap_pad 903 +aes_128_ctr 904 +aes_192_ctr 905 +aes_256_ctr 906 +id_camellia128_wrap 907 +id_camellia192_wrap 908 +id_camellia256_wrap 909 +anyExtendedKeyUsage 910 +mgf1 911 +rsassaPss 912 +aes_128_xts 913 +aes_256_xts 914 +rc4_hmac_md5 915 +aes_128_cbc_hmac_sha1 916 +aes_192_cbc_hmac_sha1 917 +aes_256_cbc_hmac_sha1 918 +rsaesOaep 919 +dhpublicnumber 920 +brainpoolP160r1 921 +brainpoolP160t1 922 +brainpoolP192r1 923 +brainpoolP192t1 924 +brainpoolP224r1 925 +brainpoolP224t1 926 +brainpoolP256r1 927 +brainpoolP256t1 928 +brainpoolP320r1 929 +brainpoolP320t1 930 +brainpoolP384r1 931 +brainpoolP384t1 932 +brainpoolP512r1 933 +brainpoolP512t1 934 +pSpecified 935 +dhSinglePass_stdDH_sha1kdf_scheme 936 +dhSinglePass_stdDH_sha224kdf_scheme 937 +dhSinglePass_stdDH_sha256kdf_scheme 938 +dhSinglePass_stdDH_sha384kdf_scheme 939 +dhSinglePass_stdDH_sha512kdf_scheme 940 +dhSinglePass_cofactorDH_sha1kdf_scheme 941 +dhSinglePass_cofactorDH_sha224kdf_scheme 942 +dhSinglePass_cofactorDH_sha256kdf_scheme 943 +dhSinglePass_cofactorDH_sha384kdf_scheme 944 +dhSinglePass_cofactorDH_sha512kdf_scheme 945 +dh_std_kdf 946 +dh_cofactor_kdf 947 +aes_128_cbc_hmac_sha256 948 +aes_192_cbc_hmac_sha256 949 +aes_256_cbc_hmac_sha256 950 +ct_precert_scts 951 +ct_precert_poison 952 +ct_precert_signer 953 +ct_cert_scts 954 +jurisdictionLocalityName 955 +jurisdictionStateOrProvinceName 956 +jurisdictionCountryName 957 +aes_128_ocb 958 +aes_192_ocb 959 +aes_256_ocb 960 +camellia_128_gcm 961 +camellia_128_ccm 962 +camellia_128_ctr 963 +camellia_128_cmac 964 +camellia_192_gcm 965 +camellia_192_ccm 966 +camellia_192_ctr 967 +camellia_192_cmac 968 +camellia_256_gcm 969 +camellia_256_ccm 970 +camellia_256_ctr 971 +camellia_256_cmac 972 +id_scrypt 973 +id_tc26 974 +gost89_cnt_12 975 +gost_mac_12 976 +id_tc26_algorithms 977 +id_tc26_sign 978 +id_GostR3410_2012_256 979 +id_GostR3410_2012_512 980 +id_tc26_digest 981 +id_GostR3411_2012_256 982 +id_GostR3411_2012_512 983 +id_tc26_signwithdigest 984 +id_tc26_signwithdigest_gost3410_2012_256 985 +id_tc26_signwithdigest_gost3410_2012_512 986 +id_tc26_mac 987 +id_tc26_hmac_gost_3411_2012_256 988 +id_tc26_hmac_gost_3411_2012_512 989 +id_tc26_cipher 990 +id_tc26_agreement 991 +id_tc26_agreement_gost_3410_2012_256 992 +id_tc26_agreement_gost_3410_2012_512 993 +id_tc26_constants 994 +id_tc26_sign_constants 995 +id_tc26_gost_3410_2012_512_constants 996 +id_tc26_gost_3410_2012_512_paramSetTest 997 +id_tc26_gost_3410_2012_512_paramSetA 998 +id_tc26_gost_3410_2012_512_paramSetB 999 +id_tc26_digest_constants 1000 +id_tc26_cipher_constants 1001 +id_tc26_gost_28147_constants 1002 +id_tc26_gost_28147_param_Z 1003 +INN 1004 +OGRN 1005 +SNILS 1006 +subjectSignTool 1007 +issuerSignTool 1008 +gost89_cbc 1009 +gost89_ecb 1010 +gost89_ctr 1011 +kuznyechik_ecb 1012 +kuznyechik_ctr 1013 +kuznyechik_ofb 1014 +kuznyechik_cbc 1015 +kuznyechik_cfb 1016 +kuznyechik_mac 1017 +chacha20_poly1305 1018 +chacha20 1019 +tlsfeature 1020 +tls1_prf 1021 +ipsec_IKE 1022 +capwapAC 1023 +capwapWTP 1024 +sshClient 1025 +sshServer 1026 +sendRouter 1027 +sendProxiedRouter 1028 +sendOwner 1029 +sendProxiedOwner 1030 +id_pkinit 1031 +pkInitClientAuth 1032 +pkInitKDC 1033 +X25519 1034 +X448 1035 +hkdf 1036 +kx_rsa 1037 +kx_ecdhe 1038 +kx_dhe 1039 +kx_ecdhe_psk 1040 +kx_dhe_psk 1041 +kx_rsa_psk 1042 +kx_psk 1043 +kx_srp 1044 +kx_gost 1045 +auth_rsa 1046 +auth_ecdsa 1047 +auth_psk 1048 +auth_dss 1049 +auth_gost01 1050 +auth_gost12 1051 +auth_srp 1052 +auth_null 1053 +fips_none 1054 +fips_140_2 1055 +blake2b512 1056 +blake2s256 1057 +id_smime_ct_contentCollection 1058 +id_smime_ct_authEnvelopedData 1059 +id_ct_xml 1060 +poly1305 1061 +siphash 1062 +kx_any 1063 +auth_any 1064 +aria_128_ecb 1065 +aria_128_cbc 1066 +aria_128_cfb128 1067 +aria_128_ofb128 1068 +aria_128_ctr 1069 +aria_192_ecb 1070 +aria_192_cbc 1071 +aria_192_cfb128 1072 +aria_192_ofb128 1073 +aria_192_ctr 1074 +aria_256_ecb 1075 +aria_256_cbc 1076 +aria_256_cfb128 1077 +aria_256_ofb128 1078 +aria_256_ctr 1079 +aria_128_cfb1 1080 +aria_192_cfb1 1081 +aria_256_cfb1 1082 +aria_128_cfb8 1083 +aria_192_cfb8 1084 +aria_256_cfb8 1085 +id_smime_aa_signingCertificateV2 1086 +ED25519 1087 +ED448 1088 +organizationIdentifier 1089 +countryCode3c 1090 +countryCode3n 1091 +dnsName 1092 +x509ExtAdmission 1093 +sha512_224 1094 +sha512_256 1095 +sha3_224 1096 +sha3_256 1097 +sha3_384 1098 +sha3_512 1099 +shake128 1100 +shake256 1101 +hmac_sha3_224 1102 +hmac_sha3_256 1103 +hmac_sha3_384 1104 +hmac_sha3_512 1105 +dsa_with_SHA384 1106 +dsa_with_SHA512 1107 +dsa_with_SHA3_224 1108 +dsa_with_SHA3_256 1109 +dsa_with_SHA3_384 1110 +dsa_with_SHA3_512 1111 +ecdsa_with_SHA3_224 1112 +ecdsa_with_SHA3_256 1113 +ecdsa_with_SHA3_384 1114 +ecdsa_with_SHA3_512 1115 +RSA_SHA3_224 1116 +RSA_SHA3_256 1117 +RSA_SHA3_384 1118 +RSA_SHA3_512 1119 +aria_128_ccm 1120 +aria_192_ccm 1121 +aria_256_ccm 1122 +aria_128_gcm 1123 +aria_192_gcm 1124 +aria_256_gcm 1125 +ffdhe2048 1126 +ffdhe3072 1127 +ffdhe4096 1128 +ffdhe6144 1129 +ffdhe8192 1130 +cmcCA 1131 +cmcRA 1132 +sm4_ecb 1133 +sm4_cbc 1134 +sm4_ofb128 1135 +sm4_cfb1 1136 +sm4_cfb128 1137 +sm4_cfb8 1138 +sm4_ctr 1139 +ISO_CN 1140 +oscca 1141 +sm_scheme 1142 +sm3 1143 +sm3WithRSAEncryption 1144 +sha512_224WithRSAEncryption 1145 +sha512_256WithRSAEncryption 1146 +id_tc26_gost_3410_2012_256_constants 1147 +id_tc26_gost_3410_2012_256_paramSetA 1148 +id_tc26_gost_3410_2012_512_paramSetC 1149 +ISO_UA 1150 +ua_pki 1151 +dstu28147 1152 +dstu28147_ofb 1153 +dstu28147_cfb 1154 +dstu28147_wrap 1155 +hmacWithDstu34311 1156 +dstu34311 1157 +dstu4145le 1158 +dstu4145be 1159 +uacurve0 1160 +uacurve1 1161 +uacurve2 1162 +uacurve3 1163 +uacurve4 1164 +uacurve5 1165 +uacurve6 1166 +uacurve7 1167 +uacurve8 1168 +uacurve9 1169 +ieee 1170 +ieee_siswg 1171 +sm2 1172 +id_tc26_cipher_gostr3412_2015_magma 1173 +magma_ctr_acpkm 1174 +magma_ctr_acpkm_omac 1175 +id_tc26_cipher_gostr3412_2015_kuznyechik 1176 +kuznyechik_ctr_acpkm 1177 +kuznyechik_ctr_acpkm_omac 1178 +id_tc26_wrap 1179 +id_tc26_wrap_gostr3412_2015_magma 1180 +magma_kexp15 1181 +id_tc26_wrap_gostr3412_2015_kuznyechik 1182 +kuznyechik_kexp15 1183 +id_tc26_gost_3410_2012_256_paramSetB 1184 +id_tc26_gost_3410_2012_256_paramSetC 1185 +id_tc26_gost_3410_2012_256_paramSetD 1186 +magma_ecb 1187 +magma_ctr 1188 +magma_ofb 1189 +magma_cbc 1190 +magma_cfb 1191 +magma_mac 1192 +hmacWithSHA512_224 1193 +hmacWithSHA512_256 1194 +gmac 1195 +kmac128 1196 +kmac256 1197 +aes_128_siv 1198 +aes_192_siv 1199 +aes_256_siv 1200 +blake2bmac 1201 +blake2smac 1202 +sshkdf 1203 +SM2_with_SM3 1204 +sskdf 1205 +x963kdf 1206 +x942kdf 1207 +id_on_SmtpUTF8Mailbox 1208 +XmppAddr 1209 +SRVName 1210 +NAIRealm 1211 +modp_1536 1212 +modp_2048 1213 +modp_3072 1214 +modp_4096 1215 +modp_6144 1216 +modp_8192 1217 +kx_gost18 1218 +cmcArchive 1219 +id_kp_bgpsec_router 1220 +id_kp_BrandIndicatorforMessageIdentification 1221 +cmKGA 1222 +id_it_caCerts 1223 +id_it_rootCaKeyUpdate 1224 +id_it_certReqTemplate 1225 +OGRNIP 1226 +classSignTool 1227 +classSignToolKC1 1228 +classSignToolKC2 1229 +classSignToolKC3 1230 +classSignToolKB1 1231 +classSignToolKB2 1232 +classSignToolKA1 1233 +id_ct_routeOriginAuthz 1234 +id_ct_rpkiManifest 1235 +id_ct_rpkiGhostbusters 1236 +id_ct_resourceTaggedAttest 1237 +id_cp 1238 +sbgp_ipAddrBlockv2 1239 +sbgp_autonomousSysNumv2 1240 +ipAddr_asNumber 1241 +ipAddr_asNumberv2 1242 +rpkiManifest 1243 +signedObject 1244 +rpkiNotify 1245 +id_ct_geofeedCSVwithCRLF 1246 +id_ct_signedChecklist 1247 +sm4_gcm 1248 +sm4_ccm 1249 +id_ct_ASPA 1250 +id_mod_cmp2000_02 1251 +id_mod_cmp2021_88 1252 +id_mod_cmp2021_02 1253 +id_it_rootCaCert 1254 +id_it_certProfile 1255 +id_it_crlStatusList 1256 +id_it_crls 1257 +id_regCtrl_altCertTemplate 1258 +id_regCtrl_algId 1259 +id_regCtrl_rsaKeyLen 1260 +id_aa_ets_attrCertificateRefs 1261 +id_aa_ets_attrRevocationRefs 1262 +id_aa_CMSAlgorithmProtection 1263 +itu_t_identified_organization 1264 +etsi 1265 +electronic_signature_standard 1266 +ess_attributes 1267 +id_aa_ets_mimeType 1268 +id_aa_ets_longTermValidation 1269 +id_aa_ets_SignaturePolicyDocument 1270 +id_aa_ets_archiveTimestampV3 1271 +id_aa_ATSHashIndex 1272 +cades 1273 +cades_attributes 1274 +id_aa_ets_signerAttrV2 1275 +id_aa_ets_sigPolicyStore 1276 +id_aa_ATSHashIndex_v2 1277 +id_aa_ATSHashIndex_v3 1278 +signedAssertion 1279 +id_aa_ets_archiveTimestampV2 1280 +hmacWithSM3 1281 +oracle 1282 +oracle_jdk_trustedkeyusage 1283 +id_ct_signedTAL 1284 +brainpoolP256r1tls13 1285 +brainpoolP384r1tls13 1286 +brainpoolP512r1tls13 1287 +brotli 1288 +zstd 1289 +sm4_xts 1290 +ms_ntds_obj_sid 1291 +ms_ntds_sec_ext 1292 +ms_cert_templ 1293 +ms_app_policies 1294 +authority_attribute_identifier 1295 +role_spec_cert_identifier 1296 +basic_att_constraints 1297 +delegated_name_constraints 1298 +time_specification 1299 +attribute_descriptor 1300 +user_notice 1301 +soa_identifier 1302 +acceptable_cert_policies 1303 +acceptable_privilege_policies 1304 +indirect_issuer 1305 +no_assertion 1306 +id_aa_issuing_distribution_point 1307 +issued_on_behalf_of 1308 +single_use 1309 +group_ac 1310 +allowed_attribute_assignments 1311 +attribute_mappings 1312 +holder_name_constraints 1313 +authorization_validation 1314 +prot_restrict 1315 +subject_alt_public_key_info 1316 +alt_signature_algorithm 1317 +alt_signature_value 1318 +associated_information 1319 +id_ct_rpkiSignedPrefixList 1320 +id_on_hardwareModuleName 1321 +id_kp_wisun_fan_device 1322 +ac_auditEntity 1323 +tcg 1324 +tcg_tcpaSpecVersion 1325 +tcg_attribute 1326 +tcg_protocol 1327 +tcg_algorithm 1328 +tcg_platformClass 1329 +tcg_ce 1330 +tcg_kp 1331 +tcg_ca 1332 +tcg_address 1333 +tcg_registry 1334 +tcg_traits 1335 +tcg_common 1336 +tcg_at_platformManufacturerStr 1337 +tcg_at_platformManufacturerId 1338 +tcg_at_platformConfigUri 1339 +tcg_at_platformModel 1340 +tcg_at_platformVersion 1341 +tcg_at_platformSerial 1342 +tcg_at_platformConfiguration 1343 +tcg_at_platformIdentifier 1344 +tcg_at_tpmManufacturer 1345 +tcg_at_tpmModel 1346 +tcg_at_tpmVersion 1347 +tcg_at_securityQualities 1348 +tcg_at_tpmProtectionProfile 1349 +tcg_at_tpmSecurityTarget 1350 +tcg_at_tbbProtectionProfile 1351 +tcg_at_tbbSecurityTarget 1352 +tcg_at_tpmIdLabel 1353 +tcg_at_tpmSpecification 1354 +tcg_at_tcgPlatformSpecification 1355 +tcg_at_tpmSecurityAssertions 1356 +tcg_at_tbbSecurityAssertions 1357 +tcg_at_tcgCredentialSpecification 1358 +tcg_at_tcgCredentialType 1359 +tcg_at_previousPlatformCertificates 1360 +tcg_at_tbbSecurityAssertions_v3 1361 +tcg_at_cryptographicAnchors 1362 +tcg_at_platformConfiguration_v1 1363 +tcg_at_platformConfiguration_v2 1364 +tcg_at_platformConfiguration_v3 1365 +tcg_at_platformConfigUri_v3 1366 +tcg_algorithm_null 1367 +tcg_kp_EKCertificate 1368 +tcg_kp_PlatformAttributeCertificate 1369 +tcg_kp_AIKCertificate 1370 +tcg_kp_PlatformKeyCertificate 1371 +tcg_kp_DeltaPlatformAttributeCertificate 1372 +tcg_kp_DeltaPlatformKeyCertificate 1373 +tcg_kp_AdditionalPlatformAttributeCertificate 1374 +tcg_kp_AdditionalPlatformKeyCertificate 1375 +tcg_ce_relevantCredentials 1376 +tcg_ce_relevantManifests 1377 +tcg_ce_virtualPlatformAttestationService 1378 +tcg_ce_migrationControllerAttestationService 1379 +tcg_ce_migrationControllerRegistrationService 1380 +tcg_ce_virtualPlatformBackupService 1381 +tcg_prt_tpmIdProtocol 1382 +tcg_address_ethernetmac 1383 +tcg_address_wlanmac 1384 +tcg_address_bluetoothmac 1385 +tcg_registry_componentClass 1386 +tcg_registry_componentClass_tcg 1387 +tcg_registry_componentClass_ietf 1388 +tcg_registry_componentClass_dmtf 1389 +tcg_registry_componentClass_pcie 1390 +tcg_registry_componentClass_disk 1391 +tcg_cap_verifiedPlatformCertificate 1392 +tcg_tr_ID 1393 +tcg_tr_category 1394 +tcg_tr_registry 1395 +tcg_tr_ID_Boolean 1396 +tcg_tr_ID_CertificateIdentifier 1397 +tcg_tr_ID_CommonCriteria 1398 +tcg_tr_ID_componentClass 1399 +tcg_tr_ID_componentIdentifierV11 1400 +tcg_tr_ID_FIPSLevel 1401 +tcg_tr_ID_ISO9000Level 1402 +tcg_tr_ID_networkMAC 1403 +tcg_tr_ID_OID 1404 +tcg_tr_ID_PEN 1405 +tcg_tr_ID_platformFirmwareCapabilities 1406 +tcg_tr_ID_platformFirmwareSignatureVerification 1407 +tcg_tr_ID_platformFirmwareUpdateCompliance 1408 +tcg_tr_ID_platformHardwareCapabilities 1409 +tcg_tr_ID_RTM 1410 +tcg_tr_ID_status 1411 +tcg_tr_ID_URI 1412 +tcg_tr_ID_UTF8String 1413 +tcg_tr_ID_IA5String 1414 +tcg_tr_ID_PEMCertString 1415 +tcg_tr_ID_PublicKey 1416 +tcg_tr_cat_platformManufacturer 1417 +tcg_tr_cat_platformModel 1418 +tcg_tr_cat_platformVersion 1419 +tcg_tr_cat_platformSerial 1420 +tcg_tr_cat_platformManufacturerIdentifier 1421 +tcg_tr_cat_platformOwnership 1422 +tcg_tr_cat_componentClass 1423 +tcg_tr_cat_componentManufacturer 1424 +tcg_tr_cat_componentModel 1425 +tcg_tr_cat_componentSerial 1426 +tcg_tr_cat_componentStatus 1427 +tcg_tr_cat_componentLocation 1428 +tcg_tr_cat_componentRevision 1429 +tcg_tr_cat_componentFieldReplaceable 1430 +tcg_tr_cat_EKCertificate 1431 +tcg_tr_cat_IAKCertificate 1432 +tcg_tr_cat_IDevIDCertificate 1433 +tcg_tr_cat_DICECertificate 1434 +tcg_tr_cat_SPDMCertificate 1435 +tcg_tr_cat_PEMCertificate 1436 +tcg_tr_cat_PlatformCertificate 1437 +tcg_tr_cat_DeltaPlatformCertificate 1438 +tcg_tr_cat_RebasePlatformCertificate 1439 +tcg_tr_cat_genericCertificate 1440 +tcg_tr_cat_CommonCriteria 1441 +tcg_tr_cat_componentIdentifierV11 1442 +tcg_tr_cat_FIPSLevel 1443 +tcg_tr_cat_ISO9000 1444 +tcg_tr_cat_networkMAC 1445 +tcg_tr_cat_attestationProtocol 1446 +tcg_tr_cat_PEN 1447 +tcg_tr_cat_platformFirmwareCapabilities 1448 +tcg_tr_cat_platformHardwareCapabilities 1449 +tcg_tr_cat_platformFirmwareSignatureVerification 1450 +tcg_tr_cat_platformFirmwareUpdateCompliance 1451 +tcg_tr_cat_RTM 1452 +tcg_tr_cat_PublicKey 1453 +ML_KEM_512 1454 +ML_KEM_768 1455 +ML_KEM_1024 1456 +ML_DSA_44 1457 +ML_DSA_65 1458 +ML_DSA_87 1459 +SLH_DSA_SHA2_128s 1460 +SLH_DSA_SHA2_128f 1461 +SLH_DSA_SHA2_192s 1462 +SLH_DSA_SHA2_192f 1463 +SLH_DSA_SHA2_256s 1464 +SLH_DSA_SHA2_256f 1465 +SLH_DSA_SHAKE_128s 1466 +SLH_DSA_SHAKE_128f 1467 +SLH_DSA_SHAKE_192s 1468 +SLH_DSA_SHAKE_192f 1469 +SLH_DSA_SHAKE_256s 1470 +SLH_DSA_SHAKE_256f 1471 +HASH_ML_DSA_44_WITH_SHA512 1472 +HASH_ML_DSA_65_WITH_SHA512 1473 +HASH_ML_DSA_87_WITH_SHA512 1474 +SLH_DSA_SHA2_128s_WITH_SHA256 1475 +SLH_DSA_SHA2_128f_WITH_SHA256 1476 +SLH_DSA_SHA2_192s_WITH_SHA512 1477 +SLH_DSA_SHA2_192f_WITH_SHA512 1478 +SLH_DSA_SHA2_256s_WITH_SHA512 1479 +SLH_DSA_SHA2_256f_WITH_SHA512 1480 +SLH_DSA_SHAKE_128s_WITH_SHAKE128 1481 +SLH_DSA_SHAKE_128f_WITH_SHAKE128 1482 +SLH_DSA_SHAKE_192s_WITH_SHAKE256 1483 +SLH_DSA_SHAKE_192f_WITH_SHAKE256 1484 +SLH_DSA_SHAKE_256s_WITH_SHAKE256 1485 +SLH_DSA_SHAKE_256f_WITH_SHAKE256 1486 +aes_128_cbc_hmac_sha1_etm 1487 +aes_192_cbc_hmac_sha1_etm 1488 +aes_256_cbc_hmac_sha1_etm 1489 +aes_128_cbc_hmac_sha256_etm 1490 +aes_192_cbc_hmac_sha256_etm 1491 +aes_256_cbc_hmac_sha256_etm 1492 +aes_128_cbc_hmac_sha512_etm 1493 +aes_192_cbc_hmac_sha512_etm 1494 +aes_256_cbc_hmac_sha512_etm 1495 +HKDF_SHA256 1496 +HKDF_SHA384 1497 +HKDF_SHA512 1498 +id_smime_ori 1499 +id_smime_ori_kem 1500 +id_alg_hss_lms_hashsig 1501 diff --git a/crates/stdlib/rustls-data/objects.txt b/crates/stdlib/rustls-data/objects.txt new file mode 100644 index 00000000000..946cdf5ec68 --- /dev/null +++ b/crates/stdlib/rustls-data/objects.txt @@ -0,0 +1,2069 @@ +# CCITT was renamed to ITU-T quite some time ago +0 : ITU-T : itu-t +!Alias ccitt itu-t + +1 : ISO : iso + +2 : JOINT-ISO-ITU-T : joint-iso-itu-t +!Alias joint-iso-ccitt joint-iso-itu-t + +iso 2 : member-body : ISO Member Body + +iso 3 : identified-organization + +# GMAC OID +iso 0 9797 3 4 : GMAC : gmac + +# HMAC OIDs +identified-organization 6 1 5 5 8 1 1 : HMAC-MD5 : hmac-md5 +identified-organization 6 1 5 5 8 1 2 : HMAC-SHA1 : hmac-sha1 + +# "1.3.36.8.3.3" +identified-organization 36 8 3 3 : x509ExtAdmission : Professional Information or basis for Admission + +identified-organization 132 : certicom-arc + +identified-organization 111 : ieee +ieee 2 1619 : ieee-siswg : IEEE Security in Storage Working Group + +joint-iso-itu-t 23 : international-organizations : International Organizations + +international-organizations 43 : wap +wap 1 : wap-wsg + +joint-iso-itu-t 5 1 5 : selected-attribute-types : Selected Attribute Types + +selected-attribute-types 55 : clearance + +member-body 840 : ISO-US : ISO US Member Body +ISO-US 10040 : X9-57 : X9.57 +X9-57 4 : X9cm : X9.57 CM ? + +member-body 156 : ISO-CN : ISO CN Member Body +ISO-CN 10197 : oscca +oscca 1 : sm-scheme + +!Cname dsa +X9cm 1 : DSA : dsaEncryption +X9cm 3 : DSA-SHA1 : dsaWithSHA1 + + +ISO-US 10045 : ansi-X9-62 : ANSI X9.62 +!module X9-62 +!Alias id-fieldType ansi-X9-62 1 +X9-62_id-fieldType 1 : prime-field +X9-62_id-fieldType 2 : characteristic-two-field +X9-62_characteristic-two-field 3 : id-characteristic-two-basis +X9-62_id-characteristic-two-basis 1 : onBasis +X9-62_id-characteristic-two-basis 2 : tpBasis +X9-62_id-characteristic-two-basis 3 : ppBasis +!Alias id-publicKeyType ansi-X9-62 2 +X9-62_id-publicKeyType 1 : id-ecPublicKey +!Alias ellipticCurve ansi-X9-62 3 +!Alias c-TwoCurve X9-62_ellipticCurve 0 +X9-62_c-TwoCurve 1 : c2pnb163v1 +X9-62_c-TwoCurve 2 : c2pnb163v2 +X9-62_c-TwoCurve 3 : c2pnb163v3 +X9-62_c-TwoCurve 4 : c2pnb176v1 +X9-62_c-TwoCurve 5 : c2tnb191v1 +X9-62_c-TwoCurve 6 : c2tnb191v2 +X9-62_c-TwoCurve 7 : c2tnb191v3 +X9-62_c-TwoCurve 8 : c2onb191v4 +X9-62_c-TwoCurve 9 : c2onb191v5 +X9-62_c-TwoCurve 10 : c2pnb208w1 +X9-62_c-TwoCurve 11 : c2tnb239v1 +X9-62_c-TwoCurve 12 : c2tnb239v2 +X9-62_c-TwoCurve 13 : c2tnb239v3 +X9-62_c-TwoCurve 14 : c2onb239v4 +X9-62_c-TwoCurve 15 : c2onb239v5 +X9-62_c-TwoCurve 16 : c2pnb272w1 +X9-62_c-TwoCurve 17 : c2pnb304w1 +X9-62_c-TwoCurve 18 : c2tnb359v1 +X9-62_c-TwoCurve 19 : c2pnb368w1 +X9-62_c-TwoCurve 20 : c2tnb431r1 +!Alias primeCurve X9-62_ellipticCurve 1 +X9-62_primeCurve 1 : prime192v1 +X9-62_primeCurve 2 : prime192v2 +X9-62_primeCurve 3 : prime192v3 +X9-62_primeCurve 4 : prime239v1 +X9-62_primeCurve 5 : prime239v2 +X9-62_primeCurve 6 : prime239v3 +X9-62_primeCurve 7 : prime256v1 +!Alias id-ecSigType ansi-X9-62 4 +!global +X9-62_id-ecSigType 1 : ecdsa-with-SHA1 +X9-62_id-ecSigType 2 : ecdsa-with-Recommended +X9-62_id-ecSigType 3 : ecdsa-with-Specified +ecdsa-with-Specified 1 : ecdsa-with-SHA224 +ecdsa-with-Specified 2 : ecdsa-with-SHA256 +ecdsa-with-Specified 3 : ecdsa-with-SHA384 +ecdsa-with-Specified 4 : ecdsa-with-SHA512 + +# SECG curve OIDs from "SEC 2: Recommended Elliptic Curve Domain Parameters" +# (http://www.secg.org/) +!Alias secg_ellipticCurve certicom-arc 0 +# SECG prime curves OIDs +secg-ellipticCurve 6 : secp112r1 +secg-ellipticCurve 7 : secp112r2 +secg-ellipticCurve 28 : secp128r1 +secg-ellipticCurve 29 : secp128r2 +secg-ellipticCurve 9 : secp160k1 +secg-ellipticCurve 8 : secp160r1 +secg-ellipticCurve 30 : secp160r2 +secg-ellipticCurve 31 : secp192k1 +# NOTE: the curve secp192r1 is the same as prime192v1 defined above +# and is therefore omitted +secg-ellipticCurve 32 : secp224k1 +secg-ellipticCurve 33 : secp224r1 +secg-ellipticCurve 10 : secp256k1 +# NOTE: the curve secp256r1 is the same as prime256v1 defined above +# and is therefore omitted +secg-ellipticCurve 34 : secp384r1 +secg-ellipticCurve 35 : secp521r1 +# SECG characteristic two curves OIDs +secg-ellipticCurve 4 : sect113r1 +secg-ellipticCurve 5 : sect113r2 +secg-ellipticCurve 22 : sect131r1 +secg-ellipticCurve 23 : sect131r2 +secg-ellipticCurve 1 : sect163k1 +secg-ellipticCurve 2 : sect163r1 +secg-ellipticCurve 15 : sect163r2 +secg-ellipticCurve 24 : sect193r1 +secg-ellipticCurve 25 : sect193r2 +secg-ellipticCurve 26 : sect233k1 +secg-ellipticCurve 27 : sect233r1 +secg-ellipticCurve 3 : sect239k1 +secg-ellipticCurve 16 : sect283k1 +secg-ellipticCurve 17 : sect283r1 +secg-ellipticCurve 36 : sect409k1 +secg-ellipticCurve 37 : sect409r1 +secg-ellipticCurve 38 : sect571k1 +secg-ellipticCurve 39 : sect571r1 + +# WAP/TLS curve OIDs (http://www.wapforum.org/) +!Alias wap-wsg-idm-ecid wap-wsg 4 +wap-wsg-idm-ecid 1 : wap-wsg-idm-ecid-wtls1 +wap-wsg-idm-ecid 3 : wap-wsg-idm-ecid-wtls3 +wap-wsg-idm-ecid 4 : wap-wsg-idm-ecid-wtls4 +wap-wsg-idm-ecid 5 : wap-wsg-idm-ecid-wtls5 +wap-wsg-idm-ecid 6 : wap-wsg-idm-ecid-wtls6 +wap-wsg-idm-ecid 7 : wap-wsg-idm-ecid-wtls7 +wap-wsg-idm-ecid 8 : wap-wsg-idm-ecid-wtls8 +wap-wsg-idm-ecid 9 : wap-wsg-idm-ecid-wtls9 +wap-wsg-idm-ecid 10 : wap-wsg-idm-ecid-wtls10 +wap-wsg-idm-ecid 11 : wap-wsg-idm-ecid-wtls11 +wap-wsg-idm-ecid 12 : wap-wsg-idm-ecid-wtls12 + + +ISO-US 113533 7 66 10 : CAST5-CBC : cast5-cbc + : CAST5-ECB : cast5-ecb +!Cname cast5-cfb64 + : CAST5-CFB : cast5-cfb +!Cname cast5-ofb64 + : CAST5-OFB : cast5-ofb +!Cname pbeWithMD5AndCast5-CBC +ISO-US 113533 7 66 12 : : pbeWithMD5AndCast5CBC + +# Macs for CMP and CRMF +ISO-US 113533 7 66 13 : id-PasswordBasedMAC : password based MAC +ISO-US 113533 7 66 30 : id-DHBasedMac : Diffie-Hellman based MAC + +ISO-US 113549 : rsadsi : RSA Data Security, Inc. + +rsadsi 1 : pkcs : RSA Data Security, Inc. PKCS + +pkcs 1 : pkcs1 +pkcs1 1 : : rsaEncryption +pkcs1 2 : RSA-MD2 : md2WithRSAEncryption +pkcs1 3 : RSA-MD4 : md4WithRSAEncryption +pkcs1 4 : RSA-MD5 : md5WithRSAEncryption +pkcs1 5 : RSA-SHA1 : sha1WithRSAEncryption +# According to PKCS #1 version 2.1 +pkcs1 7 : RSAES-OAEP : rsaesOaep +pkcs1 8 : MGF1 : mgf1 +pkcs1 9 : PSPECIFIED : pSpecified +pkcs1 10 : RSASSA-PSS : rsassaPss + +pkcs1 11 : RSA-SHA256 : sha256WithRSAEncryption +pkcs1 12 : RSA-SHA384 : sha384WithRSAEncryption +pkcs1 13 : RSA-SHA512 : sha512WithRSAEncryption +pkcs1 14 : RSA-SHA224 : sha224WithRSAEncryption +pkcs1 15 : RSA-SHA512/224 : sha512-224WithRSAEncryption +pkcs1 16 : RSA-SHA512/256 : sha512-256WithRSAEncryption + +pkcs 3 : pkcs3 +pkcs3 1 : : dhKeyAgreement + +pkcs 5 : pkcs5 +pkcs5 1 : PBE-MD2-DES : pbeWithMD2AndDES-CBC +pkcs5 3 : PBE-MD5-DES : pbeWithMD5AndDES-CBC +pkcs5 4 : PBE-MD2-RC2-64 : pbeWithMD2AndRC2-CBC +pkcs5 6 : PBE-MD5-RC2-64 : pbeWithMD5AndRC2-CBC +pkcs5 10 : PBE-SHA1-DES : pbeWithSHA1AndDES-CBC +pkcs5 11 : PBE-SHA1-RC2-64 : pbeWithSHA1AndRC2-CBC +!Cname id_pbkdf2 +pkcs5 12 : : PBKDF2 +!Cname pbes2 +pkcs5 13 : : PBES2 +!Cname pbmac1 +pkcs5 14 : : PBMAC1 + +pkcs 7 : pkcs7 +pkcs7 1 : : pkcs7-data +!Cname pkcs7-signed +pkcs7 2 : : pkcs7-signedData +!Cname pkcs7-enveloped +pkcs7 3 : : pkcs7-envelopedData +!Cname pkcs7-signedAndEnveloped +pkcs7 4 : : pkcs7-signedAndEnvelopedData +!Cname pkcs7-digest +pkcs7 5 : : pkcs7-digestData +!Cname pkcs7-encrypted +pkcs7 6 : : pkcs7-encryptedData + +pkcs 9 : pkcs9 +!module pkcs9 +pkcs9 1 : : emailAddress +pkcs9 2 : : unstructuredName +pkcs9 3 : : contentType +pkcs9 4 : : messageDigest +pkcs9 5 : : signingTime +pkcs9 6 : : countersignature +pkcs9 7 : : challengePassword +pkcs9 8 : : unstructuredAddress +!Cname extCertAttributes +pkcs9 9 : : extendedCertificateAttributes +!global + +!Cname ext-req +pkcs9 14 : extReq : Extension Request + +!Cname SMIMECapabilities +pkcs9 15 : SMIME-CAPS : S/MIME Capabilities + +# S/MIME +!Cname SMIME +pkcs9 16 : SMIME : S/MIME +SMIME 0 : id-smime-mod +SMIME 1 : id-smime-ct +SMIME 2 : id-smime-aa +SMIME 3 : id-smime-alg +SMIME 4 : id-smime-cd +SMIME 5 : id-smime-spq +SMIME 6 : id-smime-cti +SMIME 13 : id-smime-ori + +# S/MIME Modules +id-smime-mod 1 : id-smime-mod-cms +id-smime-mod 2 : id-smime-mod-ess +id-smime-mod 3 : id-smime-mod-oid +id-smime-mod 4 : id-smime-mod-msg-v3 +id-smime-mod 5 : id-smime-mod-ets-eSignature-88 +id-smime-mod 6 : id-smime-mod-ets-eSignature-97 +id-smime-mod 7 : id-smime-mod-ets-eSigPolicy-88 +id-smime-mod 8 : id-smime-mod-ets-eSigPolicy-97 + +# S/MIME Content Types +id-smime-ct 1 : id-smime-ct-receipt +id-smime-ct 2 : id-smime-ct-authData +id-smime-ct 3 : id-smime-ct-publishCert +id-smime-ct 4 : id-smime-ct-TSTInfo +id-smime-ct 5 : id-smime-ct-TDTInfo +id-smime-ct 6 : id-smime-ct-contentInfo +id-smime-ct 7 : id-smime-ct-DVCSRequestData +id-smime-ct 8 : id-smime-ct-DVCSResponseData +id-smime-ct 9 : id-smime-ct-compressedData +id-smime-ct 19 : id-smime-ct-contentCollection +id-smime-ct 23 : id-smime-ct-authEnvelopedData +id-smime-ct 24 : id-ct-routeOriginAuthz +id-smime-ct 26 : id-ct-rpkiManifest +id-smime-ct 27 : id-ct-asciiTextWithCRLF +id-smime-ct 28 : id-ct-xml +id-smime-ct 35 : id-ct-rpkiGhostbusters +id-smime-ct 36 : id-ct-resourceTaggedAttest +id-smime-ct 47 : id-ct-geofeedCSVwithCRLF +id-smime-ct 48 : id-ct-signedChecklist +id-smime-ct 49 : id-ct-ASPA +id-smime-ct 50 : id-ct-signedTAL +id-smime-ct 51 : id-ct-rpkiSignedPrefixList + +# S/MIME Attributes +id-smime-aa 1 : id-smime-aa-receiptRequest +id-smime-aa 2 : id-smime-aa-securityLabel +id-smime-aa 3 : id-smime-aa-mlExpandHistory +id-smime-aa 4 : id-smime-aa-contentHint +id-smime-aa 5 : id-smime-aa-msgSigDigest +# obsolete +id-smime-aa 6 : id-smime-aa-encapContentType +id-smime-aa 7 : id-smime-aa-contentIdentifier +# obsolete +id-smime-aa 8 : id-smime-aa-macValue +id-smime-aa 9 : id-smime-aa-equivalentLabels +id-smime-aa 10 : id-smime-aa-contentReference +id-smime-aa 11 : id-smime-aa-encrypKeyPref +id-smime-aa 12 : id-smime-aa-signingCertificate +id-smime-aa 13 : id-smime-aa-smimeEncryptCerts +id-smime-aa 14 : id-smime-aa-timeStampToken +id-smime-aa 15 : id-smime-aa-ets-sigPolicyId +id-smime-aa 16 : id-smime-aa-ets-commitmentType +id-smime-aa 17 : id-smime-aa-ets-signerLocation +id-smime-aa 18 : id-smime-aa-ets-signerAttr +id-smime-aa 19 : id-smime-aa-ets-otherSigCert +id-smime-aa 20 : id-smime-aa-ets-contentTimestamp +id-smime-aa 21 : id-smime-aa-ets-CertificateRefs +id-smime-aa 22 : id-smime-aa-ets-RevocationRefs +id-smime-aa 23 : id-smime-aa-ets-certValues +id-smime-aa 24 : id-smime-aa-ets-revocationValues +id-smime-aa 25 : id-smime-aa-ets-escTimeStamp +id-smime-aa 26 : id-smime-aa-ets-certCRLTimestamp +id-smime-aa 27 : id-smime-aa-ets-archiveTimeStamp +id-smime-aa 28 : id-smime-aa-signatureType +id-smime-aa 29 : id-smime-aa-dvcs-dvc +id-smime-aa 44 : id-aa-ets-attrCertificateRefs +id-smime-aa 45 : id-aa-ets-attrRevocationRefs +id-smime-aa 47 : id-smime-aa-signingCertificateV2 +id-smime-aa 48 : id-aa-ets-archiveTimestampV2 + +# S/MIME Algorithm Identifiers +# obsolete +id-smime-alg 1 : id-smime-alg-ESDHwith3DES +# obsolete +id-smime-alg 2 : id-smime-alg-ESDHwithRC2 +# obsolete +id-smime-alg 3 : id-smime-alg-3DESwrap +# obsolete +id-smime-alg 4 : id-smime-alg-RC2wrap +id-smime-alg 5 : id-smime-alg-ESDH +id-smime-alg 6 : id-smime-alg-CMS3DESwrap +id-smime-alg 7 : id-smime-alg-CMSRC2wrap +id-smime-alg 9 : id-alg-PWRI-KEK +id-smime-alg 17 : id-alg-hss-lms-hashsig +id-smime-alg 28 : id-alg-hkdf-with-sha256 : HKDF-SHA256 +id-smime-alg 29 : id-alg-hkdf-with-sha384 : HKDF-SHA384 +id-smime-alg 30 : id-alg-hkdf-with-sha512 : HKDF-SHA512 + +# S/MIME Certificate Distribution +id-smime-cd 1 : id-smime-cd-ldap + +# S/MIME Signature Policy Qualifier +id-smime-spq 1 : id-smime-spq-ets-sqt-uri +id-smime-spq 2 : id-smime-spq-ets-sqt-unotice + +# S/MIME Commitment Type Identifier +id-smime-cti 1 : id-smime-cti-ets-proofOfOrigin +id-smime-cti 2 : id-smime-cti-ets-proofOfReceipt +id-smime-cti 3 : id-smime-cti-ets-proofOfDelivery +id-smime-cti 4 : id-smime-cti-ets-proofOfSender +id-smime-cti 5 : id-smime-cti-ets-proofOfApproval +id-smime-cti 6 : id-smime-cti-ets-proofOfCreation + +# S/MIME OtherRecipientInfo Type Identifier +id-smime-ori 3 : id-smime-ori-kem + +pkcs9 20 : : friendlyName +pkcs9 21 : : localKeyID +!Alias ms-corp 1 3 6 1 4 1 311 +!Cname ms-csp-name +ms-corp 17 1 : CSPName : Microsoft CSP Name +ms-corp 17 2 : LocalKeySet : Microsoft Local Key set +!Alias certTypes pkcs9 22 +certTypes 1 : : x509Certificate +certTypes 2 : : sdsiCertificate +!Alias crlTypes pkcs9 23 +crlTypes 1 : : x509Crl + +pkcs9 52 : id-aa-CMSAlgorithmProtection + +!Alias pkcs12 pkcs 12 +!Alias pkcs12-pbeids pkcs12 1 + +!Cname pbe-WithSHA1And128BitRC4 +pkcs12-pbeids 1 : PBE-SHA1-RC4-128 : pbeWithSHA1And128BitRC4 +!Cname pbe-WithSHA1And40BitRC4 +pkcs12-pbeids 2 : PBE-SHA1-RC4-40 : pbeWithSHA1And40BitRC4 +!Cname pbe-WithSHA1And3_Key_TripleDES-CBC +pkcs12-pbeids 3 : PBE-SHA1-3DES : pbeWithSHA1And3-KeyTripleDES-CBC +!Cname pbe-WithSHA1And2_Key_TripleDES-CBC +pkcs12-pbeids 4 : PBE-SHA1-2DES : pbeWithSHA1And2-KeyTripleDES-CBC +!Cname pbe-WithSHA1And128BitRC2-CBC +pkcs12-pbeids 5 : PBE-SHA1-RC2-128 : pbeWithSHA1And128BitRC2-CBC +!Cname pbe-WithSHA1And40BitRC2-CBC +pkcs12-pbeids 6 : PBE-SHA1-RC2-40 : pbeWithSHA1And40BitRC2-CBC + +!Alias pkcs12-Version1 pkcs12 10 +!Alias pkcs12-BagIds pkcs12-Version1 1 +pkcs12-BagIds 1 : : keyBag +pkcs12-BagIds 2 : : pkcs8ShroudedKeyBag +pkcs12-BagIds 3 : : certBag +pkcs12-BagIds 4 : : crlBag +pkcs12-BagIds 5 : : secretBag +pkcs12-BagIds 6 : : safeContentsBag + +rsadsi 2 2 : MD2 : md2 +rsadsi 2 4 : MD4 : md4 +rsadsi 2 5 : MD5 : md5 + : MD5-SHA1 : md5-sha1 +rsadsi 2 6 : : hmacWithMD5 +rsadsi 2 7 : : hmacWithSHA1 + +sm-scheme 301 : SM2 : sm2 + +sm-scheme 401 : SM3 : sm3 +sm-scheme 504 : RSA-SM3 : sm3WithRSAEncryption + +sm-scheme 501 : SM2-SM3 : SM2-with-SM3 + +# From GM/T 0091-2020 +sm3 3 1 : : hmacWithSM3 + +# From RFC4231 +rsadsi 2 8 : : hmacWithSHA224 +rsadsi 2 9 : : hmacWithSHA256 +rsadsi 2 10 : : hmacWithSHA384 +rsadsi 2 11 : : hmacWithSHA512 + +# From RFC8018 +rsadsi 2 12 : : hmacWithSHA512-224 +rsadsi 2 13 : : hmacWithSHA512-256 + +rsadsi 3 2 : RC2-CBC : rc2-cbc + : RC2-ECB : rc2-ecb +!Cname rc2-cfb64 + : RC2-CFB : rc2-cfb +!Cname rc2-ofb64 + : RC2-OFB : rc2-ofb + : RC2-40-CBC : rc2-40-cbc + : RC2-64-CBC : rc2-64-cbc +rsadsi 3 4 : RC4 : rc4 + : RC4-40 : rc4-40 +rsadsi 3 7 : DES-EDE3-CBC : des-ede3-cbc +rsadsi 3 8 : RC5-CBC : rc5-cbc + : RC5-ECB : rc5-ecb +!Cname rc5-cfb64 + : RC5-CFB : rc5-cfb +!Cname rc5-ofb64 + : RC5-OFB : rc5-ofb + +!Cname ms-ext-req +ms-corp 2 1 14 : msExtReq : Microsoft Extension Request +!Cname ms-code-ind +ms-corp 2 1 21 : msCodeInd : Microsoft Individual Code Signing +!Cname ms-code-com +ms-corp 2 1 22 : msCodeCom : Microsoft Commercial Code Signing +!Cname ms-ctl-sign +ms-corp 10 3 1 : msCTLSign : Microsoft Trust List Signing +!Cname ms-sgc +ms-corp 10 3 3 : msSGC : Microsoft Server Gated Crypto +!Cname ms-efs +ms-corp 10 3 4 : msEFS : Microsoft Encrypted File System +!Cname ms-smartcard-login +ms-corp 20 2 2 : msSmartcardLogin : Microsoft Smartcard Login +!Cname ms-upn +ms-corp 20 2 3 : msUPN : Microsoft User Principal Name + +ms-corp 25 2 : ms-ntds-sec-ext : Microsoft NTDS CA Extension +ms-corp 25 2 1 : ms-ntds-obj-sid : Microsoft NTDS AD objectSid +ms-corp 21 7 : ms-cert-templ : Microsoft certificate template +ms-corp 21 10 : ms-app-policies : Microsoft Application Policies Extension + +1 3 6 1 4 1 188 7 1 1 2 : IDEA-CBC : idea-cbc + : IDEA-ECB : idea-ecb +!Cname idea-cfb64 + : IDEA-CFB : idea-cfb +!Cname idea-ofb64 + : IDEA-OFB : idea-ofb + +1 3 6 1 4 1 3029 1 2 : BF-CBC : bf-cbc + : BF-ECB : bf-ecb +!Cname bf-cfb64 + : BF-CFB : bf-cfb +!Cname bf-ofb64 + : BF-OFB : bf-ofb + +!Cname id-pkix +1 3 6 1 5 5 7 : PKIX + +# PKIX Arcs +id-pkix 0 : id-pkix-mod +id-pkix 1 : id-pe +id-pkix 2 : id-qt +id-pkix 3 : id-kp +id-pkix 4 : id-it +id-pkix 5 : id-pkip +id-pkix 6 : id-alg +id-pkix 7 : id-cmc +id-pkix 8 : id-on +id-pkix 9 : id-pda +id-pkix 10 : id-aca +id-pkix 11 : id-qcs +id-pkix 14 : id-cp +id-pkix 12 : id-cct +id-pkix 21 : id-ppl +id-pkix 48 : id-ad + +# PKIX Modules +id-pkix-mod 1 : id-pkix1-explicit-88 +id-pkix-mod 2 : id-pkix1-implicit-88 +id-pkix-mod 3 : id-pkix1-explicit-93 +id-pkix-mod 4 : id-pkix1-implicit-93 +id-pkix-mod 5 : id-mod-crmf +id-pkix-mod 6 : id-mod-cmc +id-pkix-mod 7 : id-mod-kea-profile-88 +id-pkix-mod 8 : id-mod-kea-profile-93 +id-pkix-mod 9 : id-mod-cmp +id-pkix-mod 10 : id-mod-qualified-cert-88 +id-pkix-mod 11 : id-mod-qualified-cert-93 +id-pkix-mod 12 : id-mod-attribute-cert +id-pkix-mod 13 : id-mod-timestamp-protocol +id-pkix-mod 14 : id-mod-ocsp +id-pkix-mod 15 : id-mod-dvcs +id-pkix-mod 16 : id-mod-cmp2000 +id-pkix-mod 50 : id-mod-cmp2000-02 +id-pkix-mod 99 : id-mod-cmp2021-88 +id-pkix-mod 100 : id-mod-cmp2021-02 + +# PKIX Private Extensions +!Cname info-access +id-pe 1 : authorityInfoAccess : Authority Information Access +id-pe 2 : biometricInfo : Biometric Info +id-pe 3 : qcStatements +id-pe 4 : ac-auditIdentity : X509v3 Audit Identity +!Alias ac-auditEntity ac-auditIdentity +id-pe 5 : ac-targeting +id-pe 6 : aaControls +id-pe 7 : sbgp-ipAddrBlock +id-pe 8 : sbgp-autonomousSysNum +id-pe 9 : sbgp-routerIdentifier +id-pe 10 : ac-proxying +!Cname sinfo-access +id-pe 11 : subjectInfoAccess : Subject Information Access +id-pe 14 : proxyCertInfo : Proxy Certificate Information +id-pe 24 : tlsfeature : TLS Feature +id-pe 28 : sbgp-ipAddrBlockv2 +id-pe 29 : sbgp-autonomousSysNumv2 + +# PKIX policyQualifiers for Internet policy qualifiers +id-qt 1 : id-qt-cps : Policy Qualifier CPS +id-qt 2 : id-qt-unotice : Policy Qualifier User Notice +id-qt 3 : textNotice + +# https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-1.3.6.1.5.5.7.3 +# PKIX key purpose identifiers +!Cname server-auth +id-kp 1 : serverAuth : TLS Web Server Authentication +!Cname client-auth +id-kp 2 : clientAuth : TLS Web Client Authentication +!Cname code-sign +id-kp 3 : codeSigning : Code Signing +!Cname email-protect +id-kp 4 : emailProtection : E-mail Protection +id-kp 5 : ipsecEndSystem : IPSec End System +id-kp 6 : ipsecTunnel : IPSec Tunnel +id-kp 7 : ipsecUser : IPSec User +!Cname time-stamp +id-kp 8 : timeStamping : Time Stamping +# From OCSP spec RFC2560 +!Cname OCSP-sign +id-kp 9 : OCSPSigning : OCSP Signing +id-kp 10 : DVCS : dvcs +!Cname ipsec-IKE +id-kp 17 : ipsecIKE : ipsec Internet Key Exchange +id-kp 18 : capwapAC : Ctrl/provision WAP Access +id-kp 19 : capwapWTP : Ctrl/Provision WAP Termination +!Cname sshClient +id-kp 21 : secureShellClient : SSH Client +!Cname sshServer +id-kp 22 : secureShellServer : SSH Server +id-kp 23 : sendRouter : Send Router +id-kp 24 : sendProxiedRouter : Send Proxied Router +id-kp 25 : sendOwner : Send Owner +id-kp 26 : sendProxiedOwner : Send Proxied Owner +id-kp 27 : cmcCA : CMC Certificate Authority +id-kp 28 : cmcRA : CMC Registration Authority +id-kp 29 : cmcArchive : CMC Archive Server +id-kp 30 : id-kp-bgpsec-router : BGPsec Router +id-kp 31 : id-kp-BrandIndicatorforMessageIdentification : Brand Indicator for Message Identification +id-kp 32 : cmKGA : Certificate Management Key Generation Authority + +# https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-1.3.6.1.5.5.7.4 +# CMP information types +id-it 1 : id-it-caProtEncCert +id-it 2 : id-it-signKeyPairTypes +id-it 3 : id-it-encKeyPairTypes +id-it 4 : id-it-preferredSymmAlg +id-it 5 : id-it-caKeyUpdateInfo +id-it 6 : id-it-currentCRL +id-it 7 : id-it-unsupportedOIDs +# [Reserved and Obsolete]: +id-it 8 : id-it-subscriptionRequest +# [Reserved and Obsolete]: +id-it 9 : id-it-subscriptionResponse +id-it 10 : id-it-keyPairParamReq +id-it 11 : id-it-keyPairParamRep +id-it 12 : id-it-revPassphrase +id-it 13 : id-it-implicitConfirm +id-it 14 : id-it-confirmWaitTime +id-it 15 : id-it-origPKIMessage +id-it 16 : id-it-suppLangTags +id-it 17 : id-it-caCerts +id-it 18 : id-it-rootCaKeyUpdate +id-it 19 : id-it-certReqTemplate +id-it 20 : id-it-rootCaCert +id-it 21 : id-it-certProfile +id-it 22 : id-it-crlStatusList +id-it 23 : id-it-crls + +# CRMF registration +id-pkip 1 : id-regCtrl +id-pkip 2 : id-regInfo + +# CRMF registration controls +id-regCtrl 1 : id-regCtrl-regToken +id-regCtrl 2 : id-regCtrl-authenticator +id-regCtrl 3 : id-regCtrl-pkiPublicationInfo +id-regCtrl 4 : id-regCtrl-pkiArchiveOptions +id-regCtrl 5 : id-regCtrl-oldCertID +id-regCtrl 6 : id-regCtrl-protocolEncrKey +id-regCtrl 7 : id-regCtrl-altCertTemplate +# id-regCtrl 8 : id-regCtrl-wtlsTemplate [Reserved and Obsolete] +# id-regCtrl 9 : id-regCtrl-regTokenUTF8 [Reserved and Obsolete] +# id-regCtrl 10 : id-regCtrl-authenticatorUTF8 [Reserved and Obsolete] +id-regCtrl 11 : id-regCtrl-algId +id-regCtrl 12 : id-regCtrl-rsaKeyLen + +# CRMF registration information +id-regInfo 1 : id-regInfo-utf8Pairs +id-regInfo 2 : id-regInfo-certReq + +# algorithms +id-alg 1 : id-alg-des40 +id-alg 2 : id-alg-noSignature +id-alg 3 : id-alg-dh-sig-hmac-sha1 +id-alg 4 : id-alg-dh-pop + +# CMC controls +id-cmc 1 : id-cmc-statusInfo +id-cmc 2 : id-cmc-identification +id-cmc 3 : id-cmc-identityProof +id-cmc 4 : id-cmc-dataReturn +id-cmc 5 : id-cmc-transactionId +id-cmc 6 : id-cmc-senderNonce +id-cmc 7 : id-cmc-recipientNonce +id-cmc 8 : id-cmc-addExtensions +id-cmc 9 : id-cmc-encryptedPOP +id-cmc 10 : id-cmc-decryptedPOP +id-cmc 11 : id-cmc-lraPOPWitness +id-cmc 15 : id-cmc-getCert +id-cmc 16 : id-cmc-getCRL +id-cmc 17 : id-cmc-revokeRequest +id-cmc 18 : id-cmc-regInfo +id-cmc 19 : id-cmc-responseInfo +id-cmc 21 : id-cmc-queryPending +id-cmc 22 : id-cmc-popLinkRandom +id-cmc 23 : id-cmc-popLinkWitness +id-cmc 24 : id-cmc-confirmCertAcceptance + +# other names +id-on 1 : id-on-personalData +id-on 3 : id-on-permanentIdentifier : Permanent Identifier +id-on 4 : id-on-hardwareModuleName : Hardware Module Name +id-on 5 : id-on-xmppAddr : XmppAddr +id-on 7 : id-on-dnsSRV : SRVName +id-on 8 : id-on-NAIRealm : NAIRealm +id-on 9 : id-on-SmtpUTF8Mailbox : Smtp UTF8 Mailbox + +# personal data attributes +id-pda 1 : id-pda-dateOfBirth +id-pda 2 : id-pda-placeOfBirth +id-pda 3 : id-pda-gender +id-pda 4 : id-pda-countryOfCitizenship +id-pda 5 : id-pda-countryOfResidence + +# attribute certificate attributes +id-aca 1 : id-aca-authenticationInfo +id-aca 2 : id-aca-accessIdentity +id-aca 3 : id-aca-chargingIdentity +id-aca 4 : id-aca-group +# attention : the following seems to be obsolete, replace by 'role' +id-aca 5 : id-aca-role +id-aca 6 : id-aca-encAttrs + +# qualified certificate statements +id-qcs 1 : id-qcs-pkixQCSyntax-v1 + +# PKIX Certificate Policies +id-cp 2 : ipAddr-asNumber +id-cp 3 : ipAddr-asNumberv2 + +# CMC content types +id-cct 1 : id-cct-crs +id-cct 2 : id-cct-PKIData +id-cct 3 : id-cct-PKIResponse + +# Predefined Proxy Certificate policy languages +id-ppl 0 : id-ppl-anyLanguage : Any language +id-ppl 1 : id-ppl-inheritAll : Inherit all +id-ppl 2 : id-ppl-independent : Independent + +# access descriptors for authority info access extension +!Cname ad-OCSP +id-ad 1 : OCSP : OCSP +!Cname ad-ca-issuers +id-ad 2 : caIssuers : CA Issuers +!Cname ad-timeStamping +id-ad 3 : ad_timestamping : AD Time Stamping +!Cname ad-dvcs +id-ad 4 : AD_DVCS : ad dvcs +id-ad 5 : caRepository : CA Repository +id-ad 10 : rpkiManifest : RPKI Manifest +id-ad 11 : signedObject : Signed Object +id-ad 13 : rpkiNotify : RPKI Notify + +!Alias id-pkix-OCSP ad-OCSP +!module id-pkix-OCSP +!Cname basic +id-pkix-OCSP 1 : basicOCSPResponse : Basic OCSP Response +id-pkix-OCSP 2 : Nonce : OCSP Nonce +id-pkix-OCSP 3 : CrlID : OCSP CRL ID +id-pkix-OCSP 4 : acceptableResponses : Acceptable OCSP Responses +id-pkix-OCSP 5 : noCheck : OCSP No Check +id-pkix-OCSP 6 : archiveCutoff : OCSP Archive Cutoff +id-pkix-OCSP 7 : serviceLocator : OCSP Service Locator +id-pkix-OCSP 8 : extendedStatus : Extended OCSP Status +id-pkix-OCSP 9 : valid +id-pkix-OCSP 10 : path +id-pkix-OCSP 11 : trustRoot : Trust Root +!global + +1 3 14 3 2 : algorithm : algorithm +algorithm 3 : RSA-NP-MD5 : md5WithRSA +algorithm 6 : DES-ECB : des-ecb +algorithm 7 : DES-CBC : des-cbc +!Cname des-ofb64 +algorithm 8 : DES-OFB : des-ofb +!Cname des-cfb64 +algorithm 9 : DES-CFB : des-cfb +algorithm 11 : rsaSignature +!Cname dsa-2 +algorithm 12 : DSA-old : dsaEncryption-old +algorithm 13 : DSA-SHA : dsaWithSHA +algorithm 15 : RSA-SHA : shaWithRSAEncryption +!Cname des-ede-ecb +algorithm 17 : DES-EDE : des-ede +!Cname des-ede3-ecb + : DES-EDE3 : des-ede3 + : DES-EDE-CBC : des-ede-cbc +!Cname des-ede-cfb64 + : DES-EDE-CFB : des-ede-cfb +!Cname des-ede3-cfb64 + : DES-EDE3-CFB : des-ede3-cfb +!Cname des-ede-ofb64 + : DES-EDE-OFB : des-ede-ofb +!Cname des-ede3-ofb64 + : DES-EDE3-OFB : des-ede3-ofb + : DESX-CBC : desx-cbc +algorithm 18 : SHA : sha +algorithm 26 : SHA1 : sha1 +!Cname dsaWithSHA1-2 +algorithm 27 : DSA-SHA1-old : dsaWithSHA1-old +algorithm 29 : RSA-SHA1-2 : sha1WithRSA + +1 3 36 3 2 1 : RIPEMD160 : ripemd160 +1 3 36 3 3 1 2 : RSA-RIPEMD160 : ripemd160WithRSA + +1 3 6 1 4 1 1722 12 2 1 : BLAKE2BMAC : blake2bmac +1 3 6 1 4 1 1722 12 2 2 : BLAKE2SMAC : blake2smac +blake2bmac 16 : BLAKE2b512 : blake2b512 +blake2smac 8 : BLAKE2s256 : blake2s256 + +!Cname sxnet +1 3 101 1 4 1 : SXNetID : Strong Extranet ID + +2 5 : X500 : directory services (X.500) + +X500 4 : X509 +X509 3 : CN : commonName +X509 4 : SN : surname +X509 5 : : serialNumber +X509 6 : C : countryName +X509 7 : L : localityName +X509 8 : ST : stateOrProvinceName +X509 9 : street : streetAddress +X509 10 : O : organizationName +X509 11 : OU : organizationalUnitName +X509 12 : title : title +X509 13 : : description +X509 14 : : searchGuide +X509 15 : : businessCategory +X509 16 : : postalAddress +X509 17 : : postalCode +X509 18 : : postOfficeBox +X509 19 : : physicalDeliveryOfficeName +X509 20 : : telephoneNumber +X509 21 : : telexNumber +X509 22 : : teletexTerminalIdentifier +X509 23 : : facsimileTelephoneNumber +X509 24 : : x121Address +X509 25 : : internationaliSDNNumber +X509 26 : : registeredAddress +X509 27 : : destinationIndicator +X509 28 : : preferredDeliveryMethod +X509 29 : : presentationAddress +X509 30 : : supportedApplicationContext +X509 31 : member : +X509 32 : owner : +X509 33 : : roleOccupant +X509 34 : seeAlso : +X509 35 : : userPassword +X509 36 : : userCertificate +X509 37 : : cACertificate +X509 38 : : authorityRevocationList +X509 39 : : certificateRevocationList +X509 40 : : crossCertificatePair +X509 41 : name : name +X509 42 : GN : givenName +X509 43 : initials : initials +X509 44 : : generationQualifier +X509 45 : : x500UniqueIdentifier +X509 46 : dnQualifier : dnQualifier +X509 47 : : enhancedSearchGuide +X509 48 : : protocolInformation +X509 49 : : distinguishedName +X509 50 : : uniqueMember +X509 51 : : houseIdentifier +X509 52 : : supportedAlgorithms +X509 53 : : deltaRevocationList +X509 54 : dmdName : +X509 65 : : pseudonym +X509 72 : role : role +X509 97 : : organizationIdentifier +X509 98 : c3 : countryCode3c +X509 99 : n3 : countryCode3n +X509 100 : : dnsName + + +X500 8 : X500algorithms : directory services - algorithms +X500algorithms 1 1 : RSA : rsa +X500algorithms 3 100 : RSA-MDC2 : mdc2WithRSA +X500algorithms 3 101 : MDC2 : mdc2 + +X500 29 : id-ce +!Cname subject-directory-attributes +id-ce 9 : subjectDirectoryAttributes : X509v3 Subject Directory Attributes +!Cname subject-key-identifier +id-ce 14 : subjectKeyIdentifier : X509v3 Subject Key Identifier +!Cname key-usage +id-ce 15 : keyUsage : X509v3 Key Usage +!Cname private-key-usage-period +id-ce 16 : privateKeyUsagePeriod : X509v3 Private Key Usage Period +!Cname subject-alt-name +id-ce 17 : subjectAltName : X509v3 Subject Alternative Name +!Cname issuer-alt-name +id-ce 18 : issuerAltName : X509v3 Issuer Alternative Name +!Cname basic-constraints +id-ce 19 : basicConstraints : X509v3 Basic Constraints +!Cname crl-number +id-ce 20 : crlNumber : X509v3 CRL Number +!Cname crl-reason +id-ce 21 : CRLReason : X509v3 CRL Reason Code +!Cname invalidity-date +id-ce 24 : invalidityDate : Invalidity Date +!Cname delta-crl +id-ce 27 : deltaCRL : X509v3 Delta CRL Indicator +!Cname issuing-distribution-point +id-ce 28 : issuingDistributionPoint : X509v3 Issuing Distribution Point +!Cname certificate-issuer +id-ce 29 : certificateIssuer : X509v3 Certificate Issuer +!Cname name-constraints +id-ce 30 : nameConstraints : X509v3 Name Constraints +!Cname crl-distribution-points +id-ce 31 : crlDistributionPoints : X509v3 CRL Distribution Points +!Cname certificate-policies +id-ce 32 : certificatePolicies : X509v3 Certificate Policies +!Cname any-policy +certificate-policies 0 : anyPolicy : X509v3 Any Policy +!Cname policy-mappings +id-ce 33 : policyMappings : X509v3 Policy Mappings +!Cname authority-key-identifier +id-ce 35 : authorityKeyIdentifier : X509v3 Authority Key Identifier +!Cname policy-constraints +id-ce 36 : policyConstraints : X509v3 Policy Constraints +!Cname ext-key-usage +id-ce 37 : extendedKeyUsage : X509v3 Extended Key Usage +!Cname authority-attribute-identifier +id-ce 38 : authorityAttributeIdentifier : X509v3 Authority Attribute Identifier +!Cname role-spec-cert-identifier +id-ce 39 : roleSpecCertIdentifier : X509v3 Role Specification Certificate Identifier +!Cname basic-att-constraints +id-ce 41 : basicAttConstraints : X509v3 Basic Attribute Certificate Constraints +!Cname delegated-name-constraints +id-ce 42 : delegatedNameConstraints : X509v3 Delegated Name Constraints +!Cname time-specification +id-ce 43 : timeSpecification : X509v3 Time Specification +!Cname freshest-crl +id-ce 46 : freshestCRL : X509v3 Freshest CRL +!Cname attribute-descriptor +id-ce 48 : attributeDescriptor : X509v3 Attribute Descriptor +!Cname user-notice +id-ce 49 : userNotice : X509v3 User Notice +!Cname soa-identifier +id-ce 50 : sOAIdentifier : X509v3 Source of Authority Identifier +!Cname acceptable-cert-policies +id-ce 52 : acceptableCertPolicies : X509v3 Acceptable Certification Policies +!Cname inhibit-any-policy +id-ce 54 : inhibitAnyPolicy : X509v3 Inhibit Any Policy +!Cname target-information +id-ce 55 : targetInformation : X509v3 AC Targeting +!Cname no-rev-avail +id-ce 56 : noRevAvail : X509v3 No Revocation Available +!Cname acceptable-privilege-policies +id-ce 57 : acceptablePrivPolicies : X509v3 Acceptable Privilege Policies +!Cname indirect-issuer +id-ce 61 : indirectIssuer : X509v3 Indirect Issuer +!Cname no-assertion +id-ce 62 : noAssertion : X509v3 No Assertion +!Cname id-aa-issuing-distribution-point +id-ce 63 : aAissuingDistributionPoint : X509v3 Attribute Authority Issuing Distribution Point +!Cname issued-on-behalf-of +id-ce 64 : issuedOnBehalfOf : X509v3 Issued On Behalf Of +!Cname single-use +id-ce 65 : singleUse : X509v3 Single Use +!Cname group-ac +id-ce 66 : groupAC : X509v3 Group Attribute Certificate +!Cname allowed-attribute-assignments +id-ce 67 : allowedAttributeAssignments : X509v3 Allowed Attribute Assignments +!Cname attribute-mappings +id-ce 68 : attributeMappings : X509v3 Attribute Mappings +!Cname holder-name-constraints +id-ce 69 : holderNameConstraints : X509v3 Holder Name Constraints +!Cname authorization-validation +id-ce 70 : authorizationValidation : X509v3 Authorization Validation +!Cname prot-restrict +id-ce 71 : protRestrict : X509v3 Protocol Restriction +!Cname subject-alt-public-key-info +id-ce 72 : subjectAltPublicKeyInfo : X509v3 Subject Alternative Public Key Info +!Cname alt-signature-algorithm +id-ce 73 : altSignatureAlgorithm : X509v3 Alternative Signature Algorithm +!Cname alt-signature-value +id-ce 74 : altSignatureValue : X509v3 Alternative Signature Value +!Cname associated-information +id-ce 75 : associatedInformation : X509v3 Associated Information + +# From RFC5280 +ext-key-usage 0 : anyExtendedKeyUsage : Any Extended Key Usage + + +!Cname netscape +2 16 840 1 113730 : Netscape : Netscape Communications Corp. +!Cname netscape-cert-extension +netscape 1 : nsCertExt : Netscape Certificate Extension +!Cname netscape-data-type +netscape 2 : nsDataType : Netscape Data Type +!Cname netscape-cert-type +netscape-cert-extension 1 : nsCertType : Netscape Cert Type +!Cname netscape-base-url +netscape-cert-extension 2 : nsBaseUrl : Netscape Base Url +!Cname netscape-revocation-url +netscape-cert-extension 3 : nsRevocationUrl : Netscape Revocation Url +!Cname netscape-ca-revocation-url +netscape-cert-extension 4 : nsCaRevocationUrl : Netscape CA Revocation Url +!Cname netscape-renewal-url +netscape-cert-extension 7 : nsRenewalUrl : Netscape Renewal Url +!Cname netscape-ca-policy-url +netscape-cert-extension 8 : nsCaPolicyUrl : Netscape CA Policy Url +!Cname netscape-ssl-server-name +netscape-cert-extension 12 : nsSslServerName : Netscape SSL Server Name +!Cname netscape-comment +netscape-cert-extension 13 : nsComment : Netscape Comment +!Cname netscape-cert-sequence +netscape-data-type 5 : nsCertSequence : Netscape Certificate Sequence +!Cname ns-sgc +netscape 4 1 : nsSGC : Netscape Server Gated Crypto + +# iso(1) +iso 3 : ORG : org +org 6 : DOD : dod +dod 1 : IANA : iana +!Alias internet iana + +internet 1 : directory : Directory +internet 2 : mgmt : Management +internet 3 : experimental : Experimental +internet 4 : private : Private +internet 5 : security : Security +internet 6 : snmpv2 : SNMPv2 +# Documents refer to "internet 7" as "mail". This however leads to ambiguities +# with RFC2798, Section 9.1.3, where "mail" is defined as the short name for +# rfc822Mailbox. The short name is therefore here left out for a reason. +# Subclasses of "mail", e.g. "MIME MHS" don't constitute a problem, as +# references are realized via long name "Mail" (with capital M). +internet 7 : : Mail + +Private 1 : enterprises : Enterprises + +# RFC 2247 +Enterprises 1466 344 : dcobject : dcObject + +# Wi-SUN Assigned Value Registry +Enterprises 45605 1 : id-kp-wisun-fan-device : Wi-SUN Alliance Field Area Network (FAN) + +# RFC 1495 +Mail 1 : mime-mhs : MIME MHS +mime-mhs 1 : mime-mhs-headings : mime-mhs-headings +mime-mhs 2 : mime-mhs-bodies : mime-mhs-bodies +mime-mhs-headings 1 : id-hex-partial-message : id-hex-partial-message +mime-mhs-headings 2 : id-hex-multipart-message : id-hex-multipart-message + +# RFC 3274 +!Cname zlib-compression +id-smime-alg 8 : ZLIB : zlib compression + +# AES aka Rijndael + +!Alias csor 2 16 840 1 101 3 +!Alias nistAlgorithms csor 4 +!Alias aes nistAlgorithms 1 + +aes 1 : AES-128-ECB : aes-128-ecb +aes 2 : AES-128-CBC : aes-128-cbc +!Cname aes-128-ofb128 +aes 3 : AES-128-OFB : aes-128-ofb +!Cname aes-128-cfb128 +aes 4 : AES-128-CFB : aes-128-cfb +aes 5 : id-aes128-wrap +aes 6 : id-aes128-GCM : aes-128-gcm +aes 7 : id-aes128-CCM : aes-128-ccm +aes 8 : id-aes128-wrap-pad + +aes 21 : AES-192-ECB : aes-192-ecb +aes 22 : AES-192-CBC : aes-192-cbc +!Cname aes-192-ofb128 +aes 23 : AES-192-OFB : aes-192-ofb +!Cname aes-192-cfb128 +aes 24 : AES-192-CFB : aes-192-cfb +aes 25 : id-aes192-wrap +aes 26 : id-aes192-GCM : aes-192-gcm +aes 27 : id-aes192-CCM : aes-192-ccm +aes 28 : id-aes192-wrap-pad + +aes 41 : AES-256-ECB : aes-256-ecb +aes 42 : AES-256-CBC : aes-256-cbc +!Cname aes-256-ofb128 +aes 43 : AES-256-OFB : aes-256-ofb +!Cname aes-256-cfb128 +aes 44 : AES-256-CFB : aes-256-cfb +aes 45 : id-aes256-wrap +aes 46 : id-aes256-GCM : aes-256-gcm +aes 47 : id-aes256-CCM : aes-256-ccm +aes 48 : id-aes256-wrap-pad + +ieee-siswg 0 1 1 : AES-128-XTS : aes-128-xts +ieee-siswg 0 1 2 : AES-256-XTS : aes-256-xts + +# There are no OIDs for these modes... + + : AES-128-CFB1 : aes-128-cfb1 + : AES-192-CFB1 : aes-192-cfb1 + : AES-256-CFB1 : aes-256-cfb1 + : AES-128-CFB8 : aes-128-cfb8 + : AES-192-CFB8 : aes-192-cfb8 + : AES-256-CFB8 : aes-256-cfb8 + : AES-128-CTR : aes-128-ctr + : AES-192-CTR : aes-192-ctr + : AES-256-CTR : aes-256-ctr + : AES-128-OCB : aes-128-ocb + : AES-192-OCB : aes-192-ocb + : AES-256-OCB : aes-256-ocb + : DES-CFB1 : des-cfb1 + : DES-CFB8 : des-cfb8 + : DES-EDE3-CFB1 : des-ede3-cfb1 + : DES-EDE3-CFB8 : des-ede3-cfb8 + +# OIDs for SHA224, SHA256, SHA385 and SHA512, according to x9.84 and +# http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html +# "Middle" names are specified to be id-sha256, id-sha384, etc., but +# we adhere to unprefixed capitals for backward compatibility... +!Alias nist_hashalgs nistAlgorithms 2 +nist_hashalgs 1 : SHA256 : sha256 +nist_hashalgs 2 : SHA384 : sha384 +nist_hashalgs 3 : SHA512 : sha512 +nist_hashalgs 4 : SHA224 : sha224 +nist_hashalgs 5 : SHA512-224 : sha512-224 +nist_hashalgs 6 : SHA512-256 : sha512-256 +nist_hashalgs 7 : SHA3-224 : sha3-224 +nist_hashalgs 8 : SHA3-256 : sha3-256 +nist_hashalgs 9 : SHA3-384 : sha3-384 +nist_hashalgs 10 : SHA3-512 : sha3-512 +nist_hashalgs 11 : SHAKE128 : shake128 +nist_hashalgs 12 : SHAKE256 : shake256 +nist_hashalgs 13 : id-hmacWithSHA3-224 : hmac-sha3-224 +nist_hashalgs 14 : id-hmacWithSHA3-256 : hmac-sha3-256 +nist_hashalgs 15 : id-hmacWithSHA3-384 : hmac-sha3-384 +nist_hashalgs 16 : id-hmacWithSHA3-512 : hmac-sha3-512 +# Below two are incomplete OIDs, to be uncommented when we figure out +# how to handle them... +# nist_hashalgs 17 : id-shake128-len : shake128-len +# nist_hashalgs 18 : id-shake256-len : shake256-len +nist_hashalgs 19 : KMAC128 : kmac128 +nist_hashalgs 20 : KMAC256 : kmac256 +# nist_hashalgs 21 : KMAC128-XOF : kmac128-xof +# nist_hashalgs 22 : KMAC256-XOF : kmac256-xof + +# OIDs for dsa-with-sha224 and dsa-with-sha256 +!Alias dsa_with_sha2 nistAlgorithms 3 +dsa_with_sha2 1 : dsa_with_SHA224 +dsa_with_sha2 2 : dsa_with_SHA256 +# Above two belong below, but kept as they are for backward compatibility +!Alias sigAlgs nistAlgorithms 3 +sigAlgs 3 : id-dsa-with-sha384 : dsa_with_SHA384 +sigAlgs 4 : id-dsa-with-sha512 : dsa_with_SHA512 +sigAlgs 5 : id-dsa-with-sha3-224 : dsa_with_SHA3-224 +sigAlgs 6 : id-dsa-with-sha3-256 : dsa_with_SHA3-256 +sigAlgs 7 : id-dsa-with-sha3-384 : dsa_with_SHA3-384 +sigAlgs 8 : id-dsa-with-sha3-512 : dsa_with_SHA3-512 +sigAlgs 9 : id-ecdsa-with-sha3-224 : ecdsa_with_SHA3-224 +sigAlgs 10 : id-ecdsa-with-sha3-256 : ecdsa_with_SHA3-256 +sigAlgs 11 : id-ecdsa-with-sha3-384 : ecdsa_with_SHA3-384 +sigAlgs 12 : id-ecdsa-with-sha3-512 : ecdsa_with_SHA3-512 +sigAlgs 13 : id-rsassa-pkcs1-v1_5-with-sha3-224 : RSA-SHA3-224 +sigAlgs 14 : id-rsassa-pkcs1-v1_5-with-sha3-256 : RSA-SHA3-256 +sigAlgs 15 : id-rsassa-pkcs1-v1_5-with-sha3-384 : RSA-SHA3-384 +sigAlgs 16 : id-rsassa-pkcs1-v1_5-with-sha3-512 : RSA-SHA3-512 +sigAlgs 17 : id-ml-dsa-44 : ML-DSA-44 +sigAlgs 18 : id-ml-dsa-65 : ML-DSA-65 +sigAlgs 19 : id-ml-dsa-87 : ML-DSA-87 +sigAlgs 20 : id-slh-dsa-sha2-128s : SLH-DSA-SHA2-128s +sigAlgs 21 : id-slh-dsa-sha2-128f : SLH-DSA-SHA2-128f +sigAlgs 22 : id-slh-dsa-sha2-192s : SLH-DSA-SHA2-192s +sigAlgs 23 : id-slh-dsa-sha2-192f : SLH-DSA-SHA2-192f +sigAlgs 24 : id-slh-dsa-sha2-256s : SLH-DSA-SHA2-256s +sigAlgs 25 : id-slh-dsa-sha2-256f : SLH-DSA-SHA2-256f +sigAlgs 26 : id-slh-dsa-shake-128s : SLH-DSA-SHAKE-128s +sigAlgs 27 : id-slh-dsa-shake-128f : SLH-DSA-SHAKE-128f +sigAlgs 28 : id-slh-dsa-shake-192s : SLH-DSA-SHAKE-192s +sigAlgs 29 : id-slh-dsa-shake-192f : SLH-DSA-SHAKE-192f +sigAlgs 30 : id-slh-dsa-shake-256s : SLH-DSA-SHAKE-256s +sigAlgs 31 : id-slh-dsa-shake-256f : SLH-DSA-SHAKE-256f +sigAlgs 32 : id-hash-ml-dsa-44-with-sha512 : HASH-ML-DSA-44-WITH-SHA512 +sigAlgs 33 : id-hash-ml-dsa-65-with-sha512 : HASH-ML-DSA-65-WITH-SHA512 +sigAlgs 34 : id-hash-ml-dsa-87-with-sha512 : HASH-ML-DSA-87-WITH-SHA512 +sigAlgs 35 : id-hash-slh-dsa-sha2-128s-with-sha256 : SLH-DSA-SHA2-128s-WITH-SHA256 +sigAlgs 36 : id-hash-slh-dsa-sha2-128f-with-sha256 : SLH-DSA-SHA2-128f-WITH-SHA256 +sigAlgs 37 : id-hash-slh-dsa-sha2-192s-with-sha512 : SLH-DSA-SHA2-192s-WITH-SHA512 +sigAlgs 38 : id-hash-slh-dsa-sha2-192f-with-sha512 : SLH-DSA-SHA2-192f-WITH-SHA512 +sigAlgs 39 : id-hash-slh-dsa-sha2-256s-with-sha512 : SLH-DSA-SHA2-256s-WITH-SHA512 +sigAlgs 40 : id-hash-slh-dsa-sha2-256f-with-sha512 : SLH-DSA-SHA2-256f-WITH-SHA512 +sigAlgs 41 : id-hash-slh-dsa-shake-128s-with-shake128 : SLH-DSA-SHAKE-128s-WITH-SHAKE128 +sigAlgs 42 : id-hash-slh-dsa-shake-128f-with-shake128 : SLH-DSA-SHAKE-128f-WITH-SHAKE128 +sigAlgs 43 : id-hash-slh-dsa-shake-192s-with-shake256 : SLH-DSA-SHAKE-192s-WITH-SHAKE256 +sigAlgs 44 : id-hash-slh-dsa-shake-192f-with-shake256 : SLH-DSA-SHAKE-192f-WITH-SHAKE256 +sigAlgs 45 : id-hash-slh-dsa-shake-256s-with-shake256 : SLH-DSA-SHAKE-256s-WITH-SHAKE256 +sigAlgs 46 : id-hash-slh-dsa-shake-256f-with-shake256 : SLH-DSA-SHAKE-256f-WITH-SHAKE256 + +# Hold instruction CRL entry extension +!Cname hold-instruction-code +id-ce 23 : holdInstructionCode : Hold Instruction Code +!Alias holdInstruction X9-57 2 +!Cname hold-instruction-none +holdInstruction 1 : holdInstructionNone : Hold Instruction None +!Cname hold-instruction-call-issuer +holdInstruction 2 : holdInstructionCallIssuer : Hold Instruction Call Issuer +!Cname hold-instruction-reject +holdInstruction 3 : holdInstructionReject : Hold Instruction Reject + +# OID's from ITU-T. Most of this is defined in RFC 1274. A couple of +# them are also mentioned in RFC 2247 +# OIDs specific to Electronic Signature Standard/CAdES are as specified in +# ETSI EN 319 122-1 V1.2.1 (2021-10): +# Electronic Signatures and Infrastructures (ESI); CAdES digital signatures; +# Part 1: Building blocks and CAdES baseline signatures +itu-t 4 : itu-t-identified-organization +itu-t-identified-organization 0: etsi +etsi 1733 : electronic-signature-standard +electronic-signature-standard 2: ess-attributes +ess-attributes 1 : id-aa-ets-mimeType +ess-attributes 2 : id-aa-ets-longTermValidation +ess-attributes 3 : id-aa-ets-SignaturePolicyDocument +ess-attributes 4 : id-aa-ets-archiveTimestampV3 +ess-attributes 5 : id-aa-ATSHashIndex +etsi 19122 : cades +cades 1 : cades-attributes +cades-attributes 1 : id-aa-ets-signerAttrV2 +cades-attributes 3 : id-aa-ets-sigPolicyStore +cades-attributes 4 : id-aa-ATSHashIndex-v2 +cades-attributes 5 : id-aa-ATSHashIndex-v3 +cades-attributes 6 : signedAssertion + +itu-t 9 : data +data 2342 : pss +pss 19200300 : ucl +ucl 100 : pilot +pilot 1 : : pilotAttributeType +pilot 3 : : pilotAttributeSyntax +pilot 4 : : pilotObjectClass +pilot 10 : : pilotGroups +pilotAttributeSyntax 4 : : iA5StringSyntax +pilotAttributeSyntax 5 : : caseIgnoreIA5StringSyntax +pilotObjectClass 3 : : pilotObject +pilotObjectClass 4 : : pilotPerson +pilotObjectClass 5 : account +pilotObjectClass 6 : document +pilotObjectClass 7 : room +pilotObjectClass 9 : : documentSeries +pilotObjectClass 13 : domain : Domain +pilotObjectClass 14 : : rFC822localPart +pilotObjectClass 15 : : dNSDomain +pilotObjectClass 17 : : domainRelatedObject +pilotObjectClass 18 : : friendlyCountry +pilotObjectClass 19 : : simpleSecurityObject +pilotObjectClass 20 : : pilotOrganization +pilotObjectClass 21 : : pilotDSA +pilotObjectClass 22 : : qualityLabelledData +pilotAttributeType 1 : UID : userId +pilotAttributeType 2 : : textEncodedORAddress +pilotAttributeType 3 : mail : rfc822Mailbox +pilotAttributeType 4 : info +pilotAttributeType 5 : : favouriteDrink +pilotAttributeType 6 : : roomNumber +pilotAttributeType 7 : photo +pilotAttributeType 8 : : userClass +pilotAttributeType 9 : host +pilotAttributeType 10 : manager +pilotAttributeType 11 : : documentIdentifier +pilotAttributeType 12 : : documentTitle +pilotAttributeType 13 : : documentVersion +pilotAttributeType 14 : : documentAuthor +pilotAttributeType 15 : : documentLocation +pilotAttributeType 20 : : homeTelephoneNumber +pilotAttributeType 21 : secretary +pilotAttributeType 22 : : otherMailbox +pilotAttributeType 23 : : lastModifiedTime +pilotAttributeType 24 : : lastModifiedBy +pilotAttributeType 25 : DC : domainComponent +pilotAttributeType 26 : : aRecord +pilotAttributeType 27 : : pilotAttributeType27 +pilotAttributeType 28 : : mXRecord +pilotAttributeType 29 : : nSRecord +pilotAttributeType 30 : : sOARecord +pilotAttributeType 31 : : cNAMERecord +pilotAttributeType 37 : : associatedDomain +pilotAttributeType 38 : : associatedName +pilotAttributeType 39 : : homePostalAddress +pilotAttributeType 40 : : personalTitle +pilotAttributeType 41 : : mobileTelephoneNumber +pilotAttributeType 42 : : pagerTelephoneNumber +pilotAttributeType 43 : : friendlyCountryName +pilotAttributeType 44 : uid : uniqueIdentifier +pilotAttributeType 45 : : organizationalStatus +pilotAttributeType 46 : : janetMailbox +pilotAttributeType 47 : : mailPreferenceOption +pilotAttributeType 48 : : buildingName +pilotAttributeType 49 : : dSAQuality +pilotAttributeType 50 : : singleLevelQuality +pilotAttributeType 51 : : subtreeMinimumQuality +pilotAttributeType 52 : : subtreeMaximumQuality +pilotAttributeType 53 : : personalSignature +pilotAttributeType 54 : : dITRedirect +pilotAttributeType 55 : audio +pilotAttributeType 56 : : documentPublisher + +international-organizations 42 : id-set : Secure Electronic Transactions + +id-set 0 : set-ctype : content types +id-set 1 : set-msgExt : message extensions +id-set 3 : set-attr +id-set 5 : set-policy +id-set 7 : set-certExt : certificate extensions +id-set 8 : set-brand + +set-ctype 0 : setct-PANData +set-ctype 1 : setct-PANToken +set-ctype 2 : setct-PANOnly +set-ctype 3 : setct-OIData +set-ctype 4 : setct-PI +set-ctype 5 : setct-PIData +set-ctype 6 : setct-PIDataUnsigned +set-ctype 7 : setct-HODInput +set-ctype 8 : setct-AuthResBaggage +set-ctype 9 : setct-AuthRevReqBaggage +set-ctype 10 : setct-AuthRevResBaggage +set-ctype 11 : setct-CapTokenSeq +set-ctype 12 : setct-PInitResData +set-ctype 13 : setct-PI-TBS +set-ctype 14 : setct-PResData +set-ctype 16 : setct-AuthReqTBS +set-ctype 17 : setct-AuthResTBS +set-ctype 18 : setct-AuthResTBSX +set-ctype 19 : setct-AuthTokenTBS +set-ctype 20 : setct-CapTokenData +set-ctype 21 : setct-CapTokenTBS +set-ctype 22 : setct-AcqCardCodeMsg +set-ctype 23 : setct-AuthRevReqTBS +set-ctype 24 : setct-AuthRevResData +set-ctype 25 : setct-AuthRevResTBS +set-ctype 26 : setct-CapReqTBS +set-ctype 27 : setct-CapReqTBSX +set-ctype 28 : setct-CapResData +set-ctype 29 : setct-CapRevReqTBS +set-ctype 30 : setct-CapRevReqTBSX +set-ctype 31 : setct-CapRevResData +set-ctype 32 : setct-CredReqTBS +set-ctype 33 : setct-CredReqTBSX +set-ctype 34 : setct-CredResData +set-ctype 35 : setct-CredRevReqTBS +set-ctype 36 : setct-CredRevReqTBSX +set-ctype 37 : setct-CredRevResData +set-ctype 38 : setct-PCertReqData +set-ctype 39 : setct-PCertResTBS +set-ctype 40 : setct-BatchAdminReqData +set-ctype 41 : setct-BatchAdminResData +set-ctype 42 : setct-CardCInitResTBS +set-ctype 43 : setct-MeAqCInitResTBS +set-ctype 44 : setct-RegFormResTBS +set-ctype 45 : setct-CertReqData +set-ctype 46 : setct-CertReqTBS +set-ctype 47 : setct-CertResData +set-ctype 48 : setct-CertInqReqTBS +set-ctype 49 : setct-ErrorTBS +set-ctype 50 : setct-PIDualSignedTBE +set-ctype 51 : setct-PIUnsignedTBE +set-ctype 52 : setct-AuthReqTBE +set-ctype 53 : setct-AuthResTBE +set-ctype 54 : setct-AuthResTBEX +set-ctype 55 : setct-AuthTokenTBE +set-ctype 56 : setct-CapTokenTBE +set-ctype 57 : setct-CapTokenTBEX +set-ctype 58 : setct-AcqCardCodeMsgTBE +set-ctype 59 : setct-AuthRevReqTBE +set-ctype 60 : setct-AuthRevResTBE +set-ctype 61 : setct-AuthRevResTBEB +set-ctype 62 : setct-CapReqTBE +set-ctype 63 : setct-CapReqTBEX +set-ctype 64 : setct-CapResTBE +set-ctype 65 : setct-CapRevReqTBE +set-ctype 66 : setct-CapRevReqTBEX +set-ctype 67 : setct-CapRevResTBE +set-ctype 68 : setct-CredReqTBE +set-ctype 69 : setct-CredReqTBEX +set-ctype 70 : setct-CredResTBE +set-ctype 71 : setct-CredRevReqTBE +set-ctype 72 : setct-CredRevReqTBEX +set-ctype 73 : setct-CredRevResTBE +set-ctype 74 : setct-BatchAdminReqTBE +set-ctype 75 : setct-BatchAdminResTBE +set-ctype 76 : setct-RegFormReqTBE +set-ctype 77 : setct-CertReqTBE +set-ctype 78 : setct-CertReqTBEX +set-ctype 79 : setct-CertResTBE +set-ctype 80 : setct-CRLNotificationTBS +set-ctype 81 : setct-CRLNotificationResTBS +set-ctype 82 : setct-BCIDistributionTBS + +set-msgExt 1 : setext-genCrypt : generic cryptogram +set-msgExt 3 : setext-miAuth : merchant initiated auth +set-msgExt 4 : setext-pinSecure +set-msgExt 5 : setext-pinAny +set-msgExt 7 : setext-track2 +set-msgExt 8 : setext-cv : additional verification + +set-policy 0 : set-policy-root + +set-certExt 0 : setCext-hashedRoot +set-certExt 1 : setCext-certType +set-certExt 2 : setCext-merchData +set-certExt 3 : setCext-cCertRequired +set-certExt 4 : setCext-tunneling +set-certExt 5 : setCext-setExt +set-certExt 6 : setCext-setQualf +set-certExt 7 : setCext-PGWYcapabilities +set-certExt 8 : setCext-TokenIdentifier +set-certExt 9 : setCext-Track2Data +set-certExt 10 : setCext-TokenType +set-certExt 11 : setCext-IssuerCapabilities + +set-attr 0 : setAttr-Cert +set-attr 1 : setAttr-PGWYcap : payment gateway capabilities +set-attr 2 : setAttr-TokenType +set-attr 3 : setAttr-IssCap : issuer capabilities + +setAttr-Cert 0 : set-rootKeyThumb +setAttr-Cert 1 : set-addPolicy + +setAttr-TokenType 1 : setAttr-Token-EMV +setAttr-TokenType 2 : setAttr-Token-B0Prime + +setAttr-IssCap 3 : setAttr-IssCap-CVM +setAttr-IssCap 4 : setAttr-IssCap-T2 +setAttr-IssCap 5 : setAttr-IssCap-Sig + +setAttr-IssCap-CVM 1 : setAttr-GenCryptgrm : generate cryptogram +setAttr-IssCap-T2 1 : setAttr-T2Enc : encrypted track 2 +setAttr-IssCap-T2 2 : setAttr-T2cleartxt : cleartext track 2 + +setAttr-IssCap-Sig 1 : setAttr-TokICCsig : ICC or token signature +setAttr-IssCap-Sig 2 : setAttr-SecDevSig : secure device signature + +set-brand 1 : set-brand-IATA-ATA +set-brand 30 : set-brand-Diners +set-brand 34 : set-brand-AmericanExpress +set-brand 35 : set-brand-JCB +set-brand 4 : set-brand-Visa +set-brand 5 : set-brand-MasterCard +set-brand 6011 : set-brand-Novus + +rsadsi 3 10 : DES-CDMF : des-cdmf +rsadsi 1 1 6 : rsaOAEPEncryptionSET + + : Oakley-EC2N-3 : ipsec3 + : Oakley-EC2N-4 : ipsec4 + +iso 0 10118 3 0 55 : whirlpool + +# GOST OIDs + +member-body 643 2 2 : cryptopro +member-body 643 2 9 : cryptocom +member-body 643 7 1 : id-tc26 + +cryptopro 3 : id-GostR3411-94-with-GostR3410-2001 : GOST R 34.11-94 with GOST R 34.10-2001 +cryptopro 4 : id-GostR3411-94-with-GostR3410-94 : GOST R 34.11-94 with GOST R 34.10-94 +!Cname id-GostR3411-94 +cryptopro 9 : md_gost94 : GOST R 34.11-94 +cryptopro 10 : id-HMACGostR3411-94 : HMAC GOST 34.11-94 +!Cname id-GostR3410-2001 +cryptopro 19 : gost2001 : GOST R 34.10-2001 +!Cname id-GostR3410-94 +cryptopro 20 : gost94 : GOST R 34.10-94 +!Cname id-Gost28147-89 +cryptopro 21 : gost89 : GOST 28147-89 + : gost89-cnt + : gost89-cnt-12 + : gost89-cbc + : gost89-ecb + : gost89-ctr +!Cname id-Gost28147-89-MAC +cryptopro 22 : gost-mac : GOST 28147-89 MAC + : gost-mac-12 +!Cname id-GostR3411-94-prf +cryptopro 23 : prf-gostr3411-94 : GOST R 34.11-94 PRF +cryptopro 98 : id-GostR3410-2001DH : GOST R 34.10-2001 DH +cryptopro 99 : id-GostR3410-94DH : GOST R 34.10-94 DH + +cryptopro 14 1 : id-Gost28147-89-CryptoPro-KeyMeshing +cryptopro 14 0 : id-Gost28147-89-None-KeyMeshing + +# GOST parameter set OIDs + +cryptopro 30 0 : id-GostR3411-94-TestParamSet +cryptopro 30 1 : id-GostR3411-94-CryptoProParamSet + +cryptopro 31 0 : id-Gost28147-89-TestParamSet +cryptopro 31 1 : id-Gost28147-89-CryptoPro-A-ParamSet +cryptopro 31 2 : id-Gost28147-89-CryptoPro-B-ParamSet +cryptopro 31 3 : id-Gost28147-89-CryptoPro-C-ParamSet +cryptopro 31 4 : id-Gost28147-89-CryptoPro-D-ParamSet +cryptopro 31 5 : id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet +cryptopro 31 6 : id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet +cryptopro 31 7 : id-Gost28147-89-CryptoPro-RIC-1-ParamSet + +cryptopro 32 0 : id-GostR3410-94-TestParamSet +cryptopro 32 2 : id-GostR3410-94-CryptoPro-A-ParamSet +cryptopro 32 3 : id-GostR3410-94-CryptoPro-B-ParamSet +cryptopro 32 4 : id-GostR3410-94-CryptoPro-C-ParamSet +cryptopro 32 5 : id-GostR3410-94-CryptoPro-D-ParamSet + +cryptopro 33 1 : id-GostR3410-94-CryptoPro-XchA-ParamSet +cryptopro 33 2 : id-GostR3410-94-CryptoPro-XchB-ParamSet +cryptopro 33 3 : id-GostR3410-94-CryptoPro-XchC-ParamSet + +cryptopro 35 0 : id-GostR3410-2001-TestParamSet +cryptopro 35 1 : id-GostR3410-2001-CryptoPro-A-ParamSet +cryptopro 35 2 : id-GostR3410-2001-CryptoPro-B-ParamSet +cryptopro 35 3 : id-GostR3410-2001-CryptoPro-C-ParamSet + +cryptopro 36 0 : id-GostR3410-2001-CryptoPro-XchA-ParamSet +cryptopro 36 1 : id-GostR3410-2001-CryptoPro-XchB-ParamSet + +id-GostR3410-94 1 : id-GostR3410-94-a +id-GostR3410-94 2 : id-GostR3410-94-aBis +id-GostR3410-94 3 : id-GostR3410-94-b +id-GostR3410-94 4 : id-GostR3410-94-bBis + +# Cryptocom LTD GOST OIDs + +cryptocom 1 6 1 : id-Gost28147-89-cc : GOST 28147-89 Cryptocom ParamSet +!Cname id-GostR3410-94-cc +cryptocom 1 5 3 : gost94cc : GOST 34.10-94 Cryptocom +!Cname id-GostR3410-2001-cc +cryptocom 1 5 4 : gost2001cc : GOST 34.10-2001 Cryptocom + +cryptocom 1 3 3 : id-GostR3411-94-with-GostR3410-94-cc : GOST R 34.11-94 with GOST R 34.10-94 Cryptocom +cryptocom 1 3 4 : id-GostR3411-94-with-GostR3410-2001-cc : GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom + +cryptocom 1 8 1 : id-GostR3410-2001-ParamSet-cc : GOST R 3410-2001 Parameter Set Cryptocom + +# TC26 GOST OIDs + +id-tc26 1 : id-tc26-algorithms +id-tc26-algorithms 1 : id-tc26-sign +!Cname id-GostR3410-2012-256 +id-tc26-sign 1 : gost2012_256: GOST R 34.10-2012 with 256 bit modulus +!Cname id-GostR3410-2012-512 +id-tc26-sign 2 : gost2012_512: GOST R 34.10-2012 with 512 bit modulus + +id-tc26-algorithms 2 : id-tc26-digest +!Cname id-GostR3411-2012-256 +id-tc26-digest 2 : md_gost12_256: GOST R 34.11-2012 with 256 bit hash +!Cname id-GostR3411-2012-512 +id-tc26-digest 3 : md_gost12_512: GOST R 34.11-2012 with 512 bit hash + +id-tc26-algorithms 3 : id-tc26-signwithdigest +id-tc26-signwithdigest 2: id-tc26-signwithdigest-gost3410-2012-256: GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit) +id-tc26-signwithdigest 3: id-tc26-signwithdigest-gost3410-2012-512: GOST R 34.10-2012 with GOST R 34.11-2012 (512 bit) + +id-tc26-algorithms 4 : id-tc26-mac +id-tc26-mac 1 : id-tc26-hmac-gost-3411-2012-256 : HMAC GOST 34.11-2012 256 bit +id-tc26-mac 2 : id-tc26-hmac-gost-3411-2012-512 : HMAC GOST 34.11-2012 512 bit + +id-tc26-algorithms 5 : id-tc26-cipher +id-tc26-cipher 1 : id-tc26-cipher-gostr3412-2015-magma +id-tc26-cipher-gostr3412-2015-magma 1 : magma-ctr-acpkm +id-tc26-cipher-gostr3412-2015-magma 2 : magma-ctr-acpkm-omac +id-tc26-cipher 2 : id-tc26-cipher-gostr3412-2015-kuznyechik +id-tc26-cipher-gostr3412-2015-kuznyechik 1 : kuznyechik-ctr-acpkm +id-tc26-cipher-gostr3412-2015-kuznyechik 2 : kuznyechik-ctr-acpkm-omac + +id-tc26-algorithms 6 : id-tc26-agreement +id-tc26-agreement 1 : id-tc26-agreement-gost-3410-2012-256 +id-tc26-agreement 2 : id-tc26-agreement-gost-3410-2012-512 + +id-tc26-algorithms 7 : id-tc26-wrap +id-tc26-wrap 1 : id-tc26-wrap-gostr3412-2015-magma +id-tc26-wrap-gostr3412-2015-magma 1 : magma-kexp15 +id-tc26-wrap 2 : id-tc26-wrap-gostr3412-2015-kuznyechik +id-tc26-wrap-gostr3412-2015-kuznyechik 1 : kuznyechik-kexp15 + +id-tc26 2 : id-tc26-constants + +id-tc26-constants 1 : id-tc26-sign-constants +id-tc26-sign-constants 1: id-tc26-gost-3410-2012-256-constants +id-tc26-gost-3410-2012-256-constants 1 : id-tc26-gost-3410-2012-256-paramSetA: GOST R 34.10-2012 (256 bit) ParamSet A +id-tc26-gost-3410-2012-256-constants 2 : id-tc26-gost-3410-2012-256-paramSetB: GOST R 34.10-2012 (256 bit) ParamSet B +id-tc26-gost-3410-2012-256-constants 3 : id-tc26-gost-3410-2012-256-paramSetC: GOST R 34.10-2012 (256 bit) ParamSet C +id-tc26-gost-3410-2012-256-constants 4 : id-tc26-gost-3410-2012-256-paramSetD: GOST R 34.10-2012 (256 bit) ParamSet D +id-tc26-sign-constants 2: id-tc26-gost-3410-2012-512-constants +id-tc26-gost-3410-2012-512-constants 0 : id-tc26-gost-3410-2012-512-paramSetTest: GOST R 34.10-2012 (512 bit) testing parameter set +id-tc26-gost-3410-2012-512-constants 1 : id-tc26-gost-3410-2012-512-paramSetA: GOST R 34.10-2012 (512 bit) ParamSet A +id-tc26-gost-3410-2012-512-constants 2 : id-tc26-gost-3410-2012-512-paramSetB: GOST R 34.10-2012 (512 bit) ParamSet B +id-tc26-gost-3410-2012-512-constants 3 : id-tc26-gost-3410-2012-512-paramSetC: GOST R 34.10-2012 (512 bit) ParamSet C + +id-tc26-constants 2 : id-tc26-digest-constants +id-tc26-constants 5 : id-tc26-cipher-constants +id-tc26-cipher-constants 1 : id-tc26-gost-28147-constants +id-tc26-gost-28147-constants 1 : id-tc26-gost-28147-param-Z : GOST 28147-89 TC26 parameter set + +member-body 643 3 131 1 1 : INN : INN +member-body 643 100 1 : OGRN : OGRN +member-body 643 100 3 : SNILS : SNILS +member-body 643 100 5 : OGRNIP : OGRNIP +member-body 643 100 111 : subjectSignTool : Signing Tool of Subject +member-body 643 100 112 : issuerSignTool : Signing Tool of Issuer +member-body 643 100 113 : classSignTool : Class of Signing Tool +member-body 643 100 113 1 : classSignToolKC1 : Class of Signing Tool KC1 +member-body 643 100 113 2 : classSignToolKC2 : Class of Signing Tool KC2 +member-body 643 100 113 3 : classSignToolKC3 : Class of Signing Tool KC3 +member-body 643 100 113 4 : classSignToolKB1 : Class of Signing Tool KB1 +member-body 643 100 113 5 : classSignToolKB2 : Class of Signing Tool KB2 +member-body 643 100 113 6 : classSignToolKA1 : Class of Signing Tool KA1 + +#GOST R34.13-2015 Grasshopper "Kuznechik" + : kuznyechik-ecb + : kuznyechik-ctr + : kuznyechik-ofb + : kuznyechik-cbc + : kuznyechik-cfb + : kuznyechik-mac + +#GOST R34.13-2015 Magma + : magma-ecb + : magma-ctr + : magma-ofb + : magma-cbc + : magma-cfb + : magma-mac + +# Definitions for Camellia cipher - CBC MODE + +1 2 392 200011 61 1 1 1 2 : CAMELLIA-128-CBC : camellia-128-cbc +1 2 392 200011 61 1 1 1 3 : CAMELLIA-192-CBC : camellia-192-cbc +1 2 392 200011 61 1 1 1 4 : CAMELLIA-256-CBC : camellia-256-cbc +1 2 392 200011 61 1 1 3 2 : id-camellia128-wrap +1 2 392 200011 61 1 1 3 3 : id-camellia192-wrap +1 2 392 200011 61 1 1 3 4 : id-camellia256-wrap + +# Definitions for Camellia cipher - ECB, CFB, OFB MODE + +!Alias ntt-ds 0 3 4401 5 +!Alias camellia ntt-ds 3 1 9 + +camellia 1 : CAMELLIA-128-ECB : camellia-128-ecb +!Cname camellia-128-ofb128 +camellia 3 : CAMELLIA-128-OFB : camellia-128-ofb +!Cname camellia-128-cfb128 +camellia 4 : CAMELLIA-128-CFB : camellia-128-cfb +camellia 6 : CAMELLIA-128-GCM : camellia-128-gcm +camellia 7 : CAMELLIA-128-CCM : camellia-128-ccm +camellia 9 : CAMELLIA-128-CTR : camellia-128-ctr +camellia 10 : CAMELLIA-128-CMAC : camellia-128-cmac + +camellia 21 : CAMELLIA-192-ECB : camellia-192-ecb +!Cname camellia-192-ofb128 +camellia 23 : CAMELLIA-192-OFB : camellia-192-ofb +!Cname camellia-192-cfb128 +camellia 24 : CAMELLIA-192-CFB : camellia-192-cfb +camellia 26 : CAMELLIA-192-GCM : camellia-192-gcm +camellia 27 : CAMELLIA-192-CCM : camellia-192-ccm +camellia 29 : CAMELLIA-192-CTR : camellia-192-ctr +camellia 30 : CAMELLIA-192-CMAC : camellia-192-cmac + +camellia 41 : CAMELLIA-256-ECB : camellia-256-ecb +!Cname camellia-256-ofb128 +camellia 43 : CAMELLIA-256-OFB : camellia-256-ofb +!Cname camellia-256-cfb128 +camellia 44 : CAMELLIA-256-CFB : camellia-256-cfb +camellia 46 : CAMELLIA-256-GCM : camellia-256-gcm +camellia 47 : CAMELLIA-256-CCM : camellia-256-ccm +camellia 49 : CAMELLIA-256-CTR : camellia-256-ctr +camellia 50 : CAMELLIA-256-CMAC : camellia-256-cmac + +# There are no OIDs for these modes... + + : CAMELLIA-128-CFB1 : camellia-128-cfb1 + : CAMELLIA-192-CFB1 : camellia-192-cfb1 + : CAMELLIA-256-CFB1 : camellia-256-cfb1 + : CAMELLIA-128-CFB8 : camellia-128-cfb8 + : CAMELLIA-192-CFB8 : camellia-192-cfb8 + : CAMELLIA-256-CFB8 : camellia-256-cfb8 + +# Definitions for ARIA cipher + +!Alias aria 1 2 410 200046 1 1 +aria 1 : ARIA-128-ECB : aria-128-ecb +aria 2 : ARIA-128-CBC : aria-128-cbc +!Cname aria-128-cfb128 +aria 3 : ARIA-128-CFB : aria-128-cfb +!Cname aria-128-ofb128 +aria 4 : ARIA-128-OFB : aria-128-ofb +aria 5 : ARIA-128-CTR : aria-128-ctr + +aria 6 : ARIA-192-ECB : aria-192-ecb +aria 7 : ARIA-192-CBC : aria-192-cbc +!Cname aria-192-cfb128 +aria 8 : ARIA-192-CFB : aria-192-cfb +!Cname aria-192-ofb128 +aria 9 : ARIA-192-OFB : aria-192-ofb +aria 10 : ARIA-192-CTR : aria-192-ctr + +aria 11 : ARIA-256-ECB : aria-256-ecb +aria 12 : ARIA-256-CBC : aria-256-cbc +!Cname aria-256-cfb128 +aria 13 : ARIA-256-CFB : aria-256-cfb +!Cname aria-256-ofb128 +aria 14 : ARIA-256-OFB : aria-256-ofb +aria 15 : ARIA-256-CTR : aria-256-ctr + +# There are no OIDs for these ARIA modes... + : ARIA-128-CFB1 : aria-128-cfb1 + : ARIA-192-CFB1 : aria-192-cfb1 + : ARIA-256-CFB1 : aria-256-cfb1 + : ARIA-128-CFB8 : aria-128-cfb8 + : ARIA-192-CFB8 : aria-192-cfb8 + : ARIA-256-CFB8 : aria-256-cfb8 + +aria 37 : ARIA-128-CCM : aria-128-ccm +aria 38 : ARIA-192-CCM : aria-192-ccm +aria 39 : ARIA-256-CCM : aria-256-ccm +aria 34 : ARIA-128-GCM : aria-128-gcm +aria 35 : ARIA-192-GCM : aria-192-gcm +aria 36 : ARIA-256-GCM : aria-256-gcm + +# Definitions for SEED cipher - ECB, CBC, OFB mode + +member-body 410 200004 : KISA : kisa +kisa 1 3 : SEED-ECB : seed-ecb +kisa 1 4 : SEED-CBC : seed-cbc +!Cname seed-cfb128 +kisa 1 5 : SEED-CFB : seed-cfb +!Cname seed-ofb128 +kisa 1 6 : SEED-OFB : seed-ofb + + +# Definitions for SM4 cipher + +sm-scheme 104 1 : SM4-ECB : sm4-ecb +sm-scheme 104 2 : SM4-CBC : sm4-cbc +!Cname sm4-ofb128 +sm-scheme 104 3 : SM4-OFB : sm4-ofb +!Cname sm4-cfb128 +sm-scheme 104 4 : SM4-CFB : sm4-cfb +sm-scheme 104 5 : SM4-CFB1 : sm4-cfb1 +sm-scheme 104 6 : SM4-CFB8 : sm4-cfb8 +sm-scheme 104 7 : SM4-CTR : sm4-ctr +sm-scheme 104 8 : SM4-GCM : sm4-gcm +sm-scheme 104 9 : SM4-CCM : sm4-ccm +sm-scheme 104 10 : SM4-XTS : sm4-xts + +# There is no OID that just denotes "HMAC" oddly enough... + + : HMAC : hmac +# Nor CMAC either + : CMAC : cmac + +# Synthetic composite ciphersuites + : RC4-HMAC-MD5 : rc4-hmac-md5 + : AES-128-CBC-HMAC-SHA1 : aes-128-cbc-hmac-sha1 + : AES-192-CBC-HMAC-SHA1 : aes-192-cbc-hmac-sha1 + : AES-256-CBC-HMAC-SHA1 : aes-256-cbc-hmac-sha1 + : AES-128-CBC-HMAC-SHA256 : aes-128-cbc-hmac-sha256 + : AES-192-CBC-HMAC-SHA256 : aes-192-cbc-hmac-sha256 + : AES-256-CBC-HMAC-SHA256 : aes-256-cbc-hmac-sha256 + : ChaCha20-Poly1305 : chacha20-poly1305 + : ChaCha20 : chacha20 + : AES-128-CBC-HMAC-SHA1-ETM : aes-128-cbc-hmac-sha1-etm + : AES-192-CBC-HMAC-SHA1-ETM : aes-192-cbc-hmac-sha1-etm + : AES-256-CBC-HMAC-SHA1-ETM : aes-256-cbc-hmac-sha1-etm + : AES-128-CBC-HMAC-SHA256-ETM : aes-128-cbc-hmac-sha256-etm + : AES-192-CBC-HMAC-SHA256-ETM : aes-192-cbc-hmac-sha256-etm + : AES-256-CBC-HMAC-SHA256-ETM : aes-256-cbc-hmac-sha256-etm + : AES-128-CBC-HMAC-SHA512-ETM : aes-128-cbc-hmac-sha512-etm + : AES-192-CBC-HMAC-SHA512-ETM : aes-192-cbc-hmac-sha512-etm + : AES-256-CBC-HMAC-SHA512-ETM : aes-256-cbc-hmac-sha512-etm + +ISO-US 10046 2 1 : dhpublicnumber : X9.42 DH + +# RFC 5639 curve OIDs (see http://www.ietf.org/rfc/rfc5639.txt) +# versionOne OBJECT IDENTIFIER ::= { +# iso(1) identified-organization(3) teletrust(36) algorithm(3) +# signature-algorithm(3) ecSign(2) ecStdCurvesAndGeneration(8) +# ellipticCurve(1) 1 } +1 3 36 3 3 2 8 1 1 1 : brainpoolP160r1 +1 3 36 3 3 2 8 1 1 2 : brainpoolP160t1 +1 3 36 3 3 2 8 1 1 3 : brainpoolP192r1 +1 3 36 3 3 2 8 1 1 4 : brainpoolP192t1 +1 3 36 3 3 2 8 1 1 5 : brainpoolP224r1 +1 3 36 3 3 2 8 1 1 6 : brainpoolP224t1 +1 3 36 3 3 2 8 1 1 7 : brainpoolP256r1 +# Alternate NID to represent the TLSv1.3 brainpoolP256r1 group + : brainpoolP256r1tls13 +1 3 36 3 3 2 8 1 1 8 : brainpoolP256t1 +1 3 36 3 3 2 8 1 1 9 : brainpoolP320r1 +1 3 36 3 3 2 8 1 1 10 : brainpoolP320t1 +1 3 36 3 3 2 8 1 1 11 : brainpoolP384r1 +# Alternate NID to represent the TLSv1.3 brainpoolP384r1 group + : brainpoolP384r1tls13 +1 3 36 3 3 2 8 1 1 12 : brainpoolP384t1 +1 3 36 3 3 2 8 1 1 13 : brainpoolP512r1 +# Alternate NID to represent the TLSv1.3 brainpoolP512r1 group + : brainpoolP512r1tls13 +1 3 36 3 3 2 8 1 1 14 : brainpoolP512t1 + +# ECDH schemes from RFC5753 +!Alias x9-63-scheme 1 3 133 16 840 63 0 +!Alias secg-scheme certicom-arc 1 + +x9-63-scheme 2 : dhSinglePass-stdDH-sha1kdf-scheme +secg-scheme 11 0 : dhSinglePass-stdDH-sha224kdf-scheme +secg-scheme 11 1 : dhSinglePass-stdDH-sha256kdf-scheme +secg-scheme 11 2 : dhSinglePass-stdDH-sha384kdf-scheme +secg-scheme 11 3 : dhSinglePass-stdDH-sha512kdf-scheme + +x9-63-scheme 3 : dhSinglePass-cofactorDH-sha1kdf-scheme +secg-scheme 14 0 : dhSinglePass-cofactorDH-sha224kdf-scheme +secg-scheme 14 1 : dhSinglePass-cofactorDH-sha256kdf-scheme +secg-scheme 14 2 : dhSinglePass-cofactorDH-sha384kdf-scheme +secg-scheme 14 3 : dhSinglePass-cofactorDH-sha512kdf-scheme +# NIDs for use with lookup tables. + : dh-std-kdf + : dh-cofactor-kdf + +# RFC 6962 Extension OIDs (see http://www.ietf.org/rfc/rfc6962.txt) +1 3 6 1 4 1 11129 2 4 2 : ct_precert_scts : CT Precertificate SCTs +1 3 6 1 4 1 11129 2 4 3 : ct_precert_poison : CT Precertificate Poison +1 3 6 1 4 1 11129 2 4 4 : ct_precert_signer : CT Precertificate Signer +1 3 6 1 4 1 11129 2 4 5 : ct_cert_scts : CT Certificate SCTs + +# CABForum EV SSL Certificate Guidelines +# (see https://cabforum.org/extended-validation/) +# OIDs for Subject Jurisdiction of Incorporation or Registration +ms-corp 60 2 1 1 : jurisdictionL : jurisdictionLocalityName +ms-corp 60 2 1 2 : jurisdictionST : jurisdictionStateOrProvinceName +ms-corp 60 2 1 3 : jurisdictionC : jurisdictionCountryName + +# SCRYPT algorithm +!Cname id-scrypt +1 3 6 1 4 1 11591 4 11 : id-scrypt : scrypt + +# NID for TLS1 PRF + : TLS1-PRF : tls1-prf + +# NID for HKDF + : HKDF : hkdf + +# NID for SSHKDF + : SSHKDF : sshkdf + +# NID for SSKDF + : SSKDF : sskdf +# NID for X942KDF + : X942KDF : x942kdf + +# NID for X963-2001 KDF + : X963KDF : x963kdf + +# RFC 4556 +1 3 6 1 5 2 3 : id-pkinit +id-pkinit 4 : pkInitClientAuth : PKINIT Client Auth +id-pkinit 5 : pkInitKDC : Signing KDC Response + +# From RFC8410 +1 3 101 110 : X25519 +1 3 101 111 : X448 +1 3 101 112 : ED25519 +1 3 101 113 : ED448 + + +# NIDs for cipher key exchange + : KxRSA : kx-rsa + : KxECDHE : kx-ecdhe + : KxDHE : kx-dhe + : KxECDHE-PSK : kx-ecdhe-psk + : KxDHE-PSK : kx-dhe-psk + : KxRSA_PSK : kx-rsa-psk + : KxPSK : kx-psk + : KxSRP : kx-srp + : KxGOST : kx-gost + : KxGOST18 : kx-gost18 + : KxANY : kx-any + +# NIDs for cipher authentication + : AuthRSA : auth-rsa + : AuthECDSA : auth-ecdsa + : AuthPSK : auth-psk + : AuthDSS : auth-dss + : AuthGOST01 : auth-gost01 + : AuthGOST12 : auth-gost12 + : AuthSRP : auth-srp + : AuthNULL : auth-null + : AuthANY : auth-any +# NID for Poly1305 + : Poly1305 : poly1305 +# NID for SipHash + : SipHash : siphash +# NIDs for RFC7919 DH parameters + : ffdhe2048 + : ffdhe3072 + : ffdhe4096 + : ffdhe6144 + : ffdhe8192 +# NIDs for RFC3526 DH parameters + : modp_1536 + : modp_2048 + : modp_3072 + : modp_4096 + : modp_6144 + : modp_8192 + +# OIDs for DSTU-4145/DSTU-7564 (http://zakon2.rada.gov.ua/laws/show/z0423-17) + +# DSTU OIDs +member-body 804 : ISO-UA +ISO-UA 2 1 1 1 : ua-pki +ua-pki 1 1 1 : dstu28147 : DSTU Gost 28147-2009 +dstu28147 2 : dstu28147-ofb : DSTU Gost 28147-2009 OFB mode +dstu28147 3 : dstu28147-cfb : DSTU Gost 28147-2009 CFB mode +dstu28147 5 : dstu28147-wrap : DSTU Gost 28147-2009 key wrap + +ua-pki 1 1 2 : hmacWithDstu34311 : HMAC DSTU Gost 34311-95 +ua-pki 1 2 1 : dstu34311 : DSTU Gost 34311-95 + +ua-pki 1 3 1 1 : dstu4145le : DSTU 4145-2002 little endian +dstu4145le 1 1 : dstu4145be : DSTU 4145-2002 big endian + +# 1.2.804. 2.1.1.1 1.3.1.1 .2.6 +# UA ua-pki 4145 le +# DSTU named curves +dstu4145le 2 0 : uacurve0 : DSTU curve 0 +dstu4145le 2 1 : uacurve1 : DSTU curve 1 +dstu4145le 2 2 : uacurve2 : DSTU curve 2 +dstu4145le 2 3 : uacurve3 : DSTU curve 3 +dstu4145le 2 4 : uacurve4 : DSTU curve 4 +dstu4145le 2 5 : uacurve5 : DSTU curve 5 +dstu4145le 2 6 : uacurve6 : DSTU curve 6 +dstu4145le 2 7 : uacurve7 : DSTU curve 7 +dstu4145le 2 8 : uacurve8 : DSTU curve 8 +dstu4145le 2 9 : uacurve9 : DSTU curve 9 +# NID for AES-SIV + : AES-128-SIV : aes-128-siv + : AES-192-SIV : aes-192-siv + : AES-256-SIV : aes-256-siv + + +!Cname oracle +joint-iso-itu-t 16 840 1 113894 : oracle-organization : Oracle organization +# Jdk trustedKeyUsage attribute +oracle 746875 1 1 : oracle-jdk-trustedkeyusage : Trusted key usage (Oracle) + +# NID for compression + : brotli : Brotli compression + : zstd : Zstandard compression + +2 23 133 : tcg : Trusted Computing Group + +tcg 1 : tcg-tcpaSpecVersion +tcg 2 : tcg-attribute : Trusted Computing Group Attributes +tcg 3 : tcg-protocol : Trusted Computing Group Protocols +tcg 4 : tcg-algorithm : Trusted Computing Group Algorithms +tcg 5 : tcg-platformClass : Trusted Computing Group Platform Classes +tcg 6 : tcg-ce : Trusted Computing Group Certificate Extensions +tcg 8 : tcg-kp : Trusted Computing Group Key Purposes +tcg 11 : tcg-ca : Trusted Computing Group Certificate Policies +tcg 17 : tcg-address : Trusted Computing Group Address Formats +tcg 18 : tcg-registry : Trusted Computing Group Registry +tcg 19 : tcg-traits : Trusted Computing Group Traits + +tcg-platformClass 1 : tcg-common : Trusted Computing Group Common +tcg-common 1 : tcg-at-platformManufacturerStr : TCG Platform Manufacturer String +tcg-common 2 : tcg-at-platformManufacturerId : TCG Platform Manufacturer ID +tcg-common 3 : tcg-at-platformConfigUri : TCG Platform Configuration URI +tcg-common 4 : tcg-at-platformModel : TCG Platform Model +tcg-common 5 : tcg-at-platformVersion : TCG Platform Version +tcg-common 6 : tcg-at-platformSerial : TCG Platform Serial Number +tcg-common 7 : tcg-at-platformConfiguration : TCG Platform Configuration +tcg-common 8 : tcg-at-platformIdentifier : TCG Platform Identifier + +tcg-attribute 1 : tcg-at-tpmManufacturer : TPM Manufacturer +tcg-attribute 2 : tcg-at-tpmModel : TPM Model +tcg-attribute 3 : tcg-at-tpmVersion : TPM Version +tcg-attribute 10 : tcg-at-securityQualities : Security Qualities +tcg-attribute 11 : tcg-at-tpmProtectionProfile : TPM Protection Profile +tcg-attribute 12 : tcg-at-tpmSecurityTarget : TPM Security Target +tcg-attribute 13 : tcg-at-tbbProtectionProfile : TBB Protection Profile +tcg-attribute 14 : tcg-at-tbbSecurityTarget : TBB Security Target +tcg-attribute 15 : tcg-at-tpmIdLabel : TPM ID Label +tcg-attribute 16 : tcg-at-tpmSpecification : TPM Specification +tcg-attribute 17 : tcg-at-tcgPlatformSpecification : TPM Platform Specification +tcg-attribute 18 : tcg-at-tpmSecurityAssertions : TPM Security Assertions +tcg-attribute 19 : tcg-at-tbbSecurityAssertions : TBB Security Assertions +tcg-attribute 23 : tcg-at-tcgCredentialSpecification : TCG Credential Specification +tcg-attribute 25 : tcg-at-tcgCredentialType : TCG Credential Type +tcg-attribute 26 : tcg-at-previousPlatformCertificates : TCG Previous Platform Certificates +tcg-attribute 27 : tcg-at-tbbSecurityAssertions-v3 : TCG TBB Security Assertions V3 +tcg-attribute 28 : tcg-at-cryptographicAnchors : TCG Cryptographic Anchors + +tcg-at-platformConfiguration 1 : tcg-at-platformConfiguration-v1 : Platform Configuration Version 1 +tcg-at-platformConfiguration 2 : tcg-at-platformConfiguration-v2 : Platform Configuration Version 2 +tcg-at-platformConfiguration 3 : tcg-at-platformConfiguration-v3 : Platform Configuration Version 3 +tcg-at-platformConfiguration 4 : tcg-at-platformConfigUri-v3 : Platform Configuration URI Version 3 + +tcg-algorithm 1 : tcg-algorithm-null : TCG NULL Algorithm + +tcg-kp 1 : tcg-kp-EKCertificate : Endorsement Key Certificate +tcg-kp 2 : tcg-kp-PlatformAttributeCertificate : Platform Attribute Certificate +tcg-kp 3 : tcg-kp-AIKCertificate : Attestation Identity Key Certificate +tcg-kp 4 : tcg-kp-PlatformKeyCertificate : Platform Key Certificate +tcg-kp 5 : tcg-kp-DeltaPlatformAttributeCertificate : Delta Platform Attribute Certificate +tcg-kp 6 : tcg-kp-DeltaPlatformKeyCertificate : Delta Platform Key Certificate +tcg-kp 7 : tcg-kp-AdditionalPlatformAttributeCertificate : Additional Platform Attribute Certificate +tcg-kp 8 : tcg-kp-AdditionalPlatformKeyCertificate : Additional Platform Key Certificate + +tcg-ce 2 : tcg-ce-relevantCredentials : Relevant Credentials +tcg-ce 3 : tcg-ce-relevantManifests : Relevant Manifests +tcg-ce 4 : tcg-ce-virtualPlatformAttestationService : Virtual Platform Attestation Service +tcg-ce 5 : tcg-ce-migrationControllerAttestationService : Migration Controller Attestation Service +tcg-ce 6 : tcg-ce-migrationControllerRegistrationService : Migration Controller Registration Service +tcg-ce 7 : tcg-ce-virtualPlatformBackupService : Virtual Platform Backup Service + +tcg-protocol 1 : tcg-prt-tpmIdProtocol : TCG TPM Protocol + +tcg-address 1 : tcg-address-ethernetmac : Ethernet MAC Address +tcg-address 2 : tcg-address-wlanmac : WLAN MAC Address +tcg-address 3 : tcg-address-bluetoothmac : Bluetooth MAC Address + +tcg-registry 3 : tcg-registry-componentClass : TCG Component Class + +tcg-registry-componentClass 1 : tcg-registry-componentClass-tcg : Trusted Computed Group Registry +tcg-registry-componentClass 2 : tcg-registry-componentClass-ietf : Internet Engineering Task Force Registry +tcg-registry-componentClass 3 : tcg-registry-componentClass-dmtf : Distributed Management Task Force Registry +tcg-registry-componentClass 4 : tcg-registry-componentClass-pcie : PCIE Component Class +tcg-registry-componentClass 5 : tcg-registry-componentClass-disk : Disk Component Class + +tcg-ca 4 : tcg-cap-verifiedPlatformCertificate : TCG Verified Platform Certificate CA Policy + +tcg-traits 1 : tcg-tr-ID : TCG Trait Identifiers +tcg-traits 2 : tcg-tr-category : TCG Trait Categories +tcg-traits 3 : tcg-tr-registry : TCG Trait Registries + +tcg-tr-ID 1 : tcg-tr-ID-Boolean : Boolean Trait +tcg-tr-ID 2 : tcg-tr-ID-CertificateIdentifier : Certificate Identifier Trait +tcg-tr-ID 3 : tcg-tr-ID-CommonCriteria : Common Criteria Trait +tcg-tr-ID 4 : tcg-tr-ID-componentClass : Component Class Trait +tcg-tr-ID 5 : tcg-tr-ID-componentIdentifierV11 : Component Identifier V1.1 Trait +tcg-tr-ID 6 : tcg-tr-ID-FIPSLevel : FIPS Level Trait +tcg-tr-ID 7 : tcg-tr-ID-ISO9000Level : ISO 9000 Level Trait +tcg-tr-ID 8 : tcg-tr-ID-networkMAC : Network MAC Trait +tcg-tr-ID 9 : tcg-tr-ID-OID : Object Identifier Trait +tcg-tr-ID 10 : tcg-tr-ID-PEN : Private Enterprise Number Trait +tcg-tr-ID 11 : tcg-tr-ID-platformFirmwareCapabilities : Platform Firmware Capabilities Trait +tcg-tr-ID 12 : tcg-tr-ID-platformFirmwareSignatureVerification : Platform Firmware Signature Verification Trait +tcg-tr-ID 13 : tcg-tr-ID-platformFirmwareUpdateCompliance : Platform Firmware Update Compliance Trait +tcg-tr-ID 14 : tcg-tr-ID-platformHardwareCapabilities : Platform Hardware Capabilities Trait +tcg-tr-ID 15 : tcg-tr-ID-RTM : Root of Trust for Measurement Trait +tcg-tr-ID 16 : tcg-tr-ID-status : Attribute Status Trait +tcg-tr-ID 17 : tcg-tr-ID-URI : Uniform Resource Identifier Trait +tcg-tr-ID 18 : tcg-tr-ID-UTF8String : UTF8String Trait +tcg-tr-ID 19 : tcg-tr-ID-IA5String : IA5String Trait +tcg-tr-ID 20 : tcg-tr-ID-PEMCertString : PEM-Encoded Certificate String Trait +tcg-tr-ID 21 : tcg-tr-ID-PublicKey : Public Key Trait + +tcg-tr-category 1 : tcg-tr-cat-platformManufacturer : Platform Manufacturer Trait Category +tcg-tr-category 2 : tcg-tr-cat-platformModel : Platform Model Trait Category +tcg-tr-category 3 : tcg-tr-cat-platformVersion : Platform Version Trait Category +tcg-tr-category 4 : tcg-tr-cat-platformSerial : Platform Serial Trait Category +tcg-tr-category 5 : tcg-tr-cat-platformManufacturerIdentifier : Platform Manufacturer Identifier Trait Category +tcg-tr-category 6 : tcg-tr-cat-platformOwnership : Platform Ownership Trait Category +tcg-tr-category 7 : tcg-tr-cat-componentClass : Component Class Trait Category +tcg-tr-category 8 : tcg-tr-cat-componentManufacturer : Component Manufacturer Trait Category +tcg-tr-category 9 : tcg-tr-cat-componentModel : Component Model Trait Category +tcg-tr-category 10 : tcg-tr-cat-componentSerial : Component Serial Trait Category +tcg-tr-category 11 : tcg-tr-cat-componentStatus : Component Status Trait Category +tcg-tr-category 12 : tcg-tr-cat-componentLocation : Component Location Trait Category +tcg-tr-category 13 : tcg-tr-cat-componentRevision : Component Revision Trait Category +tcg-tr-category 14 : tcg-tr-cat-componentFieldReplaceable : Component Field Replaceable Trait Category +tcg-tr-category 15 : tcg-tr-cat-EKCertificate : EK Certificate Trait Category +tcg-tr-category 16 : tcg-tr-cat-IAKCertificate : IAK Certificate Trait Category +tcg-tr-category 17 : tcg-tr-cat-IDevIDCertificate : IDevID Certificate Trait Category +tcg-tr-category 18 : tcg-tr-cat-DICECertificate : DICE Certificate Trait Category +tcg-tr-category 19 : tcg-tr-cat-SPDMCertificate : SPDM Certificate Trait Category +tcg-tr-category 20 : tcg-tr-cat-PEMCertificate : PEM Certificate Trait Category +tcg-tr-category 21 : tcg-tr-cat-PlatformCertificate : Platform Certificate Trait Category +tcg-tr-category 22 : tcg-tr-cat-DeltaPlatformCertificate : Delta Platform Certificate Trait Category +tcg-tr-category 23 : tcg-tr-cat-RebasePlatformCertificate : Rebase Platform Certificate Trait Category +tcg-tr-category 24 : tcg-tr-cat-genericCertificate : Generic Certificate Trait Category +tcg-tr-category 25 : tcg-tr-cat-CommonCriteria : Common Criteria Trait Category +tcg-tr-category 26 : tcg-tr-cat-componentIdentifierV11 : Component Identifier V1.1 Trait Category +tcg-tr-category 27 : tcg-tr-cat-FIPSLevel : FIPS Level Trait Category +tcg-tr-category 28 : tcg-tr-cat-ISO9000 : ISO 9000 Trait Category +tcg-tr-category 29 : tcg-tr-cat-networkMAC : Network MAC Trait Category +tcg-tr-category 30 : tcg-tr-cat-attestationProtocol : Attestation Protocol Trait Category +tcg-tr-category 31 : tcg-tr-cat-PEN : Private Enterprise Number Trait Category +tcg-tr-category 32 : tcg-tr-cat-platformFirmwareCapabilities : Platform Firmware Capabilities Trait Category +tcg-tr-category 33 : tcg-tr-cat-platformHardwareCapabilities : Platform Hardware Capabilities Trait Category +tcg-tr-category 34 : tcg-tr-cat-platformFirmwareSignatureVerification : Platform Firmware Signature Verification Trait Category +tcg-tr-category 35 : tcg-tr-cat-platformFirmwareUpdateCompliance : Platform Firmware Update Compliance Trait Category +tcg-tr-category 36 : tcg-tr-cat-RTM : Root of Trust of Measurement Trait Category +tcg-tr-category 37 : tcg-tr-cat-PublicKey : Public Key Trait Category + +!Alias nistKems nistAlgorithms 4 +nistKems 1 : id-alg-ml-kem-512 : ML-KEM-512 +nistKems 2 : id-alg-ml-kem-768 : ML-KEM-768 +nistKems 3 : id-alg-ml-kem-1024 : ML-KEM-1024 diff --git a/crates/stdlib/src/ssl.rs b/crates/stdlib/src/ssl.rs index c99ec024fa3..95cb6d99049 100644 --- a/crates/stdlib/src/ssl.rs +++ b/crates/stdlib/src/ssl.rs @@ -4959,7 +4959,11 @@ mod _ssl { vm.ctx.new_int(entry.nid), vm.ctx.new_str(entry.short_name), vm.ctx.new_str(entry.long_name), - vm.ctx.new_str(entry.oid_string()), + // OpenSSL names some objects without giving them an OID, and + // `nid2obj` reports the fourth field as None for those. + entry + .oid_string() + .map_or_else(|| vm.ctx.none(), |oid| vm.ctx.new_str(oid).into()), )) .into()) } @@ -4975,7 +4979,11 @@ mod _ssl { vm.ctx.new_int(entry.nid), vm.ctx.new_str(entry.short_name), vm.ctx.new_str(entry.long_name), - vm.ctx.new_str(entry.oid_string()), + // OpenSSL names some objects without giving them an OID, and + // `nid2obj` reports the fourth field as None for those. + entry + .oid_string() + .map_or_else(|| vm.ctx.none(), |oid| vm.ctx.new_str(oid).into()), )) .into()) } diff --git a/crates/stdlib/src/ssl/oid.rs b/crates/stdlib/src/ssl/oid.rs index ca059ff5000..91a17a8a76d 100644 --- a/crates/stdlib/src/ssl/oid.rs +++ b/crates/stdlib/src/ssl/oid.rs @@ -2,11 +2,17 @@ //! OID (Object Identifier) management for SSL/TLS //! -//! This module provides OID lookup functionality compatible with CPython's ssl module. -//! It uses oid-registry crate for well-known OIDs while maintaining NID (Numerical Identifier) -//! mappings for CPython compatibility. - -use oid_registry::asn1_rs::Oid; +//! `txt2obj` and `nid2obj` have to answer with OpenSSL's own numbers, so the +//! table behind them is read out of OpenSSL's own object database rather than +//! transcribed by hand: `obj_mac.num` carries every object's NID, and +//! `objects.txt` carries the numeric OID, short name and description for the +//! same objects. `objects.pl` is what OpenSSL generates its C tables from, +//! and the identifier it derives per object is what joins the two files here: +//! the `!Cname` override if one precedes the object, else its description, +//! else its short name -- each qualified by the enclosing `!module` and with +//! `-` spelled `_`. + +use alloc::rc::Rc; use std::collections::HashMap; /// OID entry with openssl-compatible metadata @@ -18,56 +24,16 @@ pub(super) struct OidEntry { pub short_name: &'static str, /// Long name/description (e.g., "commonName", "TLS Web Server Authentication") pub long_name: &'static str, - /// OID reference (static or dynamic) - pub oid: OidRef, -} - -/// OID reference - either from oid-registry or runtime-created -#[derive(Debug, Clone)] -pub(super) enum OidRef { - /// Static OID from oid-registry crate (stored as value) - Static(Oid<'static>), - /// OID string (for OIDs not in oid-registry) - parsed on demand - String(&'static str), + /// Dotted-decimal form, rendered once while the table is built. `None` + /// for the objects OpenSSL names but assigns no OID -- cipher and digest + /// algorithm names like `DES-EDE3` -- whose `nid2obj` reports it as such. + oid: Option>, } impl OidEntry { - /// Create entry from oid-registry static constant - pub(super) fn from_static( - nid: i32, - short_name: &'static str, - long_name: &'static str, - oid: &Oid<'static>, - ) -> Self { - Self { - nid, - short_name, - long_name, - oid: OidRef::Static(oid.clone()), - } - } - - /// Create entry from OID string (for OIDs not in oid-registry) - pub(super) const fn from_string( - nid: i32, - short_name: &'static str, - long_name: &'static str, - oid_str: &'static str, - ) -> Self { - Self { - nid, - short_name, - long_name, - oid: OidRef::String(oid_str), - } - } - - /// Get OID as string (e.g., "2.5.4.3") - pub(super) fn oid_string(&self) -> String { - match &self.oid { - OidRef::Static(oid) => oid.to_id_string(), - OidRef::String(s) => s.to_string(), - } + /// Get OID as string (e.g., "2.5.4.3"), if this object has one + pub(super) fn oid_string(&self) -> Option<&str> { + self.oid.as_deref() } } @@ -93,11 +59,17 @@ impl OidTable { let mut long_name_to_idx = HashMap::with_capacity(entries.len()); let mut oid_str_to_idx = HashMap::with_capacity(entries.len()); + // OpenSSL's own database repeats a name, and an OID, across objects; + // its lookups answer with the first such object, so keep the first. for (idx, entry) in entries.iter().enumerate() { - nid_to_idx.insert(entry.nid, idx); - short_name_to_idx.insert(entry.short_name, idx); - long_name_to_idx.insert(entry.long_name.to_lowercase(), idx); - oid_str_to_idx.insert(entry.oid_string(), idx); + nid_to_idx.entry(entry.nid).or_insert(idx); + short_name_to_idx.entry(entry.short_name).or_insert(idx); + long_name_to_idx + .entry(entry.long_name.to_lowercase()) + .or_insert(idx); + if let Some(oid) = entry.oid_string() { + oid_str_to_idx.entry(oid.to_owned()).or_insert(idx); + } } Self { @@ -135,241 +107,142 @@ impl OidTable { static OID_TABLE: rustpython_common::lock::LazyLock = rustpython_common::lock::LazyLock::new(OidTable::build); -/// Macro to define OID entry using oid-registry constant -macro_rules! oid_static { - ($nid:expr, $short:expr, $long:expr, $oid_const:path) => { - OidEntry::from_static($nid, $short, $long, &$oid_const) +/// OpenSSL's NID assignments: one `identifiernid` line per object. +static OBJ_MAC_NUM: &str = include_str!("../../rustls-data/obj_mac.num"); + +/// OpenSSL's object database: the numeric OID, short name and description of +/// each object, with `!Alias` / `!Cname` / `!module` / `!global` directives +/// between them. +static OBJECTS_TXT: &str = include_str!("../../rustls-data/objects.txt"); + +/// The name `objects.pl` derives for an object or alias: qualified by the +/// enclosing `!module`, with `-` spelled `_`. +fn qualify(name: &str, module: Option<&str>) -> Rc { + let name = match module { + Some(module) => format!("{module}_{name}"), + None => name.to_owned(), }; + name.replace('-', "_").into() } -/// Macro to define OID entry from string -macro_rules! oid_string { - ($nid:expr, $short:expr, $long:expr, $oid_str:expr) => { - OidEntry::from_string($nid, $short, $long, $oid_str) - }; +/// Expand an OID written as a mix of arc numbers and earlier names into the +/// numbers alone. Resolving against `aliases` as we go is what keeps the +/// expansion non-recursive: a name can only refer to something already read. +fn resolve_oid<'a>( + parts: impl Iterator, + aliases: &HashMap, Rc<[u64]>>, +) -> Rc<[u64]> { + let mut oid = Vec::with_capacity(16); + for part in parts { + match aliases.get(part.replace('-', "_").as_str()) { + Some(prefix) => oid.extend_from_slice(prefix), + None => oid.push(part.parse().expect("OID arc is not a number")), + } + } + oid.into() +} + +fn dotted(oid: &[u64]) -> Box { + oid.iter() + .map(u64::to_string) + .collect::>() + .join(".") + .into_boxed_str() } -/// Build the complete OID table +/// Build the complete OID table out of OpenSSL's object database fn build_oid_entries() -> Vec { - vec![ - // Priority 1: X.509 DN Attributes (OpenSSL NID values) - // These NIDs MUST match OpenSSL for CPython compatibility - oid_static!(13, "CN", "commonName", oid_registry::OID_X509_COMMON_NAME), - oid_static!(14, "C", "countryName", oid_registry::OID_X509_COUNTRY_NAME), - oid_static!( - 15, - "L", - "localityName", - oid_registry::OID_X509_LOCALITY_NAME - ), - oid_static!( - 16, - "ST", - "stateOrProvinceName", - oid_registry::OID_X509_STATE_OR_PROVINCE_NAME - ), - oid_static!( - 17, - "O", - "organizationName", - oid_registry::OID_X509_ORGANIZATION_NAME - ), - oid_static!( - 18, - "OU", - "organizationalUnitName", - oid_registry::OID_X509_ORGANIZATIONAL_UNIT - ), - oid_static!(41, "name", "name", oid_registry::OID_X509_NAME), - oid_static!(42, "GN", "givenName", oid_registry::OID_X509_GIVEN_NAME), - oid_static!(43, "initials", "initials", oid_registry::OID_X509_INITIALS), - oid_static!( - 4, - "serialNumber", - "serialNumber", - oid_registry::OID_X509_SERIALNUMBER - ), - oid_static!(100, "surname", "surname", oid_registry::OID_X509_SURNAME), - // emailAddress is special - it's in PKCS#9, not X.509 - oid_static!( - 48, - "emailAddress", - "emailAddress", - oid_registry::OID_PKCS9_EMAIL_ADDRESS - ), - // Priority 2: X.509 Extensions (Critical ones) - oid_static!( - 82, - "subjectKeyIdentifier", - "X509v3 Subject Key Identifier", - oid_registry::OID_X509_EXT_SUBJECT_KEY_IDENTIFIER - ), - oid_static!( - 83, - "keyUsage", - "X509v3 Key Usage", - oid_registry::OID_X509_EXT_KEY_USAGE - ), - oid_static!( - 85, - "subjectAltName", - "X509v3 Subject Alternative Name", - oid_registry::OID_X509_EXT_SUBJECT_ALT_NAME - ), - oid_static!( - 86, - "issuerAltName", - "X509v3 Issuer Alternative Name", - oid_registry::OID_X509_EXT_ISSUER_ALT_NAME - ), - oid_static!( - 87, - "basicConstraints", - "X509v3 Basic Constraints", - oid_registry::OID_X509_EXT_BASIC_CONSTRAINTS - ), - oid_static!( - 88, - "crlNumber", - "X509v3 CRL Number", - oid_registry::OID_X509_EXT_CRL_NUMBER - ), - oid_static!( - 90, - "authorityKeyIdentifier", - "X509v3 Authority Key Identifier", - oid_registry::OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER - ), - oid_static!( - 126, - "extendedKeyUsage", - "X509v3 Extended Key Usage", - oid_registry::OID_X509_EXT_EXTENDED_KEY_USAGE - ), - oid_static!( - 103, - "crlDistributionPoints", - "X509v3 CRL Distribution Points", - oid_registry::OID_X509_EXT_CRL_DISTRIBUTION_POINTS - ), - oid_static!( - 89, - "certificatePolicies", - "X509v3 Certificate Policies", - oid_registry::OID_X509_EXT_CERTIFICATE_POLICIES - ), - oid_static!( - 177, - "authorityInfoAccess", - "Authority Information Access", - oid_registry::OID_PKIX_AUTHORITY_INFO_ACCESS - ), - oid_static!( - 105, - "nameConstraints", - "X509v3 Name Constraints", - oid_registry::OID_X509_EXT_NAME_CONSTRAINTS - ), - // Priority 3: Extended Key Usage OIDs (not in oid-registry) - // These are defined in RFC 5280 but not in oid-registry, so we use strings - oid_string!( - 129, - "serverAuth", - "TLS Web Server Authentication", - "1.3.6.1.5.5.7.3.1" - ), - oid_string!( - 130, - "clientAuth", - "TLS Web Client Authentication", - "1.3.6.1.5.5.7.3.2" - ), - oid_string!(131, "codeSigning", "Code Signing", "1.3.6.1.5.5.7.3.3"), - oid_string!( - 132, - "emailProtection", - "E-mail Protection", - "1.3.6.1.5.5.7.3.4" - ), - oid_string!(133, "timeStamping", "Time Stamping", "1.3.6.1.5.5.7.3.8"), - oid_string!(180, "OCSPSigning", "OCSP Signing", "1.3.6.1.5.5.7.3.9"), - // Priority 4: Signature Algorithms - oid_static!( - 6, - "rsaEncryption", - "rsaEncryption", - oid_registry::OID_PKCS1_RSAENCRYPTION - ), - oid_static!( - 65, - "sha1WithRSAEncryption", - "sha1WithRSAEncryption", - oid_registry::OID_PKCS1_SHA1WITHRSA - ), - oid_static!( - 668, - "sha256WithRSAEncryption", - "sha256WithRSAEncryption", - oid_registry::OID_PKCS1_SHA256WITHRSA - ), - oid_static!( - 669, - "sha384WithRSAEncryption", - "sha384WithRSAEncryption", - oid_registry::OID_PKCS1_SHA384WITHRSA - ), - oid_static!( - 670, - "sha512WithRSAEncryption", - "sha512WithRSAEncryption", - oid_registry::OID_PKCS1_SHA512WITHRSA - ), - oid_static!( - 408, - "id-ecPublicKey", - "id-ecPublicKey", - oid_registry::OID_KEY_TYPE_EC_PUBLIC_KEY - ), - oid_static!( - 794, - "ecdsa-with-SHA256", - "ecdsa-with-SHA256", - oid_registry::OID_SIG_ECDSA_WITH_SHA256 - ), - oid_static!( - 795, - "ecdsa-with-SHA384", - "ecdsa-with-SHA384", - oid_registry::OID_SIG_ECDSA_WITH_SHA384 - ), - oid_static!( - 796, - "ecdsa-with-SHA512", - "ecdsa-with-SHA512", - oid_registry::OID_SIG_ECDSA_WITH_SHA512 - ), - // Priority 5: Hash Algorithms - oid_string!(64, "sha1", "sha1", "1.3.14.3.2.26"), - oid_static!(672, "sha256", "sha256", oid_registry::OID_NIST_HASH_SHA256), - oid_static!(673, "sha384", "sha384", oid_registry::OID_NIST_HASH_SHA384), - oid_static!(674, "sha512", "sha512", oid_registry::OID_NIST_HASH_SHA512), - oid_string!(675, "sha224", "sha224", "2.16.840.1.101.3.4.2.4"), - // Priority 6: Elliptic Curve OIDs - oid_static!(714, "secp256r1", "secp256r1", oid_registry::OID_EC_P256), - oid_string!(715, "secp384r1", "secp384r1", "1.3.132.0.34"), - oid_string!(716, "secp521r1", "secp521r1", "1.3.132.0.35"), - oid_string!(1172, "X25519", "X25519", "1.3.101.110"), - oid_string!(1173, "Ed25519", "Ed25519", "1.3.101.112"), - // Additional useful OIDs - oid_string!( - 183, - "subjectInfoAccess", - "Subject Information Access", - "1.3.6.1.5.5.7.1.11" - ), - oid_string!(920, "OCSP", "OCSP", "1.3.6.1.5.5.7.48.1"), - oid_string!(921, "caIssuers", "CA Issuers", "1.3.6.1.5.5.7.48.2"), - ] + let nids: HashMap<&str, i32> = OBJ_MAC_NUM + .lines() + .map(str::trim) + .filter(|line| !line.is_empty()) + .filter_map(|line| { + let mut field = line.split_whitespace(); + let name = field.next()?; + let nid = field.next()?.parse().ok()?; + Some((name, nid)) + }) + .collect(); + + let mut entries = Vec::with_capacity(nids.len()); + let mut aliases: HashMap, Rc<[u64]>> = HashMap::new(); + let mut cname: Option<&str> = None; + let mut module: Option<&str> = None; + + for line in OBJECTS_TXT + .lines() + .map(str::trim) + .filter(|line| !line.is_empty() && !line.starts_with('#')) + { + if let Some(directive) = line.strip_prefix('!') { + let mut field = directive.split_whitespace(); + match field.next() { + Some("Alias") => { + let alias = field.next().expect("!Alias without a name"); + let oid = resolve_oid(field, &aliases); + aliases.insert(qualify(alias, module), oid); + } + Some("Cname") => cname = Some(field.next().expect("!Cname without a name")), + Some("module") => module = Some(field.next().expect("!module without a name")), + Some("global") => module = None, + other => panic!("unknown objects.txt directive {other:?}"), + } + continue; + } + + let mut field = line.split(':').map(str::trim); + let oid = resolve_oid( + field + .next() + .expect("object without an OID") + .split_whitespace(), + &aliases, + ); + // An object written with only one name carries it as both: OpenSSL's + // `OBJ_nid2sn(NID_pkcs9_emailAddress)` answers "emailAddress" for a + // line whose short-name column is blank. + let (short_name, long_name) = match (field.next().unwrap_or(""), field.next().unwrap_or("")) + { + ("", "") => continue, + ("", name) | (name, "") => (name, name), + (short_name, long_name) => (short_name, long_name), + }; + + // Every name this object can be reached by, most specific first. They + // become aliases for later objects to build on, and the first of them + // that `obj_mac.num` knows carries this object's NID. + let mut identifiers: Vec> = Vec::with_capacity(3); + for name in [cname.take(), Some(long_name), Some(short_name)] + .into_iter() + .flatten() + .filter(|name| !name.is_empty()) + { + let name = qualify(name, module); + if !identifiers.contains(&name) { + aliases.entry(name.clone()).or_insert_with(|| oid.clone()); + identifiers.push(name); + } + } + + let Some(nid) = identifiers + .iter() + .find_map(|name| nids.get(&**name).copied()) + else { + continue; + }; + entries.push(OidEntry { + nid, + short_name, + long_name, + // A single arc does not encode: DER packs the first two into one + // byte, so OpenSSL gives the bare roots -- `iso`, `itu-t` -- a NID + // and no OID, exactly as it does for the algorithm names above. + oid: (oid.len() >= 2).then(|| dotted(&oid)), + }); + } + + assert!(cname.is_none(), "!Cname with no object after it"); + entries } // Public API Functions @@ -398,7 +271,7 @@ mod tests { let entry = find_by_nid(13).unwrap(); assert_eq!(entry.short_name, "CN"); assert_eq!(entry.long_name, "commonName"); - assert_eq!(entry.oid_string(), "2.5.4.3"); + assert_eq!(entry.oid_string(), Some("2.5.4.3")); } #[test] @@ -412,7 +285,7 @@ mod tests { fn find_by_name_short() { let entry = find_by_name("CN").unwrap(); assert_eq!(entry.nid, 13); - assert_eq!(entry.oid_string(), "2.5.4.3"); + assert_eq!(entry.oid_string(), Some("2.5.4.3")); } #[test] @@ -432,14 +305,14 @@ mod tests { fn subject_alt_name() { let entry = find_by_nid(85).unwrap(); assert_eq!(entry.short_name, "subjectAltName"); - assert_eq!(entry.oid_string(), "2.5.29.17"); + assert_eq!(entry.oid_string(), Some("2.5.29.17")); } #[test] fn server_auth_eku() { let entry = find_by_nid(129).unwrap(); assert_eq!(entry.short_name, "serverAuth"); - assert_eq!(entry.oid_string(), "1.3.6.1.5.5.7.3.1"); + assert_eq!(entry.oid_string(), Some("1.3.6.1.5.5.7.3.1")); } #[test] @@ -455,11 +328,60 @@ mod tests { #[test] fn oid_count() { let table = &*OID_TABLE; - // We should have 50+ OIDs defined + // The table is OpenSSL's whole object database, not a curated subset. assert!( - table.entries.len() >= 50, - "Expected at least 50 OIDs, got {}", + table.entries.len() >= 1000, + "Expected at least 1000 OIDs, got {}", table.entries.len() ); } + + #[test] + fn nids_agree_with_openssl() { + // Spot-check objects whose NIDs Python code and test suites depend on. + // Every row is what `_ssl.nid2obj(nid)` answers on CPython built + // against OpenSSL, covering both name shapes: a distinct short and + // long name, and a single name standing for both. + for (nid, short_name, long_name, oid) in [ + (13, "CN", "commonName", Some("2.5.4.3")), + ( + 48, + "emailAddress", + "emailAddress", + Some("1.2.840.113549.1.9.1"), + ), + ( + 85, + "subjectAltName", + "X509v3 Subject Alternative Name", + Some("2.5.29.17"), + ), + (105, "serialNumber", "serialNumber", Some("2.5.4.5")), + ( + 129, + "serverAuth", + "TLS Web Server Authentication", + Some("1.3.6.1.5.5.7.3.1"), + ), + (660, "street", "streetAddress", Some("2.5.4.9")), + // Two arcs is still an object, and OpenSSL names some objects + // with no OID at all. + (11, "X500", "directory services (X.500)", Some("2.5")), + (181, "ISO", "iso", None), + (33, "DES-EDE3", "des-ede3", None), + (114, "MD5-SHA1", "md5-sha1", None), + (405, "ansi-X9-62", "ANSI X9.62", Some("1.2.840.10045")), + ( + 983, + "md_gost12_512", + "GOST R 34.11-2012 with 512 bit hash", + Some("1.2.643.7.1.1.2.3"), + ), + ] { + let entry = find_by_nid(nid).unwrap_or_else(|| panic!("no entry for NID {nid}")); + assert_eq!(entry.short_name, short_name, "NID {nid}"); + assert_eq!(entry.long_name, long_name, "NID {nid}"); + assert_eq!(entry.oid_string(), oid, "NID {nid}"); + } + } } From 42295a0d295cad1d4aa04cbf54209cb48579c91b Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Fri, 4 Sep 2026 11:30:00 +0900 Subject: [PATCH 02/10] ssl: parse OpenSSL cipher strings in set_ciphers Replaces the pattern matcher `set_ciphers` used with the grammar `man openssl-ciphers` documents, in a new `ssl/cipher.rs` taken from #8007: `!`, `-`, `+`, `@STRENGTH`, `@SECLEVEL=n`, `+`-joined conjunctions, the DEFAULT/ALL/COMPLEMENTOF* groups, protocol versions, SUITEB*, and the aXXX/kXXX/eXXX prefixes. `set_ciphers` raises "No cipher can be selected." for a string that names nothing the provider offers, which is the one failure SSL_CTX_set_cipher_list reports, and keeps the TLS 1.3 suites selected in provider order because that setter does not reach them. A SUITEB* string pins its own key exchange groups, which `prepare_kx_groups` now reads. Against CPython's OpenSSL over 78 cipher strings, the selections agree except under `@SECLEVEL=n`, which OpenSSL applies at handshake time and this applies to the selection. `CryptoExt` gains `default_cipher_suites` so that `DEFAULT` and `ALL` are distinguishable. Co-authored-by: Ivan Mironov Assisted-by: Claude --- .cspell.json | 5 + crates/stdlib/src/ssl.rs | 155 ++--- crates/stdlib/src/ssl/cipher.rs | 873 +++++++++++++++++++++++++++++ crates/stdlib/src/ssl/providers.rs | 15 +- examples/custom_tls_providers.rs | 2 + src/interpreter.rs | 1 + 6 files changed, 934 insertions(+), 117 deletions(-) create mode 100644 crates/stdlib/src/ssl/cipher.rs diff --git a/.cspell.json b/.cspell.json index 4ac238be18b..bc56e1cd44c 100644 --- a/.cspell.json +++ b/.cspell.json @@ -71,8 +71,11 @@ // words - list of words to be always considered correct // (compound words like pyarg, baseclass, microbenchmark are handled by allowCompoundWords) "words": [ + "AESGCM", "aiterable", "alnum", + "COMPLEMENTOFALL", + "COMPLEMENTOFDEFAULT", "csock", "coro", "contig", @@ -82,6 +85,7 @@ "deduped", "deoptimized", "deoptimize", + "EECDH", "emscripten", "excs", "fdigits", @@ -109,6 +113,7 @@ "reraises", "reraising", "significand", + "SUITEB", "summands", "TESTFN", "TZPATH", diff --git a/crates/stdlib/src/ssl.rs b/crates/stdlib/src/ssl.rs index 95cb6d99049..a17fa89b863 100644 --- a/crates/stdlib/src/ssl.rs +++ b/crates/stdlib/src/ssl.rs @@ -19,6 +19,9 @@ mod oid; // Certificate operations module (parsing, validation, conversion) mod cert; +/// OpenSSL cipher string parsing for `set_ciphers` +mod cipher; + // OpenSSL compatibility layer (abstracts rustls operations) mod compat; @@ -94,6 +97,7 @@ mod _ssl { use super::cert; // Import OID module + use super::cipher; use super::oid; // Import compat module (OpenSSL compatibility layer) @@ -659,114 +663,6 @@ mod _ssl { Ok(alpn_list) } - /// Parse OpenSSL cipher string to rustls SupportedCipherSuite list - /// - /// Supports patterns like: - /// - "AES128" → filters for AES_128 - /// - "AES256" → filters for AES_256 - /// - "AES128:AES256" → both - /// - "ECDHE+AESGCM" → ECDHE AND AESGCM (both conditions must match) - /// - "ALL" or "DEFAULT" → all available - /// - "!MD5" → exclusion (ignored, rustls doesn't support weak ciphers anyway) - fn parse_cipher_string(cipher_str: &str) -> Result, String> { - if cipher_str.is_empty() { - return Err("No cipher can be selected".to_string()); - } - - let all_suites = CryptoExt::get_ext().all_ciphers_or_default(); - let mut selected = Vec::new(); - - for part in cipher_str.split(':') { - let part = part.trim(); - - // Skip exclusions (rustls doesn't support these) - if part.starts_with('!') { - continue; - } - - // Skip priority markers starting with + - if part.starts_with('+') { - continue; - } - - // Match pattern - match part { - "ALL" | "DEFAULT" | "HIGH" => { - // Add all available cipher suites - selected.extend_from_slice(all_suites); - } - _ => { - // Check if this is a compound pattern with + (AND condition) - // e.g., "ECDHE+AESGCM" means ECDHE AND AESGCM - let patterns: Vec<&str> = part.split('+').collect(); - - let mut found_any = false; - for suite in all_suites { - let name = format!("{:?}", suite.suite()); - - // Check if all patterns match (AND condition) - let matches = patterns.iter().all(|&pattern| { - // Handle common OpenSSL pattern variations - if pattern.contains("AES128") { - name.contains("AES_128") - } else if pattern.contains("AES256") { - name.contains("AES_256") - } else if pattern == "AESGCM" { - // AESGCM: AES with GCM mode - name.contains("AES") && name.contains("GCM") - } else if pattern == "AESCCM" { - // AESCCM: AES with CCM mode - name.contains("AES") && name.contains("CCM") - } else if pattern == "CHACHA20" { - name.contains("CHACHA20") - } else if pattern == "ECDHE" { - name.contains("ECDHE") - } else if pattern == "DHE" { - // DHE but not ECDHE - name.contains("DHE") && !name.contains("ECDHE") - } else if pattern == "ECDH" { - // ECDH but not ECDHE - name.contains("ECDH") && !name.contains("ECDHE") - } else if pattern == "DH" { - // DH but not DHE or ECDH - name.contains("DH") - && !name.contains("DHE") - && !name.contains("ECDH") - } else if pattern == "RSA" { - name.contains("RSA") - } else if pattern == "AES" { - name.contains("AES") - } else if pattern == "ECDSA" { - name.contains("ECDSA") - } else { - // Direct substring match for other patterns - name.contains(pattern) - } - }); - - if matches { - selected.push(*suite); - found_any = true; - } - } - - if !found_any { - // No matching cipher suite found - warn but continue - } - } - } - } - - // Remove duplicates - selected.dedup_by_key(|s| s.suite()); - - if selected.is_empty() { - Err("No cipher can be selected".to_string()) - } else { - Ok(selected) - } - } - // SSLContext - manages TLS configuration #[pyattr] #[pyclass(name = "_SSLContext", module = "ssl", traverse)] @@ -851,6 +747,9 @@ mod _ssl { /// Selected cipher suites (None = use all rustls defaults) #[pytraverse(skip)] selected_ciphers: PyRwLock>>, + /// Key exchange groups a SUITEB* cipher string pinned (RFC 6460) + #[pytraverse(skip)] + suite_b_kx_groups: PyRwLock>>, } #[derive(FromArgs)] @@ -1564,16 +1463,36 @@ mod _ssl { #[pymethod] fn set_ciphers(&self, ciphers: PyUtf8StrRef, vm: &VirtualMachine) -> PyResult<()> { - let cipher_str = ciphers.as_str(); + // `SSL_CTX_set_cipher_list` reports one failure for a string it + // cannot read and for a readable one that selects nothing, and the + // TLS 1.3 suites are not among what it can select -- they have + // their own setter -- so a string naming only those selects + // nothing either. + let (mut selected_ciphers, suite_b_kx_groups) = + cipher::CipherList::parse_to_rustls(ciphers.as_str()) + .ok() + .filter(|(suites, _)| suites.iter().any(|s| s.tls13().is_none())) + .ok_or_else(|| { + vm.new_os_subtype_error( + PySSLError::class(&vm.ctx).to_owned(), + None, + "No cipher can be selected.".to_owned(), + ) + .upcast() + })?; - // Parse cipher string and store selected ciphers - let selected_ciphers = parse_cipher_string(cipher_str).map_err(|e| { - vm.new_os_subtype_error(PySSLError::class(&vm.ctx).to_owned(), None, e) - .upcast() - })?; + // Those suites stay selected whatever the string said about them, + // in front of it and in the order the provider offers them. + let tls13: Vec<_> = CryptoExt::get_ext() + .default_ciphers_or_provider() + .iter() + .filter(|suite| suite.tls13().is_some() && !selected_ciphers.contains(suite)) + .copied() + .collect(); + let _ = selected_ciphers.splice(..0, tls13); - // Store in context *self.selected_ciphers.write() = Some(selected_ciphers); + *self.suite_b_kx_groups.write() = suite_b_kx_groups; Ok(()) } @@ -2382,6 +2301,7 @@ mod _ssl { accept_count: AtomicUsize::new(0), session_hits: AtomicUsize::new(0), selected_ciphers: PyRwLock::new(None), + suite_b_kx_groups: PyRwLock::new(None), }) } } @@ -3270,6 +3190,7 @@ mod _ssl { ) -> PyResult>> { let ctx = self.context.read(); let ecdh_curve = ctx.ecdh_curve.read().clone(); + let suite_b_kx_groups = ctx.suite_b_kx_groups.read().clone(); drop(ctx); if let Some(ref curve_name) = ecdh_curve { @@ -3278,7 +3199,9 @@ mod _ssl { Err(e) => Err(vm.new_value_error(format!("Failed to set ECDH curve: {e}"))), } } else { - Ok(None) + // A SUITEB* cipher string pins its own groups, and nothing + // else asked for a curve. + Ok(suite_b_kx_groups) } } diff --git a/crates/stdlib/src/ssl/cipher.rs b/crates/stdlib/src/ssl/cipher.rs new file mode 100644 index 00000000000..59e5f619b34 --- /dev/null +++ b/crates/stdlib/src/ssl/cipher.rs @@ -0,0 +1,873 @@ +//! OpenSSL cipher strings, as `man openssl-ciphers` defines them. +//! +//! `SSLContext.set_ciphers()` takes the same string OpenSSL does, so the whole +//! grammar has to be honoured and not just the parts that look like cipher +//! names: `!` deletes a cipher and bars it from coming back, `-` deletes one +//! that a later term may restore, `+` moves matching ciphers to the end, +//! `@STRENGTH` sorts by key length, and `@SECLEVEL=n` drops everything below +//! the level's key size. A term is itself a `+`-joined conjunction, so +//! `AES128+aECDSA` selects the intersection. +//! +//! What a term can name is likewise OpenSSL's: the `DEFAULT` / `ALL` / +//! `COMPLEMENTOFALL` groups, a protocol version, `aXXX` / `kXXX` / `eXXX` for +//! authentication, key exchange and cipher part, a bare part, or a full name +//! in either OpenSSL or IANA spelling. + +use core::str::FromStr; +use rustls::{CipherSuite, SupportedCipherSuite, crypto::SupportedKxGroup}; +use rustpython_common::lock::LazyLock; + +use super::providers::CryptoExt; + +// See `man SSL_CTX_set_security_level` for details. +const SECURITY_LEVEL_TO_MIN_BITS: &[u16] = &[0, 80, 112, 128, 192, 256]; + +pub(super) struct CipherList<'a> { + ops: Vec>, +} + +enum CipherFilterOp<'a> { + /// The cipher string @STRENGTH can be used at any point to sort the current cipher list in order of encryption + /// algorithm key length. + Strength, + + /// The cipher string @SECLEVEL=n can be used at any point to set the security level to n. + SecLevel(usize), + + /// Just add matching ciphers to the end of the current list. + Append(CipherFilterSubOpList<'a>), + + /// If ! is used then the ciphers are permanently deleted from the list. The ciphers deleted can never reappear + /// in the list even if they are explicitly stated. + DelAndBlock(CipherFilterSubOpList<'a>), + + /// If - is used then the ciphers are deleted from the list, but some or all of the ciphers can be added again + /// by later options. + Del(CipherFilterSubOpList<'a>), + + /// If + is used then the ciphers are moved to the end of the list. This option doesn't add any new ciphers it + /// just moves matching existing ones. + MoveToEnd(CipherFilterSubOpList<'a>), +} + +struct CipherFilterSubOpList<'a> { + sub_ops: Vec>, +} + +enum CipherFilterSubOp<'a> { + /// Default cipher list. Valid only as a first operation. + Default, + + /// The ciphers included in ALL, but not enabled by default. + ComplementOfDefault, + + /// All cipher suites except the eNULL ciphers. + All, + + /// The cipher suites not enabled by ALL, currently eNULL. + ComplementOfAll, + + /// The list of enabled cipher suites will be loaded from the system crypto policy configuration file. + ProfileSystem, + + /// "High" encryption cipher suites. + High, + + /// "Medium" encryption cipher suites. + Medium, + + /// "Low" encryption cipher suites. + Low, + + /// Lists cipher suites which are only supported in at least TLS v1.0. + TlsV10, + + /// Lists cipher suites which are only supported in at least TLS v1.2. + TlsV12, + + /// Lists cipher suites which are only supported in at least SSL v3. + SslV3, + + /// Enables suite B mode of operation. + SuiteB(SuiteBType), + + /// All cipher suites using encryption algorithm in Cipher Block Chaining (CBC) mode. + Cbc, + + /// AES in Galois Counter Mode (GCM): these cipher suites are only supported in TLS v1.2. + AesGcm, + + /// Match by message authentication algorithm. + Auth(&'a str), + + /// Match by key exchange algorithm. + KeyEx(&'a str), + + /// Match by part of an OpenSSL name that usually contains key exchange algorithm and symmetric cipher + /// and may contain other identifiers. + Part(&'a str), + + /// Match by full OpenSSL or IANA cipher name. + Full(&'a str), +} + +enum SuiteBType { + Use128Permit192, + Use128Only, + Use192Only, +} + +impl<'a> CipherList<'a> { + pub(super) fn parse_to_rustls( + s: &'a str, + ) -> Result>, &'static str> { + Self::parse(s)?.to_rustls() + } + + fn parse(s: &'a str) -> Result { + let ops: Vec<_> = s + .split(|c: char| c == ':' || c == ',' || c.is_ascii_whitespace()) + .filter(|s| !s.is_empty()) + .enumerate() + .map(|(i, s)| { + let suite_b = match s { + "SUITEB128" => Some(CipherFilterSubOp::SuiteB(SuiteBType::Use128Permit192)), + "SUITEB128ONLY" => Some(CipherFilterSubOp::SuiteB(SuiteBType::Use128Only)), + "SUITEB192" => Some(CipherFilterSubOp::SuiteB(SuiteBType::Use192Only)), + _ => None, + }; + + match (i, s, suite_b) { + (0, "DEFAULT", _) => Ok(CipherFilterOp::Append( + CipherFilterSubOpList::from_sub_op(CipherFilterSubOp::Default), + )), + + (0, _, Some(suite_b)) => Ok(CipherFilterOp::Append( + CipherFilterSubOpList::from_sub_op(suite_b), + )), + + (_, _, _) => CipherFilterOp::parse(s), + } + }) + .collect::>()?; + if ops.is_empty() { + Err("list of ciphers is empty") + } else { + Ok(Self { ops }) + } + } + + fn to_rustls(&self) -> Result>, &'static str> { + let mut min_bits = SECURITY_LEVEL_TO_MIN_BITS[0]; + let mut block_list = Vec::new(); + let mut ids = Vec::new(); + + let sanitize = |ids: &mut Vec, min_bits, block_list: &[u16]| { + ids.retain(|id| CIPHER_MAPPINGS.entry(*id).bits >= min_bits); + ids.retain(|id| !block_list.contains(id)); + }; + let extend = |ids: &mut Vec, source: &[u16]| { + // Extend and deduplicate. + for id in source { + if !ids.contains(id) { + ids.push(*id); + } + } + }; + let ids_to_suits = |ids: &[u16]| { + ids.iter() + .map(|id| *CIPHER_MAPPINGS.entry(*id).suite) + .collect() + }; + + for op in &self.ops { + match op { + CipherFilterOp::Strength => { + ids.sort_by_key(|id| -i32::from(CIPHER_MAPPINGS.entry(*id).bits)) + } + + CipherFilterOp::SecLevel(level) => { + min_bits = *SECURITY_LEVEL_TO_MIN_BITS + .get(*level) + .ok_or("@SECLEVEL value too big")?; + sanitize(&mut ids, min_bits, &block_list); + } + + CipherFilterOp::Append(sub_op_list) => { + let (mut new_ids, suite_b) = sub_op_list.to_rustls_ids()?; + if suite_b.is_some() { + // SUITEB* cipherstrings should appear first in the cipher list and anything + // after them is ignored. + return Ok((ids_to_suits(&new_ids), suite_b)); + } + sanitize(&mut new_ids, min_bits, &block_list); + extend(&mut ids, &new_ids); + } + + CipherFilterOp::DelAndBlock(sub_op_list) => { + extend(&mut block_list, &sub_op_list.to_rustls_ids()?.0); + sanitize(&mut ids, min_bits, &block_list); + } + + CipherFilterOp::Del(sub_op_list) => { + let (del_ids, _) = sub_op_list.to_rustls_ids()?; + ids.retain(|id| !del_ids.contains(id)); + } + + CipherFilterOp::MoveToEnd(sub_op_list) => { + let (move_ids, _) = sub_op_list.to_rustls_ids()?; + ids.sort_by_key(|id| move_ids.contains(id)) + } + } + } + + Ok((ids_to_suits(&ids), None)) + } +} + +impl<'a> CipherFilterOp<'a> { + fn parse(mut s: &'a str) -> Result { + if s == "@STRENGTH" { + return Ok(Self::Strength); + } + const SECLEVEL: &str = "@SECLEVEL="; + if s.starts_with(SECLEVEL) { + return Ok(Self::SecLevel( + usize::from_str(s.get(SECLEVEL.len()..).unwrap_or("")) + .map_err(|_| "invalid @SECLEVEL value")?, + )); + } + + let prefix = s.get(..1).unwrap_or(""); + if ["!", "-", "+"].contains(&prefix) { + s = s.get(1..).unwrap_or(""); + } + Ok(match prefix { + "!" => Self::DelAndBlock(CipherFilterSubOpList::parse(s)?), + "-" => Self::Del(CipherFilterSubOpList::parse(s)?), + "+" => Self::MoveToEnd(CipherFilterSubOpList::parse(s)?), + _ => Self::Append(CipherFilterSubOpList::parse(s)?), + }) + } +} + +impl<'a> CipherFilterSubOpList<'a> { + fn parse(s: &'a str) -> Result { + let sub_ops: Vec<_> = s + .split('+') + .filter(|s| !s.is_empty()) + .map(CipherFilterSubOp::parse) + .collect::>()?; + if sub_ops.is_empty() { + Err("list of cipher filtering operations is empty") + } else { + Ok(Self { sub_ops }) + } + } + + fn from_sub_op(sub_op: CipherFilterSubOp<'a>) -> Self { + Self { + sub_ops: vec![sub_op], + } + } + + fn to_rustls_ids(&self) -> Result>, &'static str> { + let mut ids = Vec::new(); + for sub_op in &self.sub_ops { + match sub_op { + CipherFilterSubOp::Default => { + Self::extend_or_intersect(&mut ids, &CIPHER_MAPPINGS.default) + } + + CipherFilterSubOp::ComplementOfDefault => { + Self::extend_or_intersect(&mut ids, &CIPHER_MAPPINGS.complement_of_default) + } + + CipherFilterSubOp::All => Self::extend_or_intersect(&mut ids, &CIPHER_MAPPINGS.all), + + CipherFilterSubOp::ComplementOfAll => { + Self::extend_or_intersect(&mut ids, &CIPHER_MAPPINGS.complement_of_all) + } + + CipherFilterSubOp::ProfileSystem => { + return Err( + "reading cipher suites from system crypto policy file is not supported with rustls", + ); + } + + // Every suite in the table encrypts with at least 128 bits, + // which is what "high" asks for, and so nothing is left for + // the two weaker grades to name. + CipherFilterSubOp::High => { + Self::extend_or_intersect(&mut ids, &CIPHER_MAPPINGS.all) + } + + // Nor is there a suite older than TLS 1.2 to name. + CipherFilterSubOp::Medium + | CipherFilterSubOp::Low + | CipherFilterSubOp::TlsV10 + | CipherFilterSubOp::SslV3 => Self::extend_or_intersect(&mut ids, &[]), + + CipherFilterSubOp::TlsV12 => { + Self::extend_or_intersect(&mut ids, &CIPHER_MAPPINGS.tls_1_2) + } + + // RFC 6460 + CipherFilterSubOp::SuiteB(SuiteBType::Use128Permit192) => { + return Ok(( + vec![ + CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.into(), + CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384.into(), + ], + Some(vec![ + kx_group_by_name(rustls::NamedGroup::secp256r1, "secp256r1")?, + kx_group_by_name(rustls::NamedGroup::secp384r1, "secp384r1")?, + ]), + )); + } + CipherFilterSubOp::SuiteB(SuiteBType::Use128Only) => { + return Ok(( + vec![CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.into()], + Some(vec![kx_group_by_name( + rustls::NamedGroup::secp256r1, + "secp256r1", + )?]), + )); + } + CipherFilterSubOp::SuiteB(SuiteBType::Use192Only) => { + return Ok(( + vec![CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384.into()], + Some(vec![kx_group_by_name( + rustls::NamedGroup::secp384r1, + "secp384r1", + )?]), + )); + } + + CipherFilterSubOp::Cbc => { + // OpenSSL names might contain either -CBC- or -CBC3-, IANA seems to only contain _CBC_. + let rhs = CIPHER_MAPPINGS + .select(|entry| entry.iana.split('_').any(|part| part == "CBC")); + + Self::extend_or_intersect(&mut ids, &rhs) + } + + CipherFilterSubOp::AesGcm => { + let rhs = CIPHER_MAPPINGS.select(|entry| { + let parts = || entry.openssl.split(['-', '_']); + parts().any(|part| part.starts_with("AES")) + && parts().any(|part| part == "GCM") + }); + + Self::extend_or_intersect(&mut ids, &rhs) + } + + CipherFilterSubOp::Auth(auth) => { + let rhs = CIPHER_MAPPINGS.select(|entry| match entry.suite { + SupportedCipherSuite::Tls12(c) => c.sign.iter().any(|scheme| { + scheme + .as_str() + .is_some_and(|s| s.split('_').any(|s| s == *auth)) + }), + + // usable_for_signature_algorithm() always returns true for TLS 1.3. + SupportedCipherSuite::Tls13(_) => true, + }); + + Self::extend_or_intersect(&mut ids, &rhs) + } + + CipherFilterSubOp::KeyEx(key_ex) => { + let rhs = CIPHER_MAPPINGS.select(|entry| entry.key_ex == *key_ex); + Self::extend_or_intersect(&mut ids, &rhs) + } + + CipherFilterSubOp::Part(part) => { + let rhs = CIPHER_MAPPINGS.select(|entry| name_has_part(entry.openssl, part)); + Self::extend_or_intersect(&mut ids, &rhs) + } + + CipherFilterSubOp::Full(full) => { + if let Some(id) = CIPHER_MAPPINGS.by_name(full) { + Self::extend_or_intersect(&mut ids, &[id]) + } + } + } + } + Ok((ids, None)) + } + + fn extend_or_intersect(lhs: &mut Vec, rhs: &[u16]) { + if lhs.is_empty() { + lhs.extend_from_slice(rhs) + } else { + lhs.retain(|id| rhs.contains(id)) + } + } +} + +fn kx_group_by_name( + name: rustls::NamedGroup, + error_name: &'static str, +) -> Result<&'static dyn SupportedKxGroup, &'static str> { + CryptoExt::get_ext() + .all_kx_or_default() + .iter() + .find(|g| g.name() == name) + .copied() + .ok_or(error_name) +} + +type WithOptionSuiteB = (T, Option>); + +impl<'a> CipherFilterSubOp<'a> { + fn parse(mut s: &'a str) -> Result { + Ok(match s { + "DEFAULT" => return Err("DEFAULT specified at wrong position in the cipher string"), + "SUITEB128" => { + return Err("SUITEB128 specified at wrong position in the cipher string"); + } + "SUITEB128ONLY" => { + return Err("SUITEB128ONLY specified at wrong position in the cipher string"); + } + "SUITEB192" => { + return Err("SUITEB192 specified at wrong position in the cipher string"); + } + + "COMPLEMENTOFDEFAULT" => Self::ComplementOfDefault, + "ALL" => Self::All, + "COMPLEMENTOFALL" => Self::ComplementOfAll, + "PROFILE=SYSTEM" => Self::ProfileSystem, + "HIGH" => Self::High, + "MEDIUM" => Self::Medium, + "LOW" => Self::Low, + "TLSv1.0" => Self::TlsV10, + "TLSv1.2" => Self::TlsV12, + "SSLv3" => Self::SslV3, + "CBC" => Self::Cbc, + "AESGCM" => Self::AesGcm, + + // RSA is an alias for kRSA. + "RSA" => Self::KeyEx("RSA"), + + // Every suite in the table agrees an ephemeral ECDH key, which + // ECDH selects along with the fixed and anonymous forms it also + // covers, and which ECDHE and EECDH select on their own. + "ECDH" | "ECDHE" | "EECDH" => Self::KeyEx(EPHEMERAL_ECDH), + + _ => { + let prefix = s.get(..1).unwrap_or(""); + if ["a", "k", "e"].contains(&prefix) { + s = s.get(1..).unwrap_or(""); + } + + if s.is_empty() { + return Err("item of cipher string is empty"); + } + if !s + .chars() + .all(|c| char::is_ascii_alphanumeric(&c) || matches!(c, '-' | '_')) + { + return Err("item of cipher string contains invalid characters"); + } + + match prefix { + "a" => Self::Auth(s), + "k" => Self::KeyEx(key_ex_alias(s)), + "e" => Self::Part(s), + + _ => { + if s.contains(['_', '-']) { + Self::Full(s) + } else { + Self::Part(s) + } + } + } + } + }) + } +} + +/// How the table spells the key agreement every suite in it uses. +const EPHEMERAL_ECDH: &str = "ECDH"; + +/// `kECDHE` and `kEECDH` name that same agreement. +fn key_ex_alias(key_ex: &str) -> &str { + match key_ex { + "ECDHE" | "EECDH" => EPHEMERAL_ECDH, + _ => key_ex, + } +} + +/// Whether an OpenSSL name is one a cipher-string part selects. A part +/// usually names one dash-separated piece of it, but `AES` stands for either +/// key length, and the digest names stand for a MAC that no suite in the +/// table has -- the SHA in an AEAD suite's name is its handshake hash. +fn name_has_part(openssl: &str, part: &str) -> bool { + let mut parts = openssl.split(['-', '_']); + match part { + "AES" => parts.any(|p| p.starts_with("AES")), + "SHA" | "SHA1" | "SHA256" | "SHA384" => false, + _ => parts.any(|p| p == part), + } +} + +static CIPHER_MAPPINGS: LazyLock = LazyLock::new(CipherMappings::new); + +/// What the table knows about one suite the provider offers. +struct CipherEntry { + id: u16, + openssl: &'static str, + iana: &'static str, + key_ex: &'static str, + bits: u16, + suite: &'static SupportedCipherSuite, +} + +struct CipherMappings { + /// Every suite the provider offers, in the order it offers them, which is + /// the preference order a selection out of it keeps. + entries: Vec, + complement_of_default: Vec, + complement_of_all: Vec, + default: Vec, + all: Vec, + tls_1_2: Vec, +} + +impl CipherMappings { + fn entry(&self, id: u16) -> &CipherEntry { + self.entries + .iter() + .find(|entry| entry.id == id) + .expect("BUG: cipher id is not one of the table's") + } + + fn select(&self, matches: impl Fn(&CipherEntry) -> bool) -> Vec { + self.entries + .iter() + .filter(|entry| matches(entry)) + .map(|entry| entry.id) + .collect() + } + + fn by_name(&self, name: &str) -> Option { + self.entries + .iter() + .find(|entry| entry.openssl == name || entry.iana == name) + .map(|entry| entry.id) + } + + fn new() -> Self { + let all_cipher_suites = CryptoExt::get_ext().all_ciphers_or_default(); + let default_cipher_suites = CryptoExt::get_ext().default_ciphers_or_provider(); + + let mut entries = Vec::with_capacity(all_cipher_suites.len()); + let mut all = Vec::with_capacity(all_cipher_suites.len()); + let mut tls_1_2 = Vec::with_capacity(all_cipher_suites.len()); + + for cipher in all_cipher_suites { + // See https://www.ssl.org/cipher-suite-mapping + let (openssl, iana, key_ex, bits, min_tls_ver) = match cipher.suite() { + CipherSuite::TLS13_AES_256_GCM_SHA384 => ( + "TLS_AES_256_GCM_SHA384", + "TLS_AES_256_GCM_SHA384", + "ECDH", + 256, + 13, + ), + + CipherSuite::TLS13_AES_128_GCM_SHA256 => ( + "TLS_AES_128_GCM_SHA256", + "TLS_AES_128_GCM_SHA256", + "ECDH", + 128, + 13, + ), + + CipherSuite::TLS13_CHACHA20_POLY1305_SHA256 => ( + "TLS_CHACHA20_POLY1305_SHA256", + "TLS_CHACHA20_POLY1305_SHA256", + "ECDH", + 256, + 13, + ), + + CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 => ( + "ECDHE-ECDSA-AES256-GCM-SHA384", + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", + "ECDH", + 256, + 12, + ), + + CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 => ( + "ECDHE-ECDSA-AES128-GCM-SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "ECDH", + 128, + 12, + ), + + CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 => ( + "ECDHE-ECDSA-CHACHA20-POLY1305", + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", + "ECDH", + 256, + 12, + ), + + CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 => ( + "ECDHE-RSA-AES256-GCM-SHA384", + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", + "ECDH", + 256, + 12, + ), + + CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 => ( + "ECDHE-RSA-AES128-GCM-SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "ECDH", + 128, + 12, + ), + + CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 => ( + "ECDHE-RSA-CHACHA20-POLY1305", + "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", + "ECDH", + 256, + 12, + ), + + // This is tested by that_all_rustls_ciphers_are_known(). + // This may happen after rustls update, just add more ciphers above is this case. + _ => unreachable!("BUG: Unknown cipher suite {cipher:?}"), + }; + + let id = cipher.suite().into(); + + if bits > 0 { + all.push(id); + } + if min_tls_ver >= 12 { + tls_1_2.push(id); + } + entries.push(CipherEntry { + id, + openssl, + iana, + key_ex, + bits, + suite: cipher, + }); + } + + let default: Vec<_> = default_cipher_suites + .iter() + .map(|c| u16::from(c.suite())) + .collect(); + + Self { + complement_of_default: all_cipher_suites + .iter() + .filter(|c| !default.contains(&c.suite().into())) + .map(|c| u16::from(c.suite())) + .collect(), + complement_of_all: all_cipher_suites + .iter() + .filter(|c| !all.contains(&c.suite().into())) + .map(|c| u16::from(c.suite())) + .collect(), + + entries, + default, + all, + tls_1_2, + } + } +} + +#[cfg(test)] +mod tests { + use core::hint::black_box; + use std::sync::Once; + + use rustls::crypto::aws_lc_rs; + + use super::*; + + fn install_test_crypto_provider() { + static ONCE: Once = Once::new(); + ONCE.call_once(|| { + let ext = CryptoExt { + all_cipher_suites: Some(aws_lc_rs::ALL_CIPHER_SUITES), + default_cipher_suites: Some(aws_lc_rs::DEFAULT_CIPHER_SUITES), + all_kx_groups: Some(aws_lc_rs::ALL_KX_GROUPS), + any_supported_key: Some(aws_lc_rs::sign::any_supported_type), + ticketer: aws_lc_rs::Ticketer::new, + }; + let _ = CryptoExt::set_provider(aws_lc_rs::default_provider(), ext); + }) + } + + fn cipher_names(s: &str) -> Vec<&'static str> { + install_test_crypto_provider(); + + let (suites, suite_b) = CipherList::parse_to_rustls(s).unwrap(); + assert!(suite_b.is_none()); + suites + .iter() + .map(|suite| CIPHER_MAPPINGS.entry(suite.suite().into()).openssl) + .collect() + } + + /// The metadata table has to name every suite the provider offers, and it + /// panics on one it does not, so building it is the assertion. + #[test] + fn every_rustls_cipher_is_known() { + install_test_crypto_provider(); + let _ = black_box(&*CIPHER_MAPPINGS); + } + + #[test] + fn default_and_names() { + install_test_crypto_provider(); + + let default = CryptoExt::get_ext() + .default_ciphers_or_provider() + .iter() + .map(|suite| suite.suite()) + .collect::>(); + let (suites, suite_b) = CipherList::parse_to_rustls("DEFAULT").unwrap(); + + assert!(suite_b.is_none()); + assert_eq!( + suites.iter().map(|suite| suite.suite()).collect::>(), + default + ); + // Either spelling names the same suite, and a term is a conjunction. + assert_eq!( + cipher_names("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, ECDHE-ECDSA-AES128-GCM-SHA256"), + [ + "ECDHE-RSA-AES128-GCM-SHA256", + "ECDHE-ECDSA-AES128-GCM-SHA256", + ] + ); + assert_eq!( + cipher_names("AES128+aECDSA"), + ["ECDHE-ECDSA-AES128-GCM-SHA256"] + ); + } + + #[test] + fn keyword_families() { + install_test_crypto_provider(); + + // `AES` names either key length, while `ECDH` names the ephemeral + // agreement every suite here uses, as `kECDHE` does. + assert_eq!( + cipher_names("AES"), + [ + "TLS_AES_256_GCM_SHA384", + "TLS_AES_128_GCM_SHA256", + "ECDHE-ECDSA-AES256-GCM-SHA384", + "ECDHE-ECDSA-AES128-GCM-SHA256", + "ECDHE-RSA-AES256-GCM-SHA384", + "ECDHE-RSA-AES128-GCM-SHA256", + ] + ); + assert_eq!(cipher_names("ECDH"), cipher_names("ALL")); + assert_eq!(cipher_names("kECDHE"), cipher_names("ALL")); + + // A selection keeps the order the provider offers, whatever order the + // maps it was collected out of iterate in. + assert_eq!( + cipher_names("aRSA"), + [ + "TLS_AES_256_GCM_SHA384", + "TLS_AES_128_GCM_SHA256", + "TLS_CHACHA20_POLY1305_SHA256", + "ECDHE-RSA-AES256-GCM-SHA384", + "ECDHE-RSA-AES128-GCM-SHA256", + "ECDHE-RSA-CHACHA20-POLY1305", + ] + ); + + // Nothing here is of a weaker grade, older than TLS 1.2, or carries a + // MAC of its own. + for nothing in ["MEDIUM", "LOW", "TLSv1.0", "SSLv3", "SHA256", "CBC"] { + assert_eq!(cipher_names(nothing), Vec::<&str>::new(), "{nothing}"); + } + } + + #[test] + fn deletes_and_moves() { + install_test_crypto_provider(); + + // `+` moves an existing cipher to the end rather than adding one. + assert_eq!( + cipher_names( + "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:+ECDHE-ECDSA-AES128-GCM-SHA256" + ), + [ + "ECDHE-RSA-AES128-GCM-SHA256", + "ECDHE-ECDSA-AES128-GCM-SHA256", + ] + ); + // `-` lets a later term restore the cipher; `!` does not. + assert_eq!( + cipher_names( + "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:-ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:!ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256" + ), + ["ECDHE-ECDSA-AES128-GCM-SHA256"] + ); + } + + #[test] + fn strength_and_security_level() { + install_test_crypto_provider(); + + assert_eq!( + cipher_names("ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:@STRENGTH"), + ["ECDHE-RSA-AES256-GCM-SHA384", "ECDHE-RSA-AES128-GCM-SHA256"] + ); + // The level applies to what is already selected and to what follows. + assert_eq!( + cipher_names("ECDHE-RSA-AES128-GCM-SHA256:@SECLEVEL=4:ECDHE-RSA-AES256-GCM-SHA384"), + ["ECDHE-RSA-AES256-GCM-SHA384"] + ); + } + + #[test] + fn suite_b() { + install_test_crypto_provider(); + + let (suites, suite_b) = CipherList::parse_to_rustls("SUITEB128:ALL").unwrap(); + + // Anything after a SUITEB term is ignored, and the term carries the + // key exchange groups RFC 6460 pins. + assert_eq!( + suites.iter().map(|suite| suite.suite()).collect::>(), + [ + CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + ] + ); + assert!(suite_b.is_some()); + assert!(CipherList::parse_to_rustls("ALL:SUITEB128").is_err()); + } + + #[test] + fn rejects_what_openssl_rejects() { + install_test_crypto_provider(); + + assert!(CipherList::parse_to_rustls("ALL:DEFAULT").is_err()); + assert!(CipherList::parse_to_rustls("ALL:@SECLEVEL=6").is_err()); + assert!(CipherList::parse_to_rustls("PROFILE=SYSTEM").is_err()); + assert!(CipherList::parse_to_rustls(";").is_err()); + assert!(CipherList::parse_to_rustls("").is_err()); + } +} diff --git a/crates/stdlib/src/ssl/providers.rs b/crates/stdlib/src/ssl/providers.rs index 478d02ff933..7c4be87be92 100644 --- a/crates/stdlib/src/ssl/providers.rs +++ b/crates/stdlib/src/ssl/providers.rs @@ -26,6 +26,9 @@ static CRYPTO_EXT: OnceLock = OnceLock::new(); #[derive(Clone, Copy)] pub struct CryptoExt { pub all_cipher_suites: Option<&'static [SupportedCipherSuite]>, + /// The suites `DEFAULT` selects, which an OpenSSL cipher string + /// distinguishes from the `ALL` that `all_cipher_suites` holds. + pub default_cipher_suites: Option<&'static [SupportedCipherSuite]>, pub all_kx_groups: Option<&'static [&'static dyn SupportedKxGroup]>, #[allow(clippy::type_complexity)] pub any_supported_key: Option) -> Result, Error>>, @@ -53,7 +56,17 @@ impl CryptoExt { /// Panics if a [`CryptoProvider`] hasn't been set. #[must_use] pub fn all_ciphers_or_default(&self) -> &'static [SupportedCipherSuite] { - self.all_cipher_suites.unwrap_or_else(|| { + self.all_cipher_suites + .unwrap_or_else(|| self.default_ciphers_or_provider()) + } + + /// Returns the default [`SupportedCipherSuite`]s, or the provider's own. + /// + /// # Panics + /// Panics if a [`CryptoProvider`] hasn't been set. + #[must_use] + pub fn default_ciphers_or_provider(&self) -> &'static [SupportedCipherSuite] { + self.default_cipher_suites.unwrap_or_else(|| { CryptoProvider::get_default() .expect("A CryptoProvider has been set if CryptoExt is set") .cipher_suites diff --git a/examples/custom_tls_providers.rs b/examples/custom_tls_providers.rs index 1f382fc1b84..355f75342cc 100644 --- a/examples/custom_tls_providers.rs +++ b/examples/custom_tls_providers.rs @@ -30,6 +30,7 @@ fn main() { "ring" => { let ext = CryptoExt { all_cipher_suites: Some(ring::ALL_CIPHER_SUITES), + default_cipher_suites: Some(ring::DEFAULT_CIPHER_SUITES), all_kx_groups: Some(ring::ALL_KX_GROUPS), any_supported_key: Some(ring::sign::any_supported_type), ticketer: ring::Ticketer::new, @@ -40,6 +41,7 @@ fn main() { "graviola" => { let ext = CryptoExt { all_cipher_suites: Some(rustls_graviola::suites::ALL_CIPHER_SUITES), + default_cipher_suites: None, all_kx_groups: Some(rustls_graviola::kx::ALL_KX_GROUPS), any_supported_key: None, ticketer: rustls_graviola::Ticketer::new, diff --git a/src/interpreter.rs b/src/interpreter.rs index 89e24c25b08..b8f94848686 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -35,6 +35,7 @@ fn install_default_tls_provider(_vm: &mut crate::VirtualMachine) { let ext = CryptoExt { all_cipher_suites: Some(aws_lc_rs::ALL_CIPHER_SUITES), + default_cipher_suites: Some(aws_lc_rs::DEFAULT_CIPHER_SUITES), all_kx_groups: Some(aws_lc_rs::ALL_KX_GROUPS), any_supported_key: Some(aws_lc_rs::sign::any_supported_type), ticketer: aws_lc_rs::Ticketer::new, From 9a0aaf735cd38c394f274d5620cccc0c42fc5035 Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Fri, 4 Sep 2026 17:23:16 +0900 Subject: [PATCH 03/10] ssl: finish cipher reporting and provider handling Use the provider-ordered cipher metadata table as the single source for parsing, reporting, OpenSSL names and descriptions. This makes get_ciphers reflect the context selection and validates curves and Suite B against the active provider. Keep set_ciphers from changing TLS 1.3 suites, preserve the provider's order, fix empty conjunctions, and keep FIPS initialization within the provider's filtered cipher and key-exchange defaults. Co-authored-by: Ivan Mironov Assisted-by: Claude Assisted-by: CodeRabbit Assisted-by: OpenAI Codex: GPT-5 --- .cspell.json | 1 + crates/stdlib/src/ssl.rs | 131 +++++--------- crates/stdlib/src/ssl/cipher.rs | 298 +++++++++++++++++++++++++------- crates/stdlib/src/ssl/compat.rs | 142 +-------------- src/interpreter.rs | 12 +- 5 files changed, 287 insertions(+), 297 deletions(-) diff --git a/.cspell.json b/.cspell.json index bc56e1cd44c..433fbc7f9fb 100644 --- a/.cspell.json +++ b/.cspell.json @@ -102,6 +102,7 @@ "kwonly", "lossily", "mcache", + "MLKEM", "oparg", "opargs", "pointee", diff --git a/crates/stdlib/src/ssl.rs b/crates/stdlib/src/ssl.rs index a17fa89b863..269f86b6bc2 100644 --- a/crates/stdlib/src/ssl.rs +++ b/crates/stdlib/src/ssl.rs @@ -103,8 +103,8 @@ mod _ssl { // Import compat module (OpenSSL compatibility layer) use super::compat::{ ClientConfigOptions, MultiCertResolver, ProtocolSettings, ServerConfigOptions, SslError, - create_client_config, create_server_config, curve_name_to_kx_group, extract_cipher_info, - get_cipher_encryption_desc, is_blocking_io_error, normalize_cipher_name, ssl_do_handshake, + create_client_config, create_server_config, curve_name_to_kx_group, is_blocking_io_error, + ssl_do_handshake, }; use super::providers::CryptoExt; @@ -336,10 +336,10 @@ mod _ssl { #[pyattr] const _OPENSSL_API_VERSION: (i32, i32, i32, i32, i32) = (3, 3, 0, 0, 15); - // Default cipher list for rustls - using modern secure ciphers - #[pyattr] - const _DEFAULT_CIPHERS: &str = - "TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256"; + #[pyattr(once)] + fn _DEFAULT_CIPHERS(_vm: &VirtualMachine) -> String { + cipher::default_cipher_string() + } // Has features #[pyattr] @@ -1481,15 +1481,13 @@ mod _ssl { .upcast() })?; - // Those suites stay selected whatever the string said about them, - // in front of it and in the order the provider offers them. - let tls13: Vec<_> = CryptoExt::get_ext() - .default_ciphers_or_provider() - .iter() - .filter(|suite| suite.tls13().is_some() && !selected_ciphers.contains(suite)) - .copied() - .collect(); - let _ = selected_ciphers.splice(..0, tls13); + // TLS 1.3 has a separate OpenSSL setter. Discard whatever this + // cipher string happened to match there, then restore exactly the + // provider defaults in their preference order. + selected_ciphers = cipher::restore_default_tls13( + selected_ciphers, + CryptoExt::get_ext().default_ciphers_or_provider(), + ); *self.selected_ciphers.write() = Some(selected_ciphers); *self.suite_b_kx_groups.write() = suite_b_kx_groups; @@ -1499,60 +1497,28 @@ mod _ssl { #[pymethod] fn get_ciphers(&self, vm: &VirtualMachine) -> PyListRef { - // Dynamically generate cipher list from rustls ALL_CIPHER_SUITES - // This automatically includes all cipher suites supported by the current rustls version + // What the last `set_ciphers` selected, or the provider defaults + // when no cipher string was given. + let selected = self.selected_ciphers.read().clone(); + let suites = selected + .unwrap_or_else(|| CryptoExt::get_ext().default_ciphers_or_provider().to_vec()); - let cipher_list = CryptoExt::get_ext() - .all_ciphers_or_default() + let cipher_list = suites .iter() .map(|suite| { - // Extract cipher information using unified helper - let cipher_info = extract_cipher_info(suite); - - // Convert to OpenSSL-style name - // e.g., "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" -> "ECDHE-RSA-AES128-GCM-SHA256" - let openssl_name = normalize_cipher_name(&cipher_info.name); - - // Determine key exchange and auth methods - let (kx, auth) = if cipher_info.protocol == "TLSv1.3" { - // TLS 1.3 doesn't distinguish - all use modern algos - ("any", "any") - } else if cipher_info.name.contains("ECDHE") { - // TLS 1.2 with ECDHE - let auth = if cipher_info.name.contains("ECDSA") { - "ECDSA" - } else if cipher_info.name.contains("RSA") { - "RSA" - } else { - "any" - }; - ("ECDH", auth) - } else { - ("any", "any") - }; - - // Build description string - // Format: "{name} {protocol} Kx={kx} Au={auth} Enc={enc} Mac={mac}" - let enc = get_cipher_encryption_desc(&openssl_name); - - let description = format!( - "{} {} Kx={} Au={} Enc={} Mac=AEAD", - openssl_name, cipher_info.protocol, kx, auth, enc - ); - - // Create cipher dict + let cipher = cipher::describe(suite); let dict = vm.ctx.new_dict(); - dict.set_item("name", vm.ctx.new_str(openssl_name).into(), vm) - .unwrap(); - dict.set_item("protocol", vm.ctx.new_str(cipher_info.protocol).into(), vm) - .unwrap(); - dict.set_item("id", vm.ctx.new_int(0).into(), vm).unwrap(); // Placeholder ID - dict.set_item("strength_bits", vm.ctx.new_int(cipher_info.bits).into(), vm) - .unwrap(); - dict.set_item("alg_bits", vm.ctx.new_int(cipher_info.bits).into(), vm) - .unwrap(); - dict.set_item("description", vm.ctx.new_str(description).into(), vm) - .unwrap(); + let items: [(&str, PyObjectRef); 6] = [ + ("id", vm.ctx.new_int(cipher.id).into()), + ("name", vm.ctx.new_str(cipher.name).into()), + ("protocol", vm.ctx.new_str(cipher.protocol).into()), + ("strength_bits", vm.ctx.new_int(cipher.bits).into()), + ("alg_bits", vm.ctx.new_int(cipher.bits).into()), + ("description", vm.ctx.new_str(cipher.description).into()), + ]; + for (key, value) in items { + dict.set_item(key, value, vm).unwrap(); + } dict.into() }) .collect::>(); @@ -1788,23 +1754,7 @@ mod _ssl { return Err(vm.new_type_error("ECDH curve name must be str or bytes")); }; - // Validate curve name (common curves for compatibility) - // rustls supports: X25519, secp256r1 (prime256v1), secp384r1 - let valid_curves = [ - "prime256v1", - "secp256r1", - "prime384v1", - "secp384r1", - "prime521v1", - "secp521r1", - "X25519", - "x25519", - "x448", // For future compatibility - ]; - - if !valid_curves.contains(&curve_name.as_str()) { - return Err(vm.new_value_error(format!("unknown curve name '{curve_name}'"))); - } + curve_name_to_kx_group(&curve_name).map_err(|error| vm.new_value_error(error))?; // Store the curve name to be used during handshake // This will limit the key exchange groups offered/accepted @@ -3934,14 +3884,14 @@ mod _ssl { }; // Extract cipher information outside the lock - let cipher_info = extract_cipher_info(&suite); + let cipher = cipher::describe(&suite); // Note: returns a 3-tuple (name, protocol_version, bits) // The 'description' field is part of get_ciphers() output, not cipher() Some(( - cipher_info.name, - cipher_info.protocol.to_string(), - cipher_info.bits, + cipher.name.to_owned(), + cipher.protocol.to_owned(), + cipher.bits.into(), )) } @@ -4523,14 +4473,13 @@ mod _ssl { let suite = conn.negotiated_cipher_suite()?; - // Extract cipher information using unified helper - let cipher_info = extract_cipher_info(&suite); + let cipher = cipher::describe(&suite); // Return as list with single tuple (name, version, bits) let tuple = vm.ctx.new_tuple(vec![ - vm.ctx.new_str(cipher_info.name).into(), - vm.ctx.new_str(cipher_info.protocol).into(), - vm.ctx.new_int(cipher_info.bits).into(), + vm.ctx.new_str(cipher.name).into(), + vm.ctx.new_str(cipher.protocol).into(), + vm.ctx.new_int(cipher.bits).into(), ]); Some(vm.ctx.new_list(vec![tuple.into()])) } diff --git a/crates/stdlib/src/ssl/cipher.rs b/crates/stdlib/src/ssl/cipher.rs index 59e5f619b34..0186230c5ef 100644 --- a/crates/stdlib/src/ssl/cipher.rs +++ b/crates/stdlib/src/ssl/cipher.rs @@ -117,6 +117,36 @@ enum SuiteBType { Use192Only, } +impl SuiteBType { + fn parameters( + &self, + ) -> ( + &'static [CipherSuite], + &'static [(rustls::NamedGroup, &'static str)], + ) { + match self { + Self::Use128Permit192 => ( + &[ + CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + ], + &[ + (rustls::NamedGroup::secp256r1, "secp256r1"), + (rustls::NamedGroup::secp384r1, "secp384r1"), + ], + ), + Self::Use128Only => ( + &[CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256], + &[(rustls::NamedGroup::secp256r1, "secp256r1")], + ), + Self::Use192Only => ( + &[CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384], + &[(rustls::NamedGroup::secp384r1, "secp384r1")], + ), + } + } +} + impl<'a> CipherList<'a> { pub(super) fn parse_to_rustls( s: &'a str, @@ -273,22 +303,29 @@ impl<'a> CipherFilterSubOpList<'a> { fn to_rustls_ids(&self) -> Result>, &'static str> { let mut ids = Vec::new(); + let mut first = true; for sub_op in &self.sub_ops { match sub_op { CipherFilterSubOp::Default => { - Self::extend_or_intersect(&mut ids, &CIPHER_MAPPINGS.default) - } - - CipherFilterSubOp::ComplementOfDefault => { - Self::extend_or_intersect(&mut ids, &CIPHER_MAPPINGS.complement_of_default) + Self::extend_or_intersect(&mut first, &mut ids, &CIPHER_MAPPINGS.default) } - CipherFilterSubOp::All => Self::extend_or_intersect(&mut ids, &CIPHER_MAPPINGS.all), + CipherFilterSubOp::ComplementOfDefault => Self::extend_or_intersect( + &mut first, + &mut ids, + &CIPHER_MAPPINGS.complement_of_default, + ), - CipherFilterSubOp::ComplementOfAll => { - Self::extend_or_intersect(&mut ids, &CIPHER_MAPPINGS.complement_of_all) + CipherFilterSubOp::All => { + Self::extend_or_intersect(&mut first, &mut ids, &CIPHER_MAPPINGS.all) } + CipherFilterSubOp::ComplementOfAll => Self::extend_or_intersect( + &mut first, + &mut ids, + &CIPHER_MAPPINGS.complement_of_all, + ), + CipherFilterSubOp::ProfileSystem => { return Err( "reading cipher suites from system crypto policy file is not supported with rustls", @@ -299,49 +336,29 @@ impl<'a> CipherFilterSubOpList<'a> { // which is what "high" asks for, and so nothing is left for // the two weaker grades to name. CipherFilterSubOp::High => { - Self::extend_or_intersect(&mut ids, &CIPHER_MAPPINGS.all) + Self::extend_or_intersect(&mut first, &mut ids, &CIPHER_MAPPINGS.all) } // Nor is there a suite older than TLS 1.2 to name. CipherFilterSubOp::Medium | CipherFilterSubOp::Low | CipherFilterSubOp::TlsV10 - | CipherFilterSubOp::SslV3 => Self::extend_or_intersect(&mut ids, &[]), + | CipherFilterSubOp::SslV3 => Self::extend_or_intersect(&mut first, &mut ids, &[]), CipherFilterSubOp::TlsV12 => { - Self::extend_or_intersect(&mut ids, &CIPHER_MAPPINGS.tls_1_2) + Self::extend_or_intersect(&mut first, &mut ids, &CIPHER_MAPPINGS.tls_1_2) } // RFC 6460 - CipherFilterSubOp::SuiteB(SuiteBType::Use128Permit192) => { - return Ok(( - vec![ - CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.into(), - CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384.into(), - ], - Some(vec![ - kx_group_by_name(rustls::NamedGroup::secp256r1, "secp256r1")?, - kx_group_by_name(rustls::NamedGroup::secp384r1, "secp384r1")?, - ]), - )); - } - CipherFilterSubOp::SuiteB(SuiteBType::Use128Only) => { - return Ok(( - vec![CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.into()], - Some(vec![kx_group_by_name( - rustls::NamedGroup::secp256r1, - "secp256r1", - )?]), - )); - } - CipherFilterSubOp::SuiteB(SuiteBType::Use192Only) => { - return Ok(( - vec![CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384.into()], - Some(vec![kx_group_by_name( - rustls::NamedGroup::secp384r1, - "secp384r1", - )?]), - )); + CipherFilterSubOp::SuiteB(suite_b) => { + let (suites, groups) = suite_b.parameters(); + let ids: Vec<_> = suites.iter().map(|suite| (*suite).into()).collect(); + CIPHER_MAPPINGS.validate_suite_b(&ids)?; + let groups = groups + .iter() + .map(|(group, name)| kx_group_by_name(*group, name)) + .collect::>()?; + return Ok((ids, Some(groups))); } CipherFilterSubOp::Cbc => { @@ -349,7 +366,7 @@ impl<'a> CipherFilterSubOpList<'a> { let rhs = CIPHER_MAPPINGS .select(|entry| entry.iana.split('_').any(|part| part == "CBC")); - Self::extend_or_intersect(&mut ids, &rhs) + Self::extend_or_intersect(&mut first, &mut ids, &rhs) } CipherFilterSubOp::AesGcm => { @@ -359,7 +376,7 @@ impl<'a> CipherFilterSubOpList<'a> { && parts().any(|part| part == "GCM") }); - Self::extend_or_intersect(&mut ids, &rhs) + Self::extend_or_intersect(&mut first, &mut ids, &rhs) } CipherFilterSubOp::Auth(auth) => { @@ -374,31 +391,30 @@ impl<'a> CipherFilterSubOpList<'a> { SupportedCipherSuite::Tls13(_) => true, }); - Self::extend_or_intersect(&mut ids, &rhs) + Self::extend_or_intersect(&mut first, &mut ids, &rhs) } CipherFilterSubOp::KeyEx(key_ex) => { let rhs = CIPHER_MAPPINGS.select(|entry| entry.key_ex == *key_ex); - Self::extend_or_intersect(&mut ids, &rhs) + Self::extend_or_intersect(&mut first, &mut ids, &rhs) } CipherFilterSubOp::Part(part) => { let rhs = CIPHER_MAPPINGS.select(|entry| name_has_part(entry.openssl, part)); - Self::extend_or_intersect(&mut ids, &rhs) + Self::extend_or_intersect(&mut first, &mut ids, &rhs) } CipherFilterSubOp::Full(full) => { - if let Some(id) = CIPHER_MAPPINGS.by_name(full) { - Self::extend_or_intersect(&mut ids, &[id]) - } + let rhs: Vec<_> = CIPHER_MAPPINGS.by_name(full).into_iter().collect(); + Self::extend_or_intersect(&mut first, &mut ids, &rhs) } } } Ok((ids, None)) } - fn extend_or_intersect(lhs: &mut Vec, rhs: &[u16]) { - if lhs.is_empty() { + fn extend_or_intersect(first: &mut bool, lhs: &mut Vec, rhs: &[u16]) { + if core::mem::take(first) { lhs.extend_from_slice(rhs) } else { lhs.retain(|id| rhs.contains(id)) @@ -406,7 +422,7 @@ impl<'a> CipherFilterSubOpList<'a> { } } -fn kx_group_by_name( +pub(super) fn kx_group_by_name( name: rustls::NamedGroup, error_name: &'static str, ) -> Result<&'static dyn SupportedKxGroup, &'static str> { @@ -418,22 +434,47 @@ fn kx_group_by_name( .ok_or(error_name) } +pub(super) fn kx_group_by_openssl_name(name: &str) -> Option<&'static dyn SupportedKxGroup> { + CryptoExt::get_ext() + .all_kx_or_default() + .iter() + .find(|group| kx_group_openssl_names(group.name()).contains(&name)) + .copied() +} + +fn kx_group_openssl_names(name: rustls::NamedGroup) -> &'static [&'static str] { + match name { + rustls::NamedGroup::secp256r1 => &["prime256v1", "secp256r1"], + rustls::NamedGroup::secp384r1 => &["secp384r1", "prime384v1"], + rustls::NamedGroup::secp521r1 => &["secp521r1", "prime521v1"], + rustls::NamedGroup::X25519 => &["X25519", "x25519"], + rustls::NamedGroup::X448 => &["X448", "x448"], + rustls::NamedGroup::MLKEM768 => &["MLKEM768"], + rustls::NamedGroup::MLKEM1024 => &["MLKEM1024"], + rustls::NamedGroup::secp256r1MLKEM768 => &["SecP256r1MLKEM768", "secp256r1MLKEM768"], + rustls::NamedGroup::X25519MLKEM768 => &["X25519MLKEM768"], + _ => &[], + } +} + type WithOptionSuiteB = (T, Option>); impl<'a> CipherFilterSubOp<'a> { fn parse(mut s: &'a str) -> Result { - Ok(match s { - "DEFAULT" => return Err("DEFAULT specified at wrong position in the cipher string"), - "SUITEB128" => { - return Err("SUITEB128 specified at wrong position in the cipher string"); - } + let wrong_position = match s { + "DEFAULT" => Some("DEFAULT specified at wrong position in the cipher string"), + "SUITEB128" => Some("SUITEB128 specified at wrong position in the cipher string"), "SUITEB128ONLY" => { - return Err("SUITEB128ONLY specified at wrong position in the cipher string"); - } - "SUITEB192" => { - return Err("SUITEB192 specified at wrong position in the cipher string"); + Some("SUITEB128ONLY specified at wrong position in the cipher string") } + "SUITEB192" => Some("SUITEB192 specified at wrong position in the cipher string"), + _ => None, + }; + if let Some(error) = wrong_position { + return Err(error); + } + Ok(match s { "COMPLEMENTOFDEFAULT" => Self::ComplementOfDefault, "ALL" => Self::All, "COMPLEMENTOFALL" => Self::ComplementOfAll, @@ -489,6 +530,38 @@ impl<'a> CipherFilterSubOp<'a> { } } +/// What `SSLContext.get_ciphers()` reports about one suite, laid out the way +/// `SSL_CIPHER_description` lays it out, padding included. +pub(super) struct CipherDescription { + pub id: u32, + pub name: &'static str, + pub protocol: &'static str, + pub bits: u16, + pub description: String, +} + +pub(super) fn describe(suite: &SupportedCipherSuite) -> CipherDescription { + let entry = CIPHER_MAPPINGS.entry(suite.suite().into()); + let tls13 = suite.tls13().is_some(); + let protocol = if tls13 { "TLSv1.3" } else { "TLSv1.2" }; + // A TLS 1.3 suite names neither the key agreement nor the authentication; + // the handshake settles both apart from the suite. + let key_ex = if tls13 { "any" } else { entry.key_ex }; + + CipherDescription { + // A cipher is numbered with the protocol it belongs to in the high + // half, and every TLS suite belongs to 0x0300. + id: 0x0300_0000 | u32::from(entry.id), + name: entry.openssl, + protocol, + bits: entry.bits, + description: format!( + "{:<30} {protocol} Kx={key_ex:<8} Au={:<5} Enc={:<22} Mac=AEAD", + entry.openssl, entry.auth, entry.encryption + ), + } +} + /// How the table spells the key agreement every suite in it uses. const EPHEMERAL_ECDH: &str = "ECDH"; @@ -521,6 +594,8 @@ struct CipherEntry { openssl: &'static str, iana: &'static str, key_ex: &'static str, + auth: &'static str, + encryption: &'static str, bits: u16, suite: &'static SupportedCipherSuite, } @@ -537,13 +612,23 @@ struct CipherMappings { } impl CipherMappings { + fn find(&self, id: u16) -> Option<&CipherEntry> { + self.entries.iter().find(|entry| entry.id == id) + } + fn entry(&self, id: u16) -> &CipherEntry { - self.entries - .iter() - .find(|entry| entry.id == id) + self.find(id) .expect("BUG: cipher id is not one of the table's") } + fn validate_suite_b(&self, ids: &[u16]) -> Result<(), &'static str> { + if ids.iter().all(|id| self.find(*id).is_some()) { + Ok(()) + } else { + Err("Suite B cipher is not supported by crypto provider") + } + } + fn select(&self, matches: impl Fn(&CipherEntry) -> bool) -> Vec { self.entries .iter() @@ -559,6 +644,14 @@ impl CipherMappings { .map(|entry| entry.id) } + fn default_cipher_string(&self) -> String { + self.default + .iter() + .map(|id| self.entry(*id).openssl) + .collect::>() + .join(":") + } + fn new() -> Self { let all_cipher_suites = CryptoExt::get_ext().all_ciphers_or_default(); let default_cipher_suites = CryptoExt::get_ext().default_ciphers_or_provider(); @@ -569,11 +662,13 @@ impl CipherMappings { for cipher in all_cipher_suites { // See https://www.ssl.org/cipher-suite-mapping - let (openssl, iana, key_ex, bits, min_tls_ver) = match cipher.suite() { + let (openssl, iana, key_ex, auth, enc, bits, min_tls_ver) = match cipher.suite() { CipherSuite::TLS13_AES_256_GCM_SHA384 => ( "TLS_AES_256_GCM_SHA384", "TLS_AES_256_GCM_SHA384", "ECDH", + "any", + "AESGCM(256)", 256, 13, ), @@ -582,6 +677,8 @@ impl CipherMappings { "TLS_AES_128_GCM_SHA256", "TLS_AES_128_GCM_SHA256", "ECDH", + "any", + "AESGCM(128)", 128, 13, ), @@ -590,6 +687,8 @@ impl CipherMappings { "TLS_CHACHA20_POLY1305_SHA256", "TLS_CHACHA20_POLY1305_SHA256", "ECDH", + "any", + "CHACHA20/POLY1305(256)", 256, 13, ), @@ -598,6 +697,8 @@ impl CipherMappings { "ECDHE-ECDSA-AES256-GCM-SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "ECDH", + "ECDSA", + "AESGCM(256)", 256, 12, ), @@ -606,6 +707,8 @@ impl CipherMappings { "ECDHE-ECDSA-AES128-GCM-SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "ECDH", + "ECDSA", + "AESGCM(128)", 128, 12, ), @@ -614,6 +717,8 @@ impl CipherMappings { "ECDHE-ECDSA-CHACHA20-POLY1305", "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", "ECDH", + "ECDSA", + "CHACHA20/POLY1305(256)", 256, 12, ), @@ -622,6 +727,8 @@ impl CipherMappings { "ECDHE-RSA-AES256-GCM-SHA384", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "ECDH", + "RSA", + "AESGCM(256)", 256, 12, ), @@ -630,6 +737,8 @@ impl CipherMappings { "ECDHE-RSA-AES128-GCM-SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "ECDH", + "RSA", + "AESGCM(128)", 128, 12, ), @@ -638,6 +747,8 @@ impl CipherMappings { "ECDHE-RSA-CHACHA20-POLY1305", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "ECDH", + "RSA", + "CHACHA20/POLY1305(256)", 256, 12, ), @@ -660,6 +771,8 @@ impl CipherMappings { openssl, iana, key_ex, + auth, + encryption: enc, bits, suite: cipher, }); @@ -690,6 +803,23 @@ impl CipherMappings { } } +pub(super) fn default_cipher_string() -> String { + CIPHER_MAPPINGS.default_cipher_string() +} + +pub(super) fn restore_default_tls13( + mut selected: Vec, + defaults: &[SupportedCipherSuite], +) -> Vec { + selected.retain(|suite| suite.tls13().is_none()); + let tls13 = defaults + .iter() + .filter(|suite| suite.tls13().is_some()) + .copied(); + selected.splice(..0, tls13); + selected +} + #[cfg(test)] mod tests { use core::hint::black_box; @@ -729,7 +859,16 @@ mod tests { #[test] fn every_rustls_cipher_is_known() { install_test_crypto_provider(); - let _ = black_box(&*CIPHER_MAPPINGS); + for suite in CryptoExt::get_ext().all_ciphers_or_default() { + let _ = black_box(describe(suite)); + } + + assert!( + CryptoExt::get_ext() + .all_kx_or_default() + .iter() + .all(|group| !kx_group_openssl_names(group.name()).is_empty()) + ); } #[test] @@ -748,6 +887,7 @@ mod tests { suites.iter().map(|suite| suite.suite()).collect::>(), default ); + assert_eq!(default_cipher_string(), cipher_names("DEFAULT").join(":")); // Either spelling names the same suite, and a term is a conjunction. assert_eq!( cipher_names("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, ECDHE-ECDSA-AES128-GCM-SHA256"), @@ -760,6 +900,24 @@ mod tests { cipher_names("AES128+aECDSA"), ["ECDHE-ECDSA-AES128-GCM-SHA256"] ); + + let (selected, _) = CipherList::parse_to_rustls("ALL").unwrap(); + let defaults = &[ + rustls::crypto::aws_lc_rs::cipher_suite::TLS13_AES_256_GCM_SHA384, + rustls::crypto::aws_lc_rs::cipher_suite::TLS13_AES_128_GCM_SHA256, + ]; + let selected = restore_default_tls13(selected, defaults); + assert_eq!( + selected + .iter() + .filter(|suite| suite.tls13().is_some()) + .map(|suite| suite.suite()) + .collect::>(), + [ + CipherSuite::TLS13_AES_256_GCM_SHA384, + CipherSuite::TLS13_AES_128_GCM_SHA256, + ] + ); } #[test] @@ -801,6 +959,12 @@ mod tests { for nothing in ["MEDIUM", "LOW", "TLSv1.0", "SSLv3", "SHA256", "CBC"] { assert_eq!(cipher_names(nothing), Vec::<&str>::new(), "{nothing}"); } + + // An empty first half of a conjunction stays empty rather than making + // its second half act like a fresh selection. + for nothing in ["MEDIUM+AES", "TLSv1.0+AES", "NO-SUCH-CIPHER+AES"] { + assert_eq!(cipher_names(nothing), Vec::<&str>::new(), "{nothing}"); + } } #[test] @@ -858,6 +1022,10 @@ mod tests { ); assert!(suite_b.is_some()); assert!(CipherList::parse_to_rustls("ALL:SUITEB128").is_err()); + + // A provider that omits one of the hardcoded Suite B suites must get + // an error rather than reaching the invariant-enforcing lookup. + assert!(CIPHER_MAPPINGS.validate_suite_b(&[u16::MAX]).is_err()); } #[test] diff --git a/crates/stdlib/src/ssl/compat.rs b/crates/stdlib/src/ssl/compat.rs index 7ed65ce8f4c..81f0c8b7091 100644 --- a/crates/stdlib/src/ssl/compat.rs +++ b/crates/stdlib/src/ssl/compat.rs @@ -1990,106 +1990,6 @@ impl ResolvesServerCert for MultiCertResolver { // Helper Functions for OpenSSL Compatibility: -/// Normalize cipher suite name for OpenSSL compatibility -/// -/// Converts rustls cipher names to OpenSSL format: -/// - TLS_AES_256_GCM_SHA384 → AES256-GCM-SHA384 -/// - Replaces "AES-256" with "AES256" and "AES-128" with "AES128" -pub(super) fn normalize_cipher_name(rustls_name: &str) -> String { - rustls_name - .strip_prefix("TLS_") - .unwrap_or(rustls_name) - .replace("_WITH_", "_") - .replace('_', "-") - .replace("AES-256", "AES256") - .replace("AES-128", "AES128") -} - -/// Get cipher key size in bits from cipher suite name -/// -/// Returns: -/// - 256 for AES-256 and ChaCha20 -/// - 128 for AES-128 -/// - 0 for unknown ciphers -pub(super) fn get_cipher_key_bits(cipher_name: &str) -> i32 { - if cipher_name.contains("256") || cipher_name.contains("CHACHA20") { - 256 - } else if cipher_name.contains("128") { - 128 - } else { - 0 - } -} - -/// Get encryption algorithm description from cipher name -/// -/// Returns human-readable encryption description for OpenSSL compatibility -pub(super) fn get_cipher_encryption_desc(cipher_name: &str) -> &'static str { - if cipher_name.contains("AES256") { - "AESGCM(256)" - } else if cipher_name.contains("AES128") { - "AESGCM(128)" - } else if cipher_name.contains("CHACHA20") { - "CHACHA20-POLY1305(256)" - } else { - "Unknown" - } -} - -/// Normalize rustls cipher suite name to IANA standard format -/// -/// Converts rustls Debug format names to IANA standard: -/// - "TLS13_AES_256_GCM_SHA384" -> "TLS_AES_256_GCM_SHA384" -/// - Other names remain unchanged -pub(super) fn normalize_rustls_cipher_name(rustls_name: &str) -> String { - if rustls_name.starts_with("TLS13_") { - rustls_name.replace("TLS13_", "TLS_") - } else { - rustls_name.to_string() - } -} - -/// Convert rustls protocol version to string representation -/// -/// Returns the TLS version string -/// - TLSv1.2, TLSv1.3, or "Unknown" -pub(super) fn get_protocol_version_str(version: &rustls::SupportedProtocolVersion) -> &'static str { - match version.version { - rustls::ProtocolVersion::TLSv1_2 => "TLSv1.2", - rustls::ProtocolVersion::TLSv1_3 => "TLSv1.3", - _ => "Unknown", - } -} - -/// Cipher suite information -/// -/// Contains all relevant cipher information extracted from a rustls CipherSuite -pub(super) struct CipherInfo { - /// IANA standard cipher name (e.g., "TLS_AES_256_GCM_SHA384") - pub name: String, - /// TLS protocol version (e.g., "TLSv1.2", "TLSv1.3") - pub protocol: &'static str, - /// Key size in bits (e.g., 128, 256) - pub bits: i32, -} - -/// Extract cipher information from a rustls CipherSuite -/// -/// This consolidates the common cipher extraction logic used across -/// get_ciphers(), cipher(), and shared_ciphers() methods. -pub(super) fn extract_cipher_info(suite: &rustls::SupportedCipherSuite) -> CipherInfo { - let rustls_name = format!("{:?}", suite.suite()); - let name = normalize_rustls_cipher_name(&rustls_name); - let protocol = get_protocol_version_str(suite.version()); - let bits = get_cipher_key_bits(&name); - - CipherInfo { - name, - protocol, - bits, - } -} - /// Convert curve name to rustls key exchange group /// /// Maps OpenSSL curve names (e.g., "prime256v1", "secp384r1") to rustls KxGroups. @@ -2097,43 +1997,7 @@ pub(super) fn extract_cipher_info(suite: &rustls::SupportedCipherSuite) -> Ciphe pub(super) fn curve_name_to_kx_group( curve: &str, ) -> Result, String> { - // Get the default crypto provider's key exchange groups - let all_groups = CryptoExt::get_ext().all_kx_or_default(); - - match curve { - // P-256 (also known as secp256r1 or prime256v1) - "prime256v1" | "secp256r1" => { - // Find SECP256R1 in the provider's groups - all_groups - .iter() - .find(|g| g.name() == rustls::NamedGroup::secp256r1) - .map(|g| vec![*g]) - .ok_or_else(|| "secp256r1 not supported by crypto provider".to_owned()) - } - // P-384 (also known as secp384r1 or prime384v1) - "secp384r1" | "prime384v1" => all_groups - .iter() - .find(|g| g.name() == rustls::NamedGroup::secp384r1) - .map(|g| vec![*g]) - .ok_or_else(|| "secp384r1 not supported by crypto provider".to_owned()), - // X25519 - "X25519" | "x25519" => all_groups - .iter() - .find(|g| g.name() == rustls::NamedGroup::X25519) - .map(|g| vec![*g]) - .ok_or_else(|| "X25519 not supported by crypto provider".to_owned()), - // P-521 (also known as secp521r1 or prime521v1) - "prime521v1" | "secp521r1" => all_groups - .iter() - .find(|g| g.name() == rustls::NamedGroup::secp521r1) - .map(|g| vec![*g]) - .ok_or_else(|| "secp521r1 not supported by crypto provider".to_owned()), - // X448 - "X448" | "x448" => all_groups - .iter() - .find(|g| g.name() == rustls::NamedGroup::X448) - .map(|g| vec![*g]) - .ok_or_else(|| "X448 not supported by crypto provider".to_owned()), - _ => Err(format!("unknown curve name '{curve}'")), - } + super::cipher::kx_group_by_openssl_name(curve) + .map(|group| vec![group]) + .ok_or_else(|| format!("unknown curve name '{curve}'")) } diff --git a/src/interpreter.rs b/src/interpreter.rs index b8f94848686..b9346ca1bac 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -33,10 +33,18 @@ fn install_default_tls_provider(_vm: &mut crate::VirtualMachine) { use rustls::crypto::aws_lc_rs; use rustpython_stdlib::ssl::providers::CryptoExt; + #[cfg(feature = "ssl-rustls-aws-lc-fips")] + let (all_cipher_suites, all_kx_groups) = (None, None); + #[cfg(not(feature = "ssl-rustls-aws-lc-fips"))] + let (all_cipher_suites, all_kx_groups) = ( + Some(aws_lc_rs::ALL_CIPHER_SUITES), + Some(aws_lc_rs::ALL_KX_GROUPS), + ); + let ext = CryptoExt { - all_cipher_suites: Some(aws_lc_rs::ALL_CIPHER_SUITES), + all_cipher_suites, default_cipher_suites: Some(aws_lc_rs::DEFAULT_CIPHER_SUITES), - all_kx_groups: Some(aws_lc_rs::ALL_KX_GROUPS), + all_kx_groups, any_supported_key: Some(aws_lc_rs::sign::any_supported_type), ticketer: aws_lc_rs::Ticketer::new, }; From 46084f2ad4e7a8fab16042cefb672b205c039166 Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Fri, 4 Sep 2026 19:21:50 +0900 Subject: [PATCH 04/10] ssl: preserve OpenSSL OID lookup rules Keep object-name lookup case-sensitive and canonicalize numeric OID arcs before consulting the generated OpenSSL object table. Assisted-by: OpenAI Codex: GPT-5 --- crates/stdlib/src/ssl/oid.rs | 54 +++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/crates/stdlib/src/ssl/oid.rs b/crates/stdlib/src/ssl/oid.rs index 91a17a8a76d..847c3c4125e 100644 --- a/crates/stdlib/src/ssl/oid.rs +++ b/crates/stdlib/src/ssl/oid.rs @@ -45,8 +45,8 @@ pub(super) struct OidTable { nid_to_idx: HashMap, /// Short name -> index mapping short_name_to_idx: HashMap<&'static str, usize>, - /// Long name -> index mapping (case-insensitive) - long_name_to_idx: HashMap, + /// Long name -> index mapping + long_name_to_idx: HashMap<&'static str, usize>, /// OID string -> index mapping oid_str_to_idx: HashMap, } @@ -64,9 +64,7 @@ impl OidTable { for (idx, entry) in entries.iter().enumerate() { nid_to_idx.entry(entry.nid).or_insert(idx); short_name_to_idx.entry(entry.short_name).or_insert(idx); - long_name_to_idx - .entry(entry.long_name.to_lowercase()) - .or_insert(idx); + long_name_to_idx.entry(entry.long_name).or_insert(idx); if let Some(oid) = entry.oid_string() { oid_str_to_idx.entry(oid.to_owned()).or_insert(idx); } @@ -87,22 +85,45 @@ impl OidTable { pub(super) fn find_by_oid_string(&self, oid_str: &str) -> Option<&OidEntry> { self.oid_str_to_idx - .get(oid_str) + .get(canonical_oid(oid_str)?.as_str()) .map(|&idx| &self.entries[idx]) } pub(super) fn find_by_name(&self, name: &str) -> Option<&OidEntry> { - // Try short name first (exact match) + // OpenSSL object names are case-sensitive. Try the short name first, + // as OBJ_txt2obj does when a short and long name collide. self.short_name_to_idx .get(name) - .or_else(|| { - // Try long name (case-insensitive) - self.long_name_to_idx.get(&name.to_lowercase()) - }) + .or_else(|| self.long_name_to_idx.get(name)) .map(|&idx| &self.entries[idx]) } } +/// Parse the numeric form accepted by OpenSSL and render it canonically for +/// lookup. The first arc may not have leading zeroes, while later arcs may. +fn canonical_oid(oid: &str) -> Option { + let oid = oid.trim_end_matches(' '); + let oid = oid.strip_suffix('.').unwrap_or(oid); + let mut parts = oid.split('.'); + let first = parts.next()?; + if !matches!(first, "0" | "1" | "2") { + return None; + } + + let mut canonical = first.to_owned(); + let mut count = 1; + for part in parts { + if part.is_empty() || !part.bytes().all(|byte| byte.is_ascii_digit()) { + return None; + } + let part = part.trim_start_matches('0'); + canonical.push('.'); + canonical.push_str(if part.is_empty() { "0" } else { part }); + count += 1; + } + (count >= 2).then_some(canonical) +} + /// Global OID table static OID_TABLE: rustpython_common::lock::LazyLock = rustpython_common::lock::LazyLock::new(OidTable::build); @@ -296,9 +317,16 @@ mod tests { } #[test] - fn find_by_name_case_insensitive() { - let entry = find_by_name("COMMONNAME").unwrap(); + fn find_by_name_is_case_sensitive() { + assert!(find_by_name("commonName").is_some()); + assert!(find_by_name("COMMONNAME").is_none()); + } + + #[test] + fn find_by_oid_string_normalizes_arcs() { + let entry = find_by_oid_string("2.005.004.003.").unwrap(); assert_eq!(entry.nid, 13); + assert_eq!(entry.oid_string(), Some("2.5.4.3")); } #[test] From 81545566add8cb64cb26b5008b0a8980a2468d41 Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Fri, 4 Sep 2026 19:31:00 +0900 Subject: [PATCH 05/10] ssl: preserve cleartext after MemoryBIO shutdown Read at most one TLS record while waiting for close_notify in BIO mode, leaving any post-TLS cleartext queued for the BIO owner. Co-authored-by: Ivan Mironov Assisted-by: OpenAI Codex: GPT-5 --- crates/stdlib/src/ssl.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/crates/stdlib/src/ssl.rs b/crates/stdlib/src/ssl.rs index 269f86b6bc2..e557f073847 100644 --- a/crates/stdlib/src/ssl.rs +++ b/crates/stdlib/src/ssl.rs @@ -1899,7 +1899,10 @@ mod _ssl { sock_send_method: vm.ctx.none(), sock_recv_method: vm.ctx.none(), - tls_record_header_buf: vm.ctx.none(), + tls_record_header_buf: vm + .ctx + .new_bytearray(Vec::with_capacity(TLS_RECORD_HEADER_SIZE)) + .into(), context: PyRwLock::new(zelf), server_side, server_hostname: PyRwLock::new(hostname), @@ -4382,11 +4385,11 @@ mod _ssl { return Ok(self.try_read_close_notify_socket(conn, vm)); } - // BIO mode: read from incoming BIO - match self.sock_recv(SSL3_RT_MAX_PACKET_SIZE, vm) { - Ok(bytes_obj) => { - let bytes = ArgBytesLike::try_from_object(vm, bytes_obj)?; - let data = bytes.borrow_buf(); + // BIO mode: stop at the TLS record boundary so cleartext queued + // after close_notify remains available to the BIO's owner. + match self.sock_recv_at_most_one_tls_record(vm) { + Ok(bytes) => { + let data = bytes.as_bytes(); if data.is_empty() { if let Some(ref bio) = self.incoming_bio { @@ -4401,7 +4404,7 @@ mod _ssl { return Ok(true); } - let data_slice: &[u8] = data.as_ref(); + let data_slice: &[u8] = data; let mut cursor = std::io::Cursor::new(data_slice); let _ = conn.read_tls(&mut cursor); let _ = conn.process_new_packets(); From 5a5d3e8930f443888774fe97568b73c486fe85e6 Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Fri, 4 Sep 2026 19:48:27 +0900 Subject: [PATCH 06/10] ssl: reject empty cipher conjunction operands Keep empty operands visible to the parser so malformed OpenSSL cipher strings such as AES+ and ALL++AES are rejected instead of normalized. Assisted-by: CodeRabbit Assisted-by: OpenAI Codex: GPT-5 --- crates/stdlib/src/ssl/cipher.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/stdlib/src/ssl/cipher.rs b/crates/stdlib/src/ssl/cipher.rs index 0186230c5ef..769fdbbf7fe 100644 --- a/crates/stdlib/src/ssl/cipher.rs +++ b/crates/stdlib/src/ssl/cipher.rs @@ -285,7 +285,6 @@ impl<'a> CipherFilterSubOpList<'a> { fn parse(s: &'a str) -> Result { let sub_ops: Vec<_> = s .split('+') - .filter(|s| !s.is_empty()) .map(CipherFilterSubOp::parse) .collect::>()?; if sub_ops.is_empty() { @@ -1037,5 +1036,7 @@ mod tests { assert!(CipherList::parse_to_rustls("PROFILE=SYSTEM").is_err()); assert!(CipherList::parse_to_rustls(";").is_err()); assert!(CipherList::parse_to_rustls("").is_err()); + assert!(CipherList::parse_to_rustls("AES+").is_err()); + assert!(CipherList::parse_to_rustls("ALL++AES").is_err()); } } From 5c06a02a983b178bfcd63cea27ed293eec0cfa7f Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Fri, 4 Sep 2026 20:06:32 +0900 Subject: [PATCH 07/10] ssl: make Suite B cipher ids unambiguous Spell out the u16 conversion so Windows-only iterator implementations cannot make collection type inference ambiguous. Assisted-by: OpenAI Codex: GPT-5 --- crates/stdlib/src/ssl/cipher.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/stdlib/src/ssl/cipher.rs b/crates/stdlib/src/ssl/cipher.rs index 769fdbbf7fe..ec5d639bb0e 100644 --- a/crates/stdlib/src/ssl/cipher.rs +++ b/crates/stdlib/src/ssl/cipher.rs @@ -351,7 +351,7 @@ impl<'a> CipherFilterSubOpList<'a> { // RFC 6460 CipherFilterSubOp::SuiteB(suite_b) => { let (suites, groups) = suite_b.parameters(); - let ids: Vec<_> = suites.iter().map(|suite| (*suite).into()).collect(); + let ids: Vec = suites.iter().map(|suite| u16::from(*suite)).collect(); CIPHER_MAPPINGS.validate_suite_b(&ids)?; let groups = groups .iter() From 1eab9dd32e55a478fb570dda01ad9059b7411a8c Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Fri, 4 Sep 2026 21:15:29 +0900 Subject: [PATCH 08/10] ssl: move native certificate loading behind host_env Keep platform trust-store loading and filesystem predicates on the host boundary while exposing backend-neutral certificate bytes to the rustls integration. Assisted-by: OpenAI Codex: GPT-5 --- Cargo.lock | 2 +- crates/host_env/Cargo.toml | 4 ++++ crates/host_env/src/fs.rs | 12 ++++++++++++ crates/host_env/src/lib.rs | 2 ++ crates/host_env/src/native_certs.rs | 22 ++++++++++++++++++++++ crates/stdlib/Cargo.toml | 3 +-- crates/stdlib/src/ssl.rs | 14 ++++++-------- crates/stdlib/src/ssl/cert.rs | 2 +- 8 files changed, 49 insertions(+), 12 deletions(-) create mode 100644 crates/host_env/src/native_certs.rs diff --git a/Cargo.lock b/Cargo.lock index 7447153aee7..2ea21dc461d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3463,6 +3463,7 @@ dependencies = [ "parking_lot", "paste", "rustix", + "rustls-native-certs", "rustpython-wtf8", "rustyline", "schannel", @@ -3628,7 +3629,6 @@ dependencies = [ "rand 0.10.2", "rapidhash", "rustls", - "rustls-native-certs", "rustls-pemfile", "rustls-platform-verifier", "rustpython-common", diff --git a/crates/host_env/Cargo.toml b/crates/host_env/Cargo.toml index e26fdeafe0b..165e0f655ea 100644 --- a/crates/host_env/Cargo.toml +++ b/crates/host_env/Cargo.toml @@ -8,6 +8,9 @@ rust-version.workspace = true repository.workspace = true license.workspace = true +[features] +native-certs = ["dep:rustls-native-certs"] + [dependencies] rustpython-wtf8 = { workspace = true } @@ -35,6 +38,7 @@ mac_address = { workspace = true } dns-lookup = { workspace = true } gethostname = { workspace = true } rustyline = { workspace = true } +rustls-native-certs = { workspace = true, optional = true } socket2 = { workspace = true, features = ["all"] } which = { workspace = true } diff --git a/crates/host_env/src/fs.rs b/crates/host_env/src/fs.rs index 01040e73ed5..6d41a560a68 100644 --- a/crates/host_env/src/fs.rs +++ b/crates/host_env/src/fs.rs @@ -36,6 +36,18 @@ pub fn metadata(path: impl AsRef) -> io::Result { fs::metadata(path) } +pub fn exists(path: impl AsRef) -> bool { + metadata(path).is_ok() +} + +pub fn is_file(path: impl AsRef) -> bool { + metadata(path).is_ok_and(|metadata| metadata.is_file()) +} + +pub fn is_dir(path: impl AsRef) -> bool { + metadata(path).is_ok_and(|metadata| metadata.is_dir()) +} + pub fn symlink_metadata(path: impl AsRef) -> io::Result { fs::symlink_metadata(path) } diff --git a/crates/host_env/src/lib.rs b/crates/host_env/src/lib.rs index 975ca21b626..c4db4c026b8 100644 --- a/crates/host_env/src/lib.rs +++ b/crates/host_env/src/lib.rs @@ -30,6 +30,8 @@ pub mod fileutils; pub mod fs; #[cfg(any(unix, windows))] pub mod locale; +#[cfg(all(feature = "native-certs", not(target_arch = "wasm32")))] +pub mod native_certs; pub mod readline; #[cfg(windows)] diff --git a/crates/host_env/src/native_certs.rs b/crates/host_env/src/native_certs.rs new file mode 100644 index 00000000000..a2a35c15965 --- /dev/null +++ b/crates/host_env/src/native_certs.rs @@ -0,0 +1,22 @@ +/// Certificates and errors returned by the platform's native trust-store +/// loader. Certificate bytes stay independent of any TLS backend type. +pub struct LoadResult { + pub certs: Vec>, + pub errors: Vec, +} + +pub fn load() -> LoadResult { + let result = rustls_native_certs::load_native_certs(); + LoadResult { + certs: result + .certs + .into_iter() + .map(|cert| cert.as_ref().to_vec()) + .collect(), + errors: result + .errors + .into_iter() + .map(|error| error.to_string()) + .collect(), + } +} diff --git a/crates/stdlib/Cargo.toml b/crates/stdlib/Cargo.toml index a562132ebf0..0fead982275 100644 --- a/crates/stdlib/Cargo.toml +++ b/crates/stdlib/Cargo.toml @@ -24,7 +24,7 @@ ssl-openssl-vendor = ["ssl-openssl", "openssl/vendored"] tkinter = ["dep:tk-sys", "dep:tcl-sys", "dep:widestring"] flame-it = ["flame"] -__ssl-rustls = ["ssl", "rustls", "rustls-native-certs", "rustls-pemfile", "rustls-platform-verifier", "x509-cert", "x509-parser", "der", "pem-rfc7468", "webpki-roots", "oid-registry", "pkcs8"] +__ssl-rustls = ["ssl", "rustpython-host_env/native-certs", "rustls", "rustls-pemfile", "rustls-platform-verifier", "x509-cert", "x509-parser", "der", "pem-rfc7468", "webpki-roots", "oid-registry", "pkcs8"] [dependencies] # rustpython crates @@ -92,7 +92,6 @@ foreign-types-shared = { workspace = true, optional = true } # Rustls dependencies (optional, for ssl-rustls feature) rustls = { workspace = true, default-features = false, features = ["std", "tls12"], optional = true } -rustls-native-certs = { workspace = true, optional = true } rustls-pemfile = { workspace = true, optional = true } rustls-platform-verifier = { workspace = true, optional = true } x509-cert = { workspace = true, features = ["pem", "builder"], optional = true } diff --git a/crates/stdlib/src/ssl.rs b/crates/stdlib/src/ssl.rs index e557f073847..c0e51f16311 100644 --- a/crates/stdlib/src/ssl.rs +++ b/crates/stdlib/src/ssl.rs @@ -1303,14 +1303,12 @@ mod _ssl { loader: &mut cert::CertLoader<'_>, vm: &VirtualMachine, ) -> PyResult { - use std::path::Path; - let os_module = vm.import("os", 0)?; let environ = os_module.get_attr("environ", vm)?; // Try SSL_CERT_FILE first if let Ok(cert_file) = Self::get_env_path(&environ, "SSL_CERT_FILE", vm) - && Path::new(&cert_file).exists() + && rustpython_host_env::fs::exists(&cert_file) && let Ok(stats) = loader.load_from_file(&cert_file) { self.update_cert_stats(stats); @@ -1319,7 +1317,7 @@ mod _ssl { // Try SSL_CERT_DIR (only if SSL_CERT_FILE didn't work) if let Ok(cert_dir) = Self::get_env_path(&environ, "SSL_CERT_DIR", vm) - && Path::new(&cert_dir).is_dir() + && rustpython_host_env::fs::is_dir(&cert_dir) && let Ok(stats) = loader.load_from_dir(&cert_dir) { self.update_cert_stats(stats); @@ -1367,12 +1365,12 @@ mod _ssl { #[cfg(not(windows))] { - let result = rustls_native_certs::load_native_certs(); + let result = rustpython_host_env::native_certs::load(); // Load successfully found certificates for cert in result.certs { - let is_ca = cert::is_ca_certificate(cert.as_ref()); - if store.add(cert).is_ok() { + let is_ca = cert::is_ca_certificate(&cert); + if store.add(cert.into()).is_ok() { *self.x509_cert_count.write() += 1; if is_ca { *self.ca_cert_count.write() += 1; @@ -1699,7 +1697,7 @@ mod _ssl { }; // Check if file exists - if !std::path::Path::new(&path_str).exists() { + if !rustpython_host_env::fs::exists(&path_str) { // Create FileNotFoundError with errno=ENOENT (2) let exc = vm.new_os_subtype_error( vm.ctx.exceptions.file_not_found_error.to_owned(), diff --git a/crates/stdlib/src/ssl/cert.rs b/crates/stdlib/src/ssl/cert.rs index 47d11f730b2..8c79b8019d4 100644 --- a/crates/stdlib/src/ssl/cert.rs +++ b/crates/stdlib/src/ssl/cert.rs @@ -668,7 +668,7 @@ impl<'a> CertLoader<'a> { // Skip directories and process all files // OpenSSL capath uses hash-based naming like "4e1295a3.0" - if path.is_file() + if rustpython_host_env::fs::is_file(&path) && let Ok(contents) = rustpython_host_env::fs::read(&path) { // Ignore errors for individual files (some may not be certs) From 8acdf8f09fea484f62085ab4951b9c95bb962237 Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Fri, 4 Sep 2026 21:19:55 +0900 Subject: [PATCH 09/10] ssl: invalidate server config after cipher changes Rebuild cached server configuration after set_ciphers updates the selected suites or Suite B key-exchange groups. Assisted-by: CodeRabbit Assisted-by: OpenAI Codex: GPT-5 --- crates/stdlib/src/ssl.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/stdlib/src/ssl.rs b/crates/stdlib/src/ssl.rs index c0e51f16311..60b2f3f8afa 100644 --- a/crates/stdlib/src/ssl.rs +++ b/crates/stdlib/src/ssl.rs @@ -1489,6 +1489,7 @@ mod _ssl { *self.selected_ciphers.write() = Some(selected_ciphers); *self.suite_b_kx_groups.write() = suite_b_kx_groups; + *self.server_config.write() = None; Ok(()) } From beca8d09873aa40917bd9b96ba13981f2a6e2d7d Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Fri, 4 Sep 2026 21:30:26 +0900 Subject: [PATCH 10/10] ssl: load default certificate sources independently Honor SSL_CERT_FILE and SSL_CERT_DIR independently. Keep directory certificates as lazy capath candidates, and fall back to native roots only when no environment certificate file was loaded. Co-authored-by: Ivan Mironov Assisted-by: OpenAI Codex: GPT-5 --- crates/stdlib/src/ssl.rs | 41 +++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/crates/stdlib/src/ssl.rs b/crates/stdlib/src/ssl.rs index 60b2f3f8afa..63af8b0ff1b 100644 --- a/crates/stdlib/src/ssl.rs +++ b/crates/stdlib/src/ssl.rs @@ -1292,39 +1292,46 @@ mod _ssl { /// Helper: Try to load certificates from Python's os.environ variables /// - /// Returns true if certificates were successfully loaded. + /// Returns true if certificates were successfully loaded from + /// `SSL_CERT_FILE`. `SSL_CERT_DIR` is an independent source and its + /// certificates remain hidden from store statistics until used. /// /// We use Python's os.environ instead of Rust's std::env /// because Python code can modify os.environ at runtime (e.g., - /// `os.environ['SSL_CERT_FILE'] = '/path'`), but rustls-native-certs uses - /// std::env which only sees the process environment at startup. + /// `os.environ['SSL_CERT_FILE'] = '/path'`), but the native certificate + /// loader uses std::env which only sees the process environment. fn try_load_from_python_environ( &self, - loader: &mut cert::CertLoader<'_>, + store: &mut rustls::RootCertStore, vm: &VirtualMachine, ) -> PyResult { let os_module = vm.import("os", 0)?; let environ = os_module.get_attr("environ", vm)?; - // Try SSL_CERT_FILE first + let mut loaded_certs = Vec::new(); + let mut loaded_file = false; + if let Ok(cert_file) = Self::get_env_path(&environ, "SSL_CERT_FILE", vm) && rustpython_host_env::fs::exists(&cert_file) - && let Ok(stats) = loader.load_from_file(&cert_file) { - self.update_cert_stats(stats); - return Ok(true); + let mut loader = cert::CertLoader::new(store, &mut loaded_certs); + if let Ok(stats) = loader.load_from_file(&cert_file) { + self.update_cert_stats(stats); + loaded_file = true; + } } - // Try SSL_CERT_DIR (only if SSL_CERT_FILE didn't work) + let file_cert_count = loaded_certs.len(); if let Ok(cert_dir) = Self::get_env_path(&environ, "SSL_CERT_DIR", vm) && rustpython_host_env::fs::is_dir(&cert_dir) - && let Ok(stats) = loader.load_from_dir(&cert_dir) { - self.update_cert_stats(stats); - return Ok(true); + let mut loader = cert::CertLoader::new(store, &mut loaded_certs); + if loader.load_from_dir(&cert_dir).is_ok() { + *self.capath_certs_der.write() = loaded_certs.split_off(file_cert_count); + } } - Ok(false) + Ok(loaded_file) } /// Helper: Load system certificates using rustls-native-certs @@ -1405,18 +1412,14 @@ mod _ssl { // see: test_load_default_certs_env_windows let _ = self.load_system_certificates(&mut store, vm); - let mut lazy_ca_certs = Vec::new(); - let mut loader = cert::CertLoader::new(&mut store, &mut lazy_ca_certs); - let _ = self.try_load_from_python_environ(&mut loader, vm)?; + let _ = self.try_load_from_python_environ(&mut store, vm)?; } #[cfg(not(windows))] { // Non-Windows: Try env vars first; only fallback to system certs if not set // see: test_load_default_certs_env - let mut lazy_ca_certs = Vec::new(); - let mut loader = cert::CertLoader::new(&mut store, &mut lazy_ca_certs); - let loaded = self.try_load_from_python_environ(&mut loader, vm)?; + let loaded = self.try_load_from_python_environ(&mut store, vm)?; if !loaded { let _ = self.load_system_certificates(&mut store, vm);