xref: /nrf52832-nimble/packages/NimBLE-latest/ext/tinycrypt/include/tinycrypt/cmac_mode.h (revision 042d53a763ad75cb1465103098bb88c245d95138)
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