Blame crypto/kdf/kbkdf.c

Packit c4476c
/*
Packit c4476c
 * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
Packit c4476c
 * Copyright 2019 Red Hat, Inc.
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
/*
Packit c4476c
 * This implements https://csrc.nist.gov/publications/detail/sp/800-108/final
Packit c4476c
 * section 5.1 ("counter mode") and section 5.2 ("feedback mode") in both HMAC
Packit c4476c
 * and CMAC.  That document does not name the KDFs it defines; the name is
Packit c4476c
 * derived from
Packit c4476c
 * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Key-Derivation
Packit c4476c
 *
Packit c4476c
 * Note that section 5.3 ("double-pipeline mode") is not implemented, though
Packit c4476c
 * it would be possible to do so in the future.
Packit c4476c
 *
Packit c4476c
 * These versions all assume the counter is used.  It would be relatively
Packit c4476c
 * straightforward to expose a configuration handle should the need arise.
Packit c4476c
 *
Packit c4476c
 * Variable names attempt to match those of SP800-108.
Packit c4476c
 */
Packit c4476c
Packit c4476c
#include <stdarg.h>
Packit c4476c
#include <stdlib.h>
Packit c4476c
#include <string.h>
Packit c4476c
Packit c4476c
#include <openssl/evp.h>
Packit c4476c
#include <openssl/hmac.h>
Packit c4476c
#include <openssl/cmac.h>
Packit c4476c
#include <openssl/kdf.h>
Packit c4476c
Packit c4476c
#include "internal/numbers.h"
Packit c4476c
#include "internal/cryptlib.h"
Packit c4476c
#include "crypto/evp.h"
Packit c4476c
#include "kdf_local.h"
Packit c4476c
Packit c4476c
#include "e_os.h"
Packit c4476c
Packit c4476c
#ifdef MIN
Packit c4476c
# undef MIN
Packit c4476c
#endif
Packit c4476c
#define MIN(a, b) ((a) < (b)) ? (a) : (b)
Packit c4476c
Packit c4476c
typedef struct {
Packit c4476c
    int mac_type;
Packit c4476c
    union {
Packit c4476c
        HMAC_CTX *hmac;
Packit c4476c
        CMAC_CTX *cmac;
Packit c4476c
    } m;
Packit c4476c
} MAC_CTX;
Packit c4476c
Packit c4476c
/* Our context structure. */
Packit c4476c
struct evp_kdf_impl_st {
Packit c4476c
    int mode;
Packit c4476c
Packit c4476c
    MAC_CTX *ctx_init;
Packit c4476c
Packit c4476c
    const EVP_CIPHER *cipher;
Packit c4476c
    const EVP_MD *md;
Packit c4476c
Packit c4476c
    /* Names are lowercased versions of those found in SP800-108. */
Packit c4476c
    unsigned char *ki;
Packit c4476c
    size_t ki_len;
Packit c4476c
    unsigned char *label;
Packit c4476c
    size_t label_len;
Packit c4476c
    unsigned char *context;
Packit c4476c
    size_t context_len;
Packit c4476c
    unsigned char *iv;
Packit c4476c
    size_t iv_len;
Packit c4476c
};
Packit c4476c
Packit c4476c
static MAC_CTX *EVP_MAC_CTX_new(int mac_type)
Packit c4476c
{
Packit c4476c
    MAC_CTX *ctx;
Packit c4476c
Packit c4476c
    ctx = OPENSSL_zalloc(sizeof(*ctx));
Packit c4476c
    if (ctx == NULL)
Packit c4476c
        return NULL;
Packit c4476c
Packit c4476c
    ctx->mac_type = mac_type;
Packit c4476c
    if (mac_type == EVP_KDF_KB_MAC_TYPE_HMAC) {
Packit c4476c
        if ((ctx->m.hmac = HMAC_CTX_new()) == NULL)
Packit c4476c
            goto err;
Packit c4476c
    } else {
Packit c4476c
        if ((ctx->m.cmac = CMAC_CTX_new()) == NULL)
Packit c4476c
            goto err;
Packit c4476c
    }
Packit c4476c
    return ctx;
Packit c4476c
Packit c4476c
err:
Packit c4476c
    OPENSSL_free(ctx);
Packit c4476c
    return NULL;
Packit c4476c
}
Packit c4476c
Packit c4476c
static void EVP_MAC_CTX_free(MAC_CTX *ctx)
Packit c4476c
{
Packit c4476c
    if (ctx == NULL)
Packit c4476c
        return;
Packit c4476c
Packit c4476c
    if (ctx->mac_type == EVP_KDF_KB_MAC_TYPE_HMAC)
Packit c4476c
        HMAC_CTX_free(ctx->m.hmac);
Packit c4476c
    else
Packit c4476c
        CMAC_CTX_free(ctx->m.cmac);
Packit c4476c
    OPENSSL_free(ctx);
Packit c4476c
}
Packit c4476c
Packit c4476c
static MAC_CTX *EVP_MAC_CTX_dup(MAC_CTX *sctx)
Packit c4476c
{
Packit c4476c
    MAC_CTX *ctx;
Packit c4476c
Packit c4476c
    ctx = OPENSSL_zalloc(sizeof(*sctx));
Packit c4476c
    if (ctx == NULL)
Packit c4476c
        return NULL;
Packit c4476c
Packit c4476c
    ctx->mac_type = sctx->mac_type;
Packit c4476c
    if (sctx->mac_type == EVP_KDF_KB_MAC_TYPE_HMAC) {
Packit c4476c
        if ((ctx->m.hmac = HMAC_CTX_new()) == NULL
Packit c4476c
            || HMAC_CTX_copy(ctx->m.hmac, sctx->m.hmac) <= 0)
Packit c4476c
            goto err;
Packit c4476c
    } else {
Packit c4476c
        if ((ctx->m.cmac = CMAC_CTX_new()) == NULL
Packit c4476c
            || CMAC_CTX_copy(ctx->m.cmac, sctx->m.cmac) <= 0)
Packit c4476c
            goto err;
Packit c4476c
    }
Packit c4476c
    return ctx;
Packit c4476c
Packit c4476c
err:
Packit c4476c
    EVP_MAC_CTX_free(ctx);
Packit c4476c
    return NULL;
Packit c4476c
}
Packit c4476c
Packit c4476c
static size_t EVP_MAC_size(MAC_CTX *ctx)
Packit c4476c
{
Packit c4476c
    if (ctx->mac_type == EVP_KDF_KB_MAC_TYPE_HMAC) {
Packit c4476c
        const EVP_MD *md;
Packit c4476c
Packit c4476c
        if (ctx->m.hmac == NULL)
Packit c4476c
            return 0;
Packit c4476c
        if ((md = HMAC_CTX_get_md(ctx->m.hmac)) == NULL)
Packit c4476c
            return 0;
Packit c4476c
        return (size_t)EVP_MD_size(md);
Packit c4476c
    } else {
Packit c4476c
        const EVP_CIPHER_CTX *cctx;
Packit c4476c
Packit c4476c
        if (ctx->m.cmac == NULL)
Packit c4476c
            return 0;
Packit c4476c
        if ((cctx = CMAC_CTX_get0_cipher_ctx(ctx->m.cmac)) == NULL)
Packit c4476c
            return 0;
Packit c4476c
        return EVP_CIPHER_CTX_block_size(cctx);
Packit c4476c
    }
Packit c4476c
}
Packit c4476c
Packit c4476c
static int EVP_MAC_update(MAC_CTX *ctx, const unsigned char *data,
Packit c4476c
                          size_t datalen)
Packit c4476c
{
Packit c4476c
    if (ctx->mac_type == EVP_KDF_KB_MAC_TYPE_HMAC)
Packit c4476c
        return HMAC_Update(ctx->m.hmac, data, datalen);
Packit c4476c
    else
Packit c4476c
        return CMAC_Update(ctx->m.cmac, data, datalen);
Packit c4476c
}
Packit c4476c
Packit c4476c
static int EVP_MAC_final(MAC_CTX *ctx, unsigned char *out,
Packit c4476c
                         size_t *outl, size_t outsize)
Packit c4476c
{
Packit c4476c
    if (outsize != EVP_MAC_size(ctx))
Packit c4476c
        /* we do not cope with anything else */
Packit c4476c
        return 0;
Packit c4476c
Packit c4476c
    if (ctx->mac_type == EVP_KDF_KB_MAC_TYPE_HMAC) {
Packit c4476c
        unsigned int intsize = (unsigned int)outsize;
Packit c4476c
        int ret;
Packit c4476c
Packit c4476c
        ret = HMAC_Final(ctx->m.hmac, out, &intsize);
Packit c4476c
        if (outl != NULL)
Packit c4476c
            *outl = intsize;
Packit c4476c
        return ret;
Packit c4476c
    } else {
Packit c4476c
        size_t size = outsize;
Packit c4476c
        int ret;
Packit c4476c
Packit c4476c
        ret = CMAC_Final(ctx->m.cmac, out, &size);
Packit c4476c
        if (outl != NULL)
Packit c4476c
            *outl = size;
Packit c4476c
        return ret;
Packit c4476c
    }
Packit c4476c
}
Packit c4476c
Packit c4476c
static int evp_mac_init(MAC_CTX *ctx, const EVP_MD *md,
Packit c4476c
                        const EVP_CIPHER *cipher, unsigned char *key, size_t keylen)
Packit c4476c
{
Packit c4476c
    if (ctx->mac_type == EVP_KDF_KB_MAC_TYPE_HMAC) {
Packit c4476c
        if (md == NULL)
Packit c4476c
            return 0;
Packit c4476c
        return HMAC_Init_ex(ctx->m.hmac, key, (int)keylen, md, NULL);
Packit c4476c
    } else {
Packit c4476c
        if (cipher == NULL)
Packit c4476c
            return 0;
Packit c4476c
        return CMAC_Init(ctx->m.cmac, key, keylen, cipher, NULL);
Packit c4476c
    }
Packit c4476c
}
Packit c4476c
Packit c4476c
static void kbkdf_reset(EVP_KDF_IMPL *ctx);
Packit c4476c
Packit c4476c
/* Not all platforms have htobe32(). */
Packit c4476c
static uint32_t be32(uint32_t host)
Packit c4476c
{
Packit c4476c
    uint32_t big = 0;
Packit c4476c
    const union {
Packit c4476c
        long one;
Packit c4476c
        char little;
Packit c4476c
    } is_endian = { 1 };
Packit c4476c
Packit c4476c
    if (!is_endian.little)
Packit c4476c
        return host;
Packit c4476c
Packit c4476c
    big |= (host & 0xff000000) >> 24;
Packit c4476c
    big |= (host & 0x00ff0000) >> 8;
Packit c4476c
    big |= (host & 0x0000ff00) << 8;
Packit c4476c
    big |= (host & 0x000000ff) << 24;
Packit c4476c
    return big;
Packit c4476c
}
Packit c4476c
Packit c4476c
static EVP_KDF_IMPL *kbkdf_new(void)
Packit c4476c
{
Packit c4476c
    EVP_KDF_IMPL *ctx;
Packit c4476c
Packit c4476c
    ctx = OPENSSL_zalloc(sizeof(*ctx));
Packit c4476c
    if (ctx == NULL) {
Packit c4476c
        KDFerr(KDF_F_KBKDF_NEW, ERR_R_MALLOC_FAILURE);
Packit c4476c
        return NULL;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    return ctx;
Packit c4476c
}
Packit c4476c
Packit c4476c
static void kbkdf_free(EVP_KDF_IMPL *ctx)
Packit c4476c
{
Packit c4476c
    kbkdf_reset(ctx);
Packit c4476c
    OPENSSL_free(ctx);
Packit c4476c
}
Packit c4476c
Packit c4476c
static void kbkdf_reset(EVP_KDF_IMPL *ctx)
Packit c4476c
{
Packit c4476c
    EVP_MAC_CTX_free(ctx->ctx_init);
Packit c4476c
    OPENSSL_clear_free(ctx->context, ctx->context_len);
Packit c4476c
    OPENSSL_clear_free(ctx->label, ctx->label_len);
Packit c4476c
    OPENSSL_clear_free(ctx->ki, ctx->ki_len);
Packit c4476c
    OPENSSL_clear_free(ctx->iv, ctx->iv_len);
Packit c4476c
    memset(ctx, 0, sizeof(*ctx));
Packit c4476c
}
Packit c4476c
Packit c4476c
/* SP800-108 section 5.1 or section 5.2 depending on mode. */
Packit c4476c
static int derive(MAC_CTX *ctx_init, int mode, unsigned char *iv,
Packit c4476c
                  size_t iv_len, unsigned char *label, size_t label_len,
Packit c4476c
                  unsigned char *context, size_t context_len,
Packit c4476c
                  unsigned char *k_i, size_t h, uint32_t l, unsigned char *ko,
Packit c4476c
                  size_t ko_len)
Packit c4476c
{
Packit c4476c
    int ret = 0;
Packit c4476c
    MAC_CTX *ctx = NULL;
Packit c4476c
    size_t written = 0, to_write, k_i_len = iv_len;
Packit c4476c
    const unsigned char zero = 0;
Packit c4476c
    uint32_t counter, i;
Packit c4476c
Packit c4476c
    /* Setup K(0) for feedback mode. */
Packit c4476c
    if (iv_len > 0)
Packit c4476c
        memcpy(k_i, iv, iv_len);
Packit c4476c
Packit c4476c
    for (counter = 1; written < ko_len; counter++) {
Packit c4476c
        i = be32(counter);
Packit c4476c
Packit c4476c
        ctx = EVP_MAC_CTX_dup(ctx_init);
Packit c4476c
        if (ctx == NULL)
Packit c4476c
            goto done;
Packit c4476c
Packit c4476c
        /* Perform feedback, if appropriate. */
Packit c4476c
        if (mode == EVP_KDF_KB_MODE_FEEDBACK && !EVP_MAC_update(ctx, k_i, k_i_len))
Packit c4476c
            goto done;
Packit c4476c
Packit c4476c
        if (!EVP_MAC_update(ctx, (unsigned char *)&i, 4)
Packit c4476c
            || !EVP_MAC_update(ctx, label, label_len)
Packit c4476c
            || !EVP_MAC_update(ctx, &zero, 1)
Packit c4476c
            || !EVP_MAC_update(ctx, context, context_len)
Packit c4476c
            || !EVP_MAC_update(ctx, (unsigned char *)&l, 4)
Packit c4476c
            || !EVP_MAC_final(ctx, k_i, NULL, h))
Packit c4476c
            goto done;
Packit c4476c
Packit c4476c
        to_write = ko_len - written;
Packit c4476c
        memcpy(ko + written, k_i, MIN(to_write, h));
Packit c4476c
        written += h;
Packit c4476c
Packit c4476c
        k_i_len = h;
Packit c4476c
        EVP_MAC_CTX_free(ctx);
Packit c4476c
        ctx = NULL;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    ret = 1;
Packit c4476c
done:
Packit c4476c
    EVP_MAC_CTX_free(ctx);
Packit c4476c
    return ret;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int kbkdf_derive(EVP_KDF_IMPL *ctx, unsigned char *key, size_t keylen)
Packit c4476c
{
Packit c4476c
    int ret = 0;
Packit c4476c
    unsigned char *k_i = NULL;
Packit c4476c
    uint32_t l = be32(keylen * 8);
Packit c4476c
    size_t h = 0;
Packit c4476c
Packit c4476c
    /* label, context, and iv are permitted to be empty.  Check everything
Packit c4476c
     * else. */
Packit c4476c
    if (ctx->ctx_init == NULL
Packit c4476c
        || evp_mac_init(ctx->ctx_init, ctx->md, ctx->cipher, ctx->ki, ctx->ki_len) <= 0) {
Packit c4476c
        if (ctx->ki_len == 0 || ctx->ki == NULL) {
Packit c4476c
            KDFerr(KDF_F_KBKDF_DERIVE, KDF_R_MISSING_KEY);
Packit c4476c
            return 0;
Packit c4476c
        }
Packit c4476c
        /* Could either be missing MAC or missing message digest or missing
Packit c4476c
         * cipher - arbitrarily, I pick this one. */
Packit c4476c
        KDFerr(KDF_F_KBKDF_DERIVE, KDF_R_MISSING_PARAMETER);
Packit c4476c
        return 0;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    h = EVP_MAC_size(ctx->ctx_init);
Packit c4476c
    if (h == 0)
Packit c4476c
        goto done;
Packit c4476c
    if (ctx->iv_len != 0 && ctx->iv_len != h) {
Packit c4476c
        KDFerr(KDF_F_KBKDF_DERIVE, KDF_R_INVALID_SEED_LENGTH);
Packit c4476c
        goto done;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    k_i = OPENSSL_zalloc(h);
Packit c4476c
    if (k_i == NULL)
Packit c4476c
        goto done;
Packit c4476c
Packit c4476c
    ret = derive(ctx->ctx_init, ctx->mode, ctx->iv, ctx->iv_len, ctx->label,
Packit c4476c
                 ctx->label_len, ctx->context, ctx->context_len, k_i, h, l,
Packit c4476c
                 key, keylen);
Packit c4476c
done:
Packit c4476c
    if (ret != 1)
Packit c4476c
        OPENSSL_cleanse(key, keylen);
Packit c4476c
    OPENSSL_clear_free(k_i, h);
Packit c4476c
    return ret;
Packit c4476c
}
Packit c4476c
Packit c4476c
static size_t kbkdf_size(EVP_KDF_IMPL *ctx)
Packit c4476c
{
Packit c4476c
    return UINT32_MAX/8;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int kbkdf_parse_buffer_arg(unsigned char **dst, size_t *dst_len,
Packit c4476c
                                       va_list args)
Packit c4476c
{
Packit c4476c
    const unsigned char *p;
Packit c4476c
    size_t len;
Packit c4476c
Packit c4476c
    p = va_arg(args, const unsigned char *);
Packit c4476c
    len = va_arg(args, size_t);
Packit c4476c
    OPENSSL_clear_free(*dst, *dst_len);
Packit c4476c
    if (len == 0) {
Packit c4476c
        *dst = NULL;
Packit c4476c
        *dst_len = 0;
Packit c4476c
        return 1;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    *dst = OPENSSL_memdup(p, len);
Packit c4476c
    if (*dst == NULL)
Packit c4476c
        return 0;
Packit c4476c
Packit c4476c
    *dst_len = len;
Packit c4476c
    return 1;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int kbkdf_ctrl(EVP_KDF_IMPL *ctx, int cmd, va_list args)
Packit c4476c
{
Packit c4476c
    int t;
Packit c4476c
Packit c4476c
    switch (cmd) {
Packit c4476c
    case EVP_KDF_CTRL_SET_MD:
Packit c4476c
        ctx->md = va_arg(args, const EVP_MD *);
Packit c4476c
        if (ctx->md == NULL)
Packit c4476c
            return 0;
Packit c4476c
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    case EVP_KDF_CTRL_SET_CIPHER:
Packit c4476c
        ctx->cipher = va_arg(args, const EVP_CIPHER *);
Packit c4476c
        if (ctx->cipher == NULL)
Packit c4476c
            return 0;
Packit c4476c
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    case EVP_KDF_CTRL_SET_KEY:
Packit c4476c
        return kbkdf_parse_buffer_arg(&ctx->ki,
Packit c4476c
                                      &ctx->ki_len, args);
Packit c4476c
Packit c4476c
    case EVP_KDF_CTRL_SET_SALT:
Packit c4476c
        return kbkdf_parse_buffer_arg(&ctx->label,
Packit c4476c
                                           &ctx->label_len, args);
Packit c4476c
Packit c4476c
    case EVP_KDF_CTRL_SET_KB_INFO:
Packit c4476c
        return kbkdf_parse_buffer_arg(&ctx->context,
Packit c4476c
                                           &ctx->context_len, args);
Packit c4476c
Packit c4476c
    case EVP_KDF_CTRL_SET_KB_SEED:
Packit c4476c
        return kbkdf_parse_buffer_arg(&ctx->iv,
Packit c4476c
                                           &ctx->iv_len, args);
Packit c4476c
Packit c4476c
    case EVP_KDF_CTRL_SET_KB_MODE:
Packit c4476c
        t = va_arg(args, int);
Packit c4476c
        if (t != EVP_KDF_KB_MODE_COUNTER && t != EVP_KDF_KB_MODE_FEEDBACK ) {
Packit c4476c
            KDFerr(KDF_F_KBKDF_CTRL, KDF_R_VALUE_ERROR);
Packit c4476c
            return 0;
Packit c4476c
        }
Packit c4476c
        ctx->mode = t;
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    case EVP_KDF_CTRL_SET_KB_MAC_TYPE:
Packit c4476c
        t = va_arg(args, int);
Packit c4476c
        if (t != EVP_KDF_KB_MAC_TYPE_HMAC && t != EVP_KDF_KB_MAC_TYPE_CMAC ) {
Packit c4476c
            KDFerr(KDF_F_KBKDF_CTRL, KDF_R_VALUE_ERROR);
Packit c4476c
            return 0;
Packit c4476c
        }
Packit c4476c
Packit c4476c
        if (ctx->ctx_init != NULL) {
Packit c4476c
            EVP_MAC_CTX_free(ctx->ctx_init);
Packit c4476c
        }
Packit c4476c
        ctx->ctx_init = EVP_MAC_CTX_new(t);
Packit c4476c
        if (ctx->ctx_init == NULL) {
Packit c4476c
            KDFerr(KDF_F_KBKDF_CTRL, ERR_R_MALLOC_FAILURE);
Packit c4476c
            return 0;
Packit c4476c
        }
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    default:
Packit c4476c
        return -2;
Packit c4476c
Packit c4476c
    }
Packit c4476c
}
Packit c4476c
Packit c4476c
static int kbkdf_ctrl_str(EVP_KDF_IMPL *ctx, const char *type,
Packit c4476c
                               const char *value)
Packit c4476c
{
Packit c4476c
    if (value == NULL) {
Packit c4476c
        KDFerr(KDF_F_KDF_SSHKDF_CTRL_STR, KDF_R_VALUE_MISSING);
Packit c4476c
        return 0;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (strcmp(type, "digest") == 0)
Packit c4476c
        return kdf_md2ctrl(ctx, kbkdf_ctrl, EVP_KDF_CTRL_SET_MD, value);
Packit c4476c
    /* alias, for historical reasons */
Packit c4476c
    if (strcmp(type, "md") == 0)
Packit c4476c
        return kdf_md2ctrl(ctx, kbkdf_ctrl, EVP_KDF_CTRL_SET_MD, value);
Packit c4476c
Packit c4476c
    if (strcmp(type, "cipher") == 0)
Packit c4476c
        return kdf_cipher2ctrl(ctx, kbkdf_ctrl, EVP_KDF_CTRL_SET_CIPHER, value);
Packit c4476c
Packit c4476c
    if (strcmp(type, "key") == 0)
Packit c4476c
        return kdf_str2ctrl(ctx, kbkdf_ctrl,
Packit c4476c
                            EVP_KDF_CTRL_SET_KEY, value);
Packit c4476c
Packit c4476c
    if (strcmp(type, "hexkey") == 0)
Packit c4476c
        return kdf_hex2ctrl(ctx, kbkdf_ctrl,
Packit c4476c
                            EVP_KDF_CTRL_SET_KEY, value);
Packit c4476c
Packit c4476c
    if (strcmp(type, "salt") == 0)
Packit c4476c
        return kdf_str2ctrl(ctx, kbkdf_ctrl,
Packit c4476c
                            EVP_KDF_CTRL_SET_SALT, value);
Packit c4476c
Packit c4476c
    if (strcmp(type, "hexsalt") == 0)
Packit c4476c
        return kdf_hex2ctrl(ctx, kbkdf_ctrl,
Packit c4476c
                            EVP_KDF_CTRL_SET_SALT, value);
Packit c4476c
Packit c4476c
    if (strcmp(type, "info") == 0)
Packit c4476c
        return kdf_str2ctrl(ctx, kbkdf_ctrl,
Packit c4476c
                            EVP_KDF_CTRL_SET_KB_INFO, value);
Packit c4476c
Packit c4476c
    if (strcmp(type, "hexinfo") == 0)
Packit c4476c
        return kdf_hex2ctrl(ctx, kbkdf_ctrl,
Packit c4476c
                            EVP_KDF_CTRL_SET_KB_INFO, value);
Packit c4476c
Packit c4476c
    if (strcmp(type, "seed") == 0)
Packit c4476c
        return kdf_str2ctrl(ctx, kbkdf_ctrl,
Packit c4476c
                            EVP_KDF_CTRL_SET_KB_SEED, value);
Packit c4476c
Packit c4476c
    if (strcmp(type, "hexseed") == 0)
Packit c4476c
        return kdf_hex2ctrl(ctx, kbkdf_ctrl,
Packit c4476c
                            EVP_KDF_CTRL_SET_KB_SEED, value);
Packit c4476c
Packit c4476c
    if (strcmp(type, "mode") == 0) {
Packit c4476c
        int mode;
Packit c4476c
Packit c4476c
        if (strcasecmp(value, "counter") == 0) {
Packit c4476c
            mode = EVP_KDF_KB_MODE_COUNTER;
Packit c4476c
        } else if (strcasecmp(value, "feedback") == 0) {
Packit c4476c
            mode = EVP_KDF_KB_MODE_FEEDBACK;
Packit c4476c
        } else {
Packit c4476c
            KDFerr(KDF_F_KBKDF_CTRL_STR, KDF_R_VALUE_ERROR);
Packit c4476c
            return 0;
Packit c4476c
        }
Packit c4476c
Packit c4476c
        return call_ctrl(kbkdf_ctrl, ctx, EVP_KDF_CTRL_SET_KB_MODE,
Packit c4476c
                         mode);
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (strcmp(type, "mac_type") == 0) {
Packit c4476c
        int mac_type;
Packit c4476c
Packit c4476c
        if (strcasecmp(value, "hmac") == 0) {
Packit c4476c
            mac_type = EVP_KDF_KB_MAC_TYPE_HMAC;
Packit c4476c
        } else if (strcasecmp(value, "cmac") == 0) {
Packit c4476c
            mac_type = EVP_KDF_KB_MAC_TYPE_CMAC;
Packit c4476c
        } else {
Packit c4476c
            KDFerr(KDF_F_KBKDF_CTRL_STR, KDF_R_VALUE_ERROR);
Packit c4476c
            return 0;
Packit c4476c
        }
Packit c4476c
Packit c4476c
        return call_ctrl(kbkdf_ctrl, ctx, EVP_KDF_CTRL_SET_KB_MAC_TYPE,
Packit c4476c
                         mac_type);
Packit c4476c
    }
Packit c4476c
Packit c4476c
    KDFerr(KDF_F_KBKDF_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE);
Packit c4476c
    return -2;
Packit c4476c
}
Packit c4476c
Packit c4476c
const EVP_KDF_METHOD kb_kdf_meth = {
Packit c4476c
    EVP_KDF_KB,
Packit c4476c
    kbkdf_new,
Packit c4476c
    kbkdf_free,
Packit c4476c
    kbkdf_reset,
Packit c4476c
    kbkdf_ctrl,
Packit c4476c
    kbkdf_ctrl_str,
Packit c4476c
    kbkdf_size,
Packit c4476c
    kbkdf_derive,
Packit c4476c
};
Packit c4476c