147f9c279SSumit Garg // SPDX-License-Identifier: GPL-2.0-only 247f9c279SSumit Garg /* 347f9c279SSumit Garg * Copyright (C) 2010 IBM Corporation 45d0682beSSumit Garg * Copyright (c) 2019-2021, Linaro Limited 547f9c279SSumit Garg * 647f9c279SSumit Garg * See Documentation/security/keys/trusted-encrypted.rst 747f9c279SSumit Garg */ 847f9c279SSumit Garg 947f9c279SSumit Garg #include <crypto/hash_info.h> 1047f9c279SSumit Garg #include <linux/init.h> 1147f9c279SSumit Garg #include <linux/slab.h> 1247f9c279SSumit Garg #include <linux/parser.h> 1347f9c279SSumit Garg #include <linux/string.h> 1447f9c279SSumit Garg #include <linux/err.h> 1547f9c279SSumit Garg #include <keys/trusted-type.h> 1647f9c279SSumit Garg #include <linux/key-type.h> 1747f9c279SSumit Garg #include <linux/crypto.h> 1847f9c279SSumit Garg #include <crypto/hash.h> 19a24d22b2SEric Biggers #include <crypto/sha1.h> 2047f9c279SSumit Garg #include <linux/tpm.h> 2147f9c279SSumit Garg #include <linux/tpm_command.h> 2247f9c279SSumit Garg 2347f9c279SSumit Garg #include <keys/trusted_tpm.h> 2447f9c279SSumit Garg 2547f9c279SSumit Garg static const char hmac_alg[] = "hmac(sha1)"; 2647f9c279SSumit Garg static const char hash_alg[] = "sha1"; 2747f9c279SSumit Garg static struct tpm_chip *chip; 2847f9c279SSumit Garg static struct tpm_digest *digests; 2947f9c279SSumit Garg 3047f9c279SSumit Garg struct sdesc { 3147f9c279SSumit Garg struct shash_desc shash; 3247f9c279SSumit Garg char ctx[]; 3347f9c279SSumit Garg }; 3447f9c279SSumit Garg 3547f9c279SSumit Garg static struct crypto_shash *hashalg; 3647f9c279SSumit Garg static struct crypto_shash *hmacalg; 3747f9c279SSumit Garg 3847f9c279SSumit Garg static struct sdesc *init_sdesc(struct crypto_shash *alg) 3947f9c279SSumit Garg { 4047f9c279SSumit Garg struct sdesc *sdesc; 4147f9c279SSumit Garg int size; 4247f9c279SSumit Garg 4347f9c279SSumit Garg size = sizeof(struct shash_desc) + crypto_shash_descsize(alg); 4447f9c279SSumit Garg sdesc = kmalloc(size, GFP_KERNEL); 4547f9c279SSumit Garg if (!sdesc) 4647f9c279SSumit Garg return ERR_PTR(-ENOMEM); 4747f9c279SSumit Garg sdesc->shash.tfm = alg; 4847f9c279SSumit Garg return sdesc; 4947f9c279SSumit Garg } 5047f9c279SSumit Garg 5147f9c279SSumit Garg static int TSS_sha1(const unsigned char *data, unsigned int datalen, 5247f9c279SSumit Garg unsigned char *digest) 5347f9c279SSumit Garg { 5447f9c279SSumit Garg struct sdesc *sdesc; 5547f9c279SSumit Garg int ret; 5647f9c279SSumit Garg 5747f9c279SSumit Garg sdesc = init_sdesc(hashalg); 5847f9c279SSumit Garg if (IS_ERR(sdesc)) { 595d0682beSSumit Garg pr_info("can't alloc %s\n", hash_alg); 6047f9c279SSumit Garg return PTR_ERR(sdesc); 6147f9c279SSumit Garg } 6247f9c279SSumit Garg 6347f9c279SSumit Garg ret = crypto_shash_digest(&sdesc->shash, data, datalen, digest); 64453431a5SWaiman Long kfree_sensitive(sdesc); 6547f9c279SSumit Garg return ret; 6647f9c279SSumit Garg } 6747f9c279SSumit Garg 6847f9c279SSumit Garg static int TSS_rawhmac(unsigned char *digest, const unsigned char *key, 6947f9c279SSumit Garg unsigned int keylen, ...) 7047f9c279SSumit Garg { 7147f9c279SSumit Garg struct sdesc *sdesc; 7247f9c279SSumit Garg va_list argp; 7347f9c279SSumit Garg unsigned int dlen; 7447f9c279SSumit Garg unsigned char *data; 7547f9c279SSumit Garg int ret; 7647f9c279SSumit Garg 7747f9c279SSumit Garg sdesc = init_sdesc(hmacalg); 7847f9c279SSumit Garg if (IS_ERR(sdesc)) { 795d0682beSSumit Garg pr_info("can't alloc %s\n", hmac_alg); 8047f9c279SSumit Garg return PTR_ERR(sdesc); 8147f9c279SSumit Garg } 8247f9c279SSumit Garg 8347f9c279SSumit Garg ret = crypto_shash_setkey(hmacalg, key, keylen); 8447f9c279SSumit Garg if (ret < 0) 8547f9c279SSumit Garg goto out; 8647f9c279SSumit Garg ret = crypto_shash_init(&sdesc->shash); 8747f9c279SSumit Garg if (ret < 0) 8847f9c279SSumit Garg goto out; 8947f9c279SSumit Garg 9047f9c279SSumit Garg va_start(argp, keylen); 9147f9c279SSumit Garg for (;;) { 9247f9c279SSumit Garg dlen = va_arg(argp, unsigned int); 9347f9c279SSumit Garg if (dlen == 0) 9447f9c279SSumit Garg break; 9547f9c279SSumit Garg data = va_arg(argp, unsigned char *); 9647f9c279SSumit Garg if (data == NULL) { 9747f9c279SSumit Garg ret = -EINVAL; 9847f9c279SSumit Garg break; 9947f9c279SSumit Garg } 10047f9c279SSumit Garg ret = crypto_shash_update(&sdesc->shash, data, dlen); 10147f9c279SSumit Garg if (ret < 0) 10247f9c279SSumit Garg break; 10347f9c279SSumit Garg } 10447f9c279SSumit Garg va_end(argp); 10547f9c279SSumit Garg if (!ret) 10647f9c279SSumit Garg ret = crypto_shash_final(&sdesc->shash, digest); 10747f9c279SSumit Garg out: 108453431a5SWaiman Long kfree_sensitive(sdesc); 10947f9c279SSumit Garg return ret; 11047f9c279SSumit Garg } 11147f9c279SSumit Garg 11247f9c279SSumit Garg /* 11347f9c279SSumit Garg * calculate authorization info fields to send to TPM 11447f9c279SSumit Garg */ 11547f9c279SSumit Garg int TSS_authhmac(unsigned char *digest, const unsigned char *key, 11647f9c279SSumit Garg unsigned int keylen, unsigned char *h1, 11747f9c279SSumit Garg unsigned char *h2, unsigned int h3, ...) 11847f9c279SSumit Garg { 11947f9c279SSumit Garg unsigned char paramdigest[SHA1_DIGEST_SIZE]; 12047f9c279SSumit Garg struct sdesc *sdesc; 12147f9c279SSumit Garg unsigned int dlen; 12247f9c279SSumit Garg unsigned char *data; 12347f9c279SSumit Garg unsigned char c; 12447f9c279SSumit Garg int ret; 12547f9c279SSumit Garg va_list argp; 12647f9c279SSumit Garg 12747f9c279SSumit Garg if (!chip) 12847f9c279SSumit Garg return -ENODEV; 12947f9c279SSumit Garg 13047f9c279SSumit Garg sdesc = init_sdesc(hashalg); 13147f9c279SSumit Garg if (IS_ERR(sdesc)) { 1325d0682beSSumit Garg pr_info("can't alloc %s\n", hash_alg); 13347f9c279SSumit Garg return PTR_ERR(sdesc); 13447f9c279SSumit Garg } 13547f9c279SSumit Garg 13647f9c279SSumit Garg c = !!h3; 13747f9c279SSumit Garg ret = crypto_shash_init(&sdesc->shash); 13847f9c279SSumit Garg if (ret < 0) 13947f9c279SSumit Garg goto out; 14047f9c279SSumit Garg va_start(argp, h3); 14147f9c279SSumit Garg for (;;) { 14247f9c279SSumit Garg dlen = va_arg(argp, unsigned int); 14347f9c279SSumit Garg if (dlen == 0) 14447f9c279SSumit Garg break; 14547f9c279SSumit Garg data = va_arg(argp, unsigned char *); 14647f9c279SSumit Garg if (!data) { 14747f9c279SSumit Garg ret = -EINVAL; 14847f9c279SSumit Garg break; 14947f9c279SSumit Garg } 15047f9c279SSumit Garg ret = crypto_shash_update(&sdesc->shash, data, dlen); 15147f9c279SSumit Garg if (ret < 0) 15247f9c279SSumit Garg break; 15347f9c279SSumit Garg } 15447f9c279SSumit Garg va_end(argp); 15547f9c279SSumit Garg if (!ret) 15647f9c279SSumit Garg ret = crypto_shash_final(&sdesc->shash, paramdigest); 15747f9c279SSumit Garg if (!ret) 15847f9c279SSumit Garg ret = TSS_rawhmac(digest, key, keylen, SHA1_DIGEST_SIZE, 15947f9c279SSumit Garg paramdigest, TPM_NONCE_SIZE, h1, 16047f9c279SSumit Garg TPM_NONCE_SIZE, h2, 1, &c, 0, 0); 16147f9c279SSumit Garg out: 162453431a5SWaiman Long kfree_sensitive(sdesc); 16347f9c279SSumit Garg return ret; 16447f9c279SSumit Garg } 16547f9c279SSumit Garg EXPORT_SYMBOL_GPL(TSS_authhmac); 16647f9c279SSumit Garg 16747f9c279SSumit Garg /* 16847f9c279SSumit Garg * verify the AUTH1_COMMAND (Seal) result from TPM 16947f9c279SSumit Garg */ 17047f9c279SSumit Garg int TSS_checkhmac1(unsigned char *buffer, 17147f9c279SSumit Garg const uint32_t command, 17247f9c279SSumit Garg const unsigned char *ononce, 17347f9c279SSumit Garg const unsigned char *key, 17447f9c279SSumit Garg unsigned int keylen, ...) 17547f9c279SSumit Garg { 17647f9c279SSumit Garg uint32_t bufsize; 17747f9c279SSumit Garg uint16_t tag; 17847f9c279SSumit Garg uint32_t ordinal; 17947f9c279SSumit Garg uint32_t result; 18047f9c279SSumit Garg unsigned char *enonce; 18147f9c279SSumit Garg unsigned char *continueflag; 18247f9c279SSumit Garg unsigned char *authdata; 18347f9c279SSumit Garg unsigned char testhmac[SHA1_DIGEST_SIZE]; 18447f9c279SSumit Garg unsigned char paramdigest[SHA1_DIGEST_SIZE]; 18547f9c279SSumit Garg struct sdesc *sdesc; 18647f9c279SSumit Garg unsigned int dlen; 18747f9c279SSumit Garg unsigned int dpos; 18847f9c279SSumit Garg va_list argp; 18947f9c279SSumit Garg int ret; 19047f9c279SSumit Garg 19147f9c279SSumit Garg if (!chip) 19247f9c279SSumit Garg return -ENODEV; 19347f9c279SSumit Garg 19447f9c279SSumit Garg bufsize = LOAD32(buffer, TPM_SIZE_OFFSET); 19547f9c279SSumit Garg tag = LOAD16(buffer, 0); 19647f9c279SSumit Garg ordinal = command; 19747f9c279SSumit Garg result = LOAD32N(buffer, TPM_RETURN_OFFSET); 19847f9c279SSumit Garg if (tag == TPM_TAG_RSP_COMMAND) 19947f9c279SSumit Garg return 0; 20047f9c279SSumit Garg if (tag != TPM_TAG_RSP_AUTH1_COMMAND) 20147f9c279SSumit Garg return -EINVAL; 20247f9c279SSumit Garg authdata = buffer + bufsize - SHA1_DIGEST_SIZE; 20347f9c279SSumit Garg continueflag = authdata - 1; 20447f9c279SSumit Garg enonce = continueflag - TPM_NONCE_SIZE; 20547f9c279SSumit Garg 20647f9c279SSumit Garg sdesc = init_sdesc(hashalg); 20747f9c279SSumit Garg if (IS_ERR(sdesc)) { 2085d0682beSSumit Garg pr_info("can't alloc %s\n", hash_alg); 20947f9c279SSumit Garg return PTR_ERR(sdesc); 21047f9c279SSumit Garg } 21147f9c279SSumit Garg ret = crypto_shash_init(&sdesc->shash); 21247f9c279SSumit Garg if (ret < 0) 21347f9c279SSumit Garg goto out; 21447f9c279SSumit Garg ret = crypto_shash_update(&sdesc->shash, (const u8 *)&result, 21547f9c279SSumit Garg sizeof result); 21647f9c279SSumit Garg if (ret < 0) 21747f9c279SSumit Garg goto out; 21847f9c279SSumit Garg ret = crypto_shash_update(&sdesc->shash, (const u8 *)&ordinal, 21947f9c279SSumit Garg sizeof ordinal); 22047f9c279SSumit Garg if (ret < 0) 22147f9c279SSumit Garg goto out; 22247f9c279SSumit Garg va_start(argp, keylen); 22347f9c279SSumit Garg for (;;) { 22447f9c279SSumit Garg dlen = va_arg(argp, unsigned int); 22547f9c279SSumit Garg if (dlen == 0) 22647f9c279SSumit Garg break; 22747f9c279SSumit Garg dpos = va_arg(argp, unsigned int); 22847f9c279SSumit Garg ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen); 22947f9c279SSumit Garg if (ret < 0) 23047f9c279SSumit Garg break; 23147f9c279SSumit Garg } 23247f9c279SSumit Garg va_end(argp); 23347f9c279SSumit Garg if (!ret) 23447f9c279SSumit Garg ret = crypto_shash_final(&sdesc->shash, paramdigest); 23547f9c279SSumit Garg if (ret < 0) 23647f9c279SSumit Garg goto out; 23747f9c279SSumit Garg 23847f9c279SSumit Garg ret = TSS_rawhmac(testhmac, key, keylen, SHA1_DIGEST_SIZE, paramdigest, 23947f9c279SSumit Garg TPM_NONCE_SIZE, enonce, TPM_NONCE_SIZE, ononce, 24047f9c279SSumit Garg 1, continueflag, 0, 0); 24147f9c279SSumit Garg if (ret < 0) 24247f9c279SSumit Garg goto out; 24347f9c279SSumit Garg 24447f9c279SSumit Garg if (memcmp(testhmac, authdata, SHA1_DIGEST_SIZE)) 24547f9c279SSumit Garg ret = -EINVAL; 24647f9c279SSumit Garg out: 247453431a5SWaiman Long kfree_sensitive(sdesc); 24847f9c279SSumit Garg return ret; 24947f9c279SSumit Garg } 25047f9c279SSumit Garg EXPORT_SYMBOL_GPL(TSS_checkhmac1); 25147f9c279SSumit Garg 25247f9c279SSumit Garg /* 25347f9c279SSumit Garg * verify the AUTH2_COMMAND (unseal) result from TPM 25447f9c279SSumit Garg */ 25547f9c279SSumit Garg static int TSS_checkhmac2(unsigned char *buffer, 25647f9c279SSumit Garg const uint32_t command, 25747f9c279SSumit Garg const unsigned char *ononce, 25847f9c279SSumit Garg const unsigned char *key1, 25947f9c279SSumit Garg unsigned int keylen1, 26047f9c279SSumit Garg const unsigned char *key2, 26147f9c279SSumit Garg unsigned int keylen2, ...) 26247f9c279SSumit Garg { 26347f9c279SSumit Garg uint32_t bufsize; 26447f9c279SSumit Garg uint16_t tag; 26547f9c279SSumit Garg uint32_t ordinal; 26647f9c279SSumit Garg uint32_t result; 26747f9c279SSumit Garg unsigned char *enonce1; 26847f9c279SSumit Garg unsigned char *continueflag1; 26947f9c279SSumit Garg unsigned char *authdata1; 27047f9c279SSumit Garg unsigned char *enonce2; 27147f9c279SSumit Garg unsigned char *continueflag2; 27247f9c279SSumit Garg unsigned char *authdata2; 27347f9c279SSumit Garg unsigned char testhmac1[SHA1_DIGEST_SIZE]; 27447f9c279SSumit Garg unsigned char testhmac2[SHA1_DIGEST_SIZE]; 27547f9c279SSumit Garg unsigned char paramdigest[SHA1_DIGEST_SIZE]; 27647f9c279SSumit Garg struct sdesc *sdesc; 27747f9c279SSumit Garg unsigned int dlen; 27847f9c279SSumit Garg unsigned int dpos; 27947f9c279SSumit Garg va_list argp; 28047f9c279SSumit Garg int ret; 28147f9c279SSumit Garg 28247f9c279SSumit Garg bufsize = LOAD32(buffer, TPM_SIZE_OFFSET); 28347f9c279SSumit Garg tag = LOAD16(buffer, 0); 28447f9c279SSumit Garg ordinal = command; 28547f9c279SSumit Garg result = LOAD32N(buffer, TPM_RETURN_OFFSET); 28647f9c279SSumit Garg 28747f9c279SSumit Garg if (tag == TPM_TAG_RSP_COMMAND) 28847f9c279SSumit Garg return 0; 28947f9c279SSumit Garg if (tag != TPM_TAG_RSP_AUTH2_COMMAND) 29047f9c279SSumit Garg return -EINVAL; 29147f9c279SSumit Garg authdata1 = buffer + bufsize - (SHA1_DIGEST_SIZE + 1 29247f9c279SSumit Garg + SHA1_DIGEST_SIZE + SHA1_DIGEST_SIZE); 29347f9c279SSumit Garg authdata2 = buffer + bufsize - (SHA1_DIGEST_SIZE); 29447f9c279SSumit Garg continueflag1 = authdata1 - 1; 29547f9c279SSumit Garg continueflag2 = authdata2 - 1; 29647f9c279SSumit Garg enonce1 = continueflag1 - TPM_NONCE_SIZE; 29747f9c279SSumit Garg enonce2 = continueflag2 - TPM_NONCE_SIZE; 29847f9c279SSumit Garg 29947f9c279SSumit Garg sdesc = init_sdesc(hashalg); 30047f9c279SSumit Garg if (IS_ERR(sdesc)) { 3015d0682beSSumit Garg pr_info("can't alloc %s\n", hash_alg); 30247f9c279SSumit Garg return PTR_ERR(sdesc); 30347f9c279SSumit Garg } 30447f9c279SSumit Garg ret = crypto_shash_init(&sdesc->shash); 30547f9c279SSumit Garg if (ret < 0) 30647f9c279SSumit Garg goto out; 30747f9c279SSumit Garg ret = crypto_shash_update(&sdesc->shash, (const u8 *)&result, 30847f9c279SSumit Garg sizeof result); 30947f9c279SSumit Garg if (ret < 0) 31047f9c279SSumit Garg goto out; 31147f9c279SSumit Garg ret = crypto_shash_update(&sdesc->shash, (const u8 *)&ordinal, 31247f9c279SSumit Garg sizeof ordinal); 31347f9c279SSumit Garg if (ret < 0) 31447f9c279SSumit Garg goto out; 31547f9c279SSumit Garg 31647f9c279SSumit Garg va_start(argp, keylen2); 31747f9c279SSumit Garg for (;;) { 31847f9c279SSumit Garg dlen = va_arg(argp, unsigned int); 31947f9c279SSumit Garg if (dlen == 0) 32047f9c279SSumit Garg break; 32147f9c279SSumit Garg dpos = va_arg(argp, unsigned int); 32247f9c279SSumit Garg ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen); 32347f9c279SSumit Garg if (ret < 0) 32447f9c279SSumit Garg break; 32547f9c279SSumit Garg } 32647f9c279SSumit Garg va_end(argp); 32747f9c279SSumit Garg if (!ret) 32847f9c279SSumit Garg ret = crypto_shash_final(&sdesc->shash, paramdigest); 32947f9c279SSumit Garg if (ret < 0) 33047f9c279SSumit Garg goto out; 33147f9c279SSumit Garg 33247f9c279SSumit Garg ret = TSS_rawhmac(testhmac1, key1, keylen1, SHA1_DIGEST_SIZE, 33347f9c279SSumit Garg paramdigest, TPM_NONCE_SIZE, enonce1, 33447f9c279SSumit Garg TPM_NONCE_SIZE, ononce, 1, continueflag1, 0, 0); 33547f9c279SSumit Garg if (ret < 0) 33647f9c279SSumit Garg goto out; 33747f9c279SSumit Garg if (memcmp(testhmac1, authdata1, SHA1_DIGEST_SIZE)) { 33847f9c279SSumit Garg ret = -EINVAL; 33947f9c279SSumit Garg goto out; 34047f9c279SSumit Garg } 34147f9c279SSumit Garg ret = TSS_rawhmac(testhmac2, key2, keylen2, SHA1_DIGEST_SIZE, 34247f9c279SSumit Garg paramdigest, TPM_NONCE_SIZE, enonce2, 34347f9c279SSumit Garg TPM_NONCE_SIZE, ononce, 1, continueflag2, 0, 0); 34447f9c279SSumit Garg if (ret < 0) 34547f9c279SSumit Garg goto out; 34647f9c279SSumit Garg if (memcmp(testhmac2, authdata2, SHA1_DIGEST_SIZE)) 34747f9c279SSumit Garg ret = -EINVAL; 34847f9c279SSumit Garg out: 349453431a5SWaiman Long kfree_sensitive(sdesc); 35047f9c279SSumit Garg return ret; 35147f9c279SSumit Garg } 35247f9c279SSumit Garg 35347f9c279SSumit Garg /* 35447f9c279SSumit Garg * For key specific tpm requests, we will generate and send our 35547f9c279SSumit Garg * own TPM command packets using the drivers send function. 35647f9c279SSumit Garg */ 35747f9c279SSumit Garg int trusted_tpm_send(unsigned char *cmd, size_t buflen) 35847f9c279SSumit Garg { 35947f9c279SSumit Garg int rc; 36047f9c279SSumit Garg 36147f9c279SSumit Garg if (!chip) 36247f9c279SSumit Garg return -ENODEV; 36347f9c279SSumit Garg 36447f9c279SSumit Garg dump_tpm_buf(cmd); 36547f9c279SSumit Garg rc = tpm_send(chip, cmd, buflen); 36647f9c279SSumit Garg dump_tpm_buf(cmd); 36747f9c279SSumit Garg if (rc > 0) 36847f9c279SSumit Garg /* Can't return positive return codes values to keyctl */ 36947f9c279SSumit Garg rc = -EPERM; 37047f9c279SSumit Garg return rc; 37147f9c279SSumit Garg } 37247f9c279SSumit Garg EXPORT_SYMBOL_GPL(trusted_tpm_send); 37347f9c279SSumit Garg 37447f9c279SSumit Garg /* 37547f9c279SSumit Garg * Lock a trusted key, by extending a selected PCR. 37647f9c279SSumit Garg * 37747f9c279SSumit Garg * Prevents a trusted key that is sealed to PCRs from being accessed. 37847f9c279SSumit Garg * This uses the tpm driver's extend function. 37947f9c279SSumit Garg */ 38047f9c279SSumit Garg static int pcrlock(const int pcrnum) 38147f9c279SSumit Garg { 38247f9c279SSumit Garg if (!capable(CAP_SYS_ADMIN)) 38347f9c279SSumit Garg return -EPERM; 38447f9c279SSumit Garg 38547f9c279SSumit Garg return tpm_pcr_extend(chip, pcrnum, digests) ? -EINVAL : 0; 38647f9c279SSumit Garg } 38747f9c279SSumit Garg 38847f9c279SSumit Garg /* 38947f9c279SSumit Garg * Create an object specific authorisation protocol (OSAP) session 39047f9c279SSumit Garg */ 39147f9c279SSumit Garg static int osap(struct tpm_buf *tb, struct osapsess *s, 39247f9c279SSumit Garg const unsigned char *key, uint16_t type, uint32_t handle) 39347f9c279SSumit Garg { 39447f9c279SSumit Garg unsigned char enonce[TPM_NONCE_SIZE]; 39547f9c279SSumit Garg unsigned char ononce[TPM_NONCE_SIZE]; 39647f9c279SSumit Garg int ret; 39747f9c279SSumit Garg 39847f9c279SSumit Garg ret = tpm_get_random(chip, ononce, TPM_NONCE_SIZE); 3995df16caaSJarkko Sakkinen if (ret < 0) 40047f9c279SSumit Garg return ret; 40147f9c279SSumit Garg 4025df16caaSJarkko Sakkinen if (ret != TPM_NONCE_SIZE) 4035df16caaSJarkko Sakkinen return -EIO; 4045df16caaSJarkko Sakkinen 40547f9c279SSumit Garg tpm_buf_reset(tb, TPM_TAG_RQU_COMMAND, TPM_ORD_OSAP); 40647f9c279SSumit Garg tpm_buf_append_u16(tb, type); 40747f9c279SSumit Garg tpm_buf_append_u32(tb, handle); 40847f9c279SSumit Garg tpm_buf_append(tb, ononce, TPM_NONCE_SIZE); 40947f9c279SSumit Garg 41047f9c279SSumit Garg ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE); 41147f9c279SSumit Garg if (ret < 0) 41247f9c279SSumit Garg return ret; 41347f9c279SSumit Garg 41447f9c279SSumit Garg s->handle = LOAD32(tb->data, TPM_DATA_OFFSET); 41547f9c279SSumit Garg memcpy(s->enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)]), 41647f9c279SSumit Garg TPM_NONCE_SIZE); 41747f9c279SSumit Garg memcpy(enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t) + 41847f9c279SSumit Garg TPM_NONCE_SIZE]), TPM_NONCE_SIZE); 41947f9c279SSumit Garg return TSS_rawhmac(s->secret, key, SHA1_DIGEST_SIZE, TPM_NONCE_SIZE, 42047f9c279SSumit Garg enonce, TPM_NONCE_SIZE, ononce, 0, 0); 42147f9c279SSumit Garg } 42247f9c279SSumit Garg 42347f9c279SSumit Garg /* 42447f9c279SSumit Garg * Create an object independent authorisation protocol (oiap) session 42547f9c279SSumit Garg */ 42647f9c279SSumit Garg int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce) 42747f9c279SSumit Garg { 42847f9c279SSumit Garg int ret; 42947f9c279SSumit Garg 43047f9c279SSumit Garg if (!chip) 43147f9c279SSumit Garg return -ENODEV; 43247f9c279SSumit Garg 43347f9c279SSumit Garg tpm_buf_reset(tb, TPM_TAG_RQU_COMMAND, TPM_ORD_OIAP); 43447f9c279SSumit Garg ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE); 43547f9c279SSumit Garg if (ret < 0) 43647f9c279SSumit Garg return ret; 43747f9c279SSumit Garg 43847f9c279SSumit Garg *handle = LOAD32(tb->data, TPM_DATA_OFFSET); 43947f9c279SSumit Garg memcpy(nonce, &tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)], 44047f9c279SSumit Garg TPM_NONCE_SIZE); 44147f9c279SSumit Garg return 0; 44247f9c279SSumit Garg } 44347f9c279SSumit Garg EXPORT_SYMBOL_GPL(oiap); 44447f9c279SSumit Garg 44547f9c279SSumit Garg struct tpm_digests { 44647f9c279SSumit Garg unsigned char encauth[SHA1_DIGEST_SIZE]; 44747f9c279SSumit Garg unsigned char pubauth[SHA1_DIGEST_SIZE]; 44847f9c279SSumit Garg unsigned char xorwork[SHA1_DIGEST_SIZE * 2]; 44947f9c279SSumit Garg unsigned char xorhash[SHA1_DIGEST_SIZE]; 45047f9c279SSumit Garg unsigned char nonceodd[TPM_NONCE_SIZE]; 45147f9c279SSumit Garg }; 45247f9c279SSumit Garg 45347f9c279SSumit Garg /* 45447f9c279SSumit Garg * Have the TPM seal(encrypt) the trusted key, possibly based on 45547f9c279SSumit Garg * Platform Configuration Registers (PCRs). AUTH1 for sealing key. 45647f9c279SSumit Garg */ 45747f9c279SSumit Garg static int tpm_seal(struct tpm_buf *tb, uint16_t keytype, 45847f9c279SSumit Garg uint32_t keyhandle, const unsigned char *keyauth, 45947f9c279SSumit Garg const unsigned char *data, uint32_t datalen, 46047f9c279SSumit Garg unsigned char *blob, uint32_t *bloblen, 46147f9c279SSumit Garg const unsigned char *blobauth, 46247f9c279SSumit Garg const unsigned char *pcrinfo, uint32_t pcrinfosize) 46347f9c279SSumit Garg { 46447f9c279SSumit Garg struct osapsess sess; 46547f9c279SSumit Garg struct tpm_digests *td; 46647f9c279SSumit Garg unsigned char cont; 46747f9c279SSumit Garg uint32_t ordinal; 46847f9c279SSumit Garg uint32_t pcrsize; 46947f9c279SSumit Garg uint32_t datsize; 47047f9c279SSumit Garg int sealinfosize; 47147f9c279SSumit Garg int encdatasize; 47247f9c279SSumit Garg int storedsize; 47347f9c279SSumit Garg int ret; 47447f9c279SSumit Garg int i; 47547f9c279SSumit Garg 47647f9c279SSumit Garg /* alloc some work space for all the hashes */ 47747f9c279SSumit Garg td = kmalloc(sizeof *td, GFP_KERNEL); 47847f9c279SSumit Garg if (!td) 47947f9c279SSumit Garg return -ENOMEM; 48047f9c279SSumit Garg 48147f9c279SSumit Garg /* get session for sealing key */ 48247f9c279SSumit Garg ret = osap(tb, &sess, keyauth, keytype, keyhandle); 48347f9c279SSumit Garg if (ret < 0) 48447f9c279SSumit Garg goto out; 48547f9c279SSumit Garg dump_sess(&sess); 48647f9c279SSumit Garg 48747f9c279SSumit Garg /* calculate encrypted authorization value */ 48847f9c279SSumit Garg memcpy(td->xorwork, sess.secret, SHA1_DIGEST_SIZE); 48947f9c279SSumit Garg memcpy(td->xorwork + SHA1_DIGEST_SIZE, sess.enonce, SHA1_DIGEST_SIZE); 49047f9c279SSumit Garg ret = TSS_sha1(td->xorwork, SHA1_DIGEST_SIZE * 2, td->xorhash); 49147f9c279SSumit Garg if (ret < 0) 49247f9c279SSumit Garg goto out; 49347f9c279SSumit Garg 49447f9c279SSumit Garg ret = tpm_get_random(chip, td->nonceodd, TPM_NONCE_SIZE); 4955df16caaSJarkko Sakkinen if (ret < 0) 4965df16caaSJarkko Sakkinen return ret; 4975df16caaSJarkko Sakkinen 49847f9c279SSumit Garg if (ret != TPM_NONCE_SIZE) 4995df16caaSJarkko Sakkinen return -EIO; 5005df16caaSJarkko Sakkinen 50147f9c279SSumit Garg ordinal = htonl(TPM_ORD_SEAL); 50247f9c279SSumit Garg datsize = htonl(datalen); 50347f9c279SSumit Garg pcrsize = htonl(pcrinfosize); 50447f9c279SSumit Garg cont = 0; 50547f9c279SSumit Garg 50647f9c279SSumit Garg /* encrypt data authorization key */ 50747f9c279SSumit Garg for (i = 0; i < SHA1_DIGEST_SIZE; ++i) 50847f9c279SSumit Garg td->encauth[i] = td->xorhash[i] ^ blobauth[i]; 50947f9c279SSumit Garg 51047f9c279SSumit Garg /* calculate authorization HMAC value */ 51147f9c279SSumit Garg if (pcrinfosize == 0) { 51247f9c279SSumit Garg /* no pcr info specified */ 51347f9c279SSumit Garg ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE, 51447f9c279SSumit Garg sess.enonce, td->nonceodd, cont, 51547f9c279SSumit Garg sizeof(uint32_t), &ordinal, SHA1_DIGEST_SIZE, 51647f9c279SSumit Garg td->encauth, sizeof(uint32_t), &pcrsize, 51747f9c279SSumit Garg sizeof(uint32_t), &datsize, datalen, data, 0, 51847f9c279SSumit Garg 0); 51947f9c279SSumit Garg } else { 52047f9c279SSumit Garg /* pcr info specified */ 52147f9c279SSumit Garg ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE, 52247f9c279SSumit Garg sess.enonce, td->nonceodd, cont, 52347f9c279SSumit Garg sizeof(uint32_t), &ordinal, SHA1_DIGEST_SIZE, 52447f9c279SSumit Garg td->encauth, sizeof(uint32_t), &pcrsize, 52547f9c279SSumit Garg pcrinfosize, pcrinfo, sizeof(uint32_t), 52647f9c279SSumit Garg &datsize, datalen, data, 0, 0); 52747f9c279SSumit Garg } 52847f9c279SSumit Garg if (ret < 0) 52947f9c279SSumit Garg goto out; 53047f9c279SSumit Garg 53147f9c279SSumit Garg /* build and send the TPM request packet */ 53247f9c279SSumit Garg tpm_buf_reset(tb, TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_SEAL); 53347f9c279SSumit Garg tpm_buf_append_u32(tb, keyhandle); 53447f9c279SSumit Garg tpm_buf_append(tb, td->encauth, SHA1_DIGEST_SIZE); 53547f9c279SSumit Garg tpm_buf_append_u32(tb, pcrinfosize); 53647f9c279SSumit Garg tpm_buf_append(tb, pcrinfo, pcrinfosize); 53747f9c279SSumit Garg tpm_buf_append_u32(tb, datalen); 53847f9c279SSumit Garg tpm_buf_append(tb, data, datalen); 53947f9c279SSumit Garg tpm_buf_append_u32(tb, sess.handle); 54047f9c279SSumit Garg tpm_buf_append(tb, td->nonceodd, TPM_NONCE_SIZE); 54147f9c279SSumit Garg tpm_buf_append_u8(tb, cont); 54247f9c279SSumit Garg tpm_buf_append(tb, td->pubauth, SHA1_DIGEST_SIZE); 54347f9c279SSumit Garg 54447f9c279SSumit Garg ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE); 54547f9c279SSumit Garg if (ret < 0) 54647f9c279SSumit Garg goto out; 54747f9c279SSumit Garg 54847f9c279SSumit Garg /* calculate the size of the returned Blob */ 54947f9c279SSumit Garg sealinfosize = LOAD32(tb->data, TPM_DATA_OFFSET + sizeof(uint32_t)); 55047f9c279SSumit Garg encdatasize = LOAD32(tb->data, TPM_DATA_OFFSET + sizeof(uint32_t) + 55147f9c279SSumit Garg sizeof(uint32_t) + sealinfosize); 55247f9c279SSumit Garg storedsize = sizeof(uint32_t) + sizeof(uint32_t) + sealinfosize + 55347f9c279SSumit Garg sizeof(uint32_t) + encdatasize; 55447f9c279SSumit Garg 55547f9c279SSumit Garg /* check the HMAC in the response */ 55647f9c279SSumit Garg ret = TSS_checkhmac1(tb->data, ordinal, td->nonceodd, sess.secret, 55747f9c279SSumit Garg SHA1_DIGEST_SIZE, storedsize, TPM_DATA_OFFSET, 0, 55847f9c279SSumit Garg 0); 55947f9c279SSumit Garg 56047f9c279SSumit Garg /* copy the returned blob to caller */ 56147f9c279SSumit Garg if (!ret) { 56247f9c279SSumit Garg memcpy(blob, tb->data + TPM_DATA_OFFSET, storedsize); 56347f9c279SSumit Garg *bloblen = storedsize; 56447f9c279SSumit Garg } 56547f9c279SSumit Garg out: 566453431a5SWaiman Long kfree_sensitive(td); 56747f9c279SSumit Garg return ret; 56847f9c279SSumit Garg } 56947f9c279SSumit Garg 57047f9c279SSumit Garg /* 57147f9c279SSumit Garg * use the AUTH2_COMMAND form of unseal, to authorize both key and blob 57247f9c279SSumit Garg */ 57347f9c279SSumit Garg static int tpm_unseal(struct tpm_buf *tb, 57447f9c279SSumit Garg uint32_t keyhandle, const unsigned char *keyauth, 57547f9c279SSumit Garg const unsigned char *blob, int bloblen, 57647f9c279SSumit Garg const unsigned char *blobauth, 57747f9c279SSumit Garg unsigned char *data, unsigned int *datalen) 57847f9c279SSumit Garg { 57947f9c279SSumit Garg unsigned char nonceodd[TPM_NONCE_SIZE]; 58047f9c279SSumit Garg unsigned char enonce1[TPM_NONCE_SIZE]; 58147f9c279SSumit Garg unsigned char enonce2[TPM_NONCE_SIZE]; 58247f9c279SSumit Garg unsigned char authdata1[SHA1_DIGEST_SIZE]; 58347f9c279SSumit Garg unsigned char authdata2[SHA1_DIGEST_SIZE]; 58447f9c279SSumit Garg uint32_t authhandle1 = 0; 58547f9c279SSumit Garg uint32_t authhandle2 = 0; 58647f9c279SSumit Garg unsigned char cont = 0; 58747f9c279SSumit Garg uint32_t ordinal; 58847f9c279SSumit Garg int ret; 58947f9c279SSumit Garg 59047f9c279SSumit Garg /* sessions for unsealing key and data */ 59147f9c279SSumit Garg ret = oiap(tb, &authhandle1, enonce1); 59247f9c279SSumit Garg if (ret < 0) { 5935d0682beSSumit Garg pr_info("oiap failed (%d)\n", ret); 59447f9c279SSumit Garg return ret; 59547f9c279SSumit Garg } 59647f9c279SSumit Garg ret = oiap(tb, &authhandle2, enonce2); 59747f9c279SSumit Garg if (ret < 0) { 5985d0682beSSumit Garg pr_info("oiap failed (%d)\n", ret); 59947f9c279SSumit Garg return ret; 60047f9c279SSumit Garg } 60147f9c279SSumit Garg 60247f9c279SSumit Garg ordinal = htonl(TPM_ORD_UNSEAL); 60347f9c279SSumit Garg ret = tpm_get_random(chip, nonceodd, TPM_NONCE_SIZE); 6045df16caaSJarkko Sakkinen if (ret < 0) 6055df16caaSJarkko Sakkinen return ret; 6065df16caaSJarkko Sakkinen 60747f9c279SSumit Garg if (ret != TPM_NONCE_SIZE) { 6085d0682beSSumit Garg pr_info("tpm_get_random failed (%d)\n", ret); 6095df16caaSJarkko Sakkinen return -EIO; 61047f9c279SSumit Garg } 61147f9c279SSumit Garg ret = TSS_authhmac(authdata1, keyauth, TPM_NONCE_SIZE, 61247f9c279SSumit Garg enonce1, nonceodd, cont, sizeof(uint32_t), 61347f9c279SSumit Garg &ordinal, bloblen, blob, 0, 0); 61447f9c279SSumit Garg if (ret < 0) 61547f9c279SSumit Garg return ret; 61647f9c279SSumit Garg ret = TSS_authhmac(authdata2, blobauth, TPM_NONCE_SIZE, 61747f9c279SSumit Garg enonce2, nonceodd, cont, sizeof(uint32_t), 61847f9c279SSumit Garg &ordinal, bloblen, blob, 0, 0); 61947f9c279SSumit Garg if (ret < 0) 62047f9c279SSumit Garg return ret; 62147f9c279SSumit Garg 62247f9c279SSumit Garg /* build and send TPM request packet */ 62347f9c279SSumit Garg tpm_buf_reset(tb, TPM_TAG_RQU_AUTH2_COMMAND, TPM_ORD_UNSEAL); 62447f9c279SSumit Garg tpm_buf_append_u32(tb, keyhandle); 62547f9c279SSumit Garg tpm_buf_append(tb, blob, bloblen); 62647f9c279SSumit Garg tpm_buf_append_u32(tb, authhandle1); 62747f9c279SSumit Garg tpm_buf_append(tb, nonceodd, TPM_NONCE_SIZE); 62847f9c279SSumit Garg tpm_buf_append_u8(tb, cont); 62947f9c279SSumit Garg tpm_buf_append(tb, authdata1, SHA1_DIGEST_SIZE); 63047f9c279SSumit Garg tpm_buf_append_u32(tb, authhandle2); 63147f9c279SSumit Garg tpm_buf_append(tb, nonceodd, TPM_NONCE_SIZE); 63247f9c279SSumit Garg tpm_buf_append_u8(tb, cont); 63347f9c279SSumit Garg tpm_buf_append(tb, authdata2, SHA1_DIGEST_SIZE); 63447f9c279SSumit Garg 63547f9c279SSumit Garg ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE); 63647f9c279SSumit Garg if (ret < 0) { 6375d0682beSSumit Garg pr_info("authhmac failed (%d)\n", ret); 63847f9c279SSumit Garg return ret; 63947f9c279SSumit Garg } 64047f9c279SSumit Garg 64147f9c279SSumit Garg *datalen = LOAD32(tb->data, TPM_DATA_OFFSET); 64247f9c279SSumit Garg ret = TSS_checkhmac2(tb->data, ordinal, nonceodd, 64347f9c279SSumit Garg keyauth, SHA1_DIGEST_SIZE, 64447f9c279SSumit Garg blobauth, SHA1_DIGEST_SIZE, 64547f9c279SSumit Garg sizeof(uint32_t), TPM_DATA_OFFSET, 64647f9c279SSumit Garg *datalen, TPM_DATA_OFFSET + sizeof(uint32_t), 0, 64747f9c279SSumit Garg 0); 64847f9c279SSumit Garg if (ret < 0) { 6495d0682beSSumit Garg pr_info("TSS_checkhmac2 failed (%d)\n", ret); 65047f9c279SSumit Garg return ret; 65147f9c279SSumit Garg } 65247f9c279SSumit Garg memcpy(data, tb->data + TPM_DATA_OFFSET + sizeof(uint32_t), *datalen); 65347f9c279SSumit Garg return 0; 65447f9c279SSumit Garg } 65547f9c279SSumit Garg 65647f9c279SSumit Garg /* 65747f9c279SSumit Garg * Have the TPM seal(encrypt) the symmetric key 65847f9c279SSumit Garg */ 65947f9c279SSumit Garg static int key_seal(struct trusted_key_payload *p, 66047f9c279SSumit Garg struct trusted_key_options *o) 66147f9c279SSumit Garg { 66247f9c279SSumit Garg struct tpm_buf tb; 66347f9c279SSumit Garg int ret; 66447f9c279SSumit Garg 66547f9c279SSumit Garg ret = tpm_buf_init(&tb, 0, 0); 66647f9c279SSumit Garg if (ret) 66747f9c279SSumit Garg return ret; 66847f9c279SSumit Garg 66947f9c279SSumit Garg /* include migratable flag at end of sealed key */ 67047f9c279SSumit Garg p->key[p->key_len] = p->migratable; 67147f9c279SSumit Garg 67247f9c279SSumit Garg ret = tpm_seal(&tb, o->keytype, o->keyhandle, o->keyauth, 67347f9c279SSumit Garg p->key, p->key_len + 1, p->blob, &p->blob_len, 67447f9c279SSumit Garg o->blobauth, o->pcrinfo, o->pcrinfo_len); 67547f9c279SSumit Garg if (ret < 0) 6765d0682beSSumit Garg pr_info("srkseal failed (%d)\n", ret); 67747f9c279SSumit Garg 67847f9c279SSumit Garg tpm_buf_destroy(&tb); 67947f9c279SSumit Garg return ret; 68047f9c279SSumit Garg } 68147f9c279SSumit Garg 68247f9c279SSumit Garg /* 68347f9c279SSumit Garg * Have the TPM unseal(decrypt) the symmetric key 68447f9c279SSumit Garg */ 68547f9c279SSumit Garg static int key_unseal(struct trusted_key_payload *p, 68647f9c279SSumit Garg struct trusted_key_options *o) 68747f9c279SSumit Garg { 68847f9c279SSumit Garg struct tpm_buf tb; 68947f9c279SSumit Garg int ret; 69047f9c279SSumit Garg 69147f9c279SSumit Garg ret = tpm_buf_init(&tb, 0, 0); 69247f9c279SSumit Garg if (ret) 69347f9c279SSumit Garg return ret; 69447f9c279SSumit Garg 69547f9c279SSumit Garg ret = tpm_unseal(&tb, o->keyhandle, o->keyauth, p->blob, p->blob_len, 69647f9c279SSumit Garg o->blobauth, p->key, &p->key_len); 69747f9c279SSumit Garg if (ret < 0) 6985d0682beSSumit Garg pr_info("srkunseal failed (%d)\n", ret); 69947f9c279SSumit Garg else 70047f9c279SSumit Garg /* pull migratable flag out of sealed key */ 70147f9c279SSumit Garg p->migratable = p->key[--p->key_len]; 70247f9c279SSumit Garg 70347f9c279SSumit Garg tpm_buf_destroy(&tb); 70447f9c279SSumit Garg return ret; 70547f9c279SSumit Garg } 70647f9c279SSumit Garg 70747f9c279SSumit Garg enum { 70847f9c279SSumit Garg Opt_err, 70947f9c279SSumit Garg Opt_keyhandle, Opt_keyauth, Opt_blobauth, 71047f9c279SSumit Garg Opt_pcrinfo, Opt_pcrlock, Opt_migratable, 71147f9c279SSumit Garg Opt_hash, 71247f9c279SSumit Garg Opt_policydigest, 71347f9c279SSumit Garg Opt_policyhandle, 71447f9c279SSumit Garg }; 71547f9c279SSumit Garg 71647f9c279SSumit Garg static const match_table_t key_tokens = { 71747f9c279SSumit Garg {Opt_keyhandle, "keyhandle=%s"}, 71847f9c279SSumit Garg {Opt_keyauth, "keyauth=%s"}, 71947f9c279SSumit Garg {Opt_blobauth, "blobauth=%s"}, 72047f9c279SSumit Garg {Opt_pcrinfo, "pcrinfo=%s"}, 72147f9c279SSumit Garg {Opt_pcrlock, "pcrlock=%s"}, 72247f9c279SSumit Garg {Opt_migratable, "migratable=%s"}, 72347f9c279SSumit Garg {Opt_hash, "hash=%s"}, 72447f9c279SSumit Garg {Opt_policydigest, "policydigest=%s"}, 72547f9c279SSumit Garg {Opt_policyhandle, "policyhandle=%s"}, 72647f9c279SSumit Garg {Opt_err, NULL} 72747f9c279SSumit Garg }; 72847f9c279SSumit Garg 72947f9c279SSumit Garg /* can have zero or more token= options */ 73047f9c279SSumit Garg static int getoptions(char *c, struct trusted_key_payload *pay, 73147f9c279SSumit Garg struct trusted_key_options *opt) 73247f9c279SSumit Garg { 73347f9c279SSumit Garg substring_t args[MAX_OPT_ARGS]; 73447f9c279SSumit Garg char *p = c; 73547f9c279SSumit Garg int token; 73647f9c279SSumit Garg int res; 73747f9c279SSumit Garg unsigned long handle; 73847f9c279SSumit Garg unsigned long lock; 73947f9c279SSumit Garg unsigned long token_mask = 0; 74047f9c279SSumit Garg unsigned int digest_len; 74147f9c279SSumit Garg int i; 74247f9c279SSumit Garg int tpm2; 74347f9c279SSumit Garg 74447f9c279SSumit Garg tpm2 = tpm_is_tpm2(chip); 74547f9c279SSumit Garg if (tpm2 < 0) 74647f9c279SSumit Garg return tpm2; 74747f9c279SSumit Garg 74847f9c279SSumit Garg opt->hash = tpm2 ? HASH_ALGO_SHA256 : HASH_ALGO_SHA1; 74947f9c279SSumit Garg 750*60dc5f1bSJames Bottomley if (!c) 751*60dc5f1bSJames Bottomley return 0; 752*60dc5f1bSJames Bottomley 75347f9c279SSumit Garg while ((p = strsep(&c, " \t"))) { 75447f9c279SSumit Garg if (*p == '\0' || *p == ' ' || *p == '\t') 75547f9c279SSumit Garg continue; 75647f9c279SSumit Garg token = match_token(p, key_tokens, args); 75747f9c279SSumit Garg if (test_and_set_bit(token, &token_mask)) 75847f9c279SSumit Garg return -EINVAL; 75947f9c279SSumit Garg 76047f9c279SSumit Garg switch (token) { 76147f9c279SSumit Garg case Opt_pcrinfo: 76247f9c279SSumit Garg opt->pcrinfo_len = strlen(args[0].from) / 2; 76347f9c279SSumit Garg if (opt->pcrinfo_len > MAX_PCRINFO_SIZE) 76447f9c279SSumit Garg return -EINVAL; 76547f9c279SSumit Garg res = hex2bin(opt->pcrinfo, args[0].from, 76647f9c279SSumit Garg opt->pcrinfo_len); 76747f9c279SSumit Garg if (res < 0) 76847f9c279SSumit Garg return -EINVAL; 76947f9c279SSumit Garg break; 77047f9c279SSumit Garg case Opt_keyhandle: 77147f9c279SSumit Garg res = kstrtoul(args[0].from, 16, &handle); 77247f9c279SSumit Garg if (res < 0) 77347f9c279SSumit Garg return -EINVAL; 77447f9c279SSumit Garg opt->keytype = SEAL_keytype; 77547f9c279SSumit Garg opt->keyhandle = handle; 77647f9c279SSumit Garg break; 77747f9c279SSumit Garg case Opt_keyauth: 77847f9c279SSumit Garg if (strlen(args[0].from) != 2 * SHA1_DIGEST_SIZE) 77947f9c279SSumit Garg return -EINVAL; 78047f9c279SSumit Garg res = hex2bin(opt->keyauth, args[0].from, 78147f9c279SSumit Garg SHA1_DIGEST_SIZE); 78247f9c279SSumit Garg if (res < 0) 78347f9c279SSumit Garg return -EINVAL; 78447f9c279SSumit Garg break; 78547f9c279SSumit Garg case Opt_blobauth: 786de66514dSJames Bottomley /* 787de66514dSJames Bottomley * TPM 1.2 authorizations are sha1 hashes passed in as 788de66514dSJames Bottomley * hex strings. TPM 2.0 authorizations are simple 789de66514dSJames Bottomley * passwords (although it can take a hash as well) 790de66514dSJames Bottomley */ 791de66514dSJames Bottomley opt->blobauth_len = strlen(args[0].from); 792de66514dSJames Bottomley 793de66514dSJames Bottomley if (opt->blobauth_len == 2 * TPM_DIGEST_SIZE) { 79447f9c279SSumit Garg res = hex2bin(opt->blobauth, args[0].from, 795de66514dSJames Bottomley TPM_DIGEST_SIZE); 79647f9c279SSumit Garg if (res < 0) 79747f9c279SSumit Garg return -EINVAL; 798de66514dSJames Bottomley 799de66514dSJames Bottomley opt->blobauth_len = TPM_DIGEST_SIZE; 80047f9c279SSumit Garg break; 801de66514dSJames Bottomley } 802de66514dSJames Bottomley 803de66514dSJames Bottomley if (tpm2 && opt->blobauth_len <= sizeof(opt->blobauth)) { 804de66514dSJames Bottomley memcpy(opt->blobauth, args[0].from, 805de66514dSJames Bottomley opt->blobauth_len); 806de66514dSJames Bottomley break; 807de66514dSJames Bottomley } 808de66514dSJames Bottomley 809de66514dSJames Bottomley return -EINVAL; 810de66514dSJames Bottomley 811de66514dSJames Bottomley break; 812de66514dSJames Bottomley 81347f9c279SSumit Garg case Opt_migratable: 81447f9c279SSumit Garg if (*args[0].from == '0') 81547f9c279SSumit Garg pay->migratable = 0; 8168da7520cSJarkko Sakkinen else if (*args[0].from != '1') 81747f9c279SSumit Garg return -EINVAL; 81847f9c279SSumit Garg break; 81947f9c279SSumit Garg case Opt_pcrlock: 82047f9c279SSumit Garg res = kstrtoul(args[0].from, 10, &lock); 82147f9c279SSumit Garg if (res < 0) 82247f9c279SSumit Garg return -EINVAL; 82347f9c279SSumit Garg opt->pcrlock = lock; 82447f9c279SSumit Garg break; 82547f9c279SSumit Garg case Opt_hash: 82647f9c279SSumit Garg if (test_bit(Opt_policydigest, &token_mask)) 82747f9c279SSumit Garg return -EINVAL; 82847f9c279SSumit Garg for (i = 0; i < HASH_ALGO__LAST; i++) { 82947f9c279SSumit Garg if (!strcmp(args[0].from, hash_algo_name[i])) { 83047f9c279SSumit Garg opt->hash = i; 83147f9c279SSumit Garg break; 83247f9c279SSumit Garg } 83347f9c279SSumit Garg } 83447f9c279SSumit Garg if (i == HASH_ALGO__LAST) 83547f9c279SSumit Garg return -EINVAL; 83647f9c279SSumit Garg if (!tpm2 && i != HASH_ALGO_SHA1) { 8375d0682beSSumit Garg pr_info("TPM 1.x only supports SHA-1.\n"); 83847f9c279SSumit Garg return -EINVAL; 83947f9c279SSumit Garg } 84047f9c279SSumit Garg break; 84147f9c279SSumit Garg case Opt_policydigest: 84247f9c279SSumit Garg digest_len = hash_digest_size[opt->hash]; 84347f9c279SSumit Garg if (!tpm2 || strlen(args[0].from) != (2 * digest_len)) 84447f9c279SSumit Garg return -EINVAL; 84547f9c279SSumit Garg res = hex2bin(opt->policydigest, args[0].from, 84647f9c279SSumit Garg digest_len); 84747f9c279SSumit Garg if (res < 0) 84847f9c279SSumit Garg return -EINVAL; 84947f9c279SSumit Garg opt->policydigest_len = digest_len; 85047f9c279SSumit Garg break; 85147f9c279SSumit Garg case Opt_policyhandle: 85247f9c279SSumit Garg if (!tpm2) 85347f9c279SSumit Garg return -EINVAL; 85447f9c279SSumit Garg res = kstrtoul(args[0].from, 16, &handle); 85547f9c279SSumit Garg if (res < 0) 85647f9c279SSumit Garg return -EINVAL; 85747f9c279SSumit Garg opt->policyhandle = handle; 85847f9c279SSumit Garg break; 85947f9c279SSumit Garg default: 86047f9c279SSumit Garg return -EINVAL; 86147f9c279SSumit Garg } 86247f9c279SSumit Garg } 86347f9c279SSumit Garg return 0; 86447f9c279SSumit Garg } 86547f9c279SSumit Garg 86647f9c279SSumit Garg static struct trusted_key_options *trusted_options_alloc(void) 86747f9c279SSumit Garg { 86847f9c279SSumit Garg struct trusted_key_options *options; 86947f9c279SSumit Garg int tpm2; 87047f9c279SSumit Garg 87147f9c279SSumit Garg tpm2 = tpm_is_tpm2(chip); 87247f9c279SSumit Garg if (tpm2 < 0) 87347f9c279SSumit Garg return NULL; 87447f9c279SSumit Garg 87547f9c279SSumit Garg options = kzalloc(sizeof *options, GFP_KERNEL); 87647f9c279SSumit Garg if (options) { 87747f9c279SSumit Garg /* set any non-zero defaults */ 87847f9c279SSumit Garg options->keytype = SRK_keytype; 87947f9c279SSumit Garg 88047f9c279SSumit Garg if (!tpm2) 88147f9c279SSumit Garg options->keyhandle = SRKHANDLE; 88247f9c279SSumit Garg } 88347f9c279SSumit Garg return options; 88447f9c279SSumit Garg } 88547f9c279SSumit Garg 8865d0682beSSumit Garg static int trusted_tpm_seal(struct trusted_key_payload *p, char *datablob) 88747f9c279SSumit Garg { 88847f9c279SSumit Garg struct trusted_key_options *options = NULL; 88947f9c279SSumit Garg int ret = 0; 89047f9c279SSumit Garg int tpm2; 89147f9c279SSumit Garg 89247f9c279SSumit Garg tpm2 = tpm_is_tpm2(chip); 89347f9c279SSumit Garg if (tpm2 < 0) 89447f9c279SSumit Garg return tpm2; 89547f9c279SSumit Garg 89647f9c279SSumit Garg options = trusted_options_alloc(); 8975d0682beSSumit Garg if (!options) 8985d0682beSSumit Garg return -ENOMEM; 89947f9c279SSumit Garg 9005d0682beSSumit Garg ret = getoptions(datablob, p, options); 9015d0682beSSumit Garg if (ret < 0) 90247f9c279SSumit Garg goto out; 9035d0682beSSumit Garg dump_options(options); 90447f9c279SSumit Garg 905f2219745SJames Bottomley if (!options->keyhandle && !tpm2) { 90647f9c279SSumit Garg ret = -EINVAL; 90747f9c279SSumit Garg goto out; 90847f9c279SSumit Garg } 90947f9c279SSumit Garg 91047f9c279SSumit Garg if (tpm2) 9115d0682beSSumit Garg ret = tpm2_seal_trusted(chip, p, options); 91247f9c279SSumit Garg else 9135d0682beSSumit Garg ret = key_seal(p, options); 9145d0682beSSumit Garg if (ret < 0) { 9155d0682beSSumit Garg pr_info("key_seal failed (%d)\n", ret); 91647f9c279SSumit Garg goto out; 91747f9c279SSumit Garg } 9185d0682beSSumit Garg 9195d0682beSSumit Garg if (options->pcrlock) { 92047f9c279SSumit Garg ret = pcrlock(options->pcrlock); 9215d0682beSSumit Garg if (ret < 0) { 9225d0682beSSumit Garg pr_info("pcrlock failed (%d)\n", ret); 9235d0682beSSumit Garg goto out; 9245d0682beSSumit Garg } 9255d0682beSSumit Garg } 92647f9c279SSumit Garg out: 927453431a5SWaiman Long kfree_sensitive(options); 92847f9c279SSumit Garg return ret; 92947f9c279SSumit Garg } 93047f9c279SSumit Garg 9315d0682beSSumit Garg static int trusted_tpm_unseal(struct trusted_key_payload *p, char *datablob) 93247f9c279SSumit Garg { 9335d0682beSSumit Garg struct trusted_key_options *options = NULL; 93447f9c279SSumit Garg int ret = 0; 9355d0682beSSumit Garg int tpm2; 93647f9c279SSumit Garg 9375d0682beSSumit Garg tpm2 = tpm_is_tpm2(chip); 9385d0682beSSumit Garg if (tpm2 < 0) 9395d0682beSSumit Garg return tpm2; 94047f9c279SSumit Garg 9415d0682beSSumit Garg options = trusted_options_alloc(); 9425d0682beSSumit Garg if (!options) 94347f9c279SSumit Garg return -ENOMEM; 94447f9c279SSumit Garg 9455d0682beSSumit Garg ret = getoptions(datablob, p, options); 9465d0682beSSumit Garg if (ret < 0) 9475d0682beSSumit Garg goto out; 9485d0682beSSumit Garg dump_options(options); 9495d0682beSSumit Garg 950*60dc5f1bSJames Bottomley if (!options->keyhandle && !tpm2) { 95147f9c279SSumit Garg ret = -EINVAL; 95247f9c279SSumit Garg goto out; 95347f9c279SSumit Garg } 95447f9c279SSumit Garg 9555d0682beSSumit Garg if (tpm2) 9565d0682beSSumit Garg ret = tpm2_unseal_trusted(chip, p, options); 9575d0682beSSumit Garg else 9585d0682beSSumit Garg ret = key_unseal(p, options); 9595d0682beSSumit Garg if (ret < 0) 9605d0682beSSumit Garg pr_info("key_unseal failed (%d)\n", ret); 96147f9c279SSumit Garg 9625d0682beSSumit Garg if (options->pcrlock) { 9635d0682beSSumit Garg ret = pcrlock(options->pcrlock); 96447f9c279SSumit Garg if (ret < 0) { 9655d0682beSSumit Garg pr_info("pcrlock failed (%d)\n", ret); 96647f9c279SSumit Garg goto out; 96747f9c279SSumit Garg } 96847f9c279SSumit Garg } 96947f9c279SSumit Garg out: 9705d0682beSSumit Garg kfree_sensitive(options); 97147f9c279SSumit Garg return ret; 97247f9c279SSumit Garg } 97347f9c279SSumit Garg 9745d0682beSSumit Garg static int trusted_tpm_get_random(unsigned char *key, size_t key_len) 97547f9c279SSumit Garg { 9765d0682beSSumit Garg return tpm_get_random(chip, key, key_len); 97747f9c279SSumit Garg } 97847f9c279SSumit Garg 97947f9c279SSumit Garg static void trusted_shash_release(void) 98047f9c279SSumit Garg { 98147f9c279SSumit Garg if (hashalg) 98247f9c279SSumit Garg crypto_free_shash(hashalg); 98347f9c279SSumit Garg if (hmacalg) 98447f9c279SSumit Garg crypto_free_shash(hmacalg); 98547f9c279SSumit Garg } 98647f9c279SSumit Garg 98747f9c279SSumit Garg static int __init trusted_shash_alloc(void) 98847f9c279SSumit Garg { 98947f9c279SSumit Garg int ret; 99047f9c279SSumit Garg 99147f9c279SSumit Garg hmacalg = crypto_alloc_shash(hmac_alg, 0, 0); 99247f9c279SSumit Garg if (IS_ERR(hmacalg)) { 9935d0682beSSumit Garg pr_info("could not allocate crypto %s\n", 99447f9c279SSumit Garg hmac_alg); 99547f9c279SSumit Garg return PTR_ERR(hmacalg); 99647f9c279SSumit Garg } 99747f9c279SSumit Garg 99847f9c279SSumit Garg hashalg = crypto_alloc_shash(hash_alg, 0, 0); 99947f9c279SSumit Garg if (IS_ERR(hashalg)) { 10005d0682beSSumit Garg pr_info("could not allocate crypto %s\n", 100147f9c279SSumit Garg hash_alg); 100247f9c279SSumit Garg ret = PTR_ERR(hashalg); 100347f9c279SSumit Garg goto hashalg_fail; 100447f9c279SSumit Garg } 100547f9c279SSumit Garg 100647f9c279SSumit Garg return 0; 100747f9c279SSumit Garg 100847f9c279SSumit Garg hashalg_fail: 100947f9c279SSumit Garg crypto_free_shash(hmacalg); 101047f9c279SSumit Garg return ret; 101147f9c279SSumit Garg } 101247f9c279SSumit Garg 101347f9c279SSumit Garg static int __init init_digests(void) 101447f9c279SSumit Garg { 101547f9c279SSumit Garg int i; 101647f9c279SSumit Garg 101747f9c279SSumit Garg digests = kcalloc(chip->nr_allocated_banks, sizeof(*digests), 101847f9c279SSumit Garg GFP_KERNEL); 101947f9c279SSumit Garg if (!digests) 102047f9c279SSumit Garg return -ENOMEM; 102147f9c279SSumit Garg 102247f9c279SSumit Garg for (i = 0; i < chip->nr_allocated_banks; i++) 102347f9c279SSumit Garg digests[i].alg_id = chip->allocated_banks[i].alg_id; 102447f9c279SSumit Garg 102547f9c279SSumit Garg return 0; 102647f9c279SSumit Garg } 102747f9c279SSumit Garg 10285d0682beSSumit Garg static int __init trusted_tpm_init(void) 102947f9c279SSumit Garg { 103047f9c279SSumit Garg int ret; 103147f9c279SSumit Garg 103247f9c279SSumit Garg chip = tpm_default_chip(); 103347f9c279SSumit Garg if (!chip) 10345d0682beSSumit Garg return -ENODEV; 103547f9c279SSumit Garg 103647f9c279SSumit Garg ret = init_digests(); 103747f9c279SSumit Garg if (ret < 0) 103847f9c279SSumit Garg goto err_put; 103947f9c279SSumit Garg ret = trusted_shash_alloc(); 104047f9c279SSumit Garg if (ret < 0) 104147f9c279SSumit Garg goto err_free; 104247f9c279SSumit Garg ret = register_key_type(&key_type_trusted); 104347f9c279SSumit Garg if (ret < 0) 104447f9c279SSumit Garg goto err_release; 104547f9c279SSumit Garg return 0; 104647f9c279SSumit Garg err_release: 104747f9c279SSumit Garg trusted_shash_release(); 104847f9c279SSumit Garg err_free: 104947f9c279SSumit Garg kfree(digests); 105047f9c279SSumit Garg err_put: 105147f9c279SSumit Garg put_device(&chip->dev); 105247f9c279SSumit Garg return ret; 105347f9c279SSumit Garg } 105447f9c279SSumit Garg 10555d0682beSSumit Garg static void trusted_tpm_exit(void) 105647f9c279SSumit Garg { 105747f9c279SSumit Garg if (chip) { 105847f9c279SSumit Garg put_device(&chip->dev); 105947f9c279SSumit Garg kfree(digests); 106047f9c279SSumit Garg trusted_shash_release(); 106147f9c279SSumit Garg unregister_key_type(&key_type_trusted); 106247f9c279SSumit Garg } 106347f9c279SSumit Garg } 106447f9c279SSumit Garg 10655d0682beSSumit Garg struct trusted_key_ops trusted_key_tpm_ops = { 10665d0682beSSumit Garg .migratable = 1, /* migratable by default */ 10675d0682beSSumit Garg .init = trusted_tpm_init, 10685d0682beSSumit Garg .seal = trusted_tpm_seal, 10695d0682beSSumit Garg .unseal = trusted_tpm_unseal, 10705d0682beSSumit Garg .get_random = trusted_tpm_get_random, 10715d0682beSSumit Garg .exit = trusted_tpm_exit, 10725d0682beSSumit Garg }; 1073