diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc index 797ed3cae533e5..b6bf8547834e35 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 16e329b88e360b..6f47917c03d5a6 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 3f3a1151c3d300..5ca6027ba2c316 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 c2c63d7c4d5763..f5097a372628d2 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 638fbd54854fc2..215244c7e56af2 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 9f6902e55c0a61..85fd0bc68d0bae 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 ffef66d7f7e66f..99d52061f0200e 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 75703bbdf8130f..ae1f5a3e047e11 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