This source file includes following definitions.
- StringPieceToVector
- New
- NewPrivateKey
- NewKeyPair
- CalculateSharedKey
- public_value
- tag
#include "net/quic/crypto/p256_key_exchange.h"
#include "base/logging.h"
#include "base/sys_byteorder.h"
using base::StringPiece;
using std::string;
using std::vector;
namespace net {
namespace {
const char kExportPassword[] = "";
static vector<uint8> StringPieceToVector(StringPiece piece) {
return vector<uint8>(piece.data(), piece.data() + piece.length());
}
}
P256KeyExchange::P256KeyExchange(crypto::ECPrivateKey* key_pair,
const uint8* public_key)
: key_pair_(key_pair) {
memcpy(public_key_, public_key, sizeof(public_key_));
}
P256KeyExchange::~P256KeyExchange() {
}
P256KeyExchange* P256KeyExchange::New(StringPiece key) {
if (key.size() < 2) {
DVLOG(1) << "Key pair is too small.";
return NULL;
}
const uint8* data = reinterpret_cast<const uint8*>(key.data());
size_t size = static_cast<size_t>(data[0]) |
(static_cast<size_t>(data[1]) << 8);
key.remove_prefix(2);
if (key.size() < size) {
DVLOG(1) << "Key pair does not contain key material.";
return NULL;
}
StringPiece private_piece(key.data(), size);
key.remove_prefix(size);
if (key.empty()) {
DVLOG(1) << "Key pair does not contain public key.";
return NULL;
}
StringPiece public_piece(key);
scoped_ptr<crypto::ECPrivateKey> key_pair(
crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
kExportPassword,
StringPieceToVector(private_piece),
StringPieceToVector(public_piece)));
if (!key_pair.get()) {
DVLOG(1) << "Can't decrypt private key.";
return NULL;
}
SECKEYPublicKey* public_key = key_pair->public_key();
if (public_key->keyType != ecKey ||
public_key->u.ec.publicValue.len != kUncompressedP256PointBytes ||
!public_key->u.ec.publicValue.data ||
public_key->u.ec.publicValue.data[0] != kUncompressedECPointForm) {
DVLOG(1) << "Key is invalid.";
return NULL;
}
const SECOidData* oid_data = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1);
if (!oid_data) {
DVLOG(1) << "Can't get P-256's OID.";
return NULL;
}
if (public_key->u.ec.DEREncodedParams.len != oid_data->oid.len + 2 ||
!public_key->u.ec.DEREncodedParams.data ||
public_key->u.ec.DEREncodedParams.data[0] != SEC_ASN1_OBJECT_ID ||
public_key->u.ec.DEREncodedParams.data[1] != oid_data->oid.len ||
memcmp(public_key->u.ec.DEREncodedParams.data + 2,
oid_data->oid.data, oid_data->oid.len) != 0) {
DVLOG(1) << "Key is invalid.";
}
return new P256KeyExchange(key_pair.release(),
public_key->u.ec.publicValue.data);
}
string P256KeyExchange::NewPrivateKey() {
scoped_ptr<crypto::ECPrivateKey> key_pair(crypto::ECPrivateKey::Create());
if (!key_pair.get()) {
DVLOG(1) << "Can't generate new key pair.";
return string();
}
vector<uint8> private_key;
if (!key_pair->ExportEncryptedPrivateKey(kExportPassword,
1 ,
&private_key)) {
DVLOG(1) << "Can't export private key.";
return string();
}
vector<uint8> public_key;
if (!key_pair->ExportPublicKey(&public_key)) {
DVLOG(1) << "Can't export public key.";
return string();
}
uint16 private_key_size = private_key.size();
const size_t result_size = sizeof(private_key_size) +
private_key_size +
public_key.size();
vector<char> result(result_size);
char* resultp = &result[0];
private_key_size = base::ByteSwapToLE16(private_key_size);
memcpy(resultp, &private_key_size, sizeof(private_key_size));
resultp += sizeof(private_key_size);
memcpy(resultp, &private_key[0], private_key.size());
resultp += private_key.size();
memcpy(resultp, &public_key[0], public_key.size());
return string(&result[0], result_size);
}
KeyExchange* P256KeyExchange::NewKeyPair(QuicRandom* ) const {
const string private_value = NewPrivateKey();
return P256KeyExchange::New(private_value);
}
bool P256KeyExchange::CalculateSharedKey(const StringPiece& peer_public_value,
string* out_result) const {
if (peer_public_value.size() != kUncompressedP256PointBytes ||
peer_public_value[0] != kUncompressedECPointForm) {
DVLOG(1) << "Peer public value is invalid.";
return false;
}
DCHECK(key_pair_.get());
DCHECK(key_pair_->public_key());
SECKEYPublicKey peer_public_key;
memset(&peer_public_key, 0, sizeof(peer_public_key));
peer_public_key.keyType = ecKey;
peer_public_key.u.ec.DEREncodedParams.len =
key_pair_->public_key()->u.ec.DEREncodedParams.len;
peer_public_key.u.ec.DEREncodedParams.data =
key_pair_->public_key()->u.ec.DEREncodedParams.data;
peer_public_key.u.ec.publicValue.type = siBuffer;
peer_public_key.u.ec.publicValue.data =
reinterpret_cast<uint8*>(const_cast<char*>(peer_public_value.data()));
peer_public_key.u.ec.publicValue.len = peer_public_value.size();
crypto::ScopedPK11SymKey premaster_secret(
PK11_PubDeriveWithKDF(
key_pair_->key(),
&peer_public_key,
PR_FALSE,
NULL,
NULL,
CKM_ECDH1_DERIVE,
CKM_GENERIC_SECRET_KEY_GEN,
CKA_DERIVE,
0,
CKD_NULL,
NULL,
NULL));
if (!premaster_secret.get()) {
DVLOG(1) << "Can't derive ECDH shared key.";
return false;
}
if (PK11_ExtractKeyValue(premaster_secret.get()) != SECSuccess) {
DVLOG(1) << "Can't extract raw ECDH shared key.";
return false;
}
SECItem* key_data = PK11_GetKeyData(premaster_secret.get());
if (!key_data || !key_data->data || key_data->len != kP256FieldBytes) {
DVLOG(1) << "ECDH shared key is invalid.";
return false;
}
out_result->assign(reinterpret_cast<char*>(key_data->data), key_data->len);
return true;
}
StringPiece P256KeyExchange::public_value() const {
return StringPiece(reinterpret_cast<const char*>(public_key_),
sizeof(public_key_));
}
QuicTag P256KeyExchange::tag() const { return kP256; }
}