1c26fd69fSDavid Howells /* Instantiate a public key crypto key from an X.509 Certificate 2c26fd69fSDavid Howells * 3c26fd69fSDavid Howells * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 4c26fd69fSDavid Howells * Written by David Howells (dhowells@redhat.com) 5c26fd69fSDavid Howells * 6c26fd69fSDavid Howells * This program is free software; you can redistribute it and/or 7c26fd69fSDavid Howells * modify it under the terms of the GNU General Public Licence 8c26fd69fSDavid Howells * as published by the Free Software Foundation; either version 9c26fd69fSDavid Howells * 2 of the Licence, or (at your option) any later version. 10c26fd69fSDavid Howells */ 11c26fd69fSDavid Howells 12c26fd69fSDavid Howells #define pr_fmt(fmt) "X.509: "fmt 13c26fd69fSDavid Howells #include <linux/module.h> 14c26fd69fSDavid Howells #include <linux/kernel.h> 15c26fd69fSDavid Howells #include <linux/slab.h> 16c26fd69fSDavid Howells #include <keys/asymmetric-subtype.h> 17c26fd69fSDavid Howells #include <keys/asymmetric-parser.h> 183be4beafSMimi Zohar #include <keys/system_keyring.h> 19c26fd69fSDavid Howells #include <crypto/hash.h> 20c26fd69fSDavid Howells #include "asymmetric_keys.h" 21c26fd69fSDavid Howells #include "x509_parser.h" 22c26fd69fSDavid Howells 2332c4741cSDmitry Kasatkin static bool use_builtin_keys; 2446963b77SDavid Howells static struct asymmetric_key_id *ca_keyid; 25ffb70f61SDmitry Kasatkin 26ffb70f61SDmitry Kasatkin #ifndef MODULE 27f2b3dee4SMimi Zohar static struct { 28f2b3dee4SMimi Zohar struct asymmetric_key_id id; 29f2b3dee4SMimi Zohar unsigned char data[10]; 30f2b3dee4SMimi Zohar } cakey; 31f2b3dee4SMimi Zohar 32ffb70f61SDmitry Kasatkin static int __init ca_keys_setup(char *str) 33ffb70f61SDmitry Kasatkin { 34ffb70f61SDmitry Kasatkin if (!str) /* default system keyring */ 35ffb70f61SDmitry Kasatkin return 1; 36ffb70f61SDmitry Kasatkin 3746963b77SDavid Howells if (strncmp(str, "id:", 3) == 0) { 38f2b3dee4SMimi Zohar struct asymmetric_key_id *p = &cakey.id; 39f2b3dee4SMimi Zohar size_t hexlen = (strlen(str) - 3) / 2; 40f2b3dee4SMimi Zohar int ret; 41f2b3dee4SMimi Zohar 42f2b3dee4SMimi Zohar if (hexlen == 0 || hexlen > sizeof(cakey.data)) { 43f2b3dee4SMimi Zohar pr_err("Missing or invalid ca_keys id\n"); 44f2b3dee4SMimi Zohar return 1; 45f2b3dee4SMimi Zohar } 46f2b3dee4SMimi Zohar 47f2b3dee4SMimi Zohar ret = __asymmetric_key_hex_to_key_id(str + 3, p, hexlen); 48f2b3dee4SMimi Zohar if (ret < 0) 49f2b3dee4SMimi Zohar pr_err("Unparsable ca_keys id hex string\n"); 50f2b3dee4SMimi Zohar else 5146963b77SDavid Howells ca_keyid = p; /* owner key 'id:xxxxxx' */ 5246963b77SDavid Howells } else if (strcmp(str, "builtin") == 0) { 5332c4741cSDmitry Kasatkin use_builtin_keys = true; 5446963b77SDavid Howells } 55ffb70f61SDmitry Kasatkin 56ffb70f61SDmitry Kasatkin return 1; 57ffb70f61SDmitry Kasatkin } 58ffb70f61SDmitry Kasatkin __setup("ca_keys=", ca_keys_setup); 59ffb70f61SDmitry Kasatkin #endif 60ffb70f61SDmitry Kasatkin 615ce43ad2SDavid Howells /** 625ce43ad2SDavid Howells * x509_request_asymmetric_key - Request a key by X.509 certificate params. 635ce43ad2SDavid Howells * @keyring: The keys to search. 644573b64aSDavid Howells * @id: The issuer & serialNumber to look for or NULL. 654573b64aSDavid Howells * @skid: The subjectKeyIdentifier to look for or NULL. 66f1b731dbSDmitry Kasatkin * @partial: Use partial match if true, exact if false. 675ce43ad2SDavid Howells * 684573b64aSDavid Howells * Find a key in the given keyring by identifier. The preferred identifier is 694573b64aSDavid Howells * the issuer + serialNumber and the fallback identifier is the 704573b64aSDavid Howells * subjectKeyIdentifier. If both are given, the lookup is by the former, but 714573b64aSDavid Howells * the latter must also match. 723be4beafSMimi Zohar */ 735ce43ad2SDavid Howells struct key *x509_request_asymmetric_key(struct key *keyring, 744573b64aSDavid Howells const struct asymmetric_key_id *id, 754573b64aSDavid Howells const struct asymmetric_key_id *skid, 76f1b731dbSDmitry Kasatkin bool partial) 773be4beafSMimi Zohar { 784573b64aSDavid Howells struct key *key; 794573b64aSDavid Howells key_ref_t ref; 804573b64aSDavid Howells const char *lookup; 814573b64aSDavid Howells char *req, *p; 824573b64aSDavid Howells int len; 834573b64aSDavid Howells 844573b64aSDavid Howells if (id) { 854573b64aSDavid Howells lookup = id->data; 864573b64aSDavid Howells len = id->len; 874573b64aSDavid Howells } else { 884573b64aSDavid Howells lookup = skid->data; 894573b64aSDavid Howells len = skid->len; 904573b64aSDavid Howells } 913be4beafSMimi Zohar 9246963b77SDavid Howells /* Construct an identifier "id:<keyid>". */ 934573b64aSDavid Howells p = req = kmalloc(2 + 1 + len * 2 + 1, GFP_KERNEL); 944573b64aSDavid Howells if (!req) 953be4beafSMimi Zohar return ERR_PTR(-ENOMEM); 963be4beafSMimi Zohar 97f1b731dbSDmitry Kasatkin if (partial) { 9846963b77SDavid Howells *p++ = 'i'; 9946963b77SDavid Howells *p++ = 'd'; 100f1b731dbSDmitry Kasatkin } else { 101f1b731dbSDmitry Kasatkin *p++ = 'e'; 102f1b731dbSDmitry Kasatkin *p++ = 'x'; 103f1b731dbSDmitry Kasatkin } 10446963b77SDavid Howells *p++ = ':'; 1054573b64aSDavid Howells p = bin2hex(p, lookup, len); 10646963b77SDavid Howells *p = 0; 1073be4beafSMimi Zohar 1084573b64aSDavid Howells pr_debug("Look up: \"%s\"\n", req); 1093be4beafSMimi Zohar 1104573b64aSDavid Howells ref = keyring_search(make_key_ref(keyring, 1), 1114573b64aSDavid Howells &key_type_asymmetric, req); 1124573b64aSDavid Howells if (IS_ERR(ref)) 1134573b64aSDavid Howells pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref)); 1144573b64aSDavid Howells kfree(req); 1153be4beafSMimi Zohar 1164573b64aSDavid Howells if (IS_ERR(ref)) { 1174573b64aSDavid Howells switch (PTR_ERR(ref)) { 1183be4beafSMimi Zohar /* Hide some search errors */ 1193be4beafSMimi Zohar case -EACCES: 1203be4beafSMimi Zohar case -ENOTDIR: 1213be4beafSMimi Zohar case -EAGAIN: 1223be4beafSMimi Zohar return ERR_PTR(-ENOKEY); 1233be4beafSMimi Zohar default: 1244573b64aSDavid Howells return ERR_CAST(ref); 1253be4beafSMimi Zohar } 1263be4beafSMimi Zohar } 1273be4beafSMimi Zohar 1284573b64aSDavid Howells key = key_ref_to_ptr(ref); 1294573b64aSDavid Howells if (id && skid) { 1304573b64aSDavid Howells const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); 1314573b64aSDavid Howells if (!kids->id[1]) { 1324573b64aSDavid Howells pr_debug("issuer+serial match, but expected SKID missing\n"); 1334573b64aSDavid Howells goto reject; 1344573b64aSDavid Howells } 1354573b64aSDavid Howells if (!asymmetric_key_id_same(skid, kids->id[1])) { 1364573b64aSDavid Howells pr_debug("issuer+serial match, but SKID does not\n"); 1374573b64aSDavid Howells goto reject; 1384573b64aSDavid Howells } 1394573b64aSDavid Howells } 1404573b64aSDavid Howells 1414573b64aSDavid Howells pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key)); 1424573b64aSDavid Howells return key; 1434573b64aSDavid Howells 1444573b64aSDavid Howells reject: 1454573b64aSDavid Howells key_put(key); 1464573b64aSDavid Howells return ERR_PTR(-EKEYREJECTED); 1473be4beafSMimi Zohar } 148cf5b50fdSDavid Howells EXPORT_SYMBOL_GPL(x509_request_asymmetric_key); 1493be4beafSMimi Zohar 150c26fd69fSDavid Howells /* 151b426beb6SDavid Howells * Set up the signature parameters in an X.509 certificate. This involves 152b426beb6SDavid Howells * digesting the signed data and extracting the signature. 153c26fd69fSDavid Howells */ 154b426beb6SDavid Howells int x509_get_sig_params(struct x509_certificate *cert) 155c26fd69fSDavid Howells { 15677d0910dSDavid Howells struct public_key_signature *sig = cert->sig; 157c26fd69fSDavid Howells struct crypto_shash *tfm; 158c26fd69fSDavid Howells struct shash_desc *desc; 15977d0910dSDavid Howells size_t desc_size; 160c26fd69fSDavid Howells int ret; 161c26fd69fSDavid Howells 162c26fd69fSDavid Howells pr_devel("==>%s()\n", __func__); 163c26fd69fSDavid Howells 164*6c2dc5aeSDavid Howells if (!cert->pub->pkey_algo) 165*6c2dc5aeSDavid Howells cert->unsupported_key = true; 166*6c2dc5aeSDavid Howells 167*6c2dc5aeSDavid Howells if (!sig->pkey_algo) 168*6c2dc5aeSDavid Howells cert->unsupported_sig = true; 169*6c2dc5aeSDavid Howells 170*6c2dc5aeSDavid Howells /* We check the hash if we can - even if we can't then verify it */ 171*6c2dc5aeSDavid Howells if (!sig->hash_algo) { 172*6c2dc5aeSDavid Howells cert->unsupported_sig = true; 173b426beb6SDavid Howells return 0; 174*6c2dc5aeSDavid Howells } 175b426beb6SDavid Howells 17677d0910dSDavid Howells sig->s = kmemdup(cert->raw_sig, cert->raw_sig_size, GFP_KERNEL); 17777d0910dSDavid Howells if (!sig->s) 178b426beb6SDavid Howells return -ENOMEM; 179db6c43bdSTadeusz Struk 18077d0910dSDavid Howells sig->s_size = cert->raw_sig_size; 181b426beb6SDavid Howells 182c26fd69fSDavid Howells /* Allocate the hashing algorithm we're going to need and find out how 183c26fd69fSDavid Howells * big the hash operational data will be. 184c26fd69fSDavid Howells */ 18577d0910dSDavid Howells tfm = crypto_alloc_shash(sig->hash_algo, 0, 0); 18641559420SDavid Howells if (IS_ERR(tfm)) { 18741559420SDavid Howells if (PTR_ERR(tfm) == -ENOENT) { 188*6c2dc5aeSDavid Howells cert->unsupported_sig = true; 189*6c2dc5aeSDavid Howells return 0; 19041559420SDavid Howells } 19141559420SDavid Howells return PTR_ERR(tfm); 19241559420SDavid Howells } 193c26fd69fSDavid Howells 194c26fd69fSDavid Howells desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); 19577d0910dSDavid Howells sig->digest_size = crypto_shash_digestsize(tfm); 196c26fd69fSDavid Howells 197c26fd69fSDavid Howells ret = -ENOMEM; 19877d0910dSDavid Howells sig->digest = kmalloc(sig->digest_size, GFP_KERNEL); 19977d0910dSDavid Howells if (!sig->digest) 200b426beb6SDavid Howells goto error; 201c26fd69fSDavid Howells 20277d0910dSDavid Howells desc = kzalloc(desc_size, GFP_KERNEL); 20377d0910dSDavid Howells if (!desc) 20477d0910dSDavid Howells goto error; 205c26fd69fSDavid Howells 206c26fd69fSDavid Howells desc->tfm = tfm; 207c26fd69fSDavid Howells desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; 208c26fd69fSDavid Howells 209c26fd69fSDavid Howells ret = crypto_shash_init(desc); 210c26fd69fSDavid Howells if (ret < 0) 21177d0910dSDavid Howells goto error_2; 212b426beb6SDavid Howells might_sleep(); 21377d0910dSDavid Howells ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); 21477d0910dSDavid Howells 21577d0910dSDavid Howells error_2: 21677d0910dSDavid Howells kfree(desc); 217c26fd69fSDavid Howells error: 218c26fd69fSDavid Howells crypto_free_shash(tfm); 219c26fd69fSDavid Howells pr_devel("<==%s() = %d\n", __func__, ret); 220c26fd69fSDavid Howells return ret; 221c26fd69fSDavid Howells } 222b426beb6SDavid Howells 223b426beb6SDavid Howells /* 224*6c2dc5aeSDavid Howells * Check for self-signedness in an X.509 cert and if found, check the signature 225*6c2dc5aeSDavid Howells * immediately if we can. 226b426beb6SDavid Howells */ 227*6c2dc5aeSDavid Howells int x509_check_for_self_signed(struct x509_certificate *cert) 228b426beb6SDavid Howells { 229*6c2dc5aeSDavid Howells int ret = 0; 230b426beb6SDavid Howells 231b426beb6SDavid Howells pr_devel("==>%s()\n", __func__); 232b426beb6SDavid Howells 233*6c2dc5aeSDavid Howells if (cert->sig->auth_ids[0] || cert->sig->auth_ids[1]) { 234*6c2dc5aeSDavid Howells /* If the AKID is present it may have one or two parts. If 235*6c2dc5aeSDavid Howells * both are supplied, both must match. 236*6c2dc5aeSDavid Howells */ 237*6c2dc5aeSDavid Howells bool a = asymmetric_key_id_same(cert->skid, cert->sig->auth_ids[1]); 238*6c2dc5aeSDavid Howells bool b = asymmetric_key_id_same(cert->id, cert->sig->auth_ids[0]); 239*6c2dc5aeSDavid Howells 240*6c2dc5aeSDavid Howells if (!a && !b) 241*6c2dc5aeSDavid Howells goto not_self_signed; 242*6c2dc5aeSDavid Howells 243*6c2dc5aeSDavid Howells ret = -EKEYREJECTED; 244*6c2dc5aeSDavid Howells if (((a && !b) || (b && !a)) && 245*6c2dc5aeSDavid Howells cert->sig->auth_ids[0] && cert->sig->auth_ids[1]) 246*6c2dc5aeSDavid Howells goto out; 247*6c2dc5aeSDavid Howells } 248*6c2dc5aeSDavid Howells 249*6c2dc5aeSDavid Howells ret = public_key_verify_signature(cert->pub, cert->sig); 250*6c2dc5aeSDavid Howells if (ret < 0) { 251*6c2dc5aeSDavid Howells if (ret == -ENOPKG) { 252*6c2dc5aeSDavid Howells cert->unsupported_sig = true; 253*6c2dc5aeSDavid Howells ret = 0; 254*6c2dc5aeSDavid Howells } 255*6c2dc5aeSDavid Howells goto out; 256*6c2dc5aeSDavid Howells } 257*6c2dc5aeSDavid Howells 258*6c2dc5aeSDavid Howells pr_devel("Cert Self-signature verified"); 259*6c2dc5aeSDavid Howells cert->self_signed = true; 260*6c2dc5aeSDavid Howells 261*6c2dc5aeSDavid Howells out: 262*6c2dc5aeSDavid Howells pr_devel("<==%s() = %d\n", __func__, ret); 263b426beb6SDavid Howells return ret; 264b426beb6SDavid Howells 265*6c2dc5aeSDavid Howells not_self_signed: 266*6c2dc5aeSDavid Howells pr_devel("<==%s() = 0 [not]\n", __func__); 267*6c2dc5aeSDavid Howells return 0; 268b426beb6SDavid Howells } 269c26fd69fSDavid Howells 270c26fd69fSDavid Howells /* 2713be4beafSMimi Zohar * Check the new certificate against the ones in the trust keyring. If one of 2723be4beafSMimi Zohar * those is the signing key and validates the new certificate, then mark the 2733be4beafSMimi Zohar * new certificate as being trusted. 2743be4beafSMimi Zohar * 2753be4beafSMimi Zohar * Return 0 if the new certificate was successfully validated, 1 if we couldn't 2763be4beafSMimi Zohar * find a matching parent certificate in the trusted list and an error if there 2773be4beafSMimi Zohar * is a matching certificate but the signature check fails. 2783be4beafSMimi Zohar */ 2793be4beafSMimi Zohar static int x509_validate_trust(struct x509_certificate *cert, 2803be4beafSMimi Zohar struct key *trust_keyring) 2813be4beafSMimi Zohar { 28277d0910dSDavid Howells struct public_key_signature *sig = cert->sig; 2833be4beafSMimi Zohar struct key *key; 2843be4beafSMimi Zohar int ret = 1; 2853be4beafSMimi Zohar 286*6c2dc5aeSDavid Howells if (!sig->auth_ids[0] && !sig->auth_ids[1]) 287*6c2dc5aeSDavid Howells return 1; 288*6c2dc5aeSDavid Howells 2893be4beafSMimi Zohar if (!trust_keyring) 2903be4beafSMimi Zohar return -EOPNOTSUPP; 29177d0910dSDavid Howells if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid)) 292ffb70f61SDmitry Kasatkin return -EPERM; 293*6c2dc5aeSDavid Howells if (cert->unsupported_sig) 294*6c2dc5aeSDavid Howells return -ENOPKG; 295ffb70f61SDmitry Kasatkin 2964573b64aSDavid Howells key = x509_request_asymmetric_key(trust_keyring, 29777d0910dSDavid Howells sig->auth_ids[0], sig->auth_ids[1], 298f1b731dbSDmitry Kasatkin false); 299*6c2dc5aeSDavid Howells if (IS_ERR(key)) 300*6c2dc5aeSDavid Howells return PTR_ERR(key); 301*6c2dc5aeSDavid Howells 302*6c2dc5aeSDavid Howells if (!use_builtin_keys || 303*6c2dc5aeSDavid Howells test_bit(KEY_FLAG_BUILTIN, &key->flags)) { 304*6c2dc5aeSDavid Howells ret = public_key_verify_signature( 305*6c2dc5aeSDavid Howells key->payload.data[asym_crypto], cert->sig); 306*6c2dc5aeSDavid Howells if (ret == -ENOPKG) 307*6c2dc5aeSDavid Howells cert->unsupported_sig = true; 3083be4beafSMimi Zohar } 309*6c2dc5aeSDavid Howells key_put(key); 3103be4beafSMimi Zohar return ret; 3113be4beafSMimi Zohar } 3123be4beafSMimi Zohar 3133be4beafSMimi Zohar /* 314c26fd69fSDavid Howells * Attempt to parse a data blob for a key as an X509 certificate. 315c26fd69fSDavid Howells */ 316c26fd69fSDavid Howells static int x509_key_preparse(struct key_preparsed_payload *prep) 317c26fd69fSDavid Howells { 31846963b77SDavid Howells struct asymmetric_key_ids *kids; 319c26fd69fSDavid Howells struct x509_certificate *cert; 32046963b77SDavid Howells const char *q; 321c26fd69fSDavid Howells size_t srlen, sulen; 32246963b77SDavid Howells char *desc = NULL, *p; 323c26fd69fSDavid Howells int ret; 324c26fd69fSDavid Howells 325c26fd69fSDavid Howells cert = x509_cert_parse(prep->data, prep->datalen); 326c26fd69fSDavid Howells if (IS_ERR(cert)) 327c26fd69fSDavid Howells return PTR_ERR(cert); 328c26fd69fSDavid Howells 329c26fd69fSDavid Howells pr_devel("Cert Issuer: %s\n", cert->issuer); 330c26fd69fSDavid Howells pr_devel("Cert Subject: %s\n", cert->subject); 3312ecdb23bSDavid Howells 332*6c2dc5aeSDavid Howells if (cert->unsupported_key) { 3332ecdb23bSDavid Howells ret = -ENOPKG; 3342ecdb23bSDavid Howells goto error_free_cert; 3352ecdb23bSDavid Howells } 3362ecdb23bSDavid Howells 3374e8ae72aSDavid Howells pr_devel("Cert Key Algo: %s\n", cert->pub->pkey_algo); 338fd19a3d1SDavid Howells pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to); 339c26fd69fSDavid Howells 3404e8ae72aSDavid Howells cert->pub->id_type = "X509"; 341c26fd69fSDavid Howells 342*6c2dc5aeSDavid Howells /* See if we can derive the trustability of this certificate. 343*6c2dc5aeSDavid Howells * 344*6c2dc5aeSDavid Howells * When it comes to self-signed certificates, we cannot evaluate 345*6c2dc5aeSDavid Howells * trustedness except by the fact that we obtained it from a trusted 346*6c2dc5aeSDavid Howells * location. So we just rely on x509_validate_trust() failing in this 347*6c2dc5aeSDavid Howells * case. 348*6c2dc5aeSDavid Howells * 349*6c2dc5aeSDavid Howells * Note that there's a possibility of a self-signed cert matching a 350*6c2dc5aeSDavid Howells * cert that we have (most likely a duplicate that we already trust) - 351*6c2dc5aeSDavid Howells * in which case it will be marked trusted. 352*6c2dc5aeSDavid Howells */ 353*6c2dc5aeSDavid Howells if (cert->unsupported_sig || cert->self_signed) { 354*6c2dc5aeSDavid Howells public_key_signature_free(cert->sig); 355*6c2dc5aeSDavid Howells cert->sig = NULL; 356*6c2dc5aeSDavid Howells } else { 357*6c2dc5aeSDavid Howells pr_devel("Cert Signature: %s + %s\n", 358*6c2dc5aeSDavid Howells cert->sig->pkey_algo, cert->sig->hash_algo); 359*6c2dc5aeSDavid Howells 3603be4beafSMimi Zohar ret = x509_validate_trust(cert, get_system_trusted_keyring()); 36141c89b64SPetko Manolov if (ret) 36241c89b64SPetko Manolov ret = x509_validate_trust(cert, get_ima_mok_keyring()); 363*6c2dc5aeSDavid Howells if (ret == -EKEYREJECTED) 364*6c2dc5aeSDavid Howells goto error_free_cert; 3653be4beafSMimi Zohar if (!ret) 366*6c2dc5aeSDavid Howells prep->trusted = true; 367c26fd69fSDavid Howells } 368c26fd69fSDavid Howells 369c26fd69fSDavid Howells /* Propose a description */ 370c26fd69fSDavid Howells sulen = strlen(cert->subject); 371dd2f6c44SDavid Howells if (cert->raw_skid) { 372dd2f6c44SDavid Howells srlen = cert->raw_skid_size; 373dd2f6c44SDavid Howells q = cert->raw_skid; 374dd2f6c44SDavid Howells } else { 37546963b77SDavid Howells srlen = cert->raw_serial_size; 37646963b77SDavid Howells q = cert->raw_serial; 377dd2f6c44SDavid Howells } 37846963b77SDavid Howells 379c26fd69fSDavid Howells ret = -ENOMEM; 38046963b77SDavid Howells desc = kmalloc(sulen + 2 + srlen * 2 + 1, GFP_KERNEL); 381c26fd69fSDavid Howells if (!desc) 382c26fd69fSDavid Howells goto error_free_cert; 38346963b77SDavid Howells p = memcpy(desc, cert->subject, sulen); 38446963b77SDavid Howells p += sulen; 38546963b77SDavid Howells *p++ = ':'; 38646963b77SDavid Howells *p++ = ' '; 38746963b77SDavid Howells p = bin2hex(p, q, srlen); 38846963b77SDavid Howells *p = 0; 38946963b77SDavid Howells 39046963b77SDavid Howells kids = kmalloc(sizeof(struct asymmetric_key_ids), GFP_KERNEL); 39146963b77SDavid Howells if (!kids) 39246963b77SDavid Howells goto error_free_desc; 39346963b77SDavid Howells kids->id[0] = cert->id; 39446963b77SDavid Howells kids->id[1] = cert->skid; 395c26fd69fSDavid Howells 396c26fd69fSDavid Howells /* We're pinning the module by being linked against it */ 397c26fd69fSDavid Howells __module_get(public_key_subtype.owner); 398146aa8b1SDavid Howells prep->payload.data[asym_subtype] = &public_key_subtype; 399146aa8b1SDavid Howells prep->payload.data[asym_key_ids] = kids; 400146aa8b1SDavid Howells prep->payload.data[asym_crypto] = cert->pub; 40177d0910dSDavid Howells prep->payload.data[asym_auth] = cert->sig; 402c26fd69fSDavid Howells prep->description = desc; 403c26fd69fSDavid Howells prep->quotalen = 100; 404c26fd69fSDavid Howells 405c26fd69fSDavid Howells /* We've finished with the certificate */ 406c26fd69fSDavid Howells cert->pub = NULL; 40746963b77SDavid Howells cert->id = NULL; 40846963b77SDavid Howells cert->skid = NULL; 40977d0910dSDavid Howells cert->sig = NULL; 410c26fd69fSDavid Howells desc = NULL; 411c26fd69fSDavid Howells ret = 0; 412c26fd69fSDavid Howells 41346963b77SDavid Howells error_free_desc: 41446963b77SDavid Howells kfree(desc); 415c26fd69fSDavid Howells error_free_cert: 416c26fd69fSDavid Howells x509_free_certificate(cert); 417c26fd69fSDavid Howells return ret; 418c26fd69fSDavid Howells } 419c26fd69fSDavid Howells 420c26fd69fSDavid Howells static struct asymmetric_key_parser x509_key_parser = { 421c26fd69fSDavid Howells .owner = THIS_MODULE, 422c26fd69fSDavid Howells .name = "x509", 423c26fd69fSDavid Howells .parse = x509_key_preparse, 424c26fd69fSDavid Howells }; 425c26fd69fSDavid Howells 426c26fd69fSDavid Howells /* 427c26fd69fSDavid Howells * Module stuff 428c26fd69fSDavid Howells */ 429c26fd69fSDavid Howells static int __init x509_key_init(void) 430c26fd69fSDavid Howells { 431c26fd69fSDavid Howells return register_asymmetric_key_parser(&x509_key_parser); 432c26fd69fSDavid Howells } 433c26fd69fSDavid Howells 434c26fd69fSDavid Howells static void __exit x509_key_exit(void) 435c26fd69fSDavid Howells { 436c26fd69fSDavid Howells unregister_asymmetric_key_parser(&x509_key_parser); 437c26fd69fSDavid Howells } 438c26fd69fSDavid Howells 439c26fd69fSDavid Howells module_init(x509_key_init); 440c26fd69fSDavid Howells module_exit(x509_key_exit); 441e19aaa7dSKonstantin Khlebnikov 442e19aaa7dSKonstantin Khlebnikov MODULE_DESCRIPTION("X.509 certificate parser"); 443e19aaa7dSKonstantin Khlebnikov MODULE_LICENSE("GPL"); 444