1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #pragma once
16 #include <openssl/base.h>
17 
18 #include <cstdint>
19 #include <optional>
20 
21 #include "pw_bluetooth_sapphire/internal/host/common/uint256.h"
22 #include "pw_bluetooth_sapphire/internal/host/sm/smp.h"
23 
24 namespace bt::sm {
25 
26 // Class exposing operations on ECDH keys needed for Secure Connections pairing.
27 // The only valid operation on a moved-from EcdhKey is to reassign it to an
28 // existing key.
29 class EcdhKey {
30  public:
31   // Returns a new public key on the P-256 Elliptic Curve parsed from a peer
32   // public key, or std::nullopt if the peer key is not a valid point on the
33   // curve.
34   static std::optional<EcdhKey> ParseFromPublicKey(
35       sm::PairingPublicKeyParams pub_key);
36 
37   EcdhKey(EcdhKey&& other) noexcept;
38   EcdhKey& operator=(EcdhKey&& other) noexcept;
39   virtual ~EcdhKey();
40 
41   // Returns a representation of the public key for SMP (Vol. 3 Part H
42   // Section 3.5.6).
43   sm::PairingPublicKeyParams GetSerializedPublicKey() const;
44 
45   // Returns the X/Y value of the public key as std::array wrappers for e.g.
46   // comparisons, crypto.
47   UInt256 GetPublicKeyX() const;
48   UInt256 GetPublicKeyY() const;
49 
boringssl_key()50   const EC_KEY* boringssl_key() const { return key_; }
51 
52  protected:
53   EcdhKey();
54 
mut_boringssl_key()55   EC_KEY* mut_boringssl_key() { return key_; }
set_boringssl_key(EC_KEY * k)56   void set_boringssl_key(EC_KEY* k) { key_ = k; }
57 
58  private:
59   EC_KEY* key_;
60   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(EcdhKey);
61 };
62 
63 // Specialization of EcdhKey used to ensure that when calculating the shared DH
64 // Key between two EcdhKeys, at least one has a private key.
65 class LocalEcdhKey : public EcdhKey {
66  public:
67   // Returns a new random public-private key pair on the P-256 Elliptic Curve
68   // used for DH Key exchange in Secure Connections, or std::nullopt if
69   // allocation fails.
70   static std::optional<LocalEcdhKey> Create();
71 
72   LocalEcdhKey(LocalEcdhKey&& other) noexcept;
73   LocalEcdhKey& operator=(LocalEcdhKey&& other) noexcept;
74 
75   // Returns a 256-bit DHKey calculated from our private key and the peer public
76   // key.
77   UInt256 CalculateDhKey(const EcdhKey& peer_public_key) const;
78 
79   // Used to verify correct DHKey calculation with known, non-random private and
80   // public keys.
81   void SetPrivateKeyForTesting(const UInt256& private_key);
82 
83  private:
84   LocalEcdhKey();
85   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(LocalEcdhKey);
86 };
87 
88 }  // namespace bt::sm
89