/* In-software asymmetric public-key crypto subtype * * See Documentation/crypto/asymmetric-keys.txt * * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public Licence * as published by the Free Software Foundation; either version * 2 of the Licence, or (at your option) any later version. */ //#define pr_fmt(fmt) "PKEY: "fmt //#include //#include //#include //#include //#include //#include //#include //#include //#include // // MODULE_LICENSE("GPL"); #include "public_key.h" #include "../rewrite/Lib.SoulExtraction.rewrite.h" /* * Provide a part of a description of the key for /proc/keys. */ // static void public_key_describe(const struct key *asymmetric_key, // struct seq_file *m) //{ // struct public_key *key = asymmetric_key->payload.data[asym_crypto]; // // if (key) // seq_printf(m, "%s.%s", key->id_type, key->pkey_algo); // } /* * Destroy a public key algorithm key. */ void public_key_free(struct public_key *key) { if (key) { kfree(key->key); kfree(key); } } // EXPORT_SYMBOL_GPL(public_key_free); /* * Destroy a public key algorithm key. */ // static void public_key_destroy(void *payload0, void *payload3) //{ // public_key_free(payload0); // public_key_signature_free(payload3); // } // struct public_key_completion { // struct completion completion; // int err; // }; // // static void public_key_verify_done(struct crypto_async_request *req, int err) //{ // struct public_key_completion *compl = req->data; // // if (err == -EINPROGRESS) // return; // // compl->err = err; // complete(&compl->completion); // } /* * Verify a signature using a public key. */ // int public_key_verify_signature(const struct public_key *pkey, // const struct public_key_signature *sig) //{ // struct public_key_completion compl; // struct crypto_akcipher *tfm; // struct akcipher_request *req; // struct scatterlist sig_sg, digest_sg; // const char *alg_name; // char alg_name_buf[CRYPTO_MAX_ALG_NAME]; // void *output; // unsigned int outlen; // int ret = -ENOMEM; // // pr_devel("==>%s()\n", __func__); // // BUG_ON(!pkey); // BUG_ON(!sig); // BUG_ON(!sig->s); // // if (!sig->digest) // return -ENOPKG; // // alg_name = sig->pkey_algo; // if (strcmp(sig->pkey_algo, "rsa") == 0) { // /* The data wangled by the RSA algorithm is typically padded // * and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447 // * sec 8.2]. // */ // if (snprintf(alg_name_buf, CRYPTO_MAX_ALG_NAME, // "pkcs1pad(rsa,%s)", sig->hash_algo // ) >= CRYPTO_MAX_ALG_NAME) // return -EINVAL; // alg_name = alg_name_buf; // } // // tfm = crypto_alloc_akcipher(alg_name, 0, 0); // if (IS_ERR(tfm)) // return PTR_ERR(tfm); // // req = akcipher_request_alloc(tfm, GFP_KERNEL); // if (!req) // goto error_free_tfm; // // ret = crypto_akcipher_set_pub_key(tfm, pkey->key, pkey->keylen); // if (ret) // goto error_free_req; // // ret = -ENOMEM; // outlen = crypto_akcipher_maxsize(tfm); // output = kmalloc(outlen, GFP_KERNEL); // if (!output) // goto error_free_req; // // sg_init_one(&sig_sg, sig->s, sig->s_size); // sg_init_one(&digest_sg, output, outlen); // akcipher_request_set_crypt(req, &sig_sg, &digest_sg, sig->s_size, // outlen); // init_completion(&compl.completion); // akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | // CRYPTO_TFM_REQ_MAY_SLEEP, // public_key_verify_done, &compl); // // /* Perform the verification calculation. This doesn't actually do the // * verification, but rather calculates the hash expected by the // * signature and returns that to us. // */ // ret = crypto_akcipher_verify(req); // if ((ret == -EINPROGRESS) || (ret == -EBUSY)) { // wait_for_completion(&compl.completion); // ret = compl.err; // } // if (ret < 0) // goto out_free_output; // // /* Do the actual verification step. */ // if (req->dst_len != sig->digest_size || // memcmp(sig->digest, output, sig->digest_size) != 0) // ret = -EKEYREJECTED; // // out_free_output: // kfree(output); // error_free_req: // akcipher_request_free(req); // error_free_tfm: // crypto_free_akcipher(tfm); // pr_devel("<==%s() = %d\n", __func__, ret); // return ret; // } // EXPORT_SYMBOL_GPL(public_key_verify_signature); // // static int public_key_verify_signature_2(const struct key *key, // const struct public_key_signature *sig) //{ // const struct public_key *pk = key->payload.data[asym_crypto]; // return public_key_verify_signature(pk, sig); // } /* * Public key algorithm asymmetric key subtype */ // struct asymmetric_key_subtype public_key_subtype = { // .owner = THIS_MODULE, // .name = "public_key", // .name_len = sizeof("public_key") - 1, // .describe = public_key_describe, // .destroy = public_key_destroy, // .verify_signature = public_key_verify_signature_2, // }; // EXPORT_SYMBOL_GPL(public_key_subtype);