u3_commands.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. /**
  2. * u3_tool - U3 USB stick manager
  3. * Copyright (C) 2007 Daviedev, daviedev@users.sourceforge.net
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. */
  19. #include "u3_commands.h"
  20. #include <stdlib.h>
  21. #include <unistd.h>
  22. #include <string.h>
  23. #include "u3_scsi.h"
  24. #include "u3_error.h"
  25. #include "md5.h"
  26. #ifdef WIN32
  27. # include <windows.h>
  28. # define sleep Sleep
  29. // Barf, winsock... NOT
  30. # define htonl(A) ((((uint32_t)(A) & 0xff000000) >> 24) | \
  31. (((uint32_t)(A) & 0x00ff0000) >> 8) | \
  32. (((uint32_t)(A) & 0x0000ff00) << 8) | \
  33. (((uint32_t)(A) & 0x000000ff) << 24))
  34. #else
  35. # include <arpa/inet.h> // for htonl()
  36. #endif
  37. #if __BYTE_ORDER != __LITTLE_ENDIAN
  38. # error "This tool only runs on Little Endian machines"
  39. #endif
  40. #define U3_PASSWORD_HASH_LEN 16
  41. /**
  42. * Convert textual password to hash.
  43. *
  44. * @param pass The password string, null terminated.
  45. * @param hash Buffer to write hash to, should be atleast
  46. * U3_PASSWORD_HASH_LEN long.
  47. */
  48. void u3_pass_to_hash(const char *password, uint8_t *hash) {
  49. unsigned int passlen;
  50. unsigned int unicode_passlen;
  51. uint8_t *unicode_pass;
  52. int i;
  53. passlen = strlen(password);
  54. unicode_passlen = (passlen+1)*2;
  55. unicode_pass = (uint8_t *) calloc(passlen+1, 2);
  56. for (i = 0; i < passlen + 1; i++) {
  57. unicode_pass[i*2] = password[i];
  58. }
  59. md5(unicode_pass, unicode_passlen, hash);
  60. memset(unicode_pass, 0xFF, unicode_passlen);
  61. memset(unicode_pass, 0, unicode_passlen);
  62. free(unicode_pass);
  63. }
  64. /**** public function ***/
  65. int u3_read_device_property(u3_handle_t *device, uint16_t property_id,
  66. uint8_t *buffer, uint16_t buffer_length)
  67. {
  68. uint8_t status;
  69. uint8_t cmd[U3_CMD_LEN] = {
  70. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  71. 0x00, 0x00, 0x00, 0x00
  72. };
  73. struct _write_cmd_t {
  74. uint8_t scsi_opcode;
  75. uint16_t command;
  76. uint16_t id;
  77. uint16_t length;
  78. uint16_t unknown1;
  79. uint8_t unknown2;
  80. } __attribute__ ((packed)) *property_command;
  81. struct property_header *hdr;
  82. if (buffer_length < 6) {
  83. u3_set_error(device, "buffer supplied to "
  84. "u3_read_device_property() is to small");
  85. return U3_FAILURE;
  86. }
  87. // First read header to prevent reading to much data
  88. hdr = (struct property_header *) buffer;
  89. property_command = (struct _write_cmd_t *) &cmd;
  90. property_command->id = property_id;
  91. property_command->length = sizeof(struct property_header);
  92. if (u3_send_cmd(device, cmd, U3_DATA_FROM_DEV, property_command->length,
  93. buffer, &status) != U3_SUCCESS)
  94. {
  95. return U3_FAILURE;
  96. }
  97. if (status != 0) {
  98. u3_set_error(device, "Header of property 0x%.4X could not be "
  99. "read.", property_id);
  100. return U3_FAILURE;
  101. }
  102. if (hdr->length < sizeof(struct property_header)) {
  103. u3_set_error(device, "Header of property 0x%.4X indicates a "
  104. "length of smaller then the header size. (len = %u)"
  105. , property_id, hdr->length);
  106. return U3_FAILURE;
  107. }
  108. // Read full property
  109. if (hdr->length > buffer_length) {
  110. property_command->length = buffer_length;
  111. } else {
  112. property_command->length = hdr->length;
  113. }
  114. if (u3_send_cmd(device, cmd, U3_DATA_FROM_DEV, property_command->length,
  115. buffer, &status) != U3_SUCCESS)
  116. {
  117. return U3_FAILURE;
  118. }
  119. if (status != 0) {
  120. u3_set_error(device, "Property 0x%.4X could not be read.",
  121. property_id);
  122. return U3_FAILURE;
  123. }
  124. return U3_SUCCESS;
  125. }
  126. int u3_partition(u3_handle_t *device, uint32_t cd_size) {
  127. uint8_t status;
  128. uint8_t cmd[U3_CMD_LEN] = {
  129. 0xff, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  130. 0x00, 0x00, 0x00, 0x00
  131. };
  132. struct part_info data;
  133. struct property_03 device_properties;
  134. uint32_t data_size;
  135. // calculate data partition size
  136. if (cd_size != 0) {
  137. if (u3_partition_sector_round(device, round_up, &cd_size) != U3_SUCCESS) {
  138. u3_prepend_error(device, "Failed rounding partition sectors");
  139. return U3_FAILURE;
  140. }
  141. }
  142. if (u3_read_device_property(device, 3, (uint8_t *) &device_properties,
  143. sizeof(device_properties)) != U3_SUCCESS)
  144. {
  145. u3_prepend_error(device, "Failed reading device property 0x03");
  146. return U3_FAILURE;
  147. }
  148. if (device_properties.hdr.length != sizeof(device_properties)) {
  149. u3_set_error(device, "Unexpected device property(0x03) length"
  150. ", won't risk breaking device. Aborting! (len=%X)",
  151. device_properties.hdr.length);
  152. return U3_FAILURE;
  153. }
  154. if (cd_size > device_properties.device_size) {
  155. u3_set_error(device, "Requested CD size is to big for device");
  156. return U3_FAILURE;
  157. }
  158. data_size = device_properties.device_size - cd_size;
  159. if (u3_partition_sector_round(device, round_down, &data_size) != U3_SUCCESS) {
  160. u3_prepend_error(device, "Failed rounding partition sectors");
  161. return U3_FAILURE;
  162. }
  163. // fill command data
  164. memset(&data, 0, sizeof(data));
  165. if (cd_size == 0) {
  166. data.partition_count = 1;
  167. data.unknown1 = 0x02;
  168. data.data_size = data_size;
  169. data.unknown2 = 0;
  170. data.cd_size = 0;
  171. } else {
  172. data.partition_count = 2;
  173. data.unknown1 = 0x02;
  174. data.data_size = data_size;
  175. data.unknown2 = 0x103;
  176. data.cd_size = cd_size;
  177. }
  178. if (u3_send_cmd(device, cmd, U3_DATA_TO_DEV, sizeof(data),
  179. (uint8_t *) &data, &status) != U3_SUCCESS)
  180. {
  181. return U3_FAILURE;
  182. }
  183. if (status != 0) {
  184. u3_set_error(device, "Device reported command failed: status %d", status);
  185. return U3_FAILURE;
  186. }
  187. return U3_SUCCESS;
  188. }
  189. int u3_cd_write(u3_handle_t *device, uint32_t block_num, uint8_t *block) {
  190. uint8_t status;
  191. uint8_t cmd[U3_CMD_LEN] = {
  192. 0xff, 0x42, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
  193. 0x00, 0x00, 0x00, 0x01
  194. };
  195. struct _write_cmd_t {
  196. uint8_t scsi_opcode;
  197. uint16_t command;
  198. uint8_t unknown1;
  199. uint32_t block_num;
  200. uint32_t unknown2;
  201. } __attribute__ ((packed)) *write_command;
  202. // fill command data
  203. write_command = (struct _write_cmd_t *) &cmd;
  204. write_command->block_num = htonl(block_num);
  205. if (u3_send_cmd(device, cmd, U3_DATA_TO_DEV, 2048,
  206. block, &status) != U3_SUCCESS)
  207. {
  208. return U3_FAILURE;
  209. }
  210. if (status != 0) {
  211. u3_set_error(device, "Device reported command failed: status %d", status);
  212. return U3_FAILURE;
  213. }
  214. return U3_SUCCESS;
  215. }
  216. int u3_partition_sector_round(u3_handle_t *device,
  217. enum round_dir direction, uint32_t *size)
  218. {
  219. uint8_t status;
  220. uint8_t cmd[U3_CMD_LEN] = {
  221. 0xff, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
  222. 0x00, 0x00, 0x00, 0x00
  223. };
  224. uint32_t rounded_size;
  225. // fill command data
  226. *((uint32_t *)(cmd+4)) = *size;
  227. cmd[8] = direction;
  228. if (u3_send_cmd(device, cmd, U3_DATA_FROM_DEV, sizeof(rounded_size),
  229. (uint8_t *) &rounded_size, &status) != U3_SUCCESS)
  230. {
  231. return U3_FAILURE;
  232. }
  233. if (status != 0) {
  234. u3_set_error(device,
  235. "Device reported command failed: status %d", status);
  236. return U3_FAILURE;
  237. }
  238. *size = rounded_size;
  239. return U3_SUCCESS;
  240. }
  241. int u3_security_sector_round(u3_handle_t *device,
  242. enum round_dir direction, uint32_t *size)
  243. {
  244. uint8_t status;
  245. uint8_t cmd[U3_CMD_LEN] = {
  246. 0xff, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  247. 0x00, 0x00, 0x00, 0x00
  248. };
  249. uint32_t rounded_size;
  250. // fill command data
  251. *((uint32_t *)(cmd+4)) = *size;
  252. cmd[8] = direction;
  253. if (u3_send_cmd(device, cmd, U3_DATA_FROM_DEV, sizeof(rounded_size),
  254. (uint8_t *) &rounded_size, &status) != U3_SUCCESS)
  255. {
  256. return U3_FAILURE;
  257. }
  258. if (status != 0) {
  259. u3_set_error(device,
  260. "Device reported command failed: status %d", status);
  261. return U3_FAILURE;
  262. }
  263. *size = rounded_size;
  264. return U3_SUCCESS;
  265. }
  266. int u3_partition_info(u3_handle_t *device, struct part_info *info) {
  267. uint8_t status;
  268. uint8_t cmd[U3_CMD_LEN] = {
  269. 0xff, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  270. 0x00, 0x00, 0x00, 0x00
  271. };
  272. memset(info, 0, sizeof(struct part_info));
  273. if (u3_send_cmd(device, cmd, U3_DATA_FROM_DEV, 9,
  274. (uint8_t *)info, &status) != U3_SUCCESS)
  275. {
  276. return U3_FAILURE;
  277. }
  278. //TODO: Find out if it is possible to define more then 2 partition. if so, make
  279. //this more dynamic
  280. if (info->partition_count == 2) {
  281. if (u3_send_cmd(device, cmd, U3_DATA_FROM_DEV, 16,
  282. (uint8_t *)info, &status) != U3_SUCCESS)
  283. {
  284. return U3_FAILURE;
  285. }
  286. }
  287. if (status != 0) {
  288. u3_set_error(device, "Device reported command failed: status %d", status);
  289. return U3_FAILURE;
  290. }
  291. return U3_SUCCESS;
  292. }
  293. int u3_data_partition_info(u3_handle_t *device, struct dpart_info *info) {
  294. uint8_t status;
  295. uint8_t cmd[U3_CMD_LEN] = {
  296. 0xff, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  297. 0x00, 0x00, 0x00, 0x00
  298. };
  299. memset(info, 0, sizeof(struct dpart_info));
  300. if (u3_send_cmd(device, cmd, U3_DATA_FROM_DEV, sizeof(struct dpart_info),
  301. (uint8_t *)info, &status) != U3_SUCCESS)
  302. {
  303. return U3_FAILURE;
  304. }
  305. if (status != 0) {
  306. u3_set_error(device, "Device reported command failed: status %d", status);
  307. return U3_FAILURE;
  308. }
  309. return U3_SUCCESS;
  310. }
  311. int u3_chip_info(u3_handle_t *device, struct chip_info *info) {
  312. uint8_t status;
  313. uint8_t cmd[U3_CMD_LEN] = {
  314. 0xff, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
  315. 0x00, 0x00, 0x00, 0x00
  316. };
  317. memset(info, 0, sizeof(struct chip_info));
  318. if (u3_send_cmd(device, cmd, U3_DATA_FROM_DEV, sizeof(struct chip_info),
  319. (uint8_t *)info, &status) != U3_SUCCESS)
  320. {
  321. return U3_FAILURE;
  322. }
  323. if (status != 0) {
  324. u3_set_error(device, "Device reported command failed: status %d", status);
  325. return U3_FAILURE;
  326. }
  327. return U3_SUCCESS;
  328. }
  329. int u3_reset(u3_handle_t *device) {
  330. uint8_t status;
  331. uint8_t cmd[U3_CMD_LEN] = {
  332. 0xff, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
  333. 0x00, 0x00, 0x00, 0x00
  334. };
  335. uint8_t data[12] = { // the magic numbers
  336. 0x50, 0x00, 0x00, 0x00, 0x40, 0x9c, 0x00, 0x00,
  337. 0x01, 0x00, 0x00, 0x00
  338. };
  339. if (u3_send_cmd(device, cmd, U3_DATA_TO_DEV, sizeof(data),
  340. data, &status) != U3_SUCCESS)
  341. {
  342. return U3_FAILURE;
  343. }
  344. if (status != 0) {
  345. u3_set_error(device, "Device reported command failed: status %d", status);
  346. return U3_FAILURE;
  347. }
  348. sleep(2); // wait for device to reset
  349. // u3_reopen(device);
  350. return U3_SUCCESS;
  351. }
  352. int u3_enable_security(u3_handle_t *device, const char *password) {
  353. uint8_t status;
  354. uint8_t cmd[U3_CMD_LEN] = {
  355. 0xff, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  356. 0x00, 0x00, 0x00, 0x00
  357. };
  358. struct {
  359. uint32_t size;
  360. uint8_t hash[U3_PASSWORD_HASH_LEN];
  361. } __attribute__ ((packed)) data;
  362. struct dpart_info dp_info;
  363. uint32_t secure_zone_size;
  364. // determine size
  365. //TODO: allow user to determine secure zone size... However currently we don't
  366. // understand why disable security only works on a fully secured partition...
  367. if (u3_data_partition_info(device, &dp_info) != U3_SUCCESS) {
  368. u3_prepend_error(device, "Failed reading data partition info");
  369. return U3_FAILURE;
  370. }
  371. secure_zone_size = dp_info.total_size;
  372. if (secure_zone_size != 0) {
  373. if (u3_security_sector_round(device, round_up,
  374. &secure_zone_size) != U3_SUCCESS)
  375. {
  376. u3_prepend_error(device,
  377. "Failed rounding secure zone sectors");
  378. return U3_FAILURE;
  379. }
  380. }
  381. // fill command data
  382. data.size = secure_zone_size;
  383. u3_pass_to_hash(password, data.hash);
  384. if (u3_send_cmd(device, cmd, U3_DATA_TO_DEV, sizeof(data),
  385. (uint8_t *) &data, &status) != U3_SUCCESS)
  386. {
  387. return U3_FAILURE;
  388. }
  389. if (status != 0) {
  390. u3_set_error(device, "Device reported command failed: status %d", status);
  391. return U3_FAILURE;
  392. }
  393. return U3_SUCCESS;
  394. }
  395. int u3_disable_security(u3_handle_t *device, const char *password,
  396. int * result)
  397. {
  398. uint8_t status;
  399. uint8_t cmd[U3_CMD_LEN] = {
  400. 0xff, 0xA7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  401. 0x00, 0x00, 0x00, 0x00
  402. };
  403. uint8_t passhash_buf[U3_PASSWORD_HASH_LEN];
  404. *result = 0;
  405. u3_pass_to_hash(password, passhash_buf);
  406. if (u3_send_cmd(device, cmd, U3_DATA_TO_DEV, sizeof(passhash_buf),
  407. passhash_buf, &status) != U3_SUCCESS)
  408. {
  409. return U3_FAILURE;
  410. }
  411. if (status == 0) {
  412. *result = 1;
  413. }
  414. return U3_SUCCESS;
  415. }
  416. int u3_unlock(u3_handle_t *device, const char *password, int *result) {
  417. uint8_t status;
  418. uint8_t cmd[U3_CMD_LEN] = {
  419. 0xff, 0xA4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  420. 0x00, 0x00, 0x00, 0x00
  421. };
  422. uint8_t passhash_buf[U3_PASSWORD_HASH_LEN];
  423. *result = 0;
  424. u3_pass_to_hash(password, passhash_buf);
  425. if (u3_send_cmd(device, cmd, U3_DATA_TO_DEV, sizeof(passhash_buf),
  426. passhash_buf, &status) != U3_SUCCESS)
  427. {
  428. return U3_FAILURE;
  429. }
  430. if (status == 0) {
  431. *result = 1;
  432. }
  433. return U3_SUCCESS;
  434. }
  435. int u3_change_password(u3_handle_t *device, const char *old_password,
  436. const char *new_password, int *result)
  437. {
  438. uint8_t status;
  439. uint8_t cmd[U3_CMD_LEN] = {
  440. 0xff, 0xA6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  441. 0x00, 0x00, 0x00, 0x00
  442. };
  443. uint8_t passhash_buf[U3_PASSWORD_HASH_LEN * 2];
  444. *result = 0;
  445. u3_pass_to_hash(old_password, passhash_buf);
  446. u3_pass_to_hash(new_password, passhash_buf+U3_PASSWORD_HASH_LEN);
  447. if (u3_send_cmd(device, cmd, U3_DATA_TO_DEV, sizeof(passhash_buf),
  448. (uint8_t *) passhash_buf, &status) != U3_SUCCESS)
  449. {
  450. return U3_FAILURE;
  451. }
  452. if (status == 0) {
  453. *result = 1;
  454. }
  455. return U3_SUCCESS;
  456. }