return GSS_S_COMPLETE;
}
+static OM_uint32
+unwrap_ex_des
+ (OM_uint32 *minor_status,
+ const gsskrb5_ctx context_handle,
+ krb5_context context,
+ int *conf_state,
+ gss_qop_t *qop_state,
+ krb5_keyblock *key,
+ const gss_buffer_t token_header_buffer,
+ const gss_buffer_t associated_data_buffer,
+ gss_buffer_t message_buffer
+ )
+{
+ u_char *p, *seq;
+ MD5_CTX md5;
+ u_char hash[16];
+ DES_key_schedule schedule;
+ DES_cblock deskey;
+ DES_cblock zero;
+ int i;
+ uint32_t seq_number;
+ OM_uint32 ret;
+ int cstate;
+ int cmp;
+
+ p = token_header_buffer->value;
+ ret = _gsskrb5_verify_header (&p,
+ token_header_buffer->length,
+ "\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;
+
+ if(cstate) {
+ uint8_t *e;
+
+ /* decrypt data */
+ memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
+
+ for (i = 0; i < sizeof(deskey); ++i)
+ deskey[i] ^= 0xf0;
+ DES_set_key_unchecked (&deskey, &schedule);
+ memset (&zero, 0, sizeof(zero));
+
+ e = malloc(8 + message_buffer->length);
+ if (e == NULL) {
+ *minor_status = ENOMEM;
+ return GSS_S_FAILURE;
+ }
+ memcpy(e, p, 8);
+ memcpy(e + 8, message_buffer->value, message_buffer->length);
+
+ DES_cbc_encrypt ((void *)e,
+ (void *)e,
+ 8 + message_buffer->length,
+ &schedule,
+ &zero,
+ DES_DECRYPT);
+
+ memcpy(p, e, 8);
+ memcpy(message_buffer->value, e + 8, message_buffer->length);
+ free(e);
+
+ memset (deskey, 0, sizeof(deskey));
+ memset (&schedule, 0, sizeof(schedule));
+ }
+
+ MD5_Init (&md5);
+ MD5_Update (&md5, p - 24, 8);
+ MD5_Update (&md5, p, 8);
+ MD5_Update (&md5, associated_data_buffer->value, associated_data_buffer->length);
+ MD5_Final (hash, &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 (memcmp (p - 8, hash, 8) != 0)
+ return GSS_S_BAD_MIC;
+
+ /* verify sequence number */
+
+ HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+
+ p -= 16;
+ DES_set_key_unchecked (&deskey, &schedule);
+ DES_cbc_encrypt ((void *)p, (void *)p, 8,
+ &schedule, (DES_cblock *)hash, DES_DECRYPT);
+
+ 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 = memcmp(&seq[4], "\xff\xff\xff\xff", 4);
+ else
+ cmp = 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
unwrap_des3
(OM_uint32 * minor_status,
)
{
int no_ex = 0;
- OM_uint32 minor;
krb5_keyblock *key;
krb5_context context;
OM_uint32 ret;
*minor_status = 0;
switch (keytype) {
- case KEYTYPE_DES:
case KEYTYPE_DES3:
no_ex = 1;
break;
}
switch (keytype) {
+ case KEYTYPE_DES:
+ ret = unwrap_ex_des(minor_status, ctx, context,
+ conf_state, qop_state, key,
+ token_header_buffer,
+ associated_data_buffer,
+ message_buffer);
+ break;
case KEYTYPE_ARCFOUR:
case KEYTYPE_ARCFOUR_56:
ret = _gssapi_unwrap_ex_arcfour(minor_status, ctx, context,
return GSS_S_COMPLETE;
}
+static OM_uint32
+wrap_ex_des
+ (OM_uint32 *minor_status,
+ const gsskrb5_ctx ctx,
+ krb5_context context,
+ int conf_req_flag,
+ gss_qop_t qop_req,
+ int *conf_state,
+ krb5_keyblock *key,
+ const gss_buffer_t associated_data_buffer,
+ gss_buffer_t message_buffer,
+ gss_buffer_t output_token_buffer
+ )
+{
+ u_char *p;
+ MD5_CTX md5;
+ u_char hash[16];
+ DES_key_schedule schedule;
+ DES_cblock deskey;
+ DES_cblock zero;
+ int i;
+ int32_t seq_number;
+ size_t len, total_len;
+
+ len = 22 + 8;
+ _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM);
+
+ output_token_buffer->length = total_len;
+ output_token_buffer->value = malloc(total_len);
+ if (output_token_buffer->value == NULL) {
+ output_token_buffer->length = 0;
+ *minor_status = ENOMEM;
+ return GSS_S_FAILURE;
+ }
+
+ p = _gsskrb5_make_header(output_token_buffer->value,
+ len,
+ "\x02\x01", /* TOK_ID */
+ GSS_KRB5_MECHANISM);
+
+ /* SGN_ALG */
+ memcpy (p, "\x00\x00", 2);
+ p += 2;
+ /* SEAL_ALG */
+ if(conf_req_flag)
+ memcpy (p, "\x00\x00", 2);
+ else
+ memcpy (p, "\xff\xff", 2);
+ p += 2;
+ /* Filler */
+ memcpy (p, "\xff\xff", 2);
+ p += 2;
+
+ /* fill in later */
+ memset (p, 0, 16);
+ p += 16;
+
+ /* confounder + data + pad */
+ krb5_generate_random_block(p, 8);
+
+ /* checksum */
+ MD5_Init (&md5);
+ MD5_Update (&md5, p - 24, 8);
+ MD5_Update (&md5, p, 8);
+ MD5_Update (&md5, associated_data_buffer->value, associated_data_buffer->length);
+ MD5_Final (hash, &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);
+ memcpy (p - 8, hash, 8);
+
+ /* sequence number */
+ HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
+ krb5_auth_con_getlocalseqnumber (context,
+ ctx->auth_context,
+ &seq_number);
+
+ p -= 16;
+ p[0] = (seq_number >> 0) & 0xFF;
+ p[1] = (seq_number >> 8) & 0xFF;
+ p[2] = (seq_number >> 16) & 0xFF;
+ p[3] = (seq_number >> 24) & 0xFF;
+ memset (p + 4,
+ (ctx->more_flags & LOCAL) ? 0 : 0xFF,
+ 4);
+
+ DES_set_key_unchecked (&deskey, &schedule);
+ DES_cbc_encrypt ((void *)p, (void *)p, 8,
+ &schedule, (DES_cblock *)(p + 8), DES_ENCRYPT);
+
+ krb5_auth_con_setlocalseqnumber (context,
+ ctx->auth_context,
+ ++seq_number);
+ HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
+
+ /* encrypt the data */
+ p += 16;
+
+ if(conf_req_flag) {
+ uint8_t *e;
+
+ memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
+
+ for (i = 0; i < sizeof(deskey); ++i)
+ deskey[i] ^= 0xf0;
+ DES_set_key_unchecked (&deskey, &schedule);
+ memset (&zero, 0, sizeof(zero));
+
+ e = malloc(8 + message_buffer->length);
+ if (e == NULL) {
+ gss_release_buffer(minor_status, output_token_buffer);
+ *minor_status = ENOMEM;
+ return GSS_S_FAILURE;
+ }
+ memcpy(e, p, 8);
+ memcpy(e + 8, message_buffer->value, message_buffer->length);
+
+ DES_cbc_encrypt ((void *)e,
+ (void *)e,
+ 8 + message_buffer->length,
+ &schedule,
+ &zero,
+ DES_ENCRYPT);
+
+ memcpy(p, e, 8);
+ memcpy(message_buffer->value, e + 8, message_buffer->length);
+ free(e);
+ }
+ memset (deskey, 0, sizeof(deskey));
+ memset (&schedule, 0, sizeof(schedule));
+
+ if(conf_state != NULL)
+ *conf_state = conf_req_flag;
+ *minor_status = 0;
+ return GSS_S_COMPLETE;
+}
+
static OM_uint32
wrap_des3
(OM_uint32 * minor_status,
)
{
int no_ex = 0;
- OM_uint32 minor;
krb5_context context;
krb5_keyblock *key;
OM_uint32 ret;
krb5_enctype_to_keytype (context, key->keytype, &keytype);
switch (keytype) {
- case KEYTYPE_DES:
case KEYTYPE_DES3:
krb5_free_keyblock (context, key);
no_ex = 1;
}
switch (keytype) {
+ case KEYTYPE_DES:
+ ret = wrap_ex_des(minor_status,
+ ctx, context, conf_req_flag,
+ qop_req, conf_state, key,
+ associated_data_buffer,
+ message_buffer,
+ output_token_buffer);
+ break;
case KEYTYPE_ARCFOUR:
case KEYTYPE_ARCFOUR_56:
ret = _gssapi_wrap_ex_arcfour(minor_status,