123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425 |
- #include <stdio.h>
- #include <string.h>
- #include <openssl/err.h>
- #include <openssl/obj_mac.h>
- #include <openssl/ec.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/errno.h>
- #include <argon2.h>
- extern uint8_t key_hashes[150388][6];
- extern size_t CustomBase32Decode(const char* __restrict src, size_t len,
- void* __restrict out_buf, size_t out_len);
- const uint8_t OfficialPublicKey[2][14] = {
- 0x47, 0xcf, 0xb5, 0xf7, 0xe8, 0x93, 0x1e, 0xc9, 0x3d, 0x42, 0xd1, 0x22, 0x1e, 0x7f,
- 0x98, 0x5d, 0x74, 0xaf, 0x45, 0x53, 0x70, 0xf3, 0x47, 0x39, 0x8e, 0x1b, 0x1d, 0x3e
- };
- const uint8_t salt_for_short_product_key[16] = {
- 0x06, 0x9c, 0x5e, 0xf4, 0x90, 0x67, 0x39, 0x4c,
- 0x7b, 0x61, 0xa7, 0xee, 0x36, 0x97, 0xc6, 0x02
- };
- const uint8_t salt_for_long_product_key[16] = {
- 0xa1, 0x38, 0x11, 0x98, 0x12, 0x2f, 0x28, 0xee,
- 0x2c, 0x3a, 0xa0, 0x57, 0xbd, 0xcf, 0x2d, 0x83
- };
- const uint8_t InverseSubstitutionTable[256] = {
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0x0a,0xff,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0xff,0x11,0x12,0x13,0x14,0x15,0xff,
- 0x16,0x17,0x18,0xff,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
- };
- int IsTheKeyRecorded(uint8_t Hash[6]) {
- int start = 0;
- int end = 150388;
- while (start != end) {
- int mid = (start + end) / 2;
- int j = 0;
- for (; j < 6; ++j) {
- if (Hash[j] < key_hashes[mid][j]) {
- end = mid;
- break;
- } else if (Hash[j] > key_hashes[mid][j]) {
- start = mid + 1;
- break;
- }
- }
- if (j == 6)
- return 1;
- }
- return 0;
- }
- int DecodeShortProductKey(const char* lpcszProductKey, uint8_t data[20]) {
- if (strlen(lpcszProductKey) != 23)
- return 0;
- data[0] = InverseSubstitutionTable[(uint8_t)lpcszProductKey[22]];
- data[1] = InverseSubstitutionTable[(uint8_t)lpcszProductKey[21]];
- data[2] = InverseSubstitutionTable[(uint8_t)lpcszProductKey[20]];
- data[3] = InverseSubstitutionTable[(uint8_t)lpcszProductKey[19]];
- data[4] = InverseSubstitutionTable[(uint8_t)lpcszProductKey[18]];
- data[5] = InverseSubstitutionTable[(uint8_t)lpcszProductKey[16]];
- data[6] = InverseSubstitutionTable[(uint8_t)lpcszProductKey[15]];
- data[7] = InverseSubstitutionTable[(uint8_t)lpcszProductKey[14]];
- data[8] = InverseSubstitutionTable[(uint8_t)lpcszProductKey[13]];
- data[9] = InverseSubstitutionTable[(uint8_t)lpcszProductKey[12]];
- data[10] = InverseSubstitutionTable[(uint8_t)lpcszProductKey[10]];
- data[11] = InverseSubstitutionTable[(uint8_t)lpcszProductKey[9]];
- data[12] = InverseSubstitutionTable[(uint8_t)lpcszProductKey[8]];
- data[13] = InverseSubstitutionTable[(uint8_t)lpcszProductKey[7]];
- data[14] = InverseSubstitutionTable[(uint8_t)lpcszProductKey[6]];
- data[15] = InverseSubstitutionTable[(uint8_t)lpcszProductKey[4]];
- data[16] = InverseSubstitutionTable[(uint8_t)lpcszProductKey[3]];
- data[17] = InverseSubstitutionTable[(uint8_t)lpcszProductKey[2]];
- data[18] = InverseSubstitutionTable[(uint8_t)lpcszProductKey[1]];
- data[19] = InverseSubstitutionTable[(uint8_t)lpcszProductKey[0]];
- for (int i = 0; i < 20; ++i)
- if (data[i] >= 32)
- return 0;
- return 1;
- }
- int DecodeLongProductKey(const char* lpcszProductKey, uint8_t data[14 + 5]) {
- if (strlen(lpcszProductKey) != 34)
- return 0;
- char prekey_str[30 + 1] = {};
- prekey_str[0] = lpcszProductKey[33];
- prekey_str[1] = lpcszProductKey[32];
- prekey_str[2] = lpcszProductKey[31];
- prekey_str[3] = lpcszProductKey[30];
- prekey_str[4] = lpcszProductKey[29];
- prekey_str[5] = lpcszProductKey[28];
- prekey_str[6] = lpcszProductKey[26];
- prekey_str[7] = lpcszProductKey[25];
- prekey_str[8] = lpcszProductKey[24];
- prekey_str[9] = lpcszProductKey[23];
- prekey_str[10] = lpcszProductKey[22];
- prekey_str[11] = lpcszProductKey[21];
- prekey_str[12] = lpcszProductKey[19];
- prekey_str[13] = lpcszProductKey[18];
- prekey_str[14] = lpcszProductKey[17];
- prekey_str[15] = lpcszProductKey[16];
- prekey_str[16] = lpcszProductKey[15];
- prekey_str[17] = lpcszProductKey[14];
- prekey_str[18] = lpcszProductKey[12];
- prekey_str[19] = lpcszProductKey[11];
- prekey_str[20] = lpcszProductKey[10];
- prekey_str[21] = lpcszProductKey[9];
- prekey_str[22] = lpcszProductKey[8];
- prekey_str[23] = lpcszProductKey[7];
- prekey_str[24] = lpcszProductKey[5];
- prekey_str[25] = lpcszProductKey[4];
- prekey_str[26] = lpcszProductKey[3];
- prekey_str[27] = lpcszProductKey[2];
- prekey_str[28] = lpcszProductKey[1];
- prekey_str[29] = lpcszProductKey[0];
- return CustomBase32Decode(prekey_str, 30, data, 14 + 5) ? 1 : 0;
- }
- // return key_type,
- // short product key if return 1 or 2
- // long product key if return 3
- // otherwise invalid
- int GetKeyType(const char* lpcszProductKey) {
- size_t KeyLength = strlen(lpcszProductKey);
- if (KeyLength == 23) {
- uint8_t data[20] = {};
- if (!DecodeShortProductKey(lpcszProductKey, data))
- return 0;
- uint64_t keydata_a = 0, keydata_b = 0;
- keydata_b |= (uint64_t)data[0];
- keydata_b |= (uint64_t)data[1] << 5;
- keydata_b |= (uint64_t)data[2] << 10;
- keydata_b |= (uint64_t)data[3] << 15;
- keydata_b |= (uint64_t)data[4] << 20;
- keydata_b |= (uint64_t)data[5] << 25;
- keydata_b |= (uint64_t)data[6] << 30;
- keydata_b |= (uint64_t)data[7] << 35;
- keydata_b |= (uint64_t)data[8] << 40;
- keydata_b |= (uint64_t)data[9] << 45;
- keydata_b |= (uint64_t)data[10] << 50;
- keydata_b |= (uint64_t)data[11] << 55;
- keydata_b |= (uint64_t)data[12] << 60;
- keydata_a |= (uint64_t)data[12] >> 4;
- keydata_a |= (uint64_t)data[13] << 1;
- keydata_a |= (uint64_t)data[14] << 6;
- keydata_a |= (uint64_t)data[15] << 11;
- keydata_a |= (uint64_t)data[16] << 16;
- keydata_a |= (uint64_t)data[17] << 21;
- keydata_a |= (uint64_t)data[18] << 26;
- keydata_a |= (uint64_t)data[19] << 31;
- int checksum = 0;
- if ((keydata_a & 0xc8b85c312ull) == 0x882818002ull && (keydata_b & 0x30688298668b32aull) == 0x306880904202200ull) {
- for (int i = 0; i < 20; ++i) {
- if (i == 12)
- continue;
- checksum += data[i];
- }
- if (checksum % 32 == data[12])
- return 1;
- } else if ((keydata_a & 0x6306a9612ull) == 0x430228000ull && (keydata_b & 0xc4d0ac3165804a43ull) == 0x4050a01165800a42ull) {
- for (int i = 0; i < 20; ++i) {
- if (i == 3)
- continue;
- checksum += data[i];
- }
- if (checksum % 32 == data[3])
- return 2;
- }
- } else if (KeyLength == 34) {
- return 3;
- }
- return 0;
- }
- void help() {
- printf("Usage:\n");
- printf(" ./TuxeraNTFS-verifier [path to tuxera_key.bin] <Product Key>\n");
- printf("\n");
- }
- int VerifyShortProductKey(const char* lpcszProductKey) {
- if (strlen(lpcszProductKey) != 23)
- return 0;
- char buf[25] = {};
- uint8_t Hash[6] = {};
- sprintf(buf, "%s\n", lpcszProductKey);
- argon2_hash(1,
- 1 << 16,
- 1,
- buf,
- sizeof(buf),
- salt_for_short_product_key,
- sizeof(salt_for_short_product_key),
- Hash,
- sizeof(Hash),
- NULL,
- 0,
- Argon2_d,
- ARGON2_VERSION_13);
- return IsTheKeyRecorded(Hash);
- }
- int VerifyLongProductKey(uint8_t key_data[14 + 5], const EC_POINT* PublicKey) {
- int status = 0;
- BIGNUM* s = NULL;
- BIGNUM* h = NULL;
- EC_GROUP* ec_curve = NULL;
- EC_POINT* R = NULL;
- BIGNUM* Rx = NULL;
- BIGNUM* Ry = NULL;
- uint8_t bin_R[2][14] = {};
- uint8_t Hash[5] = {};
- s = BN_bin2bn(key_data, 14, NULL);
- if (s == NULL)
- goto On_VerifyLongProductKey_Error;
- h = BN_bin2bn(key_data + 14, 5, NULL);
- if (h == NULL)
- goto On_VerifyLongProductKey_Error;
- ec_curve = EC_GROUP_new_by_curve_name(NID_secp112r1);
- if (ec_curve == NULL)
- goto On_VerifyLongProductKey_Error;
- R = EC_POINT_new(ec_curve);
- if (R == NULL)
- goto On_VerifyLongProductKey_Error;
- Rx = BN_new();
- if (Rx == NULL)
- goto On_VerifyLongProductKey_Error;
- Ry = BN_new();
- if (Ry == NULL)
- goto On_VerifyLongProductKey_Error;
- if (!EC_POINT_mul(ec_curve, R, s, PublicKey, h, NULL))
- goto On_VerifyLongProductKey_Error;
- if (!EC_POINT_get_affine_coordinates_GFp(ec_curve, R, Rx, Ry, NULL))
- goto On_VerifyLongProductKey_Error;
- BN_bn2bin(Rx, bin_R[0] + 14 - BN_num_bytes(Rx));
- BN_bn2bin(Ry, bin_R[1] + 14 - BN_num_bytes(Ry));
- argon2_hash(1,
- 1 << 16,
- 1,
- bin_R,
- sizeof(bin_R),
- salt_for_long_product_key,
- sizeof(salt_for_long_product_key),
- Hash,
- sizeof(Hash),
- NULL,
- 0,
- Argon2_d,
- ARGON2_VERSION_13);
- Hash[4] &= 0xFC;
- status = memcmp(key_data + 14, Hash, 5) == 0 ? 1 : 0;
- On_VerifyLongProductKey_Error:
- if (Ry)
- BN_free(Ry);
- if (Rx)
- BN_free(Rx);
- if (R)
- EC_POINT_free(R);
- if (ec_curve)
- EC_GROUP_free(ec_curve);
- if (h)
- BN_free(h);
- if (s)
- BN_free(s);
- return status;
- }
- EC_POINT* LoadPublicKey(const char* key_file) {
- EC_GROUP* ec_curve = NULL;
- EC_POINT* PublicKey = NULL;
- uint8_t binPublicKey[2][14] = {};
- BIGNUM* Px = NULL;
- BIGNUM* Py = NULL;
- ec_curve = EC_GROUP_new_by_curve_name(NID_secp112r1);
- if (ec_curve == NULL)
- goto On_LoadPublicKey_Error;
- PublicKey = EC_POINT_new(ec_curve);
- if (PublicKey == NULL)
- goto On_LoadPublicKey_Error;
- if (key_file == NULL) {
- memcpy(binPublicKey, OfficialPublicKey, sizeof(OfficialPublicKey));
- } else {
- int fd = -1;
- fd = open(key_file, O_RDONLY);
- if (fd == -1) {
- EC_POINT_free(PublicKey);
- PublicKey = NULL;
- goto On_LoadPublicKey_Error;
- }
- read(fd, binPublicKey, 14);
- if (14 != read(fd, binPublicKey[0], 14)) {
- EC_POINT_free(PublicKey);
- PublicKey = NULL;
- goto On_LoadPublicKey_Error;
- }
- if (14 != read(fd, binPublicKey[1], 14)) {
- EC_POINT_free(PublicKey);
- PublicKey = NULL;
- goto On_LoadPublicKey_Error;
- }
- }
- Px = BN_bin2bn(binPublicKey[0], sizeof(binPublicKey[0]), NULL);
- if (Px == NULL) {
- EC_POINT_free(PublicKey);
- PublicKey = NULL;
- goto On_LoadPublicKey_Error;
- }
- Py = BN_bin2bn(binPublicKey[1], sizeof(binPublicKey[1]), NULL);
- if (Py == NULL) {
- EC_POINT_free(PublicKey);
- PublicKey = NULL;
- goto On_LoadPublicKey_Error;
- }
- if (!EC_POINT_set_affine_coordinates_GFp(ec_curve, PublicKey, Px, Py, NULL)) {
- EC_POINT_free(PublicKey);
- PublicKey = NULL;
- goto On_LoadPublicKey_Error;
- }
- On_LoadPublicKey_Error:
- if (Py)
- BN_free(Py);
- if (Px)
- BN_free(Px);
- if (ec_curve)
- EC_GROUP_free(ec_curve);
- return PublicKey;
- }
- int main(int argc, char* argv[]) {
- if (argc != 2 && argc != 3) {
- help();
- return 0;
- }
- int KeyType = GetKeyType(argv[argc - 1]);
- switch (KeyType) {
- case 1:
- case 2:
- printf("%s\n", VerifyShortProductKey(argv[argc - 1]) ? "Valid Key" : "Invalid Key");
- break;
- case 3: {
- uint8_t key_data[14 + 5] = {};
- EC_POINT* PublicKey = NULL;
- PublicKey = LoadPublicKey(argc == 3 ? argv[1] : NULL);
- if (PublicKey == NULL) {
- printf("Failed to load public key.\n");
- return 0;
- }
- if (!DecodeLongProductKey(argv[argc - 1], key_data)) {
- printf("Invalid Key\n");
- EC_POINT_free(PublicKey);
- return 0;
- }
- printf("%s\n", VerifyLongProductKey(key_data, PublicKey) ? "Valid Key" : "Invalid Key");
- EC_POINT_free(PublicKey);
- }
- break;
- default:
- printf("Invalid Key\n");
- break;
- }
- return 0;
- }
|