Path: blob/master/security/keys/trusted-keys/trusted_tpm1.c
26424 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 <linux/init.h>10#include <linux/slab.h>11#include <linux/parser.h>12#include <linux/string.h>13#include <linux/err.h>14#include <keys/trusted-type.h>15#include <linux/key-type.h>16#include <linux/crypto.h>17#include <crypto/hash.h>18#include <crypto/sha1.h>19#include <linux/tpm.h>20#include <linux/tpm_command.h>2122#include <keys/trusted_tpm.h>2324static const char hmac_alg[] = "hmac(sha1)";25static const char hash_alg[] = "sha1";26static struct tpm_chip *chip;27static struct tpm_digest *digests;2829struct sdesc {30struct shash_desc shash;31char ctx[];32};3334static struct crypto_shash *hashalg;35static struct crypto_shash *hmacalg;3637static struct sdesc *init_sdesc(struct crypto_shash *alg)38{39struct sdesc *sdesc;40int size;4142size = sizeof(struct shash_desc) + crypto_shash_descsize(alg);43sdesc = kmalloc(size, GFP_KERNEL);44if (!sdesc)45return ERR_PTR(-ENOMEM);46sdesc->shash.tfm = alg;47return sdesc;48}4950static int TSS_sha1(const unsigned char *data, unsigned int datalen,51unsigned char *digest)52{53struct sdesc *sdesc;54int ret;5556sdesc = init_sdesc(hashalg);57if (IS_ERR(sdesc)) {58pr_info("can't alloc %s\n", hash_alg);59return PTR_ERR(sdesc);60}6162ret = crypto_shash_digest(&sdesc->shash, data, datalen, digest);63kfree_sensitive(sdesc);64return ret;65}6667static int TSS_rawhmac(unsigned char *digest, const unsigned char *key,68unsigned int keylen, ...)69{70struct sdesc *sdesc;71va_list argp;72unsigned int dlen;73unsigned char *data;74int ret;7576sdesc = init_sdesc(hmacalg);77if (IS_ERR(sdesc)) {78pr_info("can't alloc %s\n", hmac_alg);79return PTR_ERR(sdesc);80}8182ret = crypto_shash_setkey(hmacalg, key, keylen);83if (ret < 0)84goto out;85ret = crypto_shash_init(&sdesc->shash);86if (ret < 0)87goto out;8889va_start(argp, keylen);90for (;;) {91dlen = va_arg(argp, unsigned int);92if (dlen == 0)93break;94data = va_arg(argp, unsigned char *);95if (data == NULL) {96ret = -EINVAL;97break;98}99ret = crypto_shash_update(&sdesc->shash, data, dlen);100if (ret < 0)101break;102}103va_end(argp);104if (!ret)105ret = crypto_shash_final(&sdesc->shash, digest);106out:107kfree_sensitive(sdesc);108return ret;109}110111/*112* calculate authorization info fields to send to TPM113*/114int TSS_authhmac(unsigned char *digest, const unsigned char *key,115unsigned int keylen, unsigned char *h1,116unsigned char *h2, unsigned int h3, ...)117{118unsigned char paramdigest[SHA1_DIGEST_SIZE];119struct sdesc *sdesc;120unsigned int dlen;121unsigned char *data;122unsigned char c;123int ret;124va_list argp;125126if (!chip)127return -ENODEV;128129sdesc = init_sdesc(hashalg);130if (IS_ERR(sdesc)) {131pr_info("can't alloc %s\n", hash_alg);132return PTR_ERR(sdesc);133}134135c = !!h3;136ret = crypto_shash_init(&sdesc->shash);137if (ret < 0)138goto out;139va_start(argp, h3);140for (;;) {141dlen = va_arg(argp, unsigned int);142if (dlen == 0)143break;144data = va_arg(argp, unsigned char *);145if (!data) {146ret = -EINVAL;147break;148}149ret = crypto_shash_update(&sdesc->shash, data, dlen);150if (ret < 0)151break;152}153va_end(argp);154if (!ret)155ret = crypto_shash_final(&sdesc->shash, paramdigest);156if (!ret)157ret = TSS_rawhmac(digest, key, keylen, SHA1_DIGEST_SIZE,158paramdigest, TPM_NONCE_SIZE, h1,159TPM_NONCE_SIZE, h2, 1, &c, 0, 0);160out:161kfree_sensitive(sdesc);162return ret;163}164EXPORT_SYMBOL_GPL(TSS_authhmac);165166/*167* verify the AUTH1_COMMAND (Seal) result from TPM168*/169int TSS_checkhmac1(unsigned char *buffer,170const uint32_t command,171const unsigned char *ononce,172const unsigned char *key,173unsigned int keylen, ...)174{175uint32_t bufsize;176uint16_t tag;177uint32_t ordinal;178uint32_t result;179unsigned char *enonce;180unsigned char *continueflag;181unsigned char *authdata;182unsigned char testhmac[SHA1_DIGEST_SIZE];183unsigned char paramdigest[SHA1_DIGEST_SIZE];184struct sdesc *sdesc;185unsigned int dlen;186unsigned int dpos;187va_list argp;188int ret;189190if (!chip)191return -ENODEV;192193bufsize = LOAD32(buffer, TPM_SIZE_OFFSET);194tag = LOAD16(buffer, 0);195ordinal = command;196result = LOAD32N(buffer, TPM_RETURN_OFFSET);197if (tag == TPM_TAG_RSP_COMMAND)198return 0;199if (tag != TPM_TAG_RSP_AUTH1_COMMAND)200return -EINVAL;201authdata = buffer + bufsize - SHA1_DIGEST_SIZE;202continueflag = authdata - 1;203enonce = continueflag - TPM_NONCE_SIZE;204205sdesc = init_sdesc(hashalg);206if (IS_ERR(sdesc)) {207pr_info("can't alloc %s\n", hash_alg);208return PTR_ERR(sdesc);209}210ret = crypto_shash_init(&sdesc->shash);211if (ret < 0)212goto out;213ret = crypto_shash_update(&sdesc->shash, (const u8 *)&result,214sizeof result);215if (ret < 0)216goto out;217ret = crypto_shash_update(&sdesc->shash, (const u8 *)&ordinal,218sizeof ordinal);219if (ret < 0)220goto out;221va_start(argp, keylen);222for (;;) {223dlen = va_arg(argp, unsigned int);224if (dlen == 0)225break;226dpos = va_arg(argp, unsigned int);227ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen);228if (ret < 0)229break;230}231va_end(argp);232if (!ret)233ret = crypto_shash_final(&sdesc->shash, paramdigest);234if (ret < 0)235goto out;236237ret = TSS_rawhmac(testhmac, key, keylen, SHA1_DIGEST_SIZE, paramdigest,238TPM_NONCE_SIZE, enonce, TPM_NONCE_SIZE, ononce,2391, continueflag, 0, 0);240if (ret < 0)241goto out;242243if (memcmp(testhmac, authdata, SHA1_DIGEST_SIZE))244ret = -EINVAL;245out:246kfree_sensitive(sdesc);247return ret;248}249EXPORT_SYMBOL_GPL(TSS_checkhmac1);250251/*252* verify the AUTH2_COMMAND (unseal) result from TPM253*/254static int TSS_checkhmac2(unsigned char *buffer,255const uint32_t command,256const unsigned char *ononce,257const unsigned char *key1,258unsigned int keylen1,259const unsigned char *key2,260unsigned int keylen2, ...)261{262uint32_t bufsize;263uint16_t tag;264uint32_t ordinal;265uint32_t result;266unsigned char *enonce1;267unsigned char *continueflag1;268unsigned char *authdata1;269unsigned char *enonce2;270unsigned char *continueflag2;271unsigned char *authdata2;272unsigned char testhmac1[SHA1_DIGEST_SIZE];273unsigned char testhmac2[SHA1_DIGEST_SIZE];274unsigned char paramdigest[SHA1_DIGEST_SIZE];275struct sdesc *sdesc;276unsigned int dlen;277unsigned int dpos;278va_list argp;279int ret;280281bufsize = LOAD32(buffer, TPM_SIZE_OFFSET);282tag = LOAD16(buffer, 0);283ordinal = command;284result = LOAD32N(buffer, TPM_RETURN_OFFSET);285286if (tag == TPM_TAG_RSP_COMMAND)287return 0;288if (tag != TPM_TAG_RSP_AUTH2_COMMAND)289return -EINVAL;290authdata1 = buffer + bufsize - (SHA1_DIGEST_SIZE + 1291+ SHA1_DIGEST_SIZE + SHA1_DIGEST_SIZE);292authdata2 = buffer + bufsize - (SHA1_DIGEST_SIZE);293continueflag1 = authdata1 - 1;294continueflag2 = authdata2 - 1;295enonce1 = continueflag1 - TPM_NONCE_SIZE;296enonce2 = continueflag2 - TPM_NONCE_SIZE;297298sdesc = init_sdesc(hashalg);299if (IS_ERR(sdesc)) {300pr_info("can't alloc %s\n", hash_alg);301return PTR_ERR(sdesc);302}303ret = crypto_shash_init(&sdesc->shash);304if (ret < 0)305goto out;306ret = crypto_shash_update(&sdesc->shash, (const u8 *)&result,307sizeof result);308if (ret < 0)309goto out;310ret = crypto_shash_update(&sdesc->shash, (const u8 *)&ordinal,311sizeof ordinal);312if (ret < 0)313goto out;314315va_start(argp, keylen2);316for (;;) {317dlen = va_arg(argp, unsigned int);318if (dlen == 0)319break;320dpos = va_arg(argp, unsigned int);321ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen);322if (ret < 0)323break;324}325va_end(argp);326if (!ret)327ret = crypto_shash_final(&sdesc->shash, paramdigest);328if (ret < 0)329goto out;330331ret = TSS_rawhmac(testhmac1, key1, keylen1, SHA1_DIGEST_SIZE,332paramdigest, TPM_NONCE_SIZE, enonce1,333TPM_NONCE_SIZE, ononce, 1, continueflag1, 0, 0);334if (ret < 0)335goto out;336if (memcmp(testhmac1, authdata1, SHA1_DIGEST_SIZE)) {337ret = -EINVAL;338goto out;339}340ret = TSS_rawhmac(testhmac2, key2, keylen2, SHA1_DIGEST_SIZE,341paramdigest, TPM_NONCE_SIZE, enonce2,342TPM_NONCE_SIZE, ononce, 1, continueflag2, 0, 0);343if (ret < 0)344goto out;345if (memcmp(testhmac2, authdata2, SHA1_DIGEST_SIZE))346ret = -EINVAL;347out:348kfree_sensitive(sdesc);349return ret;350}351352/*353* For key specific tpm requests, we will generate and send our354* own TPM command packets using the drivers send function.355*/356int trusted_tpm_send(unsigned char *cmd, size_t buflen)357{358struct tpm_buf buf;359int rc;360361if (!chip)362return -ENODEV;363364rc = tpm_try_get_ops(chip);365if (rc)366return rc;367368buf.flags = 0;369buf.length = buflen;370buf.data = cmd;371dump_tpm_buf(cmd);372rc = tpm_transmit_cmd(chip, &buf, 4, "sending data");373dump_tpm_buf(cmd);374375if (rc > 0)376/* TPM error */377rc = -EPERM;378379tpm_put_ops(chip);380return rc;381}382EXPORT_SYMBOL_GPL(trusted_tpm_send);383384/*385* Lock a trusted key, by extending a selected PCR.386*387* Prevents a trusted key that is sealed to PCRs from being accessed.388* This uses the tpm driver's extend function.389*/390static int pcrlock(const int pcrnum)391{392if (!capable(CAP_SYS_ADMIN))393return -EPERM;394395return tpm_pcr_extend(chip, pcrnum, digests) ? -EINVAL : 0;396}397398/*399* Create an object specific authorisation protocol (OSAP) session400*/401static int osap(struct tpm_buf *tb, struct osapsess *s,402const unsigned char *key, uint16_t type, uint32_t handle)403{404unsigned char enonce[TPM_NONCE_SIZE];405unsigned char ononce[TPM_NONCE_SIZE];406int ret;407408ret = tpm_get_random(chip, ononce, TPM_NONCE_SIZE);409if (ret < 0)410return ret;411412if (ret != TPM_NONCE_SIZE)413return -EIO;414415tpm_buf_reset(tb, TPM_TAG_RQU_COMMAND, TPM_ORD_OSAP);416tpm_buf_append_u16(tb, type);417tpm_buf_append_u32(tb, handle);418tpm_buf_append(tb, ononce, TPM_NONCE_SIZE);419420ret = trusted_tpm_send(tb->data, tb->length);421if (ret < 0)422return ret;423424s->handle = LOAD32(tb->data, TPM_DATA_OFFSET);425memcpy(s->enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)]),426TPM_NONCE_SIZE);427memcpy(enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t) +428TPM_NONCE_SIZE]), TPM_NONCE_SIZE);429return TSS_rawhmac(s->secret, key, SHA1_DIGEST_SIZE, TPM_NONCE_SIZE,430enonce, TPM_NONCE_SIZE, ononce, 0, 0);431}432433/*434* Create an object independent authorisation protocol (oiap) session435*/436int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce)437{438int ret;439440if (!chip)441return -ENODEV;442443tpm_buf_reset(tb, TPM_TAG_RQU_COMMAND, TPM_ORD_OIAP);444ret = trusted_tpm_send(tb->data, tb->length);445if (ret < 0)446return ret;447448*handle = LOAD32(tb->data, TPM_DATA_OFFSET);449memcpy(nonce, &tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)],450TPM_NONCE_SIZE);451return 0;452}453EXPORT_SYMBOL_GPL(oiap);454455struct tpm_digests {456unsigned char encauth[SHA1_DIGEST_SIZE];457unsigned char pubauth[SHA1_DIGEST_SIZE];458unsigned char xorwork[SHA1_DIGEST_SIZE * 2];459unsigned char xorhash[SHA1_DIGEST_SIZE];460unsigned char nonceodd[TPM_NONCE_SIZE];461};462463/*464* Have the TPM seal(encrypt) the trusted key, possibly based on465* Platform Configuration Registers (PCRs). AUTH1 for sealing key.466*/467static int tpm_seal(struct tpm_buf *tb, uint16_t keytype,468uint32_t keyhandle, const unsigned char *keyauth,469const unsigned char *data, uint32_t datalen,470unsigned char *blob, uint32_t *bloblen,471const unsigned char *blobauth,472const unsigned char *pcrinfo, uint32_t pcrinfosize)473{474struct osapsess sess;475struct tpm_digests *td;476unsigned char cont;477uint32_t ordinal;478uint32_t pcrsize;479uint32_t datsize;480int sealinfosize;481int encdatasize;482int storedsize;483int ret;484int i;485486/* alloc some work space for all the hashes */487td = kmalloc(sizeof *td, GFP_KERNEL);488if (!td)489return -ENOMEM;490491/* get session for sealing key */492ret = osap(tb, &sess, keyauth, keytype, keyhandle);493if (ret < 0)494goto out;495dump_sess(&sess);496497/* calculate encrypted authorization value */498memcpy(td->xorwork, sess.secret, SHA1_DIGEST_SIZE);499memcpy(td->xorwork + SHA1_DIGEST_SIZE, sess.enonce, SHA1_DIGEST_SIZE);500ret = TSS_sha1(td->xorwork, SHA1_DIGEST_SIZE * 2, td->xorhash);501if (ret < 0)502goto out;503504ret = tpm_get_random(chip, td->nonceodd, TPM_NONCE_SIZE);505if (ret < 0)506goto out;507508if (ret != TPM_NONCE_SIZE) {509ret = -EIO;510goto out;511}512513ordinal = htonl(TPM_ORD_SEAL);514datsize = htonl(datalen);515pcrsize = htonl(pcrinfosize);516cont = 0;517518/* encrypt data authorization key */519for (i = 0; i < SHA1_DIGEST_SIZE; ++i)520td->encauth[i] = td->xorhash[i] ^ blobauth[i];521522/* calculate authorization HMAC value */523if (pcrinfosize == 0) {524/* no pcr info specified */525ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,526sess.enonce, td->nonceodd, cont,527sizeof(uint32_t), &ordinal, SHA1_DIGEST_SIZE,528td->encauth, sizeof(uint32_t), &pcrsize,529sizeof(uint32_t), &datsize, datalen, data, 0,5300);531} else {532/* pcr info specified */533ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,534sess.enonce, td->nonceodd, cont,535sizeof(uint32_t), &ordinal, SHA1_DIGEST_SIZE,536td->encauth, sizeof(uint32_t), &pcrsize,537pcrinfosize, pcrinfo, sizeof(uint32_t),538&datsize, datalen, data, 0, 0);539}540if (ret < 0)541goto out;542543/* build and send the TPM request packet */544tpm_buf_reset(tb, TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_SEAL);545tpm_buf_append_u32(tb, keyhandle);546tpm_buf_append(tb, td->encauth, SHA1_DIGEST_SIZE);547tpm_buf_append_u32(tb, pcrinfosize);548tpm_buf_append(tb, pcrinfo, pcrinfosize);549tpm_buf_append_u32(tb, datalen);550tpm_buf_append(tb, data, datalen);551tpm_buf_append_u32(tb, sess.handle);552tpm_buf_append(tb, td->nonceodd, TPM_NONCE_SIZE);553tpm_buf_append_u8(tb, cont);554tpm_buf_append(tb, td->pubauth, SHA1_DIGEST_SIZE);555556ret = trusted_tpm_send(tb->data, tb->length);557if (ret < 0)558goto out;559560/* calculate the size of the returned Blob */561sealinfosize = LOAD32(tb->data, TPM_DATA_OFFSET + sizeof(uint32_t));562encdatasize = LOAD32(tb->data, TPM_DATA_OFFSET + sizeof(uint32_t) +563sizeof(uint32_t) + sealinfosize);564storedsize = sizeof(uint32_t) + sizeof(uint32_t) + sealinfosize +565sizeof(uint32_t) + encdatasize;566567/* check the HMAC in the response */568ret = TSS_checkhmac1(tb->data, ordinal, td->nonceodd, sess.secret,569SHA1_DIGEST_SIZE, storedsize, TPM_DATA_OFFSET, 0,5700);571572/* copy the returned blob to caller */573if (!ret) {574memcpy(blob, tb->data + TPM_DATA_OFFSET, storedsize);575*bloblen = storedsize;576}577out:578kfree_sensitive(td);579return ret;580}581582/*583* use the AUTH2_COMMAND form of unseal, to authorize both key and blob584*/585static int tpm_unseal(struct tpm_buf *tb,586uint32_t keyhandle, const unsigned char *keyauth,587const unsigned char *blob, int bloblen,588const unsigned char *blobauth,589unsigned char *data, unsigned int *datalen)590{591unsigned char nonceodd[TPM_NONCE_SIZE];592unsigned char enonce1[TPM_NONCE_SIZE];593unsigned char enonce2[TPM_NONCE_SIZE];594unsigned char authdata1[SHA1_DIGEST_SIZE];595unsigned char authdata2[SHA1_DIGEST_SIZE];596uint32_t authhandle1 = 0;597uint32_t authhandle2 = 0;598unsigned char cont = 0;599uint32_t ordinal;600int ret;601602/* sessions for unsealing key and data */603ret = oiap(tb, &authhandle1, enonce1);604if (ret < 0) {605pr_info("oiap failed (%d)\n", ret);606return ret;607}608ret = oiap(tb, &authhandle2, enonce2);609if (ret < 0) {610pr_info("oiap failed (%d)\n", ret);611return ret;612}613614ordinal = htonl(TPM_ORD_UNSEAL);615ret = tpm_get_random(chip, nonceodd, TPM_NONCE_SIZE);616if (ret < 0)617return ret;618619if (ret != TPM_NONCE_SIZE) {620pr_info("tpm_get_random failed (%d)\n", ret);621return -EIO;622}623ret = TSS_authhmac(authdata1, keyauth, TPM_NONCE_SIZE,624enonce1, nonceodd, cont, sizeof(uint32_t),625&ordinal, bloblen, blob, 0, 0);626if (ret < 0)627return ret;628ret = TSS_authhmac(authdata2, blobauth, TPM_NONCE_SIZE,629enonce2, nonceodd, cont, sizeof(uint32_t),630&ordinal, bloblen, blob, 0, 0);631if (ret < 0)632return ret;633634/* build and send TPM request packet */635tpm_buf_reset(tb, TPM_TAG_RQU_AUTH2_COMMAND, TPM_ORD_UNSEAL);636tpm_buf_append_u32(tb, keyhandle);637tpm_buf_append(tb, blob, bloblen);638tpm_buf_append_u32(tb, authhandle1);639tpm_buf_append(tb, nonceodd, TPM_NONCE_SIZE);640tpm_buf_append_u8(tb, cont);641tpm_buf_append(tb, authdata1, SHA1_DIGEST_SIZE);642tpm_buf_append_u32(tb, authhandle2);643tpm_buf_append(tb, nonceodd, TPM_NONCE_SIZE);644tpm_buf_append_u8(tb, cont);645tpm_buf_append(tb, authdata2, SHA1_DIGEST_SIZE);646647ret = trusted_tpm_send(tb->data, tb->length);648if (ret < 0) {649pr_info("authhmac failed (%d)\n", ret);650return ret;651}652653*datalen = LOAD32(tb->data, TPM_DATA_OFFSET);654ret = TSS_checkhmac2(tb->data, ordinal, nonceodd,655keyauth, SHA1_DIGEST_SIZE,656blobauth, SHA1_DIGEST_SIZE,657sizeof(uint32_t), TPM_DATA_OFFSET,658*datalen, TPM_DATA_OFFSET + sizeof(uint32_t), 0,6590);660if (ret < 0) {661pr_info("TSS_checkhmac2 failed (%d)\n", ret);662return ret;663}664memcpy(data, tb->data + TPM_DATA_OFFSET + sizeof(uint32_t), *datalen);665return 0;666}667668/*669* Have the TPM seal(encrypt) the symmetric key670*/671static int key_seal(struct trusted_key_payload *p,672struct trusted_key_options *o)673{674struct tpm_buf tb;675int ret;676677ret = tpm_buf_init(&tb, 0, 0);678if (ret)679return ret;680681/* include migratable flag at end of sealed key */682p->key[p->key_len] = p->migratable;683684ret = tpm_seal(&tb, o->keytype, o->keyhandle, o->keyauth,685p->key, p->key_len + 1, p->blob, &p->blob_len,686o->blobauth, o->pcrinfo, o->pcrinfo_len);687if (ret < 0)688pr_info("srkseal failed (%d)\n", ret);689690tpm_buf_destroy(&tb);691return ret;692}693694/*695* Have the TPM unseal(decrypt) the symmetric key696*/697static int key_unseal(struct trusted_key_payload *p,698struct trusted_key_options *o)699{700struct tpm_buf tb;701int ret;702703ret = tpm_buf_init(&tb, 0, 0);704if (ret)705return ret;706707ret = tpm_unseal(&tb, o->keyhandle, o->keyauth, p->blob, p->blob_len,708o->blobauth, p->key, &p->key_len);709if (ret < 0)710pr_info("srkunseal failed (%d)\n", ret);711else712/* pull migratable flag out of sealed key */713p->migratable = p->key[--p->key_len];714715tpm_buf_destroy(&tb);716return ret;717}718719enum {720Opt_err,721Opt_keyhandle, Opt_keyauth, Opt_blobauth,722Opt_pcrinfo, Opt_pcrlock, Opt_migratable,723Opt_hash,724Opt_policydigest,725Opt_policyhandle,726};727728static const match_table_t key_tokens = {729{Opt_keyhandle, "keyhandle=%s"},730{Opt_keyauth, "keyauth=%s"},731{Opt_blobauth, "blobauth=%s"},732{Opt_pcrinfo, "pcrinfo=%s"},733{Opt_pcrlock, "pcrlock=%s"},734{Opt_migratable, "migratable=%s"},735{Opt_hash, "hash=%s"},736{Opt_policydigest, "policydigest=%s"},737{Opt_policyhandle, "policyhandle=%s"},738{Opt_err, NULL}739};740741/* can have zero or more token= options */742static int getoptions(char *c, struct trusted_key_payload *pay,743struct trusted_key_options *opt)744{745substring_t args[MAX_OPT_ARGS];746char *p = c;747int token;748int res;749unsigned long handle;750unsigned long lock;751unsigned long token_mask = 0;752unsigned int digest_len;753int i;754int tpm2;755756tpm2 = tpm_is_tpm2(chip);757if (tpm2 < 0)758return tpm2;759760opt->hash = tpm2 ? HASH_ALGO_SHA256 : HASH_ALGO_SHA1;761762if (!c)763return 0;764765while ((p = strsep(&c, " \t"))) {766if (*p == '\0' || *p == ' ' || *p == '\t')767continue;768token = match_token(p, key_tokens, args);769if (test_and_set_bit(token, &token_mask))770return -EINVAL;771772switch (token) {773case Opt_pcrinfo:774opt->pcrinfo_len = strlen(args[0].from) / 2;775if (opt->pcrinfo_len > MAX_PCRINFO_SIZE)776return -EINVAL;777res = hex2bin(opt->pcrinfo, args[0].from,778opt->pcrinfo_len);779if (res < 0)780return -EINVAL;781break;782case Opt_keyhandle:783res = kstrtoul(args[0].from, 16, &handle);784if (res < 0)785return -EINVAL;786opt->keytype = SEAL_keytype;787opt->keyhandle = handle;788break;789case Opt_keyauth:790if (strlen(args[0].from) != 2 * SHA1_DIGEST_SIZE)791return -EINVAL;792res = hex2bin(opt->keyauth, args[0].from,793SHA1_DIGEST_SIZE);794if (res < 0)795return -EINVAL;796break;797case Opt_blobauth:798/*799* TPM 1.2 authorizations are sha1 hashes passed in as800* hex strings. TPM 2.0 authorizations are simple801* passwords (although it can take a hash as well)802*/803opt->blobauth_len = strlen(args[0].from);804805if (opt->blobauth_len == 2 * TPM_DIGEST_SIZE) {806res = hex2bin(opt->blobauth, args[0].from,807TPM_DIGEST_SIZE);808if (res < 0)809return -EINVAL;810811opt->blobauth_len = TPM_DIGEST_SIZE;812break;813}814815if (tpm2 && opt->blobauth_len <= sizeof(opt->blobauth)) {816memcpy(opt->blobauth, args[0].from,817opt->blobauth_len);818break;819}820821return -EINVAL;822823break;824825case Opt_migratable:826if (*args[0].from == '0')827pay->migratable = 0;828else if (*args[0].from != '1')829return -EINVAL;830break;831case Opt_pcrlock:832res = kstrtoul(args[0].from, 10, &lock);833if (res < 0)834return -EINVAL;835opt->pcrlock = lock;836break;837case Opt_hash:838if (test_bit(Opt_policydigest, &token_mask))839return -EINVAL;840for (i = 0; i < HASH_ALGO__LAST; i++) {841if (!strcmp(args[0].from, hash_algo_name[i])) {842opt->hash = i;843break;844}845}846if (i == HASH_ALGO__LAST)847return -EINVAL;848if (!tpm2 && i != HASH_ALGO_SHA1) {849pr_info("TPM 1.x only supports SHA-1.\n");850return -EINVAL;851}852break;853case Opt_policydigest:854digest_len = hash_digest_size[opt->hash];855if (!tpm2 || strlen(args[0].from) != (2 * digest_len))856return -EINVAL;857res = hex2bin(opt->policydigest, args[0].from,858digest_len);859if (res < 0)860return -EINVAL;861opt->policydigest_len = digest_len;862break;863case Opt_policyhandle:864if (!tpm2)865return -EINVAL;866res = kstrtoul(args[0].from, 16, &handle);867if (res < 0)868return -EINVAL;869opt->policyhandle = handle;870break;871default:872return -EINVAL;873}874}875return 0;876}877878static struct trusted_key_options *trusted_options_alloc(void)879{880struct trusted_key_options *options;881int tpm2;882883tpm2 = tpm_is_tpm2(chip);884if (tpm2 < 0)885return NULL;886887options = kzalloc(sizeof *options, GFP_KERNEL);888if (options) {889/* set any non-zero defaults */890options->keytype = SRK_keytype;891892if (!tpm2)893options->keyhandle = SRKHANDLE;894}895return options;896}897898static int trusted_tpm_seal(struct trusted_key_payload *p, char *datablob)899{900struct trusted_key_options *options = NULL;901int ret = 0;902int tpm2;903904tpm2 = tpm_is_tpm2(chip);905if (tpm2 < 0)906return tpm2;907908options = trusted_options_alloc();909if (!options)910return -ENOMEM;911912ret = getoptions(datablob, p, options);913if (ret < 0)914goto out;915dump_options(options);916917if (!options->keyhandle && !tpm2) {918ret = -EINVAL;919goto out;920}921922if (tpm2)923ret = tpm2_seal_trusted(chip, p, options);924else925ret = key_seal(p, options);926if (ret < 0) {927pr_info("key_seal failed (%d)\n", ret);928goto out;929}930931if (options->pcrlock) {932ret = pcrlock(options->pcrlock);933if (ret < 0) {934pr_info("pcrlock failed (%d)\n", ret);935goto out;936}937}938out:939kfree_sensitive(options);940return ret;941}942943static int trusted_tpm_unseal(struct trusted_key_payload *p, char *datablob)944{945struct trusted_key_options *options = NULL;946int ret = 0;947int tpm2;948949tpm2 = tpm_is_tpm2(chip);950if (tpm2 < 0)951return tpm2;952953options = trusted_options_alloc();954if (!options)955return -ENOMEM;956957ret = getoptions(datablob, p, options);958if (ret < 0)959goto out;960dump_options(options);961962if (!options->keyhandle && !tpm2) {963ret = -EINVAL;964goto out;965}966967if (tpm2)968ret = tpm2_unseal_trusted(chip, p, options);969else970ret = key_unseal(p, options);971if (ret < 0)972pr_info("key_unseal failed (%d)\n", ret);973974if (options->pcrlock) {975ret = pcrlock(options->pcrlock);976if (ret < 0) {977pr_info("pcrlock failed (%d)\n", ret);978goto out;979}980}981out:982kfree_sensitive(options);983return ret;984}985986static int trusted_tpm_get_random(unsigned char *key, size_t key_len)987{988return tpm_get_random(chip, key, key_len);989}990991static void trusted_shash_release(void)992{993if (hashalg)994crypto_free_shash(hashalg);995if (hmacalg)996crypto_free_shash(hmacalg);997}998999static int __init trusted_shash_alloc(void)1000{1001int ret;10021003hmacalg = crypto_alloc_shash(hmac_alg, 0, 0);1004if (IS_ERR(hmacalg)) {1005pr_info("could not allocate crypto %s\n",1006hmac_alg);1007return PTR_ERR(hmacalg);1008}10091010hashalg = crypto_alloc_shash(hash_alg, 0, 0);1011if (IS_ERR(hashalg)) {1012pr_info("could not allocate crypto %s\n",1013hash_alg);1014ret = PTR_ERR(hashalg);1015goto hashalg_fail;1016}10171018return 0;10191020hashalg_fail:1021crypto_free_shash(hmacalg);1022return ret;1023}10241025static int __init init_digests(void)1026{1027int i;10281029digests = kcalloc(chip->nr_allocated_banks, sizeof(*digests),1030GFP_KERNEL);1031if (!digests)1032return -ENOMEM;10331034for (i = 0; i < chip->nr_allocated_banks; i++)1035digests[i].alg_id = chip->allocated_banks[i].alg_id;10361037return 0;1038}10391040static int __init trusted_tpm_init(void)1041{1042int ret;10431044chip = tpm_default_chip();1045if (!chip)1046return -ENODEV;10471048ret = init_digests();1049if (ret < 0)1050goto err_put;1051ret = trusted_shash_alloc();1052if (ret < 0)1053goto err_free;1054ret = register_key_type(&key_type_trusted);1055if (ret < 0)1056goto err_release;1057return 0;1058err_release:1059trusted_shash_release();1060err_free:1061kfree(digests);1062err_put:1063put_device(&chip->dev);1064return ret;1065}10661067static void trusted_tpm_exit(void)1068{1069if (chip) {1070put_device(&chip->dev);1071kfree(digests);1072trusted_shash_release();1073unregister_key_type(&key_type_trusted);1074}1075}10761077struct trusted_key_ops trusted_key_tpm_ops = {1078.migratable = 1, /* migratable by default */1079.init = trusted_tpm_init,1080.seal = trusted_tpm_seal,1081.unseal = trusted_tpm_unseal,1082.get_random = trusted_tpm_get_random,1083.exit = trusted_tpm_exit,1084};108510861087