aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/common_test/doc/src/notes.xml116
-rw-r--r--lib/common_test/vsn.mk2
-rw-r--r--lib/compiler/doc/src/compile.xml26
-rw-r--r--lib/compiler/src/Makefile1
-rw-r--r--lib/compiler/src/beam_dict.erl18
-rw-r--r--lib/compiler/src/compile.erl8
-rw-r--r--lib/compiler/src/compiler.app.src1
-rw-r--r--lib/compiler/src/core_lint.erl3
-rw-r--r--lib/compiler/src/sys_core_fold.erl112
-rw-r--r--lib/compiler/src/sys_expand_pmod.erl433
-rw-r--r--lib/compiler/src/sys_pre_expand.erl85
-rw-r--r--lib/compiler/src/v3_kernel.erl31
-rw-r--r--lib/compiler/test/Makefile1
-rw-r--r--lib/compiler/test/inline_SUITE.erl43
-rw-r--r--lib/compiler/test/pmod_SUITE.erl121
-rw-r--r--lib/compiler/test/pmod_SUITE_data/pmod_basic.erl83
-rw-r--r--lib/diameter/doc/src/notes.xml16
-rw-r--r--lib/diameter/src/base/diameter.appup.src29
-rw-r--r--lib/diameter/src/base/diameter_codec.erl8
-rw-r--r--lib/diameter/src/base/diameter_peer_fsm.erl5
-rw-r--r--lib/diameter/src/base/diameter_service.erl18
-rw-r--r--lib/diameter/test/diameter_event_SUITE.erl182
-rw-r--r--lib/diameter/test/diameter_traffic_SUITE.erl54
-rw-r--r--lib/diameter/test/modules.mk3
-rw-r--r--lib/diameter/vsn.mk4
-rw-r--r--lib/kernel/doc/src/application.xml9
-rw-r--r--lib/kernel/doc/src/error_handler.xml38
-rw-r--r--lib/kernel/doc/src/packages.xml208
-rw-r--r--lib/kernel/doc/src/ref_man.xml1
-rw-r--r--lib/kernel/src/application.erl16
-rw-r--r--lib/kernel/src/error_handler.erl53
-rw-r--r--lib/kernel/test/Makefile1
-rw-r--r--lib/kernel/test/application_SUITE.erl13
-rw-r--r--lib/kernel/test/error_handler_SUITE.erl68
-rw-r--r--lib/kernel/test/global_SUITE.erl35
-rw-r--r--lib/public_key/asn1/OTP-PUB-KEY.asn1config3
-rw-r--r--lib/public_key/doc/src/cert_records.xml45
-rw-r--r--lib/public_key/doc/src/introduction.xml20
-rw-r--r--lib/public_key/doc/src/part.xml8
-rw-r--r--lib/public_key/doc/src/public_key.xml164
-rw-r--r--lib/public_key/doc/src/public_key_records.xml12
-rw-r--r--lib/public_key/doc/src/using_public_key.xml8
-rw-r--r--lib/public_key/include/public_key.hrl19
-rw-r--r--lib/public_key/src/Makefile3
-rw-r--r--lib/public_key/src/pubkey_cert.erl228
-rw-r--r--lib/public_key/src/pubkey_crl.erl701
-rw-r--r--lib/public_key/src/pubkey_pem.erl12
-rw-r--r--lib/public_key/src/public_key.app.src1
-rw-r--r--lib/public_key/src/public_key.erl188
-rw-r--r--lib/public_key/test/erl_make_certs.erl7
-rw-r--r--lib/public_key/test/pbe_SUITE.erl105
-rw-r--r--lib/public_key/test/pkits_SUITE.erl1351
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/BadCRLIssuerNameCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/BadCRLSignatureCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/BadSignedCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/BadnotAfterDateCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/BadnotBeforeDateCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/BasicSelfIssuedCRLSigningKeyCACRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/BasicSelfIssuedCRLSigningKeyCRLCertCRL.pem15
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/BasicSelfIssuedNewKeyCACRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/BasicSelfIssuedOldKeyCACRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/BasicSelfIssuedOldKeySelfIssuedCertCRL.pem15
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/DSACACRL.pem7
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/DSAParametersInheritedCACRL.pem8
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/GeneralizedTimeCRLnextUpdateCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/GoodCACRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/GoodsubCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/GoodsubCAPanyPolicyMapping1to2CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/LongSerialNumberCACRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/Mapping1to2CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/MappingFromanyPolicyCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/MappingToanyPolicyCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/MissingbasicConstraintsCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/NameOrderCACRL.pem14
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/NegativeSerialNumberCACRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/NoPoliciesCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/NoissuingDistributionPointCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/OldCRLnextUpdateCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/P12Mapping1to3CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/P12Mapping1to3subCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/P12Mapping1to3subsubCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/P1Mapping1to234CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/P1Mapping1to234subCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/P1anyPolicyMapping1to2CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/PanyPolicyMapping1to2CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP1234CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP1234subCAP123CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP1234subsubCAP123P12CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP123CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP123subCAP12CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP123subsubCAP12P1CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP123subsubCAP2P2CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP123subsubsubCAP12P2P1CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP12CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP12subCAP1CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP12subsubCAP1P2CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP2subCA2CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP2subCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP3CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/RFC3280MandatoryAttributeTypesCACRL.pem14
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/RFC3280OptionalAttributeTypesCACRL.pem14
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/RevokedsubCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/RolloverfromPrintableStringtoUTF8StringCACRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/SeparateCertificateandCRLKeysCA2CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/SeparateCertificateandCRLKeysCRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/TrustAnchorRootCRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/TwoCRLsCABadCRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/TwoCRLsCAGoodCRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/UIDCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/UTF8StringCaseInsensitiveMatchCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/UTF8StringEncodedNamesCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/UnknownCRLEntryExtensionCACRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/UnknownCRLExtensionCACRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/WrongCRLCACRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/anyPolicyCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/basicConstraintsCriticalcAFalseCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/basicConstraintsNotCriticalCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/basicConstraintsNotCriticalcAFalseCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA1CRL.pem16
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA1deltaCRL.pem15
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA2CRL.pem15
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA2deltaCRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA3CRL.pem14
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA3deltaCRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLIndicatorNoBaseCACRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/distributionPoint1CACRL.pem16
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/distributionPoint2CACRL.pem14
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/indirectCRLCA1CRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/indirectCRLCA3CRL.pem14
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/indirectCRLCA3cRLIssuerCRL.pem15
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/indirectCRLCA4cRLIssuerCRL.pem15
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/indirectCRLCA5CRL.pem35
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy0CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy1CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy1subCA1CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy1subCA2CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy1subCAIAP5CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy1subsubCA2CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy5CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy5subCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy5subsubCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping0CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping0subCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P12CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P12subCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P12subCAIPM5CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P12subsubCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P12subsubCAIPM5CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P1CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P1subCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P1subsubCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping5CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping5subCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping5subsubCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping5subsubsubCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/keyUsageCriticalcRLSignFalseCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/keyUsageCriticalkeyCertSignFalseCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/keyUsageNotCriticalCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/keyUsageNotCriticalcRLSignFalseCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/keyUsageNotCriticalkeyCertSignFalseCACRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN1CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN1subCA1CRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN1subCA2CRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN1subCA3CRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN2CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN3CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN3subCA1CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN3subCA2CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN4CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN5CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDNS1CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDNS2CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsRFC822CA1CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsRFC822CA2CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsRFC822CA3CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsURI1CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsURI2CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/onlyContainsAttributeCertsCACRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/onlyContainsCACertsCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/onlyContainsUserCertsCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA1compromiseCRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA1otherreasonsCRL.pem13
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA2CRL1.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA2CRL2.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA3compromiseCRL.pem15
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA3otherreasonsCRL.pem15
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA4compromiseCRL.pem15
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA4otherreasonsCRL.pem15
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint0CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint0subCA2CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint0subCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint1CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint1subCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subCA0CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subCA1CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subCA4CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subsubCA00CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subsubCA11CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subsubCA41CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subsubsubCA11XCRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subsubsubCA41XCRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/pre2000CRLnextUpdateCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy0CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy0subCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy0subsubCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy0subsubsubCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy10CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy10subCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy10subsubCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy10subsubsubCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy2CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy2subCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy4CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy4subCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy4subsubCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy4subsubsubCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy5CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy5subCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy5subsubCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy5subsubsubCACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy7CACRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy7subCARE2CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy7subsubCARE2RE4CRL.pem12
-rw-r--r--lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy7subsubsubCARE2RE4CRL.pem12
-rw-r--r--lib/public_key/test/public_key_SUITE.erl283
-rw-r--r--lib/ssh/doc/src/ssh.xml3
-rw-r--r--lib/stdlib/src/erl_lint.erl72
-rw-r--r--lib/stdlib/test/Makefile1
-rw-r--r--lib/stdlib/test/erl_eval_SUITE.erl18
-rw-r--r--lib/stdlib/test/erl_eval_helper.erl28
-rw-r--r--lib/stdlib/test/erl_expand_records_SUITE.erl33
-rw-r--r--lib/stdlib/test/erl_lint_SUITE.erl22
-rw-r--r--lib/stdlib/test/escript_SUITE.erl17
-rw-r--r--lib/stdlib/test/escript_SUITE_data/emulator_flags_no_shebang10
-rw-r--r--lib/stdlib/test/shell_SUITE.erl17
-rw-r--r--lib/tools/test/cprof_SUITE.erl16
-rw-r--r--lib/tools/test/xref_SUITE.erl62
238 files changed, 5025 insertions, 2440 deletions
diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml
index 8c3b13951d..0345fab8e8 100644
--- a/lib/common_test/doc/src/notes.xml
+++ b/lib/common_test/doc/src/notes.xml
@@ -32,6 +32,122 @@
<file>notes.xml</file>
</header>
+<section><title>Common_Test 1.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Severe errors detected by <c>test_server</c> (e.g. if log
+ files directories cannot be created) will now be reported
+ to <c>common_test</c> and noted in the <c>common_test</c>
+ logs.</p>
+ <p>
+ Own Id: OTP-9769 Aux Id: kunagi-202 [113] </p>
+ </item>
+ <item>
+ <p>
+ If a busy test case generated lots of error messages,
+ cth_log_redirect:post_end_per_testcase would crash with a
+ timeout while waiting for the error logger to finish
+ handling all error reports. The default timer was 5
+ seconds. This has now been extended to 5 minutes.</p>
+ <p>
+ Own Id: OTP-10040 Aux Id: kunagi-173 [84] </p>
+ </item>
+ <item>
+ <p>
+ Some bugfixes in <c>ct_snmp:</c></p>
+ <p>
+ <list> <item> ct_snmp will now use the value of the
+ 'agent_vsns' config variable when setting the 'variables'
+ parameter to snmp application agent configuration.
+ Earlier this had to be done separately - i.e. the
+ supported versions had to be specified twice. </item>
+ <item> Snmp application failed to write notify.conf since
+ ct_snmp gave the notify type as a string instead of an
+ atom. This has been corrected. </item> </list></p>
+ <p>
+ Own Id: OTP-10432</p>
+ </item>
+ <item>
+ <p>
+ Some bugfixes in <c>ct_snmp</c>:</p>
+ <p>
+ <list> <item> Functions <c>register_users/2</c>,
+ <c>register_agents/2</c> and <c>register_usm_users/2</c>,
+ and the corresponding <c>unregister_*/1</c> functions
+ were not executable. These are corrected/rewritten.
+ </item> <item> Function <c>update_usm_users/2</c> is
+ removed, and an unregister function is added instead.
+ Update can now be done with unregister_usm_users and then
+ register_usm_users. </item> <item> Functions
+ <c>unregister_*/2</c> are added, so specific
+ users/agents/usm users can be unregistered. </item>
+ <item> Function <c>unload_mibs/1</c> is added for
+ completeness. </item> <item> Overriding configuration
+ files did not work, since the files were written in
+ priv_dir instead of in the configuration dir
+ (priv_dir/conf). This has been corrected. </item> <item>
+ Arguments to <c>register_usm_users/2</c> were faulty
+ documented. This has been corrected. </item> </list></p>
+ <p>
+ Own Id: OTP-10434 Aux Id: kunagi-264 [175] </p>
+ </item>
+ <item>
+ <p>
+ Faulty exported specs in common test has been corrected
+ to <c>ct_netconfc:hook_options/0</c> and
+ <c>inet:hostname/0</c></p>
+ <p>
+ Own Id: OTP-10601</p>
+ </item>
+ <item>
+ <p>
+ The netconf client in common_test did not adjust the
+ window after receiving data. Due to this, the client
+ stopped receiving data after a while. This has been
+ corrected.</p>
+ <p>
+ Own Id: OTP-10646</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Known Bugs and Problems</title>
+ <list>
+ <item>
+ <p>
+ The earlier undocumented cross cover feature for
+ accumulating cover data over multiple tests has now been
+ fixed and documented.</p>
+ <p>
+ Own Id: OTP-9870 Aux Id: kunagi-206 [117] </p>
+ </item>
+ <item>
+ <p>
+ CT drops error reason when groups/0 crashes.</p>
+ <p>
+ Own Id: OTP-10631 Aux Id: kunagi-345 [256] </p>
+ </item>
+ <item>
+ <p>
+ Problem opening sftp connection with ct_ssh.</p>
+ <p>
+ Own Id: OTP-10632 Aux Id: kunagi-346 [257] </p>
+ </item>
+ <item>
+ <p>
+ Event handler on a ct_master node causes hanging.</p>
+ <p>
+ Own Id: OTP-10634 Aux Id: kunagi-347 [258] </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Common_Test 1.6.3.1</title>
<section><title>Known Bugs and Problems</title>
diff --git a/lib/common_test/vsn.mk b/lib/common_test/vsn.mk
index f9bb22867e..c92fb2ca37 100644
--- a/lib/common_test/vsn.mk
+++ b/lib/common_test/vsn.mk
@@ -1 +1 @@
-COMMON_TEST_VSN = 1.6.3
+COMMON_TEST_VSN = 1.7
diff --git a/lib/compiler/doc/src/compile.xml b/lib/compiler/doc/src/compile.xml
index 27d750f929..ddaae2655d 100644
--- a/lib/compiler/doc/src/compile.xml
+++ b/lib/compiler/doc/src/compile.xml
@@ -816,6 +816,32 @@ pi() -> 3.1416.
</section>
<section>
+ <title>Inlining of list functions</title>
+ <p>The compiler can also inline a variety of list manipulation functions
+ from the stdlib's lists module.</p>
+
+ <p>This feature must be explicitly enabled with a compiler option or a
+ <c>-compile()</c> attribute in the source module.</p>
+
+ <p>To enable inlining of list functions, use the <c>inline_list_funcs</c>
+ option.</p>
+
+ <p>The following functions are inlined:</p>
+ <list type="bulleted">
+ <item><seealso marker="stdlib:lists#all/2">lists:all/2</seealso></item>
+ <item><seealso marker="stdlib:lists#any/2">lists:any/2</seealso></item>
+ <item><seealso marker="stdlib:lists#foreach/2">lists:foreach/2</seealso></item>
+ <item><seealso marker="stdlib:lists#map/2">lists:map/2</seealso></item>
+ <item><seealso marker="stdlib:lists#flatmap/2">lists:flatmap/2</seealso></item>
+ <item><seealso marker="stdlib:lists#filter/2">lists:filter/2</seealso></item>
+ <item><seealso marker="stdlib:lists#foldl/3">lists:foldl/3</seealso></item>
+ <item><seealso marker="stdlib:lists#foldr/3">lists:foldr/3</seealso></item>
+ <item><seealso marker="stdlib:lists#mapfoldl/3">lists:mapfoldl/3</seealso></item>
+ <item><seealso marker="stdlib:lists#mapfoldr/3">lists:mapfoldr/3</seealso></item>
+ </list>
+ </section>
+
+ <section>
<title>Parse Transformations</title>
<p>Parse transformations are used when a programmer wants to use
diff --git a/lib/compiler/src/Makefile b/lib/compiler/src/Makefile
index cbcbf79839..3229752be1 100644
--- a/lib/compiler/src/Makefile
+++ b/lib/compiler/src/Makefile
@@ -82,7 +82,6 @@ MODULES = \
sys_core_dsetel \
sys_core_fold \
sys_core_inline \
- sys_expand_pmod \
sys_pre_attributes \
sys_pre_expand \
v3_codegen \
diff --git a/lib/compiler/src/beam_dict.erl b/lib/compiler/src/beam_dict.erl
index 531968b3c8..ff6c7c11dc 100644
--- a/lib/compiler/src/beam_dict.erl
+++ b/lib/compiler/src/beam_dict.erl
@@ -138,7 +138,17 @@ string(Str, Dict) when is_list(Str) ->
-spec lambda(label(), non_neg_integer(), bdict()) ->
{non_neg_integer(), bdict()}.
-lambda(Lbl, NumFree, #asm{lambdas=Lambdas0}=Dict) ->
+lambda(Lbl, 0, #asm{lambdas=Lambdas0}=Dict) ->
+ case lists:keyfind(Lbl, 1, Lambdas0) of
+ {Lbl,{OldIndex,_,_,_,_}} ->
+ {OldIndex,Dict};
+ false ->
+ new_lambda(Lbl, 0, Dict)
+ end;
+lambda(Lbl, NumFree, Dict) ->
+ new_lambda(Lbl, NumFree, Dict).
+
+new_lambda(Lbl, NumFree, #asm{lambdas=Lambdas0}=Dict) ->
OldIndex = length(Lambdas0),
%% Set Index the same as OldIndex.
Index = OldIndex,
@@ -235,10 +245,12 @@ string_table(#asm{strings=Strings,string_offset=Size}) ->
-spec lambda_table(bdict()) -> {non_neg_integer(), [<<_:192>>]}.
-lambda_table(#asm{locals=Loc0,lambdas=Lambdas0}) ->
+lambda_table(#asm{exports=Ext0,locals=Loc0,lambdas=Lambdas0}) ->
Lambdas1 = sofs:relation(Lambdas0),
Loc = sofs:relation([{Lbl,{F,A}} || {F,A,Lbl} <- Loc0]),
- Lambdas2 = sofs:relative_product1(Lambdas1, Loc),
+ Ext = sofs:relation([{Lbl,{F,A}} || {F,A,Lbl} <- Ext0]),
+ All = sofs:union(Loc, Ext),
+ Lambdas2 = sofs:relative_product1(Lambdas1, All),
Lambdas = [<<F:32,A:32,Lbl:32,Index:32,NumFree:32,OldUniq:32>> ||
{{_,Lbl,Index,NumFree,OldUniq},{F,A}} <- sofs:to_external(Lambdas2)],
{length(Lambdas),Lambdas}.
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index 10e7f5e9ce..5f394f0b65 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -895,7 +895,6 @@ foldl_core_transforms(St, []) -> {ok,St}.
%%% Fetches the module name from a list of forms. The module attribute must
%%% be present.
-get_module([{attribute,_,module,{M,_As}} | _]) -> M;
get_module([{attribute,_,module,M} | _]) -> M;
get_module([_ | Rest]) ->
get_module(Rest).
@@ -907,11 +906,8 @@ add_default_base(St, Forms) ->
F = St#compile.filename,
case F of
"" ->
- M = case get_module(Forms) of
- PackageModule when is_list(PackageModule) -> last(PackageModule);
- M0 -> M0
- end,
- St#compile{base = atom_to_list(M)};
+ M = get_module(Forms),
+ St#compile{base=atom_to_list(M)};
_ ->
St
end.
diff --git a/lib/compiler/src/compiler.app.src b/lib/compiler/src/compiler.app.src
index 94c78e68f9..9a02121d8b 100644
--- a/lib/compiler/src/compiler.app.src
+++ b/lib/compiler/src/compiler.app.src
@@ -57,7 +57,6 @@
sys_core_dsetel,
sys_core_fold,
sys_core_inline,
- sys_expand_pmod,
sys_pre_attributes,
sys_pre_expand,
v3_codegen,
diff --git a/lib/compiler/src/core_lint.erl b/lib/compiler/src/core_lint.erl
index b513a8965c..21296a8b66 100644
--- a/lib/compiler/src/core_lint.erl
+++ b/lib/compiler/src/core_lint.erl
@@ -247,7 +247,8 @@ gbody(E, Def, Rt, St0) ->
false -> St1
end.
-gexpr(#c_var{name=N}, Def, _Rt, St) -> expr_var(N, Def, St);
+gexpr(#c_var{name=N}, Def, _Rt, St) when is_atom(N); is_integer(N) ->
+ expr_var(N, Def, St);
gexpr(#c_literal{}, _Def, _Rt, St) -> St;
gexpr(#c_cons{hd=H,tl=T}, Def, _Rt, St) ->
gexpr_list([H,T], Def, St);
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index 18fba7962b..f17b0bd130 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -686,11 +686,14 @@ call_1(#c_call{anno=Anno}, lists, all, [Arg1,Arg2], Sub) ->
C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
body=#c_case{arg=#c_apply{anno=Anno, op=F, args=[X]},
clauses = [CC1, CC2, CC3]}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=1}]},
body=#c_literal{val=true}},
- Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
+ Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=match_fail(Anno, Err2)},
+ body=match_fail([{function_name,{'lists^all',1}}|Anno], Err2)},
Fun = #c_fun{vars=[Xs],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
@@ -713,11 +716,14 @@ call_1(#c_call{anno=Anno}, lists, any, [Arg1,Arg2], Sub) ->
C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
body=#c_case{arg=#c_apply{anno=Anno, op=F, args=[X]},
clauses = [CC1, CC2, CC3]}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=1}]},
body=#c_literal{val=false}},
- Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
+ Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=match_fail(Anno, Err2)},
+ body=match_fail([{function_name,{'lists^any',1}}|Anno], Err2)},
Fun = #c_fun{vars=[Xs],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
@@ -733,11 +739,14 @@ call_1(#c_call{anno=Anno}, lists, foreach, [Arg1,Arg2], Sub) ->
C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
body=#c_seq{arg=#c_apply{anno=Anno, op=F, args=[X]},
body=#c_apply{anno=Anno, op=Loop, args=[Xs]}}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=1}]},
body=#c_literal{val=ok}},
- Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
+ Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=match_fail(Anno, Err)},
+ body=match_fail([{function_name,{'lists^foreach',1}}|Anno], Err)},
Fun = #c_fun{vars=[Xs],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
@@ -756,14 +765,18 @@ call_1(#c_call{anno=Anno}, lists, map, [Arg1,Arg2], Sub) ->
op=F,
args=[X]},
body=#c_cons{hd=H,
+ anno=[compiler_generated],
tl=#c_apply{anno=Anno,
op=Loop,
args=[Xs]}}}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=1}]},
body=#c_literal{val=[]}},
- Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
+ Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=match_fail(Anno, Err)},
+ body=match_fail([{function_name,{'lists^map',1}}|Anno], Err)},
Fun = #c_fun{vars=[Xs],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
@@ -780,18 +793,21 @@ call_1(#c_call{anno=Anno}, lists, flatmap, [Arg1,Arg2], Sub) ->
C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
body=#c_let{vars=[H],
arg=#c_apply{anno=Anno, op=F, args=[X]},
- body=#c_call{anno=Anno,
+ body=#c_call{anno=[compiler_generated|Anno],
module=#c_literal{val=erlang},
name=#c_literal{val='++'},
args=[H,
#c_apply{anno=Anno,
op=Loop,
args=[Xs]}]}}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=1}]},
body=#c_literal{val=[]}},
- Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
+ Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=match_fail(Anno, Err)},
+ body=match_fail([{function_name,{'lists^flatmap',1}}|Anno], Err)},
Fun = #c_fun{vars=[Xs],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
@@ -807,7 +823,7 @@ call_1(#c_call{anno=Anno}, lists, filter, [Arg1,Arg2], Sub) ->
B = #c_var{name='B'},
Err1 = #c_tuple{es=[#c_literal{val='case_clause'}, X]},
CC1 = #c_clause{pats=[#c_literal{val=true}], guard=#c_literal{val=true},
- body=#c_cons{hd=X, tl=Xs}},
+ body=#c_cons{anno=[compiler_generated], hd=X, tl=Xs}},
CC2 = #c_clause{pats=[#c_literal{val=false}], guard=#c_literal{val=true},
body=Xs},
CC3 = #c_clause{pats=[X], guard=#c_literal{val=true},
@@ -821,11 +837,14 @@ call_1(#c_call{anno=Anno}, lists, filter, [Arg1,Arg2], Sub) ->
op=Loop,
args=[Xs]},
body=Case}}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=1}]},
body=#c_literal{val=[]}},
- Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
+ Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=match_fail(Anno, Err2)},
+ body=match_fail([{function_name,{'lists^filter',1}}|Anno], Err2)},
Fun = #c_fun{vars=[Xs],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
@@ -845,10 +864,14 @@ call_1(#c_call{anno=Anno}, lists, foldl, [Arg1,Arg2,Arg3], Sub) ->
args=[Xs, #c_apply{anno=Anno,
op=F,
args=[X, A]}]}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true}, body=A},
- Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=2}]},
+ body=A},
+ Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, A, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=match_fail(Anno, Err)},
+ body=match_fail([{function_name,{'lists^foldl',2}}|Anno], Err)},
Fun = #c_fun{vars=[Xs, A],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
@@ -868,10 +891,14 @@ call_1(#c_call{anno=Anno}, lists, foldr, [Arg1,Arg2,Arg3], Sub) ->
args=[X, #c_apply{anno=Anno,
op=Loop,
args=[Xs, A]}]}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true}, body=A},
- Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=2}]},
+ body=A},
+ Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, A, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=match_fail(Anno, Err)},
+ body=match_fail([{function_name,{'lists^foldr',2}}|Anno], Err)},
Fun = #c_fun{vars=[Xs, A],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
@@ -901,7 +928,10 @@ call_1(#c_call{anno=Anno}, lists, mapfoldl, [Arg1,Arg2,Arg3], Sub) ->
op=Loop,
args=[Xs, Avar]},
#c_tuple{es=[Xs, Avar]},
- #c_tuple{es=[#c_cons{hd=X, tl=Xs}, Avar]})
+ #c_tuple{anno=[compiler_generated],
+ es=[#c_cons{anno=[compiler_generated],
+ hd=X, tl=Xs},
+ Avar]})
%%% Multiple-value version
%%% #c_let{vars=[Xs,A],
%%% %% The tuple here will be optimised
@@ -910,14 +940,18 @@ call_1(#c_call{anno=Anno}, lists, mapfoldl, [Arg1,Arg2,Arg3], Sub) ->
%%% body=#c_values{es=[#c_cons{hd=X, tl=Xs},
%%% A]}}
)},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=2}]},
%%% Tuple passing version
- body=#c_tuple{es=[#c_literal{val=[]}, Avar]}},
+ body=#c_tuple{anno=[compiler_generated],
+ es=[#c_literal{val=[]}, Avar]}},
%%% Multiple-value version
%%% body=#c_values{es=[#c_literal{val=[]}, A]}},
- Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
+ Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, Avar, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=match_fail(Anno, Err)},
+ body=match_fail([{function_name,{'lists^mapfoldl',2}}|Anno], Err)},
Fun = #c_fun{vars=[Xs, Avar],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
@@ -955,7 +989,9 @@ call_1(#c_call{anno=Anno}, lists, mapfoldr, [Arg1,Arg2,Arg3], Sub) ->
#c_tuple{es=[Xs, Avar]},
Match(#c_apply{anno=Anno, op=F, args=[X, Avar]},
#c_tuple{es=[X, Avar]},
- #c_tuple{es=[#c_cons{hd=X, tl=Xs}, Avar]}))
+ #c_tuple{anno=[compiler_generated],
+ es=[#c_cons{anno=[compiler_generated],
+ hd=X, tl=Xs}, Avar]}))
%%% Multiple-value version
%%% body=#c_let{vars=[Xs,A],
%%% %% The tuple will be optimised away
@@ -965,14 +1001,18 @@ call_1(#c_call{anno=Anno}, lists, mapfoldr, [Arg1,Arg2,Arg3], Sub) ->
%%% #c_values{es=[#c_cons{hd=X, tl=Xs},
%%% A]})}
},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=2}]},
%%% Tuple passing version
- body=#c_tuple{es=[#c_literal{val=[]}, Avar]}},
+ body=#c_tuple{anno=[compiler_generated],
+ es=[#c_literal{val=[]}, Avar]}},
%%% Multiple-value version
%%% body=#c_values{es=[#c_literal{val=[]}, A]}},
- Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
+ Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, Avar, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=match_fail(Anno, Err)},
+ body=match_fail([{function_name,{'lists^mapfoldr',2}}|Anno], Err)},
Fun = #c_fun{vars=[Xs, Avar],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
diff --git a/lib/compiler/src/sys_expand_pmod.erl b/lib/compiler/src/sys_expand_pmod.erl
deleted file mode 100644
index da644b4f0b..0000000000
--- a/lib/compiler/src/sys_expand_pmod.erl
+++ /dev/null
@@ -1,433 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
--module(sys_expand_pmod).
-
-%% Expand function definition forms of parameterized module. We assume
-%% all record definitions, imports, queries, etc., have been expanded
-%% away. Any calls on the form 'foo(...)' must be calls to local
-%% functions. Auto-generated functions (module_info,...) have not yet
-%% been added to the function definitions, but are listed in 'defined'
-%% and 'exports'. The automatic 'new/N' function is neither added to the
-%% definitions nor to the 'exports'/'defines' lists yet.
-
--export([forms/4]).
-
--record(pmod, {parameters, exports, defined, predef}).
-
-%% TODO: more abstract handling of predefined/static functions.
-
-forms(Fs0, Ps, Es0, Ds0) ->
- PreDef = [{module_info,0},{module_info,1}],
- forms(Fs0, Ps, Es0, Ds0, PreDef).
-
-forms(Fs0, Ps, Es0, Ds0, PreDef) ->
- St0 = #pmod{parameters=Ps,exports=Es0,defined=Ds0, predef=PreDef},
- {Fs1, St1} = forms(Fs0, St0),
- Es1 = update_function_names(Es0, St1),
- Ds1 = update_function_names(Ds0, St1),
- Fs2 = update_forms(Fs1, St1),
- {Fs2,Es1,Ds1}.
-
-%% This is extremely simplistic for now; all functions get an extra
-%% parameter, whether they need it or not, except for static functions.
-
-update_function_names(Es, St) ->
- [update_function_name(E, St) || E <- Es].
-
-update_function_name(E={F,A}, St) when F =/= new ->
- case ordsets:is_element(E, St#pmod.predef) of
- true -> E;
- false -> {F, A + 1}
- end;
-update_function_name(E, _St) ->
- E.
-
-update_forms([{function,L,N,A,Cs}|Fs],St) when N =/= new ->
- [{function,L,N,A+1,Cs}|update_forms(Fs,St)];
-update_forms([F|Fs],St) ->
- [F|update_forms(Fs,St)];
-update_forms([],_St) ->
- [].
-
-%% Process the program forms.
-
-forms([F0|Fs0],St0) ->
- {F1,St1} = form(F0,St0),
- {Fs1,St2} = forms(Fs0,St1),
- {[F1|Fs1],St2};
-forms([], St0) ->
- {[], St0}.
-
-%% Only function definitions are of interest here. State is not updated.
-form({function,Line,Name0,Arity0,Clauses0},St) when Name0 =/= new ->
- {Name,Arity,Clauses} = function(Name0, Arity0, Clauses0, St),
- {{function,Line,Name,Arity,Clauses},St};
-%% Pass anything else through
-form(F,St) -> {F,St}.
-
-function(Name, Arity, Clauses0, St) ->
- Clauses1 = clauses(Clauses0,St),
- {Name,Arity,Clauses1}.
-
-clauses([C|Cs],St) ->
- {clause,L,H,G,B} = clause(C,St),
- T = {tuple,L,[{var,L,V} || V <- ['_'|St#pmod.parameters]]},
- [{clause,L,H++[{match,L,T,{var,L,'THIS'}}],G,B}|clauses(Cs,St)];
-clauses([],_St) -> [].
-
-clause({clause,Line,H0,G0,B0},St) ->
- H1 = head(H0,St),
- G1 = guard(G0,St),
- B1 = exprs(B0,St),
- {clause,Line,H1,G1,B1}.
-
-head(Ps,St) -> patterns(Ps,St).
-
-patterns([P0|Ps],St) ->
- P1 = pattern(P0,St),
- [P1|patterns(Ps,St)];
-patterns([],_St) -> [].
-
-string_to_conses([], _Line, Tail) ->
- Tail;
-string_to_conses([E|Rest], Line, Tail) ->
- {cons, Line, {integer, Line, E}, string_to_conses(Rest, Line, Tail)}.
-
-pattern({var,_Line,_V}=Var,_St) -> Var;
-pattern({match,Line,L0,R0},St) ->
- L1 = pattern(L0,St),
- R1 = pattern(R0,St),
- {match,Line,L1,R1};
-pattern({integer,_Line,_I}=Integer,_St) -> Integer;
-pattern({char,_Line,_C}=Char,_St) -> Char;
-pattern({float,_Line,_F}=Float,_St) -> Float;
-pattern({atom,_Line,_A}=Atom,_St) -> Atom;
-pattern({string,_Line,_S}=String,_St) -> String;
-pattern({nil,_Line}=Nil,_St) -> Nil;
-pattern({cons,Line,H0,T0},St) ->
- H1 = pattern(H0,St),
- T1 = pattern(T0,St),
- {cons,Line,H1,T1};
-pattern({tuple,Line,Ps0},St) ->
- Ps1 = pattern_list(Ps0,St),
- {tuple,Line,Ps1};
-pattern({bin,Line,Fs},St) ->
- Fs2 = pattern_grp(Fs,St),
- {bin,Line,Fs2};
-pattern({op,_Line,'++',{nil,_},R},St) ->
- pattern(R,St);
-pattern({op,_Line,'++',{cons,Li,{char,_C2,_I}=Char,T},R},St) ->
- pattern({cons,Li,Char,{op,Li,'++',T,R}},St);
-pattern({op,_Line,'++',{cons,Li,{integer,_L2,_I}=Integer,T},R},St) ->
- pattern({cons,Li,Integer,{op,Li,'++',T,R}},St);
-pattern({op,_Line,'++',{string,Li,L},R},St) ->
- pattern(string_to_conses(L, Li, R),St);
-pattern({op,_Line,_Op,_A}=Op4,_St) -> Op4;
-pattern({op,_Line,_Op,_L,_R}=Op5,_St) -> Op5.
-
-pattern_grp([{bin_element,L1,E1,S1,T1} | Fs],St) ->
- S2 = case S1 of
- default ->
- default;
- _ ->
- expr(S1,St)
- end,
- T2 = case T1 of
- default ->
- default;
- _ ->
- bit_types(T1)
- end,
- [{bin_element,L1,expr(E1,St),S2,T2} | pattern_grp(Fs,St)];
-pattern_grp([],_St) ->
- [].
-
-bit_types([]) ->
- [];
-bit_types([Atom | Rest]) when is_atom(Atom) ->
- [Atom | bit_types(Rest)];
-bit_types([{Atom, Integer} | Rest]) when is_atom(Atom), is_integer(Integer) ->
- [{Atom, Integer} | bit_types(Rest)].
-
-pattern_list([P0|Ps],St) ->
- P1 = pattern(P0,St),
- [P1|pattern_list(Ps,St)];
-pattern_list([],_St) -> [].
-
-guard([G0|Gs],St) when is_list(G0) ->
- [guard0(G0,St) | guard(Gs,St)];
-guard(L,St) ->
- guard0(L,St).
-
-guard0([G0|Gs],St) ->
- G1 = guard_test(G0,St),
- [G1|guard0(Gs,St)];
-guard0([],_St) -> [].
-
-guard_test(Expr={call,Line,{atom,La,F},As0},St) ->
- case erl_internal:type_test(F, length(As0)) of
- true ->
- As1 = gexpr_list(As0,St),
- {call,Line,{atom,La,F},As1};
- _ ->
- gexpr(Expr,St)
- end;
-guard_test(Any,St) ->
- gexpr(Any,St).
-
-gexpr({var,_L,_V}=Var,_St) -> Var;
-% %% alternative implementation of accessing module parameters
-% case index(V,St#pmod.parameters) of
-% N when N > 0 ->
-% {call,L,{remote,L,{atom,L,erlang},{atom,L,element}},
-% [{integer,L,N+1},{var,L,'THIS'}]};
-% _ ->
-% Var
-% end;
-gexpr({integer,_Line,_I}=Integer,_St) -> Integer;
-gexpr({char,_Line,_C}=Char,_St) -> Char;
-gexpr({float,_Line,_F}=Float,_St) -> Float;
-gexpr({atom,_Line,_A}=Atom,_St) -> Atom;
-gexpr({string,_Line,_S}=String,_St) -> String;
-gexpr({nil,_Line}=Nil,_St) -> Nil;
-gexpr({cons,Line,H0,T0},St) ->
- H1 = gexpr(H0,St),
- T1 = gexpr(T0,St),
- {cons,Line,H1,T1};
-gexpr({tuple,Line,Es0},St) ->
- Es1 = gexpr_list(Es0,St),
- {tuple,Line,Es1};
-gexpr({call,Line,{atom,_La,F}=Atom,As0},St) ->
- true = erl_internal:guard_bif(F, length(As0)),
- As1 = gexpr_list(As0,St),
- {call,Line,Atom,As1};
-%% Pre-expansion generated calls to erlang:is_record/3 must also be handled
-gexpr({call,Line,{remote,La,{atom,Lb,erlang},{atom,Lc,is_record}},[_,_,_]=As0},St) ->
- As1 = gexpr_list(As0,St),
- {call,Line,{remote,La,{atom,Lb,erlang},{atom,Lc,is_record}},As1};
-%% Guard BIFs can be remote, but only in the module erlang...
-gexpr({call,Line,{remote,La,{atom,Lb,erlang},{atom,Lc,F}},As0},St) ->
- A = length(As0),
- true =
- erl_internal:guard_bif(F, A) orelse erl_internal:arith_op(F, A) orelse
- erl_internal:comp_op(F, A) orelse erl_internal:bool_op(F, A),
- As1 = gexpr_list(As0,St),
- {call,Line,{remote,La,{atom,Lb,erlang},{atom,Lc,F}},As1};
-%% Unfortunately, writing calls as {M,F}(...) is also allowed.
-gexpr({call,Line,{tuple,La,[{atom,Lb,erlang},{atom,Lc,F}]},As0},St) ->
- A = length(As0),
- true =
- erl_internal:guard_bif(F, A) orelse erl_internal:arith_op(F, A) orelse
- erl_internal:comp_op(F, A) orelse erl_internal:bool_op(F, A),
- As1 = gexpr_list(As0,St),
- {call,Line,{tuple,La,[{atom,Lb,erlang},{atom,Lc,F}]},As1};
-gexpr({bin,Line,Fs},St) ->
- Fs2 = pattern_grp(Fs,St),
- {bin,Line,Fs2};
-gexpr({op,Line,Op,A0},St) ->
- true = erl_internal:arith_op(Op, 1) orelse erl_internal:bool_op(Op, 1),
- A1 = gexpr(A0,St),
- {op,Line,Op,A1};
-gexpr({op,Line,Op,L0,R0},St) ->
- true =
- Op =:= 'andalso' orelse Op =:= 'orelse' orelse
- erl_internal:arith_op(Op, 2) orelse
- erl_internal:bool_op(Op, 2) orelse erl_internal:comp_op(Op, 2),
- L1 = gexpr(L0,St),
- R1 = gexpr(R0,St),
- {op,Line,Op,L1,R1}.
-
-gexpr_list([E0|Es],St) ->
- E1 = gexpr(E0,St),
- [E1|gexpr_list(Es,St)];
-gexpr_list([],_St) -> [].
-
-exprs([E0|Es],St) ->
- E1 = expr(E0,St),
- [E1|exprs(Es,St)];
-exprs([],_St) -> [].
-
-expr({var,_L,_V}=Var,_St) ->
- Var;
-% case index(V,St#pmod.parameters) of
-% N when N > 0 ->
-% {call,L,{remote,L,{atom,L,erlang},{atom,L,element}},
-% [{integer,L,N+1},{var,L,'THIS'}]};
-% _ ->
-% Var
-% end;
-expr({integer,_Line,_I}=Integer,_St) -> Integer;
-expr({float,_Line,_F}=Float,_St) -> Float;
-expr({atom,_Line,_A}=Atom,_St) -> Atom;
-expr({string,_Line,_S}=String,_St) -> String;
-expr({char,_Line,_C}=Char,_St) -> Char;
-expr({nil,_Line}=Nil,_St) -> Nil;
-expr({cons,Line,H0,T0},St) ->
- H1 = expr(H0,St),
- T1 = expr(T0,St),
- {cons,Line,H1,T1};
-expr({lc,Line,E0,Qs0},St) ->
- Qs1 = lc_bc_quals(Qs0,St),
- E1 = expr(E0,St),
- {lc,Line,E1,Qs1};
-expr({bc,Line,E0,Qs0},St) ->
- Qs1 = lc_bc_quals(Qs0,St),
- E1 = expr(E0,St),
- {bc,Line,E1,Qs1};
-expr({tuple,Line,Es0},St) ->
- Es1 = expr_list(Es0,St),
- {tuple,Line,Es1};
-expr({block,Line,Es0},St) ->
- Es1 = exprs(Es0,St),
- {block,Line,Es1};
-expr({'if',Line,Cs0},St) ->
- Cs1 = icr_clauses(Cs0,St),
- {'if',Line,Cs1};
-expr({'case',Line,E0,Cs0},St) ->
- E1 = expr(E0,St),
- Cs1 = icr_clauses(Cs0,St),
- {'case',Line,E1,Cs1};
-expr({'receive',Line,Cs0},St) ->
- Cs1 = icr_clauses(Cs0,St),
- {'receive',Line,Cs1};
-expr({'receive',Line,Cs0,To0,ToEs0},St) ->
- To1 = expr(To0,St),
- ToEs1 = exprs(ToEs0,St),
- Cs1 = icr_clauses(Cs0,St),
- {'receive',Line,Cs1,To1,ToEs1};
-expr({'try',Line,Es0,Scs0,Ccs0,As0},St) ->
- Es1 = exprs(Es0,St),
- Scs1 = icr_clauses(Scs0,St),
- Ccs1 = icr_clauses(Ccs0,St),
- As1 = exprs(As0,St),
- {'try',Line,Es1,Scs1,Ccs1,As1};
-expr({'fun',_,{function,_,_,_}}=ExtFun,_St) ->
- ExtFun;
-expr({'fun',Line,Body,Info},St) ->
- case Body of
- {clauses,Cs0} ->
- Cs1 = fun_clauses(Cs0,St),
- {'fun',Line,{clauses,Cs1},Info};
- {function,F,A} = Function ->
- {F1,A1} = update_function_name({F,A},St),
- if A1 =:= A ->
- {'fun',Line,Function,Info};
- true ->
- %% Must rewrite local fun-name to a fun that does a
- %% call with the extra THIS parameter.
- As = make_vars(A, Line),
- As1 = As ++ [{var,Line,'THIS'}],
- Call = {call,Line,{atom,Line,F1},As1},
- Cs = [{clause,Line,As,[],[Call]}],
- {'fun',Line,{clauses,Cs},Info}
- end;
- {function,_M,_F,_A} = Fun4 -> %This is an error in lint!
- {'fun',Line,Fun4,Info}
- end;
-expr({call,Lc,{atom,_,instance}=Name,As0},St) ->
- %% All local functions 'instance(...)' are static by definition,
- %% so they do not take a 'THIS' argument when called
- As1 = expr_list(As0,St),
- {call,Lc,Name,As1};
-expr({call,Lc,{atom,_,new}=Name,As0},St) ->
- %% All local functions 'new(...)' are static by definition,
- %% so they do not take a 'THIS' argument when called
- As1 = expr_list(As0,St),
- {call,Lc,Name,As1};
-expr({call,Lc,{atom,_,module_info}=Name,As0},St)
- when length(As0) =:= 0; length(As0) =:= 1 ->
- %% The module_info/0 and module_info/1 functions are also static.
- As1 = expr_list(As0,St),
- {call,Lc,Name,As1};
-expr({call,Lc,{atom,_Lf,_F}=Atom,As0},St) ->
- %% Local function call - needs THIS parameter.
- As1 = expr_list(As0,St),
- {call,Lc,Atom,As1 ++ [{var,0,'THIS'}]};
-expr({call,Line,F0,As0},St) ->
- %% Other function call
- F1 = expr(F0,St),
- As1 = expr_list(As0,St),
- {call,Line,F1,As1};
-expr({'catch',Line,E0},St) ->
- E1 = expr(E0,St),
- {'catch',Line,E1};
-expr({match,Line,P0,E0},St) ->
- E1 = expr(E0,St),
- P1 = pattern(P0,St),
- {match,Line,P1,E1};
-expr({bin,Line,Fs},St) ->
- Fs2 = pattern_grp(Fs,St),
- {bin,Line,Fs2};
-expr({op,Line,Op,A0},St) ->
- A1 = expr(A0,St),
- {op,Line,Op,A1};
-expr({op,Line,Op,L0,R0},St) ->
- L1 = expr(L0,St),
- R1 = expr(R0,St),
- {op,Line,Op,L1,R1};
-%% The following are not allowed to occur anywhere!
-expr({remote,Line,M0,F0},St) ->
- M1 = expr(M0,St),
- F1 = expr(F0,St),
- {remote,Line,M1,F1}.
-
-expr_list([E0|Es],St) ->
- E1 = expr(E0,St),
- [E1|expr_list(Es,St)];
-expr_list([],_St) -> [].
-
-icr_clauses([C0|Cs],St) ->
- C1 = clause(C0,St),
- [C1|icr_clauses(Cs,St)];
-icr_clauses([],_St) -> [].
-
-lc_bc_quals([{generate,Line,P0,E0}|Qs],St) ->
- E1 = expr(E0,St),
- P1 = pattern(P0,St),
- [{generate,Line,P1,E1}|lc_bc_quals(Qs,St)];
-lc_bc_quals([{b_generate,Line,P0,E0}|Qs],St) ->
- E1 = expr(E0,St),
- P1 = pattern(P0,St),
- [{b_generate,Line,P1,E1}|lc_bc_quals(Qs,St)];
-lc_bc_quals([E0|Qs],St) ->
- E1 = expr(E0,St),
- [E1|lc_bc_quals(Qs,St)];
-lc_bc_quals([],_St) -> [].
-
-fun_clauses([C0|Cs],St) ->
- C1 = clause(C0,St),
- [C1|fun_clauses(Cs,St)];
-fun_clauses([],_St) -> [].
-
-%% %% Return index from 1 upwards, or 0 if not in the list.
-%%
-%% index(X,Ys) -> index(X,Ys,1).
-%%
-%% index(X,[X|Ys],A) -> A;
-%% index(X,[Y|Ys],A) -> index(X,Ys,A+1);
-%% index(X,[],A) -> 0.
-
-make_vars(N, L) ->
- make_vars(1, N, L).
-
-make_vars(N, M, L) when N =< M ->
- V = list_to_atom("X"++integer_to_list(N)),
- [{var,L,V} | make_vars(N + 1, M, L)];
-make_vars(_, _, _) ->
- [].
diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl
index a8c69c3cb1..7d918a55ed 100644
--- a/lib/compiler/src/sys_pre_expand.erl
+++ b/lib/compiler/src/sys_pre_expand.erl
@@ -28,13 +28,12 @@
%% Main entry point.
-export([module/2]).
--import(ordsets, [from_list/1,add_element/2,union/2]).
+-import(ordsets, [from_list/1,union/2]).
-import(lists, [member/2,foldl/3,foldr/3]).
-include("../include/erl_bits.hrl").
-record(expand, {module=[], %Module name
- parameters=undefined, %Module parameters
exports=[], %Exports
imports=[], %Imports
compile=[], %Compile flags
@@ -74,88 +73,20 @@ module(Fs0, Opts0) ->
},
%% Expand the functions.
{Tfs,St1} = forms(Fs, define_functions(Fs, St0)),
- {Efs,St2} = expand_pmod(Tfs, St1),
%% Get the correct list of exported functions.
- Exports = case member(export_all, St2#expand.compile) of
- true -> gb_sets:to_list(St2#expand.defined);
- false -> St2#expand.exports
+ Exports = case member(export_all, St1#expand.compile) of
+ true -> gb_sets:to_list(St1#expand.defined);
+ false -> St1#expand.exports
end,
%% Generate all functions from stored info.
- {Ats,St3} = module_attrs(St2#expand{exports = Exports}),
+ {Ats,St3} = module_attrs(St1#expand{exports = Exports}),
{Mfs,St4} = module_predef_funcs(St3),
- {St4#expand.module, St4#expand.exports, Ats ++ Efs ++ Mfs,
+ {St4#expand.module, St4#expand.exports, Ats ++ Tfs ++ Mfs,
St4#expand.compile}.
compiler_options(Forms) ->
lists:flatten([C || {attribute,_,compile,C} <- Forms]).
-expand_pmod(Fs0, St0) ->
- case St0#expand.parameters of
- undefined ->
- {Fs0,St0};
- Ps0 ->
- Base = get_base(St0#expand.attributes),
- Ps = if is_atom(Base) ->
- ['BASE' | Ps0];
- true ->
- Ps0
- end,
- Def = gb_sets:to_list(St0#expand.defined),
- {Fs1,Xs,Ds} = sys_expand_pmod:forms(Fs0, Ps,
- St0#expand.exports,
- Def),
- St1 = St0#expand{exports=Xs,defined=gb_sets:from_list(Ds)},
- {Fs2,St2} = add_instance(Ps, Fs1, St1),
- {Fs3,St3} = ensure_new(Base, Ps0, Fs2, St2),
- {Fs3,St3#expand{attributes = [{abstract, 0, [true]}
- | St3#expand.attributes]}}
- end.
-
-get_base(As) ->
- case lists:keyfind(extends, 1, As) of
- {extends,_,[Base]} when is_atom(Base) ->
- Base;
- _ ->
- []
- end.
-
-ensure_new(Base, Ps, Fs, St) ->
- case has_new(Fs) of
- true ->
- {Fs, St};
- false ->
- add_new(Base, Ps, Fs, St)
- end.
-
-has_new([{function,_L,new,_A,_Cs} | _Fs]) ->
- true;
-has_new([_ | Fs]) ->
- has_new(Fs);
-has_new([]) ->
- false.
-
-add_new(Base, Ps, Fs, St) ->
- Vs = [{var,0,V} || V <- Ps],
- As = if is_atom(Base) ->
- [{call,0,{remote,0,{atom,0,Base},{atom,0,new}},Vs} | Vs];
- true ->
- Vs
- end,
- Body = [{call,0,{atom,0,instance},As}],
- add_func(new, Vs, Body, Fs, St).
-
-add_instance(Ps, Fs, St) ->
- Vs = [{var,0,V} || V <- Ps],
- AbsMod = [{tuple,0,[{atom,0,St#expand.module}|Vs]}],
- add_func(instance, Vs, AbsMod, Fs, St).
-
-add_func(Name, Args, Body, Fs, St) ->
- A = length(Args),
- F = {function,0,Name,A,[{clause,0,Args,[],Body}]},
- NA = {Name,A},
- {[F|Fs],St#expand{exports=add_element(NA, St#expand.exports),
- defined=gb_sets:add_element(NA, St#expand.defined)}}.
-
%% define_function(Form, State) -> State.
%% Add function to defined if form is a function.
@@ -235,10 +166,6 @@ forms([], St) -> {[],St}.
%% attribute(Attribute, Value, Line, State) -> State'.
%% Process an attribute, this just affects the state.
-attribute(module, {Module, As}, _L, St) ->
- true = is_atom(Module),
- St#expand{module=Module,
- parameters=As};
attribute(module, Module, _L, St) ->
true = is_atom(Module),
St#expand{module=Module};
diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl
index 8ef71e1346..b1bff47f69 100644
--- a/lib/compiler/src/v3_kernel.erl
+++ b/lib/compiler/src/v3_kernel.erl
@@ -235,16 +235,8 @@ gexpr_test_add(Ke, St0) ->
%% expr(Cexpr, Sub, State) -> {Kexpr,[PreKexpr],State}.
%% Convert a Core expression, flattening it at the same time.
-expr(#c_var{anno=A,name={_Name,Arity}}=Fname, Sub, St) ->
- %% A local in an expression.
- %% For now, these are wrapped into a fun by reverse
- %% etha-conversion, but really, there should be exactly one
- %% such "lambda function" for each escaping local name,
- %% instead of one for each occurrence as done now.
- Vs = [#c_var{name=list_to_atom("V" ++ integer_to_list(V))} ||
- V <- integers(1, Arity)],
- Fun = #c_fun{anno=A,vars=Vs,body=#c_apply{anno=A,op=Fname,args=Vs}},
- expr(Fun, Sub, St);
+expr(#c_var{anno=A,name={Name,Arity}}, Sub, St) ->
+ {#k_local{anno=A,name=get_fsub(Name, Arity, Sub),arity=Arity},[],St};
expr(#c_var{anno=A,name=V}, Sub, St) ->
{#k_var{anno=A,name=get_vsub(V, Sub)},[],St};
expr(#c_literal{anno=A,val=V}, _Sub, St) ->
@@ -1663,6 +1655,19 @@ uexpr(#ifun{anno=A,vars=Vs,body=B0}, {break,Rs}, St0) ->
#k_int{val=Index},#k_int{val=Uniq}|Fvs],
ret=Rs},
Free,add_local_function(Fun, St)};
+uexpr(#k_local{anno=A,name=Name,arity=Arity}, {break,Rs}, St) ->
+ Fs = get_free(Name, Arity, St),
+ FsCount = length(Fs),
+ Free = lit_list_vars(Fs),
+ %% Set dummy values for Index and Uniq -- the real values will
+ %% be assigned by beam_asm.
+ Index = Uniq = 0,
+ Bif = #k_bif{anno=#k{us=Free,ns=lit_list_vars(Rs),a=A},
+ op=#k_internal{name=make_fun,arity=FsCount+3},
+ args=[#k_atom{val=Name},#k_int{val=FsCount+Arity},
+ #k_int{val=Index},#k_int{val=Uniq}|Fs],
+ ret=Rs},
+ {Bif,Free,St};
uexpr(Lit, {break,Rs0}, St0) ->
%% Transform literals to puts here.
%%ok = io:fwrite("uexpr ~w:~p~n", [?LINE,Lit]),
@@ -1843,12 +1848,6 @@ make_list(Es) ->
#c_cons{hd=E,tl=Acc}
end, #c_literal{val=[]}, Es).
-%% List of integers in interval [N,M]. Empty list if N > M.
-
-integers(N, M) when N =< M ->
- [N|integers(N + 1, M)];
-integers(_, _) -> [].
-
%% is_in_guard(State) -> true|false.
is_in_guard(#kern{guard_refc=Refc}) ->
diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile
index 3b065ec3b9..b9c5be09ce 100644
--- a/lib/compiler/test/Makefile
+++ b/lib/compiler/test/Makefile
@@ -29,7 +29,6 @@ MODULES= \
match_SUITE \
misc_SUITE \
num_bif_SUITE \
- pmod_SUITE \
receive_SUITE \
record_SUITE \
trycatch_SUITE \
diff --git a/lib/compiler/test/inline_SUITE.erl b/lib/compiler/test/inline_SUITE.erl
index e2eb6a0dec..6dc7548437 100644
--- a/lib/compiler/test/inline_SUITE.erl
+++ b/lib/compiler/test/inline_SUITE.erl
@@ -258,6 +258,49 @@ lists(Config) when is_list(Config) ->
%% Cleanup.
erase(?MODULE),
+
+ {'EXIT',{function_clause,[{?MODULE,_,[_,not_a_list],_}|_]}} =
+ (catch lists:map(fun (X) -> X end, not_a_list)),
+ {'EXIT',{function_clause,[{?MODULE,_,[_,not_a_list],_}|_]}} =
+ (catch lists:flatmap(fun (X) -> X end, not_a_list)),
+ {'EXIT',{function_clause,[{?MODULE,_,[_,not_a_list],_}|_]}} =
+ (catch lists:foreach(fun (X) -> X end, not_a_list)),
+ {'EXIT',{function_clause,[{?MODULE,_,[_,not_a_list],_}|_]}} =
+ (catch lists:filter(fun (_) -> true end, not_a_list)),
+ {'EXIT',{function_clause,[{?MODULE,_,[_,not_a_list],_}|_]}} =
+ (catch lists:any(fun (_) -> false end, not_a_list)),
+ {'EXIT',{function_clause,[{?MODULE,_,[_,not_a_list],_}|_]}} =
+ (catch lists:all(fun (_) -> true end, not_a_list)),
+ {'EXIT',{function_clause,[{?MODULE,_,[_,acc,not_a_list],_}|_]}} =
+ (catch lists:foldl(fun (X, Acc) -> {X,Acc} end, acc, not_a_list)),
+ {'EXIT',{function_clause,[{?MODULE,_,[_,acc,not_a_list],_}|_]}} =
+ (catch lists:foldr(fun (X, Acc) -> {X,Acc} end, acc, not_a_list)),
+ {'EXIT',{function_clause,[{?MODULE,_,[_,acc,not_a_list],_}|_]}} =
+ (catch lists:mapfoldl(fun (X, Acc) -> {X,Acc} end, acc, not_a_list)),
+ {'EXIT',{function_clause,[{?MODULE,_,[_,acc,not_a_list],_}|_]}} =
+ (catch lists:mapfoldr(fun (X, Acc) -> {X,Acc} end, acc, not_a_list)),
+
+ {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,[]],_}|_]}} =
+ (catch lists:map(not_a_function, [])),
+ {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,[]],_}|_]}} =
+ (catch lists:flatmap(not_a_function, [])),
+ {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,[]],_}|_]}} =
+ (catch lists:foreach(not_a_function, [])),
+ {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,[]],_}|_]}} =
+ (catch lists:filter(not_a_function, [])),
+ {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,[]],_}|_]}} =
+ (catch lists:any(not_a_function, [])),
+ {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,[]],_}|_]}} =
+ (catch lists:all(not_a_function, [])),
+ {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,acc,[]],_}|_]}} =
+ (catch lists:foldl(not_a_function, acc, [])),
+ {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,acc,[]],_}|_]}} =
+ (catch lists:foldr(not_a_function, acc, [])),
+ {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,acc,[]],_}|_]}} =
+ (catch lists:mapfoldl(not_a_function, acc, [])),
+ {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,acc,[]],_}|_]}} =
+ (catch lists:mapfoldr(not_a_function, acc, [])),
+
ok.
my_apply(M, F, A, Init) ->
diff --git a/lib/compiler/test/pmod_SUITE.erl b/lib/compiler/test/pmod_SUITE.erl
deleted file mode 100644
index 5dd09a7245..0000000000
--- a/lib/compiler/test/pmod_SUITE.erl
+++ /dev/null
@@ -1,121 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
--module(pmod_SUITE).
-
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,end_per_testcase/2,
- basic/1, otp_8447/1]).
-
--include_lib("test_server/include/test_server.hrl").
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- test_lib:recompile(?MODULE),
- [basic, otp_8447].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
- Dog = test_server:timetrap(?t:minutes(1)),
- [{watchdog,Dog}|Config].
-
-end_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
- ok.
-
-basic(Config) when is_list(Config) ->
- ?line basic_1(Config, []),
- ?line basic_1(Config, [inline]),
- ?line basic_1(Config, [{inline,500},inline]),
- ok.
-
-basic_1(Config, Opts) ->
- io:format("Options: ~p\n", [Opts]),
- ?line ok = compile_load(pmod_basic, Config, Opts),
-
- ?line Prop1 = pmod_basic:new([{a,xb},{b,true},{c,false}]),
- ?line Prop2 = pmod_basic:new([{y,zz}]),
- ?line io:format("Prop1 = ~p\n", [Prop1]),
- ?line io:format("Prop2 = ~p\n", [Prop2]),
-
- ?line {a,xb} = Prop1:lookup(a),
- ?line none = Prop1:lookup(glurf),
- ?line false = Prop1:or_props([]),
- ?line true = Prop1:or_props([b,c]),
- ?line true = Prop1:or_props([b,d]),
- ?line false = Prop1:or_props([d]),
-
- ?line none = Prop2:lookup(kalle),
- ?line {y,zz} = Prop2:lookup(y),
- ?line {a,xb} = Prop1:lookup(a),
-
- ?line Prop3 = Prop1:prepend({blurf,true}),
- ?line io:format("Prop3 = ~p\n", [Prop3]),
- ?line {blurf,true} = Prop3:lookup(blurf),
-
- Prop4 = Prop3:append(42),
- ?line io:format("Prop4 = ~p\n", [Prop4]),
- ?line {42,5} = Prop4:stupid_sum(),
-
- %% Some record guards.
- ?line ok = Prop4:bar({s,0}),
- ?line ok = Prop4:bar_bar({s,blurf}),
- ?line error = Prop4:bar_bar({s,a,b}),
- ?line error = Prop4:bar_bar([]),
-
- %% Call from a fun.
- Fun = fun(Arg) -> Prop4:bar(Arg) end,
- ?line ok = Fun({s,0}),
-
- [{y,[1,2]},{x,[5,19]}] = Prop4:collapse([{y,[2,1]},{x,[19,5]}]),
- ok.
-
-otp_8447(Config) when is_list(Config) ->
- ?line P = pmod_basic:new(foo),
- ?line [0,0,1,1,1,0,0,1] = P:bc1(),
- ?line <<10:4>> = P:bc2(),
- ok.
-
-compile_load(Module, Conf, Opts) ->
- ?line Dir = ?config(data_dir,Conf),
- ?line Src = filename:join(Dir, atom_to_list(Module)),
- ?line Out = ?config(priv_dir,Conf),
- ?line CompRc = compile:file(Src, [report,{outdir,Out}|Opts]),
- ?line {ok,Module} = CompRc,
- ?line code:purge(Module),
- ?line {module,Module} =
- code:load_abs(filename:join(Out, atom_to_list(Module))),
- ok.
diff --git a/lib/compiler/test/pmod_SUITE_data/pmod_basic.erl b/lib/compiler/test/pmod_SUITE_data/pmod_basic.erl
deleted file mode 100644
index 19cce452dc..0000000000
--- a/lib/compiler/test/pmod_SUITE_data/pmod_basic.erl
+++ /dev/null
@@ -1,83 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
--module(pmod_basic, [Props]).
-
--export([lookup/1,or_props/1,prepend/1,append/1,stupid_sum/0]).
--export([bar/1,bar_bar/1]).
--export([bc1/0, bc2/0]).
--export([collapse/1]).
-
-lookup(Key) ->
- proplists:lookup(Key, Props).
-
-or_props(Keys) ->
- Res = or_props_1(Keys, false),
- true = is_bool(Res), %is_bool/1 does not use Props.
- Res.
-
-prepend(Term) ->
- new([Term|Props]).
-
-append(Term) ->
- pmod_basic:new(Props++[Term]).
-
-or_props_1([K|Ks], Acc) ->
- or_props_1(Ks, proplists:get_bool(K, Props) or Acc);
-or_props_1([], Acc) -> Acc.
-
-is_bool(true) -> true;
-is_bool(false) -> true;
-is_bool(_) -> false.
-
-stupid_sum() ->
- put(counter, 0),
- Res = stupid_sum_1(Props, 0),
- {Res,get(counter)}.
-
-stupid_sum_1([H|T], Sum0) ->
- try add(Sum0, H) of
- Sum -> stupid_sum_1(T, Sum)
- catch
- error:_ -> stupid_sum_1(T, Sum0)
- after
- bump()
- end;
-stupid_sum_1([], Sum) -> Sum.
-
-bump() ->
- put(counter, get(counter)+1).
-
-add(A, B) ->
- A+B.
-
--record(s, {a}).
-
-bar(S) when S#s.a == 0 -> ok.
-
-bar_bar(S) when is_record(S, s) -> ok;
-bar_bar(_) -> error.
-
-bc1() ->
- [A || <<A:1>> <= <<"9">> ].
-
-bc2() ->
- << <<A:1>> || A <- [1,0,1,0] >>.
-
-collapse(L) ->
- lists:keymap(fun lists:sort/1, 2, L).
diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml
index d448b01eba..d241e2bd19 100644
--- a/lib/diameter/doc/src/notes.xml
+++ b/lib/diameter/doc/src/notes.xml
@@ -42,6 +42,22 @@ first.</p>
<!-- ===================================================================== -->
+<section><title>Diameter 1.3.1</title>
+
+ <section><title>Known Bugs and Problems</title>
+ <list>
+ <item>
+ <p>
+ Fix function clause resulting from use of an eval
+ callback.</p>
+ <p>
+ Own Id: OTP-10685</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Diameter 1.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/diameter/src/base/diameter.appup.src b/lib/diameter/src/base/diameter.appup.src
index 5655f98c1b..a04a387918 100644
--- a/lib/diameter/src/base/diameter.appup.src
+++ b/lib/diameter/src/base/diameter.appup.src
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -24,27 +24,9 @@
{"0.10", [{restart_application, diameter}]},
{"1.0", [{restart_application, diameter}]},
{"1.1", [{restart_application, diameter}]},
- {"1.2", [{load, diameter},
- {load, diameter_capx},
- {load, diameter_codec},
- {load, diameter_peer},
- {load, diameter_reg},
- %% order significant from here
- {load, diameter_session},
- {load, diameter_peer_fsm},
- {load, diameter_service},
- {load, diameter_watchdog},
- {load, diameter_config}]},
- {"1.2.1", [{load, diameter},
- {load, diameter_capx},
- {load, diameter_peer},
- {load, diameter_reg},
- %% order significant from here
- {load, diameter_session},
- {load, diameter_peer_fsm},
- {load, diameter_service},
- {load, diameter_watchdog},
- {load, diameter_config}]}
+ {"1.2", [{restart_application, diameter}]},
+ {"1.2.1", [{restart_application, diameter}]},
+ {"1.3", [{load_module, diameter_service}]}
],
[
{"0.9", [{restart_application, diameter}]},
@@ -52,6 +34,7 @@
{"1.0", [{restart_application, diameter}]},
{"1.1", [{restart_application, diameter}]},
{"1.2", [{restart_application, diameter}]},
- {"1.2.1", [{restart_application, diameter}]}
+ {"1.2.1", [{restart_application, diameter}]},
+ {"1.3", [{load_module, diameter_service}]}
]
}.
diff --git a/lib/diameter/src/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl
index a94d37f7a8..0b0bfe3f0a 100644
--- a/lib/diameter/src/base/diameter_codec.erl
+++ b/lib/diameter/src/base/diameter_codec.erl
@@ -193,9 +193,11 @@ encode_avps(Avps) ->
msg_header(Mod, 'answer-message' = MsgName, Header) ->
?BASE = Mod,
- #diameter_header{cmd_code = Code} = Header,
- {_, Flags, ApplId} = ?BASE:msg_header(MsgName),
- {Code, Flags, ApplId};
+ #diameter_header{application_id = Aid,
+ cmd_code = Code}
+ = Header,
+ {-1, Flags, ?DIAMETER_APP_ID_COMMON} = ?BASE:msg_header(MsgName),
+ {Code, Flags, Aid};
msg_header(Mod, MsgName, _) ->
Mod:msg_header(MsgName).
diff --git a/lib/diameter/src/base/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl
index c4320fcb99..858870566f 100644
--- a/lib/diameter/src/base/diameter_peer_fsm.erl
+++ b/lib/diameter/src/base/diameter_peer_fsm.erl
@@ -388,8 +388,9 @@ transition({diameter, {recv, Pkt}}, S) ->
recv(Pkt, S);
%% Timeout when still in the same state ...
-transition({timeout, PS}, #state{state = PS}) ->
- {stop, {capx(PS), timeout}};
+transition({timeout = T, PS}, #state{state = PS} = S) ->
+ close({capx(PS), T}, S),
+ stop;
%% ... or not.
transition({timeout, _}, _) ->
diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl
index 91384b8b91..c0fccd8080 100644
--- a/lib/diameter/src/base/diameter_service.erl
+++ b/lib/diameter/src/base/diameter_service.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -859,10 +859,10 @@ i(SvcName) ->
true = ets:insert_new(?STATE_TABLE, S),
%% Start fsms for each transport.
+ send_event(SvcName, start),
lists:foreach(fun(T) -> start_fsm(T,S) end, CL),
init_shared(S),
- send_event(SvcName, start),
S.
cfg_acc({SvcName, #diameter_service{applications = Apps} = Rec, Opts},
@@ -1457,7 +1457,7 @@ make_prepare_packet(Mask, #diameter_packet{header = Hdr} = Pkt) ->
make_prepare_packet(Mask, Msg) ->
make_prepare_packet(Mask, #diameter_packet{msg = Msg}).
-%% make_prepare_header/1
+%% make_prepare_header/2
make_prepare_header(Mask, undefined) ->
Seq = diameter_session:sequence(Mask),
@@ -1465,10 +1465,11 @@ make_prepare_header(Mask, undefined) ->
hop_by_hop_id = Seq});
make_prepare_header(Mask, #diameter_header{end_to_end_id = undefined,
- hop_by_hop_id = undefined}) ->
+ hop_by_hop_id = undefined}
+ = H) ->
Seq = diameter_session:sequence(Mask),
- make_prepare_header(#diameter_header{end_to_end_id = Seq,
- hop_by_hop_id = Seq});
+ make_prepare_header(H#diameter_header{end_to_end_id = Seq,
+ hop_by_hop_id = Seq});
make_prepare_header(Mask, #diameter_header{end_to_end_id = undefined} = H) ->
Seq = diameter_session:sequence(Mask),
@@ -2053,7 +2054,7 @@ request_cb({eval_packet, RC, F}, App, Mask, T, TC, Fs, Pkt) ->
request_cb(RC, App, Mask, T, TC, [F|Fs], Pkt);
request_cb({eval, RC, F}, App, Mask, T, TC, Fs, Pkt) ->
- request_cb(RC, App, Mask, T, TC, Pkt, Fs),
+ request_cb(RC, App, Mask, T, TC, Fs, Pkt),
diameter_lib:eval(F).
%% protocol_error/5
@@ -2242,6 +2243,9 @@ rc(RC) ->
%% rc/4
+rc(#diameter_packet{msg = Rec} = Pkt, RC, Failed, Dict) ->
+ Pkt#diameter_packet{msg = rc(Rec, RC, Failed, Dict)};
+
rc(Rec, RC, Failed, Dict)
when is_integer(RC) ->
set(Rec,
diff --git a/lib/diameter/test/diameter_event_SUITE.erl b/lib/diameter/test/diameter_event_SUITE.erl
new file mode 100644
index 0000000000..7c1c76f22a
--- /dev/null
+++ b/lib/diameter/test/diameter_event_SUITE.erl
@@ -0,0 +1,182 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2013. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of events sent as a consequence of diameter:subscribe/1.
+%% Watchdog events are dealt with more extensively in the watchdog
+%% suite.
+%%
+
+-module(diameter_event_SUITE).
+
+-export([suite/0,
+ all/0,
+ init_per_testcase/2,
+ end_per_testcase/2]).
+
+%% testcases
+-export([start/1,
+ start_server/1,
+ up/1,
+ down/1,
+ cea_timeout/1,
+ stop/1]).
+
+-include("diameter.hrl").
+
+%% ===========================================================================
+
+-define(util, diameter_util).
+
+-define(ADDR, {127,0,0,1}).
+-define(REALM, "REALM").
+
+-define(SERVER, "SERVER.SERVER-REALM").
+-define(CLIENT, "CLIENT.CLIENT-REALM").
+
+-define(DICT_COMMON, ?DIAMETER_DICT_COMMON).
+-define(DICT_ACCT, ?DIAMETER_DICT_ACCOUNTING).
+
+-define(SERVER_CAPX_TMO, 6000).
+
+%% Config for diameter:start_service/2.
+-define(SERVICE(Host, Dicts),
+ [{'Origin-Host', Host},
+ {'Origin-Realm', realm(Host)},
+ {'Host-IP-Address', [?ADDR]},
+ {'Vendor-Id', 12345},
+ {'Product-Name', "OTP/diameter"},
+ {'Acct-Application-Id', [D:id() || D <- Dicts]}
+ | [{application, [{dictionary, D},
+ {module, #diameter_callback{}}]}
+ || D <- Dicts]]).
+
+%% Diameter Result-Code's:
+-define(NO_COMMON_APP, 5010).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 60}}].
+
+all() ->
+ [start,
+ start_server,
+ up,
+ down,
+ cea_timeout,
+ stop].
+
+init_per_testcase(Name, Config) ->
+ [{name, Name} | Config].
+
+end_per_testcase(_, _) ->
+ ok.
+
+%% ===========================================================================
+%% start/stop testcases
+
+start(_Config) ->
+ ok = diameter:start().
+
+start_server(Config) ->
+ diameter:subscribe(?SERVER),
+ ok = diameter:start_service(?SERVER, ?SERVICE(?SERVER, [?DICT_COMMON])),
+ LRef = ?util:listen(?SERVER, tcp, [{capabilities_cb, fun capx_cb/2},
+ {capx_timeout, ?SERVER_CAPX_TMO}]),
+ [PortNr] = ?util:lport(tcp, LRef, 20),
+ ?util:write_priv(Config, portnr, PortNr),
+ start = event(?SERVER).
+
+%% Connect with matching capabilities and expect the connection to
+%% come up.
+up(Config) ->
+ {Svc, Ref} = connect(Config, []),
+ start = event(Svc),
+ {up, Ref, {_,_Caps}, _Config, #diameter_packet{}} = event(Svc),
+ {watchdog, Ref, _, {initial, okay}, _} = event(Svc).
+
+%% Connect with non-matching capabilities and expect CEA from the peer
+%% to indicate as much and then for the transport to be restarted
+%% (after reconnect_timer).
+down(Config) ->
+ {Svc, Ref} = connect(Config, [{capabilities, [{'Acct-Application-Id',
+ [?DICT_ACCT:id()]}]},
+ {applications, [?DICT_ACCT]},
+ {reconnect_timer, 5000}]),
+ start = event(Svc),
+ {watchdog, Ref, _, {initial, down}, _} = event(Svc),
+ {closed, Ref, {'CEA', ?NO_COMMON_APP, _, #diameter_packet{}}, _}
+ = event(Svc),
+ {reconnect, Ref, _} = event(Svc).
+
+%% Connect with matching capabilities but have the server delay its
+%% CEA and cause the client to timeout.
+cea_timeout(Config) ->
+ {Svc, Ref} = connect(Config, [{capx_timeout, ?SERVER_CAPX_TMO div 2},
+ {reconnect_timer, 2*?SERVER_CAPX_TMO}]),
+ start = event(Svc),
+ {watchdog, Ref, _, {initial, down}, _} = event(Svc),
+ {closed, Ref, {'CEA', timeout}, _} = event(Svc).
+
+stop(_Config) ->
+ ok = diameter:stop().
+
+%% ----------------------------------------
+
+%% Keep the server from sending CEA until the client has timed out.
+capx_cb(_, #diameter_caps{origin_host = {_, "cea_timeout-" ++ _}}) ->
+ receive after ?SERVER_CAPX_TMO -> ok end;
+
+%% Or not.
+capx_cb(_, _Caps) ->
+ ok.
+
+%% ----------------------------------------
+
+%% Use the testcase name to construct Origin-Host of the client so
+%% that the server can match on it in capx_cb/2.
+connect(Config, Opts) ->
+ Pre = atom_to_list(proplists:get_value(name, Config)),
+ Name = Pre ++ uniq() ++ ?CLIENT,
+ diameter:subscribe(Name),
+ ok = start_service(Name, ?SERVICE(Name, [?DICT_COMMON, ?DICT_ACCT])),
+ {ok, Ref} = diameter:add_transport(Name, opts(Config, Opts)),
+ {Name, Ref}.
+
+uniq() ->
+ {MS,S,US} = now(),
+ lists:flatten(io_lib:format("-~p-~p-~p-", [MS,S,US])).
+
+event(Name) ->
+ receive #diameter_event{service = Name, info = T} -> T end.
+
+start_service(Name, Opts) ->
+ diameter:start_service(Name, [{monitor, self()} | Opts]).
+
+opts(Config, Opts) ->
+ PortNr = ?util:read_priv(Config, portnr),
+
+ {connect, [{transport_module, diameter_tcp},
+ {transport_config, [{ip, ?ADDR}, {port, 0},
+ {raddr, ?ADDR}, {rport, PortNr}]}
+ | Opts]}.
+
+realm(Host) ->
+ tl(lists:dropwhile(fun(C) -> C /= $. end, Host)).
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index c157b0e304..b41d1a6f5c 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -38,6 +38,7 @@
result_codes/1,
send_ok/1,
send_nok/1,
+ send_eval/1,
send_bad_answer/1,
send_arbitrary/1,
send_unknown/1,
@@ -123,6 +124,9 @@
%% the common application but diameter doesn't care.
-define(APP_ID, ?DIAMETER_APP_ID_COMMON).
+%% An Application-ID the server doesn't support.
+-define(BAD_APP, 42).
+
%% Config for diameter:start_service/2.
-define(SERVICE(Name),
[{'Origin-Host', Name ++ "." ++ ?REALM},
@@ -209,6 +213,7 @@ end_per_testcase(_, _) ->
tc() ->
[send_ok,
send_nok,
+ send_eval,
send_bad_answer,
send_arbitrary,
send_unknown,
@@ -310,6 +315,14 @@ send_nok(Config) ->
#'diameter_base_answer-message'{'Result-Code' = ?INVALID_AVP_BITS}
= call(Config, Req).
+%% Send an ACR and expect success.
+send_eval(Config) ->
+ Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD},
+ {'Accounting-Record-Number', 3}],
+
+ #diameter_base_accounting_ACA{'Result-Code' = ?SUCCESS}
+ = call(Config, Req).
+
%% Send an accounting ACR that the server tries to answer with an
%% inappropriate header, resulting in no answer being sent and the
%% request timing out.
@@ -574,6 +587,8 @@ req(T, _) ->
dict(['ACR' | _]) ->
?ACCT;
+dict(#diameter_base_accounting_ACR{}) ->
+ ?ACCT;
dict(_) ->
?BASE.
@@ -659,7 +674,7 @@ prepare(Pkt, Caps, send_unsupported_app) ->
#diameter_packet{bin = <<H:8/binary, _ApplId:4/binary, T/binary>>}
= E
= diameter_codec:encode(?BASE, Pkt#diameter_packet{msg = Req}),
- E#diameter_packet{bin = <<H/binary, 42:32/integer, T/binary>>};
+ E#diameter_packet{bin = <<H/binary, ?BAD_APP:32/integer, T/binary>>};
prepare(Pkt, Caps, send_error_bit) ->
#diameter_packet{header = Hdr} = Pkt,
@@ -741,9 +756,19 @@ handle_answer(Pkt, Req, ?CLIENT, Peer, Name, _Id) ->
handle_answer(Pkt, _Req, ?CLIENT, _Peer, send_detach, _Id, {Pid, Ref}) ->
Pid ! {Ref, Pkt}.
-answer(#diameter_packet{msg = Rec, errors = []}, _Req, _Peer, _) ->
+answer(Pkt, Req, _Peer, Name) ->
+ #diameter_packet{header = H, msg = Rec, errors = []} = Pkt,
+ ApplId = app(Req, Name),
+ #diameter_header{application_id = ApplId} = H, %% assert
+
Rec.
+app(_, send_unsupported_app) ->
+ ?BAD_APP;
+app(Req, _) ->
+ Dict = dict(Req),
+ Dict:id().
+
%% handle_error/6
handle_error(Reason, _Req, ?CLIENT, _Peer, _Name, _Id) ->
@@ -763,10 +788,12 @@ handle_request(#diameter_packet{header = H, msg = M}, ?SERVER, {_Ref, Caps}) ->
V = HI bsr B, %%
request(M, Caps).
+%% send_nok
request(#diameter_base_accounting_ACR{'Accounting-Record-Number' = 0},
_) ->
{eval_packet, {protocol_error, ?INVALID_AVP_BITS}, [fun log/2, invalid]};
+%% send_bad_answer
request(#diameter_base_accounting_ACR{'Session-Id' = SId,
'Accounting-Record-Type' = RT,
'Accounting-Record-Number' = 2 = RN},
@@ -782,9 +809,24 @@ request(#diameter_base_accounting_ACR{'Session-Id' = SId,
{reply, #diameter_packet{header = #diameter_header{is_error = true},%% not
msg = Ans}};
+%% send_eval
+request(#diameter_base_accounting_ACR{'Session-Id' = SId,
+ 'Accounting-Record-Type' = RT,
+ 'Accounting-Record-Number' = 3 = RN},
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}) ->
+ Ans = ['ACA', {'Result-Code', ?SUCCESS},
+ {'Session-Id', SId},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR},
+ {'Accounting-Record-Type', RT},
+ {'Accounting-Record-Number', RN}],
+ {eval, {reply, Ans}, {erlang, now, []}};
+
+%% send_ok
request(#diameter_base_accounting_ACR{'Session-Id' = SId,
'Accounting-Record-Type' = RT,
- 'Accounting-Record-Number' = RN},
+ 'Accounting-Record-Number' = 1 = RN},
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
{reply, ['ACA', {'Result-Code', ?SUCCESS},
@@ -804,16 +846,19 @@ request(#diameter_base_ASR{'Session-Id' = SId,
'Origin-Realm' = OR,
'AVP' = Avps}};
+%% send_noreply
request(#diameter_base_STR{'Termination-Cause' = T},
_Caps)
when T /= ?LOGOUT ->
discard;
+%% send_destination_5
request(#diameter_base_STR{'Destination-Realm'= R},
#diameter_caps{origin_realm = {OR, _}})
when R /= undefined, R /= OR ->
{protocol_error, ?REALM_NOT_SERVED};
+%% send_destination_6
request(#diameter_base_STR{'Destination-Host'= [H]},
#diameter_caps{origin_host = {OH, _}})
when H /= OH ->
@@ -827,6 +872,7 @@ request(#diameter_base_STR{'Session-Id' = SId},
'Origin-Host' = OH,
'Origin-Realm' = OR}};
+%% send_error
request(#diameter_base_RAR{}, _Caps) ->
receive after 2000 -> ok end,
{protocol_error, ?TOO_BUSY}.
diff --git a/lib/diameter/test/modules.mk b/lib/diameter/test/modules.mk
index 5898e125ae..80b1769d04 100644
--- a/lib/diameter/test/modules.mk
+++ b/lib/diameter/test/modules.mk
@@ -40,7 +40,8 @@ MODULES = \
diameter_relay_SUITE \
diameter_tls_SUITE \
diameter_failover_SUITE \
- diameter_dpr_SUITE
+ diameter_dpr_SUITE \
+ diameter_event_SUITE
HRL_FILES = \
diameter_ct.hrl
diff --git a/lib/diameter/vsn.mk b/lib/diameter/vsn.mk
index c9f74ffcec..7b2208137b 100644
--- a/lib/diameter/vsn.mk
+++ b/lib/diameter/vsn.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2012. All Rights Reserved.
+# Copyright Ericsson AB 2010-2013. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -18,7 +18,7 @@
# %CopyrightEnd%
APPLICATION = diameter
-DIAMETER_VSN = 1.3
+DIAMETER_VSN = 1.3.1
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(DIAMETER_VSN)$(PRE_VSN)"
diff --git a/lib/kernel/doc/src/application.xml b/lib/kernel/doc/src/application.xml
index 51a3311ec2..9f19efc793 100644
--- a/lib/kernel/doc/src/application.xml
+++ b/lib/kernel/doc/src/application.xml
@@ -121,6 +121,15 @@
</desc>
</func>
<func>
+ <name name="get_env" arity="3"/>
+ <fsummary>Get the value of a configuration parameter using a default</fsummary>
+ <desc>
+ <p>Works like <seealso marker="#get_env/2">get_env/2</seealso> but returns
+ <c><anno>Def</anno></c> value when configuration parameter
+ <c><anno>Par</anno></c> does not exist.</p>
+ </desc>
+ </func>
+ <func>
<name name="get_key" arity="1"/>
<name name="get_key" arity="2"/>
<fsummary>Get the value of an application specification key</fsummary>
diff --git a/lib/kernel/doc/src/error_handler.xml b/lib/kernel/doc/src/error_handler.xml
index acbf9a2c6e..610b65f0a2 100644
--- a/lib/kernel/doc/src/error_handler.xml
+++ b/lib/kernel/doc/src/error_handler.xml
@@ -43,19 +43,39 @@
A (possibly empty) list of arguments <c>Arg1,..,ArgN</c>
</type_desc>
<desc>
- <p>This function is evaluated if a call is made to
+ <p>This function is called by the run-time system if a call is made to
<c><anno>Module</anno>:<anno>Function</anno>(Arg1,.., ArgN)</c> and
<c><anno>Module</anno>:<anno>Function</anno>/N</c> is undefined. Note that
<c>undefined_function/3</c> is evaluated inside the process
making the original call.</p>
- <p>If <c><anno>Module</anno></c> is interpreted, the interpreter is invoked
- and the return value of the interpreted
- <c><anno>Function</anno>(Arg1,.., ArgN)</c> call is returned.</p>
- <p>Otherwise, it returns, if possible, the value of
- <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>)</c> after an attempt has been
- made to autoload <c><anno>Module</anno></c>. If this is not possible, the
- call to <c><anno>Module</anno>:<anno>Function</anno>(Arg1,.., ArgN)</c> fails with
- exit reason <c>undef</c>.</p>
+
+ <p>This function will first attempt to autoload
+ <c><anno>Module</anno></c>. If that is not possible,
+ an <c>undef</c> exception will be raised.</p>
+
+ <p>If it was possible to load <c><anno>Module</anno></c>
+ and the function <c><anno>Function</anno>/N</c> is exported,
+ it will be called.</p>
+
+ <p>Otherwise, if the function <c>'$handle_undefined_function'/2</c>
+ is exported, it will be called as
+ <c>'$handle_undefined_function'(</c><anno>Function</anno>,
+ <anno>Args</anno>).
+ </p>
+ <p>Otherwise an <c>undef</c> exception will be raised.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="raise_undef_exception" arity="3"/>
+ <fsummary>Raise an undef exception</fsummary>
+ <type_desc variable="Args">
+ A (possibly empty) list of arguments <c>Arg1,..,ArgN</c>
+ </type_desc>
+ <desc>
+ <p>Raise an <c>undef</c> exception with a stacktrace indicating
+ that <c><anno>Module</anno>:<anno>Function</anno>/N</c> is
+ undefined.
+ </p>
</desc>
</func>
<func>
diff --git a/lib/kernel/doc/src/packages.xml b/lib/kernel/doc/src/packages.xml
deleted file mode 100644
index 8a82b91a90..0000000000
--- a/lib/kernel/doc/src/packages.xml
+++ /dev/null
@@ -1,208 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2004</year><year>2012</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved online at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
-
- </legalnotice>
-
- <title>packages</title>
- <prepared>Kenneth Lundin</prepared>
- <responsible>Kenneth Lundin</responsible>
- <docno>1</docno>
- <approved>Kenneth Lundin</approved>
- <checked></checked>
- <date>2004-09-07</date>
- <rev>A</rev>
- <file>packages.sgml</file>
- </header>
- <module>packages</module>
- <modulesummary>Packages in Erlang</modulesummary>
- <description>
- <warning><p>
- Packages has since it was introduced more than 5 years ago been an
- experimental feature. Use it at your own risk, we do not
- actively maintain and develop this feature. It might however be
- supported some
- day.
- </p>
- <p>
- In spite of this packages work quite well, but there are some
- known issues in tools and other parts where packages don't work well.
- </p>
- </warning>
- <p><em>Introduction</em></p>
- <p>Packages are simply namespaces for modules.
- All old Erlang modules automatically belong to the top level
- ("empty-string") namespace, and do not need any changes.</p>
- <p>The full name of a packaged module is written as e.g.
- "<c>fee.fie.foe.foo</c>",
- i.e., as atoms separated by periods,
- where the package name is the part up to
- but not including the last period;
- in this case "<c>fee.fie.foe</c>".
- A more concrete example is the module <c>erl.lang.term</c>,
- which is in the
- package <c>erl.lang</c>.
- Package names can have any number of segments, as in
- <c>erl.lang.list.sort</c>.
- The atoms in the name can be quoted, as in <c>foo.'Bar'.baz</c>,
- or even the
- whole name, as in <c>'foo.bar.baz'</c> but the concatenation of
- atoms and
- periods must not contain two consecutive period characters or
- end with a period,
- as in <c>'foo..bar'</c>, <c>foo.'.bar'</c>, or <c>foo.'bar.'</c>.
- The periods must not be followed by whitespace.</p>
- <p>The code loader maps module names onto the file system directory
- structure.
- E.g., the module <c>erl.lang.term</c> corresponds to a file
- <c>.../erl/lang/term.beam</c>
- in the search path.
- Note that the name of the actual object file corresponds to
- the last part only of the full module name.
- (Thus, old existing modules such as <c>lists</c>
- simply map to <c>.../lists.beam</c>, exactly as before.)</p>
- <p>A packaged module in a file "<c>foo/bar/fred.erl</c>" is declared
- as:</p>
- <code type="none">
--module(foo.bar.fred).</code>
- <p>This can be compiled and loaded from the Erlang shell using
- <c>c(fred)</c>, if
- your current directory is the same as that of the file.
- The object file will be named <c>fred.beam</c>.</p>
- <p>The Erlang search path works exactly as before,
- except that the package segments will be appended to each
- directory in the path in order to find the
- file. E.g., assume the path is <c>["/usr/lib/erl", "/usr/local/lib/otp/legacy/ebin", "/home/barney/erl"]</c>.
- Then, the code for a module named <c>foo.bar.fred</c> will be
- searched for
- first as <c>"/usr/lib/erl/foo/bar/fred.beam"</c>, then
- <c>"/usr/local/lib/otp/legacy/ebin/foo/bar/fred.beam"</c>
- and lastly <c>"/home/barney/erl/foo/bar/fred.beam"</c>.
- A module
- like <c>lists</c>, which is in the top-level package,
- will be looked for as <c>"/usr/lib/erl/lists.beam"</c>,
- <c>"/usr/local/lib/otp/legacy/ebin/lists.beam"</c> and
- <c>"/home/barney/erl/lists.beam"</c>.</p>
- <p><em>Programming</em></p>
- <p>Normally, if a call is made from one module to another,
- it is assumed that the
- called module belongs to the same package as the source module.
- The compiler
- automatically expands such calls. E.g., in:</p>
- <code type="none">
--module(foo.bar.m1).
--export([f/1]).
-
-f(X) -> m2:g(X).</code>
- <p><c>m2:g(X)</c> becomes a call to <c>foo.bar.m2</c>
- If this is not what was intended, the call can be written
- explicitly, as in</p>
- <code type="none">
--module(foo.bar.m1).
--export([f/1]).
-
-f(X) -> fee.fie.foe.m2:g(X).</code>
- <p>Because the called module is given with an explicit package name,
- no expansion is done in this case.</p>
- <p>If a module from another package is used repeatedly in a module,
- an import declaration can make life easier:</p>
- <code type="none">
--module(foo.bar.m1).
--export([f/1, g/1]).
--import(fee.fie.foe.m2).
-
-f(X) -> m2:g(X).
-g(X) -> m2:h(X).</code>
- <p>will make the calls to <c>m2</c> refer to <c>fee.fie.foe.m2</c>.
- More generally, a declaration <c>-import(Package.Module).</c>
- will cause calls to <c>Module</c>
- to be expanded to <c>Package.Module</c>.</p>
- <p>Old-style function imports work as normal (but full module
- names must be
- used); e.g.:</p>
- <code type="none">
--import(fee.fie.foe.m2, [g/1, h/1]).</code>
- <p>however, it is probably better to avoid this form of import
- altogether in new
- code, since it makes it hard to see what calls are really "remote".</p>
- <p>If it is necessary to call a module in the top-level package
- from within a
- named package, the module name can be written either with an
- initial period as
- in e.g. "<c>.lists</c>", or with an empty initial atom, as in
- "<c>''.lists</c>".
- However, the best way is to use an import declaration -
- this is most obvious to
- the eye, and makes sure we don't forget adding a period somewhere:</p>
- <code type="none">
--module(foo.bar.fred).
--export([f/1]).
--import(lists).
-
-f(X) -> lists:reverse(X).</code>
- <p>The dot-syntax for module names can be used in any expression.
- All segments must
- be constant atoms, and the result must be a well-formed
- package/module name.
- E.g.:</p>
- <code type="none">
-spawn(foo.bar.fred, f, [X])</code>
- <p>is equivalent to <c>spawn('foo.bar.fred', f, [X])</c>.</p>
- <p><em>The Erlang Shell</em></p>
- <p>The shell also automatically expands remote calls,
- however currently no
- expansions are made by default.
- The user can change the behaviour by using the <c>import/1</c>
- shell command (or its abbreviation <c>use/1</c>). E.g.:</p>
- <pre>
-1> <input>import(foo.bar.m).</input>
-ok
-2> <input>m:f().</input></pre>
- <p>will evaluate <c>foo.bar.m:f()</c>.
- If a new import is made of the same name,
- this overrides any previous import.
- (It is likely that in the future, some
- system packages will be pre-imported.)</p>
- <p>In addition, the shell command <c>import_all/1</c>
- (and its alias <c>use_all/1</c>)
- imports all modules currently found in the path for a given
- package name. E.g.,
- assuming the files "<c>.../foo/bar/fred.beam</c>",
- "<c>.../foo/bar/barney.beam</c>"
- and "<c>.../foo/bar/bambam.beam</c>" can be found from our current
- path,</p>
- <pre>
-1> <input>import_all(foo.bar).</input></pre>
- <p>will make <c>fred</c>, <c>barney</c> and <c>bambam</c>
- expand to <c>foo.bar.fred</c>,
- <c>foo.bar.barney</c> and <c>foo.bar.bambam</c>, respectively.</p>
- <p>Note: The compiler does not have an "import all" directive, for the
- reason that Erlang has no compile time type checking.
- E.g. if the wrong search
- path is used at compile time, a call <c>m:f(...)</c>
- could be expanded to <c>foo.bar.m:f(...)</c>
- without any warning, instead of the intended
- <c>frob.ozz.m:f(...)</c>, if
- package <c>foo.bar</c> happens to be found first in the path.
- Explicitly
- declaring each use of a module makes for safe code.</p>
- </description>
-</erlref>
-
diff --git a/lib/kernel/doc/src/ref_man.xml b/lib/kernel/doc/src/ref_man.xml
index 9ef0959271..67d91ba585 100644
--- a/lib/kernel/doc/src/ref_man.xml
+++ b/lib/kernel/doc/src/ref_man.xml
@@ -64,6 +64,5 @@
<xi:include href="zlib_stub.xml"/>
<xi:include href="app.xml"/>
<xi:include href="config.xml"/>
- <xi:include href="packages.xml"/>
</application>
diff --git a/lib/kernel/src/application.erl b/lib/kernel/src/application.erl
index 9b7c4aa7b8..4e65883be7 100644
--- a/lib/kernel/src/application.erl
+++ b/lib/kernel/src/application.erl
@@ -23,7 +23,7 @@
which_applications/0, which_applications/1,
loaded_applications/0, permit/2]).
-export([set_env/3, set_env/4, unset_env/2, unset_env/3]).
--export([get_env/1, get_env/2, get_all_env/0, get_all_env/1]).
+-export([get_env/1, get_env/2, get_env/3, get_all_env/0, get_all_env/1]).
-export([get_key/1, get_key/2, get_all_key/0, get_all_key/1]).
-export([get_application/0, get_application/1, info/0]).
-export([start_type/0]).
@@ -264,6 +264,20 @@ get_env(Key) ->
get_env(Application, Key) ->
application_controller:get_env(Application, Key).
+-spec get_env(Application, Par, Def) -> Val when
+ Application :: atom(),
+ Par :: atom(),
+ Def :: term(),
+ Val :: term().
+
+get_env(Application, Key, Def) ->
+ case get_env(Application, Key) of
+ {ok, Val} ->
+ Val;
+ undefined ->
+ Def
+ end.
+
-spec get_all_env() -> Env when
Env :: [{Par :: atom(), Val :: term()}].
diff --git a/lib/kernel/src/error_handler.erl b/lib/kernel/src/error_handler.erl
index f8bc5f499c..a3aa1f1dcf 100644
--- a/lib/kernel/src/error_handler.erl
+++ b/lib/kernel/src/error_handler.erl
@@ -23,10 +23,12 @@
%% "error_handler: add no_native compiler directive"
-compile(no_native).
-%% A simple error handler.
+%% Callbacks called from the run-time system.
+-export([undefined_function/3,undefined_lambda/3,breakpoint/3]).
--export([undefined_function/3, undefined_lambda/3, stub_function/3,
- breakpoint/3]).
+%% Exported utility functions.
+-export([raise_undef_exception/3]).
+-export([stub_function/3]).
-spec undefined_function(Module, Function, Args) ->
any() when
@@ -41,12 +43,7 @@ undefined_function(Module, Func, Args) ->
true ->
apply(Module, Func, Args);
false ->
- case check_inheritance(Module, Args) of
- {value, Base, Args1} ->
- apply(Base, Func, Args1);
- none ->
- crash(Module, Func, Args)
- end
+ call_undefined_function_handler(Module, Func, Args)
end;
{module, _} ->
crash(Module, Func, Args);
@@ -77,6 +74,14 @@ undefined_lambda(Module, Fun, Args) ->
breakpoint(Module, Func, Args) ->
(int()):eval(Module, Func, Args).
+-spec raise_undef_exception(Module, Function, Args) -> no_return() when
+ Module :: atom(),
+ Function :: atom(),
+ Args :: list().
+
+raise_undef_exception(Module, Func, Args) ->
+ crash({Module,Func,Args,[]}).
+
%% Used to make the call to the 'int' module a "weak" one, to avoid
%% building strong components in xref or dialyzer.
@@ -130,27 +135,11 @@ ensure_loaded(Module) ->
stub_function(Mod, Func, Args) ->
exit({undef,[{Mod,Func,Args,[]}]}).
-check_inheritance(Module, Args) ->
- Attrs = erlang:get_module_info(Module, attributes),
- case lists:keyfind(extends, 1, Attrs) of
- {extends, [Base]} when is_atom(Base), Base =/= Module ->
- %% This is just a heuristic for detecting abstract modules
- %% with inheritance so they can be handled; it would be
- %% much better to do it in the emulator runtime
- case lists:keyfind(abstract, 1, Attrs) of
- {abstract, [true]} ->
- case lists:reverse(Args) of
- [M|Rs] when tuple_size(M) > 1,
- element(1,M) =:= Module,
- tuple_size(element(2,M)) > 0,
- is_atom(element(1,element(2,M))) ->
- {value, Base, lists:reverse(Rs, [element(2,M)])};
- _ ->
- {value, Base, Args}
- end;
- _ ->
- {value, Base, Args}
- end;
- _ ->
- none
+call_undefined_function_handler(Module, Func, Args) ->
+ Handler = '$handle_undefined_function',
+ case erlang:function_exported(Module, Handler, 2) of
+ false ->
+ crash(Module, Func, Args);
+ true ->
+ Module:Handler(Func, Args)
end.
diff --git a/lib/kernel/test/Makefile b/lib/kernel/test/Makefile
index 7fd3afe93c..8d2d55777b 100644
--- a/lib/kernel/test/Makefile
+++ b/lib/kernel/test/Makefile
@@ -48,6 +48,7 @@ MODULES= \
erl_distribution_SUITE \
erl_distribution_wb_SUITE \
erl_prim_loader_SUITE \
+ error_handler_SUITE \
error_logger_SUITE \
error_logger_warn_SUITE \
file_SUITE \
diff --git a/lib/kernel/test/application_SUITE.erl b/lib/kernel/test/application_SUITE.erl
index f469a0af98..2ca8840e1f 100644
--- a/lib/kernel/test/application_SUITE.erl
+++ b/lib/kernel/test/application_SUITE.erl
@@ -27,7 +27,7 @@
otp_1586/1, otp_2078/1, otp_2012/1, otp_2718/1, otp_2973/1,
otp_3002/1, otp_3184/1, otp_4066/1, otp_4227/1, otp_5363/1,
otp_5606/1,
- start_phases/1, get_key/1,
+ start_phases/1, get_key/1, get_env/1,
permit_false_start_local/1, permit_false_start_dist/1, script_start/1,
nodedown_start/1, init2973/0, loop2973/0, loop5606/1]).
@@ -49,7 +49,7 @@ all() ->
[failover, failover_comp, permissions, load,
load_use_cache, {group, reported_bugs}, start_phases,
script_start, nodedown_start, permit_false_start_local,
- permit_false_start_dist, get_key,
+ permit_false_start_dist, get_key, get_env,
{group, distr_changed}, config_change, shutdown_func, shutdown_timeout].
groups() ->
@@ -1503,6 +1503,15 @@ loop5606(Pid) ->
Pid ! {self(), Res}
end.
+get_env(suite) -> [];
+get_env(doc) ->
+ ["Tests get_env/* functions"];
+get_env(Conf) when is_list(Conf) ->
+ {ok, _} = application:get_env(kernel, error_logger),
+ undefined = application:get_env(undefined_app, a),
+ undefined = application:get_env(kernel, error_logger_xyz),
+ default = application:get_env(kernel, error_logger_xyz, default),
+ ok.
%%-----------------------------------------------------------------
%% Should be started in a CC view with:
diff --git a/lib/kernel/test/error_handler_SUITE.erl b/lib/kernel/test/error_handler_SUITE.erl
new file mode 100644
index 0000000000..2a86d39b74
--- /dev/null
+++ b/lib/kernel/test/error_handler_SUITE.erl
@@ -0,0 +1,68 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2013. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(error_handler_SUITE).
+
+-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1,
+ init_per_group/2,end_per_group/2,
+ undefined_function_handler/1]).
+
+%% Callback from error_handler.
+-export(['$handle_undefined_function'/2]).
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [undefined_function_handler].
+
+groups() ->
+ [].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+%%-----------------------------------------------------------------
+
+undefined_function_handler(_) ->
+ 42 = ?MODULE:forty_two(),
+ 42 = (id(?MODULE)):forty_two(),
+ {ok,{a,b,c}} = ?MODULE:one_arg({a,b,c}),
+ {ok,{a,b,c}} = (id(?MODULE)):one_arg({a,b,c}),
+ {'EXIT',{undef,[{?MODULE,undef_and_not_handled,[[1,2,3]],[]}|_]}} =
+ (catch ?MODULE:undef_and_not_handled([1,2,3])),
+ ok.
+
+'$handle_undefined_function'(forty_two, []) ->
+ 42;
+'$handle_undefined_function'(one_arg, [Arg]) ->
+ {ok,Arg};
+'$handle_undefined_function'(Func, Args) ->
+ error_handler:raise_undef_exception(?MODULE, Func, Args).
+
+id(I) ->
+ I.
diff --git a/lib/kernel/test/global_SUITE.erl b/lib/kernel/test/global_SUITE.erl
index b40c50f79f..9428a38660 100644
--- a/lib/kernel/test/global_SUITE.erl
+++ b/lib/kernel/test/global_SUITE.erl
@@ -91,27 +91,9 @@ end_per_group(_GroupName, Config) ->
Config.
init_per_suite(Config) ->
-
- %% Copied from test_server_ctrl ln 647, we have to do this here as
- %% the test_server only does this when run without common_test
- global:sync(),
- case global:whereis_name(test_server) of
- undefined ->
- io:format(user, "Registering test_server globally!~n",[]),
- global:register_name(test_server, whereis(test_server_ctrl));
- Pid ->
- case node() of
- N when N == node(Pid) ->
- io:format(user, "Warning: test_server already running!\n", []),
- global:re_register_name(test_server,self());
- _ ->
- ok
- end
- end,
Config.
end_per_suite(_Config) ->
- global:unregister_name(test_server),
ok.
@@ -135,8 +117,7 @@ end_per_testcase(_Case, Config) ->
?line write_high_level_trace(Config),
?line _ =
gen_server:call(global_name_server, high_level_trace_stop, infinity),
- ?line[global:unregister_name(N) || N <- global:registered_names(),
- N =/= test_server],
+ [global:unregister_name(N) || N <- global:registered_names()],
?line InitRegistered = ?registered,
?line Registered = registered(),
?line [io:format("~s local names: ~p~n", [What, N]) ||
@@ -1840,16 +1821,16 @@ do_otp_3162(StartFun, Config) ->
?line ?UNTIL
([Cp3] =:= lists:sort(rpc:call(Cp1, erlang, nodes, [])) -- [node()]),
- ?line ?UNTIL([kalle, test_server, vera] =:=
+ ?UNTIL([kalle, vera] =:=
lists:sort(rpc:call(Cp1, global, registered_names, []))),
?line ?UNTIL
([Cp3] =:= lists:sort(rpc:call(Cp2, erlang, nodes, [])) -- [node()]),
- ?line ?UNTIL([stina, test_server, vera] =:=
+ ?UNTIL([stina, vera] =:=
lists:sort(rpc:call(Cp2, global, registered_names, []))),
?line ?UNTIL
([Cp1, Cp2] =:=
lists:sort(rpc:call(Cp3, erlang, nodes, [])) -- [node()]),
- ?line ?UNTIL([kalle, stina, test_server, vera] =:=
+ ?UNTIL([kalle, stina, vera] =:=
lists:sort(rpc:call(Cp3, global, registered_names, []))),
?line pong = rpc:call(Cp2, net_adm, ping, [Cp1]),
@@ -1860,17 +1841,17 @@ do_otp_3162(StartFun, Config) ->
?line
?UNTIL(begin
NN = lists:sort(rpc:call(Cp1, global, registered_names, [])),
- [kalle, stina, test_server, vera] =:= NN
+ [kalle, stina, vera] =:= NN
end),
?line ?UNTIL
([Cp1, Cp3] =:=
lists:sort(rpc:call(Cp2, erlang, nodes, [])) -- [node()]),
- ?line ?UNTIL([kalle, stina, test_server, vera] =:=
+ ?UNTIL([kalle, stina, vera] =:=
lists:sort(rpc:call(Cp2, global, registered_names, []))),
?line ?UNTIL
([Cp1, Cp2] =:=
lists:sort(rpc:call(Cp3, erlang, nodes, [])) -- [node()]),
- ?line ?UNTIL([kalle, stina, test_server, vera] =:=
+ ?UNTIL([kalle, stina, vera] =:=
lists:sort(rpc:call(Cp3, global, registered_names, []))),
write_high_level_trace(Config),
@@ -4154,7 +4135,7 @@ init_condition(Config) ->
{"Global Locks (ETS)", global_locks},
{"Global Pid Names (ETS)", global_pid_names},
{"Global Pid Ids (ETS)", global_pid_ids}]],
- ?UNTIL([test_server] =:= global:registered_names()),
+ ?UNTIL([] =:= global:registered_names()),
?UNTIL([] =:= nodes()),
?UNTIL([node()] =:= get_known(node())),
ok.
diff --git a/lib/public_key/asn1/OTP-PUB-KEY.asn1config b/lib/public_key/asn1/OTP-PUB-KEY.asn1config
index 86f4c54748..9ca30564af 100644
--- a/lib/public_key/asn1/OTP-PUB-KEY.asn1config
+++ b/lib/public_key/asn1/OTP-PUB-KEY.asn1config
@@ -1,2 +1,3 @@
{exclusive_decode,{'OTP-PUB-KEY',
- [{decode_TBSCert_exclusive,['Certificate',[{tbsCertificate,undecoded}]]}]}}.
+ [{decode_TBSCert_exclusive,['Certificate',[{tbsCertificate,undecoded}]]},
+ {decode_TBSCertList_exclusive,['CertificateList',[{tbsCertList,undecoded}]]}]}}.
diff --git a/lib/public_key/doc/src/cert_records.xml b/lib/public_key/doc/src/cert_records.xml
index b1d2a05200..f01f7dbaf5 100644
--- a/lib/public_key/doc/src/cert_records.xml
+++ b/lib/public_key/doc/src/cert_records.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2008</year>
- <year>2012</year>
+ <year>2013</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -34,12 +34,11 @@
<file>cert_records.xml</file>
</header>
- <p>This chapter briefly describes erlang records derived from asn1
- specifications used to handle X509 certificates. The intent is to
- describe the data types and not to specify the meaning of each
+ <p>This chapter briefly describes erlang records derived from ASN1
+ specifications used to handle <c> X509 certificates</c> and <c>CertificationRequest</c>.
+ The intent is to describe the data types and not to specify the meaning of each
component for this we refer you to <url
- href="http://www.ietf.org/rfc/rfc5280.txt">RFC 5280</url>. Also
- descirbed is <p>CertificationRequest</p> that is defined by
+ href="http://www.ietf.org/rfc/rfc5280.txt">RFC 5280</url> and
<url href="http://www.rsa.com/rsalabs/node.asp?id=2124">PKCS-10</url>.
</p>
@@ -48,7 +47,7 @@
<code> -include_lib("public_key/include/public_key.hrl"). </code>
- <p>The used asn1 specifications are available <c>asn1</c> subdirectory
+ <p>The used ASN1 specifications are available <c>asn1</c> subdirectory
of the application <c>public_key</c>.
</p>
@@ -62,7 +61,7 @@
follows here.</p>
<p><c>oid() - a tuple of integers
- as generated by the asn1 compiler.</c></p>
+ as generated by the ASN1 compiler.</c></p>
<p><c>time() = uct_time() | general_time()</c></p>
@@ -101,7 +100,7 @@
#'Certificate'{
tbsCertificate, % #'TBSCertificate'{}
signatureAlgorithm, % #'AlgorithmIdentifier'{}
- signature % {0, binary()} - asn1 compact bitstring
+ signature % {0, binary()} - ASN1 compact bitstring
}.
#'TBSCertificate'{
@@ -119,7 +118,7 @@
#'AlgorithmIdentifier'{
algorithm, % oid()
- parameters % asn1_der_encoded()
+ parameters % der_encoded()
}.
</code>
@@ -127,7 +126,7 @@
#'OTPCertificate'{
tbsCertificate, % #'OTPTBSCertificate'{}
signatureAlgorithm, % #'SignatureAlgorithm'
- signature % {0, binary()} - asn1 compact bitstring
+ signature % {0, binary()} - ASN1 compact bitstring
}.
#'OTPTBSCertificate'{
@@ -290,7 +289,7 @@ oid names see table below. Ex: ?'id-dsa-with-sha1'</p>
#'Extension'{
extnID, % id_extensions() | oid()
critical, % boolean()
- extnValue % asn1_der_encoded()
+ extnValue % der_encoded()
}.
</code>
@@ -372,7 +371,7 @@ oid names see table below. Ex: ?'id-dsa-with-sha1'</p>
<row>
<cell align="left" valign="middle">id-ce-cRLDistributionPoints</cell>
- <cell align="left" valign="middle">#'DistributionPoint'{}</cell>
+ <cell align="left" valign="middle">[#'DistributionPoint'{}]</cell>
</row>
<row>
@@ -461,7 +460,7 @@ oid names see table below. Ex: ?'id-dsa-with-sha1'</p>
#'Attribute'{
type, % oid()
- values % [asn1_der_encoded()]
+ values % [der_encoded()]
}).
#'BasicConstraints'{
@@ -486,9 +485,10 @@ oid names see table below. Ex: ?'id-dsa-with-sha1'</p>
}).
#'DistributionPoint'{
- distributionPoint, % general_name() | [#AttributeTypeAndValue{}]
+ distributionPoint, % {fullName, [general_name()]} | {nameRelativeToCRLIssuer,
+ [#AttributeTypeAndValue{}]}
reasons, % [dist_reason()]
- cRLIssuer % general_name()
+ cRLIssuer % [general_name()]
}).
</code>
@@ -530,7 +530,7 @@ oid names see table below. Ex: ?'id-dsa-with-sha1'</p>
#'CertificateList'{
tbsCertList, % #'TBSCertList{}
signatureAlgorithm, % #'AlgorithmIdentifier'{}
- signature % {0, binary()} - asn1 compact bitstring
+ signature % {0, binary()} - ASN1 compact bitstring
}).
#'TBSCertList'{
@@ -589,7 +589,8 @@ oid names see table below. Ex: ?'id-dsa-with-sha1'</p>
<code>
#'IssuingDistributionPoint'{
- distributionPoint, % general_name() | [#AttributeTypeAndValue'{}]
+ distributionPoint, % {fullName, [general_name()]} | {nameRelativeToCRLIssuer,
+ [#AttributeTypeAndValue'{}]}
onlyContainsUserCerts, % boolean()
onlyContainsCACerts, % boolean()
onlySomeReasons, % [dist_reason()]
@@ -641,7 +642,7 @@ oid names see table below. Ex: ?'id-dsa-with-sha1'</p>
#'CertificationRequest'{
certificationRequestInfo #'CertificationRequestInfo'{},
signatureAlgorithm #'CertificationRequest_signatureAlgorithm'{}}.
- signature {0, binary()} - asn1 compact bitstring
+ signature {0, binary()} - ASN1 compact bitstring
}
#'CertificationRequestInfo'{
@@ -653,17 +654,17 @@ oid names see table below. Ex: ?'id-dsa-with-sha1'</p>
#'CertificationRequestInfo_subjectPKInfo'{
algorithm #'CertificationRequestInfo_subjectPKInfo_algorithm'{}
- subjectPublicKey {0, binary()} - asn1 compact bitstring
+ subjectPublicKey {0, binary()} - ASN1 compact bitstring
}
#'CertificationRequestInfo_subjectPKInfo_algorithm'{
algorithm = oid(),
- parameters = asn1_der_encoded()
+ parameters = der_encoded()
}
#'CertificationRequest_signatureAlgorithm'{
algorithm = oid(),
- parameters = asn1_der_encoded()
+ parameters = der_encoded()
}
</code>
</section>
diff --git a/lib/public_key/doc/src/introduction.xml b/lib/public_key/doc/src/introduction.xml
index e0dd5603f7..4b59cc2245 100644
--- a/lib/public_key/doc/src/introduction.xml
+++ b/lib/public_key/doc/src/introduction.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2008</year>
- <year>2012</year>
+ <year>2013</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -36,11 +36,13 @@
<section>
<title>Purpose</title>
- <p> This application provides an API to public key infrastructure
- from <url href="http://www.ietf.org/rfc/rfc5280.txt">RFC
- 5280</url> (X.509 certificates) and public key formats defined by
- the <url href="http://www.rsa.com/rsalabs/node.asp?id=2124">
- PKCS-standard</url></p>
+ <p> public_key deals with public key related file formats, digital
+ signatures and <url href="http://www.ietf.org/rfc/rfc5280.txt">
+ X-509 certificates</url>. It is a library application that
+ provides encode/decode, sign/verify, encrypt/decrypt and similar
+ functionality, it does not read or write files it expects or returns
+ file contents or partial file contents as binaries.
+ </p>
</section>
<section>
@@ -51,9 +53,9 @@
<section>
<title>Performance tips</title>
- <p>The public_key decode and encode functions will try to use the nifs
- which are in the asn1 compilers runtime modules if they can be found.
- So for the best performance you want to have the asn1 application in the
+ <p>The public_key decode and encode functions will try to use the NIFs
+ which are in the ASN1 compilers runtime modules if they can be found.
+ So for the best performance you want to have the ASN1 application in the
path of your system. </p>
</section>
diff --git a/lib/public_key/doc/src/part.xml b/lib/public_key/doc/src/part.xml
index ea3123b5bd..08fa4eec58 100644
--- a/lib/public_key/doc/src/part.xml
+++ b/lib/public_key/doc/src/part.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2008</year>
- <year>2011</year>
+ <year>2013</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -32,8 +32,10 @@
</header>
<description>
<p> This application provides an API to public key infrastructure
- from RFC 3280 (X.509 certificates) and some public key formats defined
- by the PKCS-standard. </p>
+ from <url href="http://www.ietf.org/rfc/rfc5280.txt">RFC
+ 5280</url> (X.509 certificates) and public key formats defined by
+ the <url href="http://www.rsa.com/rsalabs/node.asp?id=2124">
+ PKCS-standard</url></p>
</description>
<xi:include href="introduction.xml"/>
<xi:include href="public_key_records.xml"/>
diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml
index b240d53571..5864de2d57 100644
--- a/lib/public_key/doc/src/public_key.xml
+++ b/lib/public_key/doc/src/public_key.xml
@@ -33,12 +33,30 @@
<module>public_key</module>
<modulesummary> API module for public key infrastructure.</modulesummary>
<description>
- <p>This module provides functions to handle public key infrastructure
- from <url href="http://www.ietf.org/rfc/rfc5280.txt">RFC 5280</url>- X.509 certificates and some parts of the PKCS-standard.
+ <p>This module provides functions to handle public key infrastructure. It can
+ encode/decode different file formats (PEM, openssh), sign and verify digital signatures and validate
+ certificate paths and certificate revocation lists.
</p>
</description>
<section>
+ <title>public_key</title>
+
+ <list type="bulleted">
+ <item>public_key requires the crypto application.</item>
+
+ <item>Supports <url href="http://www.ietf.org/rfc/rfc5280.txt">RFC 5280 </url> -
+ Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile </item>
+ <item>Supports <url href="http://www.rsa.com/rsalabs/node.asp?id=2125"> PKCS-1 </url> - RSA Cryptography Standard </item>
+ <item>Supports <url href="http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf"> DSA</url>- Digital Signature Algorithm</item>
+ <item>Supports <url href="http://www.rsa.com/rsalabs/node.asp?id=2126"> PKCS-3 </url> - Diffie-Hellman Key Agreement Standard </item>
+ <item>Supports <url href="http://www.rsa.com/rsalabs/node.asp?id=2127"> PKCS-5</url> - Password-Based Cryptography Standard </item>
+ <item>Supports <url href="http://www.rsa.com/rsalabs/node.asp?id=2130"> PKCS-8</url> - Private-Key Information Syntax Standard</item>
+ <item>Supports <url href="http://www.rsa.com/rsalabs/node.asp?id=2132"> PKCS-10</url> - Certification Request Syntax Standard</item>
+ </list>
+ </section>
+
+ <section>
<title>COMMON DATA TYPES </title>
<note><p>All records used in this manual
@@ -58,7 +76,9 @@
<p><code>boolean() = true | false</code></p>
- <p><code>string = [bytes()]</code></p>
+ <p><code>string() = [bytes()]</code></p>
+
+ <p><code>der_encoded() = binary()</code></p>
<p><code>pki_asn1_type() = 'Certificate' | 'RSAPrivateKey'| 'RSAPublicKey' |
'DSAPrivateKey' | 'DSAPublicKey' | 'DHParameter' | 'SubjectPublicKeyInfo' |
@@ -87,6 +107,9 @@
<p><code> dss_digest_type() = 'sha' </code></p>
+ <p><code> crl_reason() = unspecified | keyCompromise | cACompromise | affiliationChanged | superseded | cessationOfOperation | certificateHold | privilegeWithdrawn | aACompromise
+ </code></p>
+
<p><code> ssh_file() = openssh_public_key | rfc4716_public_key |
known_hosts | auth_keys </code></p>
@@ -151,7 +174,7 @@
<func>
<name>der_decode(Asn1type, Der) -> term()</name>
- <fsummary> Decodes a public key asn1 der encoded entity.</fsummary>
+ <fsummary> Decodes a public key ASN.1 DER encoded entity.</fsummary>
<type>
<v>Asn1Type = atom()</v>
<d> ASN.1 type present in the public_key applications
@@ -159,7 +182,7 @@
<v>Der = der_encoded()</v>
</type>
<desc>
- <p> Decodes a public key ASN.1 der encoded entity.</p>
+ <p> Decodes a public key ASN.1 DER encoded entity.</p>
</desc>
</func>
@@ -181,14 +204,14 @@
<func>
<name>pem_decode(PemBin) -> [pem_entry()]</name>
<fsummary>Decode PEM binary data and return
- entries as ASN.1 der encoded entities. </fsummary>
+ entries as ASN.1 DER encoded entities. </fsummary>
<type>
<v>PemBin = binary()</v>
<d>Example {ok, PemBin} = file:read_file("cert.pem").</d>
</type>
<desc>
<p>Decode PEM binary data and return
- entries as ASN.1 der encoded entities.</p>
+ entries as ASN.1 DER encoded entities.</p>
</desc>
</func>
@@ -212,8 +235,8 @@
<v> Password = string() </v>
</type>
<desc>
- <p>Decodes a pem entry. pem_decode/1 returns a list of pem
- entries. Note that if the pem entry is of type
+ <p>Decodes a PEM entry. pem_decode/1 returns a list of PEM
+ entries. Note that if the PEM entry is of type
'SubjectPublickeyInfo' it will be further decoded to an
rsa_public_key() or dsa_public_key().</p>
</desc>
@@ -222,7 +245,7 @@
<func>
<name>pem_entry_encode(Asn1Type, Entity) -> pem_entry()</name>
<name>pem_entry_encode(Asn1Type, Entity, {CipherInfo, Password}) -> pem_entry()</name>
- <fsummary> Creates a pem entry that can be fed to pem_encode/1.</fsummary>
+ <fsummary> Creates a PEM entry that can be fed to pem_encode/1.</fsummary>
<type>
<v>Asn1Type = pki_asn1_type()</v>
<v>Entity = term()</v>
@@ -236,7 +259,7 @@
<v>Password = string()</v>
</type>
<desc>
- <p> Creates a pem entry that can be feed to pem_encode/1.</p>
+ <p> Creates a PEM entry that can be feed to pem_encode/1.</p>
</desc>
</func>
@@ -266,12 +289,12 @@
<func>
<name>pkix_decode_cert(Cert, otp|plain) -> #'Certificate'{} | #'OTPCertificate'{}</name>
- <fsummary> Decodes an ASN.1 der encoded pkix x509 certificate.</fsummary>
+ <fsummary> Decodes an ASN.1 DER encoded PKIX x509 certificate.</fsummary>
<type>
<v>Cert = der_encoded()</v>
</type>
<desc>
- <p>Decodes an ASN.1 der encoded pkix certificate. The otp option
+ <p>Decodes an ASN.1 DER encoded PKIX certificate. The otp option
will use the customized ASN.1 specification OTP-PKIX.asn1 for
decoding and also recursively decode most of the standard
parts.</p>
@@ -280,14 +303,15 @@
<func>
<name>pkix_encode(Asn1Type, Entity, otp | plain) -> der_encoded()</name>
- <fsummary>Der encodes a pkix x509 certificate or part of such a
+ <fsummary>DER encodes a PKIX x509 certificate or part of such a
certificate.</fsummary>
<type>
<v>Asn1Type = atom()</v>
<d>The ASN.1 type can be 'Certificate', 'OTPCertificate' or a subtype of either .</d>
+ <v>Entity = #'Certificate'{} | #'OTPCertificate'{} | a valid subtype</v>
</type>
<desc>
- <p>Der encodes a pkix x509 certificate or part of such a
+ <p>DER encodes a PKIX x509 certificate or part of such a
certificate. This function must be used for encoding certificates or parts of certificates
that are decoded/created in the otp format, whereas for the plain format this
function will directly call der_encode/2. </p>
@@ -357,18 +381,104 @@
</desc>
</func>
- <!-- <func> -->
- <!-- <name>pkix_path_validation()</name> -->
- <!-- <fsummary> Performs a basic path validation according to RFC 5280.</fsummary> -->
- <!-- <type> -->
- <!-- <v></v> -->
- <!-- </type> -->
- <!-- <desc> -->
- <!-- <p> Performs a basic path validation according to RFC 5280.</p> -->
- <!-- </desc> -->
- <!-- </func> -->
+ <func>
+ <name>pkix_path_validation(TrustedCert, CertChain, Options) -> {ok, {PublicKeyInfo, PolicyTree}} | {error, {bad_cert, Reason}} </name>
+ <fsummary> Performs a basic path validation according to RFC 5280.</fsummary>
+ <type>
+ <v> TrustedCert = #'OTPCertificate'{} | der_encode() | unknown_ca | selfsigned_peer </v>
+ <d>Normally a trusted certificate but it can also be one of the path validation
+ errors <c>unknown_ca </c> or <c>selfsigned_peer </c> that can be discovered while
+ constructing the input to this function and that should be run through the <c>verify_fun</c>.</d>
+ <v> CertChain = [der_encode()]</v>
+ <d>A list of DER encoded certificates in trust order ending with the peer certificate.</d>
+ <v> Options = proplists:proplists()</v>
+ <v>PublicKeyInfo = {?'rsaEncryption' | ?'id-dsa',
+ rsa_public_key() | integer(), 'NULL' | 'Dss-Parms'{}}</v>
+ <v> PolicyTree = term() </v>
+ <d>At the moment this will always be an empty list as Policies are not currently supported</d>
+ <v> Reason = cert_expired | invalid_issuer | invalid_signature | unknown_ca |
+ selfsigned_peer | name_not_permitted | missing_basic_constraint | invalid_key_usage | crl_reason()
+ </v>
+ </type>
+ <desc>
+ <p>
+ Performs a basic path validation according to
+ <url href="http://www.ietf.org/rfc/rfc5280.txt">RFC 5280.</url>
+ However CRL validation is done separately by <seealso
+ marker="public_key#pkix_crls_validate-3">pkix_crls_validate/3 </seealso> and should be called
+ from the supplied <c>verify_fun</c>
+ </p>
+
+ <taglist>
+ <p> Available options are: </p>
+
+ <tag>{verify_fun, fun()}</tag>
+ <item>
+ <p>The fun should be defined as:</p>
+
+ <code>
+fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
+ {extension, #'Extension'{}},
+ InitialUserState :: term()) ->
+ {valid, UserState :: term()} | {valid_peer, UserState :: term()} |
+ {fail, Reason :: term()} | {unknown, UserState :: term()}.
+ </code>
+
+ <p>If the verify callback fun returns {fail, Reason}, the
+ verification process is immediately stopped. If the verify
+ callback fun returns {valid, UserState}, the verification
+ process is continued, this can be used to accept specific path
+ validation errors such as <c>selfsigned_peer</c> as well as
+ verifying application specific extensions. If called with an
+ extension unknown to the user application the return value
+ {unknown, UserState} should be used.</p>
+
+ </item>
+ <tag>{max_path_length, integer()}</tag>
+ <item>
+ The <c>max_path_length</c> is the maximum number of non-self-issued
+ intermediate certificates that may follow the peer certificate
+ in a valid certification path. So if <c>max_path_length</c> is 0 the PEER must
+ be signed by the trusted ROOT-CA directly, if 1 the path can
+ be PEER, CA, ROOT-CA, if it is 2 PEER, CA, CA, ROOT-CA and so
+ on.
+ </item>
+ </taglist>
+ </desc>
+ </func>
+
+ <func>
+ <name>pkix_crls_validate(OTPCertificate, DPAndCRLs, Options) -> CRLStatus()</name>
+ <fsummary> Performs CRL validation.</fsummary>
+ <type>
+ <v> OTPCertificate = #'OTPCertificate'{}</v>
+ <v> DPAndCRLs = [{DP::#'DistributionPoint'{} ,CRL::#'CertificateList'{}}] </v>
+ <v> Options = proplists:proplists()</v>
+ <v> CRLStatus() = valid | {bad_cert, revocation_status_undetermined} |
+ {bad_cert, {revoked, crl_reason()}}</v>
+ </type>
+ <desc>
+ <p> Performs CRL validation. It is intended to be called from
+ the verify fun of <seealso marker="public_key#pkix_path_validation-3"> pkix_path_validation/3
+ </seealso></p>
+ <taglist>
+ <p> Available options are: </p>
+ <tag>{update_crl, fun()}</tag>
+ <item>
+ <p>The fun has the following type spec:</p>
+
+ <code> fun(#'DistributionPoint'{}, #'CertificateList'{}) -> #'CertificateList'{}</code>
+
+ <p>The fun should use the information in the distribution point to acesses
+ the lates possible version of the CRL. If this fun is not specified
+ public_key will use the default implementation:
+ </p>
+ <code> fun(_DP, CRL) -> CRL end</code>
+ </item>
+ </taglist>
+ </desc>
+ </func>
-
<func>
<name>pkix_sign(#'OTPTBSCertificate'{}, Key) -> der_encode()</name>
<fsummary>Signs certificate.</fsummary>
@@ -389,7 +499,7 @@
<v>Key = rsa_public_key() | dsa_public_key()</v>
</type>
<desc>
- <p> Verify pkix x.509 certificate signature.</p>
+ <p> Verify PKIX x.509 certificate signature.</p>
</desc>
</func>
diff --git a/lib/public_key/doc/src/public_key_records.xml b/lib/public_key/doc/src/public_key_records.xml
index bb90290266..e39ad0ec64 100644
--- a/lib/public_key/doc/src/public_key_records.xml
+++ b/lib/public_key/doc/src/public_key_records.xml
@@ -1,11 +1,11 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE chapter SYSTEM "chapter.dtd">
<chapter>
<header>
<copyright>
<year>2008</year>
- <year>2011</year>
+ <year>2013</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -34,7 +34,7 @@
<file>public_key_records.xml</file>
</header>
- <p>This chapter briefly describes Erlang records derived from asn1
+ <p>This chapter briefly describes Erlang records derived from ASN1
specifications used to handle public and private keys. The intent
is to describe the data types and not to specify the meaning of
each component for this we refer you to the relevant standards and RFCs.</p>
@@ -67,9 +67,9 @@
}.
#'OtherPrimeInfo'{
- prime, % integer()
- exponent, % integer()
- coefficient % integer()
+ prime, % integer()
+ exponent, % integer()
+ coefficient % integer()
}.
</code>
diff --git a/lib/public_key/doc/src/using_public_key.xml b/lib/public_key/doc/src/using_public_key.xml
index f0eaeb8654..5d9f1536d9 100644
--- a/lib/public_key/doc/src/using_public_key.xml
+++ b/lib/public_key/doc/src/using_public_key.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2011</year><year>2011</year>
+ <year>2011</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -21,7 +21,7 @@
</legalnotice>
- <title>Using the public_key API</title>
+ <title>Getting Started</title>
<file>using_public_key.xml</file>
</header>
@@ -40,7 +40,7 @@
<section>
<title>PEM files</title>
- <p> Pulic key data (keys, certificates etc) may be stored in PEM format. PEM files
+ <p> Public key data (keys, certificates etc) may be stored in PEM format. PEM files
comes from the Private Enhanced Mail Internet standard and has a
structure that looks like this:</p>
@@ -63,7 +63,7 @@
<code>1> {ok, PemBin} = file:read_file("dsa.pem").
{ok,&lt;&lt;"-----BEGIN DSA PRIVATE KEY-----\nMIIBuw"...&gt;&gt;}</code>
- <p>This PEM file only has one entry a private DSA key.</p>
+ <p>This PEM file only has one entry, a private DSA key.</p>
<code>2> [DSAEntry] = public_key:pem_decode(PemBin).
[{'DSAPrivateKey',&lt;&lt;48,130,1,187,2,1,0,2,129,129,0,183,
179,230,217,37,99,144,157,21,228,204,
diff --git a/lib/public_key/include/public_key.hrl b/lib/public_key/include/public_key.hrl
index 90ca7256ea..4d1d510f29 100644
--- a/lib/public_key/include/public_key.hrl
+++ b/lib/public_key/include/public_key.hrl
@@ -68,17 +68,32 @@
-record(revoke_state, {
reasons_mask,
cert_status,
- interim_reasons_mask
+ interim_reasons_mask,
+ valid_ext
}).
+
+-define(unspecified, 0).
+-define(keyCompromise, 1).
+-define(cACompromise, 2).
+-define(affiliationChanged, 3).
+-define(superseded, 4).
+-define(cessationOfOperation, 5).
+-define(certificateHold, 6).
+-define(removeFromCRL, 8).
+-define(privilegeWithdrawn, 9).
+-define(aACompromise, 10).
+
-type public_key() :: rsa_public_key() | dsa_public_key().
-type rsa_public_key() :: #'RSAPublicKey'{}.
-type rsa_private_key() :: #'RSAPrivateKey'{}.
-type dsa_private_key() :: #'DSAPrivateKey'{}.
-type dsa_public_key() :: {integer(), #'Dss-Parms'{}}.
+-type der_encoded() :: binary().
+-type decrypt_der() :: binary().
-type pki_asn1_type() :: 'Certificate' | 'RSAPrivateKey' | 'RSAPublicKey'
| 'DSAPrivateKey' | 'DSAPublicKey' | 'DHParameter'
- | 'SubjectPublicKeyInfo' | 'CertificationRequest'.
+ | 'SubjectPublicKeyInfo' | 'CertificationRequest' | 'CertificateList'.
-type pem_entry() :: {pki_asn1_type(), binary(), %% DER or Encrypted DER
not_encrypted | {Cipher :: string(), Salt :: binary()}}.
-type asn1_type() :: atom(). %% see "OTP-PUB-KEY.hrl
diff --git a/lib/public_key/src/Makefile b/lib/public_key/src/Makefile
index d5cd13d81a..d24122221a 100644
--- a/lib/public_key/src/Makefile
+++ b/lib/public_key/src/Makefile
@@ -44,7 +44,8 @@ MODULES = \
pubkey_ssh \
pubkey_pbe \
pubkey_cert \
- pubkey_cert_records
+ pubkey_cert_records \
+ pubkey_crl
HRL_FILES = $(INCLUDE)/public_key.hrl
diff --git a/lib/public_key/src/pubkey_cert.erl b/lib/public_key/src/pubkey_cert.erl
index f9e2025479..f53c94b334 100644
--- a/lib/public_key/src/pubkey_cert.erl
+++ b/lib/public_key/src/pubkey_cert.erl
@@ -26,10 +26,11 @@
-export([init_validation_state/3, prepare_for_next_cert/2,
validate_time/3, validate_signature/6,
validate_issuer/4, validate_names/6,
- validate_revoked_status/3, validate_extensions/4,
+ validate_extensions/4,
normalize_general_name/1, digest_type/1, is_self_signed/1,
is_issuer/2, issuer_id/2, is_fixed_dh_cert/1,
- verify_data/1, verify_fun/4]).
+ verify_data/1, verify_fun/4, select_extension/2, match_name/3,
+ extensions_list/1, cert_auth_key_id/1, time_str_2_gregorian_sec/1]).
-define(NULL, 0).
@@ -204,17 +205,6 @@ validate_names(OtpCert, Permit, Exclude, Last, UserState, VerifyFun) ->
end.
%%--------------------------------------------------------------------
--spec validate_revoked_status(#'OTPCertificate'{}, term(), fun()) ->
- term().
-%%
-%% Description: Check if certificate has been revoked.
-%%--------------------------------------------------------------------
-validate_revoked_status(_OtpCert, UserState, _VerifyFun) ->
- %% TODO: Implement or leave for application?!
- %% valid |
- %% throw({bad_cert, cert_revoked})
- UserState.
-%%--------------------------------------------------------------------
-spec validate_extensions(#'OTPCertificate'{}, #path_validation_state{},
term(), fun())->
{#path_validation_state{}, UserState :: term()}.
@@ -256,8 +246,10 @@ is_self_signed(#'OTPCertificate'{tbsCertificate=
%%
%% Description: Checks if <Issuer> issued <Candidate>.
%%--------------------------------------------------------------------
-is_issuer({rdnSequence, Issuer}, {rdnSequence, Candidate}) ->
- is_dir_name(Issuer, Candidate, true).
+is_issuer({rdnSequence, _} = Issuer, {rdnSequence, _} = Candidate) ->
+ {rdnSequence, IssuerDirName} = normalize_general_name(Issuer),
+ {rdnSequence, CandidateDirName} = normalize_general_name(Candidate),
+ is_dir_name(IssuerDirName, CandidateDirName, true).
%%--------------------------------------------------------------------
-spec issuer_id(#'OTPCertificate'{}, self | other) ->
{ok, {integer(), term()}} | {error, issuer_not_found}.
@@ -307,9 +299,9 @@ verify_fun(Otpcert, Result, UserState0, VerifyFun) ->
{valid,UserState} ->
UserState;
{fail, Reason} ->
- case Result of
+ case Reason of
{bad_cert, _} ->
- throw(Result);
+ throw(Reason);
_ ->
throw({bad_cert, Reason})
end;
@@ -321,6 +313,91 @@ verify_fun(Otpcert, Result, UserState0, VerifyFun) ->
UserState
end
end.
+%%--------------------------------------------------------------------
+-spec select_extension(Oid ::tuple(),[#'Extension'{}]) ->
+ #'Extension'{} | undefined.
+%%
+%% Description: Extracts a specific extension from a list of extensions.
+%%--------------------------------------------------------------------
+select_extension(_, []) ->
+ undefined;
+select_extension(Id, [#'Extension'{extnID = Id} = Extension | _]) ->
+ Extension;
+select_extension(Id, [_ | Extensions]) ->
+ select_extension(Id, Extensions).
+
+%%--------------------------------------------------------------------
+%% TODO:
+%%
+%% Description:
+%%--------------------------------------------------------------------
+match_name(rfc822Name, Name, [PermittedName | Rest]) ->
+ match_name(fun is_valid_host_or_domain/2, Name, PermittedName, Rest);
+
+match_name(directoryName, DirName, [PermittedName | Rest]) ->
+ match_name(fun is_rdnSeq/2, DirName, PermittedName, Rest);
+
+match_name(uniformResourceIdentifier, URI, [PermittedName | Rest]) ->
+ case split_uri(URI) of
+ incomplete ->
+ false;
+ {_, _, Host, _, _} ->
+ match_name(fun is_valid_host_or_domain/2, Host,
+ PermittedName, Rest)
+ end;
+
+match_name(emailAddress, Name, [PermittedName | Rest]) ->
+ Fun = fun(Email, PermittedEmail) ->
+ is_valid_email_address(Email, PermittedEmail,
+ string:tokens(PermittedEmail,"@"))
+ end,
+ match_name(Fun, Name, PermittedName, Rest);
+
+match_name(dNSName, Name, [PermittedName | Rest]) ->
+ Fun = fun(Domain, [$.|Domain]) -> true;
+ (Name1,Name2) ->
+ lists:suffix(string:to_lower(Name2),
+ string:to_lower(Name1))
+ end,
+ match_name(Fun, Name, [$.|PermittedName], Rest);
+
+match_name(x400Address, OrAddress, [PermittedAddr | Rest]) ->
+ match_name(fun is_or_address/2, OrAddress, PermittedAddr, Rest);
+
+match_name(ipAdress, IP, [PermittedIP | Rest]) ->
+ Fun = fun([IP1, IP2, IP3, IP4],
+ [IP5, IP6, IP7, IP8, M1, M2, M3, M4]) ->
+ is_permitted_ip([IP1, IP2, IP3, IP4],
+ [IP5, IP6, IP7, IP8],
+ [M1, M2, M3, M4]);
+ ([IP1, IP2, IP3, IP4, IP5, IP6, IP7, IP8,
+ IP9, IP10, IP11, IP12, IP13, IP14, IP15, IP16],
+ [IP17, IP18, IP19, IP20, IP21, IP22, IP23, IP24,
+ IP25, IP26, IP27, IP28, IP29, IP30, IP31, IP32,
+ M1, M2, M3, M4, M5, M6, M7, M8,
+ M9, M10, M11, M12, M13, M14, M15, M16]) ->
+ is_permitted_ip([IP1, IP2, IP3, IP4, IP5, IP6, IP7, IP8,
+ IP9, IP10, IP11, IP12, IP13,
+ IP14, IP15, IP16],
+ [IP17, IP18, IP19, IP20, IP21, IP22, IP23,
+ IP24,IP25, IP26, IP27, IP28, IP29, IP30,
+ IP31, IP32],
+ [M1, M2, M3, M4, M5, M6, M7, M8, M9, M10,
+ M11, M12, M13, M14, M15, M16]);
+ (_,_) ->
+ false
+ end,
+ match_name(Fun, IP, PermittedIP, Rest).
+
+match_name(Fun, Name, PermittedName, []) ->
+ Fun(Name, PermittedName);
+match_name(Fun, Name, PermittedName, [Head | Tail]) ->
+ case Fun(Name, PermittedName) of
+ true ->
+ true;
+ false ->
+ match_name(Fun, Name, Head, Tail)
+ end.
%%--------------------------------------------------------------------
%%% Internal functions
@@ -332,7 +409,7 @@ do_normalize_general_name(Issuer) ->
(Atter) ->
Atter
end,
- lists:sort(lists:map(Normalize, Issuer)).
+ lists:map(Normalize, Issuer).
%% See rfc3280 4.1.2.6 Subject: regarding emails.
extract_email({rdnSequence, List}) ->
@@ -477,13 +554,6 @@ strip_spaces(String) ->
string:tokens(String, " ")),
string:strip(NewString).
-select_extension(_, []) ->
- undefined;
-select_extension(Id, [#'Extension'{extnID = Id} = Extension | _]) ->
- Extension;
-select_extension(Id, [_ | Extensions]) ->
- select_extension(Id, Extensions).
-
%% No extensions present
validate_extensions(OtpCert, asn1_NOVALUE, ValidationState, ExistBasicCon,
SelfSigned, UserState, VerifyFun) ->
@@ -503,18 +573,16 @@ validate_extensions(OtpCert, [], ValidationState =
true ->
{ValidationState#path_validation_state{max_path_length = Len - 1},
UserState0};
- %% basic_constraint must appear in certs used for digital sign
- %% see 4.2.1.10 in rfc 3280
false ->
- UserState = verify_fun(OtpCert, {bad_cert, missing_basic_constraint},
- UserState0, VerifyFun),
- case SelfSigned of
+ %% basic_constraint must appear in certs used for digital sign
+ %% see 4.2.1.10 in rfc 3280
+ case is_digitally_sign_cert(OtpCert) of
true ->
- {ValidationState, UserState};
- false ->
- {ValidationState#path_validation_state{max_path_length =
- Len - 1},
- UserState}
+ missing_basic_constraints(OtpCert, SelfSigned,
+ ValidationState, VerifyFun,
+ UserState0, Len);
+ false -> %% Example CRL signer only
+ {ValidationState, UserState0}
end
end;
@@ -861,74 +929,6 @@ type_subtree_names(Type, SubTrees) ->
[Name || #'GeneralSubtree'{base = {TreeType, Name}} <- SubTrees,
TreeType =:= Type].
-match_name(rfc822Name, Name, [PermittedName | Rest]) ->
- match_name(fun is_valid_host_or_domain/2, Name, PermittedName, Rest);
-
-match_name(directoryName, DirName, [PermittedName | Rest]) ->
- match_name(fun is_rdnSeq/2, DirName, PermittedName, Rest);
-
-match_name(uniformResourceIdentifier, URI, [PermittedName | Rest]) ->
- case split_uri(URI) of
- incomplete ->
- false;
- {_, _, Host, _, _} ->
- match_name(fun is_valid_host_or_domain/2, Host,
- PermittedName, Rest)
- end;
-
-match_name(emailAddress, Name, [PermittedName | Rest]) ->
- Fun = fun(Email, PermittedEmail) ->
- is_valid_email_address(Email, PermittedEmail,
- string:tokens(PermittedEmail,"@"))
- end,
- match_name(Fun, Name, PermittedName, Rest);
-
-match_name(dNSName, Name, [PermittedName | Rest]) ->
- Fun = fun(Domain, [$.|Domain]) -> true;
- (Name1,Name2) ->
- lists:suffix(string:to_lower(Name2),
- string:to_lower(Name1))
- end,
- match_name(Fun, Name, [$.|PermittedName], Rest);
-
-match_name(x400Address, OrAddress, [PermittedAddr | Rest]) ->
- match_name(fun is_or_address/2, OrAddress, PermittedAddr, Rest);
-
-match_name(ipAdress, IP, [PermittedIP | Rest]) ->
- Fun = fun([IP1, IP2, IP3, IP4],
- [IP5, IP6, IP7, IP8, M1, M2, M3, M4]) ->
- is_permitted_ip([IP1, IP2, IP3, IP4],
- [IP5, IP6, IP7, IP8],
- [M1, M2, M3, M4]);
- ([IP1, IP2, IP3, IP4, IP5, IP6, IP7, IP8,
- IP9, IP10, IP11, IP12, IP13, IP14, IP15, IP16],
- [IP17, IP18, IP19, IP20, IP21, IP22, IP23, IP24,
- IP25, IP26, IP27, IP28, IP29, IP30, IP31, IP32,
- M1, M2, M3, M4, M5, M6, M7, M8,
- M9, M10, M11, M12, M13, M14, M15, M16]) ->
- is_permitted_ip([IP1, IP2, IP3, IP4, IP5, IP6, IP7, IP8,
- IP9, IP10, IP11, IP12, IP13,
- IP14, IP15, IP16],
- [IP17, IP18, IP19, IP20, IP21, IP22, IP23,
- IP24,IP25, IP26, IP27, IP28, IP29, IP30,
- IP31, IP32],
- [M1, M2, M3, M4, M5, M6, M7, M8, M9, M10,
- M11, M12, M13, M14, M15, M16]);
- (_,_) ->
- false
- end,
- match_name(Fun, IP, PermittedIP, Rest).
-
-match_name(Fun, Name, PermittedName, []) ->
- Fun(Name, PermittedName);
-match_name(Fun, Name, PermittedName, [Head | Tail]) ->
- case Fun(Name, PermittedName) of
- true ->
- true;
- false ->
- match_name(Fun, Name, Head, Tail)
- end.
-
is_permitted_ip([], [], []) ->
true;
is_permitted_ip([CandidatIp | CandidatIpRest],
@@ -1037,3 +1037,25 @@ is_dh(?'dhpublicnumber')->
true;
is_dh(_) ->
false.
+
+is_digitally_sign_cert(OtpCert) ->
+ TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
+ Extensions = extensions_list(TBSCert#'OTPTBSCertificate'.extensions),
+ case pubkey_cert:select_extension(?'id-ce-keyUsage', Extensions) of
+ undefined ->
+ false;
+ #'Extension'{extnValue = KeyUse} ->
+ lists:member(keyCertSign, KeyUse)
+ end.
+
+missing_basic_constraints(OtpCert, SelfSigned, ValidationState, VerifyFun, UserState0,Len) ->
+ UserState = verify_fun(OtpCert, {bad_cert, missing_basic_constraint},
+ UserState0, VerifyFun),
+ case SelfSigned of
+ true ->
+ {ValidationState, UserState};
+ false ->
+ {ValidationState#path_validation_state{max_path_length =
+ Len - 1},
+ UserState}
+ end.
diff --git a/lib/public_key/src/pubkey_crl.erl b/lib/public_key/src/pubkey_crl.erl
new file mode 100644
index 0000000000..3e4c3c8b6d
--- /dev/null
+++ b/lib/public_key/src/pubkey_crl.erl
@@ -0,0 +1,701 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(pubkey_crl).
+
+-include("public_key.hrl").
+
+-export([validate/7, init_revokation_state/0, fresh_crl/3, verify_crl_signature/4,
+ is_delta_crl/1, combines/2, match_one/2]).
+
+-record(userstate, {dpcrls,
+ idp
+ }).
+
+validate(OtpCert, OtherDPCRLs, DP, {DerCRL, CRL}, {DerDeltaCRL, DeltaCRL},
+ Options, RevokedState0) ->
+ RevokedState =
+ case verify_crl(OtpCert, DP, CRL, DerCRL, DeltaCRL,
+ DerDeltaCRL, OtherDPCRLs, Options, RevokedState0) of
+ {valid, Revoked, DeltaRevoked, RevokedState1, IDP} ->
+ TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
+ SerialNumber = TBSCert#'OTPTBSCertificate'.serialNumber,
+ CertIssuer = TBSCert#'OTPTBSCertificate'.issuer,
+ TBSCRL = CRL#'CertificateList'.tbsCertList,
+ CRLIssuer = TBSCRL#'TBSCertList'.issuer,
+ AltNames = subject_alt_names(TBSCert#'OTPTBSCertificate'.extensions),
+ revoked_status(DP, IDP, {directoryName, CRLIssuer},
+ [ {directoryName, CertIssuer} | AltNames], SerialNumber, Revoked,
+ DeltaRevoked, RevokedState1);
+ {invalid, Revoked} ->
+ Revoked
+ end,
+ crl_status(RevokedState).
+
+init_revokation_state() ->
+ #revoke_state{reasons_mask = sets:new(),
+ interim_reasons_mask = sets:new(),
+ cert_status = unrevoked}.
+
+fresh_crl(_, {undefined, undefined}, _) ->
+ %% Typically happens when there is no delta CRL that covers a CRL
+ no_fresh_crl;
+
+fresh_crl(DP, {_, #'CertificateList'{tbsCertList = TBSCRL}} = CRL, CallBack) ->
+ Now = calendar:datetime_to_gregorian_seconds(calendar:universal_time()),
+ UpdateTime =
+ pubkey_cert:time_str_2_gregorian_sec(TBSCRL#'TBSCertList'.nextUpdate),
+ case Now >= UpdateTime of
+ true ->
+ case CallBack(DP, CRL) of
+ CRL ->
+ no_fresh_crl;
+ NewCRL ->
+ fresh_crl(DP, NewCRL, CallBack)
+ end;
+ false ->
+ {fresh, CRL}
+ end.
+
+is_delta_crl(#'CertificateList'{tbsCertList = TBSCRL}) ->
+ Extensions = TBSCRL#'TBSCertList'.crlExtensions,
+ case pubkey_cert:select_extension(?'id-ce-deltaCRLIndicator',
+ Extensions) of
+ undefined ->
+ false;
+ _ ->
+ true
+ end.
+
+combines(CRL, DeltaCRL) ->
+ check_crl_num(CRL, DeltaCRL) andalso
+ check_delta_issuer_and_scope(CRL, DeltaCRL).
+
+crl_status(State)->
+ %% Fun argument is to enable future implementation of CRL checking
+ %% that does not care about all possible reasons.
+ crl_status(State, fun all_reasons/0).
+
+crl_status({skip, #revoke_state{cert_status = Status} = RevokedState}, _) ->
+ {undetermined, status(Status), RevokedState};
+
+crl_status(#revoke_state{cert_status = unrevoked = Status,
+ valid_ext = false} = RevokedState, _) ->
+ {undetermined, Status, RevokedState};
+
+crl_status(#revoke_state{cert_status = Status,
+ valid_ext = false}, _) ->
+ {finished, status(Status)};
+
+crl_status(#revoke_state{reasons_mask = Mask,
+ cert_status = Status,
+ valid_ext = true} = RevokedState, Fun) ->
+ case is_all_reasons(Mask, Fun) of
+ true ->
+ {finished, status(Status)};
+ false when (Status == unrevoked) ->
+ {undetermined, Status, RevokedState};
+ _ ->
+ {finished ,status(Status)}
+ end.
+
+verify_crl(OtpCert, DP, CRL, DerCRL, DeltaCRL, DerDeltaCRL, OtherDPCRLs,
+ Options, State0) ->
+ #'CertificateList'{tbsCertList =
+ #'TBSCertList'{crlExtensions = Extensions,
+ revokedCertificates = TmpRevoked}
+ } = CRL,
+ Revoked = revoked(TmpRevoked),
+ IDP = issuing_distribution_point(Extensions),
+
+ DeltaRevoked = delta_revoked(DeltaCRL),
+
+ ValidExt = verify_extensions(Extensions) and
+ verify_extensions(Revoked),
+
+ IntMask = compute_interim_reasons_mask(DP, IDP),
+
+ RevokedState =
+ State0#revoke_state{interim_reasons_mask = IntMask,
+ valid_ext = ValidExt},
+
+ {Fun, AdditionalArgs} = IssuerFun = proplists:get_value(issuer_fun, Options),
+
+ try verify_issuer_and_scope(OtpCert, DP, IDP, CRL) of
+ {ok, Issuer} ->
+ case Fun(DP, CRL, Issuer, AdditionalArgs) of
+ {ok, TrustedOtpCert, Path} ->
+ verify_mask_and_signatures(Revoked, DeltaRevoked,
+ RevokedState,
+ CRL, DerCRL, DeltaCRL, DerDeltaCRL,
+ IssuerFun, TrustedOtpCert, Path, OtherDPCRLs, IDP);
+ _ ->
+ {invalid, State0#revoke_state{valid_ext = ValidExt}}
+ end;
+ {error, issuer_not_found} ->
+ case Fun(DP, CRL, issuer_not_found, AdditionalArgs) of
+ {ok, TrustedOtpCert, Path} ->
+ verify_mask_and_signatures(Revoked, DeltaRevoked,
+ RevokedState, CRL, DerCRL, DeltaCRL,
+ DerDeltaCRL, IssuerFun,
+ TrustedOtpCert, Path, OtherDPCRLs, IDP);
+ _ ->
+ {invalid, {skip, State0}}
+ end
+ catch
+ throw:{bad_crl, invalid_issuer} ->
+ {invalid, {skip, State0}};
+ throw:_ ->
+ {invalid, State0#revoke_state{valid_ext = ValidExt}}
+ end.
+
+verify_mask_and_signatures(Revoked, DeltaRevoked, RevokedState, CRL, DerCRL, DeltaCRL, DerDeltaCRL,
+ IssuerFun, TrustedOtpCert, Path, OtherDPCRLs, IDP) ->
+
+ ReasonsMask = sets:union(RevokedState#revoke_state.reasons_mask,
+ RevokedState#revoke_state.interim_reasons_mask),
+ try
+ verify_interim_reasons_mask(RevokedState),
+ true = verify_crl_signatures(CRL, DerCRL, DeltaCRL, DerDeltaCRL,
+ TrustedOtpCert, Path, IssuerFun, OtherDPCRLs, IDP),
+ {valid, Revoked, DeltaRevoked, RevokedState#revoke_state{reasons_mask = ReasonsMask}, IDP}
+ catch
+ throw:_ ->
+ {invalid, RevokedState};
+ error:{badmatch, _} ->
+ {invalid, RevokedState}
+ end.
+
+
+verify_crl_signatures(CRL, DerCRL, DeltaCRL, DerDeltaCRL, TrustedOtpCert, Path,
+ IssuerFun, OtherDPCRLs, IDP) ->
+ try
+ VerifyFunAndState =
+ {fun(_, {bad_cert, _} = Reason, _UserState) ->
+ {fail, Reason};
+ (_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (_Cert, valid, UserState) ->
+ {valid, UserState};
+ (Cert, valid_peer, UserState) ->
+ case verify_crl_keybit(Cert, cRLSign) of
+ true ->
+ handle_crlsigner(Cert, IssuerFun, UserState);
+ false ->
+ {fail, crl_sign_bit_not_set}
+ end
+ end, #userstate{dpcrls = OtherDPCRLs, idp = IDP}},
+
+ {ok, {{_,Key, KeyParams},_}} =
+ public_key:pkix_path_validation(TrustedOtpCert, Path,
+ [{verify_fun, VerifyFunAndState}]),
+ true = verify_crl_signature(CRL, DerCRL, Key, KeyParams),
+ true = verify_crl_signature(DeltaCRL, DerDeltaCRL, Key, KeyParams)
+ catch
+ error:{badmatch, _} ->
+ false
+ end.
+
+handle_crlsigner(OtpCert, IssuerFun, #userstate{idp = IDP} = UserState) ->
+ case verify_crl_keybit(OtpCert, keyCertSign) of
+ true ->
+ {valid, UserState};
+ false ->
+ case not is_indirect_crl(IDP) andalso not public_key:pkix_is_self_signed(OtpCert) of
+ true ->
+ validate_crl_signing_cert(OtpCert, IssuerFun, UserState);
+ false ->
+ {valid, UserState}
+ end
+ end.
+
+validate_crl_signing_cert(_, _,#userstate{dpcrls = []} = UserState) ->
+ {valid, UserState};
+validate_crl_signing_cert(OtpCert, IssuerFun, #userstate{dpcrls = CRLInfo} = UserState) ->
+ case public_key:pkix_crls_validate(OtpCert, CRLInfo, [{issuer_fun, IssuerFun}]) of
+ valid ->
+ {valid, UserState};
+ Reason ->
+ {fail, Reason}
+ end.
+
+delta_revoked(undefined)->
+ [];
+delta_revoked(#'CertificateList'{tbsCertList =
+ #'TBSCertList'{revokedCertificates
+ = DeltaRevoked}}) ->
+ revoked(DeltaRevoked).
+
+revoked(asn1_NOVALUE) ->
+ [];
+revoked(Revoked) ->
+ Revoked.
+
+revoked_status(DP, IDP, CRLIssuer, Names, SerialNumber, Revoked, DeltaRevoked, RevokedState0) ->
+ DefaultIssuer0 = default_issuer(CRLIssuer, DeltaRevoked),
+ RevokedState1 = check_revoked(DP, IDP, DefaultIssuer0, Names, SerialNumber, DeltaRevoked, RevokedState0),
+ RevokedState = case RevokedState1#revoke_state.cert_status of
+ unrevoked when RevokedState1#revoke_state.cert_status =/= removeFromCRL ->
+ DefaultIssuer = default_issuer(CRLIssuer, Revoked),
+ check_revoked(DP, IDP, DefaultIssuer, Names, SerialNumber,
+ Revoked, RevokedState1);
+ _ ->
+ RevokedState1
+ end,
+ case RevokedState#revoke_state.cert_status of
+ removeFromCRL ->
+ RevokedState#revoke_state{cert_status = unrevoked};
+ _ ->
+ RevokedState
+ end.
+
+default_issuer(_, []) ->
+ undefined;
+default_issuer(Default, [#'TBSCertList_revokedCertificates_SEQOF'{crlEntryExtensions = Extensions}| _]) ->
+ case extension_value(?'id-ce-certificateIssuer', 'GeneralNames', Extensions) of
+ undefined ->
+ [pubkey_cert_records:transform(Default, decode)];
+ GeneralNames ->
+ gen_names(GeneralNames)
+ end.
+
+is_all_reasons(Mask, AllReasonsFun) ->
+ AllReasons = AllReasonsFun(),
+ case sets:is_subset(AllReasons, Mask) of
+ true ->
+ true;
+ false ->
+ %% As the "uspecified" reason should not
+ %% be explicitly used according to RFC 3280
+ %% and the conformance tests have test cases
+ %% that should succed, and that does not specify
+ %% "unspecified", we tolorate that it is not included.
+ sets:is_subset(sets:del_element(unspecified, AllReasons), Mask)
+ end.
+
+all_reasons() ->
+ sets:from_list([unspecified, keyCompromise,
+ cACompromise, affiliationChanged, superseded,
+ cessationOfOperation, certificateHold,
+ privilegeWithdrawn, aACompromise]).
+
+verify_issuer_and_scope(#'OTPCertificate'{tbsCertificate = TBSCert} = Cert,
+ #'DistributionPoint'{cRLIssuer = DPIssuer} = DP, IDP,
+ #'CertificateList'{tbsCertList = TBSCRL} = CRL)
+ when DPIssuer =/= asn1_NOVALUE ->
+ CRLIssuer = pubkey_cert_records:transform(TBSCRL#'TBSCertList'.issuer, decode),
+ Issuer = dp_crlissuer_to_issuer(DPIssuer),
+ case pubkey_cert:is_issuer(Issuer, CRLIssuer) and is_indirect_crl(IDP) of
+ true ->
+ verify_scope(Cert, DP, IDP),
+ issuer_id(Cert, CRL);
+ false ->
+ %% otherwise verify that the CRL issuer matches the certificate issuer
+ verify_issuer_and_scope(Cert, DP#'DistributionPoint'{
+ distributionPoint = [TBSCert#'OTPTBSCertificate'.issuer],
+ cRLIssuer = asn1_NOVALUE},
+ IDP, CRL)
+ end;
+verify_issuer_and_scope(#'OTPCertificate'{tbsCertificate = TBSCert}= Cert,
+ DP, IDP,
+ #'CertificateList'{tbsCertList = TBSCRL}) ->
+ CRLIssuer = pubkey_cert_records:transform(TBSCRL#'TBSCertList'.issuer, decode),
+ CertIssuer = TBSCert#'OTPTBSCertificate'.issuer,
+ case pubkey_cert:is_issuer(CertIssuer, CRLIssuer) of
+ true ->
+ verify_scope(Cert, DP, IDP),
+ issuer_id(Cert);
+ false ->
+ throw({bad_crl, invalid_issuer})
+ end.
+
+dp_crlissuer_to_issuer(DPCRLIssuer) ->
+ [{directoryName, Issuer}] = pubkey_cert_records:transform(DPCRLIssuer, decode),
+ Issuer.
+
+is_indirect_crl(#'IssuingDistributionPoint'{indirectCRL = Value})->
+ Value;
+is_indirect_crl(_) ->
+ false.
+
+verify_scope(_,_, undefined) ->
+ ok;
+verify_scope(#'OTPCertificate'{tbsCertificate = TBSCert}, #'DistributionPoint'{cRLIssuer = DPIssuer} = DP, IDP) ->
+ CertIssuer = TBSCert#'OTPTBSCertificate'.issuer,
+ Names = case gen_names(DPIssuer) of
+ [{directoryName, TNames}] ->
+ TNames;
+ Other ->
+ Other
+ end,
+ DPName = dp_names(DP#'DistributionPoint'.distributionPoint, Names, CertIssuer),
+ IDPName = dp_names(IDP#'IssuingDistributionPoint'.distributionPoint, Names, CertIssuer),
+ verify_scope(DPName, IDPName, Names, TBSCert, IDP).
+
+verify_scope(asn1_NOVALUE, _, asn1_NOVALUE, _, _) ->
+ throw({bad_crl, scope_error1});
+verify_scope(asn1_NOVALUE, IDPName, DPIssuerNames, TBSCert, IDP) ->
+ verify_dp_name(IDPName, DPIssuerNames),
+ verify_dp_bools(TBSCert, IDP);
+
+verify_scope(DPName, IDPName, _, TBSCert, IDP) ->
+ verify_dp_name(IDPName, DPName),
+ verify_dp_bools(TBSCert, IDP).
+
+dp_names(asn1_NOVALUE, _, _) ->
+ asn1_NOVALUE;
+dp_names({fullName, Name}, _, _) ->
+ gen_names(Name);
+dp_names({nameRelativeToCRLIssuer, Fragment}, asn1_NOVALUE, {rdnSequence, RelativeDestinguistNames}) ->
+ [{directoryName, {rdnSequence, RelativeDestinguistNames ++
+ [lists:map(fun(AttrAndValue) ->
+ pubkey_cert_records:transform(AttrAndValue, decode)
+ end, Fragment)]}}];
+dp_names({nameRelativeToCRLIssuer, Fragment},{rdnSequence, RelativeDestinguistNames}, _) ->
+ [{directoryName, {rdnSequence, RelativeDestinguistNames ++
+ [lists:map(fun(AttrAndValue) ->
+ pubkey_cert_records:transform(AttrAndValue, decode)
+ end, Fragment)]}}];
+dp_names([{rdnSequence, _}] = Name0, _,_) ->
+ [Name] = pubkey_cert_records:transform(Name0, decode),
+ [{directoryName, Name}].
+
+gen_names(asn1_NOVALUE) ->
+ asn1_NOVALUE;
+gen_names([]) ->
+ [];
+gen_names([{NameType, Name} | Rest]) ->
+ [ {NameType, pubkey_cert_records:transform(Name, decode)} | gen_names(Rest)].
+
+verify_dp_name(asn1_NOVALUE, _) ->
+ ok;
+
+verify_dp_name(IDPNames, DPorIssuerNames) ->
+ case match_one(DPorIssuerNames, IDPNames) of
+ true ->
+ ok;
+ false ->
+ throw({bad_crl, scope_error})
+ end.
+
+match_one([], _) ->
+ false;
+match_one([{Type, Name} | Names], CandidateNames) ->
+ Candidates = [NameName || {NameType, NameName} <- CandidateNames, NameType == Type],
+ case Candidates of
+ [] ->
+ false;
+ [_|_] -> case pubkey_cert:match_name(Type, Name, Candidates) of
+ true ->
+ true;
+ false ->
+ match_one(Names, CandidateNames)
+ end
+ end.
+
+verify_dp_bools(TBSCert, IDP) ->
+ BasicConstraints =
+ pubkey_cert:select_extension(?'id-ce-basicConstraints',
+ TBSCert#'OTPTBSCertificate'.extensions),
+
+ case verify_onlyContainsUserCerts(BasicConstraints, IDP) andalso
+ verify_onlyContainsCACerts(BasicConstraints, IDP) andalso
+ verify_onlyContainsAttributeCerts(IDP) of
+ true ->
+ ok;
+ _ ->
+ throw({bad_crl, scope_error})
+ end.
+
+verify_onlyContainsUserCerts(
+ #'Extension'{extnValue = #'BasicConstraints'{cA = true}},
+ #'IssuingDistributionPoint'{onlyContainsUserCerts = true}) ->
+ false;
+verify_onlyContainsUserCerts(_,_) ->
+ true.
+
+verify_onlyContainsCACerts(
+ #'Extension'{extnValue = #'BasicConstraints'{cA = true}},
+ #'IssuingDistributionPoint'{onlyContainsCACerts = true}) ->
+ true;
+verify_onlyContainsCACerts(_,#'IssuingDistributionPoint'{onlyContainsCACerts = true}) ->
+ false;
+verify_onlyContainsCACerts(_,_) ->
+ true.
+
+verify_onlyContainsAttributeCerts(
+ #'IssuingDistributionPoint'{onlyContainsAttributeCerts = Bool}) ->
+ not Bool.
+
+check_crl_num(#'CertificateList'{tbsCertList = TBSCRL},
+ #'CertificateList'{tbsCertList = TBSDeltaCRL})->
+ Extensions = TBSCRL#'TBSCertList'.crlExtensions,
+ DeltaExtensions = TBSDeltaCRL#'TBSCertList'.crlExtensions,
+
+ try
+ CRLNum = assert_extension_value(?'id-ce-cRLNumber', 'CRLNumber', Extensions),
+ DeltaBaseNum = assert_extension_value(?'id-ce-deltaCRLIndicator',
+ 'CRLNumber', DeltaExtensions),
+ DeltaCRLNum = assert_extension_value(?'id-ce-cRLNumber', 'CRLNumber', DeltaExtensions),
+ (CRLNum >= DeltaBaseNum) andalso (CRLNum < DeltaCRLNum)
+ catch
+ throw:no_extension_present ->
+ false
+ end;
+check_crl_num(_,_) ->
+ false.
+
+
+extension_value(Extension, ExtType, Extensions) ->
+ case pubkey_cert:select_extension(Extension, Extensions) of
+ #'Extension'{extnValue = Value} ->
+ public_key:der_decode(ExtType, list_to_binary(Value));
+ _ ->
+ undefined
+ end.
+
+
+assert_extension_value(Extension, ExtType, Extensions) ->
+ case extension_value(Extension, ExtType, Extensions) of
+ undefined ->
+ throw(no_extension_present);
+ Value ->
+ Value
+ end.
+
+check_delta_issuer_and_scope(_, undefined) ->
+ true;
+check_delta_issuer_and_scope(#'CertificateList'{tbsCertList = TBSCRL},
+ #'CertificateList'{tbsCertList = TBSDeltaCRL}) ->
+ case pubkey_cert:is_issuer(TBSCRL#'TBSCertList'.issuer,
+ TBSDeltaCRL#'TBSCertList'.issuer) of
+ true ->
+ check_delta_scope(TBSCRL, TBSDeltaCRL);
+ false ->
+ false
+ end.
+
+check_delta_scope(#'TBSCertList'{crlExtensions = Extensions},
+ #'TBSCertList'{crlExtensions = DeltaExtensions})->
+ IDP = issuing_distribution_point(Extensions),
+ DeltaIDP = issuing_distribution_point(DeltaExtensions),
+
+ AuthKey = authority_key_identifier(Extensions),
+ DeltaAuthKey = authority_key_identifier(DeltaExtensions),
+ is_match(IDP, DeltaIDP) andalso is_match(AuthKey, DeltaAuthKey).
+
+is_match(X, X) ->
+ true;
+is_match(_,_) ->
+ false.
+
+compute_interim_reasons_mask(#'DistributionPoint'{reasons = asn1_NOVALUE},
+ #'IssuingDistributionPoint'{onlySomeReasons =
+ asn1_NOVALUE}) ->
+ all_reasons();
+compute_interim_reasons_mask(#'DistributionPoint'{reasons = asn1_NOVALUE},
+ undefined) ->
+ all_reasons();
+
+compute_interim_reasons_mask(#'DistributionPoint'{reasons = asn1_NOVALUE},
+ #'IssuingDistributionPoint'{onlySomeReasons =
+ IDPReasons}) ->
+ sets:from_list(IDPReasons);
+compute_interim_reasons_mask(#'DistributionPoint'{reasons = DPReasons},
+ #'IssuingDistributionPoint'{onlySomeReasons =
+ asn1_NOVALUE}) ->
+ sets:from_list(DPReasons);
+compute_interim_reasons_mask(#'DistributionPoint'{reasons = DPReasons},
+ undefined) ->
+ sets:from_list(DPReasons);
+compute_interim_reasons_mask(#'DistributionPoint'{reasons = DPReasons},
+ #'IssuingDistributionPoint'{onlySomeReasons =
+ IDPReasons}) ->
+ sets:intersection(sets:from_list(DPReasons), sets:from_list(IDPReasons)).
+
+verify_interim_reasons_mask(#revoke_state{reasons_mask = Mask,
+ interim_reasons_mask = IntMask}) ->
+ case sets:fold(fun(Element, Acc) ->
+ case sets:is_element(Element, Mask) of
+ true ->
+ Acc;
+ false ->
+ true
+ end
+ end, false, IntMask) of
+ true ->
+ ok;
+ false ->
+ throw({bad_crl, mask_error})
+ end.
+
+verify_crl_signature(undefined, undefined, _,_) ->
+ true;
+verify_crl_signature(CRL, DerCRL, Key, KeyParams) ->
+ {DigestType, PlainText, Signature} = extract_crl_verify_data(CRL, DerCRL),
+ case Key of
+ #'RSAPublicKey'{} ->
+ public_key:verify(PlainText, DigestType, Signature, Key);
+ _ ->
+ public_key:verify(PlainText, DigestType, Signature,
+ {Key, KeyParams})
+ end.
+extract_crl_verify_data(CRL, DerCRL) ->
+ {0, Signature} = CRL#'CertificateList'.signature,
+ #'AlgorithmIdentifier'{algorithm = SigAlg} =
+ CRL#'CertificateList'.signatureAlgorithm,
+ PlainText = encoded_tbs_crl(DerCRL),
+ DigestType = pubkey_cert:digest_type(SigAlg),
+ {DigestType, PlainText, Signature}.
+
+encoded_tbs_crl(CRL) ->
+ {ok, PKIXCRL} =
+ 'OTP-PUB-KEY':decode_TBSCertList_exclusive(CRL),
+ {'CertificateList',
+ {'CertificateList_tbsCertList', EncodedTBSCertList}, _, _} = PKIXCRL,
+ EncodedTBSCertList.
+
+check_revoked(_,_,_,_,_,[], State) ->
+ State;
+check_revoked(#'DistributionPoint'{cRLIssuer = DPIssuer} = DP, IDP, DefaultIssuer0, Names, SerialNr,
+ [#'TBSCertList_revokedCertificates_SEQOF'{userCertificate =
+ SerialNr,
+ crlEntryExtensions =
+ Extensions}| Rest],
+ State) ->
+ Reason = revoked_reason(Extensions),
+ case (DPIssuer =/= asn1_NOVALUE) and is_indirect_crl(IDP) of
+ true ->
+ handle_indirect_crl_check(DP, IDP, DefaultIssuer0, Names, SerialNr, Extensions, Reason, Rest, State);
+ false ->
+ State#revoke_state{cert_status = Reason}
+ end;
+
+check_revoked(DP, IDP, DefaultIssuer0, Names, SerialNr,
+ [#'TBSCertList_revokedCertificates_SEQOF'{crlEntryExtensions =
+ Extensions}| Rest], State) ->
+ DefaultIssuer = case extension_value(?'id-ce-certificateIssuer', 'GeneralNames', Extensions) of
+ undefined ->
+ DefaultIssuer0;
+ GeneralNames ->
+ gen_names(GeneralNames)
+ end,
+ check_revoked(DP, IDP, DefaultIssuer, Names, SerialNr, Rest, State).
+
+handle_indirect_crl_check(DP, IDP, DefaultIssuer0, Names, SerialNr, Extensions, Reason, Rest, State) ->
+ case check_crl_issuer_extension(Names, Extensions, DefaultIssuer0) of
+ {true, _} ->
+ State#revoke_state{cert_status = Reason};
+ {false, DefaultIssuer} ->
+ check_revoked(DP, IDP, DefaultIssuer, Names, SerialNr, Rest, State)
+ end.
+
+check_crl_issuer_extension(Names, Extensions, Default0) ->
+ case extension_value(?'id-ce-certificateIssuer', 'GeneralNames', Extensions) of
+ undefined ->
+ {match_one(Default0, Names), Default0};
+ GeneralNames ->
+ Default = gen_names(GeneralNames),
+ {match_one(Default, Names), Default}
+ end.
+
+revoked_reason(Extensions) ->
+ case extension_value(?'id-ce-cRLReasons', 'CRLReason', Extensions) of
+ undefined ->
+ unspecified;
+ Value ->
+ Value
+ end.
+
+verify_crl_keybit(#'OTPCertificate'{tbsCertificate = TBS}, Bit) ->
+ case pubkey_cert:select_extension( ?'id-ce-keyUsage',
+ TBS#'OTPTBSCertificate'.extensions) of
+ #'Extension'{extnID = ?'id-ce-keyUsage',
+ extnValue = KeyUse} ->
+ lists:member(Bit, KeyUse);
+ _ ->
+ true
+ end.
+
+issuer_id(Cert, #'CertificateList'{tbsCertList = TBSCRL}) ->
+ Extensions =
+ pubkey_cert:extensions_list(TBSCRL#'TBSCertList'.crlExtensions),
+ case authority_key_identifier(Extensions) of
+ undefined ->
+ issuer_id(Cert);
+ #'AuthorityKeyIdentifier'{authorityCertIssuer = asn1_NOVALUE,
+ authorityCertSerialNumber = asn1_NOVALUE} ->
+ issuer_id(Cert);
+ #'AuthorityKeyIdentifier'{authorityCertIssuer = Issuer,
+ authorityCertSerialNumber = Nr} ->
+ {ok, {Nr, Issuer}}
+ end.
+
+issuer_id(#'OTPCertificate'{} = Cert) ->
+ case public_key:pkix_is_self_signed(Cert) of
+ true ->
+ public_key:pkix_issuer_id(Cert, self);
+ false ->
+ public_key:pkix_issuer_id(Cert, other)
+ end.
+
+status(unrevoked) ->
+ unrevoked;
+status(Reason) ->
+ {revoked, Reason}.
+
+verify_extensions([#'TBSCertList_revokedCertificates_SEQOF'{crlEntryExtensions = Ext} | Rest]) ->
+ verify_extensions(pubkey_cert:extensions_list(Ext)) and verify_extensions(Rest);
+verify_extensions([]) ->
+ true;
+verify_extensions([#'Extension'{critical = true, extnID = Id} | Rest]) ->
+ case lists:member(Id, [?'id-ce-authorityKeyIdentifier',
+ ?'id-ce-issuerAltName',
+ ?'id-ce-cRLNumber',
+ ?'id-ce-certificateIssuer',
+ ?'id-ce-deltaCRLIndicator',
+ ?'id-ce-issuingDistributionPoint',
+ ?'id-ce-freshestCRL']) of
+ true ->
+ verify_extensions(Rest);
+ false ->
+ false
+ end;
+verify_extensions([_Ext | Rest]) ->
+ verify_extensions(Rest).
+
+issuing_distribution_point(Extensions) ->
+ Enc = extension_value(?'id-ce-issuingDistributionPoint',
+ 'IssuingDistributionPoint', Extensions),
+ pubkey_cert_records:transform(Enc, decode).
+
+authority_key_identifier(Extensions) ->
+ Enc = extension_value(?'id-ce-authorityKeyIdentifier',
+ 'AuthorityKeyIdentifier', Extensions),
+ pubkey_cert_records:transform(Enc, decode).
+
+subject_alt_names(Extensions) ->
+ Enc = extension_value(?'id-ce-subjectAltName',
+ 'GeneralNames', Extensions),
+ case Enc of
+ undefined ->
+ [];
+ _ ->
+ pubkey_cert_records:transform(Enc, decode)
+ end.
diff --git a/lib/public_key/src/pubkey_pem.erl b/lib/public_key/src/pubkey_pem.erl
index 4012825f20..6bdc35fb79 100644
--- a/lib/public_key/src/pubkey_pem.erl
+++ b/lib/public_key/src/pubkey_pem.erl
@@ -167,6 +167,8 @@ split_lines(Bin) ->
%% Ignore white space at end of line
join_entry([<<"-----END ", _/binary>>| Lines], Entry) ->
{lists:reverse(Entry), Lines};
+join_entry([<<"-----END X509 CRL-----", _/binary>>| Lines], Entry) ->
+ {lists:reverse(Entry), Lines};
join_entry([Line | Lines], Entry) ->
join_entry(Lines, [Line | Entry]).
@@ -198,7 +200,9 @@ pem_start('DHParameter') ->
pem_start('CertificationRequest') ->
<<"-----BEGIN CERTIFICATE REQUEST-----">>;
pem_start('ContentInfo') ->
- <<"-----BEGIN PKCS7-----">>.
+ <<"-----BEGIN PKCS7-----">>;
+pem_start('CertificateList') ->
+ <<"-----BEGIN X509 CRL-----">>.
pem_end(<<"-----BEGIN CERTIFICATE-----">>) ->
<<"-----END CERTIFICATE-----">>;
@@ -220,6 +224,8 @@ pem_end(<<"-----BEGIN CERTIFICATE REQUEST-----">>) ->
<<"-----END CERTIFICATE REQUEST-----">>;
pem_end(<<"-----BEGIN PKCS7-----">>) ->
<<"-----END PKCS7-----">>;
+pem_end(<<"-----BEGIN X509 CRL-----">>) ->
+ <<"-----END X509 CRL-----">>;
pem_end(_) ->
undefined.
@@ -242,7 +248,9 @@ asn1_type(<<"-----BEGIN ENCRYPTED PRIVATE KEY-----">>) ->
asn1_type(<<"-----BEGIN CERTIFICATE REQUEST-----">>) ->
'CertificationRequest';
asn1_type(<<"-----BEGIN PKCS7-----">>) ->
- 'ContentInfo'.
+ 'ContentInfo';
+asn1_type(<<"-----BEGIN X509 CRL-----">>) ->
+ 'CertificateList'.
pem_decrypt() ->
<<"Proc-Type: 4,ENCRYPTED">>.
diff --git a/lib/public_key/src/public_key.app.src b/lib/public_key/src/public_key.app.src
index 4cc81ea573..9f0677606d 100644
--- a/lib/public_key/src/public_key.app.src
+++ b/lib/public_key/src/public_key.app.src
@@ -7,6 +7,7 @@
pubkey_ssh,
pubkey_cert,
pubkey_cert_records,
+ pubkey_crl,
'OTP-PUB-KEY',
'PKCS-FRAME'
]},
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index d5df53e848..5686920dd4 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -42,7 +42,8 @@
pkix_issuer_id/2,
pkix_normalize_name/1,
pkix_path_validation/3,
- ssh_decode/2, ssh_encode/2
+ ssh_decode/2, ssh_encode/2,
+ pkix_crls_validate/3
]).
-type rsa_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding'
@@ -50,6 +51,8 @@
-type public_crypt_options() :: [{rsa_pad, rsa_padding()}].
-type rsa_digest_type() :: 'md5' | 'sha'| 'sha224' | 'sha256' | 'sha384' | 'sha512'.
-type dss_digest_type() :: 'none' | 'sha'. %% None is for backwards compatibility
+-type crl_reason() :: unspecified | keyCompromise | cACompromise | affiliationChanged | superseded
+ | cessationOfOperation | certificateHold | privilegeWithdrawn | aACompromise.
-define(UINT32(X), X:32/unsigned-big-integer).
-define(DER_NULL, <<5, 0>>).
@@ -428,9 +431,9 @@ pkix_verify(DerCert, #'RSAPublicKey'{} = RSAKey)
verify(PlainText, DigestType, Signature, RSAKey).
%%--------------------------------------------------------------------
--spec pkix_is_issuer(Cert::binary()| #'OTPCertificate'{},
- IssuerCert::binary()|
- #'OTPCertificate'{}) -> boolean().
+-spec pkix_is_issuer(Cert :: der_encoded()| #'OTPCertificate'{} | #'CertificateList'{},
+ IssuerCert :: der_encoded()|
+ #'OTPCertificate'{}) -> boolean().
%%
%% Description: Checks if <IssuerCert> issued <Cert>.
%%--------------------------------------------------------------------
@@ -443,7 +446,11 @@ pkix_is_issuer(Cert, IssuerCert) when is_binary(IssuerCert) ->
pkix_is_issuer(#'OTPCertificate'{tbsCertificate = TBSCert},
#'OTPCertificate'{tbsCertificate = Candidate}) ->
pubkey_cert:is_issuer(TBSCert#'OTPTBSCertificate'.issuer,
- Candidate#'OTPTBSCertificate'.subject).
+ Candidate#'OTPTBSCertificate'.subject);
+pkix_is_issuer(#'CertificateList'{tbsCertList = TBSCRL},
+ #'OTPCertificate'{tbsCertificate = Candidate}) ->
+ pubkey_cert:is_issuer(Candidate#'OTPTBSCertificate'.subject,
+ pubkey_cert_records:transform(TBSCRL#'TBSCertList'.issuer, decode)).
%%--------------------------------------------------------------------
-spec pkix_is_self_signed(Cert::binary()| #'OTPCertificate'{}) -> boolean().
@@ -502,7 +509,7 @@ pkix_normalize_name(Issuer) ->
%%--------------------------------------------------------------------
-spec pkix_path_validation(Cert::binary()| #'OTPCertificate'{} | atom(),
CertChain :: [binary()] ,
- Options :: list()) ->
+ Options :: proplist:proplist()) ->
{ok, {PublicKeyInfo :: term(),
PolicyTree :: term()}} |
{error, {bad_cert, Reason :: term()}}.
@@ -511,7 +518,7 @@ pkix_normalize_name(Issuer) ->
pkix_path_validation(PathErr, [Cert | Chain], Options0) when is_atom(PathErr)->
{VerifyFun, Userstat0} =
proplists:get_value(verify_fun, Options0, ?DEFAULT_VERIFYFUN),
- Otpcert = pkix_decode_cert(Cert, otp),
+ Otpcert = otp_cert(Cert),
Reason = {bad_cert, PathErr},
try VerifyFun(Otpcert, Reason, Userstat0) of
{valid, Userstate} ->
@@ -537,6 +544,27 @@ pkix_path_validation(#'OTPCertificate'{} = TrustedCert, CertChain, Options)
Options),
path_validation(CertChain, ValidationState).
+%--------------------------------------------------------------------
+-spec pkix_crls_validate(#'OTPCertificate'{},
+ [{DP::#'DistributionPoint'{} ,CRL::#'CertificateList'{}}],
+ Options :: proplist:proplist()) -> valid | {bad_cert, revocation_status_undetermined}
+ | {bad_cert, {revoked, crl_reason()}}.
+
+%% Description: Performs a basic path validation according to RFC 5280.
+%%--------------------------------------------------------------------
+pkix_crls_validate(OtpCert, [{_,_,_} |_] = DPAndCRLs, Options) ->
+ pkix_crls_validate(OtpCert, DPAndCRLs, DPAndCRLs,
+ Options, pubkey_crl:init_revokation_state());
+
+pkix_crls_validate(OtpCert, DPAndCRLs0, Options) ->
+ CallBack = proplists:get_value(update_crl, Options, fun(_, CurrCRL) ->
+ CurrCRL
+ end),
+ DPAndCRLs = sort_dp_crls(DPAndCRLs0, CallBack),
+ pkix_crls_validate(OtpCert, DPAndCRLs, DPAndCRLs,
+ Options, pubkey_crl:init_revokation_state()).
+
+
%%--------------------------------------------------------------------
-spec ssh_decode(binary(), public_key | ssh_file()) -> [{public_key(), Attributes::list()}].
%%
@@ -611,12 +639,13 @@ path_validation([DerCert | Rest], ValidationState = #path_validation_state{
{error, Reason}
end;
-path_validation([DerCert | _] = Path,
+path_validation([Cert | _] = Path,
#path_validation_state{user_state = UserState0,
verify_fun = VerifyFun} =
ValidationState) ->
Reason = {bad_cert, max_path_length_reached},
- OtpCert = pkix_decode_cert(DerCert, otp),
+ OtpCert = otp_cert(Cert),
+
try VerifyFun(OtpCert, Reason, UserState0) of
{valid, UserState} ->
path_validation(Path,
@@ -630,7 +659,7 @@ path_validation([DerCert | _] = Path,
{error, Reason}
end.
-validate(DerCert, #path_validation_state{working_issuer_name = Issuer,
+validate(Cert, #path_validation_state{working_issuer_name = Issuer,
working_public_key = Key,
working_public_key_parameters =
KeyParams,
@@ -641,31 +670,31 @@ validate(DerCert, #path_validation_state{working_issuer_name = Issuer,
verify_fun = VerifyFun} =
ValidationState0) ->
- OtpCert = pkix_decode_cert(DerCert, otp),
+ OtpCert = otp_cert(Cert),
- UserState1 = pubkey_cert:validate_time(OtpCert, UserState0, VerifyFun),
+ {ValidationState1, UserState1} =
+ pubkey_cert:validate_extensions(OtpCert, ValidationState0, UserState0,
+ VerifyFun),
- UserState2 = pubkey_cert:validate_issuer(OtpCert, Issuer, UserState1, VerifyFun),
+ %% We want the key_usage extension to be checked before we validate
+ %% other things so that CRL validation errors will comply to standard
+ %% test suite description
- UserState3 = pubkey_cert:validate_names(OtpCert, Permit, Exclude, Last,
- UserState2,VerifyFun),
+ UserState2 = pubkey_cert:validate_time(OtpCert, UserState1, VerifyFun),
- UserState4 = pubkey_cert:validate_revoked_status(OtpCert, UserState3, VerifyFun),
-
- {ValidationState1, UserState5} =
- pubkey_cert:validate_extensions(OtpCert, ValidationState0, UserState4,
- VerifyFun),
+ UserState3 = pubkey_cert:validate_issuer(OtpCert, Issuer, UserState2, VerifyFun),
- %% We want the key_usage extension to be checked before we validate
- %% the signature.
- UserState6 = pubkey_cert:validate_signature(OtpCert, DerCert,
- Key, KeyParams, UserState5, VerifyFun),
+ UserState4 = pubkey_cert:validate_names(OtpCert, Permit, Exclude, Last,
+ UserState3, VerifyFun),
+
+ UserState5 = pubkey_cert:validate_signature(OtpCert, der_cert(Cert),
+ Key, KeyParams, UserState4, VerifyFun),
UserState = case Last of
false ->
- pubkey_cert:verify_fun(OtpCert, valid, UserState6, VerifyFun);
+ pubkey_cert:verify_fun(OtpCert, valid, UserState5, VerifyFun);
true ->
pubkey_cert:verify_fun(OtpCert, valid_peer,
- UserState6, VerifyFun)
+ UserState5, VerifyFun)
end,
ValidationState =
@@ -676,3 +705,110 @@ validate(DerCert, #path_validation_state{working_issuer_name = Issuer,
sized_binary(Binary) ->
Size = size(Binary),
<<?UINT32(Size), Binary/binary>>.
+
+otp_cert(Der) when is_binary(Der) ->
+ pkix_decode_cert(Der, otp);
+otp_cert(#'OTPCertificate'{} =Cert) ->
+ Cert.
+
+der_cert(#'OTPCertificate'{} = Cert) ->
+ pkix_encode('OTPCertificate', Cert, otp);
+der_cert(Der) when is_binary(Der) ->
+ Der.
+
+pkix_crls_validate(_, [],_, _, _) ->
+ {bad_cert, revocation_status_undetermined};
+pkix_crls_validate(OtpCert, [{DP, CRL, DeltaCRL} | Rest], All, Options, RevokedState0) ->
+ CallBack = proplists:get_value(update_crl, Options, fun(_, CurrCRL) ->
+ CurrCRL
+ end),
+ case pubkey_crl:fresh_crl(DP, CRL, CallBack) of
+ {fresh, CRL} ->
+ do_pkix_crls_validate(OtpCert, [{DP, CRL, DeltaCRL} | Rest],
+ All, Options, RevokedState0);
+ {fresh, NewCRL} ->
+ NewAll = [{DP, NewCRL, DeltaCRL} | All -- [{DP, CRL, DeltaCRL}]],
+ do_pkix_crls_validate(OtpCert, [{DP, NewCRL, DeltaCRL} | Rest],
+ NewAll, Options, RevokedState0);
+ no_fresh_crl ->
+ pkix_crls_validate(OtpCert, Rest, All, Options, RevokedState0)
+ end.
+
+do_pkix_crls_validate(OtpCert, [{DP, CRL, DeltaCRL} | Rest], All, Options, RevokedState0) ->
+ OtherDPCRLs = All -- [{DP, CRL, DeltaCRL}],
+ case pubkey_crl:validate(OtpCert, OtherDPCRLs, DP, CRL, DeltaCRL, Options, RevokedState0) of
+ {undetermined, _, _} when Rest == []->
+ {bad_cert, revocation_status_undetermined};
+ {undetermined, _, RevokedState} when Rest =/= []->
+ pkix_crls_validate(OtpCert, Rest, All, Options, RevokedState);
+ {finished, unrevoked} ->
+ valid;
+ {finished, Status} ->
+ {bad_cert, Status}
+ end.
+
+sort_dp_crls(DpsAndCrls, FreshCB) ->
+ Sorted = do_sort_dp_crls(DpsAndCrls, dict:new()),
+ sort_crls(Sorted, FreshCB, []).
+
+do_sort_dp_crls([], Dict) ->
+ dict:to_list(Dict);
+do_sort_dp_crls([{DP, CRL} | Rest], Dict0) ->
+ Dict = try dict:fetch(DP, Dict0) of
+ _ ->
+ dict:append(DP, CRL, Dict0)
+ catch _:_ ->
+ dict:store(DP, [CRL], Dict0)
+ end,
+ do_sort_dp_crls(Rest, Dict).
+
+sort_crls([], _, Acc) ->
+ Acc;
+
+sort_crls([{DP, AllCRLs} | Rest], FreshCB, Acc)->
+ {DeltaCRLs, CRLs} = do_sort_crls(AllCRLs),
+ DpsAndCRLs = combine(CRLs, DeltaCRLs, DP, FreshCB, []),
+ sort_crls(Rest, FreshCB, DpsAndCRLs ++ Acc).
+
+do_sort_crls(CRLs) ->
+ lists:partition(fun({_, CRL}) ->
+ pubkey_crl:is_delta_crl(CRL)
+ end, CRLs).
+
+combine([], _,_,_,Acc) ->
+ Acc;
+combine([{_, CRL} = Entry | CRLs], DeltaCRLs, DP, FreshCB, Acc) ->
+ DeltaCRL = combine(CRL, DeltaCRLs),
+ case pubkey_crl:fresh_crl(DP, DeltaCRL, FreshCB) of
+ no_fresh_crl ->
+ combine(CRLs, DeltaCRLs, DP, FreshCB, [{DP, Entry, {undefined, undefined}} | Acc]);
+ {fresh, NewDeltaCRL} ->
+ combine(CRLs, DeltaCRLs, DP, FreshCB, [{DP, Entry, NewDeltaCRL} | Acc])
+ end.
+
+combine(CRL, DeltaCRLs) ->
+ Deltas = lists:filter(fun({_,DeltaCRL}) ->
+ pubkey_crl:combines(CRL, DeltaCRL)
+ end, DeltaCRLs),
+ case Deltas of
+ [] ->
+ {undefined, undefined};
+ [Delta] ->
+ Delta;
+ [_,_|_] ->
+ Fun =
+ fun({_, #'CertificateList'{tbsCertList = FirstTBSCRL}} = CRL1,
+ {_, #'CertificateList'{tbsCertList = SecondTBSCRL}} = CRL2) ->
+ Time1 = pubkey_cert:time_str_2_gregorian_sec(
+ FirstTBSCRL#'TBSCertList'.thisUpdate),
+ Time2 = pubkey_cert:time_str_2_gregorian_sec(
+ SecondTBSCRL#'TBSCertList'.thisUpdate),
+ case Time1 > Time2 of
+ true ->
+ CRL1;
+ false ->
+ CRL2
+ end
+ end,
+ lists:foldl(Fun, hd(Deltas), tl(Deltas))
+ end.
diff --git a/lib/public_key/test/erl_make_certs.erl b/lib/public_key/test/erl_make_certs.erl
index d6bdd05d01..95e288cd71 100644
--- a/lib/public_key/test/erl_make_certs.erl
+++ b/lib/public_key/test/erl_make_certs.erl
@@ -234,7 +234,7 @@ extensions(Opts) ->
end.
default_extensions(Exts) ->
- Def = [{key_usage,undefined},
+ Def = [{key_usage, default},
{subject_altname, undefined},
{issuer_altname, undefined},
{basic_constraints, default},
@@ -265,6 +265,11 @@ extension({basic_constraints, Data}) ->
#'Extension'{extnID = ?'id-ce-basicConstraints',
extnValue = Data}
end;
+
+extension({key_usage, default}) ->
+ #'Extension'{extnID = ?'id-ce-keyUsage',
+ extnValue = [keyCertSign], critical = true};
+
extension({Id, Data, Critical}) ->
#'Extension'{extnID = Id, extnValue = Data, critical = Critical}.
diff --git a/lib/public_key/test/pbe_SUITE.erl b/lib/public_key/test/pbe_SUITE.erl
index 380a67db7b..8fba1e8cd3 100644
--- a/lib/public_key/test/pbe_SUITE.erl
+++ b/lib/public_key/test/pbe_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,72 +19,16 @@
-module(pbe_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include_lib("public_key/include/public_key.hrl").
%% Note: This directive should only be used in test suites.
-compile(export_all).
-%% Test server callback functions
-%%--------------------------------------------------------------------
-%% Function: init_per_suite(Config) -> Config
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Initialization before the whole suite
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
-init_per_suite(Config) ->
- try crypto:start() of
- ok ->
- Config
- catch _:_ ->
- {skip, "Crypto did not start"}
- end.
-%%--------------------------------------------------------------------
-%% Function: end_per_suite(Config) -> _
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after the whole suite
-%%--------------------------------------------------------------------
-end_per_suite(_Config) ->
- application:stop(crypto).
-
-%%--------------------------------------------------------------------
-%% Function: init_per_testcase(TestCase, Config) -> Config
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%%
-%% Description: Initialization before each test case
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%% Description: Initialization before each test case
-%%--------------------------------------------------------------------
-init_per_testcase(_TestCase, Config) ->
- Config.
%%--------------------------------------------------------------------
-%% Function: end_per_testcase(TestCase, Config) -> _
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after each test case
+%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
-end_per_testcase(_TestCase, _Config) ->
- ok.
-%%--------------------------------------------------------------------
-%% Function: all(Clause) -> TestCases
-%% Clause - atom() - suite | doc
-%% TestCases - [Case]
-%% Case - atom()
-%% Name of a test case.
-%% Description: Returns a list of all test cases in this test suite
-%%--------------------------------------------------------------------
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
@@ -96,17 +40,40 @@ all() ->
groups() ->
[].
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ try crypto:start() of
+ ok ->
+ Config
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ application:stop(crypto).
+
+%%--------------------------------------------------------------------
+
init_per_group(_GroupName, Config) ->
Config.
end_per_group(_GroupName, Config) ->
Config.
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+
+end_per_testcase(_TestCase, _Config) ->
+ ok.
-%% Test cases starts here.
%%--------------------------------------------------------------------
-pbdkdf1(doc) ->
- ["Test with PKCS #5 PBKDF1 Test Vectors"];
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+pbdkdf1() ->
+ [{doc,"Test with PKCS #5 PBKDF1 Test Vectors"}].
pbdkdf1(Config) when is_list(Config) ->
%%Password = "password"
%% = (0x)70617373776F7264
@@ -126,8 +93,8 @@ pbdkdf1(Config) when is_list(Config) ->
16#4A, 16#3D, 16#2A, 16#20, _/binary>> =
pubkey_pbe:pbdkdf1(Password, Salt, Count, sha).
-pbdkdf2(doc) ->
- ["Test with PKCS #5 PBKDF2 Test Vectors"];
+pbdkdf2() ->
+ [{doc,"Test with PKCS #5 PBKDF2 Test Vectors"}].
pbdkdf2(Config) when is_list(Config) ->
%% Input:
%% P = "password" (8 octets)
@@ -225,28 +192,28 @@ pbdkdf2(Config) when is_list(Config) ->
= pubkey_pbe:pbdkdf2("pass\0word",
"sa\0lt", 4096, 16, fun crypto:sha_mac/3, 20).
-encrypted_private_key_info(doc) ->
- ["Tests reading a EncryptedPrivateKeyInfo file encrypted with different ciphers"];
+encrypted_private_key_info() ->
+ [{doc,"Tests reading a EncryptedPrivateKeyInfo file encrypted with different ciphers"}].
encrypted_private_key_info(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
{ok, PemDes} = file:read_file(filename:join(Datadir, "des_cbc_enc_key.pem")),
PemDesEntry = public_key:pem_decode(PemDes),
- test_server:format("Pem entry: ~p" , [PemDesEntry]),
+ ct:print("Pem entry: ~p" , [PemDesEntry]),
[{'PrivateKeyInfo', _, {"DES-CBC",_}} = PubEntry0] = PemDesEntry,
KeyInfo = public_key:pem_entry_decode(PubEntry0, "password"),
{ok, Pem3Des} = file:read_file(filename:join(Datadir, "des_ede3_cbc_enc_key.pem")),
Pem3DesEntry = public_key:pem_decode(Pem3Des),
- test_server:format("Pem entry: ~p" , [Pem3DesEntry]),
+ ct:print("Pem entry: ~p" , [Pem3DesEntry]),
[{'PrivateKeyInfo', _, {"DES-EDE3-CBC",_}} = PubEntry1] = Pem3DesEntry,
KeyInfo = public_key:pem_entry_decode(PubEntry1, "password"),
{ok, PemRc2} = file:read_file(filename:join(Datadir, "rc2_cbc_enc_key.pem")),
PemRc2Entry = public_key:pem_decode(PemRc2),
- test_server:format("Pem entry: ~p" , [PemRc2Entry]),
+ ct:print("Pem entry: ~p" , [PemRc2Entry]),
[{'PrivateKeyInfo', _, {"RC2-CBC",_}} = PubEntry2] = PemRc2Entry,
KeyInfo = public_key:pem_entry_decode(PubEntry2, "password"),
diff --git a/lib/public_key/test/pkits_SUITE.erl b/lib/public_key/test/pkits_SUITE.erl
index e59f299399..d901adaadd 100644
--- a/lib/public_key/test/pkits_SUITE.erl
+++ b/lib/public_key/test/pkits_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -23,16 +23,18 @@
-module(pkits_SUITE).
--compile(export_all).
-
-include_lib("public_key/include/public_key.hrl").
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
-define(error(Format,Args), error(Format,Args,?FILE,?LINE)).
-define(warning(Format,Args), warning(Format,Args,?FILE,?LINE)).
-define(CERTS, "pkits/certs").
-define(MIME, "pkits/smime").
-define(CONV, "pkits/smime-pem").
+-define(CRL, "pkits/crls").
-define(NIST1, "2.16.840.1.101.3.2.1.48.1").
-define(NIST2, "2.16.840.1.101.3.2.1.48.2").
@@ -42,10 +44,13 @@
-define(NIST6, "2.16.840.1.101.3.2.1.48.6").
-record(verify_state, {
- certs_db,
- crl_info,
+ crls,
+ crl_paths,
revoke_state}).
-%%
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+
suite() ->
[{ct_hooks,[ts_install_cth]}].
@@ -54,9 +59,9 @@ all() ->
{group, validity_periods},
{group, verifying_name_chaining},
{group, verifying_paths_with_self_issued_certificates},
- %%{group, basic_certificate_revocation_tests},
- %%{group, delta_crls},
- %%{group, distribution_points},
+ {group, basic_certificate_revocation_tests},
+ {group, delta_crls},
+ {group, distribution_points},
{group, verifying_basic_constraints},
{group, key_usage},
{group, name_constraints},
@@ -72,20 +77,22 @@ groups() ->
[invalid_name_chain, whitespace_name_chain, capitalization_name_chain,
uid_name_chain, attrib_name_chain, string_name_chain]},
{verifying_paths_with_self_issued_certificates, [],
- [basic_valid, %%basic_invalid,
- crl_signing_valid, crl_signing_invalid]},
- %% {basic_certificate_revocation_tests, [],
- %% [missing_CRL, revoked_CA, revoked_peer, invalid_CRL_signature,
- %% invalid_CRL_issuer, invalid_CRL, valid_CRL,
- %% unknown_CRL_extension, old_CRL, fresh_CRL, valid_serial,
- %% invalid_serial, valid_seperate_keys, invalid_separate_keys]},
- %% {delta_crls, [], [delta_without_crl, valid_delta_crls, invalid_delta_crls]},
- %% {distribution_points, [], [valid_distribution_points,
- %% valid_distribution_points_no_issuing_distribution_point,
- %% invalid_distribution_points, valid_only_contains,
- %% invalid_only_contains, valid_only_some_reasons,
- %% invalid_only_some_reasons, valid_indirect_crl,
- %% invalid_indirect_crl, valid_crl_issuer, invalid_crl_issuer]},
+ [basic_valid, basic_invalid, crl_signing_valid, crl_signing_invalid]},
+ {basic_certificate_revocation_tests, [],
+ [missing_CRL,
+ revoked_CA,
+ revoked_peer,
+ invalid_CRL_signature,
+ invalid_CRL_issuer, invalid_CRL, valid_CRL,
+ unknown_CRL_extension, old_CRL, fresh_CRL, valid_serial,
+ invalid_serial, valid_seperate_keys, invalid_separate_keys]},
+ {delta_crls, [], [delta_without_crl, valid_delta_crls, invalid_delta_crls]},
+ {distribution_points, [], [valid_distribution_points,
+ valid_distribution_points_no_issuing_distribution_point,
+ invalid_distribution_points, valid_only_contains,
+ invalid_only_contains, valid_only_some_reasons,
+ invalid_only_some_reasons, valid_indirect_crl,
+ invalid_indirect_crl, valid_crl_issuer, invalid_crl_issuer]},
{verifying_basic_constraints,[],
[missing_basic_constraints, valid_basic_constraint, invalid_path_constraints,
valid_path_constraints]},
@@ -102,12 +109,25 @@ groups() ->
[unknown_critical_extension, unknown_not_critical_extension]}
].
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ try crypto:start() of
+ ok ->
+ crypto_support_check(Config)
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ application:stop(crypto).
+
+%%--------------------------------------------------------------------
init_per_group(_GroupName, Config) ->
Config.
end_per_group(_GroupName, Config) ->
Config.
-
+%%--------------------------------------------------------------------
init_per_testcase(_Func, Config) ->
Datadir = proplists:get_value(data_dir, Config),
put(datadir, Datadir),
@@ -116,143 +136,105 @@ init_per_testcase(_Func, Config) ->
end_per_testcase(_Func, Config) ->
Config.
-init_per_suite(Config) ->
- try crypto:start() of
- ok ->
- crypto_support_check(Config)
- catch _:_ ->
- {skip, "Crypto did not start"}
- end.
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
-end_per_suite(_Config) ->
- application:stop(crypto).
-
-%%-----------------------------------------------------------------------------
-valid_rsa_signature(doc) ->
- ["Test rsa signatur verification"];
-valid_rsa_signature(suite) ->
- [];
+%%--------------------------- signature_verification--------------------------------------------------
+valid_rsa_signature() ->
+ [{doc, "Test rsa signatur verification"}].
valid_rsa_signature(Config) when is_list(Config) ->
run([{ "4.1.1", "Valid Certificate Path Test1 EE", ok}]).
-invalid_rsa_signature(doc) ->
- ["Test rsa signatur verification"];
-invalid_rsa_signature(suite) ->
- [];
+invalid_rsa_signature() ->
+ [{doc,"Test rsa signatur verification"}].
invalid_rsa_signature(Config) when is_list(Config) ->
run([{ "4.1.2", "Invalid CA Signature Test2 EE", {bad_cert,invalid_signature}},
{ "4.1.3", "Invalid EE Signature Test3 EE", {bad_cert,invalid_signature}}]).
-valid_dsa_signature(doc) ->
- ["Test dsa signatur verification"];
-valid_dsa_signature(suite) ->
- [];
+valid_dsa_signature() ->
+ [{doc,"Test dsa signatur verification"}].
valid_dsa_signature(Config) when is_list(Config) ->
run([{ "4.1.4", "Valid DSA Signatures Test4 EE", ok},
{ "4.1.5", "Valid DSA Parameter Inheritance Test5 EE", ok}]).
-invalid_dsa_signature(doc) ->
- ["Test dsa signatur verification"];
-invalid_dsa_signature(suite) ->
- [];
+invalid_dsa_signature() ->
+ [{doc,"Test dsa signatur verification"}].
invalid_dsa_signature(Config) when is_list(Config) ->
run([{ "4.1.6", "Invalid DSA Signature Test6 EE",{bad_cert,invalid_signature}}]).
-%%-----------------------------------------------------------------------------
-not_before_invalid(doc) ->
- [""];
-not_before_invalid(suite) ->
- [];
+
+%%-----------------------------validity_periods------------------------------------------------
+not_before_invalid() ->
+ [{doc,"Test valid periods"}].
not_before_invalid(Config) when is_list(Config) ->
run([{ "4.2.1", "Invalid CA notBefore Date Test1 EE",{bad_cert, cert_expired}},
{ "4.2.2", "Invalid EE notBefore Date Test2 EE",{bad_cert, cert_expired}}]).
-not_before_valid(doc) ->
- [""];
-not_before_valid(suite) ->
- [];
+not_before_valid() ->
+ [{doc,"Test valid periods"}].
not_before_valid(Config) when is_list(Config) ->
run([{ "4.2.3", "Valid pre2000 UTC notBefore Date Test3 EE", ok},
{ "4.2.4", "Valid GeneralizedTime notBefore Date Test4 EE", ok}]).
-not_after_invalid(doc) ->
- [""];
-not_after_invalid(suite) ->
- [];
+not_after_invalid() ->
+ [{doc,"Test valid periods"}].
not_after_invalid(Config) when is_list(Config) ->
run([{ "4.2.5", "Invalid CA notAfter Date Test5 EE", {bad_cert, cert_expired}},
{ "4.2.6", "Invalid EE notAfter Date Test6 EE", {bad_cert, cert_expired}},
{ "4.2.7", "Invalid pre2000 UTC EE notAfter Date Test7 EE",{bad_cert, cert_expired}}]).
-not_after_valid(doc) ->
- [""];
-not_after_valid(suite) ->
- [];
+not_after_valid() ->
+ [{doc,"Test valid periods"}].
not_after_valid(Config) when is_list(Config) ->
run([{ "4.2.8", "Valid GeneralizedTime notAfter Date Test8 EE", ok}]).
-%%-----------------------------------------------------------------------------
-invalid_name_chain(doc) ->
- [""];
-invalid_name_chain(suite) ->
- [];
+
+%%----------------------------verifying_name_chaining-------------------------------------------------
+invalid_name_chain() ->
+ [{doc,"Test name chaining"}].
invalid_name_chain(Config) when is_list(Config) ->
run([{ "4.3.1", "Invalid Name Chaining Test1 EE", {bad_cert, invalid_issuer}},
{ "4.3.2", "Invalid Name Chaining Order Test2 EE", {bad_cert, invalid_issuer}}]).
-whitespace_name_chain(doc) ->
- [""];
-whitespace_name_chain(suite) ->
- [];
+whitespace_name_chain() ->
+ [{doc,"Test name chaining"}].
whitespace_name_chain(Config) when is_list(Config) ->
run([{ "4.3.3", "Valid Name Chaining Whitespace Test3 EE", ok},
{ "4.3.4", "Valid Name Chaining Whitespace Test4 EE", ok}]).
-capitalization_name_chain(doc) ->
- [""];
-capitalization_name_chain(suite) ->
- [];
+capitalization_name_chain() ->
+ [{doc,"Test name chaining"}].
capitalization_name_chain(Config) when is_list(Config) ->
run([{ "4.3.5", "Valid Name Chaining Capitalization Test5 EE",ok}]).
-uid_name_chain(doc) ->
- [""];
-uid_name_chain(suite) ->
- [];
+uid_name_chain() ->
+ [{doc,"Test name chaining"}].
uid_name_chain(Config) when is_list(Config) ->
run([{ "4.3.6", "Valid Name UIDs Test6 EE",ok}]).
-attrib_name_chain(doc) ->
- [""];
-attrib_name_chain(suite) ->
- [];
+attrib_name_chain() ->
+ [{doc,"Test name chaining"}].
attrib_name_chain(Config) when is_list(Config) ->
run([{ "4.3.7", "Valid RFC3280 Mandatory Attribute Types Test7 EE", ok},
{ "4.3.8", "Valid RFC3280 Optional Attribute Types Test8 EE", ok}]).
-string_name_chain(doc) ->
- [""];
-string_name_chain(suite) ->
- [];
+string_name_chain() ->
+ [{doc,"Test name chaining"}].
string_name_chain(Config) when is_list(Config) ->
run([{ "4.3.9", "Valid UTF8String Encoded Names Test9 EE", ok},
%%{ "4.3.10", "Valid Rollover from PrintableString to UTF8String Test10 EE", ok},
{ "4.3.11", "Valid UTF8String Case Insensitive Match Test11 EE", ok}]).
-%%-----------------------------------------------------------------------------
-
-basic_valid(doc) ->
- [""];
-basic_valid(suite) ->
- [];
+%%----------------------------verifying_paths_with_self_issued_certificates-------------------------------------------------
+basic_valid() ->
+ [{doc,"Test self issued certificates"}].
basic_valid(Config) when is_list(Config) ->
run([{ "4.5.1", "Valid Basic Self-Issued Old With New Test1 EE", ok},
{ "4.5.3", "Valid Basic Self-Issued New With Old Test3 EE", ok},
{ "4.5.4", "Valid Basic Self-Issued New With Old Test4 EE", ok}
]).
-basic_invalid(doc) ->
- [""];
-basic_invalid(suite) ->
- [];
+basic_invalid() ->
+ [{doc,"Test self issued certificates"}].
basic_invalid(Config) when is_list(Config) ->
run([{"4.5.2", "Invalid Basic Self-Issued Old With New Test2 EE",
{bad_cert, {revoked, keyCompromise}}},
@@ -260,84 +242,63 @@ basic_invalid(Config) when is_list(Config) ->
{bad_cert, {revoked, keyCompromise}}}
]).
-crl_signing_valid(doc) ->
- [""];
-crl_signing_valid(suite) ->
- [];
+crl_signing_valid() ->
+ [{doc,"Test self issued certificates"}].
crl_signing_valid(Config) when is_list(Config) ->
run([{ "4.5.6", "Valid Basic Self-Issued CRL Signing Key Test6 EE", ok}]).
-crl_signing_invalid(doc) ->
- [""];
-crl_signing_invalid(suite) ->
- [];
+crl_signing_invalid() ->
+ [{doc,"Test self issued certificates"}].
crl_signing_invalid(Config) when is_list(Config) ->
- run([%% { "4.5.7", "Invalid Basic Self-Issued CRL Signing Key Test7 EE",
- %% {bad_cert, {revoked, keyCompromise}}},
+ run([{ "4.5.7", "Invalid Basic Self-Issued CRL Signing Key Test7 EE",
+ {bad_cert, {revoked, keyCompromise}}},
{ "4.5.8", "Invalid Basic Self-Issued CRL Signing Key Test8 EE",
{bad_cert, invalid_key_usage}}
]).
-%%-----------------------------------------------------------------------------
-missing_CRL(doc) ->
- [""];
-missing_CRL(suite) ->
- [];
+%%-----------------------------basic_certificate_revocation_tests------------------------------------------------
+missing_CRL() ->
+ [{doc,"Test basic CRL handling"}].
missing_CRL(Config) when is_list(Config) ->
- run([{ "4.4.1", "Missing CRL Test1 EE",{bad_cert,
+ run([{ "4.4.1", "Invalid Missing CRL Test1 EE",{bad_cert,
revocation_status_undetermined}}]).
-revoked_CA(doc) ->
- [""];
-revoked_CA(suite) ->
- [];
+revoked_CA() ->
+ [{doc,"Test basic CRL handling"}].
revoked_CA(Config) when is_list(Config) ->
run([{ "4.4.2", "Invalid Revoked CA Test2 EE", {bad_cert,
{revoked, keyCompromise}}}]).
-revoked_peer(doc) ->
- [""];
-revoked_peer(suite) ->
- [];
+revoked_peer() ->
+ [{doc,"Test basic CRL handling"}].
revoked_peer(Config) when is_list(Config) ->
- run([{ "4.4.3", "Invalid Revoked EE Test3 EE", {bad_cert,
- {revoked, keyCompromise}}}]).
+ run([{ "4.4.3", "Invalid Revoked EE Test3 EE",
+ {bad_cert, {revoked, keyCompromise}}}]).
-invalid_CRL_signature(doc) ->
- [""];
-invalid_CRL_signature(suite) ->
- [];
+invalid_CRL_signature() ->
+ [{doc,"Test basic CRL handling"}].
invalid_CRL_signature(Config) when is_list(Config) ->
run([{ "4.4.4", "Invalid Bad CRL Signature Test4 EE",
- {bad_cert, revocation_status_undetermined}}]).
-
-invalid_CRL_issuer(doc) ->
- [""];
-invalid_CRL_issuer(suite) ->
- [];
+ {bad_cert, revocation_status_undetermined}}]).
+invalid_CRL_issuer() ->
+ [{doc,"Test basic CRL handling"}].
invalid_CRL_issuer(Config) when is_list(Config) ->
run({ "4.4.5", "Invalid Bad CRL Issuer Name Test5 EE",
{bad_cert, revocation_status_undetermined}}).
-invalid_CRL(doc) ->
- [""];
-invalid_CRL(suite) ->
- [];
+invalid_CRL() ->
+ [{doc,"Test basic CRL handling"}].
invalid_CRL(Config) when is_list(Config) ->
run([{ "4.4.6", "Invalid Wrong CRL Test6 EE",
{bad_cert, revocation_status_undetermined}}]).
-valid_CRL(doc) ->
- [""];
-valid_CRL(suite) ->
- [];
+valid_CRL() ->
+ [{doc,"Test basic CRL handling"}].
valid_CRL(Config) when is_list(Config) ->
run([{ "4.4.7", "Valid Two CRLs Test7 EE", ok}]).
-unknown_CRL_extension(doc) ->
- [""];
-unknown_CRL_extension(suite) ->
- [];
+unknown_CRL_extension() ->
+ [{doc,"Test basic CRL handling"}].
unknown_CRL_extension(Config) when is_list(Config) ->
run([{ "4.4.8", "Invalid Unknown CRL Entry Extension Test8 EE",
{bad_cert, {revoked, keyCompromise}}},
@@ -346,27 +307,21 @@ unknown_CRL_extension(Config) when is_list(Config) ->
{ "4.4.10", "Invalid Unknown CRL Extension Test10 EE",
{bad_cert, revocation_status_undetermined}}]).
-old_CRL(doc) ->
- [""];
-old_CRL(suite) ->
- [];
+old_CRL() ->
+ [{doc,"Test basic CRL handling"}].
old_CRL(Config) when is_list(Config) ->
run([{ "4.4.11", "Invalid Old CRL nextUpdate Test11 EE",
{bad_cert, revocation_status_undetermined}},
{ "4.4.12", "Invalid pre2000 CRL nextUpdate Test12 EE",
{bad_cert, revocation_status_undetermined}}]).
-fresh_CRL(doc) ->
- [""];
-fresh_CRL(suite) ->
- [];
+fresh_CRL() ->
+ [{doc,"Test basic CRL handling"}].
fresh_CRL(Config) when is_list(Config) ->
run([{ "4.4.13", "Valid GeneralizedTime CRL nextUpdate Test13 EE", ok}]).
-valid_serial(doc) ->
- [""];
-valid_serial(suite) ->
- [];
+valid_serial() ->
+ [{doc,"Test basic CRL handling"}].
valid_serial(Config) when is_list(Config) ->
run([
{ "4.4.14", "Valid Negative Serial Number Test14 EE",ok},
@@ -374,38 +329,30 @@ valid_serial(Config) when is_list(Config) ->
{ "4.4.17", "Valid Long Serial Number Test17 EE", ok}
]).
-invalid_serial(doc) ->
- [""];
-invalid_serial(suite) ->
- [];
+invalid_serial() ->
+ [{doc,"Test basic CRL handling"}].
invalid_serial(Config) when is_list(Config) ->
run([{ "4.4.15", "Invalid Negative Serial Number Test15 EE",
{bad_cert, {revoked, keyCompromise}}},
{ "4.4.18", "Invalid Long Serial Number Test18 EE",
{bad_cert, {revoked, keyCompromise}}}]).
-valid_seperate_keys(doc) ->
- [""];
-valid_seperate_keys(suite) ->
- [];
+valid_seperate_keys() ->
+ [{doc,"Test basic CRL handling"}].
valid_seperate_keys(Config) when is_list(Config) ->
run([{ "4.4.19", "Valid Separate Certificate and CRL Keys Test19 EE", ok}]).
-invalid_separate_keys(doc) ->
- [""];
-invalid_separate_keys(suite) ->
- [];
+invalid_separate_keys() ->
+ [{doc,"Test basic CRL handling"}].
invalid_separate_keys(Config) when is_list(Config) ->
- run([{ "4.4.20", "Invalid Separate Certificate and CRL Keys Test20",
+ run([{ "4.4.20", "Invalid Separate Certificate and CRL Keys Test20 EE",
{bad_cert, {revoked, keyCompromise}}},
- { "4.4.21", "Invalid Separate Certificate and CRL Keys Test21",
+ { "4.4.21", "Invalid Separate Certificate and CRL Keys Test21 EE",
{bad_cert, revocation_status_undetermined}}
]).
-%%-----------------------------------------------------------------------------
-missing_basic_constraints(doc) ->
- [""];
-missing_basic_constraints(suite) ->
- [];
+%%----------------------------verifying_basic_constraints-------------------------------------------------
+missing_basic_constraints() ->
+ [{doc,"Basic constraint tests"}].
missing_basic_constraints(Config) when is_list(Config) ->
run([{ "4.6.1", "Invalid Missing basicConstraints Test1 EE",
{bad_cert, missing_basic_constraint}},
@@ -414,17 +361,13 @@ missing_basic_constraints(Config) when is_list(Config) ->
{ "4.6.3", "Invalid cA False Test3 EE",
{bad_cert, missing_basic_constraint}}]).
-valid_basic_constraint(doc) ->
- [""];
-valid_basic_constraint(suite) ->
- [];
+valid_basic_constraint() ->
+ [{doc,"Basic constraint tests"}].
valid_basic_constraint(Config) when is_list(Config) ->
run([{"4.6.4", "Valid basicConstraints Not Critical Test4 EE", ok}]).
-invalid_path_constraints(doc) ->
- [""];
-invalid_path_constraints(suite) ->
- [];
+invalid_path_constraints() ->
+ [{doc,"Basic constraint tests"}].
invalid_path_constraints(Config) when is_list(Config) ->
run([{ "4.6.5", "Invalid pathLenConstraint Test5 EE", {bad_cert, max_path_length_reached}},
{ "4.6.6", "Invalid pathLenConstraint Test6 EE", {bad_cert, max_path_length_reached}},
@@ -435,10 +378,8 @@ invalid_path_constraints(Config) when is_list(Config) ->
{ "4.6.16", "Invalid Self-Issued pathLenConstraint Test16 EE",
{bad_cert, max_path_length_reached}}]).
-valid_path_constraints(doc) ->
- [""];
-valid_path_constraints(suite) ->
- [];
+valid_path_constraints() ->
+ [{doc,"Basic constraint tests"}].
valid_path_constraints(Config) when is_list(Config) ->
run([{ "4.6.7", "Valid pathLenConstraint Test7 EE", ok},
{ "4.6.8", "Valid pathLenConstraint Test8 EE", ok},
@@ -447,60 +388,54 @@ valid_path_constraints(Config) when is_list(Config) ->
{ "4.6.15", "Valid Self-Issued pathLenConstraint Test15 EE", ok},
{ "4.6.17", "Valid Self-Issued pathLenConstraint Test17 EE", ok}]).
-%%-----------------------------------------------------------------------------
-invalid_key_usage(doc) ->
- [""];
-invalid_key_usage(suite) ->
- [];
+%%-----------------------------key_usage------------------------------------------------
+invalid_key_usage() ->
+ [{doc,"Key usage tests"}].
invalid_key_usage(Config) when is_list(Config) ->
run([{ "4.7.1", "Invalid keyUsage Critical keyCertSign False Test1 EE",
{bad_cert,invalid_key_usage} },
{ "4.7.2", "Invalid keyUsage Not Critical keyCertSign False Test2 EE",
- {bad_cert,invalid_key_usage}}
- %% { "4.7.4", "Invalid keyUsage Critical cRLSign False Test4 EE",
- %% {bad_cert, revocation_status_undetermined}},
- %% { "4.7.5", "Invalid keyUsage Not Critical cRLSign False Test5 EE",
- %% {bad_cert, revocation_status_undetermined}}
+ {bad_cert,invalid_key_usage}},
+ { "4.7.4", "Invalid keyUsage Critical cRLSign False Test4 EE",
+ {bad_cert, invalid_key_usage}},
+ { "4.7.5", "Invalid keyUsage Not Critical cRLSign False Test5 EE",
+ {bad_cert, invalid_key_usage}}
]).
-valid_key_usage(doc) ->
- [""];
-valid_key_usage(suite) ->
- [];
+valid_key_usage() ->
+ [{doc,"Key usage tests"}].
valid_key_usage(Config) when is_list(Config) ->
run([{ "4.7.3", "Valid keyUsage Not Critical Test3 EE", ok}]).
%%-----------------------------------------------------------------------------
-certificate_policies(doc) -> [""];
-certificate_policies(suite) -> [];
+certificate_policies() ->
+ [{doc,"Not supported yet"}].
certificate_policies(Config) when is_list(Config) ->
- run(certificate_policies()).
+ run(certificate_policies_tests()).
%%-----------------------------------------------------------------------------
-require_explicit_policy(doc) -> [""];
-require_explicit_policy(suite) -> [];
+require_explicit_policy() ->
+ [{doc,"Not supported yet"}].
require_explicit_policy(Config) when is_list(Config) ->
- run(require_explicit_policy()).
+ run(require_explicit_policy_tests()).
%%-----------------------------------------------------------------------------
-policy_mappings(doc) -> [""];
-policy_mappings(suite) -> [];
+policy_mappings() ->
+ [{doc,"Not supported yet"}].
policy_mappings(Config) when is_list(Config) ->
- run(policy_mappings()).
+ run(policy_mappings_tests()).
%%-----------------------------------------------------------------------------
-inhibit_policy_mapping(doc) -> [""];
-inhibit_policy_mapping(suite) -> [];
+inhibit_policy_mapping() ->
+ [{doc,"Not supported yet"}].
inhibit_policy_mapping(Config) when is_list(Config) ->
- run(inhibit_policy_mapping()).
+ run(inhibit_policy_mapping_tests()).
%%-----------------------------------------------------------------------------
-inhibit_any_policy(doc) -> [""];
-inhibit_any_policy(suite) -> [];
+inhibit_any_policy() ->
+ [{doc,"Not supported yet"}].
inhibit_any_policy(Config) when is_list(Config) ->
- run(inhibit_any_policy()).
-%%-----------------------------------------------------------------------------
+ run(inhibit_any_policy_tests()).
+%%-------------------------------name_constraints----------------------------------------------
-valid_DN_name_constraints(doc) ->
- [""];
-valid_DN_name_constraints(suite) ->
- [];
+valid_DN_name_constraints() ->
+ [{doc, "Name constraints tests"}].
valid_DN_name_constraints(Config) when is_list(Config) ->
run([{ "4.13.1", "Valid DN nameConstraints Test1 EE", ok},
{ "4.13.4", "Valid DN nameConstraints Test4 EE", ok},
@@ -511,10 +446,8 @@ valid_DN_name_constraints(Config) when is_list(Config) ->
{ "4.13.18", "Valid DN nameConstraints Test18 EE", ok},
{ "4.13.19", "Valid DN nameConstraints Test19 EE", ok}]).
-invalid_DN_name_constraints(doc) ->
- [""];
-invalid_DN_name_constraints(suite) ->
- [];
+invalid_DN_name_constraints() ->
+ [{doc,"Name constraints tests"}].
invalid_DN_name_constraints(Config) when is_list(Config) ->
run([{ "4.13.2", "Invalid DN nameConstraints Test2 EE", {bad_cert, name_not_permitted}},
{ "4.13.3", "Invalid DN nameConstraints Test3 EE", {bad_cert, name_not_permitted}},
@@ -530,20 +463,15 @@ invalid_DN_name_constraints(Config) when is_list(Config) ->
{ "4.13.20", "Invalid DN nameConstraints Test20 EE",
{bad_cert, name_not_permitted}}]).
-valid_rfc822_name_constraints(doc) ->
- [""];
-valid_rfc822_name_constraints(suite) ->
- [];
+valid_rfc822_name_constraints() ->
+ [{doc,"Name constraints tests"}].
valid_rfc822_name_constraints(Config) when is_list(Config) ->
run([{ "4.13.21", "Valid RFC822 nameConstraints Test21 EE", ok},
{ "4.13.23", "Valid RFC822 nameConstraints Test23 EE", ok},
{ "4.13.25", "Valid RFC822 nameConstraints Test25 EE", ok}]).
-
-invalid_rfc822_name_constraints(doc) ->
- [""];
-invalid_rfc822_name_constraints(suite) ->
- [];
+invalid_rfc822_name_constraints() ->
+ [{doc,"Name constraints tests"}].
invalid_rfc822_name_constraints(Config) when is_list(Config) ->
run([{ "4.13.22", "Invalid RFC822 nameConstraints Test22 EE",
{bad_cert, name_not_permitted}},
@@ -552,71 +480,54 @@ invalid_rfc822_name_constraints(Config) when is_list(Config) ->
{ "4.13.26", "Invalid RFC822 nameConstraints Test26 EE",
{bad_cert, name_not_permitted}}]).
-valid_DN_and_rfc822_name_constraints(doc) ->
- [""];
-valid_DN_and_rfc822_name_constraints(suite) ->
- [];
+valid_DN_and_rfc822_name_constraints() ->
+ [{doc,"Name constraints tests"}].
valid_DN_and_rfc822_name_constraints(Config) when is_list(Config) ->
run([{ "4.13.27", "Valid DN and RFC822 nameConstraints Test27 EE", ok}]).
-invalid_DN_and_rfc822_name_constraints(doc) ->
- [""];
-invalid_DN_and_rfc822_name_constraints(suite) ->
- [];
+invalid_DN_and_rfc822_name_constraints() ->
+ [{doc,"Name constraints tests"}].
invalid_DN_and_rfc822_name_constraints(Config) when is_list(Config) ->
run([{ "4.13.28", "Invalid DN and RFC822 nameConstraints Test28 EE",
{bad_cert, name_not_permitted}},
{ "4.13.29", "Invalid DN and RFC822 nameConstraints Test29 EE",
{bad_cert, name_not_permitted}}]).
-valid_dns_name_constraints(doc) ->
- [""];
-valid_dns_name_constraints(suite) ->
- [];
+valid_dns_name_constraints() ->
+ [{doc,"Name constraints tests"}].
valid_dns_name_constraints(Config) when is_list(Config) ->
run([{ "4.13.30", "Valid DNS nameConstraints Test30 EE", ok},
{ "4.13.32", "Valid DNS nameConstraints Test32 EE", ok}]).
-invalid_dns_name_constraints(doc) ->
- [""];
-invalid_dns_name_constraints(suite) ->
- [];
+invalid_dns_name_constraints() ->
+ [{doc,"Name constraints tests"}].
invalid_dns_name_constraints(Config) when is_list(Config) ->
run([{ "4.13.31", "Invalid DNS nameConstraints Test31 EE", {bad_cert, name_not_permitted}},
{ "4.13.33", "Invalid DNS nameConstraints Test33 EE", {bad_cert, name_not_permitted}},
{ "4.13.38", "Invalid DNS nameConstraints Test38 EE", {bad_cert, name_not_permitted}}]).
-valid_uri_name_constraints(doc) ->
- [""];
-valid_uri_name_constraints(suite) ->
- [];
+valid_uri_name_constraints() ->
+ [{doc,"Name constraints tests"}].
valid_uri_name_constraints(Config) when is_list(Config) ->
run([{ "4.13.34", "Valid URI nameConstraints Test34 EE", ok},
{ "4.13.36", "Valid URI nameConstraints Test36 EE", ok}]).
-invalid_uri_name_constraints(doc) ->
- [""];
-invalid_uri_name_constraints(suite) ->
- [];
+invalid_uri_name_constraints() ->
+ [{doc,"Name constraints tests"}].
invalid_uri_name_constraints(Config) when is_list(Config) ->
run([{ "4.13.35", "Invalid URI nameConstraints Test35 EE",{bad_cert, name_not_permitted}},
{ "4.13.37", "Invalid URI nameConstraints Test37 EE",{bad_cert, name_not_permitted}}]).
-%%-----------------------------------------------------------------------------
-delta_without_crl(doc) ->
- [""];
-delta_without_crl(suite) ->
- [];
+%%------------------------------delta_crls-----------------------------------------------
+delta_without_crl() ->
+ [{doc,"Delta CRL tests"}].
delta_without_crl(Config) when is_list(Config) ->
run([{ "4.15.1", "Invalid deltaCRLIndicator No Base Test1 EE",{bad_cert,
revocation_status_undetermined}},
{"4.15.10", "Invalid delta-CRL Test10 EE", {bad_cert,
revocation_status_undetermined}}]).
-
-valid_delta_crls(doc) ->
- [""];
-valid_delta_crls(suite) ->
- [];
+valid_delta_crls() ->
+ [{doc,"Delta CRL tests"}].
valid_delta_crls(Config) when is_list(Config) ->
run([{ "4.15.2", "Valid delta-CRL Test2 EE", ok},
{ "4.15.5", "Valid delta-CRL Test5 EE", ok},
@@ -624,22 +535,17 @@ valid_delta_crls(Config) when is_list(Config) ->
{ "4.15.8", "Valid delta-CRL Test8 EE", ok}
]).
-invalid_delta_crls(doc) ->
- [""];
-invalid_delta_crls(suite) ->
- [];
+invalid_delta_crls() ->
+ [{doc,"Delta CRL tests"}].
invalid_delta_crls(Config) when is_list(Config) ->
run([{ "4.15.3", "Invalid delta-CRL Test3 EE", {bad_cert,{revoked, keyCompromise}}},
{ "4.15.4", "Invalid delta-CRL Test4 EE", {bad_cert,{revoked, keyCompromise}}},
{ "4.15.6", "Invalid delta-CRL Test6 EE", {bad_cert,{revoked, keyCompromise}}},
{ "4.15.9", "Invalid delta-CRL Test9 EE", {bad_cert,{revoked, keyCompromise}}}]).
-%%-----------------------------------------------------------------------------
-
-valid_distribution_points(doc) ->
- [""];
-valid_distribution_points(suite) ->
- [];
+%%---------------------------distribution_points--------------------------------------------------
+valid_distribution_points() ->
+ [{doc,"CRL Distribution Point tests"}].
valid_distribution_points(Config) when is_list(Config) ->
run([{ "4.14.1", "Valid distributionPoint Test1 EE", ok},
{ "4.14.4", "Valid distributionPoint Test4 EE", ok},
@@ -647,18 +553,14 @@ valid_distribution_points(Config) when is_list(Config) ->
{ "4.14.7", "Valid distributionPoint Test7 EE", ok}
]).
-valid_distribution_points_no_issuing_distribution_point(doc) ->
- [""];
-valid_distribution_points_no_issuing_distribution_point(suite) ->
- [];
+valid_distribution_points_no_issuing_distribution_point() ->
+ [{doc,"CRL Distribution Point tests"}].
valid_distribution_points_no_issuing_distribution_point(Config) when is_list(Config) ->
- run([{ "4.14.10", "Valid No issuingDistributionPoint Test10", ok}
+ run([{ "4.14.10", "Valid No issuingDistributionPoint Test10 EE", ok}
]).
-invalid_distribution_points(doc) ->
- [""];
-invalid_distribution_points(suite) ->
- [];
+invalid_distribution_points() ->
+ [{doc,"CRL Distribution Point tests"}].
invalid_distribution_points(Config) when is_list(Config) ->
run([{ "4.14.2", "Invalid distributionPoint Test2 EE", {bad_cert,{revoked, keyCompromise}}},
{ "4.14.3", "Invalid distributionPoint Test3 EE", {bad_cert,
@@ -670,40 +572,31 @@ invalid_distribution_points(Config) when is_list(Config) ->
revocation_status_undetermined}}
]).
-valid_only_contains(doc) ->
- [""];
-valid_only_contains(suite) ->
- [];
+valid_only_contains() ->
+ [{doc,"CRL Distribution Point tests"}].
valid_only_contains(Config) when is_list(Config) ->
- run([{ "4.14.13", "Valid onlyContainsCACerts CRL Test13 EE", ok}]).
-
+ run([{ "4.14.13", "Valid only Contains CA Certs Test13 EE", ok}]).
-invalid_only_contains(doc) ->
- [""];
-invalid_only_contains(suite) ->
- [];
+invalid_only_contains() ->
+ [{doc,"CRL Distribution Point tests"}].
invalid_only_contains(Config) when is_list(Config) ->
- run([{ "4.14.11", "Invalid onlyContainsUserCerts CRL Test11 EE",
+ run([{ "4.14.11", "Invalid onlyContainsUserCerts Test11 EE",
{bad_cert, revocation_status_undetermined}},
- { "4.14.12", "Invalid onlyContainsCACerts CRL Test12 EE",
+ { "4.14.12", "Invalid onlyContainsCACerts Test12 EE",
{bad_cert, revocation_status_undetermined}},
{ "4.14.14", "Invalid onlyContainsAttributeCerts Test14 EE",
{bad_cert, revocation_status_undetermined}}
]).
-valid_only_some_reasons(doc) ->
- [""];
-valid_only_some_reasons(suite) ->
- [];
+valid_only_some_reasons() ->
+ [{doc,"CRL Distribution Point tests"}].
valid_only_some_reasons(Config) when is_list(Config) ->
run([{ "4.14.18", "Valid onlySomeReasons Test18 EE", ok},
{ "4.14.19", "Valid onlySomeReasons Test19 EE", ok}
]).
-invalid_only_some_reasons(doc) ->
- [""];
-invalid_only_some_reasons(suite) ->
- [];
+invalid_only_some_reasons() ->
+ [{doc,"CRL Distribution Point tests"}].
invalid_only_some_reasons(Config) when is_list(Config) ->
run([{ "4.14.15", "Invalid onlySomeReasons Test15 EE",
{bad_cert,{revoked, keyCompromise}}},
@@ -717,20 +610,16 @@ invalid_only_some_reasons(Config) when is_list(Config) ->
{bad_cert,{revoked, affiliationChanged}}}
]).
-valid_indirect_crl(doc) ->
- [""];
-valid_indirect_crl(suite) ->
- [];
+valid_indirect_crl() ->
+ [{doc,"CRL Distribution Point tests"}].
valid_indirect_crl(Config) when is_list(Config) ->
run([{ "4.14.22", "Valid IDP with indirectCRL Test22 EE", ok},
{ "4.14.24", "Valid IDP with indirectCRL Test24 EE", ok},
{ "4.14.25", "Valid IDP with indirectCRL Test25 EE", ok}
]).
-invalid_indirect_crl(doc) ->
- [""];
-invalid_indirect_crl(suite) ->
- [];
+invalid_indirect_crl() ->
+ [{doc,"CRL Distribution Point tests"}].
invalid_indirect_crl(Config) when is_list(Config) ->
run([{ "4.14.23", "Invalid IDP with indirectCRL Test23 EE",
{bad_cert,{revoked, keyCompromise}}},
@@ -738,20 +627,16 @@ invalid_indirect_crl(Config) when is_list(Config) ->
{bad_cert, revocation_status_undetermined}}
]).
-valid_crl_issuer(doc) ->
- [""];
-valid_crl_issuer(suite) ->
- [];
+valid_crl_issuer() ->
+ [{doc,"CRL Distribution Point tests"}].
valid_crl_issuer(Config) when is_list(Config) ->
- run([{ "4.14.28", "Valid cRLIssuer Test28 EE", ok}%%,
- %%{ "4.14.29", "Valid cRLIssuer Test29 EE", ok},
- %%{ "4.14.33", "Valid cRLIssuer Test33 EE", ok}
+ run([{ "4.14.28", "Valid cRLIssuer Test28 EE", ok},
+ { "4.14.29", "Valid cRLIssuer Test29 EE", ok},
+ { "4.14.33", "Valid cRLIssuer Test33 EE", ok}
]).
-invalid_crl_issuer(doc) ->
- [""];
-invalid_crl_issuer(suite) ->
- [];
+invalid_crl_issuer() ->
+ [{doc,"CRL Distribution Point tests"}].
invalid_crl_issuer(Config) when is_list(Config) ->
run([
{ "4.14.27", "Invalid cRLIssuer Test27 EE", {bad_cert, revocation_status_undetermined}},
@@ -761,44 +646,36 @@ invalid_crl_issuer(Config) when is_list(Config) ->
{ "4.14.35", "Invalid cRLIssuer Test35 EE", {bad_cert, revocation_status_undetermined}}
]).
-
-%%distribution_points() ->
- %%{ "4.14", "Distribution Points" },
-%% [
- %% Although this test is valid it has a circular dependency. As a result
- %% an attempt is made to reursively checks a CRL path and rejected due to
- %% a CRL path validation error. PKITS notes suggest this test does not
- %% need to be run due to this issue.
-%% { "4.14.30", "Valid cRLIssuer Test30", 54 }].
+%% Although this test is valid it has a circular dependency. As a result
+%% an attempt is made to reursively checks a CRL path and rejected due to
+%% a CRL path validation error. PKITS notes suggest this test does not
+%% need to be run due to this issue.
+%% { "4.14.30", "Valid cRLIssuer Test30", 54 }
-%%-----------------------------------------------------------------------------
+%%-------------------------------private_certificate_extensions----------------------------------------------
-unknown_critical_extension(doc) ->
- [""];
-unknown_critical_extension(suite) ->
- [];
+unknown_critical_extension() ->
+ [{doc,"Test that a cert with an unknown critical extension is recjected"}].
unknown_critical_extension(Config) when is_list(Config) ->
run([{ "4.16.2", "Invalid Unknown Critical Certificate Extension Test2 EE",
{bad_cert,unknown_critical_extension}}]).
-unknown_not_critical_extension(doc) ->
- [""];
-unknown_not_critical_extension(suite) ->
- [];
+unknown_not_critical_extension() ->
+ [{doc,"Test that a not critical unknown extension is ignored"}].
unknown_not_critical_extension(Config) when is_list(Config) ->
run([{ "4.16.1", "Valid Unknown Not Critical Certificate Extension Test1 EE", ok}]).
-%%-----------------------------------------------------------------------------
+%%--------------------------------------------------------------------
+%% Internal functions ------------------------------------------------
+%%--------------------------------------------------------------------
+
run(Tests) ->
[TA] = read_certs("Trust Anchor Root Certificate"),
run(Tests, TA).
run({Chap, Test, Result}, TA) ->
CertChain = cas(Chap) ++ read_certs(Test),
- lists:foreach(fun(C) ->
- io:format("CERT: ~p~n", [public_key:pkix_decode_cert(C, otp)])
- end, CertChain),
Options = path_validation_options(TA, Chap,Test),
try public_key:pkix_path_validation(TA, CertChain, Options) of
{Result, _} -> ok;
@@ -825,7 +702,7 @@ run([],_) -> ok.
path_validation_options(TA, Chap, Test) ->
case needs_crl_options(Chap) of
true ->
- crl_options(TA, Test);
+ crl_options(TA, Chap, Test);
false ->
Fun =
fun(_,{bad_cert, _} = Reason, _) ->
@@ -839,6 +716,56 @@ path_validation_options(TA, Chap, Test) ->
[{verify_fun, {Fun, []}}]
end.
+read_certs(Test) ->
+ File = cert_file(Test),
+ Ders = erl_make_certs:pem_to_der(File),
+ [Cert || {'Certificate', Cert, not_encrypted} <- Ders].
+
+read_crls(Test) ->
+ File = crl_file(Test),
+ Ders = erl_make_certs:pem_to_der(File),
+ [CRL || {'CertificateList', CRL, not_encrypted} <- Ders].
+
+cert_file(Test) ->
+ file(?CONV, lists:append(string:tokens(Test, " -")) ++ ".pem").
+
+crl_file(Test) ->
+ file(?CRL, lists:append(string:tokens(Test, " -")) ++ ".pem").
+
+
+file(Sub,File) ->
+ TestDir = case get(datadir) of
+ undefined -> "./pkits_SUITE_data";
+ Dir when is_list(Dir) ->
+ Dir
+ end,
+ AbsFile = filename:join([TestDir,Sub,File]),
+ case filelib:is_file(AbsFile) of
+ true -> ok;
+ false ->
+ ?error("Couldn't read data from ~p ~n",[AbsFile])
+ end,
+ AbsFile.
+
+error(Format, Args, File0, Line) ->
+ File = filename:basename(File0),
+ Pid = group_leader(),
+ Pid ! {failed, File, Line},
+ io:format(Pid, "~s(~p): ERROR"++Format, [File,Line|Args]).
+
+warning(Format, Args, File0, Line) ->
+ File = filename:basename(File0),
+ io:format("~s(~p): Warning "++Format, [File,Line|Args]).
+
+crypto_support_check(Config) ->
+ try crypto:sha256(<<"Test">>) of
+ _ ->
+ Config
+ catch error:notsup ->
+ crypto:stop(),
+ {skip, "To old version of openssl"}
+ end.
+
needs_crl_options("4.4" ++ _) ->
true;
needs_crl_options("4.5" ++ _) ->
@@ -854,54 +781,69 @@ needs_crl_options("4.15" ++ _) ->
needs_crl_options(_) ->
false.
-crl_options(TA, Test) ->
- case read_crls(Test) of
- [] ->
- [];
- CRLs ->
- Fun =
- fun(_,{bad_cert, _} = Reason, _) ->
- {fail, Reason};
- (_,{extension,
- #'Extension'{extnID = ?'id-ce-cRLDistributionPoints',
- extnValue = Value}}, UserState0) ->
- UserState = update_crls(Value, UserState0),
+crl_options(_TA, Chap, _Test) ->
+ CRLNames = crl_names(Chap),
+ CRLs = crls(CRLNames),
+ Paths = lists:map(fun(CRLName) -> crl_path(CRLName) end, CRLNames),
+
+ ct:print("Paths ~p ~n Names ~p ~n", [Paths, CRLNames]),
+ Fun =
+ fun(_,{bad_cert, _} = Reason, _) ->
+ {fail, Reason};
+ (_,{extension,
+ #'Extension'{extnID = ?'id-ce-cRLDistributionPoints',
+ extnValue = Value}}, UserState0) ->
+ UserState = update_crls(Value, UserState0),
+ {valid, UserState};
+ (_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (OtpCert, Valid, UserState) when Valid == valid;
+ Valid == valid_peer ->
+ DerCRLs = UserState#verify_state.crls,
+ Paths = UserState#verify_state.crl_paths,
+ Crls = [{DerCRL, public_key:der_decode('CertificateList',
+ DerCRL)} || DerCRL <- DerCRLs],
+
+ CRLInfo0 = crl_info(OtpCert, Crls, []),
+ CRLInfo = lists:reverse(CRLInfo0),
+ PathDb = crl_path_db(lists:reverse(Crls), Paths, []),
+
+ Fun = fun(DP, CRLtoValidate, Id, PathDb0) ->
+ trusted_cert_and_path(DP, CRLtoValidate, Id, PathDb0)
+ end,
+
+ case CRLInfo of
+ [] ->
{valid, UserState};
- (_,{extension, _}, UserState) ->
- {unknown, UserState};
- (OtpCert, Valid, UserState) when Valid == valid;
- Valid == valid_peer ->
- {ErlCerts, CRLs} = UserState#verify_state.crl_info,
- CRLInfo0 =
- crl_info(OtpCert,
- ErlCerts,[{DerCRL, public_key:der_decode('CertificateList',
- DerCRL)} || DerCRL <- CRLs],
- []),
- CRLInfo = lists:reverse(CRLInfo0),
- Certs = UserState#verify_state.certs_db,
- Fun = fun(DP, CRLtoValidate, Id, CertsDb) ->
- trusted_cert_and_path(DP, CRLtoValidate, Id, CertsDb)
- end,
- Ignore = ignore_sign_test_when_building_path(Test),
+ [_|_] ->
case public_key:pkix_crls_validate(OtpCert, CRLInfo,
- [{issuer_fun,{Fun, {Ignore, Certs}}}]) of
+ [{issuer_fun,{Fun, PathDb}}]) of
valid ->
{valid, UserState};
Reason ->
{fail, Reason}
end
- end,
+ end
+ end,
- Certs = read_certs(Test),
- ErlCerts = [public_key:pkix_decode_cert(Cert, otp) || Cert <- Certs],
+ [{verify_fun, {Fun, #verify_state{crls = CRLs,
+ crl_paths = Paths}}}].
- [{verify_fun, {Fun, #verify_state{certs_db = [TA| Certs],
- crl_info = {ErlCerts, CRLs}}}}]
- end.
+crl_path_db([], [], Acc) ->
+ Acc;
+crl_path_db([{_, CRL} |CRLs], [Path | Paths], Acc) ->
+ CertPath = lists:flatten(lists:map(fun([]) ->
+ [];
+ (CertFile) ->
+ ct:print("Certfile ~p", [CertFile]),
+ read_certs(CertFile)
+ end, Path)),
+ crl_path_db(CRLs, Paths, [{CRL, CertPath}| Acc]).
-crl_info(_, _, [], Acc) ->
+
+crl_info(_, [], Acc) ->
Acc;
-crl_info(OtpCert, Certs, [{_, #'CertificateList'{tbsCertList =
+crl_info(OtpCert, [{_, #'CertificateList'{tbsCertList =
#'TBSCertList'{issuer = Issuer,
crlExtensions = CRLExtensions}}}
= CRL | Rest], Acc) ->
@@ -910,22 +852,36 @@ crl_info(OtpCert, Certs, [{_, #'CertificateList'{tbsCertList =
ExtList = pubkey_cert:extensions_list(CRLExtensions),
DPs = case pubkey_cert:select_extension(?'id-ce-cRLDistributionPoints', Extensions) of
#'Extension'{extnValue = Value} ->
- lists:map(fun(Point) -> pubkey_cert_records:transform(Point, decode) end, Value);
- _ ->
- case same_issuer(OtpCert, Issuer) of
- true ->
- [make_dp(ExtList, asn1_NOVALUE, Issuer)];
- false ->
- [make_dp(ExtList, Issuer, ignore)]
- end
+ lists:foldl(fun(Point, Acc0) ->
+ Dp = pubkey_cert_records:transform(Point, decode),
+ IDP = pubkey_cert:select_extension(?'id-ce-issuingDistributionPoint',
+ Extensions),
+ case Dp#'DistributionPoint'.cRLIssuer of
+ asn1_NOVALUE ->
+ [Dp | Acc0];
+ DpCRLIssuer ->
+ CRLIssuer = dp_crlissuer_to_issuer(DpCRLIssuer),
+ CertIssuer = OtpTBSCert#'OTPTBSCertificate'.issuer,
+ case pubkey_cert:is_issuer(CRLIssuer, CertIssuer) of
+ true ->
+ [Dp | Acc0];
+ false when (IDP =/= undefined) ->
+ Acc0;
+ false ->
+ [Dp | Acc0]
+ end
+ end
+ end, [], Value);
+ _ ->
+ case same_issuer(OtpCert, Issuer) of
+ true ->
+ [make_dp(ExtList, asn1_NOVALUE, Issuer)];
+ false ->
+ [make_dp(ExtList, Issuer, ignore)]
+ end
end,
DPsCRLs = lists:map(fun(DP) -> {DP, CRL} end, DPs),
- crl_info(OtpCert, Certs, Rest, DPsCRLs ++ Acc).
-
-ignore_sign_test_when_building_path("Invalid Bad CRL Signature Test4") ->
- true;
-ignore_sign_test_when_building_path(_) ->
- false.
+ crl_info(OtpCert, Rest, DPsCRLs ++ Acc).
same_issuer(OTPCert, Issuer) ->
DecIssuer = pubkey_cert_records:transform(Issuer, decode),
@@ -957,200 +913,23 @@ mk_issuer_dp(Issuer, _) ->
update_crls(_, State) ->
State.
-trusted_cert_and_path(DP, CRL, Id, {Ignore, CertsList}) ->
- case crl_issuer(crl_issuer_name(DP), CRL, Id, CertsList, CertsList, Ignore) of
- {ok, IssuerCert, DerIssuerCert} ->
- Certs = [{public_key:pkix_decode_cert(Cert, otp), Cert} || Cert <- CertsList],
- CertChain = build_chain(Certs, Certs, IssuerCert, Ignore, [DerIssuerCert]),
- {ok, public_key:pkix_decode_cert(hd(CertChain), otp), CertChain};
- Other ->
- Other
- end.
-
-crl_issuer_name(#'DistributionPoint'{cRLIssuer = asn1_NOVALUE}) ->
- undefined;
-crl_issuer_name(#'DistributionPoint'{cRLIssuer = [{directoryName, Issuer}]}) ->
- pubkey_cert_records:transform(Issuer, decode).
+trusted_cert_and_path(_, #'CertificateList'{} = CRL, _, PathDb) ->
+ [TrustedDERCert] = read_certs(crl_root_cert()),
+ TrustedCert = public_key:pkix_decode_cert(TrustedDERCert, otp),
-build_chain([],_, _, _,Acc) ->
- Acc;
-
-build_chain([{First, DerFirst}|Certs], All, Cert, Ignore, Acc) ->
- case public_key:pkix_is_self_signed(Cert) andalso is_test_root(Cert) of
- true ->
- Acc;
- false ->
- case public_key:pkix_is_issuer(Cert, First)
- %%andalso check_extension_cert_signer(First)
- andalso is_signer(First, Cert, Ignore)
- of
- true ->
- build_chain(All, All, First, Ignore, [DerFirst | Acc]);
- false ->
- build_chain(Certs, All, Cert, Ignore, Acc)
- end
- end.
-
-is_signer(_,_, true) ->
- true;
-is_signer(Signer, #'OTPCertificate'{} = Cert,_) ->
- TBSCert = Signer#'OTPCertificate'.tbsCertificate,
- PublicKeyInfo = TBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo,
- PublicKey = PublicKeyInfo#'OTPSubjectPublicKeyInfo'.subjectPublicKey,
- AlgInfo = PublicKeyInfo#'OTPSubjectPublicKeyInfo'.algorithm,
- PublicKeyParams = AlgInfo#'PublicKeyAlgorithm'.parameters,
- try pubkey_cert:validate_signature(Cert, public_key:pkix_encode('OTPCertificate',
- Cert, otp),
- PublicKey, PublicKeyParams, true, ?DEFAULT_VERIFYFUN) of
- true ->
- true
- catch
- _:_ ->
- false
- end;
-is_signer(Signer, #'CertificateList'{} = CRL, _) ->
- TBSCert = Signer#'OTPCertificate'.tbsCertificate,
- PublicKeyInfo = TBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo,
- PublicKey = PublicKeyInfo#'OTPSubjectPublicKeyInfo'.subjectPublicKey,
- AlgInfo = PublicKeyInfo#'OTPSubjectPublicKeyInfo'.algorithm,
- PublicKeyParams = AlgInfo#'PublicKeyAlgorithm'.parameters,
- pubkey_crl:verify_crl_signature(CRL, public_key:pkix_encode('CertificateList',
- CRL, plain),
- PublicKey, PublicKeyParams).
-
-is_test_root(OtpCert) ->
- TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
- {rdnSequence, AtterList} = TBSCert#'OTPTBSCertificate'.issuer,
- lists:member([{'AttributeTypeAndValue',{2,5,4,3},{printableString,"Trust Anchor"}}],
- AtterList).
-
-check_extension_cert_signer(OtpCert) ->
- TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
- Extensions = TBSCert#'OTPTBSCertificate'.extensions,
- case pubkey_cert:select_extension(?'id-ce-keyUsage', Extensions) of
- #'Extension'{extnValue = KeyUse} ->
- lists:member(keyCertSign, KeyUse);
- _ ->
- true
- end.
-
-check_extension_crl_signer(OtpCert) ->
- TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
- Extensions = TBSCert#'OTPTBSCertificate'.extensions,
- case pubkey_cert:select_extension(?'id-ce-keyUsage', Extensions) of
- #'Extension'{extnValue = KeyUse} ->
- lists:member(cRLSign, KeyUse);
- _ ->
- true
+ case lists:keysearch(CRL, 1, PathDb) of
+ {_, {CRL, [ _| _] = Path}} ->
+ {ok, TrustedCert, [TrustedDERCert | Path]};
+ {_, {CRL, []}} ->
+ {ok, TrustedCert, [TrustedDERCert]}
end.
-crl_issuer(undefined, CRL, issuer_not_found, _, CertsList, Ignore) ->
- crl_issuer(CRL, CertsList, Ignore);
-
-crl_issuer(IssuerName, CRL, issuer_not_found, CertsList, CertsList, Ignore) ->
- crl_issuer(IssuerName, CRL, IssuerName, CertsList, CertsList, Ignore);
-
-crl_issuer(undefined, CRL, Id, [Cert | Rest], All, false) ->
- ErlCert = public_key:pkix_decode_cert(Cert, otp),
- TBSCertificate = ErlCert#'OTPCertificate'.tbsCertificate,
- SerialNumber = TBSCertificate#'OTPTBSCertificate'.serialNumber,
- Issuer = public_key:pkix_normalize_name(
- TBSCertificate#'OTPTBSCertificate'.subject),
- Bool = is_signer(ErlCert, CRL, false),
- case {SerialNumber, Issuer} of
- Id when Bool == true ->
- {ok, ErlCert, Cert};
- _ ->
- crl_issuer(undefined, CRL, Id, Rest, All, false)
- end;
-
-crl_issuer(IssuerName, CRL, Id, [Cert | Rest], All, false) ->
- ErlCert = public_key:pkix_decode_cert(Cert, otp),
- TBSCertificate = ErlCert#'OTPCertificate'.tbsCertificate,
- SerialNumber = TBSCertificate#'OTPTBSCertificate'.serialNumber,
- %%Issuer = public_key:pkix_normalize_name(
- %% TBSCertificate#'OTPTBSCertificate'.subject),
- Bool = is_signer(ErlCert, CRL, false),
- case {SerialNumber, IssuerName} of
- Id when Bool == true ->
- {ok, ErlCert, Cert};
- {_, IssuerName} when Bool == true ->
- {ok, ErlCert, Cert};
- _ ->
- crl_issuer(IssuerName, CRL, Id, Rest, All, false)
- end;
-
-crl_issuer(undefined, CRL, _, [], CertsList, Ignore) ->
- crl_issuer(CRL, CertsList, Ignore);
-crl_issuer(CRLName, CRL, _, [], CertsList, Ignore) ->
- crl_issuer(CRLName, CRL, CertsList, Ignore).
-
-
-crl_issuer(_, [],_) ->
- {error, issuer_not_found};
-crl_issuer(CRL, [Cert | Rest], Ignore) ->
- ErlCert = public_key:pkix_decode_cert(Cert, otp),
- case public_key:pkix_is_issuer(CRL, ErlCert) andalso
- check_extension_crl_signer(ErlCert) andalso
- is_signer(ErlCert, CRL, Ignore)
- of
- true ->
- {ok, ErlCert,Cert};
- false ->
- crl_issuer(CRL, Rest, Ignore)
- end.
-
-crl_issuer(_,_, [],_) ->
- {error, issuer_not_found};
-crl_issuer(IssuerName, CRL, [Cert | Rest], Ignore) ->
- ErlCert = public_key:pkix_decode_cert(Cert, otp),
- TBSCertificate = ErlCert#'OTPCertificate'.tbsCertificate,
- Issuer = public_key:pkix_normalize_name(
- TBSCertificate#'OTPTBSCertificate'.subject),
-
- case
- public_key:pkix_is_issuer(CRL, ErlCert) andalso
- check_extension_crl_signer(ErlCert) andalso
- is_signer(ErlCert, CRL, Ignore)
- of
- true ->
- case pubkey_cert:is_issuer(Issuer, IssuerName) of
- true ->
- {ok, ErlCert,Cert};
- false ->
- crl_issuer(IssuerName, CRL, Rest, Ignore)
- end;
- false ->
- crl_issuer(IssuerName, CRL, Rest, Ignore)
- end.
-
-read_certs(Test) ->
- File = test_file(Test),
- Ders = erl_make_certs:pem_to_der(File),
- [Cert || {'Certificate', Cert, not_encrypted} <- Ders].
-
-read_crls(Test) ->
- File = test_file(Test),
- Ders = erl_make_certs:pem_to_der(File),
- [CRL || {'CertificateList', CRL, not_encrypted} <- Ders].
-test_file(Test) ->
- io:format("TEST: ~p~n", [Test]),
- file(?CONV, lists:append(string:tokens(Test, " -")) ++ ".pem").
+dp_crlissuer_to_issuer(DPCRLIssuer) ->
+ [{directoryName, Issuer}] = pubkey_cert_records:transform(DPCRLIssuer, decode),
+ Issuer.
-file(Sub,File) ->
- TestDir = case get(datadir) of
- undefined -> "./pkits_SUITE_data";
- Dir when is_list(Dir) ->
- Dir
- end,
- AbsFile = filename:join([TestDir,Sub,File]),
- case filelib:is_file(AbsFile) of
- true -> ok;
- false ->
- ?error("Couldn't read data from ~p ~n",[AbsFile])
- end,
- AbsFile.
+%%%%%%%%%%%%%%% CA mappings %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
cas(Chap) ->
CAS = intermidiate_cas(Chap),
@@ -1242,17 +1021,15 @@ intermidiate_cas(Chap) when Chap == "4.6.2" ->
intermidiate_cas(Chap) when Chap == "4.6.3" ->
["basicConstraints Not Critical cA False CA Cert"];
-intermidiate_cas(Chap) when Chap == "4.5.2";
- Chap == "4.5.5" ->
- ["Basic Self-Issued New Key CA Cert"];
-
-intermidiate_cas(Chap) when Chap == "4.5.1" ->
+intermidiate_cas(Chap) when Chap == "4.5.1";
+ Chap == "4.5.2" ->
["Basic Self-Issued New Key OldWithNew CA Cert", "Basic Self-Issued New Key CA Cert"];
intermidiate_cas(Chap) when Chap == "4.5.3" ->
["Basic Self-Issued Old Key NewWithOld CA Cert", "Basic Self-Issued Old Key CA Cert"];
-intermidiate_cas(Chap) when Chap == "4.5.4" ->
+intermidiate_cas(Chap) when Chap == "4.5.4";
+ Chap == "4.5.5" ->
["Basic Self-Issued Old Key CA Cert"];
intermidiate_cas(Chap) when Chap == "4.13.1";
@@ -1301,9 +1078,6 @@ intermidiate_cas(Chap) when Chap == "4.13.19" ->
["nameConstraints DN1 Self-Issued CA Cert",
"nameConstraints DN1 CA Cert"];
-intermidiate_cas(Chap) when Chap == "4.5.6" ->
- ["Basic Self-Issued CRL Signing Key CA Cert"];
-
intermidiate_cas(Chap) when Chap == "4.7.1";
Chap == "4.7.4" ->
["keyUsage Critical keyCertSign False CA Cert"];
@@ -1387,29 +1161,349 @@ intermidiate_cas(Chap) when Chap == "4.6.16" ->
"pathLenConstraint0 Self-Issued CA Cert",
"pathLenConstraint0 CA Cert"];
-intermidiate_cas(Chap) when Chap == "4.5.7";
- Chap == "4.5.8"
- ->
- ["Basic Self-Issued CRL Signing Key CRL Cert",
- "Basic Self-Issued CRL Signing Key CA Cert"].
+intermidiate_cas(Chap) when Chap == "4.4.1" ->
+ ["No CRL CA Cert"];
-error(Format, Args, File0, Line) ->
- File = filename:basename(File0),
- Pid = group_leader(),
- Pid ! {failed, File, Line},
- io:format(Pid, "~s(~p): ERROR"++Format, [File,Line|Args]).
+intermidiate_cas(Chap) when Chap == "4.4.2" ->
+ ["Revoked subCA Cert", "Good CA Cert"];
-warning(Format, Args, File0, Line) ->
- File = filename:basename(File0),
- io:format("~s(~p): Warning "++Format, [File,Line|Args]).
+intermidiate_cas(Chap) when Chap == "4.4.3" ->
+ ["Good CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.4.4" ->
+ ["Bad CRL Signature CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.4.5" ->
+ ["Bad CRL Issuer Name CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.4.6" ->
+ ["Wrong CRL CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.4.7" ->
+ ["Two CRLs CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.4.8" ->
+ ["Unknown CRL Entry Extension CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.4.9";
+ Chap == "4.4.10" ->
+ ["Unknown CRL Extension CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.4.11" ->
+ ["Old CRL nextUpdate CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.4.12" ->
+ ["pre2000 CRL nextUpdate CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.4.13" ->
+ ["GeneralizedTime CRL nextUpdate CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.4.14";
+ Chap == "4.4.15" ->
+ ["Negative Serial Number CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.4.16";
+ Chap == "4.4.17";
+ Chap == "4.4.18" ->
+ ["Long Serial Number CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.4.19";
+ Chap == "4.4.20" ->
+ ["Separate Certificate and CRL Keys Certificate Signing CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.4.21" ->
+ ["Separate Certificate and CRL Keys CA2 Certificate Signing CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.14.1";
+ Chap == "4.14.2";
+ Chap == "4.14.3";
+ Chap == "4.14.4" ->
+ ["distributionPoint1 CA Cert"];
+intermidiate_cas(Chap) when Chap == "4.14.5";
+ Chap == "4.14.6";
+ Chap == "4.14.7";
+ Chap == "4.14.8";
+ Chap == "4.14.9" ->
+ ["distributionPoint2 CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.14.10" ->
+ ["No issuingDistributionPoint CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.14.11" ->
+ ["onlyContainsUserCerts CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.14.12";
+ Chap == "4.14.13" ->
+ ["onlyContainsCACerts CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.14.14" ->
+ ["onlyContainsAttributeCerts CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.14.15";
+ Chap == "4.14.16" ->
+ ["onlySomeReasons CA1 Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.14.17" ->
+ ["onlySomeReasons CA2 Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.14.18" ->
+ ["onlySomeReasons CA3 Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.14.19";
+ Chap == "4.14.20";
+ Chap == "4.14.21" ->
+ ["onlySomeReasons CA4 Cert"];
+intermidiate_cas(Chap) when Chap == "4.14.22";
+ Chap == "4.14.23" ->
+ ["indirectCRL CA1 Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.14.24";
+ Chap == "4.14.25";
+ Chap == "4.14.26" ->
+ ["indirectCRL CA2 Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.14.27" ->
+ ["indirectCRL CA2 Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.14.28";
+ Chap == "4.14.29" ->
+ ["indirectCRL CA3 Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.14.31";
+ Chap == "4.14.32";
+ Chap == "4.14.33" ->
+ ["indirectCRL CA6 Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.14.34";
+ Chap == "4.14.35" ->
+ ["indirectCRL CA5 Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.15.1" ->
+ ["deltaCRLIndicator No Base CA Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.15.2";
+ Chap == "4.15.3";
+ Chap == "4.15.4";
+ Chap == "4.15.5";
+ Chap == "4.15.6";
+ Chap == "4.15.7" ->
+ ["deltaCRL CA1 Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.15.8";
+ Chap == "4.15.9" ->
+ ["deltaCRL CA2 Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.15.10" ->
+ ["deltaCRL CA3 Cert"];
+
+intermidiate_cas(Chap) when Chap == "4.5.6";
+ Chap == "4.5.7" ->
+ ["Basic Self-Issued CRL Signing Key CA Cert"];
+intermidiate_cas(Chap) when Chap == "4.5.8" ->
+ ["Basic Self-Issued CRL Signing Key CRL Cert"].
+
+
+%%%%%%%%%%%%%%% CRL mappings %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+crl_names("4.4.1") ->
+ ["Trust Anchor Root CRL"];
+crl_names("4.4.2") ->
+ ["Trust Anchor Root CRL", "Good CA CRL", "Revoked subCA CRL"];
+crl_names("4.4.3") ->
+ ["Trust Anchor Root CRL", "Good CA CRL", "Revoked subCA CRL"];
+crl_names("4.4.4") ->
+ ["Trust Anchor Root CRL", "Bad CRL Signature CA CRL"];
+crl_names("4.4.5") ->
+ ["Trust Anchor Root CRL", "Bad CRL Issuer Name CA CRL"];
+crl_names("4.4.6") ->
+ ["Trust Anchor Root CRL", "Wrong CRL CA CRL"];
+crl_names("4.4.7") ->
+ ["Trust Anchor Root CRL", "Two CRLs CA Good CRL", "Two CRLs CA Bad CRL"];
+crl_names("4.4.8") ->
+ ["Trust Anchor Root CRL", "Unknown CRL Entry Extension CA CRL"];
+crl_names(Chap) when Chap == "4.4.9";
+ Chap == "4.4.10"->
+ ["Trust Anchor Root CRL", "Unknown CRL Extension CA CRL"];
+crl_names("4.4.11") ->
+ ["Trust Anchor Root CRL", "Old CRL nextUpdate CA CRL"];
+crl_names("4.4.12") ->
+ ["Trust Anchor Root CRL", "pre2000 CRL nextUpdate CA CRL"];
+crl_names("4.4.13") ->
+ ["Trust Anchor Root CRL", "GeneralizedTime CRL nextUpdate CA CRL"];
+crl_names(Chap) when Chap == "4.4.14";
+ Chap == "4.4.15"->
+ ["Trust Anchor Root CRL", "Negative Serial Number CA CRL"];
+crl_names(Chap) when Chap == "4.4.16";
+ Chap == "4.4.17";
+ Chap == "4.4.18" ->
+ ["Trust Anchor Root CRL", "Long Serial Number CA CRL"];
+crl_names(Chap)when Chap == "4.4.19";
+ Chap == "4.4.20" ->
+ ["Trust Anchor Root CRL", "Separate Certificate and CRL Keys CRL"];
+crl_names("4.4.21") ->
+ ["Trust Anchor Root CRL", "Separate Certificate and CRL Keys CA2 CRL"];
+crl_names(Chap) when Chap == "4.5.1";
+ Chap == "4.5.2"->
+ ["Trust Anchor Root CRL", "Basic Self-Issued New Key CA CRL"];
+crl_names(Chap) when Chap == "4.5.3";
+ Chap == "4.5.4";
+ Chap == "4.5.5" ->
+ ["Trust Anchor Root CRL", "Basic Self-Issued Old Key Self-Issued Cert CRL",
+ "Basic Self-Issued Old Key CA CRL"];
+crl_names(Chap) when Chap == "4.5.6";
+ Chap == "4.5.7";
+ Chap == "4.5.8" ->
+ ["Trust Anchor Root CRL", "Basic Self-Issued CRL Signing Key CRL Cert CRL",
+ "Basic Self-Issued CRL Signing Key CA CRL"
+ ];
+crl_names("4.7.4") ->
+ ["Trust Anchor Root CRL", "keyUsage Critical cRLSign False CA CRL"];
+crl_names("4.7.5") ->
+ ["Trust Anchor Root CRL", "keyUsage Not Critical cRLSign False CA CRL"];
+crl_names(Chap) when Chap == "4.14.1";
+ Chap == "4.14.2";
+ Chap == "4.14.3";
+ Chap == "4.14.4" ->
+ ["Trust Anchor Root CRL", "distributionPoint1 CA CRL"];
+crl_names(Chap) when Chap == "4.14.5";
+ Chap == "4.14.6";
+ Chap == "4.14.7";
+ Chap == "4.14.8";
+ Chap == "4.14.9" ->
+ ["Trust Anchor Root CRL", "distributionPoint2 CA CRL"];
+crl_names("4.14.10") ->
+ ["Trust Anchor Root CRL", "No issuingDistributionPoint CA CRL"];
+crl_names("4.14.11") ->
+ ["Trust Anchor Root CRL", "onlyContainsUserCerts CA CRL"];
+crl_names(Chap) when Chap == "4.14.12";
+ Chap == "4.14.13" ->
+ ["Trust Anchor Root CRL", "onlyContainsCACerts CA CRL"];
+crl_names("4.14.14") ->
+ ["Trust Anchor Root CRL", "onlyContainsAttributeCerts CA CRL"];
+crl_names(Chap) when Chap == "4.14.15";
+ Chap == "4.14.16" ->
+ ["Trust Anchor Root CRL", "onlySomeReasons CA1 compromise CRL",
+ "onlySomeReasons CA1 other reasons CRL"];
+crl_names("4.14.17") ->
+ ["Trust Anchor Root CRL",
+ "onlySomeReasons CA2 CRL1", "onlySomeReasons CA2 CRL2"];
+crl_names("4.14.18") ->
+ ["Trust Anchor Root CRL",
+ "onlySomeReasons CA3 compromise CRL", "onlySomeReasons CA3 other reasons CRL"];
+crl_names(Chap) when Chap == "4.14.19";
+ Chap == "4.14.20";
+ Chap == "4.14.21" ->
+ ["Trust Anchor Root CRL", "onlySomeReasons CA4 compromise CRL",
+ "onlySomeReasons CA4 other reasons CRL"];
+crl_names(Chap) when Chap == "4.14.22";
+ Chap == "4.14.23";
+ Chap == "4.14.24";
+ Chap == "4.14.25";
+ Chap == "4.14.26" ->
+ ["Trust Anchor Root CRL", "indirectCRL CA1 CRL"];
+crl_names("4.14.27") ->
+ ["Trust Anchor Root CRL", "Good CA CRL"];
+
+crl_names(Chap) when Chap == "4.14.28";
+ Chap == "4.14.29" ->
+ ["Trust Anchor Root CRL", "indirectCRL CA3 CRL", "indirectCRL CA3 cRLIssuer CRL"];
+crl_names("4.14.30") ->
+ ["Trust Anchor Root CRL", "indirectCRL CA4 cRLIssuer CRL"];
+crl_names(Chap) when Chap == "4.14.31";
+ Chap == "4.14.32";
+ Chap == "4.14.33";
+ Chap == "4.14.34";
+ Chap == "4.14.35" ->
+ ["Trust Anchor Root CRL", "indirectCRL CA5 CRL"];
+crl_names("4.15.1") ->
+ ["Trust Anchor Root CRL", "deltaCRLIndicator No Base CA CRL"];
+crl_names(Chap) when Chap == "4.15.2";
+ Chap == "4.15.3";
+ Chap == "4.15.4";
+ Chap == "4.15.5";
+ Chap == "4.15.6";
+ Chap == "4.15.7" ->
+ ["Trust Anchor Root CRL", "deltaCRL CA1 CRL", "deltaCRL CA1 deltaCRL"];
+crl_names(Chap) when Chap == "4.15.8";
+ Chap == "4.15.9" ->
+ ["Trust Anchor Root CRL", "deltaCRL CA2 CRL", "deltaCRL CA2 deltaCRL"];
+crl_names("4.15.10") ->
+ ["Trust Anchor Root CRL", "deltaCRL CA3 CRL", "deltaCRL CA3 deltaCRL"].
+
+crl_root_cert() ->
+ "Trust Anchor Root Certificate".
+
+crl_path("Trust Anchor Root CRL") ->
+ []; %% Signed directly by crl_root_cert
+crl_path("Revoked subCA CRL") ->
+ ["Good CA Cert", "Revoked subCA Cert"];
+crl_path("indirectCRL CA3 cRLIssuer CRL") ->
+ ["indirectCRL CA3 Cert", "indirectCRL CA3 cRLIssuer Cert"];
+crl_path("Two CRLs CA Good CRL") ->
+ ["Two CRLs CA Cert"];
+crl_path("Two CRLs CA Bad CRL") ->
+ ["Two CRLs CA Cert"];
+crl_path("Separate Certificate and CRL Keys CRL") ->
+ ["Separate Certificate and CRL Keys CRL Signing Cert"];
+crl_path("Separate Certificate and CRL Keys CA2 CRL") ->
+ ["Separate Certificate and CRL Keys CA2 CRL Signing Cert"];
+crl_path("Basic Self-Issued Old Key Self-Issued Cert CRL") ->
+ ["Basic Self-Issued Old Key CA Cert"];
+crl_path("Basic Self-Issued Old Key CA CRL") ->
+ ["Basic Self-Issued Old Key CA Cert", "Basic Self-Issued Old Key NewWithOld CA Cert"];
+
+crl_path("Basic Self-Issued CRL Signing Key CRL Cert CRL") ->
+ ["Basic Self-Issued CRL Signing Key CA Cert"];
+crl_path("Basic Self-Issued CRL Signing Key CA CRL") ->
+ ["Basic Self-Issued CRL Signing Key CA Cert", "Basic Self-Issued CRL Signing Key CRL Cert"];
+
+crl_path("onlySomeReasons CA1 compromise CRL") ->
+ ["onlySomeReasons CA1 Cert"];
+crl_path("onlySomeReasons CA1 other reasons CRL") ->
+ ["onlySomeReasons CA1 Cert"];
+crl_path("onlySomeReasons CA3 other reasons CRL") ->
+ ["onlySomeReasons CA3 Cert"];
+crl_path("onlySomeReasons CA3 compromise CRL") ->
+ ["onlySomeReasons CA3 Cert"];
+crl_path("onlySomeReasons CA4 compromise CRL") ->
+ ["onlySomeReasons CA4 Cert"];
+crl_path("onlySomeReasons CA4 other reasons CRL") ->
+ ["onlySomeReasons CA4 Cert"];
+crl_path("Basic Self-Issued New Key CA CRL") ->
+ ["Basic Self-Issued New Key CA Cert"];
+crl_path("deltaCRL CA1 deltaCRL") ->
+ crl_path("deltaCRL CA2 CRL");
+crl_path("deltaCRL CA2 deltaCRL") ->
+ crl_path("deltaCRL CA2 CRL");
+crl_path("deltaCRL CA3 deltaCRL") ->
+ crl_path("deltaCRL CA3 CRL");
+crl_path(CRL) when CRL == "onlySomeReasons CA2 CRL1";
+ CRL == "onlySomeReasons CA2 CRL2" ->
+ ["onlySomeReasons CA2 Cert"];
+
+crl_path(CRL) ->
+ L = length(CRL),
+ Base = string:sub_string(CRL, 1, L -3),
+ [Base ++ "Cert"].
+
+crls(CRLS) ->
+ lists:foldl(fun([], Acc) ->
+ Acc;
+ (CRLFile, Acc) ->
+ [CRL] = read_crls(CRLFile),
+ [CRL | Acc]
+ end, [], CRLS).
+
+
+%% TODO: If we implement policy support
%% Certificate policy tests need special handling. They can have several
%% sub tests and we need to check the outputs are correct.
-certificate_policies() ->
+certificate_policies_tests() ->
%%{ "4.8", "Certificate Policies" },
[{"4.8.1.1", "All Certificates Same Policy Test1", "-policy anyPolicy -explicit_policy", "True", ?NIST1, ?NIST1, 0},
- {"4.8.1.2", "All Certificates Same Policy Test1", "-policy ?NIST1 -explicit_policy", "True", ?NIST1, ?NIST1, 0},
+ {"4.8.1.2", "All Certificates Same Policy Test1", "-policy ?NIST1BasicSelfIssuedCRLSigningKeyCACert.pem -explicit_policy", "True", ?NIST1, ?NIST1, 0},
{"4.8.1.3", "All Certificates Same Policy Test1", "-policy ?NIST2 -explicit_policy", "True", ?NIST1, "<empty>", 43},
{"4.8.1.4", "All Certificates Same Policy Test1", "-policy ?NIST1 -policy ?NIST2 -explicit_policy", "True", ?NIST1, ?NIST1, 0},
{"4.8.2.1", "All Certificates No Policies Test2", "-policy anyPolicy", "False", "<empty>", "<empty>", 0},
@@ -1443,7 +1537,7 @@ certificate_policies() ->
{"4.8.18.2", "User Notice Qualifier Test18", "-policy ?NIST2", "True", "?NIST1:?NIST2", "?NIST2", 0},
{"4.8.19", "User Notice Qualifier Test19", "-policy anyPolicy", "False", "?NIST1", "?NIST1", 0},
{"4.8.20", "CPS Pointer Qualifier Test20", "-policy anyPolicy -explicit_policy", "True", "?NIST1", "?NIST1", 0}].
-require_explicit_policy() ->
+require_explicit_policy_tests() ->
%%{ "4.9", "Require Explicit Policy" },
[{"4.9.1", "Valid RequireExplicitPolicy Test1", "-policy anyPolicy", "False", "<empty>", "<empty>", 0},
{"4.9.2", "Valid RequireExplicitPolicy Test2", "-policy anyPolicy", "False", "<empty>", "<empty>", 0},
@@ -1453,7 +1547,7 @@ require_explicit_policy() ->
{"4.9.6", "Valid Self-Issued requireExplicitPolicy Test6", "-policy anyPolicy", "False", "<empty>", "<empty>", 0},
{"4.9.7", "Invalid Self-Issued requireExplicitPolicy Test7", "-policy anyPolicy", "True", "<empty>", "<empty>", 43},
{"4.9.8", "Invalid Self-Issued requireExplicitPolicy Test8", "-policy anyPolicy", "True", "<empty>", "<empty>", 43}].
-policy_mappings() ->
+policy_mappings_tests() ->
%%{ "4.10", "Policy Mappings" },
[{"4.10.1.1", "Valid Policy Mapping Test1", "-policy ?NIST1", "True", "?NIST1", "?NIST1", 0},
{"4.10.1.2", "Valid Policy Mapping Test1", "-policy ?NIST2", "True", "?NIST1", "<empty>", 43},
@@ -1483,7 +1577,7 @@ policy_mappings() ->
%% TODO: check notice display
{"4.10.14", "Valid Policy Mapping Test14", "-policy anyPolicy", "True", "?NIST1", "?NIST1", 0}].
-inhibit_policy_mapping() ->
+inhibit_policy_mapping_tests() ->
%%{ "4.11", "Inhibit Policy Mapping" },
[{"4.11.1", "Invalid inhibitPolicyMapping Test1", "-policy anyPolicy", "True", "<empty>", "<empty>", 43},
{"4.11.2", "Valid inhibitPolicyMapping Test2", "-policy anyPolicy", "True", "?NIST1", "?NIST1", 0},
@@ -1496,7 +1590,7 @@ inhibit_policy_mapping() ->
{"4.11.9", "Invalid Self-Issued inhibitPolicyMapping Test9", "-policy anyPolicy", "True", "<empty>", "<empty>", 43},
{"4.11.10", "Invalid Self-Issued inhibitPolicyMapping Test10", "-policy anyPolicy", "True", "<empty>", "<empty>", 43},
{"4.11.11", "Invalid Self-Issued inhibitPolicyMapping Test11", "-policy anyPolicy", "True", "<empty>", "<empty>", 43}].
-inhibit_any_policy() ->
+inhibit_any_policy_tests() ->
%%{ "4.12", "Inhibit Any Policy" },
[{"4.12.1", "Invalid inhibitAnyPolicy Test1", "-policy anyPolicy", "True", "<empty>", "<empty>", 43},
{"4.12.2", "Valid inhibitAnyPolicy Test2", "-policy anyPolicy", "True", "?NIST1", "?NIST1", 0},
@@ -1509,12 +1603,3 @@ inhibit_any_policy() ->
{"4.12.8", "Invalid Self-Issued inhibitAnyPolicy Test8", 43 },
{"4.12.9", "Valid Self-Issued inhibitAnyPolicy Test9", ok},
{"4.12.10", "Invalid Self-Issued inhibitAnyPolicy Test10", 43 }].
-
-crypto_support_check(Config) ->
- try crypto:sha256(<<"Test">>) of
- _ ->
- Config
- catch error:notsup ->
- crypto:stop(),
- {skip, "To old version of openssl"}
- end.
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/BadCRLIssuerNameCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/BadCRLIssuerNameCACRL.pem
new file mode 100644
index 0000000000..a4cf643928
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/BadCRLIssuerNameCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzDCBtQIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZSW5jb3JyZWN0IENS
+TCBJc3N1ZXIgTmFtZRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0w
+HwYDVR0jBBgwFoAUEXLyNV0E1Q5KIAcHQSj9lHAAHHEwCgYDVR0UBAMCAQEwDQYJ
+KoZIhvcNAQELBQADggEBAIIk/+6+dqID/yKmKYDaVgXh/yLWZO4uV1m6OYRSrdfa
+8aqYcgwChIaIIX465VDCpGO2LMOXV1Z/COerJguUNRGaiSQCSrsIpNGGZTQE+HNN
+C5mabMfPuSVaBgBMzQZTY3ggLNr6x1G7dXlm+Fpo+q/fSznBVsGFHCgtp53FJHBi
+Xcd3LTBFyZLiyhITqm2xvTwyzl/URcDYBp+tWTmn7ZxADdoThK7OkY2U13O0vxKj
+/haiS1NuVbX2QkS+eH399jGQHAHiBOFlRPs8FGdshTWOJxmLMMTIuS7cIEH3Oz8t
+b1Go7j4qHIYr/b2uKHb9RBMFNRKsZfqVKEQ+1J8TPNc=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/BadCRLSignatureCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/BadCRLSignatureCACRL.pem
new file mode 100644
index 0000000000..e17fac1f20
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/BadCRLSignatureCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBxzCBsAIBATANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEdMBsGA1UEAxMUQmFkIENSTCBTaWdu
+YXR1cmUgQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAtMB8GA1Ud
+IwQYMBaAFDGLNY2eRGEwFN7nCy4UGUgk2/m9MAoGA1UdFAQDAgEBMA0GCSqGSIb3
+DQEBCwUAA4IBAQFsPfAbIcqMI+lzJmY396TIwn2ubAkQgm95U712CIuw00auDjGM
+iebAOLbNLgSktivN23rc5rPxSOqeWsNfgVxwCPKvBv7v4PsLQhzK2OyonV5Cmdl1
+biEymv88bEUcEnibvH3O0Lg3RySMNjPYqZgPfwF9b0iTYeb2JYk+lX+m3WGr5UPg
+M9nuC6sychRxGgF1AQOd/N6spvgSAazEyNqCWhcwdrOeM+HEDPAFOOFAhmCp+jjh
+Fgh2E2Gq1vbxGSzzKlRBDrO1hovT9XhvEa2SjopbWMbfOR/wPTjxEImIQDWw69RL
+KnTL/OdnUXifoSNJIJK3ffPTSG5AEHFUm6j+
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/BadSignedCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/BadSignedCACRL.pem
new file mode 100644
index 0000000000..58c89f81c6
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/BadSignedCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBwDCBqQIBATANBgkqhkiG9w0BAQsFADBGMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEWMBQGA1UEAxMNQmFkIFNpZ25lZCBD
+QRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0wHwYDVR0jBBgwFoAU
+e90QO0rgyN1EhU6IPFqLzZkik68wCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQELBQAD
+ggEBAEBt9Jji+aprAMfoXE8zclIPjs520FFAXSPqsJt77l8vTA50oUbD0sILCDfA
+raU16Pm3lIT3wuEAUmM7luTzG5Kg5qbgyv9cLm3rSJOADZCw6oahFAEbZyqOsgfP
+QYRy9EOeg8TUc6EPrlZhTrZzf2kgmDeL6WxTz2Len415oFf6JsDNMLcHSQkDzmdi
+OxYXDA2w5khPrzX0cxbMpmZVJiQksdKJg/RGGCqNJVcZwTqAZFNzSldJvx7fqQPI
+SkcKznfT/cczC37Q2uCupIyG4cntiRdIztkHiKQFRkiUxIMQA3ky3t+ib3lZDnl2
+VwGLcmmYuu4ScsqL+OP0ZjpzZKM=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/BadnotAfterDateCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/BadnotAfterDateCACRL.pem
new file mode 100644
index 0000000000..3c952437ce
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/BadnotAfterDateCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBxzCBsAIBATANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEdMBsGA1UEAxMUQmFkIG5vdEFmdGVy
+IERhdGUgQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAtMB8GA1Ud
+IwQYMBaAFCwO/ffuPPOkZuznBZ+Is+LPdEbYMAoGA1UdFAQDAgEBMA0GCSqGSIb3
+DQEBCwUAA4IBAQBcYZ4ucABlH6Z0XtJMAmcrX6txzEawWpikzfzapuRe0YBL6IHm
+LRqW+vpBfR5vSQ2PBLXFJA9eVpJjjBieF9USt58DsvTF1nuPMJCk1WhxfDrE/hWy
+vR3tnLW38c6e4+omJN9fotQilw+sq32j1yQjnR4KU+VxMs6sgs1W2XmmWpTP+fQw
+W9ukAXGzwQNmBb4mbOjLDVv3fXxzVI5gK8bhcxh83cfmHMkI+dp1g4nAxQ5gRTaw
+2ypGWph9170Z1Y/W6eznbNGA40YreXqqZeq8ujpjYlksC6tpQkOp8lBJGwi7fKaI
+IxV4vXSSbExz7A4CFQ1zYx1ciciCGWcyOyqx
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/BadnotBeforeDateCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/BadnotBeforeDateCACRL.pem
new file mode 100644
index 0000000000..fb4bf11a7c
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/BadnotBeforeDateCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByDCBsQIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UEAxMVQmFkIG5vdEJlZm9y
+ZSBEYXRlIENBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8wLTAfBgNV
+HSMEGDAWgBRjPrwanvuh8lmhL0uV/ubeVriGQDAKBgNVHRQEAwIBATANBgkqhkiG
+9w0BAQsFAAOCAQEAnN6H352YCy4U82Ndz+iFkIxTLVmwiMi00RViqbziNXLSYbbX
+MpJsCPn93wGhEOokDcJBoWq6/2QeHHmEs9rN758+loP1P1R27wgicrcPIEbT0+BT
+st0TYtZExQoXWVe5QtyTa4cNR7Wz88ga1xf3GyngnjFAHmAWrU4IOpxhKvs2FOS1
+zPaxzdgvNZyxvltIUt6zujlAxDf3wJK9qWyZSt7ORob8RVaAJR12UA60qyVbA2HX
+BdAavTzVJatY2AjtnIiFWAmtI3s/jIvLLNX5yUVVDSEDCI3zWY5YR/URyf4uViEk
+qyy8PQ83mVkpTjaWRxjFrcIvwlUvmRlHTvp2NQ==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/BasicSelfIssuedCRLSigningKeyCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/BasicSelfIssuedCRLSigningKeyCACRL.pem
new file mode 100644
index 0000000000..9a34f8a612
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/BasicSelfIssuedCRLSigningKeyCACRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIIB+zCB5AIBATANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEtMCsGA1UEAxMkQmFzaWMgU2VsZi1J
+c3N1ZWQgQ1JMIFNpZ25pbmcgS2V5IENBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEw
+ODMwMDBaMCIwIAIBAxcNMTAwMTAxMDgzMDAwWjAMMAoGA1UdFQQDCgEBoC8wLTAf
+BgNVHSMEGDAWgBQkwVVx+p7hIYUq8K1hpxW51U1DFzAKBgNVHRQEAwIBATANBgkq
+hkiG9w0BAQsFAAOCAQEAE4g/85gXzIM9TYVxAXxgc8KwavltVn6wFCluy5zwxGRz
+lpJXjJWctmJ+Z1qPVlL/K8aOW+YW+keL5zcINUYHxipyQLt+W7qeFDivq5ABgK62
+qpZ6tpwTa02IXkUDixs2QVXM7vXLrHlYacLGjIti+LUP3R7y3fLSjg3BMZcvwA17
+0N1YhfYZrNVwfwqv2H58HIdo5+SSCcUGZe9sbkqRINta3/OKnlS5e7Y4KW5I65oT
+2eX4iPmPNR6NqNv6D+mMXxt6uJGw8NRA2NqO8MS8UqkA6bmZldcdkefcJ5ETJu8r
+xewaq22gblqFL2vdcM/JJ61rcuPVZTqChfDyaQu/rg==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/BasicSelfIssuedCRLSigningKeyCRLCertCRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/BasicSelfIssuedCRLSigningKeyCRLCertCRL.pem
new file mode 100644
index 0000000000..447b7ec511
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/BasicSelfIssuedCRLSigningKeyCRLCertCRL.pem
@@ -0,0 +1,15 @@
+-----BEGIN X509 CRL-----
+MIICZjCCAU4CAQEwDQYJKoZIhvcNAQELBQAwXTELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExLTArBgNVBAMTJEJhc2ljIFNlbGYt
+SXNzdWVkIENSTCBTaWduaW5nIEtleSBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMx
+MDgzMDAwWqCBvDCBuTAfBgNVHSMEGDAWgBQpmkUuNpWd7PJeVJwT1dn2RJEsEzCB
+iQYDVR0cAQH/BH8wfaB7oHmkdzB1MQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVz
+dCBDZXJ0aWZpY2F0ZXMgMjAxMTFFMEMGA1UEAxM8U2VsZi1Jc3N1ZWQgQ2VydCBE
+UCBmb3IgQmFzaWMgU2VsZi1Jc3N1ZWQgQ1JMIFNpZ25pbmcgS2V5IENBMAoGA1Ud
+FAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQAnpcVORfH/FTHsCl1sjvHIvPQTdrMI
+73pWCshHQB8/eCwDmTg+xFk7n4KCYSRgbN6ingc4wzbnLkb1WPmw80aXbqd4Tg+/
+U9T0ANxSewLBeW0zUFFcW5LjqrxCJVV4IMDXh+D6F+M8uEWE8/UGzpz3qkIBfW/a
+KHQszpVl7i9x0MhjHFAXkJbCuB7ymXntYfbSQNHvMWwbPW+nt0HadbJqjJy4FH4V
+kaSg/tkFa1StClKjm3T+GDhISPpDWthGUmS4n9cmj4QnPSd6E57d+ix0hb5oqQAg
+DYeL9/xaN7fOIzuGknzE3+p19OT8vNhvp7mRoMpZpzPtm0so48EXagMx
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/BasicSelfIssuedNewKeyCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/BasicSelfIssuedNewKeyCACRL.pem
new file mode 100644
index 0000000000..9c3d7d42ab
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/BasicSelfIssuedNewKeyCACRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIIB8zCB3AIBATANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMcQmFzaWMgU2VsZi1J
+c3N1ZWQgTmV3IEtleSBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjAi
+MCACAQMXDTEwMDEwMTA4MzAwMFowDDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgw
+FoAUoPzALOtV7pIGbKke6V9fop9iI5UwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEL
+BQADggEBAHAue0P1w9Vgt/mvhideeiLl2unmfJC0JKCIBeeWXl0CYW5jcSrshCwZ
+dHRM5uhs8RQCNRnJIrhwuRUvh9SaDsZGFWqAlOdYbkaXdzbX1cyTigQ0tCNTN+aD
+FxGTm+CWxi6awN2a2ZcOzZ3KuB8D7q0b1mVtnMFsvV7JEMyxZRWFm5/8yJAliOKc
+8wrWtDfbpkU6c1P0l2bPzvmDirISAKwj2IwibkbQimbISwt1b/jijPOQgiArom5S
+sHzZh2DI9xdDBXLImkJveUGF1d8zIngbvyn19Iz7bT8mJVANx2K0U6kC3ODgov8b
+ARv87w9CDE+nCZz505ZS1f/pVtswcPg=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/BasicSelfIssuedOldKeyCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/BasicSelfIssuedOldKeyCACRL.pem
new file mode 100644
index 0000000000..3f330c715a
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/BasicSelfIssuedOldKeyCACRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIIB8zCB3AIBATANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMcQmFzaWMgU2VsZi1J
+c3N1ZWQgT2xkIEtleSBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjAi
+MCACAQQXDTEwMDEwMTA4MzAwMFowDDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgw
+FoAUiF++PzU5ZprrTcImGyaxKie1CCowCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEL
+BQADggEBALJPjOBcvrNJea5bTdcDaUR+3rWdWzwAFlIFN29RBQgnnwGyoPnMhBaI
+MBMMxrzPQiqc908w+4E82FSbeVKbutPPjs4izG8wE3jwPk5GmWPKozrZZ3Eliqd1
+9Kx1he6yCDnPpHZ6D4qm6qyy/xmspL7X3W40Dz56ldxu3DECDIrDACjdnu9PERDu
+acqDQPFKbcaZeCY9QX9/vsG+vrWH+HxEkzA/S9tyojYSLfVLvYubBd0OAWhTqqR6
+5h2Gx6z7DH6/1vtctb0HGg2VY7bVjpL0YhwXoTjZZXbWlLH1l7N+fP2cH5eqDwwF
+DRhIRhasjSucbUzOFXoc3dmBrOKwtjM=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/BasicSelfIssuedOldKeySelfIssuedCertCRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/BasicSelfIssuedOldKeySelfIssuedCertCRL.pem
new file mode 100644
index 0000000000..8fa388cd45
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/BasicSelfIssuedOldKeySelfIssuedCertCRL.pem
@@ -0,0 +1,15 @@
+-----BEGIN X509 CRL-----
+MIICVjCCAT4CAQEwDQYJKoZIhvcNAQELBQAwVTELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExJTAjBgNVBAMTHEJhc2ljIFNlbGYt
+SXNzdWVkIE9sZCBLZXkgQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqg
+gbQwgbEwHwYDVR0jBBgwFoAU3Q11jVNoEsTLFUDAFIYUFjChvq8wgYEGA1UdHAEB
+/wR3MHWgc6BxpG8wbTELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlm
+aWNhdGVzIDIwMTExPTA7BgNVBAMTNFNlbGYtSXNzdWVkIENlcnQgRFAgZm9yIEJh
+c2ljIFNlbGYtSXNzdWVkIE9sZCBLZXkgQ0EwCgYDVR0UBAMCAQEwDQYJKoZIhvcN
+AQELBQADggEBAMCggIi2OzR9WO+bNMEVT0PdVnX9lNyjIAmJZj6g/SECKy85ZQp/
+Xs5YY43xxXswtJ+70cQGunzXIXd22a5xTlGlcM0orE2WIbDaoJskD3D5HKPCb6MR
+C0XwhV6KGmB+H/rb77EnHEHTHQ6SwKfSaVSVrVkaGD4HYHAKiOqOzkInultUR04p
+jTJ3watfZyB+L9Xmfj+Bz/GvTCDdYOQfs9uXhWH+C7HQPe8uXD1C1tSDD9+XnUHo
+rScJkZkZpExsGvF8ngtjp+0SUmCTM7VejHtKWD2l4KO+TkjEM9PG0+Hf75iOq9eO
+UdA7iu/ozw7EbowpmABJmeVSiWD9S4/deBc=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/DSACACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/DSACACRL.pem
new file mode 100644
index 0000000000..7d1d13a767
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/DSACACRL.pem
@@ -0,0 +1,7 @@
+-----BEGIN X509 CRL-----
+MIHeMIGeAgEBMAkGByqGSM44BAMwPzELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRl
+c3QgQ2VydGlmaWNhdGVzIDIwMTExDzANBgNVBAMTBkRTQSBDQRcNMTAwMTAxMDgz
+MDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0wHwYDVR0jBBgwFoAUj5DGjHToewzIWcd9
+PFtUWWAlC7EwCgYDVR0UBAMCAQEwCQYHKoZIzjgEAwMwADAtAhQCMhWXnJJuf+2W
+pXCHP72o0SdqdAIVAMsLFa667x5ODKAkIlFPI/Ge57Hj
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/DSAParametersInheritedCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/DSAParametersInheritedCACRL.pem
new file mode 100644
index 0000000000..545293a0db
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/DSAParametersInheritedCACRL.pem
@@ -0,0 +1,8 @@
+-----BEGIN X509 CRL-----
+MIHyMIGzAgEBMAkGByqGSM44BAMwVDELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRl
+c3QgQ2VydGlmaWNhdGVzIDIwMTExJDAiBgNVBAMTG0RTQSBQYXJhbWV0ZXJzIElu
+aGVyaXRlZCBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0wHwYD
+VR0jBBgwFoAUZYGfcDqMrfZDHcjnj1WO6Evbh+IwCgYDVR0UBAMCAQEwCQYHKoZI
+zjgEAwMvADAsAhQ80F0tKnVM5ABE7rErqs6hgIc8gAIULN+1q3I9zEFZqSneZHjR
+yXC3FZQ=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/GeneralizedTimeCRLnextUpdateCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/GeneralizedTimeCRLnextUpdateCACRL.pem
new file mode 100644
index 0000000000..cab3080a90
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/GeneralizedTimeCRLnextUpdateCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB1DCBvQIBATANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEoMCYGA1UEAxMfR2VuZXJpemVkVGlt
+ZSBDUkwgbmV4dFVwZGF0ZSBDQRcNMTAwMTAxMDgzMDAwWhgPMjA1MDAxMDExMjAx
+MDBaoC8wLTAfBgNVHSMEGDAWgBR+KnXvDDbHS+cg2X9hSEeOEoMaLDAKBgNVHRQE
+AwIBATANBgkqhkiG9w0BAQsFAAOCAQEAkJf/F0AFe6ViIe9vaZwlRWs2cge1PnzK
+viLSchMF7AdYTAPq0hfWo34GTEw1e0k3KTIJlnj+fD3wpnhTA3qt3YzyS+wvdSZL
+e2Ogr4CvWKWbHi+5klCk5cJBkT5+SRZQErgATVyQYkcSYHYR8iPZ3izeSuoCPq8z
+KSBdZqgRqdJuPftmcbi4XI30zAJCDmMxuC++D3uTc8NHA6DrtAf4p2Iv0f33jtYo
+CsFBEVKpYd/0At1yxRDJ1MvKsiHZM3Pb2Ygoi5koy2gaNE34l128etEN6U0cZ7iy
+A5OYdxjNKkR1Xvk33eje3ixCOvsidtMSb7446sL6w2zQHQDJITAzcg==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/GoodCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/GoodCACRL.pem
new file mode 100644
index 0000000000..f482eae237
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/GoodCACRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIICADCB6QIBATANBgkqhkiG9w0BAQsFADBAMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEQMA4GA1UEAxMHR29vZCBDQRcNMTAw
+MTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjBEMCACAQ4XDTEwMDEwMTA4MzAwMFow
+DDAKBgNVHRUEAwoBATAgAgEPFw0xMDAxMDEwODMwMDFaMAwwCgYDVR0VBAMKAQGg
+LzAtMB8GA1UdIwQYMBaAFFgBhCQbvCtSlEo9pRByFFH1rzrJMAoGA1UdFAQDAgEB
+MA0GCSqGSIb3DQEBCwUAA4IBAQA9vPMLiinD8G7FaoTsu8T2jUrTi1OLPHxKnrlB
+rAP/eHa+VQV1HJfY5Gjq1dpNgzZqDIgQM5QHPm0aSgMN7Ultx+XzbxRswLnwgQrZ
+7f76Tlky1I+jz7/p3AEynrNR72v64SZt46UhpSuWBHoF1uEVtgirTZNfOEaGUJTN
+OaTA5U55/iw9BKjHN0e/Vd7OGnrk5h6FsgWOiasGn6/tym9teDt/L2hlOdsZsvX1
+KPc0ExUHVjJIUBYTooqyy/CuTzFHla6RYVYvJuRF5qYCxa0GTZK3ImCtJ3XfsGdf
+LEJDZ7T17xBQHucMvIVLm6vY44WUy7PqQhZJskhJMEvj01ZE
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/GoodsubCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/GoodsubCACRL.pem
new file mode 100644
index 0000000000..04790063da
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/GoodsubCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBvTCBpgIBATANBgkqhkiG9w0BAQsFADBDMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTETMBEGA1UEAxMKR29vZCBzdWJDQRcN
+MTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0wHwYDVR0jBBgwFoAUMgcs
+nnRdLV0pu7F6jTsVUrR9QngwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQELBQADggEB
+AEbJGAG0MzgAYBNHSm7qI/hQO0cVg2FSkzuKdKB4zp0Jl2hvgjJKAEnU1QMkCyW1
+7B1srXRhjyLp8lvBZPWtXtev7QSkNV9ysUiNDdg+FThP9WVsf+zPu2+UuYn57A0U
+0NeWGv0DeoZG1mzRq5DcvLk98o3ErZug8ABzaUlprx8yGvzqw5abyj7AgeXvp5fs
+0Jo+ya4e8aFrBx/8k2gPvGTv5AOaa2+tLFQsVOm4PUQk1ANklm+CIlOz5hvvZgTp
+UXaiY/BrYCSV+N7MFXNH/75HUm4PPLFr5LgI/whOgR6bFC3e/5kTdQpVBwGBNvNy
+OEp8bA7ViIqbseokJI3q29w=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/GoodsubCAPanyPolicyMapping1to2CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/GoodsubCAPanyPolicyMapping1to2CACRL.pem
new file mode 100644
index 0000000000..ed9ac1744d
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/GoodsubCAPanyPolicyMapping1to2CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB1TCBvgIBATANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTErMCkGA1UEAxMiR29vZCBzdWJDQSBQ
+YW55UG9saWN5IE1hcHBpbmcgMXRvMhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgz
+MDAwWqAvMC0wHwYDVR0jBBgwFoAUW3N5meOuBtOKpjNOFHjkoB2x5MkwCgYDVR0U
+BAMCAQEwDQYJKoZIhvcNAQELBQADggEBAKKfTLLrhhr5sQTxYh0/59xGeCAPDiAb
+hZVIWXYrEy3HdaKVI786DjInVHDAHrpvO+pL52/unPqNZAFSpNpk8+4otR2/c9lu
+7EtForVhzkCVgO+bnGnLPqgYKq91tLD/NtB4OdfXlezP1LN4f4j8yHwmkJ9kv5bS
+op2gs30YZo4f5rgRFvDFzL0bYMzHcY/NVLqnHPp+8NqPsNAdyWl/90QjCG6Fj636
+8D7SQQpDY4Qrq0raGpsspyYkMeshUhLiEb8A2rnaen0dhrG8+5W2WP0zNoSQvKH8
+D2JLtZK+l75rRRZm5V9PNrza+ZfjbEABUmJjJ/LOkLiyNna789a2+9g=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/LongSerialNumberCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/LongSerialNumberCACRL.pem
new file mode 100644
index 0000000000..d0d3787427
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/LongSerialNumberCACRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIIB/zCB6AIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UEAxMVTG9uZyBTZXJpYWwg
+TnVtYmVyIENBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMDUwMwIUfwEC
+AwQFBgcICQoLDA0ODxAREhMXDTEwMDEwMTA4MzAwMFowDDAKBgNVHRUEAwoBAaAv
+MC0wHwYDVR0jBBgwFoAUC2O3R67CBzIbf2/jOrjqC//XZKQwCgYDVR0UBAMCAQEw
+DQYJKoZIhvcNAQELBQADggEBAAT3AsJOgrvo4ohLomVgQey2sS6xh4bvK/qZmx4v
+czM1U9QpS7uO1QDgIkdxd7nGEtPqhzhjm5Uyw/M5FJwW0pOu5sRG9I/QvYgaTTbe
+u6CCwpL4fxJ42EjKicKdWvZ8+iQONDhcmHzIsvJJcg4vSkWc0S7CYwcrdbAn/KnW
+ru/Jnh4lGUxoj6GDYrroSCrPQqXk9rCTxq+wH5Ck8WQ3UyXLkVzuxWdBrNQ0Gwag
+dAh4u1o+3e+ta5V/WtQTZaSb71A0GvLqZpynu/pWDCQ8fkguvKbP55CuQLCnnukw
+nFs7zIlDlBQCYOgqvjswdzwZDSRliZD035oLDHPgSIeiWY0=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/Mapping1to2CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/Mapping1to2CACRL.pem
new file mode 100644
index 0000000000..5aa18e1b89
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/Mapping1to2CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBwjCBqwIBATANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UEAxMPTWFwcGluZyAxdG8y
+IENBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8wLTAfBgNVHSMEGDAW
+gBSZxXhpyz0zdsKZrETlsA7+ufTbxzAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQsF
+AAOCAQEAHDBNYlKeVrvQoU9wdLhmD2iI+pNFkNB0O/BJXY59wp/DFV+gyygyE1sC
+qnwOPMiKR+u9zypXr3+YbG/L0YeZuzzaFbHrm4ZYPcCRzaz0YVm7ZhbI+ea+moVW
+R5BgVfFUkfCiGNYQ5nxKif7WeYcCK+Aiy1eQ7e4munvJ5jzDrRiiZiBPRfY29FPh
+0qkp9TRqPLpY4oYwaGxe9UMKqvVdohBYqUUfdB2tgjeVlDct+MokpYL7wpnrQBTy
+yzgYpZ+GELYzhhn1Oc6PkIrYxc1h3O+tIg85uII/qFOC9qOslH0qPiVqEzwckAhZ
+HX8PPcXxLhO62X4BdaMgJhgHdUrW0g==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/MappingFromanyPolicyCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/MappingFromanyPolicyCACRL.pem
new file mode 100644
index 0000000000..4d6c9d0aaa
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/MappingFromanyPolicyCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzDCBtQIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZTWFwcGluZyBGcm9t
+IGFueVBvbGljeSBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0w
+HwYDVR0jBBgwFoAUaHMU4As0z3JA2pSW1hWreqRvLowwCgYDVR0UBAMCAQEwDQYJ
+KoZIhvcNAQELBQADggEBAKZyiDbM1h05WJkyjY/Ri6vJfUyXeHPdkeLm2K+DuxVs
+VOreMcdvbKCDm+VjAud129+ou9CUFZUn2vPwhZ5+W6Z7ohzUoo8QeWGoWkvlY/yU
+/Hf4qR6QOxUATGr/f9u3ptsbVjBKEhD66Q/OvXgiBFNzOdZOqKuuI/x/rnXyOSo4
+pYJ/RecUb1m9WaVjO1eKQCGImMbrHTnIOziAg47/IdCztubxtWwtV8jmd/zi5E+0
+FO/lBnFyyghqNjPnML0LHQUM8Lr1EnFU9Lg2m/QFg2rWghrWadYKoa6lroPKhdMn
+hTL+BnTZkrwlJ7OtCI1wQD1NHIJmiL6lDBFT6TMH1P0=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/MappingToanyPolicyCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/MappingToanyPolicyCACRL.pem
new file mode 100644
index 0000000000..a4a369c179
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/MappingToanyPolicyCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByjCBswIBATANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEgMB4GA1UEAxMXTWFwcGluZyBUbyBh
+bnlQb2xpY3kgQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAtMB8G
+A1UdIwQYMBaAFBQs7ZPxHhpwFZSLLZO0mNK3BQisMAoGA1UdFAQDAgEBMA0GCSqG
+SIb3DQEBCwUAA4IBAQAMdZWbfYwoDdwrkj0e1LjvvPiIXbBMwxuNhXG1LAaqazMF
+B3SM4/6IQ5kqLD4mXL6VTe1W3Ovu5L8DjbkXHckkq585B2s73Mwl9Ymlx7/MFahd
+taFST1d8AEQqxgBjcQ6imlEPtgJNboJqcbNS3/R/xau8OMXmY/kuSyTiMqeVq0jl
+ePVLDFrrLYaovKT0nG+7mN/afE+kyQxXaRk722ypf+38K4HHUAZwadRKPa8exyKz
+KNS8wFYjlrrua93qbpkDzmZ02gjkUJByCeBTqvkEbabUqLGfFhPJ8w/LFJiubwlI
+CmoYEAKpfR4393Uizsg6T+mHAaJmeIocAsoZBWvR
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/MissingbasicConstraintsCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/MissingbasicConstraintsCACRL.pem
new file mode 100644
index 0000000000..e84c210970
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/MissingbasicConstraintsCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzjCBtwIBATANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEkMCIGA1UEAxMbTWlzc2luZyBiYXNp
+Y0NvbnN0cmFpbnRzIENBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8w
+LTAfBgNVHSMEGDAWgBQwVrwVEY1PxibGtZyhcJLS+U8NeTAKBgNVHRQEAwIBATAN
+BgkqhkiG9w0BAQsFAAOCAQEADdJ1BXt1/rZ+Je0fEAOWJOx/zAciiWeBWaa5WMnq
+H4fvy//4+r57ZLVCN87f0fnxBSGk2bs2qZA7tkLMtVyRU12cjYsTXzqIA7w+lMGx
+Tsel+hDHGdJjAL5X7xDMOX3kfX/I5lruE+nKCxaGXWV3peJkaVdfw/qzkR7/3Woz
+aa5B7soNJv8sGyflwJCMUgAfaHZa6LopIRZ2GpmDhDYiXtujZC4NoLhKaq3LgQgF
+Y8gjpJtW7dEs7HQo33OeC4s2u8Q6T0pJkG6Xi7rGArplXTklb0MFjrEN6quGlYNC
+00HSsvG4Pf+2IPKUf4P6I0QW2CAnZqfprIPGok3Sy6tfJw==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/NameOrderCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/NameOrderCACRL.pem
new file mode 100644
index 0000000000..9aab5ae9dd
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/NameOrderCACRL.pem
@@ -0,0 +1,14 @@
+-----BEGIN X509 CRL-----
+MIICDjCB9wIBATANBgkqhkiG9w0BAQsFADCBkzELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIzAhBgNVBAsTGk9yZ2FuaXphdGlv
+bmFsIFVuaXQgTmFtZSAxMSMwIQYDVQQLExpPcmdhbml6YXRpb25hbCBVbml0IE5h
+bWUgMjEZMBcGA1UEAxMQTmFtZSBPcmRlcmluZyBDQRcNMTAwMTAxMDgzMDAwWhcN
+MzAxMjMxMDgzMDAwWqAvMC0wHwYDVR0jBBgwFoAUv0qLgZtNjBQxjFvpzN0v6HkS
+UVAwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQELBQADggEBABkyacQyoBQE5YZL2K2Q
+0f637287irENIuJeWpv9MsXXsZZfN//UeOfwIdnhAMQCx1GeEbCdAPAKkBxI3Jn2
+AVtxqytV8F7xqUiUpYRw6g2B0jjsJoaFP4AoY+BGk5/4oLwj2MzNyNcYFb/KPPgc
+Pwq4T0IR7qMz60d2lZzLhWWz50jOmvwvyxFbOcYwh1RmLB7KKcwAaPeSwlCxThQS
+sugsqHuq3K+pi7KTShAV2UWRupDOGlVyPYAuo3n4G2LmwPmwmYmnG3+KS1Azyj8B
+ywYDiAPQyG10rufsDF3GEpJzIOPt7VHv8z2SthTPmVfDFrkwshOQsb+PrltGP9bC
+V/s=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/NegativeSerialNumberCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/NegativeSerialNumberCACRL.pem
new file mode 100644
index 0000000000..62dbbc8db4
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/NegativeSerialNumberCACRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIIB8DCB2QIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZTmVnYXRpdmUgU2Vy
+aWFsIE51bWJlciBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjAiMCAC
+Af8XDTEwMDEwMTA4MzAwMFowDDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0jBBgwFoAU
+YuQuNcYPxeiR0AvBjd62r9qI2T8wCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQELBQAD
+ggEBABjkQVYJziJmvShgFK3XecyOCYDlSPShr+vgrGFBQpyi/FePWU0yot93064/
+lRSHgzS8B9yvXPJBygOGT/hbmNG/88Evu2Z1LoEOLTzq+Sbf6LahfqDpkvdf6SjM
+wy4udr0g7dVOjHQg9DM+HDij7tc150o6P0e9++0CgpXuRNQKYKRq3qn4KjBq9Yph
+S/MpUEY70hgZaL+XTbyvti83Y8nPqrVIz3VRcG7GLHAmYb3cGwf/8zNL8lpOhzOU
+MoTwN+TcRWvMlYWYoyfaaGxA+Ak3wcPsIHhHLxTyXucXGQPjrmiGqK9H6BOUZT4q
+HupHV4TbUwMoW+FXISGPVvz3ECA=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/NoPoliciesCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/NoPoliciesCACRL.pem
new file mode 100644
index 0000000000..42ee928471
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/NoPoliciesCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBwTCBqgIBATANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEXMBUGA1UEAxMOTm8gUG9saWNpZXMg
+Q0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAtMB8GA1UdIwQYMBaA
+FEIkA+2lS3acl5hcdOoFOhv8NeScMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBCwUA
+A4IBAQBuELGhtxMeER+HyzT997rCWtWbXV9HT6zgfU9AUTX2pDoNFn9iGfFkLaJm
+rSkQro17ogzl9xrF2EvdgMSSw6YxRU7MbMMmF2lXC+IbScdtAGgdURnGF/C3Omao
+dGbXXI+3gUM5YSlPqGToDB2j7tBAC+THt8Knxq1NLeRt9cXpztX/UF+B4u62ylHo
+q6jV4KLlWksRGwtEF9w/2iiQv08zz92ySgL4Z/CbBMQfX73iq6SjPFOJm1CpA0BR
+QFN33H1OC8WMHaoV8M7DBGpudcWzHZpuq9ikjLdlCmDuGEyJgceneOe6e7vsupe2
+DGRGvgwmJbJI/XbCbLnwSW3Xdsp2
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/NoissuingDistributionPointCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/NoissuingDistributionPointCACRL.pem
new file mode 100644
index 0000000000..789099d061
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/NoissuingDistributionPointCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB0TCBugIBATANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEnMCUGA1UECxMeTm8gaXNzdWluZ0Rp
+c3RyaWJ1dGlvblBvaW50IENBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+oC8wLTAfBgNVHSMEGDAWgBSzy1S/ap38n8cxDpIMp0drmQCfMTAKBgNVHRQEAwIB
+ATANBgkqhkiG9w0BAQsFAAOCAQEAqnXhjxLsCflfSGLvYk06S6AP9+nEuFtbqXDP
++T4URhv2PZ583f7hg0jEd1/SZqyNxrZk6cNNMR2DYPCX8XsP3c0lKf1wVoielyl1
+bSPCTifm0z8pJr9ORD7XHDZ4F8s/nv08f+GJmYUaE036Nw++wNMqi016tw+TrHa1
+s9jSwUvlzjg/om6n0EMTWnWTnEHngdrGkV63kuo+4yymlsEALlgmIUp41bOiWzFo
+aYxsFd2k+ZAGvv5mB1Qimcp8C1ssInLczcDQ5Un329OAz83nrgdCZcYkFBAR1A46
+p+16zuw55BiQp3gByK1NVTssEcBOkDm/M1DgS+CtE8xkfKnR6g==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/OldCRLnextUpdateCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/OldCRLnextUpdateCACRL.pem
new file mode 100644
index 0000000000..d9591e5cf1
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/OldCRLnextUpdateCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByDCBsQIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UEAxMVT2xkIENSTCBuZXh0
+VXBkYXRlIENBFw0xMDAxMDEwODMwMDBaFw0xMDAxMDIwODMwMDBaoC8wLTAfBgNV
+HSMEGDAWgBTO2h/aWsyOl/ogFSlPrJaNKs14EzAKBgNVHRQEAwIBATANBgkqhkiG
+9w0BAQsFAAOCAQEANLTjtSL1Q3Ya29eHHAMhRdlEtcNF5CMpIUxvS3eQjTH0RxIR
+EWfDguJmX5gAeyHgegi0W4E1e5qArzpestM9nXMZypQ0GuOLEqQ8QfV4UTp5B3Ng
+gdgrxRTIdlpkEG43G93gZBmZ7u+HHbBtoBM270gFtluBXTnLbs6cHsZRn3p5jOCc
+Ll/YQBCO42iRjmww2mYKy5dB18geb0YZHlKL3FbZ1JhfZlvmHilBvBSx9uy5qZgZ
+HwlONqnePLkbK+0PyLaooa5NJXmusGVuZVC9x5gzwO+ZHun8fZ8aHIDDO9RtOv5U
+6r2J4kRp8Nw6zM4yWeQOD0GfRFlsq/OM3lHgPg==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/P12Mapping1to3CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/P12Mapping1to3CACRL.pem
new file mode 100644
index 0000000000..f590198a12
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/P12Mapping1to3CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBxjCBrwIBATANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEcMBoGA1UEAxMTUDEyIE1hcHBpbmcg
+MXRvMyBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0wHwYDVR0j
+BBgwFoAU/PSNYTMygHx9NYfeX1L7afEdwRIwCgYDVR0UBAMCAQEwDQYJKoZIhvcN
+AQELBQADggEBADWFF9y8VCunmgrr/9sJCD19KF6FofJOEV4U6zjPju5N/4b3Txoc
+LiClRWHYyRqHjOlLvAOik0mopqcUhwGqQG3MpU56R8LEKScgQQiacPuSeRSflRRo
+nxGs/90yJrq9s59EN5oZH+AnhJ07R2kq1PFLMGR6MY6B4A4MZony01/BPG4EfpRn
+W270ehb6FEYIc514vHyJ65s8KfUx01BsMSTwS75LJFEmnM6pRLzZzbESQEo/5/BN
+ttRRwrNt7TlwY7zs+oSDjUEpQ4K7tbfuQtIqiGm2VsY1O8kZWYmg+eUTUplcLoEZ
+LuAkicZCYw+YPcorZ+m9nL8FbxnrPm2LjJM=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/P12Mapping1to3subCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/P12Mapping1to3subCACRL.pem
new file mode 100644
index 0000000000..acc5cde185
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/P12Mapping1to3subCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByTCBsgIBATANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWUDEyIE1hcHBpbmcg
+MXRvMyBzdWJDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0wHwYD
+VR0jBBgwFoAUvnsTk6Hkm8UnPDBT16XJ5lqWejQwCgYDVR0UBAMCAQEwDQYJKoZI
+hvcNAQELBQADggEBALLR4At4E9ny2pPCIb4rLKvVRs10lszGrH8NVo1jhuugSyMS
+wMYPWuZbUw+rpN/YwFFkM5R256ITwtEttgHkWoa3CetBBRYF6UPIMyZp0KRDQAZC
+SwPU89QvP5H8KHuB3Zg4bg1wrXZTP9vjTjxf65UQhc2S3zj1M+TBv94h5J5cHSY+
+Q9Nz5iRoxEJv55/TWa7UQYBwaDbPxdb+twKEhdocjTZRYub2LhKRlY9nmTTiM/J5
+wE0RYNQsPiUkZuNELh7ZxPCp9Gk5KqbE0qUSO7KYiPEUj5mK4F+j2Mwb6nsoT9gt
+lrN/kqlyXJMhf1wRux12aUXN9Ia92lW6WrI7iH4=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/P12Mapping1to3subsubCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/P12Mapping1to3subsubCACRL.pem
new file mode 100644
index 0000000000..d000a06282
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/P12Mapping1to3subsubCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzDCBtQIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZUDEyIE1hcHBpbmcg
+MXRvMyBzdWJzdWJDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0w
+HwYDVR0jBBgwFoAUAF05Pg/lqipeLfauaCqtM5s9m3MwCgYDVR0UBAMCAQEwDQYJ
+KoZIhvcNAQELBQADggEBABqrLgpbtj/1buUK3kRN35sQe3KtFggWeg1MO7BkQtue
+zRD3ajIwDOBbemqCmEj8w4TdlDzTiEVpaa4k4UqlcTINMdlc8AbSzs4IjZvg2Mxu
+RcGm6+Kr8YfltOSeJk1zdQve5V9ft76TSGOZqK0Q4rTYRuuTipe3EnwJUdvyTR0u
+gmPO5XTMHnyecCJoUAHFmqEy5EAjgANJ9t0DwPzK+BIPDn76PmjKd0zhd5rAhQzm
+FhgGSyUAZMLAnPrpYTJtTW+QM92qJPxOMWvDAMVTJxUrZmfaDSEOFUnoTi6yADaR
+Mu8MWB8W9CRmxNShdUht4CGu5R03u6DGBoT70fkbn2g=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/P1Mapping1to234CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/P1Mapping1to234CACRL.pem
new file mode 100644
index 0000000000..376de8c6e4
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/P1Mapping1to234CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBxzCBsAIBATANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEdMBsGA1UEAxMUUDEgTWFwcGluZyAx
+dG8yMzQgQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAtMB8GA1Ud
+IwQYMBaAFJULAalJeKp22n8JDayIFPn190eSMAoGA1UdFAQDAgEBMA0GCSqGSIb3
+DQEBCwUAA4IBAQCqaCGQVcOhNGIvLyAEZ6u7CZSlusbOFE1T7cL10Z0XpNwHIU2e
+dzV4pmt0Y3tAJyR0FIXlqZbxq6fm/S5U4cWoM62jk4PzFGu9HaocJNNOIK0Opfuk
+TwwMOpYN/6IH74iy22lb2Wdgike7G9bCWl7nvMVZw5I7OIGyy/oqkhqjtWFLC9nD
+fYRIwfG3HPD8Kc2GMVc/iTalLDe3OUcsSGTrqCg0OwGckH+CdiXQk5MfV61bwICQ
+RxURNAqzCqYhNSrDH/qcGId/3mN/LzpoBr4SVRMZhMw0MpUWSTGwe1wnarhxaSoD
+VRHuoceqwHtU+s3AzFxHRXDbv/0xHECrkNjX
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/P1Mapping1to234subCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/P1Mapping1to234subCACRL.pem
new file mode 100644
index 0000000000..316b5ba594
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/P1Mapping1to234subCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByjCBswIBATANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEgMB4GA1UEAxMXUDEgTWFwcGluZyAx
+dG8yMzQgc3ViQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAtMB8G
+A1UdIwQYMBaAFAMX5ZUA/So5eK/LRvZAmGUKAu27MAoGA1UdFAQDAgEBMA0GCSqG
+SIb3DQEBCwUAA4IBAQDCUm9OtS/rVGX56aFpRteKjEE8VKLOCXIecUda5ewyHw6a
+JRpUhGBguzOjY60yM8isBHYefdfjM4usLfZniy6NtfJ2S7yProWY7P4IYUsWgrMn
+2tXBp0LnyyWarx1f2NSeBJbsQKiw8fXLsygMnd8ISb6eA1AGKfZfxmeC4PM2Hl4/
+KbKdvxs7UWT4jD0WolZyOpjr/Ffh/uAKZB/TVks8j7ZENODT2lUc5KxmDbMCHEUp
+pd5GyRrXKJjdMMMUK/VUxOr1K22eW1FgBmx1zUiT9Uhen/bS5WXtfhVGqm1q468F
+jrPVC+/FBoFjuHU5tcxtNup3cLH6Vm4Y/v5+u2u+
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/P1anyPolicyMapping1to2CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/P1anyPolicyMapping1to2CACRL.pem
new file mode 100644
index 0000000000..709a1368ac
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/P1anyPolicyMapping1to2CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzjCBtwIBATANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEkMCIGA1UEAxMbUDFhbnlQb2xpY3kg
+TWFwcGluZyAxdG8yIENBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8w
+LTAfBgNVHSMEGDAWgBQfAigoMo5KhPi4i0HxXXvoJVJrhjAKBgNVHRQEAwIBATAN
+BgkqhkiG9w0BAQsFAAOCAQEABhVsmwrFO9I1+fkjbJM7OfRp8BbNFRh0Mhb/ky6K
+g4U6YuwlEQP6KzM3QyOyQPIh7CAljCBxJpJkXrfm29RJY3OqS4THg+FfEmIcU+MV
+1TrRd8CI6ufBCdoG0SUUsS2W1CZFjbQNEl/xAfMUkuJi2T0lbCCsb1y0lpGrFW1l
+k2HLwq3qbikjZyWhoD/k6ho1yIEg4uT03GyJUm/n7Ij4DThK7mJP5vu9VD8rGwU3
+XXsoD62oMo2duCLrH4Uj5U+k/RbYb3zdbq+6xb4WLkt9MC3zWK3NtiVWIr9Q3XjV
+3uz8fErny04GW1dGGQQn+U50ZLjCA3bG78hbyCxv07zp6g==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/PanyPolicyMapping1to2CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PanyPolicyMapping1to2CACRL.pem
new file mode 100644
index 0000000000..c039b47889
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PanyPolicyMapping1to2CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzTCBtgIBATANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEjMCEGA1UEAxMaUGFueVBvbGljeSBN
+YXBwaW5nIDF0bzIgQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAt
+MB8GA1UdIwQYMBaAFEcDJy9DPcUv2ZKsx9J20DPG+Xe7MAoGA1UdFAQDAgEBMA0G
+CSqGSIb3DQEBCwUAA4IBAQBQVc02PPmQX4EhnPqxh12Tk5NseAryd0o8bmViilep
+uCpk+roAUOXLvKHg43alw0d+OsPA435KTBLKs5hR1lrEjEqE0AW56jqYbdCmei19
+XbaaGc7hrBbraDuFqAeobbZ2jwDxN2MQqIOT5omzfyyVLUzVKNyNsxvOVCoke+ya
+n29eMlOzv61ZesITDJlkrqTEyjwaRHUQtfthv4TB0sPIP5NmLq9ThYqhaVjsEtK5
+4bS6XP6xsVw4uyPrwStEgPPAbrYZyyRVNrNJigAyEKw59Kl5GQPefAm+mAo+x5D9
+aZDC+5MDbHU4CcjPPzbX5iocBgz3rEazHL1CJbIflrlh
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP1234CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP1234CACRL.pem
new file mode 100644
index 0000000000..ef2c47424e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP1234CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBxDCBrQIBATANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEaMBgGA1UEAxMRUG9saWNpZXMgUDEy
+MzQgQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAtMB8GA1UdIwQY
+MBaAFPb9qYwmLLTP1tPr1B6tkmoduyRQMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
+CwUAA4IBAQDVVwwWNj9cO5+4t4+7LgMKvD8IGEKTakoiouH5na732HehNDO/mHzA
+cEKjj5MgEdx2JLghyLAtDsD4LTzdCANAftXnGeZJVcATUbjSecgPg5wFLLp9/mg4
+Fb5mIQeTUkYcrswC6Wa/P3vLJfu7L0vJwg6tPwnkFHw9NqsuzFqmQvrlrRtzLaDQ
+zlvg6BZkDCXSK+7gqQ84F4WJZCV9laVkymfM1ih0wXWby0VWlvAZK8SoWc6W7rep
+6dePGKx1V/lgJkYbxvMROoRKmoXSoHdxPktChC9KL0LievdasDF5/HZ5UgKNcE3n
+65jwDBq9nnOQfhhPm2WeLNlVbzY1Mzjg
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP1234subCAP123CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP1234subCAP123CRL.pem
new file mode 100644
index 0000000000..5cb4f07fdf
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP1234subCAP123CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByzCBtAIBATANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYUG9saWNpZXMgUDEy
+MzQgc3ViQ0FQMTIzFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8wLTAf
+BgNVHSMEGDAWgBS5qlCBpjRmUWidQu4piGrsHMh89zAKBgNVHRQEAwIBATANBgkq
+hkiG9w0BAQsFAAOCAQEAfV2uyHCfgiXrwk21BBpCMPiQmJ5erAU2QRfYd/IzoTgx
+sMGttr8QexaLY7rfY8K9Ju7t428gmoFYScIB8AITUCh+Z9l+wx3egQxCC9twjgRt
+zS/1ys8I2nK9CmA26ClY7TAL2ztIjFDcS+S1/tZlJxi26il6EpTjDkb4altMcwYD
+0dy7EW8Y/JAvFGBkziG9FiDThEdYK/hyDtceBEGDcWJP2s4CBOIigzdEkllFJe33
+ugx2AhLvGvHPzpyOzUPxlbKkkkoBjtU5WUl0v1PSiAa/OqXxXjOb1uuMUsHutbdM
+51I6VkQkncKEKN03OTkCgwthFM4GN5rurT02zD0KBw==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP1234subsubCAP123P12CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP1234subsubCAP123P12CRL.pem
new file mode 100644
index 0000000000..4f33bf88f8
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP1234subsubCAP123P12CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB0TCBugIBATANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEnMCUGA1UEAxMeUG9saWNpZXMgUDEy
+MzQgc3Vic3ViQ0FQMTIzUDEyFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+oC8wLTAfBgNVHSMEGDAWgBRO9F6h+Qgwe2WsksARCyzTtJYHHjAKBgNVHRQEAwIB
+ATANBgkqhkiG9w0BAQsFAAOCAQEAO3mUa/hz4u9id4j6HNSVrunOClJfxtxgVK//
+BhUHRP7DLt9PfridxGqVOENl4KKUp3Is8JDXhsQLfalp+SXUEjUNIW9tK1XGT8RM
+KuyPXfYNvK0ki8RLZBrOObwuz1bwCIr8suJnlbuO2PizZiYkd9JkPpmI4Ql7wvKQ
+qtZG/D9gMSKw8YYU0BBD38C1DBcx9zX8Juq1of2wA1bRO4+1r7d1caiauSNDICLM
+6K+5veVzXPbdi9AiCym0q2DafSijAO/tyVI7viGFriA1XXPyW4IgJTlYwj6C7bNE
+spPxDeHZOYGjSRYwnOVwl5FetLBZeXPnb+oCUueETTdCap53mg==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP123CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP123CACRL.pem
new file mode 100644
index 0000000000..9badaf1180
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP123CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBwzCBrAIBATANBgkqhkiG9w0BAQsFADBJMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEZMBcGA1UEAxMQUG9saWNpZXMgUDEy
+MyBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0wHwYDVR0jBBgw
+FoAUjCgK2g0JFGLuPT2WuHGTEonq6GMwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEL
+BQADggEBAF+cFlwOZpoC7aoNCsV8ISlb/o86hb45QuGdajlLv/vTDAstyF6123qR
+3dE5/YuJ4FTgjZqNt6iBOMIaauFE9nTeQ/G7WhB6yGOtna9QrTIIWQfi3kyuONC5
+1+YUr/dj9wBJgHXQhO1ugdweVdstePbTe0iRl1ZGG+Hs/xT5r7wji24hhtjyXoAJ
+J9A2NQoLt7wD4OBOKQUHarYY24xpnVcWryWxfS2HGdsiWfyrdVMSTzoZnIqI3kzW
+VvbVj99ShHKFmIQMqBuZZGQCrXlts5G6mknQK9TNCHCJZwX41S5Tw/dd5X+Ujdyz
+knTDjuehdwjtDecV5Dh0q0nORth5X+s=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP123subCAP12CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP123subCAP12CRL.pem
new file mode 100644
index 0000000000..bfa6e83f6c
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP123subCAP12CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByTCBsgIBATANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWUG9saWNpZXMgUDEy
+MyBzdWJDQVAxMhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0wHwYD
+VR0jBBgwFoAUzgDa/aqTQPjAoHmtwXjOHdcn9p4wCgYDVR0UBAMCAQEwDQYJKoZI
+hvcNAQELBQADggEBAEBeDNTliwQBVeWRQ3NDLEUH3xNSHfAr8itMFr1gMI8YaS7e
+qYMtIZnedQ7o1A10abrH6X4li/8UDL+7o98CTcd02D2Hrvc+QXT++nIJ5oFbt0qJ
+iOVXGQ5ZXVxSaNif729zjcAmgGKcHtVtxPvf9CgmnQ78hA6mx0ugFHs4QSmecsMt
+umd0V1AsscRGzTjvN0YCVBPpZPy/oxLU6pYp6XAmqC1UHPv8Ny1/unMz7cYoam/0
+83KZJHp8I4FSzkdhrFyLjKaaVxwWioLyQUTwrzR/qzaU1Eyk+KipzKVh470kuItM
+cDnV0OXOPuJR1XA3yhdLZU0aMtwd28WZ1Y4myPQ=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP123subsubCAP12P1CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP123subsubCAP12P1CRL.pem
new file mode 100644
index 0000000000..f8a920a1be
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP123subsubCAP12P1CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzjCBtwIBATANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEkMCIGA1UEAxMbUG9saWNpZXMgUDEy
+MyBzdWJzdWJDQVAxMlAxFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8w
+LTAfBgNVHSMEGDAWgBTkGz5Gt+bIqdjt0TN/BeHxXRIkwjAKBgNVHRQEAwIBATAN
+BgkqhkiG9w0BAQsFAAOCAQEAZg1qheMvRGkd/jBrdaoWnRb0iEuPZw9Ij5k64ZeI
+JUmMeWjKKFnLBsC0MIrEtR3NPqMU6tfZH3mmeCzJ6pjo0IozkN1OnMYFqwxrfn1T
++d/yM4fYBb12oesd7n1+c36hlHKd7dxi1xUAwCIABnX/17odaOCD9ikA2sq5XfqS
+p4Z7IUPd+i/8dF3Pkfm+cpPJaNdpdd2sxx4mmbsGcL9+2xIwhfiVavawZe0MZYxw
+kPhNVL8zL6kYUCRvB7J2hEwu1MWH3paED9MIkKyS0zVdzfg4DojApNP/nwL3JHIf
+DVscEQo6mY+6hhhOYApDNF6y81BRqasImFItcLp/fgE4tQ==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP123subsubCAP2P2CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP123subsubCAP2P2CRL.pem
new file mode 100644
index 0000000000..cbbe9d03b1
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP123subsubCAP2P2CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzjCBtwIBATANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEkMCIGA1UEAxMbUG9saWNpZXMgUDEy
+MyBzdWJzdWJDQVAxMlAyFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8w
+LTAfBgNVHSMEGDAWgBTp/LZeVhROBh3RMv2IYGsQ+AUbaTAKBgNVHRQEAwIBATAN
+BgkqhkiG9w0BAQsFAAOCAQEAYcCBk7Si8nv8UU/B0/YbctjIyBk8VOtKhIFbRunt
+alE+/Vc/c77r0Y1CfVII/DOAFcB872KtQuWyl5p8uVlVwmDlL1BKmz35mD2PS10i
+NsuofkZTp97xrRZbA1k+zqMshOzmEXReNrR/qliJpTPlH1YMNV5IN02HNYZ8+6mn
+BzAs4e8/xS2cO9ktya0ZwAqwH3ksD+etLL/MIj/3BAL9HRMOC+RcKktWkVZKqYq/
+AAzn3HlvnTUZi2OW81ABtFl2hYSJEyBcKjrSoDuZ4Utk5AuxOsLwa0hH4da+/4nx
+OreMrYjymG9FpLVq+RhVYMdJSzp8c2CU7rgN0Pap7sQY/A==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP123subsubsubCAP12P2P1CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP123subsubsubCAP12P2P1CRL.pem
new file mode 100644
index 0000000000..2a6a21b33b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP123subsubsubCAP12P2P1CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB0zCBvAIBATANBgkqhkiG9w0BAQsFADBZMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEpMCcGA1UEAxMgUG9saWNpZXMgUDEy
+MyBzdWJzdWJzdWJDQVAxMlAyUDEXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAw
+MFqgLzAtMB8GA1UdIwQYMBaAFIkgF4T7rLsJ195eXp5o9jlQH0CIMAoGA1UdFAQD
+AgEBMA0GCSqGSIb3DQEBCwUAA4IBAQAVS+qKdu5cTu1Y/7f1Yci/ULGAtX4oYox6
+0LYSSXpOl1BzTNMxUCp30N382djQEYODR8vROlVXDyEaHwMC8Dyn+YreG+1eHODk
+Mq/Hc59ckRW17LDJpyBew1535EVQa6LtC6bD72AQ1Fd+hzH90WNNQCMb4xQ6eOnF
+T1pSoKoopsA2NH3zTBVrtq1n6K7FOojGqKdO7oYqill+bRdMoYSNKQx1lskS9E1b
+lQftEmE8AAlU+Q1zV5IiiSpoEXe8/nbyTwSbYvaUHmmBgwCOdgnpJiG6TvwjcFh/
+zIQiGotG9zQszNrO7GPpvc9wQ+o2uN1Luilv1P0FRw0PBHMwmwUJ
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP12CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP12CACRL.pem
new file mode 100644
index 0000000000..1af85735f5
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP12CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBwjCBqwIBATANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UEAxMPUG9saWNpZXMgUDEy
+IENBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8wLTAfBgNVHSMEGDAW
+gBTYXzXimsE3KibOg8xzDnAVKjriMTAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQsF
+AAOCAQEAUiAHin1qZsRcAQcRXu9l1qnbsNYeC32w7Y8SR7o7SLMBjrLfpzTt3u31
+UGBH/9CfynTV2n3wVuJoCCFTdkgRn08X+Oc2sK/8g+oKvTwmoLQv0lktEsFvOFC0
+4/5wB94qkPysqGKKPj0ADujY5GBWb64Z9V6ehvxACTzKhPCNc7auvTLZEymtWW2H
+4C6nZGjUuuoZbd1Y20d0u5/18MySt5HCfKyoIfA75dsnuL7RJVFvrjcXxH40cXs8
++xizlf66wdIVeWCAr8RV4bPFmlC7fAF3UjC4MoE1RQqbWuYig79F7RS29s6XNWiq
+A0W7puTYGKoCpIUETmzBSDOsNpcfIg==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP12subCAP1CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP12subCAP1CRL.pem
new file mode 100644
index 0000000000..c96f12103b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP12subCAP1CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBxzCBsAIBATANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEdMBsGA1UEAxMUUG9saWNpZXMgUDEy
+IHN1YkNBUDEXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAtMB8GA1Ud
+IwQYMBaAFCKe1w64SM4JDjpdvtZNWCNWjcvWMAoGA1UdFAQDAgEBMA0GCSqGSIb3
+DQEBCwUAA4IBAQCPniPRTYwvNO1eFZjaR7nnHYFDRh7cAd2EsYgmh9W7kjeafaZt
+vLCnzQv82LN47Ki1z/2KWraLSRduP8qnY4wGOdRsahnrl/ss2wjMB6UiFp+Un6IA
+AKEM5MLgZwvjsadAADqJXonGzB1Eh2xmHGqZloU5V5FDewbjem/scf3yufvahMvr
+ZSjBsSUMCBfIewJq7JRkwSgyip4K/t9UBJBbsfkOOR5/rEgaZyyfI86nGhg0GawS
+FHw1fAPcG6vEKnsyyHU9JhzjtQYUi3JiZO2BamFAXfJkDOhCWfkR4ywhRUP5bqAE
+q4GAriFrKPKYB3Fp4nAhbLi4bhV4kUS+lWoT
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP12subsubCAP1P2CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP12subsubCAP1P2CRL.pem
new file mode 100644
index 0000000000..4dd0f2fca0
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP12subsubCAP1P2CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzDCBtQIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZUG9saWNpZXMgUDEy
+IHN1YnN1YkNBUDFQMhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0w
+HwYDVR0jBBgwFoAUx6U3p9D6JOV839vyXWnb7sr2me4wCgYDVR0UBAMCAQEwDQYJ
+KoZIhvcNAQELBQADggEBAKWuXLxMM7H4MkbAsQLa1RgeuDYC5FLy5mzt/UsidYqx
+rSK7vX19l658Lz1NEcq25gXzJlfOG8ZIAUkO/SXwi1IwqOU2QVkn6nJnXYP0J0c8
+QEzxYlYEC/DHDTEUltH2ZoIuOoozIT6NHw8+2/XBBjatS1nL10bhwvzRXirGFKGN
+BtASLRZeHaU0y/n2KkBuusn3HFyErzRskNRLPOTk3Lt0/RB8nbrRxUUZJXAaZJIr
+4Kj4LcatDgdgXCZ2MEC/mCByKwFiwh5RgMQqPPLMhGBRSPfPD5hVKVL2iGu8qSxK
+kkLZkwrGL9U/1mXtcajUpz+r28iLP4uJnCxt9ZBVIcg=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP2subCA2CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP2subCA2CRL.pem
new file mode 100644
index 0000000000..d2e6b8d3db
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP2subCA2CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBxTCBrgIBATANBgkqhkiG9w0BAQsFADBLMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEbMBkGA1UEAxMSUG9saWNpZXMgUDIg
+c3ViQ0EyFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8wLTAfBgNVHSME
+GDAWgBQXLOoDuAd3gT1lpb8zH8x60pj8vjAKBgNVHRQEAwIBATANBgkqhkiG9w0B
+AQsFAAOCAQEASUNpb/KK0iBuFV/Y7HRxjqNfJAhSRjOxNrEMtuql/YucrqQKFs2f
+AcbNwEWPPdW7KEd2bhyUBlJJ1g0mWCPu+bHNv9IND3bsioXiStlDblymVm/ShJ0i
+f3VWT47L0Lb6Ppye2r+A486Q468clSbDv2pj+vAPqFqUaSr5iN+Y/WTxUtAs34Dx
+qDRWP9lye1OzlLnMJSf/ZVYHdS/KmnsR9YIIeI7pNqtPf9ilDBe6Va51tpVfHnp3
+OLQersoyyDApH5KCQQv0/+4EPqZjmAcO+ALDg4Q92vfzbULImJW6rMD6dlEtITlu
+iful4K0ey6Jngy/6qFTtI/jJgzNmxsR6Zw==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP2subCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP2subCACRL.pem
new file mode 100644
index 0000000000..02c8fa43d4
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP2subCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBxDCBrQIBATANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEaMBgGA1UEAxMRUG9saWNpZXMgUDIg
+c3ViQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAtMB8GA1UdIwQY
+MBaAFF48hHOeMHBycZiugTYZ2yIOfK8DMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
+CwUAA4IBAQAIgjc4iT1LVOUqEO9SLZgx9MpR4Vt3gTa3JciJH+czDui7YgsT688m
+8/dqZXCxTkt9JYPQGABYYhwxsQC2oyjG2jercknnJ+XHk4JV2wN/XO9ItNhI+OvA
+rnKtzk6Rpf7pS3SSjeU3XR5UIOiMM2JoWGvtUhwq7b5RaLk36Z0gGp9x/3LaGDBA
+FTred1LnWgYQCO7jTGWfDT4xIJr0FqA1RNLb+xvkmA1lmhjZ20lw8HXHgFsfvb4L
+ADFkLzFQ6p/zuleXBDe8U5lusCqjls0cTaiNCdpPXuJ1I4hkPYu0raquxjC7VoM8
+LWcIpRna9gUu8sSD7k7N+NDdQSM+Op+P
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP3CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP3CACRL.pem
new file mode 100644
index 0000000000..0eac63d37a
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/PoliciesP3CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBwTCBqgIBATANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEXMBUGA1UEAxMOUG9saWNpZXMgUDMg
+Q0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAtMB8GA1UdIwQYMBaA
+FNgFqyygi8OS3Mataj+/88aY5dz9MAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBCwUA
+A4IBAQCwxaqJWjJraTqw0xo+dvcx3uD3LYUe9aJqKvZTbNqLT23k7U62qcWUz59N
+Rprnl0q9aemI80Mk/Vk4WAr9weTsOytXrNML4Rgk4Sb+WjU4OSlUZbBka1YS41Y4
+xiZzhQYrL391uyDD/FLsehWJmkO9JqeydLT1A1lAuX9m3f59PJ6waXJMMwySszDI
+T2e56JR6Vt3659YRpNScJmDKWc3wdHagNvmtn4Z/c+TtO+JN11doMwx/92uV+nic
+GVVPJQqKZDvNfK/hLxBo3nKBpXJUrU4AyYCbpe4idc6CxYMAy95UqUlFV72pnndm
+E5RRfI4x2a+BTvs8HNSX3LpruISg
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/RFC3280MandatoryAttributeTypesCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/RFC3280MandatoryAttributeTypesCACRL.pem
new file mode 100644
index 0000000000..49582a3282
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/RFC3280MandatoryAttributeTypesCACRL.pem
@@ -0,0 +1,14 @@
+-----BEGIN X509 CRL-----
+MIICDjCB9wIBATANBgkqhkiG9w0BAQsFADCBkzELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExEzARBgoJkiaJk/IsZAEZFgNnb3Yx
+IDAeBgoJkiaJk/IsZAEZFhB0ZXN0Y2VydGlmaWNhdGVzMREwDwYDVQQIEwhNYXJ5
+bGFuZDEMMAoGA1UEBRMDMzQ1MQswCQYDVQQuEwJDQRcNMTAwMTAxMDgzMDAwWhcN
+MzAxMjMxMDgzMDAwWqAvMC0wHwYDVR0jBBgwFoAU8FEYYu/OQce3sGd0awK8Mgoz
+meswCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQELBQADggEBAFqTS/IzHJiqF28DiO+F
+v++AFZ/b8cYN6B5eoSoZYBg2C7pV+5UEL0+hQlper2e6TUIEkMpSU7Y6VWc2okpS
+YR+2bNCsIDX/RB2DYzyEGgqwoBmbeTCE/bIbcxjoSUOP7YlI4wD4XgOISwVOBZoK
+Mc+341k1iHhwI0OFHv3XVHqwegy5RVcgYhWcq/H9ARUvD3+a5HDdBGTCP4r8aCcD
+46zDEsBRYVJNPsyk4cnBsR/8nh8Bufy8PWuArb+s1ZSQ0PMgtwfrvqPCM+wnl/+Z
+gN3UiKvlBG2lSrTxhOelPGvoNZrr6Z8Uw8rl1EXcLvPTJsqR17snRwWCWLR6ewAc
+XbI=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/RFC3280OptionalAttributeTypesCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/RFC3280OptionalAttributeTypesCACRL.pem
new file mode 100644
index 0000000000..106a0215db
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/RFC3280OptionalAttributeTypesCACRL.pem
@@ -0,0 +1,14 @@
+-----BEGIN X509 CRL-----
+MIICGzCCAQMCAQEwDQYJKoZIhvcNAQELBQAwgZ8xCzAJBgNVBAYTAlVTMR8wHQYD
+VQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRUwEwYDVQQHEwxHYWl0aGVyc2J1
+cmcxDTALBgNVBCoTBEpvaG4xCjAIBgNVBCsTAVExEzARBgNVBEETCkZpY3RpdGlv
+dXMxCzAJBgNVBAQTAkNBMQwwCgYDVQQsEwNJSUkxDTALBgNVBAwTBE0uRC4XDTEw
+MDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAtMB8GA1UdIwQYMBaAFJtubz+K
+p/TntYwxW86ZS5EcfHy9MAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQBB
+32Yrko9n8ahvFVhspRmxscM7BMFLDBPKByEzJomnbztKvfw1bn4lsO39UIuBQgbS
+u+w1ZEnc3FcTvU0KjPNUA8e3eiuRzhct1XtqCPo7OmtFZDP7HQaCC0M7bxLiD56K
+00ww0RoiC8Vx0TI8+A+dZIQH1g19xShQ2WGquQLC26Wcf4FeXCTS/aaPeCGurbKD
+RBpShJHmZ2zFUZy0Wyu/FG+LMQpJf/ypy5dzYO94rHYMOdjfk4q17d9rLbtzyIZl
+GIOuZHdlBJi1uVKKOWFJHc1KIEbf2dc3AOfRAcZnvWZ9cBJpm51VC3FNPjqBtxVm
+OSHxymJkNoLCs4Rr1cCL
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/RevokedsubCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/RevokedsubCACRL.pem
new file mode 100644
index 0000000000..f07d7b88bf
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/RevokedsubCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBwDCBqQIBATANBgkqhkiG9w0BAQsFADBGMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEWMBQGA1UEAxMNUmV2b2tlZCBzdWJD
+QRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0wHwYDVR0jBBgwFoAU
+lm+SmaDpdnS7X9T4+xnZzx0FoO8wCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQELBQAD
+ggEBAB+FPq0gPzR/ldksUu2y1NFGBtliXqr8+2YkuC3znY6aUv+jZG4MgXN/m30I
+hs7lxydqbF2ubdw6Er9PhmvJcnH92BREyAAUHt3zzHbCK8WKmwdofIK/tFrXr0XO
+eGPfmfmm8oHJREcNQ2ftaCvq7eTy61KqVno+p4KNKLPxWvR2uahuhFxgIXZlJVQF
+lSIPCEPGT+t+tSxFQ7RevCv9jl9KFIf8hEWpLxjxY44uucZlQaLFV0oRiiuB7Cq3
+xYM0xa8uZ5/xuBu9MJ1TKg+LWqp6dwd3BRo4BxbBHOwNeUJ+PtaR23AAoiL7s5mt
+bsFxXB0TfszCLEmLmFFfkuB6m6k=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/RolloverfromPrintableStringtoUTF8StringCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/RolloverfromPrintableStringtoUTF8StringCACRL.pem
new file mode 100644
index 0000000000..912b6c8b8f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/RolloverfromPrintableStringtoUTF8StringCACRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIIB4TCBygIBATANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJVUzEfMB0GA1UE
+CgwWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTE3MDUGA1UEAwwuUm9sbG92ZXIgZnJv
+bSBQcmludGFibGVTdHJpbmcgdG8gVVRGOFN0cmluZyBDQRcNMTAwMTAxMDgzMDAw
+WhcNMzAxMjMxMDgzMDAwWqAvMC0wHwYDVR0jBBgwFoAUtW1PKD/Hu7GYpKml0Khb
+Xkp0s+cwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQELBQADggEBAFPDLO8fJtAH7E7z
+iHWXjzFLzoHGbLXSioC2TDR+Fm3hAOwdSphltknYwSxA0SyKeru8c8RVOu0fd7dS
+CaXmFaYL9CE4HREg1zFtuSPsElkhuZgi5N2cijO4oXUgdJsssFe3O/jWTBixJONF
+ZoAu4pjxi1mcNYDK5jn45jB25RNnjvhTm84I0o5/RQOp9vzpT5V60F3npWI8m7PQ
+UswjVucpjvslv2rPZEN5DldNgg+/W/qElgRFa+loYjeJyYRftsknzt8F1g2fzC7i
+k7fJTv0ZgFOk3tdUZhFHC3DNcwb6uscyTEdodNzaPhqoNHgUBdCqbUq0zZQXsIz4
+Sfp0ZJk=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/SeparateCertificateandCRLKeysCA2CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/SeparateCertificateandCRLKeysCA2CRL.pem
new file mode 100644
index 0000000000..e3b1f68960
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/SeparateCertificateandCRLKeysCA2CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB2DCBwQIBATANBgkqhkiG9w0BAQsFADBeMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEuMCwGA1UEAxMlU2VwYXJhdGUgQ2Vy
+dGlmaWNhdGUgYW5kIENSTCBLZXlzIENBMhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMx
+MDgzMDAwWqAvMC0wHwYDVR0jBBgwFoAUE4Q9hI8eqnyBd18x3c1g85eX2bEwCgYD
+VR0UBAMCAQEwDQYJKoZIhvcNAQELBQADggEBAKN55WtVRJBOZvbUAlZXukKilUzr
+4Z8lHcq4fiql8hc6UUhmYAc/7MdfDa3NqgbUoVg7aUngm52yLgXubmnMztA5Vqum
+CXiNSmJ5AVWh7GCs8pdMHFLpFqnh1y4RTpt4AjYFC+xc18gSrsyDKWv7YEYVyQG7
+GHA9JEMm3SpSgh3B872L+neVTTMrO/bHKl54QGGp1tasaLdTkRVB/002yGBraVvE
+zfC7szqOc5v0tl4e3VrUBcNfn4QTDvl5PfrovZdPJP3Ys7139K38+kT/2YwCJ6M4
+EOAhyfzVSTgvuFoB+UlYIt10c5GA7J7pDJr4PCGTzR1K7XesSFuZCbD5Ddo=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/SeparateCertificateandCRLKeysCRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/SeparateCertificateandCRLKeysCRL.pem
new file mode 100644
index 0000000000..9e3ca350cc
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/SeparateCertificateandCRLKeysCRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIIB/DCB5QIBATANBgkqhkiG9w0BAQsFADBeMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEuMCwGA1UEAxMlU2VwYXJhdGUgQ2Vy
+dGlmaWNhdGUgYW5kIENSTCBLZXlzIENBMRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMx
+MDgzMDAwWjAiMCACAQIXDTEwMDEwMTA4MzAwMFowDDAKBgNVHRUEAwoBAaAvMC0w
+HwYDVR0jBBgwFoAUcopDCwRbPT3EVeGDxp/fkMrq914wCgYDVR0UBAMCAQEwDQYJ
+KoZIhvcNAQELBQADggEBADQCnzJmc0jLQFb6EQ2iJDMcxrSuJftSikSCoKvuRTTH
++4cqd+xjh+kkZ1FCCmG6mY/hlnLTlKYqJlrJuu/vhHZP6XYwqkrtyx23ORmAOyq7
+SAuTvPBOPRo9HyvVWWHITgAKA90A0XUK+/zg1MRKgqqslTOaNXCqhu+nvshCtLx6
+MLsCYH5LVs3GimWfsT7wSpF4cqI4QyfZLJDtGz++9M7s03LvH6QNfQ0qrSaOdCfk
+hsdtNEzNFOOy34JejUZIDie83zj7Vgr1v6Gx+c5xkoDemggV/wzLYi7Si45JQBrJ
+trqjdLNOoS7QFadH/Vw7zL06Fahe2uUOOsXac76NQl4=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/TrustAnchorRootCRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/TrustAnchorRootCRL.pem
new file mode 100644
index 0000000000..114e6e1cbf
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/TrustAnchorRootCRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIIB4zCBzAIBATANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3QgQW5jaG9y
+Fw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMCIwIAIBaBcNMTAwMTAxMDgz
+MDAwWjAMMAoGA1UdFQQDCgEBoC8wLTAfBgNVHSMEGDAWgBTkfV/RXJWGCCwFrr51
+tmWn2V2oZjAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQsFAAOCAQEAqxkdtbsha7bh
+TM3wtzeelTjR1IGQgK4R8Psc2fw2NOydlq8PeSc3qitHV6m4dqHzchQlytYprOK4
+dRitEh+RYY4UKUNu+OQQ5VFLSvuC0Wv3xn2w29VqpQtavBFfJ8Lst9520pece6x8
+6fB9L6VP4YNGIrLc+7hEjEDALJs+ttPoxNNXGMApQQi5xyZEksXQAo60ZdH/r95l
+dVCa7U2OVXO1MCuZlWQRlql0Bi3CzE26cW1jccEdU6yQ0ONKNuROR+6NsXZ2Qm2C
+lHEGWFJAZ/CWB7NjQ9maNkoioZb4IB2AKPKBcb0mT3TYspgT8zcZSP5DLC8iVOrc
+x2SLSvd35g==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/TwoCRLsCABadCRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/TwoCRLsCABadCRL.pem
new file mode 100644
index 0000000000..526eb1f6e1
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/TwoCRLsCABadCRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIIB7jCB1wIBATANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEgMB4GA1UEAxMXQmFkIENSTCBmb3Ig
+VHdvIENSTHMgQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowIjAgAgEB
+Fw0xMDAxMDEwODMwMDBaMAwwCgYDVR0VBAMKAQGgLzAtMB8GA1UdIwQYMBaAFBCh
+AdaZnYDjbf3n7ndLX/FJ2TxTMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IB
+AQB+8PsN24d0Zz4YP749N8IiCoLpju5Z7O2yP6C4n3XwSRKExXK5ROwg9adTW556
+L44a0aChbR1b7Mnz/du0vx67O0D6hMRhS7ICuiI+pkpovJsVnT2QdObWBlls2Bic
+e+iSX+eIlXHcURQc0ZkhvKiiDYgxeSo4RvxknjaauHKdIA1DQC1G2IFU+Izjg7j0
+pS5yeLaGtz7azDmrChRrP+XRCDjsSuihtS9dtDRTyUwRYjhU6plkHjjwvXaFh3EW
+ZQWN0LVL7m7M2MtXUPlKYlEG8SpcrfBS25aBg4tRLRo8w/iWY0Z3HcRYYj9HiZhU
+3Yo0R0Z2apWmbVVmxNJQy+jA
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/TwoCRLsCAGoodCRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/TwoCRLsCAGoodCRL.pem
new file mode 100644
index 0000000000..7bffa1d5cd
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/TwoCRLsCAGoodCRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBvjCBpwIBATANBgkqhkiG9w0BAQsFADBEMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEUMBIGA1UEAxMLVHdvIENSTHMgQ0EX
+DTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAtMB8GA1UdIwQYMBaAFBCh
+AdaZnYDjbf3n7ndLX/FJ2TxTMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IB
+AQAWgigQQEvB+tF9ELpYI007J23N+XwGsg5vz8wIxMsi5Sa3NDkUCZ8ByXClFLRp
+zIM650GcrIDpZCHPhfgT9bU2b2LX/4vVdSy/aI7tC+nd70UPKeH4SU7sVwAJmKQD
+NRnWLJp7VXl79yR51SEMKrwNpgoFmblJHKcLyNr8NrwmLmS/5mpGaeri0bEh53cy
+Zv9dvJI6Nvh30wbYtcEtURtCSHWYlIYs8cQML4IsYcQbWSX8uS4XqSnaUVwYKtFT
+HdUX46XIkuGdKeExJKbWXb9R9JJcCG85Qn+mfX+Z0XatgOxGpmuzJ/JbEqxPS+w0
+25GOIJTaYjoDxoOmVIpJZGcZ
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/UIDCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/UIDCACRL.pem
new file mode 100644
index 0000000000..c94eb68a11
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/UIDCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBuTCBogIBATANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEPMA0GA1UEAxMGVUlEIENBFw0xMDAx
+MDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8wLTAfBgNVHSMEGDAWgBQQP8UEMPHY
+QzaFeVyMjYud7i8cqTAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQsFAAOCAQEARJT8
+6342NMtFGT+8uvbJJ26LNypeqnke2LqSnfunR258riLofJj2E5r1NS7Ew5YjWdZH
+3BiwowR/IRuFqlj1l7gDB6L9YFVbNuJrC41UxIBzGMa2zHtTXxe610TC987XcbbT
+O4ccPzvQ3MEfiY7odLNkOpKfOHUTgOvPfpo/8X/jofZp0kBTH7q31S4XKH1XHBab
+H2kyudXTJmNkSXOdXlclPdZ1wdtt5hi/i5mYMQYnwVgQoburqiAt1LurPrOi6zgK
+JmfT7ELdKocAa0nRCBMMTZLknEAVubFfI1ViKGMGwolmVIQjlJrI7h6RMh4bUEVI
+eDsOknaIs9a+DRxKNA==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/UTF8StringCaseInsensitiveMatchCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/UTF8StringCaseInsensitiveMatchCACRL.pem
new file mode 100644
index 0000000000..a6c2055e8e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/UTF8StringCaseInsensitiveMatchCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB1zCBwAIBATANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJVUzEfMB0GA1UE
+CgwWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEtMCsGA1UEAwwkVVRGOFN0cmluZyBD
+YXNlIEluc2Vuc2l0aXZlIE1hdGNoIENBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEw
+ODMwMDBaoC8wLTAfBgNVHSMEGDAWgBRg3xjRyqlQkhEXIUTSd/Vqraa+eDAKBgNV
+HRQEAwIBATANBgkqhkiG9w0BAQsFAAOCAQEAfnKj08ZVDYA3KZCzOUW4VvkN0rgV
+qYukj5p80KK3oRJtQjiMB7M+BrG/Nu2ReWIrB2vSyryurZD2QeTcJOr68b0I/VLV
+uz4/b1/AlXgvUywrMiaXKrW/dApifr70HDghgvyCwQ1SDST/jFNBmrC//H61A3NG
+PenyRN+GkvTzlOIoJcqZ4PRX7J28D9lesW4m8Z+k7o/mF0c2F2lBMG+yzTh9ZB5W
+eaqvmY63gKTu3GRUHET6/SE2HI1fgioVFPDutr5b1uh9ACA60X+Lkg6MBhPqPGdY
+UQXKBt92Nd1aHg18VydBY9+6yBEvlQfpZyaQ/Sx7TL0SSwzKlcGDwXvVXA==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/UTF8StringEncodedNamesCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/UTF8StringEncodedNamesCACRL.pem
new file mode 100644
index 0000000000..2bfdb97dcc
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/UTF8StringEncodedNamesCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBwDCBqQIBATANBgkqhkiG9w0BAQsFADBGMQswCQYDVQQGEwJVUzEfMB0GA1UE
+CgwWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEWMBQGA1UEAwwNVVRGOFN0cmluZyBD
+QRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0wHwYDVR0jBBgwFoAU
+O2dbRPINp0h9cymMk5/VJOMSYCYwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQELBQAD
+ggEBAE2uI86u6pYfkenx+nHcN7B8ymkICJpPJlIqNfjteDVjwz9D2ra89nHKdXRE
+83ftELk0cXxN4qEuylBI+2V/WUNjll1VsTqvRSGDFu6KhjZHEjbdGHu2Z+tT7E9a
+72X3hxYJEDycSTlaR4OvFUWeKksPaKXt6HdhV7AQUHT9KbewgLDekpPKj1O1tjzs
+/NN2mt0mBqbm9dzi4oL2PezZLfEOpa1BXQR9r37HWKmDxO4SixOGNaOd+jplpzhy
+PDqftcMmgRZnKesEvKcXul1GRxreqhaF+dlvluKwzRgC9Z0x8iS8HyoqlCzdGy8x
+OuRJvqqfg0aPDn/waUA0pF7Qfwo=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/UnknownCRLEntryExtensionCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/UnknownCRLEntryExtensionCACRL.pem
new file mode 100644
index 0000000000..dfee3b2056
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/UnknownCRLEntryExtensionCACRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIICCjCB8wIBATANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEnMCUGA1UEAxMeVW5rbm93biBDUkwg
+RW50cnkgRXh0ZW5zaW9uIENBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+MDcwNQIBARcNMTAwMTAxMDgzMDAwWjAhMAoGA1UdFQQDCgEBMBMGCWCGSAFlAgEM
+AgEB/wQDAgEAoC8wLTAfBgNVHSMEGDAWgBQAphnLoS1NKC8i89JMN8//TDDN6jAK
+BgNVHRQEAwIBATANBgkqhkiG9w0BAQsFAAOCAQEAIGIA0Yful35UcVgnqPFFJiLX
+VB8WXGbleSexbAb9EgxCCpffOaMuaq51McJ+Rjspyjmn0SEnbnpeKmNbmYtnQjn0
+OxNp/Yy5ZwjufitxKb9JgFLBhfpJ2BU9H5MgPEmXA+aZf5ojGPh/2afwJKE/9H22
+wemiZlYlpA5aN7PYqWHfEPE2bd4Ey7RHleuCRpfDHx2EgumLSRYjm9q++THgGOgu
+C59aDH3vvuAItfh9eVHTYxxjRm9kjIC/RCrCvQRclRGN/SoPDBys9RQxv1iklvN2
+rLH+Os+0BB3L67GMsAFQhWXCFU6U9Yubm/mErDVFOwsmuMNNKgojKkuqAhxZzQ==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/UnknownCRLExtensionCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/UnknownCRLExtensionCACRL.pem
new file mode 100644
index 0000000000..8d7158e411
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/UnknownCRLExtensionCACRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIICBDCB7QIBATANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYVW5rbm93biBDUkwg
+RXh0ZW5zaW9uIENBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMCIwIAIB
+ARcNMTAwMTAxMDgzMDAwWjAMMAoGA1UdFQQDCgEBoEQwQjAfBgNVHSMEGDAWgBT9
+//4ZTdsMncWi2IJW67DZEGHjMTATBglghkgBZQIBDAIBAf8EAwIBADAKBgNVHRQE
+AwIBATANBgkqhkiG9w0BAQsFAAOCAQEAsguh6rQBEGU98+Fqtl5R79QDu51NuNZF
+H2otyBt8ZPFJkif8J/pquv09GgIMFsMbAtMGkVPNYEjnQ6MHSWYE2SxTYeIfOnQb
+JiED6NtncdUGsoXt2g+9gJTDdVPjl8z9p1j1QEdp6c/XEj2gEVGDkM2iAy/3QImN
+kqrG1n1QtiAOUQ1oZoIk6NnGfAvRQ5/eNZafTa7vm805Q11tE6mT8XwbUX9Cs/lL
+X5h3h7DATdVfDPYwac9NZ8rrof7FQ/jXB4p2P5PM/U2vqEM8YTuRhW2w+jGzBFY6
+ef7bd7LrSoWExjczcmVuIZDqrxYsdAc4TJbQUm8B28FkdM4NzVo2Bg==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/WrongCRLCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/WrongCRLCACRL.pem
new file mode 100644
index 0000000000..114e6e1cbf
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/WrongCRLCACRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIIB4zCBzAIBATANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3QgQW5jaG9y
+Fw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMCIwIAIBaBcNMTAwMTAxMDgz
+MDAwWjAMMAoGA1UdFQQDCgEBoC8wLTAfBgNVHSMEGDAWgBTkfV/RXJWGCCwFrr51
+tmWn2V2oZjAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQsFAAOCAQEAqxkdtbsha7bh
+TM3wtzeelTjR1IGQgK4R8Psc2fw2NOydlq8PeSc3qitHV6m4dqHzchQlytYprOK4
+dRitEh+RYY4UKUNu+OQQ5VFLSvuC0Wv3xn2w29VqpQtavBFfJ8Lst9520pece6x8
+6fB9L6VP4YNGIrLc+7hEjEDALJs+ttPoxNNXGMApQQi5xyZEksXQAo60ZdH/r95l
+dVCa7U2OVXO1MCuZlWQRlql0Bi3CzE26cW1jccEdU6yQ0ONKNuROR+6NsXZ2Qm2C
+lHEGWFJAZ/CWB7NjQ9maNkoioZb4IB2AKPKBcb0mT3TYspgT8zcZSP5DLC8iVOrc
+x2SLSvd35g==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/anyPolicyCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/anyPolicyCACRL.pem
new file mode 100644
index 0000000000..d8cd6550ee
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/anyPolicyCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBvzCBqAIBATANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMYW55UG9saWN5IENB
+Fw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8wLTAfBgNVHSMEGDAWgBS7
+yd7IHJXnQuKQoo6uA1yrJGB+hTAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQsFAAOC
+AQEAW7i6zdMI6ytGpku8kYKf2WVx9tqIMFh+vvcagsWR/9oPNp1kXgdfv/tfRS9F
+JRQ3RVYaKY2bWDVc8ISsrwZpBMe3RjfDEdqAyuNcy4B/C+O7OAtyNinAvtsYASAU
+gfDoW3s1V53iLbLDfY1uRCq7F78dHwjuuIob+tpHFR9EVUx3MgkPAyq8oLrbDdaV
+FAsq2XTgry00qj82bR0rSY7UdNMOhDy32qeoH4ZEEh0XHdBEM3xuMjwn6x6J2SiV
+96FDpO+UNcTr/VeV9sx0xJAJOqmSU+e8nL8FKCGhm02fI9CIZBV4TOICDgacRgOn
++aSLkS+XcWlyrkZL2FakdOWiXQ==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/basicConstraintsCriticalcAFalseCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/basicConstraintsCriticalcAFalseCACRL.pem
new file mode 100644
index 0000000000..b5726c158e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/basicConstraintsCriticalcAFalseCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB2DCBwQIBATANBgkqhkiG9w0BAQsFADBeMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEuMCwGA1UEAxMlYmFzaWNDb25zdHJh
+aW50cyBDcml0aWNhbCBjQSBGYWxzZSBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMx
+MDgzMDAwWqAvMC0wHwYDVR0jBBgwFoAUcN9ELwOZHBdzGPI2PBQ00AnR8u0wCgYD
+VR0UBAMCAQEwDQYJKoZIhvcNAQELBQADggEBAFaK4KYhrGo/o9KPU/OnZGglN4vq
+uuAH6a9XjvSUA/de1oHyAxw6rgxrjBo1pgtdLgSqXuYXMeqyVjZV5ew58wd7f0vG
+u06a6f3TOX3ScNZYY9/u1VRsX8/y3kKUg2+EQdr7vYCjhSIc2SLqpAnku150OwB9
+GZG7y/NRjqX9AyecyCJm16G/w9fA4+tndtvBvvDIwYn+LGrse5cgka4iR+CWzsIj
+cA17nCnhg3n88NSXrIsre1LI1YBKEHrIqbTpDglDxtJcdTtF+5/new5L+vftj0Rv
+8bR8NQPo5DBNJ5C9GnCjQgVSyMnQNhD3+LUDDScGs0QVg981FI6tusPFZpE=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/basicConstraintsNotCriticalCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/basicConstraintsNotCriticalCACRL.pem
new file mode 100644
index 0000000000..3dfeb7ca4c
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/basicConstraintsNotCriticalCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB0zCBvAIBATANBgkqhkiG9w0BAQsFADBZMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEpMCcGA1UEAxMgYmFzaWNDb25zdHJh
+aW50cyBOb3QgQ3JpdGljYWwgQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAw
+MFqgLzAtMB8GA1UdIwQYMBaAFAqkuTBDrEPINAITz+9V6L9wn0avMAoGA1UdFAQD
+AgEBMA0GCSqGSIb3DQEBCwUAA4IBAQBY/ZWklRmCU6F7pRzO8mrG3iaF2gp4Qyse
+QLf/yzlYy5XdbwzhwiClQ7EwxA9jaGD8EKopJL9sMh53QBZFivrXUP+O09cHRlMI
+SCyonmbdvnOUDwoky9YY4KrC0YI+mhbOpe6LQJcRgj2ge5C1i+UsQmUZapOUvXaI
+f5rc1TlLg4mlxYSQT9jnLV3aAwt4i6cwitTkpbYPolvjsHqfRQ2/aLLd59SNnIlv
+pdso7IaAW3aoo38dJ8ZyJZBwNAwR3dmi4oIOivHX6FwDgxNdhVIN5X/VsMeNbRu/
+mD1HePYlexWjcMfsVRx9oVsIVoT0i8dAXEnefM7n1XOadWnaW8Di
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/basicConstraintsNotCriticalcAFalseCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/basicConstraintsNotCriticalcAFalseCACRL.pem
new file mode 100644
index 0000000000..36b9df8549
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/basicConstraintsNotCriticalcAFalseCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB3DCBxQIBATANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEyMDAGA1UEAxMpYmFzaWNDb25zdHJh
+aW50cyBOb3QgQ3JpdGljYWwgY0EgRmFsc2UgQ0EXDTEwMDEwMTA4MzAwMFoXDTMw
+MTIzMTA4MzAwMFqgLzAtMB8GA1UdIwQYMBaAFDnQm7dPKTe+07CKdupqns3vRr5Y
+MAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQB5jwS9LsJUqzevwbstTFfJ
+TrsCQBjg8kn30zn2Yi0+ff92y1zfpzK3MSFfq9olKCKSpoKdwgLTZVXiHsO44X4d
+cIzo03knrnXX6wAQH0b/GXlbvQ9fEZaylTxMV7mO38UgIs9cWXdqjlsgAy37qOBT
+L5Dn2xUp2u/+QcbwyLOGP7/shriabGHlepclCQI6BxIor8gJz2zCxtovV90j7WL0
+8nF8wMwVv89hu38b92uORIQDamYDRTigiOYS5FPTirqoReA9lUdQ+hd3KaS1S/YE
+w7fmNEbkdCMg4hHAYnR0xW54Bp9bea2ANRJmdwUCz930q3XqPS8OJt/PZgOAmdYa
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA1CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA1CRL.pem
new file mode 100644
index 0000000000..338d64cd37
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA1CRL.pem
@@ -0,0 +1,16 @@
+-----BEGIN X509 CRL-----
+MIIChDCCAWwCAQEwDQYJKoZIhvcNAQELBQAwRTELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNVBAMTDGRlbHRhQ1JMIENB
+MRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjBmMCACAQIXDTEwMDEwMTA4
+MzAwMFowDDAKBgNVHRUEAwoBATAgAgEEFw0xMDAxMDEwODMwMDBaMAwwCgYDVR0V
+BAMKAQYwIAIBBRcNMTAwMTAxMDgzMDAwWjAMMAoGA1UdFQQDCgEGoIGKMIGHMB8G
+A1UdIwQYMBaAFHcYI+V2hMgUlD+C0IHqdLHgpC8zMFgGA1UdLgRRME8wTaBLoEmk
+RzBFMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTEVMBMGA1UEAxMMZGVsdGFDUkwgQ0ExMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEB
+CwUAA4IBAQCEUqY7TzVnZWYlyrtBszCIhhTKhr7tH5UHvoZkNs8lzeBMqtUDZvd6
+o0mB7WSv5R+t8tGleNhn4isudltqLAWZxxZNnht04o3YZTwKS/NRNAinBoQfZnmw
+abMmledsFuF2JrA3XYOZ5NWdlah8/MPUAKRoI0Dw7qxmLL/exsz5OAKh3qjXlzwJ
+Bdm4CYCO3DH58BQk6oJKVlqCY3ZsCuvtvjNHnLpkXAKRQ+t/OsHWssYkEVX5FizE
+WE6G6XMMcQtb2gN0QwzO8o3xyFGYyy1gkEuB+yzmqHqLYTlRZd5IvRxYYoqHbrce
+x7ROIMJEsNFw5k+b7qWYLo703GOsCxD0
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA1deltaCRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA1deltaCRL.pem
new file mode 100644
index 0000000000..4c306accba
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA1deltaCRL.pem
@@ -0,0 +1,15 @@
+-----BEGIN X509 CRL-----
+MIICWjCCAUICAQEwDQYJKoZIhvcNAQELBQAwRTELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNVBAMTDGRlbHRhQ1JMIENB
+MRcNMTEwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjCBiDAgAgEDFw0xMDA2MDEw
+ODMwMDBaMAwwCgYDVR0VBAMKAQEwIAIBBBcNMTAwNjAxMDgzMDAwWjAMMAoGA1Ud
+FQQDCgEIMCACAQUXDTEwMDEwMTA4MzAwMFowDDAKBgNVHRUEAwoBATAgAgEGFw0x
+MDA2MDEwODMwMDBaMAwwCgYDVR0VBAMKAQigPjA8MB8GA1UdIwQYMBaAFHcYI+V2
+hMgUlD+C0IHqdLHgpC8zMA0GA1UdGwEB/wQDAgEBMAoGA1UdFAQDAgEFMA0GCSqG
+SIb3DQEBCwUAA4IBAQAFVo99MjLWWcc8kdu/qveAAPZgvgHBAQqOygCNbu4J704l
+Ab9wHTJoNvghxK7iGsCGd2O7l1ODdooPWNcY3NVkY2soZmevk5F19MQX7fr4HrLp
+Dtcdfbby1PG2TX0MttfwpGDh8yfO1SFjkclmoP8f1f8mrmulJcy/sXK+H478JHO1
+lycEzMsvgGj2HCZvRziR+g3nH2AVMra4r6u+oo1ctwcWWGRkhfuyeBBJWDMh3T61
+gIbdB+Atjs3QBscvjPdU+F5XyuaBLbwEBYJOoTeSKTxfDVeYnPFghHyenItJsmII
+5IPocdTk/6/RB0wtDlMQwjNUXxe0/3WoHVy8bUQZ
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA2CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA2CRL.pem
new file mode 100644
index 0000000000..b4090dfee4
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA2CRL.pem
@@ -0,0 +1,15 @@
+-----BEGIN X509 CRL-----
+MIICQDCCASgCAQEwDQYJKoZIhvcNAQELBQAwRTELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNVBAMTDGRlbHRhQ1JMIENB
+MhcNMTAwNjAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjAiMCACAQIXDTEwMDEwMTA4
+MzAwMFowDDAKBgNVHRUEAwoBAaCBijCBhzAfBgNVHSMEGDAWgBR82Pa+A0zOz7c/
+oRm7M6u11437xDBYBgNVHS4EUTBPME2gS6BJpEcwRTELMAkGA1UEBhMCVVMxHzAd
+BgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNVBAMTDGRlbHRhQ1JM
+IENBMjAKBgNVHRQEAwIBAjANBgkqhkiG9w0BAQsFAAOCAQEA57Gy4XXEzOgR+KG2
+Yc4w8HgmX79ERY3s082LNYuSwFrA3D7hoCa+tX8tuXbF6Kgb+wocIFROzk7r+ZIp
+PegSzJQcKWoVCQiuHUfBt3MVZLojeM4n8ThfMbPOnf+Si+V4YgEcBGcgKt/pxEnZ
+d1dJu+rB+TSyUk4QuJ5X2DJn4ne+2Wf6mzoZKakJp61aDD5QxysbN/52R9QR/wdg
+awyL5mtu/8U342t+4sFbLm7X/pyDcPkp9on2ORsKGIBGGr3QoHItIAZn2ghPsT6a
+5YYcJOUm/pZwBeKoZyQ+s9Lhon5HOWs5aE3KwFdS5vo1zpB2Ps9Sv4ud2+O135oG
+tuFQTA==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA2deltaCRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA2deltaCRL.pem
new file mode 100644
index 0000000000..d305bae0ab
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA2deltaCRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIIB8jCB2wIBATANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMZGVsdGFDUkwgQ0Ey
+Fw0xMTAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMCIwIAIBAhcNMTAwMTAxMDgz
+MDAwWjAMMAoGA1UdFQQDCgEBoD4wPDAfBgNVHSMEGDAWgBR82Pa+A0zOz7c/oRm7
+M6u11437xDANBgNVHRsBAf8EAwIBATAKBgNVHRQEAwIBAzANBgkqhkiG9w0BAQsF
+AAOCAQEAWX5v6H6qmSiro3ZgYkvIi4WDhAzCpjMNElzQ7rs+mPh/1B/2CSAv+B9Q
+RXHJvMYS0XEwfvTy3N5vAhY6QMNhPKJcepJHVmng0NMOBn3DMJJ7nobJKAA95ls8
+/BP+nNjVHoq7RnLivTxvXOijGGCJACg3st64CByuwcbNcJdEJkI0usFnLEoA8W9Z
+G47VSzeORnf3EmA4IZERhS7NY3+91CDRb8R0CO0u8sVVPPWMltdN0WYSnQA9D4oV
+hOEunai3vsrn7DVSsoTrIWz7zxgIgxk+6sfaWhGIKVLW34lIdA2geMWt446/maWg
+E/O9OWirLi1qY7bp8BcCUe9UL/cfOQ==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA3CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA3CRL.pem
new file mode 100644
index 0000000000..084e49127f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA3CRL.pem
@@ -0,0 +1,14 @@
+-----BEGIN X509 CRL-----
+MIICHDCCAQQCAQEwDQYJKoZIhvcNAQELBQAwRTELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNVBAMTDGRlbHRhQ1JMIENB
+MxcNMTAwMTAxMDgzMDAwWhcNMTAwNjAxMDgzMDAwWqCBijCBhzAfBgNVHSMEGDAW
+gBTvY9OoTrH532HiDcMFo5gY0pOZ5zBYBgNVHS4EUTBPME2gS6BJpEcwRTELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExFTATBgNV
+BAMTDGRlbHRhQ1JMIENBMzAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQsFAAOCAQEA
+XB3lEAs1DWFKrU3BzflSTtmiCa5KzMZrXpDmqHt7+kWNjEMUS17TsvkrfGWOcEFJ
+9MzmGUqAuD9Z0q5kxVVNRuZhG8K9U+biCmMVFtKzxFGbz/vJkcKaroB/ukiqNQlv
+DTSKebUJJm5g0rc06LVGic+YgK2pcCwm4BsdmcCEYV3mlIhUOUA48Ww0WemFKPTw
+9A1V3URGpOzrMJYJOJff0IOVjdyGwSc+xHCtbJG4xV+/Qe1/9yYn+RqHQXUo0C7D
+GJNSr+OcpXX8urZQp4ZVQRz3OTs4eb2xRK1ZPj9Xhiv98iZwo38GaFGvMhOHv7gv
+C13eDAq4KnlQgz/wpxmHog==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA3deltaCRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA3deltaCRL.pem
new file mode 100644
index 0000000000..db02c94369
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLCA3deltaCRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzjCBtwIBATANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMZGVsdGFDUkwgQ0Ez
+Fw0xMDA2MDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoD4wPDAfBgNVHSMEGDAWgBTv
+Y9OoTrH532HiDcMFo5gY0pOZ5zANBgNVHRsBAf8EAwIBAjAKBgNVHRQEAwIBAzAN
+BgkqhkiG9w0BAQsFAAOCAQEAy7ylas55kqoznlqWS9cO6Q/EC7dPiZKF4Szp326L
+qCs4kd16Vbi3mhz7BP2iHSjO0AlaMnmGSYOlnzQEtuD6NlQB1RhuWH1kCWAaQPXU
+4K4nMJduHuGjopkIxnN8BGPfXGbeOJfl0FDQM84vkRCJ4Owq233JvEIDCEhdkYsO
+wQr+dUqPNkR1lz7fGtskqpe3aotkQ3DrS/1wuBRuTmXLKDZy63IdAe+TTp8yugnl
+9QEdYEXvMgLChLe57ZaOFVCE8349rkhikvnFWIfc1st2EsBrOaOwqFUrZReVg6qx
+wxDSf2FoINaLIX7ECkEBBmQh9SyEz8BXwaboI8z08ovRzg==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLIndicatorNoBaseCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLIndicatorNoBaseCACRL.pem
new file mode 100644
index 0000000000..781db0a18d
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/deltaCRLIndicatorNoBaseCACRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIIB3jCBxwIBATANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMcZGVsdGFDUkxJbmRp
+Y2F0b3IgTm8gQmFzZSBDQRcNMTAwNTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqA+
+MDwwHwYDVR0jBBgwFoAU9Dh2Jauk4xzAyHWMjRNrYyO2ioEwDQYDVR0bAQH/BAMC
+AQEwCgYDVR0UBAMCAQUwDQYJKoZIhvcNAQELBQADggEBAJOY+1gmjxVv2D6HNyPt
+vKA7Gk7seNkgnSPoPR24Ao0znff3gjJGgz6r0TY7IIF+ddgjmu4l6BpkS2fN2Uow
+BCFEAD/0lK0RPtuyUCdbFiSHtNQlbpbxEK0iwDAw2YoYQZBP6qobz3IIjxIZjQou
+XlOIRoXE8Lg0QHFHQF58+Bs7Exk5kU8bwCalEL36OcGihMb9wXuuJTvSuXypU5v6
+kDwwrvxx06w9O2WYC8dqriObG8Uz04+Xt6alCmcj/sU2rop6BZMheZ8bKSHXCPWB
+FWIubsW25os4rHlxDz+DmXAcRCyIyrQxz9ERTDjPhKhAUPXz+baG38/oqA3bVMn4
+HKo=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/distributionPoint1CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/distributionPoint1CACRL.pem
new file mode 100644
index 0000000000..dc27f6b6fd
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/distributionPoint1CACRL.pem
@@ -0,0 +1,16 @@
+-----BEGIN X509 CRL-----
+MIICfTCCAWUCAQEwDQYJKoZIhvcNAQELBQAwTjELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHjAcBgNVBAsTFWRpc3RyaWJ1dGlv
+blBvaW50MSBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjAiMCACAQIX
+DTEwMDEwMTA4MzAwMFowDDAKBgNVHRUEAwoBAaCBvjCBuzAfBgNVHSMEGDAWgBQR
+MHO9jXAogtJvz9I37c3rI5Hb7zCBiwYDVR0cAQH/BIGAMH6gfKB6pHgwdjELMAkG
+A1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHjAcBgNV
+BAsTFWRpc3RyaWJ1dGlvblBvaW50MSBDQTEmMCQGA1UEAxMdQ1JMMSBvZiBkaXN0
+cmlidXRpb25Qb2ludDEgQ0EwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQELBQADggEB
+ACrxG+l579by89QJva16Yro3XPJ9lXu/l8cgQpoaHZifIG9TnaWxb4WFwSBIbOqp
+rbQW7N580RJBH2SqiiUmCu6Acg2ryKfywGULkFFd0ZYMBrhtHQe7T0SJq0NFtMlZ
+A9Vgia3Tqhiam3c1oJeZnETcn35b5qLAmr+EaRpXDT4Mflqwub0kgwal6p9wmuH5
+vs4dc98l/Ub+J+ve8yVmMVq/0YSGv5Z2IjX2V9iWdjcZPnAC3BaOMvm40zy5cOWJ
+FaXii7M41MgR4d8ZMQn/UQGb2CMypm207QW3yNbuI7+/0y0vxJDo2k84ktw6sAda
+dQBSIAUmYp0Rsdtg9TwZE00=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/distributionPoint2CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/distributionPoint2CACRL.pem
new file mode 100644
index 0000000000..1ebde75c29
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/distributionPoint2CACRL.pem
@@ -0,0 +1,14 @@
+-----BEGIN X509 CRL-----
+MIICJTCCAQ0CAQEwDQYJKoZIhvcNAQELBQAwTjELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHjAcBgNVBAsTFWRpc3RyaWJ1dGlv
+blBvaW50MiBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjAiMCACAQIX
+DTEwMDEwMTA4MzAwMFowDDAKBgNVHRUEAwoBAaBnMGUwHwYDVR0jBBgwFoAURGzu
+229/605Jf3j+zeUYoOy7YGswNgYDVR0cAQH/BCwwKqAooSYwJAYDVQQDEx1DUkwx
+IG9mIGRpc3RyaWJ1dGlvblBvaW50MiBDQTAKBgNVHRQEAwIBATANBgkqhkiG9w0B
+AQsFAAOCAQEAD560RltKzGwM+LefEKN9n+UE6uNAoPwiNSYPGe9Qcu9WXsG11CqZ
+O1saNKTu0+bMx11WU3qRDyGpWZidaW0/x60RcSMR/X/RGoZw2hlixluvHpIBQwYf
+H2V2PE+OjNIeXBF9uEAV5KuBRb/Yre7GlCoXJM1j9WZRCHKwVYZ2xNog9R8STNs5
+fw4kynvydxQ6U8KjUxJeBmb6PiAf64Mcf9AXUCjakwAKJgw2zptKV75QrEEwpnVj
+sv7A5HqoMS7mLwPV2dznH+rHn/0IJp1FuS9YNs4L7oTyKZYlriy7U5pmsHHajGIc
+6g5+w/GiX51Emsi7RXjAvfpu/9MisG29PQ==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/indirectCRLCA1CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/indirectCRLCA1CRL.pem
new file mode 100644
index 0000000000..c9de28ecb9
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/indirectCRLCA1CRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIIB9zCB4AIBATANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UEAxMPaW5kaXJlY3RDUkwg
+Q0ExFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaMCIwIAIBAhcNMTAwMTAx
+MDgzMDAwWjAMMAoGA1UdFQQDCgEBoEAwPjAfBgNVHSMEGDAWgBQl+K/8r7apGht5
+S9vLZCyLS7EVzTAPBgNVHRwBAf8EBTADhAH/MAoGA1UdFAQDAgEBMA0GCSqGSIb3
+DQEBCwUAA4IBAQALqiVAlWG4BlkRVLdCVDqUtfpcaK8JLzEqoQUm4fS+Y+mdf9uA
+Q8+l8aQmcGeh/Gkufzp4bwsxkkxL81qTvuvDm4UV5q4TYz3aaWtzE/ewNWzLyLjA
+FQafw0u0ZTdXs5Z7R03DlwrGH27ZmMqjue8uV060HNTVUzWJjnSwxZ2FZ1gY6Rbe
+F0cmOk3ym2/1h61sWgBZRLG5vIGZkJe/An/pJyGL68bKTnyaPeYdKm0knt/yGGbo
+24bdwhzVLbzPIq6n8JCNWhO5r9pcmhR+XdrgddIpS341f9S41j82WGfwLCnc0pBX
+6PxVxMdDQ1qLQAbzCU3OCE98HtTv7IpDCUdi
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/indirectCRLCA3CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/indirectCRLCA3CRL.pem
new file mode 100644
index 0000000000..607f7bf989
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/indirectCRLCA3CRL.pem
@@ -0,0 +1,14 @@
+-----BEGIN X509 CRL-----
+MIICMjCCARoCAQEwDQYJKoZIhvcNAQELBQAwSDELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGDAWBgNVBAsTD2luZGlyZWN0Q1JM
+IENBMxcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqCBnTCBmjAfBgNVHSME
+GDAWgBRIk1R9xG0w/y1XRXEk30wFn0oALTBrBgNVHRwBAf8EYTBfoF2gW6RZMFcx
+CzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRgw
+FgYDVQQLEw9pbmRpcmVjdENSTCBDQTMxDTALBgNVBAMTBENSTDEwCgYDVR0UBAMC
+AQEwDQYJKoZIhvcNAQELBQADggEBACvzWPSm982N1bxs5RW+yTNbWoZ1NBGEvAUX
+B80kE0PTfchM1HbkPh4SkkVarj2/alnN4E7cMWzlq1qhc76WR4ApjPZmCW4zlw1e
+a229Eh3s15IX+CZcBEza5mQIHc5mnn2v80MPJCS7W53lvPlrD3T85bv3w3uX8UZi
+AkR4wCC12Rbnm4fEtgkIxuB7FrKb0SWf6ygBn+Tcv27CGSF9YBhVsXEyGAA8qt9N
+1eBJrRGBu1xG6rYEuW5OQgGhZgV3QhxEqUxhatPtYT8bcR07S3PrGx9Y+Mh+o9Mw
+LuHM6OiDiRdd2nRUmWWpZGOgdTKEJ0eFrqOnxHPPF3bhhiJs0hE=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/indirectCRLCA3cRLIssuerCRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/indirectCRLCA3cRLIssuerCRL.pem
new file mode 100644
index 0000000000..a366a243ba
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/indirectCRLCA3cRLIssuerCRL.pem
@@ -0,0 +1,15 @@
+-----BEGIN X509 CRL-----
+MIICajCCAVICAQEwDQYJKoZIhvcNAQELBQAwUjELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIjAgBgNVBAsTGWluZGlyZWN0Q1JM
+IENBMyBjUkxJc3N1ZXIXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqggcsw
+gcgwHwYDVR0jBBgwFoAUkdE5mMnvT1RlihhSLXwSEgpsd40wgZgGA1UdHAEB/wSB
+jTCBiqCBhKCBgaR/MH0xCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRp
+ZmljYXRlcyAyMDExMSIwIAYDVQQLExlpbmRpcmVjdENSTCBDQTMgY1JMSXNzdWVy
+MSkwJwYDVQQDEyBpbmRpcmVjdCBDUkwgZm9yIGluZGlyZWN0Q1JMIENBM4QB/zAK
+BgNVHRQEAwIBATANBgkqhkiG9w0BAQsFAAOCAQEANA7Z476bqcNnf7wWi2LE7Gws
+3Nz3U+G05Yp4xMLc4gYoKj/W+mjvsbXzJ2sjU8D2e3qHu3p0lIsFP+ZXXhvi4CEv
+3lIMQQE8/pPGxtqGDSnKRstdZPq2JvqisZFieChKH469G7yrHNMKD6C4MkQs27gj
+3cybk3G5fEGmpE5xVwHb1m2P/wD3vzkQVU6+T+RD8FPlZbqJRZEdIg/RSBQNXjbY
+ZIvKCkfl6w63f39NgMYSsfUM2g4jiv8PAoAR/RmDHgvylCoc8E2KDWiTFss/502e
+hhNTwMhEGS+Aze381vRThygIpqw29m4My844a8XVX2jZ8y6GGoiwqdby8U4wwg==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/indirectCRLCA4cRLIssuerCRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/indirectCRLCA4cRLIssuerCRL.pem
new file mode 100644
index 0000000000..596762cdbb
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/indirectCRLCA4cRLIssuerCRL.pem
@@ -0,0 +1,15 @@
+-----BEGIN X509 CRL-----
+MIICajCCAVICAQEwDQYJKoZIhvcNAQELBQAwUjELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExIjAgBgNVBAsTGWluZGlyZWN0Q1JM
+IENBNCBjUkxJc3N1ZXIXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqggcsw
+gcgwHwYDVR0jBBgwFoAU8wjrbbnFoBCk2gRF/696R68RwLkwgZgGA1UdHAEB/wSB
+jTCBiqCBhKCBgaR/MH0xCzAJBgNVBAYTAlVTMR8wHQYDVQQKExZUZXN0IENlcnRp
+ZmljYXRlcyAyMDExMSIwIAYDVQQLExlpbmRpcmVjdENSTCBDQTQgY1JMSXNzdWVy
+MSkwJwYDVQQDEyBpbmRpcmVjdCBDUkwgZm9yIGluZGlyZWN0Q1JMIENBNIQB/zAK
+BgNVHRQEAwIBATANBgkqhkiG9w0BAQsFAAOCAQEAKRPyrIpC9HqbA9TytL4xuspW
+lO0Ihz0TyIs8bWEMPSanD0tdGsO8v1QQrv/XSVeAPiDcPvwFtX47TpbPJxJQBV5/
+AfGEAJ/o5Jl9ah2yuA3Qd1UZkL85V/XJgnqxpqJeLRQoQ3PeT0rlnQUM2fru3LrF
+AZn9lpxyqfqPsNbcDwwf0dbtGOvwUC2KTkXueizW0VEFgxRmRcielTglQXSV+Y1Y
+/MLqly+BHpWOko7BnfR6Ukfod6O8vyPwhUm0VW7AxPNH/qbqcpJjMnwCN8Bzp5LL
+UfQ6pkmCRWESbba14wXPuhoPM3OhzBzpGrBMeRpml96Tf3Q6xho0V/QmOaAs8g==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/indirectCRLCA5CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/indirectCRLCA5CRL.pem
new file mode 100644
index 0000000000..fdab0bd2f1
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/indirectCRLCA5CRL.pem
@@ -0,0 +1,35 @@
+-----BEGIN X509 CRL-----
+MIIGJTCCBQ0CAQEwDQYJKoZIhvcNAQELBQAwSDELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGDAWBgNVBAsTD2luZGlyZWN0Q1JM
+IENBNRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjCCAt4wIAIBARcNMTAw
+MTAxMDgzMDAwWjAMMAoGA1UdFQQDCgEBMHoCAQIXDTEwMDEwMTA4MzAwMFowZjAK
+BgNVHRUEAwoBATBYBgNVHR0BAf8ETjBMpEowSDELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGDAWBgNVBAMTD2luZGlyZWN0Q1JM
+IENBNjAgAgEDFw0xMDAxMDEwODMwMDBaMAwwCgYDVR0VBAMKAQEwIAIBBBcNMTAw
+MTAxMDgzMDAwWjAMMAoGA1UdFQQDCgEBMHoCAQUXDTEwMDEwMTA4MzAwMFowZjAK
+BgNVHRUEAwoBATBYBgNVHR0BAf8ETjBMpEowSDELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGDAWBgNVBAMTD2luZGlyZWN0Q1JM
+IENBNzAgAgEGFw0xMDAxMDEwODMwMDBaMAwwCgYDVR0VBAMKAQEwIAIBBxcNMTAw
+MTAxMDgzMDAwWjAMMAoGA1UdFQQDCgEBMHoCAQgXDTEwMDEwMTA4MzAwMFowZjAK
+BgNVHRUEAwoBATBYBgNVHR0BAf8ETjBMpEowSDELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExGDAWBgNVBAMTD2luZGlyZWN0Q1JM
+IENBNjAgAgEJFw0xMDAxMDEwODMwMDBaMAwwCgYDVR0VBAMKAQEwegIBChcNMTAw
+MTAxMDgzMDAwWjBmMAoGA1UdFQQDCgEBMFgGA1UdHQEB/wROMEykSjBIMQswCQYD
+VQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UE
+AxMPaW5kaXJlY3RDUkwgQ0E1MCACAQsXDTEwMDEwMTA4MzAwMFowDDAKBgNVHRUE
+AwoBAaCCAa0wggGpMB8GA1UdIwQYMBaAFIH3qr1IdVmAsM/fIxid2JNGghazMIIB
+eAYDVR0cAQH/BIIBbDCCAWigggFhoIIBXaR1MHMxCzAJBgNVBAYTAlVTMR8wHQYD
+VQQKExZUZXN0IENlcnRpZmljYXRlcyAyMDExMRgwFgYDVQQLEw9pbmRpcmVjdENS
+TCBDQTUxKTAnBgNVBAMTIGluZGlyZWN0IENSTCBmb3IgaW5kaXJlY3RDUkwgQ0E2
+pHUwczELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIw
+MTExGDAWBgNVBAsTD2luZGlyZWN0Q1JMIENBNTEpMCcGA1UEAxMgaW5kaXJlY3Qg
+Q1JMIGZvciBpbmRpcmVjdENSTCBDQTekbTBrMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEYMBYGA1UECxMPaW5kaXJlY3RDUkwg
+Q0E1MSEwHwYDVQQDExhDUkwxIGZvciBpbmRpcmVjdENSTCBDQTWEAf8wCgYDVR0U
+BAMCAQEwDQYJKoZIhvcNAQELBQADggEBAD511WYLf3F/LVZg+HVRImOIHZrYvfUb
+QGXr1qzVVk86bLrZqrPNXo6+dCj/pZJrP35VxvrcapftonBK2FucTiMzWyg5WXI0
+lh3i/7BOlopDezS1m0T/vPhEYJM4ymyhbEY7vjLQWeTWEvcQIW0QGfVRpFzMzkwe
+FcIq6QleFY3hfOWT72oAdZHiweeNPc3/XMPFFkZ/3Tp52Mt1OOq49Xk8HneV/F06
+tZGefG3DrvQbkqBHF3p2qjWrwtNUHlqxJ5uCYf0UKMtwKp3KLTJgphrCOApaPapD
+Dixk3loTgU9P/PO5XAP8s+tTdwjYlYPDan/Uxi1PpwdxUZ/ghuFaW9Q=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy0CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy0CACRL.pem
new file mode 100644
index 0000000000..f6f50228e7
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy0CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBxzCBsAIBATANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEdMBsGA1UEAxMUaW5oaWJpdEFueVBv
+bGljeTAgQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAtMB8GA1Ud
+IwQYMBaAFBigoHpq/2qdhYIkzcMmhfi/ijcGMAoGA1UdFAQDAgEBMA0GCSqGSIb3
+DQEBCwUAA4IBAQB+ePMn32XQoMZZJrXrnElaigAgYnqRtRguHjnlJXmaftw3lk++
+PSQPSKUxKtuvbuczbt+jMJhTngohIIfbPfEYrSEe6kolUODSJK4Vdp+ja2jfD9ba
+VrmoHNH5JOLCm4HqaV6Cba3rKH8F+0rlw49q6YTS7otMBaaPgfVPMtketW2okiNK
+YBVOVSdC4XuxuZQZE3rz8u+T9QcOm12eMNJU/pXhFjOaagtqU1xtqEBO3LOsbMym
+uTRGJO8VoWdYNxe/jedXiAMASJlx4BQo0hJDm16wlubz4S0Ac9gHYNrFD6laVDph
+B5eNCGxHDSJkxhNtbW9ztHgQcT18pxOV4mHy
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy1CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy1CACRL.pem
new file mode 100644
index 0000000000..ad1941263c
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy1CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBxzCBsAIBATANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEdMBsGA1UEAxMUaW5oaWJpdEFueVBv
+bGljeTEgQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAtMB8GA1Ud
+IwQYMBaAFNimnieXEcOO1Bkh1yC8nO2he/LTMAoGA1UdFAQDAgEBMA0GCSqGSIb3
+DQEBCwUAA4IBAQBM2rRjH0dKX4Ay7xIJONSV1tyQoFaznksb2FKUgatoMTtF/Tbx
+WqANV/RsKCYjHc7wAlyn0LCfxyIvIGSLQTUk3+Dyk0yESy/Cz0R93eCeI2y+MZ7j
+BHz+jCEgOeV4ilL0Y2hTmHOQGBkrFfa/tWA2tAejAZmnozFhgQcfenUMXWc5uU3N
+CMS7n67+hUUE3kQ5qw5L3GtxUytXOdG4CUa96yPcMKJgJ1W4fk7FkAAGt2IM4lDM
++c3gS0+TfewBtGFPfu0kDt+0gLX/SdGGJhBnYCuoAicXhshNmhOjchP3Auo6pZHP
+0uto4/XnOnHKUanX+Cg7D++JqCa1FzShSjUn
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy1subCA1CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy1subCA1CRL.pem
new file mode 100644
index 0000000000..cc49e37c54
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy1subCA1CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByzCBtAIBATANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYaW5oaWJpdEFueVBv
+bGljeTEgc3ViQ0ExFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8wLTAf
+BgNVHSMEGDAWgBR0oNVY2StT0iuwzV1xxqG/Q6fIFTAKBgNVHRQEAwIBATANBgkq
+hkiG9w0BAQsFAAOCAQEAcdszKmraUaBp3w473eShNoALBZ1aj31fBfibxZPvtlwG
+BECryi8bmOwXZwKUE8Pr1MeQVtHYgDJhBscq9F8scmBwbmp/kRnBdN9Dgq7fe9Yd
+lke45ULwXOLkX+MdbWcNMX0OILkySpw+zpIDX1HCNeL0QKz+bXwouqgAnpj1IIFL
+yx56Vl/AGQ7S0jkR1emdZJudenGiCKkDqImjORjteSO852f04/83n6iNYDLcDzki
+uxyd+n00PMhqjiG44a5o+rAfOiJBbxv3eDMNQo7mhnTHUZnAq+3bSSQcJqCQBTNC
+zLna0kwa38h1WeQWbekOJGO2kiFd1pTss+mPmvpCBA==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy1subCA2CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy1subCA2CRL.pem
new file mode 100644
index 0000000000..846500d7af
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy1subCA2CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByzCBtAIBATANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYaW5oaWJpdEFueVBv
+bGljeTEgc3ViQ0EyFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8wLTAf
+BgNVHSMEGDAWgBSMBdzffmTbYr7bS1FkjGpm2FyjozAKBgNVHRQEAwIBATANBgkq
+hkiG9w0BAQsFAAOCAQEAsrP3R/bTvBLXn8NE+Qcr0Cr7ETparxT+Grm80Py+H77E
+UR6eT9/tvIJYTNYzpw7zEUB4vYeVqMJCZoPtP26Lkv30BLAkWEQ/kaM9720aG1pH
+sGUCpSwpnZkZeEhUW//IvCb9Ubf/aMAE+NpvLnYHBB2hQdckW8hCrMubc6jfQL2K
+DTEhwuFs8p81I2OXuA//qk9PrQlnI0dsFenmRCbSpZj3CzIjwuPbv4J2JKthNgb9
+xuFT97kzKFYa77JP+Skcicva4o0A94WVkCtcAv8FrHPNNapflzcE6edP5Y5R97SK
+yflBco+Kk8eEzkWleh3wLh04+CEoj9JYMEA+1ICv8w==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy1subCAIAP5CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy1subCAIAP5CRL.pem
new file mode 100644
index 0000000000..7ebae31c23
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy1subCAIAP5CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzjCBtwIBATANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEkMCIGA1UEAxMbaW5oaWJpdEFueVBv
+bGljeTEgc3ViQ0FJQVA1Fw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8w
+LTAfBgNVHSMEGDAWgBSJBFR0BmCz9wBuoGGOFfu+UgIGJjAKBgNVHRQEAwIBATAN
+BgkqhkiG9w0BAQsFAAOCAQEAGOaiustpHjlRoLea0ROpIk9v5o+dhhyD281DHP68
+cahcHEEDBsFZ+08KXnho7vLW55E2mnOZpjD+YAw5M1UpuZmKHgHTg14FfZhrZjco
+LjkcUC8hlCOc2ZfIpv23+Sh4dtR/iglXo5KqDiBbii0VPndtZ0M0XgTfLe+3vp1l
+ofMF2I3jkMfQSgyFMihCzguRCgjr2g8TAcX1KxaRyQD5NtelpY3f7juQo7RD3AdF
+hiZdjnCY6qtgQ/9ju/6dkWl2vNOVWQBLJ1aieo2o1UT5PiJXoMlKBbuYZpecyNRa
+bdRFkCoSybqi+qAZ0S39CBZQGuU7Une7xne9cXK+M05J8w==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy1subsubCA2CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy1subsubCA2CRL.pem
new file mode 100644
index 0000000000..669df318fe
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy1subsubCA2CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzjCBtwIBATANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEkMCIGA1UEAxMbaW5oaWJpdEFueVBv
+bGljeTEgc3Vic3ViQ0EyFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8w
+LTAfBgNVHSMEGDAWgBQRfcCcinb5STP3pIFLjjB1lTvoiDAKBgNVHRQEAwIBATAN
+BgkqhkiG9w0BAQsFAAOCAQEArE0ESZ1xjjGSyPpJ2Ru9aEVl6UtjKC1vctLfDCZD
+eLTLipnD0R6vsDscUna4h22okIeP9AEeLEOvpX5Oi0bVNhU0w6O2xP0Tc/Cfuole
+HgH4ZUJcKob6/2DpXLSayUNNL1zY8I/OS+lfsetIqOhp78xLiR0ghyeOagnkH99r
+a9eT9iCCUe/XO/N0gMOjsPkh5qOGC6gg9/XwsECc1BYf3HGzU10IC/C4rrxgrwQx
+YmpA+WDMQpEmDFXxect/9gARsgny4irJ0++2rFI1WdWKFEmMkO/l9B6GRYCjNQJX
+cS0JH8PWhv3DjvUoEeBIFDDJJwquskVZWwP6TbkfEqut+A==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy5CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy5CACRL.pem
new file mode 100644
index 0000000000..7c053d1c8a
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy5CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBxzCBsAIBATANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEdMBsGA1UEAxMUaW5oaWJpdEFueVBv
+bGljeTUgQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAtMB8GA1Ud
+IwQYMBaAFMAmgedp1p188L3VnapTDmX5nMsKMAoGA1UdFAQDAgEBMA0GCSqGSIb3
+DQEBCwUAA4IBAQCXIcfQLBFOcgt5m7Q9laH1FvfjTwZ1s2tC3d3NzBGRJRqo4lFB
+sb3PvwFL96EwopImZofRByNNmtdA1E6FS5dyiaDjOD8u9f02ZnL3PpAkuTTMyA+l
+iGSo7ZEvwYMPjWdtiN0SGLlpoVbTbAcUx4zjHOby1H6TiZcexSrf6ndRtYzR9I/0
+3jzFnqPcSIVQeB/gSrSWMj9j1gYO/UQGf6H8/YXadnYzoh7+C2lbwk27mpb0d8sc
+EkGJPa0iimLbKCmprPG5iHE0y6yUltjSia8fsubGfzNkMaJWsFepd/HMoXWC68hS
+0fI5vvDTIzHqFMAF6cZ8ddHMNbFA4XDD24FW
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy5subCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy5subCACRL.pem
new file mode 100644
index 0000000000..5c6e19906c
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy5subCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByjCBswIBATANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEgMB4GA1UEAxMXaW5oaWJpdEFueVBv
+bGljeTUgc3ViQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAtMB8G
+A1UdIwQYMBaAFGyZqbYF675wSTZMWJoi6BSIhS/bMAoGA1UdFAQDAgEBMA0GCSqG
+SIb3DQEBCwUAA4IBAQCfcJ8e+tup8Fr+n+Wg9FB/0V86blpBUsRvV6juNBKzuyuz
+b4iY4BZM1flYt9OF043DVHi7xN7BcQ7YGBal/day/v9GisD3Ia8qYdtyRCb0y70V
+6jiVJ1FVolO5New51aMcNAzmdCvmqvsj2KBm5y1zJmBwF+MeKrOk23kL4jOpX06y
+Yjfbs1xCbub01wBmE/t+rL/FZdFamC+uh3XfBUw6vCrDNvdtN31n522EV8I3ifru
+ByIJ7RgtjgeIDfCOND3TZ3i+OTEcn4XrMW+Y3BYiRKhLEpxrHkxNdgOK1ouC0HuI
+QlE/DkaDnw9rj6NnI9wlZTMCbmsSkn28VrkArw7y
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy5subsubCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy5subsubCACRL.pem
new file mode 100644
index 0000000000..793cf1291a
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitAnyPolicy5subsubCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzTCBtgIBATANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEjMCEGA1UEAxMaaW5oaWJpdEFueVBv
+bGljeTUgc3Vic3ViQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAt
+MB8GA1UdIwQYMBaAFDHhP/xiboBlzal5EAArbola6AXDMAoGA1UdFAQDAgEBMA0G
+CSqGSIb3DQEBCwUAA4IBAQBBNQhxoz5IzMcomKNxeSnmWdgwCCbynAR5YVIt4vqS
+zbN+H6DPt7UbaqhpgJTAedphGYOiVm+LYOehKXMYp6ZF2iHFC7yZ4/tbozh3hqY5
+5G1Zf2c2cXsCI9cI+uXB3jk0h1RgxaBRoAST6PS8HQJvUXM0T3QyApj2ELLjlvHx
++OrJ7XfsmOzliH8pfVdnKGzp2piSiJhdiiV/egX23AXvvQq5k3Tb0oUWo54BAso3
+2eXyypSbPTbxQXVqq4bjsVs/F7h0xgFRlwK4YPbmcpZqM1TXl0f8l/KqnFV+ZOmL
+aXghz7oTvQoFmJodMyzgWtvR4LRWnVj2v53K6AO/Jvrx
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping0CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping0CACRL.pem
new file mode 100644
index 0000000000..c709a56df7
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping0CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByzCBtAIBATANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYaW5oaWJpdFBvbGlj
+eU1hcHBpbmcwIENBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8wLTAf
+BgNVHSMEGDAWgBRYNyYHkYRgrO72QD6lK/z/lx2d2zAKBgNVHRQEAwIBATANBgkq
+hkiG9w0BAQsFAAOCAQEAvS17Fvl0x0lQNKsr9O7mk57ThTYOMkhSLLVLYCrox6vO
+B/wLW2wLJKrJ//n/VFqEGncKHNgwyF0tiBNhm9qEGp+LSbKwN/NT/ZffUmuer74d
+iUIQr7fvQYATGGY8f8a3GlQ451Wnw4LTOpfTfIOdH611ql5bQg9zsZsoamXa0WZ+
+Q9WLA9rT2AAQDWE+6jhD6PfhMZlfrOwfQ0oZJX+EDkiQ0N1BAhURxMxzflrWeedF
+nRHOyZrlIzqZ9rqaIaTcPkn3Q90fxREys2AgX59Fyp76iT3lsYpPWUytnt7e0NpY
+sZTGdW5W8/vh1jYAMhuBJNzTfk0Ilf71Le+qxQVFQA==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping0subCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping0subCACRL.pem
new file mode 100644
index 0000000000..50f92f4a14
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping0subCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzjCBtwIBATANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEkMCIGA1UEAxMbaW5oaWJpdFBvbGlj
+eU1hcHBpbmcwIHN1YkNBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8w
+LTAfBgNVHSMEGDAWgBT/tHNiUo1cljpakK4avLg8eYFjHjAKBgNVHRQEAwIBATAN
+BgkqhkiG9w0BAQsFAAOCAQEArr+kgBiRhrD9A0eGhC60oEuT+oe4x7jNWNet8W+g
+U6eESV36XCGgh37RfZtL6k40uiXm+WNM5Tir3iLaoUVR675FIWTn8deelq410jkk
+RTbEz8ikqYH/MGilEhLEfaYteQu8kqGETlDmFbmcjriRWulMGVOc7yKMIrKGRKWY
+oZXN+MB4zjkepwlJtef6ZtwNa+QkYENfLSu0fNu+MU+aqnwyLqsqNqV6paPViltB
+c47TqfXNtm18NtKDYjXdPgiLfmk0qZ+WSQK9mz2v2NSsHq7G8IeOYJ5BuaXDs3df
+fyZrzQxOFaaRNLor0m5T8HKIM4HtHVuLGioqQRGLyX5zUA==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P12CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P12CACRL.pem
new file mode 100644
index 0000000000..ec32a575b2
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P12CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzzCBuAIBATANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMcaW5oaWJpdFBvbGlj
+eU1hcHBpbmcxIFAxMiBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAv
+MC0wHwYDVR0jBBgwFoAUTWd+jd05Ga/oJt4OATR4sXUQ2qQwCgYDVR0UBAMCAQEw
+DQYJKoZIhvcNAQELBQADggEBAOTAmNbgjGjQ7urj0qwWnSMCHeyF9To1md3H2IWh
+CNZaepq/e7ALmIDr7viy2FfyNnmBi0SWz4b/3ddI+NhylyuhBX7b+hHIBcAbyuym
+ZprJeuNjk53T2KoUGrOUnRGAoUKY8I1mNrXb2oQ5+keKUevF1G4OYsjoH2i/YU/p
+xf9xMwd4fKjRZuIS62MMJBXOQgWPXu3q1K2U12M1EHJ+Uzm0vgYf54vL35Zczo1T
+42ue5Wkt2tFgiQlN5betiQhuXPSNoEcX54l3oRfo/QS2cFKzaQEYFrS4Khdy590X
+16eGQeXouMpeCARjGbBeUoVWa/qFm+40nOXtBftQOtUuGJc=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P12subCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P12subCACRL.pem
new file mode 100644
index 0000000000..8313d770c7
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P12subCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB0jCBuwIBATANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEoMCYGA1UEAxMfaW5oaWJpdFBvbGlj
+eU1hcHBpbmcxIFAxMiBzdWJDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAw
+WqAvMC0wHwYDVR0jBBgwFoAUqiaUHWQPfgW8XWCNB1f8cJVmbOcwCgYDVR0UBAMC
+AQEwDQYJKoZIhvcNAQELBQADggEBAGhzR1y9MeY8/io6ssFZCHWXI8r8OoPogUgA
++Zmv2YJAGwg2FY/ID9nYmyntsT1bsAfzPubQJJGsg6+izEwcjNGaq9S8W2doUJ/5
+LQVpPBYydzpRm9CkW+YlpxTdYxlXLJOlZOxQbAob7dUdViUgbu3bVQq0oMlgjz3z
+uMwHv4yp4xOD45CQbwALHVAoVkayZ6ESltquwQBSOaRATkbTRl7BdNcssrh9TTMS
+YYhcnWHQd4e1KWdJLb8ZSgYpAAoLLV+4QSR3B64O4vy95xwcG71puEs/RLDgW7MY
+pEnbOsL1TDq7ZjYfAHyxFXZKe7XEFknnu7A5cNjoSr65szamIn0=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P12subCAIPM5CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P12subCAIPM5CRL.pem
new file mode 100644
index 0000000000..3d86355fa7
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P12subCAIPM5CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB1jCBvwIBATANBgkqhkiG9w0BAQsFADBcMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEsMCoGA1UEAxMjaW5oaWJpdFBvbGlj
+eU1hcHBpbmcxIFAxMiBzdWJDQUlQTTUXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4
+MzAwMFqgLzAtMB8GA1UdIwQYMBaAFB0Ez3YnB48iO8L0gi7u5t0TgHtTMAoGA1Ud
+FAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQCT97ZZ9/3xeVKS7ylodjmyfxLqZ+7V
+iezI4cQFmH7cWThgfMefgj1664LrHOuiY/4bhvk1LHQj1c5pFbUYLc5hprEiv3dn
+OJejWo7PxTY47hkXIntlElUyYb/mxUPxiklQ7FEbE7RFSOTi5MZNrHgd+JITUa6x
+jPfDI0z/GO/Jo4RPZos2Iu1hVLN++sU8iMVMe7/sIoOrNw/lwudUfo+cZEKWi7xv
++1ICLtnK0XoPBTxNzb/i8cOZrjggiKole9mFEAZrs5P5dfytRTVFje+d4Aj6lYr6
+4smUCABSDWhLcyI2OLIt5taw1BigwfOsGvjMsRVgRuF/3U3LRHf+8o1M
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P12subsubCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P12subsubCACRL.pem
new file mode 100644
index 0000000000..4c8450f3b7
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P12subsubCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB1TCBvgIBATANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTErMCkGA1UEAxMiaW5oaWJpdFBvbGlj
+eU1hcHBpbmcxIFAxMiBzdWJzdWJDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgz
+MDAwWqAvMC0wHwYDVR0jBBgwFoAU14BcE4uOQXa6CrVzceijQIB0DtEwCgYDVR0U
+BAMCAQEwDQYJKoZIhvcNAQELBQADggEBAB8d26fH9sOi6DPVWkJSNU1UltmljVsq
+Z9FBaQQxT+XSQDuAxW3VxeL55+/62jWO/O8/xvfw4egnAoTjtDfOrHFCEk7AlIgX
+vdGeXe7l4sHgbaq6l/z4EDsQU7SoukhtrjUVUTz7ksLjJwraVbBc8Kun/Umpj2sc
+ZEFrn/PMyibfXkeJ5aWTosLuEyKBag/Ln7hhl4nN6LDnafj+sxvhIlPGKKE1B66S
+h+wbhxZ6QvqOGfdYlcjRwXpdRPiF2/DJApIjF3eV7CkMM8tMo0myD+xQWwjPkNPw
+29n2FmWxfSmGBhbRkJ/nPGid50jCG/1UOrtN9+pQpRS3Tpky/zFtkvo=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P12subsubCAIPM5CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P12subsubCAIPM5CRL.pem
new file mode 100644
index 0000000000..2ed760a1e5
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P12subsubCAIPM5CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB2TCBwgIBATANBgkqhkiG9w0BAQsFADBfMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEvMC0GA1UEAxMmaW5oaWJpdFBvbGlj
+eU1hcHBpbmcxIFAxMiBzdWJzdWJDQUlQTTUXDTEwMDEwMTA4MzAwMFoXDTMwMTIz
+MTA4MzAwMFqgLzAtMB8GA1UdIwQYMBaAFBKHGzVn8LyhoDa6FagpGe0am1twMAoG
+A1UdFAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQBRQeh+mh86ONreRF9oNGE+z0lr
+y1ZYBiri/f8kk7y1GbwNB6LG+M8Fve7pe8pvtawSMfGnEbaHqdOf1jzSeOQXvSBb
+htuZ+DO9kOVDRyysBLNDWTSgA7BC/MI0JwrHnUMq6twutmQ0aPe0hHZu3DdydeRt
+ncUQ6qa+dNiZ2RJCpcXwKcGPLJnafDpICui8VPRJKgj4bcdtpFICoCmnB3iqbLKe
+9s2XyNtHxfJPOW4HSASB82rWcTzNA6Px0FwXm+8TKpkopS1dlZ6cd/nYhJCj1i26
+wxRDAx634CAzhWoGaYtrE2P5epcOEnh4G49ybfPmua8RWxTyi5CvhBhtrtXp
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P1CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P1CACRL.pem
new file mode 100644
index 0000000000..f231fe784a
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P1CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzjCBtwIBATANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEkMCIGA1UEAxMbaW5oaWJpdFBvbGlj
+eU1hcHBpbmcxIFAxIENBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8w
+LTAfBgNVHSMEGDAWgBS+tp29KX8aodmL4aSAaIMorUrwATAKBgNVHRQEAwIBATAN
+BgkqhkiG9w0BAQsFAAOCAQEAUv+vJlKK7TKlyO/T/yrf26BwpHa6dJHReqjLh6e/
+iXSXPSDXvuDrj+uNAIL4o8s8X5y7h5+ivYEDyZi2lnrCsj75+IuJIBfeHnfdeCo5
+rsa2Hml6bhJX0OuZRkMlg1qDMYlN3EEqcpobXWd/TfL3RB+vw/V7WwC/F5vx5UkT
+mH0jpI0glDOOIaQIDhgXerdEMuZ4FpSdAiUtj6icPYmbaGMY+We8X07ztyv2RQsK
+frTxkyAHRM8fC79LlQzzCvTPcV9wkwKteKMY6ZzWsOfp1B9DAyK6wq2Lp+TqbJqh
+pyL/lPhKASzGVegUqAOczdo0rvNDCVIPu0gCk5PgjcpieA==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P1subCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P1subCACRL.pem
new file mode 100644
index 0000000000..3730e7c738
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P1subCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB0TCBugIBATANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEnMCUGA1UEAxMeaW5oaWJpdFBvbGlj
+eU1hcHBpbmcxIFAxIHN1YkNBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+oC8wLTAfBgNVHSMEGDAWgBTzzQc/gzDTxwJi2ubKbAGlsbaAyzAKBgNVHRQEAwIB
+ATANBgkqhkiG9w0BAQsFAAOCAQEAAuGpcOqakKHpoO5Y+E7QAQnB1fmAm4smN7eu
+RNXIdrZaVd24C1BbFzYAnjdewBVYT4adCdnslaNe4tqpq3Chh/YtmUe152/GTiXF
+MVbo5FRZhjSvK8VTVEzvSZ21b3oiqIv5d4P47XmhVfo0GtTv7Rg+x+ay8dGUgni1
+D153LEBh9beouesqqxn/8uFfxYpqmxFrS8vLdL9kxpeaFX32bM0eSOhA3lg4oCfm
+j28x6yL57beJMHjFZMN5vAXTZHZKeJS1QXak2Dt21G3VKPyq3v7iY0GDgLqQGsIp
+vPsv+nuvwdTjcQPwsMIQjZBrq2woAYvlF5hx8ofqoLNW6/oV1g==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P1subsubCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P1subsubCACRL.pem
new file mode 100644
index 0000000000..6bb1b2a960
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping1P1subsubCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB1DCBvQIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEqMCgGA1UEAxMhaW5oaWJpdFBvbGlj
+eU1hcHBpbmcxIFAxIHN1YnN1YkNBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMw
+MDBaoC8wLTAfBgNVHSMEGDAWgBQ+RXSii9LxVoxGAWZ4cCTGIsEDnjAKBgNVHRQE
+AwIBATANBgkqhkiG9w0BAQsFAAOCAQEAdMziQBhDzdFRF40rOtd55OD5MPOXWPRb
+5i6KUQcwxrHZ6xZibEhM/eHGtHW89pL4Jjzrwbp+SXz/OzJ6yU9Cf3PQsP3a7l87
+J/EY+KL++6g5V58wlaXZYOvO8v5WTSFGP6NUvg8Nq2SChq3KqVvKxp/MrFSckP74
+gd2jepabJyTeXajSMManT+wxxTKG8WKMQtiQdXclZmEgaVYgxKVgIJudF46yLEh6
+gVwhKAR8xdIBr/mztrcM+aQKvdxtz3aHuKNwm+lo0tSjxB7UojZvIMdd7fuc0V1E
+PEVJDd2+Eej5s071zlgMeaahFbVeBNgaQy5rURdHxtyMZukFdCW5aQ==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping5CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping5CACRL.pem
new file mode 100644
index 0000000000..68d33d924f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping5CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByzCBtAIBATANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYaW5oaWJpdFBvbGlj
+eU1hcHBpbmc1IENBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8wLTAf
+BgNVHSMEGDAWgBTbgAe5YizFw/3zQ+JmUSW72/QczTAKBgNVHRQEAwIBATANBgkq
+hkiG9w0BAQsFAAOCAQEANZI64pJVPbGyUy9hrPD2bO0EkxlY3aJHxDko6PaPdQ86
+dFjmX8tTCD0vmm8Hox4bI8fZHbjMDqhWxLU8NtjNJLSZX5IY7SJaaacDGaRd6laP
+05hB5MTLcEKBxH5FIetoK93e8mf+rMVRG4kCmn/UX4notzBcX0x0qKoWd2v9v2QH
+Gx7Gr6Ouae8wubYiu7aR9fCYRIcllEZVFRQ9f0bB5o4NANAUM4uq7ZrrqSRauqN/
+iNxCEeKSVnItuZnAZXpazNmXwSCdWPiRSl/77tThqoBhGKsgOvNbwJaTKJIuJ8HX
+5HgiQiSaz6Y5GySbA6rFemmW6X6o49/CiJr8cI+fKA==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping5subCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping5subCACRL.pem
new file mode 100644
index 0000000000..7925d0d1f2
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping5subCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzjCBtwIBATANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEkMCIGA1UEAxMbaW5oaWJpdFBvbGlj
+eU1hcHBpbmc1IHN1YkNBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8w
+LTAfBgNVHSMEGDAWgBTY7G2+t2/KE2PKJ8ycW6JpNrbyaDAKBgNVHRQEAwIBATAN
+BgkqhkiG9w0BAQsFAAOCAQEAOYCNoa/mt1m/IQNy9kCVeCItblOzMyiCcng/IMCd
+RQ9q7kAa/nPj/zINqGAM4GUY4yB5wHm5zVKPL/AxC4adae2Xg5o2XqJ9rRI9bSgJ
+s48iHWbFp8mU2H5Wbn/hVKSWWCi6XzP1N9QwsFJa/5nsgRDzp73VHarqIPUBahtA
+mYLPo0bIg77oHPsXYmEI+aufY88+IMtVr4iFIW3ifEQu/XbmfwNjQLopIHBn3E0+
+gyD5XDJeF5f5C3FG9vQ/3DSgrdN2DLzWHr3/dWNIkRWhVxqimffMjYUkuxi4bKQ0
++30q3zclNs0lOr240CPBkg6Y39n0Zo7ihxBoS5INvbTi4g==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping5subsubCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping5subsubCACRL.pem
new file mode 100644
index 0000000000..2fb83ef408
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping5subsubCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB0TCBugIBATANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEnMCUGA1UEAxMeaW5oaWJpdFBvbGlj
+eU1hcHBpbmc1IHN1YnN1YkNBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBa
+oC8wLTAfBgNVHSMEGDAWgBQ1p9ThS3ROVahxtEJ/Mv4EGskBuDAKBgNVHRQEAwIB
+ATANBgkqhkiG9w0BAQsFAAOCAQEAbayhlH01G0sqNxiiUyC8qPsdhUF3mHVEhoqz
+2SOwTTDzqCTLyqftFnZPAJ9fbG/FN3Denqr2ouh1Rl2mPEG3KmBA/w6gRrTzxmS0
+pC8UsBWdRvRebGZ29WJEjgslUz/r9BbSlwabF1dsAssvmv9xPxFBql4uNrLOEfap
+M9Ldo4y1eiBWd5xNTYp2zu+oBOAgywJggc7xepoUhwcPCTSrcAqmsQNLBoMYcf84
+nzm8rJ89cTqyPvpLxKjjgLdquVevhCcIG9HSCmAbb1z8SKhWaaBjRSoLmAo7845M
+VoDabAd0zNq9DEwb9WHB0zZldJ+u4LJtAAEpdl1nc2KqMADUnA==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping5subsubsubCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping5subsubsubCACRL.pem
new file mode 100644
index 0000000000..ade3f19453
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/inhibitPolicyMapping5subsubsubCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB1DCBvQIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEqMCgGA1UEAxMhaW5oaWJpdFBvbGlj
+eU1hcHBpbmc1IHN1YnN1YnN1YkNBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMw
+MDBaoC8wLTAfBgNVHSMEGDAWgBSuY8vX4sNx4/TObvw19JvSTT7cFzAKBgNVHRQE
+AwIBATANBgkqhkiG9w0BAQsFAAOCAQEAj0qjzBDkME3FgINy8gUWHlUGBpgreUMF
+1IqXG918JUeFy1vfkDdhwmg9ln2GjMquqb6J26L5mgH0EN4qUsfRZtcLHTEnMXt+
+MSKI8xOWJrid//uFlitbPPNdppvovBNSAZroq+uZLd+jDxKfiPOVlrIkbbTQvv44
+YAGrkkdsmrxSxWwrtXdLIURmW/D9J5uRkRqpMVvikD5aMLGQEangg5MO7ZLsGUBL
++mdA7YDq+RMG5F0TVoKOOlhOZhAxcgs+RMCZdJKWxJd6/gu5opHeEuOy5KShVzUW
+ABXNyqZXT4tjAjYW0Z26urTv8FeBoRoJC2Kyozm7+IR4m/H4/GaJMQ==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/keyUsageCriticalcRLSignFalseCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/keyUsageCriticalcRLSignFalseCACRL.pem
new file mode 100644
index 0000000000..4993db248d
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/keyUsageCriticalcRLSignFalseCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB1TCBvgIBATANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTErMCkGA1UEAxMia2V5VXNhZ2UgQ3Jp
+dGljYWwgY1JMU2lnbiBGYWxzZSBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgz
+MDAwWqAvMC0wHwYDVR0jBBgwFoAUwspp9bSvEy30nPIRVcsqMLPSWkkwCgYDVR0U
+BAMCAQEwDQYJKoZIhvcNAQELBQADggEBAJk/UxyWvcm6kbidRgW52BKoSxXcHpfW
+896BFKl4iGUzmYA8GanMvM9EkEoeqjrHdTABcPE1Mv0lREGRYZv9H+gD6iAnKctc
+8G74C8eYkvcdocWAixuvDMyZ+D+TxSCOo04ppe+HraHgEQRy2sgobIYdqEY6XcyS
+X0areuyMQPjqbTdOMFsTrvtSew034Q0zSoKsPZhxfMQ6zcx7JKqna8HzCO9LCZag
+r5+47Bk470ve2Xy5FrPk6sWJQal0/YHOAKKnnXoXitqst2A3cYiWgRAqpDMz2yMH
+zdtJKbBsIieZGgQiedwXDs7aKWzN5o5sh0ALyj17bbHyMrs7gvyiGvA=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/keyUsageCriticalkeyCertSignFalseCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/keyUsageCriticalkeyCertSignFalseCACRL.pem
new file mode 100644
index 0000000000..8a9a50b563
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/keyUsageCriticalkeyCertSignFalseCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB2TCBwgIBATANBgkqhkiG9w0BAQsFADBfMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEvMC0GA1UEAxMma2V5VXNhZ2UgQ3Jp
+dGljYWwga2V5Q2VydFNpZ24gRmFsc2UgQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIz
+MTA4MzAwMFqgLzAtMB8GA1UdIwQYMBaAFDRVC2f8HLHcwnIKFPBj6dSb8GP5MAoG
+A1UdFAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQB3bfisM1UBugxKYYdxZkYgpRvs
+rh8UEjPVD8z0t29+yeyiPm4bFmTZI64VNvQlcl/Jj0YdcqkWGEKdH7RS79lSQhBs
+piAcYQcdS9WzaZ1tFNG/Fvxo+MkksrQ+Z95rb0vvB+7YuTIVWqbHcJamCgZ4h+Pl
+XTUQgHedNzpPKisiLF9y32JbDJ/nnrec9wEpMn7z2Yhb2vDWhdtQoYMTk4LrMOSk
+74Cqfpuy6JEaymDfdmrIIx4JZOfmo9mQcgeN2WoV/4YYaGGL3T3Sk8FqUaTTdM9Z
+iRiqzBSTOfl4VF4e3S1ZTDv5JH0U/HrJexLhgdi3xEpE4EQIZvXVsZX6I8rn
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/keyUsageNotCriticalCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/keyUsageNotCriticalCACRL.pem
new file mode 100644
index 0000000000..844a745e39
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/keyUsageNotCriticalCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByzCBtAIBATANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYa2V5VXNhZ2UgTm90
+IENyaXRpY2FsIENBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8wLTAf
+BgNVHSMEGDAWgBTBkBFK2bQrxXB+zow7Yljlu5crczAKBgNVHRQEAwIBATANBgkq
+hkiG9w0BAQsFAAOCAQEAgK5IxkJ3u7pRpg/BKAlwCJPgj4SrjTrLeu875hsUvEfv
+mMzLN50lGQpwuuH2oaQ15Da+PGpzng6Ao5MhMt3vTqU+Yp5VQEnBIsGED0lTJDHj
+pDyQpS2d4nhdYyPrHQHJWwLoGaTBPglYqc/vASXq862RiNKywdVX4QFj9IXXUrwI
+wQ7d5uKirZUEkInjJCdVH8ryJfo9fLRD4kb3OkbO62e/HHSJO2DstQadNweLoLCM
+hhJlw5KkDXIBfQvq5pPrI76dHY9VatsnqKRkt1CUE4MVk0fOIqci2Nz77LdTsFre
+Pfe0WNoqSJpoGv4SfIr7v8Uw83bmO3Yy/enh3p9J9g==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/keyUsageNotCriticalcRLSignFalseCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/keyUsageNotCriticalcRLSignFalseCACRL.pem
new file mode 100644
index 0000000000..e0fd7bfd8f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/keyUsageNotCriticalcRLSignFalseCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB2TCBwgIBATANBgkqhkiG9w0BAQsFADBfMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEvMC0GA1UEAxMma2V5VXNhZ2UgTm90
+IENyaXRpY2FsIGNSTFNpZ24gRmFsc2UgQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIz
+MTA4MzAwMFqgLzAtMB8GA1UdIwQYMBaAFPl+UqB5ZgQIRAhleRAO3ZDmQ/HYMAoG
+A1UdFAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQCa3FLqxtdS2NeSwWMvuticdJwe
+M+xS0ZRf30G+WsPtmoRnb753WkhlJZZcglilAExrCN9BIMSEpO/UgyXpjDj7GUri
+F9QHfTdIT8QGKcZMbx/nq29ge/fdjOIkhXnBktQy5BfB8lGkYwNs20NuFpL3FaUx
+IvruMRR2AyivlndK+xcz6s2j2v1WYXlvZlFNAAHVmXR8+67zbU7t0WIN7VlkTyTa
+0mxanuASRP5FmlT+Czr6N6OERlBTp1wnvlq9BHeTGDXQp1oXu8B8sTsQHTMbuGWH
+FqGDZpZJL1BsCMuXkBk40b6b57/C5CvIy7SfX9xnvKmJs81C6910qBITMcZI
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/keyUsageNotCriticalkeyCertSignFalseCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/keyUsageNotCriticalkeyCertSignFalseCACRL.pem
new file mode 100644
index 0000000000..d7877a9b68
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/keyUsageNotCriticalkeyCertSignFalseCACRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIIB3TCBxgIBATANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEzMDEGA1UEAxMqa2V5VXNhZ2UgTm90
+IENyaXRpY2FsIGtleUNlcnRTaWduIEZhbHNlIENBFw0xMDAxMDEwODMwMDBaFw0z
+MDEyMzEwODMwMDBaoC8wLTAfBgNVHSMEGDAWgBSyJdIoMNBVaG5MtcJI88qbFfJA
+RTAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQsFAAOCAQEAtIeKFZV9BB4OBq63soXU
+rgYDlsozbj5cYoU86vXpmHddbTowwaGtFlqbfg9deTqT6r9IpdIClfZtJVT3s3Lm
+PFb/areGyQblwYuOD6Mldtdty0FH5A9uMMMCEk1iZD0Z8WApxo1bomtY/EI+ZHAF
+N9+xTE7DZtHIOSZ0nyz64fHMPDYQPDGtkK2QQ6nFNX+ljnPOCRBfwwAsndlumWRP
+SlthF8gU3A8008ytHdpkNEsUhf81ntUy4o2pftmjQOnMJT0C97CXykxZBc8f49A9
+QKsI6ql/dt1XO9hNmVp7qamXA7+yhBwfWAKnhXRQn5D64/ZqVxE9lYL7PvJrr1tM
++w==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN1CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN1CACRL.pem
new file mode 100644
index 0000000000..c999bf8b23
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN1CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByTCBsgIBATANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNvbnN0cmFp
+bnRzIEROMSBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0wHwYD
+VR0jBBgwFoAUQXhCRs1OqILn4Tnf96kWwAr874YwCgYDVR0UBAMCAQEwDQYJKoZI
+hvcNAQELBQADggEBAFtcX7FztYXgApU6J1ska8lB9xinzLv+LkatWBtqZuRZ8yYU
+LLgGDlzgHX8d51lkdXrlTe3iW6aNmKTFznTRqxPGLNA8VikBmBhNLYGgk0u3HTQD
+hZzWtyLOa4FB26lrREAgvEC7P5TB0Xd1p72E4IwKf1ZV7KOiTpw7EmHLsSWYGcDr
+96mwtkUK6g//vxJnIa+k7C9jjQboCmOyH0HSluB0KQYqislhXHO3BSBxiXVhHec5
+3ToVLhmo/v+3fgl8wkEO2RH9MRcx29+JiRrqLr5xYZy3sKKBX/7e5jT0PQsKFOqI
+CKt6oFNRwz2qzEcbHFMyoDR2+5R8zA8OHCDYf54=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN1subCA1CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN1subCA1CRL.pem
new file mode 100644
index 0000000000..3884626320
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN1subCA1CRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIIB6TCB0gIBATANBgkqhkiG9w0BAQsFADBvMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEaMBgGA1UECxMRcGVybWl0dGVkU3Vi
+dHJlZTExIzAhBgNVBAMTGm5hbWVDb25zdHJhaW50cyBETjEgc3ViQ0ExFw0xMDAx
+MDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8wLTAfBgNVHSMEGDAWgBThOA4UGBRD
+XM7nS2LHGsGS9maC6jAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQsFAAOCAQEAL1Mn
+Ok+7QkFamOzoQfdBznGodtPDmg30Cgk3VHY7mAwg0VzRhhTaUHjMrmZzpyKuNNU5
+of9K/maIKludVfLuV9NPmt4pTZWW8l02umkRg/vbAIfPGWpUhev5X3V6f+Bn5bbg
+UQvEiuFQvJzutxukSCkNzijr698Qa5qEu1HzILhO1gQxPhufrfjHqQ5qxAnJiVkm
+uOFSP/OBfuuDg7HS8kCAkzfHrtweRwrrtGf6AYzVZO/+pc7OMOyUW+kh0oXHY60n
+snh7NPi/PNGb4RANJBcQhNKHMVY23eCcwylCnfp7FfuNLSAj55aRvxvG3Pn+WQ+t
+UqzAs79/UBMKcj1IWg==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN1subCA2CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN1subCA2CRL.pem
new file mode 100644
index 0000000000..a39dd31a35
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN1subCA2CRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIIB6TCB0gIBATANBgkqhkiG9w0BAQsFADBvMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEaMBgGA1UECxMRcGVybWl0dGVkU3Vi
+dHJlZTExIzAhBgNVBAMTGm5hbWVDb25zdHJhaW50cyBETjEgc3ViQ0EyFw0xMDAx
+MDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8wLTAfBgNVHSMEGDAWgBSiL1iDW0yV
+l7fu9oe0lw7gf+CXFTAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQsFAAOCAQEAyDcs
+pkncHaUX9Ebs68OGd6Vbz7PAjZ/cnQXN6ZzCf1HVx8vtldilw0xP7L6LA1z4/sKe
+5AglNKS18TrC9jvMcs5MPI8g9jNPpmzn4tVGJiISlft8SqKPL9dvgUCODtIj+Vqv
+x5ELHuMRwAsj7vXY6FrgTwM4eTwEbRhYCxM1r05VPj8t/fl5XoNR/4vaCmDYR9uf
+JscXoSlBsXJkPrkxHnrreTiSNtP1iAiX6CXOBctSfPzhrZknzWq76UYq4LnQrqNo
+gyZ1pc46+f7RqxgGOgn/Nb6AqBy+N2vpYXabMKmNpIBmpOGq/qonbtPF/zJbj+fc
+Bafk7fSWIrCNZg0pFw==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN1subCA3CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN1subCA3CRL.pem
new file mode 100644
index 0000000000..7dc7ee7fd4
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN1subCA3CRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIIB6TCB0gIBATANBgkqhkiG9w0BAQsFADBvMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEaMBgGA1UECxMRcGVybWl0dGVkU3Vi
+dHJlZTExIzAhBgNVBAMTGm5hbWVDb25zdHJhaW50cyBETjEgc3ViQ0EzFw0xMDAx
+MDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8wLTAfBgNVHSMEGDAWgBQnSeQE2UX6
+bJiUbPztDcMkUm1VRDAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQsFAAOCAQEAuEeu
+G7nwSvVr9BxS9bMPB12xdegiBpg5U2K0vTD1JSSOR+RQ2LvwpJlkNy2oFt8+sbAi
+oTCOgifKXzi0tszHRH8vYcKy+DJ/RE8mX214KIg5Lj3DEpOlzPE19/z+eUl41Pbw
+sgnQTE+ccm2h4GlUefprR8PSZdOIcqxbDbapLHC9vz1Dy1YdM5iySa7YJ7Xk4uDe
+NtysCgwKtANPKF/qtbYQgcZxGPYArrWprgK2xyMBeux7WTQp+9xaSOU2gUmAKwzj
+bt0iV6KEkoU08FmUwzXTxX1bBsjLyIeRFPm58XbJ0MxgGdJPmMn7m2W4PPeMJpGD
+vH1qhNYwy4NsWosCfQ==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN2CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN2CACRL.pem
new file mode 100644
index 0000000000..d32449cf89
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN2CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByTCBsgIBATANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNvbnN0cmFp
+bnRzIEROMiBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0wHwYD
+VR0jBBgwFoAUo1fZW10Rs2D2AGuJUSuCwwlzqHswCgYDVR0UBAMCAQEwDQYJKoZI
+hvcNAQELBQADggEBAAky6btWTahA//H8vhr8u8hbW8h/OWD8skXuVJHLv0LdS2cI
+zzk3f1u8vwWaohmjsIdNllFU2hd3GH62mJdoXJflLxxVDm47FWdzmmlyUsxFXojL
+HI+tjwBFmSzzzd/t7GeF5mKc11PrUz9oqoSJEZVCcYQX2px2xJIzmqOkc4VWGrGo
+rIvTE8SETRWTYcE/IDOxc1lSs4KyH/MGIwMeN6Mu3p3d/H8ygXKEzf7gYR0riFW7
+ps5wlQRxDC7ICktp4f2bN8l7pw5TwjCfNmzqDbW9IlDFaRr1VUV6hpPwORT9qWVQ
+7ZbDXVLZwaWxGmp8vYh7weNKgrmfibuz/DcHqPg=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN3CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN3CACRL.pem
new file mode 100644
index 0000000000..a72350793c
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN3CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByTCBsgIBATANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNvbnN0cmFp
+bnRzIEROMyBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0wHwYD
+VR0jBBgwFoAUBtxbvscSN1mkikB0fAmdRTxKodswCgYDVR0UBAMCAQEwDQYJKoZI
+hvcNAQELBQADggEBAItPJiJOtxXyscdSk4LVnHx2Ge6LLKaoPE6qXi5JRs2t4LjU
+DJAh0bKPehBDlbvqpV6/e8pqaJP3T1DH28vZTr2gGY/Ar4BcVSzrKO0jH7j2PJU1
+Kzq68kP2/tr90XnUOuz5589ORJ9aryewWxJ5g1w5GqD4dC8NV5aDWPWAdnxVw0Dn
+DVvJl11dzlFqaZSwuDIj0IjzssosDmCrPDUjLDLn37f35XRIX7/GB3ghSrUJLsId
+TrU+ROvpQ4iO9zAVMDfQOePSnUeNpO4Sr/as3lHaFptwj0tY1PIeLcyfv8ZNZYN5
+7Q8+aKRQMPg2ZHGeF0d9ADvGLZTZ2vMCK/hHfL4=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN3subCA1CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN3subCA1CRL.pem
new file mode 100644
index 0000000000..c179e730e0
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN3subCA1CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzTCBtgIBATANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEjMCEGA1UEAxMabmFtZUNvbnN0cmFp
+bnRzIEROMyBzdWJDQTEXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAt
+MB8GA1UdIwQYMBaAFIC8xy73jhp/8Th79DXr3elYxjxQMAoGA1UdFAQDAgEBMA0G
+CSqGSIb3DQEBCwUAA4IBAQDKBu+BE4WjUUs1+SbDPdTUvtI61Eo5D0f55tSFFzqY
+3mjQN51xcisMQIFvf9dPdD7/MOUjS2GeSG7CgPObXBVkhjsNzNhgUdk7obAAuQNo
+7pj0c+Kp36GKHgSzMmOvzXOpe0OcS0iEJTqOss/+GD+a0kPUQBTQptEFJwPyDdKZ
+yIpuXbmhEtaXJVEq/fIkQLtHDv6VqsOCPDyyca/NP1J2Ed4zEHcP7w4wTcxhCkq1
+duWazm3Bnc3Qu4lIOHUP1VGum+Q4cLzFzNlWCOIaWqCVwQvywAADhy4E/mxHtGAF
+8s55z3PAJfeRKySqkJJtPI5qRgllB+n9b/HxD7DskHy/
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN3subCA2CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN3subCA2CRL.pem
new file mode 100644
index 0000000000..4f416b3ab6
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN3subCA2CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzTCBtgIBATANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEjMCEGA1UEAxMabmFtZUNvbnN0cmFp
+bnRzIEROMyBzdWJDQTIXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAt
+MB8GA1UdIwQYMBaAFMwE7WooHX7eZOoAiCrsdRG/pS5nMAoGA1UdFAQDAgEBMA0G
+CSqGSIb3DQEBCwUAA4IBAQBSQba9PCeM3gDcJ5/15bCZXzS1J88gi1mSM00AHLmm
+cvaM3zC1dupZ3+nUGrGuJeSy9gJvKmRvCGQJVVScbWaJSBCLsE2OTLQZosIbktpA
+SMDnJNCgEQMqL3S8I0U71qD4gw/f8DoxBloqVyzuwIynWZl+V9agP5UCWweDpo3n
+zqfqm4zYF2gZYgVz53l9/zYpxr8e0d6o/Y2sqk6ykbzR1e+Yw8Jr5AKs8awilABf
+Lu5pl0DO/pFtT1cX7MEtd1aoxZqQxssOS0JlosEF66VMeOKgUw4uvovkbjP9zfUr
+GfwYbvUJZ4XSDy6p68jsQKRpG7/v6V6Xy4LcZ+4I+ATD
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN4CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN4CACRL.pem
new file mode 100644
index 0000000000..bd4472556c
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN4CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByTCBsgIBATANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNvbnN0cmFp
+bnRzIERONCBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0wHwYD
+VR0jBBgwFoAUbEk2rS5YiRI2UUE7VFImJADTynUwCgYDVR0UBAMCAQEwDQYJKoZI
+hvcNAQELBQADggEBAH6NXW4G6VFh6lalxV0HfwwV4W70J+q058P1U/nVsOOg7s46
+v+bhzKwJrIovS+fGE+WmDCMbeeIzvmMnkF7ZSGmZarmGDzNGsxghmiNHW9eP2Wk2
+7QjyePG/cAff8ILOqzCHw1WZMtIgyVM3tQY492xqKPRTBac5P5DN6COtBGzKsk7O
+mtOvhcqtwMt5ejXil9ibRhAKHcgoNtzOoZoaQOvTajOP0vdFYnHHkF+bFDd+lxUE
+IHgX9IOmk1xGFgdEcSpQL+6mvV0aKk9iavdbVBQCeWzul24GRr21EVO2emR3oceI
+vBeEL509yRgDMZoosPcUPzU3MCre4KHexkxNGKg=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN5CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN5CACRL.pem
new file mode 100644
index 0000000000..bdb12dbf59
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDN5CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByTCBsgIBATANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWbmFtZUNvbnN0cmFp
+bnRzIERONSBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0wHwYD
+VR0jBBgwFoAUup8JypA5nE53Wuv7EJWs06dKXScwCgYDVR0UBAMCAQEwDQYJKoZI
+hvcNAQELBQADggEBAITmZi9ly086wq/MHAGjaUYsma31grAeyveTU+oJ7olEb42/
+ALSN0DXoO4UjV1bj/wiIPtErg0EjHWqVW4M9ID8ZdfDuXBLNBQ2NP14gJLjVTk2H
+6iHx4QK9QiB1gVdfKbj5+lTCt+7YWZtOWovr5SIlPtbNqszR1gpTLaLyIkT1FRg0
+txRaU4qTZmOIYCuWGEWeh0F9xHAZ4d30j1KcBSdHzOL28ibTjgDsYQF1680ChYu6
+TMUWY6q/ufziFDezkXkrLrtNWAwYZvS4sRynpbrhKUL+CldFK/u96ZZwL6T9Nkkn
+aY1gGgepUvLKlQt20+jmOu/L8Va7xcXK+AtuQQI=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDNS1CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDNS1CACRL.pem
new file mode 100644
index 0000000000..33e2aa1407
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDNS1CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByjCBswIBATANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEgMB4GA1UEAxMXbmFtZUNvbnN0cmFp
+bnRzIEROUzEgQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAtMB8G
+A1UdIwQYMBaAFLGqF/Djz8zSp4mmgwfd/27aB+NJMAoGA1UdFAQDAgEBMA0GCSqG
+SIb3DQEBCwUAA4IBAQA16Gsjfh0eCk00xbqXxGjwPJCTmNcQ5BQRATn1KHZNDm0l
+HSuZNQELk9z/M1jw8rEArioWWkLQEKdVQ8WtjFYYYcj7VTo8aho763/UhY1WBQQF
+ISHqASE4ygCUcwSKus12Ksk+NXvvARlv5EG/UqoSAMx+6t0VLuPteV5JtXaAgABC
+xXScnAJvH0BZJWDXh8x9TCocXxmH9SsZhgXM4WEZxRch1Z3bxLd3NrxztPXe8h7H
+9Lvp/TOEvTdjtbBn0kwomw1DCVeJd9DBNXFO5YvXyDBU3usNmHNMk0wri1roJzUg
+UrnYLYox1O/52yeQdQiSAkQ3grctmcBcJW8WaIWu
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDNS2CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDNS2CACRL.pem
new file mode 100644
index 0000000000..02b8226a6d
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsDNS2CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByjCBswIBATANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEgMB4GA1UEAxMXbmFtZUNvbnN0cmFp
+bnRzIEROUzIgQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAtMB8G
+A1UdIwQYMBaAFEZInEIJjl1TcNgWHuDByRgVNQoGMAoGA1UdFAQDAgEBMA0GCSqG
+SIb3DQEBCwUAA4IBAQAmhkWLOOzNQKAS8uW774Ig/r2A1dpM2sBujFbCeg9blw2k
+/qRHoInFtwM22vgIBInC6EZW8qPqzPeJpjIluu02T25EjxRFGiameUbHQ02XAejf
+thhUnDw6lWF+N/sIKYXCkN6TuiKC9m4LPvlmI1JC1RqGWmZIsl59ae4zV1G0iyMy
+ol7WhsPhzsQj8pRACFdznwq0ehd3L8UO43BHl8+rXVzS6f++filZ2WZHPFCR5Nq8
+l9KaNhNCE7VeBQv7dElPeknvANPEGomeXFIIPwCx7Ra2mc3mjG5qYwmX1JYjPxe4
+siLRqgKc8s5vwYGwwPqtoInJckVUxfkZ8YAu5vTI
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsRFC822CA1CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsRFC822CA1CRL.pem
new file mode 100644
index 0000000000..4b594be896
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsRFC822CA1CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzTCBtgIBATANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEjMCEGA1UEAxMabmFtZUNvbnN0cmFp
+bnRzIFJGQzgyMiBDQTEXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAt
+MB8GA1UdIwQYMBaAFMhqjrEPS6qliLinj5Hb6jNK6NXiMAoGA1UdFAQDAgEBMA0G
+CSqGSIb3DQEBCwUAA4IBAQAEHhqk9qr1vH2Svec33ko0nUKpbgipddl8h6FtsAXi
+ewGnaaUK55/3Eu4FsbORjB+jSKWvYyaXnMPecX8zseOKgDWEiPZY6i+0/16Dz/NI
+2aOEVA3hxBmSToyka2FOki/KzcWfeKpebdihmZ/pyKk2qo5ygfASyV+/3fyroafe
+0FwfIRz0EHXamVhpTBVK/nsmtk2KxccIP0QjPkCu95nAAzeXJVTbzOUAbz9ZDpnM
+puACGthyjzpNfQmx1LHF1juFUdywoQSm/c/FOoPnU2KH2Ae/x0Z+tKQ3O36c72EV
+IU8WWZP82htw8qMDi5U5gymAIdQJjsyKbg53DpbkEwom
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsRFC822CA2CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsRFC822CA2CRL.pem
new file mode 100644
index 0000000000..6aa93849c0
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsRFC822CA2CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzTCBtgIBATANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEjMCEGA1UEAxMabmFtZUNvbnN0cmFp
+bnRzIFJGQzgyMiBDQTIXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAt
+MB8GA1UdIwQYMBaAFFGAzfpJckg87Q5OC87OH0BlEnCgMAoGA1UdFAQDAgEBMA0G
+CSqGSIb3DQEBCwUAA4IBAQAw8GlFDmo7lahPoMQ4ha8PN7CTyiVN52wVziP3qO0H
+uFi2H7EZV3VuYHNfJlzeeRtXGjpxBDiYkJJIg/n4ibxdyNtRnCjWTDb0BKbnQuUb
+QxoDRWuzc6G2pJ29H3Dp6DHQ7TLZwCfPfayn3AfOJBtYQpLk6c7ejrgXWv0T1ZSv
+H871UQpCF57JNU3zco9nXYN+I2IVnfgG08JXxGJsw3PMg1xa4v3awSYQ00/8v66G
+lBekAv9no926ub3Hp2DwYwcfE7iLaOdLtnBFPjdFLuZTPIGGJeeIve6NaEAwPqWO
+ZNUKSZipydOKeYsvEVEFUxVApV4TZbcSREvjGXQlYuH9
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsRFC822CA3CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsRFC822CA3CRL.pem
new file mode 100644
index 0000000000..b2cec3d3fa
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsRFC822CA3CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzTCBtgIBATANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEjMCEGA1UEAxMabmFtZUNvbnN0cmFp
+bnRzIFJGQzgyMiBDQTMXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAt
+MB8GA1UdIwQYMBaAFJq6OU3aIXWv6kHDPGxR2KhFqX+jMAoGA1UdFAQDAgEBMA0G
+CSqGSIb3DQEBCwUAA4IBAQAAhq4g3DB1Yb6DUVC11zrj0kzA3Lbth5HDupuy0okk
+5Do0LQZeiwCI37JhQceiRGxtD5riXbo3LyL2g+XqV1OCTXAbJrRAe+5sHmwrH8pO
+PZobXV32KSzzqzPbUNn4QmQDxfQLZgGAz/aPtMDuBIm22oI5iP93csW6p0lHcu34
+Z78RF06bdhO5nd8PbU8BQ+weHoWq8h8iykRzkvxL2d+vk0rS9AbEu0Hs/tqnw/pD
+1l+cuy9gmD5MFpfoMDZ9seQAKJOt5VkKW4rphhX9b3rm2cxceIqlvqQgJip+RM/I
+v3o2PYMSOePzWfRA63LYY8B5sY79W0v/miCl08vsjte9
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsURI1CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsURI1CACRL.pem
new file mode 100644
index 0000000000..67688e4aa4
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsURI1CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByjCBswIBATANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEgMB4GA1UEAxMXbmFtZUNvbnN0cmFp
+bnRzIFVSSTEgQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAtMB8G
+A1UdIwQYMBaAFPoorUEW3ipoF8gPHCM/JgPeAhQCMAoGA1UdFAQDAgEBMA0GCSqG
+SIb3DQEBCwUAA4IBAQAr3EikSVaRZA2v0/ARpi/8rC3nZprCYF4pOzM5aC96Hooz
+oEfd6+gFBJWGGPyyQuztWCg4AYXJqqotuSL0rGteXeA7S09i58Vi0rMZEYiaw1HV
+EYvt4LDShzMpeTXstjWCfMlhWnBVII+6ga0LwGD1SWtci91T6zgYlXczH33esi9i
+ras/1f4p1SQDAyo1gHulaaBRJvqQrjE/MaL8q3Ts0kQMM57aI6UeqpydIttGUcl3
+pwNujq4V8yChxN9nB1wQauRsi9xCaqTJwLDqxouZIxdUeFWEQvRAIur8NHdhZrE0
+gvLGaebETdYzvDYEkFdVMsYNWPEmd2fZ+F8dJKYB
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsURI2CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsURI2CACRL.pem
new file mode 100644
index 0000000000..fa5a247617
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/nameConstraintsURI2CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByjCBswIBATANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEgMB4GA1UEAxMXbmFtZUNvbnN0cmFp
+bnRzIFVSSTIgQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAtMB8G
+A1UdIwQYMBaAFE3riXHf8AQBsvp2OlixumDdjNPDMAoGA1UdFAQDAgEBMA0GCSqG
+SIb3DQEBCwUAA4IBAQBk9OEGWwvZ0lgWzqgJL4OZ9j0+fjAMdi78QuVFSmvPPOi3
+kLfoOrPjMNmwi42SIz4BEyDt0iVxlq+eYqrIN5q/NqFdjl1w0UvNivcuPMjYtkdg
+4XPJXcfGCfnKbZ1voHnuDlmj6+lpUsXRA0YjgRhmGz4T26ReJO1FQy6+DDqO27+V
+CZ3JM83sNDNlcMeZZk9f46HtFq/kwvqFpTHmqWvvti1hLal0aRetSyckf01vmHQa
+14FbJwEqs6hrwxhLN6Fwd/b6lN3+vLbgucxKkFvRL0JUbPuY2VtFlJk8WOllxXMc
+MYhV7lqBnaFyCO+gWQaEIE5dDbKQTNVpmVRqbT+8
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlyContainsAttributeCertsCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlyContainsAttributeCertsCACRL.pem
new file mode 100644
index 0000000000..0c5aa4a18c
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlyContainsAttributeCertsCACRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIIB4TCBygIBATANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEmMCQGA1UEAxMdb25seUNvbnRhaW5z
+QXR0cmlidXRlQ2VydHMgQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqg
+QDA+MB8GA1UdIwQYMBaAFE0H/vYtvLUZGlBN35kEem0zcJBOMA8GA1UdHAEB/wQF
+MAOFAf8wCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQELBQADggEBAILLUDuBlm16hFFX
+7mKimuJxRJIqqqi7YTYNnUkkt1ZjNwD+Zb+YdPhJrJJMboHIGRErVjSDGwHJs0HF
+HveDuGTcBDgqyJeG0C55xjRlSkPABS4jtWVVROYX/GkccJOjCGEs8A0vMVWUrsP9
+Otao6UOKDtn4wNkaItZ1Mv8Bbk1han+DsqJIdjCc3T8RV6xZcyQ9o0uO7THeyATG
+mPT6keQhjiAbT7NtvSL7pdd+F3U+68etzFFxjwqFr7/wSJxVWzF4vtrwW6tqPcCF
+SXNG3adV0JgEG4luWVHRC2GODHTh8DeygWMtEkKtkRouQMFoZGv7MvgoqlewMTfB
+1YnOC+M=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlyContainsCACertsCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlyContainsCACertsCACRL.pem
new file mode 100644
index 0000000000..23ab0ba052
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlyContainsCACertsCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB2jCBwwIBATANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEfMB0GA1UEAxMWb25seUNvbnRhaW5z
+Q0FDZXJ0cyBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqBAMD4wHwYD
+VR0jBBgwFoAUJTjDrsotdXpbTdTAA5KIEyLHbFQwDwYDVR0cAQH/BAUwA4IB/zAK
+BgNVHRQEAwIBATANBgkqhkiG9w0BAQsFAAOCAQEAMHmB5cF8VCL97/Gfo/Dpi3SC
+hi1rnJSgDEUQFwICI2Jlyewhfxs6F/EC7F0YYnPPfiA8ajXpGp5ccAvVUIoQUBgX
+iUdjp/RBmalZoyzPw8ZkGQMyy6ehymfyMnH/wKrivmAnxtPm8SGuWVJouu0T5+7n
+8G/vJg4q42RHYQQ7ripuh6wiI+Lf9wNHAzmmGsT6vG0Yrpg0hAcQzhof9xOK88h1
+xyJPReiXKjJx8Uvp/jIRjarGdjh19va1ysYLfMypqeF3C3Lb3J9vuxLS31FdX93s
+wLY919ormQApL+COmVhzilgTKI6ZfgxFhlF3nRNMQDdGc/r3tdezNoMznqBbBA==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlyContainsUserCertsCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlyContainsUserCertsCACRL.pem
new file mode 100644
index 0000000000..e99752a506
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlyContainsUserCertsCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB3DCBxQIBATANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYb25seUNvbnRhaW5z
+VXNlckNlcnRzIENBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoEAwPjAf
+BgNVHSMEGDAWgBSdvACp3AHN/h2WiH21nk+Z3iTSBTAPBgNVHRwBAf8EBTADgQH/
+MAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQCHCFuxTPvpn0fp83f2Az3x
+GKcDG6BSg4w2lISlNPpcuzAOfsNrNNvWBc8jiwdsgKpMr2rFH7HdpvG9k+A5EqT4
+B978vmdJe6d+HJ0a6RINKrDeQ3BWUeZVyzXzKJvJNEtP6+l67BA/PV1O7t93prcA
+sUdgfm074/h81yKVQJKfsE+H9yCXo4XxlvN9/37Du9lNWtlU13tvD1Hc7FjO3pB2
++YJQwmKhlXrt+7K96k9DdPJMXGzJmpICBFxHz8KkC3f0vmYau2h8FzDZV3P0trhO
+azIpQl9N2nqKsYQ57hLeTBRQ3B9tlKm8MH3lzfYUf8Iktufhg/HGuFg35gfeZWUd
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA1compromiseCRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA1compromiseCRL.pem
new file mode 100644
index 0000000000..8aeb421af8
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA1compromiseCRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIIB/DCB5QIBATANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEcMBoGA1UEAxMTb25seVNvbWVSZWFz
+b25zIENBMRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWjAiMCACAQEXDTEw
+MDEwMTA4MzAwMFowDDAKBgNVHRUEAwoBAaBBMD8wHwYDVR0jBBgwFoAUUGjRCUEn
+h+cKTrd4VvsXju4EB3EwEAYDVR0cAQH/BAYwBIMCBWAwCgYDVR0UBAMCAQEwDQYJ
+KoZIhvcNAQELBQADggEBAGGC6QC55Xv0YiF5ILhvWpoLo4gexHND0T8vTNw6fKSa
+g9Re5ty4c1tDwJkRQ3RRY36O82BLImIyx+NltDfnu21/0zLv9XbZxHUraT+5Ch2v
+smfGOTG/zm7a0Ht0QtM6q/br1RJPbxG0c7RUyV4hooP9WDV2UIz/9ba6XfbIf6Ts
+SaDhRmu6P2hbGTuAvKwsMR+DgDRvCQ8OUdc639W2hiVXaf5+kHyQz25BDTDEOptA
+cwgpFmaZiGKgltA63nn4Fl797/VmQbQYg8pmRPsEPeF5kw6n5lbXEo7wLXG4dc4N
+GiqeRO8oi8zU8rI/ddx+zr9jUeJZQldzM9VBsOq2c8c=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA1otherreasonsCRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA1otherreasonsCRL.pem
new file mode 100644
index 0000000000..49f7456ffa
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA1otherreasonsCRL.pem
@@ -0,0 +1,13 @@
+-----BEGIN X509 CRL-----
+MIIB/TCB5gIBATANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEcMBoGA1UEAxMTb25seVNvbWVSZWFz
+b25zIENBMRcNMTAwMTAxMDgzMDAxWhcNMzAxMjMxMDgzMDAwWjAiMCACAQIXDTEw
+MDEwMTA4MzAwMFowDDAKBgNVHRUEAwoBBqBCMEAwHwYDVR0jBBgwFoAUUGjRCUEn
+h+cKTrd4VvsXju4EB3EwEQYDVR0cAQH/BAcwBYMDB5+AMAoGA1UdFAQDAgEBMA0G
+CSqGSIb3DQEBCwUAA4IBAQASB9/TxIVbi32C3VcEK5Q9oKUrzWbOmzDBEI3G1S0k
+Y451pdZaFfBVzikVlcBVTw5gikTy4TUK6sEoysiEvRlpTzYuBxqKQgXwacRlVNUG
+mzZqYmHQycTyrlZfv4PyVPrz6E9ToTvz9/DymSkswVyBm/GKZ3Rq31G8niu4xHT2
+EBz0BEW3/GN9sUC/Y4dGPcTNJc3OkcrL7t1YKfz9H+dFdXqpTW9wdt6DkyEI/Ync
+3pxo6Qnj8Wwk8U2aiDvKqQh6z/b8Mlt1CullIhKM3SqGzTqGnv7SntdZwTv/1oeY
+dbpJ6VGFTMqXxUkgDnR4ba+Tn9iMkAUakQvbjnN5/mgW
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA2CRL1.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA2CRL1.pem
new file mode 100644
index 0000000000..2d585f4780
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA2CRL1.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB2DCBwQIBATANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEcMBoGA1UEAxMTb25seVNvbWVSZWFz
+b25zIENBMhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqBBMD8wHwYDVR0j
+BBgwFoAUYGPf0iOkKdZBpKzKhnmYpmUBSK4wEAYDVR0cAQH/BAYwBIMCAxgwCgYD
+VR0UBAMCAQEwDQYJKoZIhvcNAQELBQADggEBAE7Yv0ls2R1n277KQK1TR+2NXC1y
+pY4ZorshYnrshNO+Uy23PtVCJzy0390E1CsDzIZdmz+/rXEDsQOSwCYDWrCSo6hK
+BCyTlWBfqZcNTQJnRgYV95e3yHaqY0mEgY6l+az1gDR7hC5UBwFPnFGNnY0s9JSD
+bu4LOdl+bT8QmTw02+hfMA4Q/I+ytJOkWkLs+5pLg6vyQreprf8MjJDdGxG0oKk5
+Q+vPpYQQmsyBosaz7mNSuZ799BAqRAl0ATMmT5FGldFo7whlDhyYwCnT6djdR3nd
+nsBhSdbf3LXqnKk6i79U1H+Yzx0XagnJA7wGGmHf5oIRRVDaMmQOzaf/sl0=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA2CRL2.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA2CRL2.pem
new file mode 100644
index 0000000000..657f0999fa
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA2CRL2.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB2DCBwQIBATANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEcMBoGA1UEAxMTb25seVNvbWVSZWFz
+b25zIENBMhcNMTAwMTAxMDgzMDAxWhcNMzAxMjMxMDgzMDAwWqBBMD8wHwYDVR0j
+BBgwFoAUYGPf0iOkKdZBpKzKhnmYpmUBSK4wEAYDVR0cAQH/BAYwBIMCAQYwCgYD
+VR0UBAMCAQEwDQYJKoZIhvcNAQELBQADggEBAI78t4QP3CIEpYKHa9TIyjr1Z+lq
+HE7UgiKd4HbsKK5gPDAme9A/DK/klDZoufxmSUnjJ+KO5yE5YiQITW9k2CvZL17g
+Wo8miQcf7HFp9dEEnwd6yHE10ZmqqIJrujTaa9P76KhaovCCoWlJUAyCOSF9DDyj
+5fJyJYUKxXo4FwkcViwsJgp4NK3m+YB3BYFRy/p4PQKPFYYrDMI1yx8B/lOp16UH
+rhYzMC5sohfnCpryHxNTgBu1Cy9XzITBvUniXOtMO+hY/axGojkm/IOQSlzYAahL
+AOc1qr6BEK/tkWxUJanBWTpPh5d5Rojto/uu4fOG4XbQLS4PllRZlCKQTyY=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA3compromiseCRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA3compromiseCRL.pem
new file mode 100644
index 0000000000..acac31a59e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA3compromiseCRL.pem
@@ -0,0 +1,15 @@
+-----BEGIN X509 CRL-----
+MIICPTCCASUCAQEwDQYJKoZIhvcNAQELBQAwTDELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHDAaBgNVBAsTE29ubHlTb21lUmVh
+c29ucyBDQTMXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqggaQwgaEwHwYD
+VR0jBBgwFoAULSS3l4cs7tocvt6XhBuvoBUWvmswcgYDVR0cAQH/BGgwZqBgoF6k
+XDBaMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTEcMBoGA1UECxMTb25seVNvbWVSZWFzb25zIENBMzEMMAoGA1UEAxMDQ1JMgwIF
+YDAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQsFAAOCAQEAdQRa9rY2kA/f5hPXwMzB
+IiCNKdlFB5gAcrElHOAFq8MP3BQ6LtE0dH+RoAudtqh92aydcFza5EsMVAQq99AM
+jBjlm535dj9hxo79uqC2ZReofJBNgLL5H8cktqZPCsnyeGgDWDxHGtSE7PThveN3
+4VD9Kstk04qFpJ/8TK3BPca6zEtTb0k8LkpRojumPy+KGNs936HEkGwRBQaFkn4v
+i0gosO557Q4wXMI4AQfuY5jGCavXjUkXoR1BlS0CrQqMFC69J8hOrpK7tOdDPefa
+NpCf+3pMgASPMhuc3W9/bQIQTQL/dFwdfQZCmJUrxu3e04URw13J+rDXaZKgYXb9
+cg==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA3otherreasonsCRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA3otherreasonsCRL.pem
new file mode 100644
index 0000000000..3d20df2931
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA3otherreasonsCRL.pem
@@ -0,0 +1,15 @@
+-----BEGIN X509 CRL-----
+MIICPjCCASYCAQEwDQYJKoZIhvcNAQELBQAwTDELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHDAaBgNVBAsTE29ubHlTb21lUmVh
+c29ucyBDQTMXDTEwMDEwMTA4MzAwMVoXDTMwMTIzMTA4MzAwMFqggaUwgaIwHwYD
+VR0jBBgwFoAULSS3l4cs7tocvt6XhBuvoBUWvmswcwYDVR0cAQH/BGkwZ6BgoF6k
+XDBaMQswCQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAx
+MTEcMBoGA1UECxMTb25seVNvbWVSZWFzb25zIENBMzEMMAoGA1UEAxMDQ1JMgwMH
+n4AwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQELBQADggEBAE32bsFUkG2yqjakiO6C
+h4PUu/ZdW+ec4ZPUt/0Aw5pN/yGw2DJp2nBjHbLEn8qoxZbVX7CM4Kl44520B2Mm
+rn/e/dmOMzfKLV5SxreIg2gzl0Y/mg4JqmGza4sTA8nDExWiRyqQbf7wIgK6pQEU
+sEjvc2RsJrzvIt6QryEMYAJaAe9FaMP++SnKSKisBKzcirBgTz0nrPrNkUcI2o6P
+GHW3ZwPfyDsUhx1z2sbtT3y/svye0Ksgh+2wZc3tU5zsvRAKN6fokw4ADhlporgF
+3WZLQJcywJElK3w7mPc8YL9JKieuAiul/E1dbpnm8dA9Sj5oDyooynxUav/o4HCl
+WDw=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA4compromiseCRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA4compromiseCRL.pem
new file mode 100644
index 0000000000..3b60898d4d
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA4compromiseCRL.pem
@@ -0,0 +1,15 @@
+-----BEGIN X509 CRL-----
+MIICYjCCAUoCAQEwDQYJKoZIhvcNAQELBQAwTDELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHDAaBgNVBAsTE29ubHlTb21lUmVh
+c29ucyBDQTQXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowIjAgAgECFw0x
+MDAxMDEwODMwMDBaMAwwCgYDVR0VBAMKAQGggaUwgaIwHwYDVR0jBBgwFoAUvmbc
+HgwGO/bTiDSRUyaBDWgXbskwcwYDVR0cAQH/BGkwZ6BhoF+kXTBbMQswCQYDVQQG
+EwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEcMBoGA1UECxMT
+b25seVNvbWVSZWFzb25zIENBNDENMAsGA1UEAxMEQ1JMMYMCBWAwCgYDVR0UBAMC
+AQEwDQYJKoZIhvcNAQELBQADggEBAAJIN0tHbsczxcPvHunvZEwHCJR0fVLav9lF
+XrsjWM5Qsaj0eOddNDav/I/ELvHUL2JCVu0UKLtwlNZlAIPgOKi3wEhf6qSV2WY8
+NW+zQ8Zdk+zuIsE/to9477C7VJfd95fqPhxFRzrfo3R1TCwEskmOVhvwIcsuYOfM
+fNl1ObbutpSkauLcUTJaHkdo0/QO6vSMEEVbmVbqXUOVq/Bbv4QFypTl9tEGCAeS
+SXhy9KG1XxdDJRL8nExHIqzvaBxRg0IJAHGi1ERrL3mlUyq/0AkHnT2kqrNaVzxL
+aDF48Wb41H/JPZjU73gRqAm4HHQcEIR/ZMgCQy2ZqMFxubBzw6U=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA4otherreasonsCRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA4otherreasonsCRL.pem
new file mode 100644
index 0000000000..189002c25d
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/onlySomeReasonsCA4otherreasonsCRL.pem
@@ -0,0 +1,15 @@
+-----BEGIN X509 CRL-----
+MIICYzCCAUsCAQEwDQYJKoZIhvcNAQELBQAwTDELMAkGA1UEBhMCVVMxHzAdBgNV
+BAoTFlRlc3QgQ2VydGlmaWNhdGVzIDIwMTExHDAaBgNVBAsTE29ubHlTb21lUmVh
+c29ucyBDQTQXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFowIjAgAgEDFw0x
+MDAxMDEwODMwMDBaMAwwCgYDVR0VBAMKAQOggaYwgaMwHwYDVR0jBBgwFoAUvmbc
+HgwGO/bTiDSRUyaBDWgXbskwdAYDVR0cAQH/BGowaKBhoF+kXTBbMQswCQYDVQQG
+EwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEcMBoGA1UECxMT
+b25seVNvbWVSZWFzb25zIENBNDENMAsGA1UEAxMEQ1JMMoMDB5+AMAoGA1UdFAQD
+AgEBMA0GCSqGSIb3DQEBCwUAA4IBAQA6VO6zbrPramIZ5tc+d2wb1qV2eX230xjC
+Z+k9zK/PWUvG47ZOYUDccUWhVUgH99nRvoqdhVZrF69HIqdJx8a1+kvi45meJsHN
+faOVtyb2cXnYduYiSrcVZtimnSItAc9LIKt5NvRKVbsD/ZX4Nf+fnCaQEmd1Vx89
+dWq+5Pt3iqORg89D6HzU1GFVE/ES60t7rUbYkxKdfnZhsauX6Mm7ZBIDZK6I14LD
+6qm0UicAFZzpn15jKZWD6h3s3ZGgpFBIR1CkQH5pyTLQK/jPma1mq6ktz3hHjAfR
++BFDWpDxlfjcvBm8TPB8kmPYF9zl7fj8VkpDW/g2jwvDYNwyuYq9
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint0CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint0CACRL.pem
new file mode 100644
index 0000000000..c1142fd5f2
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint0CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByDCBsQIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UEAxMVcGF0aExlbkNvbnN0
+cmFpbnQwIENBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8wLTAfBgNV
+HSMEGDAWgBSbK7JKPJDFblABySK9Y84J8Yw9+jAKBgNVHRQEAwIBATANBgkqhkiG
+9w0BAQsFAAOCAQEACbNqHOyNhLoyqsp302Qhh2DQ5xn50BIJt8FHPQoxzjgcSxkV
+vSWc3F7o93x2Gy3t90APobAPMq7lgkvI9rUyIdg3jn+mkAyaGOaZNoocBVIGwEmI
+ITL2DEhUSGag4wZgXgxAqkcvasDMihLpVudYujuqQ3sU4FLxr1jwXtdtwmXrYHSx
+W3CFNk07BfXdrjETCFJVP2fmElf1s3xOJJaw82NqWBAU7OGk/CTI0XQwxPHAqnao
+Pywh9giLL8cjIqi77qOQk3qSmPvygMXfsMQv1LkdL1UpSNta0D4NurcyLXUojN9p
+qwk5NGs5KwY5CNr3lncwUfuSkuySGB+KmoSzQA==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint0subCA2CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint0subCA2CRL.pem
new file mode 100644
index 0000000000..34b51bd784
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint0subCA2CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzDCBtQIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZcGF0aExlbkNvbnN0
+cmFpbnQwIHN1YkNBMhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0w
+HwYDVR0jBBgwFoAUxgkqG/u46T5oYHrHl86zWFF7dt4wCgYDVR0UBAMCAQEwDQYJ
+KoZIhvcNAQELBQADggEBAJqExyZTBoPDB2CCe0jcRtIcGgoQJSMase7HfvYA2gVB
+zQ+2yRT8qyeoK/ybY8kBRGQ8pSfv7R4ARlwK2vvAfx70U512ssjSDWpmAXK3EuDU
+JVvVfrmHO66z6LhZ1BUx3ngzk1tnEZnvfCWqMGkRFh3dXT142l/0uWGdEBpr/lyy
+zhhJZ+AvGuhEWpeuAI5GL4Gw7p/YBaMoioEvVVMJ16Jp9k7dwaFF7hSPLf31GCtn
+Rm/6rENr/P+vdFLRET/FG84eGMBsLtlW4y6q2boQImMqZZ6uC5hIfK1Ke4vLfEZS
+/6Qs392dyBadvH2ifTb/L95kG7zGC7fHAx2e+tECzCo=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint0subCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint0subCACRL.pem
new file mode 100644
index 0000000000..1c2c371782
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint0subCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByzCBtAIBATANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYcGF0aExlbkNvbnN0
+cmFpbnQwIHN1YkNBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8wLTAf
+BgNVHSMEGDAWgBQUYmcQfdI3xXIG0N5/tRYdyqNzXjAKBgNVHRQEAwIBATANBgkq
+hkiG9w0BAQsFAAOCAQEAFpwGZEbWR35NljL/Cqg+hxRkUXPsz9aZL5+OrEpCBF/F
+AvtTISr5emDzeNbc+DWdsPAIYIOZ/1kx31aA+0e9Hc5Bac7O246yIwM/kyODPfM+
+36CTCsUCHdIlEm2tDNOhn7gHV9y+tJkT49rRp952zeTwloKyMADiR5amnqhcoOXp
++uY55zW2wQLkADXqukppj4bP13g/R9fIZvhkTFLD1FGArjGt9HH1Hfe3n3MjI0TV
+AaD5TOm4Jogz8RsrFDz3EFMUxCb06jcGz+B3Oe5etjJ0aSpbG8d5ETgGAW3ucXbP
+eVlTs9xMJlm4s34hxYOI3Xnu2ksQ3YiHccWpFcNo8Q==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint1CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint1CACRL.pem
new file mode 100644
index 0000000000..c0dedb88c7
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint1CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByDCBsQIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UEAxMVcGF0aExlbkNvbnN0
+cmFpbnQxIENBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8wLTAfBgNV
+HSMEGDAWgBTz5HFg/xcU3o0mhTN+HPzBR2f6wTAKBgNVHRQEAwIBATANBgkqhkiG
+9w0BAQsFAAOCAQEAYUHA3NQZQRmqjqAh2cWof7Fkl+YK2qY4pF/Yo6L2+ASqcQaE
+6+YCwPVUcjJsNzrF76KKHib7UbodnAH9cBBig1d5a00OFN9n4B81Ha7C0UxKtphU
+gm7wVEBlsHY8KAcV9y+VX11UX9qJ2GEAN1pa/Kio6w42wMcW/oDrAO7UKZtzJv3M
+peqQexGUQYQMbyIh2TTz4TOk2uZovikXa2+1FiUqFPNZfHkZ4eRnQBUQBxFJT1pj
+m0QtotM8+yChkTGrP52ilV/GI3kaLuyIbZVl7adUHiIxUkrEmmkOl7OHhsKwrrTU
+9RkZtL1XF075smmMW8iNRRVEDA3HqJxv2GN0iQ==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint1subCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint1subCACRL.pem
new file mode 100644
index 0000000000..fd43b9187b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint1subCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByzCBtAIBATANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEhMB8GA1UEAxMYcGF0aExlbkNvbnN0
+cmFpbnQxIHN1YkNBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8wLTAf
+BgNVHSMEGDAWgBTlmZa1x31VQq2Bjscl9hjNrJ2QeTAKBgNVHRQEAwIBATANBgkq
+hkiG9w0BAQsFAAOCAQEAE0X1RyeBmz4sK6l9ognWRz3YK1XFln2WRcvR6Rnj5+hD
+paYtOhh2FRMNL11CqqpiG2IC1JPGKA36hx7UcF6LyhcqtDS0YEI9kXz/C5Hk60bc
+wKuIyVOZYgXOnNvsewa2LvGhi8ZUCI4L6DGdV7+OcJ/7PX3Jth+01Np7T15jo/gv
+cCCkFx3fmd9ysx2xcO2Cyd5vtqiEOK7DIoNZ6WguHlYdZb9/kDoRoWf5Qq7rmKXQ
+agJhrU6jWsCfQqY6e1oYlafSRPemgJj4kD1vtTW1D8OZc+iUFy0Fd3EZ6HT8xOAP
+9e0WFDsqL0+K31KZk5tFm3KZOrjJIxvcmLu+a1mELw==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6CACRL.pem
new file mode 100644
index 0000000000..a4bb7e3ab2
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIByDCBsQIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEeMBwGA1UEAxMVcGF0aExlbkNvbnN0
+cmFpbnQ2IENBFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMwMDBaoC8wLTAfBgNV
+HSMEGDAWgBSvvIWu/kyu4Y2XI4jIpbFgC7pO2DAKBgNVHRQEAwIBATANBgkqhkiG
+9w0BAQsFAAOCAQEAmHcSluSxj/t6JAD/aFB0G2KneIGVwM+c+dhxzVgL8/onCq0v
+KLB3BafsI5LQYRb5peAT1mCROTnVIHW0n6bE0RCQIxGty7Zh/kcjRtdL9cv5JX91
+ovjJVm7snc3XR5wUe4+8pRO3HeWurcXj/NvUOmaZg+hEnv8zgICjxndiqtPlQPjq
+/BIIDOT7FSuYwFIB5bcPBvyEjRSR7hi2UDzR9bxjiHBULC8nCbNhk5Qff0815fLK
+TQozMgMeB3D9psl8cDfO2owL77bsQx0um2QjJWW/ByMnYndkzGRt/9SkxRGHKtmV
+2rp5wMZKEQcVOm8v6KmfkdWtMBf5GCXLvjf0RQ==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subCA0CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subCA0CRL.pem
new file mode 100644
index 0000000000..a06b0839cf
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subCA0CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzDCBtQIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZcGF0aExlbkNvbnN0
+cmFpbnQ2IHN1YkNBMBcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0w
+HwYDVR0jBBgwFoAUz3Z2g3OQJMeNo21nfOtSwNTU7UgwCgYDVR0UBAMCAQEwDQYJ
+KoZIhvcNAQELBQADggEBAFyoC4W//fvuVDNbyQCjkcD+eWvMUc48a7gacH/9yFzM
+auBjPEdjd4HWqUjEH7AH75ZgRXnf1n1pL9wh9mIJmVV4hLHfnDcryOMH71gfDrft
+d72DZcCBNZv7jXSMuIjCDn4TtlF8DgldJHQ5uA1f/a+qt1nOV7OCgHStr8PsP45+
+Cf/UGN/hqLWdlvaMB7PF7Qbfm639AE4UWs5NyKQC9PaDpFw12fAUJSO6PRXnSEMT
+9xx74LAC4aZIO5CtnUE/MPIvGgJFdUneXVkGDmsg/jsXbCVhKH7fUWun9IPvehE/
+OW6kYzC+6v943J3NelQUzcWzzF0CH8DwMGEY/GcmIwI=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subCA1CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subCA1CRL.pem
new file mode 100644
index 0000000000..5aff3ab9e6
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subCA1CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzDCBtQIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZcGF0aExlbkNvbnN0
+cmFpbnQ2IHN1YkNBMRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0w
+HwYDVR0jBBgwFoAUPJqVnpNeVmLpWziQbJo6bpLb9wswCgYDVR0UBAMCAQEwDQYJ
+KoZIhvcNAQELBQADggEBAJEL4fmSZTA+fF23RGynu2YEOWQ+YFNJzfYPg8EdimTL
+8AAXERJlbKKh+51nygXhYhUEonLIVmJyK83n7rIbEaOlrfXu2M4CtSi0zPZyTNL6
+hntIw1oK90JumjJhqxc0T9viI+cCoKz5b1Y0VZ5UNrno5fHmhw784TwN8bKxTig1
+DC4mjrk38QAAEV/5xQdS0i4nXP7Tz1PO81ueqMz8kgdp+QHjFKxDOoadq1gt+7Ly
+GRuY2SlF7pKZ6e4SdGF3rJ/sSzmO0wMLkMU4074RRg0BOo7J8ow/WuMVmwi+alQJ
+l5xRRlX1d4F30oa5AuJWrOSDw87HKTfRwPvCF/U6hPY=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subCA4CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subCA4CRL.pem
new file mode 100644
index 0000000000..1cc5a4506e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subCA4CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzDCBtQIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZcGF0aExlbkNvbnN0
+cmFpbnQ2IHN1YkNBNBcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0w
+HwYDVR0jBBgwFoAUSYXbS/sRY9mZAii0C3qeExdaFXcwCgYDVR0UBAMCAQEwDQYJ
+KoZIhvcNAQELBQADggEBALcHlK8kwUx4MZCo/sdlhk02Cf/n4mMvGAzXzjTDFoO1
++Nvo1HL5xmZ9KKCTSYmfBHc/qhMAmH31I6UJAVlOdtUcq2VCRRej8OlOGLImThkt
+oClLD6mmtW1YuB6bJtsuFj+GIPvLZfkpOgKg0fDmcQRVL5DO5ajMN/BH/xJtHuiV
+n5DjNZPhJls11DOd57TzFhGVq17PhOrMvL+8nCMs4Zl7DtNKw3EJuTDGTGAB+OYx
+5FJBmick+Mnkf2ElfidE3yBiOlg0Oj/fXjb5cqCa4uR+sAqYOl9BBjM6RfVbOrhJ
+7FuBGqYEmCr0D/FT8EusGdWFDBqfDsWtXVV7LHxcm6c=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subsubCA00CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subsubCA00CRL.pem
new file mode 100644
index 0000000000..6b19bdf4f3
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subsubCA00CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB0DCBuQIBATANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEmMCQGA1UEAxMdcGF0aExlbkNvbnN0
+cmFpbnQ2IHN1YnN1YkNBMDAXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqg
+LzAtMB8GA1UdIwQYMBaAFLq54oj31FkliuMp30+gBjjdcXSCMAoGA1UdFAQDAgEB
+MA0GCSqGSIb3DQEBCwUAA4IBAQC9tjk91ybiFjv2eYZsjGMKc+y1kd1xc1xIXSdD
+dM5JR+GglRm79uK4gDZ3gTLIQpDVgYPXV+ereJ9Kg9DOl79O3h/nxtS45azUxvdb
+uk/DW7PpSZSOK4d6hW/VgZG2Giv+ZucWNnUGjsXCs4/Hhi+IZvAI/Fhtcbi5cwHQ
+RG1hqJYGsqzQ1V4iBshQnZeyjp0KFz95dIifHNsL1YJJy7ODiCE6RLGaXs064DII
+g3XyZdz7hZOFbGTR7GwkYtSyIHLm4iD/xJeCU6cA6FNd+Xb5Fs4SSteCUd0lurH1
+JQLnUF/Xjt2IowuQFnfQ7z2jq+8BRrIgkvCQp5lzteSqPE1i
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subsubCA11CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subsubCA11CRL.pem
new file mode 100644
index 0000000000..f85921377f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subsubCA11CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB0DCBuQIBATANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEmMCQGA1UEAxMdcGF0aExlbkNvbnN0
+cmFpbnQ2IHN1YnN1YkNBMTEXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqg
+LzAtMB8GA1UdIwQYMBaAFNOmRV4CnWcWfZSAD3O5hMZbtTG+MAoGA1UdFAQDAgEB
+MA0GCSqGSIb3DQEBCwUAA4IBAQChBEJUKVtETDiFUgxBvxOrmaOjI5NxDTsqyM7m
+HrkP330mh+ij8w4DJ/kOhHxC0c4EBgD7m4oUbkClmqY0LVRNaUlFHdNvftGJMg8k
+Z6Vveak9+Z3q5J7QlE8hdLCGsnQXL3gWoOjH28j3I72fW5tabTdyq7qPjNKkt0xh
+6Sv9jLxHbAWimSvj6xQ3JxO4UweFvDl72eQb+tFhrJpouhlUv13eF6eaQoVKf4to
+KRjRXWEErBEkb1fEXzUISEvQH8gbzVi8raKG/CWbUfFCkBWiqd3Ahr+w0xtmVV9W
+wk0SlM+XlKRQZ4chc+93RMQQBCC6LwN2rBmyaLUPAtzUOTA2
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subsubCA41CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subsubCA41CRL.pem
new file mode 100644
index 0000000000..744befe8d2
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subsubCA41CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB0DCBuQIBATANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEmMCQGA1UEAxMdcGF0aExlbkNvbnN0
+cmFpbnQ2IHN1YnN1YkNBNDEXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqg
+LzAtMB8GA1UdIwQYMBaAFERapgfP9vPIx0bvZKH1W8E/grxXMAoGA1UdFAQDAgEB
+MA0GCSqGSIb3DQEBCwUAA4IBAQBC2N5Gdl473M+niHqbKh49ObjDXcF0Vbam4NyC
+e5V+1D6PZLlZQDNh0ORk/MnIOYWxchUhXpUnpNfcqReFdP/kIhwlc/Nm3xveO86n
+zWuRP3NrN0N8SRz9YmLkoZvDNL5gagKCwLzeGTTi6lMKqhZnmcDH3ko7k3TOlCO7
+I7f6jEp6ECAHUbDE7UyJC93lYu98YpaM5SV4L8i58/GBpCwGsGirSxws7Xhrgr4L
+Q5UUt5v3GDNW5YiRBEuG1kMlBC4T4gX/TNsdu/8G4RT2hO+SIDOtMNfA4D4TIiY0
+OzDtVVto9DYarCyKlQKHzb6RrFL8sYZJc213B/1O4qRNeJCj
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subsubsubCA11XCRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subsubsubCA11XCRL.pem
new file mode 100644
index 0000000000..20392a29a6
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subsubsubCA11XCRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB1DCBvQIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEqMCgGA1UEAxMhcGF0aExlbkNvbnN0
+cmFpbnQ2IHN1YnN1YnN1YkNBMTFYFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMw
+MDBaoC8wLTAfBgNVHSMEGDAWgBSD2ri1xp3Iiwh8iz/tGnIl4q8b6jAKBgNVHRQE
+AwIBATANBgkqhkiG9w0BAQsFAAOCAQEAmKydWhVC5ytcp4DjzRPCIZ1myP9MGW97
+diaTIZaFdYYz52k2GD6uHBEL1rALDG6e2DiU+YbmfVJHE5RbehxwtimoWsHOtGLO
+NPTMBPwGoGHIUyR2Ex40oozOrprl5tY3y8uticLLyQQ4meUTrquM7aAEaHHYGwU/
+FziX56TGzO9Tm6ci+jlTrOwHy/uj/AVkkQS9RHk1ytgrG54WSwh/diP9qJrNGvBe
+a8Ditg8ijMjGU9J7NeDJn33G0U8/R08ZOfo0kNqD6mG8Np5meREfiCt5UGfwBOV1
+EVMpK/Liv20yc7PcJT2lKGl1eXZmiZ7TLGV0KJWUWRNy1o4cv6a1ng==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subsubsubCA41XCRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subsubsubCA41XCRL.pem
new file mode 100644
index 0000000000..8674072d00
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pathLenConstraint6subsubsubCA41XCRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB1DCBvQIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEqMCgGA1UEAxMhcGF0aExlbkNvbnN0
+cmFpbnQ2IHN1YnN1YnN1YkNBNDFYFw0xMDAxMDEwODMwMDBaFw0zMDEyMzEwODMw
+MDBaoC8wLTAfBgNVHSMEGDAWgBSh7aLzNVSln7xj5kdqUyRsSgxyLDAKBgNVHRQE
+AwIBATANBgkqhkiG9w0BAQsFAAOCAQEAB9m9d1A5cqTJSbdKDkv4KfjAJDsKOqyf
+l1QLXj28Mq43YlLbcoaivW0yL+44zumb02ZKr4v1qd7tP5QLPvv+Ew1pQwC3I8cp
+Hq33iO6VX/ZLVT+vD8wguU/Lwq+oZGFDHMatgq2CGtZ2lJbZ8/I11wR/otTBa9Ne
+krQ+n79avPaAagJoyz+1HKSerOyuyFQ9GP/v64sS3YKy5LJZ/VXC9PlpzU523ENu
+ncwldAgVmNTgxa+kPmdIzUkWLHuuggVltFtRbVsiKyJINgNcmooZhDIHCk6LsXYY
+fBMmxX4xFLGzi1p4sobgJgBkY8YBDiB2xEslOFkwKIgpRfX01T4IZQ==
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/pre2000CRLnextUpdateCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pre2000CRLnextUpdateCACRL.pem
new file mode 100644
index 0000000000..57afdac2b5
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/pre2000CRLnextUpdateCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzDCBtQIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZcHJlMjAwMCBDUkwg
+bmV4dFVwZGF0ZSBDQRcNOTgwMTAxMTIwMTAwWhcNOTkwMTAxMTIwMTAwWqAvMC0w
+HwYDVR0jBBgwFoAUHqhHnGGAaCixQpopjOYoAymSA8wwCgYDVR0UBAMCAQEwDQYJ
+KoZIhvcNAQELBQADggEBAF6aXbwxymxr0Q8xGFXYqmr5vzuVUREiNHYZMX6N6pqI
+noDmGZN1FgX3FSkcKlsiVYWPRp8VygdNPt2sctjy5OV3J8kAKXzoll7/cHVPWj3b
+uGP8B0Y3sk7oCupwlI/lPwu4Yf5hHcUofyGV4yeOCNn0BHGtOzcfStxbO/K2sG10
+ny8KKkH/+horhqSur2p6z02jq1hcHsQLt293tPfaG6skObtvWgrajbE8rPKYLHiS
+mkh+9Lxtzv/+WOR7YeBgjfg7Eu+gLC+2rrA4C/UiQT27baIzEJkaz3qarL8p4qWR
+BctCVbNVbcrgSA7pT3kavp4Te5NHLg1vRfmkHka1ESk=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy0CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy0CACRL.pem
new file mode 100644
index 0000000000..faecb30bdc
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy0CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzDCBtQIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZcmVxdWlyZUV4cGxp
+Y2l0UG9saWN5MCBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0w
+HwYDVR0jBBgwFoAUuezfulIiuLi+aveiEtUnINZnBDUwCgYDVR0UBAMCAQEwDQYJ
+KoZIhvcNAQELBQADggEBAErZavnEyTgHh/ez0LB7FgIfWGuiJB+NDDOQBT31adQW
+nPq1ylOQnG5ALE9askbusXrsw8VHIffm8bBd6JRdFXD9p7S2SzFE5skbRHVs71qr
+ytTzQhoQgYMaWRIYBx5Yg9J0+HSp7rip8FPRoPA34LRoPFmtvGyESnFQCZQMj6Ar
+DrRhaj9MFsicWAObMlIWNOsISnNkDd1s4XeRTMbZ6NgvyZ9Oo6K4S9YsPJypmaWD
+rAtkwSqyyH9yT/Ip7jNFdYfin5oE2i+dN4FCWzQXyr+z0l6dWdw/sjiDWRHVQTkA
+G/F4Ro+qR6bVtq9wt/H1qbauMxOqI+OILjfZARtV/mY=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy0subCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy0subCACRL.pem
new file mode 100644
index 0000000000..6aa182da50
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy0subCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzzCBuAIBATANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMccmVxdWlyZUV4cGxp
+Y2l0UG9saWN5MCBzdWJDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAv
+MC0wHwYDVR0jBBgwFoAUvmJ4/Tu9bpwLM/I7MqpBCPPliVowCgYDVR0UBAMCAQEw
+DQYJKoZIhvcNAQELBQADggEBABmiY4GL9Z4TINu3A3r2ReqPCf6NBrK838gjCy5y
+yomt33rwH0sDWcdU1YtKMk1iAWpBBon3nBrfylsFDAacz9oqvHBnCSYnO/b3WWLv
+rv80IaJoV6IeZC1CF7vXFcUWt0VnUgVxNzhLWOn0GEu/R/W3HIPUUvpg/0+RVG6c
+WSPwCUAidFY88P195evwDEXaKykQw6LzAlnWMvrL0lviPl4Px/GDUOBp+aZaDz+t
+ktuljb5StVBqdQ4XzemwS12ZkAGw//synft8xDg7c1Pq7csftQ1SFuEvkRaobXYp
+mSWUqhhm5pkRQBxPySvpDiYCOiQbsiTyAAnYkydIeAkX1Ps=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy0subsubCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy0subsubCACRL.pem
new file mode 100644
index 0000000000..58a10374de
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy0subsubCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB0jCBuwIBATANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEoMCYGA1UEAxMfcmVxdWlyZUV4cGxp
+Y2l0UG9saWN5MCBzdWJzdWJDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAw
+WqAvMC0wHwYDVR0jBBgwFoAU69iXen96IzUZ5M+XJCcizGenVkkwCgYDVR0UBAMC
+AQEwDQYJKoZIhvcNAQELBQADggEBADaIskgZjnU/+X04sIHx4MxEDo7nCtfaRe6U
+sgYqAEr8u9JCuba3tJgEud2meu8XRkQjagttBmG52vxS4rMiu6Xq79DPWLrdKc3x
++1Tx/wF0iACCp7B0aNfFnrF+Cg/XCQqeVlthn8EP51HmFl+Fu/0szwhHS3N4Nh67
+C7QGGL61vSUqK3V9tRSn7ubAJBJp+BFbG0uLvOlEUbs4iil1f+VlWlXr7WFfKw0F
+k9prVeYBcnyV7X4uLEpQZGk26Qo1X63H+aMUhSehqg9v+M5A8/pq5MKCRwD6S3Ej
+h8DoK5dmqjOrjfBGsS8Z1az1WsVDlC7EO/BFgTXM349j406Rpe4=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy0subsubsubCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy0subsubsubCACRL.pem
new file mode 100644
index 0000000000..34265b943c
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy0subsubsubCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB1TCBvgIBATANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTErMCkGA1UEAxMicmVxdWlyZUV4cGxp
+Y2l0UG9saWN5MCBzdWJzdWJzdWJDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgz
+MDAwWqAvMC0wHwYDVR0jBBgwFoAUtdsE1sggCC9aQcd4o0SJ2s4ua7owCgYDVR0U
+BAMCAQEwDQYJKoZIhvcNAQELBQADggEBAChXnVu5rzda6+f2NZ1nWf5qyFfBR3qb
+IwWmBIAATlpil8e/RfSjzkNP2SrKhGi7KDseMn7F6MsHlGp8McNb7ryQcd0+PSUV
+m9hELQcBosZrU/XTdctfTx2/k5mfixlK+UYqz3k7rFfG7RhdkhUexaCQFSCgBgxQ
+RhHlXyP8xpSytC0T6w8gIXxUQjK5jEBwr8uVYhadcCsQnx4I35MXmNUb52BohF3s
+p3pOdgGiCn5CmgcqBa1ybBK5qtKKHav8H6dBzNLeuG9giZC/ALpFhzB0fgkGXXFr
+52zZxy2Z8dN7OWAMTski7B2c363+TwXI7Y/Vuq3qIYLxdcFWix3zefY=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy10CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy10CACRL.pem
new file mode 100644
index 0000000000..efb8976e4e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy10CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzTCBtgIBATANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEjMCEGA1UEAxMacmVxdWlyZUV4cGxp
+Y2l0UG9saWN5MTAgQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqgLzAt
+MB8GA1UdIwQYMBaAFBnzTATRX9WAR/P4NCwRgeSYz2ufMAoGA1UdFAQDAgEBMA0G
+CSqGSIb3DQEBCwUAA4IBAQALMOPr5blCX12/wmoUiyjhE3KtwudCyjTFeRfWdh1y
+i74p1lKaCtLS2Ccqelr0fuD98PSUvKa37UrWDtj9fXTCgbe0dB2upF/hfkaCEq9b
+vO5HAuBB/hBwR/F1IsQ7qHwDkQA8WhXRfYsrneWfygUtQUzrji/nz0yF5l+GnWWX
+iMID56whZjh/ch6Uvb9qYJO2p4R1KMFJ7G+xKJQm+TsTx6iYIDP2Q8uedSstLasu
++d68KWDFkf8pAXDDgpp4ldUflWbW7Wa7tSHodxE9D9cee4Db7jmXyV7BqQUxYUwF
+9qj1mjdivXtpeTsNKhX0ASsm4jHKmSjKOYvkEALiALq/
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy10subCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy10subCACRL.pem
new file mode 100644
index 0000000000..125c24847c
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy10subCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB0DCBuQIBATANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEmMCQGA1UEAxMdcmVxdWlyZUV4cGxp
+Y2l0UG9saWN5MTAgc3ViQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAwMFqg
+LzAtMB8GA1UdIwQYMBaAFG4YpmEkD2jbLgYRliY3r8l4KVYGMAoGA1UdFAQDAgEB
+MA0GCSqGSIb3DQEBCwUAA4IBAQCZ/4QYxzZaC5BIcXVOv0Pa0KrQdGUx6Ae7knJP
+df/x+IrPcwEHZeD8dQUYnWT7EOvcJBRS3HaI8xD0+n3IFR1+ayaQuV2UCQSu2WbA
+FXx+HRApe5lWOVZsG9vg7V2ccF+8u4qIaLxxTlfOGL3m1FyK8/YXhDfNeOwRukNG
+JxHdfhaqHFtofV3Spa2HcUwKbNAEtu4SAcW55ZV0q/W1tbOBeYwBMNoNMKEVPf8B
+FhJh0ID0xyoFdFIDsj0uNkvNRazAjnUGtz0m7/PZE22qvPH2Bt9gII5UEIbWY4Nv
++Kz6TiXfjZZkl5vR4DHy6qOfQxVDbEuehfRxsBLngKLXzW3r
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy10subsubCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy10subsubCACRL.pem
new file mode 100644
index 0000000000..7754862b2e
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy10subsubCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB0zCBvAIBATANBgkqhkiG9w0BAQsFADBZMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEpMCcGA1UEAxMgcmVxdWlyZUV4cGxp
+Y2l0UG9saWN5MTAgc3Vic3ViQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4MzAw
+MFqgLzAtMB8GA1UdIwQYMBaAFFhQTw7y/nIkpNB3P6CWLHe1JOghMAoGA1UdFAQD
+AgEBMA0GCSqGSIb3DQEBCwUAA4IBAQBc9QUsQJu8eEkhD/bB2k137z1Tw2E+SOGM
+InCgU/5FjqgVS8frk2POJXSyTdZonYpJvj3fEuXLp/eViZ0+V3oe31vnFtzeQ9qv
+//rOvJd0b3yOtLFAB58oF5yms/4Zj2ekeWU38HUrQ8lVrT3p0nj7V49ENlaiXwVD
+vhsaTShUxHnVPb5W4nX/uvl6PUWXZLwzWvr3foaAbf0rgV3eWhpjspPlE0ajF0Tk
+ButtK76M4AJocWeWr1AupATbtGU+vvi+I5D7YrBGn7qxF9BvzMiq65H4YHnNfiiF
+iVtgU+GXZxft7+hmVYgX5eQKcDhSQdKKB05U8r2Q5ZRFq8o+b/Vr
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy10subsubsubCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy10subsubsubCACRL.pem
new file mode 100644
index 0000000000..caac766953
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy10subsubsubCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB1jCBvwIBATANBgkqhkiG9w0BAQsFADBcMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEsMCoGA1UEAxMjcmVxdWlyZUV4cGxp
+Y2l0UG9saWN5MTAgc3Vic3Vic3ViQ0EXDTEwMDEwMTA4MzAwMFoXDTMwMTIzMTA4
+MzAwMFqgLzAtMB8GA1UdIwQYMBaAFJaMcfwVqDvO2cT4w9BfaXF86ABLMAoGA1Ud
+FAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQBzlq+27lis3jgVun42HmkOAJ9zzdIt
+iyptjiWBCLV5lLA3gbiuroQbr6cKYWhP/qQ91g7MgSzvq/cVwCudSeqIOCJZUwRu
+Kpu6AKkK77GfWA2/GC4ZtIhsHIyA0P0MTa2ygmtxIn0ufluNzgEognWxF4Kdd0F6
+g1sJL547W8byiNlD6KtZ8Oe9PQOr1tevTWvWgSRj2bitAfcwrEBSsyG1eu/Yyeun
+opopG2H28TuBcitgZA7mjicFqzibabUUA+hqZ/X5cL+JiR+84VWc3o5fPFwpdAWr
+09gYI6qG+5O4q7tIyb8d8dIVO+FcKV+mkbZDpFu+3VWRFY4GkBjq98uJ
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy2CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy2CACRL.pem
new file mode 100644
index 0000000000..acf0e69c78
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy2CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzDCBtQIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZcmVxdWlyZUV4cGxp
+Y2l0UG9saWN5MiBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0w
+HwYDVR0jBBgwFoAUNqnZ+6o4L6D3TDvZhZ2aFaMtqccwCgYDVR0UBAMCAQEwDQYJ
+KoZIhvcNAQELBQADggEBAD8YETFOSpFWhTbHdjwH+oNciH7CRTbs6UkICQVsnIN4
+xt8m4Pvho9VeU9KNeIvmcaKaJk8HrxbhKlluWFUS/IMk+U6SQ3QSdnxLtJdvC0JT
+iARR9dKR5YX/G0JHJaAO3ULSu8Gaj093TFfQPs2ALcfg5G6BbQmxJ6qCwp/IZ61T
+x71148Lqbb0k2JVZgnnPkhe1k/7no2rjmvu4Zp0BuFkQIwceN908LGSZmuVf09R9
+6FUkYhY5s6tM0rHLLS0JGgCuYyl6RTeD/OemNh4QfA6z6N+WmvAUwzbRWtm/gDOx
+hQq+8Qcc+HErYcZfSg9cgJqRGb1J8KGGd+92uK1wHmo=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy2subCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy2subCACRL.pem
new file mode 100644
index 0000000000..426415e452
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy2subCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzzCBuAIBATANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMccmVxdWlyZUV4cGxp
+Y2l0UG9saWN5MiBzdWJDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAv
+MC0wHwYDVR0jBBgwFoAUIHf+TDCN4rNRHY+w9xx/HYOYDkcwCgYDVR0UBAMCAQEw
+DQYJKoZIhvcNAQELBQADggEBAHnk7z+QEkfo+N/q7+bAHDhYCm1ax7Vg1PSs/3WE
+OvoTOp65ghyIX7UdKdmUTpefa89C2PRORNB06xIYzQSeCkCoq7bpTW0hzMfPweY3
+MwlEqnllWldcWgczSOxsomOjJ6os81onh9ZyICGbIZLPL+HZtfPpXKdyw7riGAm3
+h3V0pHznhgcm4XEpe6iHovoFbdmWs73G0vSjLnTyDmSBVjAiEVnZLut10BGyjCRq
+ZQjLcXfXtF1aFymk1p/eN5QLMaNZ59uoGNgsjRQmod7H1Lezp0r53yA1bg9P7yXU
+RsY/pvoiI9j5t3svgZWKC5wuTmJ7nMTwlqaZDS2nWAw3/TE=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy4CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy4CACRL.pem
new file mode 100644
index 0000000000..c96cbf6314
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy4CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzDCBtQIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZcmVxdWlyZUV4cGxp
+Y2l0UG9saWN5NCBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0w
+HwYDVR0jBBgwFoAUzdHczNQxYwcsXTaxD42edb5LXmMwCgYDVR0UBAMCAQEwDQYJ
+KoZIhvcNAQELBQADggEBACOdVMcZUqu3gJlw13ZK7/NcOtSAuvEOVHfjChSXRFkp
+gVhiUJqPQYg0fs6eORxMRc/EyKUTNeKQE/08Q0pN69TSShhHJgrbI0qL+z+1l+OA
+615L/Z658Nv7uKLt0nk/RkguMQw2xIlUEKvC1S/MQAcJAiBKPnSA7fCb93ph053o
+ZOVorML758OWTjvXGykpiJMbxgdS1MQpSRrU3FGST+auQhI4Qet5QpMlA9nfHwgB
+l4lUkF73iHwV8LNHI8t/Pnd5LkKd6XWiDrQRAzhrh/UhmcspUJyFlLIxthO2Az6n
+/FIQMAHm0mvyrgmmZSsw8HCseOgTNCnQEEnWLodqabI=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy4subCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy4subCACRL.pem
new file mode 100644
index 0000000000..332b2ec9e5
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy4subCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzzCBuAIBATANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMccmVxdWlyZUV4cGxp
+Y2l0UG9saWN5NCBzdWJDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAv
+MC0wHwYDVR0jBBgwFoAUfe8OlBe79qeX5tgiSENIrLPuuo0wCgYDVR0UBAMCAQEw
+DQYJKoZIhvcNAQELBQADggEBALIg2yo0C0OaDGoUWWB1PeKkFzO29Zrz7os0w6Ta
+c4W0ufJ/V7W6GTWtNjN2zoVhWe1DJzAivJejwI89ES8kpKJvQ0FIqSmeKk6v7qM6
+gZuhVsvemsw7mb2LVd7t6ismBYCbYTBnoHc/dW+zgHLXNsjHA7aIq3zEzeiJPxgy
+qf4a48BXm8WKQVFLAJv28l/B3nanW2+rYMnEMUBlI7ytGE/gcZ5WB3x8i/NxQAa1
+mBBrHVFyNLJX1pxCmg1myP9dXj1ljlSwRHVgxfYhVcfl5H72cJg/zTQNELpqjlqO
+kM8wXuKpxsFsJpGBOfl3zjeCeFmjOyucmB/CZT3L9h+H9sY=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy4subsubCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy4subsubCACRL.pem
new file mode 100644
index 0000000000..ab40c50e73
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy4subsubCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB0jCBuwIBATANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEoMCYGA1UEAxMfcmVxdWlyZUV4cGxp
+Y2l0UG9saWN5NCBzdWJzdWJDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAw
+WqAvMC0wHwYDVR0jBBgwFoAUqerm056wCZev5/4eLhAyoRBnTIYwCgYDVR0UBAMC
+AQEwDQYJKoZIhvcNAQELBQADggEBAD08KCdOiCGTM5PYyFE+HRlYaBd1VnGIFiAb
+fCdTAlEmK+/NxqlrBGqz1zx6O09X4u/XsmvwI5Pi9ujsyxN/aHR16/JBWfUEPKDg
+2a7XOoAyKWO623Z78xWD4DbfQo32vsyDpe2ydCnYiX7qPf3muC7KNROeHMt1QwK0
+/T89l2NJmPBE5+sSCMMZ+8tY1GQgVTeNczO8zzoYcG5XZrKs503sfLvISvcCpre+
+l/LeByAhkJpr+/wlR8+eTrUMpZIhnB8x9uk9hi0YBBbdKmAR8Sqc4U/2yUPFp6ue
+FyF/txO3HXmTNYLFSYo0+G8uEkQCOFQn7BHJOybYH6ertxgKhdQ=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy4subsubsubCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy4subsubsubCACRL.pem
new file mode 100644
index 0000000000..986abff429
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy4subsubsubCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB1TCBvgIBATANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTErMCkGA1UEAxMicmVxdWlyZUV4cGxp
+Y2l0UG9saWN5NCBzdWJzdWJzdWJDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgz
+MDAwWqAvMC0wHwYDVR0jBBgwFoAUFLvRJvSegTyLDhLP2XsVsizcoyEwCgYDVR0U
+BAMCAQEwDQYJKoZIhvcNAQELBQADggEBAC0JNUPn/JJeMGuu1cv0PUV36H5zZk3z
+KXq6TT6CRatXHsIRl7bwvsJ2wnkkT4QUM0xeVl8Q50Thm/P81vxVb48w3ahA/mm8
+QtxJwkPK9VPV+jkfAW5vcTVzJZlr9EWhuYgfqC0KdUUiE2omtydtinQhGdI0ooey
+U5XP6voQwf8BKCYOgXxQNJtRE1+W96SifSUQr07fN7gXUp2MgZYwp8QPjFZrX5dH
+FqgmhSv6rdjO9knE/guw21FzA0F5rM6HjNuxre3qont7vlzpI9sx7VzrR4J87meb
+DhRujiMvn1Ge6qwNPGgSnd8P/LsA8kltmewk93W94u74GqfwQCtFtxk=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy5CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy5CACRL.pem
new file mode 100644
index 0000000000..6b45ed261f
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy5CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzDCBtQIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZcmVxdWlyZUV4cGxp
+Y2l0UG9saWN5NSBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0w
+HwYDVR0jBBgwFoAUu5GDq66u3lzY4PKQPFz6ny7hOWgwCgYDVR0UBAMCAQEwDQYJ
+KoZIhvcNAQELBQADggEBAMz51cm+tJdOQUKRaISFOoTqH2PSV3W1i/VLNoo60huI
+wSIOg0YNxG2wXxFH5UdH+SdRacD3qHlAKKyTsWgvhqZgdgbgieS4Nc1CpGnyxeXk
+FCdGt4OJ6mEToXFqJayWwR25ckoJp8k7gpseERoqgDCTPvKjp+1yrznlX8VWTKya
+dgVr+LgSLzCHY8HYekoKcQRbFWbnMBw5K7VE06CLJJIx9kHgDOU+Zqxjy+cilIIb
+HxMmsrxCwKW+ARA/LBiLpn26m9SC/fHstIopRML+1zkbXCoad2VwB9GyvLwzAoqn
+MwJuDzT0G/MZCB4n/s5J/urXFkYBVCQpivlfX9tNUU0=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy5subCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy5subCACRL.pem
new file mode 100644
index 0000000000..29a2c67261
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy5subCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzzCBuAIBATANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTElMCMGA1UEAxMccmVxdWlyZUV4cGxp
+Y2l0UG9saWN5NSBzdWJDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAv
+MC0wHwYDVR0jBBgwFoAUN9O/3txQx6/IiuiSsMRIYfA6BAEwCgYDVR0UBAMCAQEw
+DQYJKoZIhvcNAQELBQADggEBANAIgl9rVP+LLEYRL1+oori60bQTlB1+1LBFItkp
+7BfodwaAGRmWO4GV6phJzxjpi1aKVGuCg7vlwzS+/ns0mlAaghPxpelwd/KACsv1
+AnrbnVR7AW9z6/ipRID0K1V+8EJmjUdD05BjXoyDKP5Jg2v1joSB306Lv7EDGqBh
+babIXd9ZVrMJBFhW8Zp9A/c/P72LrfRkDBi5rhxI8lJeDUPTfQVUGn0nh2MHx2LQ
+vDd++QtcVY+4tPwkiNJiVNBu5dec8DBuGwNcxcZ2FnpExVglJuFf9AXlXPlXs1Ri
+6+WLqQ6sFjS8R0NhYyILqm/JtXO9mKzXAwa53nCXPytwtPk=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy5subsubCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy5subsubCACRL.pem
new file mode 100644
index 0000000000..9370cde1bf
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy5subsubCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB0jCBuwIBATANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEoMCYGA1UEAxMfcmVxdWlyZUV4cGxp
+Y2l0UG9saWN5NSBzdWJzdWJDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAw
+WqAvMC0wHwYDVR0jBBgwFoAU+IIvef+0fggC21uvMp3kNWG1bBswCgYDVR0UBAMC
+AQEwDQYJKoZIhvcNAQELBQADggEBABWp0q1/e5b14+ebJrBOiLc2iTt8KlT0ycPq
+EjyoPsQAO6krSC8L+PdSOSv4if2Udf9Xrgrk5zvDIBkVrv7+QlR0A/5kBRukZimS
+L0Q5lCJjpBmvgZRu/c5bYm32iIfJtwwEgXN4fNh3QESi+KGB+IopD9+/TxV8nAWn
+bTqJ3YPGM/tlmkpLHQD7lt7PAHe/ofrkJc8L6ircKUzmZ4vce3HQtQ79rlbyOLxW
+bN7O9mfUymz4SN/gsnll4HpJKrSBTeINssUcCUwpZ6p1IJ0/tmZHpF39HZo1W0ts
+ZB6DWqnOL5lWsw3x/QiKVgvfPjKA1mvqsXVhy/xvNFGT3kyNcC8=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy5subsubsubCACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy5subsubsubCACRL.pem
new file mode 100644
index 0000000000..db6c01924b
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy5subsubsubCACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB1TCBvgIBATANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTErMCkGA1UEAxMicmVxdWlyZUV4cGxp
+Y2l0UG9saWN5NSBzdWJzdWJzdWJDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgz
+MDAwWqAvMC0wHwYDVR0jBBgwFoAU+mK6vX5eX98fuge+H3k3gtz8EygwCgYDVR0U
+BAMCAQEwDQYJKoZIhvcNAQELBQADggEBAGQii0uxuUm9ok8RNEseRwlN5+lK2R2A
+VZUJ+vZ/O+4ye3x1RIcZ38oWF8zrGZqp6Afos6JbZLSUAGRrbmYowxXCT3vV3yA5
+SBdIoXsByE2Kh6dyeNbB/jDFRNP5rbKcwJJGqXrfnRbHXOOizHPMmWTBscj9lit6
+HIzQhlURn1bHP2GcQ17uBGSYpSVhVV247dlt4+HgReog9NC8D26xPVdnaodtBYvp
+oknWHAcjehSi5kjt4/DJ0Fym3yHGbwpkKWT0A7RXK6cCRWfvJDnGu5vrIKigQo7q
+z4ZIKE1aO2tXJ98dc8M6Z6u1MZDnn3n/9JUAhZPtZ9Gb4eEUU+qgrRk=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy7CACRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy7CACRL.pem
new file mode 100644
index 0000000000..99d47f5020
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy7CACRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBzDCBtQIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEiMCAGA1UEAxMZcmVxdWlyZUV4cGxp
+Y2l0UG9saWN5NyBDQRcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAwWqAvMC0w
+HwYDVR0jBBgwFoAUbDGXATUg3ts15QppWFmIZMwhzkowCgYDVR0UBAMCAQEwDQYJ
+KoZIhvcNAQELBQADggEBAHC+EDnf6+cnW0GTLMwWoISAn/jJ++FGGwmSv7O8st49
+YmlngcgSQdE1CmcLFM8Lsv390rQwtm57E89aLHSpSbVXvAS/ZvyS5yRgoxGJLw5r
+ulwKqAmjzrXPB/0A7mjLwXVxLBZTAqJgnIFW+qE679S4SKLWOsc66HRFsdQmFbwe
+BiF1/V5PbM83sNyN+boyBm1w5YrasEIWLajc+s+gF1dbQTKuDziD52azMegWvfIO
+xqixHCdK+CpIFObodAnW2gPHWTicXYH+ZwagtqQbI2EM7SdnbvQQe68frsfqK1k/
+SGXl0LfQl3/GmYynOg46FDf53/oRxz0bwsEa8XBpXpY=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy7subCARE2CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy7subCARE2CRL.pem
new file mode 100644
index 0000000000..dd8aaf35a7
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy7subCARE2CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB0jCBuwIBATANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEoMCYGA1UEAxMfcmVxdWlyZUV4cGxp
+Y2l0UG9saWN5NyBzdWJDQVJFMhcNMTAwMTAxMDgzMDAwWhcNMzAxMjMxMDgzMDAw
+WqAvMC0wHwYDVR0jBBgwFoAU51wljn6qTHeDe8PqadbHojThNFkwCgYDVR0UBAMC
+AQEwDQYJKoZIhvcNAQELBQADggEBACgCaW8g9ZHgkL+vcByM70Ao9B8BhlunjYHK
+905EiAQQ3OqjJzEE5YRp0uhrbChY1xoHKAjE45VIhK1aADKyV5Wt+ugBAoFLAPcN
+9FQwvTEBjUwZPCQaV54hyt/PrDBh8GJxnTpLnEb/+gl/hu2P1tDD0Zqb4BPoOxur
+abZ0PpzSCPHJdQq75RX/KZCEkaOsa4wHslFHXJXlLLh5vRqvrM23NDsY9lsNb9+3
+3mSVngQWhqVJNdFsMJisyzq88Iv3cSmgzD4oowE05khNWWhpbgxtdMYGWVqN2qEg
+EDI3oExT5CeehzLWuI7dnhKZVJl7y68n1s7KHKJtMb9vnGsiNZ4=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy7subsubCARE2RE4CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy7subsubCARE2RE4CRL.pem
new file mode 100644
index 0000000000..cce599a5fb
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy7subsubCARE2RE4CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB2DCBwQIBATANBgkqhkiG9w0BAQsFADBeMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEuMCwGA1UEAxMlcmVxdWlyZUV4cGxp
+Y2l0UG9saWN5NyBzdWJzdWJDQVJFMlJFNBcNMTAwMTAxMDgzMDAwWhcNMzAxMjMx
+MDgzMDAwWqAvMC0wHwYDVR0jBBgwFoAUbv+NCItm/pule/tkM2XqA5VIlJgwCgYD
+VR0UBAMCAQEwDQYJKoZIhvcNAQELBQADggEBADsVgmLjUlCjkqyM30ho6gvaBfoZ
+3IEMbL01Z1YWCVL/M7dkcp2H98jCurGWlEQCqlx8gXZRrrO8u7rtpHKu0oUuCcrC
+6bxljOwBRgdv0TnNB3k+FrXcaBT7/SJtGhLwjh0smLC69eI42quLSEXXHhlpmYiJ
+1cOQwPCtd+KHbeDMoKi6j7HbFD3OR7jH+OsbnwMpWdlyhDeZlXXh5vbLXtN/j6VH
+9TWdi/Tt6z049i5YcCL2l5Kq9Mp/Y2DRpLQAycHpYL+/U8yOyUq3A3MYO/fdWo1k
+H0nSPreisWgBkSD/u11jR/hPbEH9SXv2nflBaRg/9kSoAbuDknlvrLGxwbQ=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy7subsubsubCARE2RE4CRL.pem b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy7subsubsubCARE2RE4CRL.pem
new file mode 100644
index 0000000000..bd1656505c
--- /dev/null
+++ b/lib/public_key/test/pkits_SUITE_data/pkits/crls/requireExplicitPolicy7subsubsubCARE2RE4CRL.pem
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIB2zCBxAIBATANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEfMB0GA1UE
+ChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTExMC8GA1UEAxMocmVxdWlyZUV4cGxp
+Y2l0UG9saWN5NyBzdWJzdWJzdWJDQVJFMlJFNBcNMTAwMTAxMDgzMDAwWhcNMzAx
+MjMxMDgzMDAwWqAvMC0wHwYDVR0jBBgwFoAUeyxRYTEVrawsa6m+OzsYGpKqf0Qw
+CgYDVR0UBAMCAQEwDQYJKoZIhvcNAQELBQADggEBAKC0+mcSVMrZw/Yabdg8xvnX
+VJrufKnwa2sdt5WXbKX73DCh2OvTm5gJg61AkjghRN4W1VfHpQqc6lsrWHlFK+6r
+GbsL/og+JwfDgiHr+xLf9hmxlS2Uu+TK1HYUVGw/VNLoLPqre1tq4ag4W7re2Z3g
+BBZ8OyS0aUcMYpI1rp9/+PWOYo/9cEDFK2zlsIazYl0Nk8Jz8xWVzFP4gf5RXb5i
+ejUZI578baWPUfUUnEQMSqiKJmHNxPyY6REVUEFkMDu5dOlCu0GfsLBw61am3hGQ
+XvILnAB1SRdyO5uNlJLkRh9EB5aUDRUC5HydfiaSTzb0gkzdKgCRjUUsUjovcPg=
+-----END X509 CRL-----
diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl
index 2b83bc0a5c..ea48479f0b 100644
--- a/lib/public_key/test/public_key_SUITE.erl
+++ b/lib/public_key/test/public_key_SUITE.erl
@@ -20,85 +20,19 @@
%%
-module(public_key_SUITE).
+-include_lib("common_test/include/ct.hrl").
+-include_lib("public_key/include/public_key.hrl").
+
%% Note: This directive should only be used in test suites.
-compile(export_all).
-%%-include_lib("common_test/include/ct.hrl").
--include_lib("test_server/include/test_server.hrl").
-
--include_lib("public_key/include/public_key.hrl").
-
-define(TIMEOUT, 120000). % 2 min
-%% Test server callback functions
-%%--------------------------------------------------------------------
-%% Function: init_per_suite(Config) -> Config
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Initialization before the whole suite
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
-init_per_suite(Config) ->
- try crypto:start() of
- ok ->
- Config
- catch _:_ ->
- {skip, "Crypto did not start"}
- end.
-%%--------------------------------------------------------------------
-%% Function: end_per_suite(Config) -> _
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after the whole suite
-%%--------------------------------------------------------------------
-end_per_suite(_Config) ->
- application:stop(crypto).
-
-%%--------------------------------------------------------------------
-%% Function: init_per_testcase(TestCase, Config) -> Config
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%%
-%% Description: Initialization before each test case
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%% Description: Initialization before each test case
-%%--------------------------------------------------------------------
-init_per_testcase(_TestCase, Config0) ->
- Config = lists:keydelete(watchdog, 1, Config0),
- Dog = test_server:timetrap(?TIMEOUT),
- [{watchdog, Dog} | Config].
%%--------------------------------------------------------------------
-%% Function: end_per_testcase(TestCase, Config) -> _
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after each test case
+%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
-end_per_testcase(_TestCase, Config) ->
- Dog = ?config(watchdog, Config),
- case Dog of
- undefined ->
- ok;
- _ ->
- test_server:timetrap_cancel(Dog)
- end.
-%%--------------------------------------------------------------------
-%% Function: all(Clause) -> TestCases
-%% Clause - atom() - suite | doc
-%% TestCases - [Case]
-%% Case - atom()
-%% Name of a test case.
-%% Description: Returns a list of all test cases in this test suite
-%%--------------------------------------------------------------------
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
@@ -119,30 +53,46 @@ groups() ->
ssh_openssh_public_key_long_header]},
{sign_verify, [], [rsa_sign_verify, dsa_sign_verify]}
].
+%%-------------------------------------------------------------------
+init_per_suite(Config) ->
+ try crypto:start() of
+ ok ->
+ Config
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+end_per_suite(_Config) ->
+ application:stop(crypto).
+
+%%-------------------------------------------------------------------
init_per_group(_GroupName, Config) ->
Config.
end_per_group(_GroupName, Config) ->
Config.
+%%-------------------------------------------------------------------
+init_per_testcase(_TestCase, Config0) ->
+ Config = lists:keydelete(watchdog, 1, Config0),
+ Dog = ct:timetrap(?TIMEOUT),
+ [{watchdog, Dog} | Config].
-%% Test cases starts here.
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
-app(doc) ->
- "Test that the public_key app file is ok";
-app(suite) ->
- [];
+app() ->
+ [{doc, "Test that the public_key app file is ok"}].
app(Config) when is_list(Config) ->
- ok = test_server:app_test(public_key).
+ ok = ?t:app_test(public_key).
%%--------------------------------------------------------------------
-dsa_pem(doc) ->
- [""];
-dsa_pem(suite) ->
- [];
+dsa_pem() ->
+ [{doc, "DSA PEM-file decode/encode"}].
dsa_pem(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
@@ -164,10 +114,8 @@ dsa_pem(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
-rsa_pem(doc) ->
- [""];
-rsa_pem(suite) ->
- [];
+rsa_pem() ->
+ [{doc, "RSA PEM-file decode/encode"}].
rsa_pem(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
[{'RSAPrivateKey', DerRSAKey, not_encrypted} = Entry0 ] =
@@ -201,10 +149,8 @@ rsa_pem(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
-encrypted_pem(doc) ->
- [""];
-encrypted_pem(suite) ->
- [];
+encrypted_pem() ->
+ [{doc, "Encrypted PEM-file decode/encode"}].
encrypted_pem(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
@@ -234,10 +180,8 @@ encrypted_pem(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
-dh_pem(doc) ->
- [""];
-dh_pem(suite) ->
- [];
+dh_pem() ->
+ [{doc, "DH parametrs PEM-file decode/encode"}].
dh_pem(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
[{'DHParameter', DerDH, not_encrypted} = Entry] =
@@ -252,10 +196,8 @@ dh_pem(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
-pkcs10_pem(doc) ->
- [""];
-pkcs10_pem(suite) ->
- [];
+pkcs10_pem() ->
+ [{doc, "PKCS-10 PEM-file decode/encode"}].
pkcs10_pem(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
[{'CertificationRequest', DerPKCS10, not_encrypted} = Entry] =
@@ -269,10 +211,8 @@ pkcs10_pem(Config) when is_list(Config) ->
Entry = public_key:pem_entry_encode('CertificationRequest', PKCS10).
%%--------------------------------------------------------------------
-pkcs7_pem(doc) ->
- [""];
-pkcs7_pem(suite) ->
- [];
+pkcs7_pem() ->
+ [{doc, "PKCS-7 PEM-file decode/encode"}].
pkcs7_pem(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
[{'ContentInfo', DerPKCS7, not_encrypted} = Entry] =
@@ -286,10 +226,8 @@ pkcs7_pem(Config) when is_list(Config) ->
Entry = public_key:pem_entry_encode('ContentInfo', PKCS7).
%%--------------------------------------------------------------------
-cert_pem(doc) ->
- [""];
-cert_pem(suite) ->
- [];
+cert_pem() ->
+ [{doc, "Certificate PEM-file decode/encode"}].
cert_pem(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
@@ -315,10 +253,8 @@ cert_pem(Config) when is_list(Config) ->
[Entry0] = erl_make_certs:pem_to_der(filename:join(Datadir, "wdsa.pem")).
%%--------------------------------------------------------------------
-ssh_rsa_public_key(doc) ->
- "";
-ssh_rsa_public_key(suite) ->
- [];
+ssh_rsa_public_key() ->
+ [{doc, "ssh rsa public key decode/encode"}].
ssh_rsa_public_key(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
@@ -343,10 +279,8 @@ ssh_rsa_public_key(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
-ssh_dsa_public_key(doc) ->
- "";
-ssh_dsa_public_key(suite) ->
- [];
+ssh_dsa_public_key() ->
+ [{doc, "ssh dsa public key decode/encode"}].
ssh_dsa_public_key(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
@@ -370,10 +304,8 @@ ssh_dsa_public_key(Config) when is_list(Config) ->
public_key:ssh_decode(EncodedOpenSsh, public_key).
%%--------------------------------------------------------------------
-ssh_rfc4716_rsa_comment(doc) ->
- "Test comment header and rsa key";
-ssh_rfc4716_rsa_comment(suite) ->
- [];
+ssh_rfc4716_rsa_comment() ->
+ [{doc, "Test comment header and rsa key"}].
ssh_rfc4716_rsa_comment(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
@@ -388,10 +320,8 @@ ssh_rfc4716_rsa_comment(Config) when is_list(Config) ->
RSARawSsh2 = public_key:ssh_encode([{PubKey, Attributes}], rfc4716_public_key).
%%--------------------------------------------------------------------
-ssh_rfc4716_dsa_comment(doc) ->
- "Test comment header and dsa key";
-ssh_rfc4716_dsa_comment(suite) ->
- [];
+ssh_rfc4716_dsa_comment() ->
+ [{doc, "Test comment header and dsa key"}].
ssh_rfc4716_dsa_comment(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
@@ -410,10 +340,8 @@ ssh_rfc4716_dsa_comment(Config) when is_list(Config) ->
public_key:ssh_decode(Encoded, public_key).
%%--------------------------------------------------------------------
-ssh_rfc4716_rsa_subject(doc) ->
- "Test another header value than comment";
-ssh_rfc4716_rsa_subject(suite) ->
- [];
+ssh_rfc4716_rsa_subject() ->
+ [{doc, "Test another header value than comment"}].
ssh_rfc4716_rsa_subject(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
@@ -432,10 +360,8 @@ ssh_rfc4716_rsa_subject(Config) when is_list(Config) ->
public_key:ssh_decode(Encoded, public_key).
%%--------------------------------------------------------------------
-ssh_known_hosts(doc) ->
- "";
-ssh_known_hosts(suite) ->
- [];
+ssh_known_hosts() ->
+ [{doc, "ssh known hosts file encode/decode"}].
ssh_known_hosts(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
@@ -463,10 +389,8 @@ ssh_known_hosts(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
-ssh1_known_hosts(doc) ->
- "";
-ssh1_known_hosts(suite) ->
- [];
+ssh1_known_hosts() ->
+ [{doc, "ssh (ver 1) known hosts file encode/decode"}].
ssh1_known_hosts(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
@@ -485,10 +409,8 @@ ssh1_known_hosts(Config) when is_list(Config) ->
Decoded = public_key:ssh_decode(Encoded, known_hosts).
%%--------------------------------------------------------------------
-ssh_auth_keys(doc) ->
- "";
-ssh_auth_keys(suite) ->
- [];
+ssh_auth_keys() ->
+ [{doc, "ssh authorized keys file encode/decode"}].
ssh_auth_keys(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
@@ -513,10 +435,8 @@ ssh_auth_keys(Config) when is_list(Config) ->
Decoded = public_key:ssh_decode(Encoded, auth_keys).
%%--------------------------------------------------------------------
-ssh1_auth_keys(doc) ->
- "";
-ssh1_auth_keys(suite) ->
- [];
+ssh1_auth_keys() ->
+ [{doc, "ssh (ver 1) authorized keys file encode/decode"}].
ssh1_auth_keys(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
@@ -543,10 +463,8 @@ ssh1_auth_keys(Config) when is_list(Config) ->
Decoded = public_key:ssh_decode(Encoded, auth_keys).
%%--------------------------------------------------------------------
-ssh_openssh_public_key_with_comment(doc) ->
- "Test that emty lines and lines starting with # are ignored";
-ssh_openssh_public_key_with_comment(suite) ->
- [];
+ssh_openssh_public_key_with_comment() ->
+ [{doc, "Test that emty lines and lines starting with # are ignored"}].
ssh_openssh_public_key_with_comment(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
@@ -554,10 +472,8 @@ ssh_openssh_public_key_with_comment(Config) when is_list(Config) ->
[{{_, #'Dss-Parms'{}}, _}] = public_key:ssh_decode(DSARawOpenSsh, openssh_public_key).
%%--------------------------------------------------------------------
-ssh_openssh_public_key_long_header(doc) ->
- "Test that long headers are handled";
-ssh_openssh_public_key_long_header(suite) ->
- [];
+ssh_openssh_public_key_long_header() ->
+ [{doc, "Test that long headers are handled"}].
ssh_openssh_public_key_long_header(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
@@ -568,10 +484,8 @@ ssh_openssh_public_key_long_header(Config) when is_list(Config) ->
Decoded = public_key:ssh_decode(Encoded, rfc4716_public_key).
%%--------------------------------------------------------------------
-encrypt_decrypt(doc) ->
- [""];
-encrypt_decrypt(suite) ->
- [];
+encrypt_decrypt() ->
+ [{doc, "Test public_key:encrypt_private and public_key:decrypt_public"}].
encrypt_decrypt(Config) when is_list(Config) ->
{PrivateKey, _DerKey} = erl_make_certs:gen_rsa(64),
#'RSAPrivateKey'{modulus=Mod, publicExponent=Exp} = PrivateKey,
@@ -588,10 +502,8 @@ encrypt_decrypt(Config) when is_list(Config) ->
ok.
%%--------------------------------------------------------------------
-rsa_sign_verify(doc) ->
- ["Checks that we can sign and verify rsa signatures."];
-rsa_sign_verify(suite) ->
- [];
+rsa_sign_verify() ->
+ [{doc, "Checks that we can sign and verify rsa signatures."}].
rsa_sign_verify(Config) when is_list(Config) ->
Ca = {_, CaKey} = erl_make_certs:make_cert([]),
{Cert1, _} = erl_make_certs:make_cert([{key, dsa}, {issuer, Ca}]),
@@ -611,10 +523,8 @@ rsa_sign_verify(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
-dsa_sign_verify(doc) ->
- ["Checks that we can sign and verify dsa signatures."];
-dsa_sign_verify(suite) ->
- [];
+dsa_sign_verify() ->
+ [{doc, "Checks that we can sign and verify dsa signatures."}].
dsa_sign_verify(Config) when is_list(Config) ->
Ca = erl_make_certs:make_cert([]),
CertInfo = {_,CertKey1} = erl_make_certs:make_cert([{key, dsa}, {issuer, Ca}]),
@@ -650,10 +560,8 @@ dsa_sign_verify(Config) when is_list(Config) ->
{DSAPublicKey, DSAParams}).
%%--------------------------------------------------------------------
-pkix(doc) ->
- "Misc pkix tests not covered elsewhere";
-pkix(suite) ->
- [];
+pkix() ->
+ [{doc, "Misc pkix tests not covered elsewhere"}].
pkix(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
Certs0 = erl_make_certs:pem_to_der(filename:join(Datadir, "cacerts.pem")),
@@ -691,17 +599,15 @@ pkix(Config) when is_list(Config) ->
[[{'AttributeTypeAndValue', {2,5,4,3},{printableString,"ERLANGCA"}}],
[{'AttributeTypeAndValue', {2,5,4,3},{printableString," erlang ca "}}]]},
VerifyStr = {rdnSequence,
- [[{'AttributeTypeAndValue', {2,5,4,3},{printableString,"erlang ca"}}],
- [{'AttributeTypeAndValue', {2,5,4,3},{printableString,"erlangca"}}]]},
+ [[{'AttributeTypeAndValue', {2,5,4,3},{printableString,"erlangca"}}],
+ [{'AttributeTypeAndValue', {2,5,4,3},{printableString,"erlang ca"}}]]},
VerifyStr = public_key:pkix_normalize_name(TestStr),
ok.
%%--------------------------------------------------------------------
-pkix_countryname(doc) ->
- "Test workaround for certs that code x509countryname as utf8";
-pkix_countryname(suite) ->
- [];
+pkix_countryname() ->
+ [{doc, "Test workaround for certs that code x509countryname as utf8"}].
pkix_countryname(Config) when is_list(Config) ->
Cert = incorrect_pkix_cert(),
OTPCert = public_key:pkix_decode_cert(Cert, otp),
@@ -711,24 +617,9 @@ pkix_countryname(Config) when is_list(Config) ->
check_countryname(Issuer),
check_countryname(Subj).
-check_countryname({rdnSequence,DirName}) ->
- do_check_countryname(DirName).
-do_check_countryname([]) ->
- ok;
-do_check_countryname([#'AttributeTypeAndValue'{type = ?'id-at-countryName',
- value = "US"}|_]) ->
- ok;
-do_check_countryname([#'AttributeTypeAndValue'{type = ?'id-at-countryName',
- value = Value}|_]) ->
- test_server:fail({incorrect_cuntry_name, Value});
-do_check_countryname([_| Rest]) ->
- do_check_countryname(Rest).
-
%%--------------------------------------------------------------------
-pkix_path_validation(doc) ->
- "Misc pkix tests not covered elsewhere";
-pkix_path_validation(suite) ->
- [];
+pkix_path_validation() ->
+ [{doc, "Test PKIX path validation"}].
pkix_path_validation(Config) when is_list(Config) ->
CaK = {Trusted,_} =
erl_make_certs:make_cert([{key, dsa},
@@ -759,7 +650,8 @@ pkix_path_validation(Config) when is_list(Config) ->
CertK3 = {Cert3,_} = erl_make_certs:make_cert([{issuer, CertK1},
{extensions, [{basic_constraints, false}]}]),
- {Cert4,_} = erl_make_certs:make_cert([{issuer, CertK3}]),
+ {Cert4,_} = erl_make_certs:make_cert([{issuer, CertK3}, {extensions, [{key_usage, undefined}]}]),
+
{error, {bad_cert,missing_basic_constraint}} =
public_key:pkix_path_validation(Trusted, [Cert1, Cert3,Cert4], []),
@@ -796,6 +688,21 @@ pkix_path_validation(Config) when is_list(Config) ->
public_key:pkix_path_validation(unknown_ca, [Cert1], [{verify_fun,
VerifyFunAndState1}]),
ok.
+%%--------------------------------------------------------------------
+%% Internal functions ------------------------------------------------
+%%--------------------------------------------------------------------
+check_countryname({rdnSequence,DirName}) ->
+ do_check_countryname(DirName).
+do_check_countryname([]) ->
+ ok;
+do_check_countryname([#'AttributeTypeAndValue'{type = ?'id-at-countryName',
+ value = "US"}|_]) ->
+ ok;
+do_check_countryname([#'AttributeTypeAndValue'{type = ?'id-at-countryName',
+ value = Value}|_]) ->
+ ct:fail({incorrect_cuntry_name, Value});
+do_check_countryname([_| Rest]) ->
+ do_check_countryname(Rest).
check_entry_type(#'DSAPrivateKey'{}, 'DSAPrivateKey') ->
true;
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
index a0afb5056e..7f7d887d5e 100644
--- a/lib/ssh/doc/src/ssh.xml
+++ b/lib/ssh/doc/src/ssh.xml
@@ -188,6 +188,9 @@
<p>Provide, in bytes, when rekeying should be initiated,
defaults to one time each GB and one time per hour.</p>
</item>
+ <tag><c><![CDATA[{idle_time, integer()}]]></c></tag>
+ <item>
+ <p>Sets a timeout on connection when no channels are active, default is infinity</p></item>
</taglist>
</desc>
</func>
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index d24e2fff44..9a01e85006 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -94,7 +94,6 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) ->
%% the other function collections contain {Function, Arity}.
-record(lint, {state=start :: 'start' | 'attribute' | 'function',
module=[], %Module
- extends=[], %Extends
behaviour=[], %Behaviour
exports=gb_sets:empty() :: gb_set(), %Exports
imports=[], %Imports
@@ -112,7 +111,6 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) ->
enabled_warnings=[], %All enabled warnings (ordset).
errors=[], %Current errors
warnings=[], %Current warnings
- global_vt=[], %The global VarTable
file = "" :: string(), %From last file attribute
recdef_top=false :: boolean(), %true in record initialisation
%outside any fun or lc
@@ -142,10 +140,8 @@ format_error({bad_module_name, M}) ->
io_lib:format("bad module name '~s'", [M]);
format_error(redefine_module) ->
"redefining module";
-format_error(redefine_extends) ->
- "redefining extends attribute";
-format_error(extends_self) ->
- "cannot extend from self";
+format_error(pmod_unsupported) ->
+ "parameterized modules are no longer supported";
%% format_error({redefine_mod_import, M, P}) ->
%% io_lib:format("module '~s' already imported from package '~s'", [M, P]);
@@ -166,10 +162,6 @@ format_error({bad_inline,{F,A}}) ->
io_lib:format("inlined function ~w/~w undefined", [F,A]);
format_error({invalid_deprecated,D}) ->
io_lib:format("badly formed deprecated attribute ~w", [D]);
-format_error(invalid_extends) ->
- "badly formed extends attribute";
-format_error(define_instance) ->
- "defining instance function not allowed in abstract module";
format_error({bad_deprecated,{F,A}}) ->
io_lib:format("deprecated function ~w/~w undefined or not exported", [F,A]);
format_error({bad_nowarn_unused_function,{F,A}}) ->
@@ -622,8 +614,6 @@ forms(Forms0, St0) ->
pre_scan([{function,_L,new,_A,_Cs} | Fs], St) ->
pre_scan(Fs, St#lint{new=true});
-pre_scan([{attribute,_L,extends,M} | Fs], St) when is_atom(M) ->
- pre_scan(Fs, St#lint{extends=true});
pre_scan([{attribute,L,compile,C} | Fs], St) ->
case is_warn_enabled(export_all, St) andalso
member(export_all, lists:flatten([C])) of
@@ -678,41 +668,15 @@ form(Form, #lint{state=State}=St) ->
%% start_state(Form, State) -> State'
-start_state({attribute,_,module,{M,Ps}}, St0) ->
- St1 = St0#lint{module=M},
- Arity = length(Ps),
- Ps1 = if is_atom(St1#lint.extends) ->
- ['BASE', 'THIS' | Ps];
- true ->
- ['THIS' | Ps]
- end,
- Vt = orddict:from_list([{V, {bound, used, []}} || V <- Ps1]),
- St2 = add_instance(Arity, St1),
- St3 = ensure_new(Arity, St2),
- St3#lint{state=attribute, extends=[], global_vt=Vt};
+start_state({attribute,Line,module,{_,_}}=Form, St0) ->
+ St1 = add_error(Line, pmod_unsupported, St0),
+ attribute_state(Form, St1#lint{state=attribute});
start_state({attribute,_,module,M}, St0) ->
St1 = St0#lint{module=M},
- St1#lint{state=attribute, extends=[]};
+ St1#lint{state=attribute};
start_state(Form, St) ->
St1 = add_error(element(2, Form), undefined_module, St),
- attribute_state(Form, St1#lint{state=attribute, extends=[]}).
-
-ensure_new(Arity, St) ->
- case St#lint.new of
- true ->
- St;
- false ->
- add_func(new, Arity, St)
- end.
-
-add_instance(Arity, St) ->
- A = Arity + (if is_atom(St#lint.extends) -> 1; true -> 0 end),
- add_func(instance, A, St).
-
-add_func(Name, Arity, St) ->
- F = {Name, Arity},
- St#lint{exports = gb_sets:add_element(F, St#lint.exports),
- defined = gb_sets:add_element(F, St#lint.defined)}.
+ attribute_state(Form, St1#lint{state=attribute}).
%% attribute_state(Form, State) ->
%% State'
@@ -721,15 +685,6 @@ attribute_state({attribute,_L,module,_M}, #lint{module=[]}=St) ->
St;
attribute_state({attribute,L,module,_M}, St) ->
add_error(L, redefine_module, St);
-attribute_state({attribute,L,extends,M}, #lint{module=M}=St) when is_atom(M) ->
- add_error(L, extends_self, St);
-attribute_state({attribute,_L,extends,M}, #lint{extends=[]}=St)
- when is_atom(M) ->
- St#lint{extends=M};
-attribute_state({attribute,L,extends,M}, St) when is_atom(M) ->
- add_error(L, redefine_extends, St);
-attribute_state({attribute,L,extends,_M}, St) ->
- add_error(L, invalid_extends, St);
attribute_state({attribute,L,export,Es}, St) ->
export(L, Es, St);
attribute_state({attribute,L,export_type,Es}, St) ->
@@ -1322,11 +1277,9 @@ call_function(Line, F, A, #lint{usage=Usage0,called=Cd,func=Func}=St) ->
%% function(Line, Name, Arity, Clauses, State) -> State.
-function(Line, instance, _Arity, _Cs, St) when St#lint.global_vt =/= [] ->
- add_error(Line, define_instance, St);
function(Line, Name, Arity, Cs, St0) ->
St1 = define_function(Line, Name, Arity, St0#lint{func={Name,Arity}}),
- clauses(Cs, St1#lint.global_vt, St1).
+ clauses(Cs, St1).
-spec define_function(line(), atom(), arity(), lint_state()) -> lint_state().
@@ -1349,15 +1302,16 @@ function_check_max_args(Line, Arity, St) when Arity > ?MAX_ARGUMENTS ->
add_error(Line, {too_many_arguments,Arity}, St);
function_check_max_args(_, _, St) -> St.
-%% clauses([Clause], VarTable, State) -> {VarTable, State}.
+%% clauses([Clause], State) -> {VarTable, State}.
-clauses(Cs, Vt, St) ->
+clauses(Cs, St) ->
foldl(fun (C, St0) ->
- {_,St1} = clause(C, Vt, St0),
+ {_,St1} = clause(C, St0),
St1
end, St, Cs).
-clause({clause,_Line,H,G,B}, Vt0, St0) ->
+clause({clause,_Line,H,G,B}, St0) ->
+ Vt0 = [],
{Hvt,Binvt,St1} = head(H, Vt0, St0),
%% Cannot ignore BinVt since "binsize variables" may have been used.
Vt1 = vtupdate(Hvt, vtupdate(Binvt, Vt0)),
diff --git a/lib/stdlib/test/Makefile b/lib/stdlib/test/Makefile
index 29b8e28d3a..6aa09d7bd0 100644
--- a/lib/stdlib/test/Makefile
+++ b/lib/stdlib/test/Makefile
@@ -23,7 +23,6 @@ MODULES= \
dummy_via \
edlin_expand_SUITE \
epp_SUITE \
- erl_eval_helper \
erl_eval_SUITE \
erl_expand_records_SUITE \
erl_internal_SUITE \
diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl
index 47792d1052..04d49770cb 100644
--- a/lib/stdlib/test/erl_eval_SUITE.erl
+++ b/lib/stdlib/test/erl_eval_SUITE.erl
@@ -1160,24 +1160,6 @@ do_funs(LFH, EFH) ->
concat(["begin F = fun(F, N) -> [", M,
":count_down(F,N) || X <-[1]] end, F(F,2) end."]),
[[[0]]], ['F'], LFH, EFH),
-
- %% Tests for a bug found by the Dialyzer - used to crash.
- case test_server:is_native(erl_eval) of
- true ->
- %% Parameterized modules are not supported by HiPE.
- ok;
- false ->
- check(fun() -> Pmod = erl_eval_helper:new(42), Pmod:add(5) end,
- "begin Pmod = erl_eval_helper:new(42), Pmod:add(5) end.",
- 47,
- ['Pmod'], LFH, EFH),
- check(fun() -> Pmod = erl_eval_helper:new(42),
- B = Pmod:add(7), B end,
- "begin Pmod = erl_eval_helper:new(42), "
- "B = Pmod:add(7), B end.",
- 49,
- ['B','Pmod'], LFH, EFH)
- end,
ok.
count_down(F, N) when N > 0 ->
diff --git a/lib/stdlib/test/erl_eval_helper.erl b/lib/stdlib/test/erl_eval_helper.erl
deleted file mode 100644
index 6863b40108..0000000000
--- a/lib/stdlib/test/erl_eval_helper.erl
+++ /dev/null
@@ -1,28 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
--module(erl_eval_helper, [Base]).
-
--export([add/1]).
-
-add(Arg) ->
- Base+Arg.
-
-
-
diff --git a/lib/stdlib/test/erl_expand_records_SUITE.erl b/lib/stdlib/test/erl_expand_records_SUITE.erl
index e51c05a22c..94b4397a9c 100644
--- a/lib/stdlib/test/erl_expand_records_SUITE.erl
+++ b/lib/stdlib/test/erl_expand_records_SUITE.erl
@@ -35,7 +35,7 @@
init_per_group/2,end_per_group/2,
init_per_testcase/2, end_per_testcase/2]).
--export([abstract_module/1, attributes/1, expr/1, guard/1,
+-export([attributes/1, expr/1, guard/1,
init/1, pattern/1, strict/1, update/1,
otp_5915/1, otp_7931/1, otp_5990/1,
otp_7078/1, otp_7101/1]).
@@ -55,7 +55,7 @@ end_per_testcase(_Case, _Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [abstract_module, attributes, expr, guard, init,
+ [attributes, expr, guard, init,
pattern, strict, update, {group, tickets}].
groups() ->
@@ -75,33 +75,6 @@ end_per_group(_GroupName, Config) ->
Config.
-abstract_module(doc) ->
- "Compile an abstract module.";
-abstract_module(suite) -> [];
-abstract_module(Config) when is_list(Config) ->
- %% erl_expand_records does not handle abstract modules. But anyway...
- File = filename("param.erl", Config),
- Beam = filename("param.beam", Config),
- Test = <<"-module(param, [A, B]).
-
- -export([args/1]).
-
- args(C) ->
- X = local(C),
- Z = new(A, B),
- {X, Z}.
-
- local(C) ->
- module_info(C).
- ">>,
-
- ?line ok = file:write_file(File, Test),
- ?line {ok, param} = compile:file(File, [{outdir,?privdir}]),
-
- ?line ok = file:delete(File),
- ?line ok = file:delete(Beam),
- ok.
-
attributes(doc) ->
"Import module and functions.";
attributes(suite) -> [];
@@ -196,7 +169,7 @@ guard(suite) -> [];
guard(Config) when is_list(Config) ->
File = filename("guard.erl", Config),
Beam = filename("guard.beam", Config),
- Test = <<"-module(guard, [A, B]).
+ Test = <<"-module(guard).
-export([t/1]).
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl
index 774229fca9..564f27a512 100644
--- a/lib/stdlib/test/erl_lint_SUITE.erl
+++ b/lib/stdlib/test/erl_lint_SUITE.erl
@@ -2187,27 +2187,9 @@ otp_5878(Config) when is_list(Config) ->
?line [] = run(Config, Ts),
Abstr = <<"-module(lint_test, [A, B]).
-
- -export([args/1]).
-
- -record(r, {a = A, b = THIS}). % A and THIS are unbound
-
- %% param:args(compile,param:new(1,2)).
-
- args(C) ->
- X = local(C),
- Z = new(A, B),
- F = fun(THIS) -> {x, A} end, % THIS unused and shadowed
- {X, Z, THIS, F, #r{}}.
-
- local(C) ->
- module_info(C).
">>,
- ?line {error,[{5,erl_lint,{unbound_var,'A'}},
- {5,erl_lint,{unbound_var,'THIS'}}],
- [{12,erl_lint,{unused_var,'THIS'}},
- {12,erl_lint,{shadowed_var,'THIS','fun'}}]}
- = run_test2(Config, Abstr, [warn_unused_record]),
+ {errors,[{1,erl_lint,pmod_unsupported}],[]} =
+ run_test2(Config, Abstr, [warn_unused_record]),
QLC1 = <<"-module(lint_test).
-include_lib(\"stdlib/include/qlc.hrl\").
diff --git a/lib/stdlib/test/escript_SUITE.erl b/lib/stdlib/test/escript_SUITE.erl
index 7634c21a17..3749d594f2 100644
--- a/lib/stdlib/test/escript_SUITE.erl
+++ b/lib/stdlib/test/escript_SUITE.erl
@@ -26,6 +26,7 @@
errors/1,
strange_name/1,
emulator_flags/1,
+ emulator_flags_no_shebang/1,
module_script/1,
beam_script/1,
archive_script/1,
@@ -45,6 +46,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[basic, errors, strange_name, emulator_flags,
+ emulator_flags_no_shebang,
module_script, beam_script, archive_script, epp,
create_and_extract, foldl, overflow,
archive_script_file_access, unicode].
@@ -150,6 +152,21 @@ emulator_flags(Config) when is_list(Config) ->
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+emulator_flags_no_shebang(Config) when is_list(Config) ->
+ Data = ?config(data_dir, Config),
+ Dir = filename:absname(Data), %Get rid of trailing slash.
+ %% Need run_with_opts, to always use "escript" explicitly
+ ?line run_with_opts(Dir, "", "emulator_flags_no_shebang -arg1 arg2 arg3",
+ [<<"main:[\"-arg1\",\"arg2\",\"arg3\"]\n"
+ "nostick:[{nostick,[]}]\n"
+ "mnesia:[{mnesia,[\"dir\",\"a/directory\"]},{mnesia,[\"debug\",\"verbose\"]}]\n"
+ "ERL_FLAGS=false\n"
+ "unknown:[]\n"
+ "ExitCode:0">>]),
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Pick the source code from the emulator_flags script
%% Generate a new escript with a module header
diff --git a/lib/stdlib/test/escript_SUITE_data/emulator_flags_no_shebang b/lib/stdlib/test/escript_SUITE_data/emulator_flags_no_shebang
new file mode 100644
index 0000000000..47d843ebe1
--- /dev/null
+++ b/lib/stdlib/test/escript_SUITE_data/emulator_flags_no_shebang
@@ -0,0 +1,10 @@
+%% -*- erlang -*-
+%%! -nostick -mnesia dir a/directory -mnesia debug verbose
+
+main(MainArgs) ->
+ io:format("main:~p\n",[MainArgs]),
+ ErlArgs = init:get_arguments(),
+ io:format("nostick:~p\n",[[E || E <- ErlArgs, element(1, E) =:= nostick]]),
+ io:format("mnesia:~p\n", [[E || E <- ErlArgs, element(1, E) =:= mnesia]]),
+ io:format("ERL_FLAGS=~p\n", [os:getenv("ERL_FLAGS")]),
+ io:format("unknown:~p\n",[[E || E <- ErlArgs, element(1, E) =:= unknown]]).
diff --git a/lib/stdlib/test/shell_SUITE.erl b/lib/stdlib/test/shell_SUITE.erl
index a32f846bd2..f22df96697 100644
--- a/lib/stdlib/test/shell_SUITE.erl
+++ b/lib/stdlib/test/shell_SUITE.erl
@@ -28,7 +28,7 @@
refman_bit_syntax/1,
progex_bit_syntax/1, progex_records/1,
progex_lc/1, progex_funs/1,
- otp_5990/1, otp_6166/1, otp_6554/1, otp_6785/1,
+ otp_5990/1, otp_6166/1, otp_6554/1,
otp_7184/1, otp_7232/1, otp_8393/1, otp_10302/1]).
-export([ start_restricted_from_shell/1,
@@ -92,7 +92,7 @@ groups() ->
[progex_bit_syntax, progex_records, progex_lc,
progex_funs]},
{tickets, [],
- [otp_5990, otp_6166, otp_6554, otp_6785, otp_7184,
+ [otp_5990, otp_6166, otp_6554, otp_7184,
otp_7232, otp_8393, otp_10302]}].
init_per_suite(Config) ->
@@ -2543,19 +2543,6 @@ otp_6554(Config) when is_list(Config) ->
ok.
-otp_6785(doc) ->
- "OTP-6785. Parameterized modules.";
-otp_6785(suite) -> [];
-otp_6785(Config) when is_list(Config) ->
- MFile = filename:join(?config(priv_dir, Config), "parameterized.erl"),
- Contents = <<"-module(parameterized, [A]). "
- "-export([test/0]). "
- "test() -> A. ">>,
- ?line ok = compile_file(Config, MFile, Contents, []),
- ?line (parameterized:new(adsf)):test(),
- file:delete(MFile),
- ok.
-
otp_7184(doc) ->
"OTP-7184. Propagate exit signals from dying evaluator process.";
otp_7184(suite) -> [];
diff --git a/lib/tools/test/cprof_SUITE.erl b/lib/tools/test/cprof_SUITE.erl
index ce5cf66a14..93caee0c8f 100644
--- a/lib/tools/test/cprof_SUITE.erl
+++ b/lib/tools/test/cprof_SUITE.erl
@@ -230,10 +230,10 @@ on_load_test(Config) ->
%%
?line N4 = cprof:restart(),
?line {ok,Module} = c:c(File, [{outdir,Priv}]),
- ?line L = Module:seq(1, M, fun succ/1),
- ?line Lr = Module:seq_r(1, M, fun succ/1),
- ?line L = seq(1, M, fun succ/1),
- ?line Lr = seq_r(1, M, fun succ/1),
+ ?line L = Module:seq(1, M, fun (I) -> succ(I) end),
+ ?line Lr = Module:seq_r(1, M, fun (I) -> succ(I) end),
+ ?line L = seq(1, M, fun (I) -> succ(I) end),
+ ?line Lr = seq_r(1, M, fun (I) -> succ(I) end),
?line N2 = cprof:pause(),
?line {Module,0,[]} = cprof:analyse(Module),
?line M_1 = M - 1,
@@ -265,10 +265,10 @@ modules_test(Config) ->
?line M2__1 = M2 + 1,
?line erlang:yield(),
?line N = cprof:start(),
- ?line L = Module:seq(1, M, fun succ/1),
- ?line Lr = Module:seq_r(1, M, fun succ/1),
- ?line L = seq(1, M, fun succ/1),
- ?line Lr = seq_r(1, M, fun succ/1),
+ ?line L = Module:seq(1, M, fun (I) -> succ(I) end),
+ ?line Lr = Module:seq_r(1, M, fun (I) -> succ(I) end),
+ ?line L = seq(1, M, fun (I) -> succ(I) end),
+ ?line Lr = seq_r(1, M, fun (I) -> succ(I) end),
?line N = cprof:pause(),
?line Lr = lists:reverse(L),
?line M_1 = M - 1,
diff --git a/lib/tools/test/xref_SUITE.erl b/lib/tools/test/xref_SUITE.erl
index cf49526156..dc06678b8e 100644
--- a/lib/tools/test/xref_SUITE.erl
+++ b/lib/tools/test/xref_SUITE.erl
@@ -47,7 +47,7 @@
-export([
add/1, default/1, info/1, lib/1, read/1, read2/1, remove/1,
replace/1, update/1, deprecated/1, trycatch/1,
- abstract_modules/1, fun_mfa/1, fun_mfa_r14/1,
+ fun_mfa/1, fun_mfa_r14/1,
fun_mfa_vars/1, qlc/1]).
-export([
@@ -83,7 +83,7 @@ groups() ->
modules]},
{files, [],
[add, default, info, lib, read, read2, remove, replace,
- update, deprecated, trycatch, abstract_modules, fun_mfa,
+ update, deprecated, trycatch, fun_mfa,
fun_mfa_r14, fun_mfa_vars, qlc]},
{analyses, [],
[analyze, basic, md, q, variables, unused_locals]},
@@ -1669,64 +1669,6 @@ trycatch(Conf) when is_list(Conf) ->
ok.
-abstract_modules(suite) -> [];
-abstract_modules(doc) -> ["OTP-5520: Abstract (parameterized) modules."];
-abstract_modules(Conf) when is_list(Conf) ->
- Dir = ?copydir,
- File = fname(Dir, "absmod.erl"),
- MFile = fname(Dir, "absmod"),
- Beam = fname(Dir, "absmod.beam"),
- Test = <<"-module(param, [A, B]).
-
- -export([args/1]).
-
- args(C) ->
- X = local(C),
- Y = THIS:new(), % undef
- Z = new(A, B),
- {X, Y, Z}.
-
- local(C) ->
- module_info(C).
- ">>,
-
- ?line ok = file:write_file(File, Test),
-
- %% The compiler will no longer allow us to have a mismatch between
- %% the module name and the output file, so we must use a trick.
- ?line {ok, param, BeamCode} = compile:file(File, [binary,debug_info]),
- ?line ok = file:write_file(Beam, BeamCode),
-
- ?line {ok, _} = xref:start(s),
- ?line {ok, param} = xref:add_module(s, MFile, {warnings,false}),
- A = param,
- ?line {ok, [{{{A,args,1},{'$M_EXPR',new,0}},[7]},
- {{{A,args,1},{A,local,1}},[6]},
- {{{A,args,1},{A,new,2}},[8]},
- {{{A,local,1},{A,module_info,1}},[12]},
- {{{param,new,2},{param,instance,2}},[0]}]} =
- xref:q(s, "(Lin) E"),
- ?line {ok,[{param,args,1},
- {param,instance,2},
- {param,local,1},
- {param,module_info,1},
- {param,new,2}]} = xref:q(s, "F"),
-
- ?line ok = check_state(s),
- ?line xref:stop(s),
-
- ?line {ok, _} = xref:start(s, {xref_mode, modules}),
- ?line {ok, param} = xref:add_module(s, MFile),
- ?line {ok,[{param,args,1},
- {param,instance,2},
- {param,new,2}]} = xref:q(s, "X"),
- ?line ok = check_state(s),
- ?line xref:stop(s),
-
- ?line ok = file:delete(File),
- ?line ok = file:delete(Beam),
- ok.
-
fun_mfa(suite) -> [];
fun_mfa(doc) -> ["OTP-5653: fun M:F/A."];
fun_mfa(Conf) when is_list(Conf) ->