summaryrefslogtreecommitdiff
path: root/Cryptlib/OpenSSL/crypto/cmac/cmac.c
diff options
context:
space:
mode:
authorMathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>2017-09-13 12:09:40 -0700
committerMathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>2017-09-13 12:09:40 -0700
commitb6f94dbeacfc6f0a507413096189304c58dbe66c (patch)
treebce8c7db22209078618294c51d95a0c033aec7d9 /Cryptlib/OpenSSL/crypto/cmac/cmac.c
parent25f7fd1fb389a5f6356f353d16c5ead80dac6bbc (diff)
downloadefi-boot-shim-upstream/13_git1505328970.9c1c35c5.tar.gz
efi-boot-shim-upstream/13_git1505328970.9c1c35c5.zip
New upstream version 13~git1505328970.9c1c35c5upstream/13_git1505328970.9c1c35c5
Diffstat (limited to 'Cryptlib/OpenSSL/crypto/cmac/cmac.c')
-rw-r--r--Cryptlib/OpenSSL/crypto/cmac/cmac.c173
1 files changed, 128 insertions, 45 deletions
diff --git a/Cryptlib/OpenSSL/crypto/cmac/cmac.c b/Cryptlib/OpenSSL/crypto/cmac/cmac.c
index c4f13a06..2954b6eb 100644
--- a/Cryptlib/OpenSSL/crypto/cmac/cmac.c
+++ b/Cryptlib/OpenSSL/crypto/cmac/cmac.c
@@ -1,21 +1,70 @@
+/* crypto/cmac/cmac.c */
/*
- * Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2010 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
*
- * 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
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "internal/cryptlib.h"
+#include "cryptlib.h"
#include <openssl/cmac.h>
+#ifdef OPENSSL_FIPS
+# include <openssl/fips.h>
+#endif
+
struct CMAC_CTX_st {
/* Cipher context to use */
- EVP_CIPHER_CTX *cctx;
+ EVP_CIPHER_CTX cctx;
/* Keys k1 and k2 */
unsigned char k1[EVP_MAX_BLOCK_LENGTH];
unsigned char k2[EVP_MAX_BLOCK_LENGTH];
@@ -29,38 +78,40 @@ struct CMAC_CTX_st {
/* Make temporary keys K1 and K2 */
-static void make_kn(unsigned char *k1, const unsigned char *l, int bl)
+static void make_kn(unsigned char *k1, unsigned char *l, int bl)
{
int i;
- unsigned char c = l[0], carry = c >> 7, cnext;
-
/* Shift block to left, including carry */
- for (i = 0; i < bl - 1; i++, c = cnext)
- k1[i] = (c << 1) | ((cnext = l[i + 1]) >> 7);
-
+ for (i = 0; i < bl; i++) {
+ k1[i] = l[i] << 1;
+ if (i < bl - 1 && l[i + 1] & 0x80)
+ k1[i] |= 1;
+ }
/* If MSB set fixup with R */
- k1[i] = (c << 1) ^ ((0 - carry) & (bl == 16 ? 0x87 : 0x1b));
+ if (l[0] & 0x80)
+ k1[bl - 1] ^= bl == 16 ? 0x87 : 0x1b;
}
CMAC_CTX *CMAC_CTX_new(void)
{
CMAC_CTX *ctx;
-
- ctx = OPENSSL_malloc(sizeof(*ctx));
- if (ctx == NULL)
- return NULL;
- ctx->cctx = EVP_CIPHER_CTX_new();
- if (ctx->cctx == NULL) {
- OPENSSL_free(ctx);
+ ctx = OPENSSL_malloc(sizeof(CMAC_CTX));
+ if (!ctx)
return NULL;
- }
+ EVP_CIPHER_CTX_init(&ctx->cctx);
ctx->nlast_block = -1;
return ctx;
}
void CMAC_CTX_cleanup(CMAC_CTX *ctx)
{
- EVP_CIPHER_CTX_free(ctx->cctx);
+#ifdef OPENSSL_FIPS
+ if (FIPS_mode() && !ctx->cctx.engine) {
+ FIPS_cmac_ctx_cleanup(ctx);
+ return;
+ }
+#endif
+ EVP_CIPHER_CTX_cleanup(&ctx->cctx);
OPENSSL_cleanse(ctx->tbl, EVP_MAX_BLOCK_LENGTH);
OPENSSL_cleanse(ctx->k1, EVP_MAX_BLOCK_LENGTH);
OPENSSL_cleanse(ctx->k2, EVP_MAX_BLOCK_LENGTH);
@@ -70,7 +121,7 @@ void CMAC_CTX_cleanup(CMAC_CTX *ctx)
EVP_CIPHER_CTX *CMAC_CTX_get0_cipher_ctx(CMAC_CTX *ctx)
{
- return ctx->cctx;
+ return &ctx->cctx;
}
void CMAC_CTX_free(CMAC_CTX *ctx)
@@ -86,9 +137,9 @@ int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in)
int bl;
if (in->nlast_block == -1)
return 0;
- if (!EVP_CIPHER_CTX_copy(out->cctx, in->cctx))
+ if (!EVP_CIPHER_CTX_copy(&out->cctx, &in->cctx))
return 0;
- bl = EVP_CIPHER_CTX_block_size(in->cctx);
+ bl = EVP_CIPHER_CTX_block_size(&in->cctx);
memcpy(out->k1, in->k1, bl);
memcpy(out->k2, in->k2, bl);
memcpy(out->tbl, in->tbl, bl);
@@ -100,38 +151,62 @@ int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in)
int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen,
const EVP_CIPHER *cipher, ENGINE *impl)
{
- static const unsigned char zero_iv[EVP_MAX_BLOCK_LENGTH] = { 0 };
+ static unsigned char zero_iv[EVP_MAX_BLOCK_LENGTH];
+#ifdef OPENSSL_FIPS
+ if (FIPS_mode()) {
+ /* If we have an ENGINE need to allow non FIPS */
+ if ((impl || ctx->cctx.engine)
+ && !(ctx->cctx.flags & EVP_CIPH_FLAG_NON_FIPS_ALLOW)) {
+ EVPerr(EVP_F_CMAC_INIT, EVP_R_DISABLED_FOR_FIPS);
+ return 0;
+ }
+
+ /* Switch to FIPS cipher implementation if possible */
+ if (cipher != NULL) {
+ const EVP_CIPHER *fcipher;
+ fcipher = FIPS_get_cipherbynid(EVP_CIPHER_nid(cipher));
+ if (fcipher != NULL)
+ cipher = fcipher;
+ }
+ /*
+ * Other algorithm blocking will be done in FIPS_cmac_init, via
+ * FIPS_cipherinit().
+ */
+ if (!impl && !ctx->cctx.engine)
+ return FIPS_cmac_init(ctx, key, keylen, cipher, NULL);
+ }
+#endif
/* All zeros means restart */
if (!key && !cipher && !impl && keylen == 0) {
/* Not initialised */
if (ctx->nlast_block == -1)
return 0;
- if (!EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, NULL, zero_iv))
+ if (!EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, NULL, zero_iv))
return 0;
- memset(ctx->tbl, 0, EVP_CIPHER_CTX_block_size(ctx->cctx));
+ memset(ctx->tbl, 0, EVP_CIPHER_CTX_block_size(&ctx->cctx));
ctx->nlast_block = 0;
return 1;
}
- /* Initialise context */
- if (cipher && !EVP_EncryptInit_ex(ctx->cctx, cipher, impl, NULL, NULL))
+ /* Initialiase context */
+ if (cipher && !EVP_EncryptInit_ex(&ctx->cctx, cipher, impl, NULL, NULL))
return 0;
/* Non-NULL key means initialisation complete */
if (key) {
int bl;
- if (!EVP_CIPHER_CTX_cipher(ctx->cctx))
+ if (!EVP_CIPHER_CTX_cipher(&ctx->cctx))
return 0;
- if (!EVP_CIPHER_CTX_set_key_length(ctx->cctx, keylen))
+ if (!EVP_CIPHER_CTX_set_key_length(&ctx->cctx, keylen))
return 0;
- if (!EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, key, zero_iv))
+ if (!EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, key, zero_iv))
return 0;
- bl = EVP_CIPHER_CTX_block_size(ctx->cctx);
- if (!EVP_Cipher(ctx->cctx, ctx->tbl, zero_iv, bl))
+ bl = EVP_CIPHER_CTX_block_size(&ctx->cctx);
+ if (!EVP_Cipher(&ctx->cctx, ctx->tbl, zero_iv, bl))
return 0;
make_kn(ctx->k1, ctx->tbl, bl);
make_kn(ctx->k2, ctx->k1, bl);
OPENSSL_cleanse(ctx->tbl, bl);
/* Reset context again ready for first data block */
- if (!EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, NULL, zero_iv))
+ if (!EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, NULL, zero_iv))
return 0;
/* Zero tbl so resume works */
memset(ctx->tbl, 0, bl);
@@ -144,11 +219,15 @@ int CMAC_Update(CMAC_CTX *ctx, const void *in, size_t dlen)
{
const unsigned char *data = in;
size_t bl;
+#ifdef OPENSSL_FIPS
+ if (FIPS_mode() && !ctx->cctx.engine)
+ return FIPS_cmac_update(ctx, in, dlen);
+#endif
if (ctx->nlast_block == -1)
return 0;
if (dlen == 0)
return 1;
- bl = EVP_CIPHER_CTX_block_size(ctx->cctx);
+ bl = EVP_CIPHER_CTX_block_size(&ctx->cctx);
/* Copy into partial block if we need to */
if (ctx->nlast_block > 0) {
size_t nleft;
@@ -163,12 +242,12 @@ int CMAC_Update(CMAC_CTX *ctx, const void *in, size_t dlen)
return 1;
data += nleft;
/* Else not final block so encrypt it */
- if (!EVP_Cipher(ctx->cctx, ctx->tbl, ctx->last_block, bl))
+ if (!EVP_Cipher(&ctx->cctx, ctx->tbl, ctx->last_block, bl))
return 0;
}
/* Encrypt all but one of the complete blocks left */
while (dlen > bl) {
- if (!EVP_Cipher(ctx->cctx, ctx->tbl, data, bl))
+ if (!EVP_Cipher(&ctx->cctx, ctx->tbl, data, bl))
return 0;
dlen -= bl;
data += bl;
@@ -183,9 +262,13 @@ int CMAC_Update(CMAC_CTX *ctx, const void *in, size_t dlen)
int CMAC_Final(CMAC_CTX *ctx, unsigned char *out, size_t *poutlen)
{
int i, bl, lb;
+#ifdef OPENSSL_FIPS
+ if (FIPS_mode() && !ctx->cctx.engine)
+ return FIPS_cmac_final(ctx, out, poutlen);
+#endif
if (ctx->nlast_block == -1)
return 0;
- bl = EVP_CIPHER_CTX_block_size(ctx->cctx);
+ bl = EVP_CIPHER_CTX_block_size(&ctx->cctx);
*poutlen = (size_t)bl;
if (!out)
return 1;
@@ -201,7 +284,7 @@ int CMAC_Final(CMAC_CTX *ctx, unsigned char *out, size_t *poutlen)
for (i = 0; i < bl; i++)
out[i] = ctx->last_block[i] ^ ctx->k2[i];
}
- if (!EVP_Cipher(ctx->cctx, out, out, bl)) {
+ if (!EVP_Cipher(&ctx->cctx, out, out, bl)) {
OPENSSL_cleanse(out, bl);
return 0;
}
@@ -213,11 +296,11 @@ int CMAC_resume(CMAC_CTX *ctx)
if (ctx->nlast_block == -1)
return 0;
/*
- * The buffer "tbl" contains the last fully encrypted block which is the
+ * The buffer "tbl" containes the last fully encrypted block which is the
* last IV (or all zeroes if no last encrypted block). The last block has
- * not been modified since CMAC_final(). So reinitialising using the last
+ * not been modified since CMAC_final(). So reinitliasing using the last
* decrypted block will allow CMAC to continue after calling
* CMAC_Final().
*/
- return EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, NULL, ctx->tbl);
+ return EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, NULL, ctx->tbl);
}