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 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 32 static 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 38 static 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 48 static const struct crypto_type crypto_sig_type = { 49 .extsize = crypto_alg_extsize, 50 .init_tfm = crypto_sig_init_tfm, 51 #ifdef CONFIG_PROC_FS 52 .show = crypto_sig_show, 53 #endif 54 #if IS_ENABLED(CONFIG_CRYPTO_USER) 55 .report = crypto_sig_report, 56 #endif 57 .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 63 struct 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 } 67 EXPORT_SYMBOL_GPL(crypto_alloc_sig); 68 69 int 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 } 75 EXPORT_SYMBOL_GPL(crypto_sig_maxsize); 76 77 int 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 } 94 EXPORT_SYMBOL_GPL(crypto_sig_sign); 95 96 int 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 } 118 EXPORT_SYMBOL_GPL(crypto_sig_verify); 119 120 int 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 } 127 EXPORT_SYMBOL_GPL(crypto_sig_set_pubkey); 128 129 int 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 } 136 EXPORT_SYMBOL_GPL(crypto_sig_set_privkey); 137 138 MODULE_LICENSE("GPL"); 139 MODULE_DESCRIPTION("Public Key Signature Algorithms"); 140
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.