int main(int argc, char **argv) { struct krb5_key_state *key, *dk; uint8_t *dkp; int j, i; for (j = 0; j < N_TESTS; j++) { struct des3_dk_test *t = &tests[j]; key = krb5_create_key(&des3_encryption_class); krb5_set_key(key, t->key); dk = krb5_derive_key(key, t->usage, t->usagelen); krb5_free_key(key); if (memcmp(dk->ks_key, t->dk, 24)) { printf("DES3 dk("); for (i = 0; i < 24; i++) printf("%02x", t->key[i]); printf(", "); for (i = 0; i < t->usagelen; i++) printf("%02x", t->usage[i]); printf(") failed\n"); printf("should be: "); for (i = 0; i < 24; i++) printf("%02x", t->dk[i]); printf("\n result was: "); dkp = dk->ks_key; for (i = 0; i < 24; i++) printf("%02x", dkp[i]); printf("\n"); } krb5_free_key(dk); } return (0); }
static krb5_error_code AES_PRF(krb5_context context, krb5_crypto crypto, const krb5_data *in, krb5_data *out) { struct _krb5_checksum_type *ct = crypto->et->checksum; krb5_error_code ret; Checksum result; krb5_keyblock *derived; result.cksumtype = ct->type; ret = krb5_data_alloc(&result.checksum, ct->checksumsize); if (ret) { krb5_set_error_message(context, ret, N_("malloc: out memory", "")); return ret; } ret = (*ct->checksum)(context, NULL, in->data, in->length, 0, &result); if (ret) { krb5_data_free(&result.checksum); return ret; } if (result.checksum.length < crypto->et->blocksize) krb5_abortx(context, "internal prf error"); derived = NULL; ret = krb5_derive_key(context, crypto->key.key, crypto->et->type, "prf", 3, &derived); if (ret) krb5_abortx(context, "krb5_derive_key"); ret = krb5_data_alloc(out, crypto->et->blocksize); if (ret) krb5_abortx(context, "malloc failed"); { const EVP_CIPHER *c = (*crypto->et->keytype->evp)(); EVP_CIPHER_CTX *ctx; ctx = EVP_CIPHER_CTX_new(); /* ivec all zero */ if (ctx == NULL) krb5_abortx(context, "malloc failed"); EVP_CipherInit_ex(ctx, c, NULL, derived->keyvalue.data, NULL, 1); EVP_Cipher(ctx, out->data, result.checksum.data, crypto->et->blocksize); EVP_CIPHER_CTX_free(ctx); } krb5_data_free(&result.checksum); krb5_free_keyblock(context, derived); return ret; }
int main(int argc, char **argv) { struct testcase *t; krb5_context context; krb5_error_code ret; int val = 0; ret = krb5_init_context (&context); if (ret) errx (1, "krb5_init_context failed: %d", ret); for (t = tests; t->enctype != 0; ++t) { krb5_keyblock key; krb5_keyblock *dkey; key.keytype = KEYTYPE_DES3; key.keyvalue.length = MAXSIZE; key.keyvalue.data = t->key; ret = krb5_derive_key(context, &key, t->enctype, t->constant, t->constant_len, &dkey); if (ret) krb5_err (context, 1, ret, "krb5_derive_key"); if (memcmp (dkey->keyvalue.data, t->res, dkey->keyvalue.length) != 0) { const unsigned char *p = dkey->keyvalue.data; int i; printf ("derive_key failed\n"); printf ("should be: "); for (i = 0; i < dkey->keyvalue.length; ++i) printf ("%02x", t->res[i]); printf ("\nresult was: "); for (i = 0; i < dkey->keyvalue.length; ++i) printf ("%02x", p[i]); printf ("\n"); val = 1; } krb5_free_keyblock(context, dkey); } krb5_free_context(context); return val; }
/* * 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); }
krb5_error_code krb5_dk_make_checksum(const struct krb5_hash_provider *hash, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *input, krb5_data *output) { int i; const struct krb5_enc_provider *enc; size_t blocksize, keybytes, keylength; krb5_error_code ret; unsigned char constantdata[K5CLENGTH]; krb5_data datain; unsigned char *kcdata; krb5_keyblock kc; for (i=0; i<krb5_enctypes_length; i++) { if (krb5_enctypes_list[i].etype == key->enctype) break; } if (i == krb5_enctypes_length) return(KRB5_BAD_ENCTYPE); enc = krb5_enctypes_list[i].enc; /* allocate and set to-be-derived keys */ blocksize = enc->block_size; keybytes = enc->keybytes; keylength = enc->keylength; /* key->length will be tested in enc->encrypt output->length will be tested in krb5_hmac */ if ((kcdata = (unsigned char *) malloc(keylength)) == NULL) return(ENOMEM); kc.contents = kcdata; kc.length = keylength; /* derive the key */ datain.data = (char *) constantdata; datain.length = K5CLENGTH; store_32_be(usage, constantdata); datain.data[4] = (char) 0x99; if ((ret = krb5_derive_key(enc, key, &kc, &datain)) != 0) goto cleanup; /* hash the data */ datain = *input; if ((ret = krb5_hmac(hash, &kc, 1, &datain, output)) != 0) memset(output->data, 0, output->length); /* ret is set correctly by the prior call */ cleanup: memset(kcdata, 0, keylength); free(kcdata); return(ret); }
/* * 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); }