1 // SPDX-License-Identifier: GPL-2.0
4 * OFB: Output FeedBack mode
6 * Copyright (C) 2018 ARM Limited or its affiliates.
9 * Based loosely on public domain code gleaned from libtomcrypt
10 * (https://github.com/libtom/libtomcrypt).
13 #include <crypto/algapi.h>
14 #include <crypto/internal/skcipher.h>
15 #include <linux/err.h>
16 #include <linux/init.h>
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/scatterlist.h>
20 #include <linux/slab.h>
22 struct crypto_ofb_ctx
{
23 struct crypto_cipher
*child
;
28 static int crypto_ofb_setkey(struct crypto_skcipher
*parent
, const u8
*key
,
31 struct crypto_ofb_ctx
*ctx
= crypto_skcipher_ctx(parent
);
32 struct crypto_cipher
*child
= ctx
->child
;
35 crypto_cipher_clear_flags(child
, CRYPTO_TFM_REQ_MASK
);
36 crypto_cipher_set_flags(child
, crypto_skcipher_get_flags(parent
) &
38 err
= crypto_cipher_setkey(child
, key
, keylen
);
39 crypto_skcipher_set_flags(parent
, crypto_cipher_get_flags(child
) &
44 static int crypto_ofb_encrypt_segment(struct crypto_ofb_ctx
*ctx
,
45 struct skcipher_walk
*walk
,
46 struct crypto_cipher
*tfm
)
48 int bsize
= crypto_cipher_blocksize(tfm
);
49 int nbytes
= walk
->nbytes
;
51 u8
*src
= walk
->src
.virt
.addr
;
52 u8
*dst
= walk
->dst
.virt
.addr
;
56 if (ctx
->cnt
== bsize
) {
59 crypto_cipher_encrypt_one(tfm
, iv
, iv
);
62 *dst
= *src
^ iv
[ctx
->cnt
];
70 static int crypto_ofb_encrypt(struct skcipher_request
*req
)
72 struct skcipher_walk walk
;
73 struct crypto_skcipher
*tfm
= crypto_skcipher_reqtfm(req
);
75 struct crypto_ofb_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
76 struct crypto_cipher
*child
= ctx
->child
;
79 bsize
= crypto_cipher_blocksize(child
);
82 ret
= skcipher_walk_virt(&walk
, req
, false);
85 ret
= crypto_ofb_encrypt_segment(ctx
, &walk
, child
);
86 ret
= skcipher_walk_done(&walk
, ret
);
92 /* OFB encrypt and decrypt are identical */
93 static int crypto_ofb_decrypt(struct skcipher_request
*req
)
95 return crypto_ofb_encrypt(req
);
98 static int crypto_ofb_init_tfm(struct crypto_skcipher
*tfm
)
100 struct skcipher_instance
*inst
= skcipher_alg_instance(tfm
);
101 struct crypto_spawn
*spawn
= skcipher_instance_ctx(inst
);
102 struct crypto_ofb_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
103 struct crypto_cipher
*cipher
;
105 cipher
= crypto_spawn_cipher(spawn
);
107 return PTR_ERR(cipher
);
113 static void crypto_ofb_exit_tfm(struct crypto_skcipher
*tfm
)
115 struct crypto_ofb_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
117 crypto_free_cipher(ctx
->child
);
120 static void crypto_ofb_free(struct skcipher_instance
*inst
)
122 crypto_drop_skcipher(skcipher_instance_ctx(inst
));
126 static int crypto_ofb_create(struct crypto_template
*tmpl
, struct rtattr
**tb
)
128 struct skcipher_instance
*inst
;
129 struct crypto_attr_type
*algt
;
130 struct crypto_spawn
*spawn
;
131 struct crypto_alg
*alg
;
135 err
= crypto_check_attr_type(tb
, CRYPTO_ALG_TYPE_SKCIPHER
);
139 inst
= kzalloc(sizeof(*inst
) + sizeof(*spawn
), GFP_KERNEL
);
143 algt
= crypto_get_attr_type(tb
);
148 mask
= CRYPTO_ALG_TYPE_MASK
|
149 crypto_requires_off(algt
->type
, algt
->mask
,
150 CRYPTO_ALG_NEED_FALLBACK
);
152 alg
= crypto_get_attr_alg(tb
, CRYPTO_ALG_TYPE_CIPHER
, mask
);
157 spawn
= skcipher_instance_ctx(inst
);
158 err
= crypto_init_spawn(spawn
, alg
, skcipher_crypto_instance(inst
),
159 CRYPTO_ALG_TYPE_MASK
);
164 err
= crypto_inst_setname(skcipher_crypto_instance(inst
), "ofb", alg
);
168 inst
->alg
.base
.cra_priority
= alg
->cra_priority
;
169 inst
->alg
.base
.cra_blocksize
= alg
->cra_blocksize
;
170 inst
->alg
.base
.cra_alignmask
= alg
->cra_alignmask
;
172 /* We access the data as u32s when xoring. */
173 inst
->alg
.base
.cra_alignmask
|= __alignof__(u32
) - 1;
175 inst
->alg
.ivsize
= alg
->cra_blocksize
;
176 inst
->alg
.min_keysize
= alg
->cra_cipher
.cia_min_keysize
;
177 inst
->alg
.max_keysize
= alg
->cra_cipher
.cia_max_keysize
;
179 inst
->alg
.base
.cra_ctxsize
= sizeof(struct crypto_ofb_ctx
);
181 inst
->alg
.init
= crypto_ofb_init_tfm
;
182 inst
->alg
.exit
= crypto_ofb_exit_tfm
;
184 inst
->alg
.setkey
= crypto_ofb_setkey
;
185 inst
->alg
.encrypt
= crypto_ofb_encrypt
;
186 inst
->alg
.decrypt
= crypto_ofb_decrypt
;
188 inst
->free
= crypto_ofb_free
;
190 err
= skcipher_register_instance(tmpl
, inst
);
198 crypto_drop_spawn(spawn
);
204 static struct crypto_template crypto_ofb_tmpl
= {
206 .create
= crypto_ofb_create
,
207 .module
= THIS_MODULE
,
210 static int __init
crypto_ofb_module_init(void)
212 return crypto_register_template(&crypto_ofb_tmpl
);
215 static void __exit
crypto_ofb_module_exit(void)
217 crypto_unregister_template(&crypto_ofb_tmpl
);
220 module_init(crypto_ofb_module_init
);
221 module_exit(crypto_ofb_module_exit
);
223 MODULE_LICENSE("GPL");
224 MODULE_DESCRIPTION("OFB block cipher algorithm");
225 MODULE_ALIAS_CRYPTO("ofb");