1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/platform_keys/platform_keys.h"
12 #include "base/bind.h"
13 #include "base/bind_helpers.h"
14 #include "base/callback.h"
15 #include "base/compiler_specific.h"
16 #include "base/location.h"
17 #include "base/logging.h"
18 #include "base/macros.h"
19 #include "base/single_thread_task_runner.h"
20 #include "base/stl_util.h"
21 #include "base/thread_task_runner_handle.h"
22 #include "base/threading/worker_pool.h"
23 #include "chrome/browser/browser_process.h"
24 #include "chrome/browser/browser_process_platform_part_chromeos.h"
25 #include "chrome/browser/chromeos/certificate_provider/certificate_provider.h"
26 #include "chrome/browser/chromeos/net/client_cert_filter_chromeos.h"
27 #include "chrome/browser/chromeos/net/client_cert_store_chromeos.h"
28 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
29 #include "chrome/browser/chromeos/profiles/profile_helper.h"
30 #include "chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h"
31 #include "chrome/browser/net/nss_context.h"
32 #include "chrome/browser/profiles/profile.h"
33 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
34 #include "content/public/browser/browser_context.h"
35 #include "content/public/browser/browser_thread.h"
36 #include "crypto/nss_key_util.h"
37 #include "crypto/scoped_nss_types.h"
38 #include "net/base/crypto_module.h"
39 #include "net/base/net_errors.h"
40 #include "net/cert/cert_database.h"
41 #include "net/cert/nss_cert_database.h"
42 #include "net/cert/x509_util_nss.h"
43 #include "net/ssl/ssl_cert_request_info.h"
45 using content::BrowserContext
;
46 using content::BrowserThread
;
49 const char kErrorInternal
[] = "Internal Error.";
50 const char kErrorKeyNotFound
[] = "Key not found.";
51 const char kErrorCertificateNotFound
[] = "Certificate could not be found.";
52 const char kErrorAlgorithmNotSupported
[] = "Algorithm not supported.";
54 // The current maximal RSA modulus length that ChromeOS's TPM supports for key
56 const unsigned int kMaxRSAModulusLengthBits
= 2048;
61 namespace platform_keys
{
65 // Base class to store state that is common to all NSS database operations and
66 // to provide convenience methods to call back.
67 // Keeps track of the originating task runner.
68 class NSSOperationState
{
71 virtual ~NSSOperationState() {}
73 // Called if an error occurred during the execution of the NSS operation
74 // described by this object.
75 virtual void OnError(const tracked_objects::Location
& from
,
76 const std::string
& error_message
) = 0;
78 crypto::ScopedPK11Slot slot_
;
80 // The task runner on which the NSS operation was called. Any reply must be
81 // posted to this runner.
82 scoped_refptr
<base::SingleThreadTaskRunner
> origin_task_runner_
;
85 DISALLOW_COPY_AND_ASSIGN(NSSOperationState
);
88 typedef base::Callback
<void(net::NSSCertDatabase
* cert_db
)> GetCertDBCallback
;
90 // Used by GetCertDatabaseOnIOThread and called back with the requested
92 // If |token_id| is not empty, sets |slot_| of |state| accordingly and calls
93 // |callback| if the database was successfully retrieved.
94 void DidGetCertDBOnIOThread(const std::string
& token_id
,
95 const GetCertDBCallback
& callback
,
96 NSSOperationState
* state
,
97 net::NSSCertDatabase
* cert_db
) {
98 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
100 LOG(ERROR
) << "Couldn't get NSSCertDatabase.";
101 state
->OnError(FROM_HERE
, kErrorInternal
);
105 if (!token_id
.empty()) {
106 if (token_id
== kTokenIdUser
)
107 state
->slot_
= cert_db
->GetPrivateSlot();
108 else if (token_id
== kTokenIdSystem
)
109 state
->slot_
= cert_db
->GetSystemSlot();
112 LOG(ERROR
) << "Slot for token id '" << token_id
<< "' not available.";
113 state
->OnError(FROM_HERE
, kErrorInternal
);
118 callback
.Run(cert_db
);
121 // Retrieves the NSSCertDatabase from |context| and, if |token_id| is not empty,
122 // the slot for |token_id|.
123 // Must be called on the IO thread.
124 void GetCertDatabaseOnIOThread(const std::string
& token_id
,
125 const GetCertDBCallback
& callback
,
126 content::ResourceContext
* context
,
127 NSSOperationState
* state
) {
128 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
129 net::NSSCertDatabase
* cert_db
= GetNSSCertDatabaseForResourceContext(
130 context
, base::Bind(&DidGetCertDBOnIOThread
, token_id
, callback
, state
));
133 DidGetCertDBOnIOThread(token_id
, callback
, state
, cert_db
);
136 // Asynchronously fetches the NSSCertDatabase for |browser_context| and, if
137 // |token_id| is not empty, the slot for |token_id|. Stores the slot in |state|
138 // and passes the database to |callback|. Will run |callback| on the IO thread.
139 void GetCertDatabase(const std::string
& token_id
,
140 const GetCertDBCallback
& callback
,
141 BrowserContext
* browser_context
,
142 NSSOperationState
* state
) {
143 BrowserThread::PostTask(BrowserThread::IO
,
145 base::Bind(&GetCertDatabaseOnIOThread
,
148 browser_context
->GetResourceContext(),
152 class GenerateRSAKeyState
: public NSSOperationState
{
154 GenerateRSAKeyState(unsigned int modulus_length_bits
,
155 const subtle::GenerateKeyCallback
& callback
);
156 ~GenerateRSAKeyState() override
{}
158 void OnError(const tracked_objects::Location
& from
,
159 const std::string
& error_message
) override
{
160 CallBack(from
, std::string() /* no public key */, error_message
);
163 void CallBack(const tracked_objects::Location
& from
,
164 const std::string
& public_key_spki_der
,
165 const std::string
& error_message
) {
166 origin_task_runner_
->PostTask(
167 from
, base::Bind(callback_
, public_key_spki_der
, error_message
));
170 const unsigned int modulus_length_bits_
;
173 // Must be called on origin thread, therefore use CallBack().
174 subtle::GenerateKeyCallback callback_
;
177 class SignRSAState
: public NSSOperationState
{
179 SignRSAState(const std::string
& data
,
180 const std::string
& public_key
,
181 bool sign_direct_pkcs_padded
,
182 HashAlgorithm hash_algorithm
,
183 const subtle::SignCallback
& callback
);
184 ~SignRSAState() override
{}
186 void OnError(const tracked_objects::Location
& from
,
187 const std::string
& error_message
) override
{
188 CallBack(from
, std::string() /* no signature */, error_message
);
191 void CallBack(const tracked_objects::Location
& from
,
192 const std::string
& signature
,
193 const std::string
& error_message
) {
194 origin_task_runner_
->PostTask(
195 from
, base::Bind(callback_
, signature
, error_message
));
198 // The data that will be signed.
199 const std::string data_
;
201 // Must be the DER encoding of a SubjectPublicKeyInfo.
202 const std::string public_key_
;
204 // If true, |data_| will not be hashed before signing. Only PKCS#1 v1.5
205 // padding will be applied before signing.
206 // If false, |hash_algorithm_| must be set to a value != NONE.
207 const bool sign_direct_pkcs_padded_
;
209 // Determines the hash algorithm that is used to digest |data| before signing.
210 // Ignored if |sign_direct_pkcs_padded_| is true.
211 const HashAlgorithm hash_algorithm_
;
214 // Must be called on origin thread, therefore use CallBack().
215 subtle::SignCallback callback_
;
218 class SelectCertificatesState
: public NSSOperationState
{
220 explicit SelectCertificatesState(
221 const std::string
& username_hash
,
222 const bool use_system_key_slot
,
223 const scoped_refptr
<net::SSLCertRequestInfo
>& request
,
224 const subtle::SelectCertificatesCallback
& callback
);
225 ~SelectCertificatesState() override
{}
227 void OnError(const tracked_objects::Location
& from
,
228 const std::string
& error_message
) override
{
229 CallBack(from
, scoped_ptr
<net::CertificateList
>() /* no matches */,
233 void CallBack(const tracked_objects::Location
& from
,
234 scoped_ptr
<net::CertificateList
> matches
,
235 const std::string
& error_message
) {
236 origin_task_runner_
->PostTask(
237 from
, base::Bind(callback_
, base::Passed(&matches
), error_message
));
240 const std::string username_hash_
;
241 const bool use_system_key_slot_
;
242 scoped_refptr
<net::SSLCertRequestInfo
> cert_request_info_
;
243 scoped_ptr
<net::ClientCertStore
> cert_store_
;
244 scoped_ptr
<net::CertificateList
> certs_
;
247 // Must be called on origin thread, therefore use CallBack().
248 subtle::SelectCertificatesCallback callback_
;
251 class GetCertificatesState
: public NSSOperationState
{
253 explicit GetCertificatesState(const GetCertificatesCallback
& callback
);
254 ~GetCertificatesState() override
{}
256 void OnError(const tracked_objects::Location
& from
,
257 const std::string
& error_message
) override
{
259 scoped_ptr
<net::CertificateList
>() /* no certificates */,
263 void CallBack(const tracked_objects::Location
& from
,
264 scoped_ptr
<net::CertificateList
> certs
,
265 const std::string
& error_message
) {
266 origin_task_runner_
->PostTask(
267 from
, base::Bind(callback_
, base::Passed(&certs
), error_message
));
270 scoped_ptr
<net::CertificateList
> certs_
;
273 // Must be called on origin thread, therefore use CallBack().
274 GetCertificatesCallback callback_
;
277 class ImportCertificateState
: public NSSOperationState
{
279 ImportCertificateState(const scoped_refptr
<net::X509Certificate
>& certificate
,
280 const ImportCertificateCallback
& callback
);
281 ~ImportCertificateState() override
{}
283 void OnError(const tracked_objects::Location
& from
,
284 const std::string
& error_message
) override
{
285 CallBack(from
, error_message
);
288 void CallBack(const tracked_objects::Location
& from
,
289 const std::string
& error_message
) {
290 origin_task_runner_
->PostTask(from
, base::Bind(callback_
, error_message
));
293 scoped_refptr
<net::X509Certificate
> certificate_
;
296 // Must be called on origin thread, therefore use CallBack().
297 ImportCertificateCallback callback_
;
300 class RemoveCertificateState
: public NSSOperationState
{
302 RemoveCertificateState(const scoped_refptr
<net::X509Certificate
>& certificate
,
303 const RemoveCertificateCallback
& callback
);
304 ~RemoveCertificateState() override
{}
306 void OnError(const tracked_objects::Location
& from
,
307 const std::string
& error_message
) override
{
308 CallBack(from
, error_message
);
311 void CallBack(const tracked_objects::Location
& from
,
312 const std::string
& error_message
) {
313 origin_task_runner_
->PostTask(from
, base::Bind(callback_
, error_message
));
316 scoped_refptr
<net::X509Certificate
> certificate_
;
319 // Must be called on origin thread, therefore use CallBack().
320 RemoveCertificateCallback callback_
;
323 class GetTokensState
: public NSSOperationState
{
325 explicit GetTokensState(const GetTokensCallback
& callback
);
326 ~GetTokensState() override
{}
328 void OnError(const tracked_objects::Location
& from
,
329 const std::string
& error_message
) override
{
331 scoped_ptr
<std::vector
<std::string
> >() /* no token ids */,
335 void CallBack(const tracked_objects::Location
& from
,
336 scoped_ptr
<std::vector
<std::string
> > token_ids
,
337 const std::string
& error_message
) {
338 origin_task_runner_
->PostTask(
339 from
, base::Bind(callback_
, base::Passed(&token_ids
), error_message
));
343 // Must be called on origin thread, therefore use CallBack().
344 GetTokensCallback callback_
;
347 NSSOperationState::NSSOperationState()
348 : origin_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
351 GenerateRSAKeyState::GenerateRSAKeyState(
352 unsigned int modulus_length_bits
,
353 const subtle::GenerateKeyCallback
& callback
)
354 : modulus_length_bits_(modulus_length_bits
), callback_(callback
) {
357 SignRSAState::SignRSAState(const std::string
& data
,
358 const std::string
& public_key
,
359 bool sign_direct_pkcs_padded
,
360 HashAlgorithm hash_algorithm
,
361 const subtle::SignCallback
& callback
)
363 public_key_(public_key
),
364 sign_direct_pkcs_padded_(sign_direct_pkcs_padded
),
365 hash_algorithm_(hash_algorithm
),
366 callback_(callback
) {
369 SelectCertificatesState::SelectCertificatesState(
370 const std::string
& username_hash
,
371 const bool use_system_key_slot
,
372 const scoped_refptr
<net::SSLCertRequestInfo
>& cert_request_info
,
373 const subtle::SelectCertificatesCallback
& callback
)
374 : username_hash_(username_hash
),
375 use_system_key_slot_(use_system_key_slot
),
376 cert_request_info_(cert_request_info
),
377 callback_(callback
) {
380 GetCertificatesState::GetCertificatesState(
381 const GetCertificatesCallback
& callback
)
382 : callback_(callback
) {
385 ImportCertificateState::ImportCertificateState(
386 const scoped_refptr
<net::X509Certificate
>& certificate
,
387 const ImportCertificateCallback
& callback
)
388 : certificate_(certificate
), callback_(callback
) {
391 RemoveCertificateState::RemoveCertificateState(
392 const scoped_refptr
<net::X509Certificate
>& certificate
,
393 const RemoveCertificateCallback
& callback
)
394 : certificate_(certificate
), callback_(callback
) {
397 GetTokensState::GetTokensState(const GetTokensCallback
& callback
)
398 : callback_(callback
) {
401 // Does the actual key generation on a worker thread. Used by
402 // GenerateRSAKeyWithDB().
403 void GenerateRSAKeyOnWorkerThread(scoped_ptr
<GenerateRSAKeyState
> state
) {
405 LOG(ERROR
) << "No slot.";
406 state
->OnError(FROM_HERE
, kErrorInternal
);
410 crypto::ScopedSECKEYPublicKey public_key
;
411 crypto::ScopedSECKEYPrivateKey private_key
;
412 if (!crypto::GenerateRSAKeyPairNSS(
413 state
->slot_
.get(), state
->modulus_length_bits_
, true /* permanent */,
414 &public_key
, &private_key
)) {
415 LOG(ERROR
) << "Couldn't create key.";
416 state
->OnError(FROM_HERE
, kErrorInternal
);
420 crypto::ScopedSECItem
public_key_der(
421 SECKEY_EncodeDERSubjectPublicKeyInfo(public_key
.get()));
422 if (!public_key_der
) {
423 // TODO(pneubeck): Remove private_key and public_key from storage.
424 LOG(ERROR
) << "Couldn't export public key.";
425 state
->OnError(FROM_HERE
, kErrorInternal
);
430 std::string(reinterpret_cast<const char*>(public_key_der
->data
),
431 public_key_der
->len
),
432 std::string() /* no error */);
435 // Continues generating a RSA key with the obtained NSSCertDatabase. Used by
437 void GenerateRSAKeyWithDB(scoped_ptr
<GenerateRSAKeyState
> state
,
438 net::NSSCertDatabase
* cert_db
) {
439 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
440 // Only the slot and not the NSSCertDatabase is required. Ignore |cert_db|.
441 base::WorkerPool::PostTask(
443 base::Bind(&GenerateRSAKeyOnWorkerThread
, base::Passed(&state
)),
444 true /*task is slow*/);
447 // Does the actual signing on a worker thread. Used by SignRSAWithDB().
448 void SignRSAOnWorkerThread(scoped_ptr
<SignRSAState
> state
) {
449 const uint8
* public_key_uint8
=
450 reinterpret_cast<const uint8
*>(state
->public_key_
.data());
451 std::vector
<uint8
> public_key_vector(
452 public_key_uint8
, public_key_uint8
+ state
->public_key_
.size());
454 crypto::ScopedSECKEYPrivateKey rsa_key
;
456 rsa_key
= crypto::FindNSSKeyFromPublicKeyInfoInSlot(public_key_vector
,
459 rsa_key
= crypto::FindNSSKeyFromPublicKeyInfo(public_key_vector
);
462 // Fail if the key was not found or is of the wrong type.
463 if (!rsa_key
|| SECKEY_GetPrivateKeyType(rsa_key
.get()) != rsaKey
) {
464 state
->OnError(FROM_HERE
, kErrorKeyNotFound
);
468 std::string signature_str
;
469 if (state
->sign_direct_pkcs_padded_
) {
471 sizeof(*state
->data_
.data()) == sizeof(char),
472 "Can't reinterpret data if it's characters are not 8 bit large.");
473 SECItem input
= {siBuffer
,
474 reinterpret_cast<unsigned char*>(
475 const_cast<char*>(state
->data_
.data())),
476 state
->data_
.size()};
478 // Compute signature of hash.
479 int signature_len
= PK11_SignatureLen(rsa_key
.get());
480 if (signature_len
<= 0) {
481 state
->OnError(FROM_HERE
, kErrorInternal
);
485 std::vector
<unsigned char> signature(signature_len
);
486 SECItem signature_output
= {
487 siBuffer
, vector_as_array(&signature
), signature
.size()};
488 if (PK11_Sign(rsa_key
.get(), &signature_output
, &input
) == SECSuccess
)
489 signature_str
.assign(signature
.begin(), signature
.end());
491 SECOidTag sign_alg_tag
= SEC_OID_UNKNOWN
;
492 switch (state
->hash_algorithm_
) {
493 case HASH_ALGORITHM_SHA1
:
494 sign_alg_tag
= SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION
;
496 case HASH_ALGORITHM_SHA256
:
497 sign_alg_tag
= SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION
;
499 case HASH_ALGORITHM_SHA384
:
500 sign_alg_tag
= SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION
;
502 case HASH_ALGORITHM_SHA512
:
503 sign_alg_tag
= SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION
;
505 case HASH_ALGORITHM_NONE
:
510 SECItem sign_result
= {siBuffer
, nullptr, 0};
513 reinterpret_cast<const unsigned char*>(state
->data_
.data()),
514 state
->data_
.size(), rsa_key
.get(), sign_alg_tag
) == SECSuccess
) {
515 signature_str
.assign(sign_result
.data
,
516 sign_result
.data
+ sign_result
.len
);
520 if (signature_str
.empty()) {
521 LOG(ERROR
) << "Couldn't sign.";
522 state
->OnError(FROM_HERE
, kErrorInternal
);
526 state
->CallBack(FROM_HERE
, signature_str
, std::string() /* no error */);
529 // Continues signing with the obtained NSSCertDatabase. Used by Sign().
530 void SignRSAWithDB(scoped_ptr
<SignRSAState
> state
,
531 net::NSSCertDatabase
* cert_db
) {
532 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
533 // Only the slot and not the NSSCertDatabase is required. Ignore |cert_db|.
534 base::WorkerPool::PostTask(
535 FROM_HERE
, base::Bind(&SignRSAOnWorkerThread
, base::Passed(&state
)),
536 true /*task is slow*/);
539 // Called when ClientCertStoreChromeOS::GetClientCerts is done. Builds the list
540 // of net::CertificateList and calls back. Used by
541 // SelectCertificatesOnIOThread().
542 void DidSelectCertificatesOnIOThread(
543 scoped_ptr
<SelectCertificatesState
> state
) {
544 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
545 state
->CallBack(FROM_HERE
, state
->certs_
.Pass(),
546 std::string() /* no error */);
549 // Continues selecting certificates on the IO thread. Used by
550 // SelectClientCertificates().
551 void SelectCertificatesOnIOThread(scoped_ptr
<SelectCertificatesState
> state
) {
552 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
553 state
->cert_store_
.reset(new ClientCertStoreChromeOS(
554 nullptr, // no additional provider
555 make_scoped_ptr(new ClientCertFilterChromeOS(state
->use_system_key_slot_
,
556 state
->username_hash_
)),
557 ClientCertStoreChromeOS::PasswordDelegateFactory()));
559 state
->certs_
.reset(new net::CertificateList
);
561 SelectCertificatesState
* state_ptr
= state
.get();
562 state_ptr
->cert_store_
->GetClientCerts(
563 *state_ptr
->cert_request_info_
, state_ptr
->certs_
.get(),
564 base::Bind(&DidSelectCertificatesOnIOThread
, base::Passed(&state
)));
567 // Filters the obtained certificates on a worker thread. Used by
568 // DidGetCertificates().
569 void FilterCertificatesOnWorkerThread(scoped_ptr
<GetCertificatesState
> state
) {
570 scoped_ptr
<net::CertificateList
> client_certs(new net::CertificateList
);
571 for (net::CertificateList::const_iterator it
= state
->certs_
->begin();
572 it
!= state
->certs_
->end();
574 net::X509Certificate::OSCertHandle cert_handle
= (*it
)->os_cert_handle();
575 crypto::ScopedPK11Slot
cert_slot(PK11_KeyForCertExists(cert_handle
,
579 // Keep only user certificates, i.e. certs for which the private key is
580 // present and stored in the queried slot.
581 if (cert_slot
!= state
->slot_
)
584 client_certs
->push_back(*it
);
587 state
->CallBack(FROM_HERE
, client_certs
.Pass(), std::string() /* no error */);
590 // Passes the obtained certificates to the worker thread for filtering. Used by
591 // GetCertificatesWithDB().
592 void DidGetCertificates(scoped_ptr
<GetCertificatesState
> state
,
593 scoped_ptr
<net::CertificateList
> all_certs
) {
594 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
595 state
->certs_
= all_certs
.Pass();
596 base::WorkerPool::PostTask(
598 base::Bind(&FilterCertificatesOnWorkerThread
, base::Passed(&state
)),
599 true /*task is slow*/);
602 // Continues getting certificates with the obtained NSSCertDatabase. Used by
603 // GetCertificates().
604 void GetCertificatesWithDB(scoped_ptr
<GetCertificatesState
> state
,
605 net::NSSCertDatabase
* cert_db
) {
606 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
607 // Get the pointer to slot before base::Passed releases |state|.
608 PK11SlotInfo
* slot
= state
->slot_
.get();
609 cert_db
->ListCertsInSlot(
610 base::Bind(&DidGetCertificates
, base::Passed(&state
)), slot
);
613 // Does the actual certificate importing on the IO thread. Used by
614 // ImportCertificate().
615 void ImportCertificateWithDB(scoped_ptr
<ImportCertificateState
> state
,
616 net::NSSCertDatabase
* cert_db
) {
617 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
618 // TODO(pneubeck): Use |state->slot_| to verify that we're really importing to
619 // the correct token.
620 // |cert_db| is not required, ignore it.
621 net::CertDatabase
* db
= net::CertDatabase::GetInstance();
623 const net::Error cert_status
=
624 static_cast<net::Error
>(db
->CheckUserCert(state
->certificate_
.get()));
625 if (cert_status
== net::ERR_NO_PRIVATE_KEY_FOR_CERT
) {
626 state
->OnError(FROM_HERE
, kErrorKeyNotFound
);
628 } else if (cert_status
!= net::OK
) {
629 state
->OnError(FROM_HERE
, net::ErrorToString(cert_status
));
633 // Check that the private key is in the correct slot.
635 PK11_KeyForCertExists(state
->certificate_
->os_cert_handle(), NULL
, NULL
);
636 if (slot
!= state
->slot_
) {
637 state
->OnError(FROM_HERE
, kErrorKeyNotFound
);
641 const net::Error import_status
=
642 static_cast<net::Error
>(db
->AddUserCert(state
->certificate_
.get()));
643 if (import_status
!= net::OK
) {
644 LOG(ERROR
) << "Could not import certificate.";
645 state
->OnError(FROM_HERE
, net::ErrorToString(import_status
));
649 state
->CallBack(FROM_HERE
, std::string() /* no error */);
652 // Called on IO thread after the certificate removal is finished.
653 void DidRemoveCertificate(scoped_ptr
<RemoveCertificateState
> state
,
654 bool certificate_found
,
656 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
657 // CertificateNotFound error has precedence over an internal error.
658 if (!certificate_found
) {
659 state
->OnError(FROM_HERE
, kErrorCertificateNotFound
);
663 state
->OnError(FROM_HERE
, kErrorInternal
);
667 state
->CallBack(FROM_HERE
, std::string() /* no error */);
670 // Does the actual certificate removal on the IO thread. Used by
671 // RemoveCertificate().
672 void RemoveCertificateWithDB(scoped_ptr
<RemoveCertificateState
> state
,
673 net::NSSCertDatabase
* cert_db
) {
674 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
675 // Get the pointer before base::Passed clears |state|.
676 scoped_refptr
<net::X509Certificate
> certificate
= state
->certificate_
;
677 bool certificate_found
= certificate
->os_cert_handle()->isperm
;
678 cert_db
->DeleteCertAndKeyAsync(
681 &DidRemoveCertificate
, base::Passed(&state
), certificate_found
));
684 // Does the actual work to determine which tokens are available.
685 void GetTokensWithDB(scoped_ptr
<GetTokensState
> state
,
686 net::NSSCertDatabase
* cert_db
) {
687 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
688 scoped_ptr
<std::vector
<std::string
> > token_ids(new std::vector
<std::string
>);
690 // The user's token is always available.
691 token_ids
->push_back(kTokenIdUser
);
692 if (cert_db
->GetSystemSlot())
693 token_ids
->push_back(kTokenIdSystem
);
695 state
->CallBack(FROM_HERE
, token_ids
.Pass(), std::string() /* no error */);
702 void GenerateRSAKey(const std::string
& token_id
,
703 unsigned int modulus_length_bits
,
704 const GenerateKeyCallback
& callback
,
705 BrowserContext
* browser_context
) {
706 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
707 scoped_ptr
<GenerateRSAKeyState
> state(
708 new GenerateRSAKeyState(modulus_length_bits
, callback
));
710 if (modulus_length_bits
> kMaxRSAModulusLengthBits
) {
711 state
->OnError(FROM_HERE
, kErrorAlgorithmNotSupported
);
715 // Get the pointer to |state| before base::Passed releases |state|.
716 NSSOperationState
* state_ptr
= state
.get();
717 GetCertDatabase(token_id
,
718 base::Bind(&GenerateRSAKeyWithDB
, base::Passed(&state
)),
723 void SignRSAPKCS1Digest(const std::string
& token_id
,
724 const std::string
& data
,
725 const std::string
& public_key
,
726 HashAlgorithm hash_algorithm
,
727 const SignCallback
& callback
,
728 content::BrowserContext
* browser_context
) {
729 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
730 scoped_ptr
<SignRSAState
> state(
731 new SignRSAState(data
, public_key
, false /* digest before signing */,
732 hash_algorithm
, callback
));
733 // Get the pointer to |state| before base::Passed releases |state|.
734 NSSOperationState
* state_ptr
= state
.get();
736 // The NSSCertDatabase object is not required. But in case it's not available
737 // we would get more informative error messages and we can double check that
738 // we use a key of the correct token.
739 GetCertDatabase(token_id
, base::Bind(&SignRSAWithDB
, base::Passed(&state
)),
740 browser_context
, state_ptr
);
743 void SignRSAPKCS1Raw(const std::string
& token_id
,
744 const std::string
& data
,
745 const std::string
& public_key
,
746 const SignCallback
& callback
,
747 content::BrowserContext
* browser_context
) {
748 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
749 scoped_ptr
<SignRSAState
> state(new SignRSAState(
750 data
, public_key
, true /* sign directly without hashing */,
751 HASH_ALGORITHM_NONE
, callback
));
752 // Get the pointer to |state| before base::Passed releases |state|.
753 NSSOperationState
* state_ptr
= state
.get();
755 // The NSSCertDatabase object is not required. But in case it's not available
756 // we would get more informative error messages and we can double check that
757 // we use a key of the correct token.
758 GetCertDatabase(token_id
, base::Bind(&SignRSAWithDB
, base::Passed(&state
)),
759 browser_context
, state_ptr
);
762 void SelectClientCertificates(
763 const std::vector
<std::string
>& certificate_authorities
,
764 const SelectCertificatesCallback
& callback
,
765 content::BrowserContext
* browser_context
) {
766 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
768 scoped_refptr
<net::SSLCertRequestInfo
> cert_request_info(
769 new net::SSLCertRequestInfo
);
771 // Currently we do not pass down the requested certificate type to the net
772 // layer, as it does not support filtering certificates by type. Rather, we
773 // do not constrain the certificate type here, instead the caller has to apply
774 // filtering afterwards.
775 cert_request_info
->cert_authorities
= certificate_authorities
;
777 const user_manager::User
* user
=
778 chromeos::ProfileHelper::Get()->GetUserByProfile(
779 Profile::FromBrowserContext(browser_context
));
781 // Use the device-wide system key slot only if the user is of the same
782 // domain as the device is registered to.
783 policy::BrowserPolicyConnectorChromeOS
* connector
=
784 g_browser_process
->platform_part()->browser_policy_connector_chromeos();
785 bool use_system_key_slot
= connector
->GetUserAffiliation(user
->email()) ==
786 policy::USER_AFFILIATION_MANAGED
;
788 scoped_ptr
<SelectCertificatesState
> state(new SelectCertificatesState(
789 user
->username_hash(), use_system_key_slot
, cert_request_info
, callback
));
791 BrowserThread::PostTask(
792 BrowserThread::IO
, FROM_HERE
,
793 base::Bind(&SelectCertificatesOnIOThread
, base::Passed(&state
)));
796 } // namespace subtle
798 std::string
GetSubjectPublicKeyInfo(
799 const scoped_refptr
<net::X509Certificate
>& certificate
) {
800 const SECItem
& spki_der
= certificate
->os_cert_handle()->derPublicKey
;
801 return std::string(spki_der
.data
, spki_der
.data
+ spki_der
.len
);
804 bool GetPublicKey(const scoped_refptr
<net::X509Certificate
>& certificate
,
805 net::X509Certificate::PublicKeyType
* key_type
,
806 size_t* key_size_bits
) {
807 net::X509Certificate::PublicKeyType key_type_tmp
=
808 net::X509Certificate::kPublicKeyTypeUnknown
;
809 size_t key_size_bits_tmp
= 0;
810 net::X509Certificate::GetPublicKeyInfo(certificate
->os_cert_handle(),
811 &key_size_bits_tmp
, &key_type_tmp
);
813 if (key_type_tmp
== net::X509Certificate::kPublicKeyTypeUnknown
) {
814 LOG(WARNING
) << "Could not extract public key of certificate.";
817 if (key_type_tmp
!= net::X509Certificate::kPublicKeyTypeRSA
) {
818 LOG(WARNING
) << "Keys of other type than RSA are not supported.";
822 crypto::ScopedSECKEYPublicKey
public_key(
823 CERT_ExtractPublicKey(certificate
->os_cert_handle()));
825 LOG(WARNING
) << "Could not extract public key of certificate.";
828 long public_exponent
= DER_GetInteger(&public_key
->u
.rsa
.publicExponent
);
829 if (public_exponent
!= 65537L) {
830 LOG(ERROR
) << "Rejecting RSA public exponent that is unequal 65537.";
834 *key_type
= key_type_tmp
;
835 *key_size_bits
= key_size_bits_tmp
;
839 void GetCertificates(const std::string
& token_id
,
840 const GetCertificatesCallback
& callback
,
841 BrowserContext
* browser_context
) {
842 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
843 scoped_ptr
<GetCertificatesState
> state(new GetCertificatesState(callback
));
844 // Get the pointer to |state| before base::Passed releases |state|.
845 NSSOperationState
* state_ptr
= state
.get();
846 GetCertDatabase(token_id
,
847 base::Bind(&GetCertificatesWithDB
, base::Passed(&state
)),
852 void ImportCertificate(const std::string
& token_id
,
853 const scoped_refptr
<net::X509Certificate
>& certificate
,
854 const ImportCertificateCallback
& callback
,
855 BrowserContext
* browser_context
) {
856 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
857 scoped_ptr
<ImportCertificateState
> state(
858 new ImportCertificateState(certificate
, callback
));
859 // Get the pointer to |state| before base::Passed releases |state|.
860 NSSOperationState
* state_ptr
= state
.get();
862 // The NSSCertDatabase object is not required. But in case it's not available
863 // we would get more informative error messages and we can double check that
864 // we use a key of the correct token.
865 GetCertDatabase(token_id
,
866 base::Bind(&ImportCertificateWithDB
, base::Passed(&state
)),
871 void RemoveCertificate(const std::string
& token_id
,
872 const scoped_refptr
<net::X509Certificate
>& certificate
,
873 const RemoveCertificateCallback
& callback
,
874 BrowserContext
* browser_context
) {
875 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
876 scoped_ptr
<RemoveCertificateState
> state(
877 new RemoveCertificateState(certificate
, callback
));
878 // Get the pointer to |state| before base::Passed releases |state|.
879 NSSOperationState
* state_ptr
= state
.get();
881 // The NSSCertDatabase object is not required. But in case it's not available
882 // we would get more informative error messages.
883 GetCertDatabase(token_id
,
884 base::Bind(&RemoveCertificateWithDB
, base::Passed(&state
)),
889 void GetTokens(const GetTokensCallback
& callback
,
890 content::BrowserContext
* browser_context
) {
891 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
892 scoped_ptr
<GetTokensState
> state(new GetTokensState(callback
));
893 // Get the pointer to |state| before base::Passed releases |state|.
894 NSSOperationState
* state_ptr
= state
.get();
895 GetCertDatabase(std::string() /* don't get any specific slot */,
896 base::Bind(&GetTokensWithDB
, base::Passed(&state
)),
901 } // namespace platform_keys
903 } // namespace chromeos