Skip to content

Commit 47d8480

Browse files
Kevin CoffmanTrond Myklebust
authored andcommitted
gss_krb5: handle new context format from gssd
For encryption types other than DES, gssd sends down context information in a new format. This new format includes the information needed to support the new Kerberos GSS-API tokens defined in rfc4121. Signed-off-by: Kevin Coffman <[email protected]> Signed-off-by: Steve Dickson <[email protected]> Signed-off-by: Trond Myklebust <[email protected]>
1 parent 4891f2d commit 47d8480

File tree

3 files changed

+258
-4
lines changed

3 files changed

+258
-4
lines changed

include/linux/sunrpc/gss_krb5.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,21 +72,36 @@ struct gss_krb5_enctype {
7272
u32 (*decrypt) (struct crypto_blkcipher *tfm,
7373
void *iv, void *in, void *out,
7474
int length); /* decryption function */
75-
u32 (*mk_key) (struct gss_krb5_enctype *gk5e,
75+
u32 (*mk_key) (const struct gss_krb5_enctype *gk5e,
7676
struct xdr_netobj *in,
7777
struct xdr_netobj *out); /* complete key generation */
7878
};
7979

80+
/* krb5_ctx flags definitions */
81+
#define KRB5_CTX_FLAG_INITIATOR 0x00000001
82+
#define KRB5_CTX_FLAG_CFX 0x00000002
83+
#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004
84+
8085
struct krb5_ctx {
8186
int initiate; /* 1 = initiating, 0 = accepting */
8287
u32 enctype;
88+
u32 flags;
8389
const struct gss_krb5_enctype *gk5e; /* enctype-specific info */
8490
struct crypto_blkcipher *enc;
8591
struct crypto_blkcipher *seq;
92+
struct crypto_blkcipher *acceptor_enc;
93+
struct crypto_blkcipher *initiator_enc;
8694
u8 cksum[GSS_KRB5_MAX_KEYLEN];
8795
s32 endtime;
8896
u32 seq_send;
97+
u64 seq_send64;
8998
struct xdr_netobj mech_used;
99+
u8 initiator_sign[GSS_KRB5_MAX_KEYLEN];
100+
u8 acceptor_sign[GSS_KRB5_MAX_KEYLEN];
101+
u8 initiator_seal[GSS_KRB5_MAX_KEYLEN];
102+
u8 acceptor_seal[GSS_KRB5_MAX_KEYLEN];
103+
u8 initiator_integ[GSS_KRB5_MAX_KEYLEN];
104+
u8 acceptor_integ[GSS_KRB5_MAX_KEYLEN];
90105
};
91106

92107
extern spinlock_t krb5_seq_lock;
@@ -151,6 +166,10 @@ enum seal_alg {
151166
#define ENCTYPE_DES3_CBC_RAW 0x0006 /* DES-3 cbc mode raw */
152167
#define ENCTYPE_DES_HMAC_SHA1 0x0008
153168
#define ENCTYPE_DES3_CBC_SHA1 0x0010
169+
#define ENCTYPE_AES128_CTS_HMAC_SHA1_96 0x0011
170+
#define ENCTYPE_AES256_CTS_HMAC_SHA1_96 0x0012
171+
#define ENCTYPE_ARCFOUR_HMAC 0x0017
172+
#define ENCTYPE_ARCFOUR_HMAC_EXP 0x0018
154173
#define ENCTYPE_UNKNOWN 0x01ff
155174

156175
/*
@@ -238,7 +257,7 @@ int
238257
xdr_extend_head(struct xdr_buf *buf, unsigned int base, unsigned int shiftlen);
239258

240259
u32
241-
krb5_derive_key(struct gss_krb5_enctype *gk5e,
260+
krb5_derive_key(const struct gss_krb5_enctype *gk5e,
242261
const struct xdr_netobj *inkey,
243262
struct xdr_netobj *outkey,
244263
const struct xdr_netobj *in_constant);

net/sunrpc/auth_gss/gss_krb5_keys.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ static void krb5_nfold(u32 inbits, const u8 *in,
147147
* Taken from MIT Kerberos and modified.
148148
*/
149149

150-
u32 krb5_derive_key(struct gss_krb5_enctype *gk5e,
150+
u32 krb5_derive_key(const struct gss_krb5_enctype *gk5e,
151151
const struct xdr_netobj *inkey,
152152
struct xdr_netobj *outkey,
153153
const struct xdr_netobj *in_constant)

net/sunrpc/auth_gss/gss_krb5_mech.c

Lines changed: 236 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
# define RPCDBG_FACILITY RPCDBG_AUTH
4949
#endif
5050

51+
static struct gss_api_mech gss_kerberos_mech; /* forward declaration */
52+
5153
static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
5254
/*
5355
* DES (All DES enctypes are mapped to the same gss functionality)
@@ -247,6 +249,237 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx)
247249
return PTR_ERR(p);
248250
}
249251

252+
struct crypto_blkcipher *
253+
context_v2_alloc_cipher(struct krb5_ctx *ctx, u8 *key)
254+
{
255+
struct crypto_blkcipher *cp;
256+
257+
cp = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name,
258+
0, CRYPTO_ALG_ASYNC);
259+
if (IS_ERR(cp)) {
260+
dprintk("gss_kerberos_mech: unable to initialize "
261+
"crypto algorithm %s\n", ctx->gk5e->encrypt_name);
262+
return NULL;
263+
}
264+
if (crypto_blkcipher_setkey(cp, key, ctx->gk5e->keylength)) {
265+
dprintk("gss_kerberos_mech: error setting key for "
266+
"crypto algorithm %s\n", ctx->gk5e->encrypt_name);
267+
crypto_free_blkcipher(cp);
268+
return NULL;
269+
}
270+
return cp;
271+
}
272+
273+
static inline void
274+
set_cdata(u8 cdata[GSS_KRB5_K5CLENGTH], u32 usage, u8 seed)
275+
{
276+
cdata[0] = (usage>>24)&0xff;
277+
cdata[1] = (usage>>16)&0xff;
278+
cdata[2] = (usage>>8)&0xff;
279+
cdata[3] = usage&0xff;
280+
cdata[4] = seed;
281+
}
282+
283+
static int
284+
context_derive_keys_des3(struct krb5_ctx *ctx, u8 *rawkey, u32 keylen)
285+
{
286+
struct xdr_netobj c, keyin, keyout;
287+
u8 cdata[GSS_KRB5_K5CLENGTH];
288+
u32 err;
289+
290+
c.len = GSS_KRB5_K5CLENGTH;
291+
c.data = cdata;
292+
293+
keyin.data = rawkey;
294+
keyin.len = keylen;
295+
keyout.len = keylen;
296+
297+
/* seq uses the raw key */
298+
ctx->seq = context_v2_alloc_cipher(ctx, rawkey);
299+
if (ctx->seq == NULL)
300+
goto out_err;
301+
302+
ctx->enc = context_v2_alloc_cipher(ctx, rawkey);
303+
if (ctx->enc == NULL)
304+
goto out_free_seq;
305+
306+
/* derive cksum */
307+
set_cdata(cdata, KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM);
308+
keyout.data = ctx->cksum;
309+
err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c);
310+
if (err) {
311+
dprintk("%s: Error %d deriving cksum key\n",
312+
__func__, err);
313+
goto out_free_enc;
314+
}
315+
316+
return 0;
317+
318+
out_free_enc:
319+
crypto_free_blkcipher(ctx->enc);
320+
out_free_seq:
321+
crypto_free_blkcipher(ctx->seq);
322+
out_err:
323+
return -EINVAL;
324+
}
325+
326+
static int
327+
context_derive_keys_new(struct krb5_ctx *ctx, u8 *rawkey, u32 keylen)
328+
{
329+
struct xdr_netobj c, keyin, keyout;
330+
u8 cdata[GSS_KRB5_K5CLENGTH];
331+
u32 err;
332+
333+
c.len = GSS_KRB5_K5CLENGTH;
334+
c.data = cdata;
335+
336+
keyin.data = rawkey;
337+
keyin.len = keylen;
338+
keyout.len = keylen;
339+
340+
/* initiator seal encryption */
341+
set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_ENCRYPTION);
342+
keyout.data = ctx->initiator_seal;
343+
err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c);
344+
if (err) {
345+
dprintk("%s: Error %d deriving initiator_seal key\n",
346+
__func__, err);
347+
goto out_err;
348+
}
349+
ctx->initiator_enc = context_v2_alloc_cipher(ctx, ctx->initiator_seal);
350+
if (ctx->initiator_enc == NULL)
351+
goto out_err;
352+
353+
/* acceptor seal encryption */
354+
set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_ENCRYPTION);
355+
keyout.data = ctx->acceptor_seal;
356+
err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c);
357+
if (err) {
358+
dprintk("%s: Error %d deriving acceptor_seal key\n",
359+
__func__, err);
360+
goto out_free_initiator_enc;
361+
}
362+
ctx->acceptor_enc = context_v2_alloc_cipher(ctx, ctx->acceptor_seal);
363+
if (ctx->acceptor_enc == NULL)
364+
goto out_free_initiator_enc;
365+
366+
/* initiator sign checksum */
367+
set_cdata(cdata, KG_USAGE_INITIATOR_SIGN, KEY_USAGE_SEED_CHECKSUM);
368+
keyout.data = ctx->initiator_sign;
369+
err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c);
370+
if (err) {
371+
dprintk("%s: Error %d deriving initiator_sign key\n",
372+
__func__, err);
373+
goto out_free_acceptor_enc;
374+
}
375+
376+
/* acceptor sign checksum */
377+
set_cdata(cdata, KG_USAGE_ACCEPTOR_SIGN, KEY_USAGE_SEED_CHECKSUM);
378+
keyout.data = ctx->acceptor_sign;
379+
err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c);
380+
if (err) {
381+
dprintk("%s: Error %d deriving acceptor_sign key\n",
382+
__func__, err);
383+
goto out_free_acceptor_enc;
384+
}
385+
386+
/* initiator seal integrity */
387+
set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_INTEGRITY);
388+
keyout.data = ctx->initiator_integ;
389+
err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c);
390+
if (err) {
391+
dprintk("%s: Error %d deriving initiator_integ key\n",
392+
__func__, err);
393+
goto out_free_acceptor_enc;
394+
}
395+
396+
/* acceptor seal integrity */
397+
set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_INTEGRITY);
398+
keyout.data = ctx->acceptor_integ;
399+
err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c);
400+
if (err) {
401+
dprintk("%s: Error %d deriving acceptor_integ key\n",
402+
__func__, err);
403+
goto out_free_acceptor_enc;
404+
}
405+
406+
return 0;
407+
408+
out_free_acceptor_enc:
409+
crypto_free_blkcipher(ctx->acceptor_enc);
410+
out_free_initiator_enc:
411+
crypto_free_blkcipher(ctx->initiator_enc);
412+
out_err:
413+
return -EINVAL;
414+
}
415+
416+
static int
417+
gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx)
418+
{
419+
u8 rawkey[GSS_KRB5_MAX_KEYLEN];
420+
int keylen;
421+
422+
p = simple_get_bytes(p, end, &ctx->flags, sizeof(ctx->flags));
423+
if (IS_ERR(p))
424+
goto out_err;
425+
ctx->initiate = ctx->flags & KRB5_CTX_FLAG_INITIATOR;
426+
427+
p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime));
428+
if (IS_ERR(p))
429+
goto out_err;
430+
p = simple_get_bytes(p, end, &ctx->seq_send64, sizeof(ctx->seq_send64));
431+
if (IS_ERR(p))
432+
goto out_err;
433+
/* set seq_send for use by "older" enctypes */
434+
ctx->seq_send = ctx->seq_send64;
435+
if (ctx->seq_send64 != ctx->seq_send) {
436+
dprintk("%s: seq_send64 %lx, seq_send %x overflow?\n", __func__,
437+
(long unsigned)ctx->seq_send64, ctx->seq_send);
438+
goto out_err;
439+
}
440+
p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype));
441+
if (IS_ERR(p))
442+
goto out_err;
443+
ctx->gk5e = get_gss_krb5_enctype(ctx->enctype);
444+
if (ctx->gk5e == NULL) {
445+
dprintk("gss_kerberos_mech: unsupported krb5 enctype %u\n",
446+
ctx->enctype);
447+
p = ERR_PTR(-EINVAL);
448+
goto out_err;
449+
}
450+
keylen = ctx->gk5e->keylength;
451+
452+
p = simple_get_bytes(p, end, rawkey, keylen);
453+
if (IS_ERR(p))
454+
goto out_err;
455+
456+
if (p != end) {
457+
p = ERR_PTR(-EINVAL);
458+
goto out_err;
459+
}
460+
461+
ctx->mech_used.data = kmemdup(gss_kerberos_mech.gm_oid.data,
462+
gss_kerberos_mech.gm_oid.len, GFP_KERNEL);
463+
if (unlikely(ctx->mech_used.data == NULL)) {
464+
p = ERR_PTR(-ENOMEM);
465+
goto out_err;
466+
}
467+
ctx->mech_used.len = gss_kerberos_mech.gm_oid.len;
468+
469+
switch (ctx->enctype) {
470+
case ENCTYPE_DES3_CBC_RAW:
471+
return context_derive_keys_des3(ctx, rawkey, keylen);
472+
case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
473+
case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
474+
return context_derive_keys_new(ctx, rawkey, keylen);
475+
default:
476+
return -EINVAL;
477+
}
478+
479+
out_err:
480+
return PTR_ERR(p);
481+
}
482+
250483
static int
251484
gss_import_sec_context_kerberos(const void *p, size_t len,
252485
struct gss_ctx *ctx_id)
@@ -262,7 +495,7 @@ gss_import_sec_context_kerberos(const void *p, size_t len,
262495
if (len == 85)
263496
ret = gss_import_v1_context(p, end, ctx);
264497
else
265-
ret = -EINVAL;
498+
ret = gss_import_v2_context(p, end, ctx);
266499

267500
if (ret == 0)
268501
ctx_id->internal_ctx_id = ctx;
@@ -279,6 +512,8 @@ gss_delete_sec_context_kerberos(void *internal_ctx) {
279512

280513
crypto_free_blkcipher(kctx->seq);
281514
crypto_free_blkcipher(kctx->enc);
515+
crypto_free_blkcipher(kctx->acceptor_enc);
516+
crypto_free_blkcipher(kctx->initiator_enc);
282517
kfree(kctx->mech_used.data);
283518
kfree(kctx);
284519
}

0 commit comments

Comments
 (0)