pkixcert_signature_algorithm_tests.cpp (10424B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* Any copyright is dedicated to the Public Domain. 4 * http://creativecommons.org/publicdomain/zero/1.0/ */ 5 6 #include "pkixgtest.h" 7 8 #include "mozpkix/pkixder.h" 9 10 #include "secoid.h" 11 12 using namespace mozilla::pkix; 13 using namespace mozilla::pkix::test; 14 15 /* These tests generate invalid certificates on the fly, We want to test 16 * validation of those certificates, not the generation, so we 17 * need to temporarily allow disallowed signature policies before 18 * we do the actual certificate or ocsp signing 19 */ 20 class HashAlgorithmPolicies 21 { 22 static const int numberOfHashes = 4; /* sigh */ 23 static const SECOidTag hashOids[numberOfHashes]; 24 25 PRUint32 savedPolicy[numberOfHashes]; 26 27 public: 28 void EnableHashSignaturePolicy(void); 29 void RestoreHashSignaturePolicy(void); 30 }; 31 32 const SECOidTag HashAlgorithmPolicies::hashOids[numberOfHashes] = { 33 SEC_OID_MD2, 34 SEC_OID_MD4, 35 SEC_OID_MD5, 36 SEC_OID_SHA1 }; 37 38 void 39 HashAlgorithmPolicies::EnableHashSignaturePolicy(void) 40 { 41 for (int i=0;i < numberOfHashes; i++) { 42 ASSERT_EQ(SECSuccess, 43 NSS_GetAlgorithmPolicy(hashOids[i], &savedPolicy[i])); 44 ASSERT_EQ(SECSuccess, 45 NSS_SetAlgorithmPolicy(hashOids[i], NSS_USE_ALG_IN_SIGNATURE, 0)); 46 } 47 } 48 49 void 50 HashAlgorithmPolicies::RestoreHashSignaturePolicy(void) 51 { 52 for (int i=0;i < numberOfHashes; i++) { 53 ASSERT_EQ(SECSuccess, 54 NSS_SetAlgorithmPolicy(hashOids[i], savedPolicy[i], 55 NSS_USE_ALG_IN_SIGNATURE)); 56 } 57 } 58 59 static ByteString 60 CreateCert(const char* issuerCN, 61 const char* subjectCN, 62 EndEntityOrCA endEntityOrCA, 63 const TestSignatureAlgorithm& signatureAlgorithm, 64 /*out*/ ByteString& subjectDER) 65 { 66 static long serialNumberValue = 0; 67 ++serialNumberValue; 68 ByteString serialNumber(CreateEncodedSerialNumber(serialNumberValue)); 69 EXPECT_FALSE(ENCODING_FAILED(serialNumber)); 70 71 ByteString issuerDER(CNToDERName(issuerCN)); 72 EXPECT_FALSE(ENCODING_FAILED(issuerDER)); 73 subjectDER = CNToDERName(subjectCN); 74 EXPECT_FALSE(ENCODING_FAILED(subjectDER)); 75 76 ByteString extensions[2]; 77 if (endEntityOrCA == EndEntityOrCA::MustBeCA) { 78 extensions[0] = 79 CreateEncodedBasicConstraints(true, nullptr, Critical::Yes); 80 EXPECT_FALSE(ENCODING_FAILED(extensions[0])); 81 } 82 83 ScopedTestKeyPair reusedKey(CloneReusedKeyPair()); 84 HashAlgorithmPolicies policies; 85 policies.EnableHashSignaturePolicy(); 86 ByteString certDER(CreateEncodedCertificate(v3, signatureAlgorithm, 87 serialNumber, issuerDER, 88 oneDayBeforeNow, oneDayAfterNow, 89 subjectDER, *reusedKey, 90 extensions, *reusedKey, 91 signatureAlgorithm)); 92 policies.RestoreHashSignaturePolicy(); 93 EXPECT_FALSE(ENCODING_FAILED(certDER)); 94 return certDER; 95 } 96 97 98 class AlgorithmTestsTrustDomain final : public DefaultCryptoTrustDomain 99 { 100 public: 101 AlgorithmTestsTrustDomain(const ByteString& aRootDER, 102 const ByteString& aRootSubjectDER, 103 /*optional*/ const ByteString& aIntDER, 104 /*optional*/ const ByteString& aIntSubjectDER) 105 : rootDER(aRootDER) 106 , rootSubjectDER(aRootSubjectDER) 107 , intDER(aIntDER) 108 , intSubjectDER(aIntSubjectDER) 109 { 110 } 111 112 private: 113 Result GetCertTrust(EndEntityOrCA, const CertPolicyId&, Input candidateCert, 114 /*out*/ TrustLevel& trustLevel) override 115 { 116 if (InputEqualsByteString(candidateCert, rootDER)) { 117 trustLevel = TrustLevel::TrustAnchor; 118 } else { 119 trustLevel = TrustLevel::InheritsTrust; 120 } 121 return Success; 122 } 123 124 Result FindIssuer(Input encodedIssuerName, IssuerChecker& checker, Time) 125 override 126 { 127 ByteString* issuerDER = nullptr; 128 if (InputEqualsByteString(encodedIssuerName, rootSubjectDER)) { 129 issuerDER = &rootDER; 130 } else if (InputEqualsByteString(encodedIssuerName, intSubjectDER)) { 131 issuerDER = &intDER; 132 } else { 133 // FindIssuer just returns success if it can't find a potential issuer. 134 return Success; 135 } 136 Input issuerCert; 137 Result rv = issuerCert.Init(issuerDER->data(), issuerDER->length()); 138 if (rv != Success) { 139 return rv; 140 } 141 bool keepGoing; 142 return checker.Check(issuerCert, nullptr, keepGoing); 143 } 144 145 Result CheckRevocation(EndEntityOrCA, const CertID&, Time, Duration, 146 const Input*, const Input*) override 147 { 148 return Success; 149 } 150 151 Result IsChainValid(const DERArray&, Time, const CertPolicyId&) override 152 { 153 return Success; 154 } 155 156 ByteString rootDER; 157 ByteString rootSubjectDER; 158 ByteString intDER; 159 ByteString intSubjectDER; 160 }; 161 162 static const TestSignatureAlgorithm NO_INTERMEDIATE 163 { 164 TestPublicKeyAlgorithm(ByteString()), 165 TestDigestAlgorithmID::MD2, 166 ByteString(), 167 false 168 }; 169 170 struct ChainValidity final 171 { 172 ChainValidity(const TestSignatureAlgorithm& aEndEntitySignatureAlgorithm, 173 const TestSignatureAlgorithm& aOptionalIntSignatureAlgorithm, 174 const TestSignatureAlgorithm& aRootSignatureAlgorithm, 175 bool aIsValid) 176 : endEntitySignatureAlgorithm(aEndEntitySignatureAlgorithm) 177 , optionalIntermediateSignatureAlgorithm(aOptionalIntSignatureAlgorithm) 178 , rootSignatureAlgorithm(aRootSignatureAlgorithm) 179 , isValid(aIsValid) 180 { } 181 182 // In general, a certificate is generated for each of these. However, if 183 // optionalIntermediateSignatureAlgorithm is NO_INTERMEDIATE, then only 2 184 // certificates are generated. 185 // The certificate generated for the given rootSignatureAlgorithm is the 186 // trust anchor. 187 TestSignatureAlgorithm endEntitySignatureAlgorithm; 188 TestSignatureAlgorithm optionalIntermediateSignatureAlgorithm; 189 TestSignatureAlgorithm rootSignatureAlgorithm; 190 bool isValid; 191 }; 192 193 static const ChainValidity CHAIN_VALIDITY[] = 194 { 195 // The trust anchor may have a signature with an unsupported signature 196 // algorithm. 197 ChainValidity(sha256WithRSAEncryption(), 198 NO_INTERMEDIATE, 199 md5WithRSAEncryption(), 200 true), 201 ChainValidity(sha256WithRSAEncryption(), 202 NO_INTERMEDIATE, 203 md2WithRSAEncryption(), 204 true), 205 206 // Certificates that are not trust anchors must not have a signature with an 207 // unsupported signature algorithm. 208 ChainValidity(md5WithRSAEncryption(), 209 NO_INTERMEDIATE, 210 sha256WithRSAEncryption(), 211 false), 212 ChainValidity(md2WithRSAEncryption(), 213 NO_INTERMEDIATE, 214 sha256WithRSAEncryption(), 215 false), 216 ChainValidity(md2WithRSAEncryption(), 217 NO_INTERMEDIATE, 218 md5WithRSAEncryption(), 219 false), 220 ChainValidity(sha256WithRSAEncryption(), 221 md5WithRSAEncryption(), 222 sha256WithRSAEncryption(), 223 false), 224 ChainValidity(sha256WithRSAEncryption(), 225 md2WithRSAEncryption(), 226 sha256WithRSAEncryption(), 227 false), 228 ChainValidity(sha256WithRSAEncryption(), 229 md2WithRSAEncryption(), 230 md5WithRSAEncryption(), 231 false), 232 }; 233 234 class pkixcert_IsValidChainForAlgorithm 235 : public ::testing::Test 236 , public ::testing::WithParamInterface<ChainValidity> 237 { 238 }; 239 240 ::std::ostream& operator<<(::std::ostream& os, 241 const pkixcert_IsValidChainForAlgorithm&) 242 { 243 return os << "TODO (bug 1318770)"; 244 } 245 246 ::std::ostream& operator<<(::std::ostream& os, const ChainValidity&) 247 { 248 return os << "TODO (bug 1318770)"; 249 } 250 251 TEST_P(pkixcert_IsValidChainForAlgorithm, IsValidChainForAlgorithm) 252 { 253 const ChainValidity& chainValidity(GetParam()); 254 const char* rootCN = "CN=Root"; 255 ByteString rootSubjectDER; 256 ByteString rootEncoded( 257 CreateCert(rootCN, rootCN, EndEntityOrCA::MustBeCA, 258 chainValidity.rootSignatureAlgorithm, rootSubjectDER)); 259 EXPECT_FALSE(ENCODING_FAILED(rootEncoded)); 260 EXPECT_FALSE(ENCODING_FAILED(rootSubjectDER)); 261 262 const char* issuerCN = rootCN; 263 264 const char* intermediateCN = "CN=Intermediate"; 265 ByteString intermediateSubjectDER; 266 ByteString intermediateEncoded; 267 268 // If the the algorithmIdentifier is empty, then it's NO_INTERMEDIATE. 269 if (!chainValidity.optionalIntermediateSignatureAlgorithm 270 .algorithmIdentifier.empty()) { 271 intermediateEncoded = 272 CreateCert(rootCN, intermediateCN, EndEntityOrCA::MustBeCA, 273 chainValidity.optionalIntermediateSignatureAlgorithm, 274 intermediateSubjectDER); 275 EXPECT_FALSE(ENCODING_FAILED(intermediateEncoded)); 276 EXPECT_FALSE(ENCODING_FAILED(intermediateSubjectDER)); 277 issuerCN = intermediateCN; 278 } 279 280 AlgorithmTestsTrustDomain trustDomain(rootEncoded, rootSubjectDER, 281 intermediateEncoded, 282 intermediateSubjectDER); 283 284 const char* endEntityCN = "CN=End Entity"; 285 ByteString endEntitySubjectDER; 286 ByteString endEntityEncoded( 287 CreateCert(issuerCN, endEntityCN, EndEntityOrCA::MustBeEndEntity, 288 chainValidity.endEntitySignatureAlgorithm, 289 endEntitySubjectDER)); 290 EXPECT_FALSE(ENCODING_FAILED(endEntityEncoded)); 291 EXPECT_FALSE(ENCODING_FAILED(endEntitySubjectDER)); 292 293 Input endEntity; 294 ASSERT_EQ(Success, endEntity.Init(endEntityEncoded.data(), 295 endEntityEncoded.length())); 296 Result expectedResult = chainValidity.isValid 297 ? Success 298 : Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED; 299 ASSERT_EQ(expectedResult, 300 BuildCertChain(trustDomain, endEntity, Now(), 301 EndEntityOrCA::MustBeEndEntity, 302 KeyUsage::noParticularKeyUsageRequired, 303 KeyPurposeId::id_kp_serverAuth, 304 CertPolicyId::anyPolicy, nullptr)); 305 } 306 307 INSTANTIATE_TEST_SUITE_P(pkixcert_IsValidChainForAlgorithm, 308 pkixcert_IsValidChainForAlgorithm, 309 testing::ValuesIn(CHAIN_VALIDITY));