• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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