12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/crypto/curve25519_key_exchange.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/basictypes.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "crypto/curve25519.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/crypto/quic_random.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::StringPiece; 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using std::string; 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace net { 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 17b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)Curve25519KeyExchange::Curve25519KeyExchange() {} 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)Curve25519KeyExchange::~Curve25519KeyExchange() {} 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Curve25519KeyExchange* Curve25519KeyExchange::New( 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const StringPiece& private_key) { 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Curve25519KeyExchange* ka; 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We don't want to #include the NaCl headers in the public header file, so 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // we use literals for the sizes of private_key_ and public_key_. Here we 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // assert that those values are equal to the values from the NaCl header. 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) COMPILE_ASSERT( 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sizeof(ka->private_key_) == crypto::curve25519::kScalarBytes, 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) header_out_of_sync); 31b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) COMPILE_ASSERT(sizeof(ka->public_key_) == crypto::curve25519::kBytes, 32b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) header_out_of_sync); 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (private_key.size() != crypto::curve25519::kScalarBytes) { 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ka = new Curve25519KeyExchange(); 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(ka->private_key_, private_key.data(), 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) crypto::curve25519::kScalarBytes); 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) crypto::curve25519::ScalarBaseMult(ka->private_key_, ka->public_key_); 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ka; 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)string Curve25519KeyExchange::NewPrivateKey(QuicRandom* rand) { 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8 private_key[crypto::curve25519::kScalarBytes]; 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rand->RandBytes(private_key, sizeof(private_key)); 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This makes |private_key| a valid scalar, as specified on 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // http://cr.yp.to/ecdh.html 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private_key[0] &= 248; 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private_key[31] &= 127; 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private_key[31] |= 64; 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return string(reinterpret_cast<char*>(private_key), sizeof(private_key)); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 58b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)KeyExchange* Curve25519KeyExchange::NewKeyPair(QuicRandom* rand) const { 59b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const string private_value = NewPrivateKey(rand); 60b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return Curve25519KeyExchange::New(private_value); 61b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 62b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Curve25519KeyExchange::CalculateSharedKey( 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const StringPiece& peer_public_value, 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) string* out_result) const { 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (peer_public_value.size() != crypto::curve25519::kBytes) { 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8 result[crypto::curve25519::kBytes]; 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) crypto::curve25519::ScalarMult( 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private_key_, 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reinterpret_cast<const uint8*>(peer_public_value.data()), 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result); 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) out_result->assign(reinterpret_cast<char*>(result), sizeof(result)); 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)StringPiece Curve25519KeyExchange::public_value() const { 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return StringPiece(reinterpret_cast<const char*>(public_key_), 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sizeof(public_key_)); 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 85b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)QuicTag Curve25519KeyExchange::tag() const { return kC255; } 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace net 88