linux/crypto/asymmetric_keys/tpm_parser.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#define pr_fmt(fmt) "TPM-PARSER: "fmt
   3#include <linux/module.h>
   4#include <linux/kernel.h>
   5#include <linux/export.h>
   6#include <linux/slab.h>
   7#include <linux/err.h>
   8#include <keys/asymmetric-subtype.h>
   9#include <keys/asymmetric-parser.h>
  10#include <crypto/asym_tpm_subtype.h>
  11#include "tpm.asn1.h"
  12
  13struct tpm_parse_context {
  14        const void      *blob;
  15        u32             blob_len;
  16};
  17
  18/*
  19 * Note the key data of the ASN.1 blob.
  20 */
  21int tpm_note_key(void *context, size_t hdrlen,
  22                   unsigned char tag,
  23                   const void *value, size_t vlen)
  24{
  25        struct tpm_parse_context *ctx = context;
  26
  27        ctx->blob = value;
  28        ctx->blob_len = vlen;
  29
  30        return 0;
  31}
  32
  33/*
  34 * Parse a TPM-encrypted private key blob.
  35 */
  36static struct tpm_key *tpm_parse(const void *data, size_t datalen)
  37{
  38        struct tpm_parse_context ctx;
  39        long ret;
  40
  41        memset(&ctx, 0, sizeof(ctx));
  42
  43        /* Attempt to decode the private key */
  44        ret = asn1_ber_decoder(&tpm_decoder, &ctx, data, datalen);
  45        if (ret < 0)
  46                goto error;
  47
  48        return tpm_key_create(ctx.blob, ctx.blob_len);
  49
  50error:
  51        return ERR_PTR(ret);
  52}
  53/*
  54 * Attempt to parse a data blob for a key as a TPM private key blob.
  55 */
  56static int tpm_key_preparse(struct key_preparsed_payload *prep)
  57{
  58        struct tpm_key *tk;
  59
  60        /*
  61         * TPM 1.2 keys are max 2048 bits long, so assume the blob is no
  62         * more than 4x that
  63         */
  64        if (prep->datalen > 256 * 4)
  65                return -EMSGSIZE;
  66
  67        tk = tpm_parse(prep->data, prep->datalen);
  68
  69        if (IS_ERR(tk))
  70                return PTR_ERR(tk);
  71
  72        /* We're pinning the module by being linked against it */
  73        __module_get(asym_tpm_subtype.owner);
  74        prep->payload.data[asym_subtype] = &asym_tpm_subtype;
  75        prep->payload.data[asym_key_ids] = NULL;
  76        prep->payload.data[asym_crypto] = tk;
  77        prep->payload.data[asym_auth] = NULL;
  78        prep->quotalen = 100;
  79        return 0;
  80}
  81
  82static struct asymmetric_key_parser tpm_key_parser = {
  83        .owner  = THIS_MODULE,
  84        .name   = "tpm_parser",
  85        .parse  = tpm_key_preparse,
  86};
  87
  88static int __init tpm_key_init(void)
  89{
  90        return register_asymmetric_key_parser(&tpm_key_parser);
  91}
  92
  93static void __exit tpm_key_exit(void)
  94{
  95        unregister_asymmetric_key_parser(&tpm_key_parser);
  96}
  97
  98module_init(tpm_key_init);
  99module_exit(tpm_key_exit);
 100
 101MODULE_DESCRIPTION("TPM private key-blob parser");
 102MODULE_LICENSE("GPL v2");
 103