diff options
-rw-r--r-- | include/linux/sunrpc/gss_spkm3.h | 34 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 2 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_spkm3_mech.c | 131 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_spkm3_seal.c | 101 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_spkm3_token.c | 6 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_spkm3_unseal.c | 88 |
6 files changed, 180 insertions, 182 deletions
diff --git a/include/linux/sunrpc/gss_spkm3.h b/include/linux/sunrpc/gss_spkm3.h index 2cf3fbb40b4f..e3e6a3437f8b 100644 --- a/include/linux/sunrpc/gss_spkm3.h +++ b/include/linux/sunrpc/gss_spkm3.h | |||
@@ -12,27 +12,19 @@ | |||
12 | #include <linux/sunrpc/gss_asn1.h> | 12 | #include <linux/sunrpc/gss_asn1.h> |
13 | 13 | ||
14 | struct spkm3_ctx { | 14 | struct spkm3_ctx { |
15 | struct xdr_netobj ctx_id; /* per message context id */ | 15 | struct xdr_netobj ctx_id; /* per message context id */ |
16 | int qop; /* negotiated qop */ | 16 | int endtime; /* endtime of the context */ |
17 | struct xdr_netobj mech_used; | 17 | struct xdr_netobj mech_used; |
18 | unsigned int ret_flags ; | 18 | unsigned int ret_flags ; |
19 | unsigned int req_flags ; | 19 | struct xdr_netobj conf_alg; |
20 | struct xdr_netobj share_key; | 20 | struct xdr_netobj derived_conf_key; |
21 | int conf_alg; | 21 | struct xdr_netobj intg_alg; |
22 | struct crypto_blkcipher *derived_conf_key; | 22 | struct xdr_netobj derived_integ_key; |
23 | int intg_alg; | ||
24 | struct crypto_blkcipher *derived_integ_key; | ||
25 | int keyestb_alg; /* alg used to get share_key */ | ||
26 | int owf_alg; /* one way function */ | ||
27 | }; | 23 | }; |
28 | 24 | ||
29 | /* from openssl/objects.h */ | 25 | /* OIDs declarations for K-ALG, I-ALG, C-ALG, and OWF-ALG */ |
30 | /* XXX need SEAL_ALG_NONE */ | 26 | extern const struct xdr_netobj hmac_md5_oid; |
31 | #define NID_md5 4 | 27 | extern const struct xdr_netobj cast5_cbc_oid; |
32 | #define NID_dhKeyAgreement 28 | ||
33 | #define NID_des_cbc 31 | ||
34 | #define NID_sha1 64 | ||
35 | #define NID_cast5_cbc 108 | ||
36 | 28 | ||
37 | /* SPKM InnerContext Token types */ | 29 | /* SPKM InnerContext Token types */ |
38 | 30 | ||
@@ -46,11 +38,13 @@ u32 spkm3_make_token(struct spkm3_ctx *ctx, struct xdr_buf * text, struct xdr_ne | |||
46 | u32 spkm3_read_token(struct spkm3_ctx *ctx, struct xdr_netobj *read_token, struct xdr_buf *message_buffer, int toktype); | 38 | u32 spkm3_read_token(struct spkm3_ctx *ctx, struct xdr_netobj *read_token, struct xdr_buf *message_buffer, int toktype); |
47 | 39 | ||
48 | #define CKSUMTYPE_RSA_MD5 0x0007 | 40 | #define CKSUMTYPE_RSA_MD5 0x0007 |
41 | #define CKSUMTYPE_HMAC_MD5 0x0008 | ||
49 | 42 | ||
50 | s32 make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body, | 43 | s32 make_spkm3_checksum(s32 cksumtype, struct xdr_netobj *key, char *header, |
51 | int body_offset, struct xdr_netobj *cksum); | 44 | unsigned int hdrlen, struct xdr_buf *body, |
45 | unsigned int body_offset, struct xdr_netobj *cksum); | ||
52 | void asn1_bitstring_len(struct xdr_netobj *in, int *enclen, int *zerobits); | 46 | void asn1_bitstring_len(struct xdr_netobj *in, int *enclen, int *zerobits); |
53 | int decode_asn1_bitstring(struct xdr_netobj *out, char *in, int enclen, | 47 | int decode_asn1_bitstring(struct xdr_netobj *out, char *in, int enclen, |
54 | int explen); | 48 | int explen); |
55 | void spkm3_mic_header(unsigned char **hdrbuf, unsigned int *hdrlen, | 49 | void spkm3_mic_header(unsigned char **hdrbuf, unsigned int *hdrlen, |
56 | unsigned char *ctxhdr, int elen, int zbit); | 50 | unsigned char *ctxhdr, int elen, int zbit); |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index d12ee5f54c0c..a02ecc1f230d 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -68,7 +68,7 @@ static struct rpc_credops gss_credops; | |||
68 | #define GSS_CRED_SLACK 1024 /* XXX: unused */ | 68 | #define GSS_CRED_SLACK 1024 /* XXX: unused */ |
69 | /* length of a krb5 verifier (48), plus data added before arguments when | 69 | /* length of a krb5 verifier (48), plus data added before arguments when |
70 | * using integrity (two 4-byte integers): */ | 70 | * using integrity (two 4-byte integers): */ |
71 | #define GSS_VERF_SLACK 56 | 71 | #define GSS_VERF_SLACK 100 |
72 | 72 | ||
73 | /* XXX this define must match the gssd define | 73 | /* XXX this define must match the gssd define |
74 | * as it is passed to gssd to signal the use of | 74 | * as it is passed to gssd to signal the use of |
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c index d57f60838895..41465072d0b5 100644 --- a/net/sunrpc/auth_gss/gss_spkm3_mech.c +++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c | |||
@@ -82,133 +82,73 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res) | |||
82 | return q; | 82 | return q; |
83 | } | 83 | } |
84 | 84 | ||
85 | static inline const void * | ||
86 | get_key(const void *p, const void *end, struct crypto_blkcipher **res, | ||
87 | int *resalg) | ||
88 | { | ||
89 | struct xdr_netobj key = { 0 }; | ||
90 | int setkey = 0; | ||
91 | char *alg_name; | ||
92 | |||
93 | p = simple_get_bytes(p, end, resalg, sizeof(*resalg)); | ||
94 | if (IS_ERR(p)) | ||
95 | goto out_err; | ||
96 | p = simple_get_netobj(p, end, &key); | ||
97 | if (IS_ERR(p)) | ||
98 | goto out_err; | ||
99 | |||
100 | switch (*resalg) { | ||
101 | case NID_des_cbc: | ||
102 | alg_name = "cbc(des)"; | ||
103 | setkey = 1; | ||
104 | break; | ||
105 | case NID_cast5_cbc: | ||
106 | /* XXXX here in name only, not used */ | ||
107 | alg_name = "cbc(cast5)"; | ||
108 | setkey = 0; /* XXX will need to set to 1 */ | ||
109 | break; | ||
110 | case NID_md5: | ||
111 | if (key.len == 0) { | ||
112 | dprintk("RPC: SPKM3 get_key: NID_md5 zero Key length\n"); | ||
113 | } | ||
114 | alg_name = "md5"; | ||
115 | setkey = 0; | ||
116 | break; | ||
117 | default: | ||
118 | dprintk("gss_spkm3_mech: unsupported algorithm %d\n", *resalg); | ||
119 | goto out_err_free_key; | ||
120 | } | ||
121 | *res = crypto_alloc_blkcipher(alg_name, 0, CRYPTO_ALG_ASYNC); | ||
122 | if (IS_ERR(*res)) { | ||
123 | printk("gss_spkm3_mech: unable to initialize crypto algorthm %s\n", alg_name); | ||
124 | *res = NULL; | ||
125 | goto out_err_free_key; | ||
126 | } | ||
127 | if (setkey) { | ||
128 | if (crypto_blkcipher_setkey(*res, key.data, key.len)) { | ||
129 | printk("gss_spkm3_mech: error setting key for crypto algorthm %s\n", alg_name); | ||
130 | goto out_err_free_tfm; | ||
131 | } | ||
132 | } | ||
133 | |||
134 | if(key.len > 0) | ||
135 | kfree(key.data); | ||
136 | return p; | ||
137 | |||
138 | out_err_free_tfm: | ||
139 | crypto_free_blkcipher(*res); | ||
140 | out_err_free_key: | ||
141 | if(key.len > 0) | ||
142 | kfree(key.data); | ||
143 | p = ERR_PTR(-EINVAL); | ||
144 | out_err: | ||
145 | return p; | ||
146 | } | ||
147 | |||
148 | static int | 85 | static int |
149 | gss_import_sec_context_spkm3(const void *p, size_t len, | 86 | gss_import_sec_context_spkm3(const void *p, size_t len, |
150 | struct gss_ctx *ctx_id) | 87 | struct gss_ctx *ctx_id) |
151 | { | 88 | { |
152 | const void *end = (const void *)((const char *)p + len); | 89 | const void *end = (const void *)((const char *)p + len); |
153 | struct spkm3_ctx *ctx; | 90 | struct spkm3_ctx *ctx; |
91 | int version; | ||
154 | 92 | ||
155 | if (!(ctx = kzalloc(sizeof(*ctx), GFP_KERNEL))) | 93 | if (!(ctx = kzalloc(sizeof(*ctx), GFP_KERNEL))) |
156 | goto out_err; | 94 | goto out_err; |
157 | 95 | ||
96 | p = simple_get_bytes(p, end, &version, sizeof(version)); | ||
97 | if (IS_ERR(p)) | ||
98 | goto out_err_free_ctx; | ||
99 | if (version != 1) { | ||
100 | dprintk("RPC: unknown spkm3 token format: obsolete nfs-utils?\n"); | ||
101 | goto out_err_free_ctx; | ||
102 | } | ||
103 | |||
158 | p = simple_get_netobj(p, end, &ctx->ctx_id); | 104 | p = simple_get_netobj(p, end, &ctx->ctx_id); |
159 | if (IS_ERR(p)) | 105 | if (IS_ERR(p)) |
160 | goto out_err_free_ctx; | 106 | goto out_err_free_ctx; |
161 | 107 | ||
162 | p = simple_get_bytes(p, end, &ctx->qop, sizeof(ctx->qop)); | 108 | p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime)); |
163 | if (IS_ERR(p)) | 109 | if (IS_ERR(p)) |
164 | goto out_err_free_ctx_id; | 110 | goto out_err_free_ctx_id; |
165 | 111 | ||
166 | p = simple_get_netobj(p, end, &ctx->mech_used); | 112 | p = simple_get_netobj(p, end, &ctx->mech_used); |
167 | if (IS_ERR(p)) | 113 | if (IS_ERR(p)) |
168 | goto out_err_free_mech; | 114 | goto out_err_free_ctx_id; |
169 | 115 | ||
170 | p = simple_get_bytes(p, end, &ctx->ret_flags, sizeof(ctx->ret_flags)); | 116 | p = simple_get_bytes(p, end, &ctx->ret_flags, sizeof(ctx->ret_flags)); |
171 | if (IS_ERR(p)) | 117 | if (IS_ERR(p)) |
172 | goto out_err_free_mech; | 118 | goto out_err_free_mech; |
173 | 119 | ||
174 | p = simple_get_bytes(p, end, &ctx->req_flags, sizeof(ctx->req_flags)); | 120 | p = simple_get_netobj(p, end, &ctx->conf_alg); |
175 | if (IS_ERR(p)) | 121 | if (IS_ERR(p)) |
176 | goto out_err_free_mech; | 122 | goto out_err_free_mech; |
177 | 123 | ||
178 | p = simple_get_netobj(p, end, &ctx->share_key); | 124 | p = simple_get_netobj(p, end, &ctx->derived_conf_key); |
179 | if (IS_ERR(p)) | ||
180 | goto out_err_free_s_key; | ||
181 | |||
182 | p = get_key(p, end, &ctx->derived_conf_key, &ctx->conf_alg); | ||
183 | if (IS_ERR(p)) | 125 | if (IS_ERR(p)) |
184 | goto out_err_free_s_key; | 126 | goto out_err_free_conf_alg; |
185 | 127 | ||
186 | p = get_key(p, end, &ctx->derived_integ_key, &ctx->intg_alg); | 128 | p = simple_get_netobj(p, end, &ctx->intg_alg); |
187 | if (IS_ERR(p)) | 129 | if (IS_ERR(p)) |
188 | goto out_err_free_key1; | 130 | goto out_err_free_conf_key; |
189 | 131 | ||
190 | p = simple_get_bytes(p, end, &ctx->keyestb_alg, sizeof(ctx->keyestb_alg)); | 132 | p = simple_get_netobj(p, end, &ctx->derived_integ_key); |
191 | if (IS_ERR(p)) | 133 | if (IS_ERR(p)) |
192 | goto out_err_free_key2; | 134 | goto out_err_free_intg_alg; |
193 | |||
194 | p = simple_get_bytes(p, end, &ctx->owf_alg, sizeof(ctx->owf_alg)); | ||
195 | if (IS_ERR(p)) | ||
196 | goto out_err_free_key2; | ||
197 | 135 | ||
198 | if (p != end) | 136 | if (p != end) |
199 | goto out_err_free_key2; | 137 | goto out_err_free_intg_key; |
200 | 138 | ||
201 | ctx_id->internal_ctx_id = ctx; | 139 | ctx_id->internal_ctx_id = ctx; |
202 | 140 | ||
203 | dprintk("Successfully imported new spkm context.\n"); | 141 | dprintk("Successfully imported new spkm context.\n"); |
204 | return 0; | 142 | return 0; |
205 | 143 | ||
206 | out_err_free_key2: | 144 | out_err_free_intg_key: |
207 | crypto_free_blkcipher(ctx->derived_integ_key); | 145 | kfree(ctx->derived_integ_key.data); |
208 | out_err_free_key1: | 146 | out_err_free_intg_alg: |
209 | crypto_free_blkcipher(ctx->derived_conf_key); | 147 | kfree(ctx->intg_alg.data); |
210 | out_err_free_s_key: | 148 | out_err_free_conf_key: |
211 | kfree(ctx->share_key.data); | 149 | kfree(ctx->derived_conf_key.data); |
150 | out_err_free_conf_alg: | ||
151 | kfree(ctx->conf_alg.data); | ||
212 | out_err_free_mech: | 152 | out_err_free_mech: |
213 | kfree(ctx->mech_used.data); | 153 | kfree(ctx->mech_used.data); |
214 | out_err_free_ctx_id: | 154 | out_err_free_ctx_id: |
@@ -220,13 +160,16 @@ out_err: | |||
220 | } | 160 | } |
221 | 161 | ||
222 | static void | 162 | static void |
223 | gss_delete_sec_context_spkm3(void *internal_ctx) { | 163 | gss_delete_sec_context_spkm3(void *internal_ctx) |
164 | { | ||
224 | struct spkm3_ctx *sctx = internal_ctx; | 165 | struct spkm3_ctx *sctx = internal_ctx; |
225 | 166 | ||
226 | crypto_free_blkcipher(sctx->derived_integ_key); | 167 | kfree(sctx->derived_integ_key.data); |
227 | crypto_free_blkcipher(sctx->derived_conf_key); | 168 | kfree(sctx->intg_alg.data); |
228 | kfree(sctx->share_key.data); | 169 | kfree(sctx->derived_conf_key.data); |
170 | kfree(sctx->conf_alg.data); | ||
229 | kfree(sctx->mech_used.data); | 171 | kfree(sctx->mech_used.data); |
172 | kfree(sctx->ctx_id.data); | ||
230 | kfree(sctx); | 173 | kfree(sctx); |
231 | } | 174 | } |
232 | 175 | ||
@@ -238,7 +181,6 @@ gss_verify_mic_spkm3(struct gss_ctx *ctx, | |||
238 | u32 maj_stat = 0; | 181 | u32 maj_stat = 0; |
239 | struct spkm3_ctx *sctx = ctx->internal_ctx_id; | 182 | struct spkm3_ctx *sctx = ctx->internal_ctx_id; |
240 | 183 | ||
241 | dprintk("RPC: gss_verify_mic_spkm3 calling spkm3_read_token\n"); | ||
242 | maj_stat = spkm3_read_token(sctx, checksum, signbuf, SPKM_MIC_TOK); | 184 | maj_stat = spkm3_read_token(sctx, checksum, signbuf, SPKM_MIC_TOK); |
243 | 185 | ||
244 | dprintk("RPC: gss_verify_mic_spkm3 returning %d\n", maj_stat); | 186 | dprintk("RPC: gss_verify_mic_spkm3 returning %d\n", maj_stat); |
@@ -253,10 +195,9 @@ gss_get_mic_spkm3(struct gss_ctx *ctx, | |||
253 | u32 err = 0; | 195 | u32 err = 0; |
254 | struct spkm3_ctx *sctx = ctx->internal_ctx_id; | 196 | struct spkm3_ctx *sctx = ctx->internal_ctx_id; |
255 | 197 | ||
256 | dprintk("RPC: gss_get_mic_spkm3\n"); | ||
257 | |||
258 | err = spkm3_make_token(sctx, message_buffer, | 198 | err = spkm3_make_token(sctx, message_buffer, |
259 | message_token, SPKM_MIC_TOK); | 199 | message_token, SPKM_MIC_TOK); |
200 | dprintk("RPC: gss_get_mic_spkm3 returning %d\n", err); | ||
260 | return err; | 201 | return err; |
261 | } | 202 | } |
262 | 203 | ||
diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c index 18c7862bc234..b179d58c6249 100644 --- a/net/sunrpc/auth_gss/gss_spkm3_seal.c +++ b/net/sunrpc/auth_gss/gss_spkm3_seal.c | |||
@@ -39,11 +39,17 @@ | |||
39 | #include <linux/sunrpc/gss_spkm3.h> | 39 | #include <linux/sunrpc/gss_spkm3.h> |
40 | #include <linux/random.h> | 40 | #include <linux/random.h> |
41 | #include <linux/crypto.h> | 41 | #include <linux/crypto.h> |
42 | #include <linux/pagemap.h> | ||
43 | #include <linux/scatterlist.h> | ||
44 | #include <linux/sunrpc/xdr.h> | ||
42 | 45 | ||
43 | #ifdef RPC_DEBUG | 46 | #ifdef RPC_DEBUG |
44 | # define RPCDBG_FACILITY RPCDBG_AUTH | 47 | # define RPCDBG_FACILITY RPCDBG_AUTH |
45 | #endif | 48 | #endif |
46 | 49 | ||
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 | |||
47 | /* | 53 | /* |
48 | * spkm3_make_token() | 54 | * spkm3_make_token() |
49 | * | 55 | * |
@@ -66,29 +72,23 @@ spkm3_make_token(struct spkm3_ctx *ctx, | |||
66 | int ctxelen = 0, ctxzbit = 0; | 72 | int ctxelen = 0, ctxzbit = 0; |
67 | int md5elen = 0, md5zbit = 0; | 73 | int md5elen = 0, md5zbit = 0; |
68 | 74 | ||
69 | dprintk("RPC: spkm3_make_token\n"); | ||
70 | |||
71 | now = jiffies; | 75 | now = jiffies; |
72 | 76 | ||
73 | if (ctx->ctx_id.len != 16) { | 77 | if (ctx->ctx_id.len != 16) { |
74 | dprintk("RPC: spkm3_make_token BAD ctx_id.len %d\n", | 78 | dprintk("RPC: spkm3_make_token BAD ctx_id.len %d\n", |
75 | ctx->ctx_id.len); | 79 | ctx->ctx_id.len); |
76 | goto out_err; | 80 | goto out_err; |
77 | } | 81 | } |
78 | 82 | ||
79 | switch (ctx->intg_alg) { | 83 | if (!g_OID_equal(&ctx->intg_alg, &hmac_md5_oid)) { |
80 | case NID_md5: | 84 | dprintk("RPC: gss_spkm3_seal: unsupported I-ALG algorithm." |
81 | checksum_type = CKSUMTYPE_RSA_MD5; | 85 | "only support hmac-md5 I-ALG.\n"); |
82 | break; | 86 | goto out_err; |
83 | default: | 87 | } else |
84 | dprintk("RPC: gss_spkm3_seal: ctx->signalg %d not" | 88 | checksum_type = CKSUMTYPE_HMAC_MD5; |
85 | " supported\n", ctx->intg_alg); | 89 | |
86 | goto out_err; | 90 | if (!g_OID_equal(&ctx->conf_alg, &cast5_cbc_oid)) { |
87 | } | 91 | dprintk("RPC: gss_spkm3_seal: unsupported C-ALG algorithm\n"); |
88 | /* XXX since we don't support WRAP, perhaps we don't care... */ | ||
89 | if (ctx->conf_alg != NID_cast5_cbc) { | ||
90 | dprintk("RPC: gss_spkm3_seal: ctx->sealalg %d not supported\n", | ||
91 | ctx->conf_alg); | ||
92 | goto out_err; | 92 | goto out_err; |
93 | } | 93 | } |
94 | 94 | ||
@@ -96,10 +96,10 @@ spkm3_make_token(struct spkm3_ctx *ctx, | |||
96 | /* Calculate checksum over the mic-header */ | 96 | /* Calculate checksum over the mic-header */ |
97 | asn1_bitstring_len(&ctx->ctx_id, &ctxelen, &ctxzbit); | 97 | asn1_bitstring_len(&ctx->ctx_id, &ctxelen, &ctxzbit); |
98 | spkm3_mic_header(&mic_hdr.data, &mic_hdr.len, ctx->ctx_id.data, | 98 | spkm3_mic_header(&mic_hdr.data, &mic_hdr.len, ctx->ctx_id.data, |
99 | ctxelen, ctxzbit); | 99 | ctxelen, ctxzbit); |
100 | 100 | if (make_spkm3_checksum(checksum_type, &ctx->derived_integ_key, | |
101 | if (make_checksum(checksum_type, mic_hdr.data, mic_hdr.len, | 101 | (char *)mic_hdr.data, mic_hdr.len, |
102 | text, 0, &md5cksum)) | 102 | text, 0, &md5cksum)) |
103 | goto out_err; | 103 | goto out_err; |
104 | 104 | ||
105 | asn1_bitstring_len(&md5cksum, &md5elen, &md5zbit); | 105 | asn1_bitstring_len(&md5cksum, &md5elen, &md5zbit); |
@@ -121,7 +121,66 @@ spkm3_make_token(struct spkm3_ctx *ctx, | |||
121 | 121 | ||
122 | return GSS_S_COMPLETE; | 122 | return GSS_S_COMPLETE; |
123 | out_err: | 123 | out_err: |
124 | if (md5cksum.data) | ||
125 | kfree(md5cksum.data); | ||
126 | |||
124 | token->data = NULL; | 127 | token->data = NULL; |
125 | token->len = 0; | 128 | token->len = 0; |
126 | return GSS_S_FAILURE; | 129 | return GSS_S_FAILURE; |
127 | } | 130 | } |
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); | ||
diff --git a/net/sunrpc/auth_gss/gss_spkm3_token.c b/net/sunrpc/auth_gss/gss_spkm3_token.c index 854a983ccf26..35188b6ea8f7 100644 --- a/net/sunrpc/auth_gss/gss_spkm3_token.c +++ b/net/sunrpc/auth_gss/gss_spkm3_token.c | |||
@@ -172,10 +172,10 @@ spkm3_mic_header(unsigned char **hdrbuf, unsigned int *hdrlen, unsigned char *ct | |||
172 | *(u8 *)hptr++ = zbit; | 172 | *(u8 *)hptr++ = zbit; |
173 | memcpy(hptr, ctxdata, elen); | 173 | memcpy(hptr, ctxdata, elen); |
174 | hptr += elen; | 174 | hptr += elen; |
175 | *hdrlen = hptr - top; | 175 | *hdrlen = hptr - top; |
176 | } | 176 | } |
177 | 177 | ||
178 | /* | 178 | /* |
179 | * spkm3_mic_innercontext_token() | 179 | * spkm3_mic_innercontext_token() |
180 | * | 180 | * |
181 | * *tokp points to the beginning of the SPKM_MIC token described | 181 | * *tokp points to the beginning of the SPKM_MIC token described |
diff --git a/net/sunrpc/auth_gss/gss_spkm3_unseal.c b/net/sunrpc/auth_gss/gss_spkm3_unseal.c index 544eb6fd9094..e54581ca7570 100644 --- a/net/sunrpc/auth_gss/gss_spkm3_unseal.c +++ b/net/sunrpc/auth_gss/gss_spkm3_unseal.c | |||
@@ -54,66 +54,70 @@ spkm3_read_token(struct spkm3_ctx *ctx, | |||
54 | struct xdr_buf *message_buffer, /* signbuf */ | 54 | struct xdr_buf *message_buffer, /* signbuf */ |
55 | int toktype) | 55 | int toktype) |
56 | { | 56 | { |
57 | s32 checksum_type; | ||
57 | s32 code; | 58 | s32 code; |
58 | struct xdr_netobj wire_cksum = {.len =0, .data = NULL}; | 59 | struct xdr_netobj wire_cksum = {.len =0, .data = NULL}; |
59 | char cksumdata[16]; | 60 | char cksumdata[16]; |
60 | struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata}; | 61 | struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata}; |
61 | unsigned char *ptr = (unsigned char *)read_token->data; | 62 | unsigned char *ptr = (unsigned char *)read_token->data; |
62 | unsigned char *cksum; | 63 | unsigned char *cksum; |
63 | int bodysize, md5elen; | 64 | int bodysize, md5elen; |
64 | int mic_hdrlen; | 65 | int mic_hdrlen; |
65 | u32 ret = GSS_S_DEFECTIVE_TOKEN; | 66 | u32 ret = GSS_S_DEFECTIVE_TOKEN; |
66 | 67 | ||
67 | dprintk("RPC: spkm3_read_token read_token->len %d\n", read_token->len); | ||
68 | |||
69 | if (g_verify_token_header((struct xdr_netobj *) &ctx->mech_used, | 68 | if (g_verify_token_header((struct xdr_netobj *) &ctx->mech_used, |
70 | &bodysize, &ptr, read_token->len)) | 69 | &bodysize, &ptr, read_token->len)) |
71 | goto out; | 70 | goto out; |
72 | 71 | ||
73 | /* decode the token */ | 72 | /* decode the token */ |
74 | 73 | ||
75 | if (toktype == SPKM_MIC_TOK) { | 74 | if (toktype != SPKM_MIC_TOK) { |
76 | 75 | dprintk("RPC: BAD SPKM3 token type: %d\n", toktype); | |
77 | if ((ret = spkm3_verify_mic_token(&ptr, &mic_hdrlen, &cksum))) | 76 | goto out; |
78 | goto out; | 77 | } |
79 | 78 | ||
80 | if (*cksum++ != 0x03) { | 79 | if ((ret = spkm3_verify_mic_token(&ptr, &mic_hdrlen, &cksum))) |
81 | dprintk("RPC: spkm3_read_token BAD checksum type\n"); | 80 | goto out; |
82 | goto out; | 81 | |
83 | } | 82 | if (*cksum++ != 0x03) { |
84 | md5elen = *cksum++; | 83 | dprintk("RPC: spkm3_read_token BAD checksum type\n"); |
85 | cksum++; /* move past the zbit */ | 84 | goto out; |
86 | 85 | } | |
87 | if(!decode_asn1_bitstring(&wire_cksum, cksum, md5elen - 1, 16)) | 86 | md5elen = *cksum++; |
88 | goto out; | 87 | cksum++; /* move past the zbit */ |
89 | 88 | ||
90 | /* HARD CODED FOR MD5 */ | 89 | if (!decode_asn1_bitstring(&wire_cksum, cksum, md5elen - 1, 16)) |
91 | 90 | goto out; | |
92 | /* compute the checksum of the message. | 91 | |
93 | * ptr + 2 = start of header piece of checksum | 92 | /* HARD CODED FOR MD5 */ |
94 | * mic_hdrlen + 2 = length of header piece of checksum | 93 | |
95 | */ | 94 | /* compute the checksum of the message. |
96 | ret = GSS_S_DEFECTIVE_TOKEN; | 95 | * ptr + 2 = start of header piece of checksum |
97 | code = make_checksum(CKSUMTYPE_RSA_MD5, ptr + 2, | 96 | * mic_hdrlen + 2 = length of header piece of checksum |
98 | mic_hdrlen + 2, | 97 | */ |
99 | message_buffer, 0, &md5cksum); | 98 | ret = GSS_S_DEFECTIVE_TOKEN; |
100 | 99 | if (!g_OID_equal(&ctx->intg_alg, &hmac_md5_oid)) { | |
101 | if (code) | 100 | dprintk("RPC: gss_spkm3_seal: unsupported I-ALG algorithm\n"); |
102 | goto out; | 101 | goto out; |
103 | 102 | } | |
104 | dprintk("RPC: spkm3_read_token: digest wire_cksum.len %d:\n", | 103 | |
105 | wire_cksum.len); | 104 | checksum_type = CKSUMTYPE_HMAC_MD5; |
106 | 105 | ||
107 | ret = GSS_S_BAD_SIG; | 106 | code = make_spkm3_checksum(checksum_type, |
108 | code = memcmp(md5cksum.data, wire_cksum.data, wire_cksum.len); | 107 | &ctx->derived_integ_key, ptr + 2, mic_hdrlen + 2, |
109 | if (code) | 108 | message_buffer, 0, &md5cksum); |
110 | goto out; | 109 | |
111 | 110 | if (code) | |
112 | } else { | 111 | goto out; |
113 | dprintk("RPC: BAD or UNSUPPORTED SPKM3 token type: %d\n",toktype); | 112 | |
113 | ret = GSS_S_BAD_SIG; | ||
114 | code = memcmp(md5cksum.data, wire_cksum.data, wire_cksum.len); | ||
115 | if (code) { | ||
116 | dprintk("RPC: bad MIC checksum\n"); | ||
114 | goto out; | 117 | goto out; |
115 | } | 118 | } |
116 | 119 | ||
120 | |||
117 | /* XXX: need to add expiration and sequencing */ | 121 | /* XXX: need to add expiration and sequencing */ |
118 | ret = GSS_S_COMPLETE; | 122 | ret = GSS_S_COMPLETE; |
119 | out: | 123 | out: |