#define HC_DEPRECATED_CRYPTO
#include "mech_locl.h"
#include <krb5.h>
#include <roken.h>
#include "crypto-headers.h"
OM_uint32
gss_mg_gen_cb(OM_uint32 *minor_status,
const gss_channel_bindings_t b,
uint8_t p[16], gss_buffer_t buffer)
{
krb5_error_code ret;
krb5_storage *sp;
krb5_data data;
krb5_data_zero(&data);
sp = krb5_storage_emem();
if (sp == NULL) {
*minor_status = ENOMEM;
goto out;
}
krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE);
ret = krb5_store_uint32(sp, b->initiator_addrtype);
if (ret) {
*minor_status = ret;
goto out;
}
ret = krb5_store_uint32(sp, b->initiator_address.length);
if (ret) {
*minor_status = ret;
goto out;
}
ret = krb5_storage_write(sp, b->initiator_address.value,
b->initiator_address.length);
if (ret != b->initiator_address.length) {
*minor_status = ENOMEM;
goto out;
}
ret = krb5_store_uint32(sp, b->acceptor_addrtype);
if (ret) {
*minor_status = ret;
goto out;
}
ret = krb5_store_uint32(sp, b->acceptor_address.length);
if (ret) {
*minor_status = ret;
goto out;
}
ret = krb5_storage_write(sp, b->acceptor_address.value,
b->acceptor_address.length);
if (ret != b->acceptor_address.length) {
*minor_status = ENOMEM;
goto out;
}
if (b->application_data.length)
ret = krb5_storage_write(sp, b->application_data.value,
b->application_data.length);
if (ret != b->application_data.length) {
*minor_status = ENOMEM;
goto out;
}
ret = krb5_storage_to_data(sp, &data);
if (ret) {
*minor_status = ret;
goto out;
}
CCDigest(kCCDigestMD5, data.data, data.length, p);
if (buffer) {
buffer->value = data.data;
buffer->length = data.length;
} else {
krb5_data_free(&data);
}
*minor_status = 0;
return GSS_S_COMPLETE;
out:
if (sp)
krb5_storage_free(sp);
return GSS_S_FAILURE;
}
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;
}