Skip to content

Commit

Permalink
Give keys friendly names in NSS and OS X
Browse files Browse the repository at this point in the history
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
  • Loading branch information
davidben@chromium.org committed Aug 19, 2010
1 parent d2586b5 commit 6f9ebd9
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 12 deletions.
5 changes: 3 additions & 2 deletions chrome/browser/renderer_host/resource_message_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand All @@ -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,
Expand Down
1 change: 1 addition & 0 deletions chrome/browser/renderer_host/resource_message_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
16 changes: 12 additions & 4 deletions net/base/keygen_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

#include <string>

#include "googleurl/src/gurl.h"

namespace net {

// This class handles keypair generation for generating client
Expand All @@ -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 <keygen>.
Expand All @@ -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) {
}

Expand Down
31 changes: 29 additions & 2 deletions net/base/keygen_handler_mac.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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[];
Expand Down Expand Up @@ -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,
Expand All @@ -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<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.
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;

Expand Down Expand Up @@ -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)
Expand All @@ -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;
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion net/base/keygen_handler_nss.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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_);
}

Expand Down
5 changes: 3 additions & 2 deletions net/base/keygen_handler_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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();
Expand Down
17 changes: 16 additions & 1 deletion net/third_party/mozilla_security_manager/nsKeygenHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@
#include <keyhi.h> // 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 {

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.

Expand Down
4 changes: 4 additions & 0 deletions net/third_party/mozilla_security_manager/nsKeygenHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@

#include <string>

class GURL;

namespace mozilla_security_manager {

#define DEFAULT_RSA_KEYGEN_PE 65537L
Expand All @@ -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
Expand Down

0 comments on commit 6f9ebd9

Please sign in to comment.