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

Unified Diff: pkcs11.cc

Issue 2523001: Implemented ReadObjectsFromSlot() to populate pkcs11.slots on initialization. (Closed) Base URL: ssh://git@chromiumos-git/entd.git
Patch Set: Small change from feedback Created 10 years, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkcs11.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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(
« no previous file with comments | « pkcs11.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698