C++程序  |  124行  |  4.92 KB

//
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#ifndef ATTESTATION_SERVER_PKCS11_KEY_STORE_H_
#define ATTESTATION_SERVER_PKCS11_KEY_STORE_H_

#include "attestation/server/key_store.h"

#include <string>

#include <base/callback_forward.h>
#include <base/macros.h>
#include <chaps/pkcs11/cryptoki.h>
#include <chaps/token_manager_client.h>

namespace attestation {

// This class uses a PKCS #11 token as storage for key data.  The key data is
// stored in data objects with the following attributes:
// CKA_CLASS - CKO_DATA
// CKA_LABEL - A key name.
// CKA_VALUE - Binary key data (opaque to this class and the PKCS #11 token).
// CKA_APPLICATION - A constant value associated with this class.
// CKA_TOKEN - True
// CKA_PRIVATE - True
// CKA_MODIFIABLE - False
// There is no barrier between the objects created by this class and any other
// objects residing in the same token.  In practice, this means that any
// component with access to the PKCS #11 token also has access to read or delete
// key data.
class Pkcs11KeyStore : public KeyStore {
 public:
  // Does not take ownership of pointers.
  explicit Pkcs11KeyStore(chaps::TokenManagerClient* token_manager);
  ~Pkcs11KeyStore() override;

  // KeyStore interface.
  bool Read(const std::string& username,
            const std::string& key_name,
            std::string* key_data) override;
  bool Write(const std::string& username,
             const std::string& key_name,
             const std::string& key_data) override;
  bool Delete(const std::string& username,
              const std::string& key_name) override;
  bool DeleteByPrefix(const std::string& username,
                      const std::string& key_prefix) override;
  bool Register(const std::string& username,
                const std::string& label,
                KeyType key_type,
                KeyUsage key_usage,
                const std::string& private_key_blob,
                const std::string& public_key_der,
                const std::string& certificate) override;
  bool RegisterCertificate(const std::string& username,
                           const std::string& certificate) override;

 private:
  using EnumObjectsCallback =
      base::Callback<bool(const std::string& key_name,
                          CK_OBJECT_HANDLE object_handle)>;

  // Searches for a PKCS #11 object for a given key name.  If one exists, the
  // object handle is returned, otherwise CK_INVALID_HANDLE is returned.
  CK_OBJECT_HANDLE FindObject(CK_SESSION_HANDLE session_handle,
                              const std::string& key_name);

  // Gets a slot for the given |username| if |is_user_specific| or the system
  // slot otherwise. Returns false if no appropriate slot is found.
  bool GetUserSlot(const std::string& username,
                   CK_SLOT_ID_PTR slot);

  // Enumerates all PKCS #11 objects associated with keys.  The |callback| is
  // called once for each object.
  bool EnumObjects(CK_SESSION_HANDLE session_handle,
                   const EnumObjectsCallback& callback);

  // Looks up the key name for the given |object_handle| which is associated
  // with a key.  Returns true on success.
  bool GetKeyName(CK_SESSION_HANDLE session_handle,
                  CK_OBJECT_HANDLE object_handle,
                  std::string* key_name);

  // An EnumObjectsCallback for use with DeleteByPrefix.  Destroys the key
  // object identified by |object_handle| if |key_name| matches |key_prefix|.
  // Returns true on success.
  bool DeleteIfMatchesPrefix(CK_SESSION_HANDLE session_handle,
                             const std::string& key_prefix,
                             const std::string& key_name,
                             CK_OBJECT_HANDLE object_handle);

  // Extracts the |subject|, |issuer|, and |serial_number| information from an
  // X.509 |certificate|. Returns false if the value cannot be determined.
  bool GetCertificateFields(const std::string& certificate,
                            std::string* subject,
                            std::string* issuer,
                            std::string* serial_number);

  // Returns true iff the given certificate already exists in the token.
  bool DoesCertificateExist(CK_SESSION_HANDLE session_handle,
                            const std::string& certificate);

  chaps::TokenManagerClient* token_manager_;

  DISALLOW_COPY_AND_ASSIGN(Pkcs11KeyStore);
};

}  // namespace attestation

#endif  // ATTESTATION_SERVER_PKCS11_KEY_STORE_H_