blob: c4dc5fa1232694f58cc749b1ba7596d01acc16fe [file] [log] [blame]
/* Software-based Trusted Platform Module (TPM) Emulator
* Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>
* 2005-2008 Heiko Stamer <stamer@gaos.org>
*
* This module is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* This module is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* $Id: tpm_daa.c 364 2010-02-11 10:24:45Z mast $
*/
#include "tpm_emulator.h"
#include "tpm_commands.h"
#include "tpm_data.h"
#include "tpm_handles.h"
#include "tpm_marshalling.h"
#include "crypto/sha1.h"
#include "crypto/rsa.h"
#include "crypto/rc4.h"
#include "crypto/hmac.h"
#define DAA_LABEL_00 ((uint8_t*)"\x00")
#define DAA_LABEL_01 ((uint8_t*)"\x01")
#define DAA_LABEL_r0 ((uint8_t*)"r0")
#define DAA_LABEL_r1 ((uint8_t*)"r1")
#define DAA_LABEL_r2 ((uint8_t*)"r2")
UINT32 tpm_get_free_daa_session(void)
{
UINT32 i;
for (i = 0; i < TPM_MAX_SESSIONS_DAA; i++) {
if (tpmData.stany.data.sessionsDAA[i].type == TPM_ST_INVALID) {
tpmData.stany.data.sessionsDAA[i].type = TPM_ST_DAA;
tpmData.stany.data.sessionsDAA[i].handle = INDEX_TO_DAA_HANDLE(i);
return INDEX_TO_DAA_HANDLE(i);
}
}
return TPM_INVALID_HANDLE;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error on mismatch */
static TPM_RESULT tpm_daa_verify_digestContext(TPM_DAA_SESSION_DATA *session,
tpm_sha1_ctx_t *sha1)
{
TPM_DIGEST dgt;
UINT32 size, len;
BYTE *buf, *ptr;
tpm_sha1_init(sha1);
size = len = sizeof(TPM_DAA_TPM);
buf = ptr = tpm_malloc(size);
if (buf == NULL)
return -1;
memset(buf, 0, size);
if (tpm_marshal_TPM_DAA_TPM(&ptr, &len, &session->DAA_tpmSpecific)) {
tpm_free(buf);
return -1;
}
tpm_sha1_update(sha1, buf, size);
tpm_free(buf);
size = len = sizeof(TPM_DAA_JOINDATA);
buf = ptr = tpm_malloc(size);
if (buf == NULL)
return -1;
memset(buf, 0, size);
if (tpm_marshal_TPM_DAA_JOINDATA(&ptr, &len, &session->DAA_joinSession)) {
tpm_free(buf);
return -1;
}
tpm_sha1_update(sha1, buf, size);
tpm_free(buf);
tpm_sha1_final(sha1, dgt.digest);
return memcmp(dgt.digest, session->DAA_session.DAA_digestContext.digest,
sizeof(TPM_DIGEST));
}
/* Set DAA_session->DAA_digestContext = SHA-1(DAA_tpmSpecific ||
* DAA_joinSession) */
static void tpm_daa_update_digestContext(TPM_DAA_SESSION_DATA *session,
tpm_sha1_ctx_t *sha1)
{
UINT32 size, len;
BYTE *buf, *ptr;
tpm_sha1_init(sha1);
/* DAA_tpmSpecific */
size = len = sizeof(TPM_DAA_TPM);
buf = ptr = tpm_malloc(size);
if (buf == NULL)
return;
memset(buf, 0, size);
if (tpm_marshal_TPM_DAA_TPM(&ptr, &len, &session->DAA_tpmSpecific)) {
tpm_free(buf);
return;
}
tpm_sha1_update(sha1, buf, size);
tpm_free(buf);
/* DAA_joinSession */
size = len = sizeof(TPM_DAA_JOINDATA);
buf = ptr = tpm_malloc(size);
if (buf == NULL)
return;
memset(buf, 0, size);
if (tpm_marshal_TPM_DAA_JOINDATA(&ptr, &len, &session->DAA_joinSession)) {
tpm_free(buf);
return;
}
tpm_sha1_update(sha1, buf, size);
tpm_free(buf);
tpm_sha1_final(sha1, session->DAA_session.DAA_digestContext.digest);
}
/* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific) and
* return error on mismatch */
static TPM_RESULT tpm_daa_verify_digestContext_sign(TPM_DAA_SESSION_DATA *session,
tpm_sha1_ctx_t *sha1)
{
TPM_DIGEST dgt;
UINT32 size, len;
BYTE *buf, *ptr;
tpm_sha1_init(sha1);
size = len = sizeof(TPM_DAA_TPM);
buf = ptr = tpm_malloc(size);
if (buf == NULL)
return -1;
memset(buf, 0, size);
if (tpm_marshal_TPM_DAA_TPM(&ptr, &len, &session->DAA_tpmSpecific)) {
tpm_free(buf);
return -1;
}
tpm_sha1_update(sha1, buf, size);
tpm_free(buf);
tpm_sha1_final(sha1, dgt.digest);
return memcmp(dgt.digest, session->DAA_session.DAA_digestContext.digest,
sizeof(TPM_DIGEST));
}
/* Set DAA_session->DAA_digestContext = SHA-1(DAA_tpmSpecific) */
static void tpm_daa_update_digestContext_sign(TPM_DAA_SESSION_DATA *session,
tpm_sha1_ctx_t *sha1)
{
UINT32 size, len;
BYTE *buf, *ptr;
tpm_sha1_init(sha1);
size = len = sizeof(TPM_DAA_TPM);
buf = ptr = tpm_malloc(size);
if (buf == NULL)
return;
memset(buf, 0, size);
if (tpm_marshal_TPM_DAA_TPM(&ptr, &len, &session->DAA_tpmSpecific)) {
tpm_free(buf);
return;
}
tpm_sha1_update(sha1, buf, size);
tpm_free(buf);
tpm_sha1_final(sha1, session->DAA_session.DAA_digestContext.digest);
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error on mismatch */
static TPM_RESULT tpm_daa_verify_digestIssuer(TPM_DAA_SESSION_DATA *session,
tpm_sha1_ctx_t *sha1)
{
TPM_DIGEST dgt;
UINT32 size, len;
BYTE *buf, *ptr;
tpm_sha1_init(sha1);
size = len = sizeof(TPM_DAA_ISSUER);
buf = ptr = tpm_malloc(size);
if (buf == NULL)
return -1;
memset(buf, 0, size);
if (tpm_marshal_TPM_DAA_ISSUER(&ptr, &len, &session->DAA_issuerSettings)) {
tpm_free(buf);
return -1;
}
tpm_sha1_update(sha1, buf, size);
tpm_free(buf);
tpm_sha1_final(sha1, dgt.digest);
return memcmp(dgt.digest, session->DAA_tpmSpecific.DAA_digestIssuer.digest,
sizeof(TPM_DIGEST));
}
/* Set DAA_tpmSpecific->DAA_digestIssuer == SHA-1(DAA_issuerSettings) */
static void tpm_daa_update_digestIssuer(TPM_DAA_SESSION_DATA *session,
tpm_sha1_ctx_t *sha1)
{
UINT32 size, len;
BYTE *buf, *ptr;
tpm_sha1_init(sha1);
size = len = sizeof(TPM_DAA_ISSUER);
buf = ptr = tpm_malloc(size);
if (buf == NULL)
return;
memset(buf, 0, size);
if (tpm_marshal_TPM_DAA_ISSUER(&ptr, &len, &session->DAA_issuerSettings)) {
tpm_free(buf);
return;
}
tpm_sha1_update(sha1, buf, size);
tpm_free(buf);
tpm_sha1_final(sha1, session->DAA_tpmSpecific.DAA_digestIssuer.digest);
}
/* Verify that SHA-1(input) == digest and return error !TPM_SUCCESS
* on mismatch */
static TPM_RESULT tpm_daa_verify_generic(TPM_DIGEST digest, BYTE *input,
UINT32 inputSize, tpm_sha1_ctx_t *sha1)
{
TPM_DIGEST dgt;
tpm_sha1_init(sha1);
tpm_sha1_update(sha1, input, inputSize);
tpm_sha1_final(sha1, dgt.digest);
return memcmp(dgt.digest, digest.digest, sizeof(TPM_DIGEST));
}
/* Encryption and decryption of the TPM_DAA_SENSITIVE structure */
static int encrypt_daa(BYTE *iv, UINT32 iv_size, TPM_DAA_SENSITIVE *sensitive,
BYTE **enc, UINT32 *enc_size)
{
UINT32 len;
BYTE *ptr;
tpm_rc4_ctx_t rc4_ctx;
BYTE key[TPM_SYM_KEY_SIZE + iv_size];
/* marshal sensitive */
*enc_size = len = sizeof_TPM_DAA_SENSITIVE((*sensitive));
*enc = ptr = tpm_malloc(len);
if (*enc == NULL)
return -1;
if (tpm_marshal_TPM_DAA_SENSITIVE(&ptr, &len, sensitive)) {
tpm_free(*enc);
return -1;
}
/* encrypt sensitive */
memcpy(key, tpmData.permanent.data.daaKey, TPM_SYM_KEY_SIZE);
memcpy(&key[TPM_SYM_KEY_SIZE], iv, iv_size);
tpm_rc4_init(&rc4_ctx, key, sizeof(key));
tpm_rc4_crypt(&rc4_ctx, *enc, *enc, *enc_size);
return 0;
}
static int decrypt_daa(BYTE *iv, UINT32 iv_size, BYTE *enc, UINT32 enc_size,
TPM_DAA_SENSITIVE *sensitive, BYTE **buf)
{
UINT32 len;
BYTE *ptr;
tpm_rc4_ctx_t rc4_ctx;
BYTE key[TPM_SYM_KEY_SIZE + iv_size];
/* decrypt sensitive */
len = enc_size, *buf = ptr = tpm_malloc(len);
if (ptr == NULL)
return -1;
memcpy(key, tpmData.permanent.data.daaKey, TPM_SYM_KEY_SIZE);
memcpy(&key[TPM_SYM_KEY_SIZE], iv, iv_size);
tpm_rc4_init(&rc4_ctx, key, sizeof(key));
tpm_rc4_crypt(&rc4_ctx, enc, ptr, enc_size);
/* unmarshal sensitive */
if (tpm_unmarshal_TPM_DAA_SENSITIVE(&ptr, &len, sensitive)) {
tpm_free(*buf);
return -1;
}
return 0;
}
/* Computation of the HMAC which protects the integrity of the TPM_DAA_BLOB */
static int compute_daa_digest(TPM_DAA_BLOB *daaBlob, TPM_DIGEST *digest)
{
BYTE *buf, *ptr;
UINT32 len;
tpm_hmac_ctx_t hmac_ctx;
len = sizeof_TPM_DAA_BLOB((*daaBlob));
buf = ptr = tpm_malloc(len);
if (buf == NULL)
return -1;
if (tpm_marshal_TPM_DAA_BLOB(&ptr, &len, daaBlob)) {
tpm_free(buf);
return -1;
}
memset(&buf[22], 0, sizeof(TPM_DIGEST));
tpm_hmac_init(&hmac_ctx, tpmData.permanent.data.daaProof.nonce,
sizeof(tpmData.permanent.data.daaProof.nonce));
tpm_hmac_update(&hmac_ctx, buf, sizeof_TPM_DAA_BLOB((*daaBlob)));
tpm_hmac_final(&hmac_ctx, digest->digest);
tpm_free(buf);
return 0;
}
/*
* DAA commands ([TPM_Part3], Section 26)
* Operations that are necessary to setup a TPM for DAA, execute the
* JOIN process, and execute the SIGN process.
*/
#define SCRATCH_SIZE 256
TPM_RESULT TPM_DAA_Join(TPM_HANDLE handle, BYTE stage, UINT32 inputSize0,
BYTE *inputData0, UINT32 inputSize1,
BYTE *inputData1, TPM_AUTH *auth1,
TPM_COMMAND_CODE *ordinal, UINT32 *outputSize,
BYTE **outputData)
{
BYTE scratch[SCRATCH_SIZE];
TPM_DAA_SESSION_DATA *session = NULL;
TPM_RESULT res;
UINT32 cnt, len;
tpm_sha1_ctx_t sha1;
tpm_rsa_public_key_t key;
BYTE *signedData = NULL, *signatureValue = NULL, *DAA_generic_gamma = NULL,
*DAA_generic_R0 = NULL, *DAA_generic_R1 = NULL, *DAA_generic_n = NULL,
*DAA_generic_S0 = NULL, *DAA_generic_S1 = NULL, *ptr;
tpm_bn_t X, Y, Z, n, f, q, f0, f1, w1, w, gamma, r0, r1, r2, r3, r, s0, s1,
s12, s2, s3, E, E1, u2, u3, v0, v10, v1, tmp;
size_t size;
BYTE mgf1_seed[2 + sizeof(TPM_DIGEST)];
TPM_DAA_BLOB blob;
TPM_DAA_SENSITIVE sensitive;
info("TPM_DAA_Join()");
debug("handle = %.8x, stage = %d", handle, stage);
debug("stany.data.currentDAA = %.8x", tpmData.stany.data.currentDAA);
/* Initalize internal scratch pad */
memset(scratch, 0, SCRATCH_SIZE);
/* Verify authorization */
res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);
if (res != TPM_SUCCESS) return res;
/* Verify and initalize the session, for all stages greater than zero. */
if (stage > 0) {
if ((HANDLE_TO_INDEX(handle) >= TPM_MAX_SESSIONS_DAA) ||
(tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)].type !=
TPM_ST_DAA) ||
(tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)].handle !=
handle)) {
/* Probe, whether the handle from stany.data.currentDAA is valid. */
handle = tpmData.stany.data.currentDAA;
if ((HANDLE_TO_INDEX(handle) >= TPM_MAX_SESSIONS_DAA) ||
(tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)].type !=
TPM_ST_DAA) ||
(tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)].handle !=
handle))
return TPM_BAD_HANDLE;
}
session = &tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)];
}
/* TPM_DAA_JOIN [TPM_Part3], Section 26.1, Rev. 85 */
switch (stage) {
case 0:
{
/* Determine that sufficient resources are available to perform a
* DAA_Join. Assign session handle for this DAA_Join. */
handle = tpm_get_free_daa_session();
if (handle == TPM_INVALID_HANDLE)
return TPM_RESOURCES;
session = &tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)];
/* Set all fields in DAA_issuerSettings = NULL */
memset(&session->DAA_issuerSettings, 0, sizeof(TPM_DAA_ISSUER));
session->DAA_issuerSettings.tag = TPM_TAG_DAA_ISSUER;
/* Set all fields in DAA_tpmSpecific = NULL */
memset(&session->DAA_tpmSpecific, 0, sizeof(TPM_DAA_TPM));
session->DAA_tpmSpecific.tag = TPM_TAG_DAA_TPM;
/* Set all fields in DAA_session = NULL */
memset(&session->DAA_session, 0, sizeof(TPM_DAA_CONTEXT));
session->DAA_session.tag = TPM_TAG_DAA_CONTEXT;
/* Set all fields in DAA_joinSession = NULL */
memset(&session->DAA_joinSession, 0, sizeof(TPM_DAA_JOINDATA));
/* Verify that sizeOf(inputData0) == sizeOf(DAA_tpmSpecific->DAA_count)
* and return error TPM_DAA_INPUT_DATA0 on mismatch */
if (inputSize0 != sizeof(session->DAA_tpmSpecific.DAA_count)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Verify that inputData0 > 0, and return TPM_DAA_INPUT_DATA0 on
* mismatch */
ptr = inputData0, len = inputSize0;
if (tpm_unmarshal_UINT32(&ptr, &len, &cnt) || (len != 0)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
if (cnt <= 0) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set DAA_tpmSpecific->DAA_count = inputData0 */
debug("TPM_DAA_Join() -- set DAA_count := %d", cnt);
session->DAA_tpmSpecific.DAA_count = cnt;
/* Set DAA_session->DAA_digestContext = SHA-1(DAA_tpmSpecific ||
* DAA_joinSession) */
tpm_daa_update_digestContext(session, &sha1);
/* Set DAA_session->DAA_stage = 1 */
session->DAA_session.DAA_stage = 1;
/* Assign session handle for DAA_Join */
tpmData.stany.data.currentDAA = handle;
debug("TPM_DAA_Join() -- set handle := %.8x", handle);
/* Set outputData = new session handle */
*outputSize = sizeof(TPM_HANDLE);
if ((*outputData = tpm_malloc(*outputSize)) != NULL) {
ptr = *outputData, len = *outputSize;
if (tpm_marshal_TPM_HANDLE(&ptr, &len, handle)) {
debug("TPM_DAA_Join(): tpm_marshal_TPM_HANDLE() failed.");
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_FAIL;
}
} else {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 1:
{
/* Verify that DAA_session->DAA_stage == 1. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 1) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Verify that sizeOf(inputData0) == DAA_SIZE_issuerModulus and
* return error TPM_DAA_INPUT_DATA0 on mismatch */
if (inputSize0 != DAA_SIZE_issuerModulus) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* If DAA_session->DAA_scratch == NULL: */
if (!memcmp(scratch, session->DAA_session.DAA_scratch,
sizeof(session->DAA_session.DAA_scratch))) {
/* Set DAA_session->DAA_scratch = inputData0 */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
memcpy(session->DAA_session.DAA_scratch, inputData0, inputSize0);
/* Set DAA_joinSession->DAA_digest_n0 =
* SHA-1(DAA_session->DAA_scratch) */
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, session->DAA_session.DAA_scratch,
sizeof(session->DAA_session.DAA_scratch));
tpm_sha1_final(&sha1, (BYTE*) &session->DAA_joinSession.DAA_digest_n0);
/* Set DAA_tpmSpecific->DAA_rekey = SHA-1(TPM_DAA_TPM_SEED ||
* DAA_joinSession->DAA_digest_n0) */
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) &tpmData.permanent.data.tpmDAASeed,
sizeof(tpmData.permanent.data.tpmDAASeed));
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_joinSession.DAA_digest_n0,
sizeof(session->DAA_joinSession.DAA_digest_n0));
tpm_sha1_final(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey);
/* Else (If DAA_session->DAA_scratch != NULL): */
} else {
/* Set signedData = inputData0 */
signedData = inputData0;
/* Verify that sizeOf(inputData1) == DAA_SIZE_issuerModulus and
* return error TPM_DAA_INPUT_DATA1 on mismatch */
if (inputSize1 != DAA_SIZE_issuerModulus) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA1;
}
/* Set signatureValue = inputData1 */
signatureValue = inputData1;
/* Use the RSA key == [DAA_session->DAA_scratch] to verify that
* signatureValue is a signature on signedData, and return error
* TPM_DAA_ISSUER_VALIDITY on mismatch */
if (tpm_rsa_import_public_key(&key, RSA_MSB_FIRST,
session->DAA_session.DAA_scratch, DAA_SIZE_issuerModulus, NULL, 0)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_VALIDITY;
}
if (tpm_rsa_verify(&key, RSA_SSA_PKCS1_SHA1, signedData, inputSize0,
signatureValue)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_VALIDITY;
}
tpm_rsa_release_public_key(&key);
/* Set DAA_session->DAA_scratch = signedData */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
memcpy(session->DAA_session.DAA_scratch, inputData0, inputSize0);
}
/* Decrement DAA_tpmSpecific->DAA_count by 1 (unity) */
session->DAA_tpmSpecific.DAA_count--;
/* If DAA_tpmSpecific->DAA_count == 0: */
if (session->DAA_tpmSpecific.DAA_count == 0) {
/* Increment DAA_Session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
}
/* Set DAA_session->DAA_digestContext = SHA-1(DAA_tpmSpecific ||
* DAA_joinSession) */
tpm_daa_update_digestContext(session, &sha1);
/* Set outputData = NULL */
*outputSize = 0, *outputData = NULL;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 2:
{
/* Verify that DAA_session->DAA_stage == 2. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 2) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Verify that sizeOf(inputData0) == sizeOf(TPM_DAA_ISSUER) and
* return error TPM_DAA_INPUT_DATA0 on mismatch */
if (inputSize0 != sizeof(TPM_DAA_ISSUER)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set DAA_issuerSettings = inputData0. Verify that all fields in
* DAA_issuerSettings are present and return error
* TPM_DAA_INPUT_DATA0 if not. */
ptr = inputData0, len = inputSize0;
if (tpm_unmarshal_TPM_DAA_ISSUER(&ptr, &len,
&session->DAA_issuerSettings) || (len != 0) ||
!(session->DAA_issuerSettings.tag == TPM_TAG_DAA_ISSUER)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Verify that sizeOf(inputData1) == DAA_SIZE_issuerModulus and
* return error TPM_DAA_INPUT_DATA1 on mismatch */
if (inputSize1 != DAA_SIZE_issuerModulus) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA1;
}
/* Set signatureValue = inputData1 */
signatureValue = inputData1;
/* Set signedData = (DAA_joinSession->DAA_digest_n0 ||
* DAA_issuerSettings) */
memcpy(scratch, &session->DAA_joinSession.DAA_digest_n0,
sizeof(TPM_DIGEST));
memcpy(scratch + sizeof(TPM_DIGEST), inputData0, inputSize0);
signedData = scratch;
/* Use the RSA key [DAA_session->DAA_scratch] to verify that
* signatureValue is a signature on signedData, and return error
* TPM_DAA_ISSUER_VALIDITY on mismatch */
if (tpm_rsa_import_public_key(&key, RSA_MSB_FIRST,
session->DAA_session.DAA_scratch, DAA_SIZE_issuerModulus, NULL, 0)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_VALIDITY;
}
if (tpm_rsa_verify(&key, RSA_SSA_PKCS1_SHA1, signedData,
sizeof(TPM_DIGEST) + inputSize0, signatureValue)) {
tpm_rsa_release_public_key(&key);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_VALIDITY;
}
tpm_rsa_release_public_key(&key);
/* Set DAA_tpmSpecific->DAA_digestIssuer == SHA-1(DAA_issuerSettings) */
tpm_daa_update_digestIssuer(session, &sha1);
/* Set DAA_session->DAA_digestContext = SHA-1(DAA_tpmSpecific ||
* DAA_joinSession) */
tpm_daa_update_digestContext(session, &sha1);
/* Set DAA_session->DAA_scratch = NULL */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
/* Set outputData = NULL */
*outputSize = 0;
*outputData = NULL;
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 3:
{
/* Verify that DAA_session->DAA_stage == 3. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 3) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Verify that sizeOf(inputData0) == sizeOf(DAA_tpmSpecific->DAA_count)
* and return error TPM_DAA_INPUT_DATA0 on mismatch */
if (inputSize0 != sizeof(session->DAA_tpmSpecific.DAA_count)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set DAA_tpmSpecific->DAA_count = inputData0 */
ptr = inputData0, len = inputSize0;
if (tpm_unmarshal_UINT32(&ptr, &len,
&session->DAA_tpmSpecific.DAA_count) || (len != 0)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Obtain random data from the RNG and store it as
* DAA_joinSession->DAA_join_u0 */
tpm_get_random_bytes(session->DAA_joinSession.DAA_join_u0,
sizeof(session->DAA_joinSession.DAA_join_u0));
/* Obtain random data from the RNG and store it as
* DAA_joinSession->DAA_join_u1 */
tpm_get_random_bytes(session->DAA_joinSession.DAA_join_u1,
sizeof(session->DAA_joinSession.DAA_join_u1));
/* Set outputData = NULL */
*outputSize = 0, *outputData = NULL;
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Set DAA_session->DAA_digestContext = SHA-1(DAA_tpmSpecific ||
* DAA_joinSession) */
tpm_daa_update_digestContext(session, &sha1);
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 4:
{
/* Verify that DAA_session->DAA_stage == 4. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 4) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set DAA_generic_R0 = inputData0 */
DAA_generic_R0 = inputData0;
/* Verify that SHA-1(DAA_generic_R0) ==
* DAA_issuerSettings->DAA_digest_R0 and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_R0,
DAA_generic_R0, inputSize0, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set DAA_generic_n = inputData1 */
DAA_generic_n = inputData1;
/* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n
* and return error TPM_DAA_INPUT_DATA1 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n,
DAA_generic_n, inputSize1, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA1;
}
/* Set X = DAA_generic_R0 */
tpm_bn_init(X);
tpm_bn_import(X, inputSize0, 1, DAA_generic_R0);
/* Set n = DAA_generic_n */
tpm_bn_init(n);
tpm_bn_import(n, inputSize1, 1, DAA_generic_n);
/* Set f = SHA1(DAA_tpmSpecific->DAA_rekey ||
* DAA_tpmSpecific->DAA_count || 0 ) ||
* SHA1(DAA_tpmSpecific->DAA_rekey || DAA_tpmSpecific->DAA_count ||
* 1 ) mod DAA_issuerSettings->DAA_generic_q */
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey,
sizeof(session->DAA_tpmSpecific.DAA_rekey));
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count,
sizeof(session->DAA_tpmSpecific.DAA_count));
tpm_sha1_update(&sha1, DAA_LABEL_00, 1);
tpm_sha1_final(&sha1, scratch);
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey,
sizeof(session->DAA_tpmSpecific.DAA_rekey));
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count,
sizeof(session->DAA_tpmSpecific.DAA_count));
tpm_sha1_update(&sha1, DAA_LABEL_01, 1);
tpm_sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH);
tpm_bn_init(f), tpm_bn_init(q);
tpm_bn_import(f, 2 * SHA1_DIGEST_LENGTH, 1, scratch);
tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q),
1, session->DAA_issuerSettings.DAA_generic_q);
tpm_bn_mod(f, f, q);
/* Set f0 = f mod 2^DAA_power0 (erase all but the lowest DAA_power0
* bits of f) */
tpm_bn_init(f0), tpm_bn_init(tmp);
tpm_bn_ui_pow_ui(tmp, 2, DAA_power0);
tpm_bn_mod(f0, f, tmp);
/* Set DAA_session->DAA_scratch = (X^f0) mod n */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
tpm_bn_powm(tmp, X, f0, n);
tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, tmp);
tpm_bn_clear(f), tpm_bn_clear(q), tpm_bn_clear(f0), tpm_bn_clear(tmp);
tpm_bn_clear(X), tpm_bn_clear(n);
/* Set outputData = NULL */
*outputSize = 0, *outputData = NULL;
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 5:
{
/* Verify that DAA_session->DAA_stage == 5. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 5) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set DAA_generic_R1 = inputData0 */
DAA_generic_R1 = inputData0;
/* Verify that SHA-1(DAA_generic_R1) ==
* DAA_issuerSettings->DAA_digest_R1 and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_R1,
DAA_generic_R1, inputSize0, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set DAA_generic_n = inputData1 */
DAA_generic_n = inputData1;
/* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n
* and return error TPM_DAA_INPUT_DATA1 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n,
DAA_generic_n, inputSize1, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA1;
}
/* Set X = DAA_generic_R1 */
tpm_bn_init(X);
tpm_bn_import(X, inputSize0, 1, DAA_generic_R1);
/* Set n = DAA_generic_n */
tpm_bn_init(n);
tpm_bn_import(n, inputSize1, 1, DAA_generic_n);
/* Set f = SHA1(DAA_tpmSpecific->DAA_rekey ||
* DAA_tpmSpecific->DAA_count || 0 ) ||
* SHA1(DAA_tpmSpecific->DAA_rekey || DAA_tpmSpecific->DAA_count ||
* 1 ) mod DAA_issuerSettings->DAA_generic_q */
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey,
sizeof(session->DAA_tpmSpecific.DAA_rekey));
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count,
sizeof(session->DAA_tpmSpecific.DAA_count));
tpm_sha1_update(&sha1, DAA_LABEL_00, 1);
tpm_sha1_final(&sha1, scratch);
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey,
sizeof(session->DAA_tpmSpecific.DAA_rekey));
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count,
sizeof(session->DAA_tpmSpecific.DAA_count));
tpm_sha1_update(&sha1, DAA_LABEL_01, 1);
tpm_sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH);
tpm_bn_init(f), tpm_bn_init(q);
tpm_bn_import(f, 2 * SHA1_DIGEST_LENGTH, 1, scratch);
tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q),
1, session->DAA_issuerSettings.DAA_generic_q);
tpm_bn_mod(f, f, q);
/* Shift f right by DAA_power0 bits (discard the lowest DAA_power0
* bits) and label the result f1 */
tpm_bn_init(f1);
tpm_bn_fdiv_q_2exp(f1, f, DAA_power0);
/* Set Z = DAA_session->DAA_scratch */
tpm_bn_init(Z);
tpm_bn_import(Z, sizeof(session->DAA_session.DAA_scratch), -1,
session->DAA_session.DAA_scratch);
/* Set DAA_session->DAA_scratch = Z*(X^f1) mod n */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
tpm_bn_init(tmp);
tpm_bn_powm(tmp, X, f1, n);
tpm_bn_mul(tmp, tmp, Z);
tpm_bn_mod(tmp, tmp, n);
tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, tmp);
tpm_bn_clear(f), tpm_bn_clear(q), tpm_bn_clear(f1), tpm_bn_clear(tmp);
tpm_bn_clear(X), tpm_bn_clear(n), tpm_bn_clear(Z);
/* Set outputData = NULL */
*outputSize = 0, *outputData = NULL;
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 6:
{
/* Verify that DAA_session->DAA_stage == 6. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 6) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set DAA_generic_S0 = inputData0 */
DAA_generic_S0 = inputData0;
/* Verify that SHA-1(DAA_generic_S0) ==
* DAA_issuerSettings->DAA_digest_S0 and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_S0,
DAA_generic_S0, inputSize0, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set DAA_generic_n = inputData1 */
DAA_generic_n = inputData1;
/* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n
* and return error TPM_DAA_INPUT_DATA1 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n,
DAA_generic_n, inputSize1, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA1;
}
/* Set X = DAA_generic_S0 */
tpm_bn_init(X);
tpm_bn_import(X, inputSize0, 1, DAA_generic_S0);
/* Set n = DAA_generic_n */
tpm_bn_init(n);
tpm_bn_import(n, inputSize1, 1, DAA_generic_n);
/* Set Z = DAA_session->DAA_scratch */
tpm_bn_init(Z);
tpm_bn_import(Z, sizeof(session->DAA_session.DAA_scratch), -1,
session->DAA_session.DAA_scratch);
/* Set Y = DAA_joinSession->DAA_join_u0 */
tpm_bn_init(Y);
tpm_bn_import(Y, sizeof(session->DAA_joinSession.DAA_join_u0), 1,
session->DAA_joinSession.DAA_join_u0);
/* Set DAA_session->DAA_scratch = Z*(X^Y) mod n */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
tpm_bn_init(tmp);
tpm_bn_powm(tmp, X, Y, n);
tpm_bn_mul(tmp, tmp, Z);
tpm_bn_mod(tmp, tmp, n);
tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, tmp);
tpm_bn_clear(X), tpm_bn_clear(Y), tpm_bn_clear(Z), tpm_bn_clear(n), tpm_bn_clear(tmp);
/* Set outputData = NULL */
*outputSize = 0, *outputData = NULL;
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 7:
{
/* Verify that DAA_session->DAA_stage == 7. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 7) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set DAA_generic_S1 = inputData0 */
DAA_generic_S1 = inputData0;
/* Verify that SHA-1(DAA_generic_S1) ==
* DAA_issuerSettings->DAA_digest_S1 and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_S1,
DAA_generic_S1, inputSize0, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set DAA_generic_n = inputData1 */
DAA_generic_n = inputData1;
/* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n
* and return error TPM_DAA_INPUT_DATA1 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n,
DAA_generic_n, inputSize1, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA1;
}
/* Set X = DAA_generic_S1 */
tpm_bn_init(X);
tpm_bn_import(X, inputSize0, 1, DAA_generic_S1);
/* Set n = DAA_generic_n */
tpm_bn_init(n);
tpm_bn_import(n, inputSize1, 1, DAA_generic_n);
/* Set Y = DAA_joinSession->DAA_join_u1 */
tpm_bn_init(Y);
tpm_bn_import(Y, sizeof(session->DAA_joinSession.DAA_join_u1), 1,
session->DAA_joinSession.DAA_join_u1);
/* Set Z = DAA_session->DAA_scratch */
tpm_bn_init(Z);
tpm_bn_import(Z, sizeof(session->DAA_session.DAA_scratch), -1,
session->DAA_session.DAA_scratch);
/* Set DAA_session->DAA_scratch = Z*(X^Y) mod n */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
tpm_bn_init(tmp);
tpm_bn_powm(tmp, X, Y, n);
tpm_bn_mul(tmp, tmp, Z);
tpm_bn_mod(tmp, tmp, n);
tpm_bn_export(session->DAA_session.DAA_scratch, &size, 1, tmp);
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
tpm_bn_export(session->DAA_session.DAA_scratch +
(sizeof(session->DAA_session.DAA_scratch) - size),
&size, 1, tmp);
tpm_bn_clear(X), tpm_bn_clear(Y), tpm_bn_clear(Z), tpm_bn_clear(n), tpm_bn_clear(tmp);
/* Set DAA_session->DAA_digest to the SHA-1(DAA_session->DAA_scratch ||
* DAA_tpmSpecific->DAA_count || DAA_joinSession->DAA_digest_n0) */
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, session->DAA_session.DAA_scratch,
sizeof(session->DAA_session.DAA_scratch));
ptr = scratch, len = sizeof(scratch);
if (tpm_marshal_UINT32(&ptr, &len, session->DAA_tpmSpecific.DAA_count)) {
debug("TPM_DAA_Join(): tpm_marshal_UINT32() failed.");
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_FAIL;
}
tpm_sha1_update(&sha1, scratch, sizeof(UINT32));
tpm_sha1_update(&sha1, session->DAA_joinSession.DAA_digest_n0.digest,
sizeof(session->DAA_joinSession.DAA_digest_n0.digest));
tpm_sha1_final(&sha1, session->DAA_session.DAA_digest.digest);
/* Set outputData = DAA_session->DAA_scratch */
*outputSize = sizeof(session->DAA_session.DAA_scratch);
if ((*outputData = tpm_malloc(*outputSize)) != NULL) {
memcpy(*outputData, session->DAA_session.DAA_scratch, *outputSize);
} else {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
/* Set DAA_session->DAA_scratch = NULL */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 8:
{
/* Verify that DAA_session->DAA_stage == 8. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 8) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Verify inputSize0 == DAA_SIZE_NE and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (inputSize0 != DAA_SIZE_NE) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set NE = decrypt(inputData0, privEK) */
memset(scratch, 0, sizeof(scratch));
if (tpm_rsa_decrypt(&tpmData.permanent.data.endorsementKey,
RSA_ES_OAEP_SHA1, inputData0, inputSize0, scratch, &size)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DECRYPT_ERROR;
}
/* Set outputData = SHA-1(DAA_session->DAA_digest || NE) */
*outputSize = SHA1_DIGEST_LENGTH;
if ((*outputData = tpm_malloc(*outputSize)) == NULL) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, session->DAA_session.DAA_digest.digest,
sizeof(session->DAA_session.DAA_digest.digest));
tpm_sha1_update(&sha1, scratch, size);
tpm_sha1_final(&sha1, *outputData);
/* Set DAA_session->DAA_digest = NULL */
memset(&session->DAA_session.DAA_digest, 0,
sizeof(session->DAA_session.DAA_digest));
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 9:
{
/* Verify that DAA_session->DAA_stage == 9. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 9) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set DAA_generic_R0 = inputData0 */
DAA_generic_R0 = inputData0;
/* Verify that SHA-1(DAA_generic_R0) ==
* DAA_issuerSettings->DAA_digest_R0 and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_R0,
DAA_generic_R0, inputSize0, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set DAA_generic_n = inputData1 */
DAA_generic_n = inputData1;
/* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n
* and return error TPM_DAA_INPUT_DATA1 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n,
DAA_generic_n, inputSize1, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA1;
}
/* Obtain random data from the RNG and store it as
* DAA_session->DAA_contextSeed */
tpm_get_random_bytes(session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
/* Obtain DAA_SIZE_r0 bits from MGF1("r0",
* DAA_session->DAA_contextSeed), and label them Y */
memset(scratch, 0, sizeof(scratch));
memcpy(mgf1_seed, "r0", 2);
memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r0);
tpm_bn_init(Y);
tpm_bn_import(Y, DAA_SIZE_r0, 1, scratch);
/* Set X = DAA_generic_R0 */
tpm_bn_init(X);
tpm_bn_import(X, inputSize0, 1, DAA_generic_R0);
/* Set n = DAA_generic_n */
tpm_bn_init(n);
tpm_bn_import(n, inputSize1, 1, DAA_generic_n);
/* Set DAA_session->DAA_scratch = (X^Y) mod n */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
tpm_bn_init(tmp);
tpm_bn_powm(tmp, X, Y, n);
tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, tmp);
tpm_bn_clear(X), tpm_bn_clear(Y), tpm_bn_clear(n), tpm_bn_clear(tmp);
/* Set outputData = NULL */
*outputSize = 0, *outputData = NULL;
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 10:
{
/* Verify that DAA_session->DAA_stage == 10. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 10) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set DAA_generic_R1 = inputData0 */
DAA_generic_R1 = inputData0;
/* Verify that SHA-1(DAA_generic_R1) ==
* DAA_issuerSettings->DAA_digest_R1 and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_R1,
DAA_generic_R1, inputSize0, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set DAA_generic_n = inputData1 */
DAA_generic_n = inputData1;
/* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n
* and return error TPM_DAA_INPUT_DATA1 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n,
DAA_generic_n, inputSize1, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA1;
}
/* Obtain DAA_SIZE_r1 bits from MGF1("r1",
* DAA_session->DAA_contextSeed), and label them Y */
memset(scratch, 0, sizeof(scratch));
memcpy(mgf1_seed, "r1", 2);
memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r1);
tpm_bn_init(Y);
tpm_bn_import(Y, DAA_SIZE_r1, 1, scratch);
/* Set X = DAA_generic_R1 */
tpm_bn_init(X);
tpm_bn_import(X, inputSize0, 1, DAA_generic_R1);
/* Set n = DAA_generic_n */
tpm_bn_init(n);
tpm_bn_import(n, inputSize1, 1, DAA_generic_n);
/* Set Z = DAA_session->DAA_scratch */
tpm_bn_init(Z);
tpm_bn_import(Z, sizeof(session->DAA_session.DAA_scratch), -1,
session->DAA_session.DAA_scratch);
/* Set DAA_session->DAA_scratch = Z*(X^Y) mod n */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
tpm_bn_init(tmp);
tpm_bn_powm(tmp, X, Y, n);
tpm_bn_mul(tmp, tmp, Z);
tpm_bn_mod(tmp, tmp, n);
tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, tmp);
tpm_bn_clear(X), tpm_bn_clear(Y), tpm_bn_clear(Z), tpm_bn_clear(n), tpm_bn_clear(tmp);
/* Set outputData = NULL */
*outputSize = 0, *outputData = NULL;
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 11:
{
/* Verify that DAA_session->DAA_stage == 11. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 11) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set DAA_generic_S0 = inputData0 */
DAA_generic_S0 = inputData0;
/* Verify that SHA-1(DAA_generic_S0) ==
* DAA_issuerSettings->DAA_digest_S0 and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_S0,
DAA_generic_S0, inputSize0, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set DAA_generic_n = inputData1 */
DAA_generic_n = inputData1;
/* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n
* and return error TPM_DAA_INPUT_DATA1 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n,
DAA_generic_n, inputSize1, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA1;
}
/* Obtain DAA_SIZE_r2 bits from MGF1("r2",
* DAA_session->DAA_contextSeed), and label them Y */
memset(scratch, 0, sizeof(scratch));
memcpy(mgf1_seed, "r2", 2);
memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r2);
tpm_bn_init(Y);
tpm_bn_import(Y, DAA_SIZE_r2, 1, scratch);
/* Set X = DAA_generic_S0 */
tpm_bn_init(X);
tpm_bn_import(X, inputSize0, 1, DAA_generic_S0);
/* Set n = DAA_generic_n */
tpm_bn_init(n);
tpm_bn_import(n, inputSize1, 1, DAA_generic_n);
/* Set Z = DAA_session->DAA_scratch */
tpm_bn_init(Z);
tpm_bn_import(Z, sizeof(session->DAA_session.DAA_scratch), -1,
session->DAA_session.DAA_scratch);
/* Set DAA_session->DAA_scratch = Z*(X^Y) mod n */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
tpm_bn_init(tmp);
tpm_bn_powm(tmp, X, Y, n);
tpm_bn_mul(tmp, tmp, Z);
tpm_bn_mod(tmp, tmp, n);
tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, tmp);
tpm_bn_clear(X), tpm_bn_clear(Y), tpm_bn_clear(Z), tpm_bn_clear(n), tpm_bn_clear(tmp);
/* Set outputData = NULL */
*outputSize = 0, *outputData = NULL;
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 12:
{
/* Verify that DAA_session->DAA_stage == 12. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 12) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set DAA_generic_S1 = inputData0 */
DAA_generic_S1 = inputData0;
/* Verify that SHA-1(DAA_generic_S1) ==
* DAA_issuerSettings->DAA_digest_S1 and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_S1,
DAA_generic_S1, inputSize0, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set DAA_generic_n = inputData1 */
DAA_generic_n = inputData1;
/* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n
* and return error TPM_DAA_INPUT_DATA1 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n,
DAA_generic_n, inputSize1, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA1;
}
/* Obtain DAA_SIZE_r3 bits from MGF1("r3",
* DAA_session->DAA_contextSeed), and label them Y */
memset(scratch, 0, sizeof(scratch));
memcpy(mgf1_seed, "r3", 2);
memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r3);
tpm_bn_init(Y);
tpm_bn_import(Y, DAA_SIZE_r3, 1, scratch);
/* Set X = DAA_generic_S1 */
tpm_bn_init(X);
tpm_bn_import(X, inputSize0, 1, DAA_generic_S1);
/* Set n = DAA_generic_n */
tpm_bn_init(n);
tpm_bn_import(n, inputSize1, 1, DAA_generic_n);
/* Set Z = DAA_session->DAA_scratch */
tpm_bn_init(Z);
tpm_bn_import(Z, sizeof(session->DAA_session.DAA_scratch), -1,
session->DAA_session.DAA_scratch);
/* Set DAA_session->DAA_scratch = Z*(X^Y) mod n */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
tpm_bn_init(tmp);
tpm_bn_powm(tmp, X, Y, n);
tpm_bn_mul(tmp, tmp, Z);
tpm_bn_mod(tmp, tmp, n);
tpm_bn_export(session->DAA_session.DAA_scratch, &size, 1, tmp);
*outputSize = (uint32_t)size;
tpm_bn_clear(X), tpm_bn_clear(Y), tpm_bn_clear(Z), tpm_bn_clear(n), tpm_bn_clear(tmp);
/* Set outputData = DAA_session->DAA_scratch */
if ((*outputData = tpm_malloc(*outputSize)) != NULL)
memcpy(*outputData, session->DAA_session.DAA_scratch, *outputSize);
else {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
/* Set DAA_session->DAA_scratch = NULL */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 13:
{
/* Verify that DAA_session->DAA_stage == 13. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 13) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set DAA_generic_gamma = inputData0 */
DAA_generic_gamma = inputData0;
/* Verify that SHA-1(DAA_generic_gamma) ==
* DAA_issuerSettings->DAA_digest_gamma and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_gamma,
DAA_generic_gamma, inputSize0, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Verify that inputSize1 == DAA_SIZE_w and return error
* TPM_DAA_INPUT_DATA1 on mismatch */
if (inputSize1 != DAA_SIZE_w) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA1;
}
/* Set w = inputData1 */
tpm_bn_init(w);
tpm_bn_import(w, inputSize1, 1, inputData1);
/* Set w1 = w^(DAA_issuerSettings->DAA_generic_q) mod
* (DAA_generic_gamma) */
tpm_bn_init(gamma);
tpm_bn_import(gamma, inputSize0, 1, DAA_generic_gamma);
tpm_bn_init(q);
tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q),
1, session->DAA_issuerSettings.DAA_generic_q);
tpm_bn_init(w1);
tpm_bn_powm(w1, w, q, gamma);
/* If w1 != 1 (unity), return error TPM_DAA_WRONG_W */
if (tpm_bn_cmp_ui(w1, 1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_WRONG_W;
}
/* Set DAA_session->DAA_scratch = w */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, w);
tpm_bn_clear(w), tpm_bn_clear(gamma), tpm_bn_clear(w1), tpm_bn_clear(q);
/* Set outputData = NULL */
*outputSize = 0, *outputData = NULL;
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 14:
{
/* Verify that DAA_session->DAA_stage == 14. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 14) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set DAA_generic_gamma = inputData0 */
DAA_generic_gamma = inputData0;
/* Verify that SHA-1(DAA_generic_gamma) ==
* DAA_issuerSettings->DAA_digest_gamma and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_gamma,
DAA_generic_gamma, inputSize0, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set f = SHA-1(DAA_tpmSpecific->DAA_rekey ||
* DAA_tpmSpecific->DAA_count || 0) || SHA-1(DAA_tpmSpecific->DAA_rekey
* || DAA_tpmSpecific->DAA_count || 1) mod
* DAA_issuerSettings->DAA_generic_q. */
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey,
sizeof(session->DAA_tpmSpecific.DAA_rekey));
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count,
sizeof(session->DAA_tpmSpecific.DAA_count));
tpm_sha1_update(&sha1, DAA_LABEL_00, 1);
tpm_sha1_final(&sha1, scratch);
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey,
sizeof(session->DAA_tpmSpecific.DAA_rekey));
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count,
sizeof(session->DAA_tpmSpecific.DAA_count));
tpm_sha1_update(&sha1, DAA_LABEL_01, 1);
tpm_sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH);
tpm_bn_init(f), tpm_bn_init(q);
tpm_bn_import(f, 2 * SHA1_DIGEST_LENGTH, 1, scratch);
tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q),
1, session->DAA_issuerSettings.DAA_generic_q);
tpm_bn_mod(f, f, q);
/* Set E = ((DAA_session->DAA_scratch)^f) mod (DAA_generic_gamma).*/
tpm_bn_init(gamma);
tpm_bn_import(gamma, inputSize0, 1, DAA_generic_gamma);
tpm_bn_init(w);
tpm_bn_import(w, sizeof(session->DAA_session.DAA_scratch), -1,
session->DAA_session.DAA_scratch);
tpm_bn_init(E);
tpm_bn_powm(E, w, f, gamma);
/* Set outputData = E */
tpm_bn_export(scratch, &size, 1, E);
*outputSize = (uint32_t)size;
tpm_bn_clear(f), tpm_bn_clear(q), tpm_bn_clear(gamma), tpm_bn_clear(w), tpm_bn_clear(E);
if ((*outputData = tpm_malloc(*outputSize)) != NULL)
memcpy(*outputData, scratch, *outputSize);
else {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 15:
{
/* Verify that DAA_session->DAA_stage == 15. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 15) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set DAA_generic_gamma = inputData0 */
DAA_generic_gamma = inputData0;
/* Verify that SHA-1(DAA_generic_gamma) ==
* DAA_issuerSettings->DAA_digest_gamma and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_gamma,
DAA_generic_gamma, inputSize0, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Obtain DAA_SIZE_r0 bits from MGF1("r0",
* DAA_session->DAA_contextSeed), and label them r0 */
memset(scratch, 0, sizeof(scratch));
memcpy(mgf1_seed, "r0", 2);
memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r0);
tpm_bn_init(r0);
tpm_bn_import(r0, DAA_SIZE_r0, 1, scratch);
/* Obtain DAA_SIZE_r1 bits from MGF1("r1",
* DAA_session->DAA_contextSeed), and label them r1 */
memset(scratch, 0, sizeof(scratch));
memcpy(mgf1_seed, "r1", 2);
memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r1);
tpm_bn_init(r1);
tpm_bn_import(r1, DAA_SIZE_r1, 1, scratch);
/* Set r = r0 + 2^DAA_power0 * r1 mod
* (DAA_issuerSettings->DAA_generic_q). */
tpm_bn_init(q);
tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q),
1, session->DAA_issuerSettings.DAA_generic_q);
tpm_bn_init(r);
tpm_bn_ui_pow_ui(r, 2, DAA_power0);
tpm_bn_mul(r, r, r1);
tpm_bn_mod(r, r, q);
tpm_bn_add(r, r, r0);
tpm_bn_mod(r, r, q);
/* Set E1 = ((DAA_session->DAA_scratch)^r) mod (DAA_generic_gamma). */
tpm_bn_init(gamma);
tpm_bn_import(gamma, inputSize0, 1, DAA_generic_gamma);
tpm_bn_init(w);
tpm_bn_import(w, sizeof(session->DAA_session.DAA_scratch), -1,
session->DAA_session.DAA_scratch);
tpm_bn_init(E1);
tpm_bn_powm(E1, w, r, gamma);
/* Set DAA_session->DAA_scratch = NULL */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
/* Set outputData = E1 */
tpm_bn_export(scratch, &size, 1, E1);
*outputSize = (uint32_t)size;
tpm_bn_clear(r0), tpm_bn_clear(r1), tpm_bn_clear(q), tpm_bn_clear(r);
tpm_bn_clear(gamma), tpm_bn_clear(w), tpm_bn_clear(E1);
if ((*outputData = tpm_malloc(*outputSize)) != NULL)
memcpy(*outputData, scratch, *outputSize);
else {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 16:
{
BYTE *NT = NULL;
/* Verify that DAA_session->DAA_stage == 16. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 16) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Verify that inputSize0 == sizeOf(TPM_DIGEST) and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (inputSize0 != sizeof(TPM_DIGEST)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set DAA_session->DAA_digest = inputData0 */
memcpy(session->DAA_session.DAA_digest.digest, inputData0, inputSize0);
/* Obtain DAA_SIZE_NT bits from the RNG and label them NT */
if ((NT = tpm_malloc(DAA_SIZE_NT)) == NULL) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
tpm_get_random_bytes(NT, DAA_SIZE_NT);
/* Set DAA_session->DAA_digest to the SHA-1(DAA_session->DAA_digest ||
* NT)*/
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) session->DAA_session.DAA_digest.digest,
sizeof(session->DAA_session.DAA_digest.digest));
tpm_sha1_update(&sha1, NT, DAA_SIZE_NT);
tpm_sha1_final(&sha1, session->DAA_session.DAA_digest.digest);
/* Set outputData = NT */
*outputSize = DAA_SIZE_NT;
if ((*outputData = tpm_malloc(*outputSize)) != NULL)
memcpy(*outputData, NT, *outputSize);
else {
tpm_free(NT);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
tpm_free(NT);
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 17:
{
/* Verify that DAA_session->DAA_stage == 17. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 17) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Obtain DAA_SIZE_r0 bits from MGF1("r0",
* DAA_session->DAA_contextSeed), and label them r0 */
memset(scratch, 0, sizeof(scratch));
memcpy(mgf1_seed, "r0", 2);
memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r0);
tpm_bn_init(r0);
tpm_bn_import(r0, DAA_SIZE_r0, 1, scratch);
/* Set f = SHA1(DAA_tpmSpecific->DAA_rekey ||
* DAA_tpmSpecific->DAA_count || 0 ) ||
* SHA1(DAA_tpmSpecific->DAA_rekey || DAA_tpmSpecific->DAA_count ||
* 1 ) mod DAA_issuerSettings->DAA_generic_q */
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey,
sizeof(session->DAA_tpmSpecific.DAA_rekey));
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count,
sizeof(session->DAA_tpmSpecific.DAA_count));
tpm_sha1_update(&sha1, DAA_LABEL_00, 1);
tpm_sha1_final(&sha1, scratch);
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey,
sizeof(session->DAA_tpmSpecific.DAA_rekey));
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count,
sizeof(session->DAA_tpmSpecific.DAA_count));
tpm_sha1_update(&sha1, DAA_LABEL_01, 1);
tpm_sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH);
tpm_bn_init(f), tpm_bn_init(q);
tpm_bn_import(f, 2 * SHA1_DIGEST_LENGTH, 1, scratch);
tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q),
1, session->DAA_issuerSettings.DAA_generic_q);
tpm_bn_mod(f, f, q);
/* Set f0 = f mod 2^DAA_power0 (erase all but the lowest DAA_power0
* bits of f) */
tpm_bn_init(f0);
tpm_bn_init(tmp);
tpm_bn_ui_pow_ui(tmp, 2, DAA_power0);
tpm_bn_mod(f0, f, tmp);
/* Set s0 = r0 + (DAA_session->DAA_digest) * f0 in Z */
tpm_bn_init(s0);
tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_digest.digest),
1, session->DAA_session.DAA_digest.digest);
tpm_bn_mul(s0, tmp, f0);
tpm_bn_add(s0, r0, s0);
/* Set outputData = s0 */
tpm_bn_export(scratch, &size, 1, s0);
*outputSize = (uint32_t)size;
tpm_bn_clear(r0), tpm_bn_clear(f), tpm_bn_clear(q), tpm_bn_clear(f0);
tpm_bn_clear(s0), tpm_bn_clear(tmp);
if ((*outputData = tpm_malloc(*outputSize)) != NULL)
memcpy(*outputData, scratch, *outputSize);
else {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 18:
{
/* Verify that DAA_session->DAA_stage == 18. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 18) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Obtain DAA_SIZE_r1 bits from MGF1("r1",
* DAA_session->DAA_contextSeed), and label them r1 */
memset(scratch, 0, sizeof(scratch));
memcpy(mgf1_seed, "r1", 2);
memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r1);
tpm_bn_init(r1);
tpm_bn_import(r1, DAA_SIZE_r1, 1, scratch);
/* Set f = SHA1(DAA_tpmSpecific->DAA_rekey ||
* DAA_tpmSpecific->DAA_count || 0 ) ||
* SHA1(DAA_tpmSpecific->DAA_rekey || DAA_tpmSpecific->DAA_count ||
* 1 ) mod DAA_issuerSettings->DAA_generic_q */
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey,
sizeof(session->DAA_tpmSpecific.DAA_rekey));
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count,
sizeof(session->DAA_tpmSpecific.DAA_count));
tpm_sha1_update(&sha1, DAA_LABEL_00, 1);
tpm_sha1_final(&sha1, scratch);
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey,
sizeof(session->DAA_tpmSpecific.DAA_rekey));
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count,
sizeof(session->DAA_tpmSpecific.DAA_count));
tpm_sha1_update(&sha1, DAA_LABEL_01, 1);
tpm_sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH);
tpm_bn_init(f), tpm_bn_init(q);
tpm_bn_import(f, 2 * SHA1_DIGEST_LENGTH, 1, scratch);
tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q),
1, session->DAA_issuerSettings.DAA_generic_q);
tpm_bn_mod(f, f, q);
/* Shift f right by DAA_power0 bits (discard the lowest DAA_power0
* bits) and label the result f1 */
tpm_bn_init(f1);
tpm_bn_fdiv_q_2exp(f1, f, DAA_power0);
/* Set s1 = r1 + (DAA_session->DAA_digest) * f1 in Z */
tpm_bn_init(s1);
tpm_bn_init(tmp);
tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_digest.digest),
1, session->DAA_session.DAA_digest.digest);
tpm_bn_mul(s1, tmp, f1);
tpm_bn_add(s1, r1, s1);
/* Set outputData = s1 */
tpm_bn_export(scratch, &size, 1, s1);
*outputSize = (uint32_t)size;
tpm_bn_clear(r1), tpm_bn_clear(f), tpm_bn_clear(q), tpm_bn_clear(f1);
tpm_bn_clear(s1), tpm_bn_clear(tmp);
if ((*outputData = tpm_malloc(*outputSize)) != NULL)
memcpy(*outputData, scratch, *outputSize);
else {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 19:
{
/* Verify that DAA_session->DAA_stage == 19. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 19) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Obtain DAA_SIZE_r2 bits from MGF1("r2",
* DAA_session->DAA_contextSeed), and label them r2 */
memset(scratch, 0, sizeof(scratch));
memcpy(mgf1_seed, "r2", 2);
memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r2);
tpm_bn_init(r2);
tpm_bn_import(r2, DAA_SIZE_r2, 1, scratch);
/* Set s2 = r2 + (DAA_session->DAA_digest) *
* (DAA_joinSession->DAA_join_u0) mod 2^DAA_power1
* (Erase all but the lowest DAA_power1 bits of s2) */
tpm_bn_init(s2);
tpm_bn_import(s2, sizeof(session->DAA_joinSession.DAA_join_u0),
1, session->DAA_joinSession.DAA_join_u0);
tpm_bn_init(tmp);
tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_digest.digest),
1, session->DAA_session.DAA_digest.digest);
tpm_bn_mul(s2, tmp, s2);
tpm_bn_add(s2, r2, s2);
tpm_bn_ui_pow_ui(tmp, 2, DAA_power1);
tpm_bn_mod(s2, s2, tmp);
/* Set DAA_session->DAA_scratch = s2 */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, s2);
/* Set outputData = s2 */
tpm_bn_export(scratch, &size, 1, s2);
*outputSize = (uint32_t)size;
tpm_bn_clear(r2), tpm_bn_clear(s2), tpm_bn_clear(tmp);
if ((*outputData = tpm_malloc(*outputSize)) != NULL)
memcpy(*outputData, scratch, *outputSize);
else {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 20:
{
/* Verify that DAA_session->DAA_stage == 20. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 20) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Obtain DAA_SIZE_r2 bits from MGF1("r2",
* DAA_session->DAA_contextSeed), and label them r2 */
memset(scratch, 0, sizeof(scratch));
memcpy(mgf1_seed, "r2", 2);
memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r2);
tpm_bn_init(r2);
tpm_bn_import(r2, DAA_SIZE_r2, 1, scratch);
/* Set s12 = r2 + (DAA_session->DAA_digest) *
* (DAA_joinSession->DAA_join_u0) */
tpm_bn_init(s12);
tpm_bn_import(s12, sizeof(session->DAA_joinSession.DAA_join_u0),
1, session->DAA_joinSession.DAA_join_u0);
tpm_bn_init(tmp);
tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_digest.digest),
1, session->DAA_session.DAA_digest.digest);
tpm_bn_mul(s12, tmp, s12);
tpm_bn_add(s12, r2, s12);
/* Shift s12 right by DAA_power1 bit (discard the lowest DAA_power1
* bits). */
tpm_bn_fdiv_q_2exp(s12, s12, DAA_power1);
/* Set DAA_session->DAA_scratch = s12 */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, s12);
tpm_bn_clear(r2), tpm_bn_clear(s12), tpm_bn_clear(tmp);
/* Set outputData = DAA_session->DAA_digest */
*outputSize = sizeof(session->DAA_session.DAA_digest.digest);
if ((*outputData = tpm_malloc(*outputSize)) != NULL)
memcpy(*outputData, session->DAA_session.DAA_digest.digest,
*outputSize);
else {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 21:
{
/* Verify that DAA_session->DAA_stage == 21. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 21) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Obtain DAA_SIZE_r3 bits from MGF1("r3",
* DAA_session->DAA_contextSeed), and label them r3 */
memset(scratch, 0, sizeof(scratch));
memcpy(mgf1_seed, "r3", 2);
memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r3);
tpm_bn_init(r3);
tpm_bn_import(r3, DAA_SIZE_r3, 1, scratch);
/* Set s3 = r3 + (DAA_session->DAA_digest) *
* (DAA_joinSession->DAA_join_u1) + (DAA_session->DAA_scratch). */
tpm_bn_init(s3);
tpm_bn_import(s3, sizeof(session->DAA_joinSession.DAA_join_u1),
1, session->DAA_joinSession.DAA_join_u1);
tpm_bn_init(tmp);
tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_digest.digest),
1, session->DAA_session.DAA_digest.digest);
tpm_bn_mul(s3, tmp, s3);
tpm_bn_add(s3, r3, s3);
tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_scratch),
-1, session->DAA_session.DAA_scratch);
tpm_bn_add(s3, s3, tmp);
/* Set DAA_session->DAA_scratch = NULL */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
/* Set outputData = s3 */
tpm_bn_export(scratch, &size, 1, s3);
*outputSize = (uint32_t)size;
tpm_bn_clear(r3), tpm_bn_clear(s3), tpm_bn_clear(tmp);
if ((*outputData = tpm_malloc(*outputSize)) != NULL)
memcpy(*outputData, scratch, *outputSize);
else {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 22:
{
/* Verify that DAA_session->DAA_stage == 22. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 22) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Verify inputSize0 == DAA_SIZE_v0 and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (inputSize0 != DAA_SIZE_v0) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set u2 = inputData0 */
tpm_bn_init(u2);
tpm_bn_import(u2, DAA_SIZE_v0, 1, inputData0);
/* Set v0 = u2 + (DAA_joinSession->DAA_join_u0) mod 2^DAA_power1
* (Erase all but the lowest DAA_power1 bits of v0). */
tpm_bn_init(v0);
tpm_bn_import(v0, sizeof(session->DAA_joinSession.DAA_join_u0),
1, session->DAA_joinSession.DAA_join_u0);
tpm_bn_add(v0, u2, v0);
tpm_bn_init(tmp);
tpm_bn_ui_pow_ui(tmp, 2, DAA_power1);
tpm_bn_mod(v0, v0, tmp);
/* Set DAA_tpmSpecific->DAA_digest_v0 = SHA-1(v0) */
tpm_bn_export(scratch, &size, 1, v0);
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) scratch, size);
tpm_sha1_final(&sha1, session->DAA_tpmSpecific.DAA_digest_v0.digest);
/* Set v10 = u2 + (DAA_joinSession->DAA_join_u0) in Z */
tpm_bn_init(v10);
tpm_bn_import(v10, sizeof(session->DAA_joinSession.DAA_join_u0),
1, session->DAA_joinSession.DAA_join_u0);
tpm_bn_add(v10, u2, v10);
/* Shift v10 right by DAA_power1 bits (erase the lowest DAA_power1
* bits). */
tpm_bn_fdiv_q_2exp(v10, v10, DAA_power1);
/* Set DAA_session->DAA_scratch = v10 */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, v10);
tpm_bn_clear(u2), tpm_bn_clear(v0), tpm_bn_clear(tmp), tpm_bn_clear(v10);
/* Set outputData */
memset(&blob, 0, sizeof(blob));
/* Fill in TPM_DAA_BLOB with a type of TPM_RT_DAA_V0 and encrypt
* the v0 parameters */
blob.tag = TPM_TAG_DAA_BLOB;
blob.resourceType = TPM_RT_DAA_V0;
memset(blob.label, 0, sizeof(blob.label));
memset(&blob.blobIntegrity, 0, sizeof(TPM_DIGEST));
blob.additionalSize = TPM_SYM_KEY_SIZE;
blob.additionalData = tpm_malloc(blob.additionalSize);
if (blob.additionalData == NULL) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
tpm_get_random_bytes(blob.additionalData, blob.additionalSize);
sensitive.tag = TPM_TAG_DAA_SENSITIVE;
sensitive.internalSize = size;
sensitive.internalData = scratch;
if (encrypt_daa(blob.additionalData, blob.additionalSize,
&sensitive, &blob.sensitiveData, &blob.sensitiveSize)) {
tpm_free(blob.additionalData);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_ENCRYPT_ERROR;
}
if (compute_daa_digest(&blob, &blob.blobIntegrity)) {
debug("TPM_DAA_Join(): compute_daa_digest() failed.");
tpm_free(blob.sensitiveData);
tpm_free(blob.additionalData);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_FAIL;
}
/* Set outputData to the encrypted TPM_DAA_BLOB */
*outputSize = sizeof_TPM_DAA_BLOB(blob);
if ((*outputData = tpm_malloc(*outputSize)) == NULL) {
tpm_free(blob.sensitiveData);
tpm_free(blob.additionalData);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
len = *outputSize;
ptr = *outputData;
if (tpm_marshal_TPM_DAA_BLOB(&ptr, &len, &blob)) {
debug("TPM_DAA_Join(): tpm_marshal_TPM_DAA_BLOB() failed.");
tpm_free(blob.sensitiveData);
tpm_free(blob.additionalData);
tpm_free(*outputData);
*outputSize = 0;
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_FAIL;
}
tpm_free(blob.sensitiveData);
tpm_free(blob.additionalData);
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Set DAA_session->DAA_digestContext = SHA-1(DAA_tpmSpecific ||
* DAA_joinSession) */
tpm_daa_update_digestContext(session, &sha1);
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 23:
{
/* Verify that DAA_session->DAA_stage == 23. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 23) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Verify inputSize0 == DAA_SIZE_v1 and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (inputSize0 != DAA_SIZE_v1) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set u3 = inputData0 */
tpm_bn_init(u3);
tpm_bn_import(u3, DAA_SIZE_v1, 1, inputData0);
/* Set v1 = u3 + DAA_joinSession->DAA_join_u1 +
* DAA_session->DAA_scratch */
tpm_bn_init(v1);
tpm_bn_import(v1, sizeof(session->DAA_joinSession.DAA_join_u1),
1, session->DAA_joinSession.DAA_join_u1);
tpm_bn_init(tmp);
tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_scratch),
-1, session->DAA_session.DAA_scratch);
tpm_bn_add(v1, v1, tmp);
tpm_bn_add(v1, u3, v1);
/* Set DAA_tpmSpecific->DAA_digest_v1 = SHA-1(v1) */
tpm_bn_export(scratch, &size, 1, v1);
tpm_bn_clear(u3), tpm_bn_clear(v1), tpm_bn_clear(tmp);
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) scratch, size);
tpm_sha1_final(&sha1, session->DAA_tpmSpecific.DAA_digest_v1.digest);
/* Set outputData */
memset(&blob, 0, sizeof(blob));
/* Fill in TPM_DAA_BLOB with a type of TPM_RT_DAA_V1 and encrypt
* the v1 parameters */
blob.tag = TPM_TAG_DAA_BLOB;
blob.resourceType = TPM_RT_DAA_V1;
memset(blob.label, 0, sizeof(blob.label));
memset(&blob.blobIntegrity, 0, sizeof(TPM_DIGEST));
blob.additionalSize = TPM_SYM_KEY_SIZE;
blob.additionalData = tpm_malloc(blob.additionalSize);
if (blob.additionalData == NULL) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
tpm_get_random_bytes(blob.additionalData, blob.additionalSize);
sensitive.tag = TPM_TAG_DAA_SENSITIVE;
sensitive.internalSize = size;
sensitive.internalData = scratch;
if (encrypt_daa(blob.additionalData, blob.additionalSize,
&sensitive, &blob.sensitiveData, &blob.sensitiveSize)) {
tpm_free(blob.additionalData);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_ENCRYPT_ERROR;
}
if (compute_daa_digest(&blob, &blob.blobIntegrity)) {
debug("TPM_DAA_Join(): compute_daa_digest() failed.");
tpm_free(blob.sensitiveData);
tpm_free(blob.additionalData);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_FAIL;
}
/* Set outputData to the encrypted TPM_DAA_BLOB */
*outputSize = sizeof_TPM_DAA_BLOB(blob);
if ((*outputData = tpm_malloc(*outputSize)) == NULL) {
tpm_free(blob.sensitiveData);
tpm_free(blob.additionalData);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
len = *outputSize;
ptr = *outputData;
if (tpm_marshal_TPM_DAA_BLOB(&ptr, &len, &blob)) {
debug("TPM_DAA_Join(): tpm_marshal_TPM_DAA_BLOB() failed.");
tpm_free(blob.sensitiveData);
tpm_free(blob.additionalData);
tpm_free(*outputData);
*outputSize = 0;
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_FAIL;
}
tpm_free(blob.sensitiveData);
tpm_free(blob.additionalData);
/* Set DAA_session->DAA_scratch = NULL */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Set DAA_session->DAA_digestContext = SHA-1(DAA_tpmSpecific ||
* DAA_joinSession) */
tpm_daa_update_digestContext(session, &sha1);
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 24:
{
/* Verify that DAA_session->DAA_stage == 24. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 24) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext ==
* SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error
* TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set outputData = enc(DAA_tpmSpecific) */
memset(&blob, 0, sizeof(blob));
blob.tag = TPM_TAG_DAA_BLOB;
blob.resourceType = TPM_RT_DAA_TPM;
memcpy(blob.label, "DAA_tpmSpecific", 15);
memset(&blob.blobIntegrity, 0, sizeof(TPM_DIGEST));
blob.additionalSize = TPM_SYM_KEY_SIZE;
blob.additionalData = tpm_malloc(blob.additionalSize);
if (blob.additionalData == NULL) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
tpm_get_random_bytes(blob.additionalData, blob.additionalSize);
sensitive.tag = TPM_TAG_DAA_SENSITIVE;
sensitive.internalSize = len = sizeof(TPM_DAA_TPM);
sensitive.internalData = ptr = tpm_malloc(sensitive.internalSize);
if (sensitive.internalData == NULL) {
tpm_free(blob.additionalData);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
if (tpm_marshal_TPM_DAA_TPM(&ptr, &len, &session->DAA_tpmSpecific)) {
debug("TPM_DAA_Join(): tpm_marshal_TPM_DAA_TPM() failed.");
tpm_free(blob.additionalData);
tpm_free(sensitive.internalData);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_FAIL;
}
if (encrypt_daa(blob.additionalData, blob.additionalSize,
&sensitive, &blob.sensitiveData, &blob.sensitiveSize)) {
tpm_free(blob.additionalData);
tpm_free(sensitive.internalData);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_ENCRYPT_ERROR;
}
if (compute_daa_digest(&blob, &blob.blobIntegrity)) {
debug("TPM_DAA_Join(): compute_daa_digest() failed.");
tpm_free(blob.sensitiveData);
tpm_free(sensitive.internalData);
tpm_free(blob.additionalData);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_FAIL;
}
*outputSize = sizeof_TPM_DAA_BLOB(blob);
if ((*outputData = tpm_malloc(*outputSize)) == NULL) {
tpm_free(blob.sensitiveData);
tpm_free(sensitive.internalData);
tpm_free(blob.additionalData);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
len = *outputSize;
ptr = *outputData;
if (tpm_marshal_TPM_DAA_BLOB(&ptr, &len, &blob)) {
debug("TPM_DAA_Join(): tpm_marshal_TPM_DAA_BLOB() failed.");
tpm_free(blob.sensitiveData);
tpm_free(sensitive.internalData);
tpm_free(blob.additionalData);
tpm_free(*outputData);
*outputSize = 0;
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_FAIL;
}
tpm_free(blob.sensitiveData);
tpm_free(sensitive.internalData);
tpm_free(blob.additionalData);
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
default:
return TPM_DAA_STAGE;
}
}
TPM_RESULT TPM_DAA_Sign(TPM_HANDLE handle, BYTE stage, UINT32 inputSize0,
BYTE *inputData0, UINT32 inputSize1,
BYTE *inputData1, TPM_AUTH *auth1,
TPM_COMMAND_CODE *ordinal, UINT32 *outputSize,
BYTE **outputData)
{
BYTE scratch[SCRATCH_SIZE];
TPM_DAA_SESSION_DATA *session = NULL;
TPM_RESULT res;
tpm_sha1_ctx_t sha1;
BYTE *ptr, *buf;
UINT32 len;
TPM_DAA_BLOB blob;
TPM_DAA_SENSITIVE sensitive;
TPM_DIGEST digest;
BYTE *DAA_generic_R0 = NULL, *DAA_generic_R1 = NULL, *DAA_generic_n = NULL,
*DAA_generic_S0 = NULL, *DAA_generic_S1 = NULL, *DAA_generic_gamma = NULL;
BYTE mgf1_seed[2 + sizeof(TPM_DIGEST)];
tpm_bn_t X, Y, Z, n, w1, w, gamma, q, f, E, r0, r1, r, E1, f0, s0, f1, s1,
r2, s2, s12, r4, s3, tmp;
BYTE selector;
size_t size;
TPM_KEY_DATA *aikData;
TPM_KEY_HANDLE aikHandle;
info("TPM_DAA_Sign()");
debug("handle = %.8x, stage = %d", handle, stage);
debug("stany.data.currentDAA = %.8x", tpmData.stany.data.currentDAA);
/* Initalize internal scratch pad */
memset(scratch, 0, SCRATCH_SIZE);
/* Verify authorization */
res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);
if (res != TPM_SUCCESS) return res;
/* Verify and initalize the session, for all stages greater than zero. */
if (stage > 0) {
if ((HANDLE_TO_INDEX(handle) >= TPM_MAX_SESSIONS_DAA) ||
(tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)].type !=
TPM_ST_DAA) ||
(tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)].handle !=
handle)) {
/* Probe, whether the handle from stany.data.currentDAA is valid. */
handle = tpmData.stany.data.currentDAA;
if ((HANDLE_TO_INDEX(handle) >= TPM_MAX_SESSIONS_DAA) ||
(tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)].type !=
TPM_ST_DAA) ||
(tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)].handle !=
handle))
return TPM_BAD_HANDLE;
}
session = &tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)];
}
/* TPM_DAA_SIGN [TPM_Part3], Section 26.2, Rev. 85 */
switch (stage) {
case 0:
{
/* Determine that sufficient resources are available to perform a
* DAA_Sign. Assign session handle for this DAA_Sign. */
handle = tpm_get_free_daa_session();
if (handle == TPM_INVALID_HANDLE)
return TPM_RESOURCES;
session = &tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)];
/* Verify that sizeOf(inputData0) == sizeOf(TPM_DAA_ISSUER)
* and return error TPM_DAA_INPUT_DATA0 on mismatch */
if (inputSize0 != sizeof(TPM_DAA_ISSUER)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set DAA_issuerSettings = inputData0. */
/* Verify that all fields in DAA_issuerSettings are present and
* return error TPM_DAA_INPUT_DATA0 if not. */
ptr = inputData0, len = inputSize0;
if (tpm_unmarshal_TPM_DAA_ISSUER(&ptr, &len,
&session->DAA_issuerSettings) || (len != 0) ||
(session->DAA_issuerSettings.tag != TPM_TAG_DAA_ISSUER)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set all fields in DAA_session = NULL */
memset(&session->DAA_session, 0, sizeof(TPM_DAA_CONTEXT));
/* Assign new handle for session */
tpmData.stany.data.currentDAA = handle;
debug("TPM_DAA_Sign() -- set handle := %.8x", handle);
/* Set outputData to new handle */
*outputSize = sizeof(TPM_HANDLE);
if ((*outputData = tpm_malloc(*outputSize)) != NULL) {
ptr = *outputData, len = *outputSize;
if (tpm_marshal_TPM_HANDLE(&ptr, &len, handle)) {
debug("TPM_DAA_Sign(): tpm_marshal_TPM_HANDLE() failed.");
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_FAIL;
}
} else {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
/* Set DAA_session->DAA_stage = 1 */
session->DAA_session.DAA_stage = 1;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 1:
{
/* Verify that DAA_session->DAA_stage == 1. Return TPM_DAA_STAGE and
* flush handle on mismatch */
if (session->DAA_session.DAA_stage != 1) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Set DAA_tpmSpecific = unwrap(inputData0) */
ptr = inputData0, len = inputSize0;
if (tpm_unmarshal_TPM_DAA_BLOB(&ptr, &len, &blob) || (len != 0)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
sensitive.internalData = scratch;
if (decrypt_daa(blob.additionalData, blob.additionalSize,
blob.sensitiveData, blob.sensitiveSize, &sensitive, &buf)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DECRYPT_ERROR;
}
if (compute_daa_digest(&blob, &digest) ||
memcmp(&digest, &blob.blobIntegrity, sizeof(TPM_DIGEST))) {
tpm_free(buf);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
if ((blob.resourceType != TPM_RT_DAA_TPM) ||
(sensitive.tag != TPM_TAG_DAA_SENSITIVE ||
(sensitive.internalSize != sizeof(TPM_DAA_TPM)))) {
tpm_free(buf);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
if (tpm_unmarshal_TPM_DAA_TPM(&sensitive.internalData,
&sensitive.internalSize, &session->DAA_tpmSpecific)) {
tpm_free(buf);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
tpm_free(buf);
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Set DAA_session->DAA_digestContext = SHA-1(DAA_tpmSpecific) */
tpm_daa_update_digestContext_sign(session, &sha1);
/* Obtain random data from the RNG and store it as
* DAA_session->DAA_contextSeed */
tpm_get_random_bytes(session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
/* Set outputData = NULL */
*outputSize = 0, *outputData = NULL;
/* Set DAA_session->DAA_stage = 2 */
session->DAA_session.DAA_stage = 2;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 2:
{
/* Verify that DAA_session->DAA_stage == 2. Return TPM_DAA_STAGE and
* flush handle on mismatch */
if (session->DAA_session.DAA_stage != 2) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific)
* and return error TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext_sign(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set DAA_generic_R0 = inputData0 */
DAA_generic_R0 = inputData0;
/* Verify that SHA-1(DAA_generic_R0) ==
* DAA_issuerSettings->DAA_digest_R0 and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_R0,
DAA_generic_R0, inputSize0, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set DAA_generic_n = inputData1 */
DAA_generic_n = inputData1;
/* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n
* and return error TPM_DAA_INPUT_DATA1 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n,
DAA_generic_n, inputSize1, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA1;
}
/* Obtain DAA_SIZE_r0 bits from MGF1("r0",
* DAA_session->DAA_contextSeed), and label them Y */
memset(scratch, 0, sizeof(scratch));
memcpy(mgf1_seed, "r0", 2);
memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r0);
tpm_bn_init(Y);
tpm_bn_import(Y, DAA_SIZE_r0, 1, scratch);
/* Set X = DAA_generic_R0 */
tpm_bn_init(X);
tpm_bn_import(X, inputSize0, 1, DAA_generic_R0);
/* Set n = DAA_generic_n */
tpm_bn_init(n);
tpm_bn_import(n, inputSize1, 1, DAA_generic_n);
/* Set DAA_session->DAA_scratch = (X^Y) mod n */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
tpm_bn_init(tmp);
tpm_bn_powm(tmp, X, Y, n);
tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, tmp);
tpm_bn_clear(X), tpm_bn_clear(Y), tpm_bn_clear(n), tpm_bn_clear(tmp);
/* Set outputData = NULL */
*outputSize = 0, *outputData = NULL;
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 3:
{
/* Verify that DAA_session->DAA_stage == 3. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 3) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific)
* and return error TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext_sign(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set DAA_generic_R1 = inputData0 */
DAA_generic_R1 = inputData0;
/* Verify that SHA-1(DAA_generic_R1) ==
* DAA_issuerSettings->DAA_digest_R1 and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_R1,
DAA_generic_R1, inputSize0, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set DAA_generic_n = inputData1 */
DAA_generic_n = inputData1;
/* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n
* and return error TPM_DAA_INPUT_DATA1 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n,
DAA_generic_n, inputSize1, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA1;
}
/* Obtain DAA_SIZE_r1 bits from MGF1("r1",
* DAA_session->DAA_contextSeed), and label them Y */
memset(scratch, 0, sizeof(scratch));
memcpy(mgf1_seed, "r1", 2);
memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r1);
tpm_bn_init(Y);
tpm_bn_import(Y, DAA_SIZE_r1, 1, scratch);
/* Set X = DAA_generic_R1 */
tpm_bn_init(X);
tpm_bn_import(X, inputSize0, 1, DAA_generic_R1);
/* Set n = DAA_generic_n */
tpm_bn_init(n);
tpm_bn_import(n, inputSize1, 1, DAA_generic_n);
/* Set Z = DAA_session->DAA_scratch */
tpm_bn_init(Z);
tpm_bn_import(Z, sizeof(session->DAA_session.DAA_scratch), -1,
session->DAA_session.DAA_scratch);
/* Set DAA_session->DAA_scratch = Z*(X^Y) mod n */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
tpm_bn_init(tmp);
tpm_bn_powm(tmp, X, Y, n);
tpm_bn_mul(tmp, tmp, Z);
tpm_bn_mod(tmp, tmp, n);
tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, tmp);
tpm_bn_clear(X), tpm_bn_clear(Y), tpm_bn_clear(Z), tpm_bn_clear(n), tpm_bn_clear(tmp);
/* Set outputData = NULL */
*outputSize = 0, *outputData = NULL;
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 4:
{
/* Verify that DAA_session->DAA_stage == 4. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 4) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific)
* and return error TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext_sign(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set DAA_generic_S0 = inputData0 */
DAA_generic_S0 = inputData0;
/* Verify that SHA-1(DAA_generic_S0) ==
* DAA_issuerSettings->DAA_digest_S0 and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_S0,
DAA_generic_S0, inputSize0, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set DAA_generic_n = inputData1 */
DAA_generic_n = inputData1;
/* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n
* and return error TPM_DAA_INPUT_DATA1 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n,
DAA_generic_n, inputSize1, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA1;
}
/* Obtain DAA_SIZE_r2 bits from MGF1("r2",
* DAA_session->DAA_contextSeed), and label them Y */
memset(scratch, 0, sizeof(scratch));
memcpy(mgf1_seed, "r2", 2);
memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r2);
tpm_bn_init(Y);
tpm_bn_import(Y, DAA_SIZE_r2, 1, scratch);
/* Set X = DAA_generic_S0 */
tpm_bn_init(X);
tpm_bn_import(X, inputSize0, 1, DAA_generic_S0);
/* Set n = DAA_generic_n */
tpm_bn_init(n);
tpm_bn_import(n, inputSize1, 1, DAA_generic_n);
/* Set Z = DAA_session->DAA_scratch */
tpm_bn_init(Z);
tpm_bn_import(Z, sizeof(session->DAA_session.DAA_scratch), -1,
session->DAA_session.DAA_scratch);
/* Set DAA_session->DAA_scratch = Z*(X^Y) mod n */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
tpm_bn_init(tmp);
tpm_bn_powm(tmp, X, Y, n);
tpm_bn_mul(tmp, tmp, Z);
tpm_bn_mod(tmp, tmp, n);
tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, tmp);
tpm_bn_clear(X), tpm_bn_clear(Y), tpm_bn_clear(Z), tpm_bn_clear(n), tpm_bn_clear(tmp);
/* Set outputData = NULL */
*outputSize = 0, *outputData = NULL;
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 5:
{
/* Verify that DAA_session->DAA_stage == 5. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 5) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific)
* and return error TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext_sign(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set DAA_generic_S1 = inputData0 */
DAA_generic_S1 = inputData0;
/* Verify that SHA-1(DAA_generic_S1) ==
* DAA_issuerSettings->DAA_digest_S1 and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_S1,
DAA_generic_S1, inputSize0, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set DAA_generic_n = inputData1 */
DAA_generic_n = inputData1;
/* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n
* and return error TPM_DAA_INPUT_DATA1 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n,
DAA_generic_n, inputSize1, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA1;
}
/* Obtain DAA_SIZE_r4 bits from MGF1("r4",
* DAA_session->DAA_contextSeed), and label them Y */
memset(scratch, 0, sizeof(scratch));
memcpy(mgf1_seed, "r4", 2);
memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r4);
tpm_bn_init(Y);
tpm_bn_import(Y, DAA_SIZE_r4, 1, scratch);
/* Set X = DAA_generic_S1 */
tpm_bn_init(X);
tpm_bn_import(X, inputSize0, 1, DAA_generic_S1);
/* Set n = DAA_generic_n */
tpm_bn_init(n);
tpm_bn_import(n, inputSize1, 1, DAA_generic_n);
/* Set Z = DAA_session->DAA_scratch */
tpm_bn_init(Z);
tpm_bn_import(Z, sizeof(session->DAA_session.DAA_scratch), -1,
session->DAA_session.DAA_scratch);
/* Set DAA_session->DAA_scratch = Z*(X^Y) mod n */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
tpm_bn_init(tmp);
tpm_bn_powm(tmp, X, Y, n);
tpm_bn_mul(tmp, tmp, Z);
tpm_bn_mod(tmp, tmp, n);
tpm_bn_export(session->DAA_session.DAA_scratch, &size, 1, tmp);
*outputSize = (uint32_t)size;
tpm_bn_clear(X), tpm_bn_clear(Y), tpm_bn_clear(Z), tpm_bn_clear(n), tpm_bn_clear(tmp);
/* Set outputData = DAA_session->DAA_scratch */
if ((*outputData = tpm_malloc(*outputSize)) != NULL)
memcpy(*outputData, session->DAA_session.DAA_scratch, *outputSize);
else {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
/* Set DAA_session->DAA_scratch = NULL */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 6:
{
/* Verify that DAA_session->DAA_stage == 6. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 6) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific)
* and return error TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext_sign(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set DAA_generic_gamma = inputData0 */
DAA_generic_gamma = inputData0;
/* Verify that SHA-1(DAA_generic_gamma) ==
* DAA_issuerSettings->DAA_digest_gamma and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_gamma,
DAA_generic_gamma, inputSize0, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Verify that inputSize1 == DAA_SIZE_w and return error
* TPM_DAA_INPUT_DATA1 on mismatch */
if (inputSize1 != DAA_SIZE_w) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA1;
}
/* Set w = inputData1 */
tpm_bn_init(w);
tpm_bn_import(w, inputSize1, 1, inputData1);
/* Set w1 = w^(DAA_issuerSettings->DAA_generic_q) mod
* (DAA_generic_gamma) */
tpm_bn_init(gamma);
tpm_bn_import(gamma, inputSize0, 1, DAA_generic_gamma);
tpm_bn_init(q);
tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q),
1, session->DAA_issuerSettings.DAA_generic_q);
tpm_bn_init(w1);
tpm_bn_powm(w1, w, q, gamma);
/* If w1 != 1 (unity), return error TPM_DAA_WRONG_W */
if (tpm_bn_cmp_ui(w1, 1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_WRONG_W;
}
/* Set DAA_session->DAA_scratch = w */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, w);
tpm_bn_clear(w), tpm_bn_clear(gamma), tpm_bn_clear(w1), tpm_bn_clear(q);
/* Set outputData = NULL */
*outputSize = 0, *outputData = NULL;
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 7:
{
/* Verify that DAA_session->DAA_stage == 7. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 7) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific)
* and return error TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext_sign(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set DAA_generic_gamma = inputData0 */
DAA_generic_gamma = inputData0;
/* Verify that SHA-1(DAA_generic_gamma) ==
* DAA_issuerSettings->DAA_digest_gamma and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_gamma,
DAA_generic_gamma, inputSize0, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set f = SHA-1(DAA_tpmSpecific->DAA_rekey ||
* DAA_tpmSpecific->DAA_count || 0) || SHA-1(DAA_tpmSpecific->DAA_rekey
* || DAA_tpmSpecific->DAA_count || 1) mod
* DAA_issuerSettings->DAA_generic_q. */
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey,
sizeof(session->DAA_tpmSpecific.DAA_rekey));
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count,
sizeof(session->DAA_tpmSpecific.DAA_count));
tpm_sha1_update(&sha1, DAA_LABEL_00, 1);
tpm_sha1_final(&sha1, scratch);
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey,
sizeof(session->DAA_tpmSpecific.DAA_rekey));
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count,
sizeof(session->DAA_tpmSpecific.DAA_count));
tpm_sha1_update(&sha1, DAA_LABEL_01, 1);
tpm_sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH);
tpm_bn_init(f), tpm_bn_init(q);
tpm_bn_import(f, 2 * SHA1_DIGEST_LENGTH, 1, scratch);
tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q),
1, session->DAA_issuerSettings.DAA_generic_q);
tpm_bn_mod(f, f, q);
/* Set E = ((DAA_session->DAA_scratch)^f) mod (DAA_generic_gamma).*/
tpm_bn_init(gamma);
tpm_bn_import(gamma, inputSize0, 1, DAA_generic_gamma);
tpm_bn_init(w);
tpm_bn_import(w, sizeof(session->DAA_session.DAA_scratch), -1,
session->DAA_session.DAA_scratch);
tpm_bn_init(E);
tpm_bn_powm(E, w, f, gamma);
/* Set outputData = E */
tpm_bn_export(scratch, &size, 1, E);
*outputSize = (uint32_t)size;
tpm_bn_clear(f), tpm_bn_clear(q), tpm_bn_clear(gamma), tpm_bn_clear(w), tpm_bn_clear(E);
if ((*outputData = tpm_malloc(*outputSize)) != NULL)
memcpy(*outputData, scratch, *outputSize);
else {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 8:
{
/* Verify that DAA_session->DAA_stage == 8. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 8) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific)
* and return error TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext_sign(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set DAA_generic_gamma = inputData0 */
DAA_generic_gamma = inputData0;
/* Verify that SHA-1(DAA_generic_gamma) ==
* DAA_issuerSettings->DAA_digest_gamma and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_gamma,
DAA_generic_gamma, inputSize0, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Obtain DAA_SIZE_r0 bits from MGF1("r0",
* DAA_session->DAA_contextSeed), and label them r0 */
memset(scratch, 0, sizeof(scratch));
memcpy(mgf1_seed, "r0", 2);
memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r0);
tpm_bn_init(r0);
tpm_bn_import(r0, DAA_SIZE_r0, 1, scratch);
/* Obtain DAA_SIZE_r1 bits from MGF1("r1",
* DAA_session->DAA_contextSeed), and label them r1 */
memset(scratch, 0, sizeof(scratch));
memcpy(mgf1_seed, "r1", 2);
memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r1);
tpm_bn_init(r1);
tpm_bn_import(r1, DAA_SIZE_r1, 1, scratch);
/* Set r = r0 + 2^DAA_power0 * r1 mod
* (DAA_issuerSettings->DAA_generic_q). */
tpm_bn_init(q);
tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q),
1, session->DAA_issuerSettings.DAA_generic_q);
tpm_bn_init(r);
tpm_bn_ui_pow_ui(r, 2, DAA_power0);
tpm_bn_mul(r, r, r1);
tpm_bn_mod(r, r, q);
tpm_bn_add(r, r, r0);
tpm_bn_mod(r, r, q);
/* Set E1 = ((DAA_session->DAA_scratch)^r) mod (DAA_generic_gamma). */
tpm_bn_init(gamma);
tpm_bn_import(gamma, inputSize0, 1, DAA_generic_gamma);
tpm_bn_init(w);
tpm_bn_import(w, sizeof(session->DAA_session.DAA_scratch), -1,
session->DAA_session.DAA_scratch);
tpm_bn_init(E1);
tpm_bn_powm(E1, w, r, gamma);
/* Set DAA_session->DAA_scratch = NULL */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
/* Set outputData = E1 */
tpm_bn_export(scratch, &size, 1, E1);
*outputSize = (uint32_t)size;
tpm_bn_clear(r0), tpm_bn_clear(r1), tpm_bn_clear(q), tpm_bn_clear(r);
tpm_bn_clear(gamma), tpm_bn_clear(w), tpm_bn_clear(E1);
if ((*outputData = tpm_malloc(*outputSize)) != NULL)
memcpy(*outputData, scratch, *outputSize);
else {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 9:
{
BYTE *NT = NULL;
/* Verify that DAA_session->DAA_stage == 9. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 9) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific)
* and return error TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext_sign(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Verify that inputSize0 == sizeOf(TPM_DIGEST) and return error
* TPM_DAA_INPUT_DATA0 on mismatch */
if (inputSize0 != sizeof(TPM_DIGEST)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Set DAA_session->DAA_digest = inputData0 */
memcpy(&session->DAA_session.DAA_digest, inputData0, inputSize0);
/* Obtain DAA_SIZE_NT bytes from the RNG and label them NT */
if ((NT = tpm_malloc(DAA_SIZE_NT)) == NULL) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
tpm_get_random_bytes(NT, DAA_SIZE_NT);
/* Set DAA_session->DAA_digest to the SHA-1(DAA_session->DAA_digest ||
* NT)*/
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_session.DAA_digest,
sizeof(session->DAA_session.DAA_digest));
tpm_sha1_update(&sha1, NT, DAA_SIZE_NT);
tpm_sha1_final(&sha1, session->DAA_session.DAA_digest.digest);
/* Set outputData = NT */
*outputSize = DAA_SIZE_NT;
if ((*outputData = tpm_malloc(*outputSize)) != NULL)
memcpy(*outputData, NT, *outputSize);
else {
tpm_free(NT);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
tpm_free(NT);
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 10:
{
/* Verify that DAA_session->DAA_stage == 10. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 10) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific)
* and return error TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext_sign(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set selector = inputData0, verify that selector == 0 or 1, and
* return error TPM_DAA_INPUT_DATA0 on mismatch */
if (inputSize0 != sizeof(selector)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
memcpy(&selector, inputData0, sizeof(selector));
if ((selector != '\x00') && (selector != '\x01')) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* If selector == 1, verify that inputSize1 == sizeOf(TPM_DIGEST), and */
if (selector == '\x01') {
debug("DAA_Sign(): selector == 1");
if (inputSize1 != sizeof(TPM_DIGEST)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA1;
}
/* Set DAA_session->DAA_digest to SHA-1(DAA_session->DAA_digest ||
* 1 || inputData1) */
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_session.DAA_digest,
sizeof(session->DAA_session.DAA_digest));
tpm_sha1_update(&sha1, DAA_LABEL_01, 1);
tpm_sha1_update(&sha1, inputData1, inputSize1);
tpm_sha1_final(&sha1, (BYTE*) &session->DAA_session.DAA_digest);
}
/* If selector == 0, verify that inputData1 is a handle to a TPM
* identity key (AIK), and */
if (selector == '\x00') {
debug("DAA_Sign(): selector == 0");
if (tpm_unmarshal_TPM_KEY_HANDLE(&inputData1, &inputSize1,
&aikHandle) || (inputSize1 != 0))
{
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA1;
}
debug("DAA_Sign(): aikHandle == %.8x", aikHandle);
aikData = tpm_get_key(aikHandle);
if (aikData == NULL) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA1;
}
if (aikData->keyUsage != TPM_KEY_IDENTITY) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA1;
}
/* Set DAA_session->DAA_digest to SHA-1(DAA_session->DAA_digest ||
* 0 || n2) where n2 is the modulus of the AIK */
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_session.DAA_digest,
sizeof(session->DAA_session.DAA_digest));
tpm_sha1_update(&sha1, DAA_LABEL_00, 1);
tpm_rsa_export_modulus(&aikData->key, scratch, &size);
tpm_sha1_update(&sha1, scratch, size);
tpm_sha1_final(&sha1, (BYTE*) &session->DAA_session.DAA_digest);
}
/* Set outputData = DAA_session->DAA_digest */
*outputSize = sizeof(session->DAA_session.DAA_digest);
if ((*outputData = tpm_malloc(*outputSize)) != NULL)
memcpy(*outputData, &session->DAA_session.DAA_digest, *outputSize);
else {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 11:
{
/* Verify that DAA_session->DAA_stage == 11. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 11) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific)
* and return error TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext_sign(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Obtain DAA_SIZE_r0 bits from MGF1("r0",
* DAA_session->DAA_contextSeed), and label them r0 */
memset(scratch, 0, sizeof(scratch));
memcpy(mgf1_seed, "r0", 2);
memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r0);
tpm_bn_init(r0);
tpm_bn_import(r0, DAA_SIZE_r0, 1, scratch);
/* Set f = SHA1(DAA_tpmSpecific->DAA_rekey ||
* DAA_tpmSpecific->DAA_count || 0 ) ||
* SHA1(DAA_tpmSpecific->DAA_rekey || DAA_tpmSpecific->DAA_count ||
* 1 ) mod DAA_issuerSettings->DAA_generic_q */
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey,
sizeof(session->DAA_tpmSpecific.DAA_rekey));
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count,
sizeof(session->DAA_tpmSpecific.DAA_count));
tpm_sha1_update(&sha1, DAA_LABEL_00, 1);
tpm_sha1_final(&sha1, scratch);
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey,
sizeof(session->DAA_tpmSpecific.DAA_rekey));
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count,
sizeof(session->DAA_tpmSpecific.DAA_count));
tpm_sha1_update(&sha1, DAA_LABEL_01, 1);
tpm_sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH);
tpm_bn_init(f), tpm_bn_init(q);
tpm_bn_import(f, 2 * SHA1_DIGEST_LENGTH, 1, scratch);
tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q),
1, session->DAA_issuerSettings.DAA_generic_q);
tpm_bn_mod(f, f, q);
/* Set f0 = f mod 2^DAA_power0 (erase all but the lowest DAA_power0
* bits of f) */
tpm_bn_init(f0);
tpm_bn_init(tmp);
tpm_bn_ui_pow_ui(tmp, 2, DAA_power0);
tpm_bn_mod(f0, f, tmp);
/* Set s0 = r0 + (DAA_session->DAA_digest) * (f0) */
tpm_bn_init(s0);
tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_digest.digest),
1, session->DAA_session.DAA_digest.digest);
tpm_bn_mul(s0, tmp, f0);
tpm_bn_add(s0, r0, s0);
/* Set outputData = s0 */
tpm_bn_export(scratch, &size, 1, s0);
*outputSize = (uint32_t)size;
tpm_bn_clear(r0), tpm_bn_clear(f), tpm_bn_clear(q), tpm_bn_clear(f0);
tpm_bn_clear(s0), tpm_bn_clear(tmp);
if ((*outputData = tpm_malloc(*outputSize)) != NULL)
memcpy(*outputData, scratch, *outputSize);
else {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 12:
{
/* Verify that DAA_session->DAA_stage == 12. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 12) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific)
* and return error TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext_sign(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Obtain DAA_SIZE_r1 bits from MGF1("r1",
* DAA_session->DAA_contextSeed), and label them r1 */
memset(scratch, 0, sizeof(scratch));
memcpy(mgf1_seed, "r1", 2);
memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r1);
tpm_bn_init(r1);
tpm_bn_import(r1, DAA_SIZE_r1, 1, scratch);
/* Set f = SHA1(DAA_tpmSpecific->DAA_rekey ||
* DAA_tpmSpecific->DAA_count || 0 ) ||
* SHA1(DAA_tpmSpecific->DAA_rekey || DAA_tpmSpecific->DAA_count ||
* 1 ) mod DAA_issuerSettings->DAA_generic_q */
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey,
sizeof(session->DAA_tpmSpecific.DAA_rekey));
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count,
sizeof(session->DAA_tpmSpecific.DAA_count));
tpm_sha1_update(&sha1, DAA_LABEL_00, 1);
tpm_sha1_final(&sha1, scratch);
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey,
sizeof(session->DAA_tpmSpecific.DAA_rekey));
tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count,
sizeof(session->DAA_tpmSpecific.DAA_count));
tpm_sha1_update(&sha1, DAA_LABEL_01, 1);
tpm_sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH);
tpm_bn_init(f), tpm_bn_init(q);
tpm_bn_import(f, 2 * SHA1_DIGEST_LENGTH, 1, scratch);
tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q),
1, session->DAA_issuerSettings.DAA_generic_q);
tpm_bn_mod(f, f, q);
/* Shift f right by DAA_power0 bits (discard the lowest DAA_power0
* bits) and label the result f1 */
tpm_bn_init(f1);
tpm_bn_fdiv_q_2exp(f1, f, DAA_power0);
/* Set s1 = r1 + (DAA_session->DAA_digest) * (f1) */
tpm_bn_init(s1);
tpm_bn_init(tmp);
tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_digest.digest),
1, session->DAA_session.DAA_digest.digest);
tpm_bn_mul(s1, tmp, f1);
tpm_bn_add(s1, r1, s1);
/* Set outputData = s1 */
tpm_bn_export(scratch, &size, 1, s1);
*outputSize = (uint32_t)size;
tpm_bn_clear(r1), tpm_bn_clear(f), tpm_bn_clear(q), tpm_bn_clear(f1);
tpm_bn_clear(s1), tpm_bn_clear(tmp);
if ((*outputData = tpm_malloc(*outputSize)) != NULL)
memcpy(*outputData, scratch, *outputSize);
else {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 13:
{
BYTE *DAA_private_v0 = NULL;
/* Verify that DAA_session->DAA_stage == 13. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 13) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific)
* and return error TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext_sign(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set DAA_private_v0 = unwrap(inputData0) */
ptr = inputData0, len = inputSize0;
if (tpm_unmarshal_TPM_DAA_BLOB(&ptr, &len, &blob) || (len != 0)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
sensitive.internalData = scratch;
if (decrypt_daa(blob.additionalData, blob.additionalSize,
blob.sensitiveData, blob.sensitiveSize, &sensitive, &buf)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DECRYPT_ERROR;
}
if (compute_daa_digest(&blob, &digest) ||
memcmp(&digest, &blob.blobIntegrity, sizeof(TPM_DIGEST))) {
tpm_free(buf);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
if ((blob.resourceType != TPM_RT_DAA_V0) ||
(sensitive.tag != TPM_TAG_DAA_SENSITIVE ||
(sensitive.internalSize == 0) ||
(sensitive.internalSize > DAA_SIZE_v0))) {
tpm_free(buf);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
if ((DAA_private_v0 = tpm_malloc(DAA_SIZE_v0)) == NULL) {
tpm_free(buf);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
memcpy(DAA_private_v0, sensitive.internalData, sensitive.internalSize);
tpm_free(buf);
/* Verify that SHA-1(DAA_private_v0) == DAA_tpmSpecific->DAA_digest_v0
* and return error TPM_DAA_INPUT_DATA0 on mismatch */
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, DAA_private_v0, sensitive.internalSize);
tpm_sha1_final(&sha1, (BYTE*) &digest);
if (memcmp(&digest, &session->DAA_tpmSpecific.DAA_digest_v0,
sizeof(TPM_DIGEST))) {
tpm_free(DAA_private_v0);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Obtain DAA_SIZE_r2 bits from MGF1("r2",
* DAA_session->DAA_contextSeed), and label them r2 */
memset(scratch, 0, sizeof(scratch));
memcpy(mgf1_seed, "r2", 2);
memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r2);
tpm_bn_init(r2);
tpm_bn_import(r2, DAA_SIZE_r2, 1, scratch);
/* Set s2 = r2 + (DAA_session->DAA_digest) *
* (DAA_private_v0) mod 2^DAA_power1
* (Erase all but the lowest DAA_power1 bits of s2) */
tpm_bn_init(s2);
tpm_bn_import(s2, sensitive.internalSize, 1, DAA_private_v0);
tpm_free(DAA_private_v0);
tpm_bn_init(tmp);
tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_digest.digest),
1, session->DAA_session.DAA_digest.digest);
tpm_bn_mul(s2, tmp, s2);
tpm_bn_add(s2, r2, s2);
tpm_bn_ui_pow_ui(tmp, 2, DAA_power1);
tpm_bn_mod(s2, s2, tmp);
/* Set DAA_session->DAA_scratch = s2 */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, s2);
/* Set outputData = s2 */
tpm_bn_export(scratch, &size, 1, s2);
*outputSize = (uint32_t)size;
tpm_bn_clear(r2), tpm_bn_clear(s2), tpm_bn_clear(tmp);
if ((*outputData = tpm_malloc(*outputSize)) != NULL)
memcpy(*outputData, scratch, *outputSize);
else {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 14:
{
BYTE *DAA_private_v0 = NULL;
/* Verify that DAA_session->DAA_stage == 14. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 14) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific)
* and return error TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext_sign(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set DAA_private_v0 = unwrap(inputData0) */
ptr = inputData0, len = inputSize0;
if (tpm_unmarshal_TPM_DAA_BLOB(&ptr, &len, &blob) || (len != 0)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
sensitive.internalData = scratch;
if (decrypt_daa(blob.additionalData, blob.additionalSize,
blob.sensitiveData, blob.sensitiveSize, &sensitive, &buf)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DECRYPT_ERROR;
}
if (compute_daa_digest(&blob, &digest) ||
memcmp(&digest, &blob.blobIntegrity, sizeof(TPM_DIGEST))) {
tpm_free(buf);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
if ((blob.resourceType != TPM_RT_DAA_V0) ||
(sensitive.tag != TPM_TAG_DAA_SENSITIVE ||
(sensitive.internalSize == 0) ||
(sensitive.internalSize > DAA_SIZE_v0))) {
tpm_free(buf);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
if ((DAA_private_v0 = tpm_malloc(DAA_SIZE_v0)) == NULL) {
tpm_free(buf);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
memcpy(DAA_private_v0, sensitive.internalData, sensitive.internalSize);
tpm_free(buf);
/* Verify that SHA-1(DAA_private_v0) == DAA_tpmSpecific->DAA_digest_v0
* and return error TPM_DAA_INPUT_DATA0 on mismatch */
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, DAA_private_v0, sensitive.internalSize);
tpm_sha1_final(&sha1, (BYTE*) &digest);
if (memcmp(&digest, &session->DAA_tpmSpecific.DAA_digest_v0,
sizeof(TPM_DIGEST))) {
tpm_free(DAA_private_v0);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Obtain DAA_SIZE_r2 bits from MGF1("r2",
* DAA_session->DAA_contextSeed), and label them r2 */
memset(scratch, 0, sizeof(scratch));
memcpy(mgf1_seed, "r2", 2);
memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r2);
tpm_bn_init(r2);
tpm_bn_import(r2, DAA_SIZE_r2, 1, scratch);
/* Set s12 = r2 + (DAA_session->DAA_digest) * (DAA_private_v0). */
tpm_bn_init(s12);
tpm_bn_import(s12, sensitive.internalSize, 1, DAA_private_v0);
tpm_free(DAA_private_v0);
tpm_bn_init(tmp);
tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_digest.digest),
1, session->DAA_session.DAA_digest.digest);
tpm_bn_mul(s12, tmp, s12);
tpm_bn_add(s12, r2, s12);
/* Shift s12 right by DAA_power1 bits (erase the lowest DAA_power1
* bits). */
tpm_bn_fdiv_q_2exp(s12, s12, DAA_power1);
/* Set DAA_session->DAA_scratch = s12 */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, s12);
tpm_bn_clear(r2), tpm_bn_clear(s12), tpm_bn_clear(tmp);
/* Set outputData = NULL */
*outputSize = 0, *outputData = NULL;
/* Increment DAA_session->DAA_stage by 1 */
session->DAA_session.DAA_stage++;
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
case 15:
{
BYTE *DAA_private_v1 = NULL;
/* Verify that DAA_session->DAA_stage == 15. Return TPM_DAA_STAGE
* and flush handle on mismatch */
if (session->DAA_session.DAA_stage != 15) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_STAGE;
}
/* Verify that DAA_tpmSpecific->DAA_digestIssuer ==
* SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS
* on mismatch */
if (tpm_daa_verify_digestIssuer(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_ISSUER_SETTINGS;
}
/* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific)
* and return error TPM_DAA_TPM_SETTINGS on mismatch */
if (tpm_daa_verify_digestContext_sign(session, &sha1)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_TPM_SETTINGS;
}
/* Set DAA_private_v1 = unwrap(inputData0) */
ptr = inputData0, len = inputSize0;
if (tpm_unmarshal_TPM_DAA_BLOB(&ptr, &len, &blob) || (len != 0)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
sensitive.internalData = scratch;
if (decrypt_daa(blob.additionalData, blob.additionalSize,
blob.sensitiveData, blob.sensitiveSize, &sensitive, &buf)) {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DECRYPT_ERROR;
}
if (compute_daa_digest(&blob, &digest) ||
memcmp(&digest, &blob.blobIntegrity, sizeof(TPM_DIGEST))) {
tpm_free(buf);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
if ((blob.resourceType != TPM_RT_DAA_V1) ||
(sensitive.tag != TPM_TAG_DAA_SENSITIVE ||
(sensitive.internalSize == 0) ||
(sensitive.internalSize > DAA_SIZE_v1))) {
tpm_free(buf);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
if ((DAA_private_v1 = tpm_malloc(DAA_SIZE_v1)) == NULL) {
tpm_free(buf);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
memcpy(DAA_private_v1, sensitive.internalData, sensitive.internalSize);
tpm_free(buf);
/* Verify that SHA-1(DAA_private_v1) == DAA_tpmSpecific->DAA_digest_v1
* and return error TPM_DAA_INPUT_DATA0 on mismatch */
tpm_sha1_init(&sha1);
tpm_sha1_update(&sha1, DAA_private_v1, sensitive.internalSize);
tpm_sha1_final(&sha1, (BYTE*) &digest);
if (memcmp(&digest, &session->DAA_tpmSpecific.DAA_digest_v1,
sizeof(TPM_DIGEST))) {
tpm_free(DAA_private_v1);
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_DAA_INPUT_DATA0;
}
/* Obtain DAA_SIZE_r4 bits from MGF1("r4",
* DAA_session->DAA_contextSeed), and label them r4 */
memset(scratch, 0, sizeof(scratch));
memcpy(mgf1_seed, "r4", 2);
memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce,
sizeof(TPM_NONCE));
tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r4);
tpm_bn_init(r4);
tpm_bn_import(r4, DAA_SIZE_r4, 1, scratch);
/* Set s3 = r4 + (DAA_session->DAA_digest) * (DAA_private_v1) +
* (DAA_session->DAA_scratch). */
tpm_bn_init(s3);
tpm_bn_import(s3, sensitive.internalSize, 1, DAA_private_v1);
tpm_free(DAA_private_v1);
tpm_bn_init(tmp);
tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_digest.digest),
1, session->DAA_session.DAA_digest.digest);
tpm_bn_mul(s3, tmp, s3);
tpm_bn_add(s3, r4, s3);
tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_scratch),
-1, session->DAA_session.DAA_scratch);
tpm_bn_add(s3, s3, tmp);
/* Set DAA_session->DAA_scratch = NULL */
memset(session->DAA_session.DAA_scratch, 0,
sizeof(session->DAA_session.DAA_scratch));
/* Set outputData = s3 */
tpm_bn_export(scratch, &size, 1, s3);
*outputSize = (uint32_t)size;
tpm_bn_clear(r4), tpm_bn_clear(s3), tpm_bn_clear(tmp);
if ((*outputData = tpm_malloc(*outputSize)) != NULL)
memcpy(*outputData, scratch, *outputSize);
else {
memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));
return TPM_NOSPACE;
}
/* Return TPM_SUCCESS */
return TPM_SUCCESS;
}
default:
return TPM_DAA_STAGE;
}
}