diff options
-rw-r--r-- | crypto/ctr.c | 64 |
1 files changed, 33 insertions, 31 deletions
diff --git a/crypto/ctr.c b/crypto/ctr.c index b816e959fa55..57da7d0affcb 100644 --- a/crypto/ctr.c +++ b/crypto/ctr.c | |||
@@ -59,6 +59,21 @@ static int crypto_ctr_setkey(struct crypto_tfm *parent, const u8 *key, | |||
59 | return err; | 59 | return err; |
60 | } | 60 | } |
61 | 61 | ||
62 | static void crypto_ctr_crypt_final(struct blkcipher_walk *walk, | ||
63 | struct crypto_cipher *tfm, u8 *ctrblk, | ||
64 | unsigned int countersize) | ||
65 | { | ||
66 | unsigned int bsize = crypto_cipher_blocksize(tfm); | ||
67 | u8 *keystream = ctrblk + bsize; | ||
68 | u8 *src = walk->src.virt.addr; | ||
69 | u8 *dst = walk->dst.virt.addr; | ||
70 | unsigned int nbytes = walk->nbytes; | ||
71 | |||
72 | crypto_cipher_encrypt_one(tfm, keystream, ctrblk); | ||
73 | crypto_xor(keystream, src, nbytes); | ||
74 | memcpy(dst, keystream, nbytes); | ||
75 | } | ||
76 | |||
62 | static int crypto_ctr_crypt_segment(struct blkcipher_walk *walk, | 77 | static int crypto_ctr_crypt_segment(struct blkcipher_walk *walk, |
63 | struct crypto_cipher *tfm, u8 *ctrblk, | 78 | struct crypto_cipher *tfm, u8 *ctrblk, |
64 | unsigned int countersize) | 79 | unsigned int countersize) |
@@ -66,35 +81,23 @@ static int crypto_ctr_crypt_segment(struct blkcipher_walk *walk, | |||
66 | void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = | 81 | void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = |
67 | crypto_cipher_alg(tfm)->cia_encrypt; | 82 | crypto_cipher_alg(tfm)->cia_encrypt; |
68 | unsigned int bsize = crypto_cipher_blocksize(tfm); | 83 | unsigned int bsize = crypto_cipher_blocksize(tfm); |
69 | unsigned long alignmask = crypto_cipher_alignmask(tfm) | | ||
70 | (__alignof__(u32) - 1); | ||
71 | u8 ks[bsize + alignmask]; | ||
72 | u8 *keystream = (u8 *)ALIGN((unsigned long)ks, alignmask + 1); | ||
73 | u8 *src = walk->src.virt.addr; | 84 | u8 *src = walk->src.virt.addr; |
74 | u8 *dst = walk->dst.virt.addr; | 85 | u8 *dst = walk->dst.virt.addr; |
75 | unsigned int nbytes = walk->nbytes; | 86 | unsigned int nbytes = walk->nbytes; |
76 | 87 | ||
77 | do { | 88 | do { |
78 | /* create keystream */ | 89 | /* create keystream */ |
79 | fn(crypto_cipher_tfm(tfm), keystream, ctrblk); | 90 | fn(crypto_cipher_tfm(tfm), dst, ctrblk); |
80 | crypto_xor(keystream, src, min(nbytes, bsize)); | 91 | crypto_xor(dst, src, bsize); |
81 | |||
82 | /* copy result into dst */ | ||
83 | memcpy(dst, keystream, min(nbytes, bsize)); | ||
84 | 92 | ||
85 | /* increment counter in counterblock */ | 93 | /* increment counter in counterblock */ |
86 | crypto_inc(ctrblk + bsize - countersize, countersize); | 94 | crypto_inc(ctrblk + bsize - countersize, countersize); |
87 | 95 | ||
88 | if (nbytes < bsize) | ||
89 | break; | ||
90 | |||
91 | src += bsize; | 96 | src += bsize; |
92 | dst += bsize; | 97 | dst += bsize; |
93 | nbytes -= bsize; | 98 | } while ((nbytes -= bsize) >= bsize); |
94 | |||
95 | } while (nbytes); | ||
96 | 99 | ||
97 | return 0; | 100 | return nbytes; |
98 | } | 101 | } |
99 | 102 | ||
100 | static int crypto_ctr_crypt_inplace(struct blkcipher_walk *walk, | 103 | static int crypto_ctr_crypt_inplace(struct blkcipher_walk *walk, |
@@ -104,30 +107,22 @@ static int crypto_ctr_crypt_inplace(struct blkcipher_walk *walk, | |||
104 | void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = | 107 | void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = |
105 | crypto_cipher_alg(tfm)->cia_encrypt; | 108 | crypto_cipher_alg(tfm)->cia_encrypt; |
106 | unsigned int bsize = crypto_cipher_blocksize(tfm); | 109 | unsigned int bsize = crypto_cipher_blocksize(tfm); |
107 | unsigned long alignmask = crypto_cipher_alignmask(tfm) | | ||
108 | (__alignof__(u32) - 1); | ||
109 | unsigned int nbytes = walk->nbytes; | 110 | unsigned int nbytes = walk->nbytes; |
110 | u8 *src = walk->src.virt.addr; | 111 | u8 *src = walk->src.virt.addr; |
111 | u8 ks[bsize + alignmask]; | 112 | u8 *keystream = ctrblk + bsize; |
112 | u8 *keystream = (u8 *)ALIGN((unsigned long)ks, alignmask + 1); | ||
113 | 113 | ||
114 | do { | 114 | do { |
115 | /* create keystream */ | 115 | /* create keystream */ |
116 | fn(crypto_cipher_tfm(tfm), keystream, ctrblk); | 116 | fn(crypto_cipher_tfm(tfm), keystream, ctrblk); |
117 | crypto_xor(src, keystream, min(nbytes, bsize)); | 117 | crypto_xor(src, keystream, bsize); |
118 | 118 | ||
119 | /* increment counter in counterblock */ | 119 | /* increment counter in counterblock */ |
120 | crypto_inc(ctrblk + bsize - countersize, countersize); | 120 | crypto_inc(ctrblk + bsize - countersize, countersize); |
121 | 121 | ||
122 | if (nbytes < bsize) | ||
123 | break; | ||
124 | |||
125 | src += bsize; | 122 | src += bsize; |
126 | nbytes -= bsize; | 123 | } while ((nbytes -= bsize) >= bsize); |
127 | 124 | ||
128 | } while (nbytes); | 125 | return nbytes; |
129 | |||
130 | return 0; | ||
131 | } | 126 | } |
132 | 127 | ||
133 | static int crypto_ctr_crypt(struct blkcipher_desc *desc, | 128 | static int crypto_ctr_crypt(struct blkcipher_desc *desc, |
@@ -143,7 +138,7 @@ static int crypto_ctr_crypt(struct blkcipher_desc *desc, | |||
143 | crypto_instance_ctx(crypto_tfm_alg_instance(&tfm->base)); | 138 | crypto_instance_ctx(crypto_tfm_alg_instance(&tfm->base)); |
144 | unsigned long alignmask = crypto_cipher_alignmask(child) | | 139 | unsigned long alignmask = crypto_cipher_alignmask(child) | |
145 | (__alignof__(u32) - 1); | 140 | (__alignof__(u32) - 1); |
146 | u8 cblk[bsize + alignmask]; | 141 | u8 cblk[bsize * 2 + alignmask]; |
147 | u8 *counterblk = (u8 *)ALIGN((unsigned long)cblk, alignmask + 1); | 142 | u8 *counterblk = (u8 *)ALIGN((unsigned long)cblk, alignmask + 1); |
148 | int err; | 143 | int err; |
149 | 144 | ||
@@ -158,7 +153,7 @@ static int crypto_ctr_crypt(struct blkcipher_desc *desc, | |||
158 | /* initialize counter portion of counter block */ | 153 | /* initialize counter portion of counter block */ |
159 | crypto_inc(counterblk + bsize - ictx->countersize, ictx->countersize); | 154 | crypto_inc(counterblk + bsize - ictx->countersize, ictx->countersize); |
160 | 155 | ||
161 | while (walk.nbytes) { | 156 | while (walk.nbytes >= bsize) { |
162 | if (walk.src.virt.addr == walk.dst.virt.addr) | 157 | if (walk.src.virt.addr == walk.dst.virt.addr) |
163 | nbytes = crypto_ctr_crypt_inplace(&walk, child, | 158 | nbytes = crypto_ctr_crypt_inplace(&walk, child, |
164 | counterblk, | 159 | counterblk, |
@@ -170,6 +165,13 @@ static int crypto_ctr_crypt(struct blkcipher_desc *desc, | |||
170 | 165 | ||
171 | err = blkcipher_walk_done(desc, &walk, nbytes); | 166 | err = blkcipher_walk_done(desc, &walk, nbytes); |
172 | } | 167 | } |
168 | |||
169 | if (walk.nbytes) { | ||
170 | crypto_ctr_crypt_final(&walk, child, counterblk, | ||
171 | ictx->countersize); | ||
172 | err = blkcipher_walk_done(desc, &walk, 0); | ||
173 | } | ||
174 | |||
173 | return err; | 175 | return err; |
174 | } | 176 | } |
175 | 177 | ||
@@ -277,7 +279,7 @@ static struct crypto_instance *crypto_ctr_alloc(struct rtattr **tb) | |||
277 | inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER; | 279 | inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER; |
278 | inst->alg.cra_priority = alg->cra_priority; | 280 | inst->alg.cra_priority = alg->cra_priority; |
279 | inst->alg.cra_blocksize = 1; | 281 | inst->alg.cra_blocksize = 1; |
280 | inst->alg.cra_alignmask = __alignof__(u32) - 1; | 282 | inst->alg.cra_alignmask = alg->cra_alignmask | (__alignof__(u32) - 1); |
281 | inst->alg.cra_type = &crypto_blkcipher_type; | 283 | inst->alg.cra_type = &crypto_blkcipher_type; |
282 | 284 | ||
283 | inst->alg.cra_blkcipher.ivsize = ivsize; | 285 | inst->alg.cra_blkcipher.ivsize = ivsize; |