// Copyright (c) 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "net/quic/crypto/curve25519_key_exchange.h" #include "base/basictypes.h" #include "base/logging.h" #include "crypto/curve25519.h" #include "net/quic/crypto/quic_random.h" using base::StringPiece; using std::string; namespace net { Curve25519KeyExchange::Curve25519KeyExchange() {} Curve25519KeyExchange::~Curve25519KeyExchange() {} // static Curve25519KeyExchange* Curve25519KeyExchange::New( const StringPiece& private_key) { Curve25519KeyExchange* ka; // We don't want to #include the NaCl headers in the public header file, so // we use literals for the sizes of private_key_ and public_key_. Here we // assert that those values are equal to the values from the NaCl header. COMPILE_ASSERT( sizeof(ka->private_key_) == crypto::curve25519::kScalarBytes, header_out_of_sync); COMPILE_ASSERT(sizeof(ka->public_key_) == crypto::curve25519::kBytes, header_out_of_sync); if (private_key.size() != crypto::curve25519::kScalarBytes) { return NULL; } ka = new Curve25519KeyExchange(); memcpy(ka->private_key_, private_key.data(), crypto::curve25519::kScalarBytes); crypto::curve25519::ScalarBaseMult(ka->private_key_, ka->public_key_); return ka; } // static string Curve25519KeyExchange::NewPrivateKey(QuicRandom* rand) { uint8 private_key[crypto::curve25519::kScalarBytes]; rand->RandBytes(private_key, sizeof(private_key)); // This makes |private_key| a valid scalar, as specified on // http://cr.yp.to/ecdh.html private_key[0] &= 248; private_key[31] &= 127; private_key[31] |= 64; return string(reinterpret_cast<char*>(private_key), sizeof(private_key)); } KeyExchange* Curve25519KeyExchange::NewKeyPair(QuicRandom* rand) const { const string private_value = NewPrivateKey(rand); return Curve25519KeyExchange::New(private_value); } bool Curve25519KeyExchange::CalculateSharedKey( const StringPiece& peer_public_value, string* out_result) const { if (peer_public_value.size() != crypto::curve25519::kBytes) { return false; } uint8 result[crypto::curve25519::kBytes]; crypto::curve25519::ScalarMult( private_key_, reinterpret_cast<const uint8*>(peer_public_value.data()), result); out_result->assign(reinterpret_cast<char*>(result), sizeof(result)); return true; } StringPiece Curve25519KeyExchange::public_value() const { return StringPiece(reinterpret_cast<const char*>(public_key_), sizeof(public_key_)); } QuicTag Curve25519KeyExchange::tag() const { return kC255; } } // namespace net