pw-pbkdf2.c revision 1.1.1.1 1 /* $NetBSD: pw-pbkdf2.c,v 1.1.1.1 2017/02/09 01:46:42 christos Exp $ */
2
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 2009-2016 The OpenLDAP Foundation.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
11 * Public License.
12 *
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
16 */
17 /* ACKNOWLEDGEMENT:
18 * This work was initially developed by HAMANO Tsukasa <hamano (at) osstech.co.jp>
19 */
20
21 #define _GNU_SOURCE
22
23 #include <sys/cdefs.h>
24 __RCSID("$NetBSD: pw-pbkdf2.c,v 1.1.1.1 2017/02/09 01:46:42 christos Exp $");
25
26 #include "portable.h"
27 #include <ac/string.h>
28 #include "lber_pvt.h"
29 #include "lutil.h"
30 #include <stdio.h>
31 #include <stdlib.h>
32
33 #ifdef HAVE_OPENSSL
34 #include <openssl/evp.h>
35 #elif HAVE_GNUTLS
36 #include <nettle/pbkdf2.h>
37 #include <nettle/hmac.h>
38 typedef void (*pbkdf2_hmac_update)(void *, unsigned, const uint8_t *);
39 typedef void (*pbkdf2_hmac_digest)(void *, unsigned, uint8_t *);
40 #else
41 #error Unsupported crypto backend.
42 #endif
43
44 #define PBKDF2_ITERATION 10000
45 #define PBKDF2_SALT_SIZE 16
46 #define PBKDF2_SHA1_DK_SIZE 20
47 #define PBKDF2_SHA256_DK_SIZE 32
48 #define PBKDF2_SHA512_DK_SIZE 64
49 #define PBKDF2_MAX_DK_SIZE 64
50
51 const struct berval pbkdf2_scheme = BER_BVC("{PBKDF2}");
52 const struct berval pbkdf2_sha1_scheme = BER_BVC("{PBKDF2-SHA1}");
53 const struct berval pbkdf2_sha256_scheme = BER_BVC("{PBKDF2-SHA256}");
54 const struct berval pbkdf2_sha512_scheme = BER_BVC("{PBKDF2-SHA512}");
55
56 /*
57 * Converting base64 string to adapted base64 string.
58 * Adapted base64 encode is identical to general base64 encode except
59 * that it uses '.' instead of '+', and omits trailing padding '=' and
60 * whitepsace.
61 * see http://pythonhosted.org/passlib/lib/passlib.utils.html
62 * This is destructive function.
63 */
64 static int b64_to_ab64(char *str)
65 {
66 char *p = str;
67 while(*p++){
68 if(*p == '+'){
69 *p = '.';
70 }
71 if(*p == '='){
72 *p = '\0';
73 break;
74 }
75 }
76 return 0;
77 }
78
79 /*
80 * Converting adapted base64 string to base64 string.
81 * dstsize will require src length + 2, due to output string have
82 * potential to append "=" or "==".
83 * return -1 if few output buffer.
84 */
85 static int ab64_to_b64(char *src, char *dst, size_t dstsize){
86 int i;
87 char *p = src;
88 for(i=0; p[i] && p[i] != '$'; i++){
89 if(i >= dstsize){
90 dst[0] = '\0';
91 return -1;
92 }
93 if(p[i] == '.'){
94 dst[i] = '+';
95 }else{
96 dst[i] = p[i];
97 }
98 }
99 for(;i%4;i++){
100 if(i >= dstsize){
101 dst[0] = '\0';
102 return -1;
103 }
104 dst[i] = '=';
105 }
106 dst[i] = '\0';
107 return 0;
108 }
109
110 static int pbkdf2_format(
111 const struct berval *sc,
112 int iteration,
113 const struct berval *salt,
114 const struct berval *dk,
115 struct berval *msg)
116 {
117
118 int rc, msg_len;
119 char salt_b64[LUTIL_BASE64_ENCODE_LEN(PBKDF2_SALT_SIZE) + 1];
120 char dk_b64[LUTIL_BASE64_ENCODE_LEN(PBKDF2_MAX_DK_SIZE) + 1];
121
122 rc = lutil_b64_ntop((unsigned char *)salt->bv_val, salt->bv_len,
123 salt_b64, sizeof(salt_b64));
124 if(rc < 0){
125 return LUTIL_PASSWD_ERR;
126 }
127 b64_to_ab64(salt_b64);
128 rc = lutil_b64_ntop((unsigned char *)dk->bv_val, dk->bv_len,
129 dk_b64, sizeof(dk_b64));
130 if(rc < 0){
131 return LUTIL_PASSWD_ERR;
132 }
133 b64_to_ab64(dk_b64);
134 msg_len = asprintf(&msg->bv_val, "%s%d$%s$%s",
135 sc->bv_val, iteration,
136 salt_b64, dk_b64);
137 if(msg_len < 0){
138 msg->bv_len = 0;
139 return LUTIL_PASSWD_ERR;
140 }
141
142 msg->bv_len = msg_len;
143 return LUTIL_PASSWD_OK;
144 }
145
146 static int pbkdf2_encrypt(
147 const struct berval *scheme,
148 const struct berval *passwd,
149 struct berval *msg,
150 const char **text)
151 {
152 unsigned char salt_value[PBKDF2_SALT_SIZE];
153 struct berval salt;
154 unsigned char dk_value[PBKDF2_MAX_DK_SIZE];
155 struct berval dk;
156 int iteration = PBKDF2_ITERATION;
157 int rc;
158 #ifdef HAVE_OPENSSL
159 const EVP_MD *md;
160 #elif HAVE_GNUTLS
161 struct hmac_sha1_ctx sha1_ctx;
162 struct hmac_sha256_ctx sha256_ctx;
163 struct hmac_sha512_ctx sha512_ctx;
164 void * current_ctx = NULL;
165 pbkdf2_hmac_update current_hmac_update = NULL;
166 pbkdf2_hmac_digest current_hmac_digest = NULL;
167 #endif
168
169 salt.bv_val = (char *)salt_value;
170 salt.bv_len = sizeof(salt_value);
171 dk.bv_val = (char *)dk_value;
172
173 #ifdef HAVE_OPENSSL
174 if(!ber_bvcmp(scheme, &pbkdf2_scheme)){
175 dk.bv_len = PBKDF2_SHA1_DK_SIZE;
176 md = EVP_sha1();
177 }else if(!ber_bvcmp(scheme, &pbkdf2_sha1_scheme)){
178 dk.bv_len = PBKDF2_SHA1_DK_SIZE;
179 md = EVP_sha1();
180 }else if(!ber_bvcmp(scheme, &pbkdf2_sha256_scheme)){
181 dk.bv_len = PBKDF2_SHA256_DK_SIZE;
182 md = EVP_sha256();
183 }else if(!ber_bvcmp(scheme, &pbkdf2_sha512_scheme)){
184 dk.bv_len = PBKDF2_SHA512_DK_SIZE;
185 md = EVP_sha512();
186 }else{
187 return LUTIL_PASSWD_ERR;
188 }
189 #elif HAVE_GNUTLS
190 if(!ber_bvcmp(scheme, &pbkdf2_scheme)){
191 dk.bv_len = PBKDF2_SHA1_DK_SIZE;
192 current_ctx = &sha1_ctx;
193 current_hmac_update = (pbkdf2_hmac_update) &hmac_sha1_update;
194 current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha1_digest;
195 hmac_sha1_set_key(current_ctx, passwd->bv_len, (const uint8_t *) passwd->bv_val);
196 }else if(!ber_bvcmp(scheme, &pbkdf2_sha1_scheme)){
197 dk.bv_len = PBKDF2_SHA1_DK_SIZE;
198 current_ctx = &sha1_ctx;
199 current_hmac_update = (pbkdf2_hmac_update) &hmac_sha1_update;
200 current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha1_digest;
201 hmac_sha1_set_key(current_ctx, passwd->bv_len, (const uint8_t *) passwd->bv_val);
202 }else if(!ber_bvcmp(scheme, &pbkdf2_sha256_scheme)){
203 dk.bv_len = PBKDF2_SHA256_DK_SIZE;
204 current_ctx = &sha256_ctx;
205 current_hmac_update = (pbkdf2_hmac_update) &hmac_sha256_update;
206 current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha256_digest;
207 hmac_sha256_set_key(current_ctx, passwd->bv_len, (const uint8_t *) passwd->bv_val);
208 }else if(!ber_bvcmp(scheme, &pbkdf2_sha512_scheme)){
209 dk.bv_len = PBKDF2_SHA512_DK_SIZE;
210 current_ctx = &sha512_ctx;
211 current_hmac_update = (pbkdf2_hmac_update) &hmac_sha512_update;
212 current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha512_digest;
213 hmac_sha512_set_key(current_ctx, passwd->bv_len, (const uint8_t *) passwd->bv_val);
214 }else{
215 return LUTIL_PASSWD_ERR;
216 }
217 #endif
218
219 if(lutil_entropy((unsigned char *)salt.bv_val, salt.bv_len) < 0){
220 return LUTIL_PASSWD_ERR;
221 }
222
223 #ifdef HAVE_OPENSSL
224 if(!PKCS5_PBKDF2_HMAC(passwd->bv_val, passwd->bv_len,
225 (unsigned char *)salt.bv_val, salt.bv_len,
226 iteration, md, dk.bv_len, dk_value)){
227 return LUTIL_PASSWD_ERR;
228 }
229 #elif HAVE_GNUTLS
230 PBKDF2(current_ctx, current_hmac_update, current_hmac_digest,
231 dk.bv_len, iteration,
232 salt.bv_len, (const uint8_t *) salt.bv_val,
233 dk.bv_len, dk_value);
234 #endif
235
236 #ifdef SLAPD_PBKDF2_DEBUG
237 printf("Encrypt for %s\n", scheme->bv_val);
238 printf(" Password:\t%s\n", passwd->bv_val);
239
240 printf(" Salt:\t\t");
241 int i;
242 for(i=0; i<salt.bv_len; i++){
243 printf("%02x", salt_value[i]);
244 }
245 printf("\n");
246 printf(" Iteration:\t%d\n", iteration);
247
248 printf(" DK:\t\t");
249 for(i=0; i<dk.bv_len; i++){
250 printf("%02x", dk_value[i]);
251 }
252 printf("\n");
253 #endif
254
255 rc = pbkdf2_format(scheme, iteration, &salt, &dk, msg);
256
257 #ifdef SLAPD_PBKDF2_DEBUG
258 printf(" Output:\t%s\n", msg->bv_val);
259 #endif
260
261 return rc;
262 }
263
264 static int pbkdf2_check(
265 const struct berval *scheme,
266 const struct berval *passwd,
267 const struct berval *cred,
268 const char **text)
269 {
270 int rc;
271 int iteration;
272
273 /* salt_value require PBKDF2_SALT_SIZE + 1 in lutil_b64_pton. */
274 unsigned char salt_value[PBKDF2_SALT_SIZE + 1];
275 char salt_b64[LUTIL_BASE64_ENCODE_LEN(PBKDF2_SALT_SIZE) + 1];
276 /* dk_value require PBKDF2_MAX_DK_SIZE + 1 in lutil_b64_pton. */
277 unsigned char dk_value[PBKDF2_MAX_DK_SIZE + 1];
278 char dk_b64[LUTIL_BASE64_ENCODE_LEN(PBKDF2_MAX_DK_SIZE) + 1];
279 unsigned char input_dk_value[PBKDF2_MAX_DK_SIZE];
280 size_t dk_len;
281 #ifdef HAVE_OPENSSL
282 const EVP_MD *md;
283 #elif HAVE_GNUTLS
284 struct hmac_sha1_ctx sha1_ctx;
285 struct hmac_sha256_ctx sha256_ctx;
286 struct hmac_sha512_ctx sha512_ctx;
287 void * current_ctx = NULL;
288 pbkdf2_hmac_update current_hmac_update = NULL;
289 pbkdf2_hmac_digest current_hmac_digest = NULL;
290 #endif
291
292 #ifdef SLAPD_PBKDF2_DEBUG
293 printf("Checking for %s\n", scheme->bv_val);
294 printf(" Stored Value:\t%s\n", passwd->bv_val);
295 printf(" Input Cred:\t%s\n", cred->bv_val);
296 #endif
297
298 #ifdef HAVE_OPENSSL
299 if(!ber_bvcmp(scheme, &pbkdf2_scheme)){
300 dk_len = PBKDF2_SHA1_DK_SIZE;
301 md = EVP_sha1();
302 }else if(!ber_bvcmp(scheme, &pbkdf2_sha1_scheme)){
303 dk_len = PBKDF2_SHA1_DK_SIZE;
304 md = EVP_sha1();
305 }else if(!ber_bvcmp(scheme, &pbkdf2_sha256_scheme)){
306 dk_len = PBKDF2_SHA256_DK_SIZE;
307 md = EVP_sha256();
308 }else if(!ber_bvcmp(scheme, &pbkdf2_sha512_scheme)){
309 dk_len = PBKDF2_SHA512_DK_SIZE;
310 md = EVP_sha512();
311 }else{
312 return LUTIL_PASSWD_ERR;
313 }
314 #elif HAVE_GNUTLS
315 if(!ber_bvcmp(scheme, &pbkdf2_scheme)){
316 dk_len = PBKDF2_SHA1_DK_SIZE;
317 current_ctx = &sha1_ctx;
318 current_hmac_update = (pbkdf2_hmac_update) &hmac_sha1_update;
319 current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha1_digest;
320 hmac_sha1_set_key(current_ctx, cred->bv_len, (const uint8_t *) cred->bv_val);
321 }else if(!ber_bvcmp(scheme, &pbkdf2_sha1_scheme)){
322 dk_len = PBKDF2_SHA1_DK_SIZE;
323 current_ctx = &sha1_ctx;
324 current_hmac_update = (pbkdf2_hmac_update) &hmac_sha1_update;
325 current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha1_digest;
326 hmac_sha1_set_key(current_ctx, cred->bv_len, (const uint8_t *) cred->bv_val);
327 }else if(!ber_bvcmp(scheme, &pbkdf2_sha256_scheme)){
328 dk_len = PBKDF2_SHA256_DK_SIZE;
329 current_ctx = &sha256_ctx;
330 current_hmac_update = (pbkdf2_hmac_update) &hmac_sha256_update;
331 current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha256_digest;
332 hmac_sha256_set_key(current_ctx, cred->bv_len, (const uint8_t *) cred->bv_val);
333 }else if(!ber_bvcmp(scheme, &pbkdf2_sha512_scheme)){
334 dk_len = PBKDF2_SHA512_DK_SIZE;
335 current_ctx = &sha512_ctx;
336 current_hmac_update = (pbkdf2_hmac_update) &hmac_sha512_update;
337 current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha512_digest;
338 hmac_sha512_set_key(current_ctx, cred->bv_len, (const uint8_t *) cred->bv_val);
339 }else{
340 return LUTIL_PASSWD_ERR;
341 }
342 #endif
343
344 iteration = atoi(passwd->bv_val);
345 if(iteration < 1){
346 return LUTIL_PASSWD_ERR;
347 }
348
349 char *ptr;
350 ptr = strchr(passwd->bv_val, '$');
351 if(!ptr){
352 return LUTIL_PASSWD_ERR;
353 }
354 ptr++; /* skip '$' */
355 rc = ab64_to_b64(ptr, salt_b64, sizeof(salt_b64));
356 if(rc < 0){
357 return LUTIL_PASSWD_ERR;
358 }
359
360 ptr = strchr(ptr, '$');
361 if(!ptr){
362 return LUTIL_PASSWD_ERR;
363 }
364 ptr++; /* skip '$' */
365 rc = ab64_to_b64(ptr, dk_b64, sizeof(dk_b64));
366 if(rc < 0){
367 return LUTIL_PASSWD_ERR;
368 }
369
370 /* The targetsize require PBKDF2_SALT_SIZE + 1 in lutil_b64_pton. */
371 rc = lutil_b64_pton(salt_b64, salt_value, PBKDF2_SALT_SIZE + 1);
372 if(rc < 0){
373 return LUTIL_PASSWD_ERR;
374 }
375
376 /* consistency check */
377 if(rc != PBKDF2_SALT_SIZE){
378 return LUTIL_PASSWD_ERR;
379 }
380
381 /* The targetsize require PBKDF2_MAX_DK_SIZE + 1 in lutil_b64_pton. */
382 rc = lutil_b64_pton(dk_b64, dk_value, sizeof(dk_value));
383 if(rc < 0){
384 return LUTIL_PASSWD_ERR;
385 }
386
387 /* consistency check */
388 if(rc != dk_len){
389 return LUTIL_PASSWD_ERR;
390 }
391
392 #ifdef HAVE_OPENSSL
393 if(!PKCS5_PBKDF2_HMAC(cred->bv_val, cred->bv_len,
394 salt_value, PBKDF2_SALT_SIZE,
395 iteration, md, dk_len, input_dk_value)){
396 return LUTIL_PASSWD_ERR;
397 }
398 #elif HAVE_GNUTLS
399 PBKDF2(current_ctx, current_hmac_update, current_hmac_digest,
400 dk_len, iteration,
401 PBKDF2_SALT_SIZE, salt_value,
402 dk_len, input_dk_value);
403 #endif
404
405 rc = memcmp(dk_value, input_dk_value, dk_len);
406 #ifdef SLAPD_PBKDF2_DEBUG
407 printf(" Iteration:\t%d\n", iteration);
408 printf(" Base64 Salt:\t%s\n", salt_b64);
409 printf(" Base64 DK:\t%s\n", dk_b64);
410 int i;
411 printf(" Stored Salt:\t");
412 for(i=0; i<PBKDF2_SALT_SIZE; i++){
413 printf("%02x", salt_value[i]);
414 }
415 printf("\n");
416
417 printf(" Stored DK:\t");
418 for(i=0; i<dk_len; i++){
419 printf("%02x", dk_value[i]);
420 }
421 printf("\n");
422
423 printf(" Input DK:\t");
424 for(i=0; i<dk_len; i++){
425 printf("%02x", input_dk_value[i]);
426 }
427 printf("\n");
428 printf(" Result:\t%d\n", rc);
429 #endif
430 return rc?LUTIL_PASSWD_ERR:LUTIL_PASSWD_OK;
431 }
432
433 int init_module(int argc, char *argv[]) {
434 int rc;
435 rc = lutil_passwd_add((struct berval *)&pbkdf2_scheme,
436 pbkdf2_check, pbkdf2_encrypt);
437 if(rc) return rc;
438 rc = lutil_passwd_add((struct berval *)&pbkdf2_sha1_scheme,
439 pbkdf2_check, pbkdf2_encrypt);
440 if(rc) return rc;
441
442 rc = lutil_passwd_add((struct berval *)&pbkdf2_sha256_scheme,
443 pbkdf2_check, pbkdf2_encrypt);
444 if(rc) return rc;
445
446 rc = lutil_passwd_add((struct berval *)&pbkdf2_sha512_scheme,
447 pbkdf2_check, pbkdf2_encrypt);
448 return rc;
449 }
450
451 /*
452 * Local variables:
453 * indent-tabs-mode: t
454 * tab-width: 4
455 * c-basic-offset: 4
456 * End:
457 */
458