1 /******************************************************************************
2 *
3 * Copyright 2008-2012 Broadcom Corporation
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 /******************************************************************************
20 *
21 * This file contains the implementation of the AES128 and AES CMAC algorithm.
22 *
23 ******************************************************************************/
24
25 #include <bluetooth/log.h>
26
27 #include <algorithm>
28 #include <cstdint>
29
30 #include "aes.h"
31 #include "crypto_toolbox.h"
32 #include "hci/octets.h"
33
34 using bluetooth::hci::kOctet16Length;
35 using bluetooth::hci::Octet16;
36
37 namespace crypto_toolbox {
38
39 namespace {
40
41 typedef struct {
42 uint8_t* text;
43 uint16_t len;
44 uint16_t round;
45 } tCMAC_CB;
46
47 thread_local tCMAC_CB cmac_cb;
48
49 /* Rb for AES-128 as block cipher, LSB as [0] */
50 Octet16 const_Rb{0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
52
53 /** utility function to do an biteise exclusive-OR of two bit strings of the
54 * length of kOctet16Length. Result is stored in first argument.
55 */
xor_128(Octet16 * a,const Octet16 & b)56 static void xor_128(Octet16* a, const Octet16& b) {
57 uint8_t i, *aa = a->data();
58 const uint8_t* bb = b.data();
59
60 for (i = 0; i < kOctet16Length; i++) {
61 aa[i] = aa[i] ^ bb[i];
62 }
63 }
64 } // namespace
65
66 /* This function computes AES_128(key, message) */
aes_128(const Octet16 & key,const Octet16 & message)67 Octet16 aes_128(const Octet16& key, const Octet16& message) {
68 Octet16 key_reversed;
69 Octet16 message_reversed;
70 Octet16 output;
71
72 std::reverse_copy(key.begin(), key.end(), key_reversed.begin());
73 std::reverse_copy(message.begin(), message.end(), message_reversed.begin());
74
75 aes_context ctx;
76 aes_set_key(key_reversed.data(), key_reversed.size(), &ctx);
77 aes_encrypt(message_reversed.data(), output.data(), &ctx);
78
79 std::reverse(output.begin(), output.end());
80 return output;
81 }
82
83 /** utility function to padding the given text to be a 128 bits data. The
84 * parameter dest is input and output parameter, it must point to a
85 * kOctet16Length memory space; where include length bytes valid data. */
padding(Octet16 * dest,uint8_t length)86 static void padding(Octet16* dest, uint8_t length) {
87 uint8_t i, *p = dest->data();
88 /* original last block */
89 for (i = length; i < kOctet16Length; i++) {
90 p[kOctet16Length - i - 1] = (i == length) ? 0x80 : 0;
91 }
92 }
93
94 /** utility function to left shift one bit for a 128 bits value. */
leftshift_onebit(uint8_t * input,uint8_t * output)95 static void leftshift_onebit(uint8_t* input, uint8_t* output) {
96 uint8_t i, overflow = 0, next_overflow = 0;
97 /* input[0] is LSB */
98 for (i = 0; i < kOctet16Length; i++) {
99 next_overflow = (input[i] & 0x80) ? 1 : 0;
100 output[i] = (input[i] << 1) | overflow;
101 overflow = next_overflow;
102 }
103 return;
104 }
105
106 /** This function is the calculation of block cipher using AES-128. */
cmac_aes_k_calculate(const Octet16 & key)107 static Octet16 cmac_aes_k_calculate(const Octet16& key) {
108 Octet16 output;
109 Octet16 x{0}; // zero initialized
110
111 uint16_t i = 1;
112 while (i <= cmac_cb.round) {
113 /* Mi' := Mi (+) X */
114 xor_128((Octet16*)&cmac_cb.text[(cmac_cb.round - i) * kOctet16Length], x);
115
116 output = aes_128(key, *(Octet16*)&cmac_cb.text[(cmac_cb.round - i) * kOctet16Length]);
117 x = output;
118 i++;
119 }
120
121 return output;
122 }
123
124 /** This function proceeed to prepare the last block of message Mn depending on
125 * the size of the message.
126 */
cmac_prepare_last_block(const Octet16 & k1,const Octet16 & k2)127 static void cmac_prepare_last_block(const Octet16& k1, const Octet16& k2) {
128 // uint8_t x[16] = {0};
129 bool flag;
130
131 /* last block is a complete block set flag to 1 */
132 flag = ((cmac_cb.len % kOctet16Length) == 0 && cmac_cb.len != 0) ? true : false;
133
134 if (flag) { /* last block is complete block */
135 xor_128((Octet16*)&cmac_cb.text[0], k1);
136 } else /* padding then xor with k2 */
137 {
138 padding((Octet16*)&cmac_cb.text[0], (uint8_t)(cmac_cb.len % 16));
139
140 xor_128((Octet16*)&cmac_cb.text[0], k2);
141 }
142 }
143
144 /** This is the function to generate the two subkeys.
145 * |key| is CMAC key, expect SRK when used by SMP.
146 */
cmac_generate_subkey(const Octet16 & key)147 static void cmac_generate_subkey(const Octet16& key) {
148 Octet16 zero{};
149 Octet16 p = aes_128(key, zero);
150
151 Octet16 k1, k2;
152 uint8_t* pp = p.data();
153
154 /* If MSB(L) = 0, then K1 = L << 1 */
155 if ((pp[kOctet16Length - 1] & 0x80) != 0) {
156 /* Else K1 = ( L << 1 ) (+) Rb */
157 leftshift_onebit(pp, k1.data());
158 xor_128(&k1, const_Rb);
159 } else {
160 leftshift_onebit(pp, k1.data());
161 }
162
163 if ((k1[kOctet16Length - 1] & 0x80) != 0) {
164 /* K2 = (K1 << 1) (+) Rb */
165 leftshift_onebit(k1.data(), k2.data());
166 xor_128(&k2, const_Rb);
167 } else {
168 /* If MSB(K1) = 0, then K2 = K1 << 1 */
169 leftshift_onebit(k1.data(), k2.data());
170 }
171
172 cmac_prepare_last_block(k1, k2);
173 }
174
175 /** key - CMAC key in little endian order
176 * input - text to be signed in little endian byte order.
177 * length - length of the input in byte.
178 */
aes_cmac(const Octet16 & key,const uint8_t * input,uint16_t length)179 Octet16 aes_cmac(const Octet16& key, const uint8_t* input, uint16_t length) {
180 uint32_t len;
181 uint16_t diff;
182 /* n is number of rounds */
183 uint16_t n = (length + kOctet16Length - 1) / kOctet16Length;
184
185 if (n == 0) {
186 n = 1;
187 }
188 len = n * kOctet16Length;
189
190 // log::verbose("AES128_CMAC started, allocate buffer size={}", len);
191
192 /* allocate a memory space of multiple of 16 bytes to hold text */
193 cmac_cb.text = (uint8_t*)alloca(len);
194 cmac_cb.round = n;
195 diff = len - length;
196
197 if (input != NULL && length > 0) {
198 memcpy(&cmac_cb.text[diff], input, (int)length);
199 cmac_cb.len = length;
200 } else {
201 cmac_cb.len = 0;
202 }
203
204 /* prepare calculation for subkey s and last block of data */
205 cmac_generate_subkey(key);
206 /* start calculation */
207 Octet16 signature = cmac_aes_k_calculate(key);
208
209 /* clean up */
210 memset(&cmac_cb, 0, sizeof(tCMAC_CB));
211 // cmac_cb.text is auto-freed by alloca
212
213 return signature;
214 }
215
216 } // namespace crypto_toolbox
217