Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include <string> | |
| 6 #include <vector> | |
| 7 | |
| 8 #include "net/tools/transport_security_state_generator/cert_util.h" | |
| 9 #include "net/tools/transport_security_state_generator/spki_hash.h" | |
| 10 #include "testing/gmock/include/gmock/gmock.h" | |
| 11 #include "testing/gtest/include/gtest/gtest.h" | |
| 12 #include "third_party/boringssl/src/include/openssl/x509v3.h" | |
| 13 | |
| 14 namespace net { | |
| 15 | |
| 16 namespace transport_security_state { | |
| 17 | |
| 18 namespace { | |
| 19 | |
| 20 // Certficate with the subject CN set to "Chromium", the subject organisation | |
| 21 // set to "The Chromium Projects", and the subject organizational unit set to | |
| 22 // "Security." | |
| 23 static const char kSelfSignedWithCommonNamePEM[] = | |
| 24 "-----BEGIN CERTIFICATE-----\n" | |
| 25 "MIIDeTCCAmGgAwIBAgIJAKZbsC4gPYAUMA0GCSqGSIb3DQEBCwUAMFMxETAPBgNV\n" | |
| 26 "BAMMCENocm9taXVtMR4wHAYDVQQKDBVUaGUgQ2hyb21pdW0gUHJvamVjdHMxETAP\n" | |
| 27 "BgNVBAsMCFNlY3VyaXR5MQswCQYDVQQGEwJVUzAeFw0xNzAxMjkyMDU1NDFaFw0x\n" | |
| 28 "ODAxMjkyMDU1NDFaMFMxETAPBgNVBAMMCENocm9taXVtMR4wHAYDVQQKDBVUaGUg\n" | |
| 29 "Q2hyb21pdW0gUHJvamVjdHMxETAPBgNVBAsMCFNlY3VyaXR5MQswCQYDVQQGEwJV\n" | |
| 30 "UzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMlir9M85QOvQ5ok+uvH\n" | |
| 31 "XF7kmW21B22Ffdw+B2mXTV6NLGvINCdwocIlebQlAdWS2QY/WM08uAYJ3m0IGD+t\n" | |
| 32 "6OG4zG3vOmWMdFQy4XkxMsDkbV11F9n4dsF5TXEvILlupOtOWu6Up8vfFkii/x+/\n" | |
| 33 "bz4aGBDdFu6U8TdQ8ELSmHxJYi4LM0lUKTdLLte3T5Grv3UUXQW33Qs6RXZlH/ul\n" | |
| 34 "jf7/v0HQefM3XdT9djG1XRv8Ga32c8tz+wtSw7PPIWjt0ZDJxZ2/fX7YLwAt2D6N\n" | |
| 35 "zQgrNJtL0/I/j9sO6A0YQeHzmnlyoAd14VhBfEllZc51pFaut31wpbPPxtH0K0Ro\n" | |
| 36 "2XUCAwEAAaNQME4wHQYDVR0OBBYEFD7eitJ8KlIaVS4J9w2Nz+5OE8H0MB8GA1Ud\n" | |
| 37 "IwQYMBaAFD7eitJ8KlIaVS4J9w2Nz+5OE8H0MAwGA1UdEwQFMAMBAf8wDQYJKoZI\n" | |
| 38 "hvcNAQELBQADggEBAFjuy0Jhj2E/ALOkOst53/nHIpT5suru4H6YEmmPye+KCQnC\n" | |
| 39 "ws1msPyLQ8V10/kyQzJTSLbeehNyOaK99KJk+hZBVEKBa9uH3WXPpiwz1xr3STJO\n" | |
| 40 "hhV2wXGTMqe5gryR7r+n88+2TpRiZ/mAVyJm4NQgev4HZbFsl3sT50AQrrEbHHiY\n" | |
| 41 "Sh38NCR8JCVuzLBjcEEIWxjhDPkdNPJtx3cBkIDP+Cz1AUSPretGk7CQAGivq7Kq\n" | |
| 42 "9y6A59guc1RFVPeEQAxUIUDZGDQlB3PtmrXrp1/LAaDYvQCstDBgiZoamy+xSROP\n" | |
| 43 "BU2KIzRj2EUOWqtIURU4Q2QC1fbVqxVjfPowX/A=\n" | |
| 44 "-----END CERTIFICATE-----\n"; | |
| 45 | |
| 46 // Certificate without a subject CN. The subject organisation is set to | |
| 47 // "The Chromium Projects" and the subject origanisational unit is set to | |
| 48 // "Security". | |
| 49 static const char kSelfSignedWithoutCommonNamePEM[] = | |
| 50 "-----BEGIN CERTIFICATE-----\n" | |
| 51 "MIIDUzCCAjugAwIBAgIJAI18Ifktf3YOMA0GCSqGSIb3DQEBCwUAMEAxHjAcBgNV\n" | |
| 52 "BAoMFVRoZSBDaHJvbWl1bSBQcm9qZWN0czERMA8GA1UECwwIU2VjdXJpdHkxCzAJ\n" | |
| 53 "BgNVBAYTAlVTMB4XDTE3MDEyOTIxMTMwMloXDTE4MDEyOTIxMTMwMlowQDEeMBwG\n" | |
| 54 "A1UECgwVVGhlIENocm9taXVtIFByb2plY3RzMREwDwYDVQQLDAhTZWN1cml0eTEL\n" | |
| 55 "MAkGA1UEBhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCxfBIg\n" | |
| 56 "4hVljlFbyZ88mhLEKCfy/8X127H16ywcy+q+jlj7YtlWqGKlfIjKQkXKeI/xUB1F\n" | |
| 57 "ZC1S0kmVycAoahb4m+NqkfBkuxbpc5gYsv9TdgiNIhEezx6Z9OTPjGnTZVDjJNsQ\n" | |
| 58 "MVKfG+DD3qAf22PhpU2zGXCF2ECL7J/Lh6Wu/W3InuIcJGm3D7F182UK86stvC/+\n" | |
| 59 "mS9K7AJyX320vHWYsVB/jA9w6cSdlZf454E+wtsS0b+UIMF6fewg2Xb/FYxRsOjp\n" | |
| 60 "ppVpF8/2v6JzDjBhdZkYufR5M43tCEUBBK6TwfXAPfK3v2IDcoW+iOuztW5/cdTs\n" | |
| 61 "rVaGK9YqRDIeFWKNAgMBAAGjUDBOMB0GA1UdDgQWBBRh2Ef5+mRtj2sJHpXWlWai\n" | |
| 62 "D3zNXTAfBgNVHSMEGDAWgBRh2Ef5+mRtj2sJHpXWlWaiD3zNXTAMBgNVHRMEBTAD\n" | |
| 63 "AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAmxdLSlb76yre3VmugMQqybSkJr4+OZm6c\n" | |
| 64 "ES6TQeBzNrbPQhYPAfTUa2i4Cx5r4tMTp1IfUKgtng4qnKyLRgC+BV4zAfSRxbuw\n" | |
| 65 "aqicO1Whtl/Vs2Cdou10EU68kKOxLqNdzfXVVSQ/HxGFJFFJdSLfjpRTcfbORfeh\n" | |
| 66 "BfFQkjdlK8DdX8pPLjHImFKXT/8IpPPq41k2KuIhG3cd2vBNV7n7U793LSE+dPQk\n" | |
| 67 "0jKehPOfiPBl1nWr7ZTF8bYtgxboVsv73E6IoQhPGPnnDF3ISQ5/ulDQNXJr2PI3\n" | |
| 68 "ZYZ4PtSKcBi97BucW7lkt3bWY44TZGVHY1s4EGQFqU4aDyP+aR7Z\n" | |
| 69 "-----END CERTIFICATE-----\n"; | |
| 70 | |
| 71 // Certificate without a subject CN, organisation or organizational unit. | |
| 72 static const char kSelfSignedWithoutSubject[] = | |
| 73 "-----BEGIN CERTIFICATE-----\n" | |
| 74 "MIIC7TCCAdWgAwIBAgIJAOPMcoAKhzZPMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\n" | |
| 75 "BAYTAlVTMB4XDTE3MDEyOTIxNDA1MloXDTE4MDEyOTIxNDA1MlowDTELMAkGA1UE\n" | |
| 76 "BhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDLn0oths5iUbDN\n" | |
| 77 "h5IssWAf4jBRVh0c7AfVpnsriSdpgMEfApjE4Fcb3ma/8g+f2SB0x7bSLKMfpKZl\n" | |
| 78 "v7tQBuNXsbMcv1l4Ip595ZznSr74Fpuc6K0pqaVUSrgt2EVDp6lx12fFcXMI08Ar\n" | |
| 79 "76v06loe7HnO+cOCAXn3Yd89UznB7w8a+RiJlUzb4vksksSQyxCOYwahx6kuN9vh\n" | |
| 80 "MkjmzoVSbO6vtHktECsq5M2k98GZMmbXimW+lkyqsG3qJnmAYsIapDE1droPp5Cx\n" | |
| 81 "l/tQ95CKEZQDuF4Zv+fgg0eHnnCAhuCPnM8GblOTsAsSjNd8GM+4eJPPtAHdB1nn\n" | |
| 82 "HCYB/QadAgMBAAGjUDBOMB0GA1UdDgQWBBTxlQlna2f2VttJkEoeayPsCF7SxzAf\n" | |
| 83 "BgNVHSMEGDAWgBTxlQlna2f2VttJkEoeayPsCF7SxzAMBgNVHRMEBTADAQH/MA0G\n" | |
| 84 "CSqGSIb3DQEBCwUAA4IBAQBUOmDhs3K1v+tPeO+TWFw8NDfOkcWy6EX+c6K7mSwF\n" | |
| 85 "mJjqWsEUBp+WbTK6RoVjuLucH5mRF3FmRrW/hOnxIWxpHg5/9vodReLDPnUw0Anb\n" | |
| 86 "QoxKgJ41VfD8aGK8GDPOrETwbIR6+d9P6bDKukiuW41Yh5TjXLufaQ1g9C1AIEoG\n" | |
| 87 "88Akr6g9Q0vJJXGl9YcPFz6M1wm3l/lH08v2Ual52elFXYcDcoxhLCOdImmWGlnn\n" | |
| 88 "MYXxdl1ivj3hHgFXxkIbrlYKVSBhwPPgjVYKkimFcZF5Xw7wfmIl/WUtVaRpmkGp\n" | |
| 89 "3TgH7jdRQ1WXlROBct/4Z8jzs7i+Ttk8oxct2r+PdqeZ\n" | |
| 90 "-----END CERTIFICATE-----\n"; | |
| 91 | |
| 92 // Valid PEM certificate headers but invalid BASE64 content. | |
| 93 static const char kInvalidCertificatePEM[] = | |
| 94 "-----BEGIN CERTIFICATE-----\n" | |
| 95 "This is invalid base64.\n" | |
| 96 "It contains some (#$*) invalid characters.\n" | |
| 97 "-----END CERTIFICATE-----\n"; | |
| 98 | |
| 99 // Valid PEM public key headers but invalid BASE64 content. | |
| 100 static const char kInvalidPublicKeyPEM[] = | |
| 101 "-----BEGIN PUBLIC KEY-----\n" | |
| 102 "This is invalid base64.\n" | |
| 103 "It contains some (#$*) invalid characters.\n" | |
| 104 "-----END PUBLIC KEY-----\n"; | |
| 105 | |
| 106 // Valid 2048 bit RSA public key. | |
| 107 static const char kPublicKeyPEM[] = | |
| 108 "-----BEGIN PUBLIC KEY-----\n" | |
| 109 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAujzwcb5bJuC/A/Y9izGl\n" | |
| 110 "LlA3fnKGbeyn53BdVznJN4fQwU82WKVYdqt8d/1ZDRdYyhGrTgXJeCURe9VSJyX1\n" | |
| 111 "X2a5EApSFsopP8Yjy0Rl6dNOLO84KCW9dPmfHC3uP0ac4hnHT5dUr05YvhJmHCkf\n" | |
| 112 "as6v/aEgpPLDhRF6UruSUh+gIpUg/F3+vlD99HLfbloukoDtQyxW+86s9sO7RQ00\n" | |
| 113 "pd79VOoa/v09FvoS7MFgnBBOtvBQLOXjEH7/qBsnrXFtHBeOtxSLar/FL3OhVXuh\n" | |
| 114 "dUTRyc1Mg0ECtz8zHZugW+LleIm5Bf5Yr0bN1O/HfDPCkDaCldcm6xohEHn9pBaW\n" | |
| 115 "+wIDAQAB\n" | |
| 116 "-----END PUBLIC KEY-----\n"; | |
| 117 | |
| 118 // Valid 2048 bit RSA public key with incorrect PEM headers. | |
| 119 static const char kUnknownPEMHeaders[] = | |
| 120 "-----BEGIN OF SOMETHING-----\n" | |
| 121 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAujzwcb5bJuC/A/Y9izGl\n" | |
| 122 "LlA3fnKGbeyn53BdVznJN4fQwU82WKVYdqt8d/1ZDRdYyhGrTgXJeCURe9VSJyX1\n" | |
| 123 "X2a5EApSFsopP8Yjy0Rl6dNOLO84KCW9dPmfHC3uP0ac4hnHT5dUr05YvhJmHCkf\n" | |
| 124 "as6v/aEgpPLDhRF6UruSUh+gIpUg/F3+vlD99HLfbloukoDtQyxW+86s9sO7RQ00\n" | |
| 125 "pd79VOoa/v09FvoS7MFgnBBOtvBQLOXjEH7/qBsnrXFtHBeOtxSLar/FL3OhVXuh\n" | |
| 126 "dUTRyc1Mg0ECtz8zHZugW+LleIm5Bf5Yr0bN1O/HfDPCkDaCldcm6xohEHn9pBaW\n" | |
| 127 "+wIDAQAB\n" | |
| 128 "-----END OF SOMETHING-----\n"; | |
| 129 | |
| 130 TEST(CertUtilTest, GetX509CertificateFromPEM) { | |
| 131 EXPECT_NE(nullptr, GetX509CertificateFromPEM( | |
| 132 std::string(kSelfSignedWithCommonNamePEM))); | |
| 133 EXPECT_NE(nullptr, | |
| 134 GetX509CertificateFromPEM(std::string(kSelfSignedWithoutSubject))); | |
| 135 EXPECT_EQ(nullptr, | |
| 136 GetX509CertificateFromPEM(std::string(kInvalidCertificatePEM))); | |
| 137 EXPECT_EQ(nullptr, | |
| 138 GetX509CertificateFromPEM(std::string(kInvalidPublicKeyPEM))); | |
|
davidben
2017/04/03 20:53:02
I don't believe you need the std::string calls her
martijnc
2017/04/04 18:31:09
Done.
| |
| 139 } | |
| 140 | |
| 141 // Test that the SPKI digest is correctly calculated for valid certificates. | |
| 142 TEST(CertUtilTest, CalculateSPKIHashFromCertificate) { | |
| 143 bssl::UniquePtr<X509> cert1; | |
| 144 SPKIHash hash1; | |
| 145 cert1 = GetX509CertificateFromPEM(std::string(kSelfSignedWithCommonNamePEM)); | |
|
davidben
2017/04/03 20:53:02
Nit: bssl::UniquePtr<X509> cert1 = ....;
(Fold th
martijnc
2017/04/04 18:31:09
Done.
| |
| 146 EXPECT_TRUE(CalculateSPKIHashFromCertificate(cert1.get(), &hash1)); | |
| 147 std::vector<uint8_t> hash_vector(hash1.data(), hash1.data() + hash1.size()); | |
| 148 EXPECT_THAT( | |
| 149 hash_vector, | |
| 150 testing::ElementsAreArray( | |
| 151 {0xAC, 0xFB, 0x2B, 0xF3, 0x6A, 0x90, 0x47, 0xF1, 0x74, 0xAE, 0xF1, | |
| 152 0xCE, 0x63, 0x3D, 0xA9, 0x45, 0xCB, 0xA, 0xA7, 0x3F, 0x16, 0x2A, | |
| 153 0xF3, 0x88, 0x9A, 0xE2, 0x72, 0xC, 0x07, 0x63, 0x45, 0xB0})); | |
| 154 | |
| 155 bssl::UniquePtr<X509> cert2; | |
|
davidben
2017/04/03 20:53:02
Ditto.
martijnc
2017/04/04 18:31:09
Done.
| |
| 156 SPKIHash hash2; | |
| 157 cert2 = | |
| 158 GetX509CertificateFromPEM(std::string(kSelfSignedWithoutCommonNamePEM)); | |
| 159 EXPECT_TRUE(CalculateSPKIHashFromCertificate(cert2.get(), &hash2)); | |
| 160 std::vector<uint8_t> hash_vector2(hash2.data(), hash2.data() + hash2.size()); | |
| 161 EXPECT_THAT( | |
| 162 hash_vector2, | |
| 163 testing::ElementsAreArray( | |
| 164 {0x40, 0xBC, 0xD6, 0xE4, 0x10, 0x70, 0x37, 0x3C, 0xF7, 0x21, 0x51, | |
| 165 0xD7, 0x27, 0x64, 0xFD, 0xF1, 0xA, 0x89, 0x0, 0xAD, 0x75, 0xDF, | |
| 166 0xB3, 0xEA, 0x21, 0xFC, 0x6E, 0x67, 0xD5, 0xAE, 0xA4, 0x94})); | |
| 167 } | |
| 168 | |
| 169 // Test that the SPKI digest for public key's are calculated correctly. | |
| 170 TEST(CertUtilTest, CalculateSPKIHashFromKey) { | |
| 171 SPKIHash hash1; | |
| 172 EXPECT_TRUE(CalculateSPKIHashFromKey(std::string(kPublicKeyPEM), &hash1)); | |
| 173 std::vector<uint8_t> hash_vector(hash1.data(), hash1.data() + hash1.size()); | |
| 174 EXPECT_THAT( | |
| 175 hash_vector, | |
| 176 testing::ElementsAreArray( | |
| 177 {0x63, 0xB0, 0x21, 0x4, 0x3, 0x13, 0x9E, 0x36, 0xEE, 0xCB, 0x6F, | |
| 178 0xA5, 0x7A, 0x94, 0x56, 0x18, 0xBA, 0x41, 0x13, 0x8C, 0x4A, 0x48, | |
| 179 0x99, 0x80, 0x51, 0x66, 0xF8, 0x85, 0x2, 0xFC, 0x48, 0x9E})); | |
| 180 SPKIHash hash2; | |
| 181 EXPECT_FALSE( | |
| 182 CalculateSPKIHashFromKey(std::string(kInvalidPublicKeyPEM), &hash2)); | |
| 183 | |
| 184 SPKIHash hash3; | |
| 185 EXPECT_FALSE(CalculateSPKIHashFromKey( | |
| 186 std::string(kSelfSignedWithoutCommonNamePEM), &hash3)); | |
| 187 | |
| 188 SPKIHash hash4; | |
| 189 EXPECT_FALSE( | |
| 190 CalculateSPKIHashFromKey(std::string(kUnknownPEMHeaders), &hash4)); | |
| 191 } | |
| 192 | |
| 193 // Test that the subject name is extracted correctly. This should default to the | |
| 194 // subject common name and fall back to the organisation + organizational unit. | |
| 195 TEST(CertUtilTest, ExtractSubjectNameFromCertificate) { | |
| 196 bssl::UniquePtr<X509> cert1; | |
| 197 std::string name1; | |
| 198 cert1 = GetX509CertificateFromPEM(std::string(kSelfSignedWithCommonNamePEM)); | |
|
davidben
2017/04/03 20:53:02
Ditto re folding lines together.
martijnc
2017/04/04 18:31:09
Done.
| |
| 199 EXPECT_TRUE(ExtractSubjectNameFromCertificate(cert1.get(), &name1)); | |
| 200 | |
| 201 // For certficates with the subject common name field set, we should get the | |
| 202 // value of the subject common name. | |
| 203 EXPECT_EQ("Chromium", name1); | |
| 204 | |
| 205 bssl::UniquePtr<X509> cert2; | |
| 206 std::string name2; | |
| 207 cert2 = | |
| 208 GetX509CertificateFromPEM(std::string(kSelfSignedWithoutCommonNamePEM)); | |
|
davidben
2017/04/03 20:53:01
Ditto.
martijnc
2017/04/04 18:31:09
Done.
| |
| 209 EXPECT_TRUE(ExtractSubjectNameFromCertificate(cert2.get(), &name2)); | |
| 210 | |
| 211 // For certificates without a subject common name field, we should get | |
| 212 // the subject organization + " " + organizational unit instead. | |
| 213 EXPECT_EQ("The Chromium Projects Security", name2); | |
| 214 | |
| 215 bssl::UniquePtr<X509> cert3; | |
| 216 std::string name3; | |
| 217 cert3 = GetX509CertificateFromPEM(std::string(kSelfSignedWithoutSubject)); | |
|
davidben
2017/04/03 20:53:01
Ditto.
martijnc
2017/04/04 18:31:09
Done.
| |
| 218 EXPECT_FALSE(ExtractSubjectNameFromCertificate(cert3.get(), &name3)); | |
| 219 } | |
| 220 | |
| 221 } // namespace | |
| 222 | |
| 223 } // namespace transport_security_state | |
| 224 | |
| 225 } // namespace net | |
| OLD | NEW |