blob: 9c8e5edf1ca48e9d2fc372df9399d61745bce0c7 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.h"
6
7#include <cstdint>
8
9#include "third_party/boringssl/src/include/openssl/curve25519.h"
10#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
11#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
12#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
13
14namespace quic {
15namespace {
16
17class Curve25519KeyExchangeFactory : public KeyExchange::Factory {
18 public:
19 Curve25519KeyExchangeFactory() = default;
20 ~Curve25519KeyExchangeFactory() override = default;
21
22 std::unique_ptr<KeyExchange> Create(QuicRandom* rand) const override {
vasilvvc48c8712019-03-11 13:38:16 -070023 const std::string private_value =
24 Curve25519KeyExchange::NewPrivateKey(rand);
QUICHE teama6ef0a62019-03-07 20:34:33 -050025 return Curve25519KeyExchange::New(private_value);
26 }
27
28 QuicTag tag() const override { return kC255; }
29};
30
31} // namespace
32
33Curve25519KeyExchange::Curve25519KeyExchange() {}
34
35Curve25519KeyExchange::~Curve25519KeyExchange() {}
36
37// static
38std::unique_ptr<Curve25519KeyExchange> Curve25519KeyExchange::New(
39 QuicStringPiece private_key) {
40 // We don't want to #include the BoringSSL headers in the public header file,
41 // so we use literals for the sizes of private_key_ and public_key_. Here we
42 // assert that those values are equal to the values from the BoringSSL
43 // header.
44 static_assert(
45 sizeof(Curve25519KeyExchange::private_key_) == X25519_PRIVATE_KEY_LEN,
46 "header out of sync");
47 static_assert(
48 sizeof(Curve25519KeyExchange::public_key_) == X25519_PUBLIC_VALUE_LEN,
49 "header out of sync");
50
51 if (private_key.size() != X25519_PRIVATE_KEY_LEN) {
52 return nullptr;
53 }
54
55 auto ka = QuicWrapUnique(new Curve25519KeyExchange);
56 memcpy(ka->private_key_, private_key.data(), X25519_PRIVATE_KEY_LEN);
57 X25519_public_from_private(ka->public_key_, ka->private_key_);
58 return ka;
59}
60
61// static
vasilvvc48c8712019-03-11 13:38:16 -070062std::string Curve25519KeyExchange::NewPrivateKey(QuicRandom* rand) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050063 uint8_t private_key[X25519_PRIVATE_KEY_LEN];
64 rand->RandBytes(private_key, sizeof(private_key));
vasilvvc48c8712019-03-11 13:38:16 -070065 return std::string(reinterpret_cast<char*>(private_key), sizeof(private_key));
QUICHE teama6ef0a62019-03-07 20:34:33 -050066}
67
68const Curve25519KeyExchange::Factory& Curve25519KeyExchange::GetFactory()
69 const {
70 static const Factory* factory = new Curve25519KeyExchangeFactory;
71 return *factory;
72}
73
74bool Curve25519KeyExchange::CalculateSharedKey(
75 QuicStringPiece peer_public_value,
vasilvvc48c8712019-03-11 13:38:16 -070076 std::string* out_result) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -050077 if (peer_public_value.size() != X25519_PUBLIC_VALUE_LEN) {
78 return false;
79 }
80
81 uint8_t result[X25519_PUBLIC_VALUE_LEN];
82 if (!X25519(result, private_key_,
83 reinterpret_cast<const uint8_t*>(peer_public_value.data()))) {
84 return false;
85 }
86
87 out_result->assign(reinterpret_cast<char*>(result), sizeof(result));
88 return true;
89}
90
91void Curve25519KeyExchange::CalculateSharedKey(
92 QuicStringPiece peer_public_value,
vasilvvc48c8712019-03-11 13:38:16 -070093 std::string* shared_key,
QUICHE teama6ef0a62019-03-07 20:34:33 -050094 std::unique_ptr<Callback> callback) const {
95 callback->Run(CalculateSharedKey(peer_public_value, shared_key));
96}
97
98QuicStringPiece Curve25519KeyExchange::public_value() const {
99 return QuicStringPiece(reinterpret_cast<const char*>(public_key_),
100 sizeof(public_key_));
101}
102
103} // namespace quic