/* * hmacResult * * Description: * This function will return the N-byte message digest into the * Message_Digest array provided by the caller. * * Parameters: * context: [in/out] * The context to use to calculate the HMAC hash. * digest[ ]: [out] * Where the digest is returned. * NOTE 2: The length of the hash is determined by the value of * whichSha that was passed to hmacReset(). * * Returns: * sha Error Code. * */ int hmacResult(HMACContext *context, uint8_t *digest) { int ret; if (!context) return shaNull; if (context->Corrupted) return context->Corrupted; if (context->Computed) return context->Corrupted = shaStateError; /* finish up 1st pass */ /* (Use digest here as a temporary buffer.) */ ret = USHAResult(&context->shaContext, digest) || /* perform outer SHA */ /* init context for 2nd pass */ USHAReset(&context->shaContext, context->whichSha) || /* start with outer pad */ USHAInput(&context->shaContext, context->k_opad, context->blockSize) || /* then results of 1st hash */ USHAInput(&context->shaContext, digest, context->hashSize) || /* finish up 2nd pass */ USHAResult(&context->shaContext, digest); context->Computed = 1; return context->Corrupted = ret; }
/* * HMACResult * * Description: * This function will return the N-byte message digest into the * Message_Digest array provided by the caller. * NOTE: The first octet of hash is stored in the 0th element, * the last octet of hash in the Nth element. * * Parameters: * context: [in/out] * The context to use to calculate the HMAC hash. * digest: [out] * Where the digest is returned. * NOTE 2: The length of the hash is determined by the value of * whichSha that was passed to hmacReset(). * * Returns: * sha Error Code. * */ int hmacResult(HMACContext *ctx, uint8_t *digest) { if (!ctx) return shaNull; /* finish up 1st pass */ /* (Use digest here as a temporary buffer.) */ return USHAResult(&ctx->shaContext, digest) || /* perform outer SHA */ /* init context for 2nd pass */ USHAReset(&ctx->shaContext, (SHAversion)ctx->whichSha) || /* start with outer pad */ USHAInput(&ctx->shaContext, ctx->k_opad, ctx->blockSize) || /* then results of 1st hash */ USHAInput(&ctx->shaContext, digest, ctx->hashSize) || /* finish up 2nd pass */ USHAResult(&ctx->shaContext, digest); }
TSS_RESULT LIBTPMCALL TCS_Seal( UINT32 locality, TPM_KEY_HANDLE hParent, TPM_AUTHDATA * parentAuth, TPM_ENCAUTH * encDataAuth, UINT32 pcrInfoSize, BYTE * pcrInfo, UINT32 dataSize, BYTE * data, TPM_AUTH * auth, UINT32 * sealedDataSize, BYTE ** sealedData) { UINT64 offset = 0; TSS_RESULT result; UINT32 paramSize; BYTE txBlob[TSS_TPM_TXBLOB_SIZE]; TPM_COMMAND_CODE ordinal = TPM_ORD_Seal; BYTE bigendian_ordinal[sizeof(ordinal)]; BYTE bigendian_pcrInfoSize[sizeof(pcrInfoSize)]; BYTE bigendian_dataSize[sizeof(dataSize)]; TPM_NONCE h1; TPM_NONCE h1Check; struct USHAContext ctx_sha1; if(LIBTPM_IsInit() == false) { LOGERROR("libtpm not initialized"); return TCSERR(TSS_E_INTERNAL_ERROR); } LOGDEBUG("Entering TCS_Seal"); // Generate H1 USHAReset(&ctx_sha1, SHA1); UINT32ToArray(ordinal, bigendian_ordinal); UINT32ToArray(pcrInfoSize, bigendian_pcrInfoSize); UINT32ToArray(dataSize, bigendian_dataSize); USHAInput(&ctx_sha1, bigendian_ordinal, sizeof(bigendian_ordinal)); USHAInput(&ctx_sha1, encDataAuth->authdata, sizeof(encDataAuth->authdata)); USHAInput(&ctx_sha1, bigendian_pcrInfoSize, sizeof(bigendian_pcrInfoSize)); USHAInput(&ctx_sha1, pcrInfo, pcrInfoSize); USHAInput(&ctx_sha1, bigendian_dataSize, sizeof(bigendian_dataSize)); USHAInput(&ctx_sha1, data, dataSize); USHAResult(&ctx_sha1, (uint8_t *) &h1); memset(&ctx_sha1, 0, sizeof(ctx_sha1)); // Compute AUTH result = tcs_compute_auth(locality, auth, &h1, parentAuth); if(result) { return result; } // Communication with TPM result = tpm_rqu_build(TPM_ORD_Seal, &offset, txBlob, hParent, encDataAuth->authdata, pcrInfoSize, pcrInfo, dataSize, data, auth); if(result) { LOGDEBUG("tpm_rqu_build returns %x", result); return result; } UnloadBlob_Header(txBlob, ¶mSize); result = tpm_io(locality, txBlob, paramSize, txBlob, sizeof(txBlob)); if(result) { result = TDDLERR(result); LOGERROR("tpm_io returns %x", result); return result; } result = UnloadBlob_Header(txBlob, ¶mSize); if (! result) { result = tpm_rsp_parse(TPM_ORD_Seal, txBlob, paramSize, sealedDataSize, sealedData, auth); } if(! result) { // Check auth value USHAReset(&ctx_sha1, SHA1); USHAInput(&ctx_sha1, (uint8_t *) &result, sizeof(TPM_RESULT)); USHAInput(&ctx_sha1, bigendian_ordinal, sizeof(bigendian_ordinal)); USHAInput(&ctx_sha1, *sealedData, *sealedDataSize); USHAResult(&ctx_sha1, (uint8_t *) &h1Check); memset(&ctx_sha1, 0, sizeof(ctx_sha1)); result = tcs_check_auth(auth, &h1Check, parentAuth); if(result) { free(*sealedData); *sealedData = 0; } } LOGDEBUG("Exiting TCS_Seal : %x", result); return result; }
/* * hmacReset * * Description: * This function will initialize the hmacContext in preparation * for computing a new HMAC message digest. * * Parameters: * context: [in/out] * The context to reset. * whichSha: [in] * One of SHA1, SHA224, SHA256, SHA384, SHA512 * key: [in] * The secret shared key. * key_len: [in] * The length of the secret shared key. * * Returns: * sha Error Code. * */ int hmacReset(HMACContext *ctx, enum SHAversion whichSha, const unsigned char *key, int key_len) { int i, blocksize, hashsize; /* inner padding - key XORd with ipad */ unsigned char k_ipad[USHA_Max_Message_Block_Size]; /* temporary buffer when keylen > blocksize */ unsigned char tempkey[USHAMaxHashSize]; if (!ctx) return shaNull; blocksize = ctx->blockSize = USHABlockSize(whichSha); hashsize = ctx->hashSize = USHAHashSize(whichSha); ctx->whichSha = whichSha; /* * If key is longer than the hash blocksize, * reset it to key = HASH(key). */ if (key_len > blocksize) { USHAContext tctx; int err = USHAReset(&tctx, whichSha) || USHAInput(&tctx, key, key_len) || USHAResult(&tctx, tempkey); if (err != shaSuccess) return err; key = tempkey; key_len = hashsize; } /* * The HMAC transform looks like: * * SHA(K XOR opad, SHA(K XOR ipad, text)) * * where K is an n byte key. * ipad is the byte 0x36 repeated blocksize times * opad is the byte 0x5c repeated blocksize times * and text is the data being protected. */ /* store key into the pads, XOR'd with ipad and opad values */ for (i = 0; i < key_len; i++) { k_ipad[i] = key[i] ^ 0x36; ctx->k_opad[i] = key[i] ^ 0x5c; } /* remaining pad bytes are '\0' XOR'd with ipad and opad values */ for (; i < blocksize; i++) { k_ipad[i] = 0x36; ctx->k_opad[i] = 0x5c; } /* perform inner hash */ /* init context for 1st pass */ return USHAReset(&ctx->shaContext, whichSha) || /* and start with inner pad */ USHAInput(&ctx->shaContext, k_ipad, blocksize); }