1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/crypto/krb/cf2.c */
4 * Copyright (C) 2009 by the Massachusetts Institute of Technology.
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
28 * Implement KRB_FX_CF2 function per draft-ietf-krb-wg-preauth-framework-09.
29 * Take two keys and two pepper strings as input and return a combined key.
32 #include "crypto_int.h"
35 * Call the PRF function multiple times with the pepper prefixed with
36 * a count byte to get enough bits of output.
38 static krb5_error_code
39 prf_plus(krb5_context context, krb5_keyblock *k, const char *pepper,
40 size_t keybytes, char **out)
42 krb5_error_code retval = 0;
43 size_t prflen, iterations;
47 struct k5buf prf_inbuf;
49 krb5int_buf_init_dynamic(&prf_inbuf);
50 krb5int_buf_add_len(&prf_inbuf, "\001", 1);
51 krb5int_buf_add(&prf_inbuf, pepper);
52 retval = krb5_c_prf_length( context, k->enctype, &prflen);
55 iterations = keybytes / prflen;
56 if (keybytes % prflen != 0)
58 assert(iterations <= 254);
59 buffer = k5alloc(iterations * prflen, &retval);
62 if (krb5int_buf_len(&prf_inbuf) == -1) {
66 in_data.length = (krb5_int32) krb5int_buf_len(&prf_inbuf);
67 in_data.data = krb5int_buf_data(&prf_inbuf);
68 out_data.length = prflen;
69 out_data.data = buffer;
71 while (iterations > 0) {
72 retval = krb5_c_prf(context, k, &in_data, &out_data);
75 out_data.data += prflen;
85 krb5int_free_buf(&prf_inbuf);
90 krb5_error_code KRB5_CALLCONV
91 krb5_c_fx_cf2_simple(krb5_context context,
92 krb5_keyblock *k1, const char *pepper1,
93 krb5_keyblock *k2, const char *pepper2,
96 const struct krb5_keytypes *out_enctype;
97 size_t keybytes, keylength, i;
98 char *prf1 = NULL, *prf2 = NULL;
100 krb5_enctype out_enctype_num;
101 krb5_error_code retval = 0;
102 krb5_keyblock *out_key = NULL;
104 if (k1 == NULL || !krb5_c_valid_enctype(k1->enctype))
105 return KRB5_BAD_ENCTYPE;
106 if (k2 == NULL || !krb5_c_valid_enctype(k2->enctype))
107 return KRB5_BAD_ENCTYPE;
108 out_enctype_num = k1->enctype;
110 out_enctype = find_enctype(out_enctype_num);
111 assert(out_enctype != NULL);
112 if (out_enctype->prf == NULL) {
114 krb5int_set_error(&(context->err), KRB5_CRYPTO_INTERNAL,
115 _("Enctype %d has no PRF"), out_enctype_num);
116 return KRB5_CRYPTO_INTERNAL;
118 keybytes = out_enctype->enc->keybytes;
119 keylength = out_enctype->enc->keylength;
121 retval = prf_plus(context, k1, pepper1, keybytes, &prf1);
124 retval = prf_plus(context, k2, pepper2, keybytes, &prf2);
127 for (i = 0; i < keybytes; i++)
129 retval = krb5int_c_init_keyblock(context, out_enctype_num, keylength,
134 keydata.length = keybytes;
135 retval = (*out_enctype->rand2key)(&keydata, out_key);
143 krb5int_c_free_keyblock( context, out_key);
144 zapfree(prf1, keybytes);
145 zapfree(prf2, keybytes);