ref: 9196c18d376d4f18c686bcfec8550f9c8659d5ea
src/libs/mynewt-nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
/* cmac_mode.h -- interface to a CMAC implementation */ /* * Copyright (C) 2017 by Intel Corporation, All Rights Reserved * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - 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. * * - Neither the name of Intel Corporation nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS 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 COPYRIGHT OWNER OR 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. */ /** * @file * @brief Interface to a CMAC implementation. * * Overview: CMAC is defined NIST in SP 800-38B, and is the standard algorithm * for computing a MAC using a block cipher. It can compute the MAC * for a byte string of any length. It is distinguished from CBC-MAC * in the processing of the final message block; CMAC uses a * different technique to compute the final message block is full * size or only partial, while CBC-MAC uses the same technique for * both. This difference permits CMAC to be applied to variable * length messages, while all messages authenticated by CBC-MAC must * be the same length. * * Security: AES128-CMAC mode of operation offers 64 bits of security against * collision attacks. Note however that an external attacker cannot * generate the tags him/herself without knowing the MAC key. In this * sense, to attack the collision property of AES128-CMAC, an * external attacker would need the cooperation of the legal user to * produce an exponentially high number of tags (e.g. 2^64) to * finally be able to look for collisions and benefit from them. As * an extra precaution, the current implementation allows to at most * 2^48 calls to the tc_cmac_update function before re-calling * tc_cmac_setup (allowing a new key to be set), as suggested in * Appendix B of SP 800-38B. * * Requires: AES-128 * * Usage: This implementation provides a "scatter-gather" interface, so that * the CMAC value can be computed incrementally over a message * scattered in different segments throughout memory. Experience shows * this style of interface tends to minimize the burden of programming * correctly. Like all symmetric key operations, it is session * oriented. * * To begin a CMAC session, use tc_cmac_setup to initialize a struct * tc_cmac_struct with encryption key and buffer. Our implementation * always assume that the AES key to be the same size as the block * cipher block size. Once setup, this data structure can be used for * many CMAC computations. * * Once the state has been setup with a key, computing the CMAC of * some data requires three steps: * * (1) first use tc_cmac_init to initialize a new CMAC computation. * (2) next mix all of the data into the CMAC computation state using * tc_cmac_update. If all of the data resides in a single data * segment then only one tc_cmac_update call is needed; if data * is scattered throughout memory in n data segments, then n calls * will be needed. CMAC IS ORDER SENSITIVE, to be able to detect * attacks that swap bytes, so the order in which data is mixed * into the state is critical! * (3) Once all of the data for a message has been mixed, use * tc_cmac_final to compute the CMAC tag value. * * Steps (1)-(3) can be repeated as many times as you want to CMAC * multiple messages. A practical limit is 2^48 1K messages before you * have to change the key. * * Once you are done computing CMAC with a key, it is a good idea to * destroy the state so an attacker cannot recover the key; use * tc_cmac_erase to accomplish this. */ #ifndef __TC_CMAC_MODE_H__ #define __TC_CMAC_MODE_H__ #include <tinycrypt/aes.h> #include <stddef.h> #ifdef __cplusplus extern "C" { #endif /* padding for last message block */ #define TC_CMAC_PADDING 0x80 /* struct tc_cmac_struct represents the state of a CMAC computation */ typedef struct tc_cmac_struct { /* initialization vector */ uint8_t iv[TC_AES_BLOCK_SIZE]; /* used if message length is a multiple of block_size bytes */ uint8_t K1[TC_AES_BLOCK_SIZE]; /* used if message length isn't a multiple block_size bytes */ uint8_t K2[TC_AES_BLOCK_SIZE]; /* where to put bytes that didn't fill a block */ uint8_t leftover[TC_AES_BLOCK_SIZE]; /* identifies the encryption key */ unsigned int keyid; /* next available leftover location */ unsigned int leftover_offset; /* AES key schedule */ TCAesKeySched_t sched; /* calls to tc_cmac_update left before re-key */ uint64_t countdown; } *TCCmacState_t; /** * @brief Configures the CMAC state to use the given AES key * @return returns TC_CRYPTO_SUCCESS (1) after having configured the CMAC state * returns TC_CRYPTO_FAIL (0) if: * s == NULL or * key == NULL * * @param s IN/OUT -- the state to set up * @param key IN -- the key to use * @param sched IN -- AES key schedule */ int tc_cmac_setup(TCCmacState_t s, const uint8_t *key, TCAesKeySched_t sched); /** * @brief Erases the CMAC state * @return returns TC_CRYPTO_SUCCESS (1) after having configured the CMAC state * returns TC_CRYPTO_FAIL (0) if: * s == NULL * * @param s IN/OUT -- the state to erase */ int tc_cmac_erase(TCCmacState_t s); /** * @brief Initializes a new CMAC computation * @return returns TC_CRYPTO_SUCCESS (1) after having initialized the CMAC state * returns TC_CRYPTO_FAIL (0) if: * s == NULL * * @param s IN/OUT -- the state to initialize */ int tc_cmac_init(TCCmacState_t s); /** * @brief Incrementally computes CMAC over the next data segment * @return returns TC_CRYPTO_SUCCESS (1) after successfully updating the CMAC state * returns TC_CRYPTO_FAIL (0) if: * s == NULL or * if data == NULL when dlen > 0 * * @param s IN/OUT -- the CMAC state * @param data IN -- the next data segment to MAC * @param dlen IN -- the length of data in bytes */ int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t dlen); /** * @brief Generates the tag from the CMAC state * @return returns TC_CRYPTO_SUCCESS (1) after successfully generating the tag * returns TC_CRYPTO_FAIL (0) if: * tag == NULL or * s == NULL * * @param tag OUT -- the CMAC tag * @param s IN -- CMAC state */ int tc_cmac_final(uint8_t *tag, TCCmacState_t s); #ifdef __cplusplus } #endif #endif /* __TC_CMAC_MODE_H__ */ |