Example #1
0
uint32_t TPM_CreateMigrationBlob(unsigned int keyhandle,
				 unsigned char *keyauth,
				 unsigned char *migauth,
				 int migtype,
				 unsigned char *migblob,
				 unsigned int migblen,
				 unsigned char *keyblob,
				 unsigned int keyblen,
				 unsigned char *rndblob,
				 unsigned int *rndblen,
				 unsigned char *outblob,
				 unsigned int *outblen)
{
	unsigned char create_mig_fmt[] =
	    "00 c3 T l l s % @ l % o % l % o %";
	unsigned char create_mig_fmt_noauth[] =
	    "00 c2 T l l s % @ l % o %";
	uint32_t ret;
	unsigned char tpmdata[TPM_MAX_BUFF_SIZE];
	unsigned char nonceodd[TPM_NONCE_SIZE];
	unsigned char enonce1[TPM_NONCE_SIZE];
	unsigned char enonce2[TPM_NONCE_SIZE];
	unsigned char c;
	uint32_t ordinal;
	uint32_t keyhndl;
	uint32_t datsize;
	uint16_t migscheme;
	uint32_t authhandle1;
	uint32_t authhandle2;
	unsigned char authdata1[TPM_HASH_SIZE];
	unsigned char authdata2[TPM_HASH_SIZE];
	uint32_t size1;
	uint32_t size2;
	keydata k;

	/* check input arguments */
	if (migauth == NULL || migblob == NULL || keyblob == NULL)
		return ERR_NULL_ARG;
	if (rndblob == NULL || rndblen == NULL || outblob == NULL
	    || outblen == NULL)
		return ERR_NULL_ARG;
	if (migtype != 1 && migtype != 2)
		return ERR_BAD_ARG;
	TSS_KeyExtract(keyblob, &k);
	/* move data to Network byte order variables for HMAC calculation */
	ordinal = htonl(0x28);
	keyhndl = htonl(keyhandle);
	migscheme = htons(migtype);
	datsize = htonl(k.privkeylen);
	/* generate odd nonce */
	TSS_gennonce(nonceodd);
	c = 0;
	if (keyauth != NULL) {	/* parent key password is required */
		/* open TWO OIAP sessions: Parent and Migrating Key */
		ret = TSS_OIAPopen(&authhandle1, enonce1);
		if (ret != 0)
			return ret;
		ret = TSS_OIAPopen(&authhandle2, enonce2);
		if (ret != 0)
			return ret;
		/* calculate Parent KEY authorization HMAC value */
		ret =
		    TSS_authhmac(authdata1, keyauth, TPM_HASH_SIZE,
				 enonce1, nonceodd, c, TPM_U32_SIZE,
				 &ordinal, TPM_U16_SIZE, &migscheme,
				 migblen, migblob, TPM_U32_SIZE, &datsize,
				 k.privkeylen, k.encprivkey, 0, 0);
		if (ret != 0) {
			TSS_OIAPclose(authhandle1);
			TSS_OIAPclose(authhandle2);
			return ret;
		}
		/* calculate Migration authorization HMAC value */
		ret =
		    TSS_authhmac(authdata2, migauth, TPM_HASH_SIZE,
				 enonce2, nonceodd, c, TPM_U32_SIZE,
				 &ordinal, TPM_U16_SIZE, &migscheme,
				 migblen, migblob, TPM_U32_SIZE, &datsize,
				 k.privkeylen, k.encprivkey, 0, 0);
		if (ret != 0) {
			TSS_OIAPclose(authhandle1);
			TSS_OIAPclose(authhandle2);
			return ret;
		}
		/* build the request buffer */
		ret = TSS_buildbuff(create_mig_fmt, tpmdata,
				    ordinal,
				    keyhndl,
				    migscheme,
				    migblen, migblob,
				    k.privkeylen, k.encprivkey,
				    authhandle1,
				    TPM_NONCE_SIZE, nonceodd,
				    c,
				    TPM_HASH_SIZE, authdata1,
				    authhandle2,
				    TPM_NONCE_SIZE, nonceodd,
				    c, TPM_HASH_SIZE, authdata2);

		if ((ret & ERR_MASK) != 0) {
			TSS_OIAPclose(authhandle1);
			TSS_OIAPclose(authhandle2);
			return ret;
		}
		/* transmit buffer to the TPM device and read the reply */
		ret = TPM_Transmit(tpmdata, "CreateMigrationBlob");
		if (ret != 0) {
			TSS_OIAPclose(authhandle1);
			TSS_OIAPclose(authhandle2);
			return ret;
		}
		/* validate HMAC in response */
		size1 = LOAD32(tpmdata, TPM_DATA_OFFSET);
		size2 =
		    LOAD32(tpmdata,
			   TPM_DATA_OFFSET + TPM_U32_SIZE + size1);
		if (size1 != 0) {
			ret = TSS_checkhmac2(tpmdata, ordinal, nonceodd,
					     keyauth, TPM_HASH_SIZE,
					     migauth, TPM_HASH_SIZE,
					     TPM_U32_SIZE, TPM_DATA_OFFSET,
					     size1,
					     TPM_DATA_OFFSET +
					     TPM_U32_SIZE, TPM_U32_SIZE,
					     TPM_DATA_OFFSET +
					     TPM_U32_SIZE + size1, size2,
					     TPM_DATA_OFFSET +
					     TPM_U32_SIZE + size1 +
					     TPM_U32_SIZE, 0, 0);
		} else {
			ret = TSS_checkhmac2(tpmdata, ordinal, nonceodd,
					     keyauth, TPM_HASH_SIZE,
					     migauth, TPM_HASH_SIZE,
					     TPM_U32_SIZE, TPM_DATA_OFFSET,
					     TPM_U32_SIZE,
					     TPM_DATA_OFFSET +
					     TPM_U32_SIZE, size2,
					     TPM_DATA_OFFSET +
					     TPM_U32_SIZE + TPM_U32_SIZE,
					     0, 0);
		}
		TSS_OIAPclose(authhandle1);
		TSS_OIAPclose(authhandle2);
		if (ret != 0)
			return ret;
	} else {		/* no parent key password required */

		/* open OIAP session for the Migrating Key */
		ret = TSS_OIAPopen(&authhandle1, enonce1);
		if (ret != 0)
			return ret;
		/* calculate Migration authorization HMAC value */
		ret =
		    TSS_authhmac(authdata1, migauth, TPM_HASH_SIZE,
				 enonce1, nonceodd, c, TPM_U32_SIZE,
				 &ordinal, TPM_U16_SIZE, &migscheme,
				 migblen, migblob, TPM_U32_SIZE, &datsize,
				 k.privkeylen, k.encprivkey, 0, 0);
		if (ret != 0) {
			TSS_OIAPclose(authhandle1);
			return ret;
		}
		/* build the request buffer */
		ret = TSS_buildbuff(create_mig_fmt_noauth, tpmdata,
				    ordinal,
				    keyhndl,
				    migscheme,
				    migblen, migblob,
				    k.privkeylen, k.encprivkey,
				    authhandle1,
				    TPM_NONCE_SIZE, nonceodd,
				    c, TPM_HASH_SIZE, authdata1);

		if ((ret & ERR_MASK) != 0) {
			TSS_OIAPclose(authhandle1);
			return ret;
		}
		/* transmit buffer to the TPM device and read the reply */
		ret = TPM_Transmit(tpmdata, "CreateMigrationBlob");
		if (ret != 0) {
			TSS_OIAPclose(authhandle1);
			return ret;
		}
		/* check HMAC in response */
		size1 = LOAD32(tpmdata, TPM_DATA_OFFSET);
		size2 =
		    LOAD32(tpmdata,
			   TPM_DATA_OFFSET + TPM_U32_SIZE + size1);
		if (size1 != 0) {
			ret =
			    TSS_checkhmac1(tpmdata, ordinal, nonceodd,
					   migauth, TPM_HASH_SIZE,
					   TPM_U32_SIZE, TPM_DATA_OFFSET,
					   size1,
					   TPM_DATA_OFFSET + TPM_U32_SIZE,
					   TPM_U32_SIZE,
					   TPM_DATA_OFFSET + TPM_U32_SIZE +
					   size1, size2,
					   TPM_DATA_OFFSET + TPM_U32_SIZE +
					   size1 + TPM_U32_SIZE, 0, 0);
		} else {
			ret =
			    TSS_checkhmac1(tpmdata, ordinal, nonceodd,
					   migauth, TPM_HASH_SIZE,
					   TPM_U32_SIZE, TPM_DATA_OFFSET,
					   TPM_U32_SIZE,
					   TPM_DATA_OFFSET + TPM_U32_SIZE,
					   size2,
					   TPM_DATA_OFFSET + TPM_U32_SIZE +
					   TPM_U32_SIZE, 0, 0);
		}
		TSS_OIAPclose(authhandle1);
		if (ret != 0)
			return ret;
	}
	memcpy(rndblob, tpmdata + TPM_DATA_OFFSET + TPM_U32_SIZE, size1);
	memcpy(outblob,
	       tpmdata + TPM_DATA_OFFSET + TPM_U32_SIZE + size1 +
	       TPM_U32_SIZE, size2);
	*rndblen = size1;
	*outblen = size2;
	return 0;
}
Example #2
0
/*
 * use the AUTH2_COMMAND form of unseal, to authorize both key and blob
 */
static int tpm_unseal(struct tpm_buf *tb,
		      uint32_t keyhandle, const unsigned char *keyauth,
		      const unsigned char *blob, int bloblen,
		      const unsigned char *blobauth,
		      unsigned char *data, unsigned int *datalen)
{
	unsigned char nonceodd[TPM_NONCE_SIZE];
	unsigned char enonce1[TPM_NONCE_SIZE];
	unsigned char enonce2[TPM_NONCE_SIZE];
	unsigned char authdata1[SHA1_DIGEST_SIZE];
	unsigned char authdata2[SHA1_DIGEST_SIZE];
	uint32_t authhandle1 = 0;
	uint32_t authhandle2 = 0;
	unsigned char cont = 0;
	uint32_t ordinal;
	uint32_t keyhndl;
	int ret;

	/* sessions for unsealing key and data */
	ret = oiap(tb, &authhandle1, enonce1);
	if (ret < 0) {
		pr_info("trusted_key: oiap failed (%d)\n", ret);
		return ret;
	}
	ret = oiap(tb, &authhandle2, enonce2);
	if (ret < 0) {
		pr_info("trusted_key: oiap failed (%d)\n", ret);
		return ret;
	}

	ordinal = htonl(TPM_ORD_UNSEAL);
	keyhndl = htonl(SRKHANDLE);
	ret = tpm_get_random(TPM_ANY_NUM, nonceodd, TPM_NONCE_SIZE);
	if (ret != TPM_NONCE_SIZE) {
		pr_info("trusted_key: tpm_get_random failed (%d)\n", ret);
		return ret;
	}
	ret = TSS_authhmac(authdata1, keyauth, TPM_NONCE_SIZE,
			   enonce1, nonceodd, cont, sizeof(uint32_t),
			   &ordinal, bloblen, blob, 0, 0);
	if (ret < 0)
		return ret;
	ret = TSS_authhmac(authdata2, blobauth, TPM_NONCE_SIZE,
			   enonce2, nonceodd, cont, sizeof(uint32_t),
			   &ordinal, bloblen, blob, 0, 0);
	if (ret < 0)
		return ret;

	/* build and send TPM request packet */
	INIT_BUF(tb);
	store16(tb, TPM_TAG_RQU_AUTH2_COMMAND);
	store32(tb, TPM_UNSEAL_SIZE + bloblen);
	store32(tb, TPM_ORD_UNSEAL);
	store32(tb, keyhandle);
	storebytes(tb, blob, bloblen);
	store32(tb, authhandle1);
	storebytes(tb, nonceodd, TPM_NONCE_SIZE);
	store8(tb, cont);
	storebytes(tb, authdata1, SHA1_DIGEST_SIZE);
	store32(tb, authhandle2);
	storebytes(tb, nonceodd, TPM_NONCE_SIZE);
	store8(tb, cont);
	storebytes(tb, authdata2, SHA1_DIGEST_SIZE);

	ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, MAX_BUF_SIZE);
	if (ret < 0) {
		pr_info("trusted_key: authhmac failed (%d)\n", ret);
		return ret;
	}

	*datalen = LOAD32(tb->data, TPM_DATA_OFFSET);
	ret = TSS_checkhmac2(tb->data, ordinal, nonceodd,
			     keyauth, SHA1_DIGEST_SIZE,
			     blobauth, SHA1_DIGEST_SIZE,
			     sizeof(uint32_t), TPM_DATA_OFFSET,
			     *datalen, TPM_DATA_OFFSET + sizeof(uint32_t), 0,
			     0);
	if (ret < 0) {
		pr_info("trusted_key: TSS_checkhmac2 failed (%d)\n", ret);
		return ret;
	}
	memcpy(data, tb->data + TPM_DATA_OFFSET + sizeof(uint32_t), *datalen);
	return 0;
}
Example #3
0
File: seal.c Project: 3van/tpmtotp
uint32_t TPM_Unseal(uint32_t keyhandle,
		    unsigned char *keyauth,
		    unsigned char *dataauth,
		    unsigned char *blob, unsigned int bloblen,
		    unsigned char *rawdata, unsigned int *datalen)
{
	unsigned char unseal_fmt[] = "00 C3 T l l % l % o % l % o %";
	unsigned char unseal_fmt_noauth[] = "00 C2 T l l % l % o %";
	uint32_t ret;
	unsigned char tpmdata[TPM_MAX_BUFF_SIZE];
	unsigned char nonceodd[TPM_NONCE_SIZE];
	unsigned char enonce1[TPM_NONCE_SIZE];
	unsigned char enonce2[TPM_NONCE_SIZE];
	unsigned char dummyauth[TPM_NONCE_SIZE];
	unsigned char *passptr2;
	unsigned char c;
	uint32_t ordinal;
	uint32_t keyhndl;
	uint32_t authhandle1;
	uint32_t authhandle2;
	unsigned char authdata1[TPM_HASH_SIZE];
	unsigned char authdata2[TPM_HASH_SIZE];

	memset(dummyauth, 0, sizeof dummyauth);
	/* check input arguments */
	if (rawdata == NULL || blob == NULL)
		return ERR_NULL_ARG;
	if (dataauth == NULL)
		passptr2 = dummyauth;
	else
		passptr2 = dataauth;
	if (keyauth != NULL) {	/* key password specified */
		/* open TWO OIAP sessions, Key and Data */
		ret = TSS_OIAPopen(&authhandle1, enonce1);
		if (ret != 0)
			return ret;
		ret = TSS_OIAPopen(&authhandle2, enonce2);
		if (ret != 0)
			return ret;
		/* data to Network byte order variables for HMAC calculation */
		ordinal = htonl(0x18);
		keyhndl = htonl(keyhandle);
		/* generate odd nonce */
		TSS_gennonce(nonceodd);
		c = 0;
		/* calculate KEY authorization HMAC value */
		ret =
		    TSS_authhmac(authdata1, keyauth, TPM_HASH_SIZE,
				 enonce1, nonceodd, c, TPM_U32_SIZE,
				 &ordinal, bloblen, blob, 0, 0);
		if (ret != 0) {
			TSS_OIAPclose(authhandle1);
			TSS_OIAPclose(authhandle2);
			return ret;
		}
		/* calculate DATA authorization HMAC value */
		ret =
		    TSS_authhmac(authdata2, passptr2, TPM_NONCE_SIZE,
				 enonce2, nonceodd, c, TPM_U32_SIZE,
				 &ordinal, bloblen, blob, 0, 0);
		if (ret != 0) {
			TSS_OIAPclose(authhandle1);
			TSS_OIAPclose(authhandle2);
			return ret;
		}
		/* build the request buffer */
		ret = TSS_buildbuff(unseal_fmt, tpmdata,
				    ordinal,
				    keyhndl,
				    bloblen, blob,
				    authhandle1,
				    TPM_NONCE_SIZE, nonceodd,
				    c,
				    TPM_HASH_SIZE, authdata1,
				    authhandle2,
				    TPM_NONCE_SIZE, nonceodd,
				    c, TPM_HASH_SIZE, authdata2);

		if ((ret & ERR_MASK) != 0) {
			TSS_OIAPclose(authhandle1);
			TSS_OIAPclose(authhandle2);
			return ret;
		}
		/* transmit buffer to the TPM device and read the reply */
		ret = TPM_Transmit(tpmdata, "Unseal");
		if (ret != 0) {
			TSS_OIAPclose(authhandle1);
			TSS_OIAPclose(authhandle2);
			return ret;
		}
		*datalen = LOAD32(tpmdata, TPM_DATA_OFFSET);
		/* check HMAC in response */
		ret = TSS_checkhmac2(tpmdata, ordinal, nonceodd,
				     keyauth, TPM_HASH_SIZE,
				     passptr2, TPM_HASH_SIZE,
				     TPM_U32_SIZE, TPM_DATA_OFFSET,
				     *datalen,
				     TPM_DATA_OFFSET + TPM_U32_SIZE, 0, 0);
		TSS_OIAPclose(authhandle1);
		TSS_OIAPclose(authhandle2);
		if (ret != 0)
			return ret;
	} else {		/* no key password */

		/* open ONE OIAP session, for the Data */
		ret = TSS_OIAPopen(&authhandle2, enonce2);
		if (ret != 0)
			return ret;
		/* data to Network byte order variables for HMAC calculation */
		ordinal = htonl(0x18);
		keyhndl = htonl(keyhandle);
		/* generate odd nonce */
		TSS_gennonce(nonceodd);
		c = 0;
		/* calculate DATA authorization HMAC value */
		ret =
		    TSS_authhmac(authdata2, passptr2, TPM_NONCE_SIZE,
				 enonce2, nonceodd, c, TPM_U32_SIZE,
				 &ordinal, bloblen, blob, 0, 0);
		if (ret != 0) {
			TSS_OIAPclose(authhandle2);
			return ret;
		}
		/* build the request buffer */
		ret = TSS_buildbuff(unseal_fmt_noauth, tpmdata,
				    ordinal,
				    keyhndl,
				    bloblen, blob,
				    authhandle2,
				    TPM_NONCE_SIZE, nonceodd,
				    c, TPM_HASH_SIZE, authdata2);

		if ((ret & ERR_MASK) != 0) {
			TSS_OIAPclose(authhandle2);
			return ret;
		}
		/* transmit buffer to the TPM device and read the reply */
		ret = TPM_Transmit(tpmdata, "Unseal");
		if (ret != 0) {
			TSS_OIAPclose(authhandle2);
			return ret;
		}
		*datalen = LOAD32(tpmdata, TPM_DATA_OFFSET);
		/* check HMAC in response */
		ret = TSS_checkhmac1(tpmdata, ordinal, nonceodd,
				     passptr2, TPM_HASH_SIZE,
				     TPM_U32_SIZE, TPM_DATA_OFFSET,
				     *datalen,
				     TPM_DATA_OFFSET + TPM_U32_SIZE, 0, 0);
		TSS_OIAPclose(authhandle2);
		if (ret != 0)
			return ret;
	}
	/* copy decrypted data back to caller */
	memcpy(rawdata, tpmdata + TPM_DATA_OFFSET + TPM_U32_SIZE,
	       *datalen);
	return 0;
}