1 /******************************************************************************
2  *
3  *  Copyright 2019 The Android Open Source Project
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 #include "security/ecdh_keys.h"
20 
21 /**********************************************************************************************************************
22  TODO: We should have random number management in separate file, and we
23        should honour all the random number requirements from the spec!!
24 **********************************************************************************************************************/
25 #include <string.h>
26 
27 #include <cstdlib>
28 #include <ctime>
29 
30 #include "security/ecc/p_256_ecc_pp.h"
31 
32 namespace {
33 
34 static bool srand_initiated = false;
35 
36 template <size_t SIZE>
GenerateRandom()37 static std::array<uint8_t, SIZE> GenerateRandom() {
38   if (!srand_initiated) {
39     srand_initiated = true;
40     // TODO:  We need a proper  random number generator here.
41     // use current time as seed for random generator
42     std::srand(std::time(nullptr));
43   }
44 
45   std::array<uint8_t, SIZE> r;
46   for (size_t i = 0; i < SIZE; i++) r[i] = std::rand();
47   return r;
48 }
49 }  // namespace
50 /*********************************************************************************************************************/
51 
52 namespace bluetooth {
53 namespace security {
54 
GenerateECDHKeyPair()55 std::pair<std::array<uint8_t, 32>, EcdhPublicKey> GenerateECDHKeyPair() {
56   std::array<uint8_t, 32> private_key = GenerateRandom<32>();
57   std::array<uint8_t, 32> private_key_copy = private_key;
58   ecc::Point public_key;
59 
60   ECC_PointMult(&public_key, &(ecc::curve_p256.G), (uint32_t*)private_key_copy.data());
61 
62   EcdhPublicKey pk;
63   memcpy(pk.x.data(), public_key.x, 32);
64   memcpy(pk.y.data(), public_key.y, 32);
65 
66   /* private_key, public key pair */
67   return std::make_pair<std::array<uint8_t, 32>, EcdhPublicKey>(std::move(private_key), std::move(pk));
68 }
69 
ValidateECDHPoint(EcdhPublicKey pk)70 bool ValidateECDHPoint(EcdhPublicKey pk) {
71   ecc::Point public_key;
72   memcpy(public_key.x, pk.x.data(), 32);
73   memcpy(public_key.y, pk.y.data(), 32);
74   memset(public_key.z, 0, 32);
75   return ECC_ValidatePoint(public_key);
76 }
77 
ComputeDHKey(std::array<uint8_t,32> my_private_key,EcdhPublicKey remote_public_key)78 std::array<uint8_t, 32> ComputeDHKey(std::array<uint8_t, 32> my_private_key, EcdhPublicKey remote_public_key) {
79   ecc::Point peer_publ_key, new_publ_key;
80   uint32_t private_key[8];
81   memcpy(private_key, my_private_key.data(), 32);
82   memcpy(peer_publ_key.x, remote_public_key.x.data(), 32);
83   memcpy(peer_publ_key.y, remote_public_key.y.data(), 32);
84   memset(peer_publ_key.z, 0, 32);
85   peer_publ_key.z[0] = 1;
86 
87   ECC_PointMult(&new_publ_key, &peer_publ_key, (uint32_t*)private_key);
88 
89   std::array<uint8_t, 32> dhkey;
90   memcpy(dhkey.data(), new_publ_key.x, 32);
91   return dhkey;
92 }
93 
94 }  // namespace security
95 }  // namespace bluetooth
96