/src/ibmswtpm2/src/CryptCmac.c
Line | Count | Source |
1 | | /********************************************************************************/ |
2 | | /* */ |
3 | | /* Message Authentication Codes Based on a Symmetric Block Cipher */ |
4 | | /* Written by Ken Goldman */ |
5 | | /* IBM Thomas J. Watson Research Center */ |
6 | | /* $Id: CryptCmac.c 1262 2018-07-11 21:03:43Z kgoldman $ */ |
7 | | /* */ |
8 | | /* Licenses and Notices */ |
9 | | /* */ |
10 | | /* 1. Copyright Licenses: */ |
11 | | /* */ |
12 | | /* - Trusted Computing Group (TCG) grants to the user of the source code in */ |
13 | | /* this specification (the "Source Code") a worldwide, irrevocable, */ |
14 | | /* nonexclusive, royalty free, copyright license to reproduce, create */ |
15 | | /* derivative works, distribute, display and perform the Source Code and */ |
16 | | /* derivative works thereof, and to grant others the rights granted herein. */ |
17 | | /* */ |
18 | | /* - The TCG grants to the user of the other parts of the specification */ |
19 | | /* (other than the Source Code) the rights to reproduce, distribute, */ |
20 | | /* display, and perform the specification solely for the purpose of */ |
21 | | /* developing products based on such documents. */ |
22 | | /* */ |
23 | | /* 2. Source Code Distribution Conditions: */ |
24 | | /* */ |
25 | | /* - Redistributions of Source Code must retain the above copyright licenses, */ |
26 | | /* this list of conditions and the following disclaimers. */ |
27 | | /* */ |
28 | | /* - Redistributions in binary form must reproduce the above copyright */ |
29 | | /* licenses, this list of conditions and the following disclaimers in the */ |
30 | | /* documentation and/or other materials provided with the distribution. */ |
31 | | /* */ |
32 | | /* 3. Disclaimers: */ |
33 | | /* */ |
34 | | /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ |
35 | | /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ |
36 | | /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ |
37 | | /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ |
38 | | /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ |
39 | | /* information on specification licensing rights available through TCG */ |
40 | | /* membership agreements. */ |
41 | | /* */ |
42 | | /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ |
43 | | /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ |
44 | | /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ |
45 | | /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ |
46 | | /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ |
47 | | /* */ |
48 | | /* - Without limitation, TCG and its members and licensors disclaim all */ |
49 | | /* liability, including liability for infringement of any proprietary */ |
50 | | /* rights, relating to use of information in this specification and to the */ |
51 | | /* implementation of this specification, and TCG disclaims all liability for */ |
52 | | /* cost of procurement of substitute goods or services, lost profits, loss */ |
53 | | /* of use, loss of data or any incidental, consequential, direct, indirect, */ |
54 | | /* or special damages, whether under contract, tort, warranty or otherwise, */ |
55 | | /* arising in any way out of use or reliance upon this specification or any */ |
56 | | /* information herein. */ |
57 | | /* */ |
58 | | /* (c) Copyright IBM Corp. and others, 2018 */ |
59 | | /* */ |
60 | | /********************************************************************************/ |
61 | | |
62 | | /* 10.2.6 CryptCmac.c */ |
63 | | /* 10.2.6.1 Introduction */ |
64 | | /* This file contains the implementation of the message authentication codes based on a symmetric |
65 | | block cipher. These functions only use the single block encryption functions of the selected |
66 | | symmetric cryptographic library. */ |
67 | | /* 10.2.6.2 Includes, Defines, and Typedefs */ |
68 | | #define _CRYPT_HASH_C_ |
69 | | #include "Tpm.h" |
70 | | #include "CryptSym.h" |
71 | | #if ALG_CMAC |
72 | | /* 10.2.6.3 Functions */ |
73 | | /* 10.2.6.3.1 CryptCmacStart() */ |
74 | | /* This is the function to start the CMAC sequence operation. It initializes the dispatch |
75 | | functions for the data and end operations for CMAC and initializes the parameters that are |
76 | | used for the processing of data, including the key, key size and block cipher algorithm. */ |
77 | | UINT16 |
78 | | CryptCmacStart( |
79 | | SMAC_STATE *state, |
80 | | TPMU_PUBLIC_PARMS *keyParms, |
81 | | TPM_ALG_ID macAlg, |
82 | | TPM2B *key |
83 | | ) |
84 | 0 | { |
85 | 0 | tpmCmacState_t *cState = &state->state.cmac; |
86 | 0 | TPMT_SYM_DEF_OBJECT *def = &keyParms->symDetail.sym; |
87 | | // |
88 | 0 | if(macAlg != TPM_ALG_CMAC) |
89 | 0 | return 0; |
90 | | // set up the encryption algorithm and parameters |
91 | 0 | cState->symAlg = def->algorithm; |
92 | 0 | cState->keySizeBits = def->keyBits.sym; |
93 | 0 | cState->iv.t.size = CryptGetSymmetricBlockSize(def->algorithm, |
94 | 0 | def->keyBits.sym); |
95 | 0 | MemoryCopy2B(&cState->symKey.b, key, sizeof(cState->symKey.t.buffer)); |
96 | | // Set up the dispatch methods for the CMAC |
97 | 0 | state->smacMethods.data = CryptCmacData; |
98 | 0 | state->smacMethods.end = CryptCmacEnd; |
99 | 0 | return cState->iv.t.size; |
100 | 0 | } |
101 | | |
102 | | /* 10.2.6.3.2 CryptCmacData() */ |
103 | | /* This function is used to add data to the CMAC sequence computation. The function will XOR new |
104 | | data into the IV. If the buffer is full, and there is additional input data, the data is |
105 | | encrypted into the IV buffer, the new data is then XOR into the IV. When the data runs out, the |
106 | | function returns without encrypting even if the buffer is full. The last data block of a sequence |
107 | | will not be encrypted until the call to CryptCmacEnd(). This is to allow the proper subkey to be |
108 | | computed and applied before the last block is encrypted. */ |
109 | | void |
110 | | CryptCmacData( |
111 | | SMAC_STATES *state, |
112 | | UINT32 size, |
113 | | const BYTE *buffer |
114 | | ) |
115 | 0 | { |
116 | 0 | tpmCmacState_t *cmacState = &state->cmac; |
117 | 0 | TPM_ALG_ID algorithm = cmacState->symAlg; |
118 | 0 | BYTE *key = cmacState->symKey.t.buffer; |
119 | 0 | UINT16 keySizeInBits = cmacState->keySizeBits; |
120 | 0 | tpmCryptKeySchedule_t keySchedule; |
121 | 0 | TpmCryptSetSymKeyCall_t encrypt; |
122 | | // |
123 | 0 | SELECT(ENCRYPT); |
124 | 0 | while(size > 0) |
125 | 0 | { |
126 | 0 | if(cmacState->bcount == cmacState->iv.t.size) |
127 | 0 | { |
128 | 0 | ENCRYPT(&keySchedule, cmacState->iv.t.buffer, cmacState->iv.t.buffer); |
129 | 0 | cmacState->bcount = 0; |
130 | 0 | } |
131 | 0 | for(;(size > 0) && (cmacState->bcount < cmacState->iv.t.size); |
132 | 0 | size--, cmacState->bcount++) |
133 | 0 | { |
134 | 0 | cmacState->iv.t.buffer[cmacState->bcount] ^= *buffer++; |
135 | 0 | } |
136 | 0 | } |
137 | 0 | } |
138 | | /* 10.2.6.3.3 CryptCmacEnd() */ |
139 | | /* This is the completion function for the CMAC. It does padding, if needed, and selects the subkey |
140 | | to be applied before the last block is encrypted. */ |
141 | | UINT16 |
142 | | CryptCmacEnd( |
143 | | SMAC_STATES *state, |
144 | | UINT32 outSize, |
145 | | BYTE *outBuffer |
146 | | ) |
147 | 0 | { |
148 | 0 | tpmCmacState_t *cState = &state->cmac; |
149 | | // Need to set algorithm, key, and keySizeInBits in the local context so that |
150 | | // the SELECT and ENCRYPT macros will work here |
151 | 0 | TPM_ALG_ID algorithm = cState->symAlg; |
152 | 0 | BYTE *key = cState->symKey.t.buffer; |
153 | 0 | UINT16 keySizeInBits = cState->keySizeBits; |
154 | 0 | tpmCryptKeySchedule_t keySchedule; |
155 | 0 | TpmCryptSetSymKeyCall_t encrypt; |
156 | 0 | TPM2B_IV subkey = {{0, {0}}}; |
157 | 0 | BOOL xorVal; |
158 | 0 | UINT16 i; |
159 | 0 | subkey.t.size = cState->iv.t.size; |
160 | | // Encrypt a block of zero |
161 | 0 | SELECT(ENCRYPT); |
162 | 0 | ENCRYPT(&keySchedule, subkey.t.buffer, subkey.t.buffer); |
163 | | // shift left by 1 and XOR with 0x0...87 if the MSb was 0 |
164 | 0 | xorVal = ((subkey.t.buffer[0] & 0x80) == 0) ? 0 : 0x87; |
165 | 0 | ShiftLeft(&subkey.b); |
166 | 0 | subkey.t.buffer[subkey.t.size - 1] ^= xorVal; |
167 | | // this is a sanity check to make sure that the algorithm is working properly. |
168 | | // remove this check when debug is done |
169 | 0 | pAssert(cState->bcount <= cState->iv.t.size); |
170 | | // If the buffer is full then no need to compute subkey 2. |
171 | 0 | if(cState->bcount < cState->iv.t.size) |
172 | 0 | { |
173 | | //Pad the data |
174 | 0 | cState->iv.t.buffer[cState->bcount++] ^= 0x80; |
175 | | // The rest of the data is a pad of zero which would simply be XORed |
176 | | // with the iv value so nothing to do... |
177 | | // Now compute K2 |
178 | 0 | xorVal = ((subkey.t.buffer[0] & 0x80) == 0) ? 0 : 0x87; |
179 | 0 | ShiftLeft(&subkey.b); |
180 | 0 | subkey.t.buffer[subkey.t.size - 1] ^= xorVal; |
181 | 0 | } |
182 | | // XOR the subkey into the IV |
183 | 0 | for(i = 0; i < subkey.t.size; i++) |
184 | 0 | cState->iv.t.buffer[i] ^= subkey.t.buffer[i]; |
185 | 0 | ENCRYPT(&keySchedule, cState->iv.t.buffer, cState->iv.t.buffer); |
186 | 0 | i = (UINT16)MIN(cState->iv.t.size, outSize); |
187 | 0 | MemoryCopy(outBuffer, cState->iv.t.buffer, i); |
188 | 0 | return i; |
189 | 0 | } |
190 | | #endif |