[openssl-commits] [openssl] master update

Richard Levitte levitte at openssl.org
Mon Oct 29 12:37:27 UTC 2018


The branch master has been updated
       via  f842b6b2a4d7cbb9d22e4605c502b73f25bb6a7b (commit)
       via  2bdb4af50364121a5f0e47024e9f71e1a6025fcf (commit)
       via  5e55159b3adbb30482992e8fa8621e47d331d012 (commit)
       via  0145dd324e8fcfd2c0dfe296c12586101f0cf3b9 (commit)
       via  567db2c17d4ea8a0164d7abd8aed65b7a634bb40 (commit)
      from  f9e43929c46b38667f67e02765fe0f1c0d3061d6 (commit)


- Log -----------------------------------------------------------------
commit f842b6b2a4d7cbb9d22e4605c502b73f25bb6a7b
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Oct 24 20:20:00 2018 +0200

    Add convenience functions EVP_str2ctrl() and EVP_hex2ctrl()
    
    These functions are generalizations of EVP_PKEY_CTX_str2ctrl() and
    EVP_PKEY_CTX_hex2ctrl().  They will parse the value, and then pass the
    parsed result and length to a callback that knows exactly how to pass
    them on to a main _ctrl function, along with a context structure
    pointer.
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/7393)

commit 2bdb4af50364121a5f0e47024e9f71e1a6025fcf
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Oct 24 18:36:31 2018 +0200

    Adapt test/evp_test.c to deal with available EVP_MACs
    
    If a MAC isn't available as an EVP_MAC, the MAC test falls back to the
    corresponding EVP_PKEY method.
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/7393)

commit 5e55159b3adbb30482992e8fa8621e47d331d012
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Oct 24 18:35:32 2018 +0200

    Add generic EVP_PKEY_METHOD for EVP_MACs
    
    The MAC EVP_PKEY implementations are currently implemented for each
    MAC.  However, with the EVP_MAC API, only one such implementation is
    needed.
    
    This implementation takes into account the differences between HMAC
    and CMAC implementations, and observes that all other current MAC
    implementations seem to follow the HMAC model.
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/7393)

commit 0145dd324e8fcfd2c0dfe296c12586101f0cf3b9
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Oct 24 18:34:53 2018 +0200

    Add automatic initializations support for EVP_MAC objects
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/7393)

commit 567db2c17d4ea8a0164d7abd8aed65b7a634bb40
Author: Richard Levitte <levitte at openssl.org>
Date:   Fri Oct 12 22:27:18 2018 +0200

    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: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/7393)

-----------------------------------------------------------------------

Summary of changes:
 crypto/err/openssl.txt                   |   6 +
 crypto/evp/build.info                    |   3 +-
 crypto/{conf/conf_lcl.h => evp/c_allm.c} |   6 +-
 crypto/evp/evp_err.c                     |   6 +
 crypto/evp/evp_lib.c                     |  27 +++
 crypto/evp/evp_locl.h                    |   5 +
 crypto/evp/mac_lib.c                     | 185 ++++++++++++++++
 crypto/evp/names.c                       |  75 ++++++-
 crypto/evp/pkey_mac.c                    | 368 +++++++++++++++++++++++++++++++
 crypto/include/internal/evp_int.h        |  26 +++
 crypto/init.c                            |  25 +++
 doc/man3/EVP_MAC.pod                     | 348 +++++++++++++++++++++++++++++
 include/openssl/crypto.h                 |   9 +-
 include/openssl/evp.h                    |  47 ++++
 include/openssl/evperr.h                 |   6 +
 include/openssl/objects.h                |   3 +-
 include/openssl/ossl_typ.h               |   2 +
 ssl/ssl_init.c                           |   3 +-
 test/evp_test.c                          | 192 ++++++++++++++--
 util/libcrypto.num                       |  20 ++
 util/private.num                         |   5 +
 21 files changed, 1341 insertions(+), 26 deletions(-)
 copy crypto/{conf/conf_lcl.h => evp/c_allm.c} (77%)
 create mode 100644 crypto/evp/mac_lib.c
 create mode 100644 crypto/evp/pkey_mac.c
 create mode 100644 doc/man3/EVP_MAC.pod

diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 489ccc0..151bc83 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -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
@@ -802,6 +807,7 @@ EVP_F_PKCS5_PBE_KEYIVGEN:117:PKCS5_PBE_keyivgen
 EVP_F_PKCS5_V2_PBE_KEYIVGEN:118:PKCS5_v2_PBE_keyivgen
 EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN:164:PKCS5_v2_PBKDF2_keyivgen
 EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN:180:PKCS5_v2_scrypt_keyivgen
+EVP_F_PKEY_MAC_INIT:214:pkey_mac_init
 EVP_F_PKEY_SET_TYPE:158:pkey_set_type
 EVP_F_RC2_MAGIC_TO_METH:109:rc2_magic_to_meth
 EVP_F_RC5_CTRL:125:rc5_ctrl
diff --git a/crypto/evp/build.info b/crypto/evp/build.info
index cc33ac3..84193b0 100644
--- a/crypto/evp/build.info
+++ b/crypto/evp/build.info
@@ -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 c_allm.c pkey_mac.c
 
 INCLUDE[e_aes.o]=.. ../modes
 INCLUDE[e_aes_cbc_hmac_sha1.o]=../modes
diff --git a/crypto/conf/conf_lcl.h b/crypto/evp/c_allm.c
similarity index 77%
copy from crypto/conf/conf_lcl.h
copy to crypto/evp/c_allm.c
index 6e1f7fe..d5eb858 100644
--- a/crypto/conf/conf_lcl.h
+++ b/crypto/evp/c_allm.c
@@ -7,5 +7,9 @@
  * https://www.openssl.org/source/license.html
  */
 
-void conf_add_ssl_module(void);
+#include <openssl/evp.h>
+#include "internal/evp_int.h"
 
+void openssl_add_all_macs_int(void)
+{
+}
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c
index ec6efb6..32760db 100644
--- a/crypto/evp/evp_err.c
+++ b/crypto/evp/evp_err.c
@@ -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"},
@@ -145,6 +150,7 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
      "PKCS5_v2_PBKDF2_keyivgen"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, 0),
      "PKCS5_v2_scrypt_keyivgen"},
+    {ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_MAC_INIT, 0), "pkey_mac_init"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_SET_TYPE, 0), "pkey_set_type"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_RC2_MAGIC_TO_METH, 0), "rc2_magic_to_meth"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_RC5_CTRL, 0), "rc5_ctrl"},
diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c
index 1b3c984..01c8939 100644
--- a/crypto/evp/evp_lib.c
+++ b/crypto/evp/evp_lib.c
@@ -526,3 +526,30 @@ int EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx, int flags)
 {
     return (ctx->flags & flags);
 }
+
+int EVP_str2ctrl(int (*cb)(void *ctx, int cmd, void *buf, size_t buflen),
+                 void *ctx, int cmd, const char *value)
+{
+    size_t len;
+
+    len = strlen(value);
+    if (len > INT_MAX)
+        return -1;
+    return cb(ctx, cmd, (void *)value, len);
+}
+
+int EVP_hex2ctrl(int (*cb)(void *ctx, int cmd, void *buf, size_t buflen),
+                 void *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 = cb(ctx, cmd, bin, binlen);
+    OPENSSL_free(bin);
+    return rv;
+}
diff --git a/crypto/evp/evp_locl.h b/crypto/evp/evp_locl.h
index f1589d6..eaee472 100644
--- a/crypto/evp/evp_locl.h
+++ b/crypto/evp/evp_locl.h
@@ -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,
diff --git a/crypto/evp/mac_lib.c b/crypto/evp/mac_lib.c
new file mode 100644
index 0000000..2786a01
--- /dev/null
+++ b/crypto/evp/mac_lib.c
@@ -0,0 +1,185 @@
+/*
+ * 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;
+}
diff --git a/crypto/evp/names.c b/crypto/evp/names.c
index 077c2a6..6cdab22 100644
--- a/crypto/evp/names.c
+++ b/crypto/evp/names.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-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
@@ -55,6 +55,22 @@ int EVP_add_digest(const EVP_MD *md)
     return r;
 }
 
+int EVP_add_mac(const EVP_MAC *m)
+{
+    int r;
+
+    if (m == NULL)
+        return 0;
+
+    r = OBJ_NAME_add(OBJ_nid2sn(m->type), OBJ_NAME_TYPE_MAC_METH,
+                     (const char *)m);
+    if (r == 0)
+        return 0;
+    r = OBJ_NAME_add(OBJ_nid2ln(m->type), OBJ_NAME_TYPE_MAC_METH,
+                     (const char *)m);
+    return r;
+}
+
 const EVP_CIPHER *EVP_get_cipherbyname(const char *name)
 {
     const EVP_CIPHER *cp;
@@ -77,8 +93,20 @@ const EVP_MD *EVP_get_digestbyname(const char *name)
     return cp;
 }
 
+const EVP_MAC *EVP_get_macbyname(const char *name)
+{
+    const EVP_MAC *mp;
+
+    if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_MACS, NULL))
+        return NULL;
+
+    mp = (const EVP_MAC *)OBJ_NAME_get(name, OBJ_NAME_TYPE_MAC_METH);
+    return mp;
+}
+
 void evp_cleanup_int(void)
 {
+    OBJ_NAME_cleanup(OBJ_NAME_TYPE_MAC_METH);
     OBJ_NAME_cleanup(OBJ_NAME_TYPE_CIPHER_METH);
     OBJ_NAME_cleanup(OBJ_NAME_TYPE_MD_METH);
     /*
@@ -178,3 +206,48 @@ void EVP_MD_do_all_sorted(void (*fn) (const EVP_MD *md,
     dc.arg = arg;
     OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH, do_all_md_fn, &dc);
 }
+
+struct doall_mac {
+    void *arg;
+    void (*fn) (const EVP_MAC *ciph,
+                const char *from, const char *to, void *arg);
+};
+
+static void do_all_mac_fn(const OBJ_NAME *nm, void *arg)
+{
+    struct doall_mac *dc = arg;
+
+    if (nm->alias)
+        dc->fn(NULL, nm->name, nm->data, dc->arg);
+    else
+        dc->fn((const EVP_MAC *)nm->data, nm->name, NULL, dc->arg);
+}
+
+void EVP_MAC_do_all(void (*fn)
+                    (const EVP_MAC *ciph, const char *from, const char *to,
+                     void *x), void *arg)
+{
+    struct doall_mac dc;
+
+    /* Ignore errors */
+    OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_MACS, NULL);
+
+    dc.fn = fn;
+    dc.arg = arg;
+    OBJ_NAME_do_all(OBJ_NAME_TYPE_MAC_METH, do_all_mac_fn, &dc);
+}
+
+void EVP_MAC_do_all_sorted(void (*fn)
+                           (const EVP_MAC *ciph, const char *from,
+                            const char *to, void *x), void *arg)
+{
+    struct doall_mac dc;
+
+    /* Ignore errors */
+    OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_MACS, NULL);
+
+    dc.fn = fn;
+    dc.arg = arg;
+    OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MAC_METH, do_all_mac_fn, &dc);
+}
+
diff --git a/crypto/evp/pkey_mac.c b/crypto/evp/pkey_mac.c
new file mode 100644
index 0000000..d4aa585
--- /dev/null
+++ b/crypto/evp/pkey_mac.c
@@ -0,0 +1,368 @@
+/*
+ * 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 <openssl/err.h>
+#include <openssl/evp.h>
+#include "internal/evp_int.h"
+
+/* MAC PKEY context structure */
+
+typedef struct {
+    EVP_MAC_CTX *ctx;
+
+    /*
+     * We know of two MAC types:
+     *
+     * 1. those who take a secret in raw form, i.e. raw data as a
+     *    ASN1_OCTET_STRING embedded in a EVP_PKEY.  So far, that's
+     *    all of them but CMAC.
+     * 2. those who take a secret with associated cipher in very generic
+     *    form, i.e. a complete EVP_MAC_CTX embedded in a PKEY.  So far,
+     *    only CMAC does this.
+     *
+     * (one might wonder why the second form isn't used for all)
+     */
+#define MAC_TYPE_RAW    1   /* HMAC like MAC type (all but CMAC so far) */
+#define MAC_TYPE_MAC    2   /* CMAC like MAC type (only CMAC known so far) */
+    int type;
+
+    /* The following is only used for MAC_TYPE_RAW implementations */
+    struct {
+        const EVP_MD *md;           /* temp storage of MD */
+        ASN1_OCTET_STRING ktmp;     /* temp storage for key */
+    } raw_data;
+} MAC_PKEY_CTX;
+
+static int pkey_mac_init(EVP_PKEY_CTX *ctx)
+{
+    MAC_PKEY_CTX *hctx;
+    int nid = ctx->pmeth->pkey_id;
+
+    if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL) {
+        EVPerr(EVP_F_PKEY_MAC_INIT, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+
+    /* We're being smart and using the same base NIDs for PKEY and for MAC */
+    hctx->ctx = EVP_MAC_CTX_new_id(nid);
+    if (hctx->ctx == NULL) {
+        OPENSSL_free(hctx);
+        return 0;
+    }
+
+    if (nid == EVP_PKEY_CMAC) {
+        hctx->type = MAC_TYPE_MAC;
+    } else {
+        hctx->type = MAC_TYPE_RAW;
+        hctx->raw_data.ktmp.type = V_ASN1_OCTET_STRING;
+    }
+
+    EVP_PKEY_CTX_set_data(ctx, hctx);
+    ctx->keygen_info_count = 0;
+
+    return 1;
+}
+
+static void pkey_mac_cleanup(EVP_PKEY_CTX *ctx);
+
+static int pkey_mac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
+{
+    MAC_PKEY_CTX *sctx, *dctx;
+
+    if (!pkey_mac_init(dst))
+        return 0;
+
+    sctx = EVP_PKEY_CTX_get_data(src);
+    dctx = EVP_PKEY_CTX_get_data(dst);
+
+    if (!EVP_MAC_CTX_copy(dctx->ctx, sctx->ctx))
+        goto err;
+
+    switch (dctx->type) {
+    case MAC_TYPE_RAW:
+        dctx->raw_data.md = sctx->raw_data.md;
+        if (ASN1_STRING_get0_data(&sctx->raw_data.ktmp) != NULL &&
+            !ASN1_STRING_copy(&dctx->raw_data.ktmp, &sctx->raw_data.ktmp))
+            goto err;
+        break;
+    case MAC_TYPE_MAC:
+        /* Nothing more to do */
+        break;
+    default:
+        /* This should be dead code */
+        return 0;
+    }
+    return 1;
+ err:
+    pkey_mac_cleanup (dst);
+    return 0;
+}
+
+static void pkey_mac_cleanup(EVP_PKEY_CTX *ctx)
+{
+    MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
+
+    if (hctx != NULL) {
+        switch (hctx->type) {
+        case MAC_TYPE_RAW:
+            OPENSSL_clear_free(hctx->raw_data.ktmp.data,
+                               hctx->raw_data.ktmp.length);
+            break;
+        }
+        EVP_MAC_CTX_free(hctx->ctx);
+        OPENSSL_free(hctx);
+        EVP_PKEY_CTX_set_data(ctx, NULL);
+    }
+}
+
+static int pkey_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+    MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
+    int nid = ctx->pmeth->pkey_id;
+
+    switch (hctx->type) {
+    case MAC_TYPE_RAW:
+        {
+            ASN1_OCTET_STRING *hkey = NULL;
+
+            if (!hctx->raw_data.ktmp.data)
+                return 0;
+            hkey = ASN1_OCTET_STRING_dup(&hctx->raw_data.ktmp);
+            if (!hkey)
+                return 0;
+            EVP_PKEY_assign(pkey, nid, hkey);
+        }
+        break;
+    case MAC_TYPE_MAC:
+        {
+            EVP_MAC_CTX *cmkey = EVP_MAC_CTX_new_id(nid);
+
+            if (cmkey == NULL)
+                return 0;
+            if (!EVP_MAC_CTX_copy(cmkey, hctx->ctx)) {
+                EVP_MAC_CTX_free(cmkey);
+                return 0;
+            }
+            EVP_PKEY_assign(pkey, nid, cmkey);
+        }
+        break;
+    default:
+        /* This should be dead code */
+        return 0;
+    }
+
+    return 1;
+}
+
+static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+    MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(EVP_MD_CTX_pkey_ctx(ctx));
+
+    if (!EVP_MAC_update(hctx->ctx, data, count))
+        return 0;
+    return 1;
+}
+
+static int pkey_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
+{
+    MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
+    ASN1_OCTET_STRING *key = NULL;
+    int rv = 1;
+    /*
+     * For MACs with the EVP_PKEY_FLAG_SIGCTX_CUSTOM flag set and that
+     * gets the key passed as an ASN.1 OCTET STRING, we set the key here,
+     * as this may be only time it's set during a DigestSign.
+     *
+     * MACs that pass around the key in form of EVP_MAC_CTX are setting
+     * the key through other mechanisms.  (this is only CMAC for now)
+     */
+    int set_key =
+        hctx->type == MAC_TYPE_RAW
+        && (ctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) != 0;
+
+    if (set_key) {
+        if (EVP_PKEY_id(EVP_PKEY_CTX_get0_pkey(ctx))
+            != EVP_MAC_nid(EVP_MAC_CTX_mac(hctx->ctx)))
+            return 0;
+        key = EVP_PKEY_get0(EVP_PKEY_CTX_get0_pkey(ctx));
+        if (key == NULL)
+            return 0;
+    }
+
+    /* Some MACs don't support this control...  that's fine */
+    EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_FLAGS,
+                 EVP_MD_CTX_test_flags(mctx, ~EVP_MD_CTX_FLAG_NO_INIT));
+
+    EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT);
+    EVP_MD_CTX_set_update_fn(mctx, int_update);
+
+    if (set_key)
+        rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY, key->data,
+                          key->length);
+    return rv > 0;
+}
+
+static int pkey_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig,
+                             size_t *siglen, EVP_MD_CTX *mctx)
+{
+    MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
+
+    return EVP_MAC_final(hctx->ctx, sig, siglen);
+}
+
+static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
+{
+    MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
+
+    switch (type) {
+
+    case EVP_PKEY_CTRL_CIPHER:
+        switch (hctx->type) {
+        case MAC_TYPE_RAW:
+            return -2;       /* The raw types don't support ciphers */
+        case MAC_TYPE_MAC:
+            {
+                int rv;
+
+                if ((rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_ENGINE,
+                                       ctx->engine)) < 0
+                    || (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_CIPHER,
+                                          p2)) < 0
+                    || !(rv = EVP_MAC_init(hctx->ctx)))
+                    return rv;
+            }
+            break;
+        default:
+            /* This should be dead code */
+            return 0;
+        }
+        break;
+
+    case EVP_PKEY_CTRL_MD:
+        switch (hctx->type) {
+        case MAC_TYPE_RAW:
+            hctx->raw_data.md = p2;
+            break;
+        case MAC_TYPE_MAC:
+            if (ctx->pkey != NULL
+                && !EVP_MAC_CTX_copy(hctx->ctx,
+                                     (EVP_MAC_CTX *)ctx->pkey->pkey.ptr))
+                return 0;
+            if (!EVP_MAC_init(hctx->ctx))
+                return 0;
+            break;
+        default:
+            /* This should be dead code */
+            return 0;
+        }
+        break;
+
+    case EVP_PKEY_CTRL_SET_DIGEST_SIZE:
+        return EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_SIZE, (size_t)p1);
+
+    case EVP_PKEY_CTRL_SET_MAC_KEY:
+        switch (hctx->type) {
+        case MAC_TYPE_RAW:
+            if ((!p2 && p1 > 0) || (p1 < -1))
+                return 0;
+            if (!ASN1_OCTET_STRING_set(&hctx->raw_data.ktmp, p2, p1))
+                return 0;
+            break;
+        case MAC_TYPE_MAC:
+            if (!EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY, p2, p1))
+                return 0;
+            break;
+        default:
+            /* This should be dead code */
+            return 0;
+        }
+        break;
+
+    case EVP_PKEY_CTRL_DIGESTINIT:
+        switch (hctx->type) {
+        case MAC_TYPE_RAW:
+            /* Ensure that we have attached the implementation */
+            if (!EVP_MAC_init(hctx->ctx))
+                return 0;
+            {
+                int rv;
+                ASN1_OCTET_STRING *key =
+                    (ASN1_OCTET_STRING *)ctx->pkey->pkey.ptr;
+
+                if ((rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_ENGINE,
+                                       ctx->engine)) < 0
+                    || (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_MD,
+                                          hctx->raw_data.md)) < 0
+                    || (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY,
+                                          key->data, key->length)) < 0)
+                    return rv;
+            }
+            break;
+        case MAC_TYPE_MAC:
+            return -2;       /* The mac types don't support ciphers */
+        default:
+            /* This should be dead code */
+            return 0;
+        }
+        break;
+
+    default:
+        return -2;
+
+    }
+    return 1;
+}
+
+static int pkey_mac_ctrl_str(EVP_PKEY_CTX *ctx,
+                              const char *type, const char *value)
+{
+    MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
+
+    return EVP_MAC_ctrl_str(hctx->ctx, type, value);
+}
+
+/*
+ * When this is actually used, the following will be replaced with real
+ * EVP_PKEY_METHODs, all exactly the same apart from the type and possibly
+ * the flags.
+ */
+
+extern const EVP_PKEY_METHOD FAKE_pkey_meth;
+const EVP_PKEY_METHOD FAKE_pkey_meth = {
+    20870442 /* EVP_PKEY_FAKE, a beast times 31337 (you do the math) */,
+    EVP_PKEY_FLAG_SIGCTX_CUSTOM,
+    pkey_mac_init,
+    pkey_mac_copy,
+    pkey_mac_cleanup,
+
+    0, 0,
+
+    0,
+    pkey_mac_keygen,
+
+    0, 0,
+
+    0, 0,
+
+    0, 0,
+
+    pkey_mac_signctx_init,
+    pkey_mac_signctx,
+
+    0, 0,
+
+    0, 0,
+
+    0, 0,
+
+    0, 0,
+
+    pkey_mac_ctrl,
+    pkey_mac_ctrl_str
+};
diff --git a/crypto/include/internal/evp_int.h b/crypto/include/internal/evp_int.h
index d86aed3..dadade3 100644
--- a/crypto/include/internal/evp_int.h
+++ b/crypto/include/internal/evp_int.h
@@ -112,6 +112,31 @@ extern const EVP_PKEY_METHOD hkdf_pkey_meth;
 extern const EVP_PKEY_METHOD poly1305_pkey_meth;
 extern const EVP_PKEY_METHOD siphash_pkey_meth;
 
+/* struct evp_mac_impl_st is defined by the implementation */
+typedef struct evp_mac_impl_st EVP_MAC_IMPL;
+struct evp_mac_st {
+    int type;
+    EVP_MAC_IMPL *(*new) (void);
+    int (*copy) (EVP_MAC_IMPL *macdst, EVP_MAC_IMPL *macsrc);
+    void (*free) (EVP_MAC_IMPL *macctx);
+    size_t (*size) (EVP_MAC_IMPL *macctx);
+    int (*init) (EVP_MAC_IMPL *macctx);
+    int (*update) (EVP_MAC_IMPL *macctx, const unsigned char *data,
+                   size_t datalen);
+    int (*final) (EVP_MAC_IMPL *macctx, unsigned char *out);
+    int (*ctrl) (EVP_MAC_IMPL *macctx, int cmd, va_list args);
+    int (*ctrl_str) (EVP_MAC_IMPL *macctx, const char *type, const char *value);
+};
+
+/*
+ * This function is internal for now, but can be made external when needed.
+ * The documentation would read:
+ *
+ * EVP_add_mac() adds the MAC implementation C<mac> to the internal
+ * object database.
+ */
+int EVP_add_mac(const EVP_MAC *mac);
+
 struct evp_md_st {
     int type;
     int pkey_type;
@@ -423,6 +448,7 @@ struct evp_pkey_st {
 
 void openssl_add_all_ciphers_int(void);
 void openssl_add_all_digests_int(void);
+void openssl_add_all_macs_int(void);
 void evp_cleanup_int(void);
 void evp_app_cleanup_int(void);
 
diff --git a/crypto/init.c b/crypto/init.c
index 209d1a4..fc6aade 100644
--- a/crypto/init.c
+++ b/crypto/init.c
@@ -235,6 +235,23 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_digests)
     return 1;
 }
 
+static CRYPTO_ONCE add_all_macs = CRYPTO_ONCE_STATIC_INIT;
+DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_macs)
+{
+    /*
+     * OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time
+     * pulling in all the macs during static linking
+     */
+#ifndef OPENSSL_NO_AUTOALGINIT
+# ifdef OPENSSL_INIT_DEBUG
+    fprintf(stderr, "OPENSSL_INIT: ossl_init_add_all_macs: "
+                    "openssl_add_all_macs_int()\n");
+# endif
+    openssl_add_all_macs_int();
+#endif
+    return 1;
+}
+
 DEFINE_RUN_ONCE_STATIC(ossl_init_no_add_algs)
 {
     /* Do nothing */
@@ -619,6 +636,14 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
             && !RUN_ONCE(&add_all_digests, ossl_init_add_all_digests))
         return 0;
 
+    if ((opts & OPENSSL_INIT_NO_ADD_ALL_MACS)
+            && !RUN_ONCE(&add_all_macs, ossl_init_no_add_algs))
+        return 0;
+
+    if ((opts & OPENSSL_INIT_ADD_ALL_MACS)
+            && !RUN_ONCE(&add_all_macs, ossl_init_add_all_macs))
+        return 0;
+
     if ((opts & OPENSSL_INIT_ATFORK)
             && !openssl_init_fork_handlers())
         return 0;
diff --git a/doc/man3/EVP_MAC.pod b/doc/man3/EVP_MAC.pod
new file mode 100644
index 0000000..a30f3fa
--- /dev/null
+++ b/doc/man3/EVP_MAC.pod
@@ -0,0 +1,348 @@
+=pod
+
+=head1 NAME
+
+EVP_MAC, EVP_MAC_CTX, EVP_MAC_CTX_new, EVP_MAC_CTX_new_id, EVP_MAC_CTX_free,
+EVP_MAC_CTX_copy, EVP_MAC_CTX_mac, EVP_MAC_size, EVP_MAC_init, EVP_MAC_update,
+EVP_MAC_final, EVP_MAC_ctrl, EVP_MAC_vctrl, EVP_MAC_ctrl_str,
+EVP_MAC_str2ctrl, EVP_MAC_hex2ctrl, EVP_MAC_nid, EVP_MAC_name,
+EVP_get_macbyname, EVP_get_macbynid, EVP_get_macbyobj - EVP MAC routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ typedef struct evp_mac_st EVP_MAC;
+ typedef struct evp_mac_ctx_st EVP_MAC_CTX;
+
+ EVP_MAC_CTX *EVP_MAC_CTX_new(const EVP_MAC *mac);
+ EVP_MAC_CTX *EVP_MAC_CTX_new_id(int nid);
+ void EVP_MAC_CTX_free(EVP_MAC_CTX *ctx);
+ int EVP_MAC_CTX_copy(EVP_MAC_CTX *dest, EVP_MAC_CTX *src);
+ const EVP_MAC *EVP_MAC_CTX_mac(EVP_MAC_CTX *ctx);
+ size_t EVP_MAC_size(EVP_MAC_CTX *ctx);
+ int EVP_MAC_init(EVP_MAC_CTX *ctx);
+ int EVP_MAC_update(EVP_MAC_CTX *ctx, const unsigned char *data, size_t datalen);
+ int EVP_MAC_final(EVP_MAC_CTX *ctx, unsigned char *out, size_t *poutlen);
+ int EVP_MAC_ctrl(EVP_MAC_CTX *ctx, int cmd, ...);
+ int EVP_MAC_vctrl(EVP_MAC_CTX *ctx, int cmd, va_list args);
+ int EVP_MAC_ctrl_str(EVP_MAC_CTX *ctx, const char *type, const char *value);
+ int EVP_MAC_str2ctrl(EVP_MAC_CTX *ctx, int cmd, const char *value);
+ int EVP_MAC_hex2ctrl(EVP_MAC_CTX *ctx, int cmd, const char *value);
+ int EVP_MAC_nid(const EVP_MAC *mac);
+ const char *EVP_MAC_name(const EVP_MAC *mac);
+ const EVP_MAC *EVP_get_macbyname(const char *name);
+ const EVP_MAC *EVP_get_macbynid(int nid);
+ const EVP_MAC *EVP_get_macbyobj(const ASN1_OBJECT *o);
+
+=head1 DESCRIPTION
+
+These types and functions help the application to calculate MACs of
+different types and with different underlying algorithms if there are
+any.
+
+MACs are a bit complex insofar that some of them use other algorithms
+for actual computation.  HMAC uses a digest, and CMAC uses a cipher.
+Therefore, there are sometimes two contexts to keep track of, one for
+the MAC algorithm itself and one for the underlying computation
+algorithm if there is one.
+
+To make things less ambiguous, this manual talks about a "context" or
+"MAC context", which is to denote the MAC level context, and about a
+"underlying context", or "computation context", which is to denote the
+context for the underlying computation algorithm if there is one.
+
+=head2 Types
+
+B<EVP_MAC> is a type that holds the implementation of a MAC.
+
+B<EVP_MAC_CTX> is a context type that holds internal MAC information
+as well as a reference to a computation context, for those MACs that
+rely on an underlying computation algorithm.
+
+=head2 Context manipulation functions
+
+EVP_MAC_CTX_new() creates a new context for the MAC type C<mac>.
+EVP_MAC_CTX_new_id() creates a new context for the numerical MAC
+identity <nid>.
+The created context can then be used with most other functions
+described here.
+
+EVP_MAC_CTX_free() frees the contents of the context, including an
+underlying context if there is one, as well as the context itself.
+B<NULL> is a valid parameter, for which this function is a no-op.
+
+EVP_MAC_CTX_copy() makes a deep copy of the C<src> context to the
+C<dest> context.
+The C<dest> context I<must> have been created before calling this
+function.
+
+EVP_MAC_CTX_mac() returns the B<EVP_MAC> associated with the context
+C<ctx>.
+
+=head2 Computing functions
+
+EVP_MAC_init() sets up the underlying context with information given
+through diverse controls.
+This should be called before calling EVP_MAC_update() and
+EVP_MAC_final().
+
+EVP_MAC_reset() resets the computation for the given context.
+This may not be supported by the MAC implementation.
+
+EVP_MAC_update() adds C<datalen> bytes from C<data> to the MAC input.
+
+EVP_MAC_final() does the final computation and stores the result in
+the memory pointed at by C<out>, and sets its size in the B<size_t>
+the C<poutlen> points at.
+If C<out> is B<NULL>, then no computation is made.
+To figure out what the output length will be and allocate space for it
+dynamically, simply call with C<out> being B<NULL> and C<poutlen>
+pointing at a valid location, then allocate space and make a second
+call with C<out> pointing at the allocated space.
+
+EVP_MAC_ctrl() is used to manipulate or get information on aspects of
+the MAC which may vary depending on the MAC algorithm or its
+implementation.
+This includes the MAC key, and for MACs that use other algorithms to
+do their computation, this is also the way to tell it which one to
+use.
+This functions takes variable arguments, the exact expected arguments
+depend on C<cmd>.
+EVP_MAC_ctrl() can be called both before and after EVP_MAC_init(), but
+the effect will depend on what control is being use.
+See </CONTROLS> below for a description of standard controls.
+
+EVP_MAC_vctrl() is the variant of EVP_MAC_ctrl() that takes a
+C<va_list> argument instead of variadic arguments.
+
+EVP_MAC_ctrl_str() is an alternative to EVP_MAC_ctrl() to control the
+MAC implementation as E<lt> C<type>, C<value> E<gt> pairs.
+The MAC implementation documentation should specify what control type
+strings are accepted.
+
+EVP_MAC_str2ctrl() and EVP_MAC_hex2ctrl() are helper functions to
+control the MAC implementation with raw strings or with strings
+containing hexadecimal numbers.
+The latter are decoded into bitstrings that are sent on to
+EVP_MAC_ctrl().
+
+=head2 Information functions
+
+EVP_MAC_size() returns the MAC output size for the given context.
+
+EVP_MAC_nid() returns the numeric identity of the given MAC implementation.
+
+EVP_MAC_name() returns the name of the given MAC implementation.
+
+=head2 Object database functions
+
+EVP_get_macbyname() fetches a MAC implementation from the object
+database by name.
+
+EVP_get_macbynid() fetches a MAC implementation from the object
+database by numeric identity.
+
+EVP_get_macbyobj() fetches a MAC implementation from the object
+database by ASN.1 OBJECT (i.e. an encoded OID).
+
+=head1 CONTROLS
+
+The standard controls are:
+
+=over 4
+
+=item B<EVP_MAC_CTRL_SET_KEY>
+
+This control expects two arguments: C<unsigned char *key>, C<size_t keylen>
+
+These will set the MAC key from the given string of the given length.
+The string may be any bitstring, and can contain NUL bytes.
+
+For MACs that use an underlying computation algorithm, the algorithm
+I<must> be set first, see B<EVP_MAC_CTRL_SET_ENGINE>,
+B<EVP_MAC_CTRL_SET_MD> and B<EVP_MAC_CTRL_SET_CIPHER> below.
+
+=item B<EVP_MAC_CTRL_SET_FLAGS>
+
+This control expects one arguments: C<unsigned long flags>
+
+These will set the MAC flags to the given numbers.
+Some MACs do not support this option.
+
+=item B<EVP_MAC_CTRL_SET_ENGINE>
+
+=item B<EVP_MAC_CTRL_SET_MD>
+
+=item B<EVP_MAC_CTRL_SET_CIPHER>
+
+For MAC implementations that use an underlying computation algorithm,
+these controls set what the algorithm should be, and the engine that
+implements the algorithm if needed.
+
+B<EVP_MAC_CTRL_SET_ENGINE> takes one argument: C<ENGINE *>
+
+B<EVP_MAC_CTRL_SET_MD> takes one argument: C<EVP_MD *>
+
+B<EVP_MAC_CTRL_SET_CIPHER> takes one argument: C<EVP_CIPHER *>
+
+=item B<EVP_MAC_CTRL_SET_SIZE>
+
+For MAC implementations that support it, set the output size that
+EVP_MAC_final() should produce.
+The allowed sizes vary between MAC implementations.
+
+=back
+
+All these control should be used before the calls to any of
+EVP_MAC_init(), EVP_MAC_update() and EVP_MAC_final() for a full
+computation.
+Anything else may give undefined results.
+
+=head1 NOTES
+
+EVP_get_macbynid(), EVP_get_macbyobj() and EVP_MAC_name() are
+implemented as a macro.
+
+=head1 RETURN VALUES
+
+EVP_MAC_CTX_new() and EVP_MAC_CTX_new_id() return a pointer to a newly
+created EVP_MAC_CTX, or NULL if allocation failed.
+
+EVP_MAC_CTX_free() returns nothing at all.
+
+EVP_MAC_CTX_copy(), EVP_MAC_reset(), EVP_MAC_init(), EVP_MAC_update(),
+and EVP_MAC_final() return 1 on success, 0 on error.
+
+EVP_MAC_ctrl(), EVP_MAC_ctrl_str(), EVP_MAC_str2ctrl() and
+EVP_MAC_hex2ctrl() return 1 on success and 0 or a negative value on
+error.
+In particular, the value -2 indicates that the given control type
+isn't supported by the MAC implementation.
+
+EVP_MAC_size() returns the expected output size, or 0 if it isn't
+set.
+If it isn't set, a call to EVP_MAC_init() should get it set.
+
+EVP_MAC_nid() returns the numeric identity for the given C<mac>.
+
+EVP_MAC_name() returns the name for the given C<mac>, if it has been
+added to the object database.
+
+EVP_add_mac() returns 1 if the given C<mac> was successfully added to
+the object database, otherwise 0.
+
+EVP_get_macbyname(), EVP_get_macbynid() and EVP_get_macbyobj() return
+the request MAC implementation, if it exists in the object database,
+otherwise B<NULL>.
+
+=head1 EXAMPLE
+
+  #include <stdlib.h>
+  #include <stdio.h>
+  #include <string.h>
+  #include <stdarg.h>
+  #include <unistd.h>
+
+  #include <openssl/evp.h>
+  #include <openssl/err.h>
+
+  int ctrl_ign_unsupported(EVP_MAC_CTX *ctx, int cmd, ...)
+  {
+      va_list args;
+      int rv;
+
+      va_start(args, cmd);
+      rv = EVP_MAC_vctrl(ctx, cmd, args);
+      va_end(args);
+
+      if (rv == -2)
+          rv = 1;       /* Ignore unsupported, pretend it worked fine */
+
+      return rv;
+  }
+
+  int main() {
+      const EVP_MAC *mac =
+          EVP_get_macbyname(getenv("MY_MAC"));
+      const EVP_CIPHER *cipher =
+          EVP_get_cipherbyname(getenv("MY_MAC_CIPHER"));
+      const EVP_MD *digest =
+          EVP_get_digestbyname(getenv("MY_MAC_DIGEST"));
+      const char *key = getenv("MY_KEY");
+      EVP_MAC_CTX *ctx = NULL;
+
+      unsigned char buf[4096];
+      ssize_t read_l;
+      size_t final_l;
+
+      size_t i;
+
+      if (mac == NULL
+          || key == NULL
+          || (ctx = EVP_MAC_CTX_new(mac)) == NULL
+          || (cipher != NULL
+              && !ctrl_ign_unsupported(ctx, EVP_MAC_CTRL_SET_CIPHER, cipher))
+          || (digest != NULL
+              && !ctrl_ign_unsupported(ctx, EVP_MAC_CTRL_SET_MD, digest))
+          || EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_KEY, key, strlen(key)) <= 0)
+          goto err;
+
+      if (!EVP_MAC_init(ctx))
+          goto err;
+
+      while ( (read_l = read(STDIN_FILENO, buf, sizeof(buf))) < 0) {
+          if (!EVP_MAC_update(ctx, buf, read_l))
+              goto err;
+      }
+
+      if (!EVP_MAC_final(ctx, buf, &final_l))
+          goto err;
+
+      printf("Result: ");
+      for (i = 0; i < final_l; i++)
+          printf("%02X", buf[i]);
+      printf("\n");
+
+      EVP_MAC_CTX_free(ctx);
+      exit(0);
+
+   err:
+      EVP_MAC_CTX_free(ctx);
+      fprintf(stderr, "Something went wrong\n");
+      ERR_print_errors_fp(stderr);
+      exit (1);
+  }
+
+A run of this program, called with correct environment variables, can
+look like this:
+
+  $ MY_MAC=cmac MY_KEY=secret0123456789 MY_MAC_CIPHER=aes-128-cbc \
+    LD_LIBRARY_PATH=. ./foo < foo.c
+  Result: ECCAAFF041B22A2299EB90A1B53B6D45
+
+(in this example, that program was stored in F<foo.c> and compiled to
+F<./foo>)
+
+=head1 SEE ALSO
+
+=begin comment
+
+Add links to existing implementations in this form:
+
+L<EVP_MAC_CMAC(7)>
+
+Make sure the documentation exists in doc/man7/
+
+=end comment
+
+=head1 COPYRIGHT
+
+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
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/include/openssl/crypto.h b/include/openssl/crypto.h
index 7e50b1b..889b342 100644
--- a/include/openssl/crypto.h
+++ b/include/openssl/crypto.h
@@ -377,7 +377,14 @@ int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len);
 /* OPENSSL_INIT_ZLIB                         0x00010000L */
 # define OPENSSL_INIT_ATFORK                 0x00020000L
 /* OPENSSL_INIT_BASE_ONLY                    0x00040000L */
-/* OPENSSL_INIT flag range 0xfff00000 reserved for OPENSSL_init_ssl() */
+/* FREE: 0x00080000L */
+/* OPENSSL_INIT flag range 0x03f00000 reserved for OPENSSL_init_ssl() */
+# define OPENSSL_INIT_NO_ADD_ALL_MACS        0x04000000L
+# define OPENSSL_INIT_ADD_ALL_MACS           0x08000000L
+/* FREE: 0x10000000L */
+/* FREE: 0x20000000L */
+/* FREE: 0x40000000L */
+/* FREE: 0x80000000L */
 /* Max OPENSSL_INIT flag value is 0x80000000 */
 
 /* openssl and dasync not counted as builtin */
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index 8c80519..4b4c956 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -10,6 +10,8 @@
 #ifndef HEADER_ENVELOPE_H
 # define HEADER_ENVELOPE_H
 
+# include <stdarg.h>
+
 # include <openssl/opensslconf.h>
 # include <openssl/ossl_typ.h>
 # include <openssl/symhacks.h>
@@ -983,6 +985,43 @@ void EVP_MD_do_all_sorted(void (*fn)
                            (const EVP_MD *ciph, const char *from,
                             const char *to, void *x), void *arg);
 
+/* MAC stuff */
+
+EVP_MAC_CTX *EVP_MAC_CTX_new(const EVP_MAC *mac);
+EVP_MAC_CTX *EVP_MAC_CTX_new_id(int nid);
+void EVP_MAC_CTX_free(EVP_MAC_CTX *ctx);
+int EVP_MAC_CTX_copy(EVP_MAC_CTX *dest, EVP_MAC_CTX *src);
+const EVP_MAC *EVP_MAC_CTX_mac(EVP_MAC_CTX *ctx);
+size_t EVP_MAC_size(EVP_MAC_CTX *ctx);
+int EVP_MAC_init(EVP_MAC_CTX *ctx);
+int EVP_MAC_update(EVP_MAC_CTX *ctx, const unsigned char *data, size_t datalen);
+int EVP_MAC_final(EVP_MAC_CTX *ctx, unsigned char *out, size_t *poutlen);
+int EVP_MAC_ctrl(EVP_MAC_CTX *ctx, int cmd, ...);
+int EVP_MAC_vctrl(EVP_MAC_CTX *ctx, int cmd, va_list args);
+int EVP_MAC_ctrl_str(EVP_MAC_CTX *ctx, const char *type, const char *value);
+int EVP_MAC_str2ctrl(EVP_MAC_CTX *ctx, int cmd, const char *value);
+int EVP_MAC_hex2ctrl(EVP_MAC_CTX *ctx, int cmd, const char *value);
+int EVP_MAC_nid(const EVP_MAC *mac);
+
+# define EVP_get_macbynid(a)    EVP_get_macbyname(OBJ_nid2sn(a))
+# define EVP_get_macbyobj(a)    EVP_get_macbynid(OBJ_obj2nid(a))
+# define EVP_MAC_name(o)        OBJ_nid2sn(EVP_MAC_nid(o))
+const EVP_MAC *EVP_get_macbyname(const char *name);
+void EVP_MAC_do_all(void (*fn)
+                    (const EVP_MAC *ciph, const char *from, const char *to,
+                     void *x), void *arg);
+void EVP_MAC_do_all_sorted(void (*fn)
+                           (const EVP_MAC *ciph, const char *from,
+                            const char *to, void *x), void *arg);
+
+# define EVP_MAC_CTRL_SET_KEY           0x01 /* unsigned char *, size_t */
+# define EVP_MAC_CTRL_SET_FLAGS         0x02 /* unsigned long */
+# define EVP_MAC_CTRL_SET_ENGINE        0x03 /* ENGINE * */
+# define EVP_MAC_CTRL_SET_MD            0x04 /* EVP_MD * */
+# define EVP_MAC_CTRL_SET_CIPHER        0x04 /* EVP_CIPHER * */
+# define EVP_MAC_CTRL_SET_SIZE          0x05 /* size_t */
+
+/* PKEY stuff */
 int EVP_PKEY_decrypt_old(unsigned char *dec_key,
                          const unsigned char *enc_key, int enc_key_len,
                          EVP_PKEY *private_key);
@@ -1631,6 +1670,14 @@ void EVP_PKEY_meth_get_digest_custom(EVP_PKEY_METHOD *pmeth,
                                                              EVP_MD_CTX *mctx));
 void EVP_add_alg_module(void);
 
+/*
+ * Convenient helper functions to transfer string based controls.
+ * The callback gets called with the parsed value.
+ */
+int EVP_str2ctrl(int (*cb)(void *ctx, int cmd, void *buf, size_t buflen),
+                 void *ctx, int cmd, const char *value);
+int EVP_hex2ctrl(int (*cb)(void *ctx, int cmd, void *buf, size_t buflen),
+                 void *ctx, int cmd, const char *hex);
 
 # ifdef  __cplusplus
 }
diff --git a/include/openssl/evperr.h b/include/openssl/evperr.h
index d2d44c2..a17e159 100644
--- a/include/openssl/evperr.h
+++ b/include/openssl/evperr.h
@@ -50,6 +50,11 @@ int ERR_load_EVP_strings(void);
 # define EVP_F_EVP_DIGESTINIT_EX                          128
 # define EVP_F_EVP_ENCRYPTFINAL_EX                        127
 # define EVP_F_EVP_ENCRYPTUPDATE                          167
+# define EVP_F_EVP_MAC_CTRL                               209
+# define EVP_F_EVP_MAC_CTRL_STR                           210
+# define EVP_F_EVP_MAC_CTX_COPY                           211
+# define EVP_F_EVP_MAC_CTX_NEW                            213
+# define EVP_F_EVP_MAC_INIT                               212
 # define EVP_F_EVP_MD_CTX_COPY_EX                         110
 # define EVP_F_EVP_MD_SIZE                                162
 # define EVP_F_EVP_OPENINIT                               102
@@ -112,6 +117,7 @@ int ERR_load_EVP_strings(void);
 # define EVP_F_PKCS5_V2_PBE_KEYIVGEN                      118
 # define EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN                   164
 # define EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN                   180
+# define EVP_F_PKEY_MAC_INIT                              214
 # define EVP_F_PKEY_SET_TYPE                              158
 # define EVP_F_RC2_MAGIC_TO_METH                          109
 # define EVP_F_RC5_CTRL                                   125
diff --git a/include/openssl/objects.h b/include/openssl/objects.h
index 5e8b576..8e1eb0f 100644
--- a/include/openssl/objects.h
+++ b/include/openssl/objects.h
@@ -20,7 +20,8 @@
 # define OBJ_NAME_TYPE_CIPHER_METH       0x02
 # define OBJ_NAME_TYPE_PKEY_METH         0x03
 # define OBJ_NAME_TYPE_COMP_METH         0x04
-# define OBJ_NAME_TYPE_NUM               0x05
+# define OBJ_NAME_TYPE_MAC_METH          0x05
+# define OBJ_NAME_TYPE_NUM               0x06
 
 # define OBJ_NAME_ALIAS                  0x8000
 
diff --git a/include/openssl/ossl_typ.h b/include/openssl/ossl_typ.h
index 7993ca2..9ea26de 100644
--- a/include/openssl/ossl_typ.h
+++ b/include/openssl/ossl_typ.h
@@ -90,6 +90,8 @@ typedef struct evp_cipher_st EVP_CIPHER;
 typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX;
 typedef struct evp_md_st EVP_MD;
 typedef struct evp_md_ctx_st EVP_MD_CTX;
+typedef struct evp_mac_st EVP_MAC;
+typedef struct evp_mac_ctx_st EVP_MAC_CTX;
 typedef struct evp_pkey_st EVP_PKEY;
 
 typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD;
diff --git a/ssl/ssl_init.c b/ssl/ssl_init.c
index c0ccb93..31dce9c 100644
--- a/ssl/ssl_init.c
+++ b/ssl/ssl_init.c
@@ -199,7 +199,8 @@ int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS * settings)
                              | OPENSSL_INIT_LOAD_CONFIG
 #endif
                              | OPENSSL_INIT_ADD_ALL_CIPHERS
-                             | OPENSSL_INIT_ADD_ALL_DIGESTS,
+                             | OPENSSL_INIT_ADD_ALL_DIGESTS
+                             | OPENSSL_INIT_ADD_ALL_MACS,
                              settings))
         return 0;
 
diff --git a/test/evp_test.c b/test/evp_test.c
index 2ac69e1..be18afb 100644
--- a/test/evp_test.c
+++ b/test/evp_test.c
@@ -832,8 +832,9 @@ static const EVP_TEST_METHOD cipher_test_method = {
 **/
 
 typedef struct mac_data_st {
-    /* MAC type */
-    int type;
+    /* MAC type in one form or another */
+    const EVP_MAC *mac;          /* for mac_test_run_mac */
+    int type;                    /* for mac_test_run_pkey */
     /* Algorithm string for this MAC */
     char *alg;
     /* MAC key */
@@ -851,37 +852,62 @@ typedef struct mac_data_st {
 
 static int mac_test_init(EVP_TEST *t, const char *alg)
 {
-    int type;
+    const EVP_MAC *mac = NULL;
+    int type = NID_undef;
     MAC_DATA *mdat;
 
-    if (strcmp(alg, "HMAC") == 0) {
-        type = EVP_PKEY_HMAC;
-    } else if (strcmp(alg, "CMAC") == 0) {
+    if ((mac = EVP_get_macbyname(alg)) == NULL) {
+        /*
+         * Since we didn't find an EVP_MAC, we check for known EVP_PKEY methods
+         * For debugging purposes, we allow 'NNNN by EVP_PKEY' to force running
+         * the EVP_PKEY method.
+         */
+        size_t sz = strlen(alg);
+        static const char epilogue[] = " by EVP_PKEY";
+
+        if (strcmp(alg + sz - (sizeof(epilogue) - 1), epilogue) == 0)
+            sz -= sizeof(epilogue) - 1;
+
+        if (strncmp(alg, "HMAC", sz) == 0) {
+            type = EVP_PKEY_HMAC;
+        } else if (strncmp(alg, "CMAC", sz) == 0) {
 #ifndef OPENSSL_NO_CMAC
-        type = EVP_PKEY_CMAC;
+            type = EVP_PKEY_CMAC;
 #else
-        t->skip = 1;
-        return 1;
+            t->skip = 1;
+            return 1;
 #endif
-    } else if (strcmp(alg, "Poly1305") == 0) {
+        } else if (strncmp(alg, "Poly1305", sz) == 0) {
 #ifndef OPENSSL_NO_POLY1305
-        type = EVP_PKEY_POLY1305;
+            type = EVP_PKEY_POLY1305;
 #else
-        t->skip = 1;
-        return 1;
+            t->skip = 1;
+            return 1;
 #endif
-    } else if (strcmp(alg, "SipHash") == 0) {
+        } else if (strncmp(alg, "SipHash", sz) == 0) {
 #ifndef OPENSSL_NO_SIPHASH
-        type = EVP_PKEY_SIPHASH;
+            type = EVP_PKEY_SIPHASH;
 #else
-        t->skip = 1;
-        return 1;
+            t->skip = 1;
+            return 1;
 #endif
-    } else
-        return 0;
+        } else {
+            /*
+             * Not a known EVP_PKEY method either.  If it's a known OID, then
+             * assume it's been disabled.
+             */
+            if (OBJ_sn2nid(alg) != NID_undef || OBJ_ln2nid(alg) != NID_undef) {
+                t->skip = 1;
+                return 1;
+            }
+
+            return 0;
+        }
+    }
 
     mdat = OPENSSL_zalloc(sizeof(*mdat));
     mdat->type = type;
+    mdat->mac = mac;
     mdat->controls = sk_OPENSSL_STRING_new_null();
     t->data = mdat;
     return 1;
@@ -927,7 +953,7 @@ static int mac_test_parse(EVP_TEST *t,
     return 0;
 }
 
-static int mac_test_run(EVP_TEST *t)
+static int mac_test_run_pkey(EVP_TEST *t)
 {
     MAC_DATA *expected = t->data;
     EVP_MD_CTX *mctx = NULL;
@@ -938,6 +964,12 @@ static int mac_test_run(EVP_TEST *t)
     size_t got_len;
     int i;
 
+    if (expected->alg == NULL)
+        TEST_info("Trying the EVP_PKEY %s test", OBJ_nid2sn(expected->type));
+    else
+        TEST_info("Trying the EVP_PKEY %s test with %s",
+                  OBJ_nid2sn(expected->type), expected->alg);
+
 #ifdef OPENSSL_NO_DES
     if (expected->alg != NULL && strstr(expected->alg, "DES") != NULL) {
         /* Skip DES */
@@ -1005,6 +1037,126 @@ static int mac_test_run(EVP_TEST *t)
     return 1;
 }
 
+static int mac_test_run_mac(EVP_TEST *t)
+{
+    MAC_DATA *expected = t->data;
+    EVP_MAC_CTX *ctx = NULL;
+    const void *algo = NULL;
+    int algo_ctrl = 0;
+    unsigned char *got = NULL;
+    size_t got_len;
+    int rv, i;
+
+    if (expected->alg == NULL)
+        TEST_info("Trying the EVP_MAC %s test", EVP_MAC_name(expected->mac));
+    else
+        TEST_info("Trying the EVP_MAC %s test with %s",
+                  EVP_MAC_name(expected->mac), expected->alg);
+
+#ifdef OPENSSL_NO_DES
+    if (expected->alg != NULL && strstr(expected->alg, "DES") != NULL) {
+        /* Skip DES */
+        t->err = NULL;
+        goto err;
+    }
+#endif
+
+    if ((ctx = EVP_MAC_CTX_new(expected->mac)) == NULL) {
+        t->err = "MAC_CREATE_ERROR";
+        goto err;
+    }
+
+    if (expected->alg != NULL
+        && ((algo_ctrl = EVP_MAC_CTRL_SET_CIPHER,
+             algo = EVP_get_cipherbyname(expected->alg)) == NULL
+            && (algo_ctrl = EVP_MAC_CTRL_SET_MD,
+                algo = EVP_get_digestbyname(expected->alg)) == NULL)) {
+        t->err = "MAC_BAD_ALGORITHM";
+        goto err;
+    }
+
+
+    if (algo_ctrl != 0) {
+        rv = EVP_MAC_ctrl(ctx, algo_ctrl, algo);
+        if (rv == -2) {
+            t->err = "MAC_CTRL_INVALID";
+            goto err;
+        } else if (rv <= 0) {
+            t->err = "MAC_CTRL_ERROR";
+            goto err;
+        }
+    }
+
+    rv = EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_KEY,
+                      expected->key, expected->key_len);
+    if (rv == -2) {
+        t->err = "MAC_CTRL_INVALID";
+        goto err;
+    } else if (rv <= 0) {
+        t->err = "MAC_CTRL_ERROR";
+        goto err;
+    }
+
+    if (!EVP_MAC_init(ctx)) {
+        t->err = "MAC_INIT_ERROR";
+        goto err;
+    }
+    for (i = 0; i < sk_OPENSSL_STRING_num(expected->controls); i++) {
+        char *p, *tmpval;
+        char *value = sk_OPENSSL_STRING_value(expected->controls, i);
+
+        if (!TEST_ptr(tmpval = OPENSSL_strdup(value))) {
+            t->err = "MAC_CTRL_ERROR";
+            goto err;
+        }
+        p = strchr(tmpval, ':');
+        if (p != NULL)
+            *p++ = '\0';
+        rv = EVP_MAC_ctrl_str(ctx, tmpval, p);
+        OPENSSL_free(tmpval);
+        if (rv == -2) {
+            t->err = "MAC_CTRL_INVALID";
+            goto err;
+        } else if (rv <= 0) {
+            t->err = "MAC_CTRL_ERROR";
+            goto err;
+        }
+    }
+    if (!EVP_MAC_update(ctx, expected->input, expected->input_len)) {
+        t->err = "MAC_UPDATE_ERROR";
+        goto err;
+    }
+    if (!EVP_MAC_final(ctx, NULL, &got_len)) {
+        t->err = "MAC_FINAL_LENGTH_ERROR";
+        goto err;
+    }
+    if (!TEST_ptr(got = OPENSSL_malloc(got_len))) {
+        t->err = "TEST_FAILURE";
+        goto err;
+    }
+    if (!EVP_MAC_final(ctx, got, &got_len)
+        || !memory_err_compare(t, "TEST_MAC_ERR",
+                               expected->output, expected->output_len,
+                               got, got_len)) {
+        t->err = "TEST_MAC_ERR";
+        goto err;
+    }
+    t->err = NULL;
+ err:
+    EVP_MAC_CTX_free(ctx);
+    OPENSSL_free(got);
+    return 1;
+}
+
+static int mac_test_run(EVP_TEST *t)
+{
+    MAC_DATA *expected = t->data;
+
+    if (expected->mac != NULL)
+        return mac_test_run_mac(t);
+    return mac_test_run_pkey(t);
+}
+
 static const EVP_TEST_METHOD mac_test_method = {
     "MAC",
     mac_test_init,
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 31f8781..f159a40 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4577,3 +4577,23 @@ OCSP_resp_get0_respdata                 4530	1_1_0j	EXIST::FUNCTION:OCSP
 EVP_MD_CTX_set_pkey_ctx                 4531	1_1_1	EXIST::FUNCTION:
 EVP_PKEY_meth_set_digest_custom         4532	1_1_1	EXIST::FUNCTION:
 EVP_PKEY_meth_get_digest_custom         4533	1_1_1	EXIST::FUNCTION:
+EVP_MAC_CTX_new                         4534	1_1_2	EXIST::FUNCTION:
+EVP_MAC_CTX_new_id                      4535	1_1_2	EXIST::FUNCTION:
+EVP_MAC_CTX_free                        4536	1_1_2	EXIST::FUNCTION:
+EVP_MAC_CTX_copy                        4537	1_1_2	EXIST::FUNCTION:
+EVP_MAC_CTX_mac                         4538	1_1_2	EXIST::FUNCTION:
+EVP_MAC_size                            4539	1_1_2	EXIST::FUNCTION:
+EVP_MAC_init                            4540	1_1_2	EXIST::FUNCTION:
+EVP_MAC_update                          4541	1_1_2	EXIST::FUNCTION:
+EVP_MAC_final                           4542	1_1_2	EXIST::FUNCTION:
+EVP_MAC_ctrl                            4543	1_1_2	EXIST::FUNCTION:
+EVP_MAC_vctrl                           4544	1_1_2	EXIST::FUNCTION:
+EVP_MAC_ctrl_str                        4545	1_1_2	EXIST::FUNCTION:
+EVP_MAC_str2ctrl                        4546	1_1_2	EXIST::FUNCTION:
+EVP_MAC_hex2ctrl                        4547	1_1_2	EXIST::FUNCTION:
+EVP_MAC_nid                             4548	1_1_2	EXIST::FUNCTION:
+EVP_get_macbyname                       4549	1_1_2	EXIST::FUNCTION:
+EVP_MAC_do_all                          4550	1_1_2	EXIST::FUNCTION:
+EVP_MAC_do_all_sorted                   4551	1_1_2	EXIST::FUNCTION:
+EVP_str2ctrl                            4552	1_1_2	EXIST::FUNCTION:
+EVP_hex2ctrl                            4553	1_1_2	EXIST::FUNCTION:
diff --git a/util/private.num b/util/private.num
index 2bfe987..27d352a 100644
--- a/util/private.num
+++ b/util/private.num
@@ -22,6 +22,8 @@ CRYPTO_EX_dup                           datatype
 CRYPTO_EX_free                          datatype
 CRYPTO_EX_new                           datatype
 DTLS_timer_cb                           datatype
+EVP_MAC                                 datatype
+EVP_MAC_CTX                             datatype
 EVP_PKEY_gen_cb                         datatype
 EVP_PKEY_METHOD                         datatype
 EVP_PKEY_ASN1_METHOD                    datatype
@@ -185,6 +187,7 @@ ERR_free_strings                        define deprecated 1.1.0
 ERR_load_crypto_strings                 define deprecated 1.1.0
 EVP_DigestSignUpdate                    define
 EVP_DigestVerifyUpdate                  define
+EVP_MAC_name                            define
 EVP_MD_CTX_block_size                   define
 EVP_MD_CTX_size                         define
 EVP_MD_CTX_type                         define
@@ -271,6 +274,8 @@ EVP_cast5_cfb                           define
 EVP_cleanup                             define deprecated 1.1.0
 EVP_get_digestbynid                     define
 EVP_get_digestbyobj                     define
+EVP_get_macbynid                        define
+EVP_get_macbyobj                        define
 EVP_idea_cfb                            define
 EVP_rc2_cfb                             define
 EVP_rc5_32_12_16_cfb                    define


More information about the openssl-commits mailing list