test.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889
  1. #include "xinput_auth.h"
  2. #include "xinput_descriptors.h"
  3. #include "config.h"
  4. #include "usb_app_drivers.h"
  5. #include "src/libxsm3/excrypt.h"
  6. #include "src/libxsm3/usbdsec.h"
  7. #include "src/libxsm3/xsm3.h"
  8. #include <algorithm>
  9. #include <cstdio>
  10. #include <cstdlib>
  11. #include <cstring>
  12. #include <vector>
  13. #define CHECK(condition) check(bool(condition), #condition, __LINE__)
  14. static void check(bool condition, const char *expression, int line)
  15. {
  16. if (!condition) {
  17. fprintf(stderr, "%s:%d: %s\n", __FILE__, line, expression);
  18. abort();
  19. }
  20. }
  21. using Bytes = std::vector<uint8_t>;
  22. struct Fixture {
  23. const char *console;
  24. const char *nonce;
  25. const char *identification;
  26. const char *init;
  27. const char *init_response;
  28. const char *verify[3];
  29. const char *verify_response[3];
  30. };
  31. #include "fixtures.h"
  32. static Bytes hex(const char *text)
  33. {
  34. CHECK(strlen(text) % 2 == 0);
  35. Bytes result;
  36. while (*text) {
  37. unsigned byte;
  38. CHECK(sscanf(text, "%2x", &byte) == 1);
  39. result.push_back(byte);
  40. text += 2;
  41. }
  42. return result;
  43. }
  44. static void checksum(Bytes &packet)
  45. {
  46. CHECK(packet.size() == size_t(packet[4]) + 6);
  47. packet.back() = 0;
  48. for (size_t i = 5; i + 1 < packet.size(); i++)
  49. packet.back() ^= packet[i];
  50. }
  51. static void checkPacket(const Bytes &packet, size_t length)
  52. {
  53. CHECK(packet.size() == length);
  54. CHECK(packet[0] == 0x49 && packet[1] == 0x4C);
  55. CHECK(packet[2] == 0 && packet[3] == 0);
  56. Bytes copy = packet;
  57. checksum(copy);
  58. CHECK(copy == packet);
  59. }
  60. static uint32_t lockDepth;
  61. static unsigned notifications, rngCalls, workerStarts;
  62. static bool workerAvailable = true, rngAvailable = true;
  63. static bool resetInRng, replaceInRng;
  64. static uint8_t *ep0;
  65. static uint16_t offered, transferred;
  66. static unsigned transfers;
  67. static const tusb_control_request_t *callbackRequest;
  68. static const Bytes *callbackPayload;
  69. static uint8_t callbackEndpoint;
  70. static xfer_result_t callbackResult;
  71. static uint32_t callbackLength;
  72. static unsigned callbacks;
  73. extern "C" bool __wrap_usbd_control_xfer_cb(uint8_t rhport, uint8_t ep,
  74. xfer_result_t result,
  75. uint32_t length);
  76. extern "C" bool __real_usbd_control_xfer_cb(uint8_t rhport, uint8_t ep,
  77. xfer_result_t result,
  78. uint32_t length)
  79. {
  80. CHECK(rhport == 0 && ep == callbackEndpoint);
  81. CHECK(result == callbackResult && length == callbackLength);
  82. CHECK(xinputAuthReceived(callbackRequest->wLength) ==
  83. (ep == 0 && result == XFER_RESULT_SUCCESS &&
  84. length == callbackRequest->wLength));
  85. callbacks++;
  86. // Model TinyUSB copying only received bytes, never the SETUP wLength.
  87. if (ep == 0 && !callbackPayload->empty()) {
  88. CHECK(ep0 != nullptr);
  89. size_t copied = std::min<size_t>(length, offered);
  90. copied = std::min(copied, callbackPayload->size());
  91. memcpy(ep0, callbackPayload->data(), copied);
  92. }
  93. return xinputClassDriver()->control_xfer_cb(0, CONTROL_STAGE_DATA,
  94. callbackRequest);
  95. }
  96. static bool data(const tusb_control_request_t &req, const Bytes &payload,
  97. uint32_t actual, uint8_t ep = 0,
  98. xfer_result_t result = XFER_RESULT_SUCCESS)
  99. {
  100. CHECK(!xinputAuthReceived(req.wLength));
  101. callbackRequest = &req;
  102. callbackPayload = &payload;
  103. callbackEndpoint = ep;
  104. callbackResult = result;
  105. callbackLength = actual;
  106. unsigned before = callbacks;
  107. bool ok = __wrap_usbd_control_xfer_cb(0, ep, result, actual);
  108. CHECK(callbacks == before + 1);
  109. CHECK(!xinputAuthReceived(req.wLength));
  110. callbackRequest = nullptr;
  111. callbackPayload = nullptr;
  112. return ok;
  113. }
  114. static bool data(const tusb_control_request_t &req, const Bytes &payload = {})
  115. {
  116. bool input = req.bmRequestType & 0x80;
  117. return data(req, payload, input ? transferred : req.wLength,
  118. input ? 0x80 : 0);
  119. }
  120. static tusb_control_request_t request(uint8_t command, uint16_t length,
  121. uint8_t type = 0xC1,
  122. uint16_t index = 0x0103)
  123. {
  124. return { type, command, 0, index, length };
  125. }
  126. bool tud_control_xfer(uint8_t rhport, const tusb_control_request_t *req,
  127. void *buffer, uint16_t length)
  128. {
  129. CHECK(rhport == 0);
  130. CHECK(lockDepth == 0);
  131. CHECK(buffer != nullptr);
  132. CHECK(length <= 46);
  133. ep0 = static_cast<uint8_t *>(buffer);
  134. offered = length;
  135. transferred = std::min(length, req->wLength);
  136. transfers++;
  137. return true;
  138. }
  139. uint32_t xinputAuthLock()
  140. {
  141. return lockDepth++;
  142. }
  143. void xinputAuthUnlock(uint32_t mask)
  144. {
  145. CHECK(lockDepth == mask + 1);
  146. lockDepth = mask;
  147. }
  148. bool xinputAuthStartWorker()
  149. {
  150. workerStarts++;
  151. return workerAvailable;
  152. }
  153. void xinputAuthNotify()
  154. {
  155. CHECK(lockDepth == 0);
  156. notifications++;
  157. }
  158. void xinputAuthBoardSerial(char serial[13])
  159. {
  160. memcpy(serial, "012345ABCDEF", 13);
  161. }
  162. static bool setup(const tusb_control_request_t &req)
  163. {
  164. ep0 = nullptr;
  165. offered = transferred = 0;
  166. unsigned before = transfers;
  167. bool ok = xinputAuthControl(0, CONTROL_STAGE_SETUP, &req);
  168. CHECK(lockDepth == 0);
  169. CHECK(transfers == before + unsigned(ok));
  170. return ok;
  171. }
  172. static void out(uint8_t command, const Bytes &packet, uint16_t index = 0x0103,
  173. uint8_t type = 0x41)
  174. {
  175. auto req = request(command, packet.size(), type, index);
  176. unsigned before = notifications;
  177. CHECK(setup(req));
  178. CHECK(offered == packet.size() && transferred == packet.size());
  179. CHECK(notifications == before);
  180. CHECK(data(req, packet));
  181. CHECK(notifications == before + 1);
  182. CHECK(xinputAuthControl(0, CONTROL_STAGE_ACK, &req));
  183. CHECK(notifications == before + 1);
  184. }
  185. bool xsm3_random_bytes(uint8_t *buffer, size_t length)
  186. {
  187. CHECK(lockDepth == 0);
  188. CHECK(length == 16);
  189. rngCalls++;
  190. for (size_t i = 0; i < length; i++)
  191. buffer[i] = 0x90 + i;
  192. if (resetInRng) {
  193. resetInRng = false;
  194. xinputAuthReset();
  195. }
  196. if (replaceInRng) {
  197. replaceInRng = false;
  198. out(0x82, hex(fixtures[1].init));
  199. }
  200. return rngAvailable;
  201. }
  202. static Bytes in(uint8_t command, uint16_t length = 65535,
  203. uint16_t index = 0x0103, uint8_t type = 0xC1)
  204. {
  205. auto req = request(command, length, type, index);
  206. CHECK(setup(req));
  207. Bytes result(ep0, ep0 + transferred);
  208. unsigned before = transfers;
  209. CHECK(data(req));
  210. CHECK(xinputAuthControl(0, CONTROL_STAGE_ACK, &req));
  211. CHECK(transfers == before);
  212. return result;
  213. }
  214. static void state(uint8_t expected)
  215. {
  216. CHECK(in(0x86) == Bytes({ expected, 0 }));
  217. }
  218. static void noReply()
  219. {
  220. CHECK(!setup(request(0x83, 46)));
  221. }
  222. static void failed()
  223. {
  224. noReply();
  225. CHECK(!setup(request(0x86, 2)));
  226. CHECK(!setup(request(0x87, 22, 0x41)));
  227. xinputAuthProcess();
  228. noReply();
  229. }
  230. /*
  231. * This console uses only primitives, never xsm3_do_challenge_* or its globals.
  232. * Every packet is also compared with the independent OpenSSL/Python fixture,
  233. * so matching bugs in the shared primitives cannot bless a broken exchange.
  234. */
  235. class Console {
  236. public:
  237. const Fixture &fixture;
  238. Bytes nonce, id, key1, key2, controller, hash, salt;
  239. explicit Console(const Fixture &data)
  240. : fixture(data)
  241. , nonce(hex(data.nonce))
  242. , id(hex(data.console))
  243. , key1(16)
  244. , key2(16)
  245. , controller(16)
  246. , hash(20)
  247. , salt(16)
  248. {
  249. uint8_t digest[20], kv1[16], kv2[16];
  250. ExCryptSha(id.data(), id.size(), digest);
  251. auto root1 = hex("828078683a523a9810f40c127066dcba");
  252. auto root2 = hex("66621a78f8609c8a269a04aed85c1ec8");
  253. UsbdSecXSM3AuthenticationCrypt(root1.data(), digest, 16, kv1,
  254. 1);
  255. UsbdSecXSM3AuthenticationCrypt(root2.data(), digest + 4, 16,
  256. kv2, 1);
  257. Bytes swapped(nonce.begin() + 8, nonce.end());
  258. swapped.insert(swapped.end(), nonce.begin(), nonce.begin() + 8);
  259. UsbdSecXSM3AuthenticationCrypt(kv1, nonce.data(), 16,
  260. key1.data(), 1);
  261. UsbdSecXSM3AuthenticationCrypt(kv2, swapped.data(), 16,
  262. key2.data(), 1);
  263. }
  264. Bytes init()
  265. {
  266. Bytes plain = nonce;
  267. plain.insert(plain.end(), id.begin(), id.end());
  268. Bytes packet(34);
  269. packet[0] = 0x49;
  270. packet[1] = 0x4C;
  271. packet[4] = 28;
  272. auto cryptKey = hex("e35bfb1ccdad325bf70e07fd623da7c4");
  273. auto macKey = hex("8f2908380b5bfe687c26462a51f2bc19");
  274. uint8_t mac[8];
  275. UsbdSecXSM3AuthenticationCrypt(cryptKey.data(), plain.data(),
  276. 24, packet.data() + 5, 1);
  277. UsbdSecXSM3AuthenticationMac(macKey.data(), nullptr,
  278. packet.data() + 5, 24, mac);
  279. memcpy(packet.data() + 29, mac + 4, 4);
  280. checksum(packet);
  281. CHECK(packet == hex(fixture.init));
  282. return packet;
  283. }
  284. void acceptInit(const Bytes &response)
  285. {
  286. checkPacket(response, 46);
  287. CHECK(response == hex(fixture.init_response));
  288. uint8_t plain[32];
  289. UsbdSecXSM3AuthenticationCrypt(key1.data(), response.data() + 5,
  290. 32, plain, 0);
  291. CHECK(std::equal(nonce.begin(), nonce.end(), plain + 16));
  292. memcpy(controller.data(), plain, 16);
  293. ExCryptSha(plain, sizeof plain, hash.data());
  294. memcpy(salt.data(), controller.data() + 12, 4);
  295. memcpy(salt.data() + 4, nonce.data() + 12, 4);
  296. }
  297. Bytes verify(unsigned iteration)
  298. {
  299. CHECK(iteration < 3);
  300. for (unsigned i = 0; i < 8; i++)
  301. salt[8 + i] = 0x60 + iteration * 8 + i;
  302. Bytes packet(22);
  303. packet[0] = 0x49;
  304. packet[1] = 0x4C;
  305. packet[4] = 16;
  306. UsbdSecXSM3AuthenticationCrypt(controller.data(),
  307. salt.data() + 8, 8,
  308. packet.data() + 5, 1);
  309. UsbdSecXSM3AuthenticationMac(hash.data(), salt.data(),
  310. packet.data() + 5, 8,
  311. packet.data() + 13);
  312. checksum(packet);
  313. CHECK(packet == hex(fixture.verify[iteration]));
  314. return packet;
  315. }
  316. void acceptVerify(Bytes response, unsigned iteration)
  317. {
  318. checkPacket(response, 22);
  319. CHECK(response == hex(fixture.verify_response[iteration]));
  320. uint8_t mac[8];
  321. UsbdSecXSM3AuthenticationMac(key2.data(), salt.data(),
  322. response.data() + 5, 8, mac);
  323. CHECK(memcmp(mac, response.data() + 13, 8) == 0);
  324. }
  325. };
  326. static void begin(Console &console, uint16_t index = 0x0103,
  327. uint8_t type = 0x41)
  328. {
  329. unsigned before = rngCalls;
  330. out(0x82, console.init(), index, type);
  331. CHECK(rngCalls == before);
  332. state(1);
  333. noReply();
  334. xinputAuthProcess();
  335. CHECK(rngCalls == before + 1);
  336. state(2);
  337. console.acceptInit(in(0x83));
  338. xinputAuthProcess();
  339. CHECK(rngCalls == before + 1);
  340. }
  341. static void exchange(Console &console)
  342. {
  343. for (unsigned i = 0; i < 3; i++) {
  344. unsigned before = rngCalls;
  345. out(0x87, console.verify(i));
  346. state(1);
  347. noReply();
  348. xinputAuthProcess();
  349. CHECK(rngCalls == before);
  350. state(2);
  351. Bytes response = in(0x83);
  352. CHECK(in(0x83) == response);
  353. console.acceptVerify(response, i);
  354. }
  355. }
  356. static void cryptoKnownAnswers()
  357. {
  358. uint8_t digest[20];
  359. ExCryptSha(reinterpret_cast<const uint8_t *>("abc"), 3, digest);
  360. CHECK(Bytes(digest, digest + 20) ==
  361. hex("a9993e364706816aba3e25717850c26c9cd0d89d"));
  362. ExCryptSha(reinterpret_cast<const uint8_t *>(""), 0, digest);
  363. CHECK(Bytes(digest, digest + 20) ==
  364. hex("da39a3ee5e6b4b0d3255bfef95601890afd80709"));
  365. // This vendor helper only supports single-block SHA-1 (at most 55 bytes).
  366. uint8_t message[55];
  367. for (unsigned i = 0; i < sizeof message; i++)
  368. message[i] = i;
  369. ExCryptSha(message, 32, digest);
  370. CHECK(Bytes(digest, digest + 20) ==
  371. hex("ae5bd8efea5322c4d9986d06680a781392f9a642"));
  372. ExCryptSha(message, sizeof message, digest);
  373. CHECK(Bytes(digest, digest + 20) ==
  374. hex("8ae2d46729cfe68ff927af5eec9c7d1b66d65ac2"));
  375. uint64_t key;
  376. auto keyBytes = hex("133457799bbcdff1");
  377. memcpy(&key, keyBytes.data(), 8);
  378. EXCRYPT_DES_STATE des;
  379. ExCryptDesKey(&des, &key);
  380. auto plain = hex("0123456789abcdef");
  381. uint8_t encrypted[8], recovered[8];
  382. ExCryptDesEcb(&des, plain.data(), encrypted, 1);
  383. CHECK(Bytes(encrypted, encrypted + 8) == hex("85e813540f0ab405"));
  384. ExCryptDesEcb(&des, encrypted, recovered, 0);
  385. CHECK(Bytes(recovered, recovered + 8) == plain);
  386. uint8_t parity[256], input[256];
  387. for (unsigned i = 0; i < 256; i++)
  388. input[i] = i;
  389. ExCryptDesParity(input, sizeof input, parity);
  390. for (unsigned i = 0; i < 256; i++)
  391. CHECK((parity[i] & 0xFE) == (i & 0xFE));
  392. // DES ignores parity bits; this helper does not normalize odd parity.
  393. for (unsigned i = 0; i < 256; i += 8) {
  394. EXCRYPT_DES_STATE original, adjusted;
  395. memcpy(&key, input + i, 8);
  396. ExCryptDesKey(&original, &key);
  397. memcpy(&key, parity + i, 8);
  398. ExCryptDesKey(&adjusted, &key);
  399. CHECK(memcmp(&original, &adjusted, sizeof original) == 0);
  400. }
  401. uint8_t macKey[16], data[24];
  402. for (unsigned i = 0; i < sizeof macKey; i++)
  403. macKey[i] = i;
  404. for (unsigned i = 0; i < sizeof data; i++)
  405. data[i] = i;
  406. auto salt = hex("ffffffffffffffff1020304050607080");
  407. UsbdSecXSM3AuthenticationMac(macKey, salt.data(), data, sizeof data,
  408. encrypted);
  409. CHECK(Bytes(encrypted, encrypted + 8) == hex(mac_wrap));
  410. CHECK(salt == hex(salt_wrap));
  411. puts("PASS SHA-1/DES known answers, DES parity, salted MAC wrap");
  412. }
  413. static void descriptors()
  414. {
  415. static_assert(sizeof(tusb_control_request_t) == 8, "SETUP size");
  416. CHECK(sizeof XINPUT_CONFIG_BODY == 144);
  417. CHECK(sizeof XINPUT_CONFIG_BODY + 9 == 153);
  418. const uint8_t counts[] = { 2, 4, 1, 0 };
  419. const uint8_t protocols[] = { 1, 3, 2, 0x13 };
  420. const uint8_t classLengths[] = { 17, 27, 9, 6 };
  421. const uint8_t endpoints[] = { 0x81, 0x02, 0x83, 0x04, 0x85, 0x06, 0x86 };
  422. const uint8_t intervals[] = { 1, 8, 2, 4, 0x40, 0x10, 0x10 };
  423. unsigned interfaces = 0, endpoint = 0, localEndpoints = 0;
  424. unsigned classDescriptors = 0;
  425. for (size_t offset = 0; offset < sizeof XINPUT_CONFIG_BODY;) {
  426. const uint8_t *d = XINPUT_CONFIG_BODY + offset;
  427. CHECK(d[0] >= 2 && offset + d[0] <= sizeof XINPUT_CONFIG_BODY);
  428. switch (d[1]) {
  429. case 4:
  430. if (interfaces)
  431. CHECK(localEndpoints == counts[interfaces - 1]);
  432. CHECK(interfaces < 4 && d[0] == 9);
  433. CHECK(d[2] == interfaces && d[3] == 0);
  434. CHECK(d[4] == counts[interfaces] && d[5] == 0xFF);
  435. CHECK(d[6] == (interfaces == 3 ? 0xFD : 0x5D));
  436. CHECK(d[7] == protocols[interfaces]);
  437. CHECK(d[8] == (interfaces == 3 ? 4 : 0));
  438. if (interfaces == 3)
  439. CHECK(offset + 8 ==
  440. XINPUT_SECURITY_STRING_OFFSET);
  441. interfaces++;
  442. localEndpoints = 0;
  443. break;
  444. case 5:
  445. CHECK(interfaces > 0 && endpoint < 7);
  446. CHECK(d[0] == 7 && d[2] == endpoints[endpoint]);
  447. CHECK(d[3] == 3 && d[4] == 32 && d[5] == 0);
  448. CHECK(d[6] == intervals[endpoint]);
  449. endpoint++;
  450. localEndpoints++;
  451. break;
  452. case 0x21:
  453. case 0x41:
  454. CHECK(interfaces > 0 &&
  455. classDescriptors == interfaces - 1);
  456. CHECK(d[0] == classLengths[classDescriptors]);
  457. CHECK(d[1] == (interfaces == 4 ? 0x41 : 0x21));
  458. classDescriptors++;
  459. break;
  460. default:
  461. CHECK(false);
  462. }
  463. offset += d[0];
  464. }
  465. CHECK(interfaces == 4 && endpoint == 7 && classDescriptors == 4);
  466. CHECK(localEndpoints == 0);
  467. CHECK(XINPUT_SECURITY_STRING_OFFSET == 137);
  468. CHECK(strcmp(XINPUT_SECURITY_STRING,
  469. "Xbox Security Method 3, Version 1.00, \xc2\xa9 2005 Microsoft "
  470. "Corporation. All rights reserved.") == 0);
  471. puts("PASS descriptor lengths, interfaces, endpoints, security string");
  472. }
  473. static const uint16_t lengths[] = {
  474. 0, 1, 2, 5, 21, 22, 23, 28, 29, 33, 34,
  475. 35, 45, 46, 47, 255, 256, 32767, 32768, 65534, 65535,
  476. };
  477. static void identificationAndBounds()
  478. {
  479. xinputAuthPrepare();
  480. CHECK(workerStarts == 1);
  481. CHECK(strlen(xinputAuthSerial()) == 12);
  482. CHECK(strcmp(xinputAuthSerial(), "012345ABCDEF") == 0);
  483. auto expected = hex(fixtures[0].identification);
  484. for (uint16_t index : { 3, 0x0103 }) {
  485. for (uint16_t length : lengths) {
  486. Bytes id = in(0x81, length, index);
  487. CHECK(offered == 29);
  488. Bytes truncated = expected;
  489. truncated.resize(std::min<size_t>(length, 29));
  490. CHECK(id == truncated);
  491. }
  492. }
  493. CHECK(in(0x81, 65535, 0, 0xC0) == expected);
  494. CHECK(in(0x81) == expected);
  495. CHECK(memcmp(expected.data() + 5, xinputAuthSerial(), 12) == 0);
  496. Bytes checked = expected;
  497. checksum(checked);
  498. CHECK(checked == expected);
  499. state(1);
  500. noReply();
  501. CHECK(!setup(request(0x87, 22, 0x41)));
  502. Console console(fixtures[0]);
  503. begin(console);
  504. for (uint8_t command : { 0x82, 0x87 }) {
  505. for (uint16_t length : lengths) {
  506. if (length == (command == 0x82 ? 34 : 22))
  507. continue;
  508. CHECK(!setup(request(command, length, 0x41)));
  509. CHECK(in(0x83) == hex(fixtures[0].init_response));
  510. }
  511. }
  512. for (uint8_t command : { 0x83, 0x84, 0x86 }) {
  513. Bytes full = in(command);
  514. for (uint16_t length : lengths) {
  515. Bytes reply = in(command, length);
  516. CHECK(offered == full.size());
  517. Bytes truncated = full;
  518. truncated.resize(std::min<size_t>(length, full.size()));
  519. CHECK(reply == truncated);
  520. }
  521. }
  522. for (uint8_t command : { 0x81, 0x82, 0x83, 0x84, 0x86, 0x87 }) {
  523. bool output = command == 0x82 || command == 0x87;
  524. uint16_t length = command == 0x82 ? 34 : 22;
  525. uint8_t correct = output ? 0x41 : 0xC1;
  526. CHECK(!setup(request(command, length, correct ^ 0x80)));
  527. for (uint8_t type : { 0x00, 0x01, 0x21, 0x42, 0x43, 0x80, 0x81,
  528. 0xA1, 0xC2, 0xC3 })
  529. CHECK(!setup(request(command, length, type)));
  530. for (uint16_t index : { 0, 1, 2, 4, 0x0100, 0x0203, 65535 })
  531. CHECK(!setup(request(command, length, correct, index)));
  532. CHECK(!setup(request(command, length, correct - 1, 3)));
  533. }
  534. for (uint8_t command : { 0x00, 0x80, 0x85, 0x88, 0xFF }) {
  535. CHECK(!setup(request(command, 34, 0x41)));
  536. CHECK(!setup(request(command, 46)));
  537. }
  538. CHECK(in(0x83) == hex(fixtures[0].init_response));
  539. puts("PASS identification, serial stability, lengths and request routing");
  540. }
  541. static void sessions()
  542. {
  543. for (unsigned round = 0; round < 2; round++) {
  544. for (const auto &fixture : fixtures) {
  545. Console console(fixture);
  546. if (round)
  547. xinputAuthReset();
  548. begin(console, round ? 3 : 0x0103);
  549. auto keepalive =
  550. request(0x84, 0, 0x41, round ? 3 : 0x0103);
  551. keepalive.wValue = 3;
  552. unsigned notified = notifications;
  553. CHECK(setup(keepalive));
  554. CHECK(offered == 0);
  555. CHECK(xinputAuthControl(0, CONTROL_STAGE_ACK,
  556. &keepalive));
  557. CHECK(notifications == notified);
  558. state(2);
  559. CHECK(in(0x83) == hex(fixture.init_response));
  560. exchange(console);
  561. for (uint16_t length : lengths) {
  562. auto expected = hex(fixture.verify_response[2]);
  563. expected.resize(std::min<size_t>(length, 22));
  564. CHECK(in(0x83, length) == expected);
  565. CHECK(offered == 22);
  566. }
  567. }
  568. }
  569. Console device(fixtures[0]);
  570. begin(device, 0, 0x40);
  571. CHECK(in(0x83, 65535, 0, 0xC0) == hex(fixtures[0].init_response));
  572. exchange(device);
  573. CHECK(in(0x81) == hex(fixtures[0].identification));
  574. state(1);
  575. noReply();
  576. CHECK(strcmp(xinputAuthSerial(), "012345ABCDEF") == 0);
  577. puts("PASS two consoles, OUT keepalive, reinit/reset, repeated verification, IN truncation");
  578. }
  579. static void stagesAndReset()
  580. {
  581. xinputAuthReset();
  582. auto req = request(0x82, 34, 0x41);
  583. CHECK(!data(req));
  584. CHECK(setup(req));
  585. unsigned before = notifications, randomBefore = rngCalls;
  586. CHECK(xinputAuthControl(0, CONTROL_STAGE_ACK, &req));
  587. xinputAuthProcess();
  588. CHECK(notifications == before && rngCalls == randomBefore);
  589. auto init = hex(fixtures[0].init);
  590. CHECK(data(req, init));
  591. CHECK(notifications == before + 1);
  592. CHECK(!data(req, init));
  593. xinputAuthReset();
  594. xinputAuthProcess();
  595. CHECK(rngCalls == randomBefore);
  596. state(1);
  597. noReply();
  598. CHECK(setup(req));
  599. xinputAuthReset();
  600. CHECK(!data(req, init));
  601. Console console(fixtures[0]);
  602. begin(console);
  603. auto replyReq = request(0x83, 46);
  604. CHECK(setup(replyReq));
  605. uint8_t *owned = ep0;
  606. Bytes snapshot(owned, owned + offered);
  607. xinputAuthReset();
  608. CHECK(Bytes(owned, owned + snapshot.size()) == snapshot);
  609. CHECK(data(replyReq));
  610. CHECK(xinputAuthControl(0, CONTROL_STAGE_ACK, &replyReq));
  611. noReply();
  612. out(0x82, console.init());
  613. CHECK(setup(request(0x86, 2)));
  614. owned = ep0;
  615. CHECK(owned[0] == 1 && owned[1] == 0);
  616. xinputAuthProcess();
  617. CHECK(owned[0] == 1 && owned[1] == 0);
  618. state(2);
  619. resetInRng = true;
  620. out(0x82, console.init());
  621. xinputAuthProcess();
  622. CHECK(!resetInRng);
  623. state(1);
  624. noReply();
  625. CHECK(!setup(request(0x87, 22, 0x41)));
  626. begin(console);
  627. exchange(console);
  628. replaceInRng = true;
  629. out(0x82, console.init());
  630. xinputAuthProcess();
  631. CHECK(!replaceInRng);
  632. state(1);
  633. noReply();
  634. xinputAuthProcess();
  635. Console replacement(fixtures[1]);
  636. replacement.acceptInit(in(0x83));
  637. exchange(replacement);
  638. puts("PASS EP0 stages, buffer ownership, reset/replacement during crypto");
  639. }
  640. static void invalidChallenges()
  641. {
  642. for (bool verify : { false, true }) {
  643. for (unsigned corruption = 0; corruption < 4; corruption++) {
  644. Console console(fixtures[0]);
  645. begin(console);
  646. Bytes packet = verify ? console.verify(0) :
  647. console.init();
  648. switch (corruption) {
  649. case 0:
  650. packet.back() ^= 1;
  651. break;
  652. case 1:
  653. packet[verify ? 13 : 29] ^= 1;
  654. checksum(packet);
  655. break;
  656. case 2:
  657. packet[4] = 0;
  658. break;
  659. case 3:
  660. packet[4] = 255;
  661. break;
  662. }
  663. unsigned before = rngCalls;
  664. out(verify ? 0x87 : 0x82, packet);
  665. noReply();
  666. state(1);
  667. xinputAuthProcess();
  668. CHECK(rngCalls == before);
  669. failed();
  670. CHECK(std::all_of(xsm3_challenge_response,
  671. xsm3_challenge_response + 48,
  672. [](uint8_t b) { return b == 0; }));
  673. Console recovery(fixtures[1]);
  674. begin(recovery);
  675. exchange(recovery);
  676. }
  677. }
  678. Console console(fixtures[0]);
  679. begin(console);
  680. rngAvailable = false;
  681. out(0x82, console.init());
  682. xinputAuthProcess();
  683. failed();
  684. rngAvailable = true;
  685. begin(console);
  686. exchange(console);
  687. workerAvailable = false;
  688. xinputAuthPrepare();
  689. CHECK(!setup(request(0x81, 29)));
  690. CHECK(!setup(request(0x82, 34, 0x41)));
  691. workerAvailable = true;
  692. xinputAuthPrepare();
  693. CHECK(in(0x81) == hex(fixtures[0].identification));
  694. begin(console);
  695. exchange(console);
  696. puts("PASS malformed packets, checksum/MAC failures, RNG/worker failures");
  697. }
  698. static void receivedLengths()
  699. {
  700. unsigned rejected = 0;
  701. for (bool verify : { false, true }) {
  702. uint16_t expected = verify ? 22 : 34;
  703. auto reject = [&](uint32_t actual, uint8_t endpoint,
  704. xfer_result_t result) {
  705. Console console(fixtures[0]);
  706. begin(console);
  707. Bytes packet = verify ? console.verify(0) :
  708. console.init();
  709. auto req =
  710. request(verify ? 0x87 : 0x82, expected, 0x41);
  711. CHECK(setup(req));
  712. uint8_t *buffer = ep0;
  713. unsigned before = notifications,
  714. randomBefore = rngCalls;
  715. CHECK(!data(req, packet, actual, endpoint, result));
  716. if (endpoint == 0) {
  717. size_t copied =
  718. std::min<uint32_t>(actual, expected);
  719. CHECK(std::equal(packet.begin(),
  720. packet.begin() + copied,
  721. buffer));
  722. CHECK(std::all_of(
  723. buffer + copied, buffer + expected,
  724. [](uint8_t b) { return b == 0; }));
  725. }
  726. CHECK(notifications == before && !xinputAuthBusy());
  727. CHECK(xinputAuthControl(0, CONTROL_STAGE_ACK, &req));
  728. CHECK(notifications == before);
  729. failed();
  730. CHECK(rngCalls == randomBefore);
  731. // A later full-length callback cannot revive the rejected job.
  732. CHECK(!data(req));
  733. CHECK(notifications == before);
  734. Console recovery(fixtures[1]);
  735. begin(recovery);
  736. exchange(recovery);
  737. rejected++;
  738. };
  739. for (uint32_t actual = 0; actual < expected; actual++)
  740. reject(actual, 0, XFER_RESULT_SUCCESS);
  741. for (uint32_t actual : { uint32_t(expected + 1), 46u, 64u, 255u,
  742. 256u, 65535u, 65536u, UINT32_MAX })
  743. reject(actual, 0, XFER_RESULT_SUCCESS);
  744. for (auto result : { XFER_RESULT_FAILED, XFER_RESULT_STALLED,
  745. XFER_RESULT_TIMEOUT, XFER_RESULT_INVALID })
  746. reject(expected, 0, result);
  747. for (uint8_t endpoint : { 1, 2, 0x80, 0x81, 0xFF })
  748. reject(expected, endpoint, XFER_RESULT_SUCCESS);
  749. }
  750. CHECK(rejected == 90);
  751. puts("PASS 90 EP0 rejects: every short init/verify, oversized counts, "
  752. "failed results, wrong endpoints, recovery");
  753. }
  754. extern "C" const uint16_t *__wrap_tud_descriptor_string_cb(uint8_t index,
  755. uint16_t langid);
  756. static unsigned stringDelegations;
  757. static uint8_t delegatedIndex;
  758. static uint16_t delegatedLanguage;
  759. static const uint16_t fallbackString[] = { 0x0304, 'Z' };
  760. extern "C" const uint16_t *__real_tud_descriptor_string_cb(uint8_t index,
  761. uint16_t langid)
  762. {
  763. stringDelegations++;
  764. delegatedIndex = index;
  765. delegatedLanguage = langid;
  766. return index == 0xFF ? nullptr : fallbackString;
  767. }
  768. static void stringDescriptors()
  769. {
  770. static const char expected[] =
  771. "Xbox Security Method 3, Version 1.00, \xA9 2005 Microsoft "
  772. "Corporation. All rights reserved.";
  773. static_assert(sizeof expected == 89, "88 security code units plus NUL");
  774. for (uint8_t mode = 0; mode <= MODE_MAX; mode++) {
  775. g_usbMode = mode;
  776. for (unsigned index = 0; index <= 255; index++) {
  777. for (uint16_t language :
  778. { 0, 0x0409, 0x0411, 0xFFFF }) {
  779. unsigned before = stringDelegations;
  780. const uint16_t *descriptor =
  781. __wrap_tud_descriptor_string_cb(
  782. index, language);
  783. if (mode == MODE_XBOX && index == 4) {
  784. CHECK(stringDelegations == before);
  785. CHECK(descriptor != nullptr);
  786. CHECK(descriptor[0] == 0x03B2);
  787. for (size_t i = 0; i < 88; i++) {
  788. uint16_t code =
  789. uint8_t(expected[i]);
  790. CHECK(descriptor[i + 1] ==
  791. code);
  792. }
  793. // Include the tail beyond two EP0 packets; USB
  794. // strings have no terminating UTF-16 NUL.
  795. Bytes bytes;
  796. for (size_t i = 0; i < 89; i++) {
  797. bytes.push_back(descriptor[i] &
  798. 0xFF);
  799. bytes.push_back(descriptor[i] >>
  800. 8);
  801. }
  802. CHECK(bytes.size() == 178 &&
  803. bytes[0] == 178);
  804. CHECK(bytes[176] == '.' &&
  805. bytes[177] == 0);
  806. } else {
  807. CHECK(stringDelegations == before + 1);
  808. CHECK(delegatedIndex == index);
  809. CHECK(delegatedLanguage == language);
  810. CHECK(descriptor ==
  811. (index == 255 ? nullptr :
  812. fallbackString));
  813. }
  814. }
  815. }
  816. }
  817. g_usbMode = MODE_XBOX;
  818. puts("PASS actual string wrapper: full 178 bytes, all indices/modes, "
  819. "language and null delegation");
  820. }
  821. void modeTests();
  822. int main()
  823. {
  824. cryptoKnownAnswers();
  825. descriptors();
  826. identificationAndBounds();
  827. sessions();
  828. stagesAndReset();
  829. invalidChallenges();
  830. receivedLengths();
  831. stringDescriptors();
  832. modeTests();
  833. CHECK(lockDepth == 0);
  834. puts("PASS all native XInput regression tests");
  835. return 0;
  836. }