diff --git a/security/keys/trusted_defined.c b/security/keys/trusted_defined.c index aaaa069967a6..3dc3db15b5d9 100644 --- a/security/keys/trusted_defined.c +++ b/security/keys/trusted_defined.c @@ -108,7 +108,8 @@ static int TSS_rawhmac(unsigned char *digest, const unsigned char *key, goto out; } va_end(argp); - ret = crypto_shash_final(&sdesc->shash, digest); + if (!ret) + ret = crypto_shash_final(&sdesc->shash, digest); out: kfree(sdesc); return ret; @@ -117,9 +118,9 @@ static int TSS_rawhmac(unsigned char *digest, const unsigned char *key, /* * calculate authorization info fields to send to TPM */ -static uint32_t TSS_authhmac(unsigned char *digest, const unsigned char *key, - const unsigned int keylen, unsigned char *h1, - unsigned char *h2, unsigned char h3, ...) +static int TSS_authhmac(unsigned char *digest, const unsigned char *key, + const unsigned int keylen, unsigned char *h1, + unsigned char *h2, unsigned char h3, ...) { unsigned char paramdigest[SHA1_DIGEST_SIZE]; struct sdesc *sdesc; @@ -146,15 +147,17 @@ static uint32_t TSS_authhmac(unsigned char *digest, const unsigned char *key, break; data = va_arg(argp, unsigned char *); ret = crypto_shash_update(&sdesc->shash, data, dlen); - if (ret < 0) + if (ret < 0) { + va_end(argp); goto out; + } } va_end(argp); ret = crypto_shash_final(&sdesc->shash, paramdigest); if (!ret) - TSS_rawhmac(digest, key, keylen, SHA1_DIGEST_SIZE, - paramdigest, TPM_NONCE_SIZE, h1, - TPM_NONCE_SIZE, h2, 1, &c, 0, 0); + ret = TSS_rawhmac(digest, key, keylen, SHA1_DIGEST_SIZE, + paramdigest, TPM_NONCE_SIZE, h1, + TPM_NONCE_SIZE, h2, 1, &c, 0, 0); out: kfree(sdesc); return ret; @@ -163,11 +166,11 @@ static uint32_t TSS_authhmac(unsigned char *digest, const unsigned char *key, /* * verify the AUTH1_COMMAND (Seal) result from TPM */ -static uint32_t TSS_checkhmac1(unsigned char *buffer, - const uint32_t command, - const unsigned char *ononce, - const unsigned char *key, - const unsigned int keylen, ...) +static int TSS_checkhmac1(unsigned char *buffer, + const uint32_t command, + const unsigned char *ononce, + const unsigned char *key, + const unsigned int keylen, ...) { uint32_t bufsize; uint16_t tag; @@ -219,18 +222,22 @@ static uint32_t TSS_checkhmac1(unsigned char *buffer, break; dpos = va_arg(argp, unsigned int); ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen); - if (ret < 0) + if (ret < 0) { + va_end(argp); goto out; + } } va_end(argp); ret = crypto_shash_final(&sdesc->shash, paramdigest); if (ret < 0) goto out; + ret = TSS_rawhmac(testhmac, key, keylen, SHA1_DIGEST_SIZE, paramdigest, TPM_NONCE_SIZE, enonce, TPM_NONCE_SIZE, ononce, 1, continueflag, 0, 0); if (ret < 0) goto out; + if (memcmp(testhmac, authdata, SHA1_DIGEST_SIZE)) ret = -EINVAL; out: @@ -241,13 +248,13 @@ static uint32_t TSS_checkhmac1(unsigned char *buffer, /* * verify the AUTH2_COMMAND (unseal) result from TPM */ -static uint32_t TSS_checkhmac2(unsigned char *buffer, - const uint32_t command, - const unsigned char *ononce, - const unsigned char *key1, - const unsigned int keylen1, - const unsigned char *key2, - const unsigned int keylen2, ...) +static int TSS_checkhmac2(unsigned char *buffer, + const uint32_t command, + const unsigned char *ononce, + const unsigned char *key1, + const unsigned int keylen1, + const unsigned char *key2, + const unsigned int keylen2, ...) { uint32_t bufsize; uint16_t tag; @@ -309,9 +316,12 @@ static uint32_t TSS_checkhmac2(unsigned char *buffer, break; dpos = va_arg(argp, unsigned int); ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen); - if (ret < 0) + if (ret < 0) { + va_end(argp); goto out; + } } + va_end(argp); ret = crypto_shash_final(&sdesc->shash, paramdigest); if (ret < 0) goto out; @@ -319,6 +329,8 @@ static uint32_t TSS_checkhmac2(unsigned char *buffer, ret = TSS_rawhmac(testhmac1, key1, keylen1, SHA1_DIGEST_SIZE, paramdigest, TPM_NONCE_SIZE, enonce1, TPM_NONCE_SIZE, ononce, 1, continueflag1, 0, 0); + if (ret < 0) + goto out; if (memcmp(testhmac1, authdata1, SHA1_DIGEST_SIZE)) { ret = -EINVAL; goto out; @@ -326,6 +338,8 @@ static uint32_t TSS_checkhmac2(unsigned char *buffer, ret = TSS_rawhmac(testhmac2, key2, keylen2, SHA1_DIGEST_SIZE, paramdigest, TPM_NONCE_SIZE, enonce2, TPM_NONCE_SIZE, ononce, 1, continueflag2, 0, 0); + if (ret < 0) + goto out; if (memcmp(testhmac2, authdata2, SHA1_DIGEST_SIZE)) ret = -EINVAL; out: @@ -364,8 +378,8 @@ static int tpm_get_random(struct tpm_buf *tb, unsigned char *buf, uint32_t len) store32(tb, TPM_ORD_GETRANDOM); store32(tb, len); ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, sizeof tb->data); - memcpy(buf, tb->data + TPM_GETRANDOM_SIZE, len); - + if (!ret) + memcpy(buf, tb->data + TPM_GETRANDOM_SIZE, len); return ret; } @@ -392,10 +406,13 @@ static int my_get_random(unsigned char *buf, int len) static int pcrlock(const int pcrnum) { unsigned char hash[SHA1_DIGEST_SIZE]; + int ret; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - my_get_random(hash, SHA1_DIGEST_SIZE); + ret = my_get_random(hash, SHA1_DIGEST_SIZE); + if (ret < 0) + return ret; return tpm_pcr_extend(TPM_ANY_NUM, pcrnum, hash) ? -EINVAL : 0; } @@ -431,9 +448,8 @@ static int osap(struct tpm_buf *tb, struct osapsess *s, TPM_NONCE_SIZE); memcpy(enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t) + TPM_NONCE_SIZE]), TPM_NONCE_SIZE); - ret = TSS_rawhmac(s->secret, key, SHA1_DIGEST_SIZE, TPM_NONCE_SIZE, - enonce, TPM_NONCE_SIZE, ononce, 0, 0); - return ret; + return TSS_rawhmac(s->secret, key, SHA1_DIGEST_SIZE, TPM_NONCE_SIZE, + enonce, TPM_NONCE_SIZE, ononce, 0, 0); } /* @@ -454,7 +470,7 @@ static int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce) *handle = LOAD32(tb->data, TPM_DATA_OFFSET); memcpy(nonce, &tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)], TPM_NONCE_SIZE); - return ret; + return 0; } struct tpm_digests { @@ -521,20 +537,23 @@ static int tpm_seal(struct tpm_buf *tb, const uint16_t keytype, /* calculate authorization HMAC value */ if (pcrinfosize == 0) { /* no pcr info specified */ - TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE, - sess.enonce, td->nonceodd, cont, sizeof(uint32_t), - &ordinal, SHA1_DIGEST_SIZE, td->encauth, - sizeof(uint32_t), &pcrsize, sizeof(uint32_t), - &datsize, datalen, data, 0, 0); + ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE, + sess.enonce, td->nonceodd, cont, + sizeof(uint32_t), &ordinal, SHA1_DIGEST_SIZE, + td->encauth, sizeof(uint32_t), &pcrsize, + sizeof(uint32_t), &datsize, datalen, data, 0, + 0); } else { /* pcr info specified */ - TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE, - sess.enonce, td->nonceodd, cont, sizeof(uint32_t), - &ordinal, SHA1_DIGEST_SIZE, td->encauth, - sizeof(uint32_t), &pcrsize, pcrinfosize, - pcrinfo, sizeof(uint32_t), &datsize, datalen, - data, 0, 0); + ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE, + sess.enonce, td->nonceodd, cont, + sizeof(uint32_t), &ordinal, SHA1_DIGEST_SIZE, + td->encauth, sizeof(uint32_t), &pcrsize, + pcrinfosize, pcrinfo, sizeof(uint32_t), + &datsize, datalen, data, 0, 0); } + if (ret < 0) + return ret; /* build and send the TPM request packet */ INIT_BUF(tb); @@ -569,8 +588,10 @@ static int tpm_seal(struct tpm_buf *tb, const uint16_t keytype, 0); /* copy the returned blob to caller */ - memcpy(blob, tb->data + TPM_DATA_OFFSET, storedsize); - *bloblen = storedsize; + if (!ret) { + memcpy(blob, tb->data + TPM_DATA_OFFSET, storedsize); + *bloblen = storedsize; + } return ret; } @@ -614,12 +635,16 @@ static int tpm_unseal(struct tpm_buf *tb, pr_info("trusted_key: tpm_get_random failed (%d)\n", ret); return ret; } - TSS_authhmac(authdata1, keyauth, TPM_NONCE_SIZE, - enonce1, nonceodd, cont, sizeof(uint32_t), - &ordinal, bloblen, blob, 0, 0); - TSS_authhmac(authdata2, blobauth, TPM_NONCE_SIZE, - enonce2, nonceodd, cont, sizeof(uint32_t), - &ordinal, bloblen, blob, 0, 0); + ret = TSS_authhmac(authdata1, keyauth, TPM_NONCE_SIZE, + enonce1, nonceodd, cont, sizeof(uint32_t), + &ordinal, bloblen, blob, 0, 0); + if (ret < 0) + return ret; + ret = TSS_authhmac(authdata2, blobauth, TPM_NONCE_SIZE, + enonce2, nonceodd, cont, sizeof(uint32_t), + &ordinal, bloblen, blob, 0, 0); + if (ret < 0) + return ret; /* build and send TPM request packet */ INIT_BUF(tb); @@ -650,10 +675,12 @@ static int tpm_unseal(struct tpm_buf *tb, sizeof(uint32_t), TPM_DATA_OFFSET, *datalen, TPM_DATA_OFFSET + sizeof(uint32_t), 0, 0); - if (ret < 0) + if (ret < 0) { pr_info("trusted_key: TSS_checkhmac2 failed (%d)\n", ret); + return ret; + } memcpy(data, tb->data + TPM_DATA_OFFSET + sizeof(uint32_t), *datalen); - return ret; + return 0; } /* @@ -697,11 +724,11 @@ static int key_unseal(struct trusted_key_payload *p, ret = tpm_unseal(tb, o->keyhandle, o->keyauth, p->blob, p->blob_len, o->blobauth, p->key, &p->key_len); - /* pull migratable flag out of sealed key */ - p->migratable = p->key[--p->key_len]; - if (ret < 0) pr_info("trusted_key: srkunseal failed (%d)\n", ret); + else + /* pull migratable flag out of sealed key */ + p->migratable = p->key[--p->key_len]; kfree(tb); return ret; @@ -854,12 +881,11 @@ static struct trusted_key_options *trusted_options_alloc(void) struct trusted_key_options *options; options = kzalloc(sizeof *options, GFP_KERNEL); - if (!options) - return options; - - /* set any non-zero defaults */ - options->keytype = SRK_keytype; - options->keyhandle = SRKHANDLE; + if (options) { + /* set any non-zero defaults */ + options->keytype = SRK_keytype; + options->keyhandle = SRKHANDLE; + } return options; } @@ -872,9 +898,8 @@ static struct trusted_key_payload *trusted_payload_alloc(struct key *key) if (ret < 0) return p; p = kzalloc(sizeof *p, GFP_KERNEL); - - /* migratable by default */ - p->migratable = 1; + if (p) + p->migratable = 1; /* migratable by default */ return p; }