diff options
Diffstat (limited to 'openssl-1.1.0h/crypto/hmac')
-rw-r--r-- | openssl-1.1.0h/crypto/hmac/build.info | 3 | ||||
-rw-r--r-- | openssl-1.1.0h/crypto/hmac/hm_ameth.c | 125 | ||||
-rw-r--r-- | openssl-1.1.0h/crypto/hmac/hm_pmeth.c | 210 | ||||
-rw-r--r-- | openssl-1.1.0h/crypto/hmac/hmac.c | 240 | ||||
-rw-r--r-- | openssl-1.1.0h/crypto/hmac/hmac_lcl.h | 33 |
5 files changed, 611 insertions, 0 deletions
diff --git a/openssl-1.1.0h/crypto/hmac/build.info b/openssl-1.1.0h/crypto/hmac/build.info new file mode 100644 index 0000000..09f67c2 --- /dev/null +++ b/openssl-1.1.0h/crypto/hmac/build.info @@ -0,0 +1,3 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + hmac.c hm_ameth.c hm_pmeth.c diff --git a/openssl-1.1.0h/crypto/hmac/hm_ameth.c b/openssl-1.1.0h/crypto/hmac/hm_ameth.c new file mode 100644 index 0000000..78ae0ea --- /dev/null +++ b/openssl-1.1.0h/crypto/hmac/hm_ameth.c @@ -0,0 +1,125 @@ +/* + * Copyright 2007-2016 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 <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/evp.h> +#include "internal/asn1_int.h" + +#define HMAC_TEST_PRIVATE_KEY_FORMAT + +/* + * HMAC "ASN1" method. This is just here to indicate the maximum HMAC output + * length and to free up an HMAC key. + */ + +static int hmac_size(const EVP_PKEY *pkey) +{ + return EVP_MAX_MD_SIZE; +} + +static void hmac_key_free(EVP_PKEY *pkey) +{ + ASN1_OCTET_STRING *os = EVP_PKEY_get0(pkey); + if (os) { + if (os->data) + OPENSSL_cleanse(os->data, os->length); + ASN1_OCTET_STRING_free(os); + } +} + +static int hmac_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) +{ + switch (op) { + case ASN1_PKEY_CTRL_DEFAULT_MD_NID: + *(int *)arg2 = NID_sha256; + return 1; + + default: + return -2; + } +} + +static int hmac_pkey_public_cmp(const EVP_PKEY *a, const EVP_PKEY *b) +{ + return ASN1_OCTET_STRING_cmp(EVP_PKEY_get0(a), EVP_PKEY_get0(b)); +} + +#ifdef HMAC_TEST_PRIVATE_KEY_FORMAT +/* + * A bogus private key format for test purposes. This is simply the HMAC key + * with "HMAC PRIVATE KEY" in the headers. When enabled the genpkey utility + * can be used to "generate" HMAC keys. + */ + +static int old_hmac_decode(EVP_PKEY *pkey, + const unsigned char **pder, int derlen) +{ + ASN1_OCTET_STRING *os; + os = ASN1_OCTET_STRING_new(); + if (os == NULL || !ASN1_OCTET_STRING_set(os, *pder, derlen)) + goto err; + if (!EVP_PKEY_assign(pkey, EVP_PKEY_HMAC, os)) + goto err; + return 1; + + err: + ASN1_OCTET_STRING_free(os); + return 0; +} + +static int old_hmac_encode(const EVP_PKEY *pkey, unsigned char **pder) +{ + int inc; + ASN1_OCTET_STRING *os = EVP_PKEY_get0(pkey); + if (pder) { + if (!*pder) { + *pder = OPENSSL_malloc(os->length); + if (*pder == NULL) + return -1; + inc = 0; + } else + inc = 1; + + memcpy(*pder, os->data, os->length); + + if (inc) + *pder += os->length; + } + + return os->length; +} + +#endif + +const EVP_PKEY_ASN1_METHOD hmac_asn1_meth = { + EVP_PKEY_HMAC, + EVP_PKEY_HMAC, + 0, + + "HMAC", + "OpenSSL HMAC method", + + 0, 0, hmac_pkey_public_cmp, 0, + + 0, 0, 0, + + hmac_size, + 0, 0, + 0, 0, 0, 0, 0, 0, 0, + + hmac_key_free, + hmac_pkey_ctrl, +#ifdef HMAC_TEST_PRIVATE_KEY_FORMAT + old_hmac_decode, + old_hmac_encode +#else + 0, 0 +#endif +}; diff --git a/openssl-1.1.0h/crypto/hmac/hm_pmeth.c b/openssl-1.1.0h/crypto/hmac/hm_pmeth.c new file mode 100644 index 0000000..5b98477 --- /dev/null +++ b/openssl-1.1.0h/crypto/hmac/hm_pmeth.c @@ -0,0 +1,210 @@ +/* + * Copyright 2007-2016 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 <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/x509.h> +#include <openssl/x509v3.h> +#include <openssl/evp.h> +#include <openssl/hmac.h> +#include "internal/evp_int.h" + +/* HMAC pkey context structure */ + +typedef struct { + const EVP_MD *md; /* MD for HMAC use */ + ASN1_OCTET_STRING ktmp; /* Temp storage for key */ + HMAC_CTX *ctx; +} HMAC_PKEY_CTX; + +static int pkey_hmac_init(EVP_PKEY_CTX *ctx) +{ + HMAC_PKEY_CTX *hctx; + + hctx = OPENSSL_zalloc(sizeof(*hctx)); + if (hctx == NULL) + return 0; + hctx->ktmp.type = V_ASN1_OCTET_STRING; + hctx->ctx = HMAC_CTX_new(); + if (hctx->ctx == NULL) { + OPENSSL_free(hctx); + return 0; + } + + ctx->data = hctx; + ctx->keygen_info_count = 0; + + return 1; +} + +static void pkey_hmac_cleanup(EVP_PKEY_CTX *ctx); + +static int pkey_hmac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) +{ + HMAC_PKEY_CTX *sctx, *dctx; + + /* allocate memory for dst->data and a new HMAC_CTX in dst->data->ctx */ + if (!pkey_hmac_init(dst)) + return 0; + sctx = EVP_PKEY_CTX_get_data(src); + dctx = EVP_PKEY_CTX_get_data(dst); + dctx->md = sctx->md; + if (!HMAC_CTX_copy(dctx->ctx, sctx->ctx)) + goto err; + if (sctx->ktmp.data) { + if (!ASN1_OCTET_STRING_set(&dctx->ktmp, + sctx->ktmp.data, sctx->ktmp.length)) + goto err; + } + return 1; +err: + /* release HMAC_CTX in dst->data->ctx and memory allocated for dst->data */ + pkey_hmac_cleanup (dst); + return 0; +} + +static void pkey_hmac_cleanup(EVP_PKEY_CTX *ctx) +{ + HMAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx); + + if (hctx != NULL) { + HMAC_CTX_free(hctx->ctx); + OPENSSL_clear_free(hctx->ktmp.data, hctx->ktmp.length); + OPENSSL_free(hctx); + EVP_PKEY_CTX_set_data(ctx, NULL); + } +} + +static int pkey_hmac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) +{ + ASN1_OCTET_STRING *hkey = NULL; + HMAC_PKEY_CTX *hctx = ctx->data; + if (!hctx->ktmp.data) + return 0; + hkey = ASN1_OCTET_STRING_dup(&hctx->ktmp); + if (!hkey) + return 0; + EVP_PKEY_assign(pkey, EVP_PKEY_HMAC, hkey); + + return 1; +} + +static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + HMAC_PKEY_CTX *hctx = EVP_MD_CTX_pkey_ctx(ctx)->data; + if (!HMAC_Update(hctx->ctx, data, count)) + return 0; + return 1; +} + +static int hmac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) +{ + HMAC_PKEY_CTX *hctx = ctx->data; + HMAC_CTX_set_flags(hctx->ctx, + 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); + return 1; +} + +static int hmac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + EVP_MD_CTX *mctx) +{ + unsigned int hlen; + HMAC_PKEY_CTX *hctx = ctx->data; + int l = EVP_MD_CTX_size(mctx); + + if (l < 0) + return 0; + *siglen = l; + if (!sig) + return 1; + + if (!HMAC_Final(hctx->ctx, sig, &hlen)) + return 0; + *siglen = (size_t)hlen; + return 1; +} + +static int pkey_hmac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) +{ + HMAC_PKEY_CTX *hctx = ctx->data; + ASN1_OCTET_STRING *key; + switch (type) { + + case EVP_PKEY_CTRL_SET_MAC_KEY: + if ((!p2 && p1 > 0) || (p1 < -1)) + return 0; + if (!ASN1_OCTET_STRING_set(&hctx->ktmp, p2, p1)) + return 0; + break; + + case EVP_PKEY_CTRL_MD: + hctx->md = p2; + break; + + case EVP_PKEY_CTRL_DIGESTINIT: + key = (ASN1_OCTET_STRING *)ctx->pkey->pkey.ptr; + if (!HMAC_Init_ex(hctx->ctx, key->data, key->length, hctx->md, + ctx->engine)) + return 0; + break; + + default: + return -2; + + } + return 1; +} + +static int pkey_hmac_ctrl_str(EVP_PKEY_CTX *ctx, + const char *type, const char *value) +{ + if (!value) { + return 0; + } + if (strcmp(type, "key") == 0) + return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value); + if (strcmp(type, "hexkey") == 0) + return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value); + return -2; +} + +const EVP_PKEY_METHOD hmac_pkey_meth = { + EVP_PKEY_HMAC, + 0, + pkey_hmac_init, + pkey_hmac_copy, + pkey_hmac_cleanup, + + 0, 0, + + 0, + pkey_hmac_keygen, + + 0, 0, + + 0, 0, + + 0, 0, + + hmac_signctx_init, + hmac_signctx, + + 0, 0, + + 0, 0, + + 0, 0, + + 0, 0, + + pkey_hmac_ctrl, + pkey_hmac_ctrl_str +}; diff --git a/openssl-1.1.0h/crypto/hmac/hmac.c b/openssl-1.1.0h/crypto/hmac/hmac.c new file mode 100644 index 0000000..3374105 --- /dev/null +++ b/openssl-1.1.0h/crypto/hmac/hmac.c @@ -0,0 +1,240 @@ +/* + * Copyright 1995-2016 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "internal/cryptlib.h" +#include <openssl/hmac.h> +#include <openssl/opensslconf.h> +#include "hmac_lcl.h" + +int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, + const EVP_MD *md, ENGINE *impl) +{ + int i, j, reset = 0; + unsigned char pad[HMAC_MAX_MD_CBLOCK]; + + /* If we are changing MD then we must have a key */ + if (md != NULL && md != ctx->md && (key == NULL || len < 0)) + return 0; + + if (md != NULL) { + reset = 1; + ctx->md = md; + } else if (ctx->md) { + md = ctx->md; + } else { + return 0; + } + + if (key != NULL) { + reset = 1; + j = EVP_MD_block_size(md); + OPENSSL_assert(j <= (int)sizeof(ctx->key)); + if (j < len) { + if (!EVP_DigestInit_ex(ctx->md_ctx, md, impl)) + goto err; + if (!EVP_DigestUpdate(ctx->md_ctx, key, len)) + goto err; + if (!EVP_DigestFinal_ex(ctx->md_ctx, ctx->key, + &ctx->key_length)) + goto err; + } else { + if (len < 0 || len > (int)sizeof(ctx->key)) + return 0; + memcpy(ctx->key, key, len); + ctx->key_length = len; + } + if (ctx->key_length != HMAC_MAX_MD_CBLOCK) + memset(&ctx->key[ctx->key_length], 0, + HMAC_MAX_MD_CBLOCK - ctx->key_length); + } + + if (reset) { + for (i = 0; i < HMAC_MAX_MD_CBLOCK; i++) + pad[i] = 0x36 ^ ctx->key[i]; + if (!EVP_DigestInit_ex(ctx->i_ctx, md, impl)) + goto err; + if (!EVP_DigestUpdate(ctx->i_ctx, pad, EVP_MD_block_size(md))) + goto err; + + for (i = 0; i < HMAC_MAX_MD_CBLOCK; i++) + pad[i] = 0x5c ^ ctx->key[i]; + if (!EVP_DigestInit_ex(ctx->o_ctx, md, impl)) + goto err; + if (!EVP_DigestUpdate(ctx->o_ctx, pad, EVP_MD_block_size(md))) + goto err; + } + if (!EVP_MD_CTX_copy_ex(ctx->md_ctx, ctx->i_ctx)) + goto err; + return 1; + err: + return 0; +} + +#if OPENSSL_API_COMPAT < 0x10100000L +int HMAC_Init(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md) +{ + if (key && md) + HMAC_CTX_reset(ctx); + return HMAC_Init_ex(ctx, key, len, md, NULL); +} +#endif + +int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len) +{ + if (!ctx->md) + return 0; + return EVP_DigestUpdate(ctx->md_ctx, data, len); +} + +int HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) +{ + unsigned int i; + unsigned char buf[EVP_MAX_MD_SIZE]; + + if (!ctx->md) + goto err; + + if (!EVP_DigestFinal_ex(ctx->md_ctx, buf, &i)) + goto err; + if (!EVP_MD_CTX_copy_ex(ctx->md_ctx, ctx->o_ctx)) + goto err; + if (!EVP_DigestUpdate(ctx->md_ctx, buf, i)) + goto err; + if (!EVP_DigestFinal_ex(ctx->md_ctx, md, len)) + goto err; + return 1; + err: + return 0; +} + +size_t HMAC_size(const HMAC_CTX *ctx) +{ + return EVP_MD_size((ctx)->md); +} + +HMAC_CTX *HMAC_CTX_new(void) +{ + HMAC_CTX *ctx = OPENSSL_zalloc(sizeof(HMAC_CTX)); + + if (ctx != NULL) { + if (!HMAC_CTX_reset(ctx)) { + HMAC_CTX_free(ctx); + return NULL; + } + } + return ctx; +} + +static void hmac_ctx_cleanup(HMAC_CTX *ctx) +{ + EVP_MD_CTX_reset(ctx->i_ctx); + EVP_MD_CTX_reset(ctx->o_ctx); + EVP_MD_CTX_reset(ctx->md_ctx); + ctx->md = NULL; + ctx->key_length = 0; + OPENSSL_cleanse(ctx->key, sizeof(ctx->key)); +} + +void HMAC_CTX_free(HMAC_CTX *ctx) +{ + if (ctx != NULL) { + hmac_ctx_cleanup(ctx); + EVP_MD_CTX_free(ctx->i_ctx); + EVP_MD_CTX_free(ctx->o_ctx); + EVP_MD_CTX_free(ctx->md_ctx); + OPENSSL_free(ctx); + } +} + +int HMAC_CTX_reset(HMAC_CTX *ctx) +{ + hmac_ctx_cleanup(ctx); + if (ctx->i_ctx == NULL) + ctx->i_ctx = EVP_MD_CTX_new(); + if (ctx->i_ctx == NULL) + goto err; + if (ctx->o_ctx == NULL) + ctx->o_ctx = EVP_MD_CTX_new(); + if (ctx->o_ctx == NULL) + goto err; + if (ctx->md_ctx == NULL) + ctx->md_ctx = EVP_MD_CTX_new(); + if (ctx->md_ctx == NULL) + goto err; + ctx->md = NULL; + return 1; + err: + hmac_ctx_cleanup(ctx); + return 0; +} + +int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx) +{ + if (!HMAC_CTX_reset(dctx)) + goto err; + if (!EVP_MD_CTX_copy_ex(dctx->i_ctx, sctx->i_ctx)) + goto err; + if (!EVP_MD_CTX_copy_ex(dctx->o_ctx, sctx->o_ctx)) + goto err; + if (!EVP_MD_CTX_copy_ex(dctx->md_ctx, sctx->md_ctx)) + goto err; + memcpy(dctx->key, sctx->key, HMAC_MAX_MD_CBLOCK); + dctx->key_length = sctx->key_length; + dctx->md = sctx->md; + return 1; + err: + hmac_ctx_cleanup(dctx); + return 0; +} + +unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len, + const unsigned char *d, size_t n, unsigned char *md, + unsigned int *md_len) +{ + HMAC_CTX *c = NULL; + static unsigned char m[EVP_MAX_MD_SIZE]; + static const unsigned char dummy_key[1] = {'\0'}; + + if (md == NULL) + md = m; + if ((c = HMAC_CTX_new()) == NULL) + goto err; + + /* For HMAC_Init_ex, NULL key signals reuse. */ + if (key == NULL && key_len == 0) { + key = dummy_key; + } + + if (!HMAC_Init_ex(c, key, key_len, evp_md, NULL)) + goto err; + if (!HMAC_Update(c, d, n)) + goto err; + if (!HMAC_Final(c, md, md_len)) + goto err; + HMAC_CTX_free(c); + return md; + err: + HMAC_CTX_free(c); + return NULL; +} + +void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags) +{ + EVP_MD_CTX_set_flags(ctx->i_ctx, flags); + EVP_MD_CTX_set_flags(ctx->o_ctx, flags); + EVP_MD_CTX_set_flags(ctx->md_ctx, flags); +} + +const EVP_MD *HMAC_CTX_get_md(const HMAC_CTX *ctx) +{ + return ctx->md; +} diff --git a/openssl-1.1.0h/crypto/hmac/hmac_lcl.h b/openssl-1.1.0h/crypto/hmac/hmac_lcl.h new file mode 100644 index 0000000..4c156dc --- /dev/null +++ b/openssl-1.1.0h/crypto/hmac/hmac_lcl.h @@ -0,0 +1,33 @@ +/* + * Copyright 1995-2016 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 + */ + +#ifndef HEADER_HMAC_LCL_H +# define HEADER_HMAC_LCL_H + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 /* emacs indentation fix */ +} +#endif + +struct hmac_ctx_st { + const EVP_MD *md; + EVP_MD_CTX *md_ctx; + EVP_MD_CTX *i_ctx; + EVP_MD_CTX *o_ctx; + unsigned int key_length; + unsigned char key[HMAC_MAX_MD_CBLOCK]; +}; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif |