Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * linux/net/sunrpc/gss_spkm3_token.c | |
3 | * | |
4 | * Copyright (c) 2003 The Regents of the University of Michigan. | |
5 | * All rights reserved. | |
6 | * | |
7 | * Andy Adamson <andros@umich.edu> | |
8 | * | |
9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | |
12 | * | |
13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | |
18 | * 3. Neither the name of the University nor the names of its | |
19 | * contributors may be used to endorse or promote products derived | |
20 | * from this software without specific prior written permission. | |
21 | * | |
22 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
23 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
24 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
25 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | |
29 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
30 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
31 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
33 | * | |
34 | */ | |
35 | ||
36 | #include <linux/types.h> | |
37 | #include <linux/slab.h> | |
38 | #include <linux/jiffies.h> | |
39 | #include <linux/sunrpc/gss_spkm3.h> | |
40 | #include <linux/random.h> | |
41 | #include <linux/crypto.h> | |
42 | ||
43 | #ifdef RPC_DEBUG | |
44 | # define RPCDBG_FACILITY RPCDBG_AUTH | |
45 | #endif | |
46 | ||
47 | /* | |
48 | * asn1_bitstring_len() | |
49 | * | |
50 | * calculate the asn1 bitstring length of the xdr_netobject | |
51 | */ | |
52 | void | |
53 | asn1_bitstring_len(struct xdr_netobj *in, int *enclen, int *zerobits) | |
54 | { | |
55 | int i, zbit = 0,elen = in->len; | |
56 | char *ptr; | |
57 | ||
58 | ptr = &in->data[in->len -1]; | |
59 | ||
60 | /* count trailing 0's */ | |
61 | for(i = in->len; i > 0; i--) { | |
62 | if (*ptr == 0) { | |
63 | ptr--; | |
64 | elen--; | |
65 | } else | |
66 | break; | |
67 | } | |
68 | ||
69 | /* count number of 0 bits in final octet */ | |
70 | ptr = &in->data[elen - 1]; | |
71 | for(i = 0; i < 8; i++) { | |
72 | short mask = 0x01; | |
73 | ||
74 | if (!((mask << i) & *ptr)) | |
75 | zbit++; | |
76 | else | |
77 | break; | |
78 | } | |
79 | *enclen = elen; | |
80 | *zerobits = zbit; | |
81 | } | |
82 | ||
83 | /* | |
84 | * decode_asn1_bitstring() | |
85 | * | |
86 | * decode a bitstring into a buffer of the expected length. | |
87 | * enclen = bit string length | |
88 | * explen = expected length (define in rfc) | |
89 | */ | |
90 | int | |
91 | decode_asn1_bitstring(struct xdr_netobj *out, char *in, int enclen, int explen) | |
92 | { | |
93 | if (!(out->data = kmalloc(explen,GFP_KERNEL))) | |
94 | return 0; | |
95 | out->len = explen; | |
96 | memset(out->data, 0, explen); | |
97 | memcpy(out->data, in, enclen); | |
98 | return 1; | |
99 | } | |
100 | ||
101 | /* | |
102 | * SPKMInnerContextToken choice SPKM_MIC asn1 token layout | |
103 | * | |
104 | * contextid is always 16 bytes plain data. max asn1 bitstring len = 17. | |
105 | * | |
106 | * tokenlen = pos[0] to end of token (max pos[45] with MD5 cksum) | |
107 | * | |
108 | * pos value | |
109 | * ---------- | |
110 | * [0] a4 SPKM-MIC tag | |
111 | * [1] ?? innertoken length (max 44) | |
112 | * | |
113 | * | |
114 | * tok_hdr piece of checksum data starts here | |
115 | * | |
116 | * the maximum mic-header len = 9 + 17 = 26 | |
117 | * mic-header | |
118 | * ---------- | |
119 | * [2] 30 SEQUENCE tag | |
120 | * [3] ?? mic-header length: (max 23) = TokenID + ContextID | |
121 | * | |
122 | * TokenID - all fields constant and can be hardcoded | |
123 | * ------- | |
124 | * [4] 02 Type 2 | |
125 | * [5] 02 Length 2 | |
126 | * [6][7] 01 01 TokenID (SPKM_MIC_TOK) | |
127 | * | |
128 | * ContextID - encoded length not constant, calculated | |
129 | * --------- | |
130 | * [8] 03 Type 3 | |
131 | * [9] ?? encoded length | |
132 | * [10] ?? ctxzbit | |
133 | * [11] contextid | |
134 | * | |
135 | * mic_header piece of checksum data ends here. | |
136 | * | |
137 | * int-cksum - encoded length not constant, calculated | |
138 | * --------- | |
139 | * [??] 03 Type 3 | |
140 | * [??] ?? encoded length | |
141 | * [??] ?? md5zbit | |
142 | * [??] int-cksum (NID_md5 = 16) | |
143 | * | |
144 | * maximum SPKM-MIC innercontext token length = | |
145 | * 10 + encoded contextid_size(17 max) + 2 + encoded | |
146 | * cksum_size (17 maxfor NID_md5) = 46 | |
147 | */ | |
148 | ||
149 | /* | |
150 | * spkm3_mic_header() | |
151 | * | |
152 | * Prepare the SPKM_MIC_TOK mic-header for check-sum calculation | |
153 | * elen: 16 byte context id asn1 bitstring encoded length | |
154 | */ | |
155 | void | |
156 | spkm3_mic_header(unsigned char **hdrbuf, unsigned int *hdrlen, unsigned char *ctxdata, int elen, int zbit) | |
157 | { | |
158 | char *hptr = *hdrbuf; | |
159 | char *top = *hdrbuf; | |
160 | ||
161 | *(u8 *)hptr++ = 0x30; | |
162 | *(u8 *)hptr++ = elen + 7; /* on the wire header length */ | |
163 | ||
164 | /* tokenid */ | |
165 | *(u8 *)hptr++ = 0x02; | |
166 | *(u8 *)hptr++ = 0x02; | |
167 | *(u8 *)hptr++ = 0x01; | |
168 | *(u8 *)hptr++ = 0x01; | |
169 | ||
170 | /* coniextid */ | |
171 | *(u8 *)hptr++ = 0x03; | |
172 | *(u8 *)hptr++ = elen + 1; /* add 1 to include zbit */ | |
173 | *(u8 *)hptr++ = zbit; | |
174 | memcpy(hptr, ctxdata, elen); | |
175 | hptr += elen; | |
176 | *hdrlen = hptr - top; | |
177 | } | |
178 | ||
179 | /* | |
180 | * spkm3_mic_innercontext_token() | |
181 | * | |
182 | * *tokp points to the beginning of the SPKM_MIC token described | |
183 | * in rfc 2025, section 3.2.1: | |
184 | * | |
185 | */ | |
186 | void | |
187 | spkm3_make_mic_token(unsigned char **tokp, int toklen, struct xdr_netobj *mic_hdr, struct xdr_netobj *md5cksum, int md5elen, int md5zbit) | |
188 | { | |
189 | unsigned char *ict = *tokp; | |
190 | ||
191 | *(u8 *)ict++ = 0xa4; | |
192 | *(u8 *)ict++ = toklen - 2; | |
193 | memcpy(ict, mic_hdr->data, mic_hdr->len); | |
194 | ict += mic_hdr->len; | |
195 | ||
196 | *(u8 *)ict++ = 0x03; | |
197 | *(u8 *)ict++ = md5elen + 1; /* add 1 to include zbit */ | |
198 | *(u8 *)ict++ = md5zbit; | |
199 | memcpy(ict, md5cksum->data, md5elen); | |
200 | } | |
201 | ||
202 | u32 | |
203 | spkm3_verify_mic_token(unsigned char **tokp, int *mic_hdrlen, unsigned char **cksum) | |
204 | { | |
205 | struct xdr_netobj spkm3_ctx_id = {.len =0, .data = NULL}; | |
206 | unsigned char *ptr = *tokp; | |
207 | int ctxelen; | |
208 | u32 ret = GSS_S_DEFECTIVE_TOKEN; | |
209 | ||
210 | /* spkm3 innercontext token preamble */ | |
211 | if ((ptr[0] != 0xa4) || (ptr[2] != 0x30)) { | |
212 | dprintk("RPC: BAD SPKM ictoken preamble\n"); | |
213 | goto out; | |
214 | } | |
215 | ||
216 | *mic_hdrlen = ptr[3]; | |
217 | ||
218 | /* token type */ | |
219 | if ((ptr[4] != 0x02) || (ptr[5] != 0x02)) { | |
220 | dprintk("RPC: BAD asn1 SPKM3 token type\n"); | |
221 | goto out; | |
222 | } | |
223 | ||
224 | /* only support SPKM_MIC_TOK */ | |
225 | if((ptr[6] != 0x01) || (ptr[7] != 0x01)) { | |
226 | dprintk("RPC: ERROR unsupported SPKM3 token \n"); | |
227 | goto out; | |
228 | } | |
229 | ||
230 | /* contextid */ | |
231 | if (ptr[8] != 0x03) { | |
232 | dprintk("RPC: BAD SPKM3 asn1 context-id type\n"); | |
233 | goto out; | |
234 | } | |
235 | ||
236 | ctxelen = ptr[9]; | |
237 | if (ctxelen > 17) { /* length includes asn1 zbit octet */ | |
238 | dprintk("RPC: BAD SPKM3 contextid len %d\n", ctxelen); | |
239 | goto out; | |
240 | } | |
241 | ||
242 | /* ignore ptr[10] */ | |
243 | ||
244 | if(!decode_asn1_bitstring(&spkm3_ctx_id, &ptr[11], ctxelen - 1, 16)) | |
245 | goto out; | |
246 | ||
247 | /* | |
248 | * in the current implementation: the optional int-alg is not present | |
249 | * so the default int-alg (md5) is used the optional snd-seq field is | |
250 | * also not present | |
251 | */ | |
252 | ||
253 | if (*mic_hdrlen != 6 + ctxelen) { | |
254 | dprintk("RPC: BAD SPKM_ MIC_TOK header len %d: we only support default int-alg (should be absent) and do not support snd-seq\n", *mic_hdrlen); | |
255 | goto out; | |
256 | } | |
257 | /* checksum */ | |
258 | *cksum = (&ptr[10] + ctxelen); /* ctxelen includes ptr[10] */ | |
259 | ||
260 | ret = GSS_S_COMPLETE; | |
261 | out: | |
a51482bd | 262 | kfree(spkm3_ctx_id.data); |
1da177e4 LT |
263 | return ret; |
264 | } | |
265 |