TPM_RC TPM2_Startup( Startup_In *in // IN: input parameter list ) { STARTUP_TYPE startup; BYTE locality = _plat__LocalityGet(); // The command needs NV update. RETURN_IF_NV_IS_NOT_AVAILABLE; // Get the flags for the current startup locality and the H-CRTM. // Rather than generalizing the locality setting, this code takes advantage // of the fact that the PC Client specification only allows Startup() // from locality 0 and 3. To generalize this probably would require a // redo of the NV space and since this is a feature that is hardly ever used // outside of the PC Client, this code just support the PC Client needs. // Input Validation // Check that the locality is a supported value if(locality != 0 && locality != 3) return TPM_RC_LOCALITY; // If there was a H-CRTM, then treat the locality as being 3 // regardless of what the Startup() was. This is done to preserve the // H-CRTM PCR so that they don't get overwritten with the normal // PCR startup initialization. This basically means that g_StartupLocality3 // and g_DrtmPreStartup can't both be SET at the same time. if(g_DrtmPreStartup) locality = 0; g_StartupLocality3 = (locality == 3); #if USE_DA_USED // If there was no orderly shutdown, then their might have been a write to // failedTries that didn't get recorded but only if g_daUsed was SET in the // shutdown state g_daUsed = (gp.orderlyState == SU_DA_USED_VALUE); if(g_daUsed) gp.orderlyState = SU_NONE_VALUE; #endif g_prevOrderlyState = gp.orderlyState; // If there was a proper shutdown, then the startup modifiers are in the // orderlyState. Turn them off in the copy. if(IS_ORDERLY(g_prevOrderlyState)) g_prevOrderlyState &= ~(PRE_STARTUP_FLAG | STARTUP_LOCALITY_3); // If this is a Resume, if(in->startupType == TPM_SU_STATE) { // then there must have been a prior TPM2_ShutdownState(STATE) if(g_prevOrderlyState != TPM_SU_STATE) return TPM_RCS_VALUE + RC_Startup_startupType; // and the part of NV used for state save must have been recovered // correctly. // NOTE: if this fails, then the caller will need to do Startup(CLEAR). The // code for Startup(Clear) cannot fail if the NV can't be read correctly // because that would prevent the TPM from ever getting unstuck. if(g_nvOk == FALSE) return TPM_RC_NV_UNINITIALIZED; // For Resume, the H-CRTM has to be the same as the previous boot if(g_DrtmPreStartup != ((gp.orderlyState & PRE_STARTUP_FLAG) != 0)) return TPM_RCS_VALUE + RC_Startup_startupType; if(g_StartupLocality3 != ((gp.orderlyState & STARTUP_LOCALITY_3) != 0)) return TPM_RC_LOCALITY; } // Clean up the gp state gp.orderlyState = g_prevOrderlyState; // Internal Date Update if((gp.orderlyState == TPM_SU_STATE) && (g_nvOk == TRUE)) { // Always read the data that is only cleared on a Reset because this is not // a reset NvRead(&gr, NV_STATE_RESET_DATA, sizeof(gr)); if(in->startupType == TPM_SU_STATE) { // If this is a startup STATE (a Resume) need to read the data // that is cleared on a startup CLEAR because this is not a Reset // or Restart. NvRead(&gc, NV_STATE_CLEAR_DATA, sizeof(gc)); startup = SU_RESUME; } else startup = SU_RESTART; } else // Will do a TPM reset if Shutdown(CLEAR) and Startup(CLEAR) or no shutdown // or there was a failure reading the NV data. startup = SU_RESET; // Startup for cryptographic library. Don't do this until after the orderly // state has been read in from NV. if (CryptStartup(startup) == FALSE) { // libtpms changed begin FAIL(FATAL_ERROR_INTERNAL); } // libtpms changed end // When the cryptographic library has been started, indicate that a TPM2_Startup // command has been received. TPMRegisterStartup(); // Read the platform unique value that is used as VENDOR_PERMANENT // authorization value g_platformUniqueDetails.t.size = (UINT16)_plat__GetUnique(1, sizeof(g_platformUniqueDetails.t.buffer), g_platformUniqueDetails.t.buffer); // Start up subsystems // Start set the safe flag TimeStartup(startup); // Start dictionary attack subsystem DAStartup(startup); // Enable hierarchies HierarchyStartup(startup); // Restore/Initialize PCR PCRStartup(startup, locality); // Restore/Initialize command audit information CommandAuditStartup(startup); //// The following code was moved from Time.c where it made no sense switch (startup) { case SU_RESUME: // Resume sequence gr.restartCount++; break; case SU_RESTART: // Hibernate sequence gr.clearCount++; gr.restartCount++; break; default: // Reset object context ID to 0 gr.objectContextID = 0; // Reset clearCount to 0 gr.clearCount = 0; // Reset sequence // Increase resetCount gp.resetCount++; // Write resetCount to NV NV_SYNC_PERSISTENT(resetCount); gp.totalResetCount++; // We do not expect the total reset counter overflow during the life // time of TPM. if it ever happens, TPM will be put to failure mode // and there is no way to recover it. // The reason that there is no recovery is that we don't increment // the NV totalResetCount when incrementing would make it 0. When the // TPM starts up again, the old value of totalResetCount will be read // and we will get right back to here with the increment failing. #if 0 /* libtpms added */ if(gp.totalResetCount == 0) FAIL(FATAL_ERROR_INTERNAL); #endif /* libtpms added */ // Write total reset counter to NV NV_SYNC_PERSISTENT(totalResetCount); // Reset restartCount gr.restartCount = 0; break; } // Initialize session table SessionStartup(startup); // Initialize object table ObjectStartup(); // Initialize index/evict data. This function clears read/write locks // in NV index NvEntityStartup(startup); // Initialize the orderly shut down flag for this cycle to SU_NONE_VALUE. gp.orderlyState = SU_NONE_VALUE; NV_SYNC_PERSISTENT(orderlyState); // This can be reset after the first completion of a TPM2_Startup() after // a power loss. It can probably be reset earlier but this is an OK place. g_powerWasLost = FALSE; return TPM_RC_SUCCESS; }
int main(int argc, char **argv) { Base32 b32; AES_KEY AESEncKey; MD5Context ctx; unsigned char alphabet[] = "123456789ABCDEFGHJKMNPQRSTUVWXYZ"; unsigned char szKey32[33]; // AES Key unsigned char AESEncryptIv[] = { 0x55, 0x12, 0x90, 0x32, 0x41, 0x85, 0xBC, 0x54, 0x04, 0x19, 0xAE, 0x49, 0x32, 0x99, 0x2D, 0x08 }; char *signature = 0; // rsa signature unsigned char plaintext[33], ciphertext[33], *pKey = 0; unsigned char *pSzData32, szData255[33]; int encodeLength = 0, keylength = 0, i, x; // NOTE: TEMP SAMPLE HARDWARE ID USED unsigned long int prng, licensetype = 0, features = 0, hwid[2] = { 0xDEADBEEF, 0xCAFEBABE }; //printf(">> KOrUPt's Keygen for KKeygenMe #2\n"); if(argc != 2){ printf("\tUsage: %s <registration name>\n", argv[0]); return -1; }else if(strlen(argv[1]) > 9){ printf("Name too long\n"); return -1; } SetErrorMode(SEM_NOGPFAULTERRORBOX); // md5 hash our name CryptStartup(); MD5Init(&ctx); MD5Update(&ctx, (unsigned char *)argv[1], strlen(argv[1])); MD5Final(&ctx); memset(ciphertext, 0, sizeof(ciphertext)); memset(szKey32, 0, sizeof(szKey32)); // set up our AES key(= md5 hashed name) for(i = 0; i < 16; i++) sprintf((char *)szKey32 + strlen((char *)szKey32), "%02x", ctx.digest[i]); CryptCleanup(); #ifdef _LOCALTEST // we'll encode the key with our local hwid as opposed to one given to us by our customer char drive[4] = "A:\\"; hwid[0] = GetProcessorFeatures(); for(drive[0] = 'A'; drive[0] <= 'Z'; drive[0]++){ if(GetDriveType(drive) == DRIVE_FIXED){ hwid[1] = GetSystemVolumeSerial(drive); break; } } #endif // Create key srand(GetTickCount()); memset(plaintext, 0, 33); *(u_long *)(plaintext) = prng = (rand() % 0xffffffff) + 0xdeadbeef; *(u_long *)(plaintext + 4) = KEY_MAGIC; *(u_long *)(plaintext + 8) = prng + 512; features |= SKILL_UNDEAD | SKILL_YOUCANFLY; *(u_long *)(plaintext + 12) = features; *(u_long *)(plaintext + 16) = hwid[0]; *(u_long *)(plaintext + 20) = hwid[1]; licensetype = PRO_KEY; *(u_long *)(plaintext + 24) = licensetype; prng = (rand() % 1000000) + 0xBADC0DED; *(u_long *)(plaintext + 28) = prng; // this part of the key has to be >= 0xBADCODED #ifdef _DEBUG printf("\n>> Md5 of name: %s\n", szKey32); hexdump(stdout, "\n--------\nPlaintext:", plaintext, 32); #endif AES_set_encrypt_key(szKey32, 32 * 8, &AESEncKey); AES_cbc_encrypt(plaintext, ciphertext, 32, &AESEncKey, AESEncryptIv, AES_ENCRYPT); #ifdef _DEBUG hexdump(stdout, "Ciphertext:", ciphertext, 32); printf("\nHardware id: %04X-%04X\n", hwid[0], hwid[1]); #endif encodeLength = b32.GetEncode32Length(32); pSzData32 = (unsigned char *)malloc(encodeLength + 1); if(pSzData32){ memset(pSzData32, 0, encodeLength + 1); if(b32.Encode32(ciphertext, 32, pSzData32)){ b32.Map32(pSzData32, encodeLength, alphabet); }else{ printf("An error occoured during Base32 translation\n"); free(pSzData32); return -1; } // add hypthens i = 0, x = 0; pKey = (unsigned char *)malloc(encodeLength + 13); if(pKey){ memset(pKey, 0, encodeLength + 13); while(x < encodeLength){ memcpy(pKey + i, pSzData32 + x, 4); i += 4, x += 4; *(pKey + (i++)) = '-'; } // remove trailing hythen *(pKey + (encodeLength + 12)) = 0; // sign key SignLicenseKey((char *)pKey, &signature); // write key details to file FILE* signatureFile; signatureFile = fopen("license.key", "w"); if(signatureFile){ printf("Generated key file license.key\n"); fprintf(signatureFile, "%s*%s*%s*", argv[1], pKey, signature); fclose(signatureFile); } free(pKey); } free(pSzData32); } return 0; }