Path: blob/master/security/keys/trusted-keys/trusted_tpm1.c
29520 views
// SPDX-License-Identifier: GPL-2.0-only1/*2* Copyright (C) 2010 IBM Corporation3* Copyright (c) 2019-2021, Linaro Limited4*5* See Documentation/security/keys/trusted-encrypted.rst6*/78#include <crypto/hash_info.h>9#include <crypto/sha1.h>10#include <crypto/utils.h>11#include <linux/init.h>12#include <linux/slab.h>13#include <linux/parser.h>14#include <linux/string.h>15#include <linux/err.h>16#include <keys/trusted-type.h>17#include <linux/key-type.h>18#include <linux/tpm.h>19#include <linux/tpm_command.h>2021#include <keys/trusted_tpm.h>2223static struct tpm_chip *chip;24static struct tpm_digest *digests;2526/* implementation specific TPM constants */27#define TPM_SIZE_OFFSET 228#define TPM_RETURN_OFFSET 629#define TPM_DATA_OFFSET 103031#define LOAD32(buffer, offset) (ntohl(*(uint32_t *)&buffer[offset]))32#define LOAD32N(buffer, offset) (*(uint32_t *)&buffer[offset])33#define LOAD16(buffer, offset) (ntohs(*(uint16_t *)&buffer[offset]))3435struct osapsess {36uint32_t handle;37unsigned char secret[SHA1_DIGEST_SIZE];38unsigned char enonce[TPM_NONCE_SIZE];39};4041/* discrete values, but have to store in uint16_t for TPM use */42enum {43SEAL_keytype = 1,44SRK_keytype = 445};4647#define TPM_DEBUG 04849#if TPM_DEBUG50static inline void dump_options(struct trusted_key_options *o)51{52pr_info("sealing key type %d\n", o->keytype);53pr_info("sealing key handle %0X\n", o->keyhandle);54pr_info("pcrlock %d\n", o->pcrlock);55pr_info("pcrinfo %d\n", o->pcrinfo_len);56print_hex_dump(KERN_INFO, "pcrinfo ", DUMP_PREFIX_NONE,5716, 1, o->pcrinfo, o->pcrinfo_len, 0);58}5960static inline void dump_sess(struct osapsess *s)61{62print_hex_dump(KERN_INFO, "trusted-key: handle ", DUMP_PREFIX_NONE,6316, 1, &s->handle, 4, 0);64pr_info("secret:\n");65print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE,6616, 1, &s->secret, SHA1_DIGEST_SIZE, 0);67pr_info("trusted-key: enonce:\n");68print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE,6916, 1, &s->enonce, SHA1_DIGEST_SIZE, 0);70}7172static inline void dump_tpm_buf(unsigned char *buf)73{74int len;7576pr_info("\ntpm buffer\n");77len = LOAD32(buf, TPM_SIZE_OFFSET);78print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, buf, len, 0);79}80#else81static inline void dump_options(struct trusted_key_options *o)82{83}8485static inline void dump_sess(struct osapsess *s)86{87}8889static inline void dump_tpm_buf(unsigned char *buf)90{91}92#endif9394static int TSS_rawhmac(unsigned char *digest, const unsigned char *key,95unsigned int keylen, ...)96{97struct hmac_sha1_ctx hmac_ctx;98va_list argp;99unsigned int dlen;100unsigned char *data;101int ret = 0;102103hmac_sha1_init_usingrawkey(&hmac_ctx, key, keylen);104105va_start(argp, keylen);106for (;;) {107dlen = va_arg(argp, unsigned int);108if (dlen == 0)109break;110data = va_arg(argp, unsigned char *);111if (data == NULL) {112ret = -EINVAL;113break;114}115hmac_sha1_update(&hmac_ctx, data, dlen);116}117va_end(argp);118if (!ret)119hmac_sha1_final(&hmac_ctx, digest);120return ret;121}122123/*124* calculate authorization info fields to send to TPM125*/126static int TSS_authhmac(unsigned char *digest, const unsigned char *key,127unsigned int keylen, unsigned char *h1,128unsigned char *h2, unsigned int h3, ...)129{130unsigned char paramdigest[SHA1_DIGEST_SIZE];131struct sha1_ctx sha_ctx;132unsigned int dlen;133unsigned char *data;134unsigned char c;135int ret = 0;136va_list argp;137138if (!chip)139return -ENODEV;140141c = !!h3;142sha1_init(&sha_ctx);143va_start(argp, h3);144for (;;) {145dlen = va_arg(argp, unsigned int);146if (dlen == 0)147break;148data = va_arg(argp, unsigned char *);149if (!data) {150ret = -EINVAL;151break;152}153sha1_update(&sha_ctx, data, dlen);154}155va_end(argp);156if (!ret)157sha1_final(&sha_ctx, paramdigest);158if (!ret)159ret = TSS_rawhmac(digest, key, keylen, SHA1_DIGEST_SIZE,160paramdigest, TPM_NONCE_SIZE, h1,161TPM_NONCE_SIZE, h2, 1, &c, 0, 0);162return ret;163}164165/*166* verify the AUTH1_COMMAND (Seal) result from TPM167*/168static int TSS_checkhmac1(unsigned char *buffer,169const uint32_t command,170const unsigned char *ononce,171const unsigned char *key,172unsigned int keylen, ...)173{174uint32_t bufsize;175uint16_t tag;176uint32_t ordinal;177uint32_t result;178unsigned char *enonce;179unsigned char *continueflag;180unsigned char *authdata;181unsigned char testhmac[SHA1_DIGEST_SIZE];182unsigned char paramdigest[SHA1_DIGEST_SIZE];183struct sha1_ctx sha_ctx;184unsigned int dlen;185unsigned int dpos;186va_list argp;187int ret;188189if (!chip)190return -ENODEV;191192bufsize = LOAD32(buffer, TPM_SIZE_OFFSET);193tag = LOAD16(buffer, 0);194ordinal = command;195result = LOAD32N(buffer, TPM_RETURN_OFFSET);196if (tag == TPM_TAG_RSP_COMMAND)197return 0;198if (tag != TPM_TAG_RSP_AUTH1_COMMAND)199return -EINVAL;200authdata = buffer + bufsize - SHA1_DIGEST_SIZE;201continueflag = authdata - 1;202enonce = continueflag - TPM_NONCE_SIZE;203204sha1_init(&sha_ctx);205sha1_update(&sha_ctx, (const u8 *)&result, sizeof(result));206sha1_update(&sha_ctx, (const u8 *)&ordinal, sizeof(ordinal));207va_start(argp, keylen);208for (;;) {209dlen = va_arg(argp, unsigned int);210if (dlen == 0)211break;212dpos = va_arg(argp, unsigned int);213sha1_update(&sha_ctx, buffer + dpos, dlen);214}215va_end(argp);216sha1_final(&sha_ctx, paramdigest);217218ret = TSS_rawhmac(testhmac, key, keylen, SHA1_DIGEST_SIZE, paramdigest,219TPM_NONCE_SIZE, enonce, TPM_NONCE_SIZE, ononce,2201, continueflag, 0, 0);221if (ret < 0)222return ret;223224if (crypto_memneq(testhmac, authdata, SHA1_DIGEST_SIZE))225return -EINVAL;226return 0;227}228229/*230* verify the AUTH2_COMMAND (unseal) result from TPM231*/232static int TSS_checkhmac2(unsigned char *buffer,233const uint32_t command,234const unsigned char *ononce,235const unsigned char *key1,236unsigned int keylen1,237const unsigned char *key2,238unsigned int keylen2, ...)239{240uint32_t bufsize;241uint16_t tag;242uint32_t ordinal;243uint32_t result;244unsigned char *enonce1;245unsigned char *continueflag1;246unsigned char *authdata1;247unsigned char *enonce2;248unsigned char *continueflag2;249unsigned char *authdata2;250unsigned char testhmac1[SHA1_DIGEST_SIZE];251unsigned char testhmac2[SHA1_DIGEST_SIZE];252unsigned char paramdigest[SHA1_DIGEST_SIZE];253struct sha1_ctx sha_ctx;254unsigned int dlen;255unsigned int dpos;256va_list argp;257int ret;258259bufsize = LOAD32(buffer, TPM_SIZE_OFFSET);260tag = LOAD16(buffer, 0);261ordinal = command;262result = LOAD32N(buffer, TPM_RETURN_OFFSET);263264if (tag == TPM_TAG_RSP_COMMAND)265return 0;266if (tag != TPM_TAG_RSP_AUTH2_COMMAND)267return -EINVAL;268authdata1 = buffer + bufsize - (SHA1_DIGEST_SIZE + 1269+ SHA1_DIGEST_SIZE + SHA1_DIGEST_SIZE);270authdata2 = buffer + bufsize - (SHA1_DIGEST_SIZE);271continueflag1 = authdata1 - 1;272continueflag2 = authdata2 - 1;273enonce1 = continueflag1 - TPM_NONCE_SIZE;274enonce2 = continueflag2 - TPM_NONCE_SIZE;275276sha1_init(&sha_ctx);277sha1_update(&sha_ctx, (const u8 *)&result, sizeof(result));278sha1_update(&sha_ctx, (const u8 *)&ordinal, sizeof(ordinal));279280va_start(argp, keylen2);281for (;;) {282dlen = va_arg(argp, unsigned int);283if (dlen == 0)284break;285dpos = va_arg(argp, unsigned int);286sha1_update(&sha_ctx, buffer + dpos, dlen);287}288va_end(argp);289sha1_final(&sha_ctx, paramdigest);290291ret = TSS_rawhmac(testhmac1, key1, keylen1, SHA1_DIGEST_SIZE,292paramdigest, TPM_NONCE_SIZE, enonce1,293TPM_NONCE_SIZE, ononce, 1, continueflag1, 0, 0);294if (ret < 0)295return ret;296if (crypto_memneq(testhmac1, authdata1, SHA1_DIGEST_SIZE))297return -EINVAL;298ret = TSS_rawhmac(testhmac2, key2, keylen2, SHA1_DIGEST_SIZE,299paramdigest, TPM_NONCE_SIZE, enonce2,300TPM_NONCE_SIZE, ononce, 1, continueflag2, 0, 0);301if (ret < 0)302return ret;303if (crypto_memneq(testhmac2, authdata2, SHA1_DIGEST_SIZE))304return -EINVAL;305return 0;306}307308/*309* For key specific tpm requests, we will generate and send our310* own TPM command packets using the drivers send function.311*/312static int trusted_tpm_send(unsigned char *cmd, size_t buflen)313{314struct tpm_buf buf;315int rc;316317if (!chip)318return -ENODEV;319320rc = tpm_try_get_ops(chip);321if (rc)322return rc;323324buf.flags = 0;325buf.length = buflen;326buf.data = cmd;327dump_tpm_buf(cmd);328rc = tpm_transmit_cmd(chip, &buf, 4, "sending data");329dump_tpm_buf(cmd);330331if (rc > 0)332/* TPM error */333rc = -EPERM;334335tpm_put_ops(chip);336return rc;337}338339/*340* Lock a trusted key, by extending a selected PCR.341*342* Prevents a trusted key that is sealed to PCRs from being accessed.343* This uses the tpm driver's extend function.344*/345static int pcrlock(const int pcrnum)346{347if (!capable(CAP_SYS_ADMIN))348return -EPERM;349350return tpm_pcr_extend(chip, pcrnum, digests) ? -EINVAL : 0;351}352353/*354* Create an object specific authorisation protocol (OSAP) session355*/356static int osap(struct tpm_buf *tb, struct osapsess *s,357const unsigned char *key, uint16_t type, uint32_t handle)358{359unsigned char enonce[TPM_NONCE_SIZE];360unsigned char ononce[TPM_NONCE_SIZE];361int ret;362363ret = tpm_get_random(chip, ononce, TPM_NONCE_SIZE);364if (ret < 0)365return ret;366367if (ret != TPM_NONCE_SIZE)368return -EIO;369370tpm_buf_reset(tb, TPM_TAG_RQU_COMMAND, TPM_ORD_OSAP);371tpm_buf_append_u16(tb, type);372tpm_buf_append_u32(tb, handle);373tpm_buf_append(tb, ononce, TPM_NONCE_SIZE);374375ret = trusted_tpm_send(tb->data, tb->length);376if (ret < 0)377return ret;378379s->handle = LOAD32(tb->data, TPM_DATA_OFFSET);380memcpy(s->enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)]),381TPM_NONCE_SIZE);382memcpy(enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t) +383TPM_NONCE_SIZE]), TPM_NONCE_SIZE);384return TSS_rawhmac(s->secret, key, SHA1_DIGEST_SIZE, TPM_NONCE_SIZE,385enonce, TPM_NONCE_SIZE, ononce, 0, 0);386}387388/*389* Create an object independent authorisation protocol (oiap) session390*/391static int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce)392{393int ret;394395if (!chip)396return -ENODEV;397398tpm_buf_reset(tb, TPM_TAG_RQU_COMMAND, TPM_ORD_OIAP);399ret = trusted_tpm_send(tb->data, tb->length);400if (ret < 0)401return ret;402403*handle = LOAD32(tb->data, TPM_DATA_OFFSET);404memcpy(nonce, &tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)],405TPM_NONCE_SIZE);406return 0;407}408409struct tpm_digests {410unsigned char encauth[SHA1_DIGEST_SIZE];411unsigned char pubauth[SHA1_DIGEST_SIZE];412unsigned char xorwork[SHA1_DIGEST_SIZE * 2];413unsigned char xorhash[SHA1_DIGEST_SIZE];414unsigned char nonceodd[TPM_NONCE_SIZE];415};416417/*418* Have the TPM seal(encrypt) the trusted key, possibly based on419* Platform Configuration Registers (PCRs). AUTH1 for sealing key.420*/421static int tpm_seal(struct tpm_buf *tb, uint16_t keytype,422uint32_t keyhandle, const unsigned char *keyauth,423const unsigned char *data, uint32_t datalen,424unsigned char *blob, uint32_t *bloblen,425const unsigned char *blobauth,426const unsigned char *pcrinfo, uint32_t pcrinfosize)427{428struct osapsess sess;429struct tpm_digests *td;430unsigned char cont;431uint32_t ordinal;432uint32_t pcrsize;433uint32_t datsize;434int sealinfosize;435int encdatasize;436int storedsize;437int ret;438int i;439440/* alloc some work space for all the hashes */441td = kmalloc(sizeof *td, GFP_KERNEL);442if (!td)443return -ENOMEM;444445/* get session for sealing key */446ret = osap(tb, &sess, keyauth, keytype, keyhandle);447if (ret < 0)448goto out;449dump_sess(&sess);450451/* calculate encrypted authorization value */452memcpy(td->xorwork, sess.secret, SHA1_DIGEST_SIZE);453memcpy(td->xorwork + SHA1_DIGEST_SIZE, sess.enonce, SHA1_DIGEST_SIZE);454sha1(td->xorwork, SHA1_DIGEST_SIZE * 2, td->xorhash);455456ret = tpm_get_random(chip, td->nonceodd, TPM_NONCE_SIZE);457if (ret < 0)458goto out;459460if (ret != TPM_NONCE_SIZE) {461ret = -EIO;462goto out;463}464465ordinal = htonl(TPM_ORD_SEAL);466datsize = htonl(datalen);467pcrsize = htonl(pcrinfosize);468cont = 0;469470/* encrypt data authorization key */471for (i = 0; i < SHA1_DIGEST_SIZE; ++i)472td->encauth[i] = td->xorhash[i] ^ blobauth[i];473474/* calculate authorization HMAC value */475if (pcrinfosize == 0) {476/* no pcr info specified */477ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,478sess.enonce, td->nonceodd, cont,479sizeof(uint32_t), &ordinal, SHA1_DIGEST_SIZE,480td->encauth, sizeof(uint32_t), &pcrsize,481sizeof(uint32_t), &datsize, datalen, data, 0,4820);483} else {484/* pcr info specified */485ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,486sess.enonce, td->nonceodd, cont,487sizeof(uint32_t), &ordinal, SHA1_DIGEST_SIZE,488td->encauth, sizeof(uint32_t), &pcrsize,489pcrinfosize, pcrinfo, sizeof(uint32_t),490&datsize, datalen, data, 0, 0);491}492if (ret < 0)493goto out;494495/* build and send the TPM request packet */496tpm_buf_reset(tb, TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_SEAL);497tpm_buf_append_u32(tb, keyhandle);498tpm_buf_append(tb, td->encauth, SHA1_DIGEST_SIZE);499tpm_buf_append_u32(tb, pcrinfosize);500tpm_buf_append(tb, pcrinfo, pcrinfosize);501tpm_buf_append_u32(tb, datalen);502tpm_buf_append(tb, data, datalen);503tpm_buf_append_u32(tb, sess.handle);504tpm_buf_append(tb, td->nonceodd, TPM_NONCE_SIZE);505tpm_buf_append_u8(tb, cont);506tpm_buf_append(tb, td->pubauth, SHA1_DIGEST_SIZE);507508ret = trusted_tpm_send(tb->data, tb->length);509if (ret < 0)510goto out;511512/* calculate the size of the returned Blob */513sealinfosize = LOAD32(tb->data, TPM_DATA_OFFSET + sizeof(uint32_t));514encdatasize = LOAD32(tb->data, TPM_DATA_OFFSET + sizeof(uint32_t) +515sizeof(uint32_t) + sealinfosize);516storedsize = sizeof(uint32_t) + sizeof(uint32_t) + sealinfosize +517sizeof(uint32_t) + encdatasize;518519/* check the HMAC in the response */520ret = TSS_checkhmac1(tb->data, ordinal, td->nonceodd, sess.secret,521SHA1_DIGEST_SIZE, storedsize, TPM_DATA_OFFSET, 0,5220);523524/* copy the returned blob to caller */525if (!ret) {526memcpy(blob, tb->data + TPM_DATA_OFFSET, storedsize);527*bloblen = storedsize;528}529out:530kfree_sensitive(td);531return ret;532}533534/*535* use the AUTH2_COMMAND form of unseal, to authorize both key and blob536*/537static int tpm_unseal(struct tpm_buf *tb,538uint32_t keyhandle, const unsigned char *keyauth,539const unsigned char *blob, int bloblen,540const unsigned char *blobauth,541unsigned char *data, unsigned int *datalen)542{543unsigned char nonceodd[TPM_NONCE_SIZE];544unsigned char enonce1[TPM_NONCE_SIZE];545unsigned char enonce2[TPM_NONCE_SIZE];546unsigned char authdata1[SHA1_DIGEST_SIZE];547unsigned char authdata2[SHA1_DIGEST_SIZE];548uint32_t authhandle1 = 0;549uint32_t authhandle2 = 0;550unsigned char cont = 0;551uint32_t ordinal;552int ret;553554/* sessions for unsealing key and data */555ret = oiap(tb, &authhandle1, enonce1);556if (ret < 0) {557pr_info("oiap failed (%d)\n", ret);558return ret;559}560ret = oiap(tb, &authhandle2, enonce2);561if (ret < 0) {562pr_info("oiap failed (%d)\n", ret);563return ret;564}565566ordinal = htonl(TPM_ORD_UNSEAL);567ret = tpm_get_random(chip, nonceodd, TPM_NONCE_SIZE);568if (ret < 0)569return ret;570571if (ret != TPM_NONCE_SIZE) {572pr_info("tpm_get_random failed (%d)\n", ret);573return -EIO;574}575ret = TSS_authhmac(authdata1, keyauth, TPM_NONCE_SIZE,576enonce1, nonceodd, cont, sizeof(uint32_t),577&ordinal, bloblen, blob, 0, 0);578if (ret < 0)579return ret;580ret = TSS_authhmac(authdata2, blobauth, TPM_NONCE_SIZE,581enonce2, nonceodd, cont, sizeof(uint32_t),582&ordinal, bloblen, blob, 0, 0);583if (ret < 0)584return ret;585586/* build and send TPM request packet */587tpm_buf_reset(tb, TPM_TAG_RQU_AUTH2_COMMAND, TPM_ORD_UNSEAL);588tpm_buf_append_u32(tb, keyhandle);589tpm_buf_append(tb, blob, bloblen);590tpm_buf_append_u32(tb, authhandle1);591tpm_buf_append(tb, nonceodd, TPM_NONCE_SIZE);592tpm_buf_append_u8(tb, cont);593tpm_buf_append(tb, authdata1, SHA1_DIGEST_SIZE);594tpm_buf_append_u32(tb, authhandle2);595tpm_buf_append(tb, nonceodd, TPM_NONCE_SIZE);596tpm_buf_append_u8(tb, cont);597tpm_buf_append(tb, authdata2, SHA1_DIGEST_SIZE);598599ret = trusted_tpm_send(tb->data, tb->length);600if (ret < 0) {601pr_info("authhmac failed (%d)\n", ret);602return ret;603}604605*datalen = LOAD32(tb->data, TPM_DATA_OFFSET);606ret = TSS_checkhmac2(tb->data, ordinal, nonceodd,607keyauth, SHA1_DIGEST_SIZE,608blobauth, SHA1_DIGEST_SIZE,609sizeof(uint32_t), TPM_DATA_OFFSET,610*datalen, TPM_DATA_OFFSET + sizeof(uint32_t), 0,6110);612if (ret < 0) {613pr_info("TSS_checkhmac2 failed (%d)\n", ret);614return ret;615}616memcpy(data, tb->data + TPM_DATA_OFFSET + sizeof(uint32_t), *datalen);617return 0;618}619620/*621* Have the TPM seal(encrypt) the symmetric key622*/623static int key_seal(struct trusted_key_payload *p,624struct trusted_key_options *o)625{626struct tpm_buf tb;627int ret;628629ret = tpm_buf_init(&tb, 0, 0);630if (ret)631return ret;632633/* include migratable flag at end of sealed key */634p->key[p->key_len] = p->migratable;635636ret = tpm_seal(&tb, o->keytype, o->keyhandle, o->keyauth,637p->key, p->key_len + 1, p->blob, &p->blob_len,638o->blobauth, o->pcrinfo, o->pcrinfo_len);639if (ret < 0)640pr_info("srkseal failed (%d)\n", ret);641642tpm_buf_destroy(&tb);643return ret;644}645646/*647* Have the TPM unseal(decrypt) the symmetric key648*/649static int key_unseal(struct trusted_key_payload *p,650struct trusted_key_options *o)651{652struct tpm_buf tb;653int ret;654655ret = tpm_buf_init(&tb, 0, 0);656if (ret)657return ret;658659ret = tpm_unseal(&tb, o->keyhandle, o->keyauth, p->blob, p->blob_len,660o->blobauth, p->key, &p->key_len);661if (ret < 0)662pr_info("srkunseal failed (%d)\n", ret);663else664/* pull migratable flag out of sealed key */665p->migratable = p->key[--p->key_len];666667tpm_buf_destroy(&tb);668return ret;669}670671enum {672Opt_err,673Opt_keyhandle, Opt_keyauth, Opt_blobauth,674Opt_pcrinfo, Opt_pcrlock, Opt_migratable,675Opt_hash,676Opt_policydigest,677Opt_policyhandle,678};679680static const match_table_t key_tokens = {681{Opt_keyhandle, "keyhandle=%s"},682{Opt_keyauth, "keyauth=%s"},683{Opt_blobauth, "blobauth=%s"},684{Opt_pcrinfo, "pcrinfo=%s"},685{Opt_pcrlock, "pcrlock=%s"},686{Opt_migratable, "migratable=%s"},687{Opt_hash, "hash=%s"},688{Opt_policydigest, "policydigest=%s"},689{Opt_policyhandle, "policyhandle=%s"},690{Opt_err, NULL}691};692693/* can have zero or more token= options */694static int getoptions(char *c, struct trusted_key_payload *pay,695struct trusted_key_options *opt)696{697substring_t args[MAX_OPT_ARGS];698char *p = c;699int token;700int res;701unsigned long handle;702unsigned long lock;703unsigned long token_mask = 0;704unsigned int digest_len;705int i;706int tpm2;707708tpm2 = tpm_is_tpm2(chip);709if (tpm2 < 0)710return tpm2;711712opt->hash = tpm2 ? HASH_ALGO_SHA256 : HASH_ALGO_SHA1;713714if (!c)715return 0;716717while ((p = strsep(&c, " \t"))) {718if (*p == '\0' || *p == ' ' || *p == '\t')719continue;720token = match_token(p, key_tokens, args);721if (test_and_set_bit(token, &token_mask))722return -EINVAL;723724switch (token) {725case Opt_pcrinfo:726opt->pcrinfo_len = strlen(args[0].from) / 2;727if (opt->pcrinfo_len > MAX_PCRINFO_SIZE)728return -EINVAL;729res = hex2bin(opt->pcrinfo, args[0].from,730opt->pcrinfo_len);731if (res < 0)732return -EINVAL;733break;734case Opt_keyhandle:735res = kstrtoul(args[0].from, 16, &handle);736if (res < 0)737return -EINVAL;738opt->keytype = SEAL_keytype;739opt->keyhandle = handle;740break;741case Opt_keyauth:742if (strlen(args[0].from) != 2 * SHA1_DIGEST_SIZE)743return -EINVAL;744res = hex2bin(opt->keyauth, args[0].from,745SHA1_DIGEST_SIZE);746if (res < 0)747return -EINVAL;748break;749case Opt_blobauth:750/*751* TPM 1.2 authorizations are sha1 hashes passed in as752* hex strings. TPM 2.0 authorizations are simple753* passwords (although it can take a hash as well)754*/755opt->blobauth_len = strlen(args[0].from);756757if (opt->blobauth_len == 2 * TPM_DIGEST_SIZE) {758res = hex2bin(opt->blobauth, args[0].from,759TPM_DIGEST_SIZE);760if (res < 0)761return -EINVAL;762763opt->blobauth_len = TPM_DIGEST_SIZE;764break;765}766767if (tpm2 && opt->blobauth_len <= sizeof(opt->blobauth)) {768memcpy(opt->blobauth, args[0].from,769opt->blobauth_len);770break;771}772773return -EINVAL;774775break;776777case Opt_migratable:778if (*args[0].from == '0')779pay->migratable = 0;780else if (*args[0].from != '1')781return -EINVAL;782break;783case Opt_pcrlock:784res = kstrtoul(args[0].from, 10, &lock);785if (res < 0)786return -EINVAL;787opt->pcrlock = lock;788break;789case Opt_hash:790if (test_bit(Opt_policydigest, &token_mask))791return -EINVAL;792for (i = 0; i < HASH_ALGO__LAST; i++) {793if (!strcmp(args[0].from, hash_algo_name[i])) {794opt->hash = i;795break;796}797}798if (i == HASH_ALGO__LAST)799return -EINVAL;800if (!tpm2 && i != HASH_ALGO_SHA1) {801pr_info("TPM 1.x only supports SHA-1.\n");802return -EINVAL;803}804break;805case Opt_policydigest:806digest_len = hash_digest_size[opt->hash];807if (!tpm2 || strlen(args[0].from) != (2 * digest_len))808return -EINVAL;809res = hex2bin(opt->policydigest, args[0].from,810digest_len);811if (res < 0)812return -EINVAL;813opt->policydigest_len = digest_len;814break;815case Opt_policyhandle:816if (!tpm2)817return -EINVAL;818res = kstrtoul(args[0].from, 16, &handle);819if (res < 0)820return -EINVAL;821opt->policyhandle = handle;822break;823default:824return -EINVAL;825}826}827return 0;828}829830static struct trusted_key_options *trusted_options_alloc(void)831{832struct trusted_key_options *options;833int tpm2;834835tpm2 = tpm_is_tpm2(chip);836if (tpm2 < 0)837return NULL;838839options = kzalloc(sizeof *options, GFP_KERNEL);840if (options) {841/* set any non-zero defaults */842options->keytype = SRK_keytype;843844if (!tpm2)845options->keyhandle = SRKHANDLE;846}847return options;848}849850static int trusted_tpm_seal(struct trusted_key_payload *p, char *datablob)851{852struct trusted_key_options *options = NULL;853int ret = 0;854int tpm2;855856tpm2 = tpm_is_tpm2(chip);857if (tpm2 < 0)858return tpm2;859860options = trusted_options_alloc();861if (!options)862return -ENOMEM;863864ret = getoptions(datablob, p, options);865if (ret < 0)866goto out;867dump_options(options);868869if (!options->keyhandle && !tpm2) {870ret = -EINVAL;871goto out;872}873874if (tpm2)875ret = tpm2_seal_trusted(chip, p, options);876else877ret = key_seal(p, options);878if (ret < 0) {879pr_info("key_seal failed (%d)\n", ret);880goto out;881}882883if (options->pcrlock) {884ret = pcrlock(options->pcrlock);885if (ret < 0) {886pr_info("pcrlock failed (%d)\n", ret);887goto out;888}889}890out:891kfree_sensitive(options);892return ret;893}894895static int trusted_tpm_unseal(struct trusted_key_payload *p, char *datablob)896{897struct trusted_key_options *options = NULL;898int ret = 0;899int tpm2;900901tpm2 = tpm_is_tpm2(chip);902if (tpm2 < 0)903return tpm2;904905options = trusted_options_alloc();906if (!options)907return -ENOMEM;908909ret = getoptions(datablob, p, options);910if (ret < 0)911goto out;912dump_options(options);913914if (!options->keyhandle && !tpm2) {915ret = -EINVAL;916goto out;917}918919if (tpm2)920ret = tpm2_unseal_trusted(chip, p, options);921else922ret = key_unseal(p, options);923if (ret < 0)924pr_info("key_unseal failed (%d)\n", ret);925926if (options->pcrlock) {927ret = pcrlock(options->pcrlock);928if (ret < 0) {929pr_info("pcrlock failed (%d)\n", ret);930goto out;931}932}933out:934kfree_sensitive(options);935return ret;936}937938static int trusted_tpm_get_random(unsigned char *key, size_t key_len)939{940return tpm_get_random(chip, key, key_len);941}942943static int __init init_digests(void)944{945int i;946947digests = kcalloc(chip->nr_allocated_banks, sizeof(*digests),948GFP_KERNEL);949if (!digests)950return -ENOMEM;951952for (i = 0; i < chip->nr_allocated_banks; i++)953digests[i].alg_id = chip->allocated_banks[i].alg_id;954955return 0;956}957958static int __init trusted_tpm_init(void)959{960int ret;961962chip = tpm_default_chip();963if (!chip)964return -ENODEV;965966ret = init_digests();967if (ret < 0)968goto err_put;969ret = register_key_type(&key_type_trusted);970if (ret < 0)971goto err_free;972return 0;973err_free:974kfree(digests);975err_put:976put_device(&chip->dev);977return ret;978}979980static void trusted_tpm_exit(void)981{982if (chip) {983put_device(&chip->dev);984kfree(digests);985unregister_key_type(&key_type_trusted);986}987}988989struct trusted_key_ops trusted_key_tpm_ops = {990.migratable = 1, /* migratable by default */991.init = trusted_tpm_init,992.seal = trusted_tpm_seal,993.unseal = trusted_tpm_unseal,994.get_random = trusted_tpm_get_random,995.exit = trusted_tpm_exit,996};997998999