smp_cmac.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. /******************************************************************************
  2. *
  3. * Copyright (C) 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. * This file contains the implementation of the AES128 CMAC algorithm.
  21. *
  22. ******************************************************************************/
  23. #include "common/bt_target.h"
  24. #include "osi/allocator.h"
  25. #if SMP_INCLUDED == TRUE
  26. // #include <stdio.h>
  27. #include <string.h>
  28. #include "stack/btm_ble_api.h"
  29. #include "smp_int.h"
  30. #include "stack/hcimsgs.h"
  31. typedef struct {
  32. UINT8 *text;
  33. UINT16 len;
  34. UINT16 round;
  35. } tCMAC_CB;
  36. tCMAC_CB cmac_cb;
  37. /* Rb for AES-128 as block cipher, LSB as [0] */
  38. const BT_OCTET16 const_Rb = {
  39. 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  40. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  41. };
  42. void print128(BT_OCTET16 x, const UINT8 *key_name)
  43. {
  44. #if SMP_DEBUG == TRUE && SMP_DEBUG_VERBOSE == TRUE
  45. UINT8 *p = (UINT8 *)x;
  46. UINT8 i;
  47. SMP_TRACE_WARNING("%s(MSB ~ LSB) = ", key_name);
  48. for (i = 0; i < 4; i ++) {
  49. SMP_TRACE_WARNING("%02x %02x %02x %02x",
  50. p[BT_OCTET16_LEN - i * 4 - 1], p[BT_OCTET16_LEN - i * 4 - 2],
  51. p[BT_OCTET16_LEN - i * 4 - 3], p[BT_OCTET16_LEN - i * 4 - 4]);
  52. }
  53. #endif
  54. }
  55. /*******************************************************************************
  56. **
  57. ** Function padding
  58. **
  59. ** Description utility function to padding the given text to be a 128 bits
  60. ** data. The parameter dest is input and output parameter, it
  61. ** must point to a BT_OCTET16_LEN memory space; where include
  62. ** length bytes valid data.
  63. **
  64. ** Returns void
  65. **
  66. *******************************************************************************/
  67. static void padding ( BT_OCTET16 dest, UINT8 length )
  68. {
  69. UINT8 i, *p = dest;
  70. /* original last block */
  71. for ( i = length ; i < BT_OCTET16_LEN; i++ ) {
  72. p[BT_OCTET16_LEN - i - 1] = ( i == length ) ? 0x80 : 0;
  73. }
  74. }
  75. /*******************************************************************************
  76. **
  77. ** Function leftshift_onebit
  78. **
  79. ** Description utility function to left shift one bit for a 128 bits value.
  80. **
  81. ** Returns void
  82. **
  83. *******************************************************************************/
  84. static void leftshift_onebit(UINT8 *input, UINT8 *output)
  85. {
  86. UINT8 i, overflow = 0 , next_overflow = 0;
  87. SMP_TRACE_EVENT ("leftshift_onebit ");
  88. /* input[0] is LSB */
  89. for ( i = 0; i < BT_OCTET16_LEN ; i ++ ) {
  90. next_overflow = (input[i] & 0x80) ? 1 : 0;
  91. output[i] = (input[i] << 1) | overflow;
  92. overflow = next_overflow;
  93. }
  94. return;
  95. }
  96. /*******************************************************************************
  97. **
  98. ** Function cmac_aes_cleanup
  99. **
  100. ** Description clean up function for AES_CMAC algorithm.
  101. **
  102. ** Returns void
  103. **
  104. *******************************************************************************/
  105. static void cmac_aes_cleanup(void)
  106. {
  107. if (cmac_cb.text != NULL) {
  108. osi_free(cmac_cb.text);
  109. }
  110. memset(&cmac_cb, 0, sizeof(tCMAC_CB));
  111. }
  112. /*******************************************************************************
  113. **
  114. ** Function cmac_aes_k_calculate
  115. **
  116. ** Description This function is the calculation of block cipher using AES-128.
  117. **
  118. ** Returns void
  119. **
  120. *******************************************************************************/
  121. static BOOLEAN cmac_aes_k_calculate(BT_OCTET16 key, UINT8 *p_signature, UINT16 tlen)
  122. {
  123. tSMP_ENC output;
  124. UINT8 i = 1, err = 0;
  125. UINT8 x[16] = {0};
  126. UINT8 *p_mac;
  127. SMP_TRACE_EVENT ("cmac_aes_k_calculate ");
  128. while (i <= cmac_cb.round) {
  129. smp_xor_128(&cmac_cb.text[(cmac_cb.round - i)*BT_OCTET16_LEN], x); /* Mi' := Mi (+) X */
  130. if (!SMP_Encrypt(key, BT_OCTET16_LEN, &cmac_cb.text[(cmac_cb.round - i)*BT_OCTET16_LEN], BT_OCTET16_LEN, &output)) {
  131. err = 1;
  132. break;
  133. }
  134. memcpy(x, output.param_buf, BT_OCTET16_LEN);
  135. i ++;
  136. }
  137. if (!err) {
  138. p_mac = output.param_buf + (BT_OCTET16_LEN - tlen);
  139. memcpy(p_signature, p_mac, tlen);
  140. SMP_TRACE_DEBUG("tlen = %d p_mac = %p", tlen, p_mac);
  141. SMP_TRACE_DEBUG("p_mac[0] = 0x%02x p_mac[1] = 0x%02x p_mac[2] = 0x%02x p_mac[3] = 0x%02x",
  142. *p_mac, *(p_mac + 1), *(p_mac + 2), *(p_mac + 3));
  143. SMP_TRACE_DEBUG("p_mac[4] = 0x%02x p_mac[5] = 0x%02x p_mac[6] = 0x%02x p_mac[7] = 0x%02x",
  144. *(p_mac + 4), *(p_mac + 5), *(p_mac + 6), *(p_mac + 7));
  145. return TRUE;
  146. } else {
  147. return FALSE;
  148. }
  149. }
  150. /*******************************************************************************
  151. **
  152. ** Function cmac_prepare_last_block
  153. **
  154. ** Description This function proceeed to prepare the last block of message
  155. ** Mn depending on the size of the message.
  156. **
  157. ** Returns void
  158. **
  159. *******************************************************************************/
  160. static void cmac_prepare_last_block (BT_OCTET16 k1, BT_OCTET16 k2)
  161. {
  162. // UINT8 x[16] = {0};
  163. BOOLEAN flag;
  164. SMP_TRACE_EVENT ("cmac_prepare_last_block ");
  165. /* last block is a complete block set flag to 1 */
  166. flag = ((cmac_cb.len % BT_OCTET16_LEN) == 0 && cmac_cb.len != 0) ? TRUE : FALSE;
  167. SMP_TRACE_DEBUG("flag = %d round = %d", flag, cmac_cb.round);
  168. if ( flag ) {
  169. /* last block is complete block */
  170. smp_xor_128(&cmac_cb.text[0], k1);
  171. } else { /* padding then xor with k2 */
  172. padding(&cmac_cb.text[0], (UINT8)(cmac_cb.len % 16));
  173. smp_xor_128(&cmac_cb.text[0], k2);
  174. }
  175. }
  176. /*******************************************************************************
  177. **
  178. ** Function cmac_subkey_cont
  179. **
  180. ** Description This is the callback function when CIPHk(0[128]) is completed.
  181. **
  182. ** Returns void
  183. **
  184. *******************************************************************************/
  185. static void cmac_subkey_cont(tSMP_ENC *p)
  186. {
  187. UINT8 k1[BT_OCTET16_LEN], k2[BT_OCTET16_LEN];
  188. UINT8 *pp = p->param_buf;
  189. SMP_TRACE_EVENT ("cmac_subkey_cont ");
  190. print128(pp, (const UINT8 *)"K1 before shift");
  191. /* If MSB(L) = 0, then K1 = L << 1 */
  192. if ( (pp[BT_OCTET16_LEN - 1] & 0x80) != 0 ) {
  193. /* Else K1 = ( L << 1 ) (+) Rb */
  194. leftshift_onebit(pp, k1);
  195. smp_xor_128(k1, const_Rb);
  196. } else {
  197. leftshift_onebit(pp, k1);
  198. }
  199. if ( (k1[BT_OCTET16_LEN - 1] & 0x80) != 0 ) {
  200. /* K2 = (K1 << 1) (+) Rb */
  201. leftshift_onebit(k1, k2);
  202. smp_xor_128(k2, const_Rb);
  203. } else {
  204. /* If MSB(K1) = 0, then K2 = K1 << 1 */
  205. leftshift_onebit(k1, k2);
  206. }
  207. print128(k1, (const UINT8 *)"K1");
  208. print128(k2, (const UINT8 *)"K2");
  209. cmac_prepare_last_block (k1, k2);
  210. }
  211. /*******************************************************************************
  212. **
  213. ** Function cmac_generate_subkey
  214. **
  215. ** Description This is the function to generate the two subkeys.
  216. **
  217. ** Parameters key - CMAC key, expect SRK when used by SMP.
  218. **
  219. ** Returns void
  220. **
  221. *******************************************************************************/
  222. static BOOLEAN cmac_generate_subkey(BT_OCTET16 key)
  223. {
  224. BT_OCTET16 z = {0};
  225. BOOLEAN ret = TRUE;
  226. tSMP_ENC output;
  227. SMP_TRACE_EVENT (" cmac_generate_subkey");
  228. if (SMP_Encrypt(key, BT_OCTET16_LEN, z, BT_OCTET16_LEN, &output)) {
  229. cmac_subkey_cont(&output);;
  230. } else {
  231. ret = FALSE;
  232. }
  233. return ret;
  234. }
  235. /*******************************************************************************
  236. **
  237. ** Function aes_cipher_msg_auth_code
  238. **
  239. ** Description This is the AES-CMAC Generation Function with tlen implemented.
  240. **
  241. ** Parameters key - CMAC key in little endian order, expect SRK when used by SMP.
  242. ** input - text to be signed in little endian byte order.
  243. ** length - length of the input in byte.
  244. ** tlen - lenth of mac desired
  245. ** p_signature - data pointer to where signed data to be stored, tlen long.
  246. **
  247. ** Returns FALSE if out of resources, TRUE in other cases.
  248. **
  249. *******************************************************************************/
  250. BOOLEAN aes_cipher_msg_auth_code(BT_OCTET16 key, UINT8 *input, UINT16 length,
  251. UINT16 tlen, UINT8 *p_signature)
  252. {
  253. UINT16 len, diff;
  254. UINT16 n = (length + BT_OCTET16_LEN - 1) / BT_OCTET16_LEN; /* n is number of rounds */
  255. BOOLEAN ret = FALSE;
  256. SMP_TRACE_EVENT ("%s", __func__);
  257. if (n == 0) {
  258. n = 1;
  259. }
  260. len = n * BT_OCTET16_LEN;
  261. SMP_TRACE_DEBUG("AES128_CMAC started, allocate buffer size = %d", len);
  262. /* allocate a memory space of multiple of 16 bytes to hold text */
  263. if ((cmac_cb.text = (UINT8 *)osi_malloc(len)) != NULL) {
  264. cmac_cb.round = n;
  265. memset(cmac_cb.text, 0, len);
  266. diff = len - length;
  267. if (input != NULL && length > 0) {
  268. memcpy(&cmac_cb.text[diff] , input, (int)length);
  269. cmac_cb.len = length;
  270. } else {
  271. cmac_cb.len = 0;
  272. }
  273. /* prepare calculation for subkey s and last block of data */
  274. if (cmac_generate_subkey(key)) {
  275. /* start calculation */
  276. ret = cmac_aes_k_calculate(key, p_signature, tlen);
  277. }
  278. /* clean up */
  279. cmac_aes_cleanup();
  280. } else {
  281. ret = FALSE;
  282. SMP_TRACE_ERROR("No resources");
  283. }
  284. return ret;
  285. }
  286. #if 0 /* testing code, sample data from spec */
  287. void test_cmac_cback(UINT8 *p_mac, UINT16 tlen)
  288. {
  289. SMP_TRACE_EVENT ("test_cmac_cback ");
  290. SMP_TRACE_ERROR("test_cmac_cback");
  291. }
  292. void test_cmac(void)
  293. {
  294. SMP_TRACE_EVENT ("test_cmac ");
  295. UINT8 M[64] = {
  296. 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
  297. 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
  298. 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
  299. 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
  300. 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
  301. 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
  302. 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
  303. 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
  304. };
  305. UINT8 key[16] = {
  306. 0x3c, 0x4f, 0xcf, 0x09, 0x88, 0x15, 0xf7, 0xab,
  307. 0xa6, 0xd2, 0xae, 0x28, 0x16, 0x15, 0x7e, 0x2b
  308. };
  309. UINT8 i = 0, tmp;
  310. UINT16 len;
  311. len = 64;
  312. for (i = 0; i < len / 2; i ++) {
  313. tmp = M[i];
  314. M[i] = M[len - 1 - i];
  315. M[len - 1 - i] = tmp;
  316. }
  317. memset(&cmac_cb, 0, sizeof(tCMAC_CB));
  318. SMP_TRACE_WARNING("\n Example 1: len = %d\n", len);
  319. aes_cipher_msg_auth_code(key, M, len, 128, test_cmac_cback, 0);
  320. }
  321. #endif
  322. #endif