aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorKevin Coffman <kwc@citi.umich.edu>2010-03-17 13:02:51 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-05-14 15:09:16 -0400
commit81d4a4333a1dfd6070f046265d928bb4c79aff88 (patch)
tree652fce6cd75be7388f0cd5c45aec653814710791 /net
parenta8cc1cb7d7a12b0e2855832d10cfbfaffebfad6c (diff)
gss_krb5: introduce encryption type framework
Add enctype framework and change functions to use the generic values from it rather than the values hard-coded for des. Signed-off-by: Kevin Coffman <kwc@citi.umich.edu> Signed-off-by: Steve Dickson <steved@redhat.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_crypto.c18
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_mech.c90
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_seal.c49
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_unseal.c15
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_wrap.c79
5 files changed, 182 insertions, 69 deletions
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index 746b3e139aed..ccd5236953f7 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * linux/net/sunrpc/gss_krb5_crypto.c 2 * linux/net/sunrpc/gss_krb5_crypto.c
3 * 3 *
4 * Copyright (c) 2000 The Regents of the University of Michigan. 4 * Copyright (c) 2000-2008 The Regents of the University of Michigan.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Andy Adamson <andros@umich.edu> 7 * Andy Adamson <andros@umich.edu>
@@ -58,13 +58,13 @@ krb5_encrypt(
58{ 58{
59 u32 ret = -EINVAL; 59 u32 ret = -EINVAL;
60 struct scatterlist sg[1]; 60 struct scatterlist sg[1];
61 u8 local_iv[16] = {0}; 61 u8 local_iv[GSS_KRB5_MAX_BLOCKSIZE] = {0};
62 struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv }; 62 struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv };
63 63
64 if (length % crypto_blkcipher_blocksize(tfm) != 0) 64 if (length % crypto_blkcipher_blocksize(tfm) != 0)
65 goto out; 65 goto out;
66 66
67 if (crypto_blkcipher_ivsize(tfm) > 16) { 67 if (crypto_blkcipher_ivsize(tfm) > GSS_KRB5_MAX_BLOCKSIZE) {
68 dprintk("RPC: gss_k5encrypt: tfm iv size too large %d\n", 68 dprintk("RPC: gss_k5encrypt: tfm iv size too large %d\n",
69 crypto_blkcipher_ivsize(tfm)); 69 crypto_blkcipher_ivsize(tfm));
70 goto out; 70 goto out;
@@ -92,13 +92,13 @@ krb5_decrypt(
92{ 92{
93 u32 ret = -EINVAL; 93 u32 ret = -EINVAL;
94 struct scatterlist sg[1]; 94 struct scatterlist sg[1];
95 u8 local_iv[16] = {0}; 95 u8 local_iv[GSS_KRB5_MAX_BLOCKSIZE] = {0};
96 struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv }; 96 struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv };
97 97
98 if (length % crypto_blkcipher_blocksize(tfm) != 0) 98 if (length % crypto_blkcipher_blocksize(tfm) != 0)
99 goto out; 99 goto out;
100 100
101 if (crypto_blkcipher_ivsize(tfm) > 16) { 101 if (crypto_blkcipher_ivsize(tfm) > GSS_KRB5_MAX_BLOCKSIZE) {
102 dprintk("RPC: gss_k5decrypt: tfm iv size too large %d\n", 102 dprintk("RPC: gss_k5decrypt: tfm iv size too large %d\n",
103 crypto_blkcipher_ivsize(tfm)); 103 crypto_blkcipher_ivsize(tfm));
104 goto out; 104 goto out;
@@ -157,7 +157,7 @@ out:
157} 157}
158 158
159struct encryptor_desc { 159struct encryptor_desc {
160 u8 iv[8]; /* XXX hard-coded blocksize */ 160 u8 iv[GSS_KRB5_MAX_BLOCKSIZE];
161 struct blkcipher_desc desc; 161 struct blkcipher_desc desc;
162 int pos; 162 int pos;
163 struct xdr_buf *outbuf; 163 struct xdr_buf *outbuf;
@@ -198,7 +198,7 @@ encryptor(struct scatterlist *sg, void *data)
198 desc->fraglen += sg->length; 198 desc->fraglen += sg->length;
199 desc->pos += sg->length; 199 desc->pos += sg->length;
200 200
201 fraglen = thislen & 7; /* XXX hardcoded blocksize */ 201 fraglen = thislen & (crypto_blkcipher_blocksize(desc->desc.tfm) - 1);
202 thislen -= fraglen; 202 thislen -= fraglen;
203 203
204 if (thislen == 0) 204 if (thislen == 0)
@@ -256,7 +256,7 @@ gss_encrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf,
256} 256}
257 257
258struct decryptor_desc { 258struct decryptor_desc {
259 u8 iv[8]; /* XXX hard-coded blocksize */ 259 u8 iv[GSS_KRB5_MAX_BLOCKSIZE];
260 struct blkcipher_desc desc; 260 struct blkcipher_desc desc;
261 struct scatterlist frags[4]; 261 struct scatterlist frags[4];
262 int fragno; 262 int fragno;
@@ -278,7 +278,7 @@ decryptor(struct scatterlist *sg, void *data)
278 desc->fragno++; 278 desc->fragno++;
279 desc->fraglen += sg->length; 279 desc->fraglen += sg->length;
280 280
281 fraglen = thislen & 7; /* XXX hardcoded blocksize */ 281 fraglen = thislen & (crypto_blkcipher_blocksize(desc->desc.tfm) - 1);
282 thislen -= fraglen; 282 thislen -= fraglen;
283 283
284 if (thislen == 0) 284 if (thislen == 0)
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index afe09108e1b0..a66eb706aeb7 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * linux/net/sunrpc/gss_krb5_mech.c 2 * linux/net/sunrpc/gss_krb5_mech.c
3 * 3 *
4 * Copyright (c) 2001 The Regents of the University of Michigan. 4 * Copyright (c) 2001-2008 The Regents of the University of Michigan.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Andy Adamson <andros@umich.edu> 7 * Andy Adamson <andros@umich.edu>
@@ -48,6 +48,50 @@
48# define RPCDBG_FACILITY RPCDBG_AUTH 48# define RPCDBG_FACILITY RPCDBG_AUTH
49#endif 49#endif
50 50
51static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
52 /*
53 * DES (All DES enctypes are mapped to the same gss functionality)
54 */
55 {
56 .etype = ENCTYPE_DES_CBC_RAW,
57 .ctype = CKSUMTYPE_RSA_MD5,
58 .name = "des-cbc-crc",
59 .encrypt_name = "cbc(des)",
60 .cksum_name = "md5",
61 .encrypt = krb5_encrypt,
62 .decrypt = krb5_decrypt,
63 .signalg = SGN_ALG_DES_MAC_MD5,
64 .sealalg = SEAL_ALG_DES,
65 .keybytes = 7,
66 .keylength = 8,
67 .blocksize = 8,
68 .cksumlength = 8,
69 },
70};
71
72static const int num_supported_enctypes =
73 ARRAY_SIZE(supported_gss_krb5_enctypes);
74
75static int
76supported_gss_krb5_enctype(int etype)
77{
78 int i;
79 for (i = 0; i < num_supported_enctypes; i++)
80 if (supported_gss_krb5_enctypes[i].etype == etype)
81 return 1;
82 return 0;
83}
84
85static const struct gss_krb5_enctype *
86get_gss_krb5_enctype(int etype)
87{
88 int i;
89 for (i = 0; i < num_supported_enctypes; i++)
90 if (supported_gss_krb5_enctypes[i].etype == etype)
91 return &supported_gss_krb5_enctypes[i];
92 return NULL;
93}
94
51static const void * 95static const void *
52simple_get_bytes(const void *p, const void *end, void *res, int len) 96simple_get_bytes(const void *p, const void *end, void *res, int len)
53{ 97{
@@ -78,35 +122,45 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
78} 122}
79 123
80static inline const void * 124static inline const void *
81get_key(const void *p, const void *end, struct crypto_blkcipher **res) 125get_key(const void *p, const void *end,
126 struct krb5_ctx *ctx, struct crypto_blkcipher **res)
82{ 127{
83 struct xdr_netobj key; 128 struct xdr_netobj key;
84 int alg; 129 int alg;
85 char *alg_name;
86 130
87 p = simple_get_bytes(p, end, &alg, sizeof(alg)); 131 p = simple_get_bytes(p, end, &alg, sizeof(alg));
88 if (IS_ERR(p)) 132 if (IS_ERR(p))
89 goto out_err; 133 goto out_err;
134
135 switch (alg) {
136 case ENCTYPE_DES_CBC_CRC:
137 case ENCTYPE_DES_CBC_MD4:
138 case ENCTYPE_DES_CBC_MD5:
139 /* Map all these key types to ENCTYPE_DES_CBC_RAW */
140 alg = ENCTYPE_DES_CBC_RAW;
141 break;
142 }
143
144 if (!supported_gss_krb5_enctype(alg)) {
145 printk(KERN_WARNING "gss_kerberos_mech: unsupported "
146 "encryption key algorithm %d\n", alg);
147 goto out_err;
148 }
90 p = simple_get_netobj(p, end, &key); 149 p = simple_get_netobj(p, end, &key);
91 if (IS_ERR(p)) 150 if (IS_ERR(p))
92 goto out_err; 151 goto out_err;
93 152
94 switch (alg) { 153 *res = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name, 0,
95 case ENCTYPE_DES_CBC_RAW: 154 CRYPTO_ALG_ASYNC);
96 alg_name = "cbc(des)";
97 break;
98 default:
99 printk("gss_kerberos_mech: unsupported algorithm %d\n", alg);
100 goto out_err_free_key;
101 }
102 *res = crypto_alloc_blkcipher(alg_name, 0, CRYPTO_ALG_ASYNC);
103 if (IS_ERR(*res)) { 155 if (IS_ERR(*res)) {
104 printk("gss_kerberos_mech: unable to initialize crypto algorithm %s\n", alg_name); 156 printk(KERN_WARNING "gss_kerberos_mech: unable to initialize "
157 "crypto algorithm %s\n", ctx->gk5e->encrypt_name);
105 *res = NULL; 158 *res = NULL;
106 goto out_err_free_key; 159 goto out_err_free_key;
107 } 160 }
108 if (crypto_blkcipher_setkey(*res, key.data, key.len)) { 161 if (crypto_blkcipher_setkey(*res, key.data, key.len)) {
109 printk("gss_kerberos_mech: error setting key for crypto algorithm %s\n", alg_name); 162 printk(KERN_WARNING "gss_kerberos_mech: error setting key for "
163 "crypto algorithm %s\n", ctx->gk5e->encrypt_name);
110 goto out_err_free_tfm; 164 goto out_err_free_tfm;
111 } 165 }
112 166
@@ -134,6 +188,10 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx)
134 /* Old format supports only DES! Any other enctype uses new format */ 188 /* Old format supports only DES! Any other enctype uses new format */
135 ctx->enctype = ENCTYPE_DES_CBC_RAW; 189 ctx->enctype = ENCTYPE_DES_CBC_RAW;
136 190
191 ctx->gk5e = get_gss_krb5_enctype(ctx->enctype);
192 if (ctx->gk5e == NULL)
193 goto out_err;
194
137 /* The downcall format was designed before we completely understood 195 /* The downcall format was designed before we completely understood
138 * the uses of the context fields; so it includes some stuff we 196 * the uses of the context fields; so it includes some stuff we
139 * just give some minimal sanity-checking, and some we ignore 197 * just give some minimal sanity-checking, and some we ignore
@@ -164,10 +222,10 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx)
164 p = simple_get_netobj(p, end, &ctx->mech_used); 222 p = simple_get_netobj(p, end, &ctx->mech_used);
165 if (IS_ERR(p)) 223 if (IS_ERR(p))
166 goto out_err; 224 goto out_err;
167 p = get_key(p, end, &ctx->enc); 225 p = get_key(p, end, ctx, &ctx->enc);
168 if (IS_ERR(p)) 226 if (IS_ERR(p))
169 goto out_err_free_mech; 227 goto out_err_free_mech;
170 p = get_key(p, end, &ctx->seq); 228 p = get_key(p, end, ctx, &ctx->seq);
171 if (IS_ERR(p)) 229 if (IS_ERR(p))
172 goto out_err_free_key1; 230 goto out_err_free_key1;
173 if (p != end) { 231 if (p != end) {
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index 71c2014e7ebf..46c6f44e5c3f 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/krb5/k5seal.c 4 * Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/krb5/k5seal.c
5 * 5 *
6 * Copyright (c) 2000 The Regents of the University of Michigan. 6 * Copyright (c) 2000-2008 The Regents of the University of Michigan.
7 * All rights reserved. 7 * All rights reserved.
8 * 8 *
9 * Andy Adamson <andros@umich.edu> 9 * Andy Adamson <andros@umich.edu>
@@ -70,36 +70,47 @@
70 70
71DEFINE_SPINLOCK(krb5_seq_lock); 71DEFINE_SPINLOCK(krb5_seq_lock);
72 72
73static char *
74setup_token(struct krb5_ctx *ctx, struct xdr_netobj *token)
75{
76 __be16 *ptr, *krb5_hdr;
77 int body_size = GSS_KRB5_TOK_HDR_LEN + ctx->gk5e->cksumlength;
78
79 token->len = g_token_size(&ctx->mech_used, body_size);
80
81 ptr = (__be16 *)token->data;
82 g_make_token_header(&ctx->mech_used, body_size, (unsigned char **)&ptr);
83
84 /* ptr now at start of header described in rfc 1964, section 1.2.1: */
85 krb5_hdr = ptr;
86 *ptr++ = KG_TOK_MIC_MSG;
87 *ptr++ = cpu_to_le16(ctx->gk5e->signalg);
88 *ptr++ = SEAL_ALG_NONE;
89 *ptr++ = 0xffff;
90
91 return (char *)krb5_hdr;
92}
93
73static u32 94static u32
74gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text, 95gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text,
75 struct xdr_netobj *token) 96 struct xdr_netobj *token)
76{ 97{
77 char cksumdata[16]; 98 char cksumdata[GSS_KRB5_MAX_CKSUM_LEN];
78 struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata}; 99 struct xdr_netobj md5cksum = {.len = sizeof(cksumdata),
79 unsigned char *ptr, *msg_start; 100 .data = cksumdata};
101 void *ptr;
80 s32 now; 102 s32 now;
81 u32 seq_send; 103 u32 seq_send;
82 104
83 dprintk("RPC: gss_krb5_seal\n"); 105 dprintk("RPC: %s\n", __func__);
84 BUG_ON(ctx == NULL); 106 BUG_ON(ctx == NULL);
85 107
86 now = get_seconds(); 108 now = get_seconds();
87 109
88 token->len = g_token_size(&ctx->mech_used, GSS_KRB5_TOK_HDR_LEN + 8); 110 ptr = setup_token(ctx, token);
89
90 ptr = token->data;
91 g_make_token_header(&ctx->mech_used, GSS_KRB5_TOK_HDR_LEN + 8, &ptr);
92
93 /* ptr now at header described in rfc 1964, section 1.2.1: */
94 ptr[0] = (unsigned char) ((KG_TOK_MIC_MSG >> 8) & 0xff);
95 ptr[1] = (unsigned char) (KG_TOK_MIC_MSG & 0xff);
96
97 msg_start = ptr + GSS_KRB5_TOK_HDR_LEN + 8;
98
99 *(__be16 *)(ptr + 2) = htons(SGN_ALG_DES_MAC_MD5);
100 memset(ptr + 4, 0xff, 4);
101 111
102 if (make_checksum("md5", ptr, 8, text, 0, &md5cksum)) 112 if (make_checksum((char *)ctx->gk5e->cksum_name, ptr, 8,
113 text, 0, &md5cksum))
103 return GSS_S_FAILURE; 114 return GSS_S_FAILURE;
104 115
105 if (krb5_encrypt(ctx->seq, NULL, md5cksum.data, 116 if (krb5_encrypt(ctx->seq, NULL, md5cksum.data,
diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
index 069d4b59807a..10ee641a39d0 100644
--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/krb5/k5unseal.c 4 * Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/krb5/k5unseal.c
5 * 5 *
6 * Copyright (c) 2000 The Regents of the University of Michigan. 6 * Copyright (c) 2000-2008 The Regents of the University of Michigan.
7 * All rights reserved. 7 * All rights reserved.
8 * 8 *
9 * Andy Adamson <andros@umich.edu> 9 * Andy Adamson <andros@umich.edu>
@@ -76,8 +76,9 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
76{ 76{
77 int signalg; 77 int signalg;
78 int sealalg; 78 int sealalg;
79 char cksumdata[16]; 79 char cksumdata[GSS_KRB5_MAX_CKSUM_LEN];
80 struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata}; 80 struct xdr_netobj md5cksum = {.len = sizeof(cksumdata),
81 .data = cksumdata};
81 s32 now; 82 s32 now;
82 int direction; 83 int direction;
83 u32 seqnum; 84 u32 seqnum;
@@ -97,7 +98,7 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
97 /* XXX sanity-check bodysize?? */ 98 /* XXX sanity-check bodysize?? */
98 99
99 signalg = ptr[2] + (ptr[3] << 8); 100 signalg = ptr[2] + (ptr[3] << 8);
100 if (signalg != SGN_ALG_DES_MAC_MD5) 101 if (signalg != ctx->gk5e->signalg)
101 return GSS_S_DEFECTIVE_TOKEN; 102 return GSS_S_DEFECTIVE_TOKEN;
102 103
103 sealalg = ptr[4] + (ptr[5] << 8); 104 sealalg = ptr[4] + (ptr[5] << 8);
@@ -107,13 +108,15 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
107 if ((ptr[6] != 0xff) || (ptr[7] != 0xff)) 108 if ((ptr[6] != 0xff) || (ptr[7] != 0xff))
108 return GSS_S_DEFECTIVE_TOKEN; 109 return GSS_S_DEFECTIVE_TOKEN;
109 110
110 if (make_checksum("md5", ptr, 8, message_buffer, 0, &md5cksum)) 111 if (make_checksum((char *)ctx->gk5e->cksum_name, ptr, 8,
112 message_buffer, 0, &md5cksum))
111 return GSS_S_FAILURE; 113 return GSS_S_FAILURE;
112 114
113 if (krb5_encrypt(ctx->seq, NULL, md5cksum.data, md5cksum.data, 16)) 115 if (krb5_encrypt(ctx->seq, NULL, md5cksum.data, md5cksum.data, 16))
114 return GSS_S_FAILURE; 116 return GSS_S_FAILURE;
115 117
116 if (memcmp(md5cksum.data + 8, ptr + GSS_KRB5_TOK_HDR_LEN, 8)) 118 if (memcmp(md5cksum.data + 8, ptr + GSS_KRB5_TOK_HDR_LEN,
119 ctx->gk5e->cksumlength))
117 return GSS_S_BAD_SIG; 120 return GSS_S_BAD_SIG;
118 121
119 /* it got through unscathed. Make sure the context is unexpired */ 122 /* it got through unscathed. Make sure the context is unexpired */
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index b45b59b17ae1..7188891bcc33 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -1,3 +1,33 @@
1/*
2 * COPYRIGHT (c) 2008
3 * The Regents of the University of Michigan
4 * ALL RIGHTS RESERVED
5 *
6 * Permission is granted to use, copy, create derivative works
7 * and redistribute this software and such derivative works
8 * for any purpose, so long as the name of The University of
9 * Michigan is not used in any advertising or publicity
10 * pertaining to the use of distribution of this software
11 * without specific, written prior authorization. If the
12 * above copyright notice or any other identification of the
13 * University of Michigan is included in any copy of any
14 * portion of this software, then the disclaimer below must
15 * also be included.
16 *
17 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
18 * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
19 * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
20 * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
21 * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
23 * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
24 * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
25 * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
26 * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
27 * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGES.
29 */
30
1#include <linux/types.h> 31#include <linux/types.h>
2#include <linux/jiffies.h> 32#include <linux/jiffies.h>
3#include <linux/sunrpc/gss_krb5.h> 33#include <linux/sunrpc/gss_krb5.h>
@@ -128,8 +158,9 @@ static u32
128gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, 158gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
129 struct xdr_buf *buf, struct page **pages) 159 struct xdr_buf *buf, struct page **pages)
130{ 160{
131 char cksumdata[16]; 161 char cksumdata[GSS_KRB5_MAX_CKSUM_LEN];
132 struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata}; 162 struct xdr_netobj md5cksum = {.len = sizeof(cksumdata),
163 .data = cksumdata};
133 int blocksize = 0, plainlen; 164 int blocksize = 0, plainlen;
134 unsigned char *ptr, *msg_start; 165 unsigned char *ptr, *msg_start;
135 s32 now; 166 s32 now;
@@ -137,7 +168,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
137 struct page **tmp_pages; 168 struct page **tmp_pages;
138 u32 seq_send; 169 u32 seq_send;
139 170
140 dprintk("RPC: gss_wrap_kerberos\n"); 171 dprintk("RPC: %s\n", __func__);
141 172
142 now = get_seconds(); 173 now = get_seconds();
143 174
@@ -146,8 +177,9 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
146 BUG_ON((buf->len - offset) % blocksize); 177 BUG_ON((buf->len - offset) % blocksize);
147 plainlen = blocksize + buf->len - offset; 178 plainlen = blocksize + buf->len - offset;
148 179
149 headlen = g_token_size(&kctx->mech_used, 24 + plainlen) - 180 headlen = g_token_size(&kctx->mech_used,
150 (buf->len - offset); 181 GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength + plainlen) -
182 (buf->len - offset);
151 183
152 ptr = buf->head[0].iov_base + offset; 184 ptr = buf->head[0].iov_base + offset;
153 /* shift data to make room for header. */ 185 /* shift data to make room for header. */
@@ -157,25 +189,26 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
157 BUG_ON((buf->len - offset - headlen) % blocksize); 189 BUG_ON((buf->len - offset - headlen) % blocksize);
158 190
159 g_make_token_header(&kctx->mech_used, 191 g_make_token_header(&kctx->mech_used,
160 GSS_KRB5_TOK_HDR_LEN + 8 + plainlen, &ptr); 192 GSS_KRB5_TOK_HDR_LEN +
193 kctx->gk5e->cksumlength + plainlen, &ptr);
161 194
162 195
163 /* ptr now at header described in rfc 1964, section 1.2.1: */ 196 /* ptr now at header described in rfc 1964, section 1.2.1: */
164 ptr[0] = (unsigned char) ((KG_TOK_WRAP_MSG >> 8) & 0xff); 197 ptr[0] = (unsigned char) ((KG_TOK_WRAP_MSG >> 8) & 0xff);
165 ptr[1] = (unsigned char) (KG_TOK_WRAP_MSG & 0xff); 198 ptr[1] = (unsigned char) (KG_TOK_WRAP_MSG & 0xff);
166 199
167 msg_start = ptr + 24; 200 msg_start = ptr + GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength;
168 201
169 *(__be16 *)(ptr + 2) = htons(SGN_ALG_DES_MAC_MD5); 202 *(__be16 *)(ptr + 2) = cpu_to_le16(kctx->gk5e->signalg);
170 memset(ptr + 4, 0xff, 4); 203 memset(ptr + 4, 0xff, 4);
171 *(__be16 *)(ptr + 4) = htons(SEAL_ALG_DES); 204 *(__be16 *)(ptr + 4) = cpu_to_le16(kctx->gk5e->sealalg);
172 205
173 make_confounder(msg_start, blocksize); 206 make_confounder(msg_start, blocksize);
174 207
175 /* XXXJBF: UGH!: */ 208 /* XXXJBF: UGH!: */
176 tmp_pages = buf->pages; 209 tmp_pages = buf->pages;
177 buf->pages = pages; 210 buf->pages = pages;
178 if (make_checksum("md5", ptr, 8, buf, 211 if (make_checksum((char *)kctx->gk5e->cksum_name, ptr, 8, buf,
179 offset + headlen - blocksize, &md5cksum)) 212 offset + headlen - blocksize, &md5cksum))
180 return GSS_S_FAILURE; 213 return GSS_S_FAILURE;
181 buf->pages = tmp_pages; 214 buf->pages = tmp_pages;
@@ -207,8 +240,9 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
207{ 240{
208 int signalg; 241 int signalg;
209 int sealalg; 242 int sealalg;
210 char cksumdata[16]; 243 char cksumdata[GSS_KRB5_MAX_CKSUM_LEN];
211 struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata}; 244 struct xdr_netobj md5cksum = {.len = sizeof(cksumdata),
245 .data = cksumdata};
212 s32 now; 246 s32 now;
213 int direction; 247 int direction;
214 s32 seqnum; 248 s32 seqnum;
@@ -217,6 +251,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
217 void *data_start, *orig_start; 251 void *data_start, *orig_start;
218 int data_len; 252 int data_len;
219 int blocksize; 253 int blocksize;
254 int crypt_offset;
220 255
221 dprintk("RPC: gss_unwrap_kerberos\n"); 256 dprintk("RPC: gss_unwrap_kerberos\n");
222 257
@@ -234,22 +269,27 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
234 /* get the sign and seal algorithms */ 269 /* get the sign and seal algorithms */
235 270
236 signalg = ptr[2] + (ptr[3] << 8); 271 signalg = ptr[2] + (ptr[3] << 8);
237 if (signalg != SGN_ALG_DES_MAC_MD5) 272 if (signalg != kctx->gk5e->signalg)
238 return GSS_S_DEFECTIVE_TOKEN; 273 return GSS_S_DEFECTIVE_TOKEN;
239 274
240 sealalg = ptr[4] + (ptr[5] << 8); 275 sealalg = ptr[4] + (ptr[5] << 8);
241 if (sealalg != SEAL_ALG_DES) 276 if (sealalg != kctx->gk5e->sealalg)
242 return GSS_S_DEFECTIVE_TOKEN; 277 return GSS_S_DEFECTIVE_TOKEN;
243 278
244 if ((ptr[6] != 0xff) || (ptr[7] != 0xff)) 279 if ((ptr[6] != 0xff) || (ptr[7] != 0xff))
245 return GSS_S_DEFECTIVE_TOKEN; 280 return GSS_S_DEFECTIVE_TOKEN;
246 281
247 if (gss_decrypt_xdr_buf(kctx->enc, buf, 282 /*
248 ptr + GSS_KRB5_TOK_HDR_LEN + 8 - (unsigned char *)buf->head[0].iov_base)) 283 * Data starts after token header and checksum. ptr points
284 * to the beginning of the token header
285 */
286 crypt_offset = ptr + (GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength) -
287 (unsigned char *)buf->head[0].iov_base;
288 if (gss_decrypt_xdr_buf(kctx->enc, buf, crypt_offset))
249 return GSS_S_DEFECTIVE_TOKEN; 289 return GSS_S_DEFECTIVE_TOKEN;
250 290
251 if (make_checksum("md5", ptr, 8, buf, 291 if (make_checksum((char *)kctx->gk5e->cksum_name, ptr, 8, buf,
252 ptr + GSS_KRB5_TOK_HDR_LEN + 8 - (unsigned char *)buf->head[0].iov_base, &md5cksum)) 292 crypt_offset, &md5cksum))
253 return GSS_S_FAILURE; 293 return GSS_S_FAILURE;
254 294
255 if (krb5_encrypt(kctx->seq, NULL, md5cksum.data, 295 if (krb5_encrypt(kctx->seq, NULL, md5cksum.data,
@@ -280,7 +320,8 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
280 * better to copy and encrypt at the same time. */ 320 * better to copy and encrypt at the same time. */
281 321
282 blocksize = crypto_blkcipher_blocksize(kctx->enc); 322 blocksize = crypto_blkcipher_blocksize(kctx->enc);
283 data_start = ptr + GSS_KRB5_TOK_HDR_LEN + 8 + blocksize; 323 data_start = ptr + (GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength) +
324 blocksize;
284 orig_start = buf->head[0].iov_base + offset; 325 orig_start = buf->head[0].iov_base + offset;
285 data_len = (buf->head[0].iov_base + buf->head[0].iov_len) - data_start; 326 data_len = (buf->head[0].iov_base + buf->head[0].iov_len) - data_start;
286 memmove(orig_start, data_start, data_len); 327 memmove(orig_start, data_start, data_len);