1
2 /*
3 * Licensed Materials - Property of IBM
4 *
5 * trousers - An open source TCG Software Stack
6 *
7 * (C) Copyright International Business Machines Corp. 2007
8 *
9 */
10
11
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15
16 #include "trousers/tss.h"
17 #include "trousers_types.h"
18 #include "tcs_tsp.h"
19 #include "tcs_utils.h"
20 #include "tcs_int_literals.h"
21 #include "capabilities.h"
22 #include "tcslog.h"
23 #include "tcsps.h"
24 #include "req_mgr.h"
25
26
27 TSS_RESULT
TCSP_EstablishTransport_Internal(TCS_CONTEXT_HANDLE hContext,UINT32 ulTransControlFlags,TCS_KEY_HANDLE hEncKey,UINT32 ulTransSessionInfoSize,BYTE * rgbTransSessionInfo,UINT32 ulSecretSize,BYTE * rgbSecret,TPM_AUTH * pEncKeyAuth,TPM_MODIFIER_INDICATOR * pbLocality,TCS_HANDLE * hTransSession,UINT32 * ulCurrentTicks,BYTE ** prgbCurrentTicks,TPM_NONCE * pTransNonce)28 TCSP_EstablishTransport_Internal(TCS_CONTEXT_HANDLE hContext,
29 UINT32 ulTransControlFlags,
30 TCS_KEY_HANDLE hEncKey,
31 UINT32 ulTransSessionInfoSize,
32 BYTE* rgbTransSessionInfo,
33 UINT32 ulSecretSize,
34 BYTE* rgbSecret,
35 TPM_AUTH* pEncKeyAuth,
36 TPM_MODIFIER_INDICATOR* pbLocality,
37 TCS_HANDLE* hTransSession,
38 UINT32* ulCurrentTicks,
39 BYTE** prgbCurrentTicks,
40 TPM_NONCE* pTransNonce)
41 {
42 TSS_RESULT result;
43 UINT32 paramSize;
44 UINT64 offset;
45 TPM_KEY_HANDLE keySlot = TPM_KH_TRANSPORT;
46 BYTE txBlob[TSS_TPM_TXBLOB_SIZE];
47
48 if ((result = ctx_verify_context(hContext)))
49 return result;
50
51 if (ulTransControlFlags == TSS_TCSATTRIB_TRANSPORT_EXCLUSIVE) {
52 if ((result = ctx_req_exclusive_transport(hContext)))
53 return result;
54 }
55
56 if (pEncKeyAuth) {
57 if ((result = auth_mgr_check(hContext, &pEncKeyAuth->AuthHandle)))
58 return result;
59 }
60
61 /* if hEncKey is set to TPM_KH_TRANSPORT, that's the signal to the TPM that this will be
62 * an unencrypted transport session, so we don't need to check that its loaded */
63 if (hEncKey != TPM_KH_TRANSPORT) {
64 if ((result = ensureKeyIsLoaded(hContext, hEncKey, &keySlot)))
65 return result;
66 }
67
68 offset = TSS_TPM_TXBLOB_HDR_LEN;
69 LoadBlob_UINT32(&offset, keySlot, txBlob);
70 LoadBlob(&offset, ulTransSessionInfoSize, txBlob, rgbTransSessionInfo);
71 LoadBlob_UINT32(&offset, ulSecretSize, txBlob);
72 LoadBlob(&offset, ulSecretSize, txBlob, rgbSecret);
73 if (pEncKeyAuth) {
74 LoadBlob_Auth(&offset, txBlob, pEncKeyAuth);
75 LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, offset, TPM_ORD_EstablishTransport,
76 txBlob);
77 } else
78 LoadBlob_Header(TPM_TAG_RQU_COMMAND, offset, TPM_ORD_EstablishTransport, txBlob);
79
80 if ((result = req_mgr_submit_req(txBlob)))
81 goto done;
82
83 if ((result = UnloadBlob_Header(txBlob, ¶mSize))) {
84 LogDebugFn("UnloadBlob_Header failed: rc=0x%x", result);
85 goto done;
86 }
87
88 offset = TSS_TPM_TXBLOB_HDR_LEN;
89 UnloadBlob_UINT32(&offset, hTransSession, txBlob);
90 UnloadBlob_UINT32(&offset, pbLocality, txBlob);
91
92 *ulCurrentTicks = sizeof(TPM_STRUCTURE_TAG)
93 + sizeof(UINT64)
94 + sizeof(UINT16)
95 + sizeof(TPM_NONCE);
96
97 *prgbCurrentTicks = malloc(*ulCurrentTicks);
98 if (*prgbCurrentTicks == NULL) {
99 result = TCSERR(TSS_E_OUTOFMEMORY);
100 goto done;
101 }
102
103 UnloadBlob(&offset, *ulCurrentTicks, txBlob, *prgbCurrentTicks);
104 UnloadBlob(&offset, sizeof(TPM_NONCE), txBlob, (BYTE *)pTransNonce);
105 if (pEncKeyAuth)
106 UnloadBlob_Auth(&offset, txBlob, pEncKeyAuth);
107
108 ctx_set_transport_enabled(hContext, *hTransSession);
109 done:
110 auth_mgr_release_auth(pEncKeyAuth, NULL, hContext);
111 return result;
112 }
113
114 TSS_RESULT
TCSP_ExecuteTransport_Internal(TCS_CONTEXT_HANDLE hContext,TPM_COMMAND_CODE unWrappedCommandOrdinal,UINT32 ulWrappedCmdParamInSize,BYTE * rgbWrappedCmdParamIn,UINT32 * pulHandleListSize,TCS_HANDLE ** rghHandles,TPM_AUTH * pWrappedCmdAuth1,TPM_AUTH * pWrappedCmdAuth2,TPM_AUTH * pTransAuth,UINT64 * punCurrentTicks,TPM_MODIFIER_INDICATOR * pbLocality,TPM_RESULT * pulWrappedCmdReturnCode,UINT32 * ulWrappedCmdParamOutSize,BYTE ** rgbWrappedCmdParamOut)115 TCSP_ExecuteTransport_Internal(TCS_CONTEXT_HANDLE hContext,
116 TPM_COMMAND_CODE unWrappedCommandOrdinal,
117 UINT32 ulWrappedCmdParamInSize,
118 BYTE* rgbWrappedCmdParamIn,
119 UINT32* pulHandleListSize, /* in, out */
120 TCS_HANDLE** rghHandles, /* in, out */
121 TPM_AUTH* pWrappedCmdAuth1, /* in, out */
122 TPM_AUTH* pWrappedCmdAuth2, /* in, out */
123 TPM_AUTH* pTransAuth, /* in, out */
124 UINT64* punCurrentTicks,
125 TPM_MODIFIER_INDICATOR* pbLocality,
126 TPM_RESULT* pulWrappedCmdReturnCode,
127 UINT32* ulWrappedCmdParamOutSize,
128 BYTE** rgbWrappedCmdParamOut)
129 {
130 TSS_RESULT result;
131 UINT32 paramSize, wrappedSize, val1 = 0, val2 = 0, *pVal1 = NULL, *pVal2 = NULL;
132 TCS_HANDLE handle1 = 0, handle2 = 0;
133 UINT64 offset, wrappedOffset = 0;
134 BYTE txBlob[TSS_TPM_TXBLOB_SIZE];
135
136
137 if (*pulHandleListSize > 2) {
138 LogDebugFn("************ EXPAND KEYSLOT SIZE *********");
139 return TCSERR(TSS_E_INTERNAL_ERROR);
140 }
141
142 if ((result = ctx_verify_context(hContext)))
143 return result;
144
145 if (pWrappedCmdAuth1)
146 if ((result = auth_mgr_check(hContext, &pWrappedCmdAuth1->AuthHandle)))
147 goto done;
148
149 if (pWrappedCmdAuth2)
150 if ((result = auth_mgr_check(hContext, &pWrappedCmdAuth2->AuthHandle)))
151 goto done;
152
153 switch (unWrappedCommandOrdinal) {
154 /* If the command is FlushSpecific, we get handle that needs to be freed, but we don't know
155 * what type it is. */
156 case TPM_ORD_FlushSpecific:
157 if (*pulHandleListSize == 0) { /* invalid */
158 result = TCSERR(TSS_E_BAD_PARAMETER);
159 goto done;
160 }
161
162 /* If this is a transport handle, remove the context's reference to the session */
163 ctx_set_transport_disabled(hContext, rghHandles[0]);
164
165 /* Is it a key? If so, jump to the get_slot_lite and key management calls below */
166 if (ctx_has_key_loaded(hContext, *rghHandles[0]))
167 goto map_key_handles;
168
169 /* fall through */
170 case TPM_ORD_Terminate_Handle:
171 if (!auth_mgr_check(hContext, rghHandles[0]))
172 auth_mgr_release_auth_handle(*rghHandles[0], hContext, FALSE);
173
174 /* If the handle is an auth handle or any other kind of handle, there's no
175 * mapping done in the TCS, so pass its value straight to the TPM and jump over
176 * the switch statement below where we assume FLushSpecific is being done on a
177 * key */
178 handle1 = val1 = *rghHandles[0];
179 pVal1 = &val1;
180
181 goto build_command;
182 default:
183 break;
184 }
185
186 map_key_handles:
187 if (*pulHandleListSize == 2) {
188 handle2 = (*rghHandles)[1];
189
190 if ((result = get_slot_lite(hContext, handle2, &val2))) {
191 *pulHandleListSize = 0;
192 goto done;
193 }
194
195 pVal2 = &val2;
196 }
197
198 if (*pulHandleListSize >= 1) {
199 handle1 = *rghHandles[0];
200
201 *pulHandleListSize = 0;
202
203 if ((result = get_slot_lite(hContext, handle1, &val1)))
204 goto done;
205
206 pVal1 = &val1;
207 }
208
209 switch (unWrappedCommandOrdinal) {
210 case TPM_ORD_EvictKey:
211 case TPM_ORD_FlushSpecific:
212 {
213 if ((result = ctx_remove_key_loaded(hContext, handle1)))
214 goto done;
215
216 if ((result = key_mgr_dec_ref_count(handle1)))
217 goto done;
218
219 /* we can't call key_mgr_ref_cnt() here since it calls TPM_EvictKey directly */
220 mc_set_slot_by_handle(handle1, NULL_TPM_HANDLE);
221 break;
222 }
223 case TPM_ORD_OIAP:
224 {
225 /* are the maximum number of auth sessions open? */
226 if (auth_mgr_req_new(hContext) == FALSE) {
227 if ((result = auth_mgr_swap_out(hContext)))
228 goto done;
229 }
230
231 break;
232 }
233 case TPM_ORD_OSAP:
234 {
235 UINT16 entityType;
236 UINT32 entityValue, newEntValue;
237
238 /* are the maximum number of auth sessions open? */
239 if (auth_mgr_req_new(hContext) == FALSE) {
240 if ((result = auth_mgr_swap_out(hContext)))
241 goto done;
242 }
243
244 offset = 0;
245 UnloadBlob_UINT16(&offset, &entityType, rgbWrappedCmdParamIn);
246 UnloadBlob_UINT32(&offset, &entityValue, rgbWrappedCmdParamIn);
247
248 if (entityType == TCPA_ET_KEYHANDLE || entityType == TCPA_ET_KEY) {
249 if (ensureKeyIsLoaded(hContext, entityValue, &newEntValue))
250 return TCSERR(TSS_E_KEY_NOT_LOADED);
251
252 /* OSAP is never encrypted in a transport session, so changing
253 * rgbWrappedCmdParamIn is ok here */
254 offset = sizeof(UINT16);
255 LoadBlob_UINT32(&offset, newEntValue, rgbWrappedCmdParamIn);
256 }
257
258 break;
259 }
260 case TPM_ORD_DSAP:
261 {
262 UINT16 entityType;
263 UINT32 keyHandle, tpmKeyHandle;
264
265 /* are the maximum number of auth sessions open? */
266 if (auth_mgr_req_new(hContext) == FALSE) {
267 if ((result = auth_mgr_swap_out(hContext)))
268 goto done;
269 }
270
271 offset = 0;
272 UnloadBlob_UINT16(&offset, &entityType, rgbWrappedCmdParamIn);
273 UnloadBlob_UINT32(&offset, &keyHandle, rgbWrappedCmdParamIn);
274
275 if (ensureKeyIsLoaded(hContext, keyHandle, &tpmKeyHandle)) {
276 result = TCSERR(TSS_E_KEY_NOT_LOADED);
277 goto done;
278 }
279
280 /* DSAP's only encrypted paramter is entityValue, so replacing keyHandle inside
281 * rgbWrappedCmdParamIn is ok */
282 offset = sizeof(UINT16);
283 LoadBlob_UINT32(&offset, tpmKeyHandle, rgbWrappedCmdParamIn);
284 }
285 default:
286 break;
287 }
288
289 build_command:
290 if ((result = tpm_rqu_build(TPM_ORD_ExecuteTransport, &wrappedOffset,
291 &txBlob[TSS_TXBLOB_WRAPPEDCMD_OFFSET], unWrappedCommandOrdinal,
292 pVal1, pVal2, ulWrappedCmdParamInSize, rgbWrappedCmdParamIn,
293 pWrappedCmdAuth1, pWrappedCmdAuth2)))
294 goto done;
295
296 /* The blob we'll load here looks like this:
297 *
298 * |TAGet|LENet|ORDet|wrappedCmdSize|wrappedCmd|AUTHet|
299 *
300 * wrappedCmd looks like this:
301 *
302 * |TAGw|LENw|ORDw|HANDLESw|DATAw|AUTH1w|AUTH2w|
303 *
304 * w = wrapped command info
305 * et = execute transport command info
306 *
307 * Note that the wrapped command was loaded into the blob by the tpm_rqu_build call
308 * above.
309 *
310 */
311 offset = TSS_TPM_TXBLOB_HDR_LEN;
312 /* Load wrapped command size: |wrappedCmdSize| */
313 LoadBlob_UINT32(&offset, wrappedOffset, txBlob);
314
315 /* offset + wrappedOffset is the position of the execute transport auth struct */
316 offset += wrappedOffset;
317
318 if (pTransAuth) {
319 /* Load the auth for the execute transport command: |AUTHet| */
320 LoadBlob_Auth(&offset, txBlob, pTransAuth);
321 /* Load the outer header: |TAGet|LENet|ORDet| */
322 LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, offset, TPM_ORD_ExecuteTransport,
323 txBlob);
324 } else {
325 /* Load the outer header: |TAGet|LENet|ORDet| */
326 LoadBlob_Header(TPM_TAG_RQU_COMMAND, offset, TPM_ORD_ExecuteTransport, txBlob);
327 }
328
329 if ((result = req_mgr_submit_req(txBlob)))
330 goto done;
331
332 /* Unload the Execute Transport (outer) header */
333 if ((result = UnloadBlob_Header(txBlob, ¶mSize))) {
334 LogDebugFn("UnloadBlob_Header failed: rc=0x%x", result);
335 goto done;
336 }
337
338 /* The response from the TPM looks like this:
339 *
340 * |TAGet|LENet|RCet|currentTicks|locality|wrappedRspSize|wrappedRsp|AUTHet|
341 *
342 * and wrappedRsp looks like:
343 *
344 * |TAGw|LENw|RCw|HANDLESw|DATAw|AUTH1w|AUTH2w|
345 */
346
347 offset = TSS_TPM_TXBLOB_HDR_LEN;
348 UnloadBlob_UINT64(&offset, punCurrentTicks, txBlob);
349 UnloadBlob_UINT32(&offset, pbLocality, txBlob);
350
351 /* Unload the wrapped response size: |wrappedRspSize| */
352 UnloadBlob_UINT32(&offset, &wrappedSize, txBlob);
353
354 /* We've parsed right up to wrappedRsp, so save off this offset for later */
355 wrappedOffset = offset;
356
357 /* The current offset + the response size will be the offset of |AUTHet| */
358 offset += wrappedSize;
359 if (pTransAuth)
360 UnloadBlob_Auth(&offset, txBlob, pTransAuth);
361
362 /* Now parse through the returned response @ wrappedOffset */
363 if ((result = UnloadBlob_Header(&txBlob[wrappedOffset], ¶mSize))) {
364 LogDebugFn("Wrapped command (Ordinal 0x%x) failed: rc=0x%x",
365 unWrappedCommandOrdinal, result);
366
367 /* This is the result of the wrapped command. If its not success, return its value
368 * in the pulWrappedCmdReturnCode variable and return indicating that the execute
369 * transport command was successful */
370 *pulWrappedCmdReturnCode = result;
371 *ulWrappedCmdParamOutSize = 0;
372 *rgbWrappedCmdParamOut = NULL;
373 auth_mgr_release_auth(pWrappedCmdAuth1, pWrappedCmdAuth2, hContext);
374
375 return TSS_SUCCESS;
376 }
377
378 *pulWrappedCmdReturnCode = TSS_SUCCESS;
379
380 pVal1 = pVal2 = NULL;
381 switch (unWrappedCommandOrdinal) {
382 /* The commands below have 1 outgoing handle */
383 case TPM_ORD_LoadKey2:
384 pVal1 = &val1;
385 break;
386 default:
387 break;
388 }
389
390 result = tpm_rsp_parse(TPM_ORD_ExecuteTransport, &txBlob[wrappedOffset], paramSize,
391 pVal1, pVal2, ulWrappedCmdParamOutSize, rgbWrappedCmdParamOut,
392 pWrappedCmdAuth1, pWrappedCmdAuth2);
393
394 offset = 0;
395 switch (unWrappedCommandOrdinal) {
396 case TPM_ORD_LoadKey2:
397 {
398 TCS_KEY_HANDLE tcs_handle = NULL_TCS_HANDLE;
399
400 if ((result = load_key_final(hContext, handle1, &tcs_handle, NULL, val1)))
401 goto done;
402
403 *rghHandles[0] = tcs_handle;
404 *pulHandleListSize = 1;
405 break;
406 }
407 case TPM_ORD_DSAP:
408 case TPM_ORD_OSAP:
409 case TPM_ORD_OIAP:
410 {
411 UINT32 handle;
412
413 UnloadBlob_UINT32(&offset, &handle, *rgbWrappedCmdParamOut);
414 result = auth_mgr_add(hContext, handle);
415 break;
416 }
417 default:
418 break;
419 }
420
421 done:
422 auth_mgr_release_auth(pWrappedCmdAuth1, pWrappedCmdAuth2, hContext);
423 return result;
424 }
425
426 TSS_RESULT
TCSP_ReleaseTransportSigned_Internal(TCS_CONTEXT_HANDLE hContext,TCS_KEY_HANDLE hSignatureKey,TPM_NONCE * AntiReplayNonce,TPM_AUTH * pKeyAuth,TPM_AUTH * pTransAuth,TPM_MODIFIER_INDICATOR * pbLocality,UINT32 * pulCurrentTicksSize,BYTE ** prgbCurrentTicks,UINT32 * pulSignatureSize,BYTE ** prgbSignature)427 TCSP_ReleaseTransportSigned_Internal(TCS_CONTEXT_HANDLE hContext,
428 TCS_KEY_HANDLE hSignatureKey,
429 TPM_NONCE* AntiReplayNonce,
430 TPM_AUTH* pKeyAuth, /* in, out */
431 TPM_AUTH* pTransAuth, /* in, out */
432 TPM_MODIFIER_INDICATOR* pbLocality,
433 UINT32* pulCurrentTicksSize,
434 BYTE** prgbCurrentTicks,
435 UINT32* pulSignatureSize,
436 BYTE** prgbSignature)
437 {
438 TSS_RESULT result;
439 UINT32 paramSize;
440 UINT64 offset;
441 TPM_KEY_HANDLE keySlot;
442 BYTE txBlob[TSS_TPM_TXBLOB_SIZE];
443
444 if ((result = ctx_verify_context(hContext)))
445 return result;
446
447 if (pKeyAuth) {
448 if ((result = auth_mgr_check(hContext, &pKeyAuth->AuthHandle)))
449 return result;
450 }
451
452 if ((result = ensureKeyIsLoaded(hContext, hSignatureKey, &keySlot)))
453 return result;
454
455 offset = TSS_TPM_TXBLOB_HDR_LEN;
456 LoadBlob_UINT32(&offset, keySlot, txBlob);
457 LoadBlob(&offset, sizeof(TPM_NONCE), txBlob, (BYTE *)AntiReplayNonce);
458 if (pKeyAuth) {
459 LoadBlob_Auth(&offset, txBlob, pKeyAuth);
460 LoadBlob_Auth(&offset, txBlob, pTransAuth);
461 LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, offset, TPM_ORD_ReleaseTransportSigned,
462 txBlob);
463 } else {
464 LoadBlob_Auth(&offset, txBlob, pTransAuth);
465 LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, offset, TPM_ORD_ReleaseTransportSigned,
466 txBlob);
467 }
468
469 if ((result = req_mgr_submit_req(txBlob)))
470 goto done;
471
472 if ((result = UnloadBlob_Header(txBlob, ¶mSize))) {
473 LogDebugFn("UnloadBlob_Header failed: rc=0x%x", result);
474 goto done;
475 }
476
477 /* unconditionally disable our accounting of the session */
478 ctx_set_transport_disabled(hContext, NULL);
479
480 offset = TSS_TPM_TXBLOB_HDR_LEN;
481 UnloadBlob_UINT32(&offset, pbLocality, txBlob);
482
483 *pulCurrentTicksSize = sizeof(TPM_STRUCTURE_TAG)
484 + sizeof(UINT64)
485 + sizeof(UINT16)
486 + sizeof(TPM_NONCE);
487
488 *prgbCurrentTicks = malloc(*pulCurrentTicksSize);
489 if (*prgbCurrentTicks == NULL) {
490 result = TCSERR(TSS_E_OUTOFMEMORY);
491 goto done;
492 }
493
494 UnloadBlob(&offset, *pulCurrentTicksSize, txBlob, *prgbCurrentTicks);
495 UnloadBlob_UINT32(&offset, pulSignatureSize, txBlob);
496
497 *prgbSignature = malloc(*pulSignatureSize);
498 if (*prgbSignature == NULL) {
499 free(*prgbCurrentTicks);
500 result = TCSERR(TSS_E_OUTOFMEMORY);
501 goto done;
502 }
503
504 UnloadBlob(&offset, *pulSignatureSize, txBlob, *prgbSignature);
505
506 if (pKeyAuth)
507 UnloadBlob_Auth(&offset, txBlob, pKeyAuth);
508 UnloadBlob_Auth(&offset, txBlob, pTransAuth);
509
510 done:
511 auth_mgr_release_auth(pKeyAuth, NULL, hContext);
512 return result;
513 }
514