1*5c591343SA. Cody Schuffelen /* Microsoft Reference Implementation for TPM 2.0
2*5c591343SA. Cody Schuffelen *
3*5c591343SA. Cody Schuffelen * The copyright in this software is being made available under the BSD License,
4*5c591343SA. Cody Schuffelen * included below. This software may be subject to other third party and
5*5c591343SA. Cody Schuffelen * contributor rights, including patent rights, and no such rights are granted
6*5c591343SA. Cody Schuffelen * under this license.
7*5c591343SA. Cody Schuffelen *
8*5c591343SA. Cody Schuffelen * Copyright (c) Microsoft Corporation
9*5c591343SA. Cody Schuffelen *
10*5c591343SA. Cody Schuffelen * All rights reserved.
11*5c591343SA. Cody Schuffelen *
12*5c591343SA. Cody Schuffelen * BSD License
13*5c591343SA. Cody Schuffelen *
14*5c591343SA. Cody Schuffelen * Redistribution and use in source and binary forms, with or without modification,
15*5c591343SA. Cody Schuffelen * are permitted provided that the following conditions are met:
16*5c591343SA. Cody Schuffelen *
17*5c591343SA. Cody Schuffelen * Redistributions of source code must retain the above copyright notice, this list
18*5c591343SA. Cody Schuffelen * of conditions and the following disclaimer.
19*5c591343SA. Cody Schuffelen *
20*5c591343SA. Cody Schuffelen * Redistributions in binary form must reproduce the above copyright notice, this
21*5c591343SA. Cody Schuffelen * list of conditions and the following disclaimer in the documentation and/or
22*5c591343SA. Cody Schuffelen * other materials provided with the distribution.
23*5c591343SA. Cody Schuffelen *
24*5c591343SA. Cody Schuffelen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25*5c591343SA. Cody Schuffelen * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26*5c591343SA. Cody Schuffelen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27*5c591343SA. Cody Schuffelen * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28*5c591343SA. Cody Schuffelen * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29*5c591343SA. Cody Schuffelen * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30*5c591343SA. Cody Schuffelen * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31*5c591343SA. Cody Schuffelen * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32*5c591343SA. Cody Schuffelen * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33*5c591343SA. Cody Schuffelen * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*5c591343SA. Cody Schuffelen */
35*5c591343SA. Cody Schuffelen //** Introduction
36*5c591343SA. Cody Schuffelen //
37*5c591343SA. Cody Schuffelen // This file contains the implementation of the message authentication codes based
38*5c591343SA. Cody Schuffelen // on a symmetric block cipher. These functions only use the single block
39*5c591343SA. Cody Schuffelen // encryption functions of the selected symmetric cryptographic library.
40*5c591343SA. Cody Schuffelen
41*5c591343SA. Cody Schuffelen //** Includes, Defines, and Typedefs
42*5c591343SA. Cody Schuffelen #define _CRYPT_HASH_C_
43*5c591343SA. Cody Schuffelen #include "Tpm.h"
44*5c591343SA. Cody Schuffelen #include "CryptSym.h"
45*5c591343SA. Cody Schuffelen
46*5c591343SA. Cody Schuffelen #if ALG_CMAC
47*5c591343SA. Cody Schuffelen
48*5c591343SA. Cody Schuffelen //** Functions
49*5c591343SA. Cody Schuffelen
50*5c591343SA. Cody Schuffelen //*** CryptCmacStart()
51*5c591343SA. Cody Schuffelen // This is the function to start the CMAC sequence operation. It initializes the
52*5c591343SA. Cody Schuffelen // dispatch functions for the data and end operations for CMAC and initializes the
53*5c591343SA. Cody Schuffelen // parameters that are used for the processing of data, including the key, key size
54*5c591343SA. Cody Schuffelen // and block cipher algorithm.
55*5c591343SA. Cody Schuffelen UINT16
CryptCmacStart(SMAC_STATE * state,TPMU_PUBLIC_PARMS * keyParms,TPM_ALG_ID macAlg,TPM2B * key)56*5c591343SA. Cody Schuffelen CryptCmacStart(
57*5c591343SA. Cody Schuffelen SMAC_STATE *state,
58*5c591343SA. Cody Schuffelen TPMU_PUBLIC_PARMS *keyParms,
59*5c591343SA. Cody Schuffelen TPM_ALG_ID macAlg,
60*5c591343SA. Cody Schuffelen TPM2B *key
61*5c591343SA. Cody Schuffelen )
62*5c591343SA. Cody Schuffelen {
63*5c591343SA. Cody Schuffelen tpmCmacState_t *cState = &state->state.cmac;
64*5c591343SA. Cody Schuffelen TPMT_SYM_DEF_OBJECT *def = &keyParms->symDetail.sym;
65*5c591343SA. Cody Schuffelen //
66*5c591343SA. Cody Schuffelen if(macAlg != TPM_ALG_CMAC)
67*5c591343SA. Cody Schuffelen return 0;
68*5c591343SA. Cody Schuffelen // set up the encryption algorithm and parameters
69*5c591343SA. Cody Schuffelen cState->symAlg = def->algorithm;
70*5c591343SA. Cody Schuffelen cState->keySizeBits = def->keyBits.sym;
71*5c591343SA. Cody Schuffelen cState->iv.t.size = CryptGetSymmetricBlockSize(def->algorithm,
72*5c591343SA. Cody Schuffelen def->keyBits.sym);
73*5c591343SA. Cody Schuffelen MemoryCopy2B(&cState->symKey.b, key, sizeof(cState->symKey.t.buffer));
74*5c591343SA. Cody Schuffelen
75*5c591343SA. Cody Schuffelen // Set up the dispatch methods for the CMAC
76*5c591343SA. Cody Schuffelen state->smacMethods.data = CryptCmacData;
77*5c591343SA. Cody Schuffelen state->smacMethods.end = CryptCmacEnd;
78*5c591343SA. Cody Schuffelen return cState->iv.t.size;
79*5c591343SA. Cody Schuffelen }
80*5c591343SA. Cody Schuffelen
81*5c591343SA. Cody Schuffelen
82*5c591343SA. Cody Schuffelen //*** CryptCmacData()
83*5c591343SA. Cody Schuffelen // This function is used to add data to the CMAC sequence computation. The function
84*5c591343SA. Cody Schuffelen // will XOR new data into the IV. If the buffer is full, and there is additional
85*5c591343SA. Cody Schuffelen // input data, the data is encrypted into the IV buffer, the new data is then
86*5c591343SA. Cody Schuffelen // XOR into the IV. When the data runs out, the function returns without encrypting
87*5c591343SA. Cody Schuffelen // even if the buffer is full. The last data block of a sequence will not be
88*5c591343SA. Cody Schuffelen // encrypted until the call to CryptCmacEnd(). This is to allow the proper subkey
89*5c591343SA. Cody Schuffelen // to be computed and applied before the last block is encrypted.
90*5c591343SA. Cody Schuffelen void
CryptCmacData(SMAC_STATES * state,UINT32 size,const BYTE * buffer)91*5c591343SA. Cody Schuffelen CryptCmacData(
92*5c591343SA. Cody Schuffelen SMAC_STATES *state,
93*5c591343SA. Cody Schuffelen UINT32 size,
94*5c591343SA. Cody Schuffelen const BYTE *buffer
95*5c591343SA. Cody Schuffelen )
96*5c591343SA. Cody Schuffelen {
97*5c591343SA. Cody Schuffelen tpmCmacState_t *cmacState = &state->cmac;
98*5c591343SA. Cody Schuffelen TPM_ALG_ID algorithm = cmacState->symAlg;
99*5c591343SA. Cody Schuffelen BYTE *key = cmacState->symKey.t.buffer;
100*5c591343SA. Cody Schuffelen UINT16 keySizeInBits = cmacState->keySizeBits;
101*5c591343SA. Cody Schuffelen tpmCryptKeySchedule_t keySchedule;
102*5c591343SA. Cody Schuffelen TpmCryptSetSymKeyCall_t encrypt;
103*5c591343SA. Cody Schuffelen //
104*5c591343SA. Cody Schuffelen // Set up the encryption values based on the algorithm
105*5c591343SA. Cody Schuffelen switch (algorithm)
106*5c591343SA. Cody Schuffelen {
107*5c591343SA. Cody Schuffelen FOR_EACH_SYM(ENCRYPT_CASE)
108*5c591343SA. Cody Schuffelen default:
109*5c591343SA. Cody Schuffelen FAIL(FATAL_ERROR_INTERNAL);
110*5c591343SA. Cody Schuffelen }
111*5c591343SA. Cody Schuffelen while(size > 0)
112*5c591343SA. Cody Schuffelen {
113*5c591343SA. Cody Schuffelen if(cmacState->bcount == cmacState->iv.t.size)
114*5c591343SA. Cody Schuffelen {
115*5c591343SA. Cody Schuffelen ENCRYPT(&keySchedule, cmacState->iv.t.buffer, cmacState->iv.t.buffer);
116*5c591343SA. Cody Schuffelen cmacState->bcount = 0;
117*5c591343SA. Cody Schuffelen }
118*5c591343SA. Cody Schuffelen for(;(size > 0) && (cmacState->bcount < cmacState->iv.t.size);
119*5c591343SA. Cody Schuffelen size--, cmacState->bcount++)
120*5c591343SA. Cody Schuffelen {
121*5c591343SA. Cody Schuffelen cmacState->iv.t.buffer[cmacState->bcount] ^= *buffer++;
122*5c591343SA. Cody Schuffelen }
123*5c591343SA. Cody Schuffelen }
124*5c591343SA. Cody Schuffelen }
125*5c591343SA. Cody Schuffelen
126*5c591343SA. Cody Schuffelen //*** CryptCmacEnd()
127*5c591343SA. Cody Schuffelen // This is the completion function for the CMAC. It does padding, if needed, and
128*5c591343SA. Cody Schuffelen // selects the subkey to be applied before the last block is encrypted.
129*5c591343SA. Cody Schuffelen UINT16
CryptCmacEnd(SMAC_STATES * state,UINT32 outSize,BYTE * outBuffer)130*5c591343SA. Cody Schuffelen CryptCmacEnd(
131*5c591343SA. Cody Schuffelen SMAC_STATES *state,
132*5c591343SA. Cody Schuffelen UINT32 outSize,
133*5c591343SA. Cody Schuffelen BYTE *outBuffer
134*5c591343SA. Cody Schuffelen )
135*5c591343SA. Cody Schuffelen {
136*5c591343SA. Cody Schuffelen tpmCmacState_t *cState = &state->cmac;
137*5c591343SA. Cody Schuffelen // Need to set algorithm, key, and keySizeInBits in the local context so that
138*5c591343SA. Cody Schuffelen // the SELECT and ENCRYPT macros will work here
139*5c591343SA. Cody Schuffelen TPM_ALG_ID algorithm = cState->symAlg;
140*5c591343SA. Cody Schuffelen BYTE *key = cState->symKey.t.buffer;
141*5c591343SA. Cody Schuffelen UINT16 keySizeInBits = cState->keySizeBits;
142*5c591343SA. Cody Schuffelen tpmCryptKeySchedule_t keySchedule;
143*5c591343SA. Cody Schuffelen TpmCryptSetSymKeyCall_t encrypt;
144*5c591343SA. Cody Schuffelen TPM2B_IV subkey = {{0, {0}}};
145*5c591343SA. Cody Schuffelen BOOL xorVal;
146*5c591343SA. Cody Schuffelen UINT16 i;
147*5c591343SA. Cody Schuffelen
148*5c591343SA. Cody Schuffelen subkey.t.size = cState->iv.t.size;
149*5c591343SA. Cody Schuffelen // Encrypt a block of zero
150*5c591343SA. Cody Schuffelen // Set up the encryption values based on the algorithm
151*5c591343SA. Cody Schuffelen switch (algorithm)
152*5c591343SA. Cody Schuffelen {
153*5c591343SA. Cody Schuffelen FOR_EACH_SYM(ENCRYPT_CASE)
154*5c591343SA. Cody Schuffelen default:
155*5c591343SA. Cody Schuffelen return 0;
156*5c591343SA. Cody Schuffelen }
157*5c591343SA. Cody Schuffelen ENCRYPT(&keySchedule, subkey.t.buffer, subkey.t.buffer);
158*5c591343SA. Cody Schuffelen
159*5c591343SA. Cody Schuffelen // shift left by 1 and XOR with 0x0...87 if the MSb was 0
160*5c591343SA. Cody Schuffelen xorVal = ((subkey.t.buffer[0] & 0x80) == 0) ? 0 : 0x87;
161*5c591343SA. Cody Schuffelen ShiftLeft(&subkey.b);
162*5c591343SA. Cody Schuffelen subkey.t.buffer[subkey.t.size - 1] ^= xorVal;
163*5c591343SA. Cody Schuffelen // this is a sanity check to make sure that the algorithm is working properly.
164*5c591343SA. Cody Schuffelen // remove this check when debug is done
165*5c591343SA. Cody Schuffelen pAssert(cState->bcount <= cState->iv.t.size);
166*5c591343SA. Cody Schuffelen // If the buffer is full then no need to compute subkey 2.
167*5c591343SA. Cody Schuffelen if(cState->bcount < cState->iv.t.size)
168*5c591343SA. Cody Schuffelen {
169*5c591343SA. Cody Schuffelen //Pad the data
170*5c591343SA. Cody Schuffelen cState->iv.t.buffer[cState->bcount++] ^= 0x80;
171*5c591343SA. Cody Schuffelen // The rest of the data is a pad of zero which would simply be XORed
172*5c591343SA. Cody Schuffelen // with the iv value so nothing to do...
173*5c591343SA. Cody Schuffelen // Now compute K2
174*5c591343SA. Cody Schuffelen xorVal = ((subkey.t.buffer[0] & 0x80) == 0) ? 0 : 0x87;
175*5c591343SA. Cody Schuffelen ShiftLeft(&subkey.b);
176*5c591343SA. Cody Schuffelen subkey.t.buffer[subkey.t.size - 1] ^= xorVal;
177*5c591343SA. Cody Schuffelen }
178*5c591343SA. Cody Schuffelen // XOR the subkey into the IV
179*5c591343SA. Cody Schuffelen for(i = 0; i < subkey.t.size; i++)
180*5c591343SA. Cody Schuffelen cState->iv.t.buffer[i] ^= subkey.t.buffer[i];
181*5c591343SA. Cody Schuffelen ENCRYPT(&keySchedule, cState->iv.t.buffer, cState->iv.t.buffer);
182*5c591343SA. Cody Schuffelen i = (UINT16)MIN(cState->iv.t.size, outSize);
183*5c591343SA. Cody Schuffelen MemoryCopy(outBuffer, cState->iv.t.buffer, i);
184*5c591343SA. Cody Schuffelen
185*5c591343SA. Cody Schuffelen return i;
186*5c591343SA. Cody Schuffelen }
187*5c591343SA. Cody Schuffelen #endif
188*5c591343SA. Cody Schuffelen
189