Path: blob/master/security/keys/trusted-keys/trusted_tpm1.c
51320 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/hex.h>12#include <linux/init.h>13#include <linux/slab.h>14#include <linux/parser.h>15#include <linux/string.h>16#include <linux/err.h>17#include <keys/trusted-type.h>18#include <linux/key-type.h>19#include <linux/tpm.h>20#include <linux/tpm_command.h>2122#include <keys/trusted_tpm.h>2324static struct tpm_chip *chip;25static struct tpm_digest *digests;2627/* implementation specific TPM constants */28#define TPM_SIZE_OFFSET 229#define TPM_RETURN_OFFSET 630#define TPM_DATA_OFFSET 103132#define LOAD32(buffer, offset) (ntohl(*(uint32_t *)&buffer[offset]))33#define LOAD32N(buffer, offset) (*(uint32_t *)&buffer[offset])34#define LOAD16(buffer, offset) (ntohs(*(uint16_t *)&buffer[offset]))3536struct osapsess {37uint32_t handle;38unsigned char secret[SHA1_DIGEST_SIZE];39unsigned char enonce[TPM_NONCE_SIZE];40};4142/* discrete values, but have to store in uint16_t for TPM use */43enum {44SEAL_keytype = 1,45SRK_keytype = 446};4748#define TPM_DEBUG 04950#if TPM_DEBUG51static inline void dump_options(struct trusted_key_options *o)52{53pr_info("sealing key type %d\n", o->keytype);54pr_info("sealing key handle %0X\n", o->keyhandle);55pr_info("pcrlock %d\n", o->pcrlock);56pr_info("pcrinfo %d\n", o->pcrinfo_len);57print_hex_dump(KERN_INFO, "pcrinfo ", DUMP_PREFIX_NONE,5816, 1, o->pcrinfo, o->pcrinfo_len, 0);59}6061static inline void dump_sess(struct osapsess *s)62{63print_hex_dump(KERN_INFO, "trusted-key: handle ", DUMP_PREFIX_NONE,6416, 1, &s->handle, 4, 0);65pr_info("secret:\n");66print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE,6716, 1, &s->secret, SHA1_DIGEST_SIZE, 0);68pr_info("trusted-key: enonce:\n");69print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE,7016, 1, &s->enonce, SHA1_DIGEST_SIZE, 0);71}7273static inline void dump_tpm_buf(unsigned char *buf)74{75int len;7677pr_info("\ntpm buffer\n");78len = LOAD32(buf, TPM_SIZE_OFFSET);79print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, buf, len, 0);80}81#else82static inline void dump_options(struct trusted_key_options *o)83{84}8586static inline void dump_sess(struct osapsess *s)87{88}8990static inline void dump_tpm_buf(unsigned char *buf)91{92}93#endif9495static int TSS_rawhmac(unsigned char *digest, const unsigned char *key,96unsigned int keylen, ...)97{98struct hmac_sha1_ctx hmac_ctx;99va_list argp;100unsigned int dlen;101unsigned char *data;102int ret = 0;103104hmac_sha1_init_usingrawkey(&hmac_ctx, key, keylen);105106va_start(argp, keylen);107for (;;) {108dlen = va_arg(argp, unsigned int);109if (dlen == 0)110break;111data = va_arg(argp, unsigned char *);112if (data == NULL) {113ret = -EINVAL;114break;115}116hmac_sha1_update(&hmac_ctx, data, dlen);117}118va_end(argp);119if (!ret)120hmac_sha1_final(&hmac_ctx, digest);121return ret;122}123124/*125* calculate authorization info fields to send to TPM126*/127static int TSS_authhmac(unsigned char *digest, const unsigned char *key,128unsigned int keylen, unsigned char *h1,129unsigned char *h2, unsigned int h3, ...)130{131unsigned char paramdigest[SHA1_DIGEST_SIZE];132struct sha1_ctx sha_ctx;133unsigned int dlen;134unsigned char *data;135unsigned char c;136int ret = 0;137va_list argp;138139if (!chip)140return -ENODEV;141142c = !!h3;143sha1_init(&sha_ctx);144va_start(argp, h3);145for (;;) {146dlen = va_arg(argp, unsigned int);147if (dlen == 0)148break;149data = va_arg(argp, unsigned char *);150if (!data) {151ret = -EINVAL;152break;153}154sha1_update(&sha_ctx, data, dlen);155}156va_end(argp);157if (!ret)158sha1_final(&sha_ctx, paramdigest);159if (!ret)160ret = TSS_rawhmac(digest, key, keylen, SHA1_DIGEST_SIZE,161paramdigest, TPM_NONCE_SIZE, h1,162TPM_NONCE_SIZE, h2, 1, &c, 0, 0);163return ret;164}165166/*167* verify the AUTH1_COMMAND (Seal) result from TPM168*/169static int 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 sha1_ctx sha_ctx;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;204205sha1_init(&sha_ctx);206sha1_update(&sha_ctx, (const u8 *)&result, sizeof(result));207sha1_update(&sha_ctx, (const u8 *)&ordinal, sizeof(ordinal));208va_start(argp, keylen);209for (;;) {210dlen = va_arg(argp, unsigned int);211if (dlen == 0)212break;213dpos = va_arg(argp, unsigned int);214sha1_update(&sha_ctx, buffer + dpos, dlen);215}216va_end(argp);217sha1_final(&sha_ctx, paramdigest);218219ret = TSS_rawhmac(testhmac, key, keylen, SHA1_DIGEST_SIZE, paramdigest,220TPM_NONCE_SIZE, enonce, TPM_NONCE_SIZE, ononce,2211, continueflag, 0, 0);222if (ret < 0)223return ret;224225if (crypto_memneq(testhmac, authdata, SHA1_DIGEST_SIZE))226return -EINVAL;227return 0;228}229230/*231* verify the AUTH2_COMMAND (unseal) result from TPM232*/233static int TSS_checkhmac2(unsigned char *buffer,234const uint32_t command,235const unsigned char *ononce,236const unsigned char *key1,237unsigned int keylen1,238const unsigned char *key2,239unsigned int keylen2, ...)240{241uint32_t bufsize;242uint16_t tag;243uint32_t ordinal;244uint32_t result;245unsigned char *enonce1;246unsigned char *continueflag1;247unsigned char *authdata1;248unsigned char *enonce2;249unsigned char *continueflag2;250unsigned char *authdata2;251unsigned char testhmac1[SHA1_DIGEST_SIZE];252unsigned char testhmac2[SHA1_DIGEST_SIZE];253unsigned char paramdigest[SHA1_DIGEST_SIZE];254struct sha1_ctx sha_ctx;255unsigned int dlen;256unsigned int dpos;257va_list argp;258int ret;259260bufsize = LOAD32(buffer, TPM_SIZE_OFFSET);261tag = LOAD16(buffer, 0);262ordinal = command;263result = LOAD32N(buffer, TPM_RETURN_OFFSET);264265if (tag == TPM_TAG_RSP_COMMAND)266return 0;267if (tag != TPM_TAG_RSP_AUTH2_COMMAND)268return -EINVAL;269authdata1 = buffer + bufsize - (SHA1_DIGEST_SIZE + 1270+ SHA1_DIGEST_SIZE + SHA1_DIGEST_SIZE);271authdata2 = buffer + bufsize - (SHA1_DIGEST_SIZE);272continueflag1 = authdata1 - 1;273continueflag2 = authdata2 - 1;274enonce1 = continueflag1 - TPM_NONCE_SIZE;275enonce2 = continueflag2 - TPM_NONCE_SIZE;276277sha1_init(&sha_ctx);278sha1_update(&sha_ctx, (const u8 *)&result, sizeof(result));279sha1_update(&sha_ctx, (const u8 *)&ordinal, sizeof(ordinal));280281va_start(argp, keylen2);282for (;;) {283dlen = va_arg(argp, unsigned int);284if (dlen == 0)285break;286dpos = va_arg(argp, unsigned int);287sha1_update(&sha_ctx, buffer + dpos, dlen);288}289va_end(argp);290sha1_final(&sha_ctx, paramdigest);291292ret = TSS_rawhmac(testhmac1, key1, keylen1, SHA1_DIGEST_SIZE,293paramdigest, TPM_NONCE_SIZE, enonce1,294TPM_NONCE_SIZE, ononce, 1, continueflag1, 0, 0);295if (ret < 0)296return ret;297if (crypto_memneq(testhmac1, authdata1, SHA1_DIGEST_SIZE))298return -EINVAL;299ret = TSS_rawhmac(testhmac2, key2, keylen2, SHA1_DIGEST_SIZE,300paramdigest, TPM_NONCE_SIZE, enonce2,301TPM_NONCE_SIZE, ononce, 1, continueflag2, 0, 0);302if (ret < 0)303return ret;304if (crypto_memneq(testhmac2, authdata2, SHA1_DIGEST_SIZE))305return -EINVAL;306return 0;307}308309/*310* For key specific tpm requests, we will generate and send our311* own TPM command packets using the drivers send function.312*/313static int trusted_tpm_send(unsigned char *cmd, size_t buflen)314{315struct tpm_buf buf;316int rc;317318if (!chip)319return -ENODEV;320321rc = tpm_try_get_ops(chip);322if (rc)323return rc;324325buf.flags = 0;326buf.length = buflen;327buf.data = cmd;328dump_tpm_buf(cmd);329rc = tpm_transmit_cmd(chip, &buf, 4, "sending data");330dump_tpm_buf(cmd);331332if (rc > 0)333/* TPM error */334rc = -EPERM;335336tpm_put_ops(chip);337return rc;338}339340/*341* Lock a trusted key, by extending a selected PCR.342*343* Prevents a trusted key that is sealed to PCRs from being accessed.344* This uses the tpm driver's extend function.345*/346static int pcrlock(const int pcrnum)347{348if (!capable(CAP_SYS_ADMIN))349return -EPERM;350351return tpm_pcr_extend(chip, pcrnum, digests) ? -EINVAL : 0;352}353354/*355* Create an object specific authorisation protocol (OSAP) session356*/357static int osap(struct tpm_buf *tb, struct osapsess *s,358const unsigned char *key, uint16_t type, uint32_t handle)359{360unsigned char enonce[TPM_NONCE_SIZE];361unsigned char ononce[TPM_NONCE_SIZE];362int ret;363364ret = tpm_get_random(chip, ononce, TPM_NONCE_SIZE);365if (ret < 0)366return ret;367368if (ret != TPM_NONCE_SIZE)369return -EIO;370371tpm_buf_reset(tb, TPM_TAG_RQU_COMMAND, TPM_ORD_OSAP);372tpm_buf_append_u16(tb, type);373tpm_buf_append_u32(tb, handle);374tpm_buf_append(tb, ononce, TPM_NONCE_SIZE);375376ret = trusted_tpm_send(tb->data, tb->length);377if (ret < 0)378return ret;379380s->handle = LOAD32(tb->data, TPM_DATA_OFFSET);381memcpy(s->enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)]),382TPM_NONCE_SIZE);383memcpy(enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t) +384TPM_NONCE_SIZE]), TPM_NONCE_SIZE);385return TSS_rawhmac(s->secret, key, SHA1_DIGEST_SIZE, TPM_NONCE_SIZE,386enonce, TPM_NONCE_SIZE, ononce, 0, 0);387}388389/*390* Create an object independent authorisation protocol (oiap) session391*/392static int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce)393{394int ret;395396if (!chip)397return -ENODEV;398399tpm_buf_reset(tb, TPM_TAG_RQU_COMMAND, TPM_ORD_OIAP);400ret = trusted_tpm_send(tb->data, tb->length);401if (ret < 0)402return ret;403404*handle = LOAD32(tb->data, TPM_DATA_OFFSET);405memcpy(nonce, &tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)],406TPM_NONCE_SIZE);407return 0;408}409410struct tpm_digests {411unsigned char encauth[SHA1_DIGEST_SIZE];412unsigned char pubauth[SHA1_DIGEST_SIZE];413unsigned char xorwork[SHA1_DIGEST_SIZE * 2];414unsigned char xorhash[SHA1_DIGEST_SIZE];415unsigned char nonceodd[TPM_NONCE_SIZE];416};417418/*419* Have the TPM seal(encrypt) the trusted key, possibly based on420* Platform Configuration Registers (PCRs). AUTH1 for sealing key.421*/422static int tpm_seal(struct tpm_buf *tb, uint16_t keytype,423uint32_t keyhandle, const unsigned char *keyauth,424const unsigned char *data, uint32_t datalen,425unsigned char *blob, uint32_t *bloblen,426const unsigned char *blobauth,427const unsigned char *pcrinfo, uint32_t pcrinfosize)428{429struct osapsess sess;430struct tpm_digests *td;431unsigned char cont;432uint32_t ordinal;433uint32_t pcrsize;434uint32_t datsize;435int sealinfosize;436int encdatasize;437int storedsize;438int ret;439int i;440441/* alloc some work space for all the hashes */442td = kmalloc(sizeof *td, GFP_KERNEL);443if (!td)444return -ENOMEM;445446/* get session for sealing key */447ret = osap(tb, &sess, keyauth, keytype, keyhandle);448if (ret < 0)449goto out;450dump_sess(&sess);451452/* calculate encrypted authorization value */453memcpy(td->xorwork, sess.secret, SHA1_DIGEST_SIZE);454memcpy(td->xorwork + SHA1_DIGEST_SIZE, sess.enonce, SHA1_DIGEST_SIZE);455sha1(td->xorwork, SHA1_DIGEST_SIZE * 2, td->xorhash);456457ret = tpm_get_random(chip, td->nonceodd, TPM_NONCE_SIZE);458if (ret < 0)459goto out;460461if (ret != TPM_NONCE_SIZE) {462ret = -EIO;463goto out;464}465466ordinal = htonl(TPM_ORD_SEAL);467datsize = htonl(datalen);468pcrsize = htonl(pcrinfosize);469cont = 0;470471/* encrypt data authorization key */472for (i = 0; i < SHA1_DIGEST_SIZE; ++i)473td->encauth[i] = td->xorhash[i] ^ blobauth[i];474475/* calculate authorization HMAC value */476if (pcrinfosize == 0) {477/* no pcr info specified */478ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,479sess.enonce, td->nonceodd, cont,480sizeof(uint32_t), &ordinal, SHA1_DIGEST_SIZE,481td->encauth, sizeof(uint32_t), &pcrsize,482sizeof(uint32_t), &datsize, datalen, data, 0,4830);484} else {485/* pcr info specified */486ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE,487sess.enonce, td->nonceodd, cont,488sizeof(uint32_t), &ordinal, SHA1_DIGEST_SIZE,489td->encauth, sizeof(uint32_t), &pcrsize,490pcrinfosize, pcrinfo, sizeof(uint32_t),491&datsize, datalen, data, 0, 0);492}493if (ret < 0)494goto out;495496/* build and send the TPM request packet */497tpm_buf_reset(tb, TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_SEAL);498tpm_buf_append_u32(tb, keyhandle);499tpm_buf_append(tb, td->encauth, SHA1_DIGEST_SIZE);500tpm_buf_append_u32(tb, pcrinfosize);501tpm_buf_append(tb, pcrinfo, pcrinfosize);502tpm_buf_append_u32(tb, datalen);503tpm_buf_append(tb, data, datalen);504tpm_buf_append_u32(tb, sess.handle);505tpm_buf_append(tb, td->nonceodd, TPM_NONCE_SIZE);506tpm_buf_append_u8(tb, cont);507tpm_buf_append(tb, td->pubauth, SHA1_DIGEST_SIZE);508509ret = trusted_tpm_send(tb->data, tb->length);510if (ret < 0)511goto out;512513/* calculate the size of the returned Blob */514sealinfosize = LOAD32(tb->data, TPM_DATA_OFFSET + sizeof(uint32_t));515encdatasize = LOAD32(tb->data, TPM_DATA_OFFSET + sizeof(uint32_t) +516sizeof(uint32_t) + sealinfosize);517storedsize = sizeof(uint32_t) + sizeof(uint32_t) + sealinfosize +518sizeof(uint32_t) + encdatasize;519520/* check the HMAC in the response */521ret = TSS_checkhmac1(tb->data, ordinal, td->nonceodd, sess.secret,522SHA1_DIGEST_SIZE, storedsize, TPM_DATA_OFFSET, 0,5230);524525/* copy the returned blob to caller */526if (!ret) {527memcpy(blob, tb->data + TPM_DATA_OFFSET, storedsize);528*bloblen = storedsize;529}530out:531kfree_sensitive(td);532return ret;533}534535/*536* use the AUTH2_COMMAND form of unseal, to authorize both key and blob537*/538static int tpm_unseal(struct tpm_buf *tb,539uint32_t keyhandle, const unsigned char *keyauth,540const unsigned char *blob, int bloblen,541const unsigned char *blobauth,542unsigned char *data, unsigned int *datalen)543{544unsigned char nonceodd[TPM_NONCE_SIZE];545unsigned char enonce1[TPM_NONCE_SIZE];546unsigned char enonce2[TPM_NONCE_SIZE];547unsigned char authdata1[SHA1_DIGEST_SIZE];548unsigned char authdata2[SHA1_DIGEST_SIZE];549uint32_t authhandle1 = 0;550uint32_t authhandle2 = 0;551unsigned char cont = 0;552uint32_t ordinal;553int ret;554555/* sessions for unsealing key and data */556ret = oiap(tb, &authhandle1, enonce1);557if (ret < 0) {558pr_info("oiap failed (%d)\n", ret);559return ret;560}561ret = oiap(tb, &authhandle2, enonce2);562if (ret < 0) {563pr_info("oiap failed (%d)\n", ret);564return ret;565}566567ordinal = htonl(TPM_ORD_UNSEAL);568ret = tpm_get_random(chip, nonceodd, TPM_NONCE_SIZE);569if (ret < 0)570return ret;571572if (ret != TPM_NONCE_SIZE) {573pr_info("tpm_get_random failed (%d)\n", ret);574return -EIO;575}576ret = TSS_authhmac(authdata1, keyauth, TPM_NONCE_SIZE,577enonce1, nonceodd, cont, sizeof(uint32_t),578&ordinal, bloblen, blob, 0, 0);579if (ret < 0)580return ret;581ret = TSS_authhmac(authdata2, blobauth, TPM_NONCE_SIZE,582enonce2, nonceodd, cont, sizeof(uint32_t),583&ordinal, bloblen, blob, 0, 0);584if (ret < 0)585return ret;586587/* build and send TPM request packet */588tpm_buf_reset(tb, TPM_TAG_RQU_AUTH2_COMMAND, TPM_ORD_UNSEAL);589tpm_buf_append_u32(tb, keyhandle);590tpm_buf_append(tb, blob, bloblen);591tpm_buf_append_u32(tb, authhandle1);592tpm_buf_append(tb, nonceodd, TPM_NONCE_SIZE);593tpm_buf_append_u8(tb, cont);594tpm_buf_append(tb, authdata1, SHA1_DIGEST_SIZE);595tpm_buf_append_u32(tb, authhandle2);596tpm_buf_append(tb, nonceodd, TPM_NONCE_SIZE);597tpm_buf_append_u8(tb, cont);598tpm_buf_append(tb, authdata2, SHA1_DIGEST_SIZE);599600ret = trusted_tpm_send(tb->data, tb->length);601if (ret < 0) {602pr_info("authhmac failed (%d)\n", ret);603return ret;604}605606*datalen = LOAD32(tb->data, TPM_DATA_OFFSET);607ret = TSS_checkhmac2(tb->data, ordinal, nonceodd,608keyauth, SHA1_DIGEST_SIZE,609blobauth, SHA1_DIGEST_SIZE,610sizeof(uint32_t), TPM_DATA_OFFSET,611*datalen, TPM_DATA_OFFSET + sizeof(uint32_t), 0,6120);613if (ret < 0) {614pr_info("TSS_checkhmac2 failed (%d)\n", ret);615return ret;616}617memcpy(data, tb->data + TPM_DATA_OFFSET + sizeof(uint32_t), *datalen);618return 0;619}620621/*622* Have the TPM seal(encrypt) the symmetric key623*/624static int key_seal(struct trusted_key_payload *p,625struct trusted_key_options *o)626{627struct tpm_buf tb;628int ret;629630ret = tpm_buf_init(&tb, 0, 0);631if (ret)632return ret;633634/* include migratable flag at end of sealed key */635p->key[p->key_len] = p->migratable;636637ret = tpm_seal(&tb, o->keytype, o->keyhandle, o->keyauth,638p->key, p->key_len + 1, p->blob, &p->blob_len,639o->blobauth, o->pcrinfo, o->pcrinfo_len);640if (ret < 0)641pr_info("srkseal failed (%d)\n", ret);642643tpm_buf_destroy(&tb);644return ret;645}646647/*648* Have the TPM unseal(decrypt) the symmetric key649*/650static int key_unseal(struct trusted_key_payload *p,651struct trusted_key_options *o)652{653struct tpm_buf tb;654int ret;655656ret = tpm_buf_init(&tb, 0, 0);657if (ret)658return ret;659660ret = tpm_unseal(&tb, o->keyhandle, o->keyauth, p->blob, p->blob_len,661o->blobauth, p->key, &p->key_len);662if (ret < 0)663pr_info("srkunseal failed (%d)\n", ret);664else665/* pull migratable flag out of sealed key */666p->migratable = p->key[--p->key_len];667668tpm_buf_destroy(&tb);669return ret;670}671672enum {673Opt_err,674Opt_keyhandle, Opt_keyauth, Opt_blobauth,675Opt_pcrinfo, Opt_pcrlock, Opt_migratable,676Opt_hash,677Opt_policydigest,678Opt_policyhandle,679};680681static const match_table_t key_tokens = {682{Opt_keyhandle, "keyhandle=%s"},683{Opt_keyauth, "keyauth=%s"},684{Opt_blobauth, "blobauth=%s"},685{Opt_pcrinfo, "pcrinfo=%s"},686{Opt_pcrlock, "pcrlock=%s"},687{Opt_migratable, "migratable=%s"},688{Opt_hash, "hash=%s"},689{Opt_policydigest, "policydigest=%s"},690{Opt_policyhandle, "policyhandle=%s"},691{Opt_err, NULL}692};693694/* can have zero or more token= options */695static int getoptions(char *c, struct trusted_key_payload *pay,696struct trusted_key_options *opt)697{698substring_t args[MAX_OPT_ARGS];699char *p = c;700int token;701int res;702unsigned long handle;703unsigned long lock;704unsigned long token_mask = 0;705unsigned int digest_len;706int i;707int tpm2;708709tpm2 = tpm_is_tpm2(chip);710if (tpm2 < 0)711return tpm2;712713opt->hash = tpm2 ? HASH_ALGO_SHA256 : HASH_ALGO_SHA1;714715if (!c)716return 0;717718while ((p = strsep(&c, " \t"))) {719if (*p == '\0' || *p == ' ' || *p == '\t')720continue;721token = match_token(p, key_tokens, args);722if (test_and_set_bit(token, &token_mask))723return -EINVAL;724725switch (token) {726case Opt_pcrinfo:727opt->pcrinfo_len = strlen(args[0].from) / 2;728if (opt->pcrinfo_len > MAX_PCRINFO_SIZE)729return -EINVAL;730res = hex2bin(opt->pcrinfo, args[0].from,731opt->pcrinfo_len);732if (res < 0)733return -EINVAL;734break;735case Opt_keyhandle:736res = kstrtoul(args[0].from, 16, &handle);737if (res < 0)738return -EINVAL;739opt->keytype = SEAL_keytype;740opt->keyhandle = handle;741break;742case Opt_keyauth:743if (strlen(args[0].from) != 2 * SHA1_DIGEST_SIZE)744return -EINVAL;745res = hex2bin(opt->keyauth, args[0].from,746SHA1_DIGEST_SIZE);747if (res < 0)748return -EINVAL;749break;750case Opt_blobauth:751/*752* TPM 1.2 authorizations are sha1 hashes passed in as753* hex strings. TPM 2.0 authorizations are simple754* passwords (although it can take a hash as well)755*/756opt->blobauth_len = strlen(args[0].from);757758if (opt->blobauth_len == 2 * TPM_DIGEST_SIZE) {759res = hex2bin(opt->blobauth, args[0].from,760TPM_DIGEST_SIZE);761if (res < 0)762return -EINVAL;763764opt->blobauth_len = TPM_DIGEST_SIZE;765break;766}767768if (tpm2 && opt->blobauth_len <= sizeof(opt->blobauth)) {769memcpy(opt->blobauth, args[0].from,770opt->blobauth_len);771break;772}773774return -EINVAL;775776break;777778case Opt_migratable:779if (*args[0].from == '0')780pay->migratable = 0;781else if (*args[0].from != '1')782return -EINVAL;783break;784case Opt_pcrlock:785res = kstrtoul(args[0].from, 10, &lock);786if (res < 0)787return -EINVAL;788opt->pcrlock = lock;789break;790case Opt_hash:791if (test_bit(Opt_policydigest, &token_mask))792return -EINVAL;793for (i = 0; i < HASH_ALGO__LAST; i++) {794if (!strcmp(args[0].from, hash_algo_name[i])) {795opt->hash = i;796break;797}798}799if (i == HASH_ALGO__LAST)800return -EINVAL;801if (!tpm2 && i != HASH_ALGO_SHA1) {802pr_info("TPM 1.x only supports SHA-1.\n");803return -EINVAL;804}805break;806case Opt_policydigest:807digest_len = hash_digest_size[opt->hash];808if (!tpm2 || strlen(args[0].from) != (2 * digest_len))809return -EINVAL;810res = hex2bin(opt->policydigest, args[0].from,811digest_len);812if (res < 0)813return -EINVAL;814opt->policydigest_len = digest_len;815break;816case Opt_policyhandle:817if (!tpm2)818return -EINVAL;819res = kstrtoul(args[0].from, 16, &handle);820if (res < 0)821return -EINVAL;822opt->policyhandle = handle;823break;824default:825return -EINVAL;826}827}828return 0;829}830831static struct trusted_key_options *trusted_options_alloc(void)832{833struct trusted_key_options *options;834int tpm2;835836tpm2 = tpm_is_tpm2(chip);837if (tpm2 < 0)838return NULL;839840options = kzalloc(sizeof *options, GFP_KERNEL);841if (options) {842/* set any non-zero defaults */843options->keytype = SRK_keytype;844845if (!tpm2)846options->keyhandle = SRKHANDLE;847}848return options;849}850851static int trusted_tpm_seal(struct trusted_key_payload *p, char *datablob)852{853struct trusted_key_options *options = NULL;854int ret = 0;855int tpm2;856857tpm2 = tpm_is_tpm2(chip);858if (tpm2 < 0)859return tpm2;860861options = trusted_options_alloc();862if (!options)863return -ENOMEM;864865ret = getoptions(datablob, p, options);866if (ret < 0)867goto out;868dump_options(options);869870if (!options->keyhandle && !tpm2) {871ret = -EINVAL;872goto out;873}874875if (tpm2)876ret = tpm2_seal_trusted(chip, p, options);877else878ret = key_seal(p, options);879if (ret < 0) {880pr_info("key_seal failed (%d)\n", ret);881goto out;882}883884if (options->pcrlock) {885ret = pcrlock(options->pcrlock);886if (ret < 0) {887pr_info("pcrlock failed (%d)\n", ret);888goto out;889}890}891out:892kfree_sensitive(options);893return ret;894}895896static int trusted_tpm_unseal(struct trusted_key_payload *p, char *datablob)897{898struct trusted_key_options *options = NULL;899int ret = 0;900int tpm2;901902tpm2 = tpm_is_tpm2(chip);903if (tpm2 < 0)904return tpm2;905906options = trusted_options_alloc();907if (!options)908return -ENOMEM;909910ret = getoptions(datablob, p, options);911if (ret < 0)912goto out;913dump_options(options);914915if (!options->keyhandle && !tpm2) {916ret = -EINVAL;917goto out;918}919920if (tpm2)921ret = tpm2_unseal_trusted(chip, p, options);922else923ret = key_unseal(p, options);924if (ret < 0)925pr_info("key_unseal failed (%d)\n", ret);926927if (options->pcrlock) {928ret = pcrlock(options->pcrlock);929if (ret < 0) {930pr_info("pcrlock failed (%d)\n", ret);931goto out;932}933}934out:935kfree_sensitive(options);936return ret;937}938939static int trusted_tpm_get_random(unsigned char *key, size_t key_len)940{941return tpm_get_random(chip, key, key_len);942}943944static int __init init_digests(void)945{946int i;947948digests = kcalloc(chip->nr_allocated_banks, sizeof(*digests),949GFP_KERNEL);950if (!digests)951return -ENOMEM;952953for (i = 0; i < chip->nr_allocated_banks; i++)954digests[i].alg_id = chip->allocated_banks[i].alg_id;955956return 0;957}958959static int __init trusted_tpm_init(void)960{961int ret;962963chip = tpm_default_chip();964if (!chip)965return -ENODEV;966967ret = init_digests();968if (ret < 0)969goto err_put;970ret = register_key_type(&key_type_trusted);971if (ret < 0)972goto err_free;973return 0;974err_free:975kfree(digests);976err_put:977put_device(&chip->dev);978return ret;979}980981static void trusted_tpm_exit(void)982{983if (chip) {984put_device(&chip->dev);985kfree(digests);986unregister_key_type(&key_type_trusted);987}988}989990struct trusted_key_ops trusted_key_tpm_ops = {991.migratable = 1, /* migratable by default */992.init = trusted_tpm_init,993.seal = trusted_tpm_seal,994.unseal = trusted_tpm_unseal,995.get_random = trusted_tpm_get_random,996.exit = trusted_tpm_exit,997};9989991000