1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C)2006 USAGI/WIDE Project 4 * 5 * Author: 6 * Kazunori Miyazawa <miyazawa@linux-ipv6.org> 7 */ 8 9 #include <crypto/internal/cipher.h> 10 #include <crypto/internal/hash.h> 11 #include <crypto/utils.h> 12 #include <linux/err.h> 13 #include <linux/kernel.h> 14 #include <linux/module.h> 15 #include <linux/slab.h> 16 #include <linux/string.h> 17 18 static u_int32_t ks[12] = {0x01010101, 0x01010101, 0x01010101, 0x01010101, 19 0x02020202, 0x02020202, 0x02020202, 0x02020202, 20 0x03030303, 0x03030303, 0x03030303, 0x03030303}; 21 22 /* 23 * +------------------------ 24 * | <parent tfm> 25 * +------------------------ 26 * | xcbc_tfm_ctx 27 * +------------------------ 28 * | consts (block size * 2) 29 * +------------------------ 30 */ 31 struct xcbc_tfm_ctx { 32 struct crypto_cipher *child; 33 u8 consts[]; 34 }; 35 36 #define XCBC_BLOCKSIZE 16 37 38 static int crypto_xcbc_digest_setkey(struct crypto_shash *parent, 39 const u8 *inkey, unsigned int keylen) 40 { 41 struct xcbc_tfm_ctx *ctx = crypto_shash_ctx(parent); 42 u8 *consts = ctx->consts; 43 int err = 0; 44 u8 key1[XCBC_BLOCKSIZE]; 45 int bs = sizeof(key1); 46 47 if ((err = crypto_cipher_setkey(ctx->child, inkey, keylen))) 48 return err; 49 50 crypto_cipher_encrypt_one(ctx->child, consts, (u8 *)ks + bs); 51 crypto_cipher_encrypt_one(ctx->child, consts + bs, (u8 *)ks + bs * 2); 52 crypto_cipher_encrypt_one(ctx->child, key1, (u8 *)ks); 53 54 return crypto_cipher_setkey(ctx->child, key1, bs); 55 56 } 57 58 static int crypto_xcbc_digest_init(struct shash_desc *pdesc) 59 { 60 int bs = crypto_shash_blocksize(pdesc->tfm); 61 u8 *prev = shash_desc_ctx(pdesc); 62 63 memset(prev, 0, bs); 64 return 0; 65 } 66 67 static int crypto_xcbc_digest_update(struct shash_desc *pdesc, const u8 *p, 68 unsigned int len) 69 { 70 struct crypto_shash *parent = pdesc->tfm; 71 struct xcbc_tfm_ctx *tctx = crypto_shash_ctx(parent); 72 struct crypto_cipher *tfm = tctx->child; 73 int bs = crypto_shash_blocksize(parent); 74 u8 *prev = shash_desc_ctx(pdesc); 75 76 do { 77 crypto_xor(prev, p, bs); 78 crypto_cipher_encrypt_one(tfm, prev, prev); 79 p += bs; 80 len -= bs; 81 } while (len >= bs); 82 return len; 83 } 84 85 static int crypto_xcbc_digest_finup(struct shash_desc *pdesc, const u8 *src, 86 unsigned int len, u8 *out) 87 { 88 struct crypto_shash *parent = pdesc->tfm; 89 struct xcbc_tfm_ctx *tctx = crypto_shash_ctx(parent); 90 struct crypto_cipher *tfm = tctx->child; 91 int bs = crypto_shash_blocksize(parent); 92 u8 *prev = shash_desc_ctx(pdesc); 93 unsigned int offset = 0; 94 95 crypto_xor(prev, src, len); 96 if (len != bs) { 97 prev[len] ^= 0x80; 98 offset += bs; 99 } 100 crypto_xor(prev, &tctx->consts[offset], bs); 101 crypto_cipher_encrypt_one(tfm, out, prev); 102 return 0; 103 } 104 105 static int xcbc_init_tfm(struct crypto_tfm *tfm) 106 { 107 struct crypto_cipher *cipher; 108 struct crypto_instance *inst = (void *)tfm->__crt_alg; 109 struct crypto_cipher_spawn *spawn = crypto_instance_ctx(inst); 110 struct xcbc_tfm_ctx *ctx = crypto_tfm_ctx(tfm); 111 112 cipher = crypto_spawn_cipher(spawn); 113 if (IS_ERR(cipher)) 114 return PTR_ERR(cipher); 115 116 ctx->child = cipher; 117 118 return 0; 119 }; 120 121 static void xcbc_exit_tfm(struct crypto_tfm *tfm) 122 { 123 struct xcbc_tfm_ctx *ctx = crypto_tfm_ctx(tfm); 124 crypto_free_cipher(ctx->child); 125 } 126 127 static int xcbc_create(struct crypto_template *tmpl, struct rtattr **tb) 128 { 129 struct shash_instance *inst; 130 struct crypto_cipher_spawn *spawn; 131 struct crypto_alg *alg; 132 u32 mask; 133 int err; 134 135 err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH, &mask); 136 if (err) 137 return err; 138 139 inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); 140 if (!inst) 141 return -ENOMEM; 142 spawn = shash_instance_ctx(inst); 143 144 err = crypto_grab_cipher(spawn, shash_crypto_instance(inst), 145 crypto_attr_alg_name(tb[1]), 0, mask); 146 if (err) 147 goto err_free_inst; 148 alg = crypto_spawn_cipher_alg(spawn); 149 150 err = -EINVAL; 151 if (alg->cra_blocksize != XCBC_BLOCKSIZE) 152 goto err_free_inst; 153 154 err = crypto_inst_setname(shash_crypto_instance(inst), tmpl->name, alg); 155 if (err) 156 goto err_free_inst; 157 158 inst->alg.base.cra_priority = alg->cra_priority; 159 inst->alg.base.cra_blocksize = alg->cra_blocksize; 160 inst->alg.base.cra_ctxsize = sizeof(struct xcbc_tfm_ctx) + 161 alg->cra_blocksize * 2; 162 inst->alg.base.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY | 163 CRYPTO_AHASH_ALG_FINAL_NONZERO; 164 165 inst->alg.digestsize = alg->cra_blocksize; 166 inst->alg.descsize = alg->cra_blocksize; 167 168 inst->alg.base.cra_init = xcbc_init_tfm; 169 inst->alg.base.cra_exit = xcbc_exit_tfm; 170 171 inst->alg.init = crypto_xcbc_digest_init; 172 inst->alg.update = crypto_xcbc_digest_update; 173 inst->alg.finup = crypto_xcbc_digest_finup; 174 inst->alg.setkey = crypto_xcbc_digest_setkey; 175 176 inst->free = shash_free_singlespawn_instance; 177 178 err = shash_register_instance(tmpl, inst); 179 if (err) { 180 err_free_inst: 181 shash_free_singlespawn_instance(inst); 182 } 183 return err; 184 } 185 186 static struct crypto_template crypto_xcbc_tmpl = { 187 .name = "xcbc", 188 .create = xcbc_create, 189 .module = THIS_MODULE, 190 }; 191 192 static int __init crypto_xcbc_module_init(void) 193 { 194 return crypto_register_template(&crypto_xcbc_tmpl); 195 } 196 197 static void __exit crypto_xcbc_module_exit(void) 198 { 199 crypto_unregister_template(&crypto_xcbc_tmpl); 200 } 201 202 module_init(crypto_xcbc_module_init); 203 module_exit(crypto_xcbc_module_exit); 204 205 MODULE_LICENSE("GPL"); 206 MODULE_DESCRIPTION("XCBC keyed hash algorithm"); 207 MODULE_ALIAS_CRYPTO("xcbc"); 208 MODULE_IMPORT_NS("CRYPTO_INTERNAL"); 209