1/* SPDX-License-Identifier: GPL-2.0-or-later */ 2/* 3 * Public Key Signature Algorithm 4 * 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 0x0000000e 21 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 int __maybe_unused crypto_sig_report_stat(struct sk_buff *skb, 49 struct crypto_alg *alg) 50{ 51 struct crypto_stat_akcipher rsig = {}; 52 53 strscpy(rsig.type, "sig", sizeof(rsig.type)); 54 55 return nla_put(skb, CRYPTOCFGA_STAT_AKCIPHER, sizeof(rsig), &rsig); 56} 57 58static const struct crypto_type crypto_sig_type = { 59 .extsize = crypto_alg_extsize, 60 .init_tfm = crypto_sig_init_tfm, 61#ifdef CONFIG_PROC_FS 62 .show = crypto_sig_show, 63#endif 64#if IS_ENABLED(CONFIG_CRYPTO_USER) 65 .report = crypto_sig_report, 66#endif 67#ifdef CONFIG_CRYPTO_STATS 68 .report_stat = crypto_sig_report_stat, 69#endif 70 .maskclear = ~CRYPTO_ALG_TYPE_MASK, 71 .maskset = CRYPTO_ALG_TYPE_SIG_MASK, 72 .type = CRYPTO_ALG_TYPE_SIG, 73 .tfmsize = offsetof(struct crypto_sig, base), 74}; 75 76struct crypto_sig *crypto_alloc_sig(const char *alg_name, u32 type, u32 mask) 77{ 78 return crypto_alloc_tfm(alg_name, &crypto_sig_type, type, mask); 79} 80EXPORT_SYMBOL_GPL(crypto_alloc_sig); 81 82int crypto_sig_maxsize(struct crypto_sig *tfm) 83{ 84 struct crypto_akcipher **ctx = crypto_sig_ctx(tfm); 85 86 return crypto_akcipher_maxsize(*ctx); 87} 88EXPORT_SYMBOL_GPL(crypto_sig_maxsize); 89 90int crypto_sig_sign(struct crypto_sig *tfm, 91 const void *src, unsigned int slen, 92 void *dst, unsigned int dlen) 93{ 94 struct crypto_akcipher **ctx = crypto_sig_ctx(tfm); 95 struct crypto_akcipher_sync_data data = { 96 .tfm = *ctx, 97 .src = src, 98 .dst = dst, 99 .slen = slen, 100 .dlen = dlen, 101 }; 102 103 return crypto_akcipher_sync_prep(&data) ?: 104 crypto_akcipher_sync_post(&data, 105 crypto_akcipher_sign(data.req)); 106} 107EXPORT_SYMBOL_GPL(crypto_sig_sign); 108 109int crypto_sig_verify(struct crypto_sig *tfm, 110 const void *src, unsigned int slen, 111 const void *digest, unsigned int dlen) 112{ 113 struct crypto_akcipher **ctx = crypto_sig_ctx(tfm); 114 struct crypto_akcipher_sync_data data = { 115 .tfm = *ctx, 116 .src = src, 117 .slen = slen, 118 .dlen = dlen, 119 }; 120 int err; 121 122 err = crypto_akcipher_sync_prep(&data); 123 if (err) 124 return err; 125 126 memcpy(data.buf + slen, digest, dlen); 127 128 return crypto_akcipher_sync_post(&data, 129 crypto_akcipher_verify(data.req)); 130} 131EXPORT_SYMBOL_GPL(crypto_sig_verify); 132 133int crypto_sig_set_pubkey(struct crypto_sig *tfm, 134 const void *key, unsigned int keylen) 135{ 136 struct crypto_akcipher **ctx = crypto_sig_ctx(tfm); 137 138 return crypto_akcipher_set_pub_key(*ctx, key, keylen); 139} 140EXPORT_SYMBOL_GPL(crypto_sig_set_pubkey); 141 142int crypto_sig_set_privkey(struct crypto_sig *tfm, 143 const void *key, unsigned int keylen) 144{ 145 struct crypto_akcipher **ctx = crypto_sig_ctx(tfm); 146 147 return crypto_akcipher_set_priv_key(*ctx, key, keylen); 148} 149EXPORT_SYMBOL_GPL(crypto_sig_set_privkey); 150 151MODULE_LICENSE("GPL"); 152MODULE_DESCRIPTION("Public Key Signature Algorithms"); 153