Exemple #1
0
/*
 * Function to derive a new key from a given key and given constant data.
 */
static krb5_error_code
derive_key_lucid(const gss_krb5_lucid_key_t *in, gss_krb5_lucid_key_t *out,
		 int usage, char extra)
{
	krb5_error_code code;
	unsigned char constant_data[K5CLENGTH];
	krb5_data datain;
	int keylength;
	void *enc;
	krb5_keyblock kin, kout;  /* must send krb5_keyblock, not lucid! */
#ifdef HAVE_HEIMDAL
	krb5_context kcontext;
	krb5_keyblock *outkey;
#endif

	/*
	 * XXX Hack alert.  We don't have "legal" access to these
	 * values and structures located in libk5crypto
	 */
	switch (in->type) {
	case ENCTYPE_DES3_CBC_SHA1:
#ifdef HAVE_KRB5
	case ENCTYPE_DES3_CBC_RAW:
#endif
		keylength = 24;
#ifdef HAVE_KRB5
		enc = &krb5int_enc_des3;
#endif
		break;
	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
		keylength = 16;
#ifdef HAVE_KRB5
		enc = &krb5int_enc_aes128;
#endif
		break;
	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
		keylength = 32;
#ifdef HAVE_KRB5
		enc = &krb5int_enc_aes256;
#endif
		break;
	default:
		code = KRB5_BAD_ENCTYPE;
		goto out;
	}

	/* allocate memory for output key */
	if ((out->data = malloc(keylength)) == NULL) {
		code = ENOMEM;
		goto out;
	}
	out->length = keylength;
	out->type = in->type;

	/* Convert to correct format for call to krb5_derive_key */
	key_lucid_to_krb5(in, &kin);
	key_lucid_to_krb5(out, &kout);

	datain.data = (char *) constant_data;
	datain.length = K5CLENGTH;

	((char *)(datain.data))[0] = (usage>>24)&0xff;
	((char *)(datain.data))[1] = (usage>>16)&0xff;
	((char *)(datain.data))[2] = (usage>>8)&0xff;
	((char *)(datain.data))[3] = usage&0xff;

	((char *)(datain.data))[4] = (char) extra;

#ifdef HAVE_KRB5
	code = krb5_derive_key(enc, &kin, &kout, &datain);
#else
	if ((code = krb5_init_context(&kcontext))) {
	}
	code = krb5_derive_key(kcontext, &kin, in->type, constant_data, K5CLENGTH, &outkey);
#endif
	if (code) {
		free(out->data);
		out->data = NULL;
		goto out;
	}
#ifdef HAVE_KRB5
	key_krb5_to_lucid(&kout, out);
#else
	key_krb5_to_lucid(outkey, out);
	krb5_free_keyblock(kcontext, outkey);
	krb5_free_context(kcontext);
#endif

  out:
  	if (code)
		printerr(0, "ERROR: %s: returning error %d (%s)\n",
			 __FUNCTION__, code, error_message(code));
	return (code);
}
/*
 * Function to derive a new key from a given key and given constant data.
 */
static krb5_error_code
derive_key_lucid(const gss_krb5_lucid_key_t *in, gss_krb5_lucid_key_t *out,
		 int usage, char extra)
{
	krb5_error_code code;
	unsigned char constant_data[K5CLENGTH];
	krb5_data datain;
	int keylength __attribute__ ((unused));
#ifdef HAVE_KRB5
	void *enc;
#endif
	krb5_keyblock kin;  /* must send krb5_keyblock, not lucid! */
#if defined(HAVE_HEIMDAL) || HAVE_KRB5INT_DERIVE_KEY
	krb5_context kcontext;
	krb5_keyblock *outkey;
#else
	krb5_keyblock kout;
#endif
#if HAVE_KRB5INT_DERIVE_KEY
	krb5_key key_in, key_out;
#endif

	/*
	 * XXX Hack alert.  We don't have "legal" access to these
	 * values and structures located in libk5crypto
	 */
	switch (in->type) {
	case ENCTYPE_DES3_CBC_SHA1:
#ifdef HAVE_KRB5
	case ENCTYPE_DES3_CBC_RAW:
#endif
		keylength = 24;
#ifdef HAVE_KRB5
		enc = &krb5int_enc_des3;
#endif
		break;
	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
		keylength = 16;
#ifdef HAVE_KRB5
		enc = &krb5int_enc_aes128;
#endif
		break;
	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
		keylength = 32;
#ifdef HAVE_KRB5
		enc = &krb5int_enc_aes256;
#endif
		break;
	default:
		code = KRB5_BAD_ENCTYPE;
		goto out;
	}

	/* Convert to correct format for call to krb5_derive_key */
	key_lucid_to_krb5(in, &kin);

	datain.data = (char *) constant_data;
	datain.length = K5CLENGTH;

	((char *)(datain.data))[0] = (usage>>24)&0xff;
	((char *)(datain.data))[1] = (usage>>16)&0xff;
	((char *)(datain.data))[2] = (usage>>8)&0xff;
	((char *)(datain.data))[3] = usage&0xff;

	((char *)(datain.data))[4] = (char) extra;

	/* Step 1: Init context */
	/* Heimdal and newer MIT Kerberos require kcontext */
#if defined(HAVE_KRB5INT_DERIVE_KEY) || defined(HAVE_HEIMDAL)
	code = krb5_init_context(&kcontext);
	if (code)
		goto out;
#endif

	/* Step 2: Get the derived key */
#ifdef HAVE_KRB5
#if HAVE_KRB5INT_DERIVE_KEY
	code = krb5_k_create_key(kcontext, &kin, &key_in);
	if (code)
		goto out;

	code = ll_krb5int_derive_key(enc, key_in, &key_out, &datain,
				     DERIVE_RFC3961);

	krb5_k_free_key(kcontext, key_in);
	if (code == 0) {
		krb5_k_key_keyblock(kcontext, key_out, &outkey);
		krb5_k_free_key(kcontext, key_out);
	}
#else  /* !HAVE_KRB5INT_DERIVE_KEY */
	out->length = keylength;
	out->type = in->type;

	key_lucid_to_krb5(out, &kout);

	code = krb5_derive_key(enc, &kin, &kout, &datain);
#endif	/* HAVE_KRB5INT_DERIVE_KEY */
#else	/* !defined(HAVE_KRB5) */
	code = krb5_derive_key(kcontext, &kin, in->type, constant_data, K5CLENGTH, &outkey);
#endif	/* defined(HAVE_KRB5) */

	if (code)
		goto out;

	/* Step 3: Copy the key to out */
#if defined(HAVE_KRB5INT_DERIVE_KEY) || defined(HAVE_HEIMDAL)
	code = key_krb5_to_lucid(outkey, out);
	krb5_free_keyblock(kcontext, outkey);
#else	/* !defined(HAVE_KRB5) */
	code = key_krb5_to_lucid(&kout, out);
#endif	/* defined(HAVE_KRB5) */

	/* Step 4: Free the context */
#if defined(HAVE_KRB5INT_DERIVE_KEY) || defined(HAVE_HEIMDAL)
	krb5_free_context(kcontext);
#endif

  out:
	if (code)
		printerr(0, "ERROR: %s: returning error %d (%s)\n",
			 __FUNCTION__, code, error_message(code));
	return (code);
}