uint16_t _cpri__HashBlock(TPM_ALG_ID alg, uint32_t in_len, uint8_t *in, uint32_t out_len, uint8_t *out) { uint8_t digest[SHA_DIGEST_MAX_BYTES]; const uint16_t digest_len = _cpri__GetDigestSize(alg); if (digest_len == 0) return 0; switch (alg) { case TPM_ALG_SHA1: DCRYPTO_SHA1_hash(in, in_len, digest); break; case TPM_ALG_SHA256: DCRYPTO_SHA256_hash(in, in_len, digest); break; /* TODO: add support for SHA384 and SHA512 * * case TPM_ALG_SHA384: * DCRYPTO_SHA384_hash(in, in_len, p); * break; * case TPM_ALG_SHA512: * DCRYPTO_SHA512_hash(in, in_len, p); * break; */ default: FAIL(FATAL_ERROR_INTERNAL); break; } out_len = MIN(out_len, digest_len); memcpy(out, digest, out_len); return out_len; }
//*** _cpri__StartHash() // Functions starts a hash stack // Start a hash stack and returns the digest size. As a side effect, the // value of 'stateSize' in hashState is updated to indicate the number of bytes // of state that were saved. This function calls GetHashServer() and that function // will put the TPM into failure mode if the hash algorithm is not supported. // return type: CRTYP_RESULT // 0 hash is TPM_ALG_NULL // >0 digest size UINT16 _cpri__StartHash( TPM_ALG_ID hashAlg, // IN: hash algorithm BOOL sequence, // IN: TRUE if the state should be saved CPRI_HASH_STATE *hashState // OUT: the state of hash stack. ) { OSSL_HASH_STATE *state = (OSSL_HASH_STATE *)&hashState->state; const HASH_INFO *hashInfo = GetHashInfoPointer(hashAlg); UINT16 retVal = 0; // Not supported pAssert(sequence == FALSE); // Valid algorithm? if (hashInfo == NULL) { goto Cleanup; } if (BCryptCreateHash(g_hAlg[GetHashIndex(hashAlg)], &state->hHash, NULL, 0, NULL, 0, 0) != 0) { goto Cleanup; } retVal = _cpri__GetDigestSize(hashAlg); hashState->hashAlg = hashAlg; Cleanup: return retVal; }
static TPM_RC TSE_MGF1(unsigned char *mask, uint32_t maskLen, const unsigned char *mgfSeed, uint16_t mgfSeedlen, TPMI_ALG_HASH halg) { TPM_RC rc = 0; unsigned char counter[4]; /* 4 octets */ uint32_t count; /* counter as an integral type */ uint32_t outLen; TPMT_HA digest; uint16_t digestSize = _cpri__GetDigestSize(halg); digest.hashAlg = halg; #if 0 if (rc == 0) { /* this is possible with arrayLen on a 64 bit architecture, comment to quiet beam */ if ((maskLen / TPM_DIGEST_SIZE) > 0xffffffff) { /*constant condition*/ if (tseVerbose) printf("TSE_MGF1: Error (fatal), Output length too large for 32 bit counter\n"); rc = TPM_FAIL; /* should never occur */ } } #endif /* 1.If l > 2^32(hLen), output "mask too long" and stop. */ /* NOTE Checked by caller */ /* 2. Let T be the empty octet string. */ /* 3. For counter from 0 to [masklen/hLen] - 1, do the following: */ for (count = 0, outLen = 0 ; (rc == 0) && (outLen < maskLen) ; count++) { /* a. Convert counter to an octet string C of length 4 octets - see Section 4.1 */ /* C = I2OSP(counter, 4) NOTE Basically big endian */ uint32_t count_n = htonl(count); memcpy(counter, &count_n, 4); /* b.Concatenate the hash of the seed mgfSeed and C to the octet string T: */ /* T = T || Hash (mgfSeed || C) */ /* If the entire digest is needed for the mask */ if ((outLen + digestSize) < maskLen) { rc = TSE_Hash_Generate(&digest, mgfSeedlen, mgfSeed, 4, counter, 0, NULL); memcpy(mask + outLen, &digest.digest, digestSize); outLen += digestSize; } /* if the mask is not modulo TPM_DIGEST_SIZE, only part of the final digest is needed */ else { /* hash to a temporary digest variable */ rc = TSE_Hash_Generate(&digest, mgfSeedlen, mgfSeed, 4, counter, 0, NULL); /* copy what's needed */ memcpy(mask + outLen, &digest.digest, maskLen - outLen); outLen = maskLen; /* outLen = outLen + maskLen - outLen */ } } /* 4.Output the leading l octets of T as the octet string mask. */ return rc; }
int main(int argc, char *argv[]) { TPM_RC rc = 0; int i; /* argc iterator */ char *prc = NULL; /* pointer return code */ const char *inFilename = NULL; const char *outFilename = NULL; FILE *inFile = NULL; FILE *outFile = NULL; UINT32 sizeInBytes; /* hash algorithm mapped to size */ uint32_t pcrmask = 0; /* pcr register mask */ TPML_PCR_SELECTION pcrs; unsigned int pcrCount = 0; TPMU_HA pcr[IMPLEMENTATION_PCR]; /* all the PCRs */ int pr = FALSE; TPMT_HA digest; uint8_t pcrBytes[IMPLEMENTATION_PCR * MAX_DIGEST_SIZE]; UINT16 pcrLength; /* command line defaults */ digest.hashAlg = TPM_ALG_SHA256; ERR_load_crypto_strings (); OpenSSL_add_all_algorithms (); for (i=1 ; (i<argc) && (rc == 0) ; i++) { if (strcmp(argv[i],"-halg") == 0) { i++; if (i < argc) { if (strcmp(argv[i],"sha256") == 0) { digest.hashAlg = TPM_ALG_SHA256; } else if (strcmp(argv[i],"sha1") == 0) { digest.hashAlg = TPM_ALG_SHA1; } else { printf("Bad parameter for -halg\n"); printUsage(); } } else { printf("Missing parameter for -hi\n"); printUsage(); } } else if (strcmp(argv[i],"-bm") == 0) { i++; if (i < argc) { if (1 != sscanf(argv[i], "%x", &pcrmask)) { printf("Invalid -bm argument '%s'\n", argv[i]); printUsage(); } } else { printf("-bm option needs a value\n"); printUsage(); } } else if (strcmp(argv[i],"-of") == 0) { i++; if (i < argc) { outFilename = argv[i]; } else { printf("-of option needs a value\n"); printUsage(); } } else if (strcmp(argv[i],"-if") == 0) { i++; if (i < argc) { inFilename = argv[i]; } else { printf("-if option needs a value\n"); printUsage(); } } else if (strcmp(argv[i],"-pr") == 0) { pr = TRUE; } else if (strcmp(argv[i],"-h") == 0) { printUsage(); } else if (strcmp(argv[i],"-v") == 0) { verbose = TRUE; TSE_SetProperty(TPM_TRACE_LEVEL, "2"); } else { printf("\n%s is not a valid option\n", argv[i]); printUsage(); } } if (pcrmask == 0) { printf("Missing handle parameter -bm\n"); printUsage(); } if (inFilename == NULL) { printf("Missing handle parameter -if\n"); printUsage(); } /* open the input file */ if (rc == 0) { inFile = fopen(inFilename, "r"); if (inFile == NULL) { printf("Error opening %s for %s, %s\n", inFilename, "r", strerror(errno)); rc = EXIT_FAILURE; } } if (rc == 0) { sizeInBytes = _cpri__GetDigestSize(digest.hashAlg); } /* Table 102 - Definition of TPML_PCR_SELECTION Structure */ if (rc == 0) { pcrs.count = 1; /* hard code one hash algorithm */ /* Table 85 - Definition of TPMS_PCR_SELECTION Structure - pcrSelections */ pcrs.pcrSelections[0].hash = digest.hashAlg; pcrs.pcrSelections[0].sizeofSelect= 3; /* hard code 24 pcrs */ /* TCG always marshals lower PCR first */ pcrs.pcrSelections[0].pcrSelect[0] = (pcrmask >> 0) & 0xff; pcrs.pcrSelections[0].pcrSelect[1] = (pcrmask >> 8) & 0xff; pcrs.pcrSelections[0].pcrSelect[2] = (pcrmask >> 16) & 0xff; }
TPM_RC TSE_RSA_padding_add_PKCS1_OAEP(unsigned char *em, uint32_t emLen, const unsigned char *from, uint32_t fLen, const unsigned char *p, int plen, TPMI_ALG_HASH halg) { TPM_RC rc = 0; TPMT_HA lHash; unsigned char *db; unsigned char *dbMask = NULL; /* freed @1 */ unsigned char *seed = NULL; /* freed @2 */ unsigned char *maskedDb; unsigned char *seedMask; unsigned char *maskedSeed; uint16_t hlen = _cpri__GetDigestSize(halg); /* 1.a. If the length of L is greater than the input limitation for */ /* the hash function (2^61-1 octets for SHA-1) then output "parameter */ /* string too long" and stop. */ if (rc == 0) { if (plen > 0xffff) { if (tseVerbose) printf("TSE_RSA_padding_add_PKCS1_OAEP: Error, " "label %u too long\n", plen); rc = TSE_RC_RSA_PADDING; } } /* 1.b. If ||M|| > emLen-2hLen-1 then output "message too long" and stop. */ if (rc == 0) { if (emLen < ((2 * hlen) + 2 + fLen)) { if (tseVerbose) printf("TSE_RSA_padding_add_PKCS1_OAEP: Error, " "message length %u too large for encoded length %u\n", fLen, emLen); rc = TSE_RC_RSA_PADDING; } } /* 2.a. Let lHash = Hash(L), an octet string of length hLen. */ if (rc == 0) { lHash.hashAlg = halg; rc = TSE_Hash_Generate(&lHash, plen, p, 0, NULL); } if (rc == 0) { /* 2.b. Generate an octet string PS consisting of emLen-||M||-2hLen-2 zero octets. The length of PS may be 0. */ /* 2.c. Concatenate lHash, PS, a single octet of 0x01 the message M, to form a data block DB as: DB = lHash || PS || 01 || M */ /* NOTE Since db is eventually maskedDb, part of em, create directly in em */ db = em + hlen + 1; memcpy(db, &lHash.digest, hlen); /* lHash */ /* PSlen = emlen - flen - (2 * hlen) - 2 */ memset(db + hlen, 0, /* PS */ emLen - fLen - (2 * hlen) - 2); /* position of 0x01 in db is hlen + PSlen = hlen + emlen - flen - (2 * hlen) - 2 = emlen - hlen - flen - 2 */ db[emLen - fLen - hlen - 2] = 0x01; memcpy(db + emLen - fLen - hlen - 1, from, fLen); /* M */ } /* 2.d. Generate a random octet string seed of length hLen. */ if (rc == 0) { rc = TSE_Malloc(&seed, hlen); } if (rc == 0) { rc = TSE_RandBytes(seed, hlen); } if (rc == 0) { rc = TSE_Malloc(&dbMask, emLen - hlen - 1); } if (rc == 0) { /* 2.e. Let dbMask = MGF(seed, emLen-hLen-1). */ rc = TSE_MGF1(dbMask, emLen - hlen -1, /* dbLen */ seed, hlen, halg); } if (rc == 0) { /* 2.f. Let maskedDB = DB xor dbMask. */ /* NOTE Since maskedDB is eventually em, XOR directly to em */ maskedDb = em + hlen + 1; TSE_XOR(maskedDb, db, dbMask, emLen - hlen -1); /* 2.g. Let seedMask = MGF(maskedDB, hLen). */ /* NOTE Since seedMask is eventually em, create directly to em */ seedMask = em + 1; rc = TSE_MGF1(seedMask, hlen, maskedDb, emLen - hlen - 1, halg); } if (rc == 0) { /* 2.h. Let maskedSeed = seed xor seedMask. */ /* NOTE Since maskedSeed is eventually em, create directly to em */ maskedSeed = em + 1; TSE_XOR(maskedSeed, seed, seedMask, hlen); /* 2.i. 0x00, maskedSeed, and maskedDb to form EM */ /* NOTE Created directly in em */ } free(dbMask); /* @1 */ free(seed); /* @2 */ return rc; }