Path: blob/master/crypto/asymmetric_keys/pkcs8_parser.c
26282 views
// SPDX-License-Identifier: GPL-2.0-or-later1/* PKCS#8 Private Key parser [RFC 5208].2*3* Copyright (C) 2016 Red Hat, Inc. All Rights Reserved.4* Written by David Howells ([email protected])5*/67#define pr_fmt(fmt) "PKCS8: "fmt8#include <linux/module.h>9#include <linux/kernel.h>10#include <linux/export.h>11#include <linux/slab.h>12#include <linux/err.h>13#include <linux/oid_registry.h>14#include <keys/asymmetric-subtype.h>15#include <keys/asymmetric-parser.h>16#include <crypto/public_key.h>17#include "pkcs8.asn1.h"1819struct pkcs8_parse_context {20struct public_key *pub;21unsigned long data; /* Start of data */22enum OID last_oid; /* Last OID encountered */23enum OID algo_oid; /* Algorithm OID */24u32 key_size;25const void *key;26};2728/*29* Note an OID when we find one for later processing when we know how to30* interpret it.31*/32int pkcs8_note_OID(void *context, size_t hdrlen,33unsigned char tag,34const void *value, size_t vlen)35{36struct pkcs8_parse_context *ctx = context;3738ctx->last_oid = look_up_OID(value, vlen);39if (ctx->last_oid == OID__NR) {40char buffer[50];4142sprint_oid(value, vlen, buffer, sizeof(buffer));43pr_info("Unknown OID: [%lu] %s\n",44(unsigned long)value - ctx->data, buffer);45}46return 0;47}4849/*50* Note the version number of the ASN.1 blob.51*/52int pkcs8_note_version(void *context, size_t hdrlen,53unsigned char tag,54const void *value, size_t vlen)55{56if (vlen != 1 || ((const u8 *)value)[0] != 0) {57pr_warn("Unsupported PKCS#8 version\n");58return -EBADMSG;59}60return 0;61}6263/*64* Note the public algorithm.65*/66int pkcs8_note_algo(void *context, size_t hdrlen,67unsigned char tag,68const void *value, size_t vlen)69{70struct pkcs8_parse_context *ctx = context;7172if (ctx->last_oid != OID_rsaEncryption)73return -ENOPKG;7475ctx->pub->pkey_algo = "rsa";76return 0;77}7879/*80* Note the key data of the ASN.1 blob.81*/82int pkcs8_note_key(void *context, size_t hdrlen,83unsigned char tag,84const void *value, size_t vlen)85{86struct pkcs8_parse_context *ctx = context;8788ctx->key = value;89ctx->key_size = vlen;90return 0;91}9293/*94* Parse a PKCS#8 private key blob.95*/96static struct public_key *pkcs8_parse(const void *data, size_t datalen)97{98struct pkcs8_parse_context ctx;99struct public_key *pub;100long ret;101102memset(&ctx, 0, sizeof(ctx));103104ret = -ENOMEM;105ctx.pub = kzalloc(sizeof(struct public_key), GFP_KERNEL);106if (!ctx.pub)107goto error;108109ctx.data = (unsigned long)data;110111/* Attempt to decode the private key */112ret = asn1_ber_decoder(&pkcs8_decoder, &ctx, data, datalen);113if (ret < 0)114goto error_decode;115116ret = -ENOMEM;117pub = ctx.pub;118pub->key = kmemdup(ctx.key, ctx.key_size, GFP_KERNEL);119if (!pub->key)120goto error_decode;121122pub->keylen = ctx.key_size;123pub->key_is_private = true;124return pub;125126error_decode:127kfree(ctx.pub);128error:129return ERR_PTR(ret);130}131132/*133* Attempt to parse a data blob for a key as a PKCS#8 private key.134*/135static int pkcs8_key_preparse(struct key_preparsed_payload *prep)136{137struct public_key *pub;138139pub = pkcs8_parse(prep->data, prep->datalen);140if (IS_ERR(pub))141return PTR_ERR(pub);142143pr_devel("Cert Key Algo: %s\n", pub->pkey_algo);144pub->id_type = "PKCS8";145146/* We're pinning the module by being linked against it */147__module_get(public_key_subtype.owner);148prep->payload.data[asym_subtype] = &public_key_subtype;149prep->payload.data[asym_key_ids] = NULL;150prep->payload.data[asym_crypto] = pub;151prep->payload.data[asym_auth] = NULL;152prep->quotalen = 100;153return 0;154}155156static struct asymmetric_key_parser pkcs8_key_parser = {157.owner = THIS_MODULE,158.name = "pkcs8",159.parse = pkcs8_key_preparse,160};161162/*163* Module stuff164*/165static int __init pkcs8_key_init(void)166{167return register_asymmetric_key_parser(&pkcs8_key_parser);168}169170static void __exit pkcs8_key_exit(void)171{172unregister_asymmetric_key_parser(&pkcs8_key_parser);173}174175module_init(pkcs8_key_init);176module_exit(pkcs8_key_exit);177178MODULE_DESCRIPTION("PKCS#8 certificate parser");179MODULE_LICENSE("GPL");180181182