2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
8 * Copyright (c) 2002 Naval Research Laboratory (NRL/CCS)
10 * Permission to use, copy, modify and distribute this software and its
11 * documentation is hereby granted, provided that both the copyright
12 * notice and this permission notice appear in all copies of the software,
13 * derivative works or modified versions, and any portions thereof.
15 * NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
16 * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
17 * RESULTING FROM THE USE OF THIS SOFTWARE.
19 * Key combination function.
21 * If Key1 and Key2 are two keys to be combined, the algorithm to combine
26 * k-truncate is defined as truncating to the key size the input.
28 * DR is defined as the generate "random" data from a key
29 * (defined in crypto draft)
31 * DK is defined as the key derivation function (krb5_derive_key())
33 * (note: | means "concatenate")
35 * Combine key algorithm:
37 * R1 = DR(Key1, n-fold(Key2)) [ Output is length of Key1 ]
38 * R2 = DR(Key2, n-fold(Key1)) [ Output is length of Key2 ]
40 * rnd = n-fold(R1 | R2) [ Note: output size of nfold must be appropriately
41 * sized for random-to-key function ]
42 * tkey = random-to-key(rnd)
43 * Combine-Key(Key1, Key2) = DK(tkey, CombineConstant)
45 * CombineConstant is defined as the byte string:
47 * { 0x63 0x6f 0x6d 0x62 0x69 0x6e 0x65 }, which corresponds to the
48 * ASCII encoding of the string "combine"
55 /* Solaris Kerberos */
56 static krb5_error_code dr
57 (krb5_context context
,
58 const struct krb5_enc_provider
*enc
, const krb5_keyblock
*inkey
,
59 unsigned char *outdata
, const krb5_data
*in_constant
);
62 * We only support this combine_keys algorithm for des and 3des keys.
63 * Everything else should use the PRF defined in the crypto framework.
64 * We don't implement that yet.
67 static krb5_boolean
enctype_ok (krb5_enctype e
)
70 case ENCTYPE_DES_CBC_CRC
:
71 case ENCTYPE_DES_CBC_MD4
:
72 case ENCTYPE_DES_CBC_MD5
:
73 case ENCTYPE_DES3_CBC_SHA1
:
80 krb5_error_code krb5int_c_combine_keys
81 (krb5_context context
, krb5_keyblock
*key1
, krb5_keyblock
*key2
, krb5_keyblock
*outkey
)
83 unsigned char *r1
, *r2
, *combined
, *rnd
, *output
;
84 size_t keybytes
, keylength
;
85 const struct krb5_enc_provider
*enc
;
86 krb5_data input
, randbits
;
90 if (!(enctype_ok(key1
->enctype
)&&enctype_ok(key2
->enctype
)))
91 return (KRB5_CRYPTO_INTERNAL
);
94 if (key1
->length
!= key2
->length
|| key1
->enctype
!= key2
->enctype
)
95 return (KRB5_CRYPTO_INTERNAL
);
98 * Find our encryption algorithm
101 for (i
= 0; i
< krb5_enctypes_length
; i
++) {
102 if (krb5_enctypes_list
[i
].etype
== key1
->enctype
)
106 if (i
== krb5_enctypes_length
)
107 return (KRB5_BAD_ENCTYPE
);
109 enc
= krb5_enctypes_list
[i
].enc
;
111 keybytes
= enc
->keybytes
;
112 keylength
= enc
->keylength
;
115 * Allocate and set up buffers
118 if ((r1
= (unsigned char *) malloc(keybytes
)) == NULL
)
121 if ((r2
= (unsigned char *) malloc(keybytes
)) == NULL
) {
126 if ((rnd
= (unsigned char *) malloc(keybytes
)) == NULL
) {
132 if ((combined
= (unsigned char *) malloc(keybytes
* 2)) == NULL
) {
139 if ((output
= (unsigned char *) malloc(keylength
)) == NULL
) {
148 * Get R1 and R2 (by running the input keys through the DR algorithm.
149 * Note this is most of derive-key, but not all.
152 input
.length
= key2
->length
;
153 input
.data
= (char *) key2
->contents
;
154 /* Solaris Kerberos */
155 if ((ret
= dr(context
, enc
, key1
, r1
, &input
)))
162 for (i
= 0; i
< keybytes
; i
++)
163 printf(" %02x", (unsigned char) r1
[i
]);
168 input
.length
= key1
->length
;
169 input
.data
= (char *) key1
->contents
;
170 /* Solaris Kerberos */
171 if ((ret
= dr(context
, enc
, key2
, r2
, &input
)))
178 for (i
= 0; i
< keybytes
; i
++)
179 printf(" %02x", (unsigned char) r2
[i
]);
185 * Concatenate the two keys together, and then run them through
186 * n-fold to reduce them to a length appropriate for the random-to-key
187 * operation. Note here that krb5_nfold() takes sizes in bits, hence
191 memcpy(combined
, r1
, keybytes
);
192 memcpy(combined
+ keybytes
, r2
, keybytes
);
194 krb5_nfold((keybytes
* 2) * 8, combined
, keybytes
* 8, rnd
);
200 for (i
= 0; i
< keybytes
; i
++)
201 printf(" %02x", (unsigned char) rnd
[i
]);
207 * Run the "random" bits through random-to-key to produce a encryption
211 randbits
.length
= keybytes
;
212 randbits
.data
= (char *) rnd
;
213 tkey
.length
= keylength
;
214 tkey
.contents
= output
;
216 /* Solaris Kerberos */
217 if ((ret
= (*(enc
->make_key
))(context
, &randbits
, &tkey
)))
224 for (i
= 0; i
< tkey
.length
; i
++)
225 printf(" %02x", (unsigned char) tkey
.contents
[i
]);
231 * Run through derive-key one more time to produce the final key.
232 * Note that the input to derive-key is the ASCII string "combine".
235 input
.length
= 7; /* Note; change this if string length changes */
236 input
.data
= "combine";
239 * Just FYI: _if_ we have space here in the key, then simply use it
240 * without modification. But if the key is blank (no allocated storage)
241 * then allocate some memory for it. This allows programs to use one of
242 * the existing keys as the output key, _or_ pass in a blank keyblock
243 * for us to allocate. It's easier for us to allocate it since we already
244 * know the crypto library internals
247 if (outkey
->length
== 0 || outkey
->contents
== NULL
) {
248 outkey
->contents
= (krb5_octet
*) malloc(keylength
);
249 if (!outkey
->contents
) {
253 outkey
->length
= keylength
;
254 outkey
->enctype
= key1
->enctype
;
258 /* Solaris Kerberos */
259 if ((ret
= krb5_derive_key(context
, enc
, &tkey
, outkey
, &input
))) {
261 free(outkey
->contents
);
262 outkey
->contents
= NULL
;
271 for (i
= 0; i
< outkey
->length
; i
++)
272 printf(" %02x", (unsigned char) outkey
->contents
[i
]);
280 memset(r1
, 0, keybytes
);
281 memset(r2
, 0, keybytes
);
282 memset(rnd
, 0, keybytes
);
283 memset(combined
, 0, keybytes
* 2);
284 memset(output
, 0, keylength
);
296 * Our DR function; mostly taken from derive.c
299 /* Solaris Kerberos */
300 static krb5_error_code dr
301 ( krb5_context context
,
302 const struct krb5_enc_provider
*enc
,
303 const krb5_keyblock
*inkey
,
305 const krb5_data
*in_constant
)
307 size_t blocksize
, keybytes
, keylength
, n
;
308 unsigned char *inblockdata
, *outblockdata
;
309 krb5_data inblock
, outblock
;
311 blocksize
= enc
->block_size
;
312 keybytes
= enc
->keybytes
;
313 keylength
= enc
->keylength
;
315 /* allocate and set up buffers */
317 if ((inblockdata
= (unsigned char *) malloc(blocksize
)) == NULL
)
320 if ((outblockdata
= (unsigned char *) malloc(blocksize
)) == NULL
) {
325 inblock
.data
= (char *) inblockdata
;
326 inblock
.length
= blocksize
;
328 outblock
.data
= (char *) outblockdata
;
329 outblock
.length
= blocksize
;
331 /* initialize the input block */
333 if (in_constant
->length
== inblock
.length
) {
334 memcpy(inblock
.data
, in_constant
->data
, inblock
.length
);
336 krb5_nfold(in_constant
->length
*8, (unsigned char *) in_constant
->data
,
337 inblock
.length
*8, (unsigned char *) inblock
.data
);
340 /* loop encrypting the blocks until enough key bytes are generated */
343 while (n
< keybytes
) {
344 /* Solaris Kerberos */
345 (*(enc
->encrypt
))(context
, inkey
, 0, &inblock
, &outblock
);
347 if ((keybytes
- n
) <= outblock
.length
) {
348 memcpy(out
+n
, outblock
.data
, (keybytes
- n
));
352 memcpy(out
+n
, outblock
.data
, outblock
.length
);
353 memcpy(inblock
.data
, outblock
.data
, outblock
.length
);
354 n
+= outblock
.length
;
357 /* clean memory, free resources and exit */
359 memset(inblockdata
, 0, blocksize
);
360 memset(outblockdata
, 0, blocksize
);