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