> why don't you look at the source code. We have a smp_c1() in net/bluetooth/smp.c in \ > the kernel (including actual test vectors). And there is also bt_crypto_c1() in \ > src/shared/crypto.c in BlueZ userspace. Shame on me, but static analysis of the kernel code has never been a strong point of mine. So, the only built-in test case for smp_c1() that I found is called test_c1(), and it contains the very case described in the standard. As for userspace tools, I found out that they yield same results as my code (and the former kernel code, apparently): see the attached source file. When the second, real-life test case is commented out, everything is ok. Unfortunately, none of the uses of bt_crypto_c1() explain why calling it with inputs set to legitimate values and exact packet captures does not produce the captured result. Everything seems to comply, and I`m sure that the problem is some insanely subtle detail I fail to understand. > And on a side note, the PDUs from pairing request / response need to fed into c1 as \ > they are received over the air. Meaning you can not mask out bits and then feed it \ > in. That has been clarified in an erratum and especially important for LE Secure \ > Connections (which Linux does support). Exactly as I do, actually. Or do I? Are these request/response packet dumps I got on my capture the ones that have to be put into _pres and _preq variables from the code attached?
#include <stdio.h> #include "src/shared/util.h" #include "src/shared/crypto.h" int main() { uint8_t retn[16] = {}, conf[16] = {}, _mrand[16] = {}; uint8_t _preq[7] = {}, _pres[7] = {}; uint8_t _ia[6] = {}, _ra[6] = {}; uint8_t _iat = 0, _rat = 0; uint32_t _code = 0; /// example from standard: _code = 000000; _iat = 0x01; _rat = 0x00; memcpy(&_ia, "\xA6\xA5\xA4\xA3\xA2\xA1", sizeof(_ia)); /// str2ba("A1:A2:A3:A4:A5:A6", &); memcpy(&_ra, "\xB6\xB5\xB4\xB3\xB2\xB1", sizeof(_ra)); /// str2ba("B1:B2:B3:B4:B5:B6", &); memcpy(&_preq, "\x01\x01\x00\x00\x10\x07\x07", sizeof(_preq)); memcpy(&_pres, "\x02\x03\x00\x00\x08\x00\x05", sizeof(_pres)); memcpy(_mrand, "\xE0\x2E\x70\xC6\x4E\x27\x88\x63\x0E\x6F\xAD\x56\x21\xD5\x83\x57", sizeof(_mrand)); memcpy(conf, "\x86\x3B\xF1\xBE\xC5\x4D\xA7\xD2\xEA\x88\x89\x87\xEF\x3F\x1E\x1E", sizeof(conf)); //* /// real example: _code = 415188; _iat = 0x01; _rat = 0x01; memcpy(&_ia, "\xC4\x30\x19\x3A\x5A\x30", sizeof(_ia)); /// str2ba("30:5A:3A:19:30:C4", &); memcpy(&_ra, "\xB9\x97\x2D\x5B\xC3\xC1", sizeof(_ra)); /// str2ba("C1:C3:5B:2D:97:B9", &); memcpy(&_preq, "\x01\x01\x00\x05\x10\x07\x07", sizeof(_preq)); memcpy(&_pres, "\x02\x02\x00\x05\x10\x06\x03", sizeof(_pres)); memcpy(_mrand, "\xDB\x7A\x48\xD9\xC5\x1F\x76\x43\x9C\xE4\x00\x56\x84\xF4\xE7\x1B", sizeof(_mrand)); memcpy(conf, "\xEF\xDC\x1C\x63\xAF\x8B\x97\x1D\xFC\x35\x1F\x1D\x26\x21\x60\xFC", sizeof(conf)); //*/ uint8_t k[16] = {}; put_le32(_code, k); bt_crypto_c1(bt_crypto_new(), k, _mrand, &_pres, &_preq, _iat, &_ia, _rat, &_ra, retn); util_hexdump('\n', retn, sizeof(retn), printf, 0); util_hexdump('\n', conf, sizeof(conf), printf, 0); printf("\n\n %s!\n", (memcmp(retn, conf, sizeof(retn)))? "FAIL" : "PASS"); return 0; }