| Index: pkcs11.cc
|
| diff --git a/pkcs11.cc b/pkcs11.cc
|
| index a469726cee90bbee799202ffb5d8e32b09bddc26..894886c37e1d68ef0e1372ddffcd738ae131b645 100644
|
| --- a/pkcs11.cc
|
| +++ b/pkcs11.cc
|
| @@ -28,7 +28,9 @@ namespace entd {
|
| // SlotObject JavaScript interface wrapper around Pkcs11SlotHandler.
|
| class SlotObject : public JSObjectWrapper<SlotObject> {
|
| public:
|
| - SlotObject() : slot_handler_(NULL) { }
|
| + SlotObject() : slot_handler_(NULL) {}
|
| + SlotObject(const std::string& label, const std::string& key_id)
|
| + : label_(label), key_identifier_(key_id), slot_handler_(NULL) {}
|
| virtual ~SlotObject() {}
|
|
|
| virtual bool Initialize();
|
| @@ -52,7 +54,7 @@ class SlotObject : public JSObjectWrapper<SlotObject> {
|
| // Setters
|
|
|
| // Stores the key identifier and passes it to the slot handler.
|
| - const bool SetKeyIdentifier(const std::string& id) {
|
| + bool SetKeyIdentifier(const std::string& id) {
|
| key_identifier_ = id;
|
| return slot_handler_->SetKeyIdentifier(label_, id);
|
| }
|
| @@ -72,6 +74,41 @@ class SlotObject : public JSObjectWrapper<SlotObject> {
|
| DISALLOW_COPY_AND_ASSIGN(SlotObject);
|
| };
|
|
|
| +// Class Certificate declaration (implementation below)
|
| +// Certificate JavaScript interface wrapper around Pkcs11CertificateHandler.
|
| +class Certificate : public JSObjectWrapper<Certificate> {
|
| + public:
|
| + Certificate() {}
|
| + virtual ~Certificate() {}
|
| +
|
| + // JSObjectWrapper Interface
|
| + virtual void ParseConstructorArgs(
|
| + v8::Handle<v8::Object> obj, const v8::Arguments& args);
|
| + static void SetTemplateBindings(
|
| + v8::Handle<v8::ObjectTemplate> template_object);
|
| + static const char* GetClassName() { return "Certificate"; }
|
| +
|
| + // Accessors
|
| + const chromeos::Blob& certificate() const { return certificate_; }
|
| + const std::string& subject() const { return subject_; }
|
| +
|
| + // Certificate handler management
|
| + static void InitCertificateHandler(Pkcs11CertificateHandler* handler) {
|
| + certificate_handler_ = handler;
|
| + }
|
| + static Pkcs11CertificateHandler* certificate_handler() {
|
| + return certificate_handler_;
|
| + }
|
| +
|
| + private:
|
| + // The certificate may contain binary data, so store it as an array of bytes
|
| + // instead of a string.
|
| + chromeos::Blob certificate_;
|
| + std::string subject_;
|
| + static Pkcs11CertificateHandler* certificate_handler_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(Certificate);
|
| +};
|
|
|
| // class Pkcs11CertificateHandlerLocalFile
|
| // Test Certificate handler that returns the contents of a file.
|
| @@ -775,11 +812,129 @@ class Pkcs11SlotHandlerOpenCryptoki : public Pkcs11SlotHandlerInMemory {
|
| res = Pkcs11SlotHandlerInMemory::Initialize();
|
| }
|
|
|
| - // TODO(stevenjb): read existing objects into objects_
|
| -
|
| return res;
|
| }
|
|
|
| + bool ReadObjectsFromSlot(Pkcs11* pkcs11) {
|
| + CK_SESSION_HANDLE session_handle = NULL;
|
| + CK_RV rv = C_OpenSession(slot_id_,
|
| + CKF_SERIAL_SESSION|CKF_RW_SESSION, NULL, NULL,
|
| + &session_handle);
|
| + if (rv != CKR_OK) {
|
| + LOG(ERROR) << "C_OpenSession failed, error: " << rv
|
| + << ", slot: " << slot_index_;
|
| + return false;
|
| + }
|
| +
|
| + // Gather a list of objects in the slot
|
| + int num_objects = 0;
|
| +
|
| + rv = C_FindObjectsInit(session_handle, NULL, 0);
|
| + if (rv != CKR_OK) {
|
| + LOG(ERROR) << "C_FindObjectsInit failed: " << rv;
|
| + return false;
|
| + }
|
| +
|
| + while (1) {
|
| + CK_ULONG count;
|
| + CK_OBJECT_HANDLE object;
|
| + rv = C_FindObjects(session_handle, &object, 1, &count);
|
| + if (rv != CKR_OK) {
|
| + LOG(ERROR) << "C_FindObjects failed: " << rv;
|
| + return false;
|
| + }
|
| + if (count == 0) {
|
| + // No more objects to read, exit loop.
|
| + break;
|
| + }
|
| + ++num_objects;
|
| +
|
| + const size_t LABEL_MAX_LENGTH = 256;
|
| + const size_t IDSTR_MAX_LENGTH = 8;
|
| + const size_t SUBJECT_MAX_LENGTH = 1024;
|
| +
|
| + // Define a template with the values we are interested in
|
| + CK_OBJECT_CLASS obj_class;
|
| + char obj_label[LABEL_MAX_LENGTH];
|
| + CK_BYTE idstr[IDSTR_MAX_LENGTH];
|
| + CK_BYTE subject[SUBJECT_MAX_LENGTH];
|
| +
|
| + CK_ATTRIBUTE obj_template[] = {
|
| + { CKA_CLASS, &obj_class, sizeof(obj_class) },
|
| + { CKA_LABEL, obj_label, LABEL_MAX_LENGTH },
|
| + { CKA_ID, idstr, IDSTR_MAX_LENGTH },
|
| + { CKA_SUBJECT, subject, SUBJECT_MAX_LENGTH },
|
| + };
|
| + int n_attr = sizeof(obj_template) / sizeof(CK_ATTRIBUTE);
|
| +
|
| + // Read values into obj_template
|
| + rv = C_GetAttributeValue(session_handle, object, obj_template, n_attr);
|
| + if (rv != CKR_OK) {
|
| + LOG(ERROR) << "C_GetAttributeValue failed: " << rv
|
| + << " obj: " << num_objects;
|
| + }
|
| + obj_class = *(static_cast<CK_OBJECT_CLASS*>(obj_template[0].pValue));
|
| + if (obj_class == CKO_CERTIFICATE ||
|
| + obj_class == CKO_PUBLIC_KEY ||
|
| + obj_class == CKO_PRIVATE_KEY) {
|
| + if (obj_template[1].ulValueLen > 0) {
|
| + // Only parse certificate and key objects with a valid label
|
| + std::string label = TemplateToString(obj_template[1]);
|
| + std::string idstr = GetKeyFromId(
|
| + static_cast<CK_BYTE*>(obj_template[2].pValue),
|
| + obj_template[2].ulValueLen);
|
| + std::string subject = TemplateToString(obj_template[3]);
|
| + Object* obj = AddObject(label);
|
| + if (!obj->key_identifier_.empty() && obj->key_identifier_ != idstr) {
|
| + LOG(WARNING) << "Object '" << label << "' "
|
| + << "with mismatched key identifers: "
|
| + << "'" << obj->key_identifier_ << "'"
|
| + << " != '" << idstr << "'";
|
| + } else {
|
| + obj->key_identifier_ = idstr;
|
| + obj->subject_ = subject;
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + C_FindObjectsFinal(session_handle);
|
| +
|
| + LOG(INFO) << "Found " << num_objects << " objects in slot.";
|
| +
|
| + // Iterate through the list of objects and generate
|
| + // SlotObject objects and insert them into pkcs11.slots.
|
| + for (ObjectMap::iterator iter = objects_.begin();
|
| + iter != objects_.end(); ++iter) {
|
| + Object* object = iter->second.get();
|
| +
|
| + // Build a slot object
|
| + SlotObject* slot_object = new SlotObject(object->label_,
|
| + object->key_identifier_);
|
| + slot_object->Initialize();
|
| + slot_object->SetSlotHandler(pkcs11->slot_handler());
|
| + slot_object->obj()->Set(v8::String::NewSymbol("label"),
|
| + v8::String::New(object->label_.c_str()),
|
| + v8::ReadOnly);
|
| + slot_object->obj()->Set(v8::String::NewSymbol("keyIdentifier"),
|
| + v8::String::New(object->key_identifier_.c_str()));
|
| +
|
| + // Build a certificate
|
| + Certificate* certificate = new Certificate();
|
| + certificate->Initialize();
|
| + certificate->obj()->Set(v8::String::NewSymbol("subject"),
|
| + v8::String::New(object->subject_.c_str()));
|
| +
|
| + // Add the certificate to the slot object
|
| + slot_object->obj()->Set(v8::String::NewSymbol("certificate"),
|
| + certificate->obj());
|
| +
|
| + // Add the object to pkcs11.slots ("slots[label] = obj")
|
| + pkcs11->AddJSSlotObject(slot_object);
|
| + }
|
| + return true;
|
| + }
|
| +
|
| // Returns false if the key is longer than a reasonable maximum length.
|
| virtual bool SetKeyIdentifier(const std::string& label,
|
| const std::string& keyid) {
|
| @@ -1123,6 +1278,11 @@ class Pkcs11SlotHandlerOpenCryptoki : public Pkcs11SlotHandlerInMemory {
|
| return handle;
|
| }
|
|
|
| + std::string TemplateToString(const CK_ATTRIBUTE& attr) {
|
| + const char* value = static_cast<const char*>(attr.pValue);
|
| + return std::string(value, attr.ulValueLen);
|
| + }
|
| +
|
| // openssl crypto library interface
|
|
|
| struct RsaKeyInfo {
|
| @@ -1224,6 +1384,12 @@ class Pkcs11SlotHandlerOpenCryptoki : public Pkcs11SlotHandlerInMemory {
|
| return true;
|
| }
|
|
|
| + // Inverse of GetKeyIdStr
|
| + std::string GetKeyFromId(CK_BYTE* idstrp, CK_ULONG idstrlen) {
|
| + chromeos::Blob bytes = chromeos::Blob(idstrp, idstrp+idstrlen);
|
| + return chromeos::AsciiEncode(bytes);
|
| + }
|
| +
|
| std::string user_pin_;
|
| CK_ULONG slot_index_;
|
| CK_SLOT_ID slot_id_;
|
| @@ -1286,7 +1452,7 @@ class CSR : public JSObjectWrapper<CSR> {
|
| };
|
|
|
| // static
|
| -Pkcs11CertificateHandler* CSR::certificate_handler_;
|
| +Pkcs11CertificateHandler* CSR::certificate_handler_ = NULL;
|
|
|
| // Base64 encoded version of the CSR
|
| static v8::Handle<v8::Value> dispatch_CSRToString(const v8::Arguments& args) {
|
| @@ -1337,44 +1503,10 @@ void CSR::ParseConstructorArgs(
|
| }
|
|
|
|
|
| -// Class Certificate
|
| -// Certificate JavaScript interface wrapper around Pkcs11CertificateHandler.
|
| -class Certificate : public JSObjectWrapper<Certificate> {
|
| - public:
|
| - Certificate() {}
|
| - virtual ~Certificate() {}
|
| -
|
| - // JSObjectWrapper Interface
|
| - virtual void ParseConstructorArgs(
|
| - v8::Handle<v8::Object> obj, const v8::Arguments& args);
|
| - static void SetTemplateBindings(
|
| - v8::Handle<v8::ObjectTemplate> template_object);
|
| - static const char* GetClassName() { return "Certificate"; }
|
| -
|
| - // Accessors
|
| - const chromeos::Blob& certificate() const { return certificate_; }
|
| - const std::string& subject() const { return subject_; }
|
| -
|
| - // Certificate handler management
|
| - static void InitCertificateHandler(Pkcs11CertificateHandler* handler) {
|
| - certificate_handler_ = handler;
|
| - }
|
| - static Pkcs11CertificateHandler* certificate_handler() {
|
| - return certificate_handler_;
|
| - }
|
| -
|
| - private:
|
| - // The certificate may contain binary data, so store it as an array of bytes
|
| - // instead of a string.
|
| - chromeos::Blob certificate_;
|
| - std::string subject_;
|
| - static Pkcs11CertificateHandler* certificate_handler_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(Certificate);
|
| -};
|
| +// Class Certificate Implementation
|
|
|
| // static
|
| -Pkcs11CertificateHandler* Certificate::certificate_handler_;
|
| +Pkcs11CertificateHandler* Certificate::certificate_handler_ = NULL;
|
|
|
| // Returns the contents of the Certificate as a string.
|
| // Note: if this is binary and not Base64, results may be unexpected.
|
| @@ -1414,9 +1546,6 @@ void Certificate::ParseConstructorArgs(v8::Handle<v8::Object> obj,
|
| return;
|
| }
|
|
|
| - // Set the 'content' property to the input content
|
| - obj->Set(v8::String::NewSymbol("content"),
|
| - content->ToString());
|
| // Set the 'subject' property to the certificate subject
|
| obj->Set(v8::String::NewSymbol("subject"),
|
| v8::String::New(subject_.c_str()));
|
| @@ -1453,13 +1582,14 @@ static v8::Handle<v8::Value> dispatch_generateKeyPair(
|
|
|
| // Argument 0 is the key identifier
|
| v8::Handle<v8::String> v8keyid = args[0]->ToString();
|
| - slot->obj()->Set(v8::String::NewSymbol("keyIdentifier"), v8keyid);
|
| std::string keyid = std::string(*v8::String::Utf8Value(v8keyid));
|
| bool res = slot->SetKeyIdentifier(keyid);
|
| if (!res) {
|
| utils::ThrowV8Exception(std::string("Invalid key id: ") + keyid);
|
| return v8::False();
|
| }
|
| + // Set the JS keyIdentifier property
|
| + slot->obj()->Set(v8::String::NewSymbol("keyIdentifier"), v8keyid);
|
|
|
| // Argumnet 1 is the passphrase (optional)
|
| std::string passphrase; // defaults to empty
|
| @@ -1476,11 +1606,6 @@ static v8::Handle<v8::Value> dispatch_generateKeyPair(
|
| return v8::False();
|
| }
|
|
|
| - // Set the JS publicKey property
|
| - v8::Handle<v8::String> v8_public_key =
|
| - v8::String::New(slot->GetPublicKey().c_str());
|
| - slot->obj()->Set(v8::String::NewSymbol("publicKey"), v8_public_key);
|
| -
|
| return v8::True();
|
| }
|
|
|
| @@ -1557,15 +1682,8 @@ void SlotObject::ParseConstructorArgs(
|
| return;
|
| }
|
|
|
| - // Add a this to pkcs11.slots ("slots.{label} = {cert}")
|
| - v8::Local<v8::Value> slotsvalue =
|
| - pkcs11->obj()->Get(v8::String::NewSymbol("slots"));
|
| - if (slotsvalue.IsEmpty() || !slotsvalue->IsObject()) {
|
| - LOG(ERROR) << "'slots' is not an object in pkcs11";
|
| - return;
|
| - }
|
| - v8::Local<v8::Object> slots = v8::Local<v8::Object>::Cast(slotsvalue);
|
| - slots->Set(v8label->ToString(), obj);
|
| + // Add this to pkcs11.slots ("slots[label] = obj")
|
| + pkcs11->AddJSSlotObject(this);
|
| }
|
|
|
|
|
| @@ -1581,6 +1699,19 @@ Pkcs11::~Pkcs11() {
|
| CleanupTemplate(); // We only have one Pkcs11 instance.
|
| }
|
|
|
| +// Called any time slot_handler_ or certificate_handler_ gets set.
|
| +void Pkcs11::SetupHandlers() {
|
| + // The certificate handler may need access to the slot handler
|
| + certificate_handler()->SetSlotHandler(slot_handler());
|
| +
|
| + // Set up the CSR and Certificate sub-classes with the certificate handler.
|
| + CSR::InitCertificateHandler(certificate_handler());
|
| + Certificate::InitCertificateHandler(certificate_handler());
|
| +}
|
| +
|
| +// This always gets called first by InitializeXXX()
|
| +// so that obj() is available for other initialization
|
| +// functions (e.g. ReadObjectsFromSlot())
|
| bool Pkcs11::Initialize() {
|
| if (slot_handler_.get() == NULL) {
|
| // Default slot handler
|
| @@ -1592,12 +1723,8 @@ bool Pkcs11::Initialize() {
|
| certificate_handler_.reset(new Pkcs11CertificateHandlerLocalFile("", ""));
|
| certificate_handler_->Initialize();
|
| }
|
| - // The certificate handler may need access to the slot handler
|
| - certificate_handler()->SetSlotHandler(slot_handler());
|
|
|
| - // Set up the CSR and Certificate sub-classes with the certificate handler.
|
| - CSR::InitCertificateHandler(certificate_handler());
|
| - Certificate::InitCertificateHandler(certificate_handler());
|
| + SetupHandlers();
|
|
|
| // Initialize the pkcs11 template specially
|
| v8::Handle<v8::FunctionTemplate> t = GetTemplate();
|
| @@ -1615,8 +1742,13 @@ bool Pkcs11::InitializeOpenCryptoki(const std::string& test_cert,
|
| const std::string& engine) {
|
| LOG(INFO) << "Initializing pkcs11 with opencryptoki and engine:" << engine;
|
|
|
| - slot_handler_.reset(new Pkcs11SlotHandlerOpenCryptoki());
|
| - slot_handler_->Initialize();
|
| + bool res = Initialize();
|
| +
|
| + Pkcs11SlotHandlerOpenCryptoki* slot_handler =
|
| + new Pkcs11SlotHandlerOpenCryptoki();
|
| + slot_handler_.reset(slot_handler);
|
| + slot_handler->Initialize();
|
| + slot_handler->ReadObjectsFromSlot(this);
|
|
|
| Pkcs11CertificateHandlerOpenSslPkcs11Engine* cert_handler =
|
| new Pkcs11CertificateHandlerOpenSslPkcs11Engine();
|
| @@ -1626,14 +1758,21 @@ bool Pkcs11::InitializeOpenCryptoki(const std::string& test_cert,
|
| cert_handler->SetOutputDER();
|
| certificate_handler_.reset(cert_handler);
|
|
|
| - return Initialize();
|
| + SetupHandlers();
|
| +
|
| + return res;
|
| }
|
|
|
| bool Pkcs11::InitializeGLaptop(const std::string& test_cert) {
|
| LOG(INFO) << "Initializing pkcs11 with opencryptoki, no ssl engine.";
|
|
|
| - slot_handler_.reset(new Pkcs11SlotHandlerGLaptop());
|
| - slot_handler_->Initialize();
|
| + bool res = Initialize();
|
| +
|
| + Pkcs11SlotHandlerGLaptop* slot_handler =
|
| + new Pkcs11SlotHandlerGLaptop();
|
| + slot_handler_.reset(slot_handler);
|
| + slot_handler->Initialize();
|
| + slot_handler->ReadObjectsFromSlot(this);
|
|
|
| Pkcs11CertificateHandlerOpenSsl* cert_handler =
|
| new Pkcs11CertificateHandlerOpenSsl();
|
| @@ -1642,12 +1781,16 @@ bool Pkcs11::InitializeGLaptop(const std::string& test_cert) {
|
| cert_handler->SetOutputDER();
|
| certificate_handler_.reset(cert_handler);
|
|
|
| - return Initialize();
|
| + SetupHandlers();
|
| +
|
| + return res;
|
| }
|
|
|
| bool Pkcs11::InitializeOpenSSL(const std::string& test_cert) {
|
| LOG(INFO) << "Initializing pkcs11 with openssl.";
|
|
|
| + bool res = Initialize();
|
| +
|
| slot_handler_.reset(new Pkcs11SlotHandlerInMemory());
|
| slot_handler_->Initialize();
|
|
|
| @@ -1657,11 +1800,15 @@ bool Pkcs11::InitializeOpenSSL(const std::string& test_cert) {
|
| cert_handler->SetTestCertificate(test_cert);
|
| certificate_handler_.reset(cert_handler);
|
|
|
| - return Initialize();
|
| + SetupHandlers();
|
| +
|
| + return res;
|
| }
|
|
|
| bool Pkcs11::InitializeLocalFiles(const std::string& csr,
|
| const std::string& cert) {
|
| + bool res = Initialize();
|
| +
|
| slot_handler_.reset(new Pkcs11SlotHandlerInMemory());
|
| slot_handler_->Initialize();
|
|
|
| @@ -1669,7 +1816,22 @@ bool Pkcs11::InitializeLocalFiles(const std::string& csr,
|
| new Pkcs11CertificateHandlerLocalFile(csr, cert));
|
| certificate_handler_->Initialize();
|
|
|
| - return Initialize();
|
| + SetupHandlers();
|
| +
|
| + return res;
|
| +}
|
| +
|
| +// pkcs11[slot_object->label()] = slot_object->obj()
|
| +bool Pkcs11::AddJSSlotObject(const SlotObject* slot_object) {
|
| + v8::Local<v8::Value> slotsvalue = obj()->Get(v8::String::NewSymbol("slots"));
|
| + if (slotsvalue.IsEmpty() || !slotsvalue->IsObject()) {
|
| + LOG(ERROR) << "'slots' is not an object in pkcs11";
|
| + return false;
|
| + }
|
| + v8::Local<v8::Object> slots = v8::Local<v8::Object>::Cast(slotsvalue);
|
| + v8::Local<v8::String> v8label = v8::String::New(slot_object->label().c_str());
|
| + slots->Set(v8label, slot_object->obj());
|
| + return true;
|
| }
|
|
|
| static v8::Handle<v8::Value> dispatch_setUserPin(
|
|
|