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