1 /* Software-based Trusted Platform Module (TPM) Emulator
2 * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>
3 *
4 * This module is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
8 *
9 * This module is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * $Id: tpm_transport.c 367 2010-02-13 15:52:18Z mast $
15 */
16
17 /*
18 * Thanks go to Edison Su (<sudison@gmail.com>) for providing
19 * the initial Transport Session patch.
20 */
21
22 #include "tpm_emulator.h"
23 #include "tpm_commands.h"
24 #include "tpm_handles.h"
25 #include "tpm_marshalling.h"
26 #include "tpm_data.h"
27 #include "crypto/rsa.h"
28 #include "crypto/sha1.h"
29
30 /*
31 * Transport Sessions ([TPM_Part3], Section 24)
32 */
33
debug_buf(const char * str,uint8_t * buf,size_t buf_len)34 static void debug_buf(const char *str, uint8_t *buf, size_t buf_len)
35 {
36 static char map[] = "0123456789abcdef";
37 char hex[buf_len * 3];
38 size_t i;
39 for (i = 0; i < buf_len; i++) {
40 hex[i*3 + 0] = map[buf[i] >> 4];
41 hex[i*3 + 1] = map[buf[i] & 0x0f];
42 hex[i*3 + 2] = ' ';
43 }
44 hex[sizeof(hex) - 1] = 0;
45 debug("%s%s", str, hex);
46 }
47
decrypt_transport_auth(TPM_KEY_DATA * key,BYTE * enc,UINT32 enc_size,TPM_TRANSPORT_AUTH * trans_auth)48 static int decrypt_transport_auth(TPM_KEY_DATA *key, BYTE *enc, UINT32 enc_size,
49 TPM_TRANSPORT_AUTH *trans_auth)
50 {
51 BYTE *buf;
52 size_t buf_size;
53 int scheme;
54 switch (key->encScheme) {
55 case TPM_ES_RSAESOAEP_SHA1_MGF1: scheme = RSA_ES_OAEP_SHA1; break;
56 case TPM_ES_RSAESPKCSv15: scheme = RSA_ES_PKCSV15; break;
57 default: return -1;
58 }
59 buf = tpm_malloc(key->key.size);
60 if (buf == NULL
61 || tpm_rsa_decrypt(&key->key, scheme, enc, enc_size, buf, &buf_size)
62 || buf_size != sizeof_TPM_TRANSPORT_AUTH(x)
63 || (((UINT16)buf[0] << 8) | buf[1]) != TPM_TAG_TRANSPORT_AUTH) {
64 tpm_free(buf);
65 return -1;
66 }
67 trans_auth->tag = TPM_TAG_TRANSPORT_AUTH;
68 memcpy(trans_auth->authData, &buf[2], sizeof(TPM_AUTHDATA));
69 tpm_free(buf);
70 return 0;
71 }
72
transport_log_in(BYTE * params,BYTE * pubKeyHash,TPM_DIGEST * transDigest)73 static void transport_log_in(BYTE *params, BYTE *pubKeyHash,
74 TPM_DIGEST *transDigest)
75 {
76 BYTE *ptr, buf[sizeof_TPM_TRANSPORT_LOG_IN(x)];
77 UINT32 len;
78 tpm_sha1_ctx_t sha1;
79
80 ptr = buf; len = sizeof(buf);
81 tpm_marshal_TPM_TAG(&ptr, &len, TPM_TAG_TRANSPORT_LOG_IN);
82 tpm_marshal_BLOB(&ptr, &len, params, SHA1_DIGEST_LENGTH);
83 tpm_marshal_BLOB(&ptr, &len, pubKeyHash, SHA1_DIGEST_LENGTH);
84 tpm_sha1_init(&sha1);
85 tpm_sha1_update(&sha1, transDigest->digest, sizeof(transDigest->digest));
86 tpm_sha1_update(&sha1, buf, sizeof(buf));
87 tpm_sha1_final(&sha1, transDigest->digest);
88 debug_buf("LogIn: transDigest: ", transDigest->digest, sizeof(transDigest->digest));
89 }
90
transport_log_out(BYTE * params,TPM_DIGEST * transDigest)91 static void transport_log_out(BYTE *params, TPM_DIGEST *transDigest)
92 {
93 BYTE *ptr, buf[sizeof_TPM_TRANSPORT_LOG_OUT(x)];
94 UINT32 len;
95 tpm_sha1_ctx_t sha1;
96
97 ptr = buf; len = sizeof(buf);
98 tpm_marshal_TPM_TAG(&ptr, &len, TPM_TAG_TRANSPORT_LOG_OUT);
99 tpm_marshal_TPM_CURRENT_TICKS(&ptr, &len, &tpmData.stany.data.currentTicks);
100 tpm_marshal_BLOB(&ptr, &len, params, SHA1_DIGEST_LENGTH);
101 tpm_marshal_TPM_MODIFIER_INDICATOR(&ptr, &len, tpmData.stany.flags.localityModifier);
102 tpm_sha1_init(&sha1);
103 tpm_sha1_update(&sha1, transDigest->digest, sizeof(transDigest->digest));
104 tpm_sha1_update(&sha1, buf, sizeof(buf));
105 tpm_sha1_final(&sha1, transDigest->digest);
106 debug_buf("LogOut: transDigest: ", transDigest->digest, sizeof(transDigest->digest));
107 }
108
TPM_EstablishTransport(TPM_KEY_HANDLE encHandle,TPM_TRANSPORT_PUBLIC * transPublic,UINT32 secretSize,BYTE * secret,TPM_AUTH * auth1,TPM_TRANSHANDLE * transHandle,TPM_MODIFIER_INDICATOR * locality,TPM_CURRENT_TICKS * currentTicks,TPM_NONCE * transNonceEven)109 TPM_RESULT TPM_EstablishTransport(TPM_KEY_HANDLE encHandle,
110 TPM_TRANSPORT_PUBLIC *transPublic,
111 UINT32 secretSize, BYTE *secret,
112 TPM_AUTH *auth1,
113 TPM_TRANSHANDLE *transHandle,
114 TPM_MODIFIER_INDICATOR *locality,
115 TPM_CURRENT_TICKS *currentTicks,
116 TPM_NONCE *transNonceEven)
117 {
118 TPM_RESULT res;
119 TPM_KEY_DATA *key;
120 TPM_TRANSPORT_AUTH trans_auth;
121 TPM_SESSION_DATA *session;
122
123 info("TPM_EstablishTransport()");
124 /* setup authorization data */
125 if (encHandle == TPM_KH_TRANSPORT) {
126 if (auth1->authHandle != TPM_INVALID_HANDLE) return TPM_BADTAG;
127 if (transPublic->transAttributes & TPM_TRANSPORT_ENCRYPT) return TPM_BAD_SCHEME;
128 if (secretSize != 20) return TPM_BAD_PARAM_SIZE;
129 memcpy(trans_auth.authData, secret, 20);
130 } else {
131 /* get key and verify its usage */
132 key = tpm_get_key(encHandle);
133 if (key == NULL) return TPM_INVALID_KEYHANDLE;
134 if (key->keyUsage != TPM_KEY_STORAGE && key->keyUsage != TPM_KEY_LEGACY)
135 return TPM_INVALID_KEYUSAGE;
136 /* verify authorization */
137 if (key->authDataUsage != TPM_AUTH_NEVER) {
138 res = tpm_verify_auth(auth1, key->usageAuth, encHandle);
139 if (res != TPM_SUCCESS) return res;
140 if (decrypt_transport_auth(key, secret, secretSize, &trans_auth))
141 return TPM_DECRYPT_ERROR;
142 }
143 }
144 /* check whether the transport has to be encrypted */
145 if (transPublic->transAttributes & TPM_TRANSPORT_ENCRYPT) {
146 if (tpmData.permanent.flags.FIPS
147 && transPublic->algID == TPM_ALG_MGF1) return TPM_INAPPROPRIATE_ENC;
148 /* until now, only MGF1 is supported */
149 if (transPublic->algID != TPM_ALG_MGF1) return TPM_BAD_KEY_PROPERTY;
150 }
151 /* initialize transport session */
152 tpm_get_random_bytes(transNonceEven->nonce, sizeof(transNonceEven->nonce));
153 *transHandle = tpm_get_free_session(TPM_ST_TRANSPORT);
154 session = tpm_get_transport(*transHandle);
155 if (session == NULL) return TPM_RESOURCES;
156 session->transInternal.transHandle = *transHandle;
157 memset(&session->transInternal.transDigest, 0, sizeof(TPM_DIGEST));
158 memcpy(&session->transInternal.transPublic, transPublic,
159 sizeof_TPM_TRANSPORT_PUBLIC((*transPublic)));
160 memcpy(&session->transInternal.transNonceEven, transNonceEven, sizeof(TPM_NONCE));
161 memcpy(&session->nonceEven, transNonceEven, sizeof(TPM_NONCE));
162 memcpy(&session->transInternal.authData, trans_auth.authData, sizeof(TPM_AUTHDATA));
163 *locality = tpmData.stany.flags.localityModifier;
164 memcpy(currentTicks, &tpmData.stany.data.currentTicks, sizeof(TPM_CURRENT_TICKS));
165 /* perform transport logging */
166 if (transPublic->transAttributes & TPM_TRANSPORT_LOG) {
167 tpm_sha1_ctx_t sha1;
168 BYTE *ptr, buf[4 + 4 + 4 + sizeof_TPM_CURRENT_TICKS(x) + 20];
169 UINT32 len;
170 /* log input */
171 memset(buf, 0, sizeof(buf));
172 transport_log_in(auth1->digest, buf, &session->transInternal.transDigest);
173 /* compute digest of output parameters and log output */
174 ptr = buf; len = sizeof(buf);
175 tpm_marshal_UINT32(&ptr, &len, TPM_SUCCESS);
176 tpm_marshal_TPM_COMMAND_CODE(&ptr, &len, TPM_ORD_EstablishTransport);
177 tpm_marshal_TPM_MODIFIER_INDICATOR(&ptr, &len, *locality);
178 tpm_marshal_TPM_CURRENT_TICKS(&ptr, &len, currentTicks);
179 tpm_marshal_TPM_NONCE(&ptr, &len, transNonceEven);
180 tpm_sha1_init(&sha1);
181 tpm_sha1_update(&sha1, buf, sizeof(buf));
182 tpm_sha1_final(&sha1, buf);
183 transport_log_out(buf, &session->transInternal.transDigest);
184 }
185 /* check whether this is a exclusive transport session */
186 if (transPublic->transAttributes & TPM_TRANSPORT_EXCLUSIVE) {
187 tpmData.stany.flags.transportExclusive = TRUE;
188 tpmData.stany.data.transExclusive = *transHandle;
189 }
190 auth1->continueAuthSession = FALSE;
191 return TPM_SUCCESS;
192 }
193
194 extern UINT32 tpm_get_in_param_offset(TPM_COMMAND_CODE ordinal);
195 extern UINT32 tpm_get_out_param_offset(TPM_COMMAND_CODE ordinal);
196 extern void tpm_compute_in_param_digest(TPM_REQUEST *req);
197 extern void tpm_execute_command(TPM_REQUEST *req, TPM_RESPONSE *rsp);
198 extern void tpm_compute_out_param_digest(TPM_COMMAND_CODE ordinal, TPM_RESPONSE *rsp);
199
decrypt_wrapped_command(BYTE * buf,UINT32 buf_len,TPM_AUTH * auth,TPM_SESSION_DATA * session)200 static void decrypt_wrapped_command(BYTE *buf, UINT32 buf_len, TPM_AUTH *auth,
201 TPM_SESSION_DATA *session)
202
203 {
204 UINT32 i, j;
205 BYTE mask[SHA1_DIGEST_LENGTH];
206 tpm_sha1_ctx_t sha1;
207 for (i = 0; buf_len > 0; i++) {
208 tpm_sha1_init(&sha1);
209 tpm_sha1_update(&sha1, session->nonceEven.nonce, sizeof(session->nonceEven.nonce));
210 tpm_sha1_update(&sha1, auth->nonceOdd.nonce, sizeof(auth->nonceOdd.nonce));
211 tpm_sha1_update(&sha1, (uint8_t*)"in", 2);
212 tpm_sha1_update(&sha1, session->transInternal.authData, sizeof(TPM_SECRET));
213 tpm_sha1_update_be32(&sha1, i);
214 tpm_sha1_final(&sha1, mask);
215 for (j = 0; j < sizeof(mask) && buf_len > 0; j++) {
216 *buf++ ^= mask[j];
217 buf_len--;
218 }
219 }
220 }
221
encrypt_wrapped_command(BYTE * buf,UINT32 buf_len,TPM_AUTH * auth,TPM_SESSION_DATA * session)222 static void encrypt_wrapped_command(BYTE *buf, UINT32 buf_len, TPM_AUTH *auth,
223 TPM_SESSION_DATA *session)
224 {
225 UINT32 i, j;
226 BYTE mask[SHA1_DIGEST_LENGTH];
227 tpm_sha1_ctx_t sha1;
228 for (i = 0; buf_len > 0; i++) {
229 tpm_sha1_init(&sha1);
230 tpm_sha1_update(&sha1, session->nonceEven.nonce, sizeof(session->nonceEven.nonce));
231 tpm_sha1_update(&sha1, auth->nonceOdd.nonce, sizeof(auth->nonceOdd.nonce));
232 tpm_sha1_update(&sha1, (uint8_t*)"out", 3);
233 tpm_sha1_update(&sha1, session->transInternal.authData, sizeof(TPM_SECRET));
234 tpm_sha1_update_be32(&sha1, i);
235 tpm_sha1_final(&sha1, mask);
236 for (j = 0; j < sizeof(mask) && buf_len > 0; j++) {
237 *buf++ ^= mask[j];
238 buf_len--;
239 }
240 }
241 }
242
compute_key_digest(TPM_REQUEST * req,TPM_DIGEST * digest)243 static void compute_key_digest(TPM_REQUEST *req, TPM_DIGEST *digest)
244 {
245 tpm_sha1_ctx_t ctx;
246 TPM_HANDLE h1, h2;
247 TPM_KEY_DATA *k1, *k2;
248 BYTE *ptr;
249 UINT32 len, offset = tpm_get_in_param_offset(req->ordinal);
250 /* handle some exceptions */
251 if (req->ordinal == TPM_ORD_FlushSpecific) offset = 0;
252 else if (req->ordinal == TPM_ORD_OwnerReadInternalPub) offset = 4;
253 /* compute public key digests */
254 if (offset == 0) {
255 debug("no handles");
256 memset(digest, 0, sizeof(TPM_DIGEST));
257 } else if (offset == 4) {
258 debug("one handle");
259 ptr = req->param; len = 4;
260 tpm_unmarshal_TPM_HANDLE(&ptr, &len, &h1);
261 k1 = tpm_get_key(h1);
262 if (k1 != NULL && tpm_compute_key_data_digest(k1, digest) == 0) {
263 debug("key found");
264 /* compute outer hash */
265 tpm_sha1_init(&ctx);
266 tpm_sha1_update(&ctx, digest->digest, sizeof(digest->digest));
267 tpm_sha1_final(&ctx, digest->digest);
268 } else {
269 memset(digest, 0, sizeof(TPM_DIGEST));
270 }
271 } else if (offset == 8) {
272 TPM_DIGEST digest2;
273 debug("two handles");
274 ptr = req->param; len = 8;
275 tpm_unmarshal_TPM_HANDLE(&ptr, &len, &h1);
276 tpm_unmarshal_TPM_HANDLE(&ptr, &len, &h2);
277 k1 = tpm_get_key(h1);
278 k2 = tpm_get_key(h2);
279 if (k1 != NULL && tpm_compute_key_data_digest(k1, digest) == 0
280 && k2 != NULL && tpm_compute_key_data_digest(k2, &digest2) == 0) {
281 debug("two keys found");
282 /* compute outer hash */
283 tpm_sha1_init(&ctx);
284 tpm_sha1_update(&ctx, digest->digest, sizeof(digest->digest));
285 tpm_sha1_update(&ctx, digest2.digest, sizeof(digest2.digest));
286 tpm_sha1_final(&ctx, digest->digest);
287 } else {
288 memset(digest, 0, sizeof(TPM_DIGEST));
289 }
290 } else {
291 memset(digest, 0, sizeof(TPM_DIGEST));
292 }
293 }
294
TPM_ExecuteTransport(UINT32 inWrappedCmdSize,BYTE * inWrappedCmd,TPM_AUTH * auth1,UINT64 * currentTicks,TPM_MODIFIER_INDICATOR * locality,UINT32 * outWrappedCmdSize,BYTE ** outWrappedCmd)295 TPM_RESULT TPM_ExecuteTransport(UINT32 inWrappedCmdSize, BYTE *inWrappedCmd,
296 TPM_AUTH *auth1, UINT64 *currentTicks,
297 TPM_MODIFIER_INDICATOR *locality,
298 UINT32 *outWrappedCmdSize, BYTE **outWrappedCmd)
299 {
300 TPM_RESULT res;
301 TPM_SESSION_DATA *session;
302 TPM_REQUEST req;
303 TPM_RESPONSE rsp;
304 BYTE *ptr, buf[4 * 4 + 8 + 20];
305 UINT32 len, offset;
306 tpm_sha1_ctx_t sha1;
307 info("TPM_ExecuteTransport()");
308 /* get transport session */
309 session = tpm_get_transport(auth1->authHandle);
310 if (session == NULL) return TPM_BAD_PARAMETER;
311 /* unmarshal wrapped command */
312 len = inWrappedCmdSize;
313 ptr = inWrappedCmd;
314 if (tpm_unmarshal_TPM_REQUEST(&ptr, &len, &req)) return TPM_FAIL;
315 /* decrypt wrapped command if needed */
316 ptr = tpm_malloc(req.paramSize);
317 if (ptr == NULL) return TPM_FAIL;
318 memcpy(ptr, req.param, req.paramSize);
319 if (session->transInternal.transPublic.transAttributes & TPM_TRANSPORT_ENCRYPT) {
320 if (req.ordinal == TPM_ORD_OIAP || req.ordinal == TPM_ORD_OSAP) {
321 offset = req.paramSize;
322 } else if (req.ordinal == TPM_ORD_DSAP) {
323 offset = 30;
324 } else {
325 offset = tpm_get_in_param_offset(req.ordinal);
326 }
327 debug("decrypting %d bytes, starting at pos %d", req.paramSize - offset, offset);
328 decrypt_wrapped_command(ptr + offset, req.paramSize - offset, auth1, session);
329 }
330 req.param = ptr;
331 /* verify authorization */
332 tpm_compute_in_param_digest(&req);
333 tpm_sha1_init(&sha1);
334 tpm_sha1_update_be32(&sha1, TPM_ORD_ExecuteTransport);
335 tpm_sha1_update_be32(&sha1, inWrappedCmdSize);
336 tpm_sha1_update(&sha1, req.auth1.digest, sizeof(req.auth1.digest));
337 tpm_sha1_final(&sha1, auth1->digest);
338 res = tpm_verify_auth(auth1, session->transInternal.authData, TPM_INVALID_HANDLE);
339 if (res != TPM_SUCCESS) {
340 tpm_free(req.param);
341 return res;
342 }
343 /* nested transport sessions are not allowed */
344 if (req.ordinal == TPM_ORD_EstablishTransport
345 || req.ordinal == TPM_ORD_ExecuteTransport
346 || req.ordinal == TPM_ORD_ReleaseTransportSigned) {
347 tpm_free(req.param);
348 return TPM_NO_WRAP_TRANSPORT;
349 }
350 /* log input parameters */
351 if (session->transInternal.transPublic.transAttributes & TPM_TRANSPORT_LOG) {
352 TPM_DIGEST keyDigest;
353 compute_key_digest(&req, &keyDigest);
354 transport_log_in(req.auth1.digest, keyDigest.digest,
355 &session->transInternal.transDigest);
356 }
357 /* execute and audit command*/
358 tpm_audit_request(req.ordinal, &req);
359 tpm_execute_command(&req, &rsp);
360 tpm_audit_response(req.ordinal, &rsp);
361 tpm_free(req.param);
362 /* get locality and ticks */
363 *locality = tpmData.stany.flags.localityModifier;
364 *currentTicks = tpmData.stany.data.currentTicks.currentTicks;
365 /* if required, compute digest of internal output parameters */
366 debug("result = %d", rsp.result);
367 if (rsp.result == TPM_SUCCESS) {
368 if (rsp.tag == TPM_TAG_RSP_COMMAND) {
369 rsp.auth1 = &req.auth1;
370 tpm_compute_out_param_digest(req.ordinal, &rsp);
371 }
372 /* encrypt parameters */
373 if (session->transInternal.transPublic.transAttributes & TPM_TRANSPORT_ENCRYPT) {
374 if (req.ordinal == TPM_ORD_OIAP || req.ordinal == TPM_ORD_OSAP) {
375 offset = rsp.paramSize;
376 } else if (req.ordinal == TPM_ORD_DSAP) {
377 offset = rsp.paramSize;
378 } else {
379 offset = tpm_get_out_param_offset(req.ordinal);
380 }
381 debug("encrypting %d bytes, starting at pos %d", rsp.paramSize - offset, offset);
382 encrypt_wrapped_command(rsp.param + offset, rsp.paramSize - offset, auth1, session);
383 }
384 } else {
385 rsp.auth1 = &req.auth1;
386 memset(rsp.auth1->digest, 0, sizeof(*rsp.auth1->digest));
387 }
388 /* marshal response */
389 *outWrappedCmdSize = len = rsp.size;
390 *outWrappedCmd = ptr = tpm_malloc(len);
391 if (ptr == NULL) {
392 tpm_free(rsp.param);
393 return TPM_FAIL;
394 }
395 tpm_marshal_TPM_RESPONSE(&ptr, &len, &rsp);
396 debug("marshalling done.");
397 /* log output parameters */
398 if (session->transInternal.transPublic.transAttributes & TPM_TRANSPORT_LOG) {
399 transport_log_out(rsp.auth1->digest, &session->transInternal.transDigest);
400 }
401 tpm_free(rsp.param);
402 /* compute digest of output parameters */
403 ptr = buf; len = sizeof(buf);
404 tpm_marshal_UINT32(&ptr, &len, TPM_SUCCESS);
405 tpm_marshal_TPM_COMMAND_CODE(&ptr, &len, TPM_ORD_ExecuteTransport);
406 tpm_marshal_UINT64(&ptr, &len, *currentTicks);
407 tpm_marshal_TPM_MODIFIER_INDICATOR(&ptr, &len, *locality);
408 tpm_marshal_UINT32(&ptr, &len, *outWrappedCmdSize);
409 memcpy(ptr, rsp.auth1->digest, sizeof(rsp.auth1->digest));
410 tpm_sha1_init(&sha1);
411 tpm_sha1_update(&sha1, buf, sizeof(buf));
412 tpm_sha1_final(&sha1, auth1->digest);
413 return TPM_SUCCESS;
414 }
415
TPM_ReleaseTransportSigned(TPM_KEY_HANDLE keyHandle,TPM_NONCE * antiReplay,TPM_AUTH * auth1,TPM_AUTH * auth2,TPM_MODIFIER_INDICATOR * locality,TPM_CURRENT_TICKS * currentTicks,UINT32 * sigSize,BYTE ** sig)416 TPM_RESULT TPM_ReleaseTransportSigned(TPM_KEY_HANDLE keyHandle,
417 TPM_NONCE *antiReplay,
418 TPM_AUTH *auth1, TPM_AUTH *auth2,
419 TPM_MODIFIER_INDICATOR *locality,
420 TPM_CURRENT_TICKS *currentTicks,
421 UINT32 *sigSize, BYTE **sig)
422 {
423 TPM_RESULT res;
424 TPM_KEY_DATA *key;
425 TPM_SESSION_DATA *session;
426 BYTE buf[30 + 20];
427 info("TPM_ReleaseTransportSigned()");
428 /* get key */
429 key = tpm_get_key(keyHandle);
430 if (key == NULL) return TPM_INVALID_KEYHANDLE;
431 /* verify authorization */
432 if (auth2->authHandle != TPM_INVALID_HANDLE
433 || key->authDataUsage != TPM_AUTH_NEVER) {
434 res = tpm_verify_auth(auth1, key->usageAuth, keyHandle);
435 if (res != TPM_SUCCESS) return res;
436 session = tpm_get_transport(auth2->authHandle);
437 if (session == NULL) return TPM_INVALID_AUTHHANDLE;
438 res = tpm_verify_auth(auth2, session->transInternal.authData, TPM_INVALID_HANDLE);
439 if (res != TPM_SUCCESS) return (res == TPM_AUTHFAIL) ? TPM_AUTH2FAIL : res;
440 } else {
441 session = tpm_get_transport(auth1->authHandle);
442 if (session == NULL) return TPM_INVALID_AUTHHANDLE;
443 res = tpm_verify_auth(auth1, session->transInternal.authData, TPM_INVALID_HANDLE);
444 if (res != TPM_SUCCESS) return res;
445 }
446 /* invalidate transport session */
447 auth1->continueAuthSession = FALSE;
448 /* logging must be enabled */
449 if (!(session->transInternal.transPublic.transAttributes & TPM_TRANSPORT_LOG))
450 return TPM_BAD_MODE;
451 *locality = tpmData.stany.flags.localityModifier;
452 memcpy(currentTicks, &tpmData.stany.data.currentTicks, sizeof(TPM_CURRENT_TICKS));
453 transport_log_out(auth1->digest, &session->transInternal.transDigest);
454 /* setup a TPM_SIGN_INFO structure */
455 memcpy(&buf[0], (uint8_t*)"\x00\x05TRAN", 6);
456 memcpy(&buf[6], antiReplay->nonce, 20);
457 memcpy(&buf[26], (uint8_t*)"\x00\x00\x00\x14", 4);
458 memcpy(&buf[30], session->transInternal.transDigest.digest, 20);
459 /* sign info structure */
460 if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_SHA1) {
461 tpm_sha1_ctx_t ctx;
462 debug("TPM_SS_RSASSAPKCS1v15_SHA1");
463 tpm_sha1_init(&ctx);
464 tpm_sha1_update(&ctx, buf, sizeof(buf));
465 tpm_sha1_final(&ctx, buf);
466 res = tpm_sign(key, auth1, FALSE, buf, SHA1_DIGEST_LENGTH, sig, sigSize);
467 } else if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_INFO) {
468 debug("TPM_SS_RSASSAPKCS1v15_INFO");
469 res = tpm_sign(key, auth1, TRUE, buf, sizeof(buf), sig, sigSize);
470 } else {
471 debug("unsupported signature scheme: %02x", key->sigScheme);
472 res = TPM_INVALID_KEYUSAGE;
473 }
474 return res;
475 }
476