]> git.sur5r.net Git - openldap/commitdiff
ITS#8198 Optionally use libnettle instead of OpenSSL for crypto
authorLuca Bruno <luca.bruno@rocket-internet.de>
Wed, 5 Nov 2014 14:32:33 +0000 (15:32 +0100)
committerQuanah Gibson-Mount <quanah@openldap.org>
Mon, 31 Aug 2015 15:30:55 +0000 (10:30 -0500)
OpenLDAP can be configured to be either built with OpenSSL or
GnuTLS. This commit adds support for building pw-pbkbdf2 module
without OpenSSL, by using PBKDF2 crypto primitives provided by
libnettle.
Closes hamano/openldap-pbkdf2#2

Signed-off-by: Luca Bruno <luca.bruno@rocket-internet.de>
contrib/slapd-modules/passwd/pbkdf2/pw-pbkdf2.c

index e0f5dfd74c22ad569f9992985818ba35f7aaf07f..83559086a7d8981ecf7eb151c5018c74d2cea4a2 100644 (file)
 #include <ac/string.h>
 #include "lber_pvt.h"
 #include "lutil.h"
+#include <stdio.h>
+#include <stdlib.h>
 
+#ifdef HAVE_OPENSSL
 #include <openssl/evp.h>
+#elif HAVE_GNUTLS
+#include <nettle/pbkdf2.h>
+#include <nettle/hmac.h>
+typedef void (*pbkdf2_hmac_update)(void *, unsigned, const uint8_t *);
+typedef void (*pbkdf2_hmac_digest)(void *, unsigned, uint8_t *);
+#else
+#error Unsupported crypto backend.
+#endif
 
 #define PBKDF2_ITERATION 10000
 #define PBKDF2_SALT_SIZE 16
@@ -139,11 +150,22 @@ static int pbkdf2_encrypt(
        struct berval dk;
        int iteration = PBKDF2_ITERATION;
        int rc;
+#ifdef HAVE_OPENSSL
        const EVP_MD *md;
+#else
+       struct hmac_sha1_ctx sha1_ctx;
+       struct hmac_sha256_ctx sha256_ctx;
+       struct hmac_sha512_ctx sha512_ctx;
+       void * current_ctx = NULL;
+       pbkdf2_hmac_update current_hmac_update = NULL;
+       pbkdf2_hmac_digest current_hmac_digest = NULL;
+#endif
 
        salt.bv_val = (char *)salt_value;
        salt.bv_len = sizeof(salt_value);
        dk.bv_val = (char *)dk_value;
+
+#ifdef HAVE_OPENSSL
        if(!ber_bvcmp(scheme, &pbkdf2_scheme)){
                dk.bv_len = PBKDF2_SHA1_DK_SIZE;
                md = EVP_sha1();
@@ -159,16 +181,52 @@ static int pbkdf2_encrypt(
        }else{
                return LUTIL_PASSWD_ERR;
        }
+#else
+       if(!ber_bvcmp(scheme, &pbkdf2_scheme)){
+               dk.bv_len = PBKDF2_SHA1_DK_SIZE;
+               current_ctx = &sha1_ctx;
+               current_hmac_update = (pbkdf2_hmac_update) &hmac_sha1_update;
+               current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha1_digest;
+               hmac_sha1_set_key(current_ctx, passwd->bv_len, (const uint8_t *) passwd->bv_val);
+       }else if(!ber_bvcmp(scheme, &pbkdf2_sha1_scheme)){
+               dk.bv_len = PBKDF2_SHA1_DK_SIZE;
+               current_ctx = &sha1_ctx;
+               current_hmac_update = (pbkdf2_hmac_update) &hmac_sha1_update;
+               current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha1_digest;
+               hmac_sha1_set_key(current_ctx, passwd->bv_len, (const uint8_t *) passwd->bv_val);
+       }else if(!ber_bvcmp(scheme, &pbkdf2_sha256_scheme)){
+               dk.bv_len = PBKDF2_SHA256_DK_SIZE;
+               current_ctx = &sha256_ctx;
+               current_hmac_update = (pbkdf2_hmac_update) &hmac_sha256_update;
+               current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha256_digest;
+               hmac_sha256_set_key(current_ctx, passwd->bv_len, (const uint8_t *) passwd->bv_val);
+       }else if(!ber_bvcmp(scheme, &pbkdf2_sha512_scheme)){
+               dk.bv_len = PBKDF2_SHA512_DK_SIZE;
+               current_ctx = &sha512_ctx;
+               current_hmac_update = (pbkdf2_hmac_update) &hmac_sha512_update;
+               current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha512_digest;
+               hmac_sha512_set_key(current_ctx, passwd->bv_len, (const uint8_t *) passwd->bv_val);
+       }else{
+               return LUTIL_PASSWD_ERR;
+       }
+#endif
 
        if(lutil_entropy((unsigned char *)salt.bv_val, salt.bv_len) < 0){
                return LUTIL_PASSWD_ERR;
        }
 
+#ifdef HAVE_OPENSSL
        if(!PKCS5_PBKDF2_HMAC(passwd->bv_val, passwd->bv_len,
                                                  (unsigned char *)salt.bv_val, salt.bv_len,
                                                  iteration, md, dk.bv_len, dk_value)){
                return LUTIL_PASSWD_ERR;
        }
+#else
+       PBKDF2(current_ctx, current_hmac_update, current_hmac_digest,
+                                                 dk.bv_len, iteration,
+                                                 salt.bv_len, (const uint8_t *) salt.bv_val,
+                                                 dk.bv_len, dk_value);
+#endif
 
 #ifdef SLAPD_PBKDF2_DEBUG
        printf("Encrypt for %s\n", scheme->bv_val);
@@ -215,7 +273,16 @@ static int pbkdf2_check(
        char dk_b64[LUTIL_BASE64_ENCODE_LEN(PBKDF2_MAX_DK_SIZE) + 1];
        unsigned char input_dk_value[PBKDF2_MAX_DK_SIZE];
        size_t dk_len;
+#ifdef HAVE_OPENSSL
        const EVP_MD *md;
+#else
+       struct hmac_sha1_ctx sha1_ctx;
+       struct hmac_sha256_ctx sha256_ctx;
+       struct hmac_sha512_ctx sha512_ctx;
+       void * current_ctx = NULL;
+       pbkdf2_hmac_update current_hmac_update = NULL;
+       pbkdf2_hmac_digest current_hmac_digest = NULL;
+#endif
 
 #ifdef SLAPD_PBKDF2_DEBUG
        printf("Checking for %s\n", scheme->bv_val);
@@ -223,6 +290,7 @@ static int pbkdf2_check(
        printf("  Input Cred:\t%s\n", cred->bv_val);
 #endif
 
+#ifdef HAVE_OPENSSL
        if(!ber_bvcmp(scheme, &pbkdf2_scheme)){
                dk_len = PBKDF2_SHA1_DK_SIZE;
                md = EVP_sha1();
@@ -238,6 +306,35 @@ static int pbkdf2_check(
        }else{
                return LUTIL_PASSWD_ERR;
        }
+#else
+       if(!ber_bvcmp(scheme, &pbkdf2_scheme)){
+               dk_len = PBKDF2_SHA1_DK_SIZE;
+               current_ctx = &sha1_ctx;
+               current_hmac_update = (pbkdf2_hmac_update) &hmac_sha1_update;
+               current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha1_digest;
+               hmac_sha1_set_key(current_ctx, cred->bv_len, (const uint8_t *) cred->bv_val);
+       }else if(!ber_bvcmp(scheme, &pbkdf2_sha1_scheme)){
+               dk_len = PBKDF2_SHA1_DK_SIZE;
+               current_ctx = &sha1_ctx;
+               current_hmac_update = (pbkdf2_hmac_update) &hmac_sha1_update;
+               current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha1_digest;
+               hmac_sha1_set_key(current_ctx, cred->bv_len, (const uint8_t *) cred->bv_val);
+       }else if(!ber_bvcmp(scheme, &pbkdf2_sha256_scheme)){
+               dk_len = PBKDF2_SHA256_DK_SIZE;
+               current_ctx = &sha256_ctx;
+               current_hmac_update = (pbkdf2_hmac_update) &hmac_sha256_update;
+               current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha256_digest;
+               hmac_sha256_set_key(current_ctx, cred->bv_len, (const uint8_t *) cred->bv_val);
+       }else if(!ber_bvcmp(scheme, &pbkdf2_sha512_scheme)){
+               dk_len = PBKDF2_SHA512_DK_SIZE;
+               current_ctx = &sha512_ctx;
+               current_hmac_update = (pbkdf2_hmac_update) &hmac_sha512_update;
+               current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha512_digest;
+               hmac_sha512_set_key(current_ctx, cred->bv_len, (const uint8_t *) cred->bv_val);
+       }else{
+               return LUTIL_PASSWD_ERR;
+       }
+#endif
 
        iteration = atoi(passwd->bv_val);
        if(iteration < 1){
@@ -287,11 +384,18 @@ static int pbkdf2_check(
                return LUTIL_PASSWD_ERR;
        }
 
+#ifdef HAVE_OPENSSL
        if(!PKCS5_PBKDF2_HMAC(cred->bv_val, cred->bv_len,
                                                  salt_value, PBKDF2_SALT_SIZE,
                                                  iteration, md, dk_len, input_dk_value)){
                return LUTIL_PASSWD_ERR;
        }
+#else
+       PBKDF2(current_ctx, current_hmac_update, current_hmac_digest,
+                                                 dk_len, iteration,
+                                                 PBKDF2_SALT_SIZE, salt_value,
+                                                 dk_len, input_dk_value);
+#endif
 
        rc = memcmp(dk_value, input_dk_value, dk_len);
 #ifdef SLAPD_PBKDF2_DEBUG