enterprise_platform_keys_apitest_nss.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include <cryptohi.h>
65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
70529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/macros.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/strings/stringprintf.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_apitest.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
1246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/net/nss_context.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/net/url_request_mock_util.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/chromeos_switches.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/login/user_names.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "components/policy/core/browser/browser_policy_connector.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "components/policy/core/common/mock_configuration_policy_provider.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "components/policy/core/common/policy_map.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/content_switches.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_utils.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/nss_util_internal.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/scoped_test_system_nss_key_slot.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "extensions/browser/notification_types.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
26effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "net/cert/nss_cert_database.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/test/url_request/url_request_mock_http_job.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "policy/policy_constants.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
30effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
31effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochnamespace {
32effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
33effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// The test extension has a certificate referencing this private key which will
34effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// be stored in the user's token in the test setup.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// openssl genrsa > privkey.pem
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// openssl pkcs8 -inform pem -in privkey.pem -topk8
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   -outform der -out privkey8.der -nocrypt
39effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// xxd -i privkey8.der
40effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst unsigned char privateKeyPkcs8User[] = {
41effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    0x30, 0x82, 0x01, 0x55, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
42effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
43effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    0x01, 0x3f, 0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00,
44effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    0xc7, 0xc1, 0x4d, 0xd5, 0xdc, 0x3a, 0x2e, 0x1f, 0x42, 0x30, 0x3d, 0x21,
45effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    0x1e, 0xa2, 0x1f, 0x60, 0xcb, 0x71, 0x11, 0x53, 0xb0, 0x75, 0xa0, 0x62,
46effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    0xfe, 0x5e, 0x0a, 0xde, 0xb0, 0x0f, 0x48, 0x97, 0x5e, 0x42, 0xa7, 0x3a,
47effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    0xd1, 0xca, 0x4c, 0xe3, 0xdb, 0x5f, 0x31, 0xc2, 0x99, 0x08, 0x89, 0xcd,
48effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    0x6d, 0x20, 0xaa, 0x75, 0xe6, 0x2b, 0x98, 0xd2, 0xf3, 0x7b, 0x4b, 0xe5,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0x9b, 0xfe, 0xe2, 0x6d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x40, 0x4a,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0xf5, 0x76, 0x10, 0xe7, 0xb8, 0x89, 0x70, 0x3f, 0x75, 0x3c, 0xab, 0x3e,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0x04, 0x96, 0x83, 0xcb, 0x34, 0x1d, 0xcd, 0x6a, 0xed, 0x69, 0x07, 0x5c,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0xee, 0xcb, 0x63, 0x6f, 0x6b, 0xfc, 0xcf, 0xee, 0xa2, 0xc4, 0x67, 0x05,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0x68, 0x4d, 0x21, 0x7e, 0x3e, 0xde, 0x74, 0x72, 0xf8, 0x04, 0x35, 0x66,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0x1e, 0x6b, 0x1d, 0xef, 0x77, 0xf7, 0x33, 0xf0, 0x35, 0xcf, 0x35, 0x6e,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0x53, 0x3f, 0x9d, 0x02, 0x21, 0x00, 0xee, 0x48, 0x67, 0x1b, 0x24, 0x6e,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0x3d, 0x7b, 0xa0, 0xc3, 0xee, 0x8a, 0x2e, 0xc7, 0xd0, 0xa1, 0xdb, 0x25,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0x31, 0x12, 0x99, 0x43, 0x06, 0x3c, 0xb0, 0x80, 0x35, 0x2b, 0xf4, 0xc5,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0xa2, 0xd3, 0x02, 0x21, 0x00, 0xd6, 0x9b, 0x8b, 0x75, 0x91, 0x52, 0xd4,
59effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    0xf0, 0x76, 0xcf, 0xa2, 0xbe, 0xa6, 0xaf, 0x72, 0x6c, 0x52, 0xf9, 0xc9,
60effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    0x0e, 0xea, 0x4a, 0x4c, 0xd2, 0xdf, 0x25, 0x70, 0xc6, 0x66, 0x35, 0x9d,
61effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    0xbf, 0x02, 0x21, 0x00, 0xe8, 0x9e, 0x40, 0x21, 0xcc, 0x37, 0xde, 0xc7,
62effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    0xd1, 0x13, 0x55, 0xcd, 0x0a, 0x8c, 0x40, 0xcd, 0xb1, 0xed, 0xa5, 0xf1,
63effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    0x7d, 0x33, 0x64, 0x64, 0x5c, 0xfe, 0x5c, 0x6a, 0x34, 0x03, 0xb8, 0xc7,
64effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    0x02, 0x20, 0x17, 0xe1, 0xb5, 0x52, 0x3e, 0xfa, 0xc5, 0xc1, 0x80, 0xa7,
65effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    0x38, 0x88, 0x18, 0xca, 0x7b, 0x64, 0x3c, 0x93, 0x99, 0x61, 0x34, 0x87,
66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    0x52, 0x27, 0x41, 0x37, 0xcc, 0x65, 0xf7, 0xa7, 0xcd, 0xc7, 0x02, 0x21,
67effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    0x00, 0x8a, 0x17, 0x7f, 0xf9, 0x45, 0xf3, 0xfd, 0xf7, 0x96, 0x62, 0xf3,
68effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    0x7a, 0x09, 0xfb, 0xe9, 0x9e, 0xc7, 0x7a, 0x1f, 0x53, 0x1a, 0xb8, 0xd5,
69effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    0x88, 0x9d, 0xd4, 0x79, 0x57, 0x88, 0x68, 0x72, 0x6f};
70effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
71effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// The test extension has a certificate referencing this private key which will
720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// be stored in the system token in the test setup.
730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochconst unsigned char privateKeyPkcs8System[] = {
740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    0x30, 0x82, 0x01, 0x54, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
75c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
76010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    0x01, 0x3e, 0x30, 0x82, 0x01, 0x3a, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00,
770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    0xe8, 0xb3, 0x04, 0xb1, 0xad, 0xef, 0x6b, 0xe5, 0xbe, 0xc9, 0x05, 0x75,
78c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    0x07, 0x41, 0xf5, 0x70, 0x50, 0xc2, 0xe8, 0xee, 0xeb, 0x09, 0x9d, 0x49,
795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    0x64, 0x4c, 0x60, 0x61, 0x80, 0xbe, 0xc5, 0x41, 0xf3, 0x8c, 0x57, 0x90,
805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    0x3a, 0x44, 0x62, 0x6d, 0x51, 0xb8, 0xbb, 0xc6, 0x9a, 0x16, 0xdf, 0xf9,
81c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    0xce, 0xe3, 0xb8, 0x8c, 0x2e, 0xa2, 0x16, 0xc8, 0xed, 0xc7, 0xf8, 0x4f,
82effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    0xbd, 0xd3, 0x6e, 0x63, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x40, 0x76,
83effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    0xc9, 0x83, 0xf8, 0xeb, 0xd0, 0x8f, 0xa4, 0xdd, 0x4a, 0xa2, 0xe5, 0x85,
845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    0xc9, 0xee, 0xef, 0xe1, 0xda, 0x4d, 0xac, 0x41, 0x01, 0x4c, 0x70, 0x7d,
855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    0xa9, 0xdb, 0x7d, 0x8a, 0x8a, 0x58, 0x09, 0x04, 0x45, 0x43, 0xa4, 0xf3,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0xb4, 0x98, 0xf6, 0x34, 0x68, 0x5f, 0xc1, 0xc2, 0xa7, 0x86, 0x3e, 0xec,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0x84, 0x0b, 0x18, 0xbc, 0xb1, 0xee, 0x6f, 0x3f, 0xb1, 0x6d, 0xbc, 0x3e,
88558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    0xbf, 0x6d, 0x31, 0x02, 0x21, 0x00, 0xff, 0x9d, 0x90, 0x4f, 0x0e, 0xe8,
89558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    0x7e, 0xf3, 0x38, 0xa7, 0xec, 0x73, 0x80, 0xf9, 0x39, 0x2c, 0xaa, 0x33,
90558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    0x91, 0x72, 0x10, 0x7c, 0x8b, 0xc3, 0x61, 0x6d, 0x40, 0x96, 0xac, 0xb3,
91558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    0x5e, 0xc9, 0x02, 0x21, 0x00, 0xe9, 0x0c, 0xa1, 0x34, 0xf2, 0x43, 0x3c,
92558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    0x74, 0xec, 0x1a, 0xf6, 0x80, 0x8e, 0x50, 0x10, 0x6d, 0x55, 0x64, 0xce,
93558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    0x47, 0x4a, 0x1e, 0x34, 0x27, 0x6c, 0x49, 0x79, 0x6a, 0x23, 0xc6, 0x9d,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0xcb, 0x02, 0x20, 0x48, 0xda, 0xa8, 0xc1, 0xcf, 0xb6, 0xf6, 0x4f, 0xee,
95    0x4a, 0xf6, 0x3a, 0xa9, 0x7c, 0xdf, 0x0d, 0xda, 0xe8, 0xdd, 0xc0, 0x8b,
96    0xf0, 0x63, 0x89, 0x69, 0x60, 0x51, 0x33, 0x60, 0xbf, 0xb2, 0xf9, 0x02,
97    0x21, 0x00, 0xb4, 0x77, 0x81, 0x46, 0x7c, 0xec, 0x30, 0x1e, 0xe2, 0xcf,
98    0x26, 0x5f, 0xfa, 0xd4, 0x69, 0x44, 0x21, 0x42, 0x84, 0xb2, 0x93, 0xe4,
99    0xbb, 0xc2, 0x63, 0x8a, 0xaa, 0x28, 0xd5, 0x37, 0x72, 0xed, 0x02, 0x20,
100    0x16, 0xde, 0x3d, 0x57, 0xc5, 0xd5, 0x3d, 0x90, 0x8b, 0xfd, 0x90, 0x3b,
101    0xd8, 0x71, 0x69, 0x5e, 0x8d, 0xb4, 0x48, 0x1c, 0xa4, 0x01, 0xce, 0xc1,
102    0xb5, 0x6f, 0xe9, 0x1b, 0x32, 0x91, 0x34, 0x38
103};
104
105const base::FilePath::CharType kTestExtensionDir[] =
106    FILE_PATH_LITERAL("extensions/api_test/enterprise_platform_keys");
107const base::FilePath::CharType kUpdateManifestFileName[] =
108    FILE_PATH_LITERAL("update_manifest.xml");
109
110void ImportPrivateKeyPKCS8ToSlot(const unsigned char* pkcs8_der,
111                                 size_t pkcs8_der_size,
112                                 PK11SlotInfo* slot) {
113  SECItem pki_der_user = {
114      siBuffer,
115      // NSS requires non-const data even though it is just for input.
116      const_cast<unsigned char*>(pkcs8_der),
117      pkcs8_der_size};
118
119  SECKEYPrivateKey* seckey = NULL;
120  ASSERT_EQ(SECSuccess,
121            PK11_ImportDERPrivateKeyInfoAndReturnKey(slot,
122                                                     &pki_der_user,
123                                                     NULL,    // nickname
124                                                     NULL,    // publicValue
125                                                     true,    // isPerm
126                                                     true,    // isPrivate
127                                                     KU_ALL,  // usage
128                                                     &seckey,
129                                                     NULL));
130}
131
132// The managed_storage extension has a key defined in its manifest, so that
133// its extension ID is well-known and the policy system can push policies for
134// the extension.
135const char kTestExtensionID[] = "aecpbnckhoppanpmefllkdkohionpmig";
136
137enum SystemToken {
138  SYSTEM_TOKEN_EXISTS,
139  SYSTEM_TOKEN_NOT_EXISTS
140};
141
142enum DeviceStatus {
143  DEVICE_STATUS_ENROLLED,
144  DEVICE_STATUS_NOT_ENROLLED
145};
146
147enum UserAffiliation {
148  USER_AFFILIATION_ENROLLED_DOMAIN,
149  USER_AFFILIATION_UNRELATED
150};
151
152struct Params {
153  Params(SystemToken system_token,
154         DeviceStatus device_status,
155         UserAffiliation user_affiliation)
156      : system_token_(system_token),
157        device_status_(device_status),
158        user_affiliation_(user_affiliation) {}
159
160  SystemToken system_token_;
161  DeviceStatus device_status_;
162  UserAffiliation user_affiliation_;
163};
164
165class EnterprisePlatformKeysTest
166    : public ExtensionApiTest,
167      public ::testing::WithParamInterface<Params> {
168 public:
169  EnterprisePlatformKeysTest() {}
170
171  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
172    ExtensionApiTest::SetUpCommandLine(command_line);
173
174    // Enable the WebCrypto API.
175    command_line->AppendSwitch(
176        switches::kEnableExperimentalWebPlatformFeatures);
177
178    std::string user_email = "someuser@anydomain.com";
179
180    // The command line flag kLoginUser determines the user's email and thus
181    // his affiliation to the domain that the device is enrolled to.
182    if (GetParam().user_affiliation_ == USER_AFFILIATION_ENROLLED_DOMAIN)
183      user_email = chromeos::login::kStubUser;
184
185    command_line->AppendSwitchASCII(chromeos::switches::kLoginUser, user_email);
186  }
187
188  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
189    ExtensionApiTest::SetUpInProcessBrowserTestFixture();
190
191    if (GetParam().device_status_ == DEVICE_STATUS_ENROLLED) {
192      device_policy_test_helper_.device_policy()->policy_data().set_username(
193          chromeos::login::kStubUser);
194
195      device_policy_test_helper_.device_policy()->Build();
196      device_policy_test_helper_.MarkAsEnterpriseOwned();
197    }
198
199    EXPECT_CALL(policy_provider_, IsInitializationComplete(testing::_))
200        .WillRepeatedly(testing::Return(true));
201    policy_provider_.SetAutoRefresh();
202    policy::BrowserPolicyConnector::SetPolicyProviderForTesting(
203        &policy_provider_);
204  }
205
206  virtual void SetUpOnMainThread() OVERRIDE {
207    if (GetParam().system_token_ == SYSTEM_TOKEN_EXISTS) {
208      base::RunLoop loop;
209      content::BrowserThread::PostTask(
210          content::BrowserThread::IO,
211          FROM_HERE,
212          base::Bind(&EnterprisePlatformKeysTest::SetUpTestSystemSlotOnIO,
213                     base::Unretained(this),
214                     browser()->profile()->GetResourceContext(),
215                     loop.QuitClosure()));
216      loop.Run();
217    }
218
219    ExtensionApiTest::SetUpOnMainThread();
220
221    // Enable the URLRequestMock, which is required for force-installing the
222    // test extension through policy.
223    content::BrowserThread::PostTask(
224        content::BrowserThread::IO,
225        FROM_HERE,
226        base::Bind(chrome_browser_net::SetUrlRequestMocksEnabled, true));
227
228    {
229      base::RunLoop loop;
230      GetNSSCertDatabaseForProfile(
231          browser()->profile(),
232          base::Bind(&EnterprisePlatformKeysTest::DidGetCertDatabase,
233                     base::Unretained(this),
234                     loop.QuitClosure()));
235      loop.Run();
236    }
237
238    SetPolicy();
239  }
240
241  virtual void TearDownOnMainThread() OVERRIDE {
242    ExtensionApiTest::TearDownOnMainThread();
243
244    if (GetParam().system_token_ == SYSTEM_TOKEN_EXISTS) {
245      base::RunLoop loop;
246      content::BrowserThread::PostTask(
247          content::BrowserThread::IO,
248          FROM_HERE,
249          base::Bind(&EnterprisePlatformKeysTest::TearDownTestSystemSlotOnIO,
250                     base::Unretained(this),
251                     loop.QuitClosure()));
252      loop.Run();
253    }
254  }
255
256 private:
257  void DidGetCertDatabase(const base::Closure& done_callback,
258                          net::NSSCertDatabase* cert_db) {
259    // In order to use a prepared certificate, import a private key to the
260    // user's token for which the Javscript test will import the certificate.
261    ImportPrivateKeyPKCS8ToSlot(privateKeyPkcs8User,
262                                arraysize(privateKeyPkcs8User),
263                                cert_db->GetPrivateSlot().get());
264    done_callback.Run();
265  }
266
267  void SetUpTestSystemSlotOnIO(content::ResourceContext* context,
268                               const base::Closure& done_callback) {
269    test_system_slot_.reset(new crypto::ScopedTestSystemNSSKeySlot());
270    ASSERT_TRUE(test_system_slot_->ConstructedSuccessfully());
271
272    // Import a private key to the system slot.  The Javascript part of this
273    // test has a prepared certificate for this key.
274    ImportPrivateKeyPKCS8ToSlot(privateKeyPkcs8System,
275                                arraysize(privateKeyPkcs8System),
276                                test_system_slot_->slot());
277
278    content::BrowserThread::PostTask(
279        content::BrowserThread::UI, FROM_HERE, done_callback);
280  }
281
282  void TearDownTestSystemSlotOnIO(const base::Closure& done_callback) {
283    test_system_slot_.reset();
284
285    content::BrowserThread::PostTask(
286        content::BrowserThread::UI, FROM_HERE, done_callback);
287  }
288
289  void SetPolicy() {
290    // Extensions that are force-installed come from an update URL, which
291    // defaults to the webstore. Use a mock URL for this test with an update
292    // manifest that includes the crx file of the test extension.
293    base::FilePath update_manifest_path =
294        base::FilePath(kTestExtensionDir).Append(kUpdateManifestFileName);
295    GURL update_manifest_url(
296        net::URLRequestMockHTTPJob::GetMockUrl(update_manifest_path));
297
298    scoped_ptr<base::ListValue> forcelist(new base::ListValue);
299    forcelist->AppendString(base::StringPrintf(
300        "%s;%s", kTestExtensionID, update_manifest_url.spec().c_str()));
301
302    policy::PolicyMap policy;
303    policy.Set(policy::key::kExtensionInstallForcelist,
304               policy::POLICY_LEVEL_MANDATORY,
305               policy::POLICY_SCOPE_MACHINE,
306               forcelist.release(),
307               NULL);
308
309    // Set the policy and wait until the extension is installed.
310    content::WindowedNotificationObserver observer(
311        extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED,
312        content::NotificationService::AllSources());
313    policy_provider_.UpdateChromePolicy(policy);
314    observer.Wait();
315  }
316
317  policy::DevicePolicyCrosTestHelper device_policy_test_helper_;
318  scoped_ptr<crypto::ScopedTestSystemNSSKeySlot> test_system_slot_;
319  policy::MockConfigurationPolicyProvider policy_provider_;
320};
321
322}  // namespace
323
324IN_PROC_BROWSER_TEST_P(EnterprisePlatformKeysTest, Basic) {
325  // By default, the system token is disabled.
326  std::string system_token_availability = "";
327
328  // Only if the system token exists, and the current user is of the same domain
329  // as the device is enrolled to, the system token is available to the
330  // extension.
331  if (GetParam().system_token_ == SYSTEM_TOKEN_EXISTS &&
332      GetParam().device_status_ == DEVICE_STATUS_ENROLLED &&
333      GetParam().user_affiliation_ == USER_AFFILIATION_ENROLLED_DOMAIN) {
334    system_token_availability = "systemTokenEnabled";
335  }
336
337  ASSERT_TRUE(RunExtensionSubtest(
338      "",
339      base::StringPrintf("chrome-extension://%s/basic.html?%s",
340                         kTestExtensionID,
341                         system_token_availability.c_str())))
342      << message_;
343}
344
345INSTANTIATE_TEST_CASE_P(
346    CheckSystemTokenAvailability,
347    EnterprisePlatformKeysTest,
348    ::testing::Values(Params(SYSTEM_TOKEN_EXISTS,
349                             DEVICE_STATUS_ENROLLED,
350                             USER_AFFILIATION_ENROLLED_DOMAIN),
351                      Params(SYSTEM_TOKEN_EXISTS,
352                             DEVICE_STATUS_ENROLLED,
353                             USER_AFFILIATION_UNRELATED),
354                      Params(SYSTEM_TOKEN_EXISTS,
355                             DEVICE_STATUS_NOT_ENROLLED,
356                             USER_AFFILIATION_UNRELATED),
357                      Params(SYSTEM_TOKEN_NOT_EXISTS,
358                             DEVICE_STATUS_ENROLLED,
359                             USER_AFFILIATION_ENROLLED_DOMAIN)));
360
361class EnterprisePlatformKeysTestNonPolicyInstalledExtension
362    : public EnterprisePlatformKeysTest {};
363
364// Ensure that extensions that are not pre-installed by policy throw an install
365// warning if they request the enterprise.platformKeys permission in the
366// manifest and that such extensions don't see the
367// chrome.enterprise.platformKeys namespace.
368IN_PROC_BROWSER_TEST_F(ExtensionApiTest,
369                       EnterprisePlatformKeysIsRestrictedToPolicyExtension) {
370  ASSERT_TRUE(RunExtensionSubtest("enterprise_platform_keys",
371                                  "api_not_available.html",
372                                  kFlagIgnoreManifestWarnings));
373
374  base::FilePath extension_path =
375      test_data_dir_.AppendASCII("enterprise_platform_keys");
376  ExtensionService* service =
377      extensions::ExtensionSystem::Get(profile())->extension_service();
378  const extensions::Extension* extension =
379      GetExtensionByPath(service->extensions(), extension_path);
380  ASSERT_FALSE(extension->install_warnings().empty());
381  EXPECT_EQ(
382      "'enterprise.platformKeys' is not allowed for specified install "
383      "location.",
384      extension->install_warnings()[0].message);
385}
386