Whamcloud - gitweb
land lustre part of b_hd_sec on HEAD.
[fs/lustre-release.git] / lustre / sec / gss / gss_krb5_crypto.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Modifications for Lustre
5  * Copyright 2004, Cluster File Systems, Inc.
6  * All rights reserved
7  * Author: Eric Mei <ericm@clusterfs.com>
8  */
9
10 /*
11  *  linux/net/sunrpc/gss_krb5_crypto.c
12  *
13  *  Copyright (c) 2000 The Regents of the University of Michigan.
14  *  All rights reserved.
15  *
16  *  Andy Adamson   <andros@umich.edu>
17  *  Bruce Fields   <bfields@umich.edu>
18  */
19
20 /*
21  * Copyright (C) 1998 by the FundsXpress, INC.
22  *
23  * All rights reserved.
24  *
25  * Export of this software from the United States of America may require
26  * a specific license from the United States Government.  It is the
27  * responsibility of any person or organization contemplating export to
28  * obtain such a license before exporting.
29  *
30  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
31  * distribute this software and its documentation for any purpose and
32  * without fee is hereby granted, provided that the above copyright
33  * notice appear in all copies and that both that copyright notice and
34  * this permission notice appear in supporting documentation, and that
35  * the name of FundsXpress. not be used in advertising or publicity pertaining
36  * to distribution of the software without specific, written prior
37  * permission.  FundsXpress makes no representations about the suitability of
38  * this software for any purpose.  It is provided "as is" without express
39  * or implied warranty.
40  *
41  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
42  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
43  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
44  */
45
46 #ifndef EXPORT_SYMTAB
47 # define EXPORT_SYMTAB
48 #endif
49 #define DEBUG_SUBSYSTEM S_SEC
50 #ifdef __KERNEL__
51 #include <linux/init.h>
52 #include <linux/module.h>
53 #include <linux/slab.h>
54 #include <linux/crypto.h>
55 #else
56 #include <liblustre.h>
57 #include "../kcrypto/libcrypto.h"
58 #endif
59
60 #include <libcfs/kp30.h>
61 #include <linux/obd.h>
62 #include <linux/obd_class.h>
63 #include <linux/obd_support.h>
64 #include <linux/lustre_idl.h>
65 #include <linux/lustre_net.h>
66 #include <linux/lustre_import.h>
67 #include <linux/lustre_sec.h>
68
69 #include "gss_err.h"
70 #include "gss_internal.h"
71 #include "gss_api.h"
72 #include "gss_krb5.h"
73
74 __u32
75 krb5_encrypt(struct crypto_tfm *tfm,
76              void * iv,
77              void * in,
78              void * out,
79              int length)
80 {
81         __u32 ret = -EINVAL;
82         struct scatterlist sg[1];
83         __u8 local_iv[16] = {0};
84
85         if (length % crypto_tfm_alg_blocksize(tfm) != 0)
86                 goto out;
87
88         if (crypto_tfm_alg_ivsize(tfm) > 16) {
89                 CERROR("tfm iv size to large %d\n", crypto_tfm_alg_ivsize(tfm));
90                 goto out;
91         }
92
93         if (iv)
94                 memcpy(local_iv, iv, crypto_tfm_alg_ivsize(tfm));
95
96         memcpy(out, in, length);
97         sg[0].page = virt_to_page(out);
98         sg[0].offset = offset_in_page(out);
99         sg[0].length = length;
100
101         ret = crypto_cipher_encrypt_iv(tfm, sg, sg, length, local_iv);
102
103 out:
104         return(ret);
105 }
106
107 //EXPORT_SYMBOL(krb5_encrypt);
108
109 __u32
110 krb5_decrypt(struct crypto_tfm *tfm,
111              void * iv,
112              void * in,
113              void * out,
114              int length)
115 {
116         __u32 ret = -EINVAL;
117         struct scatterlist sg[1];
118         __u8 local_iv[16] = {0};
119
120         if (length % crypto_tfm_alg_blocksize(tfm) != 0)
121                 goto out;
122
123         if (crypto_tfm_alg_ivsize(tfm) > 16) {
124                 CERROR("tfm iv size to large %d\n", crypto_tfm_alg_ivsize(tfm));
125                 goto out;
126         }
127         if (iv)
128                 memcpy(local_iv,iv, crypto_tfm_alg_ivsize(tfm));
129
130         memcpy(out, in, length);
131         sg[0].page = virt_to_page(out);
132         sg[0].offset = offset_in_page(out);
133         sg[0].length = length;
134
135         ret = crypto_cipher_decrypt_iv(tfm, sg, sg, length, local_iv);
136
137 out:
138         return(ret);
139 }
140
141 //EXPORT_SYMBOL(krb5_decrypt);
142
143 void
144 buf_to_sg(struct scatterlist *sg, char *ptr, int len)
145 {
146         sg->page = virt_to_page(ptr);
147         sg->offset = offset_in_page(ptr);
148         sg->length = len;
149 }
150
151 /* checksum the plaintext data and hdrlen bytes of the token header */
152 __s32
153 make_checksum(__s32 cksumtype,
154               char *header, int hdrlen,
155               rawobj_t *body,
156               rawobj_t *cksum)
157 {
158         char                           *cksumname;
159         struct crypto_tfm              *tfm = NULL; /* XXX add to ctx? */
160         struct scatterlist              sg[1];
161         __u32                           code = GSS_S_FAILURE;
162
163         switch (cksumtype) {
164                 case CKSUMTYPE_RSA_MD5:
165                         cksumname = "md5";
166                         break;
167                 default:
168                         CERROR("unsupported checksum %d", cksumtype);
169                         goto out;
170         }
171         if (!(tfm = crypto_alloc_tfm(cksumname, 0)))
172                 goto out;
173         cksum->len = crypto_tfm_alg_digestsize(tfm);
174         OBD_ALLOC(cksum->data, cksum->len);
175         if (!cksum->data)
176                 goto out;
177
178         crypto_digest_init(tfm);
179         buf_to_sg(sg, header, hdrlen);
180         crypto_digest_update(tfm, sg, 1);
181         if (body->len) {
182                 buf_to_sg(sg, body->data, body->len);
183                 crypto_digest_update(tfm, sg, 1);
184         }
185
186         crypto_digest_final(tfm, cksum->data);
187         code = 0;
188 out:
189         if (tfm)
190                 crypto_free_tfm(tfm);
191         return code;
192 }
193
194 //EXPORT_SYMBOL(make_checksum);
195
196 static
197 void obj_to_scatter_list(rawobj_t *obj, struct scatterlist *list,
198                          int listlen)
199 {
200         __u8   *ptr = obj->data;
201         __u32   size = obj->len;
202         int index = 0;
203
204         while (size) {
205                 LASSERT(index++ < listlen);
206                 list->page = virt_to_page(ptr);
207                 list->offset = (int) ptr & (~PAGE_MASK);
208                 list->length = (list->offset + size) > PAGE_SIZE ?
209                                 (PAGE_SIZE - list->offset) : size;
210                 ptr += list->length;
211                 size -= list->length;
212                 list++;
213         }
214 }
215
216 int gss_encrypt_rawobj(struct crypto_tfm *tfm,
217                        rawobj_t *inobj, rawobj_t *outobj,
218                        int enc)
219 {
220         struct scatterlist *src_list, *dst_list;
221         __u8 local_iv[16] = {0};
222         int list_len;
223         __u32 rc;
224         ENTRY;
225
226         LASSERT(outobj->len >= inobj->len);
227
228         list_len = ((inobj->len + PAGE_SIZE - 1) >> PAGE_SHIFT) + 1;
229         OBD_ALLOC(src_list, sizeof(*src_list) * list_len * 2);
230         if (!src_list) {
231                 CERROR("can't alloc %d\n", sizeof(*src_list) * list_len * 2);
232                 RETURN(-ENOMEM);
233         }
234         dst_list = src_list + list_len;
235
236         obj_to_scatter_list(inobj, src_list, list_len);
237         obj_to_scatter_list(outobj, dst_list, list_len);
238
239         if (enc)
240                 rc = crypto_cipher_encrypt_iv(tfm, dst_list, src_list,
241                                               inobj->len, local_iv);
242         else
243                 rc = crypto_cipher_decrypt_iv(tfm, dst_list, src_list,
244                                               inobj->len, local_iv);
245
246         if (rc) {
247                 CERROR("encrypt error %u\n", rc);
248                 GOTO(out_free, rc);
249         }
250
251         outobj->len = inobj->len;
252
253 out_free:
254         OBD_FREE(src_list, sizeof(*src_list) * list_len * 2);
255         RETURN(rc);
256 }