140 lines · c
1/* SPDX-License-Identifier: GPL-2.0-or-later */2/*3 * Public Key Signature Algorithm4 *5 * Copyright (c) 2023 Herbert Xu <herbert@gondor.apana.org.au>6 */7 8#include <crypto/akcipher.h>9#include <crypto/internal/sig.h>10#include <linux/cryptouser.h>11#include <linux/kernel.h>12#include <linux/module.h>13#include <linux/scatterlist.h>14#include <linux/seq_file.h>15#include <linux/string.h>16#include <net/netlink.h>17 18#include "internal.h"19 20#define CRYPTO_ALG_TYPE_SIG_MASK 0x0000000e21 22static const struct crypto_type crypto_sig_type;23 24static int crypto_sig_init_tfm(struct crypto_tfm *tfm)25{26 if (tfm->__crt_alg->cra_type != &crypto_sig_type)27 return crypto_init_akcipher_ops_sig(tfm);28 29 return 0;30}31 32static void __maybe_unused crypto_sig_show(struct seq_file *m,33 struct crypto_alg *alg)34{35 seq_puts(m, "type : sig\n");36}37 38static int __maybe_unused crypto_sig_report(struct sk_buff *skb,39 struct crypto_alg *alg)40{41 struct crypto_report_akcipher rsig = {};42 43 strscpy(rsig.type, "sig", sizeof(rsig.type));44 45 return nla_put(skb, CRYPTOCFGA_REPORT_AKCIPHER, sizeof(rsig), &rsig);46}47 48static const struct crypto_type crypto_sig_type = {49 .extsize = crypto_alg_extsize,50 .init_tfm = crypto_sig_init_tfm,51#ifdef CONFIG_PROC_FS52 .show = crypto_sig_show,53#endif54#if IS_ENABLED(CONFIG_CRYPTO_USER)55 .report = crypto_sig_report,56#endif57 .maskclear = ~CRYPTO_ALG_TYPE_MASK,58 .maskset = CRYPTO_ALG_TYPE_SIG_MASK,59 .type = CRYPTO_ALG_TYPE_SIG,60 .tfmsize = offsetof(struct crypto_sig, base),61};62 63struct crypto_sig *crypto_alloc_sig(const char *alg_name, u32 type, u32 mask)64{65 return crypto_alloc_tfm(alg_name, &crypto_sig_type, type, mask);66}67EXPORT_SYMBOL_GPL(crypto_alloc_sig);68 69int crypto_sig_maxsize(struct crypto_sig *tfm)70{71 struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);72 73 return crypto_akcipher_maxsize(*ctx);74}75EXPORT_SYMBOL_GPL(crypto_sig_maxsize);76 77int crypto_sig_sign(struct crypto_sig *tfm,78 const void *src, unsigned int slen,79 void *dst, unsigned int dlen)80{81 struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);82 struct crypto_akcipher_sync_data data = {83 .tfm = *ctx,84 .src = src,85 .dst = dst,86 .slen = slen,87 .dlen = dlen,88 };89 90 return crypto_akcipher_sync_prep(&data) ?:91 crypto_akcipher_sync_post(&data,92 crypto_akcipher_sign(data.req));93}94EXPORT_SYMBOL_GPL(crypto_sig_sign);95 96int crypto_sig_verify(struct crypto_sig *tfm,97 const void *src, unsigned int slen,98 const void *digest, unsigned int dlen)99{100 struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);101 struct crypto_akcipher_sync_data data = {102 .tfm = *ctx,103 .src = src,104 .slen = slen,105 .dlen = dlen,106 };107 int err;108 109 err = crypto_akcipher_sync_prep(&data);110 if (err)111 return err;112 113 memcpy(data.buf + slen, digest, dlen);114 115 return crypto_akcipher_sync_post(&data,116 crypto_akcipher_verify(data.req));117}118EXPORT_SYMBOL_GPL(crypto_sig_verify);119 120int crypto_sig_set_pubkey(struct crypto_sig *tfm,121 const void *key, unsigned int keylen)122{123 struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);124 125 return crypto_akcipher_set_pub_key(*ctx, key, keylen);126}127EXPORT_SYMBOL_GPL(crypto_sig_set_pubkey);128 129int crypto_sig_set_privkey(struct crypto_sig *tfm,130 const void *key, unsigned int keylen)131{132 struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);133 134 return crypto_akcipher_set_priv_key(*ctx, key, keylen);135}136EXPORT_SYMBOL_GPL(crypto_sig_set_privkey);137 138MODULE_LICENSE("GPL");139MODULE_DESCRIPTION("Public Key Signature Algorithms");140