Move CMAC to providers
authorRichard Levitte <levitte@openssl.org>
Sat, 1 Jun 2019 09:18:15 +0000 (11:18 +0200)
committerRichard Levitte <levitte@openssl.org>
Thu, 15 Aug 2019 20:12:25 +0000 (22:12 +0200)
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/8877)

crypto/cmac/build.info
crypto/cmac/cm_meth.c [deleted file]
providers/common/build.info
providers/common/include/internal/provider_algs.h
providers/common/macs/build.info [new file with mode: 0644]
providers/common/macs/cmac_prov.c [new file with mode: 0644]
providers/default/defltprov.c
providers/fips/fipsprov.c

index c460598e20c6e495136aa43f3bba55bc6ab3094e..f6c8bfabbcc11173333dc0dc550376d0ceec5425 100644 (file)
@@ -1,2 +1,6 @@
 LIBS=../../libcrypto
-SOURCE[../../libcrypto]=cmac.c cm_ameth.c cm_meth.c
+
+$COMMON=cmac.c
+
+SOURCE[../../libcrypto]=$COMMON cm_ameth.c
+SOURCE[../../providers/fips]=$COMMON
diff --git a/crypto/cmac/cm_meth.c b/crypto/cmac/cm_meth.c
deleted file mode 100644 (file)
index 07acf05..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (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 <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-#include <openssl/evp.h>
-#include <openssl/cmac.h>
-#include "internal/evp_int.h"
-
-/* local CMAC pkey structure */
-
-/* typedef EVP_MAC_IMPL */
-struct evp_mac_impl_st {
-    /* tmpcipher and tmpengine are set to NULL after a CMAC_Init call */
-    const EVP_CIPHER *tmpcipher; /* cached CMAC cipher */
-    const ENGINE *tmpengine;     /* cached CMAC cipher engine */
-    CMAC_CTX *ctx;
-};
-
-static EVP_MAC_IMPL *cmac_new(void)
-{
-    EVP_MAC_IMPL *cctx;
-
-    if ((cctx = OPENSSL_zalloc(sizeof(*cctx))) == NULL
-        || (cctx->ctx = CMAC_CTX_new()) == NULL) {
-        OPENSSL_free(cctx);
-        cctx = NULL;
-    }
-
-    return cctx;
-}
-
-static void cmac_free(EVP_MAC_IMPL *cctx)
-{
-    if (cctx != NULL) {
-        CMAC_CTX_free(cctx->ctx);
-        OPENSSL_free(cctx);
-    }
-}
-
-static EVP_MAC_IMPL *cmac_dup(const EVP_MAC_IMPL *csrc)
-{
-    EVP_MAC_IMPL *cdst = cmac_new();
-
-    if (cdst == NULL)
-        return NULL;
-
-    if (!CMAC_CTX_copy(cdst->ctx, csrc->ctx)) {
-        cmac_free(cdst);
-        return NULL;
-    }
-
-    cdst->tmpengine = csrc->tmpengine;
-    cdst->tmpcipher = csrc->tmpcipher;
-
-    return cdst;
-}
-
-static size_t cmac_size(EVP_MAC_IMPL *cctx)
-{
-    return EVP_CIPHER_CTX_block_size(CMAC_CTX_get0_cipher_ctx(cctx->ctx));
-}
-
-static int cmac_init(EVP_MAC_IMPL *cctx)
-{
-    int rv = CMAC_Init(cctx->ctx, NULL, 0, cctx->tmpcipher,
-                       (ENGINE *)cctx->tmpengine);
-    cctx->tmpcipher = NULL;
-    cctx->tmpengine = NULL;
-
-    return rv;
-}
-
-static int cmac_update(EVP_MAC_IMPL *cctx, const unsigned char *data,
-                       size_t datalen)
-{
-    return CMAC_Update(cctx->ctx, data, datalen);
-}
-
-static int cmac_final(EVP_MAC_IMPL *cctx, unsigned char *out)
-{
-    size_t hlen;
-
-    return CMAC_Final(cctx->ctx, out, &hlen);
-}
-
-static int cmac_ctrl(EVP_MAC_IMPL *cctx, int cmd, va_list args)
-{
-    switch (cmd) {
-    case EVP_MAC_CTRL_SET_KEY:
-        {
-            const unsigned char *key = va_arg(args, const unsigned char *);
-            size_t keylen = va_arg(args, size_t);
-            int rv = CMAC_Init(cctx->ctx, key, keylen, cctx->tmpcipher,
-                               (ENGINE *)cctx->tmpengine);
-
-            cctx->tmpcipher = NULL;
-            cctx->tmpengine = NULL;
-
-            return rv;
-        }
-        break;
-    case EVP_MAC_CTRL_SET_CIPHER:
-        cctx->tmpcipher = va_arg(args, const EVP_CIPHER *);
-        break;
-    case EVP_MAC_CTRL_SET_ENGINE:
-        cctx->tmpengine = va_arg(args, const ENGINE *);
-        break;
-    default:
-        return -2;
-    }
-    return 1;
-}
-
-static int cmac_ctrl_int(EVP_MAC_IMPL *hctx, int cmd, ...)
-{
-    int rv;
-    va_list args;
-
-    va_start(args, cmd);
-    rv = cmac_ctrl(hctx, cmd, args);
-    va_end(args);
-
-    return rv;
-}
-
-static int cmac_ctrl_str_cb(void *hctx, int cmd, void *buf, size_t buflen)
-{
-    return cmac_ctrl_int(hctx, cmd, buf, buflen);
-}
-
-static int cmac_ctrl_str(EVP_MAC_IMPL *cctx, const char *type,
-                         const char *value)
-{
-    if (!value)
-        return 0;
-    if (strcmp(type, "cipher") == 0) {
-        const EVP_CIPHER *c = EVP_get_cipherbyname(value);
-
-        if (c == NULL)
-            return 0;
-        return cmac_ctrl_int(cctx, EVP_MAC_CTRL_SET_CIPHER, c);
-    }
-    if (strcmp(type, "key") == 0)
-        return EVP_str2ctrl(cmac_ctrl_str_cb, cctx, EVP_MAC_CTRL_SET_KEY,
-                            value);
-    if (strcmp(type, "hexkey") == 0)
-        return EVP_hex2ctrl(cmac_ctrl_str_cb, cctx, EVP_MAC_CTRL_SET_KEY,
-                            value);
-    return -2;
-}
-
-const EVP_MAC cmac_meth = {
-    EVP_MAC_CMAC,
-    cmac_new,
-    cmac_dup,
-    cmac_free,
-    cmac_size,
-    cmac_init,
-    cmac_update,
-    cmac_final,
-    cmac_ctrl,
-    cmac_ctrl_str
-};
index bc106d0b0fa66c65de503a194cbe53e09e8ce834..4c977d3f256c8c2753ce94faa56c43b420103bce 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS=digests ciphers exchange keymgmt
+SUBDIRS=digests ciphers macs exchange keymgmt
 
 SOURCE[../../libcrypto]=\
         provider_err.c provlib.c
index c35230758ef44a5c8cc53bad82a778b8bce6540b..c59fc186909f8a4768e3f6c8189a5866c32a325d 100644 (file)
@@ -69,6 +69,7 @@ extern const OSSL_DISPATCH aria128gcm_functions[];
 /* MACs */
 extern const OSSL_DISPATCH blake2bmac_functions[];
 extern const OSSL_DISPATCH blake2smac_functions[];
+extern const OSSL_DISPATCH cmac_functions[];
 
 /* Key management */
 extern const OSSL_DISPATCH dh_keymgmt_functions[];
diff --git a/providers/common/macs/build.info b/providers/common/macs/build.info
new file mode 100644 (file)
index 0000000..4871e4b
--- /dev/null
@@ -0,0 +1,11 @@
+$COMMON=cmac_prov.c
+
+LIBS=../../../libcrypto
+SOURCE[../../../libcrypto]=$COMMON
+INCLUDE[../../../libcrypto]=. ../../../crypto
+
+IF[{- !$disabled{fips} -}]
+  MODULES=../../fips
+  SOURCE[../../fips]=$COMMON
+  INCLUDE[../../fips]=. ../../../crypto
+ENDIF
diff --git a/providers/common/macs/cmac_prov.c b/providers/common/macs/cmac_prov.c
new file mode 100644 (file)
index 0000000..ca42a67
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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/opensslconf.h>
+#ifndef OPENSSL_NO_CMAC
+
+# include <openssl/core_numbers.h>
+# include <openssl/core_names.h>
+# include <openssl/params.h>
+# include <openssl/engine.h>
+# include <openssl/evp.h>
+# include <openssl/cmac.h>
+
+# include "internal/provider_algs.h"
+# include "internal/provider_ctx.h"
+
+/*
+ * Forward declaration of everything implemented here.  This is not strictly
+ * necessary for the compiler, but provides an assurance that the signatures
+ * of the functions in the dispatch table are correct.
+ */
+static OSSL_OP_mac_newctx_fn cmac_new;
+static OSSL_OP_mac_dupctx_fn cmac_dup;
+static OSSL_OP_mac_freectx_fn cmac_free;
+static OSSL_OP_mac_gettable_ctx_params_fn cmac_gettable_ctx_params;
+static OSSL_OP_mac_ctx_get_params_fn cmac_ctx_get_params;
+static OSSL_OP_mac_settable_ctx_params_fn cmac_settable_ctx_params;
+static OSSL_OP_mac_ctx_set_params_fn cmac_ctx_set_params;
+static OSSL_OP_mac_init_fn cmac_init;
+static OSSL_OP_mac_update_fn cmac_update;
+static OSSL_OP_mac_final_fn cmac_final;
+
+/* local CMAC data */
+
+struct cmac_data_st {
+    void *provctx;
+    CMAC_CTX *ctx;
+
+    /*
+     * References to the underlying cipher implementation.  tmpcipher
+     * caches the cipher, always.  alloc_cipher only holds a reference
+     * to an explicitly fetched cipher.
+     * tmpcipher is cleared after a CMAC_Init call.
+     */
+    const EVP_CIPHER *tmpcipher; /* cached CMAC cipher */
+    EVP_CIPHER *alloc_cipher;    /* fetched CMAC cipher */
+
+    /*
+     * Conditions for legacy EVP_CIPHER uses.
+     * tmpengine is cleared after a CMAC_Init call.
+     */
+    ENGINE *tmpengine;           /* CMAC cipher engine (legacy) */
+};
+
+static void *cmac_new(void *provctx)
+{
+    struct cmac_data_st *macctx;
+
+    if ((macctx = OPENSSL_zalloc(sizeof(*macctx))) == NULL
+        || (macctx->ctx = CMAC_CTX_new()) == NULL) {
+        OPENSSL_free(macctx);
+        macctx = NULL;
+    }
+    macctx->provctx = provctx;
+
+    return macctx;
+}
+
+static void cmac_free(void *vmacctx)
+{
+    struct cmac_data_st *macctx = vmacctx;
+
+    if (macctx != NULL) {
+        CMAC_CTX_free(macctx->ctx);
+        EVP_CIPHER_meth_free(macctx->alloc_cipher);
+        OPENSSL_free(macctx);
+    }
+}
+
+static void *cmac_dup(void *vsrc)
+{
+    struct cmac_data_st *src = vsrc;
+    struct cmac_data_st *dst = cmac_new(src->provctx);
+
+    if (!CMAC_CTX_copy(dst->ctx, src->ctx)) {
+        cmac_free(dst);
+        return NULL;
+    }
+
+    if (src->alloc_cipher != NULL && !EVP_CIPHER_up_ref(src->alloc_cipher)) {
+        cmac_free(dst);
+        return NULL;
+    }
+
+    dst->tmpengine = src->tmpengine;
+    dst->tmpcipher = src->tmpcipher;
+    dst->alloc_cipher = src->alloc_cipher;
+    return dst;
+}
+
+static size_t cmac_size(void *vmacctx)
+{
+    struct cmac_data_st *macctx = vmacctx;
+
+    return EVP_CIPHER_CTX_block_size(CMAC_CTX_get0_cipher_ctx(macctx->ctx));
+}
+
+static int cmac_init(void *vmacctx)
+{
+    struct cmac_data_st *macctx = vmacctx;
+    int rv = CMAC_Init(macctx->ctx, NULL, 0, macctx->tmpcipher,
+                       (ENGINE *)macctx->tmpengine);
+
+    macctx->tmpcipher = NULL;
+    macctx->tmpengine = NULL;
+
+    return rv;
+}
+
+static int cmac_update(void *vmacctx, const unsigned char *data,
+                       size_t datalen)
+{
+    struct cmac_data_st *macctx = vmacctx;
+
+    return CMAC_Update(macctx->ctx, data, datalen);
+}
+
+static int cmac_final(void *vmacctx, unsigned char *out, size_t *outl,
+                      size_t outsize)
+{
+    struct cmac_data_st *macctx = vmacctx;
+
+    return CMAC_Final(macctx->ctx, out, outl);
+}
+
+static const OSSL_PARAM known_gettable_ctx_params[] = {
+    OSSL_PARAM_size_t(OSSL_MAC_PARAM_OUTLEN, NULL),
+    OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), /* Same as "outlen" */
+    OSSL_PARAM_END
+};
+static const OSSL_PARAM *cmac_gettable_ctx_params(void)
+{
+    return known_gettable_ctx_params;
+}
+
+static int cmac_ctx_get_params(void *vmacctx, OSSL_PARAM params[])
+{
+    OSSL_PARAM *p;
+
+    if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_OUTLEN)) != NULL
+        || (p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL)
+        return OSSL_PARAM_set_size_t(p, cmac_size(vmacctx));
+
+    return 1;
+}
+
+static const OSSL_PARAM known_settable_ctx_params[] = {
+    /* "algorithm" and "cipher" are the same parameter */
+    OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_ALGORITHM, NULL, 0),
+    OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_CIPHER, NULL, 0),
+    OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_ENGINE, NULL, 0),
+    OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_PROPERTIES, NULL, 0),
+    OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0),
+    OSSL_PARAM_END
+};
+static const OSSL_PARAM *cmac_settable_ctx_params(void)
+{
+    return known_settable_ctx_params;
+}
+
+/*
+ * ALL parameters should be set before init().
+ */
+static int cmac_ctx_set_params(void *vmacctx, const OSSL_PARAM params[])
+{
+    struct cmac_data_st *macctx = vmacctx;
+    const OSSL_PARAM *p;
+
+    if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_CIPHER)) != NULL
+        || ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_ALGORITHM))
+            != NULL)) {
+        if (p->data_type != OSSL_PARAM_UTF8_STRING)
+            return 0;
+
+        {
+            const char *algoname = p->data;
+            const char *propquery = NULL;
+
+#ifndef FIPS_MODE /* Inside the FIPS module, we don't support engines */
+            ENGINE_finish(macctx->tmpengine);
+            macctx->tmpengine = NULL;
+
+            if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_ENGINE))
+                != NULL) {
+                if (p->data_type != OSSL_PARAM_UTF8_STRING)
+                    return 0;
+
+                macctx->tmpengine = ENGINE_by_id(p->data);
+                if (macctx->tmpengine == NULL)
+                    return 0;
+            }
+#endif
+            if ((p = OSSL_PARAM_locate_const(params,
+                                             OSSL_MAC_PARAM_PROPERTIES))
+                != NULL) {
+                if (p->data_type != OSSL_PARAM_UTF8_STRING)
+                    return 0;
+
+                propquery = p->data;
+            }
+
+            EVP_CIPHER_meth_free(macctx->alloc_cipher);
+
+            macctx->tmpcipher = macctx->alloc_cipher =
+                EVP_CIPHER_fetch(PROV_LIBRARY_CONTEXT_OF(macctx->provctx),
+                                 algoname, propquery);
+
+#ifndef FIPS_MODE /* Inside the FIPS module, we don't support legacy digests */
+            /* TODO(3.0) BEGIN legacy stuff, to be removed */
+            if (macctx->tmpcipher == NULL)
+                macctx->tmpcipher = EVP_get_cipherbyname(algoname);
+            /* TODO(3.0) END of legacy stuff */
+#endif
+
+            if (macctx->tmpcipher == NULL)
+                return 0;
+        }
+    }
+    if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) {
+        if (p->data_type != OSSL_PARAM_OCTET_STRING)
+            return 0;
+
+        if (!CMAC_Init(macctx->ctx, p->data, p->data_size,
+                       macctx->tmpcipher, macctx->tmpengine))
+            return 0;
+
+        macctx->tmpcipher = NULL;
+        macctx->tmpengine = NULL;
+    }
+    return 1;
+}
+
+const OSSL_DISPATCH cmac_functions[] = {
+    { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))cmac_new },
+    { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))cmac_dup },
+    { OSSL_FUNC_MAC_FREECTX, (void (*)(void))cmac_free },
+    { OSSL_FUNC_MAC_INIT, (void (*)(void))cmac_init },
+    { OSSL_FUNC_MAC_UPDATE, (void (*)(void))cmac_update },
+    { OSSL_FUNC_MAC_FINAL, (void (*)(void))cmac_final },
+    { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS,
+      (void (*)(void))cmac_gettable_ctx_params },
+    { OSSL_FUNC_MAC_CTX_GET_PARAMS, (void (*)(void))cmac_ctx_get_params },
+    { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS,
+      (void (*)(void))cmac_settable_ctx_params },
+    { OSSL_FUNC_MAC_CTX_SET_PARAMS, (void (*)(void))cmac_ctx_set_params },
+    { 0, NULL }
+};
+
+#endif
index f4457a4d901e68410a49161d4ba22e7db199bfbe..dc8011c8f7c9eaa5600404705b60cbe8edd5768e 100644 (file)
@@ -127,6 +127,9 @@ static const OSSL_ALGORITHM deflt_macs[] = {
 #ifndef OPENSSL_NO_BLAKE2
     { "BLAKE2BMAC", "default=yes", blake2bmac_functions },
     { "BLAKE2SMAC", "default=yes", blake2smac_functions },
+#endif
+#ifndef OPENSSL_NO_CMAC
+    { "CMAC", "default=yes", cmac_functions },
 #endif
     { NULL, NULL, NULL }
 };
index a59ebce23901ebe1ae3df4cc85b63a6e0c73f760..96e5e1dc419619a77074ccbdbb362c88381a5ec1 100644 (file)
@@ -274,6 +274,11 @@ static const OSSL_ALGORITHM fips_ciphers[] = {
     { NULL, NULL, NULL }
 };
 
+static const OSSL_ALGORITHM fips_macs[] = {
+    { "CMAC", "fips=yes", cmac_functions },
+    { NULL, NULL, NULL }
+};
+
 static const OSSL_ALGORITHM *fips_query(OSSL_PROVIDER *prov,
                                          int operation_id,
                                          int *no_cache)
@@ -284,6 +289,8 @@ static const OSSL_ALGORITHM *fips_query(OSSL_PROVIDER *prov,
         return fips_digests;
     case OSSL_OP_CIPHER:
         return fips_ciphers;
+    case OSSL_OP_MAC:
+        return fips_macs;
     }
     return NULL;
 }