diff options
-rw-r--r-- | crypto/err/openssl.txt | 5 | ||||
-rw-r--r-- | crypto/evp/build.info | 3 | ||||
-rw-r--r-- | crypto/evp/evp_err.c | 5 | ||||
-rw-r--r-- | crypto/evp/evp_locl.h | 5 | ||||
-rw-r--r-- | crypto/evp/mac_lib.c | 185 | ||||
-rw-r--r-- | crypto/evp/names.c | 75 | ||||
-rw-r--r-- | crypto/include/internal/evp_int.h | 25 | ||||
-rw-r--r-- | doc/man3/EVP_MAC.pod | 348 | ||||
-rw-r--r-- | include/openssl/evp.h | 32 | ||||
-rw-r--r-- | include/openssl/evperr.h | 5 | ||||
-rw-r--r-- | include/openssl/objects.h | 3 | ||||
-rw-r--r-- | include/openssl/ossl_typ.h | 2 | ||||
-rw-r--r-- | util/libcrypto.num | 18 | ||||
-rw-r--r-- | util/private.num | 5 |
14 files changed, 713 insertions, 3 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; diff --git a/doc/man3/EVP_MAC.pod b/doc/man3/EVP_MAC.pod new file mode 100644 index 0000000000..a30f3fa691 --- /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/evp.h b/include/openssl/evp.h index 8c8051993f..79543d731b 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,36 @@ 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); + +/* PKEY stuff */ int EVP_PKEY_decrypt_old(unsigned char *dec_key, const unsigned char *enc_key, int enc_key_len, EVP_PKEY *private_key); diff --git a/include/openssl/evperr.h b/include/openssl/evperr.h index d2d44c2434..684bc7ceb0 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 diff --git a/include/openssl/objects.h b/include/openssl/objects.h index 5e8b5762f8..8e1eb0f6c3 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 7993ca28f3..9ea26de0d9 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/util/libcrypto.num b/util/libcrypto.num index 31f8781158..61236dfba2 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -4577,3 +4577,21 @@ 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: diff --git a/util/private.num b/util/private.num index 2bfe987b43..27d352acae 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 |