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