/* * 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); }