• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 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 #include <openssl/aes.h>
16 
17 // Including just to make sure we don't get build failures due to -Werror
18 #include <openssl/base.h>
19 #include <openssl/bn.h>
20 #include <openssl/cmac.h>
21 #include <openssl/ec.h>
22 #include <openssl/ecdh.h>
23 #include <openssl/nid.h>
24 
25 #include <array>
26 #include <cstdint>
27 #include <cstring>
28 
29 #include "pw_bytes/endian.h"
30 #include "pw_unit_test/framework.h"
31 
32 namespace {
33 
34 // Reusing code from the `pw_bluetooth_sapphire` project to exercise
35 // `boringssl` integration.
36 constexpr uint32_t k24BitMax = 0xFFFFFF;
37 constexpr size_t kUInt128Size = 16;
38 using UInt128 = std::array<uint8_t, kUInt128Size>;
39 
Swap128(const UInt128 & in,UInt128 * out)40 void Swap128(const UInt128& in, UInt128* out) {
41   for (size_t i = 0; i < in.size(); ++i) {
42     (*out)[i] = in[in.size() - i - 1];
43   }
44 }
45 
TEST(Boringssl,UseAes)46 TEST(Boringssl, UseAes) {
47   // This just tests that building against boringssl, including headers, and
48   // using functions works when depending on the `pw_third_party.boringssl`
49   // module.
50   alignas(16) const UInt128 irk{{0x9B,
51                                  0x7D,
52                                  0x39,
53                                  0x0A,
54                                  0xA6,
55                                  0x10,
56                                  0x10,
57                                  0x34,
58                                  0x05,
59                                  0xAD,
60                                  0xC8,
61                                  0x57,
62                                  0xA3,
63                                  0x34,
64                                  0x02,
65                                  0xEC}};
66   const uint32_t prand = 0x708194;
67   const uint32_t kExpected = 0x0DFBAA;
68 
69   // Ah()
70   // r' = padding || r.
71   alignas(16) UInt128 r_prime;
72   r_prime.fill(0);
73   *reinterpret_cast<uint32_t*>(r_prime.data()) =
74       pw::bytes::ConvertOrderTo(pw::endian::little, prand & k24BitMax);
75 
76   // Encrypt()
77   alignas(16) UInt128 hash128;
78   const UInt128& key = irk;
79   const UInt128& plaintext_data = r_prime;
80   UInt128* out_encrypted_data = &hash128;
81 
82   alignas(16) UInt128 be_k;
83   alignas(16) UInt128 be_pt;
84   alignas(16) UInt128 be_enc;
85   Swap128(key, &be_k);
86   Swap128(plaintext_data, &be_pt);
87 
88   AES_KEY k;
89   AES_set_encrypt_key(be_k.data(), 128, &k);
90   AES_encrypt(be_pt.data(), be_enc.data(), &k);
91 
92   Swap128(be_enc, out_encrypted_data);
93 
94   auto ah =
95       pw::bytes::ConvertOrderFrom(
96           pw::endian::little, *reinterpret_cast<uint32_t*>(hash128.data())) &
97       k24BitMax;
98   EXPECT_EQ(kExpected, ah);
99 }
100 }  // namespace
101