/src/ibmswtpm2/src/SymmetricCommands.c
Line | Count | Source (jump to first uncovered line) |
1 | | /********************************************************************************/ |
2 | | /* */ |
3 | | /* Symmetric Commands */ |
4 | | /* Written by Ken Goldman */ |
5 | | /* IBM Thomas J. Watson Research Center */ |
6 | | /* $Id: SymmetricCommands.c 1259 2018-07-10 19:11:09Z 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, 2016 - 2018 */ |
59 | | /* */ |
60 | | /********************************************************************************/ |
61 | | |
62 | | #include "Tpm.h" |
63 | | #include "EncryptDecrypt_fp.h" |
64 | | #if CC_EncryptDecrypt2 |
65 | | #include "EncryptDecrypt_spt_fp.h" |
66 | | #endif |
67 | | #if CC_EncryptDecrypt // Conditional expansion of this file |
68 | | TPM_RC |
69 | | TPM2_EncryptDecrypt( |
70 | | EncryptDecrypt_In *in, // IN: input parameter list |
71 | | EncryptDecrypt_Out *out // OUT: output parameter list |
72 | | ) |
73 | 0 | { |
74 | 0 | #if CC_EncryptDecrypt2 |
75 | 0 | return EncryptDecryptShared(in->keyHandle, in->decrypt, in->mode, |
76 | 0 | &in->ivIn, &in->inData, out); |
77 | | #else |
78 | | OBJECT *symKey; |
79 | | UINT16 keySize; |
80 | | UINT16 blockSize; |
81 | | BYTE *key; |
82 | | TPM_ALG_ID alg; |
83 | | TPM_ALG_ID mode; |
84 | | TPM_RC result; |
85 | | BOOL OK; |
86 | | TPMA_OBJECT attributes; |
87 | | // Input Validation |
88 | | symKey = HandleToObject(in->keyHandle); |
89 | | mode = symKey->publicArea.parameters.symDetail.sym.mode.sym; |
90 | | attributes = symKey->publicArea.objectAttributes; |
91 | | // The input key should be a symmetric key |
92 | | if(symKey->publicArea.type != TPM_ALG_SYMCIPHER) |
93 | | return TPM_RCS_KEY + RC_EncryptDecrypt_keyHandle; |
94 | | // The key must be unrestricted and allow the selected operation |
95 | | OK = IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted) |
96 | | if(YES == in->decrypt) |
97 | | OK = OK && IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt); |
98 | | else |
99 | | OK = OK && IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign); |
100 | | if(!OK) |
101 | | return TPM_RCS_ATTRIBUTES + RC_EncryptDecrypt_keyHandle; |
102 | | // If the key mode is not TPM_ALG_NULL... |
103 | | // or TPM_ALG_NULL |
104 | | if(mode != TPM_ALG_NULL) |
105 | | { |
106 | | // then the input mode has to be TPM_ALG_NULL or the same as the key |
107 | | if((in->mode != TPM_ALG_NULL) && (in->mode != mode)) |
108 | | return TPM_RCS_MODE + RC_EncryptDecrypt_mode; |
109 | | } |
110 | | else |
111 | | { |
112 | | // if the key mode is null, then the input can't be null |
113 | | if(in->mode == TPM_ALG_NULL) |
114 | | return TPM_RCS_MODE + RC_EncryptDecrypt_mode; |
115 | | mode = in->mode; |
116 | | } |
117 | | // The input iv for ECB mode should be an Empty Buffer. All the other modes |
118 | | // should have an iv size same as encryption block size |
119 | | keySize = symKey->publicArea.parameters.symDetail.sym.keyBits.sym; |
120 | | alg = symKey->publicArea.parameters.symDetail.sym.algorithm; |
121 | | blockSize = CryptGetSymmetricBlockSize(alg, keySize); |
122 | | // reverify the algorithm. This is mainly to keep static analysis tools happy |
123 | | if(blockSize == 0) |
124 | | return TPM_RCS_KEY + RC_EncryptDecrypt_keyHandle; |
125 | | // Note: When an algorithm is not supported by a TPM, the TPM_ALG_xxx for that |
126 | | // algorithm is not defined. However, it is assumed that the ALG_xxx_VALUE for |
127 | | // the algorithm is always defined. Both have the same numeric value. |
128 | | // ALG_xxx_VALUE is used here so that the code does not get cluttered with |
129 | | // #ifdef's. Having this check does not mean that the algorithm is supported. |
130 | | // If it was not supported the unmarshaling code would have rejected it before |
131 | | // this function were called. This means that, depending on the implementation, |
132 | | // the check could be redundant but it doesn't hurt. |
133 | | if(((mode == ALG_ECB_VALUE) && (in->ivIn.t.size != 0)) |
134 | | || ((mode != ALG_ECB_VALUE) && (in->ivIn.t.size != blockSize))) |
135 | | return TPM_RCS_SIZE + RC_EncryptDecrypt_ivIn; |
136 | | // The input data size of CBC mode or ECB mode must be an even multiple of |
137 | | // the symmetric algorithm's block size |
138 | | if(((mode == ALG_CBC_VALUE) || (mode == ALG_ECB_VALUE)) |
139 | | && ((in->inData.t.size % blockSize) != 0)) |
140 | | return TPM_RCS_SIZE + RC_EncryptDecrypt_inData; |
141 | | // Copy IV |
142 | | // Note: This is copied here so that the calls to the encrypt/decrypt functions |
143 | | // will modify the output buffer, not the input buffer |
144 | | out->ivOut = in->ivIn; |
145 | | // Command Output |
146 | | key = symKey->sensitive.sensitive.sym.t.buffer; |
147 | | // For symmetric encryption, the cipher data size is the same as plain data |
148 | | // size. |
149 | | out->outData.t.size = in->inData.t.size; |
150 | | if(in->decrypt == YES) |
151 | | { |
152 | | // Decrypt data to output |
153 | | result = CryptSymmetricDecrypt(out->outData.t.buffer, alg, keySize, key, |
154 | | &(out->ivOut), mode, in->inData.t.size, |
155 | | in->inData.t.buffer); |
156 | | } |
157 | | else |
158 | | { |
159 | | // Encrypt data to output |
160 | | result = CryptSymmetricEncrypt(out->outData.t.buffer, alg, keySize, key, |
161 | | &(out->ivOut), mode, in->inData.t.size, |
162 | | in->inData.t.buffer); |
163 | | } |
164 | | return result; |
165 | | #endif // CC_EncryptDecrypt2 |
166 | 0 | } |
167 | | #endif // CC_EncryptDecrypt |
168 | | #include "Tpm.h" |
169 | | #include "EncryptDecrypt2_fp.h" |
170 | | #include "EncryptDecrypt_spt_fp.h" |
171 | | #if CC_EncryptDecrypt2 // Conditional expansion of this file |
172 | | TPM_RC |
173 | | TPM2_EncryptDecrypt2( |
174 | | EncryptDecrypt2_In *in, // IN: input parameter list |
175 | | EncryptDecrypt2_Out *out // OUT: output parameter list |
176 | | ) |
177 | 0 | { |
178 | 0 | TPM_RC result; |
179 | | // EncryptDecyrptShared() performs the operations as shown in |
180 | | // TPM2_EncrypDecrypt |
181 | 0 | result = EncryptDecryptShared(in->keyHandle, in->decrypt, in->mode, |
182 | 0 | &in->ivIn, &in->inData, |
183 | 0 | (EncryptDecrypt_Out *)out); |
184 | | // Handle response code swizzle. |
185 | 0 | switch(result) |
186 | 0 | { |
187 | 0 | case TPM_RCS_MODE + RC_EncryptDecrypt_mode: |
188 | 0 | result = TPM_RCS_MODE + RC_EncryptDecrypt2_mode; |
189 | 0 | break; |
190 | 0 | case TPM_RCS_SIZE + RC_EncryptDecrypt_ivIn: |
191 | 0 | result = TPM_RCS_SIZE + RC_EncryptDecrypt2_ivIn; |
192 | 0 | break; |
193 | 0 | case TPM_RCS_SIZE + RC_EncryptDecrypt_inData: |
194 | 0 | result = TPM_RCS_SIZE + RC_EncryptDecrypt2_inData; |
195 | 0 | break; |
196 | 0 | default: |
197 | 0 | break; |
198 | 0 | } |
199 | 0 | return result; |
200 | 0 | } |
201 | | #endif // CC_EncryptDecrypt2 |
202 | | #include "Tpm.h" |
203 | | #include "Hash_fp.h" |
204 | | #if CC_Hash // Conditional expansion of this file |
205 | | TPM_RC |
206 | | TPM2_Hash( |
207 | | Hash_In *in, // IN: input parameter list |
208 | | Hash_Out *out // OUT: output parameter list |
209 | | ) |
210 | 0 | { |
211 | 0 | HASH_STATE hashState; |
212 | | // Command Output |
213 | | // Output hash |
214 | | // Start hash stack |
215 | 0 | out->outHash.t.size = CryptHashStart(&hashState, in->hashAlg); |
216 | | // Adding hash data |
217 | 0 | CryptDigestUpdate2B(&hashState, &in->data.b); |
218 | | // Complete hash |
219 | 0 | CryptHashEnd2B(&hashState, &out->outHash.b); |
220 | | // Output ticket |
221 | 0 | out->validation.tag = TPM_ST_HASHCHECK; |
222 | 0 | out->validation.hierarchy = in->hierarchy; |
223 | 0 | if(in->hierarchy == TPM_RH_NULL) |
224 | 0 | { |
225 | | // Ticket is not required |
226 | 0 | out->validation.hierarchy = TPM_RH_NULL; |
227 | 0 | out->validation.digest.t.size = 0; |
228 | 0 | } |
229 | 0 | else if(in->data.t.size >= sizeof(TPM_GENERATED) |
230 | 0 | && !TicketIsSafe(&in->data.b)) |
231 | 0 | { |
232 | | // Ticket is not safe |
233 | 0 | out->validation.hierarchy = TPM_RH_NULL; |
234 | 0 | out->validation.digest.t.size = 0; |
235 | 0 | } |
236 | 0 | else |
237 | 0 | { |
238 | | // Compute ticket |
239 | 0 | TicketComputeHashCheck(in->hierarchy, in->hashAlg, |
240 | 0 | &out->outHash, &out->validation); |
241 | 0 | } |
242 | 0 | return TPM_RC_SUCCESS; |
243 | 0 | } |
244 | | #endif // CC_Hash |
245 | | #include "Tpm.h" |
246 | | #include "HMAC_fp.h" |
247 | | #if CC_HMAC // Conditional expansion of this file |
248 | | TPM_RC |
249 | | TPM2_HMAC( |
250 | | HMAC_In *in, // IN: input parameter list |
251 | | HMAC_Out *out // OUT: output parameter list |
252 | | ) |
253 | | { |
254 | | HMAC_STATE hmacState; |
255 | | OBJECT *hmacObject; |
256 | | TPMI_ALG_HASH hashAlg; |
257 | | TPMT_PUBLIC *publicArea; |
258 | | // Input Validation |
259 | | // Get HMAC key object and public area pointers |
260 | | hmacObject = HandleToObject(in->handle); |
261 | | publicArea = &hmacObject->publicArea; |
262 | | // Make sure that the key is an HMAC key |
263 | | if(publicArea->type != TPM_ALG_KEYEDHASH) |
264 | | return TPM_RCS_TYPE + RC_HMAC_handle; |
265 | | // and that it is unrestricted |
266 | | if (IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)) |
267 | | return TPM_RCS_ATTRIBUTES + RC_HMAC_handle; |
268 | | // and that it is a signing key |
269 | | if (!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)) |
270 | | return TPM_RCS_KEY + RC_HMAC_handle; |
271 | | // See if the key has a default |
272 | | if(publicArea->parameters.keyedHashDetail.scheme.scheme == TPM_ALG_NULL) |
273 | | // it doesn't so use the input value |
274 | | hashAlg = in->hashAlg; |
275 | | else |
276 | | { |
277 | | // key has a default so use it |
278 | | hashAlg |
279 | | = publicArea->parameters.keyedHashDetail.scheme.details.hmac.hashAlg; |
280 | | // and verify that the input was either the TPM_ALG_NULL or the default |
281 | | if(in->hashAlg != TPM_ALG_NULL && in->hashAlg != hashAlg) |
282 | | hashAlg = TPM_ALG_NULL; |
283 | | } |
284 | | // if we ended up without a hash algorithm then return an error |
285 | | if(hashAlg == TPM_ALG_NULL) |
286 | | return TPM_RCS_VALUE + RC_HMAC_hashAlg; |
287 | | // Command Output |
288 | | // Start HMAC stack |
289 | | out->outHMAC.t.size = CryptHmacStart2B(&hmacState, hashAlg, |
290 | | &hmacObject->sensitive.sensitive.bits.b); |
291 | | // Adding HMAC data |
292 | | CryptDigestUpdate2B(&hmacState.hashState, &in->buffer.b); |
293 | | // Complete HMAC |
294 | | CryptHmacEnd2B(&hmacState, &out->outHMAC.b); |
295 | | return TPM_RC_SUCCESS; |
296 | | } |
297 | | #endif // CC_HMAC |
298 | | |
299 | | #include "Tpm.h" |
300 | | #include "MAC_fp.h" |
301 | | #if CC_MAC // Conditional expansion of this file |
302 | | /* Error Returns Meaning */ |
303 | | /* TPM_RC_ATTRIBUTES key referenced by handle is a restricted key */ |
304 | | /* TPM_RC_KEY handle does not reference a signing key */ |
305 | | /* TPM_RC_TYPE key referenced by handle is not an HMAC key */ |
306 | | /* TPM_RC_VALUE hashAlg is not compatible with the hash algorithm of the scheme of the object |
307 | | referenced by handle */ |
308 | | TPM_RC |
309 | | TPM2_MAC( |
310 | | MAC_In *in, // IN: input parameter list |
311 | | MAC_Out *out // OUT: output parameter list |
312 | | ) |
313 | 0 | { |
314 | 0 | OBJECT *keyObject; |
315 | 0 | HMAC_STATE state; |
316 | 0 | TPMT_PUBLIC *publicArea; |
317 | 0 | TPM_RC result; |
318 | | // Input Validation |
319 | | // Get MAC key object and public area pointers |
320 | 0 | keyObject = HandleToObject(in->handle); |
321 | 0 | publicArea = &keyObject->publicArea; |
322 | | // If the key is not able to do a MAC, indicate that the handle selects an |
323 | | // object that can't do a MAC |
324 | 0 | result = CryptSelectMac(publicArea, &in->inScheme); |
325 | 0 | if(result == TPM_RCS_TYPE) |
326 | 0 | return TPM_RCS_TYPE + RC_MAC_handle; |
327 | | // If there is another error type, indicate that the scheme and key are not |
328 | | // compatible |
329 | 0 | if(result != TPM_RC_SUCCESS) |
330 | 0 | return RcSafeAddToResult(result, RC_MAC_inScheme); |
331 | | // Make sure that the key is not restricted |
332 | 0 | if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)) |
333 | 0 | return TPM_RCS_ATTRIBUTES + RC_MAC_handle; |
334 | | // and that it is a signing key |
335 | 0 | if(!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)) |
336 | 0 | return TPM_RCS_KEY + RC_MAC_handle; |
337 | | // Command Output |
338 | 0 | out->outMAC.t.size = CryptMacStart(&state, &publicArea->parameters, |
339 | 0 | in->inScheme, |
340 | 0 | &keyObject->sensitive.sensitive.any.b); |
341 | | // If the mac can't start, treat it as a fatal error |
342 | 0 | if(out->outMAC.t.size == 0) |
343 | 0 | return TPM_RC_FAILURE; |
344 | 0 | CryptDigestUpdate2B(&state.hashState, &in->buffer.b); |
345 | | // If the MAC result is not what was expected, it is a fatal error |
346 | 0 | if(CryptHmacEnd2B(&state, &out->outMAC.b) != out->outMAC.t.size) |
347 | 0 | return TPM_RC_FAILURE; |
348 | 0 | return TPM_RC_SUCCESS; |
349 | 0 | } |
350 | | #endif // CC_MAC |