TuxeraNTFS-keygen.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. #include <stdint.h>
  2. #include <stddef.h>
  3. #include <stdio.h>
  4. #include <memory.h>
  5. #include <openssl/err.h>
  6. #include <openssl/obj_mac.h>
  7. #include <openssl/ec.h>
  8. #include <unistd.h>
  9. #include <fcntl.h>
  10. #include <sys/types.h>
  11. #include <sys/errno.h>
  12. #include <argon2.h>
  13. //--------in helper.c
  14. extern void PrintBytes(const uint8_t* bytes, size_t len);
  15. extern size_t CustomBase32Encode(const void* __restrict src, size_t len,
  16. char* __restrict out_buf, size_t out_len);
  17. extern unsigned long PrintKeyInfo(const EC_KEY* lpcECKey, int* lperrno);
  18. //--------end
  19. const uint8_t salt[16] = {
  20. 0xa1, 0x38, 0x11, 0x98, 0x12, 0x2f, 0x28, 0xee,
  21. 0x2c, 0x3a, 0xa0, 0x57, 0xbd, 0xcf, 0x2d, 0x83
  22. };
  23. // sn = (r - hash * PrivateKey) * EllipticCurveGenerator
  24. unsigned long CalculateSN(const BIGNUM* r, const BIGNUM* hash, const BIGNUM* PrivateKey, const BIGNUM* order, uint8_t* lpSN) {
  25. unsigned long ErrorCode = 0;
  26. BIGNUM* sn = NULL;
  27. BIGNUM* tmp = NULL;
  28. BN_CTX* bn_ctx = NULL;
  29. sn = BN_new();
  30. if (sn == NULL) {
  31. ErrorCode = ERR_get_error();
  32. goto On_CalculateSN_Error;
  33. }
  34. tmp = BN_new();
  35. if (tmp == NULL) {
  36. ErrorCode = ERR_get_error();
  37. goto On_CalculateSN_Error;
  38. }
  39. bn_ctx = BN_CTX_new();
  40. if (bn_ctx == NULL) {
  41. ErrorCode = ERR_get_error();
  42. goto On_CalculateSN_Error;
  43. }
  44. if (!BN_mod_mul(tmp, hash, PrivateKey, order, bn_ctx)) { // tmp = hash * PrivateKey
  45. ErrorCode = ERR_get_error();
  46. goto On_CalculateSN_Error;
  47. }
  48. if (!BN_mod_sub(sn, r, tmp, order, bn_ctx)) { // sn = r - tmp
  49. ErrorCode = ERR_get_error();
  50. goto On_CalculateSN_Error;
  51. }
  52. memset(lpSN, 0, 14);
  53. if (!BN_bn2bin(sn, lpSN)) {
  54. ErrorCode = ERR_get_error();
  55. goto On_CalculateSN_Error;
  56. }
  57. On_CalculateSN_Error:
  58. if (bn_ctx)
  59. BN_CTX_free(bn_ctx);
  60. if (tmp)
  61. BN_free(tmp);
  62. if (sn)
  63. BN_free(sn);
  64. return ErrorCode;
  65. }
  66. unsigned long CalculateHash(const BIGNUM* r, const EC_KEY* ecKey, uint8_t* lpHash) {
  67. unsigned long ErrorCode = 0;
  68. EC_POINT* rG = NULL;
  69. BIGNUM* rG_x = NULL;
  70. BIGNUM* rG_y = NULL;
  71. uint8_t bin_rG[2][14] = {};
  72. rG = EC_POINT_new(EC_KEY_get0_group(ecKey));
  73. if (rG == NULL) {
  74. ErrorCode = ERR_get_error();
  75. goto On_CalculateHash_Error;
  76. }
  77. if (!EC_POINT_mul(EC_KEY_get0_group(ecKey), rG, r, NULL, NULL, NULL)) {
  78. ErrorCode = ERR_get_error();
  79. goto On_CalculateHash_Error;
  80. }
  81. rG_x = BN_new();
  82. if (rG_x == NULL) {
  83. ErrorCode = ERR_get_error();
  84. goto On_CalculateHash_Error;
  85. }
  86. rG_y = BN_new();
  87. if (rG_y == NULL) {
  88. ErrorCode = ERR_get_error();
  89. goto On_CalculateHash_Error;
  90. }
  91. if (!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ecKey), rG, rG_x, rG_y, NULL)) {
  92. ErrorCode = ERR_get_error();
  93. goto On_CalculateHash_Error;
  94. }
  95. if (!BN_bn2bin(rG_x, bin_rG[0] + sizeof(bin_rG[0]) - BN_num_bytes(rG_x))) {
  96. ErrorCode = ERR_get_error();
  97. goto On_CalculateHash_Error;
  98. }
  99. if (!BN_bn2bin(rG_y, bin_rG[1] + sizeof(bin_rG[1]) - BN_num_bytes(rG_y))) {
  100. ErrorCode = ERR_get_error();
  101. goto On_CalculateHash_Error;
  102. }
  103. argon2_hash(1, 1 << 16, 1, bin_rG, sizeof(bin_rG), salt, sizeof(salt), lpHash, 5, NULL, 0, Argon2_d, ARGON2_VERSION_13);
  104. lpHash[5 - 1] &= 0xFC;
  105. On_CalculateHash_Error:
  106. if (rG_y)
  107. BN_free(rG_y);
  108. if (rG_x)
  109. BN_free(rG_x);
  110. if (rG)
  111. EC_POINT_free(rG);
  112. return ErrorCode;
  113. }
  114. // Long product key has 34 chars, like "xxxxxx-xxxxxx-xxxxxx-xxxxxx-xxxxxx"
  115. char* GetEncodedLongProductKey(const uint8_t* lpSN, const uint8_t* lpHash) {
  116. uint8_t ProductKeyData[19];
  117. char buffer[128] = {};
  118. char* lpszEncodedLongProductKey = NULL;
  119. memcpy(ProductKeyData, lpSN, 14);
  120. memcpy(ProductKeyData + 14, lpHash, 5);
  121. size_t len = CustomBase32Encode(ProductKeyData, sizeof(ProductKeyData), buffer, sizeof(buffer) - 1);
  122. if (sizeof(buffer) - 1 < len) {
  123. // overflow
  124. return lpszEncodedLongProductKey;
  125. }
  126. lpszEncodedLongProductKey = malloc(34 + 1);
  127. if (lpszEncodedLongProductKey == NULL)
  128. return lpszEncodedLongProductKey;
  129. buffer[len - 1] = 0; // ProductKey[len - 1] must be '0' because lpHash[4] was &-masked by 0xFC, remove it
  130. len--;
  131. { // reverse ProductKey
  132. char* start = buffer;
  133. char* end = buffer + len - 1;
  134. while (start < end) {
  135. char tmp = *start;
  136. *start = *end;
  137. *end = tmp;
  138. start++;
  139. end--;
  140. }
  141. }
  142. sprintf(lpszEncodedLongProductKey,
  143. "%.6s-%.6s-%.6s-%.6s-%.6s",
  144. buffer,
  145. buffer + 6,
  146. buffer + 6 * 2,
  147. buffer + 6 * 3,
  148. buffer + 6 * 4);
  149. return lpszEncodedLongProductKey;
  150. }
  151. unsigned long PrintLongProductKey(const uint8_t* lpPrivateKey) {
  152. unsigned long ErrorCode = 0;
  153. BIGNUM* PrivateKey = NULL;
  154. EC_KEY* ecKey = NULL;
  155. BIGNUM* r = NULL;
  156. BIGNUM* order = NULL;
  157. BIGNUM* hash = NULL;
  158. uint8_t binSN[14] = {};
  159. uint8_t binHash[5] = {};
  160. PrivateKey = BN_bin2bn(lpPrivateKey, 112 / 8, NULL);
  161. if (PrivateKey == NULL) {
  162. ErrorCode = ERR_get_error();
  163. goto On_PrintLongProductKey_Error;
  164. }
  165. ecKey = EC_KEY_new_by_curve_name(NID_secp112r1);
  166. if (ecKey == NULL) {
  167. ErrorCode = ERR_get_error();
  168. goto On_PrintLongProductKey_Error;
  169. }
  170. if (!EC_KEY_set_private_key(ecKey, PrivateKey)) {
  171. ErrorCode = ERR_get_error();
  172. goto On_PrintLongProductKey_Error;
  173. }
  174. { // set public key
  175. EC_POINT* PublicKey = EC_POINT_new(EC_KEY_get0_group(ecKey));
  176. if (PublicKey == NULL) {
  177. ErrorCode = ERR_get_error();
  178. goto On_PrintLongProductKey_Error;
  179. }
  180. if (!EC_POINT_mul(EC_KEY_get0_group(ecKey), PublicKey, PrivateKey, NULL, NULL, NULL)) {
  181. ErrorCode = ERR_get_error();
  182. EC_POINT_free(PublicKey);
  183. goto On_PrintLongProductKey_Error;
  184. }
  185. if (!EC_KEY_set_public_key(ecKey, PublicKey)) {
  186. ErrorCode = ERR_get_error();
  187. EC_POINT_free(PublicKey);
  188. goto On_PrintLongProductKey_Error;
  189. }
  190. EC_POINT_free(PublicKey);
  191. }
  192. ErrorCode = PrintKeyInfo(ecKey, NULL);
  193. if (ErrorCode)
  194. goto On_PrintLongProductKey_Error;
  195. r = BN_new();
  196. if (r == NULL) {
  197. ErrorCode = ERR_get_error();
  198. goto On_PrintLongProductKey_Error;
  199. }
  200. order = BN_new();
  201. if (order == NULL) {
  202. ErrorCode = ERR_get_error();
  203. goto On_PrintLongProductKey_Error;
  204. }
  205. if (!EC_GROUP_get_order(EC_KEY_get0_group(ecKey), order, NULL)) {
  206. ErrorCode = ERR_get_error();
  207. goto On_PrintLongProductKey_Error;
  208. }
  209. if (!BN_rand_range(r, order)) {
  210. ErrorCode = ERR_get_error();
  211. goto On_PrintLongProductKey_Error;
  212. }
  213. ErrorCode = CalculateHash(r, ecKey, binHash);
  214. if (ErrorCode)
  215. goto On_PrintLongProductKey_Error;
  216. hash = BN_bin2bn(binHash, sizeof(binHash), NULL);
  217. if (hash == NULL) {
  218. ErrorCode = ERR_get_error();
  219. goto On_PrintLongProductKey_Error;
  220. }
  221. ErrorCode = CalculateSN(r, hash, PrivateKey, order, binSN);
  222. if (ErrorCode)
  223. goto On_PrintLongProductKey_Error;
  224. char* key = GetEncodedLongProductKey(binSN, binHash);
  225. if (key != NULL) {
  226. printf("Long product key: %s\n", key);
  227. free(key);
  228. } else {
  229. printf("GetEncodedLongProductKey failed!\n");
  230. }
  231. On_PrintLongProductKey_Error:
  232. if (hash)
  233. BN_free(hash);
  234. if (order)
  235. BN_free(order);
  236. if (r)
  237. BN_free(r);
  238. if (ecKey)
  239. EC_KEY_free(ecKey);
  240. if (PrivateKey)
  241. BN_free(PrivateKey);
  242. return ErrorCode;
  243. }
  244. unsigned long PrintShortProductKey(const uint8_t* binPrivateKey) {
  245. // todo
  246. return 0;
  247. }
  248. char ReadPrivateKey(const char* lpszFilePath, uint8_t* lpPrivateKey, size_t KeyLength) {
  249. int fd = open(lpszFilePath, O_RDONLY);
  250. if (fd == -1) {
  251. printf("Failed to open file. CODE: 0x%08x\n", errno);
  252. return 0;
  253. }
  254. if (KeyLength != read(fd, lpPrivateKey, KeyLength)) {
  255. printf("Failed to read file or read incompletely. CODE: 0x%08x\n", errno);
  256. return 0;
  257. }
  258. close(fd);
  259. return 1;
  260. }
  261. void help() {
  262. printf("Usage:\n");
  263. printf(" ./TuxeraNTFS-keygen <path to tuxera_key.bin>\n");
  264. printf("\n");
  265. }
  266. int main(int argc, char* argv[]) {
  267. if (argc != 2) {
  268. help();
  269. return 0;
  270. }
  271. unsigned long ErrorCode = 0;
  272. uint8_t binPrivateKey[14] = {};
  273. if (!ReadPrivateKey(argv[1], binPrivateKey, sizeof(binPrivateKey)))
  274. goto OnError;
  275. PrintLongProductKey(binPrivateKey);
  276. OnError:
  277. return (int)ErrorCode;
  278. }