1 /*
2 * Copyright 2014-2022 The GmSSL Project. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the License); you may
5 * not use this file except in compliance with the License.
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 */
9
10
11
12 /*
13 PBKDF2 (P, S, c, dkLen)
14
15 Options: PRF underlying pseudorandom function (hLen
16 denotes the length in octets of the
17 pseudorandom function output)
18
19 Input: P password, an octet string
20 S salt, an octet string
21 c iteration count, a positive integer
22 dkLen intended length in octets of the derived
23 key, a positive integer, at most
24 (2^32 - 1) * hLen
25
26 Output: DK derived key, a dkLen-octet string
27
28 Steps:
29
30 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and
31 stop.
32
33 2. Let l be the number of hLen-octet blocks in the derived key,
34 rounding up, and let r be the number of octets in the last
35 block:
36
37 l = CEIL (dkLen / hLen) ,
38 r = dkLen - (l - 1) * hLen .
39
40 Here, CEIL (x) is the "ceiling" function, i.e. the smallest
41 integer greater than, or equal to, x.
42
43 3. For each block of the derived key apply the function F defined
44 below to the password P, the salt S, the iteration count c, and
45 the block index to compute the block:
46
47 T_1 = F (P, S, c, 1) ,
48 T_2 = F (P, S, c, 2) ,
49 ...
50 T_l = F (P, S, c, l) ,
51
52 where the function F is defined as the exclusive-or sum of the
53 first c iterates of the underlying pseudorandom function PRF
54 applied to the password P and the concatenation of the salt S
55 and the block index i:
56
57 F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c
58
59 where
60
61 U_1 = PRF (P, S || INT (i)) ,
62 U_2 = PRF (P, U_1) ,
63 ...
64 U_c = PRF (P, U_{c-1}) .
65
66 Here, INT (i) is a four-octet encoding of the integer i, most
67 significant octet first.
68
69 4. Concatenate the blocks and extract the first dkLen octets to
70 produce a derived key DK:
71
72 DK = T_1 || T_2 || ... || T_l<0..r-1>
73
74 5. Output the derived key DK.
75 */
76
77 #include <stdio.h>
78 #include <stdlib.h>
79 #include <string.h>
80 #include <gmssl/asn1.h>
81 #include <gmssl/hmac.h>
82 #include <gmssl/digest.h>
83 #include <gmssl/error.h>
84 #include <gmssl/oid.h>
85 #include <gmssl/endian.h>
86 #include <gmssl/mem.h>
87
pbkdf2_genkey(const DIGEST * digest,const char * pass,size_t passlen,const uint8_t * salt,size_t saltlen,size_t count,size_t outlen,uint8_t * out)88 int pbkdf2_genkey(const DIGEST *digest,
89 const char *pass, size_t passlen,
90 const uint8_t *salt, size_t saltlen, size_t count,
91 size_t outlen, uint8_t *out)
92 {
93 HMAC_CTX ctx;
94 HMAC_CTX ctx_tmpl;
95 uint32_t iter = 1;
96 uint8_t iter_be[4];
97 uint8_t tmp_block[64];
98 uint8_t key_block[64];
99 size_t len;
100
101 hmac_init(&ctx_tmpl, digest, (uint8_t *)pass, passlen);
102
103 while (outlen > 0) {
104 size_t i;
105
106 PUTU32(iter_be, iter);
107 iter++;
108
109 ctx = ctx_tmpl;
110 hmac_update(&ctx, salt, saltlen);
111 hmac_update(&ctx, iter_be, sizeof(iter_be));
112 hmac_finish(&ctx, tmp_block, &len);
113 memcpy(key_block, tmp_block, len);
114
115 for (i = 1; i < count; i++) {
116 ctx = ctx_tmpl;
117 hmac_update(&ctx, tmp_block, len);
118 hmac_finish(&ctx, tmp_block, &len);
119 memxor(key_block, tmp_block, len);
120 }
121
122 if (outlen < len) {
123 memcpy(out, key_block, outlen);
124 out += outlen;
125 outlen = 0;
126 } else {
127 memcpy(out, key_block, len);
128 out += len;
129 outlen -= len;
130 }
131 }
132
133 memset(&ctx, 0, sizeof(ctx));
134 memset(key_block, 0, sizeof(key_block));
135 memset(tmp_block, 0, sizeof(key_block));
136 return 1;
137 }
138
pbkdf2_hmac_sm3_genkey(const char * pass,size_t passlen,const uint8_t * salt,size_t saltlen,size_t count,size_t outlen,uint8_t * out)139 int pbkdf2_hmac_sm3_genkey(
140 const char *pass, size_t passlen,
141 const uint8_t *salt, size_t saltlen, size_t count,
142 size_t outlen, uint8_t *out)
143 {
144 SM3_HMAC_CTX ctx;
145 SM3_HMAC_CTX ctx_tmpl;
146 uint32_t iter = 1;
147 uint8_t iter_be[4];
148 uint8_t tmp_block[SM3_DIGEST_SIZE];
149 uint8_t key_block[SM3_DIGEST_SIZE];
150 size_t len;
151
152 sm3_hmac_init(&ctx_tmpl, (uint8_t *)pass, passlen);
153
154 while (outlen > 0) {
155 size_t i;
156
157 PUTU32(iter_be, iter);
158 iter++;
159
160 ctx = ctx_tmpl;
161 sm3_hmac_update(&ctx, salt, saltlen);
162 sm3_hmac_update(&ctx, iter_be, sizeof(iter_be));
163 sm3_hmac_finish(&ctx, tmp_block);
164 memcpy(key_block, tmp_block, SM3_DIGEST_SIZE);
165
166 for (i = 1; i < count; i++) {
167 ctx = ctx_tmpl;
168 sm3_hmac_update(&ctx, tmp_block, SM3_DIGEST_SIZE);
169 sm3_hmac_finish(&ctx, tmp_block);
170 memxor(key_block, tmp_block, SM3_DIGEST_SIZE);
171 }
172
173 if (outlen < SM3_DIGEST_SIZE) {
174 memcpy(out, key_block, outlen);
175 out += outlen;
176 outlen = 0;
177 } else {
178 memcpy(out, key_block, SM3_DIGEST_SIZE);
179 out += len;
180 outlen -= len;
181 }
182 }
183
184 memset(&ctx, 0, sizeof(ctx));
185 memset(key_block, 0, sizeof(key_block));
186 memset(tmp_block, 0, sizeof(key_block));
187 return 1;
188 }
189