Commit 567db2c1 authored by Richard Levitte's avatar Richard Levitte
Browse files

Add EVP_MAC API



We currently implement EVP MAC methods as EVP_PKEY methods.  This
change creates a separate EVP API for MACs, to replace the current
EVP_PKEY ones.

A note about this EVP API and how it interfaces with underlying MAC
implementations:

Other EVP APIs pass the EVP API context down to implementations, and
it can be observed that the implementations use the pointer to their
own private data almost exclusively.  The EVP_MAC API deviates from
that pattern by passing the pointer to the implementation's private
data directly, and thereby deny the implementations access to the
EVP_MAC context structure.  This change is made to provide a clearer
separation between the EVP library itself and the implementations of
its supported algorithm classes.

Reviewed-by: default avatarPaul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/7393)
parent f9e43929
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -740,6 +740,11 @@ EVP_F_EVP_DIGESTFINALXOF:174:EVP_DigestFinalXOF
EVP_F_EVP_DIGESTINIT_EX:128:EVP_DigestInit_ex
EVP_F_EVP_ENCRYPTFINAL_EX:127:EVP_EncryptFinal_ex
EVP_F_EVP_ENCRYPTUPDATE:167:EVP_EncryptUpdate
EVP_F_EVP_MAC_CTRL:209:EVP_MAC_ctrl
EVP_F_EVP_MAC_CTRL_STR:210:EVP_MAC_ctrl_str
EVP_F_EVP_MAC_CTX_COPY:211:EVP_MAC_CTX_copy
EVP_F_EVP_MAC_CTX_NEW:213:EVP_MAC_CTX_new
EVP_F_EVP_MAC_INIT:212:EVP_MAC_init
EVP_F_EVP_MD_CTX_COPY_EX:110:EVP_MD_CTX_copy_ex
EVP_F_EVP_MD_SIZE:162:EVP_MD_size
EVP_F_EVP_OPENINIT:102:EVP_OpenInit
+2 −1
Original line number Diff line number Diff line
@@ -12,7 +12,8 @@ SOURCE[../../libcrypto]=\
        evp_pkey.c evp_pbe.c p5_crpt.c p5_crpt2.c pbe_scrypt.c \
        e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c \
        e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \
        e_chacha20_poly1305.c cmeth_lib.c
        e_chacha20_poly1305.c cmeth_lib.c \
        mac_lib.c

INCLUDE[e_aes.o]=.. ../modes
INCLUDE[e_aes_cbc_hmac_sha1.o]=../modes
+5 −0
Original line number Diff line number Diff line
@@ -54,6 +54,11 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTFINAL_EX, 0),
     "EVP_EncryptFinal_ex"},
    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTUPDATE, 0), "EVP_EncryptUpdate"},
    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTRL, 0), "EVP_MAC_ctrl"},
    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTRL_STR, 0), "EVP_MAC_ctrl_str"},
    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTX_COPY, 0), "EVP_MAC_CTX_copy"},
    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTX_NEW, 0), "EVP_MAC_CTX_new"},
    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_INIT, 0), "EVP_MAC_init"},
    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MD_CTX_COPY_EX, 0), "EVP_MD_CTX_copy_ex"},
    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MD_SIZE, 0), "EVP_MD_size"},
    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_OPENINIT, 0), "EVP_OpenInit"},
+5 −0
Original line number Diff line number Diff line
@@ -41,6 +41,11 @@ struct evp_cipher_ctx_st {
    unsigned char final[EVP_MAX_BLOCK_LENGTH]; /* possible final block */
} /* EVP_CIPHER_CTX */ ;

struct evp_mac_ctx_st {
    const EVP_MAC *meth;         /* Method structure */
    void *data;                  /* Individual method data */
} /* EVP_MAC_CTX */;

int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
                             int passlen, ASN1_TYPE *param,
                             const EVP_CIPHER *c, const EVP_MD *md,

crypto/evp/mac_lib.c

0 → 100644
+185 −0
Original line number Diff line number Diff line
/*
 * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

#include <string.h>
#include <stdarg.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/ossl_typ.h>
#include "internal/nelem.h"
#include "internal/evp_int.h"
#include "evp_locl.h"

EVP_MAC_CTX *EVP_MAC_CTX_new_id(int id)
{
    const EVP_MAC *mac = EVP_get_macbynid(id);

    if (mac == NULL)
        return NULL;
    return EVP_MAC_CTX_new(mac);
}

EVP_MAC_CTX *EVP_MAC_CTX_new(const EVP_MAC *mac)
{
    EVP_MAC_CTX *ctx = OPENSSL_zalloc(sizeof(EVP_MAC_CTX));

    if (ctx == NULL || (ctx->data = mac->new()) == NULL) {
        EVPerr(EVP_F_EVP_MAC_CTX_NEW, ERR_R_MALLOC_FAILURE);
        OPENSSL_free(ctx);
        ctx = NULL;
    } else {
        ctx->meth = mac;
    }
    return ctx;
}

void EVP_MAC_CTX_free(EVP_MAC_CTX *ctx)
{
    if (ctx != NULL && ctx->data != NULL) {
        ctx->meth->free(ctx->data);
        ctx->data = NULL;
    }
    OPENSSL_free(ctx);
}

int EVP_MAC_CTX_copy(EVP_MAC_CTX *dst, EVP_MAC_CTX *src)
{
    EVP_MAC_IMPL *macdata;

    if (src->data != NULL && !dst->meth->copy(dst->data, src->data))
        return 0;

    macdata = dst->data;
    *dst = *src;
    dst->data = macdata;

    return 1;
}

const EVP_MAC *EVP_MAC_CTX_mac(EVP_MAC_CTX *ctx)
{
    return ctx->meth;
}

size_t EVP_MAC_size(EVP_MAC_CTX *ctx)
{
    if (ctx->data != NULL)
        return ctx->meth->size(ctx->data);
    /* If the MAC hasn't been initialized yet, we return zero */
    return 0;
}

int EVP_MAC_init(EVP_MAC_CTX *ctx)
{
    return ctx->meth->init(ctx->data);
}

int EVP_MAC_update(EVP_MAC_CTX *ctx, const unsigned char *data, size_t datalen)
{
    return ctx->meth->update(ctx->data, data, datalen);
}

int EVP_MAC_final(EVP_MAC_CTX *ctx, unsigned char *out, size_t *poutlen)
{
    int l = ctx->meth->size(ctx->data);

    if (l < 0)
        return 0;
    if (poutlen != NULL)
        *poutlen = l;
    if (out == NULL)
        return 1;
    return ctx->meth->final(ctx->data, out);
}

int EVP_MAC_ctrl(EVP_MAC_CTX *ctx, int cmd, ...)
{
    int ok = -1;
    va_list args;

    va_start(args, cmd);
    ok = EVP_MAC_vctrl(ctx, cmd, args);
    va_end(args);

    if (ok == -2)
        EVPerr(EVP_F_EVP_MAC_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);

    return ok;
}

int EVP_MAC_vctrl(EVP_MAC_CTX *ctx, int cmd, va_list args)
{
    int ok = 1;

    if (ctx == NULL || ctx->meth == NULL)
        return -2;

    switch (cmd) {
#if 0
    case ...:
        /* code */
        ok = 1;
        break;
#endif
    default:
        if (ctx->meth->ctrl != NULL)
            ok = ctx->meth->ctrl(ctx->data, cmd, args);
        else
            ok = -2;
        break;
    }

    return ok;
}

int EVP_MAC_ctrl_str(EVP_MAC_CTX *ctx, const char *type, const char *value)
{
    int ok = 1;

    if (ctx == NULL || ctx->meth == NULL || ctx->meth->ctrl_str == NULL) {
        EVPerr(EVP_F_EVP_MAC_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
        return -2;
    }

    ok = ctx->meth->ctrl_str(ctx->data, type, value);

    if (ok == -2)
        EVPerr(EVP_F_EVP_MAC_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
    return ok;
}

int EVP_MAC_str2ctrl(EVP_MAC_CTX *ctx, int cmd, const char *value)
{
    size_t len;

    len = strlen(value);
    if (len > INT_MAX)
        return -1;
    return EVP_MAC_ctrl(ctx, cmd, value, len);
}

int EVP_MAC_hex2ctrl(EVP_MAC_CTX *ctx, int cmd, const char *hex)
{
    unsigned char *bin;
    long binlen;
    int rv = -1;

    bin = OPENSSL_hexstr2buf(hex, &binlen);
    if (bin == NULL)
        return 0;
    if (binlen <= INT_MAX)
        rv = EVP_MAC_ctrl(ctx, cmd, bin, (size_t)binlen);
    OPENSSL_free(bin);
    return rv;
}

int EVP_MAC_nid(const EVP_MAC *mac)
{
    return mac->type;
}
Loading