pbkdf2.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // ECOin - Copyright (c) - 2014/2022 - GPLv3 - epsylon@riseup.net (https://03c8.net)
  2. #include <string.h>
  3. #include "pbkdf2.h"
  4. static inline uint32_t
  5. be32dec(const void *pp)
  6. {
  7. const uint8_t *p = (uint8_t const *)pp;
  8. return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) +
  9. ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24));
  10. }
  11. static inline void
  12. be32enc(void *pp, uint32_t x)
  13. {
  14. uint8_t * p = (uint8_t *)pp;
  15. p[3] = x & 0xff;
  16. p[2] = (x >> 8) & 0xff;
  17. p[1] = (x >> 16) & 0xff;
  18. p[0] = (x >> 24) & 0xff;
  19. }
  20. /* Initialize an HMAC-SHA256 operation with the given key. */
  21. void
  22. HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen)
  23. {
  24. unsigned char pad[64];
  25. unsigned char khash[32];
  26. const unsigned char * K = (const unsigned char *)_K;
  27. size_t i;
  28. /* If Klen > 64, the key is really SHA256(K). */
  29. if (Klen > 64) {
  30. SHA256_Init(&ctx->ictx);
  31. SHA256_Update(&ctx->ictx, K, Klen);
  32. SHA256_Final(khash, &ctx->ictx);
  33. K = khash;
  34. Klen = 32;
  35. }
  36. /* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */
  37. SHA256_Init(&ctx->ictx);
  38. memset(pad, 0x36, 64);
  39. for (i = 0; i < Klen; i++)
  40. pad[i] ^= K[i];
  41. SHA256_Update(&ctx->ictx, pad, 64);
  42. /* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */
  43. SHA256_Init(&ctx->octx);
  44. memset(pad, 0x5c, 64);
  45. for (i = 0; i < Klen; i++)
  46. pad[i] ^= K[i];
  47. SHA256_Update(&ctx->octx, pad, 64);
  48. /* Clean the stack. */
  49. memset(khash, 0, 32);
  50. }
  51. /* Add bytes to the HMAC-SHA256 operation. */
  52. void
  53. HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void *in, size_t len)
  54. {
  55. /* Feed data to the inner SHA256 operation. */
  56. SHA256_Update(&ctx->ictx, in, len);
  57. }
  58. /* Finish an HMAC-SHA256 operation. */
  59. void
  60. HMAC_SHA256_Final(unsigned char digest[32], HMAC_SHA256_CTX * ctx)
  61. {
  62. unsigned char ihash[32];
  63. /* Finish the inner SHA256 operation. */
  64. SHA256_Final(ihash, &ctx->ictx);
  65. /* Feed the inner hash to the outer SHA256 operation. */
  66. SHA256_Update(&ctx->octx, ihash, 32);
  67. /* Finish the outer SHA256 operation. */
  68. SHA256_Final(digest, &ctx->octx);
  69. /* Clean the stack. */
  70. memset(ihash, 0, 32);
  71. }
  72. void
  73. PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt,
  74. size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen)
  75. {
  76. HMAC_SHA256_CTX PShctx, hctx;
  77. size_t i;
  78. uint8_t ivec[4];
  79. uint8_t U[32];
  80. uint8_t T[32];
  81. uint64_t j;
  82. int k;
  83. size_t clen;
  84. /* Compute HMAC state after processing P and S. */
  85. HMAC_SHA256_Init(&PShctx, passwd, passwdlen);
  86. HMAC_SHA256_Update(&PShctx, salt, saltlen);
  87. /* Iterate through the blocks. */
  88. for (i = 0; i * 32 < dkLen; i++) {
  89. /* Generate INT(i + 1). */
  90. be32enc(ivec, (uint32_t)(i + 1));
  91. /* Compute U_1 = PRF(P, S || INT(i)). */
  92. memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX));
  93. HMAC_SHA256_Update(&hctx, ivec, 4);
  94. HMAC_SHA256_Final(U, &hctx);
  95. /* T_i = U_1 ... */
  96. memcpy(T, U, 32);
  97. for (j = 2; j <= c; j++) {
  98. /* Compute U_j. */
  99. HMAC_SHA256_Init(&hctx, passwd, passwdlen);
  100. HMAC_SHA256_Update(&hctx, U, 32);
  101. HMAC_SHA256_Final(U, &hctx);
  102. /* ... xor U_j ... */
  103. for (k = 0; k < 32; k++)
  104. T[k] ^= U[k];
  105. }
  106. /* Copy as many bytes as necessary into buf. */
  107. clen = dkLen - i * 32;
  108. if (clen > 32)
  109. clen = 32;
  110. memcpy(&buf[i * 32], T, clen);
  111. }
  112. /* Clean PShctx, since we never called _Final on it. */
  113. memset(&PShctx, 0, sizeof(HMAC_SHA256_CTX));
  114. }