static void check_hmac(void) { unsigned char buf[4] = { 0, 0, 0, 0 }; char hmackey[] = "hello-world"; size_t hmackey_size = sizeof(hmackey); unsigned int hmaclen; unsigned char hmac[EVP_MAX_MD_SIZE]; HMAC_CTX c; char answer[20] = "\x2c\xfa\x32\xb7\x2b\x8a\xf6\xdf\xcf\xda" "\x6f\xd1\x52\x4d\x54\x58\x73\x0f\xf3\x24"; HMAC_CTX_init(&c); HMAC_Init_ex(&c, hmackey, hmackey_size, EVP_sha1(), NULL); HMAC_Update(&c, buf, sizeof(buf)); HMAC_Final(&c, hmac, &hmaclen); HMAC_CTX_cleanup(&c); if (hmaclen != 20) errx(1, "hmaclen = %d\n", (int)hmaclen); if (ct_memcmp(hmac, answer, hmaclen) != 0) errx(1, "wrong answer\n"); }
KRB5_LIB_FUNCTION int KRB5_LIB_CALL krb5_data_ct_cmp(const krb5_data *data1, const krb5_data *data2) { if (data1->length != data2->length) return data1->length - data2->length; return ct_memcmp(data1->data, data2->data, data1->length); }
OM_uint32 _gsskrb5_verify_header(u_char **str, size_t total_len, const void *type, gss_OID oid) { OM_uint32 ret; size_t len; u_char *p = *str; ret = _gssapi_verify_mech_header(str, total_len, oid); if (ret) return ret; len = total_len - (*str - p); if (len < 2) return GSS_S_DEFECTIVE_TOKEN; if (ct_memcmp (*str, type, 2) != 0) return GSS_S_DEFECTIVE_TOKEN; *str += 2; return 0; }
OM_uint32 gss_mg_validate_cb(OM_uint32 *minor_status, const gss_channel_bindings_t b, const uint8_t p[16], gss_buffer_t buffer) { static uint8_t zeros[16] = { 0 }; OM_uint32 major_status, junk; uint8_t hash[16]; if (b != GSS_C_NO_CHANNEL_BINDINGS && memcmp(p, zeros, sizeof(zeros)) != 0) { major_status = gss_mg_gen_cb(minor_status, b, hash, buffer); if (major_status) return major_status; if(ct_memcmp(hash, p, sizeof(hash)) != 0) { gss_release_buffer(&junk, buffer); *minor_status = 0; return GSS_S_BAD_BINDINGS; } } else { buffer->length = 0; buffer->value = NULL; } return GSS_S_COMPLETE; }
int RSA_check_key(const RSA *key) { static const unsigned char inbuf[] = "hello, world!"; RSA *rsa = rk_UNCONST(key); void *buffer; int ret; /* * XXX I have no clue how to implement this w/o a bignum library. * Well, when we have a RSA key pair, we can try to encrypt/sign * and then decrypt/verify. */ if ((rsa->d == NULL || rsa->n == NULL) && (rsa->p == NULL || rsa->q || rsa->dmp1 == NULL || rsa->dmq1 == NULL || rsa->iqmp == NULL)) return 0; buffer = malloc(RSA_size(rsa)); if (buffer == NULL) return 0; ret = RSA_private_encrypt(sizeof(inbuf), inbuf, buffer, rsa, RSA_PKCS1_PADDING); if (ret == -1) { free(buffer); return 0; } ret = RSA_public_decrypt(ret, buffer, buffer, rsa, RSA_PKCS1_PADDING); if (ret == -1) { free(buffer); return 0; } if (ret == sizeof(inbuf) && ct_memcmp(buffer, inbuf, sizeof(inbuf)) == 0) { free(buffer); return 1; } free(buffer); return 0; }
OM_uint32 _gssapi_verify_mech_header(u_char **str, size_t total_len, gss_OID mech) { const u_char *p; ssize_t mech_len; mech_len = _gsskrb5_get_mech (*str, total_len, &p); if (mech_len < 0) return GSS_S_DEFECTIVE_TOKEN; if (mech_len != mech->length) return GSS_S_BAD_MECH; if (ct_memcmp(p, mech->elements, mech->length) != 0) return GSS_S_BAD_MECH; p += mech_len; *str = rk_UNCONST(p); return GSS_S_COMPLETE; }
krb5_error_code _krb5_des_verify(krb5_context context, CCDigestAlg alg, struct _krb5_key_data *key, const void *data, size_t len, Checksum *C) { struct _krb5_evp_schedule *ctx = key->schedule->data; CCDigestRef m; unsigned char tmp[24]; unsigned char res[16]; unsigned char ivec[8]; krb5_error_code ret = 0; m = CCDigestCreate(alg); if (m == NULL) { krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); return ENOMEM; } memset(ivec, 0, sizeof(ivec)); EVP_CipherInit_ex(&ctx->dctx, NULL, NULL, NULL, (void *)ivec, -1); EVP_Cipher(&ctx->dctx, tmp, C->checksum.data, 24); CCDigestUpdate(m, tmp, 8); /* confounder */ CCDigestUpdate(m, data, len); CCDigestFinal(m, res); CCDigestDestroy(m); if(ct_memcmp(res, tmp + 8, sizeof(res)) != 0) { krb5_clear_error_message (context); ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; } memset(tmp, 0, sizeof(tmp)); memset(res, 0, sizeof(res)); return ret; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL _krb5_des_verify(krb5_context context, const EVP_MD *evp_md, struct _krb5_key_data *key, const void *data, size_t len, Checksum *C) { struct _krb5_evp_schedule *ctx = key->schedule->data; EVP_MD_CTX *m; unsigned char tmp[24]; unsigned char res[16]; DES_cblock ivec; krb5_error_code ret = 0; m = EVP_MD_CTX_create(); if (m == NULL) return krb5_enomem(context); memset(&ivec, 0, sizeof(ivec)); EVP_CipherInit_ex(&ctx->dctx, NULL, NULL, NULL, (void *)&ivec, -1); EVP_Cipher(&ctx->dctx, tmp, C->checksum.data, 24); EVP_DigestInit_ex(m, evp_md, NULL); EVP_DigestUpdate(m, tmp, 8); /* confounder */ EVP_DigestUpdate(m, data, len); EVP_DigestFinal_ex (m, res, NULL); EVP_MD_CTX_destroy(m); if(ct_memcmp(res, tmp + 8, sizeof(res)) != 0) { krb5_clear_error_message (context); ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; } memset(tmp, 0, sizeof(tmp)); memset(res, 0, sizeof(res)); return ret; }
static OM_uint32 verify_mic_des (OM_uint32 * minor_status, const gsskrb5_ctx context_handle, krb5_context context, const gss_buffer_t message_buffer, const gss_buffer_t token_buffer, gss_qop_t * qop_state, krb5_keyblock *key, char *type ) { u_char *p; EVP_MD_CTX *md5; u_char hash[16], *seq; DES_key_schedule schedule; EVP_CIPHER_CTX des_ctx; DES_cblock zero; DES_cblock deskey; uint32_t seq_number; OM_uint32 ret; int cmp; p = token_buffer->value; ret = _gsskrb5_verify_header (&p, token_buffer->length, type, GSS_KRB5_MECHANISM); if (ret) return ret; if (memcmp(p, "\x00\x00", 2) != 0) return GSS_S_BAD_SIG; p += 2; if (memcmp (p, "\xff\xff\xff\xff", 4) != 0) return GSS_S_BAD_MIC; p += 4; p += 16; /* verify checksum */ md5 = EVP_MD_CTX_create(); EVP_DigestInit_ex(md5, EVP_md5(), NULL); EVP_DigestUpdate(md5, p - 24, 8); EVP_DigestUpdate(md5, message_buffer->value, message_buffer->length); EVP_DigestFinal_ex(md5, hash, NULL); EVP_MD_CTX_destroy(md5); memset (&zero, 0, sizeof(zero)); memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); DES_set_key_unchecked (&deskey, &schedule); DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), &schedule, &zero); if (ct_memcmp (p - 8, hash, 8) != 0) { memset (deskey, 0, sizeof(deskey)); memset (&schedule, 0, sizeof(schedule)); return GSS_S_BAD_MIC; } /* verify sequence number */ HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); p -= 16; EVP_CIPHER_CTX_init(&des_ctx); EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, hash, 0); EVP_Cipher(&des_ctx, p, p, 8); EVP_CIPHER_CTX_cleanup(&des_ctx); memset (deskey, 0, sizeof(deskey)); memset (&schedule, 0, sizeof(schedule)); seq = p; _gsskrb5_decode_om_uint32(seq, &seq_number); if (context_handle->more_flags & LOCAL) cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4); else cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4); if (cmp != 0) { HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); return GSS_S_BAD_MIC; } ret = _gssapi_msg_order_check(context_handle->order, seq_number); if (ret) { HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); return ret; } HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); return GSS_S_COMPLETE; }
static OM_uint32 verify_mic_des3 (OM_uint32 * minor_status, const gsskrb5_ctx context_handle, krb5_context context, const gss_buffer_t message_buffer, const gss_buffer_t token_buffer, gss_qop_t * qop_state, krb5_keyblock *key, char *type ) { u_char *p; u_char *seq; uint32_t seq_number; OM_uint32 ret; krb5_crypto crypto; krb5_data seq_data; int cmp, docompat; Checksum csum; char *tmp; char ivec[8]; p = token_buffer->value; ret = _gsskrb5_verify_header (&p, token_buffer->length, type, GSS_KRB5_MECHANISM); 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(context, key, ETYPE_DES3_CBC_NONE, &crypto); if (ret){ *minor_status = ret; return GSS_S_FAILURE; } /* verify sequence number */ docompat = 0; retry: if (docompat) memset(ivec, 0, 8); else memcpy(ivec, p + 8, 8); ret = krb5_decrypt_ivec (context, crypto, KRB5_KU_USAGE_SEQ, p, 8, &seq_data, ivec); if (ret) { if (docompat++) { krb5_crypto_destroy (context, crypto); *minor_status = ret; return GSS_S_FAILURE; } else goto retry; } if (seq_data.length != 8) { krb5_data_free (&seq_data); if (docompat++) { krb5_crypto_destroy (context, crypto); return GSS_S_BAD_MIC; } else goto retry; } HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); seq = seq_data.data; _gsskrb5_decode_om_uint32(seq, &seq_number); if (context_handle->more_flags & LOCAL) cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4); else cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4); krb5_data_free (&seq_data); if (cmp != 0) { krb5_crypto_destroy (context, crypto); *minor_status = 0; HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); return GSS_S_BAD_MIC; } ret = _gssapi_msg_order_check(context_handle->order, seq_number); if (ret) { krb5_crypto_destroy (context, crypto); *minor_status = 0; HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); return ret; } /* verify checksum */ tmp = malloc (message_buffer->length + 8); if (tmp == NULL) { krb5_crypto_destroy (context, crypto); HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); *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 (context, crypto, KRB5_KU_USAGE_SIGN, tmp, message_buffer->length + 8, &csum); free (tmp); if (ret) { krb5_crypto_destroy (context, crypto); *minor_status = ret; HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); return GSS_S_BAD_MIC; } HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); krb5_crypto_destroy (context, crypto); return GSS_S_COMPLETE; }
OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status, const gsskrb5_ctx context_handle, krb5_context context, const gss_buffer_t input_message_buffer, gss_buffer_t output_message_buffer, int *conf_state, gss_qop_t *qop_state, krb5_keyblock *key) { u_char Klocaldata[16]; krb5_keyblock Klocal; krb5_error_code ret; uint32_t seq_number; size_t datalen; OM_uint32 omret; u_char k6_data[16], SND_SEQ[8], Confounder[8]; u_char cksum_data[8]; u_char *p, *p0; int cmp; int conf_flag; size_t padlen = 0, len; if (conf_state) *conf_state = 0; if (qop_state) *qop_state = 0; p0 = input_message_buffer->value; if (IS_DCE_STYLE(context_handle)) { len = GSS_ARCFOUR_WRAP_TOKEN_SIZE + GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE; if (input_message_buffer->length < len) return GSS_S_BAD_MECH; } else { len = input_message_buffer->length; } omret = _gssapi_verify_mech_header(&p0, len, GSS_KRB5_MECHANISM); if (omret) return omret; /* length of mech header */ len = (p0 - (u_char *)input_message_buffer->value) + GSS_ARCFOUR_WRAP_TOKEN_SIZE; if (len > input_message_buffer->length) return GSS_S_BAD_MECH; /* length of data */ datalen = input_message_buffer->length - len; p = p0; if (memcmp(p, "\x02\x01", 2) != 0) return GSS_S_BAD_SIG; p += 2; if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */ return GSS_S_BAD_SIG; p += 2; if (memcmp (p, "\x10\x00", 2) == 0) conf_flag = 1; else if (memcmp (p, "\xff\xff", 2) == 0) conf_flag = 0; else return GSS_S_BAD_SIG; p += 2; if (memcmp (p, "\xff\xff", 2) != 0) return GSS_S_BAD_MIC; p = NULL; ret = arcfour_mic_key(context, key, p0 + 16, 8, /* SGN_CKSUM */ k6_data, sizeof(k6_data)); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } { EVP_CIPHER_CTX rc4_key; EVP_CIPHER_CTX_init(&rc4_key); EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); EVP_Cipher(&rc4_key, SND_SEQ, p0 + 8, 8); EVP_CIPHER_CTX_cleanup(&rc4_key); memset(k6_data, 0, sizeof(k6_data)); } _gss_mg_decode_be_uint32(SND_SEQ, &seq_number); if (context_handle->more_flags & LOCAL) cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4); else cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4); if (cmp != 0) { *minor_status = 0; return GSS_S_BAD_MIC; } { int i; Klocal.keytype = key->keytype; Klocal.keyvalue.data = Klocaldata; Klocal.keyvalue.length = sizeof(Klocaldata); for (i = 0; i < 16; i++) Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0; } ret = arcfour_mic_key(context, &Klocal, SND_SEQ, 4, k6_data, sizeof(k6_data)); memset(Klocaldata, 0, sizeof(Klocaldata)); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } output_message_buffer->value = malloc(datalen); if (output_message_buffer->value == NULL) { *minor_status = ENOMEM; return GSS_S_FAILURE; } output_message_buffer->length = datalen; if(conf_flag) { EVP_CIPHER_CTX rc4_key; EVP_CIPHER_CTX_init(&rc4_key); EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); EVP_Cipher(&rc4_key, Confounder, p0 + 24, 8); EVP_Cipher(&rc4_key, output_message_buffer->value, p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, datalen); EVP_CIPHER_CTX_cleanup(&rc4_key); } else { memcpy(Confounder, p0 + 24, 8); /* Confounder */ memcpy(output_message_buffer->value, p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, datalen); } memset(k6_data, 0, sizeof(k6_data)); if (!IS_DCE_STYLE(context_handle)) { ret = _gssapi_verify_pad(output_message_buffer, datalen, &padlen); if (ret) { _gsskrb5_release_buffer(minor_status, output_message_buffer); *minor_status = 0; return ret; } output_message_buffer->length -= padlen; } ret = arcfour_mic_cksum(context, key, KRB5_KU_USAGE_SEAL, cksum_data, sizeof(cksum_data), p0, 8, Confounder, sizeof(Confounder), output_message_buffer->value, output_message_buffer->length + padlen); if (ret) { _gsskrb5_release_buffer(minor_status, output_message_buffer); *minor_status = ret; return GSS_S_FAILURE; } cmp = ct_memcmp(cksum_data, p0 + 16, 8); /* SGN_CKSUM */ if (cmp) { _gsskrb5_release_buffer(minor_status, output_message_buffer); *minor_status = 0; return GSS_S_BAD_MIC; } HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); omret = _gssapi_msg_order_check(context_handle->gk5c.order, seq_number); HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); if (omret) return omret; if (conf_state) *conf_state = conf_flag; *minor_status = 0; return GSS_S_COMPLETE; }
OM_uint32 _gssapi_verify_mic_arcfour(OM_uint32 * minor_status, const gsskrb5_ctx context_handle, krb5_context context, const gss_buffer_t message_buffer, const gss_buffer_t token_buffer, gss_qop_t * qop_state, krb5_keyblock *key, const char *type) { krb5_error_code ret; uint32_t seq_number; OM_uint32 omret; u_char SND_SEQ[8], cksum_data[8], *p; char k6_data[16]; int cmp; if (qop_state) *qop_state = 0; p = token_buffer->value; omret = _gsskrb5_verify_header (&p, token_buffer->length, type, GSS_KRB5_MECHANISM); if (omret) return omret; if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */ return GSS_S_BAD_SIG; p += 2; if (memcmp (p, "\xff\xff\xff\xff", 4) != 0) return GSS_S_BAD_MIC; p += 4; ret = arcfour_mic_cksum(context, key, KRB5_KU_USAGE_SIGN, cksum_data, sizeof(cksum_data), p - 8, 8, message_buffer->value, message_buffer->length, NULL, 0); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } ret = arcfour_mic_key(context, key, cksum_data, sizeof(cksum_data), k6_data, sizeof(k6_data)); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } cmp = ct_memcmp(cksum_data, p + 8, 8); if (cmp) { *minor_status = 0; return GSS_S_BAD_MIC; } { EVP_CIPHER_CTX rc4_key; EVP_CIPHER_CTX_init(&rc4_key); EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, (void *)k6_data, NULL, 0); EVP_Cipher(&rc4_key, SND_SEQ, p, 8); EVP_CIPHER_CTX_cleanup(&rc4_key); memset(k6_data, 0, sizeof(k6_data)); } _gss_mg_decode_be_uint32(SND_SEQ, &seq_number); if (context_handle->more_flags & LOCAL) cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4); else cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4); memset(SND_SEQ, 0, sizeof(SND_SEQ)); if (cmp != 0) { *minor_status = 0; return GSS_S_BAD_MIC; } HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); omret = _gssapi_msg_order_check(context_handle->gk5c.order, seq_number); HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); if (omret) return omret; *minor_status = 0; return GSS_S_COMPLETE; }
static OM_uint32 unwrap_des (OM_uint32 * minor_status, const gsskrb5_ctx context_handle, const gss_buffer_t input_message_buffer, gss_buffer_t output_message_buffer, int * conf_state, gss_qop_t * qop_state, krb5_keyblock *key ) { u_char *p, *seq; size_t len; EVP_MD_CTX *md5; u_char hash[16]; EVP_CIPHER_CTX *des_ctx; DES_key_schedule schedule; DES_cblock deskey; DES_cblock zero; size_t i; uint32_t seq_number; size_t padlength; OM_uint32 ret; int cstate; int cmp; int token_len; if (IS_DCE_STYLE(context_handle)) { token_len = 22 + 8 + 15; /* 45 */ } else { token_len = input_message_buffer->length; } p = input_message_buffer->value; ret = _gsskrb5_verify_header (&p, token_len, "\x02\x01", GSS_KRB5_MECHANISM); if (ret) return ret; if (memcmp (p, "\x00\x00", 2) != 0) return GSS_S_BAD_SIG; p += 2; if (memcmp (p, "\x00\x00", 2) == 0) { cstate = 1; } else if (memcmp (p, "\xFF\xFF", 2) == 0) { cstate = 0; } else return GSS_S_BAD_MIC; p += 2; if(conf_state != NULL) *conf_state = cstate; if (memcmp (p, "\xff\xff", 2) != 0) return GSS_S_DEFECTIVE_TOKEN; p += 2; p += 16; len = p - (u_char *)input_message_buffer->value; if(cstate) { /* decrypt data */ memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); memset (&zero, 0, sizeof(zero)); for (i = 0; i < sizeof(deskey); ++i) deskey[i] ^= 0xf0; des_ctx = EVP_CIPHER_CTX_new(); if (des_ctx == NULL) { memset (deskey, 0, sizeof(deskey)); *minor_status = ENOMEM; return GSS_S_FAILURE; } EVP_CipherInit_ex(des_ctx, EVP_des_cbc(), NULL, deskey, zero, 0); EVP_Cipher(des_ctx, p, p, input_message_buffer->length - len); EVP_CIPHER_CTX_free(des_ctx); memset (deskey, 0, sizeof(deskey)); } if (IS_DCE_STYLE(context_handle)) { padlength = 0; } else { /* check pad */ ret = _gssapi_verify_pad(input_message_buffer, input_message_buffer->length - len, &padlength); if (ret) return ret; } md5 = EVP_MD_CTX_create(); EVP_DigestInit_ex(md5, EVP_md5(), NULL); EVP_DigestUpdate(md5, p - 24, 8); EVP_DigestUpdate(md5, p, input_message_buffer->length - len); EVP_DigestFinal_ex(md5, hash, NULL); EVP_MD_CTX_destroy(md5); memset (&zero, 0, sizeof(zero)); memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); DES_set_key_unchecked (&deskey, &schedule); DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), &schedule, &zero); if (ct_memcmp (p - 8, hash, 8) != 0) { memset (deskey, 0, sizeof(deskey)); memset (&schedule, 0, sizeof(schedule)); return GSS_S_BAD_MIC; } /* verify sequence number */ des_ctx = EVP_CIPHER_CTX_new(); if (des_ctx == NULL) { memset (deskey, 0, sizeof(deskey)); memset (&schedule, 0, sizeof(schedule)); *minor_status = ENOMEM; return GSS_S_FAILURE; } HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); p -= 16; EVP_CipherInit_ex(des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, hash, 0); EVP_Cipher(des_ctx, p, p, 8); EVP_CIPHER_CTX_free(des_ctx); memset (deskey, 0, sizeof(deskey)); memset (&schedule, 0, sizeof(schedule)); seq = p; _gsskrb5_decode_om_uint32(seq, &seq_number); if (context_handle->more_flags & LOCAL) cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4); else cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4); if (cmp != 0) { HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); return GSS_S_BAD_MIC; } ret = _gssapi_msg_order_check(context_handle->order, seq_number); if (ret) { HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); return ret; } HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); /* copy out data */ output_message_buffer->length = input_message_buffer->length - len - padlength - 8; output_message_buffer->value = malloc(output_message_buffer->length); if(output_message_buffer->length != 0 && output_message_buffer->value == NULL) return GSS_S_FAILURE; memcpy (output_message_buffer->value, p + 24, output_message_buffer->length); return GSS_S_COMPLETE; }
static OM_uint32 unwrap_des3 (OM_uint32 * minor_status, const gsskrb5_ctx context_handle, krb5_context context, const gss_buffer_t input_message_buffer, gss_buffer_t output_message_buffer, int * conf_state, gss_qop_t * qop_state, krb5_keyblock *key ) { u_char *p; size_t len; u_char *seq; krb5_data seq_data; u_char cksum[20]; uint32_t seq_number; size_t padlength; OM_uint32 ret; int cstate; krb5_crypto crypto; Checksum csum; int cmp; int token_len; if (IS_DCE_STYLE(context_handle)) { token_len = 34 + 8 + 15; /* 57 */ } else { token_len = input_message_buffer->length; } p = input_message_buffer->value; ret = _gsskrb5_verify_header (&p, token_len, "\x02\x01", GSS_KRB5_MECHANISM); if (ret) return ret; if (memcmp (p, "\x04\x00", 2) != 0) /* HMAC SHA1 DES3_KD */ return GSS_S_BAD_SIG; p += 2; if (ct_memcmp (p, "\x02\x00", 2) == 0) { cstate = 1; } else if (ct_memcmp (p, "\xff\xff", 2) == 0) { cstate = 0; } else return GSS_S_BAD_MIC; p += 2; if(conf_state != NULL) *conf_state = cstate; if (ct_memcmp (p, "\xff\xff", 2) != 0) return GSS_S_DEFECTIVE_TOKEN; p += 2; p += 28; len = p - (u_char *)input_message_buffer->value; if(cstate) { /* decrypt data */ krb5_data tmp; ret = krb5_crypto_init(context, key, ETYPE_DES3_CBC_NONE, &crypto); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } ret = krb5_decrypt(context, crypto, KRB5_KU_USAGE_SEAL, p, input_message_buffer->length - len, &tmp); krb5_crypto_destroy(context, crypto); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } assert (tmp.length == input_message_buffer->length - len); memcpy (p, tmp.data, tmp.length); krb5_data_free(&tmp); } if (IS_DCE_STYLE(context_handle)) { padlength = 0; } else { /* check pad */ ret = _gssapi_verify_pad(input_message_buffer, input_message_buffer->length - len, &padlength); if (ret) return ret; } /* verify sequence number */ HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); p -= 28; ret = krb5_crypto_init(context, key, ETYPE_DES3_CBC_NONE, &crypto); if (ret) { *minor_status = ret; HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); return GSS_S_FAILURE; } { DES_cblock ivec; memcpy(&ivec, p + 8, 8); ret = krb5_decrypt_ivec (context, crypto, KRB5_KU_USAGE_SEQ, p, 8, &seq_data, &ivec); } krb5_crypto_destroy (context, crypto); if (ret) { *minor_status = ret; HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); return GSS_S_FAILURE; } if (seq_data.length != 8) { krb5_data_free (&seq_data); *minor_status = 0; HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); return GSS_S_BAD_MIC; } seq = seq_data.data; _gsskrb5_decode_om_uint32(seq, &seq_number); if (context_handle->more_flags & LOCAL) cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4); else cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4); krb5_data_free (&seq_data); if (cmp != 0) { *minor_status = 0; HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); return GSS_S_BAD_MIC; } ret = _gssapi_msg_order_check(context_handle->order, seq_number); if (ret) { *minor_status = 0; HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); return ret; } HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); /* verify checksum */ memcpy (cksum, p + 8, 20); memcpy (p + 20, p - 8, 8); csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3; csum.checksum.length = 20; csum.checksum.data = cksum; ret = krb5_crypto_init(context, key, 0, &crypto); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } ret = krb5_verify_checksum (context, crypto, KRB5_KU_USAGE_SIGN, p + 20, input_message_buffer->length - len + 8, &csum); krb5_crypto_destroy (context, crypto); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } /* copy out data */ output_message_buffer->length = input_message_buffer->length - len - padlength - 8; output_message_buffer->value = malloc(output_message_buffer->length); if(output_message_buffer->length != 0 && output_message_buffer->value == NULL) return GSS_S_FAILURE; memcpy (output_message_buffer->value, p + 36, output_message_buffer->length); return GSS_S_COMPLETE; }