static int decrypt_transport_auth(TPM_KEY_DATA *key, BYTE *enc, UINT32 enc_size, TPM_TRANSPORT_AUTH *trans_auth) { BYTE *buf; size_t buf_size; int scheme; switch (key->encScheme) { case TPM_ES_RSAESOAEP_SHA1_MGF1: scheme = RSA_ES_OAEP_SHA1; break; case TPM_ES_RSAESPKCSv15: scheme = RSA_ES_PKCSV15; break; default: return -1; } buf = tpm_malloc(key->key.size); if (buf == NULL || tpm_rsa_decrypt(&key->key, scheme, enc, enc_size, buf, &buf_size) || buf_size != sizeof_TPM_TRANSPORT_AUTH(x) || (((UINT16)buf[0] << 8) | buf[1]) != TPM_TAG_TRANSPORT_AUTH) { tpm_free(buf); return -1; } trans_auth->tag = TPM_TAG_TRANSPORT_AUTH; memcpy(trans_auth->authData, &buf[2], sizeof(TPM_AUTHDATA)); tpm_free(buf); return 0; }
TPM_RESULT TPM_TakeOwnership(TPM_PROTOCOL_ID protocolID, UINT32 encOwnerAuthSize, BYTE *encOwnerAuth, UINT32 encSrkAuthSize, BYTE *encSrkAuth, TPM_KEY *srkParams, TPM_AUTH *auth1, TPM_KEY *srkPub) { TPM_RESULT res; tpm_rsa_private_key_t *ek = &tpmData.permanent.data.endorsementKey; TPM_KEY_DATA *srk = &tpmData.permanent.data.srk; size_t buf_size = ek->size >> 3; BYTE buf[buf_size]; info("TPM_TakeOwnership()"); if (!ek->size) return TPM_NO_ENDORSEMENT; if (protocolID != TPM_PID_OWNER) return TPM_BAD_PARAMETER; if (tpmData.permanent.flags.owned) return TPM_OWNER_SET; if (!tpmData.permanent.flags.ownership) return TPM_INSTALL_DISABLED; /* decrypt ownerAuth */ if (tpm_rsa_decrypt(ek, RSA_ES_OAEP_SHA1, encOwnerAuth, encOwnerAuthSize, buf, &buf_size) != 0) return TPM_DECRYPT_ERROR; if (buf_size != sizeof(TPM_SECRET)) return TPM_BAD_KEY_PROPERTY; memcpy(tpmData.permanent.data.ownerAuth, buf, buf_size); /* verify authorization */ res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER); if (res != TPM_SUCCESS) return res; if (tpm_get_auth(auth1->authHandle)->type != TPM_ST_OIAP) return TPM_AUTHFAIL; /* reset srk and decrypt srkAuth */ memset(srk, 0, sizeof(*srk)); if (tpm_rsa_decrypt(ek, RSA_ES_OAEP_SHA1, encSrkAuth, encSrkAuthSize, buf, &buf_size) != 0) return TPM_DECRYPT_ERROR; if (buf_size != sizeof(TPM_SECRET)) return TPM_BAD_KEY_PROPERTY; memcpy(srk->usageAuth, buf, buf_size); /* validate SRK parameters */ if (srkParams->keyFlags & TPM_KEY_FLAG_MIGRATABLE || srkParams->keyUsage != TPM_KEY_STORAGE) return TPM_INVALID_KEYUSAGE; if (srkParams->algorithmParms.algorithmID != TPM_ALG_RSA || srkParams->algorithmParms.encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1 || srkParams->algorithmParms.sigScheme != TPM_SS_NONE || srkParams->algorithmParms.parmSize == 0 || srkParams->algorithmParms.parms.rsa.keyLength != 2048 || srkParams->algorithmParms.parms.rsa.numPrimes != 2 || srkParams->algorithmParms.parms.rsa.exponentSize != 0 || srkParams->PCRInfoSize != 0) return TPM_BAD_KEY_PROPERTY; /* setup and generate SRK */ srk->keyFlags = srkParams->keyFlags; srk->keyFlags |= TPM_KEY_FLAG_PCR_IGNORE; srk->keyFlags &= ~TPM_KEY_FLAG_HAS_PCR; srk->keyUsage = srkParams->keyUsage; srk->encScheme = srkParams->algorithmParms.encScheme; srk->sigScheme = srkParams->algorithmParms.sigScheme; srk->authDataUsage = srkParams->authDataUsage; debug("srk->authDataUsage = %02x", srk->authDataUsage); srk->parentPCRStatus = FALSE; srkParams->algorithmParms.parms.rsa.keyLength = 2048; if (tpm_rsa_generate_key(&srk->key, srkParams->algorithmParms.parms.rsa.keyLength)) return TPM_FAIL; srk->payload = TPM_PT_ASYM; /* generate context, delegate, and DAA key */ tpm_get_random_bytes(tpmData.permanent.data.contextKey, sizeof(tpmData.permanent.data.contextKey)); tpm_get_random_bytes(tpmData.permanent.data.delegateKey, sizeof(tpmData.permanent.data.delegateKey)); tpm_get_random_bytes(tpmData.permanent.data.daaKey, sizeof(tpmData.permanent.data.daaKey)); /* export SRK */ memcpy(srkPub, srkParams, sizeof(TPM_KEY)); srkPub->pubKey.keyLength = srk->key.size >> 3; srkPub->pubKey.key = tpm_malloc(srkPub->pubKey.keyLength); if (srkPub->pubKey.key == NULL) { tpm_rsa_release_private_key(&srk->key); srk->payload = TPM_PT_NONE; return TPM_FAIL; } tpm_rsa_export_modulus(&srk->key, srkPub->pubKey.key, NULL); /* setup tpmProof/daaProof and set state to owned */ tpm_get_random_bytes(tpmData.permanent.data.tpmProof.nonce, sizeof(tpmData.permanent.data.tpmProof.nonce)); tpm_get_random_bytes(tpmData.permanent.data.daaProof.nonce, sizeof(tpmData.permanent.data.daaProof.nonce)); tpmData.permanent.flags.readPubek = FALSE; tpmData.permanent.flags.owned = TRUE; return TPM_SUCCESS; }