0001
0002
0003
0004
0005
0006
0007
0008 #define pr_fmt(fmt) "PKCS8: "fmt
0009 #include <linux/module.h>
0010 #include <linux/kernel.h>
0011 #include <linux/export.h>
0012 #include <linux/slab.h>
0013 #include <linux/err.h>
0014 #include <linux/oid_registry.h>
0015 #include <keys/asymmetric-subtype.h>
0016 #include <keys/asymmetric-parser.h>
0017 #include <crypto/public_key.h>
0018 #include "pkcs8.asn1.h"
0019
0020 struct pkcs8_parse_context {
0021 struct public_key *pub;
0022 unsigned long data;
0023 enum OID last_oid;
0024 enum OID algo_oid;
0025 u32 key_size;
0026 const void *key;
0027 };
0028
0029
0030
0031
0032
0033 int pkcs8_note_OID(void *context, size_t hdrlen,
0034 unsigned char tag,
0035 const void *value, size_t vlen)
0036 {
0037 struct pkcs8_parse_context *ctx = context;
0038
0039 ctx->last_oid = look_up_OID(value, vlen);
0040 if (ctx->last_oid == OID__NR) {
0041 char buffer[50];
0042
0043 sprint_oid(value, vlen, buffer, sizeof(buffer));
0044 pr_info("Unknown OID: [%lu] %s\n",
0045 (unsigned long)value - ctx->data, buffer);
0046 }
0047 return 0;
0048 }
0049
0050
0051
0052
0053 int pkcs8_note_version(void *context, size_t hdrlen,
0054 unsigned char tag,
0055 const void *value, size_t vlen)
0056 {
0057 if (vlen != 1 || ((const u8 *)value)[0] != 0) {
0058 pr_warn("Unsupported PKCS#8 version\n");
0059 return -EBADMSG;
0060 }
0061 return 0;
0062 }
0063
0064
0065
0066
0067 int pkcs8_note_algo(void *context, size_t hdrlen,
0068 unsigned char tag,
0069 const void *value, size_t vlen)
0070 {
0071 struct pkcs8_parse_context *ctx = context;
0072
0073 if (ctx->last_oid != OID_rsaEncryption)
0074 return -ENOPKG;
0075
0076 ctx->pub->pkey_algo = "rsa";
0077 return 0;
0078 }
0079
0080
0081
0082
0083 int pkcs8_note_key(void *context, size_t hdrlen,
0084 unsigned char tag,
0085 const void *value, size_t vlen)
0086 {
0087 struct pkcs8_parse_context *ctx = context;
0088
0089 ctx->key = value;
0090 ctx->key_size = vlen;
0091 return 0;
0092 }
0093
0094
0095
0096
0097 static struct public_key *pkcs8_parse(const void *data, size_t datalen)
0098 {
0099 struct pkcs8_parse_context ctx;
0100 struct public_key *pub;
0101 long ret;
0102
0103 memset(&ctx, 0, sizeof(ctx));
0104
0105 ret = -ENOMEM;
0106 ctx.pub = kzalloc(sizeof(struct public_key), GFP_KERNEL);
0107 if (!ctx.pub)
0108 goto error;
0109
0110 ctx.data = (unsigned long)data;
0111
0112
0113 ret = asn1_ber_decoder(&pkcs8_decoder, &ctx, data, datalen);
0114 if (ret < 0)
0115 goto error_decode;
0116
0117 ret = -ENOMEM;
0118 pub = ctx.pub;
0119 pub->key = kmemdup(ctx.key, ctx.key_size, GFP_KERNEL);
0120 if (!pub->key)
0121 goto error_decode;
0122
0123 pub->keylen = ctx.key_size;
0124 pub->key_is_private = true;
0125 return pub;
0126
0127 error_decode:
0128 kfree(ctx.pub);
0129 error:
0130 return ERR_PTR(ret);
0131 }
0132
0133
0134
0135
0136 static int pkcs8_key_preparse(struct key_preparsed_payload *prep)
0137 {
0138 struct public_key *pub;
0139
0140 pub = pkcs8_parse(prep->data, prep->datalen);
0141 if (IS_ERR(pub))
0142 return PTR_ERR(pub);
0143
0144 pr_devel("Cert Key Algo: %s\n", pub->pkey_algo);
0145 pub->id_type = "PKCS8";
0146
0147
0148 __module_get(public_key_subtype.owner);
0149 prep->payload.data[asym_subtype] = &public_key_subtype;
0150 prep->payload.data[asym_key_ids] = NULL;
0151 prep->payload.data[asym_crypto] = pub;
0152 prep->payload.data[asym_auth] = NULL;
0153 prep->quotalen = 100;
0154 return 0;
0155 }
0156
0157 static struct asymmetric_key_parser pkcs8_key_parser = {
0158 .owner = THIS_MODULE,
0159 .name = "pkcs8",
0160 .parse = pkcs8_key_preparse,
0161 };
0162
0163
0164
0165
0166 static int __init pkcs8_key_init(void)
0167 {
0168 return register_asymmetric_key_parser(&pkcs8_key_parser);
0169 }
0170
0171 static void __exit pkcs8_key_exit(void)
0172 {
0173 unregister_asymmetric_key_parser(&pkcs8_key_parser);
0174 }
0175
0176 module_init(pkcs8_key_init);
0177 module_exit(pkcs8_key_exit);
0178
0179 MODULE_DESCRIPTION("PKCS#8 certificate parser");
0180 MODULE_LICENSE("GPL");