Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(726)

Side by Side Diff: net/base/hsts_preloaded.h

Issue 9863001: net: move HSTS preloaded and pinning info out of code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: ... Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | net/base/hsts_preloaded.certs » ('j') | net/base/hsts_preloaded.json » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // This file is automatically generated by hsts_preloaded_generate.go
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 2
5 #ifndef NET_BASE_PUBLIC_KEY_HASHES_ 3 #ifndef NET_BASE_HSTS_PRELOADED_H_
6 #define NET_BASE_PUBLIC_KEY_HASHES_ 4 #define NET_BASE_HSTS_PRELOADED_H_
7 #pragma once 5 #pragma once
8 6
9 // This file contains SubjectPublicKeyInfo hashes for public key pinning. The 7 // These are SubjectPublicKeyInfo hashes for public key pinning. The
10 // hashes are base64 encoded, SHA1 digests. 8 // hashes are base64 encoded, SHA1 digests.
11 9
10 static const char kSPKIHash_TestSPKI[] =
11 "sha1/AAAAAAAAAAAAAAAAAAAAAAAAAAA=";
12
12 #if 0 13 #if 0
13 -----BEGIN CERTIFICATE----- 14 -----BEGIN CERTIFICATE-----
palmer 2012/03/26 23:40:21 Since the certificates are in the .certs file, may
agl 2012/03/28 16:20:30 That's a fair point. Although I'd like to remove t
14 MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkG 15 MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkG
15 A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz 16 A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
16 cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 17 cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
17 MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV 18 MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
18 BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt 19 BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
19 YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN 20 YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
20 ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE 21 ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
21 BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is 22 BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
22 I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G 23 I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
23 CSqGSIb3DQEBBQUAA4GBABByUqkFFBkyCEHwxWsKzH4PIRnN5GfcX6kb5sroc50i 24 CSqGSIb3DQEBBQUAA4GBABByUqkFFBkyCEHwxWsKzH4PIRnN5GfcX6kb5sroc50i
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 Af8CAQAwOgYDVR0fBDMwMTAvoC2gK4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20v 73 Af8CAQAwOgYDVR0fBDMwMTAvoC2gK4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20v
73 Y3Jscy9zZWN1cmVjYS5jcmwwDQYJKoZIhvcNAQEFBQADgYEAuIojxkiWsRF8YHde 74 Y3Jscy9zZWN1cmVjYS5jcmwwDQYJKoZIhvcNAQEFBQADgYEAuIojxkiWsRF8YHde
74 BZqrocb6ghwYB8TrgbCoZutJqOkM0ymt9e8kTP3kS8p/XmOrmSfLnzYhLLkQYGfN 75 BZqrocb6ghwYB8TrgbCoZutJqOkM0ymt9e8kTP3kS8p/XmOrmSfLnzYhLLkQYGfN
75 0rTw8Ktx5YtaiScRhKqOv5nwnQkhClIZmloJ0pC3+gz4fniisIWvXEyZ2VxVKfml 76 0rTw8Ktx5YtaiScRhKqOv5nwnQkhClIZmloJ0pC3+gz4fniisIWvXEyZ2VxVKfml
76 UUIuOss4jHg7y/j7lYe8vJD5UDI= 77 UUIuOss4jHg7y/j7lYe8vJD5UDI=
77 -----END CERTIFICATE----- 78 -----END CERTIFICATE-----
78 #endif 79 #endif
79 static const char kSPKIHash_Google1024[] = 80 static const char kSPKIHash_Google1024[] =
80 "sha1/QMVAHW+MuvCLAO3vse6H0AWzuc0="; 81 "sha1/QMVAHW+MuvCLAO3vse6H0AWzuc0=";
81 82
82 // Not yet used publicly.
83 static const char kSPKIHash_Google2048[] = 83 static const char kSPKIHash_Google2048[] =
84 "sha1/AbkhxY0L343gKf+cki7NVWp+ozk="; 84 "sha1/AbkhxY0L343gKf+cki7NVWp+ozk=";
85 85
86 #if 0 86 #if 0
87 -----BEGIN CERTIFICATE----- 87 -----BEGIN CERTIFICATE-----
88 MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV 88 MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
89 UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy 89 UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy
90 dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 90 dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1
91 MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx 91 MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx
92 dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B 92 dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF 316 eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
317 hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 317 hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
318 Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe 318 Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
319 vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep 319 vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
320 +OkuE6N36B9K 320 +OkuE6N36B9K
321 -----END CERTIFICATE----- 321 -----END CERTIFICATE-----
322 #endif 322 #endif
323 static const char kSPKIHash_DigiCertEVRoot[] = 323 static const char kSPKIHash_DigiCertEVRoot[] =
324 "sha1/gzF+YoVCU9bXeDGQ7JGQVumRueM="; 324 "sha1/gzF+YoVCU9bXeDGQ7JGQVumRueM=";
325 325
326 // Not public
327 static const char kSPKIHash_Tor1[] = 326 static const char kSPKIHash_Tor1[] =
328 "sha1/juNxSTv9UANmpC9kF5GKpmWNx3Y="; 327 "sha1/juNxSTv9UANmpC9kF5GKpmWNx3Y=";
328
329 static const char kSPKIHash_Tor2[] = 329 static const char kSPKIHash_Tor2[] =
330 "sha1/lia43lPolzSPVIq34Dw57uYcLD8="; 330 "sha1/lia43lPolzSPVIq34Dw57uYcLD8=";
331
331 static const char kSPKIHash_Tor3[] = 332 static const char kSPKIHash_Tor3[] =
332 "sha1/rzEyQIKOh77j87n5bjWUNguXF8Y="; 333 "sha1/rzEyQIKOh77j87n5bjWUNguXF8Y=";
333 334
334 #if 0 335 #if 0
335 -----BEGIN CERTIFICATE----- 336 -----BEGIN CERTIFICATE-----
336 MIICPTCCAaYCEQDNun9W8N/kvFT+IqyzcqpVMA0GCSqGSIb3DQEBAgUAMF8xCzAJ 337 MIICPTCCAaYCEQDNun9W8N/kvFT+IqyzcqpVMA0GCSqGSIb3DQEBAgUAMF8xCzAJ
337 BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xh 338 BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xh
338 c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05 339 c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05
339 NjAxMjkwMDAwMDBaFw0yODA4MDEyMzU5NTlaMF8xCzAJBgNVBAYTAlVTMRcwFQYD 340 NjAxMjkwMDAwMDBaFw0yODA4MDEyMzU5NTlaMF8xCzAJBgNVBAYTAlVTMRcwFQYD
340 VQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMSBQdWJsaWMgUHJp 341 VQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMSBQdWJsaWMgUHJp
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
571 seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz 572 seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz
572 4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+ 573 4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+
573 BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR 574 BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR
574 lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3 575 lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3
575 7M2CYfE45k+XmCpajQ== 576 7M2CYfE45k+XmCpajQ==
576 -----END CERTIFICATE----- 577 -----END CERTIFICATE-----
577 #endif 578 #endif
578 static const char kSPKIHash_VeriSignUniversal[] = 579 static const char kSPKIHash_VeriSignUniversal[] =
579 "sha1/u8I+KQuzKHcdrT6iTb30I70GsD0="; 580 "sha1/u8I+KQuzKHcdrT6iTb30I70GsD0=";
580 581
581 // Not public
582 static const char kSPKIHash_Twitter1[] = 582 static const char kSPKIHash_Twitter1[] =
583 "sha1/Vv7zwhR9TtOIN/29MFI4cgHld40="; 583 "sha1/Vv7zwhR9TtOIN/29MFI4cgHld40=";
584 584
585 #if 0 585 #if 0
586 -----BEGIN CERTIFICATE----- 586 -----BEGIN CERTIFICATE-----
587 MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEW 587 MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEW
588 MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFs 588 MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFs
589 IENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQG 589 IENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQG
590 EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg 590 EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg
591 R2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvPE1A 591 R2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvPE1A
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
726 AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH 726 AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH
727 SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G 727 SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G
728 spki4cErx5z481+oghLrGREt 728 spki4cErx5z481+oghLrGREt
729 -----END CERTIFICATE----- 729 -----END CERTIFICATE-----
730 #endif 730 #endif
731 static const char kSPKIHash_GeoTrustPrimary_G3[] = 731 static const char kSPKIHash_GeoTrustPrimary_G3[] =
732 "sha1/nKmNAK90Dd2BgNITRaWLjy6UONY="; 732 "sha1/nKmNAK90Dd2BgNITRaWLjy6UONY=";
733 733
734 #if 0 734 #if 0
735 -----BEGIN CERTIFICATE----- 735 -----BEGIN CERTIFICATE-----
736 MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u 736 MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML
agl 2012/03/26 21:20:29 Note that this is the same certificate, but the PE
737 ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp 737 RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp
738 bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV 738 bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5
739 BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx 739 IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp
740 NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3 740 ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3
741 d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl 741 MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3
742 MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u 742 LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp
743 ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A 743 YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG
744 MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL 744 A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp
745 Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr 745 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq
746 hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW 746 K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe
747 nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi 747 sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX
748 VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E 748 MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT
749 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ 749 XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/
750 KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy 750 HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH
751 T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf 751 4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
752 zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT 752 HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub
753 J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e 753 j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo
754 nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE= 754 U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
755 zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b
756 u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+
757 bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er
758 fF6adulZkMV8gzURZVE=
755 -----END CERTIFICATE----- 759 -----END CERTIFICATE-----
756 #endif 760 #endif
757 static const char kSPKIHash_Entrust_2048[] = 761 static const char kSPKIHash_Entrust_2048[] =
758 "sha1/VeSB0RGAvtiJuQijMfmhJAkWuXA="; 762 "sha1/VeSB0RGAvtiJuQijMfmhJAkWuXA=";
759 763
760 #if 0 764 #if 0
761 -----BEGIN CERTIFICATE----- 765 -----BEGIN CERTIFICATE-----
762 MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC 766 MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC
763 VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 767 VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0
764 Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW 768 Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after
1228 r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4 1232 r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4
1229 04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r 1233 04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r
1230 GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9 1234 GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9
1231 3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P 1235 3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P
1232 lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ 1236 lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/
1233 -----END CERTIFICATE----- 1237 -----END CERTIFICATE-----
1234 #endif 1238 #endif
1235 static const char kSPKIHash_GTECyberTrustGlobalRoot[] = 1239 static const char kSPKIHash_GTECyberTrustGlobalRoot[] =
1236 "sha1/WXkS3mF11m/EI7d3E3THlt5viHI="; 1240 "sha1/WXkS3mF11m/EI7d3E3THlt5viHI=";
1237 1241
1238 #endif // NET_BASE_PUBLIC_KEY_HASHES_ 1242 // The following is static data describing the hosts that are hardcoded with
1239 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1243 // certificate pins or HSTS information.
1240 // Use of this source code is governed by a BSD-style license that can be
1241 // found in the LICENSE file.
1242
1243 #include "net/base/transport_security_state.h"
1244
1245 #if defined(USE_OPENSSL)
1246 #include <openssl/ecdsa.h>
1247 #include <openssl/ssl.h>
1248 #else // !defined(USE_OPENSSL)
1249 #include <cryptohi.h>
1250 #include <hasht.h>
1251 #include <keyhi.h>
1252 #include <pk11pub.h>
1253 #include <nspr.h>
1254 #endif
1255
1256 #include <algorithm>
1257 #include <utility>
1258
1259 #include "base/base64.h"
1260 #include "base/json/json_reader.h"
1261 #include "base/json/json_writer.h"
1262 #include "base/logging.h"
1263 #include "base/memory/scoped_ptr.h"
1264 #include "base/metrics/histogram.h"
1265 #include "base/sha1.h"
1266 #include "base/string_number_conversions.h"
1267 #include "base/string_tokenizer.h"
1268 #include "base/string_util.h"
1269 #include "base/time.h"
1270 #include "base/utf_string_conversions.h"
1271 #include "base/values.h"
1272 #include "crypto/sha2.h"
1273 #include "googleurl/src/gurl.h"
1274 #include "net/base/asn1_util.h"
1275 #include "net/base/dns_util.h"
1276 #include "net/base/public_key_hashes.h"
1277 #include "net/base/ssl_info.h"
1278 #include "net/base/x509_certificate.h"
1279 #include "net/http/http_util.h"
1280
1281 #if defined(USE_OPENSSL)
1282 #include "crypto/openssl_util.h"
1283 #endif
1284
1285 namespace net {
1286
1287 const long int TransportSecurityState::kMaxHSTSAgeSecs = 86400 * 365; // 1 year
1288
1289 TransportSecurityState::TransportSecurityState(const std::string& hsts_hosts)
1290 : delegate_(NULL) {
1291 if (!hsts_hosts.empty()) {
1292 bool dirty;
1293 Deserialise(hsts_hosts, &dirty, &forced_hosts_);
1294 }
1295 }
1296
1297 static std::string HashHost(const std::string& canonicalized_host) {
1298 char hashed[crypto::kSHA256Length];
1299 crypto::SHA256HashString(canonicalized_host, hashed, sizeof(hashed));
1300 return std::string(hashed, sizeof(hashed));
1301 }
1302
1303 void TransportSecurityState::SetDelegate(
1304 TransportSecurityState::Delegate* delegate) {
1305 delegate_ = delegate;
1306 }
1307
1308 void TransportSecurityState::EnableHost(const std::string& host,
1309 const DomainState& state) {
1310 DCHECK(CalledOnValidThread());
1311
1312 const std::string canonicalized_host = CanonicalizeHost(host);
1313 if (canonicalized_host.empty())
1314 return;
1315
1316 // Only override a preloaded state if the new state describes a more strict
1317 // policy. TODO(palmer): Reconsider this?
1318 DomainState existing_state;
1319 if (IsPreloadedSTS(canonicalized_host, true, &existing_state) &&
1320 canonicalized_host == CanonicalizeHost(existing_state.domain) &&
1321 existing_state.IsMoreStrict(state)) {
1322 return;
1323 }
1324
1325 // Use the original creation date if we already have this host.
1326 DomainState state_copy(state);
1327 if (GetDomainState(&existing_state, host, true) &&
1328 !existing_state.created.is_null()) {
1329 state_copy.created = existing_state.created;
1330 }
1331
1332 // We don't store these values.
1333 state_copy.preloaded = false;
1334 state_copy.domain.clear();
1335
1336 enabled_hosts_[HashHost(canonicalized_host)] = state_copy;
1337 DirtyNotify();
1338 }
1339
1340 bool TransportSecurityState::DeleteHost(const std::string& host) {
1341 DCHECK(CalledOnValidThread());
1342
1343 const std::string canonicalized_host = CanonicalizeHost(host);
1344 if (canonicalized_host.empty())
1345 return false;
1346
1347 std::map<std::string, DomainState>::iterator i = enabled_hosts_.find(
1348 HashHost(canonicalized_host));
1349 if (i != enabled_hosts_.end()) {
1350 enabled_hosts_.erase(i);
1351 DirtyNotify();
1352 return true;
1353 }
1354 return false;
1355 }
1356
1357 bool TransportSecurityState::HasPinsForHost(DomainState* result,
1358 const std::string& host,
1359 bool sni_available) {
1360 DCHECK(CalledOnValidThread());
1361
1362 return HasMetadata(result, host, sni_available) &&
1363 (!result->dynamic_spki_hashes.empty() ||
1364 !result->preloaded_spki_hashes.empty());
1365 }
1366
1367 bool TransportSecurityState::GetDomainState(DomainState* result,
1368 const std::string& host,
1369 bool sni_available) {
1370 DCHECK(CalledOnValidThread());
1371
1372 return HasMetadata(result, host, sni_available);
1373 }
1374
1375 bool TransportSecurityState::HasMetadata(DomainState* result,
1376 const std::string& host,
1377 bool sni_available) {
1378 DCHECK(CalledOnValidThread());
1379
1380 DomainState state;
1381 const std::string canonicalized_host = CanonicalizeHost(host);
1382 if (canonicalized_host.empty())
1383 return false;
1384
1385 bool has_preload = IsPreloadedSTS(canonicalized_host, sni_available, &state);
1386 std::string canonicalized_preload = CanonicalizeHost(state.domain);
1387
1388 base::Time current_time(base::Time::Now());
1389
1390 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
1391 std::string host_sub_chunk(&canonicalized_host[i],
1392 canonicalized_host.size() - i);
1393 // Exact match of a preload always wins.
1394 if (has_preload && host_sub_chunk == canonicalized_preload) {
1395 *result = state;
1396 return true;
1397 }
1398
1399 std::map<std::string, DomainState>::iterator j =
1400 enabled_hosts_.find(HashHost(host_sub_chunk));
1401 if (j == enabled_hosts_.end())
1402 continue;
1403
1404 if (current_time > j->second.expiry &&
1405 current_time > j->second.dynamic_spki_hashes_expiry) {
1406 enabled_hosts_.erase(j);
1407 DirtyNotify();
1408 continue;
1409 }
1410
1411 state = j->second;
1412 state.domain = DNSDomainToString(host_sub_chunk);
1413
1414 // Succeed if we matched the domain exactly or if subdomain matches are
1415 // allowed.
1416 if (i == 0 || j->second.include_subdomains) {
1417 *result = state;
1418 return true;
1419 }
1420
1421 return false;
1422 }
1423
1424 return false;
1425 }
1426
1427 void TransportSecurityState::DeleteSince(const base::Time& time) {
1428 DCHECK(CalledOnValidThread());
1429
1430 bool dirtied = false;
1431
1432 std::map<std::string, DomainState>::iterator i = enabled_hosts_.begin();
1433 while (i != enabled_hosts_.end()) {
1434 if (i->second.created >= time) {
1435 dirtied = true;
1436 enabled_hosts_.erase(i++);
1437 } else {
1438 i++;
1439 }
1440 }
1441
1442 if (dirtied)
1443 DirtyNotify();
1444 }
1445
1446 // MaxAgeToInt converts a string representation of a number of seconds into a
1447 // int. We use strtol in order to handle overflow correctly. The string may
1448 // contain an arbitary number which we should truncate correctly rather than
1449 // throwing a parse failure.
1450 static bool MaxAgeToInt(std::string::const_iterator begin,
1451 std::string::const_iterator end,
1452 int* result) {
1453 const std::string s(begin, end);
1454 char* endptr;
1455 long int i = strtol(s.data(), &endptr, 10 /* base */);
1456 if (*endptr || i < 0)
1457 return false;
1458 if (i > TransportSecurityState::kMaxHSTSAgeSecs)
1459 i = TransportSecurityState::kMaxHSTSAgeSecs;
1460 *result = i;
1461 return true;
1462 }
1463
1464 // Strip, Split, StringPair, and ParsePins are private implementation details
1465 // of ParsePinsHeader(std::string&, DomainState&).
1466 static std::string Strip(const std::string& source) {
1467 if (source.empty())
1468 return source;
1469
1470 std::string::const_iterator start = source.begin();
1471 std::string::const_iterator end = source.end();
1472 HttpUtil::TrimLWS(&start, &end);
1473 return std::string(start, end);
1474 }
1475
1476 typedef std::pair<std::string, std::string> StringPair;
1477
1478 static StringPair Split(const std::string& source, char delimiter) {
1479 StringPair pair;
1480 size_t point = source.find(delimiter);
1481
1482 pair.first = source.substr(0, point);
1483 if (std::string::npos != point)
1484 pair.second = source.substr(point + 1);
1485
1486 return pair;
1487 }
1488
1489 // TODO(palmer): Support both sha256 and sha1. This will require additional
1490 // infrastructure code changes and can come in a later patch.
1491 //
1492 // static
1493 bool TransportSecurityState::ParsePin(const std::string& value,
1494 SHA1Fingerprint* out) {
1495 StringPair slash = Split(Strip(value), '/');
1496 if (slash.first != "sha1")
1497 return false;
1498
1499 std::string decoded;
1500 if (!base::Base64Decode(slash.second, &decoded) ||
1501 decoded.size() != arraysize(out->data)) {
1502 return false;
1503 }
1504
1505 memcpy(out->data, decoded.data(), arraysize(out->data));
1506 return true;
1507 }
1508
1509 static bool ParseAndAppendPin(const std::string& value,
1510 FingerprintVector* fingerprints) {
1511 // The base64'd fingerprint MUST be a quoted-string. 20 bytes base64'd is 28
1512 // characters; 32 bytes base64'd is 44 characters. TODO(palmer): Support
1513 // SHA256.
1514 size_t size = value.size();
1515 if (size != 30 || value[0] != '"' || value[size - 1] != '"')
1516 return false;
1517
1518 std::string unquoted = HttpUtil::Unquote(value);
1519 std::string decoded;
1520 SHA1Fingerprint fp;
1521
1522 if (!base::Base64Decode(unquoted, &decoded) ||
1523 decoded.size() != arraysize(fp.data)) {
1524 return false;
1525 }
1526
1527 memcpy(fp.data, decoded.data(), arraysize(fp.data));
1528 fingerprints->push_back(fp);
1529 return true;
1530 }
1531
1532 // static
1533 bool TransportSecurityState::GetPublicKeyHash(
1534 const X509Certificate& cert, SHA1Fingerprint* spki_hash) {
1535 std::string der_bytes;
1536 if (!X509Certificate::GetDEREncoded(cert.os_cert_handle(), &der_bytes))
1537 return false;
1538
1539 base::StringPiece spki;
1540 if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki))
1541 return false;
1542
1543 base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(spki.data()),
1544 spki.size(), spki_hash->data);
1545
1546 return true;
1547 }
1548
1549 struct FingerprintsEqualPredicate {
1550 explicit FingerprintsEqualPredicate(const SHA1Fingerprint& fingerprint) :
1551 fingerprint_(fingerprint) {}
1552
1553 bool operator()(const SHA1Fingerprint& other) const {
1554 return fingerprint_.Equals(other);
1555 }
1556
1557 const SHA1Fingerprint& fingerprint_;
1558 };
1559
1560 // Returns true iff there is an item in |pins| which is not present in
1561 // |from_cert_chain|. Such an SPKI hash is called a "backup pin".
1562 static bool IsBackupPinPresent(const FingerprintVector& pins,
1563 const FingerprintVector& from_cert_chain) {
1564 for (FingerprintVector::const_iterator
1565 i = pins.begin(); i != pins.end(); ++i) {
1566 FingerprintVector::const_iterator j =
1567 std::find_if(from_cert_chain.begin(), from_cert_chain.end(),
1568 FingerprintsEqualPredicate(*i));
1569 if (j == from_cert_chain.end())
1570 return true;
1571 }
1572
1573 return false;
1574 }
1575
1576 static bool HashesIntersect(const FingerprintVector& a,
1577 const FingerprintVector& b) {
1578 for (FingerprintVector::const_iterator
1579 i = a.begin(); i != a.end(); ++i) {
1580 FingerprintVector::const_iterator j =
1581 std::find_if(b.begin(), b.end(), FingerprintsEqualPredicate(*i));
1582 if (j != b.end())
1583 return true;
1584 }
1585
1586 return false;
1587 }
1588
1589 // Returns true iff |pins| contains both a live and a backup pin. A live pin
1590 // is a pin whose SPKI is present in the certificate chain in |ssl_info|. A
1591 // backup pin is a pin intended for disaster recovery, not day-to-day use, and
1592 // thus must be absent from the certificate chain. The Public-Key-Pins header
1593 // specification requires both.
1594 static bool IsPinListValid(const FingerprintVector& pins,
1595 const SSLInfo& ssl_info) {
1596 if (pins.size() < 2)
1597 return false;
1598
1599 const FingerprintVector& from_cert_chain = ssl_info.public_key_hashes;
1600 if (from_cert_chain.empty())
1601 return false;
1602
1603 return IsBackupPinPresent(pins, from_cert_chain) &&
1604 HashesIntersect(pins, from_cert_chain);
1605 }
1606
1607 // "Public-Key-Pins" ":"
1608 // "max-age" "=" delta-seconds ";"
1609 // "pin-" algo "=" base64 [ ";" ... ]
1610 //
1611 // static
1612 bool TransportSecurityState::ParsePinsHeader(const std::string& value,
1613 const SSLInfo& ssl_info,
1614 DomainState* state) {
1615 bool parsed_max_age = false;
1616 int max_age = 0;
1617 FingerprintVector pins;
1618
1619 std::string source = value;
1620
1621 while (!source.empty()) {
1622 StringPair semicolon = Split(source, ';');
1623 semicolon.first = Strip(semicolon.first);
1624 semicolon.second = Strip(semicolon.second);
1625 StringPair equals = Split(semicolon.first, '=');
1626 equals.first = Strip(equals.first);
1627 equals.second = Strip(equals.second);
1628
1629 if (LowerCaseEqualsASCII(equals.first, "max-age")) {
1630 if (equals.second.empty() ||
1631 !MaxAgeToInt(equals.second.begin(), equals.second.end(), &max_age)) {
1632 return false;
1633 }
1634 if (max_age > kMaxHSTSAgeSecs)
1635 max_age = kMaxHSTSAgeSecs;
1636 parsed_max_age = true;
1637 } else if (LowerCaseEqualsASCII(equals.first, "pin-sha1")) {
1638 if (!ParseAndAppendPin(equals.second, &pins))
1639 return false;
1640 } else if (LowerCaseEqualsASCII(equals.first, "pin-sha256")) {
1641 // TODO(palmer)
1642 } else {
1643 // Silently ignore unknown directives for forward compatibility.
1644 }
1645
1646 source = semicolon.second;
1647 }
1648
1649 if (!parsed_max_age || !IsPinListValid(pins, ssl_info))
1650 return false;
1651
1652 state->max_age = max_age;
1653 state->dynamic_spki_hashes_expiry =
1654 base::Time::Now() + base::TimeDelta::FromSeconds(max_age);
1655
1656 state->dynamic_spki_hashes.clear();
1657 if (max_age > 0) {
1658 for (FingerprintVector::const_iterator i = pins.begin();
1659 i != pins.end(); i++) {
1660 state->dynamic_spki_hashes.push_back(*i);
1661 }
1662 }
1663
1664 return true;
1665 }
1666
1667 // "Strict-Transport-Security" ":"
1668 // "max-age" "=" delta-seconds [ ";" "includeSubDomains" ]
1669 //
1670 // static
1671 bool TransportSecurityState::ParseHeader(const std::string& value,
1672 int* max_age,
1673 bool* include_subdomains) {
1674 DCHECK(max_age);
1675 DCHECK(include_subdomains);
1676
1677 int max_age_candidate = 0;
1678
1679 enum ParserState {
1680 START,
1681 AFTER_MAX_AGE_LABEL,
1682 AFTER_MAX_AGE_EQUALS,
1683 AFTER_MAX_AGE,
1684 AFTER_MAX_AGE_INCLUDE_SUB_DOMAINS_DELIMITER,
1685 AFTER_INCLUDE_SUBDOMAINS,
1686 } state = START;
1687
1688 StringTokenizer tokenizer(value, " \t=;");
1689 tokenizer.set_options(StringTokenizer::RETURN_DELIMS);
1690 while (tokenizer.GetNext()) {
1691 DCHECK(!tokenizer.token_is_delim() || tokenizer.token().length() == 1);
1692 switch (state) {
1693 case START:
1694 if (IsAsciiWhitespace(*tokenizer.token_begin()))
1695 continue;
1696 if (!LowerCaseEqualsASCII(tokenizer.token(), "max-age"))
1697 return false;
1698 state = AFTER_MAX_AGE_LABEL;
1699 break;
1700
1701 case AFTER_MAX_AGE_LABEL:
1702 if (IsAsciiWhitespace(*tokenizer.token_begin()))
1703 continue;
1704 if (*tokenizer.token_begin() != '=')
1705 return false;
1706 DCHECK_EQ(tokenizer.token().length(), 1U);
1707 state = AFTER_MAX_AGE_EQUALS;
1708 break;
1709
1710 case AFTER_MAX_AGE_EQUALS:
1711 if (IsAsciiWhitespace(*tokenizer.token_begin()))
1712 continue;
1713 if (!MaxAgeToInt(tokenizer.token_begin(),
1714 tokenizer.token_end(),
1715 &max_age_candidate))
1716 return false;
1717 state = AFTER_MAX_AGE;
1718 break;
1719
1720 case AFTER_MAX_AGE:
1721 if (IsAsciiWhitespace(*tokenizer.token_begin()))
1722 continue;
1723 if (*tokenizer.token_begin() != ';')
1724 return false;
1725 state = AFTER_MAX_AGE_INCLUDE_SUB_DOMAINS_DELIMITER;
1726 break;
1727
1728 case AFTER_MAX_AGE_INCLUDE_SUB_DOMAINS_DELIMITER:
1729 if (IsAsciiWhitespace(*tokenizer.token_begin()))
1730 continue;
1731 if (!LowerCaseEqualsASCII(tokenizer.token(), "includesubdomains"))
1732 return false;
1733 state = AFTER_INCLUDE_SUBDOMAINS;
1734 break;
1735
1736 case AFTER_INCLUDE_SUBDOMAINS:
1737 if (!IsAsciiWhitespace(*tokenizer.token_begin()))
1738 return false;
1739 break;
1740
1741 default:
1742 NOTREACHED();
1743 }
1744 }
1745
1746 // We've consumed all the input. Let's see what state we ended up in.
1747 switch (state) {
1748 case START:
1749 case AFTER_MAX_AGE_LABEL:
1750 case AFTER_MAX_AGE_EQUALS:
1751 return false;
1752 case AFTER_MAX_AGE:
1753 *max_age = max_age_candidate;
1754 *include_subdomains = false;
1755 return true;
1756 case AFTER_MAX_AGE_INCLUDE_SUB_DOMAINS_DELIMITER:
1757 return false;
1758 case AFTER_INCLUDE_SUBDOMAINS:
1759 *max_age = max_age_candidate;
1760 *include_subdomains = true;
1761 return true;
1762 default:
1763 NOTREACHED();
1764 return false;
1765 }
1766 }
1767
1768 // Side pinning and superfluous certificates:
1769 //
1770 // In SSLClientSocketNSS::DoVerifyCertComplete we look for certificates with a
1771 // Subject of CN=meta. When we find one we'll currently try and parse side
1772 // pinned key from it.
1773 //
1774 // A side pin is a key which can be pinned to, but also can be kept offline and
1775 // still held by the site owner. The CN=meta certificate is just a backwards
1776 // compatiable method of carrying a lump of bytes to the client. (We could use
1777 // a TLS extension just as well, but it's a lot easier for admins to add extra
1778 // certificates to the chain.)
1779
1780 // A TagMap represents the simple key-value structure that we use. Keys are
1781 // 32-bit ints. Values are byte strings.
1782 typedef std::map<uint32, base::StringPiece> TagMap;
1783
1784 // ParseTags parses a list of key-value pairs from |in| to |out| and advances
1785 // |in| past the data. The key-value pair data is:
1786 // u16le num_tags
1787 // u32le tag[num_tags]
1788 // u16le lengths[num_tags]
1789 // ...data...
1790 static bool ParseTags(base::StringPiece* in, TagMap *out) {
1791 // Many part of Chrome already assume little-endian. This is just to help
1792 // anyone who should try to port it in the future.
1793 #if defined(__BYTE_ORDER)
1794 // Linux check
1795 COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN, assumes_little_endian);
1796 #elif defined(__BIG_ENDIAN__)
1797 // Mac check
1798 #error assumes little endian
1799 #endif
1800
1801 uint16 num_tags_16;
1802 if (in->size() < sizeof(num_tags_16))
1803 return false;
1804
1805 memcpy(&num_tags_16, in->data(), sizeof(num_tags_16));
1806 in->remove_prefix(sizeof(num_tags_16));
1807 unsigned num_tags = num_tags_16;
1808
1809 if (in->size() < 6 * num_tags)
1810 return false;
1811
1812 const uint32* tags = reinterpret_cast<const uint32*>(in->data());
1813 const uint16* lens = reinterpret_cast<const uint16*>(
1814 in->data() + 4*num_tags);
1815 in->remove_prefix(6*num_tags);
1816
1817 uint32 prev_tag = 0;
1818 for (unsigned i = 0; i < num_tags; i++) {
1819 size_t len = lens[i];
1820 uint32 tag = tags[i];
1821
1822 if (in->size() < len)
1823 return false;
1824 // tags must be in ascending order.
1825 if (i > 0 && prev_tag >= tag)
1826 return false;
1827 (*out)[tag] = base::StringPiece(in->data(), len);
1828 in->remove_prefix(len);
1829 prev_tag = tag;
1830 }
1831
1832 return true;
1833 }
1834
1835 // GetTag extracts the data associated with |tag| in |tags|.
1836 static bool GetTag(uint32 tag, const TagMap& tags, base::StringPiece* out) {
1837 TagMap::const_iterator i = tags.find(tag);
1838 if (i == tags.end())
1839 return false;
1840
1841 *out = i->second;
1842 return true;
1843 }
1844
1845 // kP256SubjectPublicKeyInfoPrefix can be prepended onto a P256 elliptic curve
1846 // point in X9.62 format in order to make a valid SubjectPublicKeyInfo. The
1847 // ASN.1 interpretation of these bytes is:
1848 //
1849 // 0:d=0 hl=2 l= 89 cons: SEQUENCE
1850 // 2:d=1 hl=2 l= 19 cons: SEQUENCE
1851 // 4:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
1852 // 13:d=2 hl=2 l= 8 prim: OBJECT :prime256v1
1853 // 23:d=1 hl=2 l= 66 prim: BIT STRING
1854 static const uint8 kP256SubjectPublicKeyInfoPrefix[] = {
1855 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
1856 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
1857 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
1858 0x42, 0x00,
1859 };
1860
1861 // VerifySignature returns true iff |sig| is a valid signature of
1862 // |hash| by |pubkey|. The actual implementation is crypto library
1863 // specific.
1864 static bool VerifySignature(const base::StringPiece& pubkey,
1865 const base::StringPiece& sig,
1866 const base::StringPiece& hash);
1867
1868 #if defined(USE_OPENSSL)
1869
1870 static EVP_PKEY* DecodeX962P256PublicKey(
1871 const base::StringPiece& pubkey_bytes) {
1872 // The public key is an X9.62 encoded P256 point.
1873 if (pubkey_bytes.size() != 1 + 2*32)
1874 return NULL;
1875
1876 std::string pubkey_spki(
1877 reinterpret_cast<const char*>(kP256SubjectPublicKeyInfoPrefix),
1878 sizeof(kP256SubjectPublicKeyInfoPrefix));
1879 pubkey_spki += pubkey_bytes.as_string();
1880
1881 EVP_PKEY* ret = NULL;
1882 const unsigned char* der_pubkey =
1883 reinterpret_cast<const unsigned char*>(pubkey_spki.data());
1884 d2i_PUBKEY(&ret, &der_pubkey, pubkey_spki.size());
1885 return ret;
1886 }
1887
1888 static bool VerifySignature(const base::StringPiece& pubkey,
1889 const base::StringPiece& sig,
1890 const base::StringPiece& hash) {
1891 crypto::ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free> secpubkey(
1892 DecodeX962P256PublicKey(pubkey));
1893 if (!secpubkey.get())
1894 return false;
1895
1896
1897 crypto::ScopedOpenSSL<EC_KEY, EC_KEY_free> ec_key(
1898 EVP_PKEY_get1_EC_KEY(secpubkey.get()));
1899 if (!ec_key.get())
1900 return false;
1901
1902 return ECDSA_verify(0, reinterpret_cast<const unsigned char*>(hash.data()),
1903 hash.size(),
1904 reinterpret_cast<const unsigned char*>(sig.data()),
1905 sig.size(), ec_key.get()) == 1;
1906 }
1907
1908 #else
1909
1910 // DecodeX962P256PublicKey parses an uncompressed, X9.62 format, P256 elliptic
1911 // curve point from |pubkey_bytes| and returns it as a SECKEYPublicKey.
1912 static SECKEYPublicKey* DecodeX962P256PublicKey(
1913 const base::StringPiece& pubkey_bytes) {
1914 // The public key is an X9.62 encoded P256 point.
1915 if (pubkey_bytes.size() != 1 + 2*32)
1916 return NULL;
1917
1918 std::string pubkey_spki(
1919 reinterpret_cast<const char*>(kP256SubjectPublicKeyInfoPrefix),
1920 sizeof(kP256SubjectPublicKeyInfoPrefix));
1921 pubkey_spki += pubkey_bytes.as_string();
1922
1923 SECItem der;
1924 memset(&der, 0, sizeof(der));
1925 der.data = reinterpret_cast<uint8*>(const_cast<char*>(pubkey_spki.data()));
1926 der.len = pubkey_spki.size();
1927
1928 CERTSubjectPublicKeyInfo* spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&der);
1929 if (!spki)
1930 return NULL;
1931 SECKEYPublicKey* public_key = SECKEY_ExtractPublicKey(spki);
1932 SECKEY_DestroySubjectPublicKeyInfo(spki);
1933
1934 return public_key;
1935 }
1936
1937 static bool VerifySignature(const base::StringPiece& pubkey,
1938 const base::StringPiece& sig,
1939 const base::StringPiece& hash) {
1940 SECKEYPublicKey* secpubkey = DecodeX962P256PublicKey(pubkey);
1941 if (!secpubkey)
1942 return false;
1943
1944 SECItem sigitem;
1945 memset(&sigitem, 0, sizeof(sigitem));
1946 sigitem.data = reinterpret_cast<uint8*>(const_cast<char*>(sig.data()));
1947 sigitem.len = sig.size();
1948
1949 // |decoded_sigitem| is newly allocated, as is the data that it points to.
1950 SECItem* decoded_sigitem = DSAU_DecodeDerSigToLen(
1951 &sigitem, SECKEY_SignatureLen(secpubkey));
1952
1953 if (!decoded_sigitem) {
1954 SECKEY_DestroyPublicKey(secpubkey);
1955 return false;
1956 }
1957
1958 SECItem hashitem;
1959 memset(&hashitem, 0, sizeof(hashitem));
1960 hashitem.data = reinterpret_cast<unsigned char*>(
1961 const_cast<char*>(hash.data()));
1962 hashitem.len = hash.size();
1963
1964 SECStatus rv = PK11_Verify(secpubkey, decoded_sigitem, &hashitem, NULL);
1965 SECKEY_DestroyPublicKey(secpubkey);
1966 SECITEM_FreeItem(decoded_sigitem, PR_TRUE);
1967 return rv == SECSuccess;
1968 }
1969
1970 #endif // !defined(USE_OPENSSL)
1971
1972 // These are the tag values that we use. Tags are little-endian on the wire and
1973 // these values correspond to the ASCII of the name.
1974 static const uint32 kTagALGO = 0x4f474c41;
1975 static const uint32 kTagP256 = 0x36353250;
1976 static const uint32 kTagPUBK = 0x4b425550;
1977 static const uint32 kTagSIG = 0x474953;
1978 static const uint32 kTagSPIN = 0x4e495053;
1979
1980 // static
1981 bool TransportSecurityState::ParseSidePin(
1982 const base::StringPiece& leaf_spki,
1983 const base::StringPiece& in_side_info,
1984 FingerprintVector* out_pub_key_hash) {
1985 base::StringPiece side_info(in_side_info);
1986
1987 TagMap outer;
1988 if (!ParseTags(&side_info, &outer))
1989 return false;
1990 // trailing data is not allowed
1991 if (side_info.size())
1992 return false;
1993
1994 base::StringPiece side_pin_bytes;
1995 if (!GetTag(kTagSPIN, outer, &side_pin_bytes))
1996 return false;
1997
1998 bool have_parsed_a_key = false;
1999 uint8 leaf_spki_hash[crypto::kSHA256Length];
2000 bool have_leaf_spki_hash = false;
2001
2002 while (side_pin_bytes.size() > 0) {
2003 TagMap side_pin;
2004 if (!ParseTags(&side_pin_bytes, &side_pin))
2005 return false;
2006
2007 base::StringPiece algo, pubkey, sig;
2008 if (!GetTag(kTagALGO, side_pin, &algo) ||
2009 !GetTag(kTagPUBK, side_pin, &pubkey) ||
2010 !GetTag(kTagSIG, side_pin, &sig)) {
2011 return false;
2012 }
2013
2014 if (algo.size() != sizeof(kTagP256) ||
2015 0 != memcmp(algo.data(), &kTagP256, sizeof(kTagP256))) {
2016 // We don't support anything but P256 at the moment.
2017 continue;
2018 }
2019
2020 if (!have_leaf_spki_hash) {
2021 crypto::SHA256HashString(
2022 leaf_spki.as_string(), leaf_spki_hash, sizeof(leaf_spki_hash));
2023 have_leaf_spki_hash = true;
2024 }
2025
2026 if (VerifySignature(pubkey, sig, base::StringPiece(
2027 reinterpret_cast<const char*>(leaf_spki_hash),
2028 sizeof(leaf_spki_hash)))) {
2029 SHA1Fingerprint fpr;
2030 base::SHA1HashBytes(
2031 reinterpret_cast<const uint8*>(pubkey.data()),
2032 pubkey.size(),
2033 fpr.data);
2034 out_pub_key_hash->push_back(fpr);
2035 have_parsed_a_key = true;
2036 }
2037 }
2038
2039 return have_parsed_a_key;
2040 }
2041
2042 // This function converts the binary hashes, which we store in
2043 // |enabled_hosts_|, to a base64 string which we can include in a JSON file.
2044 static std::string HashedDomainToExternalString(const std::string& hashed) {
2045 std::string out;
2046 CHECK(base::Base64Encode(hashed, &out));
2047 return out;
2048 }
2049
2050 // This inverts |HashedDomainToExternalString|, above. It turns an external
2051 // string (from a JSON file) into an internal (binary) string.
2052 static std::string ExternalStringToHashedDomain(const std::string& external) {
2053 std::string out;
2054 if (!base::Base64Decode(external, &out) ||
2055 out.size() != crypto::kSHA256Length) {
2056 return std::string();
2057 }
2058
2059 return out;
2060 }
2061
2062 static ListValue* SPKIHashesToListValue(const FingerprintVector& hashes) {
2063 ListValue* pins = new ListValue;
2064
2065 for (FingerprintVector::const_iterator i = hashes.begin();
2066 i != hashes.end(); ++i) {
2067 std::string hash_str(reinterpret_cast<const char*>(i->data),
2068 sizeof(i->data));
2069 std::string b64;
2070 base::Base64Encode(hash_str, &b64);
2071 pins->Append(new StringValue("sha1/" + b64));
2072 }
2073
2074 return pins;
2075 }
2076
2077 bool TransportSecurityState::Serialise(std::string* output) {
2078 DCHECK(CalledOnValidThread());
2079
2080 DictionaryValue toplevel;
2081 base::Time now = base::Time::Now();
2082 for (std::map<std::string, DomainState>::const_iterator
2083 i = enabled_hosts_.begin(); i != enabled_hosts_.end(); ++i) {
2084 DictionaryValue* state = new DictionaryValue;
2085 state->SetBoolean("include_subdomains", i->second.include_subdomains);
2086 state->SetDouble("created", i->second.created.ToDoubleT());
2087 state->SetDouble("expiry", i->second.expiry.ToDoubleT());
2088 state->SetDouble("dynamic_spki_hashes_expiry",
2089 i->second.dynamic_spki_hashes_expiry.ToDoubleT());
2090
2091 switch (i->second.mode) {
2092 case DomainState::MODE_STRICT:
2093 state->SetString("mode", "strict");
2094 break;
2095 case DomainState::MODE_SPDY_ONLY:
2096 state->SetString("mode", "spdy-only");
2097 break;
2098 case DomainState::MODE_PINNING_ONLY:
2099 state->SetString("mode", "pinning-only");
2100 break;
2101 default:
2102 NOTREACHED() << "DomainState with unknown mode";
2103 delete state;
2104 continue;
2105 }
2106
2107 state->Set("preloaded_spki_hashes",
2108 SPKIHashesToListValue(i->second.preloaded_spki_hashes));
2109
2110 if (now < i->second.dynamic_spki_hashes_expiry) {
2111 state->Set("dynamic_spki_hashes",
2112 SPKIHashesToListValue(i->second.dynamic_spki_hashes));
2113 }
2114
2115 toplevel.Set(HashedDomainToExternalString(i->first), state);
2116 }
2117
2118 base::JSONWriter::WriteWithOptions(&toplevel,
2119 base::JSONWriter::OPTIONS_PRETTY_PRINT,
2120 output);
2121 return true;
2122 }
2123
2124 bool TransportSecurityState::LoadEntries(const std::string& input,
2125 bool* dirty) {
2126 DCHECK(CalledOnValidThread());
2127
2128 enabled_hosts_.clear();
2129 return Deserialise(input, dirty, &enabled_hosts_);
2130 }
2131
2132 static bool AddHash(const std::string& type_and_base64,
2133 FingerprintVector* out) {
2134 SHA1Fingerprint hash;
2135
2136 if (!TransportSecurityState::ParsePin(type_and_base64, &hash))
2137 return false;
2138
2139 out->push_back(hash);
2140 return true;
2141 }
2142
2143 static void SPKIHashesFromListValue(FingerprintVector* hashes,
2144 const ListValue& pins) {
2145 size_t num_pins = pins.GetSize();
2146 for (size_t i = 0; i < num_pins; ++i) {
2147 std::string type_and_base64;
2148 if (pins.GetString(i, &type_and_base64))
2149 AddHash(type_and_base64, hashes);
2150 }
2151 }
2152
2153 // static
2154 bool TransportSecurityState::Deserialise(
2155 const std::string& input,
2156 bool* dirty,
2157 std::map<std::string, DomainState>* out) {
2158 scoped_ptr<Value> value(
2159 base::JSONReader::Read(input, false /* do not allow trailing commas */));
2160 if (!value.get() || !value->IsType(Value::TYPE_DICTIONARY))
2161 return false;
2162
2163 DictionaryValue* dict_value = reinterpret_cast<DictionaryValue*>(value.get());
2164 const base::Time current_time(base::Time::Now());
2165 bool dirtied = false;
2166
2167 for (DictionaryValue::key_iterator i = dict_value->begin_keys();
2168 i != dict_value->end_keys(); ++i) {
2169 DictionaryValue* state;
2170 if (!dict_value->GetDictionaryWithoutPathExpansion(*i, &state))
2171 continue;
2172
2173 bool include_subdomains;
2174 std::string mode_string;
2175 double created;
2176 double expiry;
2177 double dynamic_spki_hashes_expiry = 0.0;
2178
2179 if (!state->GetBoolean("include_subdomains", &include_subdomains) ||
2180 !state->GetString("mode", &mode_string) ||
2181 !state->GetDouble("expiry", &expiry)) {
2182 continue;
2183 }
2184
2185 // Don't fail if this key is not present.
2186 (void) state->GetDouble("dynamic_spki_hashes_expiry",
2187 &dynamic_spki_hashes_expiry);
2188
2189 ListValue* pins_list = NULL;
2190 FingerprintVector preloaded_spki_hashes;
2191 if (state->GetList("preloaded_spki_hashes", &pins_list))
2192 SPKIHashesFromListValue(&preloaded_spki_hashes, *pins_list);
2193
2194 FingerprintVector dynamic_spki_hashes;
2195 if (state->GetList("dynamic_spki_hashes", &pins_list))
2196 SPKIHashesFromListValue(&dynamic_spki_hashes, *pins_list);
2197
2198 DomainState::Mode mode;
2199 if (mode_string == "strict") {
2200 mode = DomainState::MODE_STRICT;
2201 } else if (mode_string == "spdy-only") {
2202 mode = DomainState::MODE_SPDY_ONLY;
2203 } else if (mode_string == "pinning-only") {
2204 mode = DomainState::MODE_PINNING_ONLY;
2205 } else {
2206 LOG(WARNING) << "Unknown TransportSecurityState mode string found: "
2207 << mode_string;
2208 continue;
2209 }
2210
2211 base::Time expiry_time = base::Time::FromDoubleT(expiry);
2212 base::Time dynamic_spki_hashes_expiry_time =
2213 base::Time::FromDoubleT(dynamic_spki_hashes_expiry);
2214 base::Time created_time;
2215 if (state->GetDouble("created", &created)) {
2216 created_time = base::Time::FromDoubleT(created);
2217 } else {
2218 // We're migrating an old entry with no creation date. Make sure we
2219 // write the new date back in a reasonable time frame.
2220 dirtied = true;
2221 created_time = base::Time::Now();
2222 }
2223
2224 if (expiry_time <= current_time &&
2225 dynamic_spki_hashes_expiry_time <= current_time) {
2226 // Make sure we dirty the state if we drop an entry.
2227 dirtied = true;
2228 continue;
2229 }
2230
2231 std::string hashed = ExternalStringToHashedDomain(*i);
2232 if (hashed.empty()) {
2233 dirtied = true;
2234 continue;
2235 }
2236
2237 DomainState new_state;
2238 new_state.mode = mode;
2239 new_state.created = created_time;
2240 new_state.expiry = expiry_time;
2241 new_state.include_subdomains = include_subdomains;
2242 new_state.preloaded_spki_hashes = preloaded_spki_hashes;
2243 new_state.dynamic_spki_hashes = dynamic_spki_hashes;
2244 new_state.dynamic_spki_hashes_expiry = dynamic_spki_hashes_expiry_time;
2245 (*out)[hashed] = new_state;
2246 }
2247
2248 *dirty = dirtied;
2249 return true;
2250 }
2251
2252 TransportSecurityState::~TransportSecurityState() {
2253 }
2254
2255 void TransportSecurityState::DirtyNotify() {
2256 DCHECK(CalledOnValidThread());
2257
2258 if (delegate_)
2259 delegate_->StateIsDirty(this);
2260 }
2261
2262 // static
2263 std::string TransportSecurityState::CanonicalizeHost(const std::string& host) {
2264 // We cannot perform the operations as detailed in the spec here as |host|
2265 // has already undergone IDN processing before it reached us. Thus, we check
2266 // that there are no invalid characters in the host and lowercase the result.
2267
2268 std::string new_host;
2269 if (!DNSDomainFromDot(host, &new_host)) {
2270 // DNSDomainFromDot can fail if any label is > 63 bytes or if the whole
2271 // name is >255 bytes. However, search terms can have those properties.
2272 return std::string();
2273 }
2274
2275 for (size_t i = 0; new_host[i]; i += new_host[i] + 1) {
2276 const unsigned label_length = static_cast<unsigned>(new_host[i]);
2277 if (!label_length)
2278 break;
2279
2280 for (size_t j = 0; j < label_length; ++j) {
2281 // RFC 3490, 4.1, step 3
2282 if (!IsSTD3ASCIIValidCharacter(new_host[i + 1 + j]))
2283 return std::string();
2284
2285 new_host[i + 1 + j] = tolower(new_host[i + 1 + j]);
2286 }
2287
2288 // step 3(b)
2289 if (new_host[i + 1] == '-' ||
2290 new_host[i + label_length] == '-') {
2291 return std::string();
2292 }
2293 }
2294
2295 return new_host;
2296 }
2297
2298 // |ReportUMAOnPinFailure| uses these to report which domain was associated
2299 // with the public key pinning failure.
2300 //
2301 // DO NOT CHANGE THE ORDERING OF THESE NAMES OR REMOVE ANY OF THEM. Add new
2302 // domains at the END of the listing (but before DOMAIN_NUM_EVENTS).
2303 enum SecondLevelDomainName {
2304 DOMAIN_NOT_PINNED,
2305
2306 DOMAIN_GOOGLE_COM,
2307 DOMAIN_ANDROID_COM,
2308 DOMAIN_GOOGLE_ANALYTICS_COM,
2309 DOMAIN_GOOGLEPLEX_COM,
2310 DOMAIN_YTIMG_COM,
2311 DOMAIN_GOOGLEUSERCONTENT_COM,
2312 DOMAIN_YOUTUBE_COM,
2313 DOMAIN_GOOGLEAPIS_COM,
2314 DOMAIN_GOOGLEADSERVICES_COM,
2315 DOMAIN_GOOGLECODE_COM,
2316 DOMAIN_APPSPOT_COM,
2317 DOMAIN_GOOGLESYNDICATION_COM,
2318 DOMAIN_DOUBLECLICK_NET,
2319 DOMAIN_GSTATIC_COM,
2320 DOMAIN_GMAIL_COM,
2321 DOMAIN_GOOGLEMAIL_COM,
2322 DOMAIN_GOOGLEGROUPS_COM,
2323
2324 DOMAIN_TORPROJECT_ORG,
2325
2326 DOMAIN_TWITTER_COM,
2327 DOMAIN_TWIMG_COM,
2328
2329 DOMAIN_AKAMAIHD_NET,
2330
2331 // Boundary value for UMA_HISTOGRAM_ENUMERATION:
2332 DOMAIN_NUM_EVENTS
2333 };
2334
2335 // PublicKeyPins contains a number of SubjectPublicKeyInfo hashes for a site.
2336 // The validated certificate chain for the site must not include any of
2337 // |excluded_hashes| and must include one or more of |required_hashes|.
2338 struct PublicKeyPins {
2339 const char* const* required_hashes;
2340 const char* const* excluded_hashes;
2341 };
2342
2343 struct HSTSPreload {
2344 uint8 length;
2345 bool include_subdomains;
2346 char dns_name[30];
2347 bool https_required;
2348 PublicKeyPins pins;
2349 SecondLevelDomainName second_level_domain_name;
2350 };
2351
2352 static bool HasPreload(const struct HSTSPreload* entries, size_t num_entries,
2353 const std::string& canonicalized_host, size_t i,
2354 TransportSecurityState::DomainState* out, bool* ret) {
2355 for (size_t j = 0; j < num_entries; j++) {
2356 if (entries[j].length == canonicalized_host.size() - i &&
2357 memcmp(entries[j].dns_name, &canonicalized_host[i],
2358 entries[j].length) == 0) {
2359 if (!entries[j].include_subdomains && i != 0) {
2360 *ret = false;
2361 } else {
2362 out->include_subdomains = entries[j].include_subdomains;
2363 *ret = true;
2364 if (!entries[j].https_required)
2365 out->mode = TransportSecurityState::DomainState::MODE_PINNING_ONLY;
2366 if (entries[j].pins.required_hashes) {
2367 const char* const* hash = entries[j].pins.required_hashes;
2368 while (*hash) {
2369 bool ok = AddHash(*hash, &out->preloaded_spki_hashes);
2370 DCHECK(ok) << " failed to parse " << *hash;
2371 hash++;
2372 }
2373 }
2374 if (entries[j].pins.excluded_hashes) {
2375 const char* const* hash = entries[j].pins.excluded_hashes;
2376 while (*hash) {
2377 bool ok = AddHash(*hash, &out->bad_preloaded_spki_hashes);
2378 DCHECK(ok) << " failed to parse " << *hash;
2379 hash++;
2380 }
2381 }
2382 }
2383 return true;
2384 }
2385 }
2386 return false;
2387 }
2388 1244
2389 // kNoRejectedPublicKeys is a placeholder for when no public keys are rejected. 1245 // kNoRejectedPublicKeys is a placeholder for when no public keys are rejected.
2390 static const char* const kNoRejectedPublicKeys[] = { 1246 static const char* const kNoRejectedPublicKeys[] = {
2391 NULL, 1247 NULL,
2392 }; 1248 };
2393 1249
1250 static const char* const kTestAcceptableCerts[] = {
1251 kSPKIHash_TestSPKI,
1252 NULL,
1253 };
1254 #define kTestPins { \
1255 kTestAcceptableCerts, \
1256 kNoRejectedPublicKeys, \
1257 }
1258
2394 static const char* const kGoogleAcceptableCerts[] = { 1259 static const char* const kGoogleAcceptableCerts[] = {
2395 kSPKIHash_VeriSignClass3, 1260 kSPKIHash_VeriSignClass3,
2396 kSPKIHash_VeriSignClass3_G3, 1261 kSPKIHash_VeriSignClass3_G3,
2397 kSPKIHash_Google1024, 1262 kSPKIHash_Google1024,
2398 kSPKIHash_Google2048, 1263 kSPKIHash_Google2048,
2399 kSPKIHash_EquifaxSecureCA, 1264 kSPKIHash_EquifaxSecureCA,
2400 NULL, 1265 NULL,
2401 }; 1266 };
2402 static const char* const kGoogleRejectedCerts[] = { 1267 static const char* const kGoogleRejectedCerts[] = {
2403 kSPKIHash_Aetna, 1268 kSPKIHash_Aetna,
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2444 kSPKIHash_GeoTrustPrimary_G2, 1309 kSPKIHash_GeoTrustPrimary_G2,
2445 kSPKIHash_GeoTrustPrimary_G3, 1310 kSPKIHash_GeoTrustPrimary_G3,
2446 kSPKIHash_Twitter1, 1311 kSPKIHash_Twitter1,
2447 NULL, 1312 NULL,
2448 }; 1313 };
2449 #define kTwitterComPins { \ 1314 #define kTwitterComPins { \
2450 kTwitterComAcceptableCerts, \ 1315 kTwitterComAcceptableCerts, \
2451 kNoRejectedPublicKeys, \ 1316 kNoRejectedPublicKeys, \
2452 } 1317 }
2453 1318
2454 // kTwitterCDNAcceptableCerts are the set of public keys valid for Twitter's
2455 // CDNs, which includes all the keys from kTwitterComAcceptableCerts.
2456 static const char* const kTwitterCDNAcceptableCerts[] = { 1319 static const char* const kTwitterCDNAcceptableCerts[] = {
2457 kSPKIHash_VeriSignClass1, 1320 kSPKIHash_VeriSignClass1,
2458 kSPKIHash_VeriSignClass3, 1321 kSPKIHash_VeriSignClass3,
2459 kSPKIHash_VeriSignClass3_G4, 1322 kSPKIHash_VeriSignClass3_G4,
2460 kSPKIHash_VeriSignClass4_G3, 1323 kSPKIHash_VeriSignClass4_G3,
2461 kSPKIHash_VeriSignClass3_G3, 1324 kSPKIHash_VeriSignClass3_G3,
2462 kSPKIHash_VeriSignClass1_G3, 1325 kSPKIHash_VeriSignClass1_G3,
2463 kSPKIHash_VeriSignClass2_G3, 1326 kSPKIHash_VeriSignClass2_G3,
2464 kSPKIHash_VeriSignClass3_G2, 1327 kSPKIHash_VeriSignClass3_G2,
2465 kSPKIHash_VeriSignClass2_G2, 1328 kSPKIHash_VeriSignClass2_G2,
2466 kSPKIHash_VeriSignClass3_G5, 1329 kSPKIHash_VeriSignClass3_G5,
2467 kSPKIHash_VeriSignUniversal, 1330 kSPKIHash_VeriSignUniversal,
2468 kSPKIHash_GeoTrustGlobal, 1331 kSPKIHash_GeoTrustGlobal,
2469 kSPKIHash_GeoTrustGlobal2, 1332 kSPKIHash_GeoTrustGlobal2,
2470 kSPKIHash_GeoTrustUniversal, 1333 kSPKIHash_GeoTrustUniversal,
2471 kSPKIHash_GeoTrustUniversal2, 1334 kSPKIHash_GeoTrustUniversal2,
2472 kSPKIHash_GeoTrustPrimary, 1335 kSPKIHash_GeoTrustPrimary,
2473 kSPKIHash_GeoTrustPrimary_G2, 1336 kSPKIHash_GeoTrustPrimary_G2,
2474 kSPKIHash_GeoTrustPrimary_G3, 1337 kSPKIHash_GeoTrustPrimary_G3,
2475 kSPKIHash_Twitter1, 1338 kSPKIHash_Twitter1,
2476
2477 kSPKIHash_Entrust_2048, 1339 kSPKIHash_Entrust_2048,
2478 kSPKIHash_Entrust_EV, 1340 kSPKIHash_Entrust_EV,
2479 kSPKIHash_Entrust_G2, 1341 kSPKIHash_Entrust_G2,
2480 kSPKIHash_Entrust_SSL, 1342 kSPKIHash_Entrust_SSL,
2481 kSPKIHash_AAACertificateServices, 1343 kSPKIHash_AAACertificateServices,
2482 kSPKIHash_AddTrustClass1CARoot, 1344 kSPKIHash_AddTrustClass1CARoot,
2483 kSPKIHash_AddTrustExternalCARoot, 1345 kSPKIHash_AddTrustExternalCARoot,
2484 kSPKIHash_AddTrustPublicCARoot, 1346 kSPKIHash_AddTrustPublicCARoot,
2485 kSPKIHash_AddTrustQualifiedCARoot, 1347 kSPKIHash_AddTrustQualifiedCARoot,
2486 kSPKIHash_COMODOCertificationAuthority, 1348 kSPKIHash_COMODOCertificationAuthority,
2487 kSPKIHash_SecureCertificateServices, 1349 kSPKIHash_SecureCertificateServices,
2488 kSPKIHash_TrustedCertificateServices, 1350 kSPKIHash_TrustedCertificateServices,
2489 kSPKIHash_UTNDATACorpSGC, 1351 kSPKIHash_UTNDATACorpSGC,
2490 kSPKIHash_UTNUSERFirstClientAuthenticationandEmail, 1352 kSPKIHash_UTNUSERFirstClientAuthenticationandEmail,
2491 kSPKIHash_UTNUSERFirstHardware, 1353 kSPKIHash_UTNUSERFirstHardware,
2492 kSPKIHash_UTNUSERFirstObject, 1354 kSPKIHash_UTNUSERFirstObject,
2493 kSPKIHash_GTECyberTrustGlobalRoot, 1355 kSPKIHash_GTECyberTrustGlobalRoot,
2494 NULL, 1356 NULL,
2495 }; 1357 };
2496 #define kTwitterCDNPins { \ 1358 #define kTwitterCDNPins { \
2497 kTwitterCDNAcceptableCerts, \ 1359 kTwitterCDNAcceptableCerts, \
2498 kNoRejectedPublicKeys, \ 1360 kNoRejectedPublicKeys, \
2499 } 1361 }
2500 1362
2501 // kTestAcceptableCerts doesn't actually match any public keys and is used 1363 #define kNoPins {\
2502 // with "pinningtest.appspot.com", below, to test if pinning is active.
2503 static const char* const kTestAcceptableCerts[] = {
2504 "sha1/AAAAAAAAAAAAAAAAAAAAAAAAAAA=",
2505 NULL,
2506 };
2507 #define kTestPins { \
2508 kTestAcceptableCerts, \
2509 kNoRejectedPublicKeys, \
2510 }
2511
2512 #define kNoPins { \
2513 NULL, NULL, \ 1364 NULL, NULL, \
2514 } 1365 }
2515 1366
2516 #if defined(OS_CHROMEOS)
2517 static const bool kTwitterHSTS = true;
2518 #else
2519 static const bool kTwitterHSTS = false;
2520 #endif
2521
2522 // In the medium term this list is likely to just be hardcoded here. This
2523 // slightly odd form removes the need for additional relocations records.
2524 static const struct HSTSPreload kPreloadedSTS[] = { 1367 static const struct HSTSPreload kPreloadedSTS[] = {
2525 // (*.)google.com, iff using SSL must use an acceptable certificate. 1368 {25, true, "\013pinningtest\007appspot\003com", false, kTestPins, DOMAIN_APPSP OT_COM },
2526 {12, true, "\006google\003com", false, kGooglePins, DOMAIN_GOOGLE_COM }, 1369 {12, true, "\006google\003com", false, kGooglePins, DOMAIN_GOOGLE_COM },
2527 {25, true, "\013pinningtest\007appspot\003com", false, kTestPins, DOMAIN_APPSP OT_COM }, 1370 {19, true, "\006health\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
2528 // Now we force HTTPS for subtrees of google.com.
2529 {19, true, "\006health\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
2530 {21, true, "\010checkout\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_C OM }, 1371 {21, true, "\010checkout\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_C OM },
2531 {19, true, "\006chrome\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM }, 1372 {19, true, "\006chrome\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
2532 {17, true, "\004docs\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM } , 1373 {17, true, "\004docs\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM } ,
2533 {18, true, "\005sites\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM }, 1374 {18, true, "\005sites\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
2534 {25, true, "\014spreadsheets\006google\003com", true, kGooglePins, DOMAIN_GOOG LE_COM }, 1375 {25, true, "\014spreadsheets\006google\003com", true, kGooglePins, DOMAIN_GOOG LE_COM },
2535 {22, false, "\011appengine\006google\003com", true, kGooglePins, DOMAIN_GOOGLE _COM }, 1376 {22, false, "\011appengine\006google\003com", true, kGooglePins, DOMAIN_GOOGLE _COM },
2536 {22, true, "\011encrypted\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_ COM }, 1377 {22, true, "\011encrypted\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_ COM },
2537 {21, true, "\010accounts\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_C OM }, 1378 {21, true, "\010accounts\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_C OM },
2538 {21, true, "\010profiles\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_C OM }, 1379 {21, true, "\010profiles\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_C OM },
2539 {17, true, "\004mail\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM } , 1380 {17, true, "\004mail\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM } ,
2540 {23, true, "\012talkgadget\006google\003com", true, kGooglePins, DOMAIN_GOOGLE _COM }, 1381 {23, true, "\012talkgadget\006google\003com", true, kGooglePins, DOMAIN_GOOGLE _COM },
2541 {17, true, "\004talk\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM } , 1382 {17, true, "\004talk\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM } ,
2542 {29, true, "\020hostedtalkgadget\006google\003com", true, kGooglePins, DOMAIN_ GOOGLE_COM }, 1383 {29, true, "\020hostedtalkgadget\006google\003com", true, kGooglePins, DOMAIN_ GOOGLE_COM },
2543 {17, true, "\004plus\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM } , 1384 {17, true, "\004plus\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM } ,
2544 // Other Google-related domains that must use HTTPS.
2545 {20, true, "\006market\007android\003com", true, kGooglePins, DOMAIN_ANDROID_C OM }, 1385 {20, true, "\006market\007android\003com", true, kGooglePins, DOMAIN_ANDROID_C OM },
2546 {26, true, "\003ssl\020google-analytics\003com", true, kGooglePins, DOMAIN_GOO GLE_ANALYTICS_COM }, 1386 {26, true, "\003ssl\020google-analytics\003com", true, kGooglePins, DOMAIN_GOO GLE_ANALYTICS_COM },
2547 {18, true, "\005drive\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM }, 1387 {18, true, "\005drive\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
2548 {16, true, "\012googleplex\003com", true, kGooglePins, DOMAIN_GOOGLEPLEX_COM } , 1388 {16, true, "\012googleplex\003com", true, kGooglePins, DOMAIN_GOOGLEPLEX_COM } ,
2549 {19, true, "\006groups\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM }, 1389 {19, true, "\006groups\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
2550 {17, true, "\004apis\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM } , 1390 {17, true, "\004apis\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM } ,
2551 // chart.apis.google.com is *not* HSTS because the certificate doesn't match 1391 {23, true, "\005chart\004apis\006google\003com", false, kGooglePins, DOMAIN_GO OGLE_COM },
2552 // and there are lots of links out there that still use the name. The correct
2553 // hostname for this is chart.googleapis.com.
2554 {23, true, "\005chart\004apis\006google\003com", false, kGooglePins, DOMAIN_GO OGLE_COM},
2555
2556 // Other Google-related domains that must use an acceptable certificate
2557 // iff using SSL.
2558 {11, true, "\005ytimg\003com", false, kGooglePins, DOMAIN_YTIMG_COM }, 1392 {11, true, "\005ytimg\003com", false, kGooglePins, DOMAIN_YTIMG_COM },
2559 {23, true, "\021googleusercontent\003com", false, kGooglePins, DOMAIN_GOOGLEUS ERCONTENT_COM }, 1393 {23, true, "\021googleusercontent\003com", false, kGooglePins, DOMAIN_GOOGLEUS ERCONTENT_COM },
2560 {13, true, "\007youtube\003com", false, kGooglePins, DOMAIN_YOUTUBE_COM }, 1394 {13, true, "\007youtube\003com", false, kGooglePins, DOMAIN_YOUTUBE_COM },
2561 {16, true, "\012googleapis\003com", false, kGooglePins, DOMAIN_GOOGLEAPIS_COM }, 1395 {16, true, "\012googleapis\003com", false, kGooglePins, DOMAIN_GOOGLEAPIS_COM },
2562 {22, true, "\020googleadservices\003com", false, kGooglePins, DOMAIN_GOOGLEADS ERVICES_COM }, 1396 {22, true, "\020googleadservices\003com", false, kGooglePins, DOMAIN_GOOGLEADS ERVICES_COM },
2563 {16, true, "\012googlecode\003com", false, kGooglePins, DOMAIN_GOOGLECODE_COM }, 1397 {16, true, "\012googlecode\003com", false, kGooglePins, DOMAIN_GOOGLECODE_COM },
2564 {13, true, "\007appspot\003com", false, kGooglePins, DOMAIN_APPSPOT_COM }, 1398 {13, true, "\007appspot\003com", false, kGooglePins, DOMAIN_APPSPOT_COM },
2565 {23, true, "\021googlesyndication\003com", false, kGooglePins, DOMAIN_GOOGLESY NDICATION_COM }, 1399 {23, true, "\021googlesyndication\003com", false, kGooglePins, DOMAIN_GOOGLESY NDICATION_COM },
2566 {17, true, "\013doubleclick\003net", false, kGooglePins, DOMAIN_DOUBLECLICK_NE T }, 1400 {17, true, "\013doubleclick\003net", false, kGooglePins, DOMAIN_DOUBLECLICK_NE T },
2567 {17, true, "\003ssl\007gstatic\003com", false, kGooglePins, DOMAIN_GSTATIC_COM }, 1401 {17, true, "\003ssl\007gstatic\003com", false, kGooglePins, DOMAIN_GSTATIC_COM },
2568 // Exclude the learn.doubleclick.net subdomain because it uses a different
2569 // CA.
2570 {23, true, "\005learn\013doubleclick\003net", false, kNoPins, DOMAIN_NOT_PINNE D }, 1402 {23, true, "\005learn\013doubleclick\003net", false, kNoPins, DOMAIN_NOT_PINNE D },
2571 // Now we force HTTPS for other sites that have requested it.
2572 {16, false, "\003www\006paypal\003com", true, kNoPins, DOMAIN_NOT_PINNED }, 1403 {16, false, "\003www\006paypal\003com", true, kNoPins, DOMAIN_NOT_PINNED },
2573 {16, false, "\003www\006elanex\003biz", true, kNoPins, DOMAIN_NOT_PINNED }, 1404 {16, false, "\003www\006elanex\003biz", true, kNoPins, DOMAIN_NOT_PINNED },
2574 {12, true, "\006jottit\003com", true, kNoPins, DOMAIN_NOT_PINNED }, 1405 {12, true, "\006jottit\003com", true, kNoPins, DOMAIN_NOT_PINNED },
2575 {19, true, "\015sunshinepress\003org", true, kNoPins, DOMAIN_NOT_PINNED }, 1406 {19, true, "\015sunshinepress\003org", true, kNoPins, DOMAIN_NOT_PINNED },
2576 {21, false, "\003www\013noisebridge\003net", true, kNoPins, DOMAIN_NOT_PINNED }, 1407 {21, false, "\003www\013noisebridge\003net", true, kNoPins, DOMAIN_NOT_PINNED },
2577 {10, false, "\004neg9\003org", true, kNoPins, DOMAIN_NOT_PINNED }, 1408 {10, false, "\004neg9\003org", true, kNoPins, DOMAIN_NOT_PINNED },
2578 {12, true, "\006riseup\003net", true, kNoPins, DOMAIN_NOT_PINNED }, 1409 {12, true, "\006riseup\003net", true, kNoPins, DOMAIN_NOT_PINNED },
2579 {11, false, "\006factor\002cc", true, kNoPins, DOMAIN_NOT_PINNED }, 1410 {11, false, "\006factor\002cc", true, kNoPins, DOMAIN_NOT_PINNED },
2580 {22, false, "\007members\010mayfirst\003org", true, kNoPins, DOMAIN_NOT_PINNED }, 1411 {22, false, "\007members\010mayfirst\003org", true, kNoPins, DOMAIN_NOT_PINNED },
2581 {22, false, "\007support\010mayfirst\003org", true, kNoPins, DOMAIN_NOT_PINNED }, 1412 {22, false, "\007support\010mayfirst\003org", true, kNoPins, DOMAIN_NOT_PINNED },
2582 {17, false, "\002id\010mayfirst\003org", true, kNoPins, DOMAIN_NOT_PINNED }, 1413 {17, false, "\002id\010mayfirst\003org", true, kNoPins, DOMAIN_NOT_PINNED },
2583 {20, false, "\005lists\010mayfirst\003org", true, kNoPins, DOMAIN_NOT_PINNED } , 1414 {20, false, "\005lists\010mayfirst\003org", true, kNoPins, DOMAIN_NOT_PINNED } ,
2584 {19, true, "\015splendidbacon\003com", true, kNoPins, DOMAIN_NOT_PINNED }, 1415 {19, true, "\015splendidbacon\003com", true, kNoPins, DOMAIN_NOT_PINNED },
2585 {28, false, "\016aladdinschools\007appspot\003com", true, kNoPins, DOMAIN_NOT_ PINNED }, 1416 {28, false, "\016aladdinschools\007appspot\003com", true, kNoPins, DOMAIN_NOT_ PINNED },
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2618 {10, false, "\004kyps\003net", true, kNoPins, DOMAIN_NOT_PINNED }, 1449 {10, false, "\004kyps\003net", true, kNoPins, DOMAIN_NOT_PINNED },
2619 {14, false, "\003www\004kyps\003net", true, kNoPins, DOMAIN_NOT_PINNED }, 1450 {14, false, "\003www\004kyps\003net", true, kNoPins, DOMAIN_NOT_PINNED },
2620 {17, true, "\003app\007recurly\003com", true, kNoPins, DOMAIN_NOT_PINNED }, 1451 {17, true, "\003app\007recurly\003com", true, kNoPins, DOMAIN_NOT_PINNED },
2621 {17, true, "\003api\007recurly\003com", true, kNoPins, DOMAIN_NOT_PINNED }, 1452 {17, true, "\003api\007recurly\003com", true, kNoPins, DOMAIN_NOT_PINNED },
2622 {13, false, "\007greplin\003com", true, kNoPins, DOMAIN_NOT_PINNED }, 1453 {13, false, "\007greplin\003com", true, kNoPins, DOMAIN_NOT_PINNED },
2623 {17, false, "\003www\007greplin\003com", true, kNoPins, DOMAIN_NOT_PINNED }, 1454 {17, false, "\003www\007greplin\003com", true, kNoPins, DOMAIN_NOT_PINNED },
2624 {27, true, "\006luneta\016nearbuysystems\003com", true, kNoPins, DOMAIN_NOT_PI NNED }, 1455 {27, true, "\006luneta\016nearbuysystems\003com", true, kNoPins, DOMAIN_NOT_PI NNED },
2625 {12, true, "\006ubertt\003org", true, kNoPins, DOMAIN_NOT_PINNED }, 1456 {12, true, "\006ubertt\003org", true, kNoPins, DOMAIN_NOT_PINNED },
2626 {9, true, "\004pixi\002me", true, kNoPins, DOMAIN_NOT_PINNED }, 1457 {9, true, "\004pixi\002me", true, kNoPins, DOMAIN_NOT_PINNED },
2627 {14, true, "\010grepular\003com", true, kNoPins, DOMAIN_NOT_PINNED }, 1458 {14, true, "\010grepular\003com", true, kNoPins, DOMAIN_NOT_PINNED },
2628 {16, false , "\012mydigipass\003com", true, kNoPins, DOMAIN_NOT_PINNED }, 1459 {16, false, "\012mydigipass\003com", true, kNoPins, DOMAIN_NOT_PINNED },
2629 {20, false , "\003www\012mydigipass\003com", true, kNoPins, DOMAIN_NOT_PINNED }, 1460 {20, false, "\003www\012mydigipass\003com", true, kNoPins, DOMAIN_NOT_PINNED } ,
2630 {26, false , "\011developer\012mydigipass\003com", true, kNoPins, DOMAIN_NOT_P INNED }, 1461 {26, false, "\011developer\012mydigipass\003com", true, kNoPins, DOMAIN_NOT_PI NNED },
2631 {30, false , "\003www\011developer\012mydigipass\003com", true, kNoPins, DOMAI N_NOT_PINNED }, 1462 {30, false, "\003www\011developer\012mydigipass\003com", true, kNoPins, DOMAIN _NOT_PINNED },
2632 {24, false , "\007sandbox\012mydigipass\003com", true, kNoPins, DOMAIN_NOT_PIN NED }, 1463 {24, false, "\007sandbox\012mydigipass\003com", true, kNoPins, DOMAIN_NOT_PINN ED },
2633 {28, false , "\003www\007sandbox\012mydigipass\003com", true, kNoPins, DOMAIN_ NOT_PINNED }, 1464 {28, false, "\003www\007sandbox\012mydigipass\003com", true, kNoPins, DOMAIN_N OT_PINNED },
2634 {12, true, "\006crypto\003cat", true, kNoPins, DOMAIN_NOT_PINNED }, 1465 {12, true, "\006crypto\003cat", true, kNoPins, DOMAIN_NOT_PINNED },
2635 {25, true, "\014bigshinylock\006minazo\003net", true, kNoPins, DOMAIN_NOT_PINN ED }, 1466 {25, true, "\014bigshinylock\006minazo\003net", true, kNoPins, DOMAIN_NOT_PINN ED },
2636 {10, true, "\005crate\002io", true, kNoPins, DOMAIN_NOT_PINNED }, 1467 {10, true, "\005crate\002io", true, kNoPins, DOMAIN_NOT_PINNED },
2637 1468 {13, false, "\007twitter\003com", false, kTwitterComPins, DOMAIN_TWITTER_COM } ,
2638 {13, false, "\007twitter\003com", kTwitterHSTS, kTwitterComPins, DOMAIN_TWITTE R_COM }, 1469 {17, true, "\003www\007twitter\003com", false, kTwitterComPins, DOMAIN_TWITTER _COM },
2639 {17, true, "\003www\007twitter\003com", kTwitterHSTS, kTwitterComPins, DOMAIN_ TWITTER_COM }, 1470 {17, true, "\003api\007twitter\003com", false, kTwitterCDNPins, DOMAIN_TWITTER _COM },
2640 {17, true, "\003api\007twitter\003com", kTwitterHSTS, kTwitterCDNPins, DOMAIN_ TWITTER_COM }, 1471 {19, true, "\005oauth\007twitter\003com", false, kTwitterComPins, DOMAIN_TWITT ER_COM },
2641 {19, true, "\005oauth\007twitter\003com", kTwitterHSTS, kTwitterComPins, DOMAI N_TWITTER_COM }, 1472 {20, true, "\006mobile\007twitter\003com", false, kTwitterComPins, DOMAIN_TWIT TER_COM },
2642 {20, true, "\006mobile\007twitter\003com", kTwitterHSTS, kTwitterComPins, DOMA IN_TWITTER_COM }, 1473 {17, true, "\003dev\007twitter\003com", false, kTwitterComPins, DOMAIN_TWITTER _COM },
2643 {17, true, "\003dev\007twitter\003com", kTwitterHSTS, kTwitterComPins, DOMAIN_ TWITTER_COM }, 1474 {22, true, "\010business\007twitter\003com", false, kTwitterComPins, DOMAIN_TW ITTER_COM },
2644 {22, true, "\010business\007twitter\003com", kTwitterHSTS, kTwitterComPins, DO MAIN_TWITTER_COM },
2645 {22, true, "\010platform\007twitter\003com", false, kTwitterCDNPins, DOMAIN_TW ITTER_COM }, 1475 {22, true, "\010platform\007twitter\003com", false, kTwitterCDNPins, DOMAIN_TW ITTER_COM },
2646 {15, true, "\003si0\005twimg\003com", false, kTwitterCDNPins, DOMAIN_TWIMG_COM }, 1476 {15, true, "\003si0\005twimg\003com", false, kTwitterCDNPins, DOMAIN_TWIMG_COM },
2647 {23, true, "\010twimg0-a\010akamaihd\003net", false, kTwitterCDNPins, DOMAIN_A KAMAIHD_NET }, 1477 {23, true, "\010twimg0-a\010akamaihd\003net", false, kTwitterCDNPins, DOMAIN_A KAMAIHD_NET },
2648 }; 1478 };
2649 static const size_t kNumPreloadedSTS = ARRAYSIZE_UNSAFE(kPreloadedSTS); 1479 static const size_t kNumPreloadedSTS = ARRAYSIZE_UNSAFE(kPreloadedSTS);
2650 1480
2651 static const struct HSTSPreload kPreloadedSNISTS[] = { 1481 static const struct HSTSPreload kPreloadedSNISTS[] = {
2652 // These SNI-only domains must always use HTTPS.
2653 {11, false, "\005gmail\003com", true, kGooglePins, DOMAIN_GMAIL_COM }, 1482 {11, false, "\005gmail\003com", true, kGooglePins, DOMAIN_GMAIL_COM },
2654 {16, false, "\012googlemail\003com", true, kGooglePins, DOMAIN_GOOGLEMAIL_COM }, 1483 {16, false, "\012googlemail\003com", true, kGooglePins, DOMAIN_GOOGLEMAIL_COM },
2655 {15, false, "\003www\005gmail\003com", true, kGooglePins, DOMAIN_GMAIL_COM }, 1484 {15, false, "\003www\005gmail\003com", true, kGooglePins, DOMAIN_GMAIL_COM },
2656 {20, false, "\003www\012googlemail\003com", true, kGooglePins, DOMAIN_GOOGLEMA IL_COM }, 1485 {20, false, "\003www\012googlemail\003com", true, kGooglePins, DOMAIN_GOOGLEMA IL_COM },
2657 // These SNI-only domains must use an acceptable certificate iff using
2658 // HTTPS.
2659 {22, true, "\020google-analytics\003com", false, kGooglePins, DOMAIN_GOOGLE_AN ALYTICS_COM }, 1486 {22, true, "\020google-analytics\003com", false, kGooglePins, DOMAIN_GOOGLE_AN ALYTICS_COM },
2660 // www. requires SNI.
2661 {18, true, "\014googlegroups\003com", false, kGooglePins, DOMAIN_GOOGLEGROUPS_ COM }, 1487 {18, true, "\014googlegroups\003com", false, kGooglePins, DOMAIN_GOOGLEGROUPS_ COM },
2662 }; 1488 };
2663 static const size_t kNumPreloadedSNISTS = ARRAYSIZE_UNSAFE(kPreloadedSNISTS); 1489 static const size_t kNumPreloadedSNISTS = ARRAYSIZE_UNSAFE(kPreloadedSNISTS);
2664 1490
2665 // Returns the HSTSPreload entry for the |canonicalized_host| in |entries|, 1491 #endif // NET_BASE_HSTS_PRELOADED_H_
2666 // or NULL if there is none. Prefers exact hostname matches to those that
2667 // match only because HSTSPreload.include_subdomains is true.
2668 //
2669 // |canonicalized_host| should be the hostname as canonicalized by
2670 // CanonicalizeHost.
2671 static const struct HSTSPreload* GetHSTSPreload(
2672 const std::string& canonicalized_host,
2673 const struct HSTSPreload* entries,
2674 size_t num_entries) {
2675 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
2676 for (size_t j = 0; j < num_entries; j++) {
2677 const struct HSTSPreload* entry = entries + j;
2678
2679 if (i != 0 && !entry->include_subdomains)
2680 continue;
2681
2682 if (entry->length == canonicalized_host.size() - i &&
2683 memcmp(entry->dns_name, &canonicalized_host[i], entry->length) == 0) {
2684 return entry;
2685 }
2686 }
2687 }
2688
2689 return NULL;
2690 }
2691
2692 // static
2693 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host,
2694 bool sni_available) {
2695 std::string canonicalized_host = CanonicalizeHost(host);
2696 const struct HSTSPreload* entry =
2697 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS);
2698
2699 if (entry && entry->pins.required_hashes == kGoogleAcceptableCerts)
2700 return true;
2701
2702 if (sni_available) {
2703 entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS,
2704 kNumPreloadedSNISTS);
2705 if (entry && entry->pins.required_hashes == kGoogleAcceptableCerts)
2706 return true;
2707 }
2708
2709 return false;
2710 }
2711
2712 // static
2713 void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) {
2714 std::string canonicalized_host = CanonicalizeHost(host);
2715
2716 const struct HSTSPreload* entry =
2717 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS);
2718
2719 if (!entry) {
2720 entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS,
2721 kNumPreloadedSNISTS);
2722 }
2723
2724 DCHECK(entry);
2725 DCHECK(entry->pins.required_hashes);
2726 DCHECK(entry->second_level_domain_name != DOMAIN_NOT_PINNED);
2727
2728 UMA_HISTOGRAM_ENUMERATION("Net.PublicKeyPinFailureDomain",
2729 entry->second_level_domain_name, DOMAIN_NUM_EVENTS);
2730 }
2731
2732 // IsPreloadedSTS returns true if the canonicalized hostname should always be
2733 // considered to have STS enabled.
2734 bool TransportSecurityState::IsPreloadedSTS(
2735 const std::string& canonicalized_host,
2736 bool sni_available,
2737 DomainState* out) {
2738 DCHECK(CalledOnValidThread());
2739
2740 out->preloaded = true;
2741 out->mode = DomainState::MODE_STRICT;
2742 out->include_subdomains = false;
2743
2744 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
2745 std::string host_sub_chunk(&canonicalized_host[i],
2746 canonicalized_host.size() - i);
2747 out->domain = DNSDomainToString(host_sub_chunk);
2748 std::string hashed_host(HashHost(host_sub_chunk));
2749 if (forced_hosts_.find(hashed_host) != forced_hosts_.end()) {
2750 *out = forced_hosts_[hashed_host];
2751 out->domain = DNSDomainToString(host_sub_chunk);
2752 out->preloaded = true;
2753 return true;
2754 }
2755 bool ret;
2756 if (HasPreload(kPreloadedSTS, kNumPreloadedSTS, canonicalized_host, i, out,
2757 &ret)) {
2758 return ret;
2759 }
2760 if (sni_available &&
2761 HasPreload(kPreloadedSNISTS, kNumPreloadedSNISTS, canonicalized_host, i,
2762 out, &ret)) {
2763 return ret;
2764 }
2765 }
2766
2767 return false;
2768 }
2769
2770 static std::string HashesToBase64String(
2771 const FingerprintVector& hashes) {
2772 std::vector<std::string> hashes_strs;
2773 for (FingerprintVector::const_iterator
2774 i = hashes.begin(); i != hashes.end(); i++) {
2775 std::string s;
2776 const std::string hash_str(reinterpret_cast<const char*>(i->data),
2777 sizeof(i->data));
2778 base::Base64Encode(hash_str, &s);
2779 hashes_strs.push_back(s);
2780 }
2781
2782 return JoinString(hashes_strs, ',');
2783 }
2784
2785 TransportSecurityState::DomainState::DomainState()
2786 : mode(MODE_STRICT),
2787 created(base::Time::Now()),
2788 include_subdomains(false),
2789 preloaded(false) {
2790 }
2791
2792 TransportSecurityState::DomainState::~DomainState() {
2793 }
2794
2795 bool TransportSecurityState::DomainState::IsChainOfPublicKeysPermitted(
2796 const FingerprintVector& hashes) {
2797
2798 if (HashesIntersect(bad_preloaded_spki_hashes, hashes)) {
2799 LOG(ERROR) << "Rejecting public key chain for domain " << domain
2800 << ". Validated chain: " << HashesToBase64String(hashes)
2801 << ", matches one or more bad hashes: "
2802 << HashesToBase64String(bad_preloaded_spki_hashes);
2803 return false;
2804 }
2805
2806 if (!(dynamic_spki_hashes.empty() && preloaded_spki_hashes.empty()) &&
2807 !HashesIntersect(dynamic_spki_hashes, hashes) &&
2808 !HashesIntersect(preloaded_spki_hashes, hashes)) {
2809 LOG(ERROR) << "Rejecting public key chain for domain " << domain
2810 << ". Validated chain: " << HashesToBase64String(hashes)
2811 << ", expected: " << HashesToBase64String(dynamic_spki_hashes)
2812 << " or: " << HashesToBase64String(preloaded_spki_hashes);
2813
2814 return false;
2815 }
2816
2817 return true;
2818 }
2819
2820 bool TransportSecurityState::DomainState::IsMoreStrict(
2821 const TransportSecurityState::DomainState& other) {
2822 if (this->dynamic_spki_hashes.empty() && !other.dynamic_spki_hashes.empty())
2823 return false;
2824
2825 if (!this->include_subdomains && other.include_subdomains)
2826 return false;
2827
2828 return true;
2829 }
2830
2831 bool TransportSecurityState::DomainState::ShouldRedirectHTTPToHTTPS()
2832 const {
2833 return mode == MODE_STRICT;
2834 }
2835
2836 } // namespace
OLDNEW
« no previous file with comments | « no previous file | net/base/hsts_preloaded.certs » ('j') | net/base/hsts_preloaded.json » ('J')

Powered by Google App Engine
This is Rietveld 408576698