summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2018-10-12 22:27:18 +0200
committerRichard Levitte <levitte@openssl.org>2018-10-29 13:35:19 +0100
commit567db2c17d4ea8a0164d7abd8aed65b7a634bb40 (patch)
tree064c9a50082bc9cda43b96dcde3f7eba5a0c6bd5 /crypto
parentf9e43929c46b38667f67e02765fe0f1c0d3061d6 (diff)
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@oracle.com> (Merged from https://github.com/openssl/openssl/pull/7393)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/err/openssl.txt5
-rw-r--r--crypto/evp/build.info3
-rw-r--r--crypto/evp/evp_err.c5
-rw-r--r--crypto/evp/evp_locl.h5
-rw-r--r--crypto/evp/mac_lib.c185
-rw-r--r--crypto/evp/names.c75
-rw-r--r--crypto/include/internal/evp_int.h25
7 files changed, 301 insertions, 2 deletions
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 489ccc0986..0fe35302bc 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
diff --git a/crypto/evp/build.info b/crypto/evp/build.info
index cc33ac3c49..6967fe9dc1 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
INCLUDE[e_aes.o]=.. ../modes
INCLUDE[e_aes_cbc_hmac_sha1.o]=../modes
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c
index ec6efb6e97..219a6c8641 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"},
diff --git a/crypto/evp/evp_locl.h b/crypto/evp/evp_locl.h
index f1589d6828..eaee472b92 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 0000000000..2786a012a5
--- /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 077c2a6c4b..6cdab2256c 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/include/internal/evp_int.h b/crypto/include/internal/evp_int.h
index d86aed36f0..5bc9408676 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;