aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/auth_gss/gss_krb5_crypto.c
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@fieldses.org>2005-10-13 16:55:13 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2005-10-19 02:19:46 -0400
commit14ae162c24d985593d5b19437d7f3d8fd0062b59 (patch)
tree750fbc08e6a6e0cb00bfad7c871144a757ac43de /net/sunrpc/auth_gss/gss_krb5_crypto.c
parentbfa91516b57483fc9c81d8d90325fd2c3c16ac48 (diff)
RPCSEC_GSS: Add support for privacy to krb5 rpcsec_gss mechanism.
Add support for privacy to the krb5 rpcsec_gss mechanism. Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc/auth_gss/gss_krb5_crypto.c')
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_crypto.c156
1 files changed, 154 insertions, 2 deletions
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index 2baf93f8b8f5..3f3d5437f02d 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -218,7 +218,7 @@ checksummer(struct scatterlist *sg, void *data)
218/* checksum the plaintext data and hdrlen bytes of the token header */ 218/* checksum the plaintext data and hdrlen bytes of the token header */
219s32 219s32
220make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body, 220make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
221 struct xdr_netobj *cksum) 221 int body_offset, struct xdr_netobj *cksum)
222{ 222{
223 char *cksumname; 223 char *cksumname;
224 struct crypto_tfm *tfm = NULL; /* XXX add to ctx? */ 224 struct crypto_tfm *tfm = NULL; /* XXX add to ctx? */
@@ -243,7 +243,8 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
243 crypto_digest_init(tfm); 243 crypto_digest_init(tfm);
244 buf_to_sg(sg, header, hdrlen); 244 buf_to_sg(sg, header, hdrlen);
245 crypto_digest_update(tfm, sg, 1); 245 crypto_digest_update(tfm, sg, 1);
246 process_xdr_buf(body, 0, body->len, checksummer, tfm); 246 process_xdr_buf(body, body_offset, body->len - body_offset,
247 checksummer, tfm);
247 crypto_digest_final(tfm, cksum->data); 248 crypto_digest_final(tfm, cksum->data);
248 code = 0; 249 code = 0;
249out: 250out:
@@ -252,3 +253,154 @@ out:
252} 253}
253 254
254EXPORT_SYMBOL(make_checksum); 255EXPORT_SYMBOL(make_checksum);
256
257struct encryptor_desc {
258 u8 iv[8]; /* XXX hard-coded blocksize */
259 struct crypto_tfm *tfm;
260 int pos;
261 struct xdr_buf *outbuf;
262 struct page **pages;
263 struct scatterlist infrags[4];
264 struct scatterlist outfrags[4];
265 int fragno;
266 int fraglen;
267};
268
269static int
270encryptor(struct scatterlist *sg, void *data)
271{
272 struct encryptor_desc *desc = data;
273 struct xdr_buf *outbuf = desc->outbuf;
274 struct page *in_page;
275 int thislen = desc->fraglen + sg->length;
276 int fraglen, ret;
277 int page_pos;
278
279 /* Worst case is 4 fragments: head, end of page 1, start
280 * of page 2, tail. Anything more is a bug. */
281 BUG_ON(desc->fragno > 3);
282 desc->infrags[desc->fragno] = *sg;
283 desc->outfrags[desc->fragno] = *sg;
284
285 page_pos = desc->pos - outbuf->head[0].iov_len;
286 if (page_pos >= 0 && page_pos < outbuf->page_len) {
287 /* pages are not in place: */
288 int i = (page_pos + outbuf->page_base) >> PAGE_CACHE_SHIFT;
289 in_page = desc->pages[i];
290 } else {
291 in_page = sg->page;
292 }
293 desc->infrags[desc->fragno].page = in_page;
294 desc->fragno++;
295 desc->fraglen += sg->length;
296 desc->pos += sg->length;
297
298 fraglen = thislen & 7; /* XXX hardcoded blocksize */
299 thislen -= fraglen;
300
301 if (thislen == 0)
302 return 0;
303
304 ret = crypto_cipher_encrypt_iv(desc->tfm, desc->outfrags, desc->infrags,
305 thislen, desc->iv);
306 if (ret)
307 return ret;
308 if (fraglen) {
309 desc->outfrags[0].page = sg->page;
310 desc->outfrags[0].offset = sg->offset + sg->length - fraglen;
311 desc->outfrags[0].length = fraglen;
312 desc->infrags[0] = desc->outfrags[0];
313 desc->infrags[0].page = in_page;
314 desc->fragno = 1;
315 desc->fraglen = fraglen;
316 } else {
317 desc->fragno = 0;
318 desc->fraglen = 0;
319 }
320 return 0;
321}
322
323int
324gss_encrypt_xdr_buf(struct crypto_tfm *tfm, struct xdr_buf *buf, int offset,
325 struct page **pages)
326{
327 int ret;
328 struct encryptor_desc desc;
329
330 BUG_ON((buf->len - offset) % crypto_tfm_alg_blocksize(tfm) != 0);
331
332 memset(desc.iv, 0, sizeof(desc.iv));
333 desc.tfm = tfm;
334 desc.pos = offset;
335 desc.outbuf = buf;
336 desc.pages = pages;
337 desc.fragno = 0;
338 desc.fraglen = 0;
339
340 ret = process_xdr_buf(buf, offset, buf->len - offset, encryptor, &desc);
341 return ret;
342}
343
344EXPORT_SYMBOL(gss_encrypt_xdr_buf);
345
346struct decryptor_desc {
347 u8 iv[8]; /* XXX hard-coded blocksize */
348 struct crypto_tfm *tfm;
349 struct scatterlist frags[4];
350 int fragno;
351 int fraglen;
352};
353
354static int
355decryptor(struct scatterlist *sg, void *data)
356{
357 struct decryptor_desc *desc = data;
358 int thislen = desc->fraglen + sg->length;
359 int fraglen, ret;
360
361 /* Worst case is 4 fragments: head, end of page 1, start
362 * of page 2, tail. Anything more is a bug. */
363 BUG_ON(desc->fragno > 3);
364 desc->frags[desc->fragno] = *sg;
365 desc->fragno++;
366 desc->fraglen += sg->length;
367
368 fraglen = thislen & 7; /* XXX hardcoded blocksize */
369 thislen -= fraglen;
370
371 if (thislen == 0)
372 return 0;
373
374 ret = crypto_cipher_decrypt_iv(desc->tfm, desc->frags, desc->frags,
375 thislen, desc->iv);
376 if (ret)
377 return ret;
378 if (fraglen) {
379 desc->frags[0].page = sg->page;
380 desc->frags[0].offset = sg->offset + sg->length - fraglen;
381 desc->frags[0].length = fraglen;
382 desc->fragno = 1;
383 desc->fraglen = fraglen;
384 } else {
385 desc->fragno = 0;
386 desc->fraglen = 0;
387 }
388 return 0;
389}
390
391int
392gss_decrypt_xdr_buf(struct crypto_tfm *tfm, struct xdr_buf *buf, int offset)
393{
394 struct decryptor_desc desc;
395
396 /* XXXJBF: */
397 BUG_ON((buf->len - offset) % crypto_tfm_alg_blocksize(tfm) != 0);
398
399 memset(desc.iv, 0, sizeof(desc.iv));
400 desc.tfm = tfm;
401 desc.fragno = 0;
402 desc.fraglen = 0;
403 return process_xdr_buf(buf, offset, buf->len - offset, decryptor, &desc);
404}
405
406EXPORT_SYMBOL(gss_decrypt_xdr_buf);