Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * linux/net/sunrpc/gss_spkm3_seal.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> | |
adeb8133 OK |
42 | #include <linux/pagemap.h> |
43 | #include <linux/scatterlist.h> | |
44 | #include <linux/sunrpc/xdr.h> | |
1da177e4 LT |
45 | |
46 | #ifdef RPC_DEBUG | |
47 | # define RPCDBG_FACILITY RPCDBG_AUTH | |
48 | #endif | |
49 | ||
adeb8133 OK |
50 | const struct xdr_netobj hmac_md5_oid = { 8, "\x2B\x06\x01\x05\x05\x08\x01\x01"}; |
51 | const struct xdr_netobj cast5_cbc_oid = {9, "\x2A\x86\x48\x86\xF6\x7D\x07\x42\x0A"}; | |
52 | ||
1da177e4 LT |
53 | /* |
54 | * spkm3_make_token() | |
55 | * | |
56 | * Only SPKM_MIC_TOK with md5 intg-alg is supported | |
57 | */ | |
58 | ||
59 | u32 | |
00fd6e14 | 60 | spkm3_make_token(struct spkm3_ctx *ctx, |
1da177e4 LT |
61 | struct xdr_buf * text, struct xdr_netobj * token, |
62 | int toktype) | |
63 | { | |
64 | s32 checksum_type; | |
65 | char tokhdrbuf[25]; | |
9e57b302 BF |
66 | char cksumdata[16]; |
67 | struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata}; | |
1da177e4 | 68 | struct xdr_netobj mic_hdr = {.len = 0, .data = tokhdrbuf}; |
9eed129b | 69 | int tokenlen = 0; |
1da177e4 LT |
70 | unsigned char *ptr; |
71 | s32 now; | |
72 | int ctxelen = 0, ctxzbit = 0; | |
73 | int md5elen = 0, md5zbit = 0; | |
74 | ||
1da177e4 | 75 | now = jiffies; |
1da177e4 LT |
76 | |
77 | if (ctx->ctx_id.len != 16) { | |
78 | dprintk("RPC: spkm3_make_token BAD ctx_id.len %d\n", | |
adeb8133 | 79 | ctx->ctx_id.len); |
1da177e4 LT |
80 | goto out_err; |
81 | } | |
adeb8133 OK |
82 | |
83 | if (!g_OID_equal(&ctx->intg_alg, &hmac_md5_oid)) { | |
84 | dprintk("RPC: gss_spkm3_seal: unsupported I-ALG algorithm." | |
85 | "only support hmac-md5 I-ALG.\n"); | |
86 | goto out_err; | |
87 | } else | |
88 | checksum_type = CKSUMTYPE_HMAC_MD5; | |
89 | ||
90 | if (!g_OID_equal(&ctx->conf_alg, &cast5_cbc_oid)) { | |
91 | dprintk("RPC: gss_spkm3_seal: unsupported C-ALG algorithm\n"); | |
1da177e4 LT |
92 | goto out_err; |
93 | } | |
94 | ||
95 | if (toktype == SPKM_MIC_TOK) { | |
1da177e4 LT |
96 | /* Calculate checksum over the mic-header */ |
97 | asn1_bitstring_len(&ctx->ctx_id, &ctxelen, &ctxzbit); | |
98 | spkm3_mic_header(&mic_hdr.data, &mic_hdr.len, ctx->ctx_id.data, | |
adeb8133 OK |
99 | ctxelen, ctxzbit); |
100 | if (make_spkm3_checksum(checksum_type, &ctx->derived_integ_key, | |
101 | (char *)mic_hdr.data, mic_hdr.len, | |
102 | text, 0, &md5cksum)) | |
1da177e4 LT |
103 | goto out_err; |
104 | ||
105 | asn1_bitstring_len(&md5cksum, &md5elen, &md5zbit); | |
9eed129b | 106 | tokenlen = 10 + ctxelen + 1 + md5elen + 1; |
1da177e4 LT |
107 | |
108 | /* Create token header using generic routines */ | |
9eed129b | 109 | token->len = g_token_size(&ctx->mech_used, tokenlen); |
1da177e4 LT |
110 | |
111 | ptr = token->data; | |
9eed129b | 112 | g_make_token_header(&ctx->mech_used, tokenlen, &ptr); |
1da177e4 LT |
113 | |
114 | spkm3_make_mic_token(&ptr, tokenlen, &mic_hdr, &md5cksum, md5elen, md5zbit); | |
115 | } else if (toktype == SPKM_WRAP_TOK) { /* Not Supported */ | |
116 | dprintk("RPC: gss_spkm3_seal: SPKM_WRAP_TOK not supported\n"); | |
117 | goto out_err; | |
118 | } | |
1da177e4 LT |
119 | |
120 | /* XXX need to implement sequence numbers, and ctx->expired */ | |
121 | ||
122 | return GSS_S_COMPLETE; | |
123 | out_err: | |
adeb8133 OK |
124 | if (md5cksum.data) |
125 | kfree(md5cksum.data); | |
126 | ||
1da177e4 LT |
127 | token->data = NULL; |
128 | token->len = 0; | |
129 | return GSS_S_FAILURE; | |
130 | } | |
adeb8133 OK |
131 | |
132 | static int | |
133 | spkm3_checksummer(struct scatterlist *sg, void *data) | |
134 | { | |
135 | struct hash_desc *desc = data; | |
136 | ||
137 | return crypto_hash_update(desc, sg, sg->length); | |
138 | } | |
139 | ||
140 | /* checksum the plaintext data and hdrlen bytes of the token header */ | |
141 | s32 | |
142 | make_spkm3_checksum(s32 cksumtype, struct xdr_netobj *key, char *header, | |
143 | unsigned int hdrlen, struct xdr_buf *body, | |
144 | unsigned int body_offset, struct xdr_netobj *cksum) | |
145 | { | |
146 | char *cksumname; | |
147 | struct hash_desc desc; /* XXX add to ctx? */ | |
148 | struct scatterlist sg[1]; | |
149 | int err; | |
150 | ||
151 | switch (cksumtype) { | |
152 | case CKSUMTYPE_HMAC_MD5: | |
153 | cksumname = "md5"; | |
154 | break; | |
155 | default: | |
156 | dprintk("RPC: spkm3_make_checksum:" | |
157 | " unsupported checksum %d", cksumtype); | |
158 | return GSS_S_FAILURE; | |
159 | } | |
160 | ||
161 | if (key->data == NULL || key->len <= 0) return GSS_S_FAILURE; | |
162 | ||
163 | desc.tfm = crypto_alloc_hash(cksumname, 0, CRYPTO_ALG_ASYNC); | |
164 | if (IS_ERR(desc.tfm)) | |
165 | return GSS_S_FAILURE; | |
166 | cksum->len = crypto_hash_digestsize(desc.tfm); | |
167 | desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; | |
168 | ||
169 | err = crypto_hash_setkey(desc.tfm, key->data, key->len); | |
170 | if (err) | |
171 | goto out; | |
172 | ||
173 | sg_set_buf(sg, header, hdrlen); | |
174 | crypto_hash_update(&desc, sg, 1); | |
175 | ||
176 | xdr_process_buf(body, body_offset, body->len - body_offset, | |
177 | spkm3_checksummer, &desc); | |
178 | crypto_hash_final(&desc, cksum->data); | |
179 | ||
180 | out: | |
181 | crypto_free_hash(desc.tfm); | |
182 | ||
183 | return err ? GSS_S_FAILURE : 0; | |
184 | } | |
185 | ||
186 | EXPORT_SYMBOL(make_spkm3_checksum); |