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