2 * linux/net/sunrpc/gss_krb5_crypto.c
4 * Copyright (c) 2000 The Regents of the University of Michigan.
7 * Andy Adamson <andros@umich.edu>
8 * Bruce Fields <bfields@umich.edu>
12 * Copyright (C) 1998 by the FundsXpress, INC.
14 * All rights reserved.
16 * Export of this software from the United States of America may require
17 * a specific license from the United States Government. It is the
18 * responsibility of any person or organization contemplating export to
19 * obtain such a license before exporting.
21 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
22 * distribute this software and its documentation for any purpose and
23 * without fee is hereby granted, provided that the above copyright
24 * notice appear in all copies and that both that copyright notice and
25 * this permission notice appear in supporting documentation, and that
26 * the name of FundsXpress. not be used in advertising or publicity pertaining
27 * to distribution of the software without specific, written prior
28 * permission. FundsXpress makes no representations about the suitability of
29 * this software for any purpose. It is provided "as is" without express
30 * or implied warranty.
32 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
33 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
34 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
37 #include <linux/types.h>
39 #include <linux/slab.h>
40 #include <asm/scatterlist.h>
41 #include <linux/crypto.h>
42 #include <linux/highmem.h>
43 #include <linux/pagemap.h>
44 #include <linux/sunrpc/gss_krb5.h>
47 # define RPCDBG_FACILITY RPCDBG_AUTH
52 struct crypto_tfm
*tfm
,
59 struct scatterlist sg
[1];
60 u8 local_iv
[16] = {0};
62 dprintk("RPC: krb5_encrypt: input data:\n");
63 print_hexl((u32
*)in
, length
, 0);
65 if (length
% crypto_tfm_alg_blocksize(tfm
) != 0)
68 if (crypto_tfm_alg_ivsize(tfm
) > 16) {
69 dprintk("RPC: gss_k5encrypt: tfm iv size to large %d\n",
70 crypto_tfm_alg_ivsize(tfm
));
75 memcpy(local_iv
, iv
, crypto_tfm_alg_ivsize(tfm
));
77 memcpy(out
, in
, length
);
78 sg
[0].page
= virt_to_page(out
);
79 sg
[0].offset
= offset_in_page(out
);
80 sg
[0].length
= length
;
82 ret
= crypto_cipher_encrypt_iv(tfm
, sg
, sg
, length
, local_iv
);
84 dprintk("RPC: krb5_encrypt: output data:\n");
85 print_hexl((u32
*)out
, length
, 0);
87 dprintk("RPC: krb5_encrypt returns %d\n",ret
);
91 EXPORT_SYMBOL(krb5_encrypt
);
95 struct crypto_tfm
*tfm
,
102 struct scatterlist sg
[1];
103 u8 local_iv
[16] = {0};
105 dprintk("RPC: krb5_decrypt: input data:\n");
106 print_hexl((u32
*)in
, length
, 0);
108 if (length
% crypto_tfm_alg_blocksize(tfm
) != 0)
111 if (crypto_tfm_alg_ivsize(tfm
) > 16) {
112 dprintk("RPC: gss_k5decrypt: tfm iv size to large %d\n",
113 crypto_tfm_alg_ivsize(tfm
));
117 memcpy(local_iv
,iv
, crypto_tfm_alg_ivsize(tfm
));
119 memcpy(out
, in
, length
);
120 sg
[0].page
= virt_to_page(out
);
121 sg
[0].offset
= offset_in_page(out
);
122 sg
[0].length
= length
;
124 ret
= crypto_cipher_decrypt_iv(tfm
, sg
, sg
, length
, local_iv
);
126 dprintk("RPC: krb5_decrypt: output_data:\n");
127 print_hexl((u32
*)out
, length
, 0);
129 dprintk("RPC: gss_k5decrypt returns %d\n",ret
);
133 EXPORT_SYMBOL(krb5_decrypt
);
136 buf_to_sg(struct scatterlist
*sg
, char *ptr
, int len
) {
137 sg
->page
= virt_to_page(ptr
);
138 sg
->offset
= offset_in_page(ptr
);
142 /* checksum the plaintext data and hdrlen bytes of the token header */
144 make_checksum(s32 cksumtype
, char *header
, int hdrlen
, struct xdr_buf
*body
,
145 struct xdr_netobj
*cksum
)
148 struct crypto_tfm
*tfm
= NULL
; /* XXX add to ctx? */
149 struct scatterlist sg
[1];
150 u32 code
= GSS_S_FAILURE
;
151 int len
, thislen
, offset
;
155 case CKSUMTYPE_RSA_MD5
:
159 dprintk("RPC: krb5_make_checksum:"
160 " unsupported checksum %d", cksumtype
);
163 if (!(tfm
= crypto_alloc_tfm(cksumname
, 0)))
165 cksum
->len
= crypto_tfm_alg_digestsize(tfm
);
166 if ((cksum
->data
= kmalloc(cksum
->len
, GFP_KERNEL
)) == NULL
)
169 crypto_digest_init(tfm
);
170 buf_to_sg(sg
, header
, hdrlen
);
171 crypto_digest_update(tfm
, sg
, 1);
172 if (body
->head
[0].iov_len
) {
173 buf_to_sg(sg
, body
->head
[0].iov_base
, body
->head
[0].iov_len
);
174 crypto_digest_update(tfm
, sg
, 1);
177 len
= body
->page_len
;
179 offset
= body
->page_base
& (PAGE_CACHE_SIZE
- 1);
180 i
= body
->page_base
>> PAGE_CACHE_SHIFT
;
181 thislen
= PAGE_CACHE_SIZE
- offset
;
185 sg
->page
= body
->pages
[i
];
187 sg
->length
= thislen
;
188 kmap(sg
->page
); /* XXX kmap_atomic? */
189 crypto_digest_update(tfm
, sg
, 1);
194 thislen
= PAGE_CACHE_SIZE
;
197 if (body
->tail
[0].iov_len
) {
198 buf_to_sg(sg
, body
->tail
[0].iov_base
, body
->tail
[0].iov_len
);
199 crypto_digest_update(tfm
, sg
, 1);
201 crypto_digest_final(tfm
, cksum
->data
);
205 crypto_free_tfm(tfm
);
209 EXPORT_SYMBOL(make_checksum
);