1// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "net/quic/crypto/curve25519_key_exchange.h" 6 7#include "base/basictypes.h" 8#include "base/logging.h" 9#include "crypto/curve25519.h" 10#include "net/quic/crypto/quic_random.h" 11 12using base::StringPiece; 13using std::string; 14 15namespace net { 16 17Curve25519KeyExchange::Curve25519KeyExchange() {} 18 19Curve25519KeyExchange::~Curve25519KeyExchange() {} 20 21// static 22Curve25519KeyExchange* Curve25519KeyExchange::New( 23 const StringPiece& private_key) { 24 Curve25519KeyExchange* ka; 25 // We don't want to #include the NaCl headers in the public header file, so 26 // we use literals for the sizes of private_key_ and public_key_. Here we 27 // assert that those values are equal to the values from the NaCl header. 28 COMPILE_ASSERT( 29 sizeof(ka->private_key_) == crypto::curve25519::kScalarBytes, 30 header_out_of_sync); 31 COMPILE_ASSERT(sizeof(ka->public_key_) == crypto::curve25519::kBytes, 32 header_out_of_sync); 33 34 if (private_key.size() != crypto::curve25519::kScalarBytes) { 35 return NULL; 36 } 37 38 ka = new Curve25519KeyExchange(); 39 memcpy(ka->private_key_, private_key.data(), 40 crypto::curve25519::kScalarBytes); 41 crypto::curve25519::ScalarBaseMult(ka->private_key_, ka->public_key_); 42 return ka; 43} 44 45// static 46string Curve25519KeyExchange::NewPrivateKey(QuicRandom* rand) { 47 uint8 private_key[crypto::curve25519::kScalarBytes]; 48 rand->RandBytes(private_key, sizeof(private_key)); 49 50 // This makes |private_key| a valid scalar, as specified on 51 // http://cr.yp.to/ecdh.html 52 private_key[0] &= 248; 53 private_key[31] &= 127; 54 private_key[31] |= 64; 55 return string(reinterpret_cast<char*>(private_key), sizeof(private_key)); 56} 57 58KeyExchange* Curve25519KeyExchange::NewKeyPair(QuicRandom* rand) const { 59 const string private_value = NewPrivateKey(rand); 60 return Curve25519KeyExchange::New(private_value); 61} 62 63bool Curve25519KeyExchange::CalculateSharedKey( 64 const StringPiece& peer_public_value, 65 string* out_result) const { 66 if (peer_public_value.size() != crypto::curve25519::kBytes) { 67 return false; 68 } 69 70 uint8 result[crypto::curve25519::kBytes]; 71 crypto::curve25519::ScalarMult( 72 private_key_, 73 reinterpret_cast<const uint8*>(peer_public_value.data()), 74 result); 75 out_result->assign(reinterpret_cast<char*>(result), sizeof(result)); 76 77 return true; 78} 79 80StringPiece Curve25519KeyExchange::public_value() const { 81 return StringPiece(reinterpret_cast<const char*>(public_key_), 82 sizeof(public_key_)); 83} 84 85QuicTag Curve25519KeyExchange::tag() const { return kC255; } 86 87} // namespace net 88