root/crypto/asymmetric_keys/pkcs8_parser.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pkcs8_note_OID
  2. pkcs8_note_version
  3. pkcs8_note_algo
  4. pkcs8_note_key
  5. pkcs8_parse
  6. pkcs8_key_preparse
  7. pkcs8_key_init
  8. pkcs8_key_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /* PKCS#8 Private Key parser [RFC 5208].
   3  *
   4  * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved.
   5  * Written by David Howells (dhowells@redhat.com)
   6  */
   7 
   8 #define pr_fmt(fmt) "PKCS8: "fmt
   9 #include <linux/module.h>
  10 #include <linux/kernel.h>
  11 #include <linux/export.h>
  12 #include <linux/slab.h>
  13 #include <linux/err.h>
  14 #include <linux/oid_registry.h>
  15 #include <keys/asymmetric-subtype.h>
  16 #include <keys/asymmetric-parser.h>
  17 #include <crypto/public_key.h>
  18 #include "pkcs8.asn1.h"
  19 
  20 struct pkcs8_parse_context {
  21         struct public_key *pub;
  22         unsigned long   data;                   /* Start of data */
  23         enum OID        last_oid;               /* Last OID encountered */
  24         enum OID        algo_oid;               /* Algorithm OID */
  25         u32             key_size;
  26         const void      *key;
  27 };
  28 
  29 /*
  30  * Note an OID when we find one for later processing when we know how to
  31  * interpret it.
  32  */
  33 int pkcs8_note_OID(void *context, size_t hdrlen,
  34                    unsigned char tag,
  35                    const void *value, size_t vlen)
  36 {
  37         struct pkcs8_parse_context *ctx = context;
  38 
  39         ctx->last_oid = look_up_OID(value, vlen);
  40         if (ctx->last_oid == OID__NR) {
  41                 char buffer[50];
  42 
  43                 sprint_oid(value, vlen, buffer, sizeof(buffer));
  44                 pr_info("Unknown OID: [%lu] %s\n",
  45                         (unsigned long)value - ctx->data, buffer);
  46         }
  47         return 0;
  48 }
  49 
  50 /*
  51  * Note the version number of the ASN.1 blob.
  52  */
  53 int pkcs8_note_version(void *context, size_t hdrlen,
  54                        unsigned char tag,
  55                        const void *value, size_t vlen)
  56 {
  57         if (vlen != 1 || ((const u8 *)value)[0] != 0) {
  58                 pr_warn("Unsupported PKCS#8 version\n");
  59                 return -EBADMSG;
  60         }
  61         return 0;
  62 }
  63 
  64 /*
  65  * Note the public algorithm.
  66  */
  67 int pkcs8_note_algo(void *context, size_t hdrlen,
  68                     unsigned char tag,
  69                     const void *value, size_t vlen)
  70 {
  71         struct pkcs8_parse_context *ctx = context;
  72 
  73         if (ctx->last_oid != OID_rsaEncryption)
  74                 return -ENOPKG;
  75 
  76         ctx->pub->pkey_algo = "rsa";
  77         return 0;
  78 }
  79 
  80 /*
  81  * Note the key data of the ASN.1 blob.
  82  */
  83 int pkcs8_note_key(void *context, size_t hdrlen,
  84                    unsigned char tag,
  85                    const void *value, size_t vlen)
  86 {
  87         struct pkcs8_parse_context *ctx = context;
  88 
  89         ctx->key = value;
  90         ctx->key_size = vlen;
  91         return 0;
  92 }
  93 
  94 /*
  95  * Parse a PKCS#8 private key blob.
  96  */
  97 static struct public_key *pkcs8_parse(const void *data, size_t datalen)
  98 {
  99         struct pkcs8_parse_context ctx;
 100         struct public_key *pub;
 101         long ret;
 102 
 103         memset(&ctx, 0, sizeof(ctx));
 104 
 105         ret = -ENOMEM;
 106         ctx.pub = kzalloc(sizeof(struct public_key), GFP_KERNEL);
 107         if (!ctx.pub)
 108                 goto error;
 109 
 110         ctx.data = (unsigned long)data;
 111 
 112         /* Attempt to decode the private key */
 113         ret = asn1_ber_decoder(&pkcs8_decoder, &ctx, data, datalen);
 114         if (ret < 0)
 115                 goto error_decode;
 116 
 117         ret = -ENOMEM;
 118         pub = ctx.pub;
 119         pub->key = kmemdup(ctx.key, ctx.key_size, GFP_KERNEL);
 120         if (!pub->key)
 121                 goto error_decode;
 122 
 123         pub->keylen = ctx.key_size;
 124         pub->key_is_private = true;
 125         return pub;
 126 
 127 error_decode:
 128         kfree(ctx.pub);
 129 error:
 130         return ERR_PTR(ret);
 131 }
 132 
 133 /*
 134  * Attempt to parse a data blob for a key as a PKCS#8 private key.
 135  */
 136 static int pkcs8_key_preparse(struct key_preparsed_payload *prep)
 137 {
 138         struct public_key *pub;
 139 
 140         pub = pkcs8_parse(prep->data, prep->datalen);
 141         if (IS_ERR(pub))
 142                 return PTR_ERR(pub);
 143 
 144         pr_devel("Cert Key Algo: %s\n", pub->pkey_algo);
 145         pub->id_type = "PKCS8";
 146 
 147         /* We're pinning the module by being linked against it */
 148         __module_get(public_key_subtype.owner);
 149         prep->payload.data[asym_subtype] = &public_key_subtype;
 150         prep->payload.data[asym_key_ids] = NULL;
 151         prep->payload.data[asym_crypto] = pub;
 152         prep->payload.data[asym_auth] = NULL;
 153         prep->quotalen = 100;
 154         return 0;
 155 }
 156 
 157 static struct asymmetric_key_parser pkcs8_key_parser = {
 158         .owner  = THIS_MODULE,
 159         .name   = "pkcs8",
 160         .parse  = pkcs8_key_preparse,
 161 };
 162 
 163 /*
 164  * Module stuff
 165  */
 166 static int __init pkcs8_key_init(void)
 167 {
 168         return register_asymmetric_key_parser(&pkcs8_key_parser);
 169 }
 170 
 171 static void __exit pkcs8_key_exit(void)
 172 {
 173         unregister_asymmetric_key_parser(&pkcs8_key_parser);
 174 }
 175 
 176 module_init(pkcs8_key_init);
 177 module_exit(pkcs8_key_exit);
 178 
 179 MODULE_DESCRIPTION("PKCS#8 certificate parser");
 180 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */