Blame crypto/kdf/pbkdf2.c

Packit c4476c
/*
Packit c4476c
 * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
Packit c4476c
 *
Packit c4476c
 * Licensed under the Apache License 2.0 (the "License").  You may not use
Packit c4476c
 * this file except in compliance with the License.  You can obtain a copy
Packit c4476c
 * in the file LICENSE in the source distribution or at
Packit c4476c
 * https://www.openssl.org/source/license.html
Packit c4476c
 */
Packit c4476c
Packit c4476c
#include <stdlib.h>
Packit c4476c
#include <stdarg.h>
Packit c4476c
#include <string.h>
Packit c4476c
#include <openssl/hmac.h>
Packit c4476c
#include <openssl/evp.h>
Packit c4476c
#include <openssl/kdf.h>
Packit c4476c
#include "internal/cryptlib.h"
Packit c4476c
#include "crypto/evp.h"
Packit c4476c
#include "kdf_local.h"
Packit c4476c
Packit c4476c
static void kdf_pbkdf2_reset(EVP_KDF_IMPL *impl);
Packit c4476c
static void kdf_pbkdf2_init(EVP_KDF_IMPL *impl);
Packit c4476c
static int pkcs5_pbkdf2_alg(const char *pass, size_t passlen,
Packit c4476c
                            const unsigned char *salt, int saltlen, int iter,
Packit c4476c
                            const EVP_MD *digest, unsigned char *key,
Packit c4476c
                            size_t keylen);
Packit c4476c
Packit c4476c
struct evp_kdf_impl_st {
Packit c4476c
    unsigned char *pass;
Packit c4476c
    size_t pass_len;
Packit c4476c
    unsigned char *salt;
Packit c4476c
    size_t salt_len;
Packit c4476c
    int iter;
Packit c4476c
    const EVP_MD *md;
Packit c4476c
};
Packit c4476c
Packit c4476c
static EVP_KDF_IMPL *kdf_pbkdf2_new(void)
Packit c4476c
{
Packit c4476c
    EVP_KDF_IMPL *impl;
Packit c4476c
Packit c4476c
    impl = OPENSSL_zalloc(sizeof(*impl));
Packit c4476c
    if (impl == NULL) {
Packit c4476c
        KDFerr(KDF_F_KDF_PBKDF2_NEW, ERR_R_MALLOC_FAILURE);
Packit c4476c
        return NULL;
Packit c4476c
    }
Packit c4476c
    kdf_pbkdf2_init(impl);
Packit c4476c
    return impl;
Packit c4476c
}
Packit c4476c
Packit c4476c
static void kdf_pbkdf2_free(EVP_KDF_IMPL *impl)
Packit c4476c
{
Packit c4476c
    kdf_pbkdf2_reset(impl);
Packit c4476c
    OPENSSL_free(impl);
Packit c4476c
}
Packit c4476c
Packit c4476c
static void kdf_pbkdf2_reset(EVP_KDF_IMPL *impl)
Packit c4476c
{
Packit c4476c
    OPENSSL_free(impl->salt);
Packit c4476c
    OPENSSL_clear_free(impl->pass, impl->pass_len);
Packit c4476c
    memset(impl, 0, sizeof(*impl));
Packit c4476c
    kdf_pbkdf2_init(impl);
Packit c4476c
}
Packit c4476c
Packit c4476c
static void kdf_pbkdf2_init(EVP_KDF_IMPL *impl)
Packit c4476c
{
Packit c4476c
    impl->iter = PKCS5_DEFAULT_ITER;
Packit c4476c
    impl->md = EVP_sha1();
Packit c4476c
}
Packit c4476c
Packit c4476c
static int pbkdf2_set_membuf(unsigned char **buffer, size_t *buflen,
Packit c4476c
                             const unsigned char *new_buffer,
Packit c4476c
                             size_t new_buflen)
Packit c4476c
{
Packit c4476c
    if (new_buffer == NULL)
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    OPENSSL_clear_free(*buffer, *buflen);
Packit c4476c
Packit c4476c
    if (new_buflen > 0) {
Packit c4476c
        *buffer = OPENSSL_memdup(new_buffer, new_buflen);
Packit c4476c
    } else {
Packit c4476c
        *buffer = OPENSSL_malloc(1);
Packit c4476c
    }
Packit c4476c
    if (*buffer == NULL) {
Packit c4476c
        KDFerr(KDF_F_PBKDF2_SET_MEMBUF, ERR_R_MALLOC_FAILURE);
Packit c4476c
        return 0;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    *buflen = new_buflen;
Packit c4476c
    return 1;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int kdf_pbkdf2_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args)
Packit c4476c
{
Packit c4476c
    int iter;
Packit c4476c
    const unsigned char *p;
Packit c4476c
    size_t len;
Packit c4476c
    const EVP_MD *md;
Packit c4476c
Packit c4476c
    switch (cmd) {
Packit c4476c
    case EVP_KDF_CTRL_SET_PASS:
Packit c4476c
        p = va_arg(args, const unsigned char *);
Packit c4476c
        len = va_arg(args, size_t);
Packit c4476c
        return pbkdf2_set_membuf(&impl->pass, &impl->pass_len, p, len);
Packit c4476c
Packit c4476c
    case EVP_KDF_CTRL_SET_SALT:
Packit c4476c
        p = va_arg(args, const unsigned char *);
Packit c4476c
        len = va_arg(args, size_t);
Packit c4476c
        return pbkdf2_set_membuf(&impl->salt, &impl->salt_len, p, len);
Packit c4476c
Packit c4476c
    case EVP_KDF_CTRL_SET_ITER:
Packit c4476c
        iter = va_arg(args, int);
Packit c4476c
        if (iter < 1)
Packit c4476c
            return 0;
Packit c4476c
Packit c4476c
        impl->iter = iter;
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    case EVP_KDF_CTRL_SET_MD:
Packit c4476c
        md = va_arg(args, const EVP_MD *);
Packit c4476c
        if (md == NULL)
Packit c4476c
            return 0;
Packit c4476c
Packit c4476c
        impl->md = md;
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    default:
Packit c4476c
        return -2;
Packit c4476c
    }
Packit c4476c
}
Packit c4476c
Packit c4476c
static int kdf_pbkdf2_ctrl_str(EVP_KDF_IMPL *impl, const char *type,
Packit c4476c
                               const char *value)
Packit c4476c
{
Packit c4476c
    if (value == NULL) {
Packit c4476c
        KDFerr(KDF_F_KDF_PBKDF2_CTRL_STR, KDF_R_VALUE_MISSING);
Packit c4476c
        return 0;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (strcmp(type, "pass") == 0)
Packit c4476c
        return kdf_str2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_PASS,
Packit c4476c
                            value);
Packit c4476c
Packit c4476c
    if (strcmp(type, "hexpass") == 0)
Packit c4476c
        return kdf_hex2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_PASS,
Packit c4476c
                            value);
Packit c4476c
Packit c4476c
    if (strcmp(type, "salt") == 0)
Packit c4476c
        return kdf_str2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_SALT,
Packit c4476c
                            value);
Packit c4476c
Packit c4476c
    if (strcmp(type, "hexsalt") == 0)
Packit c4476c
        return kdf_hex2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_SALT,
Packit c4476c
                            value);
Packit c4476c
Packit c4476c
    if (strcmp(type, "iter") == 0)
Packit c4476c
        return call_ctrl(kdf_pbkdf2_ctrl, impl, EVP_KDF_CTRL_SET_ITER,
Packit c4476c
                         atoi(value));
Packit c4476c
Packit c4476c
    if (strcmp(type, "digest") == 0)
Packit c4476c
        return kdf_md2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_MD, value);
Packit c4476c
Packit c4476c
    return -2;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int kdf_pbkdf2_derive(EVP_KDF_IMPL *impl, unsigned char *key,
Packit c4476c
                             size_t keylen)
Packit c4476c
{
Packit c4476c
    if (impl->pass == NULL) {
Packit c4476c
        KDFerr(KDF_F_KDF_PBKDF2_DERIVE, KDF_R_MISSING_PASS);
Packit c4476c
        return 0;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (impl->salt == NULL) {
Packit c4476c
        KDFerr(KDF_F_KDF_PBKDF2_DERIVE, KDF_R_MISSING_SALT);
Packit c4476c
        return 0;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    return pkcs5_pbkdf2_alg((char *)impl->pass, impl->pass_len,
Packit c4476c
                            impl->salt, impl->salt_len, impl->iter,
Packit c4476c
                            impl->md, key, keylen);
Packit c4476c
}
Packit c4476c
Packit c4476c
const EVP_KDF_METHOD pbkdf2_kdf_meth = {
Packit c4476c
    EVP_KDF_PBKDF2,
Packit c4476c
    kdf_pbkdf2_new,
Packit c4476c
    kdf_pbkdf2_free,
Packit c4476c
    kdf_pbkdf2_reset,
Packit c4476c
    kdf_pbkdf2_ctrl,
Packit c4476c
    kdf_pbkdf2_ctrl_str,
Packit c4476c
    NULL,
Packit c4476c
    kdf_pbkdf2_derive
Packit c4476c
};
Packit c4476c
Packit c4476c
/*
Packit c4476c
 * This is an implementation of PKCS#5 v2.0 password based encryption key
Packit c4476c
 * derivation function PBKDF2. SHA1 version verified against test vectors
Packit c4476c
 * posted by Peter Gutmann to the PKCS-TNG mailing list.
Packit c4476c
 */
Packit c4476c
Packit c4476c
static int pkcs5_pbkdf2_alg(const char *pass, size_t passlen,
Packit c4476c
                            const unsigned char *salt, int saltlen, int iter,
Packit c4476c
                            const EVP_MD *digest, unsigned char *key,
Packit c4476c
                            size_t keylen)
Packit c4476c
{
Packit c4476c
    int ret = 0;
Packit c4476c
    unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4];
Packit c4476c
    int cplen, j, k, tkeylen, mdlen;
Packit c4476c
    unsigned long i = 1;
Packit c4476c
    HMAC_CTX *hctx_tpl = NULL, *hctx = NULL;
Packit c4476c
Packit c4476c
    mdlen = EVP_MD_size(digest);
Packit c4476c
    if (mdlen < 0)
Packit c4476c
        return 0;
Packit c4476c
Packit c4476c
    hctx_tpl = HMAC_CTX_new();
Packit c4476c
    if (hctx_tpl == NULL)
Packit c4476c
        return 0;
Packit c4476c
    p = key;
Packit c4476c
    tkeylen = keylen;
Packit c4476c
    if (!HMAC_Init_ex(hctx_tpl, pass, passlen, digest, NULL))
Packit c4476c
        goto err;
Packit c4476c
    hctx = HMAC_CTX_new();
Packit c4476c
    if (hctx == NULL)
Packit c4476c
        goto err;
Packit c4476c
    while (tkeylen) {
Packit c4476c
        if (tkeylen > mdlen)
Packit c4476c
            cplen = mdlen;
Packit c4476c
        else
Packit c4476c
            cplen = tkeylen;
Packit c4476c
        /*
Packit c4476c
         * We are unlikely to ever use more than 256 blocks (5120 bits!) but
Packit c4476c
         * just in case...
Packit c4476c
         */
Packit c4476c
        itmp[0] = (unsigned char)((i >> 24) & 0xff);
Packit c4476c
        itmp[1] = (unsigned char)((i >> 16) & 0xff);
Packit c4476c
        itmp[2] = (unsigned char)((i >> 8) & 0xff);
Packit c4476c
        itmp[3] = (unsigned char)(i & 0xff);
Packit c4476c
        if (!HMAC_CTX_copy(hctx, hctx_tpl))
Packit c4476c
            goto err;
Packit c4476c
        if (!HMAC_Update(hctx, salt, saltlen)
Packit c4476c
                || !HMAC_Update(hctx, itmp, 4)
Packit c4476c
                || !HMAC_Final(hctx, digtmp, NULL))
Packit c4476c
            goto err;
Packit c4476c
        memcpy(p, digtmp, cplen);
Packit c4476c
        for (j = 1; j < iter; j++) {
Packit c4476c
            if (!HMAC_CTX_copy(hctx, hctx_tpl))
Packit c4476c
                goto err;
Packit c4476c
            if (!HMAC_Update(hctx, digtmp, mdlen)
Packit c4476c
                    || !HMAC_Final(hctx, digtmp, NULL))
Packit c4476c
                goto err;
Packit c4476c
            for (k = 0; k < cplen; k++)
Packit c4476c
                p[k] ^= digtmp[k];
Packit c4476c
        }
Packit c4476c
        tkeylen -= cplen;
Packit c4476c
        i++;
Packit c4476c
        p += cplen;
Packit c4476c
    }
Packit c4476c
    ret = 1;
Packit c4476c
Packit c4476c
err:
Packit c4476c
    HMAC_CTX_free(hctx);
Packit c4476c
    HMAC_CTX_free(hctx_tpl);
Packit c4476c
    return ret;
Packit c4476c
}