diff options
Diffstat (limited to 'crypto/authenc.c')
-rw-r--r-- | crypto/authenc.c | 66 |
1 files changed, 28 insertions, 38 deletions
diff --git a/crypto/authenc.c b/crypto/authenc.c index aa442dea5c43..394e73308e31 100644 --- a/crypto/authenc.c +++ b/crypto/authenc.c | |||
@@ -87,17 +87,18 @@ badkey: | |||
87 | goto out; | 87 | goto out; |
88 | } | 88 | } |
89 | 89 | ||
90 | static int crypto_authenc_hash(struct aead_request *req) | 90 | static u8 *crypto_authenc_hash(struct aead_request *req, unsigned int flags, |
91 | struct scatterlist *cipher, | ||
92 | unsigned int cryptlen) | ||
91 | { | 93 | { |
92 | struct crypto_aead *authenc = crypto_aead_reqtfm(req); | 94 | struct crypto_aead *authenc = crypto_aead_reqtfm(req); |
93 | struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); | 95 | struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); |
94 | struct crypto_hash *auth = ctx->auth; | 96 | struct crypto_hash *auth = ctx->auth; |
95 | struct hash_desc desc = { | 97 | struct hash_desc desc = { |
96 | .tfm = auth, | 98 | .tfm = auth, |
99 | .flags = aead_request_flags(req) & flags, | ||
97 | }; | 100 | }; |
98 | u8 *hash = aead_request_ctx(req); | 101 | u8 *hash = aead_request_ctx(req); |
99 | struct scatterlist *dst = req->dst; | ||
100 | unsigned int cryptlen = req->cryptlen; | ||
101 | int err; | 102 | int err; |
102 | 103 | ||
103 | hash = (u8 *)ALIGN((unsigned long)hash + crypto_hash_alignmask(auth), | 104 | hash = (u8 *)ALIGN((unsigned long)hash + crypto_hash_alignmask(auth), |
@@ -112,7 +113,7 @@ static int crypto_authenc_hash(struct aead_request *req) | |||
112 | if (err) | 113 | if (err) |
113 | goto auth_unlock; | 114 | goto auth_unlock; |
114 | 115 | ||
115 | err = crypto_hash_update(&desc, dst, cryptlen); | 116 | err = crypto_hash_update(&desc, cipher, cryptlen); |
116 | if (err) | 117 | if (err) |
117 | goto auth_unlock; | 118 | goto auth_unlock; |
118 | 119 | ||
@@ -121,7 +122,21 @@ auth_unlock: | |||
121 | spin_unlock_bh(&ctx->auth_lock); | 122 | spin_unlock_bh(&ctx->auth_lock); |
122 | 123 | ||
123 | if (err) | 124 | if (err) |
124 | return err; | 125 | return ERR_PTR(err); |
126 | |||
127 | return hash; | ||
128 | } | ||
129 | |||
130 | static int crypto_authenc_genicv(struct aead_request *req, unsigned int flags) | ||
131 | { | ||
132 | struct crypto_aead *authenc = crypto_aead_reqtfm(req); | ||
133 | struct scatterlist *dst = req->dst; | ||
134 | unsigned int cryptlen = req->cryptlen; | ||
135 | u8 *hash; | ||
136 | |||
137 | hash = crypto_authenc_hash(req, flags, dst, cryptlen); | ||
138 | if (IS_ERR(hash)) | ||
139 | return PTR_ERR(hash); | ||
125 | 140 | ||
126 | scatterwalk_map_and_copy(hash, dst, cryptlen, | 141 | scatterwalk_map_and_copy(hash, dst, cryptlen, |
127 | crypto_aead_authsize(authenc), 1); | 142 | crypto_aead_authsize(authenc), 1); |
@@ -132,7 +147,7 @@ static void crypto_authenc_encrypt_done(struct crypto_async_request *req, | |||
132 | int err) | 147 | int err) |
133 | { | 148 | { |
134 | if (!err) | 149 | if (!err) |
135 | err = crypto_authenc_hash(req->data); | 150 | err = crypto_authenc_genicv(req->data, 0); |
136 | 151 | ||
137 | aead_request_complete(req->data, err); | 152 | aead_request_complete(req->data, err); |
138 | } | 153 | } |
@@ -154,50 +169,25 @@ static int crypto_authenc_encrypt(struct aead_request *req) | |||
154 | if (err) | 169 | if (err) |
155 | return err; | 170 | return err; |
156 | 171 | ||
157 | return crypto_authenc_hash(req); | 172 | return crypto_authenc_genicv(req, CRYPTO_TFM_REQ_MAY_SLEEP); |
158 | } | 173 | } |
159 | 174 | ||
160 | static int crypto_authenc_verify(struct aead_request *req, | 175 | static int crypto_authenc_verify(struct aead_request *req, |
161 | unsigned int cryptlen) | 176 | unsigned int cryptlen) |
162 | { | 177 | { |
163 | struct crypto_aead *authenc = crypto_aead_reqtfm(req); | 178 | struct crypto_aead *authenc = crypto_aead_reqtfm(req); |
164 | struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); | 179 | u8 *ohash; |
165 | struct crypto_hash *auth = ctx->auth; | ||
166 | struct hash_desc desc = { | ||
167 | .tfm = auth, | ||
168 | .flags = aead_request_flags(req), | ||
169 | }; | ||
170 | u8 *ohash = aead_request_ctx(req); | ||
171 | u8 *ihash; | 180 | u8 *ihash; |
172 | struct scatterlist *src = req->src; | 181 | struct scatterlist *src = req->src; |
173 | unsigned int authsize; | 182 | unsigned int authsize; |
174 | int err; | ||
175 | 183 | ||
176 | ohash = (u8 *)ALIGN((unsigned long)ohash + crypto_hash_alignmask(auth), | 184 | ohash = crypto_authenc_hash(req, CRYPTO_TFM_REQ_MAY_SLEEP, src, |
177 | crypto_hash_alignmask(auth) + 1); | 185 | cryptlen); |
178 | ihash = ohash + crypto_hash_digestsize(auth); | 186 | if (IS_ERR(ohash)) |
179 | 187 | return PTR_ERR(ohash); | |
180 | spin_lock_bh(&ctx->auth_lock); | ||
181 | err = crypto_hash_init(&desc); | ||
182 | if (err) | ||
183 | goto auth_unlock; | ||
184 | |||
185 | err = crypto_hash_update(&desc, req->assoc, req->assoclen); | ||
186 | if (err) | ||
187 | goto auth_unlock; | ||
188 | |||
189 | err = crypto_hash_update(&desc, src, cryptlen); | ||
190 | if (err) | ||
191 | goto auth_unlock; | ||
192 | |||
193 | err = crypto_hash_final(&desc, ohash); | ||
194 | auth_unlock: | ||
195 | spin_unlock_bh(&ctx->auth_lock); | ||
196 | |||
197 | if (err) | ||
198 | return err; | ||
199 | 188 | ||
200 | authsize = crypto_aead_authsize(authenc); | 189 | authsize = crypto_aead_authsize(authenc); |
190 | ihash = ohash + authsize; | ||
201 | scatterwalk_map_and_copy(ihash, src, cryptlen, authsize, 0); | 191 | scatterwalk_map_and_copy(ihash, src, cryptlen, authsize, 0); |
202 | return memcmp(ihash, ohash, authsize) ? -EBADMSG: 0; | 192 | return memcmp(ihash, ohash, authsize) ? -EBADMSG: 0; |
203 | } | 193 | } |