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