From 6f9ebd9f3a6e14139a3e28d9bd415cc250e644d5 Mon Sep 17 00:00:00 2001 From: "davidben@chromium.org" Date: Thu, 19 Aug 2010 23:12:12 +0000 Subject: Give keys friendly names in NSS and OS X This will make them browsing them easier in Keychain Access and certutil. It also gives them a more useful name in Keychain permission dialogs. The friendly name is currently just the hostname which requested the key. It would be nice to have some surrounding text with localization, but this works for now. BUG=none TEST=none Review URL: http://codereview.chromium.org/2806045 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@56774 0039d316-1c4b-4281-b951-d872f2087c98 --- .../renderer_host/resource_message_filter.cc | 5 ++-- .../renderer_host/resource_message_filter.h | 1 + net/base/keygen_handler.h | 16 ++++++++--- net/base/keygen_handler_mac.cc | 31 ++++++++++++++++++++-- net/base/keygen_handler_nss.cc | 2 +- net/base/keygen_handler_unittest.cc | 5 ++-- .../mozilla_security_manager/nsKeygenHandler.cpp | 17 +++++++++++- .../mozilla_security_manager/nsKeygenHandler.h | 4 +++ 8 files changed, 69 insertions(+), 12 deletions(-) diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc index 797ed3c..b6bf854 100644 --- a/chrome/browser/renderer_host/resource_message_filter.cc +++ b/chrome/browser/renderer_host/resource_message_filter.cc @@ -1558,7 +1558,7 @@ void ResourceMessageFilter::OnKeygen(uint32 key_size_index, FROM_HERE, NewRunnableMethod( this, &ResourceMessageFilter::OnKeygenOnWorkerThread, - key_size_in_bits, challenge_string, reply_msg), + key_size_in_bits, challenge_string, url, reply_msg), true)) { NOTREACHED() << "Failed to dispatch keygen task to worker pool"; ViewHostMsg_Keygen::WriteReplyParams(reply_msg, std::string()); @@ -1570,13 +1570,14 @@ void ResourceMessageFilter::OnKeygen(uint32 key_size_index, void ResourceMessageFilter::OnKeygenOnWorkerThread( int key_size_in_bits, const std::string& challenge_string, + const GURL& url, IPC::Message* reply_msg) { DCHECK(reply_msg); // Verify we are on a worker thread. DCHECK(!MessageLoop::current()); // Generate a signed public key and challenge, then send it back. - net::KeygenHandler keygen_handler(key_size_in_bits, challenge_string); + net::KeygenHandler keygen_handler(key_size_in_bits, challenge_string, url); ViewHostMsg_Keygen::WriteReplyParams( reply_msg, diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h index 16e329b..6f47917 100644 --- a/chrome/browser/renderer_host/resource_message_filter.h +++ b/chrome/browser/renderer_host/resource_message_filter.h @@ -359,6 +359,7 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, void OnKeygenOnWorkerThread( int key_size_in_bits, const std::string& challenge_string, + const GURL& url, IPC::Message* reply_msg); void OnGetExtensionMessageBundle(const std::string& extension_id, IPC::Message* reply_msg); diff --git a/net/base/keygen_handler.h b/net/base/keygen_handler.h index 3f3a115..5ca6027 100644 --- a/net/base/keygen_handler.h +++ b/net/base/keygen_handler.h @@ -8,6 +8,8 @@ #include +#include "googleurl/src/gurl.h" + namespace net { // This class handles keypair generation for generating client @@ -17,9 +19,12 @@ namespace net { class KeygenHandler { public: - // Creates a handler that will generate a key with the given key size - // and incorporate the |challenge| into the Netscape SPKAC structure. - inline KeygenHandler(int key_size_in_bits, const std::string& challenge); + // Creates a handler that will generate a key with the given key size and + // incorporate the |challenge| into the Netscape SPKAC structure. The request + // for the key originated from |url|. + inline KeygenHandler(int key_size_in_bits, + const std::string& challenge, + const GURL& url); // Actually generates the key-pair and the cert request (SPKAC), and returns // a base64-encoded string suitable for use as the form value of . @@ -31,13 +36,16 @@ class KeygenHandler { private: int key_size_in_bits_; // key size in bits (usually 2048) std::string challenge_; // challenge string sent by server + GURL url_; // the URL that requested the key bool stores_key_; // should the generated key-pair be stored persistently? }; KeygenHandler::KeygenHandler(int key_size_in_bits, - const std::string& challenge) + const std::string& challenge, + const GURL& url) : key_size_in_bits_(key_size_in_bits), challenge_(challenge), + url_(url), stores_key_(true) { } diff --git a/net/base/keygen_handler_mac.cc b/net/base/keygen_handler_mac.cc index c2c63d7..f5097a3 100644 --- a/net/base/keygen_handler_mac.cc +++ b/net/base/keygen_handler_mac.cc @@ -13,6 +13,8 @@ #include "base/lock.h" #include "base/logging.h" #include "base/scoped_cftyperef.h" +#include "base/string_util.h" +#include "base/sys_string_conversions.h" // These are in Security.framework but not declared in a public header. extern const SecAsn1Template kSecAsn1AlgorithmIDTemplate[]; @@ -89,6 +91,7 @@ static const SecAsn1Template kSignedPublicKeyAndChallengeTemplate[] = { static OSStatus CreateRSAKeyPair(int size_in_bits, + SecAccessRef initial_access, SecKeyRef* out_pub_key, SecKeyRef* out_priv_key); static OSStatus SignData(CSSM_DATA data, @@ -98,14 +101,31 @@ static OSStatus SignData(CSSM_DATA data, std::string KeygenHandler::GenKeyAndSignChallenge() { std::string result; OSStatus err; + SecAccessRef initial_access = NULL; SecKeyRef public_key = NULL; SecKeyRef private_key = NULL; SecAsn1CoderRef coder = NULL; CSSM_DATA signature = {0, NULL}; { + if (url_.has_host()) { + // TODO(davidben): Use something like "Key generated for + // example.com", but localize it. + scoped_cftyperef label( + base::SysUTF8ToCFStringRef(url_.host())); + // Create an initial access object to set the SecAccessRef. This + // sets a label on the Keychain dialogs. Pass NULL as the second + // argument to use the default trusted list; only allow the + // current application to access without user confirmation. + err = SecAccessCreate(label, NULL, &initial_access); + // If we fail, just continue without a label. + if (err) + base::LogCSSMError("SecAccessCreate", err); + } + // Create the key-pair. - err = CreateRSAKeyPair(key_size_in_bits_, &public_key, &private_key); + err = CreateRSAKeyPair(key_size_in_bits_, initial_access, + &public_key, &private_key); if (err) goto failure; @@ -188,6 +208,8 @@ std::string KeygenHandler::GenKeyAndSignChallenge() { free(signature.Data); if (coder) SecAsn1CoderRelease(coder); + if (initial_access) + CFRelease(initial_access); if (public_key) CFRelease(public_key); if (private_key) @@ -196,7 +218,12 @@ std::string KeygenHandler::GenKeyAndSignChallenge() { } +// Create an RSA key pair with size |size_in_bits|. |initial_access| +// is passed as the initial access control list in Keychain. The +// public and private keys are placed in |out_pub_key| and +// |out_priv_key|, respectively. static OSStatus CreateRSAKeyPair(int size_in_bits, + SecAccessRef initial_access, SecKeyRef* out_pub_key, SecKeyRef* out_priv_key) { OSStatus err; @@ -221,7 +248,7 @@ static OSStatus CreateRSAKeyPair(int size_in_bits, CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_SIGN | CSSM_KEYUSE_UNWRAP, CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_SENSITIVE, - NULL, + initial_access, out_pub_key, out_priv_key); } if (err) diff --git a/net/base/keygen_handler_nss.cc b/net/base/keygen_handler_nss.cc index 638fbd5..215244c 100644 --- a/net/base/keygen_handler_nss.cc +++ b/net/base/keygen_handler_nss.cc @@ -12,7 +12,7 @@ namespace psm = mozilla_security_manager; namespace net { std::string KeygenHandler::GenKeyAndSignChallenge() { - return psm::GenKeyAndSignChallenge(key_size_in_bits_, challenge_, + return psm::GenKeyAndSignChallenge(key_size_in_bits_, challenge_, url_, stores_key_); } diff --git a/net/base/keygen_handler_unittest.cc b/net/base/keygen_handler_unittest.cc index 9f6902e..85fd0bc 100644 --- a/net/base/keygen_handler_unittest.cc +++ b/net/base/keygen_handler_unittest.cc @@ -73,7 +73,7 @@ void AssertValidSignedPublicKeyAndChallenge(const std::string& result, } TEST_F(KeygenHandlerTest, SmokeTest) { - KeygenHandler handler(768, "some challenge"); + KeygenHandler handler(768, "some challenge", GURL("http://www.example.com")); handler.set_stores_key(false); // Don't leave the key-pair behind std::string result = handler.GenKeyAndSignChallenge(); LOG(INFO) << "KeygenHandler produced: " << result; @@ -90,7 +90,8 @@ class ConcurrencyTestTask : public Task { } virtual void Run() { - KeygenHandler handler(768, "some challenge"); + KeygenHandler handler(768, "some challenge", + GURL("http://www.example.com")); handler.set_stores_key(false); // Don't leave the key-pair behind. *result_ = handler.GenKeyAndSignChallenge(); event_->Signal(); diff --git a/net/third_party/mozilla_security_manager/nsKeygenHandler.cpp b/net/third_party/mozilla_security_manager/nsKeygenHandler.cpp index ffef66d..99d5206 100644 --- a/net/third_party/mozilla_security_manager/nsKeygenHandler.cpp +++ b/net/third_party/mozilla_security_manager/nsKeygenHandler.cpp @@ -48,9 +48,11 @@ #include // SECKEY_CreateSubjectPublicKeyInfo() #include "base/base64.h" +#include "base/logging.h" #include "base/nss_util_internal.h" #include "base/nss_util.h" -#include "base/logging.h" +#include "base/string_util.h" +#include "googleurl/src/gurl.h" namespace { @@ -94,6 +96,7 @@ namespace mozilla_security_manager { // in mozilla/security/manager/ssl/src/nsKeygenHandler.cpp. std::string GenKeyAndSignChallenge(int key_size_in_bits, const std::string& challenge, + const GURL& url, bool stores_key) { // Key pair generation mechanism - only RSA is supported at present. PRUint32 keyGenMechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; // from nss/pkcs11t.h @@ -171,6 +174,18 @@ std::string GenKeyAndSignChallenge(int key_size_in_bits, goto failure; } + // Set friendly names for the keys. + if (url.has_host()) { + // TODO(davidben): Use something like "Key generated for + // example.com", but localize it. + const std::string& label = url.host(); + { + base::AutoNSSWriteLock lock; + PK11_SetPublicKeyNickname(publicKey, label.c_str()); + PK11_SetPrivateKeyNickname(privateKey, label.c_str()); + } + } + // The CA expects the signed public key in a specific format // Let's create that now. diff --git a/net/third_party/mozilla_security_manager/nsKeygenHandler.h b/net/third_party/mozilla_security_manager/nsKeygenHandler.h index 75703bb..ae1f5a3 100644 --- a/net/third_party/mozilla_security_manager/nsKeygenHandler.h +++ b/net/third_party/mozilla_security_manager/nsKeygenHandler.h @@ -42,6 +42,8 @@ #include +class GURL; + namespace mozilla_security_manager { #define DEFAULT_RSA_KEYGEN_PE 65537L @@ -52,9 +54,11 @@ namespace mozilla_security_manager { // Parameters: // key_size_in_bits: key size in bits (usually 2048) // challenge: challenge string sent by server +// url: the URL which requested the SPKAC // stores_key: should the generated key pair be stored persistently? std::string GenKeyAndSignChallenge(int key_size_in_bits, const std::string& challenge, + const GURL& url, bool stores_key); } // namespace mozilla_security_manager -- cgit v1.1