1a9681bf3SDavid Howells /* In-software asymmetric public-key crypto subtype 2a9681bf3SDavid Howells * 3a9681bf3SDavid Howells * See Documentation/crypto/asymmetric-keys.txt 4a9681bf3SDavid Howells * 5a9681bf3SDavid Howells * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 6a9681bf3SDavid Howells * Written by David Howells (dhowells@redhat.com) 7a9681bf3SDavid Howells * 8a9681bf3SDavid Howells * This program is free software; you can redistribute it and/or 9a9681bf3SDavid Howells * modify it under the terms of the GNU General Public Licence 10a9681bf3SDavid Howells * as published by the Free Software Foundation; either version 11a9681bf3SDavid Howells * 2 of the Licence, or (at your option) any later version. 12a9681bf3SDavid Howells */ 13a9681bf3SDavid Howells 14a9681bf3SDavid Howells #define pr_fmt(fmt) "PKEY: "fmt 15a9681bf3SDavid Howells #include <linux/module.h> 16a9681bf3SDavid Howells #include <linux/export.h> 17a9681bf3SDavid Howells #include <linux/kernel.h> 18a9681bf3SDavid Howells #include <linux/slab.h> 19a9681bf3SDavid Howells #include <linux/seq_file.h> 20a9681bf3SDavid Howells #include <keys/asymmetric-subtype.h> 21a9681bf3SDavid Howells #include "public_key.h" 22a9681bf3SDavid Howells 23a9681bf3SDavid Howells MODULE_LICENSE("GPL"); 24a9681bf3SDavid Howells 259abc4e66SDavid Howells const char *const pkey_algo_name[PKEY_ALGO__LAST] = { 26a9681bf3SDavid Howells [PKEY_ALGO_DSA] = "DSA", 27a9681bf3SDavid Howells [PKEY_ALGO_RSA] = "RSA", 28a9681bf3SDavid Howells }; 299abc4e66SDavid Howells EXPORT_SYMBOL_GPL(pkey_algo_name); 30a9681bf3SDavid Howells 31206ce59aSDavid Howells const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST] = { 32206ce59aSDavid Howells #if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \ 33206ce59aSDavid Howells defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE) 34206ce59aSDavid Howells [PKEY_ALGO_RSA] = &RSA_public_key_algorithm, 35206ce59aSDavid Howells #endif 36206ce59aSDavid Howells }; 37206ce59aSDavid Howells EXPORT_SYMBOL_GPL(pkey_algo); 38206ce59aSDavid Howells 399abc4e66SDavid Howells const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = { 40a9681bf3SDavid Howells [PKEY_ID_PGP] = "PGP", 41a9681bf3SDavid Howells [PKEY_ID_X509] = "X509", 42a9681bf3SDavid Howells }; 439abc4e66SDavid Howells EXPORT_SYMBOL_GPL(pkey_id_type_name); 44a9681bf3SDavid Howells 45a9681bf3SDavid Howells /* 46a9681bf3SDavid Howells * Provide a part of a description of the key for /proc/keys. 47a9681bf3SDavid Howells */ 48a9681bf3SDavid Howells static void public_key_describe(const struct key *asymmetric_key, 49a9681bf3SDavid Howells struct seq_file *m) 50a9681bf3SDavid Howells { 51a9681bf3SDavid Howells struct public_key *key = asymmetric_key->payload.data; 52a9681bf3SDavid Howells 53a9681bf3SDavid Howells if (key) 54a9681bf3SDavid Howells seq_printf(m, "%s.%s", 559abc4e66SDavid Howells pkey_id_type_name[key->id_type], key->algo->name); 56a9681bf3SDavid Howells } 57a9681bf3SDavid Howells 58a9681bf3SDavid Howells /* 59a9681bf3SDavid Howells * Destroy a public key algorithm key. 60a9681bf3SDavid Howells */ 61a9681bf3SDavid Howells void public_key_destroy(void *payload) 62a9681bf3SDavid Howells { 63a9681bf3SDavid Howells struct public_key *key = payload; 64a9681bf3SDavid Howells int i; 65a9681bf3SDavid Howells 66a9681bf3SDavid Howells if (key) { 67a9681bf3SDavid Howells for (i = 0; i < ARRAY_SIZE(key->mpi); i++) 68a9681bf3SDavid Howells mpi_free(key->mpi[i]); 69a9681bf3SDavid Howells kfree(key); 70a9681bf3SDavid Howells } 71a9681bf3SDavid Howells } 72a9681bf3SDavid Howells EXPORT_SYMBOL_GPL(public_key_destroy); 73a9681bf3SDavid Howells 74a9681bf3SDavid Howells /* 75a9681bf3SDavid Howells * Verify a signature using a public key. 76a9681bf3SDavid Howells */ 77*3d167d68SDavid Howells int public_key_verify_signature(const struct public_key *pk, 78a9681bf3SDavid Howells const struct public_key_signature *sig) 79a9681bf3SDavid Howells { 80*3d167d68SDavid Howells const struct public_key_algorithm *algo; 81a9681bf3SDavid Howells 82*3d167d68SDavid Howells BUG_ON(!pk); 83*3d167d68SDavid Howells BUG_ON(!pk->mpi[0]); 84*3d167d68SDavid Howells BUG_ON(!pk->mpi[1]); 85*3d167d68SDavid Howells BUG_ON(!sig); 86*3d167d68SDavid Howells BUG_ON(!sig->digest); 87*3d167d68SDavid Howells BUG_ON(!sig->mpi[0]); 88*3d167d68SDavid Howells 89*3d167d68SDavid Howells algo = pk->algo; 90*3d167d68SDavid Howells if (!algo) { 91*3d167d68SDavid Howells if (pk->pkey_algo >= PKEY_ALGO__LAST) 92*3d167d68SDavid Howells return -ENOPKG; 93*3d167d68SDavid Howells algo = pkey_algo[pk->pkey_algo]; 94*3d167d68SDavid Howells if (!algo) 95*3d167d68SDavid Howells return -ENOPKG; 96*3d167d68SDavid Howells } 97*3d167d68SDavid Howells 98*3d167d68SDavid Howells if (!algo->verify_signature) 99a9681bf3SDavid Howells return -ENOTSUPP; 100a9681bf3SDavid Howells 101*3d167d68SDavid Howells if (sig->nr_mpi != algo->n_sig_mpi) { 102a9681bf3SDavid Howells pr_debug("Signature has %u MPI not %u\n", 103*3d167d68SDavid Howells sig->nr_mpi, algo->n_sig_mpi); 104a9681bf3SDavid Howells return -EINVAL; 105a9681bf3SDavid Howells } 106a9681bf3SDavid Howells 107*3d167d68SDavid Howells return algo->verify_signature(pk, sig); 108*3d167d68SDavid Howells } 109*3d167d68SDavid Howells EXPORT_SYMBOL_GPL(public_key_verify_signature); 110*3d167d68SDavid Howells 111*3d167d68SDavid Howells static int public_key_verify_signature_2(const struct key *key, 112*3d167d68SDavid Howells const struct public_key_signature *sig) 113*3d167d68SDavid Howells { 114*3d167d68SDavid Howells const struct public_key *pk = key->payload.data; 115*3d167d68SDavid Howells return public_key_verify_signature(pk, sig); 116a9681bf3SDavid Howells } 117a9681bf3SDavid Howells 118a9681bf3SDavid Howells /* 119a9681bf3SDavid Howells * Public key algorithm asymmetric key subtype 120a9681bf3SDavid Howells */ 121a9681bf3SDavid Howells struct asymmetric_key_subtype public_key_subtype = { 122a9681bf3SDavid Howells .owner = THIS_MODULE, 123a9681bf3SDavid Howells .name = "public_key", 124a9681bf3SDavid Howells .describe = public_key_describe, 125a9681bf3SDavid Howells .destroy = public_key_destroy, 126*3d167d68SDavid Howells .verify_signature = public_key_verify_signature_2, 127a9681bf3SDavid Howells }; 128a9681bf3SDavid Howells EXPORT_SYMBOL_GPL(public_key_subtype); 129