Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[CRYPTO] authenc: Add givencrypt operation

This patch implements the givencrypt function for authenc. It simply
calls the givencrypt operation on the underlying cipher instead of encrypt.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

+114 -22
+114 -22
crypto/authenc.c
··· 10 10 * 11 11 */ 12 12 13 + #include <crypto/aead.h> 13 14 #include <crypto/internal/skcipher.h> 14 15 #include <crypto/authenc.h> 15 16 #include <crypto/scatterwalk.h> ··· 88 87 goto out; 89 88 } 90 89 90 + static void authenc_chain(struct scatterlist *head, struct scatterlist *sg, 91 + int chain) 92 + { 93 + if (chain) { 94 + head->length += sg->length; 95 + sg = scatterwalk_sg_next(sg); 96 + } 97 + 98 + if (sg) 99 + scatterwalk_sg_chain(head, 2, sg); 100 + else 101 + sg_mark_end(head); 102 + } 103 + 91 104 static u8 *crypto_authenc_hash(struct aead_request *req, unsigned int flags, 92 105 struct scatterlist *cipher, 93 106 unsigned int cryptlen) ··· 142 127 return hash; 143 128 } 144 129 145 - static int crypto_authenc_genicv(struct aead_request *req, unsigned int flags) 130 + static int crypto_authenc_genicv(struct aead_request *req, u8 *iv, 131 + unsigned int flags) 146 132 { 147 133 struct crypto_aead *authenc = crypto_aead_reqtfm(req); 148 134 struct scatterlist *dst = req->dst; 149 - unsigned int cryptlen = req->cryptlen; 135 + struct scatterlist cipher[2]; 136 + struct page *dstp; 137 + unsigned int ivsize = crypto_aead_ivsize(authenc); 138 + unsigned int cryptlen; 139 + u8 *vdst; 150 140 u8 *hash; 151 141 152 - hash = crypto_authenc_hash(req, flags, dst, cryptlen); 142 + dstp = sg_page(dst); 143 + vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + dst->offset; 144 + 145 + sg_init_table(cipher, 2); 146 + sg_set_buf(cipher, iv, ivsize); 147 + authenc_chain(cipher, dst, vdst == iv + ivsize); 148 + 149 + cryptlen = req->cryptlen + ivsize; 150 + hash = crypto_authenc_hash(req, flags, cipher, cryptlen); 153 151 if (IS_ERR(hash)) 154 152 return PTR_ERR(hash); 155 153 156 - scatterwalk_map_and_copy(hash, dst, cryptlen, 154 + scatterwalk_map_and_copy(hash, cipher, cryptlen, 157 155 crypto_aead_authsize(authenc), 1); 158 156 return 0; 159 157 } ··· 174 146 static void crypto_authenc_encrypt_done(struct crypto_async_request *req, 175 147 int err) 176 148 { 177 - if (!err) 178 - err = crypto_authenc_genicv(req->data, 0); 149 + if (!err) { 150 + struct aead_request *areq = req->data; 151 + struct crypto_aead *authenc = crypto_aead_reqtfm(areq); 152 + struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); 153 + struct ablkcipher_request *abreq = aead_request_ctx(areq); 154 + u8 *iv = (u8 *)(abreq + 1) + 155 + crypto_ablkcipher_reqsize(ctx->enc); 156 + 157 + err = crypto_authenc_genicv(areq, iv, 0); 158 + } 179 159 180 160 aead_request_complete(req->data, err); 181 161 } ··· 193 157 struct crypto_aead *authenc = crypto_aead_reqtfm(req); 194 158 struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); 195 159 struct ablkcipher_request *abreq = aead_request_ctx(req); 160 + struct crypto_ablkcipher *enc = ctx->enc; 161 + struct scatterlist *dst = req->dst; 162 + unsigned int cryptlen = req->cryptlen; 163 + u8 *iv = (u8 *)(abreq + 1) + crypto_ablkcipher_reqsize(enc); 196 164 int err; 197 165 198 - ablkcipher_request_set_tfm(abreq, ctx->enc); 166 + ablkcipher_request_set_tfm(abreq, enc); 199 167 ablkcipher_request_set_callback(abreq, aead_request_flags(req), 200 168 crypto_authenc_encrypt_done, req); 201 - ablkcipher_request_set_crypt(abreq, req->src, req->dst, req->cryptlen, 202 - req->iv); 169 + ablkcipher_request_set_crypt(abreq, req->src, dst, cryptlen, req->iv); 170 + 171 + memcpy(iv, req->iv, crypto_aead_ivsize(authenc)); 203 172 204 173 err = crypto_ablkcipher_encrypt(abreq); 205 174 if (err) 206 175 return err; 207 176 208 - return crypto_authenc_genicv(req, CRYPTO_TFM_REQ_MAY_SLEEP); 177 + return crypto_authenc_genicv(req, iv, CRYPTO_TFM_REQ_MAY_SLEEP); 178 + } 179 + 180 + static void crypto_authenc_givencrypt_done(struct crypto_async_request *req, 181 + int err) 182 + { 183 + if (!err) { 184 + struct aead_givcrypt_request *greq = req->data; 185 + 186 + err = crypto_authenc_genicv(&greq->areq, greq->giv, 0); 187 + } 188 + 189 + aead_request_complete(req->data, err); 190 + } 191 + 192 + static int crypto_authenc_givencrypt(struct aead_givcrypt_request *req) 193 + { 194 + struct crypto_aead *authenc = aead_givcrypt_reqtfm(req); 195 + struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); 196 + struct aead_request *areq = &req->areq; 197 + struct skcipher_givcrypt_request *greq = aead_request_ctx(areq); 198 + u8 *iv = req->giv; 199 + int err; 200 + 201 + skcipher_givcrypt_set_tfm(greq, ctx->enc); 202 + skcipher_givcrypt_set_callback(greq, aead_request_flags(areq), 203 + crypto_authenc_givencrypt_done, areq); 204 + skcipher_givcrypt_set_crypt(greq, areq->src, areq->dst, areq->cryptlen, 205 + areq->iv); 206 + skcipher_givcrypt_set_giv(greq, iv, req->seq); 207 + 208 + err = crypto_skcipher_givencrypt(greq); 209 + if (err) 210 + return err; 211 + 212 + return crypto_authenc_genicv(areq, iv, CRYPTO_TFM_REQ_MAY_SLEEP); 209 213 } 210 214 211 215 static int crypto_authenc_verify(struct aead_request *req, 216 + struct scatterlist *cipher, 212 217 unsigned int cryptlen) 213 218 { 214 219 struct crypto_aead *authenc = crypto_aead_reqtfm(req); 215 220 u8 *ohash; 216 221 u8 *ihash; 217 - struct scatterlist *src = req->src; 218 222 unsigned int authsize; 219 223 220 - ohash = crypto_authenc_hash(req, CRYPTO_TFM_REQ_MAY_SLEEP, src, 224 + ohash = crypto_authenc_hash(req, CRYPTO_TFM_REQ_MAY_SLEEP, cipher, 221 225 cryptlen); 222 226 if (IS_ERR(ohash)) 223 227 return PTR_ERR(ohash); 224 228 225 229 authsize = crypto_aead_authsize(authenc); 226 230 ihash = ohash + authsize; 227 - scatterwalk_map_and_copy(ihash, src, cryptlen, authsize, 0); 231 + scatterwalk_map_and_copy(ihash, cipher, cryptlen, authsize, 0); 228 232 return memcmp(ihash, ohash, authsize) ? -EBADMSG: 0; 229 233 } 230 234 231 - static void crypto_authenc_decrypt_done(struct crypto_async_request *req, 232 - int err) 235 + static int crypto_authenc_iverify(struct aead_request *req, u8 *iv, 236 + unsigned int cryptlen) 233 237 { 234 - aead_request_complete(req->data, err); 238 + struct crypto_aead *authenc = crypto_aead_reqtfm(req); 239 + struct scatterlist *src = req->src; 240 + struct scatterlist cipher[2]; 241 + struct page *srcp; 242 + unsigned int ivsize = crypto_aead_ivsize(authenc); 243 + u8 *vsrc; 244 + 245 + srcp = sg_page(src); 246 + vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + src->offset; 247 + 248 + sg_init_table(cipher, 2); 249 + sg_set_buf(cipher, iv, ivsize); 250 + authenc_chain(cipher, src, vsrc == iv + ivsize); 251 + 252 + return crypto_authenc_verify(req, cipher, cryptlen + ivsize); 235 253 } 236 254 237 255 static int crypto_authenc_decrypt(struct aead_request *req) ··· 295 205 struct ablkcipher_request *abreq = aead_request_ctx(req); 296 206 unsigned int cryptlen = req->cryptlen; 297 207 unsigned int authsize = crypto_aead_authsize(authenc); 208 + u8 *iv = req->iv; 298 209 int err; 299 210 300 211 if (cryptlen < authsize) 301 212 return -EINVAL; 302 213 cryptlen -= authsize; 303 214 304 - err = crypto_authenc_verify(req, cryptlen); 215 + err = crypto_authenc_iverify(req, iv, cryptlen); 305 216 if (err) 306 217 return err; 307 218 308 219 ablkcipher_request_set_tfm(abreq, ctx->enc); 309 220 ablkcipher_request_set_callback(abreq, aead_request_flags(req), 310 - crypto_authenc_decrypt_done, req); 311 - ablkcipher_request_set_crypt(abreq, req->src, req->dst, cryptlen, 312 - req->iv); 221 + req->base.complete, req->base.data); 222 + ablkcipher_request_set_crypt(abreq, req->src, req->dst, cryptlen, iv); 313 223 314 224 return crypto_ablkcipher_decrypt(abreq); 315 225 } ··· 338 248 (crypto_hash_alignmask(auth) & 339 249 ~(crypto_tfm_ctx_alignment() - 1)) + 340 250 crypto_hash_digestsize(auth) * 2, 341 - sizeof(struct ablkcipher_request) + 342 - crypto_ablkcipher_reqsize(enc)); 251 + sizeof(struct skcipher_givcrypt_request) + 252 + crypto_ablkcipher_reqsize(enc) + 253 + crypto_ablkcipher_ivsize(enc)); 343 254 344 255 spin_lock_init(&ctx->auth_lock); 345 256 ··· 438 347 inst->alg.cra_aead.setkey = crypto_authenc_setkey; 439 348 inst->alg.cra_aead.encrypt = crypto_authenc_encrypt; 440 349 inst->alg.cra_aead.decrypt = crypto_authenc_decrypt; 350 + inst->alg.cra_aead.givencrypt = crypto_authenc_givencrypt; 441 351 442 352 out: 443 353 crypto_mod_put(auth);