ClientCDKey.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855
  1. // ClientCDKey
  2. // Class that implements WON CD-Key functionality for use by clients. Allows conversion
  3. // to/from human readable string. Implements persistance to the registry in a secure
  4. // manner. Implements a lightweight validation check of the key.
  5. // Uncomment the following line to use original Lightweight check algorithm. This
  6. // should only be needed for CD-Keys used in Beta builds of Homeworld.
  7. //#define __LWCHECK_ORIG
  8. #include "common/won.h"
  9. #include "common/OutputOperators.h"
  10. #include "common/RegKey.h"
  11. #include "common/CRC16.h"
  12. #include "crypt/BFSymmetricKey.h"
  13. #include "crypt/CryptException.h"
  14. #include "ClientCDKey.h"
  15. #ifdef _DEBUG
  16. #include "common/WONException.h"
  17. #include "common/WONExceptCodes.h"
  18. #endif
  19. // private namespace for using and constants
  20. namespace {
  21. using std::hex;
  22. using std::dec;
  23. using WONCommon::RawBuffer;
  24. using WONCommon::RegKey;
  25. using WONCommon::CRC16;
  26. using WONCrypt::BFSymmetricKey;
  27. using WONCDKey::ClientCDKey;
  28. // Constants
  29. const unsigned char BETA_MASK = 0x01;
  30. const unsigned int BINARYKEY_LEN = 16;
  31. const char SKIPCHAR_MAP[] = { '-', ' ', '\t', '\0' };
  32. const char* STRINGKEY_MAP = "CVCNCVCNCVCNCVCNNNNN";
  33. const unsigned int STRINGKEY_LEN = strlen(STRINGKEY_MAP);
  34. const int DASH_OFFSET = 4;
  35. const string REG_CDKEY_PATH(REG_CONST::REG_WON_KEY_NAME + REG_CONST::REG_BACKSLASH + "CDKeys");
  36. const string INVALIDKEY_STR( "#######INVALID KEY######");
  37. };
  38. // ** Constructors / Destructor
  39. // Standard constructor
  40. ClientCDKey::ClientCDKey(const string& theProductR) :
  41. mProduct(theProductR),
  42. mValidity(Invalid),
  43. mLightCheck(0),
  44. mKey(),
  45. mStrKey(),
  46. mBinKey()
  47. {}
  48. // Copy Constructor
  49. ClientCDKey::ClientCDKey(const ClientCDKey& theKeyR) :
  50. mProduct(theKeyR.mProduct),
  51. mValidity(theKeyR.mValidity),
  52. mLightCheck(theKeyR.mLightCheck),
  53. mKey(theKeyR.mKey),
  54. mStrKey(theKeyR.mStrKey),
  55. mBinKey(theKeyR.mBinKey)
  56. {}
  57. // Destructor
  58. ClientCDKey::~ClientCDKey()
  59. {}
  60. // ** Private Methods **
  61. // ClientCDKey::RemoveSkipChars
  62. // Removes all occurences of chars in the SKIPCHAR_MAP from specified string. Note
  63. // that string is modified in place.
  64. void
  65. ClientCDKey::RemoveSkipChars(string& theStrR)
  66. {
  67. WTRACE("ClientCDKey::RemoveSkipChars");
  68. WDBG_LL("ClientCDKey::RemoveSkipChars Old string=" << theStrR);
  69. // Delete all chars from SKIPCHAR map
  70. for (const char* p=SKIPCHAR_MAP; *p; p++)
  71. {
  72. string::size_type aPos = theStrR.rfind(*p);
  73. while (aPos != string::npos)
  74. {
  75. theStrR.erase(aPos, 1);
  76. aPos = theStrR.rfind(*p);
  77. }
  78. }
  79. WDBG_LL("ClientCDKey::RemoveSkipChars New string=" << theStrR);
  80. }
  81. // ClientCDKey::ValFromBits
  82. // Generates unsignec har value starting a bit theOffset and using theBits bits from
  83. // 8 byte buffer.
  84. char
  85. ClientCDKey::ValFromBits(const __int64& aBuf, unsigned int theOffset, unsigned int theBits)
  86. {
  87. WTRACE("ClientCDKey::ValFromBits");
  88. char aRet = 0;
  89. while (theBits-- > 0)
  90. {
  91. aRet <<= 1;
  92. __int64 aMask = 1;
  93. aMask <<= (theOffset + theBits);
  94. if (aBuf & aMask)
  95. aRet |= 0x01;
  96. }
  97. return aRet;
  98. }
  99. // ClientCDKey::ProcessCChar
  100. // Places a C into 8 byte buffer starting at theOffset. Cs use 4 bits. Value of
  101. // theOffset is incremented by 4.
  102. bool
  103. ClientCDKey::ProcessCChar(__int64& theBuf, unsigned int& theOffset, char theChar)
  104. {
  105. WTRACE("ClientCDKey::ProcessCChar");
  106. WDBG_LL("ClientCDKey::ProcessCChar char=" << theChar << " offset=" << theOffset);
  107. bool aRet = true;
  108. __int64 aMask = 0;
  109. // Determine mask based on char
  110. switch (toupper(theChar))
  111. {
  112. case 'B':
  113. aMask = 0; break;
  114. case 'C':
  115. aMask = 1; break;
  116. case 'D':
  117. aMask = 2; break;
  118. case 'F':
  119. aMask = 3; break;
  120. case 'G':
  121. aMask = 4; break;
  122. case 'J':
  123. aMask = 5; break;
  124. case 'L':
  125. aMask = 6; break;
  126. case 'M':
  127. aMask = 7; break;
  128. case 'N':
  129. aMask = 8; break;
  130. case 'P':
  131. aMask = 9; break;
  132. case 'R':
  133. aMask = 10; break;
  134. case 'S':
  135. aMask = 11; break;
  136. case 'T':
  137. aMask = 12; break;
  138. case 'W':
  139. aMask = 13; break;
  140. case 'X':
  141. aMask = 14; break;
  142. case 'Z':
  143. aMask = 15; break;
  144. default:
  145. WDBG_LH("ClientCDKey::ProcessCChar Bad input, char=" << theChar);
  146. return false;
  147. }
  148. // Shift mask by offset and or with buffer. Update offset
  149. theBuf |= (aMask << theOffset);
  150. theOffset += 4;
  151. return aRet;
  152. }
  153. // ClientCDKey::ProcessVChar
  154. // Places a V into 8 byte buffer starting at theOffset. Vs use 2 bits. Value of
  155. // theOffset is incremented by 2.
  156. bool
  157. ClientCDKey::ProcessVChar(__int64& theBuf, unsigned int& theOffset, char theChar)
  158. {
  159. WTRACE("ClientCDKey::ProcessVChar");
  160. WDBG_LL("ClientCDKey::ProcessVChar char=" << theChar << " offset=" << theOffset);
  161. bool aRet = true;
  162. __int64 aMask = 0;
  163. // Determine mask based on char
  164. switch (toupper(theChar))
  165. {
  166. case 'A':
  167. aMask = 0; break;
  168. case 'E':
  169. aMask = 1; break;
  170. case 'U':
  171. aMask = 2; break;
  172. case 'Y':
  173. aMask = 3; break;
  174. default:
  175. WDBG_LH("ClientCDKey::ProcessVChar Bad input, char=" << theChar);
  176. return false;
  177. }
  178. // Shift mask by offset and or with buffer. Update offset
  179. theBuf |= (aMask << theOffset);
  180. theOffset += 2;
  181. return aRet;
  182. }
  183. // ClientCDKey::ProcessNChar
  184. // Places a N into 8 byte buffer starting at theOffset. Ns use 3 bits. Value of
  185. // theOffset is incremented by 3.
  186. bool
  187. ClientCDKey::ProcessNChar(__int64& theBuf, unsigned int& theOffset, char theChar)
  188. {
  189. WTRACE("ClientCDKey::ProcessNChar");
  190. WDBG_LL("ClientCDKey::ProcessNChar char=" << theChar << " offset=" << theOffset);
  191. bool aRet = ((isdigit(theChar)) && (theChar > '1'));
  192. if (aRet)
  193. {
  194. __int64 aMask = (theChar - '0') - 2;
  195. // Shift mask by offset and or with buffer. Update offset
  196. theBuf |= (aMask << theOffset);
  197. theOffset += 3;
  198. }
  199. return aRet;
  200. }
  201. // ClientCDKey::BuildCChar
  202. // Extracts a C from buffer starting at offset theOffset. Extracted C is appened
  203. // to mStrKey. Cs use 4 bits. Value of theOffset is incremented by 4.
  204. void
  205. ClientCDKey::BuildCChar(const __int64& theBuf, unsigned int& theOffset) const
  206. {
  207. WTRACE("ClientCDKey::BuildCChar");
  208. WDBG_LL("ClientCDKey::BuildCChar offset=" << theOffset);
  209. char aChar = 0;
  210. // Determine mask based on char
  211. switch (ValFromBits(theBuf, theOffset, 4))
  212. {
  213. case 0:
  214. aChar = 'B'; break;
  215. case 1:
  216. aChar = 'C'; break;
  217. case 2:
  218. aChar = 'D'; break;
  219. case 3:
  220. aChar = 'F'; break;
  221. case 4:
  222. aChar = 'G'; break;
  223. case 5:
  224. aChar = 'J'; break;
  225. case 6:
  226. aChar = 'L'; break;
  227. case 7:
  228. aChar = 'M'; break;
  229. case 8:
  230. aChar = 'N'; break;
  231. case 9:
  232. aChar = 'P'; break;
  233. case 10:
  234. aChar = 'R'; break;
  235. case 11:
  236. aChar = 'S'; break;
  237. case 12:
  238. aChar = 'T'; break;
  239. case 13:
  240. aChar = 'W'; break;
  241. case 14:
  242. aChar = 'X'; break;
  243. case 15:
  244. aChar = 'Z'; break;
  245. #ifdef _DEBUG
  246. default:
  247. throw WONCommon::WONException(WONCommon::ExSoftwareFail, __LINE__, __FILE__,
  248. "ClientCDKey::BuildCChar ValFromBits returned invalid char!");
  249. break;
  250. #endif
  251. }
  252. // Add char to buf and update offset
  253. WDBG_LL("ClientCDKey::BuildCChar Char=" << aChar);
  254. mStrKey += aChar;
  255. theOffset += 4;
  256. }
  257. // ClientCDKey::BuildVChar
  258. // Extracts a V from buffer starting at offset theOffset. Extracted V is appened
  259. // to mStrKey. Vs use 2 bits. Value of theOffset is incremented by 2.
  260. void
  261. ClientCDKey::BuildVChar(const __int64& theBuf, unsigned int& theOffset) const
  262. {
  263. WTRACE("ClientCDKey::BuildVChar");
  264. WDBG_LL("ClientCDKey::BuildVChar offset=" << theOffset);
  265. char aChar = 0;
  266. // Determine mask based on char
  267. switch (ValFromBits(theBuf, theOffset, 2))
  268. {
  269. case 0:
  270. aChar = 'A'; break;
  271. case 1:
  272. aChar = 'E'; break;
  273. case 2:
  274. aChar = 'U'; break;
  275. case 3:
  276. aChar = 'Y'; break;
  277. #ifdef _DEBUG
  278. default:
  279. throw WONCommon::WONException(WONCommon::ExSoftwareFail, __LINE__, __FILE__,
  280. "ClientCDKey::BuildVChar ValFromBits returned invalid char!");
  281. break;
  282. #endif
  283. }
  284. // Add char to buf and update offset
  285. WDBG_LL("ClientCDKey::BuildVChar Char=" << aChar);
  286. mStrKey += aChar;
  287. theOffset += 2;
  288. }
  289. // ClientCDKey::BuildNChar
  290. // Extracts a N from buffer starting at offset theOffset. Extracted N is appened
  291. // to mStrKey. Ns use 32 bits. Value of theOffset is incremented by 3.
  292. void
  293. ClientCDKey::BuildNChar(const __int64& theBuf, unsigned int& theOffset) const
  294. {
  295. WTRACE("ClientCDKey::BuildNChar");
  296. WDBG_LL("ClientCDKey::BuildNChar offset=" << theOffset);
  297. char aChar = ValFromBits(theBuf, theOffset, 3) + '0' + 2;
  298. #ifdef _DEBUG
  299. if ((aChar < '2') || (aChar > '9'))
  300. throw WONCommon::WONException(WONCommon::ExSoftwareFail, __LINE__, __FILE__,
  301. "ClientCDKey::BuildNChar ValFromBits returned invalid char!");
  302. #endif
  303. // Add char to buf and update offset
  304. WDBG_LL("ClientCDKey::BuildNChar Char=" << aChar);
  305. mStrKey += aChar;
  306. theOffset += 3;
  307. }
  308. // ClientCDKey::CreateSymmetricKey
  309. // Creates a symmetric key from product name used to save/load CD-Key to/from
  310. // the registry. Symmetric key is created via a series of CRCs on the product.
  311. void
  312. ClientCDKey::CreateSymmetricKey(BFSymmetricKey& theSymKeyR) const
  313. {
  314. WTRACE("ClientCDKey::CreateSymmetricKey");
  315. WDBG_LL("ClientCDKey::CreateSymmetricKey from product=" << mProduct);
  316. CRC16 aCRC;
  317. RawBuffer aBuf;
  318. // CRC the product and use it as 1st 2 bytes of key
  319. aCRC.Put(mProduct);
  320. unsigned short aCheckSum = aCRC.GetCRC();
  321. WDBG_LL("ClientCDKey::CreateSymmetricKey First CRC=" << aCheckSum);
  322. aBuf.assign(reinterpret_cast<unsigned char*>(&aCheckSum), sizeof(aCheckSum));
  323. // CRC each of 1st 3 chars of product and add them to key.
  324. for (int i=0; (i < 3) && (i < mProduct.size()); i++)
  325. {
  326. aCRC.Put(static_cast<unsigned char>(mProduct[i]));
  327. aCheckSum = aCRC.GetCRC();
  328. WDBG_LL("ClientCDKey::CreateSymmetricKey Add CRC=" << aCheckSum);
  329. aBuf.append(reinterpret_cast<unsigned char*>(&aCheckSum), sizeof(aCheckSum));
  330. }
  331. // Create the key
  332. WDBG_LL("ClientCDKey::CreateSymmetricKey Buf=" << aBuf);
  333. theSymKeyR.Create(aBuf.size(), aBuf.data());
  334. }
  335. // ** Protected Methods **
  336. // ClientCDKey::LightValidityCheck
  337. // Perform lightwight validty check on mKey. Return light checksum.
  338. unsigned char
  339. ClientCDKey::LightValidityCheck() const
  340. {
  341. WTRACE("ClientCDKey::LightValidityCheck");
  342. WDBG_LL("ClientCDKey::LightValidityCheck key=" << mKey);
  343. CRC16 aCRC;
  344. #ifndef __LWCHECK_ORIG
  345. aCRC.Put(mProduct);
  346. #endif
  347. aCRC.Put(mKey);
  348. WDBG_LL("ClientCDKey::LightValidityCheck Key CRC=" << aCRC.GetCRC());
  349. // Take the middle 8 bits of the the 16 bit CRC to get the 8-bit light check
  350. unsigned char aRet = (aCRC.GetCRC() & 0x0fff) >> 4;
  351. WDBG_LL(hex << "ClientCDKey::LightValidityCheck Checksum=" << aCRC.GetCRC() << " lightCheck=" << aRet << dec);
  352. return aRet;
  353. }
  354. // ClientCDKey::BuildStringKey
  355. // Build string representation of CD-Key from internal form.
  356. void
  357. ClientCDKey::BuildStringKey() const
  358. {
  359. WTRACE("ClientCDKey::BuildStringKey");
  360. __int64 aBuf = BufferFromFields();
  361. unsigned int anOffset = 0;
  362. // Extract each char from 8 byte vuffer and add to mStrKey
  363. WDBG_LL("ClientCDKey::BuildStringKey Buf=" << hex << aBuf << dec);
  364. mStrKey.erase();
  365. for (int i=0; i < STRINGKEY_LEN;)
  366. {
  367. switch (STRINGKEY_MAP[i])
  368. {
  369. case 'C':
  370. BuildCChar(aBuf, anOffset); break;
  371. case 'V':
  372. BuildVChar(aBuf, anOffset); break;
  373. case 'N':
  374. BuildNChar(aBuf, anOffset); break;
  375. #ifdef _DEBUG
  376. default:
  377. throw WONCommon::WONException(WONCommon::ExSoftwareFail, __LINE__, __FILE__,
  378. "ClientCDKey::BuildStringKey Unknown char is STRINGKEY_MAP!");
  379. break;
  380. #endif
  381. }
  382. // Add dash every four chars
  383. if ((((++i) % DASH_OFFSET) == 0) && (i < STRINGKEY_LEN))
  384. mStrKey += '-';
  385. }
  386. WDBG_LL("ClientCDKey::BuildStringKey StrKey=" << mStrKey);
  387. }
  388. // ClientCDKey::FieldsFromBuffer
  389. // Fill in internal fields from 8 byte buffer. Light check is byte 3, key is bytes
  390. // 0-2 and 4-7.
  391. void
  392. ClientCDKey::FieldsFromBuffer(const __int64& theBuf)
  393. {
  394. WTRACE("ClientCDKey::FieldsFromBuffer");
  395. WDBG_LL("ClientCDKey::FieldsFromBuffer Buffer=" << hex << theBuf << dec);
  396. const unsigned char* aP = reinterpret_cast<const unsigned char*>(&theBuf);
  397. // Extract lightCheck, byte 3
  398. mLightCheck = *(aP+3);
  399. WDBG_LL("ClientCDKey::FieldsFromBuffer lightCheck=" << hex << mLightCheck << dec);
  400. // Key value is rest of bytes (0-2, 4-7)
  401. mKey.assign(aP, 3);
  402. mKey.append(aP+4, 4);
  403. WDBG_LL("ClientCDKey::FieldsFromBuffer key=" << mKey);
  404. }
  405. // ClientCDKey::BufferFromFields
  406. // Build 8 byte raw form from internal fields. Light check is byte 3, key is bytes
  407. // 0-2 and 4-7.
  408. __int64
  409. ClientCDKey::BufferFromFields() const
  410. {
  411. WTRACE("ClientCDKey::BufferFromFields");
  412. __int64 aRet = 0;
  413. unsigned char* aP = reinterpret_cast<unsigned char*>(&aRet);
  414. // Put lightCheck, byte 3
  415. WDBG_LL("ClientCDKey::BufferFromFields lightCheck=" << hex << mLightCheck << dec);
  416. *(aP+3) = mLightCheck;
  417. // Put key, bytes 0-2, 4-7
  418. memcpy(aP, mKey.data(), 3);
  419. memcpy(aP+4, mKey.data()+3, 4);
  420. WDBG_LL("ClientCDKey::FieldsFromBuffer Buffer=" << hex << aRet << dec);
  421. return aRet;
  422. }
  423. // ClientCDKey::DecryptKey
  424. // Decrypt 16 byte binary key into 8 byte buffer. Uses symmetric key built from product
  425. // name for decryption.
  426. bool
  427. ClientCDKey::DecryptKey(__int64& theBufR)
  428. {
  429. WTRACE("ClientCDKey::DecryptKey");
  430. try
  431. {
  432. // Build symmetric key from product
  433. WDBG_LL("ClientCDKey::DecryptKey Creating symmetric key from product=" << mProduct);
  434. BFSymmetricKey aSymKey;
  435. CreateSymmetricKey(aSymKey);
  436. // Decrypt the key
  437. WDBG_LL("ClientCDKey::DecryptKey Decrypting CDKey.");
  438. BFSymmetricKey::CryptReturn aDecrypt(aSymKey.Decrypt(mBinKey.data(), mBinKey.size()));
  439. auto_ptr<unsigned char> aDelP(aDecrypt.first);
  440. if (aDecrypt.second != sizeof(theBufR))
  441. {
  442. WDBG_LM("ClientCDKey::DecryptKey Decrypt of key has bad length.");
  443. return false;
  444. }
  445. // Fill buffer with decrypted key
  446. memcpy(static_cast<void*>(&theBufR), aDecrypt.first, sizeof(theBufR));
  447. }
  448. catch (WONCrypt::CryptException& anExR)
  449. {
  450. WDBG_LH("ClientCDKey::DecryptKey exception decrypting key: " << anExR);
  451. return false;
  452. }
  453. return true;
  454. }
  455. // ClientCDKey::EncryptKey
  456. // Encrypts into 8 byte buffer in 16 byte binary. Uses symmetric key built from product
  457. // name for encryption.
  458. bool
  459. ClientCDKey::EncryptKey(const __int64& theBufR) const
  460. {
  461. WTRACE("ClientCDKey::EncryptKey");
  462. try
  463. {
  464. // Build symmetric key from product
  465. WDBG_LL("ClientCDKey::EncryptKey Creating symmetric key from product=" << mProduct);
  466. BFSymmetricKey aSymKey;
  467. CreateSymmetricKey(aSymKey);
  468. // Decrypt the key
  469. WDBG_LL("ClientCDKey::EncryptKey Encrypting CDKey.");
  470. BFSymmetricKey::CryptReturn anEncrypt(aSymKey.Encrypt(reinterpret_cast<const unsigned char*>(&theBufR), sizeof(theBufR)));
  471. auto_ptr<unsigned char> aDelP(anEncrypt.first);
  472. if (anEncrypt.second != BINARYKEY_LEN)
  473. {
  474. WDBG_LM("ClientCDKey::EncryptKey Encrypt of key has bad length.");
  475. return false;
  476. }
  477. // Fill BinKey with encrypted key
  478. mBinKey.assign(anEncrypt.first, anEncrypt.second);
  479. }
  480. catch (WONCrypt::CryptException& anExR)
  481. {
  482. WDBG_LH("ClientCDKey::EncryptKey exception encrypting key: " << anExR);
  483. return false;
  484. }
  485. return true;
  486. }
  487. // ** Public Methods **
  488. // Assignment operator
  489. ClientCDKey&
  490. ClientCDKey::operator=(const ClientCDKey& theKeyR)
  491. {
  492. if (this != &theKeyR) // protect vs a = a
  493. {
  494. mProduct = theKeyR.mProduct;
  495. mLightCheck = theKeyR.mLightCheck;
  496. mKey = theKeyR.mKey;
  497. mValidity = theKeyR.mValidity;
  498. mStrKey = theKeyR.mStrKey;
  499. mBinKey = theKeyR.mBinKey;
  500. }
  501. return *this;
  502. }
  503. // ClientCDKey::IsEqual
  504. // Comapre 2 client keys for equality.
  505. bool
  506. ClientCDKey::IsEqual(const ClientCDKey& theKeyR) const
  507. {
  508. WTRACE("ClientCDKey::IsEqual");
  509. return ((mLightCheck == theKeyR.mLightCheck) && (mKey == theKeyR.mKey) &&
  510. (mProduct == theKeyR.mProduct));
  511. }
  512. // ClientCDKey::IsValid
  513. // Check client key for validity. Performs lightweight check only if needed.
  514. bool
  515. ClientCDKey::IsValid() const
  516. {
  517. WTRACE("ClientCDKey::IsValid");
  518. if (mValidity == Unknown)
  519. mValidity = (LightValidityCheck() == mLightCheck ? Valid : Invalid);
  520. WDBG_LM("ClientCDKey::IsValid Validity=" << mValidity);
  521. return (mValidity == Valid);
  522. }
  523. // ClientCDKey::IsBeta
  524. // Checks to see if this is a beta key. Key is beta if bit 0 of first byte of
  525. // mKey is set.
  526. bool
  527. ClientCDKey::IsBeta() const
  528. {
  529. WTRACE("ClientCDKey::IsBeta");
  530. WDBG_LM("ClientCDKey::IsBeta Key=" << mKey);
  531. return (mKey.size() >= 1 ? (mKey[0] & BETA_MASK) : false);
  532. }
  533. // ClientCDKey::Init(__int64)
  534. // Initializes key from 8 byte raw buffer. Does not validate key.
  535. bool
  536. ClientCDKey::Init(const __int64& theKeyR)
  537. {
  538. WTRACE("ClientCDKey::Init(__int64)");
  539. WDBG_LH("ClientCDKey::Init(__int64) Key=" << hex << theKeyR << dec);
  540. mValidity = Unknown;
  541. mKey.erase();
  542. mStrKey.erase();
  543. mBinKey.erase();
  544. WDBG_LM("ClientCDKey::Init(__int64) Extracting fields.");
  545. FieldsFromBuffer(theKeyR);
  546. return true;
  547. }
  548. // ClientCDKey::Init(string)
  549. // Initializes key from human readbale string. Does not validate key.
  550. bool
  551. ClientCDKey::Init(const string& theKeyR)
  552. {
  553. WTRACE("ClientCDKey::Init(string)");
  554. WDBG_LH("ClientCDKey::Init(string) String=" << theKeyR);
  555. mValidity = Unknown;
  556. mKey.erase();
  557. mBinKey.erase();
  558. // Init StrKey and remove and dashes
  559. mStrKey = theKeyR;
  560. RemoveSkipChars(mStrKey);
  561. // Validate length
  562. if (mStrKey.size() != STRINGKEY_LEN)
  563. {
  564. WDBG_LH("ClientCDKey::Init(string) Key length invalid, len=" << mStrKey.size());
  565. mValidity = Invalid;
  566. return false;
  567. }
  568. // Process each char in string
  569. WDBG_LM("ClientCDKey::Init(string) Parsing string key.");
  570. __int64 aBuf = 0;
  571. unsigned int anOffset = 0;
  572. for (int i=0; i < STRINGKEY_LEN; i++)
  573. {
  574. bool aTst = true;
  575. switch (STRINGKEY_MAP[i])
  576. {
  577. case 'C':
  578. aTst = ProcessCChar(aBuf, anOffset, mStrKey[i]); break;
  579. case 'V':
  580. aTst = ProcessVChar(aBuf, anOffset, mStrKey[i]); break;
  581. case 'N':
  582. aTst = ProcessNChar(aBuf, anOffset, mStrKey[i]); break;
  583. #ifdef _DEBUG
  584. default:
  585. throw WONCommon::WONException(WONCommon::ExSoftwareFail, __LINE__, __FILE__,
  586. "ClientCDKey::Init(string) Unknown char is STRINGKEY_MAP!");
  587. break;
  588. #endif
  589. }
  590. if (! aTst)
  591. {
  592. WDBG_LH("ClientCDKey::Init(string) Parse of string to binary failed.");
  593. mValidity = Invalid;
  594. return false;
  595. }
  596. }
  597. // Extract fields from buffer
  598. WDBG_LM("ClientCDKey::Init(string) Extracting fields.");
  599. FieldsFromBuffer(aBuf);
  600. mStrKey.erase();
  601. return true;
  602. }
  603. // ClientCDKey::Init(RawBuffer)
  604. // Initializes key from encrypted binary buffer. Does not validate key.
  605. bool
  606. ClientCDKey::Init(const RawBuffer& theKeyR)
  607. {
  608. WTRACE("ClientCDKey::Init(RawBuffer)");
  609. WDBG_LH("ClientCDKey::Init(RawBuffer) Buf=" << theKeyR);
  610. mValidity = Unknown;
  611. mKey.erase();
  612. mStrKey.erase();
  613. // Init BinKey and validate length
  614. mBinKey = theKeyR;
  615. if (mBinKey.size() != BINARYKEY_LEN)
  616. {
  617. WDBG_LH("ClientCDKey::Init(RawBuffer) Key length invalid, len=" << mBinKey.size());
  618. mValidity = Invalid;
  619. return false;
  620. }
  621. // Build symmetric key from Product name
  622. __int64 aBuf = 0;
  623. if (! DecryptKey(aBuf))
  624. {
  625. WDBG_LH("ClientCDKey::Init(RawBuffer) Decrypt of bin key failed.");
  626. mValidity = Invalid;
  627. return false;
  628. }
  629. WDBG_LM("ClientCDKey::Init(RawBuffer) Extracting fields.");
  630. FieldsFromBuffer(aBuf);
  631. return true;
  632. }
  633. // ClientCDKey::AsString
  634. // Returns human readable string form of CD-Key. Builds string form if needed.
  635. const string&
  636. ClientCDKey::AsString(bool validate) const
  637. {
  638. WTRACE("ClientCDKey::AsString");
  639. if ((mStrKey.empty()) || (mValidity != Valid))
  640. {
  641. if ((! validate) || (IsValid()))
  642. BuildStringKey();
  643. else
  644. mStrKey = INVALIDKEY_STR;
  645. }
  646. return mStrKey;
  647. }
  648. // ClientCDKey::AsString
  649. // Returns encrypted binary form of CD-Key. Builds binary form if needed.
  650. const RawBuffer&
  651. ClientCDKey::AsBinary() const
  652. {
  653. WTRACE("ClientCDKey::AsBinary");
  654. if (mBinKey.empty())
  655. {
  656. if (IsValid())
  657. EncryptKey(BufferFromFields());
  658. else
  659. mBinKey.erase();
  660. }
  661. return mBinKey;
  662. }
  663. // ClientCDKey::Load
  664. // Loads CD-Key from WON standard location in registry. Entry is registry must be
  665. // the enrypted binary form. Calls Init(RawBuffer).
  666. bool
  667. ClientCDKey::Load()
  668. {
  669. WTRACE("ClientCDKey::Load");
  670. WDBG_LM("ClientCDKey::Load Loading key from registry.");
  671. // Open registry key
  672. RegKey aRegKey(REG_CDKEY_PATH, HKEY_LOCAL_MACHINE);
  673. if (! aRegKey.IsOpen())
  674. {
  675. WDBG_LH("ClientCDKey::Load Fail open registry key: " << REG_CDKEY_PATH);
  676. mValidity = Invalid;
  677. return false;
  678. }
  679. // Fetch key from registry for value product
  680. unsigned char* aBufP = NULL;
  681. unsigned long aLen = 0;
  682. if (aRegKey.GetValue(mProduct, aBufP, aLen) != RegKey::Ok)
  683. {
  684. WDBG_LH("ClientCDKey::Load Fail fetch key value for product=" << mProduct);
  685. mValidity = Invalid;
  686. return false;
  687. }
  688. // Build buffer and call Init(RawBuffer)
  689. RawBuffer aKey(aBufP, aLen);
  690. delete aBufP;
  691. return Init(aKey);
  692. }
  693. // ClientCDKey::Save
  694. // Saves CD-Key to WON standard location in registry. Entry is saved to registry as
  695. // the enrypted binary form. Calls AsBinary().
  696. bool
  697. ClientCDKey::Save() const
  698. {
  699. WTRACE("ClientCDKey::Save");
  700. WDBG_LM("ClientCDKey::Save Save encrypted key to registry.");
  701. // Open registry key
  702. RegKey aRegKey(REG_CDKEY_PATH, HKEY_LOCAL_MACHINE, true);
  703. if (! aRegKey.IsOpen())
  704. {
  705. WDBG_LH("ClientCDKey::Save Fail open registry key: " << REG_CDKEY_PATH);
  706. return false;
  707. }
  708. // Build encrypted binary form if needed and write to registry
  709. AsBinary();
  710. return aRegKey.SetValue(mProduct.c_str(), mBinKey.data(), mBinKey.size());
  711. }
  712. // ClientCDKey::CleanReg
  713. // Cleans registry of CD-Key in WON standard location.
  714. bool
  715. ClientCDKey::CleanReg()
  716. {
  717. WTRACE("ClientCDKey::CleanReg");
  718. WDBG_LM("ClientCDKey::CleanReg Clean key from registry.");
  719. // Open registry key
  720. RegKey aRegKey(REG_CDKEY_PATH, HKEY_LOCAL_MACHINE, true);
  721. if (! aRegKey.IsOpen())
  722. {
  723. WDBG_LH("ClientCDKey::CleanReg Fail open registry key: " << REG_CDKEY_PATH);
  724. return false;
  725. }
  726. // Delete key from registry
  727. return aRegKey.DeleteValue(mProduct.c_str());
  728. }