pkixcheck_CheckSignatureAlgorithm_tests.cpp (13603B)
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 /* This code is made available to you under your choice of the following sets 4 * of licensing terms: 5 */ 6 /* This Source Code Form is subject to the terms of the Mozilla Public 7 * License, v. 2.0. If a copy of the MPL was not distributed with this 8 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 */ 10 /* Copyright 2015 Mozilla Contributors 11 * 12 * Licensed under the Apache License, Version 2.0 (the "License"); 13 * you may not use this file except in compliance with the License. 14 * You may obtain a copy of the License at 15 * 16 * http://www.apache.org/licenses/LICENSE-2.0 17 * 18 * Unless required by applicable law or agreed to in writing, software 19 * distributed under the License is distributed on an "AS IS" BASIS, 20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 * See the License for the specific language governing permissions and 22 * limitations under the License. 23 */ 24 25 #include "pkixgtest.h" 26 27 #include "mozpkix/pkixder.h" 28 29 using namespace mozilla::pkix; 30 using namespace mozilla::pkix::test; 31 32 namespace mozilla { namespace pkix { 33 34 extern Result CheckSignatureAlgorithm( 35 TrustDomain& trustDomain, EndEntityOrCA endEntityOrCA, 36 Time notBefore, 37 const der::SignedDataWithSignature& signedData, 38 Input signatureValue); 39 40 } } // namespace mozilla::pkix 41 42 struct CheckSignatureAlgorithmTestParams 43 { 44 ByteString signatureAlgorithmValue; 45 ByteString signatureValue; 46 unsigned int signatureLengthInBytes; 47 Result expectedResult; 48 }; 49 50 ::std::ostream& operator<<(::std::ostream& os, 51 const CheckSignatureAlgorithmTestParams&) 52 { 53 return os << "TODO (bug 1318770)"; 54 } 55 56 #define BS(s) ByteString(s, MOZILLA_PKIX_ARRAY_LENGTH(s)) 57 58 // python DottedOIDToCode.py --tlv sha256WithRSAEncryption 1.2.840.113549.1.1.11 59 static const uint8_t tlv_sha256WithRSAEncryption[] = { 60 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b 61 }; 62 63 // Same as tlv_sha256WithRSAEncryption, except one without the "0x0b" and with 64 // the DER length decreased accordingly. 65 static const uint8_t tlv_sha256WithRSAEncryption_truncated[] = { 66 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01 67 }; 68 69 // python DottedOIDToCode.py --tlv sha-1WithRSAEncryption 1.2.840.113549.1.1.5 70 static const uint8_t tlv_sha_1WithRSAEncryption[] = { 71 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05 72 }; 73 74 // python DottedOIDToCode.py --tlv sha1WithRSASignature 1.3.14.3.2.29 75 static const uint8_t tlv_sha1WithRSASignature[] = { 76 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d 77 }; 78 79 // python DottedOIDToCode.py --tlv md5WithRSAEncryption 1.2.840.113549.1.1.4 80 static const uint8_t tlv_md5WithRSAEncryption[] = { 81 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04 82 }; 83 84 // CA/B Forum BR 1.8.1 Section 7.1.3.2.1 85 // Params for RSA-PSS with SHA-256, MGF-1 with SHA-256, and a salt length 86 // of 32 bytes: 87 static const uint8_t rsaPSSWithSHA256[] = { 88 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30, 89 0x34, 0xa0, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 90 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 91 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d, 0x06, 92 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 93 0xa2, 0x03, 0x02, 0x01, 0x20 94 }; 95 96 static const CheckSignatureAlgorithmTestParams 97 CHECKSIGNATUREALGORITHM_TEST_PARAMS[] = 98 { 99 { // Both algorithm IDs are empty 100 ByteString(), 101 ByteString(), 102 2048 / 8, 103 Result::ERROR_BAD_DER, 104 }, 105 { // signatureAlgorithm is empty, signature is supported. 106 ByteString(), 107 BS(tlv_sha256WithRSAEncryption), 108 2048 / 8, 109 Result::ERROR_BAD_DER, 110 }, 111 { // signatureAlgorithm is supported, signature is empty. 112 BS(tlv_sha256WithRSAEncryption), 113 ByteString(), 114 2048 / 8, 115 Result::ERROR_BAD_DER, 116 }, 117 { // Algorithms match, both are supported. 118 BS(tlv_sha256WithRSAEncryption), 119 BS(tlv_sha256WithRSAEncryption), 120 2048 / 8, 121 Success 122 }, 123 { // Algorithms do not match because signatureAlgorithm is truncated. 124 BS(tlv_sha256WithRSAEncryption_truncated), 125 BS(tlv_sha256WithRSAEncryption), 126 2048 / 8, 127 Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED 128 }, 129 { // Algorithms do not match because signature is truncated. 130 BS(tlv_sha256WithRSAEncryption), 131 BS(tlv_sha256WithRSAEncryption_truncated), 132 2048 / 8, 133 Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED 134 }, 135 { // Algorithms do not match, both are supported. 136 BS(tlv_sha_1WithRSAEncryption), 137 BS(tlv_sha256WithRSAEncryption), 138 2048 / 8, 139 Result::ERROR_SIGNATURE_ALGORITHM_MISMATCH, 140 }, 141 { // Algorithms do not match, both are supported. 142 BS(tlv_sha256WithRSAEncryption), 143 BS(tlv_sha_1WithRSAEncryption), 144 2048 / 8, 145 Result::ERROR_SIGNATURE_ALGORITHM_MISMATCH, 146 }, 147 { // Algorithms match, both are unsupported. 148 BS(tlv_md5WithRSAEncryption), 149 BS(tlv_md5WithRSAEncryption), 150 2048 / 8, 151 Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED 152 }, 153 { // signatureAlgorithm is unsupported, signature is supported. 154 BS(tlv_md5WithRSAEncryption), 155 BS(tlv_sha256WithRSAEncryption), 156 2048 / 8, 157 Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED 158 }, 159 { // signatureAlgorithm is supported, signature is unsupported. 160 BS(tlv_sha256WithRSAEncryption), 161 BS(tlv_md5WithRSAEncryption), 162 2048 / 8, 163 Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED 164 }, 165 { // Both have the optional NULL parameter. 166 BS(tlv_sha256WithRSAEncryption) + TLV(der::NULLTag, ByteString()), 167 BS(tlv_sha256WithRSAEncryption) + TLV(der::NULLTag, ByteString()), 168 2048 / 8, 169 Success 170 }, 171 { // signatureAlgorithm has the optional NULL parameter, signature doesn't. 172 BS(tlv_sha256WithRSAEncryption) + TLV(der::NULLTag, ByteString()), 173 BS(tlv_sha256WithRSAEncryption), 174 2048 / 8, 175 Success 176 }, 177 { // signatureAlgorithm does not have the optional NULL parameter, signature 178 // does. 179 BS(tlv_sha256WithRSAEncryption), 180 BS(tlv_sha256WithRSAEncryption) + TLV(der::NULLTag, ByteString()), 181 2048 / 8, 182 Success 183 }, 184 { // The different OIDs for RSA-with-SHA1 we support are semantically 185 // equivalent. 186 BS(tlv_sha1WithRSASignature), 187 BS(tlv_sha_1WithRSAEncryption), 188 2048 / 8, 189 Success, 190 }, 191 { // The different OIDs for RSA-with-SHA1 we support are semantically 192 // equivalent (opposite order). 193 BS(tlv_sha_1WithRSAEncryption), 194 BS(tlv_sha1WithRSASignature), 195 2048 / 8, 196 Success, 197 }, 198 { // Algorithms match, both are supported, key size is not a multile of 128 199 // bits. This test verifies that we're not wrongly rounding up the 200 // signature size like we did in the original patch for bug 1131767. 201 BS(tlv_sha256WithRSAEncryption), 202 BS(tlv_sha256WithRSAEncryption), 203 (2048 / 8) - 1, 204 Success 205 }, 206 { 207 // signatureAlgorithm and signature are RSA-PSS 208 BS(rsaPSSWithSHA256), 209 BS(rsaPSSWithSHA256), 210 2048 / 8, 211 Success 212 }, 213 { 214 // signatureAlgorithm is RSA-PSS, signature is RSA PKCS#1v1.5 215 BS(rsaPSSWithSHA256), 216 BS(tlv_sha256WithRSAEncryption), 217 2048 / 8, 218 Result::ERROR_SIGNATURE_ALGORITHM_MISMATCH 219 }, 220 }; 221 222 class pkixcheck_CheckSignatureAlgorithm 223 : public ::testing::Test 224 , public ::testing::WithParamInterface<CheckSignatureAlgorithmTestParams> 225 { 226 }; 227 228 class pkixcheck_CheckSignatureAlgorithm_TrustDomain final 229 : public EverythingFailsByDefaultTrustDomain 230 { 231 public: 232 explicit pkixcheck_CheckSignatureAlgorithm_TrustDomain( 233 unsigned int aPublicKeySizeInBits) 234 : publicKeySizeInBits(aPublicKeySizeInBits) 235 , checkedDigestAlgorithm(false) 236 , checkedModulusSizeInBits(false) 237 { 238 } 239 240 Result CheckSignatureDigestAlgorithm(DigestAlgorithm, EndEntityOrCA, Time) 241 override 242 { 243 checkedDigestAlgorithm = true; 244 return Success; 245 } 246 247 Result CheckRSAPublicKeyModulusSizeInBits(EndEntityOrCA endEntityOrCA, 248 unsigned int modulusSizeInBits) 249 override 250 { 251 EXPECT_EQ(EndEntityOrCA::MustBeEndEntity, endEntityOrCA); 252 EXPECT_EQ(publicKeySizeInBits, modulusSizeInBits); 253 checkedModulusSizeInBits = true; 254 return Success; 255 } 256 257 const unsigned int publicKeySizeInBits; 258 bool checkedDigestAlgorithm; 259 bool checkedModulusSizeInBits; 260 }; 261 262 TEST_P(pkixcheck_CheckSignatureAlgorithm, CheckSignatureAlgorithm) 263 { 264 const Time now(Now()); 265 const CheckSignatureAlgorithmTestParams& params(GetParam()); 266 267 Input signatureValueInput; 268 ASSERT_EQ(Success, 269 signatureValueInput.Init(params.signatureValue.data(), 270 params.signatureValue.length())); 271 272 pkixcheck_CheckSignatureAlgorithm_TrustDomain 273 trustDomain(params.signatureLengthInBytes * 8); 274 275 der::SignedDataWithSignature signedData; 276 ASSERT_EQ(Success, 277 signedData.algorithm.Init(params.signatureAlgorithmValue.data(), 278 params.signatureAlgorithmValue.length())); 279 280 ByteString dummySignature(params.signatureLengthInBytes, 0xDE); 281 ASSERT_EQ(Success, 282 signedData.signature.Init(dummySignature.data(), 283 dummySignature.length())); 284 285 ASSERT_EQ(params.expectedResult, 286 CheckSignatureAlgorithm(trustDomain, EndEntityOrCA::MustBeEndEntity, 287 now, signedData, signatureValueInput)); 288 ASSERT_EQ(params.expectedResult == Success, 289 trustDomain.checkedDigestAlgorithm); 290 ASSERT_EQ(params.expectedResult == Success, 291 trustDomain.checkedModulusSizeInBits); 292 } 293 294 INSTANTIATE_TEST_SUITE_P( 295 pkixcheck_CheckSignatureAlgorithm, pkixcheck_CheckSignatureAlgorithm, 296 testing::ValuesIn(CHECKSIGNATUREALGORITHM_TEST_PARAMS)); 297 298 class pkixcheck_CheckSignatureAlgorithm_BuildCertChain_TrustDomain 299 : public DefaultCryptoTrustDomain 300 { 301 public: 302 explicit pkixcheck_CheckSignatureAlgorithm_BuildCertChain_TrustDomain( 303 const ByteString& aIssuer) 304 : issuer(aIssuer) 305 { 306 } 307 308 Result GetCertTrust(EndEntityOrCA, const CertPolicyId&, 309 Input cert, /*out*/ TrustLevel& trustLevel) override 310 { 311 trustLevel = InputEqualsByteString(cert, issuer) 312 ? TrustLevel::TrustAnchor 313 : TrustLevel::InheritsTrust; 314 return Success; 315 } 316 317 Result FindIssuer(Input, IssuerChecker& checker, Time) override 318 { 319 EXPECT_FALSE(ENCODING_FAILED(issuer)); 320 321 Input issuerInput; 322 EXPECT_EQ(Success, issuerInput.Init(issuer.data(), issuer.length())); 323 324 bool keepGoing; 325 EXPECT_EQ(Success, checker.Check(issuerInput, nullptr, keepGoing)); 326 EXPECT_FALSE(keepGoing); 327 328 return Success; 329 } 330 331 Result CheckRevocation(EndEntityOrCA, const CertID&, Time, Duration, 332 /*optional*/ const Input*, 333 /*optional*/ const Input*) override 334 { 335 return Success; 336 } 337 338 Result IsChainValid(const DERArray&, Time, const CertPolicyId&) override 339 { 340 return Success; 341 } 342 343 ByteString issuer; 344 }; 345 346 // Test that CheckSignatureAlgorithm actually gets called at some point when 347 // BuildCertChain is called. 348 TEST_F(pkixcheck_CheckSignatureAlgorithm, BuildCertChain) 349 { 350 ScopedTestKeyPair keyPair(CloneReusedKeyPair()); 351 ASSERT_TRUE(keyPair.get()); 352 353 ByteString issuerExtensions[2]; 354 issuerExtensions[0] = CreateEncodedBasicConstraints(true, nullptr, 355 Critical::No); 356 ASSERT_FALSE(ENCODING_FAILED(issuerExtensions[0])); 357 358 ByteString issuer(CreateEncodedCertificate(3, 359 sha256WithRSAEncryption(), 360 CreateEncodedSerialNumber(1), 361 CNToDERName("issuer"), 362 oneDayBeforeNow, oneDayAfterNow, 363 CNToDERName("issuer"), 364 *keyPair, 365 issuerExtensions, 366 *keyPair, 367 sha256WithRSAEncryption())); 368 ASSERT_FALSE(ENCODING_FAILED(issuer)); 369 370 ByteString subject(CreateEncodedCertificate(3, 371 sha1WithRSAEncryption(), 372 CreateEncodedSerialNumber(2), 373 CNToDERName("issuer"), 374 oneDayBeforeNow, oneDayAfterNow, 375 CNToDERName("subject"), 376 *keyPair, 377 nullptr, 378 *keyPair, 379 sha256WithRSAEncryption())); 380 ASSERT_FALSE(ENCODING_FAILED(subject)); 381 382 Input subjectInput; 383 ASSERT_EQ(Success, subjectInput.Init(subject.data(), subject.length())); 384 pkixcheck_CheckSignatureAlgorithm_BuildCertChain_TrustDomain 385 trustDomain(issuer); 386 Result rv = BuildCertChain(trustDomain, subjectInput, Now(), 387 EndEntityOrCA::MustBeEndEntity, 388 KeyUsage::noParticularKeyUsageRequired, 389 KeyPurposeId::anyExtendedKeyUsage, 390 CertPolicyId::anyPolicy, 391 nullptr); 392 ASSERT_EQ(Result::ERROR_SIGNATURE_ALGORITHM_MISMATCH, rv); 393 }