2
0

Crypto.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. #include "Crypto.h"
  2. #include <mbedtls/base64.h> // for mbedtls_base64_encode, mbedtls_base64_...
  3. #include <mbedtls/bignum.h> // for mbedtls_mpi_free, mbedtls_mpi_init
  4. #include <mbedtls/ctr_drbg.h> // for mbedtls_ctr_drbg_free, mbedtls_ctr_drb...
  5. #include <mbedtls/entropy.h> // for mbedtls_entropy_free, mbedtls_entropy_...
  6. #include <mbedtls/pkcs5.h> // for mbedtls_pkcs5_pbkdf2_hmac
  7. #include <cstdint> // for uint8_t
  8. #include <stdexcept> // for runtime_error
  9. extern "C" {
  10. #include "aes.h" // for AES_ECB_decrypt, AES_init_ctx, AES_ctx
  11. }
  12. static unsigned char DHGenerator[1] = {2};
  13. CryptoMbedTLS::CryptoMbedTLS() {}
  14. CryptoMbedTLS::~CryptoMbedTLS() {
  15. if (aesCtxInitialized) {
  16. mbedtls_aes_free(&aesCtx);
  17. }
  18. }
  19. std::vector<uint8_t> CryptoMbedTLS::base64Decode(const std::string& data) {
  20. // Calculate max decode length
  21. size_t requiredSize;
  22. mbedtls_base64_encode(nullptr, 0, &requiredSize, (unsigned char*)data.c_str(),
  23. data.size());
  24. std::vector<uint8_t> output(requiredSize);
  25. size_t outputLen = 0;
  26. mbedtls_base64_decode(output.data(), requiredSize, &outputLen,
  27. (unsigned char*)data.c_str(), data.size());
  28. return std::vector<uint8_t>(output.begin(), output.begin() + outputLen);
  29. }
  30. std::string CryptoMbedTLS::base64Encode(const std::vector<uint8_t>& data) {
  31. // Calculate max output length
  32. size_t requiredSize;
  33. mbedtls_base64_encode(nullptr, 0, &requiredSize, data.data(), data.size());
  34. std::vector<uint8_t> output(requiredSize);
  35. size_t outputLen = 0;
  36. mbedtls_base64_encode(output.data(), requiredSize, &outputLen, data.data(),
  37. data.size());
  38. return std::string(output.begin(), output.begin() + outputLen);
  39. }
  40. // Sha1
  41. void CryptoMbedTLS::sha1Init() {
  42. // Init mbedtls md context, pick sha1
  43. mbedtls_md_init(&sha1Context);
  44. mbedtls_md_setup(&sha1Context, mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), 1);
  45. mbedtls_md_starts(&sha1Context);
  46. }
  47. void CryptoMbedTLS::sha1Update(const std::string& s) {
  48. sha1Update(std::vector<uint8_t>(s.begin(), s.end()));
  49. }
  50. void CryptoMbedTLS::sha1Update(const std::vector<uint8_t>& vec) {
  51. mbedtls_md_update(&sha1Context, vec.data(), vec.size());
  52. }
  53. std::vector<uint8_t> CryptoMbedTLS::sha1FinalBytes() {
  54. std::vector<uint8_t> digest(20); // SHA1 digest size
  55. mbedtls_md_finish(&sha1Context, digest.data());
  56. mbedtls_md_free(&sha1Context);
  57. return digest;
  58. }
  59. std::string CryptoMbedTLS::sha1Final() {
  60. auto digest = sha1FinalBytes();
  61. return std::string(digest.begin(), digest.end());
  62. }
  63. // HMAC SHA1
  64. std::vector<uint8_t> CryptoMbedTLS::sha1HMAC(
  65. const std::vector<uint8_t>& inputKey, const std::vector<uint8_t>& message) {
  66. std::vector<uint8_t> digest(20); // SHA1 digest size
  67. sha1Init();
  68. mbedtls_md_hmac_starts(&sha1Context, inputKey.data(), inputKey.size());
  69. mbedtls_md_hmac_update(&sha1Context, message.data(), message.size());
  70. mbedtls_md_hmac_finish(&sha1Context, digest.data());
  71. mbedtls_md_free(&sha1Context);
  72. return digest;
  73. }
  74. // AES CTR
  75. void CryptoMbedTLS::aesCTRXcrypt(const std::vector<uint8_t>& key,
  76. std::vector<uint8_t>& iv, uint8_t* buffer,
  77. size_t nbytes) {
  78. if (!aesCtxInitialized) {
  79. mbedtls_aes_init(&aesCtx);
  80. aesCtxInitialized = true;
  81. }
  82. // needed for internal cache
  83. size_t off = 0;
  84. unsigned char streamBlock[16] = {0};
  85. // set IV
  86. if (mbedtls_aes_setkey_enc(&aesCtx, key.data(), key.size() * 8) != 0) {
  87. throw std::runtime_error("Failed to set AES key");
  88. }
  89. // Perform decrypt
  90. if (mbedtls_aes_crypt_ctr(&aesCtx, nbytes, &off, iv.data(), streamBlock,
  91. buffer, buffer) != 0) {
  92. throw std::runtime_error("Failed to decrypt");
  93. }
  94. }
  95. void CryptoMbedTLS::aesECBdecrypt(const std::vector<uint8_t>& key,
  96. std::vector<uint8_t>& data) {
  97. struct AES_ctx aesCtr;
  98. AES_init_ctx(&aesCtr, key.data());
  99. for (unsigned int x = 0; x < data.size() / 16; x++) {
  100. AES_ECB_decrypt(&aesCtr, data.data() + (x * 16));
  101. }
  102. }
  103. // PBKDF2
  104. std::vector<uint8_t> CryptoMbedTLS::pbkdf2HmacSha1(
  105. const std::vector<uint8_t>& password, const std::vector<uint8_t>& salt,
  106. int iterations, int digestSize) {
  107. auto digest = std::vector<uint8_t>(digestSize);
  108. // Init sha context
  109. sha1Init();
  110. mbedtls_pkcs5_pbkdf2_hmac(&sha1Context, password.data(), password.size(),
  111. salt.data(), salt.size(), iterations, digestSize,
  112. digest.data());
  113. // Free sha context
  114. mbedtls_md_free(&sha1Context);
  115. return digest;
  116. }
  117. void CryptoMbedTLS::dhInit() {
  118. privateKey = generateVectorWithRandomData(DH_KEY_SIZE);
  119. // initialize big num
  120. mbedtls_mpi prime, generator, res, privKey;
  121. mbedtls_mpi_init(&prime);
  122. mbedtls_mpi_init(&generator);
  123. mbedtls_mpi_init(&privKey);
  124. mbedtls_mpi_init(&res);
  125. // Read bin into big num mpi
  126. mbedtls_mpi_read_binary(&prime, DHPrime, sizeof(DHPrime));
  127. mbedtls_mpi_read_binary(&generator, DHGenerator, sizeof(DHGenerator));
  128. mbedtls_mpi_read_binary(&privKey, privateKey.data(), DH_KEY_SIZE);
  129. // perform diffie hellman G^X mod P
  130. mbedtls_mpi_exp_mod(&res, &generator, &privKey, &prime, NULL);
  131. // Write generated public key to vector
  132. this->publicKey = std::vector<uint8_t>(DH_KEY_SIZE);
  133. mbedtls_mpi_write_binary(&res, publicKey.data(), DH_KEY_SIZE);
  134. // Release memory
  135. mbedtls_mpi_free(&prime);
  136. mbedtls_mpi_free(&generator);
  137. mbedtls_mpi_free(&privKey);
  138. mbedtls_mpi_free(&res);
  139. }
  140. std::vector<uint8_t> CryptoMbedTLS::dhCalculateShared(
  141. const std::vector<uint8_t>& remoteKey) {
  142. // initialize big num
  143. mbedtls_mpi prime, remKey, res, privKey;
  144. mbedtls_mpi_init(&prime);
  145. mbedtls_mpi_init(&remKey);
  146. mbedtls_mpi_init(&privKey);
  147. mbedtls_mpi_init(&res);
  148. // Read bin into big num mpi
  149. mbedtls_mpi_read_binary(&prime, DHPrime, sizeof(DHPrime));
  150. mbedtls_mpi_read_binary(&remKey, remoteKey.data(), remoteKey.size());
  151. mbedtls_mpi_read_binary(&privKey, privateKey.data(), DH_KEY_SIZE);
  152. // perform diffie hellman (G^Y)^X mod P (for shared secret)
  153. mbedtls_mpi_exp_mod(&res, &remKey, &privKey, &prime, NULL);
  154. auto sharedKey = std::vector<uint8_t>(DH_KEY_SIZE);
  155. mbedtls_mpi_write_binary(&res, sharedKey.data(), DH_KEY_SIZE);
  156. // Release memory
  157. mbedtls_mpi_free(&prime);
  158. mbedtls_mpi_free(&remKey);
  159. mbedtls_mpi_free(&privKey);
  160. mbedtls_mpi_free(&res);
  161. return sharedKey;
  162. }
  163. // Random stuff
  164. std::vector<uint8_t> CryptoMbedTLS::generateVectorWithRandomData(
  165. size_t length) {
  166. std::vector<uint8_t> randomVector(length);
  167. mbedtls_entropy_context entropy;
  168. mbedtls_ctr_drbg_context ctrDrbg;
  169. // Personification string
  170. const char* pers = "cspotGen";
  171. // init entropy and random num generator
  172. mbedtls_entropy_init(&entropy);
  173. mbedtls_ctr_drbg_init(&ctrDrbg);
  174. // Seed the generator
  175. mbedtls_ctr_drbg_seed(&ctrDrbg, mbedtls_entropy_func, &entropy,
  176. (const unsigned char*)pers, 7);
  177. // Generate random bytes
  178. mbedtls_ctr_drbg_random(&ctrDrbg, randomVector.data(), length);
  179. // Release memory
  180. mbedtls_entropy_free(&entropy);
  181. mbedtls_ctr_drbg_free(&ctrDrbg);
  182. return randomVector;
  183. }