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 22 static const struct crypto_type crypto_sig_type; 23 24 static inline struct crypto_sig *__crypto_sig_tfm(struct crypto_tfm *tfm) 25 { 26 return container_of(tfm, struct crypto_sig, base); 27 } 28 29 static int crypto_sig_init_tfm(struct crypto_tfm *tfm) 30 { 31 if (tfm->__crt_alg->cra_type != &crypto_sig_type) 32 return crypto_init_akcipher_ops_sig(tfm); 33 34 return 0; 35 } 36 37 static void __maybe_unused crypto_sig_show(struct seq_file *m, 38 struct crypto_alg *alg) 39 { 40 seq_puts(m, "type : sig\n"); 41 } 42 43 static int __maybe_unused crypto_sig_report(struct sk_buff *skb, 44 struct crypto_alg *alg) 45 { 46 struct crypto_report_akcipher rsig = {}; 47 48 strscpy(rsig.type, "sig", sizeof(rsig.type)); 49 50 return nla_put(skb, CRYPTOCFGA_REPORT_AKCIPHER, sizeof(rsig), &rsig); 51 } 52 53 static int __maybe_unused crypto_sig_report_stat(struct sk_buff *skb, 54 struct crypto_alg *alg) 55 { 56 struct crypto_stat_akcipher rsig = {}; 57 58 strscpy(rsig.type, "sig", sizeof(rsig.type)); 59 60 return nla_put(skb, CRYPTOCFGA_STAT_AKCIPHER, sizeof(rsig), &rsig); 61 } 62 63 static const struct crypto_type crypto_sig_type = { 64 .extsize = crypto_alg_extsize, 65 .init_tfm = crypto_sig_init_tfm, 66 #ifdef CONFIG_PROC_FS 67 .show = crypto_sig_show, 68 #endif 69 #if IS_ENABLED(CONFIG_CRYPTO_USER) 70 .report = crypto_sig_report, 71 #endif 72 #ifdef CONFIG_CRYPTO_STATS 73 .report_stat = crypto_sig_report_stat, 74 #endif 75 .maskclear = ~CRYPTO_ALG_TYPE_MASK, 76 .maskset = CRYPTO_ALG_TYPE_SIG_MASK, 77 .type = CRYPTO_ALG_TYPE_SIG, 78 .tfmsize = offsetof(struct crypto_sig, base), 79 }; 80 81 struct crypto_sig *crypto_alloc_sig(const char *alg_name, u32 type, u32 mask) 82 { 83 return crypto_alloc_tfm(alg_name, &crypto_sig_type, type, mask); 84 } 85 EXPORT_SYMBOL_GPL(crypto_alloc_sig); 86 87 int crypto_sig_maxsize(struct crypto_sig *tfm) 88 { 89 struct crypto_akcipher **ctx = crypto_sig_ctx(tfm); 90 91 return crypto_akcipher_maxsize(*ctx); 92 } 93 EXPORT_SYMBOL_GPL(crypto_sig_maxsize); 94 95 int crypto_sig_sign(struct crypto_sig *tfm, 96 const void *src, unsigned int slen, 97 void *dst, unsigned int dlen) 98 { 99 struct crypto_akcipher **ctx = crypto_sig_ctx(tfm); 100 struct crypto_akcipher_sync_data data = { 101 .tfm = *ctx, 102 .src = src, 103 .dst = dst, 104 .slen = slen, 105 .dlen = dlen, 106 }; 107 108 return crypto_akcipher_sync_prep(&data) ?: 109 crypto_akcipher_sync_post(&data, 110 crypto_akcipher_sign(data.req)); 111 } 112 EXPORT_SYMBOL_GPL(crypto_sig_sign); 113 114 int crypto_sig_verify(struct crypto_sig *tfm, 115 const void *src, unsigned int slen, 116 const void *digest, unsigned int dlen) 117 { 118 struct crypto_akcipher **ctx = crypto_sig_ctx(tfm); 119 struct crypto_akcipher_sync_data data = { 120 .tfm = *ctx, 121 .src = src, 122 .slen = slen, 123 .dlen = dlen, 124 }; 125 int err; 126 127 err = crypto_akcipher_sync_prep(&data); 128 if (err) 129 return err; 130 131 memcpy(data.buf + slen, digest, dlen); 132 133 return crypto_akcipher_sync_post(&data, 134 crypto_akcipher_verify(data.req)); 135 } 136 EXPORT_SYMBOL_GPL(crypto_sig_verify); 137 138 int crypto_sig_set_pubkey(struct crypto_sig *tfm, 139 const void *key, unsigned int keylen) 140 { 141 struct crypto_akcipher **ctx = crypto_sig_ctx(tfm); 142 143 return crypto_akcipher_set_pub_key(*ctx, key, keylen); 144 } 145 EXPORT_SYMBOL_GPL(crypto_sig_set_pubkey); 146 147 int crypto_sig_set_privkey(struct crypto_sig *tfm, 148 const void *key, unsigned int keylen) 149 { 150 struct crypto_akcipher **ctx = crypto_sig_ctx(tfm); 151 152 return crypto_akcipher_set_priv_key(*ctx, key, keylen); 153 } 154 EXPORT_SYMBOL_GPL(crypto_sig_set_privkey); 155 156 MODULE_LICENSE("GPL"); 157 MODULE_DESCRIPTION("Public Key Signature Algorithms"); 158