2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 2009-2015 The OpenLDAP Foundation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
11 * A copy of this license is available in the file LICENSE in the
12 * top-level directory of the distribution or, alternatively, at
13 * <http://www.OpenLDAP.org/license.html>.
16 * This work was initially developed by HAMANO Tsukasa <hamano@osstech.co.jp>
22 #include <ac/string.h>
26 #include <openssl/evp.h>
28 #define PBKDF2_ITERATION 10000
29 #define PBKDF2_SALT_SIZE 16
30 #define PBKDF2_SHA1_DK_SIZE 20
31 #define PBKDF2_SHA256_DK_SIZE 32
32 #define PBKDF2_SHA512_DK_SIZE 64
33 #define PBKDF2_MAX_DK_SIZE 64
35 const struct berval pbkdf2_scheme = BER_BVC("{PBKDF2}");
36 const struct berval pbkdf2_sha1_scheme = BER_BVC("{PBKDF2-SHA1}");
37 const struct berval pbkdf2_sha256_scheme = BER_BVC("{PBKDF2-SHA256}");
38 const struct berval pbkdf2_sha512_scheme = BER_BVC("{PBKDF2-SHA512}");
41 * Converting base64 string to adapted base64 string.
42 * Adapted base64 encode is identical to general base64 encode except
43 * that it uses '.' instead of '+', and omits trailing padding '=' and
45 * see http://pythonhosted.org/passlib/lib/passlib.utils.html
46 * This is destructive function.
48 static int b64_to_ab64(char *str)
64 * Converting adapted base64 string to base64 string.
65 * dstsize will require src length + 2, due to output string have
66 * potential to append "=" or "==".
67 * return -1 if few output buffer.
69 static int ab64_to_b64(char *src, char *dst, size_t dstsize){
72 for(i=0; p[i] && p[i] != '$'; i++){
94 static int pbkdf2_format(
95 const struct berval *sc,
97 const struct berval *salt,
98 const struct berval *dk,
103 char salt_b64[LUTIL_BASE64_ENCODE_LEN(PBKDF2_SALT_SIZE) + 1];
104 char dk_b64[LUTIL_BASE64_ENCODE_LEN(PBKDF2_MAX_DK_SIZE) + 1];
106 rc = lutil_b64_ntop((unsigned char *)salt->bv_val, salt->bv_len,
107 salt_b64, sizeof(salt_b64));
109 return LUTIL_PASSWD_ERR;
111 b64_to_ab64(salt_b64);
112 rc = lutil_b64_ntop((unsigned char *)dk->bv_val, dk->bv_len,
113 dk_b64, sizeof(dk_b64));
115 return LUTIL_PASSWD_ERR;
118 msg_len = asprintf(&msg->bv_val, "%s%d$%s$%s",
119 sc->bv_val, iteration,
123 return LUTIL_PASSWD_ERR;
126 msg->bv_len = msg_len;
127 return LUTIL_PASSWD_OK;
130 static int pbkdf2_encrypt(
131 const struct berval *scheme,
132 const struct berval *passwd,
136 unsigned char salt_value[PBKDF2_SALT_SIZE];
138 unsigned char dk_value[PBKDF2_MAX_DK_SIZE];
140 int iteration = PBKDF2_ITERATION;
144 salt.bv_val = (char *)salt_value;
145 salt.bv_len = sizeof(salt_value);
146 dk.bv_val = (char *)dk_value;
147 if(!ber_bvcmp(scheme, &pbkdf2_scheme)){
148 dk.bv_len = PBKDF2_SHA1_DK_SIZE;
150 }else if(!ber_bvcmp(scheme, &pbkdf2_sha1_scheme)){
151 dk.bv_len = PBKDF2_SHA1_DK_SIZE;
153 }else if(!ber_bvcmp(scheme, &pbkdf2_sha256_scheme)){
154 dk.bv_len = PBKDF2_SHA256_DK_SIZE;
156 }else if(!ber_bvcmp(scheme, &pbkdf2_sha512_scheme)){
157 dk.bv_len = PBKDF2_SHA512_DK_SIZE;
160 return LUTIL_PASSWD_ERR;
163 if(lutil_entropy((unsigned char *)salt.bv_val, salt.bv_len) < 0){
164 return LUTIL_PASSWD_ERR;
167 if(!PKCS5_PBKDF2_HMAC(passwd->bv_val, passwd->bv_len,
168 (unsigned char *)salt.bv_val, salt.bv_len,
169 iteration, md, dk.bv_len, dk_value)){
170 return LUTIL_PASSWD_ERR;
173 #ifdef SLAPD_PBKDF2_DEBUG
174 printf("Encrypt for %s\n", scheme->bv_val);
175 printf(" Password:\t%s\n", passwd->bv_val);
177 printf(" Salt:\t\t");
179 for(i=0; i<salt.bv_len; i++){
180 printf("%02x", salt_value[i]);
183 printf(" Iteration:\t%d\n", iteration);
186 for(i=0; i<dk.bv_len; i++){
187 printf("%02x", dk_value[i]);
192 rc = pbkdf2_format(scheme, iteration, &salt, &dk, msg);
194 #ifdef SLAPD_PBKDF2_DEBUG
195 printf(" Output:\t%s\n", msg->bv_val);
201 static int pbkdf2_check(
202 const struct berval *scheme,
203 const struct berval *passwd,
204 const struct berval *cred,
210 /* salt_value require PBKDF2_SALT_SIZE + 1 in lutil_b64_pton. */
211 unsigned char salt_value[PBKDF2_SALT_SIZE + 1];
212 char salt_b64[LUTIL_BASE64_ENCODE_LEN(PBKDF2_SALT_SIZE) + 1];
213 /* dk_value require PBKDF2_MAX_DK_SIZE + 1 in lutil_b64_pton. */
214 unsigned char dk_value[PBKDF2_MAX_DK_SIZE + 1];
215 char dk_b64[LUTIL_BASE64_ENCODE_LEN(PBKDF2_MAX_DK_SIZE) + 1];
216 unsigned char input_dk_value[PBKDF2_MAX_DK_SIZE];
220 #ifdef SLAPD_PBKDF2_DEBUG
221 printf("Checking for %s\n", scheme->bv_val);
222 printf(" Stored Value:\t%s\n", passwd->bv_val);
223 printf(" Input Cred:\t%s\n", cred->bv_val);
226 if(!ber_bvcmp(scheme, &pbkdf2_scheme)){
227 dk_len = PBKDF2_SHA1_DK_SIZE;
229 }else if(!ber_bvcmp(scheme, &pbkdf2_sha1_scheme)){
230 dk_len = PBKDF2_SHA1_DK_SIZE;
232 }else if(!ber_bvcmp(scheme, &pbkdf2_sha256_scheme)){
233 dk_len = PBKDF2_SHA256_DK_SIZE;
235 }else if(!ber_bvcmp(scheme, &pbkdf2_sha512_scheme)){
236 dk_len = PBKDF2_SHA512_DK_SIZE;
239 return LUTIL_PASSWD_ERR;
242 iteration = atoi(passwd->bv_val);
244 return LUTIL_PASSWD_ERR;
248 ptr = strchr(passwd->bv_val, '$');
250 return LUTIL_PASSWD_ERR;
252 ptr++; /* skip '$' */
253 rc = ab64_to_b64(ptr, salt_b64, sizeof(salt_b64));
255 return LUTIL_PASSWD_ERR;
258 ptr = strchr(ptr, '$');
260 return LUTIL_PASSWD_ERR;
262 ptr++; /* skip '$' */
263 rc = ab64_to_b64(ptr, dk_b64, sizeof(dk_b64));
265 return LUTIL_PASSWD_ERR;
268 /* The targetsize require PBKDF2_SALT_SIZE + 1 in lutil_b64_pton. */
269 rc = lutil_b64_pton(salt_b64, salt_value, PBKDF2_SALT_SIZE + 1);
271 return LUTIL_PASSWD_ERR;
274 /* consistency check */
275 if(rc != PBKDF2_SALT_SIZE){
276 return LUTIL_PASSWD_ERR;
279 /* The targetsize require PBKDF2_MAX_DK_SIZE + 1 in lutil_b64_pton. */
280 rc = lutil_b64_pton(dk_b64, dk_value, sizeof(dk_value));
282 return LUTIL_PASSWD_ERR;
285 /* consistency check */
287 return LUTIL_PASSWD_ERR;
290 if(!PKCS5_PBKDF2_HMAC(cred->bv_val, cred->bv_len,
291 salt_value, PBKDF2_SALT_SIZE,
292 iteration, md, dk_len, input_dk_value)){
293 return LUTIL_PASSWD_ERR;
296 rc = memcmp(dk_value, input_dk_value, dk_len);
297 #ifdef SLAPD_PBKDF2_DEBUG
298 printf(" Iteration:\t%d\n", iteration);
299 printf(" Base64 Salt:\t%s\n", salt_b64);
300 printf(" Base64 DK:\t%s\n", dk_b64);
302 printf(" Stored Salt:\t");
303 for(i=0; i<PBKDF2_SALT_SIZE; i++){
304 printf("%02x", salt_value[i]);
308 printf(" Stored DK:\t");
309 for(i=0; i<dk_len; i++){
310 printf("%02x", dk_value[i]);
314 printf(" Input DK:\t");
315 for(i=0; i<dk_len; i++){
316 printf("%02x", input_dk_value[i]);
319 printf(" Result:\t%d\n", rc);
321 return rc?LUTIL_PASSWD_ERR:LUTIL_PASSWD_OK;
324 int init_module(int argc, char *argv[]) {
326 rc = lutil_passwd_add((struct berval *)&pbkdf2_scheme,
327 pbkdf2_check, pbkdf2_encrypt);
329 rc = lutil_passwd_add((struct berval *)&pbkdf2_sha1_scheme,
330 pbkdf2_check, pbkdf2_encrypt);
333 rc = lutil_passwd_add((struct berval *)&pbkdf2_sha256_scheme,
334 pbkdf2_check, pbkdf2_encrypt);
337 rc = lutil_passwd_add((struct berval *)&pbkdf2_sha512_scheme,
338 pbkdf2_check, pbkdf2_encrypt);
344 * indent-tabs-mode: t