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