Commit 6f9ebd9f authored by davidben@chromium.org's avatar davidben@chromium.org

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
parent d2586b55
...@@ -1558,7 +1558,7 @@ void ResourceMessageFilter::OnKeygen(uint32 key_size_index, ...@@ -1558,7 +1558,7 @@ void ResourceMessageFilter::OnKeygen(uint32 key_size_index,
FROM_HERE, FROM_HERE,
NewRunnableMethod( NewRunnableMethod(
this, &ResourceMessageFilter::OnKeygenOnWorkerThread, this, &ResourceMessageFilter::OnKeygenOnWorkerThread,
key_size_in_bits, challenge_string, reply_msg), key_size_in_bits, challenge_string, url, reply_msg),
true)) { true)) {
NOTREACHED() << "Failed to dispatch keygen task to worker pool"; NOTREACHED() << "Failed to dispatch keygen task to worker pool";
ViewHostMsg_Keygen::WriteReplyParams(reply_msg, std::string()); ViewHostMsg_Keygen::WriteReplyParams(reply_msg, std::string());
...@@ -1570,13 +1570,14 @@ void ResourceMessageFilter::OnKeygen(uint32 key_size_index, ...@@ -1570,13 +1570,14 @@ void ResourceMessageFilter::OnKeygen(uint32 key_size_index,
void ResourceMessageFilter::OnKeygenOnWorkerThread( void ResourceMessageFilter::OnKeygenOnWorkerThread(
int key_size_in_bits, int key_size_in_bits,
const std::string& challenge_string, const std::string& challenge_string,
const GURL& url,
IPC::Message* reply_msg) { IPC::Message* reply_msg) {
DCHECK(reply_msg); DCHECK(reply_msg);
// Verify we are on a worker thread. // Verify we are on a worker thread.
DCHECK(!MessageLoop::current()); DCHECK(!MessageLoop::current());
// Generate a signed public key and challenge, then send it back. // 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( ViewHostMsg_Keygen::WriteReplyParams(
reply_msg, reply_msg,
......
...@@ -359,6 +359,7 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, ...@@ -359,6 +359,7 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
void OnKeygenOnWorkerThread( void OnKeygenOnWorkerThread(
int key_size_in_bits, int key_size_in_bits,
const std::string& challenge_string, const std::string& challenge_string,
const GURL& url,
IPC::Message* reply_msg); IPC::Message* reply_msg);
void OnGetExtensionMessageBundle(const std::string& extension_id, void OnGetExtensionMessageBundle(const std::string& extension_id,
IPC::Message* reply_msg); IPC::Message* reply_msg);
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include <string> #include <string>
#include "googleurl/src/gurl.h"
namespace net { namespace net {
// This class handles keypair generation for generating client // This class handles keypair generation for generating client
...@@ -17,9 +19,12 @@ namespace net { ...@@ -17,9 +19,12 @@ namespace net {
class KeygenHandler { class KeygenHandler {
public: public:
// Creates a handler that will generate a key with the given key size // Creates a handler that will generate a key with the given key size and
// and incorporate the |challenge| into the Netscape SPKAC structure. // incorporate the |challenge| into the Netscape SPKAC structure. The request
inline KeygenHandler(int key_size_in_bits, const std::string& challenge); // 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 // Actually generates the key-pair and the cert request (SPKAC), and returns
// a base64-encoded string suitable for use as the form value of <keygen>. // a base64-encoded string suitable for use as the form value of <keygen>.
...@@ -31,13 +36,16 @@ class KeygenHandler { ...@@ -31,13 +36,16 @@ class KeygenHandler {
private: private:
int key_size_in_bits_; // key size in bits (usually 2048) int key_size_in_bits_; // key size in bits (usually 2048)
std::string challenge_; // challenge string sent by server 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? bool stores_key_; // should the generated key-pair be stored persistently?
}; };
KeygenHandler::KeygenHandler(int key_size_in_bits, 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), : key_size_in_bits_(key_size_in_bits),
challenge_(challenge), challenge_(challenge),
url_(url),
stores_key_(true) { stores_key_(true) {
} }
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#include "base/lock.h" #include "base/lock.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/scoped_cftyperef.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. // These are in Security.framework but not declared in a public header.
extern const SecAsn1Template kSecAsn1AlgorithmIDTemplate[]; extern const SecAsn1Template kSecAsn1AlgorithmIDTemplate[];
...@@ -89,6 +91,7 @@ static const SecAsn1Template kSignedPublicKeyAndChallengeTemplate[] = { ...@@ -89,6 +91,7 @@ static const SecAsn1Template kSignedPublicKeyAndChallengeTemplate[] = {
static OSStatus CreateRSAKeyPair(int size_in_bits, static OSStatus CreateRSAKeyPair(int size_in_bits,
SecAccessRef initial_access,
SecKeyRef* out_pub_key, SecKeyRef* out_pub_key,
SecKeyRef* out_priv_key); SecKeyRef* out_priv_key);
static OSStatus SignData(CSSM_DATA data, static OSStatus SignData(CSSM_DATA data,
...@@ -98,14 +101,31 @@ static OSStatus SignData(CSSM_DATA data, ...@@ -98,14 +101,31 @@ static OSStatus SignData(CSSM_DATA data,
std::string KeygenHandler::GenKeyAndSignChallenge() { std::string KeygenHandler::GenKeyAndSignChallenge() {
std::string result; std::string result;
OSStatus err; OSStatus err;
SecAccessRef initial_access = NULL;
SecKeyRef public_key = NULL; SecKeyRef public_key = NULL;
SecKeyRef private_key = NULL; SecKeyRef private_key = NULL;
SecAsn1CoderRef coder = NULL; SecAsn1CoderRef coder = NULL;
CSSM_DATA signature = {0, 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<CFStringRef> 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. // 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) if (err)
goto failure; goto failure;
...@@ -188,6 +208,8 @@ std::string KeygenHandler::GenKeyAndSignChallenge() { ...@@ -188,6 +208,8 @@ std::string KeygenHandler::GenKeyAndSignChallenge() {
free(signature.Data); free(signature.Data);
if (coder) if (coder)
SecAsn1CoderRelease(coder); SecAsn1CoderRelease(coder);
if (initial_access)
CFRelease(initial_access);
if (public_key) if (public_key)
CFRelease(public_key); CFRelease(public_key);
if (private_key) if (private_key)
...@@ -196,7 +218,12 @@ std::string KeygenHandler::GenKeyAndSignChallenge() { ...@@ -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, static OSStatus CreateRSAKeyPair(int size_in_bits,
SecAccessRef initial_access,
SecKeyRef* out_pub_key, SecKeyRef* out_pub_key,
SecKeyRef* out_priv_key) { SecKeyRef* out_priv_key) {
OSStatus err; OSStatus err;
...@@ -221,7 +248,7 @@ static OSStatus CreateRSAKeyPair(int size_in_bits, ...@@ -221,7 +248,7 @@ static OSStatus CreateRSAKeyPair(int size_in_bits,
CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_SIGN | CSSM_KEYUSE_UNWRAP, CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_SIGN | CSSM_KEYUSE_UNWRAP,
CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT |
CSSM_KEYATTR_SENSITIVE, CSSM_KEYATTR_SENSITIVE,
NULL, initial_access,
out_pub_key, out_priv_key); out_pub_key, out_priv_key);
} }
if (err) if (err)
......
...@@ -12,7 +12,7 @@ namespace psm = mozilla_security_manager; ...@@ -12,7 +12,7 @@ namespace psm = mozilla_security_manager;
namespace net { namespace net {
std::string KeygenHandler::GenKeyAndSignChallenge() { std::string KeygenHandler::GenKeyAndSignChallenge() {
return psm::GenKeyAndSignChallenge(key_size_in_bits_, challenge_, return psm::GenKeyAndSignChallenge(key_size_in_bits_, challenge_, url_,
stores_key_); stores_key_);
} }
......
...@@ -73,7 +73,7 @@ void AssertValidSignedPublicKeyAndChallenge(const std::string& result, ...@@ -73,7 +73,7 @@ void AssertValidSignedPublicKeyAndChallenge(const std::string& result,
} }
TEST_F(KeygenHandlerTest, SmokeTest) { 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 handler.set_stores_key(false); // Don't leave the key-pair behind
std::string result = handler.GenKeyAndSignChallenge(); std::string result = handler.GenKeyAndSignChallenge();
LOG(INFO) << "KeygenHandler produced: " << result; LOG(INFO) << "KeygenHandler produced: " << result;
...@@ -90,7 +90,8 @@ class ConcurrencyTestTask : public Task { ...@@ -90,7 +90,8 @@ class ConcurrencyTestTask : public Task {
} }
virtual void Run() { 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. handler.set_stores_key(false); // Don't leave the key-pair behind.
*result_ = handler.GenKeyAndSignChallenge(); *result_ = handler.GenKeyAndSignChallenge();
event_->Signal(); event_->Signal();
......
...@@ -48,9 +48,11 @@ ...@@ -48,9 +48,11 @@
#include <keyhi.h> // SECKEY_CreateSubjectPublicKeyInfo() #include <keyhi.h> // SECKEY_CreateSubjectPublicKeyInfo()
#include "base/base64.h" #include "base/base64.h"
#include "base/logging.h"
#include "base/nss_util_internal.h" #include "base/nss_util_internal.h"
#include "base/nss_util.h" #include "base/nss_util.h"
#include "base/logging.h" #include "base/string_util.h"
#include "googleurl/src/gurl.h"
namespace { namespace {
...@@ -94,6 +96,7 @@ namespace mozilla_security_manager { ...@@ -94,6 +96,7 @@ namespace mozilla_security_manager {
// in mozilla/security/manager/ssl/src/nsKeygenHandler.cpp. // in mozilla/security/manager/ssl/src/nsKeygenHandler.cpp.
std::string GenKeyAndSignChallenge(int key_size_in_bits, std::string GenKeyAndSignChallenge(int key_size_in_bits,
const std::string& challenge, const std::string& challenge,
const GURL& url,
bool stores_key) { bool stores_key) {
// Key pair generation mechanism - only RSA is supported at present. // Key pair generation mechanism - only RSA is supported at present.
PRUint32 keyGenMechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; // from nss/pkcs11t.h PRUint32 keyGenMechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; // from nss/pkcs11t.h
...@@ -171,6 +174,18 @@ std::string GenKeyAndSignChallenge(int key_size_in_bits, ...@@ -171,6 +174,18 @@ std::string GenKeyAndSignChallenge(int key_size_in_bits,
goto failure; 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 // The CA expects the signed public key in a specific format
// Let's create that now. // Let's create that now.
......
...@@ -42,6 +42,8 @@ ...@@ -42,6 +42,8 @@
#include <string> #include <string>
class GURL;
namespace mozilla_security_manager { namespace mozilla_security_manager {
#define DEFAULT_RSA_KEYGEN_PE 65537L #define DEFAULT_RSA_KEYGEN_PE 65537L
...@@ -52,9 +54,11 @@ namespace mozilla_security_manager { ...@@ -52,9 +54,11 @@ namespace mozilla_security_manager {
// Parameters: // Parameters:
// key_size_in_bits: key size in bits (usually 2048) // key_size_in_bits: key size in bits (usually 2048)
// challenge: challenge string sent by server // challenge: challenge string sent by server
// url: the URL which requested the SPKAC
// stores_key: should the generated key pair be stored persistently? // stores_key: should the generated key pair be stored persistently?
std::string GenKeyAndSignChallenge(int key_size_in_bits, std::string GenKeyAndSignChallenge(int key_size_in_bits,
const std::string& challenge, const std::string& challenge,
const GURL& url,
bool stores_key); bool stores_key);
} // namespace mozilla_security_manager } // namespace mozilla_security_manager
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment