aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crypto/xcbc.c164
1 files changed, 73 insertions, 91 deletions
diff --git a/crypto/xcbc.c b/crypto/xcbc.c
index 9d502e67a5c0..1e30b31f33c6 100644
--- a/crypto/xcbc.c
+++ b/crypto/xcbc.c
@@ -26,69 +26,67 @@
26static u_int32_t ks[12] = {0x01010101, 0x01010101, 0x01010101, 0x01010101, 26static u_int32_t ks[12] = {0x01010101, 0x01010101, 0x01010101, 0x01010101,
27 0x02020202, 0x02020202, 0x02020202, 0x02020202, 27 0x02020202, 0x02020202, 0x02020202, 0x02020202,
28 0x03030303, 0x03030303, 0x03030303, 0x03030303}; 28 0x03030303, 0x03030303, 0x03030303, 0x03030303};
29
29/* 30/*
30 * +------------------------ 31 * +------------------------
31 * | <parent tfm> 32 * | <parent tfm>
32 * +------------------------ 33 * +------------------------
33 * | crypto_xcbc_ctx 34 * | xcbc_tfm_ctx
34 * +------------------------ 35 * +------------------------
35 * | odds (block size) 36 * | consts (block size * 2)
36 * +------------------------ 37 * +------------------------
37 * | prev (block size) 38 */
39struct xcbc_tfm_ctx {
40 struct crypto_cipher *child;
41 u8 ctx[];
42};
43
44/*
38 * +------------------------ 45 * +------------------------
39 * | key (block size) 46 * | <shash desc>
40 * +------------------------ 47 * +------------------------
41 * | consts (block size * 3) 48 * | xcbc_desc_ctx
49 * +------------------------
50 * | odds (block size)
51 * +------------------------
52 * | prev (block size)
42 * +------------------------ 53 * +------------------------
43 */ 54 */
44struct crypto_xcbc_ctx { 55struct xcbc_desc_ctx {
45 struct crypto_cipher *child;
46 u8 *odds;
47 u8 *prev;
48 u8 *key;
49 u8 *consts;
50 unsigned int keylen;
51 unsigned int len; 56 unsigned int len;
57 u8 ctx[];
52}; 58};
53 59
54static int _crypto_xcbc_digest_setkey(struct crypto_shash *parent, 60static int crypto_xcbc_digest_setkey(struct crypto_shash *parent,
55 struct crypto_xcbc_ctx *ctx) 61 const u8 *inkey, unsigned int keylen)
56{ 62{
63 unsigned long alignmask = crypto_shash_alignmask(parent);
64 struct xcbc_tfm_ctx *ctx = crypto_shash_ctx(parent);
57 int bs = crypto_shash_blocksize(parent); 65 int bs = crypto_shash_blocksize(parent);
66 u8 *consts = PTR_ALIGN(&ctx->ctx[0], alignmask + 1);
58 int err = 0; 67 int err = 0;
59 u8 key1[bs]; 68 u8 key1[bs];
60 69
61 if ((err = crypto_cipher_setkey(ctx->child, ctx->key, ctx->keylen))) 70 if ((err = crypto_cipher_setkey(ctx->child, inkey, keylen)))
62 return err; 71 return err;
63 72
64 crypto_cipher_encrypt_one(ctx->child, key1, ctx->consts); 73 crypto_cipher_encrypt_one(ctx->child, consts, (u8 *)ks + bs);
74 crypto_cipher_encrypt_one(ctx->child, consts + bs, (u8 *)ks + bs * 2);
75 crypto_cipher_encrypt_one(ctx->child, key1, (u8 *)ks);
65 76
66 return crypto_cipher_setkey(ctx->child, key1, bs); 77 return crypto_cipher_setkey(ctx->child, key1, bs);
67}
68
69static int crypto_xcbc_digest_setkey(struct crypto_shash *parent,
70 const u8 *inkey, unsigned int keylen)
71{
72 struct crypto_xcbc_ctx *ctx = crypto_shash_ctx(parent);
73
74 if (keylen != crypto_cipher_blocksize(ctx->child))
75 return -EINVAL;
76 78
77 ctx->keylen = keylen;
78 memcpy(ctx->key, inkey, keylen);
79 ctx->consts = (u8*)ks;
80
81 return _crypto_xcbc_digest_setkey(parent, ctx);
82} 79}
83 80
84static int crypto_xcbc_digest_init(struct shash_desc *pdesc) 81static int crypto_xcbc_digest_init(struct shash_desc *pdesc)
85{ 82{
86 struct crypto_xcbc_ctx *ctx = crypto_shash_ctx(pdesc->tfm); 83 unsigned long alignmask = crypto_shash_alignmask(pdesc->tfm);
84 struct xcbc_desc_ctx *ctx = shash_desc_ctx(pdesc);
87 int bs = crypto_shash_blocksize(pdesc->tfm); 85 int bs = crypto_shash_blocksize(pdesc->tfm);
86 u8 *prev = PTR_ALIGN(&ctx->ctx[0], alignmask + 1) + bs;
88 87
89 ctx->len = 0; 88 ctx->len = 0;
90 memset(ctx->odds, 0, bs); 89 memset(prev, 0, bs);
91 memset(ctx->prev, 0, bs);
92 90
93 return 0; 91 return 0;
94} 92}
@@ -97,39 +95,43 @@ static int crypto_xcbc_digest_update(struct shash_desc *pdesc, const u8 *p,
97 unsigned int len) 95 unsigned int len)
98{ 96{
99 struct crypto_shash *parent = pdesc->tfm; 97 struct crypto_shash *parent = pdesc->tfm;
100 struct crypto_xcbc_ctx *ctx = crypto_shash_ctx(parent); 98 unsigned long alignmask = crypto_shash_alignmask(parent);
101 struct crypto_cipher *tfm = ctx->child; 99 struct xcbc_tfm_ctx *tctx = crypto_shash_ctx(parent);
100 struct xcbc_desc_ctx *ctx = shash_desc_ctx(pdesc);
101 struct crypto_cipher *tfm = tctx->child;
102 int bs = crypto_shash_blocksize(parent); 102 int bs = crypto_shash_blocksize(parent);
103 u8 *odds = PTR_ALIGN(&ctx->ctx[0], alignmask + 1);
104 u8 *prev = odds + bs;
103 105
104 /* checking the data can fill the block */ 106 /* checking the data can fill the block */
105 if ((ctx->len + len) <= bs) { 107 if ((ctx->len + len) <= bs) {
106 memcpy(ctx->odds + ctx->len, p, len); 108 memcpy(odds + ctx->len, p, len);
107 ctx->len += len; 109 ctx->len += len;
108 return 0; 110 return 0;
109 } 111 }
110 112
111 /* filling odds with new data and encrypting it */ 113 /* filling odds with new data and encrypting it */
112 memcpy(ctx->odds + ctx->len, p, bs - ctx->len); 114 memcpy(odds + ctx->len, p, bs - ctx->len);
113 len -= bs - ctx->len; 115 len -= bs - ctx->len;
114 p += bs - ctx->len; 116 p += bs - ctx->len;
115 117
116 crypto_xor(ctx->prev, ctx->odds, bs); 118 crypto_xor(prev, odds, bs);
117 crypto_cipher_encrypt_one(tfm, ctx->prev, ctx->prev); 119 crypto_cipher_encrypt_one(tfm, prev, prev);
118 120
119 /* clearing the length */ 121 /* clearing the length */
120 ctx->len = 0; 122 ctx->len = 0;
121 123
122 /* encrypting the rest of data */ 124 /* encrypting the rest of data */
123 while (len > bs) { 125 while (len > bs) {
124 crypto_xor(ctx->prev, p, bs); 126 crypto_xor(prev, p, bs);
125 crypto_cipher_encrypt_one(tfm, ctx->prev, ctx->prev); 127 crypto_cipher_encrypt_one(tfm, prev, prev);
126 p += bs; 128 p += bs;
127 len -= bs; 129 len -= bs;
128 } 130 }
129 131
130 /* keeping the surplus of blocksize */ 132 /* keeping the surplus of blocksize */
131 if (len) { 133 if (len) {
132 memcpy(ctx->odds, p, len); 134 memcpy(odds, p, len);
133 ctx->len = len; 135 ctx->len = len;
134 } 136 }
135 137
@@ -139,29 +141,20 @@ static int crypto_xcbc_digest_update(struct shash_desc *pdesc, const u8 *p,
139static int crypto_xcbc_digest_final(struct shash_desc *pdesc, u8 *out) 141static int crypto_xcbc_digest_final(struct shash_desc *pdesc, u8 *out)
140{ 142{
141 struct crypto_shash *parent = pdesc->tfm; 143 struct crypto_shash *parent = pdesc->tfm;
142 struct crypto_xcbc_ctx *ctx = crypto_shash_ctx(parent); 144 unsigned long alignmask = crypto_shash_alignmask(parent);
143 struct crypto_cipher *tfm = ctx->child; 145 struct xcbc_tfm_ctx *tctx = crypto_shash_ctx(parent);
146 struct xcbc_desc_ctx *ctx = shash_desc_ctx(pdesc);
147 struct crypto_cipher *tfm = tctx->child;
144 int bs = crypto_shash_blocksize(parent); 148 int bs = crypto_shash_blocksize(parent);
145 int err = 0; 149 u8 *consts = PTR_ALIGN(&tctx->ctx[0], alignmask + 1);
150 u8 *odds = PTR_ALIGN(&ctx->ctx[0], alignmask + 1);
151 u8 *prev = odds + bs;
152 unsigned int offset = 0;
146 153
147 if (ctx->len == bs) { 154 if (ctx->len != bs) {
148 u8 key2[bs];
149
150 if ((err = crypto_cipher_setkey(tfm, ctx->key, ctx->keylen)) != 0)
151 return err;
152
153 crypto_cipher_encrypt_one(tfm, key2,
154 (u8 *)(ctx->consts + bs));
155
156 crypto_xor(ctx->prev, ctx->odds, bs);
157 crypto_xor(ctx->prev, key2, bs);
158 _crypto_xcbc_digest_setkey(parent, ctx);
159
160 crypto_cipher_encrypt_one(tfm, out, ctx->prev);
161 } else {
162 u8 key3[bs];
163 unsigned int rlen; 155 unsigned int rlen;
164 u8 *p = ctx->odds + ctx->len; 156 u8 *p = odds + ctx->len;
157
165 *p = 0x80; 158 *p = 0x80;
166 p++; 159 p++;
167 160
@@ -169,19 +162,13 @@ static int crypto_xcbc_digest_final(struct shash_desc *pdesc, u8 *out)
169 if (rlen) 162 if (rlen)
170 memset(p, 0, rlen); 163 memset(p, 0, rlen);
171 164
172 if ((err = crypto_cipher_setkey(tfm, ctx->key, ctx->keylen)) != 0) 165 offset += bs;
173 return err; 166 }
174
175 crypto_cipher_encrypt_one(tfm, key3,
176 (u8 *)(ctx->consts + bs * 2));
177 167
178 crypto_xor(ctx->prev, ctx->odds, bs); 168 crypto_xor(prev, odds, bs);
179 crypto_xor(ctx->prev, key3, bs); 169 crypto_xor(prev, consts + offset, bs);
180 170
181 _crypto_xcbc_digest_setkey(parent, ctx); 171 crypto_cipher_encrypt_one(tfm, out, prev);
182
183 crypto_cipher_encrypt_one(tfm, out, ctx->prev);
184 }
185 172
186 return 0; 173 return 0;
187} 174}
@@ -191,31 +178,20 @@ static int xcbc_init_tfm(struct crypto_tfm *tfm)
191 struct crypto_cipher *cipher; 178 struct crypto_cipher *cipher;
192 struct crypto_instance *inst = (void *)tfm->__crt_alg; 179 struct crypto_instance *inst = (void *)tfm->__crt_alg;
193 struct crypto_spawn *spawn = crypto_instance_ctx(inst); 180 struct crypto_spawn *spawn = crypto_instance_ctx(inst);
194 struct crypto_xcbc_ctx *ctx = crypto_tfm_ctx(tfm); 181 struct xcbc_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
195 int bs = crypto_tfm_alg_blocksize(tfm);
196 182
197 cipher = crypto_spawn_cipher(spawn); 183 cipher = crypto_spawn_cipher(spawn);
198 if (IS_ERR(cipher)) 184 if (IS_ERR(cipher))
199 return PTR_ERR(cipher); 185 return PTR_ERR(cipher);
200 186
201 switch(bs) {
202 case 16:
203 break;
204 default:
205 return -EINVAL;
206 }
207
208 ctx->child = cipher; 187 ctx->child = cipher;
209 ctx->odds = (u8*)(ctx+1);
210 ctx->prev = ctx->odds + bs;
211 ctx->key = ctx->prev + bs;
212 188
213 return 0; 189 return 0;
214}; 190};
215 191
216static void xcbc_exit_tfm(struct crypto_tfm *tfm) 192static void xcbc_exit_tfm(struct crypto_tfm *tfm)
217{ 193{
218 struct crypto_xcbc_ctx *ctx = crypto_tfm_ctx(tfm); 194 struct xcbc_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
219 crypto_free_cipher(ctx->child); 195 crypto_free_cipher(ctx->child);
220} 196}
221 197
@@ -254,12 +230,18 @@ static int xcbc_create(struct crypto_template *tmpl, struct rtattr **tb)
254 230
255 inst->alg.base.cra_priority = alg->cra_priority; 231 inst->alg.base.cra_priority = alg->cra_priority;
256 inst->alg.base.cra_blocksize = alg->cra_blocksize; 232 inst->alg.base.cra_blocksize = alg->cra_blocksize;
257 inst->alg.base.cra_alignmask = alg->cra_alignmask; 233 inst->alg.base.cra_alignmask = alg->cra_alignmask | 3;
258 234
259 inst->alg.digestsize = alg->cra_blocksize; 235 inst->alg.digestsize = alg->cra_blocksize;
260 inst->alg.base.cra_ctxsize = sizeof(struct crypto_xcbc_ctx) + 236 inst->alg.descsize = ALIGN(sizeof(struct xcbc_desc_ctx),
261 ALIGN(alg->cra_blocksize * 3, 237 crypto_tfm_ctx_alignment()) +
262 sizeof(void *)); 238 (alg->cra_alignmask &
239 ~(crypto_tfm_ctx_alignment() - 1)) +
240 alg->cra_blocksize * 2;
241
242 inst->alg.base.cra_ctxsize = ALIGN(sizeof(struct xcbc_tfm_ctx),
243 alg->cra_alignmask) +
244 alg->cra_blocksize * 2;
263 inst->alg.base.cra_init = xcbc_init_tfm; 245 inst->alg.base.cra_init = xcbc_init_tfm;
264 inst->alg.base.cra_exit = xcbc_exit_tfm; 246 inst->alg.base.cra_exit = xcbc_exit_tfm;
265 247