From 4a97b498958408c0bd6889c19bf0eb045b03808a Mon Sep 17 00:00:00 2001 From: Assar Westerlund Date: Sun, 27 Aug 2000 03:50:07 +0000 Subject: [PATCH] re-organize and add 3DES code git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@9000 ec53bebd-3082-4978-b11e-865c3cabbd6b --- lib/gssapi/get_mic.c | 202 ++++++++++++++++++++++++++++++++++---- lib/gssapi/krb5/get_mic.c | 202 ++++++++++++++++++++++++++++++++++---- 2 files changed, 368 insertions(+), 36 deletions(-) diff --git a/lib/gssapi/get_mic.c b/lib/gssapi/get_mic.c index 863e2e9bd..0575e0c57 100644 --- a/lib/gssapi/get_mic.c +++ b/lib/gssapi/get_mic.c @@ -35,19 +35,21 @@ RCSID("$Id$"); -OM_uint32 gss_get_mic +static OM_uint32 +mic_des (OM_uint32 * minor_status, const gss_ctx_id_t context_handle, gss_qop_t qop_req, const gss_buffer_t message_buffer, - gss_buffer_t message_token + gss_buffer_t message_token, + krb5_keyblock *key ) { u_char *p; MD5_CTX md5; u_char hash[16]; des_key_schedule schedule; - des_cblock key; + des_cblock deskey; des_cblock zero; int32_t seq_number; size_t len, total_len; @@ -56,42 +58,44 @@ OM_uint32 gss_get_mic message_token->length = total_len; message_token->value = malloc (total_len); - if (message_token->value == NULL) + if (message_token->value == NULL) { + *minor_status = ENOMEM; return GSS_S_FAILURE; + } p = gssapi_krb5_make_header(message_token->value, len, - "\x01\x01"); + "\x01\x01"); /* TOK_ID */ - memcpy (p, "\x00\x00", 2); + memcpy (p, "\x00\x00", 2); /* SGN_ALG = DES MAC MD5 */ p += 2; - memcpy (p, "\xff\xff\xff\xff", 4); + + memcpy (p, "\xff\xff\xff\xff", 4); /* Filler */ p += 4; - /* Fill in later */ + /* Fill in later (SND-SEQ) */ memset (p, 0, 16); p += 16; /* checksum */ MD5Init (&md5); MD5Update (&md5, p - 24, 8); - MD5Update (&md5, message_buffer->value, - message_buffer->length); + MD5Update (&md5, message_buffer->value, message_buffer->length); MD5Final (hash, &md5); memset (&zero, 0, sizeof(zero)); - gss_krb5_getsomekey(context_handle, &key); - des_set_key (&key, schedule); - des_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), + memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); + des_set_key (&deskey, schedule); + des_cbc_cksum ((const void *)hash, (void *)hash, sizeof(hash), schedule, &zero); - memcpy (p - 8, hash, 8); + memcpy (p - 8, hash, 8); /* SGN_CKSUM */ /* sequence number */ krb5_auth_getlocalseqnumber (gssapi_krb5_context, context_handle->auth_context, &seq_number); - p -= 16; + p -= 16; /* SND_SEQ */ p[0] = (seq_number >> 0) & 0xFF; p[1] = (seq_number >> 8) & 0xFF; p[2] = (seq_number >> 16) & 0xFF; @@ -100,16 +104,178 @@ OM_uint32 gss_get_mic (context_handle->more_flags & LOCAL) ? 0 : 0xFF, 4); - des_set_key (&key, schedule); - des_cbc_encrypt ((void *)p, (void *)p, 8, + des_set_key (&deskey, schedule); + des_cbc_encrypt ((const void *)p, (void *)p, 8, schedule, (des_cblock *)(p + 8), DES_ENCRYPT); krb5_auth_setlocalseqnumber (gssapi_krb5_context, context_handle->auth_context, ++seq_number); - memset (key, 0, sizeof(key)); + memset (deskey, 0, sizeof(deskey)); memset (schedule, 0, sizeof(schedule)); return GSS_S_COMPLETE; } + +static OM_uint32 +mic_des3 + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token, + krb5_keyblock *key + ) +{ + u_char *p; + Checksum cksum; + u_char seq[8]; + + int32_t seq_number; + size_t len, total_len; + + krb5_crypto crypto; + krb5_error_code kret; + krb5_data encdata; + char *tmp; + + gssapi_krb5_encap_length (36, &len, &total_len); + + message_token->length = total_len; + message_token->value = malloc (total_len); + if (message_token->value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + p = gssapi_krb5_make_header(message_token->value, + len, + "\x01\x01"); /* TOK-ID */ + + memcpy (p, "\x04\x00", 2); /* SGN_ALG = HMAC SHA1 DES3-KD */ + p += 2; + + memcpy (p, "\xff\xff\xff\xff", 4); /* filler */ + p += 4; + + /* this should be done in parts */ + + tmp = malloc (message_buffer->length + 8); + if (tmp == NULL) { + free (message_token->value); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy (tmp, p - 8, 8); + memcpy (tmp + 8, message_buffer->value, message_buffer->length); + + kret = krb5_crypto_init(gssapi_krb5_context, key, 0, &crypto); + if (kret) { + free (message_token->value); + free (tmp); + *minor_status = kret; + return GSS_S_FAILURE; + } + + kret = krb5_create_checksum (gssapi_krb5_context, + crypto, + KRB5_KU_USAGE_SIGN, + tmp, + message_buffer->length + 8, + &cksum); + free (tmp); + krb5_crypto_destroy (gssapi_krb5_context, crypto); + if (kret) { + free (message_token->value); + *minor_status = kret; + return GSS_S_FAILURE; + } + + memcpy (p + 8, cksum.checksum.data, cksum.checksum.length); + + /* sequence number */ + krb5_auth_getlocalseqnumber (gssapi_krb5_context, + context_handle->auth_context, + &seq_number); + + seq[0] = (seq_number >> 0) & 0xFF; + seq[1] = (seq_number >> 8) & 0xFF; + seq[2] = (seq_number >> 16) & 0xFF; + seq[3] = (seq_number >> 24) & 0xFF; + memset (seq + 4, + (context_handle->more_flags & LOCAL) ? 0 : 0xFF, + 4); + + kret = krb5_crypto_init(gssapi_krb5_context, key, + ETYPE_DES3_CBC_NONE, &crypto); + if (kret) { + free (message_token->value); + *minor_status = kret; + return GSS_S_FAILURE; + } + + kret = krb5_encrypt (gssapi_krb5_context, + crypto, + KRB5_KU_USAGE_SEQ, + seq, 8, &encdata); + krb5_crypto_destroy (gssapi_krb5_context, crypto); + if (kret) { + free (message_token->value); + *minor_status = kret; + return GSS_S_FAILURE; + } + + assert (encdata.length == 8); + + memcpy (p, encdata.data, encdata.length); + krb5_data_free (&encdata); + + p += 8 + cksum.checksum.length; + + memcpy (p, message_buffer->value, message_buffer->length); + + krb5_auth_setlocalseqnumber (gssapi_krb5_context, + context_handle->auth_context, + ++seq_number); + + free_Checksum (&cksum); + return GSS_S_COMPLETE; +} + +OM_uint32 gss_get_mic + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token + ) +{ + krb5_keyblock *key; + OM_uint32 ret; + krb5_keytype keytype; + + ret = gss_krb5_getsomekey(context_handle, &key); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + krb5_enctype_to_keytype (gssapi_krb5_context, key->keytype, &keytype); + + switch (keytype) { + case KEYTYPE_DES : + ret = mic_des (minor_status, context_handle, qop_req, + message_buffer, message_token, key); + break; + case KEYTYPE_DES3 : + ret = mic_des3 (minor_status, context_handle, qop_req, + message_buffer, message_token, key); + break; + default : + *minor_status = KRB5_PROG_ETYPE_NOSUPP; + ret = GSS_S_FAILURE; + break; + } + krb5_free_keyblock (gssapi_krb5_context, key); + return ret; +} diff --git a/lib/gssapi/krb5/get_mic.c b/lib/gssapi/krb5/get_mic.c index 863e2e9bd..0575e0c57 100644 --- a/lib/gssapi/krb5/get_mic.c +++ b/lib/gssapi/krb5/get_mic.c @@ -35,19 +35,21 @@ RCSID("$Id$"); -OM_uint32 gss_get_mic +static OM_uint32 +mic_des (OM_uint32 * minor_status, const gss_ctx_id_t context_handle, gss_qop_t qop_req, const gss_buffer_t message_buffer, - gss_buffer_t message_token + gss_buffer_t message_token, + krb5_keyblock *key ) { u_char *p; MD5_CTX md5; u_char hash[16]; des_key_schedule schedule; - des_cblock key; + des_cblock deskey; des_cblock zero; int32_t seq_number; size_t len, total_len; @@ -56,42 +58,44 @@ OM_uint32 gss_get_mic message_token->length = total_len; message_token->value = malloc (total_len); - if (message_token->value == NULL) + if (message_token->value == NULL) { + *minor_status = ENOMEM; return GSS_S_FAILURE; + } p = gssapi_krb5_make_header(message_token->value, len, - "\x01\x01"); + "\x01\x01"); /* TOK_ID */ - memcpy (p, "\x00\x00", 2); + memcpy (p, "\x00\x00", 2); /* SGN_ALG = DES MAC MD5 */ p += 2; - memcpy (p, "\xff\xff\xff\xff", 4); + + memcpy (p, "\xff\xff\xff\xff", 4); /* Filler */ p += 4; - /* Fill in later */ + /* Fill in later (SND-SEQ) */ memset (p, 0, 16); p += 16; /* checksum */ MD5Init (&md5); MD5Update (&md5, p - 24, 8); - MD5Update (&md5, message_buffer->value, - message_buffer->length); + MD5Update (&md5, message_buffer->value, message_buffer->length); MD5Final (hash, &md5); memset (&zero, 0, sizeof(zero)); - gss_krb5_getsomekey(context_handle, &key); - des_set_key (&key, schedule); - des_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), + memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); + des_set_key (&deskey, schedule); + des_cbc_cksum ((const void *)hash, (void *)hash, sizeof(hash), schedule, &zero); - memcpy (p - 8, hash, 8); + memcpy (p - 8, hash, 8); /* SGN_CKSUM */ /* sequence number */ krb5_auth_getlocalseqnumber (gssapi_krb5_context, context_handle->auth_context, &seq_number); - p -= 16; + p -= 16; /* SND_SEQ */ p[0] = (seq_number >> 0) & 0xFF; p[1] = (seq_number >> 8) & 0xFF; p[2] = (seq_number >> 16) & 0xFF; @@ -100,16 +104,178 @@ OM_uint32 gss_get_mic (context_handle->more_flags & LOCAL) ? 0 : 0xFF, 4); - des_set_key (&key, schedule); - des_cbc_encrypt ((void *)p, (void *)p, 8, + des_set_key (&deskey, schedule); + des_cbc_encrypt ((const void *)p, (void *)p, 8, schedule, (des_cblock *)(p + 8), DES_ENCRYPT); krb5_auth_setlocalseqnumber (gssapi_krb5_context, context_handle->auth_context, ++seq_number); - memset (key, 0, sizeof(key)); + memset (deskey, 0, sizeof(deskey)); memset (schedule, 0, sizeof(schedule)); return GSS_S_COMPLETE; } + +static OM_uint32 +mic_des3 + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token, + krb5_keyblock *key + ) +{ + u_char *p; + Checksum cksum; + u_char seq[8]; + + int32_t seq_number; + size_t len, total_len; + + krb5_crypto crypto; + krb5_error_code kret; + krb5_data encdata; + char *tmp; + + gssapi_krb5_encap_length (36, &len, &total_len); + + message_token->length = total_len; + message_token->value = malloc (total_len); + if (message_token->value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + p = gssapi_krb5_make_header(message_token->value, + len, + "\x01\x01"); /* TOK-ID */ + + memcpy (p, "\x04\x00", 2); /* SGN_ALG = HMAC SHA1 DES3-KD */ + p += 2; + + memcpy (p, "\xff\xff\xff\xff", 4); /* filler */ + p += 4; + + /* this should be done in parts */ + + tmp = malloc (message_buffer->length + 8); + if (tmp == NULL) { + free (message_token->value); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy (tmp, p - 8, 8); + memcpy (tmp + 8, message_buffer->value, message_buffer->length); + + kret = krb5_crypto_init(gssapi_krb5_context, key, 0, &crypto); + if (kret) { + free (message_token->value); + free (tmp); + *minor_status = kret; + return GSS_S_FAILURE; + } + + kret = krb5_create_checksum (gssapi_krb5_context, + crypto, + KRB5_KU_USAGE_SIGN, + tmp, + message_buffer->length + 8, + &cksum); + free (tmp); + krb5_crypto_destroy (gssapi_krb5_context, crypto); + if (kret) { + free (message_token->value); + *minor_status = kret; + return GSS_S_FAILURE; + } + + memcpy (p + 8, cksum.checksum.data, cksum.checksum.length); + + /* sequence number */ + krb5_auth_getlocalseqnumber (gssapi_krb5_context, + context_handle->auth_context, + &seq_number); + + seq[0] = (seq_number >> 0) & 0xFF; + seq[1] = (seq_number >> 8) & 0xFF; + seq[2] = (seq_number >> 16) & 0xFF; + seq[3] = (seq_number >> 24) & 0xFF; + memset (seq + 4, + (context_handle->more_flags & LOCAL) ? 0 : 0xFF, + 4); + + kret = krb5_crypto_init(gssapi_krb5_context, key, + ETYPE_DES3_CBC_NONE, &crypto); + if (kret) { + free (message_token->value); + *minor_status = kret; + return GSS_S_FAILURE; + } + + kret = krb5_encrypt (gssapi_krb5_context, + crypto, + KRB5_KU_USAGE_SEQ, + seq, 8, &encdata); + krb5_crypto_destroy (gssapi_krb5_context, crypto); + if (kret) { + free (message_token->value); + *minor_status = kret; + return GSS_S_FAILURE; + } + + assert (encdata.length == 8); + + memcpy (p, encdata.data, encdata.length); + krb5_data_free (&encdata); + + p += 8 + cksum.checksum.length; + + memcpy (p, message_buffer->value, message_buffer->length); + + krb5_auth_setlocalseqnumber (gssapi_krb5_context, + context_handle->auth_context, + ++seq_number); + + free_Checksum (&cksum); + return GSS_S_COMPLETE; +} + +OM_uint32 gss_get_mic + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token + ) +{ + krb5_keyblock *key; + OM_uint32 ret; + krb5_keytype keytype; + + ret = gss_krb5_getsomekey(context_handle, &key); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + krb5_enctype_to_keytype (gssapi_krb5_context, key->keytype, &keytype); + + switch (keytype) { + case KEYTYPE_DES : + ret = mic_des (minor_status, context_handle, qop_req, + message_buffer, message_token, key); + break; + case KEYTYPE_DES3 : + ret = mic_des3 (minor_status, context_handle, qop_req, + message_buffer, message_token, key); + break; + default : + *minor_status = KRB5_PROG_ETYPE_NOSUPP; + ret = GSS_S_FAILURE; + break; + } + krb5_free_keyblock (gssapi_krb5_context, key); + return ret; +}