|
|
#include <stdio.h> | #include <stdio.h> |
#include <syslog.h> | #include <syslog.h> |
#include <string.h> | #include <string.h> |
|
#include <errno.h> |
#include <gssapi/gssapi.h> | #include <gssapi/gssapi.h> |
#include <rpc/rpc.h> | #include <rpc/rpc.h> |
#include <rpc/auth_gss.h> | #include <rpc/auth_gss.h> |
|
|
#ifdef HAVE_KRB5 | #ifdef HAVE_KRB5 |
#include <krb5.h> | #include <krb5.h> |
| |
|
/* for 3DES */ |
|
#define KG_USAGE_SEAL 22 |
|
#define KG_USAGE_SIGN 23 |
|
#define KG_USAGE_SEQ 24 |
|
|
|
/* for rfc???? */ |
|
#define KG_USAGE_ACCEPTOR_SEAL 22 |
|
#define KG_USAGE_ACCEPTOR_SIGN 23 |
|
#define KG_USAGE_INITIATOR_SEAL 24 |
|
#define KG_USAGE_INITIATOR_SIGN 25 |
|
|
|
/* Lifted from mit src/lib/gssapi/krb5/gssapiP_krb5.h */ |
|
enum seal_alg { |
|
SEAL_ALG_NONE = 0xffff, |
|
SEAL_ALG_DES = 0x0000, |
|
SEAL_ALG_1 = 0x0001, /* not published */ |
|
SEAL_ALG_MICROSOFT_RC4 = 0x0010, /* microsoft w2k; */ |
|
SEAL_ALG_DES3KD = 0x0002 |
|
}; |
|
|
|
#define KEY_USAGE_SEED_ENCRYPTION 0xAA |
|
#define KEY_USAGE_SEED_INTEGRITY 0x55 |
|
#define KEY_USAGE_SEED_CHECKSUM 0x99 |
|
#define K5CLENGTH 5 |
|
|
|
/* Flags for version 2 context flags */ |
|
#define KRB5_CTX_FLAG_INITIATOR 0x00000001 |
|
#define KRB5_CTX_FLAG_CFX 0x00000002 |
|
#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004 |
|
|
|
/* |
|
* XXX Hack alert. We don't have "legal" access to these |
|
* structures located in libk5crypto |
|
*/ |
|
extern void krb5int_enc_arcfour; |
|
extern void krb5int_enc_des3; |
|
extern void krb5int_enc_aes128; |
|
extern void krb5int_enc_aes256; |
|
extern int krb5_derive_key(); |
|
|
|
void *get_enc_provider(); |
|
|
/* XXX spkm3 seems to actually want it this big, yipes. */ | /* XXX spkm3 seems to actually want it this big, yipes. */ |
#define MAX_CTX_LEN 4096 | #define MAX_CTX_LEN 4096 |
| |
|
|
|
|
#ifdef HAVE_LUCID_CONTEXT_SUPPORT | #ifdef HAVE_LUCID_CONTEXT_SUPPORT |
| |
/* Don't use the private structure, use the exported lucid structure */ | /* Don't use the private structure, use the exported lucid structure */ |
|
Lines 86-92
typedef struct _krb5_gss_ctx_id_rec {
|
Link Here
|
|---|
|
uint64_t seq_recv; /* gssint_uint64 */ | uint64_t seq_recv; /* gssint_uint64 */ |
void *seqstate; | void *seqstate; |
krb5_auth_context auth_context; | krb5_auth_context auth_context; |
gss_buffer_desc *mech_used; /* gss_OID_desc */ |
gss_OID_desc *mech_used; /* gss_OID_desc */ |
/* Protocol spec revision | /* Protocol spec revision |
0 => RFC 1964 with 3DES and RC4 enhancements | 0 => RFC 1964 with 3DES and RC4 enhancements |
1 => draft-ietf-krb-wg-gssapi-cfx-01 | 1 => draft-ietf-krb-wg-gssapi-cfx-01 |
|
Lines 123-129
typedef struct _krb5_gss_ctx_id_rec {
|
Link Here
|
|---|
|
int established; | int established; |
int big_endian; | int big_endian; |
krb5_auth_context auth_context; | krb5_auth_context auth_context; |
gss_buffer_desc *mech_used; |
gss_OID_desc *mech_used; |
int nctypes; | int nctypes; |
krb5_cksumtype *ctypes; | krb5_cksumtype *ctypes; |
} krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t; | } krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t; |
|
Lines 144-149
write_lucid_keyblock(char **p, char *end
|
Link Here
|
|---|
|
return 0; | return 0; |
} | } |
| |
|
static void |
|
key_lucid_to_krb5(const gss_krb5_lucid_key_t *lin, krb5_keyblock *kout) |
|
{ |
|
memset(kout, '\0', sizeof(kout)); |
|
kout->enctype = lin->type; |
|
kout->length = lin->length; |
|
kout->contents = lin->data; |
|
} |
|
|
|
static void |
|
key_krb5_to_lucid(const krb5_keyblock *kin, gss_krb5_lucid_key_t *lout) |
|
{ |
|
memset(lout, '\0', sizeof(lout)); |
|
lout->type = kin->enctype; |
|
lout->length = kin->length; |
|
lout->data = kin->contents; |
|
} |
|
|
|
/* |
|
* Function to derive a new key from a given key and given constant data. |
|
*/ |
|
static krb5_error_code |
|
derive_key_lucid(const gss_krb5_lucid_key_t *in, gss_krb5_lucid_key_t *out, |
|
int usage, char extra) |
|
{ |
|
krb5_error_code code; |
|
unsigned char constant_data[K5CLENGTH]; |
|
krb5_data datain; |
|
int keylength; |
|
void *enc; |
|
krb5_keyblock kin, kout; /* must send krb5_keyblock, not lucid! */ |
|
|
|
/* |
|
* XXX Hack alert. We don't have "legal" access to these |
|
* values and structures located in libk5crypto |
|
*/ |
|
switch (in->type) { |
|
case ENCTYPE_DES3_CBC_RAW: |
|
keylength = 24; |
|
enc = &krb5int_enc_des3; |
|
break; |
|
case ENCTYPE_AES128_CTS_HMAC_SHA1_96: |
|
keylength = 16; |
|
enc = &krb5int_enc_aes128; |
|
break; |
|
case ENCTYPE_AES256_CTS_HMAC_SHA1_96: |
|
keylength = 32; |
|
enc = &krb5int_enc_aes256; |
|
break; |
|
default: |
|
code = KRB5_BAD_ENCTYPE; |
|
goto out; |
|
} |
|
|
|
/* allocate memory for output key */ |
|
if ((out->data = malloc(keylength)) == NULL) { |
|
code = ENOMEM; |
|
goto out; |
|
} |
|
out->length = keylength; |
|
out->type = in->type; |
|
|
|
/* Convert to correct format for call to krb5_derive_key */ |
|
key_lucid_to_krb5(in, &kin); |
|
key_lucid_to_krb5(out, &kout); |
|
|
|
datain.data = (char *) constant_data; |
|
datain.length = K5CLENGTH; |
|
|
|
datain.data[0] = (usage>>24)&0xff; |
|
datain.data[1] = (usage>>16)&0xff; |
|
datain.data[2] = (usage>>8)&0xff; |
|
datain.data[3] = usage&0xff; |
|
|
|
datain.data[4] = (char) extra; |
|
|
|
if ((code = krb5_derive_key(enc, &kin, &kout, &datain))) { |
|
free(out->data); |
|
out->data = NULL; |
|
goto out; |
|
} |
|
key_krb5_to_lucid(&kout, out); |
|
|
|
out: |
|
if (code) |
|
printerr(0, "ERROR: derive_key_lucid returning error %d (%s)\n", |
|
code, error_message(code)); |
|
return (code); |
|
} |
|
|
static int | static int |
prepare_krb5_rfc1964_buffer(gss_krb5_lucid_context_v1_t *lctx, | prepare_krb5_rfc1964_buffer(gss_krb5_lucid_context_v1_t *lctx, |
gss_buffer_desc *buf) | gss_buffer_desc *buf) |
|
Lines 183-189
prepare_krb5_rfc1964_buffer(gss_krb5_luc
|
Link Here
|
|---|
|
if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err; | if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err; |
word_send_seq = lctx->send_seq; /* XXX send_seq is 64-bit */ | word_send_seq = lctx->send_seq; /* XXX send_seq is 64-bit */ |
if (WRITE_BYTES(&p, end, word_send_seq)) goto out_err; | if (WRITE_BYTES(&p, end, word_send_seq)) goto out_err; |
if (write_buffer(&p, end, (gss_buffer_desc*)&krb5oid)) goto out_err; |
if (write_oid(&p, end, &krb5oid)) goto out_err; |
| |
printerr(2, "prepare_krb5_rfc1964_buffer: serializing keys with " | printerr(2, "prepare_krb5_rfc1964_buffer: serializing keys with " |
"enctype %d and length %d\n", | "enctype %d and length %d\n", |
|
Lines 212-228
prepare_krb5_rfc1964_buffer(gss_krb5_luc
|
Link Here
|
|---|
|
return 0; | return 0; |
out_err: | out_err: |
printerr(0, "ERROR: failed serializing krb5 context for kernel\n"); | printerr(0, "ERROR: failed serializing krb5 context for kernel\n"); |
if (buf->value) free(buf->value); |
if (buf->value) { |
|
free(buf->value); |
|
buf->value = NULL; |
|
} |
buf->length = 0; | buf->length = 0; |
if (enc_key.data) free(enc_key.data); |
if (enc_key.data) { |
|
free(enc_key.data); |
|
enc_key.data = NULL; |
|
} |
return -1; | return -1; |
} | } |
| |
|
/* |
|
* Prepare a new-style buffer to send to the kernel for newer encryption |
|
* types -- or for DES3. |
|
* |
|
* The new format is: |
|
* |
|
* u32 version; This is two (2) |
|
* s32 endtime; |
|
* u32 flags; |
|
* #define KRB5_CTX_FLAG_INITIATOR 0x00000001 |
|
* #define KRB5_CTX_FLAG_CFX 0x00000002 |
|
* #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004 |
|
* u64 seq_send; |
|
* u32 enctype; ( encrption type of keys ) |
|
* u32 size_of_each_key; ( size of each key in bytes ) |
|
* u32 number_of_keys; ( N -- should always be 3 for now ) |
|
* keydata-1; ( Ke ) |
|
* keydata-2; ( Ki ) |
|
* keydata-3; ( Kc ) |
|
* |
|
*/ |
static int | static int |
prepare_krb5_rfc_cfx_buffer(gss_krb5_lucid_context_v1_t *lctx, |
prepare_krb5_ctx_v2_buffer(gss_krb5_lucid_context_v1_t *lctx, |
gss_buffer_desc *buf) | gss_buffer_desc *buf) |
{ | { |
printerr(0, "ERROR: prepare_krb5_rfc_cfx_buffer: not implemented\n"); |
char *p, *end; |
|
static uint32_t version = 2; |
|
uint32_t v2_flags = 0; |
|
gss_krb5_lucid_key_t enc_key; |
|
gss_krb5_lucid_key_t derived_key; |
|
gss_buffer_desc fakeoid; |
|
uint32_t enctype; |
|
uint32_t keysize; |
|
uint32_t numkeys; |
|
|
|
memset(&enc_key, 0, sizeof(enc_key)); |
|
memset(&fakeoid, 0, sizeof(fakeoid)); |
|
|
|
if (!(buf->value = calloc(1, MAX_CTX_LEN))) |
|
goto out_err; |
|
p = buf->value; |
|
end = buf->value + MAX_CTX_LEN; |
|
|
|
/* Version 2 */ |
|
if (WRITE_BYTES(&p, end , version)) goto out_err; |
|
if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err; |
|
|
|
if (lctx->initiate) |
|
v2_flags |= KRB5_CTX_FLAG_INITIATOR; |
|
if (lctx->protocol != 0) |
|
v2_flags |= KRB5_CTX_FLAG_CFX; |
|
if (lctx->protocol != 0 && lctx->cfx_kd.have_acceptor_subkey == 1) |
|
v2_flags |= KRB5_CTX_FLAG_ACCEPTOR_SUBKEY; |
|
|
|
if (WRITE_BYTES(&p, end, v2_flags)) goto out_err; |
|
|
|
if (WRITE_BYTES(&p, end, lctx->send_seq)) goto out_err; |
|
|
|
/* Protocol 0 here implies DES3 or RC4 */ |
|
if (lctx->protocol == 0) { |
|
enctype = lctx->rfc1964_kd.ctx_key.type; |
|
keysize = lctx->rfc1964_kd.ctx_key.length; |
|
numkeys = 3; /* XXX is always gonna be three? */ |
|
} else { |
|
if (lctx->cfx_kd.have_acceptor_subkey) { |
|
enctype = lctx->cfx_kd.acceptor_subkey.type; |
|
keysize = lctx->cfx_kd.acceptor_subkey.length; |
|
} else { |
|
enctype = lctx->cfx_kd.ctx_key.type; |
|
keysize = lctx->cfx_kd.ctx_key.length; |
|
} |
|
numkeys = 3; |
|
} |
|
printerr(2, "prepare_krb5_ctx_v2_buffer: serializing %d keys with " |
|
"enctype %d and size %d\n", numkeys, enctype, keysize); |
|
if (WRITE_BYTES(&p, end, enctype)) goto out_err; |
|
if (WRITE_BYTES(&p, end, keysize)) goto out_err; |
|
if (WRITE_BYTES(&p, end, numkeys)) goto out_err; |
|
|
|
if (lctx->protocol == 0) { |
|
/* derive and send down: Ke, Ki, and Kc */ |
|
/* Ke */ |
|
if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data, |
|
lctx->rfc1964_kd.ctx_key.length)) |
|
goto out_err; |
|
|
|
/* Ki */ |
|
if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data, |
|
lctx->rfc1964_kd.ctx_key.length)) |
|
goto out_err; |
|
|
|
/* Kc */ |
|
if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key, |
|
&derived_key, |
|
KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM)) |
|
goto out_err; |
|
if (write_bytes(&p, end, derived_key.data, |
|
derived_key.length)) |
|
goto out_err; |
|
free(derived_key.data); |
|
} else { |
|
gss_krb5_lucid_key_t *keyptr; |
|
uint32_t sign_usage, seal_usage; |
|
|
|
if (lctx->cfx_kd.have_acceptor_subkey) |
|
keyptr = &lctx->cfx_kd.acceptor_subkey; |
|
else |
|
keyptr = &lctx->cfx_kd.ctx_key; |
|
|
|
if (lctx->initiate == 1) { |
|
sign_usage = KG_USAGE_INITIATOR_SIGN; |
|
seal_usage = KG_USAGE_INITIATOR_SEAL; |
|
} else { |
|
sign_usage = KG_USAGE_ACCEPTOR_SIGN; |
|
seal_usage = KG_USAGE_ACCEPTOR_SEAL; |
|
} |
|
|
|
/* derive and send down: Ke, Ki, and Kc */ |
|
|
|
/* Ke */ |
|
if (derive_key_lucid(keyptr, &derived_key, |
|
seal_usage, KEY_USAGE_SEED_ENCRYPTION)) |
|
goto out_err; |
|
if (write_bytes(&p, end, derived_key.data, |
|
derived_key.length)) |
|
goto out_err; |
|
free(derived_key.data); |
|
|
|
/* Ki */ |
|
if (derive_key_lucid(keyptr, &derived_key, |
|
seal_usage, KEY_USAGE_SEED_INTEGRITY)) |
|
goto out_err; |
|
if (write_bytes(&p, end, derived_key.data, |
|
derived_key.length)) |
|
goto out_err; |
|
free(derived_key.data); |
|
|
|
/* Kc */ |
|
if (derive_key_lucid(keyptr, &derived_key, |
|
sign_usage, KEY_USAGE_SEED_CHECKSUM)) |
|
goto out_err; |
|
if (write_bytes(&p, end, derived_key.data, |
|
derived_key.length)) |
|
goto out_err; |
|
free(derived_key.data); |
|
} |
|
|
|
buf->length = p - (char *)buf->value; |
|
return 0; |
|
|
|
out_err: |
|
printerr(0, "ERROR: prepare_krb5_ctx_v2_buffer: " |
|
"failed serializing krb5 context for kernel\n"); |
|
if (buf->value) { |
|
free(buf->value); |
|
buf->value = NULL; |
|
} |
|
buf->length = 0; |
|
if (enc_key.data) { |
|
free(enc_key.data); |
|
enc_key.data = NULL; |
|
} |
return -1; | return -1; |
} | } |
| |
|
Lines 258-268
serialize_krb5_ctx(gss_ctx_id_t ctx, gss
|
Link Here
|
|---|
|
break; | break; |
} | } |
| |
/* Now lctx points to a lucid context that we can send down to kernel */ |
/* |
if (lctx->protocol == 0) |
* Now lctx points to a lucid context that we can send down to kernel |
|
* |
|
* Note: we send down different information to the kernel depending |
|
* on the protocol version and the enctyption type. |
|
* For protocol version 0 with all enctypes besides DES3, we use |
|
* the original format. For protocol version != 0 or DES3, we |
|
* send down the new style information. |
|
*/ |
|
|
|
if (lctx->protocol == 0 && |
|
lctx->rfc1964_kd.ctx_key.type == ENCTYPE_DES_CBC_RAW) |
retcode = prepare_krb5_rfc1964_buffer(lctx, buf); | retcode = prepare_krb5_rfc1964_buffer(lctx, buf); |
else | else |
retcode = prepare_krb5_rfc_cfx_buffer(lctx, buf); |
retcode = prepare_krb5_ctx_v2_buffer(lctx, buf); |
| |
maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, return_ctx); | maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, return_ctx); |
if (maj_stat != GSS_S_COMPLETE) { | if (maj_stat != GSS_S_COMPLETE) { |
|
Lines 300-305
write_keyblock(char **p, char *end, stru
|
Link Here
|
|---|
|
} | } |
| |
/* | /* |
|
* Function to derive a new key from a given key and given constant data. |
|
*/ |
|
static krb5_error_code |
|
derive_key(const krb5_keyblock *in, krb5_keyblock *out, int usage, char extra) |
|
{ |
|
krb5_error_code code; |
|
unsigned char constant_data[K5CLENGTH]; |
|
krb5_data datain; |
|
int keylength; |
|
void *enc; |
|
|
|
/* |
|
* XXX Hack alert. We don't have "legal" access to these |
|
* values and structures located in libk5crypto |
|
*/ |
|
switch (in->enctype) { |
|
case ENCTYPE_DES3_CBC_RAW: |
|
keylength = 24; |
|
enc = &krb5int_enc_des3; |
|
break; |
|
case ENCTYPE_ARCFOUR_HMAC: |
|
keylength = 16; |
|
enc = &krb5int_enc_arcfour; |
|
break; |
|
default: |
|
code = KRB5_BAD_ENCTYPE; |
|
goto out; |
|
} |
|
|
|
/* allocate memory for output key */ |
|
if ((out->contents = malloc(keylength)) == NULL) { |
|
code = ENOMEM; |
|
goto out; |
|
} |
|
out->length = keylength; |
|
out->enctype = in->enctype; |
|
|
|
datain.data = (char *) constant_data; |
|
datain.length = K5CLENGTH; |
|
|
|
datain.data[0] = (usage>>24)&0xff; |
|
datain.data[1] = (usage>>16)&0xff; |
|
datain.data[2] = (usage>>8)&0xff; |
|
datain.data[3] = usage&0xff; |
|
|
|
datain.data[4] = (char) extra; |
|
|
|
if ((code = krb5_derive_key(enc, in, out, &datain))) { |
|
free(out->contents); |
|
out->contents = NULL; |
|
} |
|
|
|
out: |
|
if (code) |
|
printerr(0, "ERROR: derive_key returning error %d (%s)\n", |
|
code, error_message(code)); |
|
return (code); |
|
} |
|
|
|
/* |
* We really shouldn't know about glue-layer context structure, but | * We really shouldn't know about glue-layer context structure, but |
* we need to get at the real krb5 context pointer. This should be | * we need to get at the real krb5 context pointer. This should be |
* removed as soon as we say there is no support for MIT Kerberos | * removed as soon as we say there is no support for MIT Kerberos |
|
Lines 315-359
serialize_krb5_ctx(gss_ctx_id_t ctx, gss
|
Link Here
|
|---|
|
{ | { |
krb5_gss_ctx_id_t kctx = ((gss_union_ctx_id_t)ctx)->internal_ctx_id; | krb5_gss_ctx_id_t kctx = ((gss_union_ctx_id_t)ctx)->internal_ctx_id; |
char *p, *end; | char *p, *end; |
static int constant_one = 1; |
|
static int constant_zero = 0; | static int constant_zero = 0; |
|
static int constant_one = 1; |
|
static int constant_two = 2; |
uint32_t word_seq_send; | uint32_t word_seq_send; |
|
u_int64_t seq_send_64bit; |
|
uint32_t v2_flags = 0; |
|
krb5_keyblock derived_key; |
|
uint32_t numkeys; |
| |
if (!(buf->value = calloc(1, MAX_CTX_LEN))) | if (!(buf->value = calloc(1, MAX_CTX_LEN))) |
goto out_err; | goto out_err; |
p = buf->value; | p = buf->value; |
end = buf->value + MAX_CTX_LEN; | end = buf->value + MAX_CTX_LEN; |
| |
if (kctx->initiate) { |
switch (kctx->sealalg) { |
if (WRITE_BYTES(&p, end, constant_one)) goto out_err; |
case SEAL_ALG_DES: |
} |
/* Versions 0 and 1 */ |
else { |
if (kctx->initiate) { |
if (WRITE_BYTES(&p, end, constant_zero)) goto out_err; |
if (WRITE_BYTES(&p, end, constant_one)) goto out_err; |
} |
} |
if (kctx->seed_init) { |
else { |
if (WRITE_BYTES(&p, end, constant_one)) goto out_err; |
if (WRITE_BYTES(&p, end, constant_zero)) goto out_err; |
} |
} |
else { |
if (kctx->seed_init) { |
if (WRITE_BYTES(&p, end, constant_zero)) goto out_err; |
if (WRITE_BYTES(&p, end, constant_one)) goto out_err; |
} |
} |
if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed))) |
else { |
goto out_err; |
if (WRITE_BYTES(&p, end, constant_zero)) goto out_err; |
if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err; |
} |
if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err; |
if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed))) |
if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err; |
goto out_err; |
word_seq_send = kctx->seq_send; |
if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err; |
if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err; |
if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err; |
if (write_buffer(&p, end, kctx->mech_used)) goto out_err; |
if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err; |
|
word_seq_send = kctx->seq_send; |
printerr(2, "serialize_krb5_ctx: serializing keys with " |
if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err; |
"enctype %d and length %d\n", |
if (write_oid(&p, end, kctx->mech_used)) goto out_err; |
kctx->enc->enctype, kctx->enc->length); |
|
|
printerr(2, "serialize_krb5_ctx: serializing keys with " |
|
"enctype %d and length %d\n", |
|
kctx->enc->enctype, kctx->enc->length); |
| |
if (write_keyblock(&p, end, kctx->enc)) goto out_err; |
if (write_keyblock(&p, end, kctx->enc)) goto out_err; |
if (write_keyblock(&p, end, kctx->seq)) goto out_err; |
if (write_keyblock(&p, end, kctx->seq)) goto out_err; |
|
break; |
|
case SEAL_ALG_MICROSOFT_RC4: |
|
case SEAL_ALG_DES3KD: |
|
/* u32 version; ( 2 ) |
|
* s32 endtime; |
|
* u32 flags; |
|
* #define KRB5_CTX_FLAG_INITIATOR 0x00000001 |
|
* #define KRB5_CTX_FLAG_CFX 0x00000002 |
|
* #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004 |
|
* u64 seq_send; |
|
* u32 enctype; |
|
* u32 size_of_each_key; ( size in bytes ) |
|
* u32 number_of_keys; ( N (assumed to be 3 for now) ) |
|
* keydata-1; ( Ke (Kenc for DES3) ) |
|
* keydata-2; ( Ki (Kseq for DES3) ) |
|
* keydata-3; ( Kc (derived checksum key) ) |
|
*/ |
|
/* Version 2 */ |
|
if (WRITE_BYTES(&p, end , constant_two)) goto out_err; |
|
if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err; |
|
|
|
/* Only applicable flag for is initiator */ |
|
if (kctx->initiate) v2_flags |= KRB5_CTX_FLAG_INITIATOR; |
|
if (WRITE_BYTES(&p, end, v2_flags)) goto out_err; |
|
|
|
seq_send_64bit = kctx->seq_send; |
|
if (WRITE_BYTES(&p, end, seq_send_64bit)) goto out_err; |
|
|
|
if (WRITE_BYTES(&p, end, kctx->enc->enctype)) goto out_err; |
|
if (WRITE_BYTES(&p, end, kctx->enc->length)) goto out_err; |
|
numkeys = 3; |
|
if (WRITE_BYTES(&p, end, numkeys)) goto out_err; |
|
printerr(2, "serialize_krb5_ctx: serializing %d keys with " |
|
"enctype %d and size %d\n", |
|
numkeys, kctx->enc->enctype, kctx->enc->length); |
|
|
|
/* Ke */ |
|
if (write_bytes(&p, end, kctx->enc->contents, |
|
kctx->enc->length)) |
|
goto out_err; |
|
|
|
/* Ki */ |
|
if (write_bytes(&p, end, kctx->enc->contents, |
|
kctx->enc->length)) |
|
goto out_err; |
|
|
|
/* Kc */ |
|
if (derive_key(kctx->seq, &derived_key, |
|
KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM)) |
|
goto out_err; |
|
if (write_bytes(&p, end, derived_key.contents, |
|
derived_key.length)) |
|
goto out_err; |
|
free(derived_key.contents); |
|
break; |
|
default: |
|
printerr(0, "ERROR: serialize_krb5_ctx: unsupported seal " |
|
"algorithm %d\n", kctx->sealalg); |
|
goto out_err; |
|
} |
| |
buf->length = p - (char *)buf->value; | buf->length = p - (char *)buf->value; |
return 0; | return 0; |
|
|
out_err: | out_err: |
printerr(0, "ERROR: failed serializing krb5 context for kernel\n"); | printerr(0, "ERROR: failed serializing krb5 context for kernel\n"); |
if (buf->value) free(buf->value); | if (buf->value) free(buf->value); |