diff options
Diffstat (limited to 'crypto/heimdal/lib/gssapi/verify_mic.c')
-rw-r--r-- | crypto/heimdal/lib/gssapi/verify_mic.c | 191 |
1 files changed, 169 insertions, 22 deletions
diff --git a/crypto/heimdal/lib/gssapi/verify_mic.c b/crypto/heimdal/lib/gssapi/verify_mic.c index 1cc4c52..608de67 100644 --- a/crypto/heimdal/lib/gssapi/verify_mic.c +++ b/crypto/heimdal/lib/gssapi/verify_mic.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2000 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,22 +33,24 @@ #include "gssapi_locl.h" -RCSID("$Id: verify_mic.c,v 1.9 2000/01/25 23:14:47 assar Exp $"); +RCSID("$Id: verify_mic.c,v 1.12 2001/01/29 02:08:59 assar Exp $"); -OM_uint32 gss_verify_mic +static OM_uint32 +verify_mic_des (OM_uint32 * minor_status, const gss_ctx_id_t context_handle, const gss_buffer_t message_buffer, const gss_buffer_t token_buffer, - gss_qop_t * qop_state + gss_qop_t * qop_state, + krb5_keyblock *key ) { u_char *p; MD5_CTX md5; u_char hash[16], seq_data[8]; des_key_schedule schedule; - des_cblock key; des_cblock zero; + des_cblock deskey; int32_t seq_number; OM_uint32 ret; @@ -68,25 +70,20 @@ OM_uint32 gss_verify_mic p += 16; /* verify checksum */ - MD5Init (&md5); - MD5Update (&md5, p - 24, 8); - MD5Update (&md5, message_buffer->value, + MD5_Init (&md5); + MD5_Update (&md5, p - 24, 8); + MD5_Update (&md5, message_buffer->value, message_buffer->length); - MD5Final (hash, &md5); + MD5_Final (hash, &md5); memset (&zero, 0, sizeof(zero)); -#if 0 - memcpy (&key, context_handle->auth_context->key.keyvalue.data, - sizeof(key)); -#endif - memcpy (&key, context_handle->auth_context->remote_subkey->keyvalue.data, - sizeof(key)); - - des_set_key (&key, schedule); - des_cbc_cksum ((const void *)hash, (void *)hash, sizeof(hash), + memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); + + des_set_key (&deskey, schedule); + des_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), schedule, &zero); if (memcmp (p - 8, hash, 8) != 0) { - memset (key, 0, sizeof(key)); + memset (deskey, 0, sizeof(deskey)); memset (schedule, 0, sizeof(schedule)); return GSS_S_BAD_MIC; } @@ -105,11 +102,11 @@ OM_uint32 gss_verify_mic 4); p -= 16; - des_set_key (&key, schedule); - des_cbc_encrypt ((const void *)p, (void *)p, 8, + des_set_key (&deskey, schedule); + des_cbc_encrypt ((void *)p, (void *)p, 8, schedule, (des_cblock *)hash, DES_DECRYPT); - memset (key, 0, sizeof(key)); + memset (deskey, 0, sizeof(deskey)); memset (schedule, 0, sizeof(schedule)); if (memcmp (p, seq_data, 8) != 0) { @@ -122,3 +119,153 @@ OM_uint32 gss_verify_mic return GSS_S_COMPLETE; } + +static OM_uint32 +verify_mic_des3 + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t * qop_state, + krb5_keyblock *key + ) +{ + u_char *p; + u_char seq[8]; + int32_t seq_number; + OM_uint32 ret; + krb5_crypto crypto; + krb5_data seq_data; + int cmp; + Checksum csum; + char *tmp; + + p = token_buffer->value; + ret = gssapi_krb5_verify_header (&p, + token_buffer->length, + "\x01\x01"); + if (ret) + return ret; + + if (memcmp(p, "\x04\x00", 2) != 0) /* SGN_ALG = HMAC SHA1 DES3-KD */ + return GSS_S_BAD_SIG; + p += 2; + if (memcmp (p, "\xff\xff\xff\xff", 4) != 0) + return GSS_S_BAD_MIC; + p += 4; + + ret = krb5_crypto_init(gssapi_krb5_context, key, + ETYPE_DES3_CBC_NONE, &crypto); + if (ret){ + *minor_status = ret; + return GSS_S_FAILURE; + } + + /* verify sequence number */ + + ret = krb5_decrypt (gssapi_krb5_context, + crypto, + KRB5_KU_USAGE_SEQ, + p, 8, &seq_data); + if (ret) { + krb5_crypto_destroy (gssapi_krb5_context, crypto); + *minor_status = ret; + return GSS_S_FAILURE; + } + + if (seq_data.length != 8) { + krb5_crypto_destroy (gssapi_krb5_context, crypto); + krb5_data_free (&seq_data); + return GSS_S_BAD_MIC; + } + + krb5_auth_getremoteseqnumber (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) ? 0xFF : 0, + 4); + cmp = memcmp (seq, seq_data.data, seq_data.length); + krb5_data_free (&seq_data); + if (cmp != 0) { + krb5_crypto_destroy (gssapi_krb5_context, crypto); + return GSS_S_BAD_MIC; + } + + /* verify checksum */ + + tmp = malloc (message_buffer->length + 8); + if (tmp == NULL) { + krb5_crypto_destroy (gssapi_krb5_context, crypto); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + memcpy (tmp, p - 8, 8); + memcpy (tmp + 8, message_buffer->value, message_buffer->length); + + csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3; + csum.checksum.length = 20; + csum.checksum.data = p + 8; + + ret = krb5_verify_checksum (gssapi_krb5_context, crypto, + KRB5_KU_USAGE_SIGN, + tmp, message_buffer->length + 8, + &csum); + free (tmp); + if (ret) { + krb5_crypto_destroy (gssapi_krb5_context, crypto); + *minor_status = ret; + return GSS_S_BAD_MIC; + } + + krb5_auth_setremoteseqnumber (gssapi_krb5_context, + context_handle->auth_context, + ++seq_number); + + krb5_crypto_destroy (gssapi_krb5_context, crypto); + return GSS_S_COMPLETE; +} + +OM_uint32 +gss_verify_mic + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t * qop_state + ) +{ + krb5_keyblock *key; + OM_uint32 ret; + krb5_keytype keytype; + + ret = krb5_auth_con_getremotesubkey (gssapi_krb5_context, + context_handle->auth_context, + &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 = verify_mic_des (minor_status, context_handle, + message_buffer, token_buffer, qop_state, key); + break; + case KEYTYPE_DES3 : + ret = verify_mic_des3 (minor_status, context_handle, + message_buffer, token_buffer, qop_state, key); + break; + default : + *minor_status = KRB5_PROG_ETYPE_NOSUPP; + ret = GSS_S_FAILURE; + break; + } + krb5_free_keyblock (gssapi_krb5_context, key); + return ret; +} |