void PrintTPMT_SIGNATURE( TPMT_SIGNATURE *sig ) { printf( "TPMT_SIGNATURE:\n" ); printf( "\tsigAlg = 0x%4.4x\n", sig->sigAlg ); printf( "\tsignature(TPMU_SIGNATURE):\n" ); switch ( sig->sigAlg ) { case TPM_ALG_RSASSA: case TPM_ALG_RSAPSS: printf( "\t\tTPMS_SIGNATURE_RSA:\n" ); printf( "\t\t\thash = 0x%4.4x\n", sig->signature.rsassa.hash ); printf( "\t\t\tsig(PUBLIC_KEY_RSA_2B):\n" ); printf( "\t\t\t\tsize = 0x%4.4x\n", sig->signature.rsassa.sig.t.size ); printf( "\t\t\t\tbuffer = " ); PrintSizedBuffer( &sig->signature.rsassa.sig.b ); break; case TPM_ALG_ECDSA: case TPM_ALG_ECDAA: case TPM_ALG_SM2: case TPM_ALG_ECSCHNORR: printf( "\t\tTPMS_SIGNATURE_ECC:\n" ); printf( "\t\t\thash = 0x%4.4x\n", sig->signature.ecdsa.hash); printf( "\t\t\tsignatureR(TPM2B_ECC_PARAMETER):\n" ); printf( "\t\t\t\tsize = 0x%4.4x\n", sig->signature.ecdsa.signatureR.t.size ); printf( "\t\t\t\tbuffer = " ); PrintSizedBuffer( &sig->signature.ecdsa.signatureR.b ); printf( "\t\t\tsignatureS(TPM2B_ECC_PARAMETER):\n" ); printf( "\t\t\t\tsize = 0x%4.4x\n", sig->signature.ecdsa.signatureS.t.size ); printf( "\t\t\t\tbuffer = " ); PrintSizedBuffer( &sig->signature.ecdsa.signatureS.b ); break; case TPM_ALG_HMAC: printf( "\t\tTPMS_HA:\n" ); printf( "\t\t\thashAlg = 0x%4.4x\n", sig->signature.hmac.hashAlg); printf( "\t\t\tdigest = " ); UINT16 size = 0; switch ( sig->signature.hmac.hashAlg ) { case TPM_ALG_SHA1: size = SHA1_DIGEST_SIZE; break; case TPM_ALG_SHA256: size = SHA256_DIGEST_SIZE; break; case TPM_ALG_SHA384: size = SHA384_DIGEST_SIZE; break; case TPM_ALG_SHA512: size = SHA512_DIGEST_SIZE; break; case TPM_ALG_SM3_256: size = SM3_256_DIGEST_SIZE; break; } PrintBuffer( (BYTE *)&sig->signature.hmac.digest, size ); break; } }
int quote(TPM_HANDLE akHandle, PCR_LIST pcrList, TPMI_ALG_HASH algorithmId) { UINT32 rval; TPM2B_DATA qualifyingData; UINT8 qualDataString[] = { 0x00, 0xff, 0x55, 0xaa }; TPMT_SIG_SCHEME inScheme; TPML_PCR_SELECTION pcrSelection; TPMS_AUTH_RESPONSE sessionDataOut; TSS2_SYS_CMD_AUTHS sessionsData; TSS2_SYS_RSP_AUTHS sessionsDataOut; TPM2B_ATTEST quoted = { { sizeof(TPM2B_ATTEST)-2, } }; TPMT_SIGNATURE signature; TPMS_AUTH_COMMAND *sessionDataArray[1]; TPMS_AUTH_RESPONSE *sessionDataOutArray[1]; sessionDataArray[0] = &sessionData; sessionDataOutArray[0] = &sessionDataOut; sessionsDataOut.rspAuths = &sessionDataOutArray[0]; sessionsData.cmdAuths = &sessionDataArray[0]; sessionsDataOut.rspAuthsCount = 1; sessionsData.cmdAuthsCount = 1; sessionData.sessionHandle = TPM_RS_PW; sessionData.nonce.t.size = 0; *( (UINT8 *)((void *)&sessionData.sessionAttributes ) ) = 0; if (sessionData.hmac.t.size > 0 && hexPasswd) { sessionData.hmac.t.size = sizeof(sessionData.hmac) - 2; if (hex2ByteStructure((char *)sessionData.hmac.t.buffer, &sessionData.hmac.t.size, sessionData.hmac.t.buffer) != 0) { printf( "Failed to convert Hex format password for AK Passwd.\n"); return -1; } } if(!qualifedData.t.size) { qualifyingData.t.size = sizeof( qualDataString ); memcpy( &qualifyingData.t.buffer[0], qualDataString, sizeof( qualDataString ) ); } else { qualifyingData = qualifedData; // shallow copy ok since there are no pointers } inScheme.scheme = TPM_ALG_NULL; pcrSelection.count = 1; pcrSelection.pcrSelections[0].hash = algorithmId; pcrSelection.pcrSelections[0].sizeofSelect = 3; // Clear out PCR select bit field pcrSelection.pcrSelections[0].pcrSelect[0] = 0; pcrSelection.pcrSelections[0].pcrSelect[1] = 0; pcrSelection.pcrSelections[0].pcrSelect[2] = 0; // Now set the PCR you want for(int l=0;l<pcrList.size; l++) { UINT32 pcrId = pcrList.id[l]; pcrSelection.pcrSelections[0].pcrSelect[( pcrId/8 )] |= ( 1 << ( pcrId) % 8); } memset( (void *)&signature, 0, sizeof(signature) ); rval = Tss2_Sys_Quote(sysContext, akHandle, &sessionsData, &qualifyingData, &inScheme, &pcrSelection, "ed, &signature, &sessionsDataOut ); if(rval != TPM_RC_SUCCESS) { printf("\nQuote Failed ! ErrorCode: 0x%0x\n\n", rval); return -1; } printf( "\nquoted:\n " ); PrintSizedBuffer( (TPM2B *)"ed ); //PrintTPM2B_ATTEST("ed); printf( "\nsignature:\n " ); PrintBuffer( (UINT8 *)&signature, sizeof(signature) ); //PrintTPMT_SIGNATURE(&signature); FILE *fp = fopen(outFilePath,"w+"); if(NULL == fp) { printf("OutFile: %s Can Not Be Created !\n",outFilePath); return -2; } if(fwrite("ed, calcSizeofTPM2B_ATTEST("ed), 1 ,fp) != 1) { fclose(fp); printf("OutFile: %s Write quoted Data In Error!\n",outFilePath); return -3; } if(fwrite(&signature, calcSizeofTPMT_SIGNATURE(&signature), 1, fp) != 1) { fclose(fp); printf("OutFile: %s Write signature Data In Error!\n",outFilePath); return -4; } fclose(fp); return 0; }
// // This function calculates the session HMAC and updates session state. // UINT32 TpmComputeSessionHmac( TSS2_SYS_CONTEXT *sysContext, TPMS_AUTH_COMMAND *pSessionDataIn, // Pointer to session input struct TPM_HANDLE entityHandle, // Used to determine if we're accessing a different // resource than the bound resoure. TPM_RC responseCode, // Response code for the command, 0xffff for "none" is // used to indicate that no response code is present // (used for calculating command HMACs vs response HMACs). TPM_HANDLE handle1, // First handle == 0xff000000 indicates no handle TPM_HANDLE handle2, // Second handle == 0xff000000 indicates no handle TPMA_SESSION sessionAttributes, // Current session attributes TPM2B_DIGEST *result, // Where the result hash is saved. TPM_RC sessionCmdRval ) { TPM2B_MAX_BUFFER hmacKey; TPM2B *bufferList[7]; TPM2B_DIGEST pHash; SESSION *pSession = 0; TPM2B_AUTH authValue; TPM2B sessionAttributesByteBuffer; UINT16 i; TPM_RC rval; UINT8 nvNameChanged = 0; ENTITY *nvEntity; UINT8 commandCode[4] = { 0, 0, 0, 0 }; UINT32 *cmdCodePtr; UINT32 cmdCode; hmacKey.b.size = 0; rval = GetSessionStruct( pSessionDataIn->sessionHandle, &pSession ); if( rval != TPM_RC_SUCCESS ) { return rval; } pHash.t.size = sizeof( TPM2B_DIGEST ) - 2; rval = ( *CalcPHash )( sysContext, handle1, handle2, pSession->authHash, responseCode, &pHash ); if( rval != TPM_RC_SUCCESS ) return rval; // Use entityHandle to get authValue, if any. if( ( pSession->bind == TPM_RH_NULL ) || ( ( pSession->bind != TPM_RH_NULL ) && ( pSession->bind == entityHandle ) ) ) { rval = GetEntityAuth( entityHandle, &authValue ); if( rval != TPM_RC_SUCCESS ) authValue.t.size = 0; } else { authValue.t.size = 0; } rval = Tss2_Sys_GetCommandCode( sysContext, &commandCode ); if( rval != TPM_RC_SUCCESS ) return rval; if( ( entityHandle >> HR_SHIFT ) == TPM_HT_NV_INDEX ) { // If NV index, get status wrt to name change. If name has changed, // we have to treat it as if its not the bound entity, even if it was // the bound entity. nvNameChanged = pSession->nvNameChanged; } rval = ConcatSizedByteBuffer( (TPM2B_MAX_BUFFER *)&hmacKey, &( pSession->sessionKey.b ) ); if( ( pSession->bind == TPM_RH_NULL ) || ( pSession->bind != entityHandle ) || nvNameChanged ) { rval = ConcatSizedByteBuffer( (TPM2B_MAX_BUFFER *)&hmacKey, &( authValue.b ) ); } #ifdef DEBUG DebugPrintf( 0, "\n\nhmacKey = " ); PrintSizedBuffer( &(hmacKey.b) ); #endif // Create buffer list i = 0; bufferList[i++] = &pHash.b; bufferList[i++] = &( pSession->nonceNewer.b ); bufferList[i++] = &( pSession->nonceOlder.b ); bufferList[i++] = &( pSession->nonceTpmDecrypt.b ); bufferList[i++] = &( pSession->nonceTpmEncrypt.b ); sessionAttributesByteBuffer.size = 1; sessionAttributesByteBuffer.buffer[0] = *(UINT8 *)&sessionAttributes; bufferList[i++] = &( sessionAttributesByteBuffer ); bufferList[i++] = 0; cmdCodePtr = (UINT32 *)&commandCode[0]; cmdCode = *cmdCodePtr; #ifdef DEBUG for( i = 0; bufferList[i] != 0; i++ ) { DebugPrintf( 0, "\n\nbufferlist[%d]:\n", i ); PrintSizedBuffer( bufferList[i] ); } #endif rval = (*HmacFunctionPtr)( pSession->authHash, &hmacKey.b, &( bufferList[0] ), result ); if( rval != TPM_RC_SUCCESS ) return rval; if( ( responseCode != TPM_RC_NO_RESPONSE ) && ( cmdCode == TPM_CC_NV_Write || cmdCode == TPM_CC_NV_Increment || cmdCode == TPM_CC_NV_SetBits ) ) { rval = GetEntity( entityHandle, &nvEntity ); if( rval != TPM_RC_SUCCESS ) { return rval; } else { // Only change session's nvNameChanged parameter when // the NV index's name changes due to a write. if( nvEntity->nvNameChanged == 0 ) { pSession->nvNameChanged = 1; nvEntity->nvNameChanged = 1; } } } return rval; }
// // This function is a helper function used to calculate cpHash and rpHash. // // NOTE: for calculating cpHash, set responseCode to TPM_RC_NO_RESPONSE; this // tells the function to leave it out of the calculation. // TPM_RC TpmCalcPHash( TSS2_SYS_CONTEXT *sysContext, TPM_HANDLE handle1, TPM_HANDLE handle2, TPMI_ALG_HASH authHash, TPM_RC responseCode, TPM2B_DIGEST *pHash ) { TPM_RC rval = TPM_RC_SUCCESS; UINT32 i; TPM2B_NAME name1; TPM2B_NAME name2; TPM2B_MAX_BUFFER hashInput; // Byte stream to be hashed to create pHash UINT8 *hashInputPtr; size_t parametersSize; const uint8_t *startParams; UINT8 cmdCode[4] = {0,0,0,0}; UINT8 *cmdCodePtr = &cmdCode[0]; name1.b.size = name2.b.size = 0; // Calculate pHash // // Only get names for commands if( responseCode == TPM_RC_NO_RESPONSE ) { // Get names for the handles rval = TpmHandleToName( handle1, &name1 ); if( rval != TPM_RC_SUCCESS ) return rval; } #ifdef DEBUG OpenOutFile( &outFp ); TpmClientPrintf( 0, "\n\nNAME1 = \n" ); PrintSizedBuffer( &(name1.b) ); CloseOutFile( &outFp ); #endif // Only get names for commands if( responseCode == TPM_RC_NO_RESPONSE ) { rval = Tss2_Sys_GetCpBuffer( sysContext, ¶metersSize, &startParams); if( rval != TPM_RC_SUCCESS ) return rval; rval = TpmHandleToName( handle2, &name2 ); if( rval != TPM_RC_SUCCESS ) return rval; } else { rval = Tss2_Sys_GetRpBuffer( sysContext, ¶metersSize, &startParams); if( rval != TPM_RC_SUCCESS ) return rval; } #ifdef DEBUG OpenOutFile( &outFp ); TpmClientPrintf( 0, "\n\nNAME2 = \n" ); PrintSizedBuffer( &(name2.b) ); CloseOutFile( &outFp ); #endif // Create pHash input byte stream: first add response code, if any. hashInput.b.size = 0; if( responseCode != TPM_RC_NO_RESPONSE ) { hashInputPtr = &( hashInput.t.buffer[hashInput.b.size] ); *(UINT32 *)hashInputPtr = CHANGE_ENDIAN_DWORD( responseCode ); hashInput.b.size += 4; hashInputPtr += 4; } // Create pHash input byte stream: now add command code. rval = Tss2_Sys_GetCommandCode( sysContext, &cmdCode ); if( rval != TPM_RC_SUCCESS ) return rval; hashInputPtr = &( hashInput.t.buffer[hashInput.b.size] ); *(UINT32 *)hashInputPtr = CHANGE_ENDIAN_DWORD( *(UINT32 *)cmdCodePtr ); hashInput.t.size += 4; // Create pHash input byte stream: now add in names for the handles. rval = ConcatSizedByteBuffer( &hashInput, &( name1.b ) ); if( rval != TPM_RC_SUCCESS ) return rval; rval = ConcatSizedByteBuffer( &hashInput, &( name2.b ) ); if( rval != TPM_RC_SUCCESS ) return rval; if( ( hashInput.t.size + parametersSize ) <= sizeof( hashInput.t.buffer ) ) { // Create pHash input byte stream: now add in parameters byte stream for( i = 0; i < parametersSize; i++ ) hashInput.t.buffer[hashInput.t.size + i ] = startParams[i]; hashInput.t.size += (UINT16)parametersSize; } else { return( APPLICATION_ERROR( TSS2_BASE_RC_INSUFFICIENT_BUFFER ) ); } #ifdef DEBUG OpenOutFile( &outFp ); TpmClientPrintf( 0, "\n\nPHASH input bytes= \n" ); PrintSizedBuffer( &(hashInput.b) ); CloseOutFile( &outFp ); #endif // Now hash the whole mess. if( hashInput.t.size > sizeof( hashInput.t.buffer ) ) { rval = APPLICATION_ERROR( TSS2_BASE_RC_INSUFFICIENT_BUFFER ); } else { rval = TpmHash( authHash, hashInput.t.size, &( hashInput.t.buffer[0] ), pHash ); if( rval != TPM_RC_SUCCESS ) return rval; #ifdef DEBUG OpenOutFile( &outFp ); TpmClientPrintf( 0, "\n\nPHASH = " ); PrintSizedBuffer( &(pHash->b) ); CloseOutFile( &outFp ); #endif } return rval; }