1b528cefcSMark Murray /*
2ae771770SStanislav Sedov * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray * All rights reserved.
5b528cefcSMark Murray *
6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray * modification, are permitted provided that the following conditions
8b528cefcSMark Murray * are met:
9b528cefcSMark Murray *
10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray *
13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray * documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray *
17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray * may be used to endorse or promote products derived from this software
19b528cefcSMark Murray * without specific prior written permission.
20b528cefcSMark Murray *
21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray * SUCH DAMAGE.
32b528cefcSMark Murray */
33b528cefcSMark Murray
34b528cefcSMark Murray #include "krb5_locl.h"
35b528cefcSMark Murray
36ae771770SStanislav Sedov struct _krb5_key_usage {
37b528cefcSMark Murray unsigned usage;
38ae771770SStanislav Sedov struct _krb5_key_data key;
39b528cefcSMark Murray };
40b528cefcSMark Murray
41b528cefcSMark Murray
42ae771770SStanislav Sedov #ifndef HEIMDAL_SMALLER
43ae771770SStanislav Sedov #define DES3_OLD_ENCTYPE 1
44b528cefcSMark Murray #endif
45b528cefcSMark Murray
46b528cefcSMark Murray static krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
47ae771770SStanislav Sedov unsigned, struct _krb5_key_data**);
48ae771770SStanislav Sedov static struct _krb5_key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
49b528cefcSMark Murray
50ae771770SStanislav Sedov static void free_key_schedule(krb5_context,
51ae771770SStanislav Sedov struct _krb5_key_data *,
52ae771770SStanislav Sedov struct _krb5_encryption_type *);
5333f12199SDoug Rabson
5433f12199SDoug Rabson /*
55ae771770SStanislav Sedov * Converts etype to a user readable string and sets as a side effect
56ae771770SStanislav Sedov * the krb5_error_message containing this string. Returns
57ae771770SStanislav Sedov * KRB5_PROG_ETYPE_NOSUPP in not the conversion of the etype failed in
58ae771770SStanislav Sedov * which case the error code of the etype convesion is returned.
59b528cefcSMark Murray */
60b528cefcSMark Murray
61b528cefcSMark Murray static krb5_error_code
unsupported_enctype(krb5_context context,krb5_enctype etype)62ae771770SStanislav Sedov unsupported_enctype(krb5_context context, krb5_enctype etype)
63b528cefcSMark Murray {
64b528cefcSMark Murray krb5_error_code ret;
65ae771770SStanislav Sedov char *name;
66b528cefcSMark Murray
67ae771770SStanislav Sedov ret = krb5_enctype_to_string(context, etype, &name);
68b528cefcSMark Murray if (ret)
69b528cefcSMark Murray return ret;
70b528cefcSMark Murray
71ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
72ae771770SStanislav Sedov N_("Encryption type %s not supported", ""),
73ae771770SStanislav Sedov name);
74ae771770SStanislav Sedov free(name);
75b528cefcSMark Murray return KRB5_PROG_ETYPE_NOSUPP;
76c80b5a63SAssar Westerlund }
77b528cefcSMark Murray
7847085b17SAssar Westerlund /*
79ae771770SStanislav Sedov *
8047085b17SAssar Westerlund */
8147085b17SAssar Westerlund
82ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_enctype_keysize(krb5_context context,krb5_enctype type,size_t * keysize)832d485134SJacques Vidrine krb5_enctype_keysize(krb5_context context,
842d485134SJacques Vidrine krb5_enctype type,
852d485134SJacques Vidrine size_t *keysize)
862d485134SJacques Vidrine {
87ae771770SStanislav Sedov struct _krb5_encryption_type *et = _krb5_find_enctype(type);
882d485134SJacques Vidrine if(et == NULL) {
89ae771770SStanislav Sedov return unsupported_enctype (context, type);
902d485134SJacques Vidrine }
912d485134SJacques Vidrine *keysize = et->keytype->size;
922d485134SJacques Vidrine return 0;
932d485134SJacques Vidrine }
942d485134SJacques Vidrine
95ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_enctype_keybits(krb5_context context,krb5_enctype type,size_t * keybits)9633f12199SDoug Rabson krb5_enctype_keybits(krb5_context context,
9733f12199SDoug Rabson krb5_enctype type,
9833f12199SDoug Rabson size_t *keybits)
9933f12199SDoug Rabson {
100ae771770SStanislav Sedov struct _krb5_encryption_type *et = _krb5_find_enctype(type);
10133f12199SDoug Rabson if(et == NULL) {
102ae771770SStanislav Sedov return unsupported_enctype (context, type);
10333f12199SDoug Rabson }
10433f12199SDoug Rabson *keybits = et->keytype->bits;
10533f12199SDoug Rabson return 0;
10633f12199SDoug Rabson }
10733f12199SDoug Rabson
108ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_generate_random_keyblock(krb5_context context,krb5_enctype type,krb5_keyblock * key)109b528cefcSMark Murray krb5_generate_random_keyblock(krb5_context context,
110b528cefcSMark Murray krb5_enctype type,
111b528cefcSMark Murray krb5_keyblock *key)
112b528cefcSMark Murray {
113b528cefcSMark Murray krb5_error_code ret;
114ae771770SStanislav Sedov struct _krb5_encryption_type *et = _krb5_find_enctype(type);
115c80b5a63SAssar Westerlund if(et == NULL) {
116ae771770SStanislav Sedov return unsupported_enctype (context, type);
117c80b5a63SAssar Westerlund }
118b528cefcSMark Murray ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
119b528cefcSMark Murray if(ret)
120b528cefcSMark Murray return ret;
121b528cefcSMark Murray key->keytype = type;
122b528cefcSMark Murray if(et->keytype->random_key)
123b528cefcSMark Murray (*et->keytype->random_key)(context, key);
124b528cefcSMark Murray else
125b528cefcSMark Murray krb5_generate_random_block(key->keyvalue.data,
126b528cefcSMark Murray key->keyvalue.length);
127b528cefcSMark Murray return 0;
128b528cefcSMark Murray }
129b528cefcSMark Murray
130b528cefcSMark Murray static krb5_error_code
_key_schedule(krb5_context context,struct _krb5_key_data * key)131b528cefcSMark Murray _key_schedule(krb5_context context,
132ae771770SStanislav Sedov struct _krb5_key_data *key)
133b528cefcSMark Murray {
134b528cefcSMark Murray krb5_error_code ret;
135ae771770SStanislav Sedov struct _krb5_encryption_type *et = _krb5_find_enctype(key->key->keytype);
136ae771770SStanislav Sedov struct _krb5_key_type *kt;
137ae771770SStanislav Sedov
138ae771770SStanislav Sedov if (et == NULL) {
139ae771770SStanislav Sedov return unsupported_enctype (context,
140ae771770SStanislav Sedov key->key->keytype);
141ae771770SStanislav Sedov }
142ae771770SStanislav Sedov
143ae771770SStanislav Sedov kt = et->keytype;
144b528cefcSMark Murray
145b528cefcSMark Murray if(kt->schedule == NULL)
146b528cefcSMark Murray return 0;
14747085b17SAssar Westerlund if (key->schedule != NULL)
14847085b17SAssar Westerlund return 0;
149b528cefcSMark Murray ALLOC(key->schedule, 1);
150c80b5a63SAssar Westerlund if(key->schedule == NULL) {
151ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
152b528cefcSMark Murray return ENOMEM;
153c80b5a63SAssar Westerlund }
154b528cefcSMark Murray ret = krb5_data_alloc(key->schedule, kt->schedule_size);
155b528cefcSMark Murray if(ret) {
156b528cefcSMark Murray free(key->schedule);
157b528cefcSMark Murray key->schedule = NULL;
158b528cefcSMark Murray return ret;
159b528cefcSMark Murray }
160ae771770SStanislav Sedov (*kt->schedule)(context, kt, key);
161b528cefcSMark Murray return 0;
162b528cefcSMark Murray }
163b528cefcSMark Murray
164b528cefcSMark Murray /************************************************************
165b528cefcSMark Murray * *
166b528cefcSMark Murray ************************************************************/
167b528cefcSMark Murray
168b528cefcSMark Murray static krb5_error_code
SHA1_checksum(krb5_context context,struct _krb5_key_data * key,const void * data,size_t len,unsigned usage,Checksum * C)169b528cefcSMark Murray SHA1_checksum(krb5_context context,
170ae771770SStanislav Sedov struct _krb5_key_data *key,
17147085b17SAssar Westerlund const void *data,
172b528cefcSMark Murray size_t len,
17347085b17SAssar Westerlund unsigned usage,
174b528cefcSMark Murray Checksum *C)
175b528cefcSMark Murray {
176ae771770SStanislav Sedov if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_sha1(), NULL) != 1)
177ae771770SStanislav Sedov krb5_abortx(context, "sha1 checksum failed");
178ae771770SStanislav Sedov return 0;
179b528cefcSMark Murray }
180b528cefcSMark Murray
181b528cefcSMark Murray /* HMAC according to RFC2104 */
182ae771770SStanislav Sedov krb5_error_code
_krb5_internal_hmac(krb5_context context,struct _krb5_checksum_type * cm,const void * data,size_t len,unsigned usage,struct _krb5_key_data * keyblock,Checksum * result)183ae771770SStanislav Sedov _krb5_internal_hmac(krb5_context context,
184ae771770SStanislav Sedov struct _krb5_checksum_type *cm,
18547085b17SAssar Westerlund const void *data,
186b528cefcSMark Murray size_t len,
18747085b17SAssar Westerlund unsigned usage,
188ae771770SStanislav Sedov struct _krb5_key_data *keyblock,
189b528cefcSMark Murray Checksum *result)
190b528cefcSMark Murray {
191b528cefcSMark Murray unsigned char *ipad, *opad;
192b528cefcSMark Murray unsigned char *key;
193b528cefcSMark Murray size_t key_len;
194ae771770SStanislav Sedov size_t i;
195b528cefcSMark Murray
196a0c37ec3SJacques Vidrine ipad = malloc(cm->blocksize + len);
197a0c37ec3SJacques Vidrine if (ipad == NULL)
198a0c37ec3SJacques Vidrine return ENOMEM;
199a0c37ec3SJacques Vidrine opad = malloc(cm->blocksize + cm->checksumsize);
200a0c37ec3SJacques Vidrine if (opad == NULL) {
201a0c37ec3SJacques Vidrine free(ipad);
202a0c37ec3SJacques Vidrine return ENOMEM;
203a0c37ec3SJacques Vidrine }
204a0c37ec3SJacques Vidrine memset(ipad, 0x36, cm->blocksize);
205a0c37ec3SJacques Vidrine memset(opad, 0x5c, cm->blocksize);
206a0c37ec3SJacques Vidrine
207b528cefcSMark Murray if(keyblock->key->keyvalue.length > cm->blocksize){
208b528cefcSMark Murray (*cm->checksum)(context,
209b528cefcSMark Murray keyblock,
210b528cefcSMark Murray keyblock->key->keyvalue.data,
211b528cefcSMark Murray keyblock->key->keyvalue.length,
21247085b17SAssar Westerlund usage,
213b528cefcSMark Murray result);
214b528cefcSMark Murray key = result->checksum.data;
215b528cefcSMark Murray key_len = result->checksum.length;
216b528cefcSMark Murray } else {
217b528cefcSMark Murray key = keyblock->key->keyvalue.data;
218b528cefcSMark Murray key_len = keyblock->key->keyvalue.length;
219b528cefcSMark Murray }
220b528cefcSMark Murray for(i = 0; i < key_len; i++){
221b528cefcSMark Murray ipad[i] ^= key[i];
222b528cefcSMark Murray opad[i] ^= key[i];
223b528cefcSMark Murray }
224b528cefcSMark Murray memcpy(ipad + cm->blocksize, data, len);
22547085b17SAssar Westerlund (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len,
22647085b17SAssar Westerlund usage, result);
227b528cefcSMark Murray memcpy(opad + cm->blocksize, result->checksum.data,
228b528cefcSMark Murray result->checksum.length);
229b528cefcSMark Murray (*cm->checksum)(context, keyblock, opad,
23047085b17SAssar Westerlund cm->blocksize + cm->checksumsize, usage, result);
231b528cefcSMark Murray memset(ipad, 0, cm->blocksize + len);
232b528cefcSMark Murray free(ipad);
233b528cefcSMark Murray memset(opad, 0, cm->blocksize + cm->checksumsize);
234b528cefcSMark Murray free(opad);
235a0c37ec3SJacques Vidrine
236a0c37ec3SJacques Vidrine return 0;
237a0c37ec3SJacques Vidrine }
238a0c37ec3SJacques Vidrine
239ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_hmac(krb5_context context,krb5_cksumtype cktype,const void * data,size_t len,unsigned usage,krb5_keyblock * key,Checksum * result)240a0c37ec3SJacques Vidrine krb5_hmac(krb5_context context,
241a0c37ec3SJacques Vidrine krb5_cksumtype cktype,
242a0c37ec3SJacques Vidrine const void *data,
243a0c37ec3SJacques Vidrine size_t len,
244a0c37ec3SJacques Vidrine unsigned usage,
245a0c37ec3SJacques Vidrine krb5_keyblock *key,
246a0c37ec3SJacques Vidrine Checksum *result)
247a0c37ec3SJacques Vidrine {
248ae771770SStanislav Sedov struct _krb5_checksum_type *c = _krb5_find_checksum(cktype);
249ae771770SStanislav Sedov struct _krb5_key_data kd;
250a0c37ec3SJacques Vidrine krb5_error_code ret;
251a0c37ec3SJacques Vidrine
252a0c37ec3SJacques Vidrine if (c == NULL) {
253ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
254ae771770SStanislav Sedov N_("checksum type %d not supported", ""),
255a0c37ec3SJacques Vidrine cktype);
256a0c37ec3SJacques Vidrine return KRB5_PROG_SUMTYPE_NOSUPP;
257a0c37ec3SJacques Vidrine }
258a0c37ec3SJacques Vidrine
259a0c37ec3SJacques Vidrine kd.key = key;
260a0c37ec3SJacques Vidrine kd.schedule = NULL;
261a0c37ec3SJacques Vidrine
262ae771770SStanislav Sedov ret = _krb5_internal_hmac(context, c, data, len, usage, &kd, result);
263a0c37ec3SJacques Vidrine
264a0c37ec3SJacques Vidrine if (kd.schedule)
265a0c37ec3SJacques Vidrine krb5_free_data(context, kd.schedule);
266a0c37ec3SJacques Vidrine
267a0c37ec3SJacques Vidrine return ret;
268b528cefcSMark Murray }
269b528cefcSMark Murray
270ae771770SStanislav Sedov krb5_error_code
_krb5_SP_HMAC_SHA1_checksum(krb5_context context,struct _krb5_key_data * key,const void * data,size_t len,unsigned usage,Checksum * result)271ae771770SStanislav Sedov _krb5_SP_HMAC_SHA1_checksum(krb5_context context,
272ae771770SStanislav Sedov struct _krb5_key_data *key,
27347085b17SAssar Westerlund const void *data,
274b528cefcSMark Murray size_t len,
27547085b17SAssar Westerlund unsigned usage,
276b528cefcSMark Murray Checksum *result)
277b528cefcSMark Murray {
278ae771770SStanislav Sedov struct _krb5_checksum_type *c = _krb5_find_checksum(CKSUMTYPE_SHA1);
2792d485134SJacques Vidrine Checksum res;
2802d485134SJacques Vidrine char sha1_data[20];
281a0c37ec3SJacques Vidrine krb5_error_code ret;
282b528cefcSMark Murray
2832d485134SJacques Vidrine res.checksum.data = sha1_data;
2842d485134SJacques Vidrine res.checksum.length = sizeof(sha1_data);
2852d485134SJacques Vidrine
286ae771770SStanislav Sedov ret = _krb5_internal_hmac(context, c, data, len, usage, key, &res);
287a0c37ec3SJacques Vidrine if (ret)
288a0c37ec3SJacques Vidrine krb5_abortx(context, "hmac failed");
2892d485134SJacques Vidrine memcpy(result->checksum.data, res.checksum.data, result->checksum.length);
290ae771770SStanislav Sedov return 0;
29147085b17SAssar Westerlund }
29247085b17SAssar Westerlund
293ae771770SStanislav Sedov struct _krb5_checksum_type _krb5_checksum_sha1 = {
294b528cefcSMark Murray CKSUMTYPE_SHA1,
295b528cefcSMark Murray "sha1",
296b528cefcSMark Murray 64,
297b528cefcSMark Murray 20,
298b528cefcSMark Murray F_CPROOF,
299b528cefcSMark Murray SHA1_checksum,
300b528cefcSMark Murray NULL
301b528cefcSMark Murray };
302b528cefcSMark Murray
303ae771770SStanislav Sedov struct _krb5_checksum_type *
_krb5_find_checksum(krb5_cksumtype type)304ae771770SStanislav Sedov _krb5_find_checksum(krb5_cksumtype type)
305b528cefcSMark Murray {
306b528cefcSMark Murray int i;
307ae771770SStanislav Sedov for(i = 0; i < _krb5_num_checksums; i++)
308ae771770SStanislav Sedov if(_krb5_checksum_types[i]->type == type)
309ae771770SStanislav Sedov return _krb5_checksum_types[i];
310b528cefcSMark Murray return NULL;
311b528cefcSMark Murray }
312b528cefcSMark Murray
313b528cefcSMark Murray static krb5_error_code
get_checksum_key(krb5_context context,krb5_crypto crypto,unsigned usage,struct _krb5_checksum_type * ct,struct _krb5_key_data ** key)314b528cefcSMark Murray get_checksum_key(krb5_context context,
315b528cefcSMark Murray krb5_crypto crypto,
316b528cefcSMark Murray unsigned usage, /* not krb5_key_usage */
317ae771770SStanislav Sedov struct _krb5_checksum_type *ct,
318ae771770SStanislav Sedov struct _krb5_key_data **key)
319b528cefcSMark Murray {
320b528cefcSMark Murray krb5_error_code ret = 0;
321b528cefcSMark Murray
322b528cefcSMark Murray if(ct->flags & F_DERIVED)
323b528cefcSMark Murray ret = _get_derived_key(context, crypto, usage, key);
324b528cefcSMark Murray else if(ct->flags & F_VARIANT) {
325ae771770SStanislav Sedov size_t i;
326b528cefcSMark Murray
327b528cefcSMark Murray *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
328c80b5a63SAssar Westerlund if(*key == NULL) {
329ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
330b528cefcSMark Murray return ENOMEM;
331c80b5a63SAssar Westerlund }
332b528cefcSMark Murray ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
333b528cefcSMark Murray if(ret)
334b528cefcSMark Murray return ret;
335b528cefcSMark Murray for(i = 0; i < (*key)->key->keyvalue.length; i++)
336b528cefcSMark Murray ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
337b528cefcSMark Murray } else {
338b528cefcSMark Murray *key = &crypto->key;
339b528cefcSMark Murray }
340b528cefcSMark Murray if(ret == 0)
341b528cefcSMark Murray ret = _key_schedule(context, *key);
342b528cefcSMark Murray return ret;
343b528cefcSMark Murray }
344b528cefcSMark Murray
345b528cefcSMark Murray static krb5_error_code
create_checksum(krb5_context context,struct _krb5_checksum_type * ct,krb5_crypto crypto,unsigned usage,void * data,size_t len,Checksum * result)346a0c37ec3SJacques Vidrine create_checksum (krb5_context context,
347ae771770SStanislav Sedov struct _krb5_checksum_type *ct,
348b528cefcSMark Murray krb5_crypto crypto,
349b528cefcSMark Murray unsigned usage,
350b528cefcSMark Murray void *data,
351b528cefcSMark Murray size_t len,
352b528cefcSMark Murray Checksum *result)
353b528cefcSMark Murray {
354b528cefcSMark Murray krb5_error_code ret;
355ae771770SStanislav Sedov struct _krb5_key_data *dkey;
356b528cefcSMark Murray int keyed_checksum;
357b528cefcSMark Murray
35833f12199SDoug Rabson if (ct->flags & F_DISABLED) {
359ae771770SStanislav Sedov krb5_clear_error_message (context);
36033f12199SDoug Rabson return KRB5_PROG_SUMTYPE_NOSUPP;
36133f12199SDoug Rabson }
362b528cefcSMark Murray keyed_checksum = (ct->flags & F_KEYED) != 0;
363c80b5a63SAssar Westerlund if(keyed_checksum && crypto == NULL) {
364ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
365ae771770SStanislav Sedov N_("Checksum type %s is keyed but no "
366ae771770SStanislav Sedov "crypto context (key) was passed in", ""),
36733f12199SDoug Rabson ct->name);
368b528cefcSMark Murray return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
369c80b5a63SAssar Westerlund }
37047085b17SAssar Westerlund if(keyed_checksum) {
371b528cefcSMark Murray ret = get_checksum_key(context, crypto, usage, ct, &dkey);
37247085b17SAssar Westerlund if (ret)
37347085b17SAssar Westerlund return ret;
37447085b17SAssar Westerlund } else
375b528cefcSMark Murray dkey = NULL;
376b528cefcSMark Murray result->cksumtype = ct->type;
37733f12199SDoug Rabson ret = krb5_data_alloc(&result->checksum, ct->checksumsize);
37833f12199SDoug Rabson if (ret)
37933f12199SDoug Rabson return (ret);
380ae771770SStanislav Sedov return (*ct->checksum)(context, dkey, data, len, usage, result);
381b528cefcSMark Murray }
382b528cefcSMark Murray
383a0c37ec3SJacques Vidrine static int
arcfour_checksum_p(struct _krb5_checksum_type * ct,krb5_crypto crypto)384ae771770SStanislav Sedov arcfour_checksum_p(struct _krb5_checksum_type *ct, krb5_crypto crypto)
385a0c37ec3SJacques Vidrine {
386a0c37ec3SJacques Vidrine return (ct->type == CKSUMTYPE_HMAC_MD5) &&
387a0c37ec3SJacques Vidrine (crypto->key.key->keytype == KEYTYPE_ARCFOUR);
388a0c37ec3SJacques Vidrine }
389a0c37ec3SJacques Vidrine
390ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_create_checksum(krb5_context context,krb5_crypto crypto,krb5_key_usage usage,int type,void * data,size_t len,Checksum * result)391a0c37ec3SJacques Vidrine krb5_create_checksum(krb5_context context,
392b528cefcSMark Murray krb5_crypto crypto,
393a0c37ec3SJacques Vidrine krb5_key_usage usage,
394a0c37ec3SJacques Vidrine int type,
395b528cefcSMark Murray void *data,
396b528cefcSMark Murray size_t len,
397b528cefcSMark Murray Checksum *result)
398b528cefcSMark Murray {
399ae771770SStanislav Sedov struct _krb5_checksum_type *ct = NULL;
400a0c37ec3SJacques Vidrine unsigned keyusage;
401b528cefcSMark Murray
402a0c37ec3SJacques Vidrine /* type 0 -> pick from crypto */
403c80b5a63SAssar Westerlund if (type) {
404ae771770SStanislav Sedov ct = _krb5_find_checksum(type);
405c80b5a63SAssar Westerlund } else if (crypto) {
406b528cefcSMark Murray ct = crypto->et->keyed_checksum;
407b528cefcSMark Murray if (ct == NULL)
408c80b5a63SAssar Westerlund ct = crypto->et->checksum;
409c80b5a63SAssar Westerlund }
410c80b5a63SAssar Westerlund
411c80b5a63SAssar Westerlund if(ct == NULL) {
412ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
413ae771770SStanislav Sedov N_("checksum type %d not supported", ""),
414c80b5a63SAssar Westerlund type);
415b528cefcSMark Murray return KRB5_PROG_SUMTYPE_NOSUPP;
416c80b5a63SAssar Westerlund }
417b528cefcSMark Murray
418a0c37ec3SJacques Vidrine if (arcfour_checksum_p(ct, crypto)) {
419a0c37ec3SJacques Vidrine keyusage = usage;
420ae771770SStanislav Sedov _krb5_usage2arcfour(context, &keyusage);
421a0c37ec3SJacques Vidrine } else
422a0c37ec3SJacques Vidrine keyusage = CHECKSUM_USAGE(usage);
423a0c37ec3SJacques Vidrine
424a0c37ec3SJacques Vidrine return create_checksum(context, ct, crypto, keyusage,
425a0c37ec3SJacques Vidrine data, len, result);
426b528cefcSMark Murray }
427b528cefcSMark Murray
428b528cefcSMark Murray static krb5_error_code
verify_checksum(krb5_context context,krb5_crypto crypto,unsigned usage,void * data,size_t len,Checksum * cksum)429b528cefcSMark Murray verify_checksum(krb5_context context,
430b528cefcSMark Murray krb5_crypto crypto,
431b528cefcSMark Murray unsigned usage, /* not krb5_key_usage */
432b528cefcSMark Murray void *data,
433b528cefcSMark Murray size_t len,
434b528cefcSMark Murray Checksum *cksum)
435b528cefcSMark Murray {
436b528cefcSMark Murray krb5_error_code ret;
437ae771770SStanislav Sedov struct _krb5_key_data *dkey;
438b528cefcSMark Murray int keyed_checksum;
439b528cefcSMark Murray Checksum c;
440ae771770SStanislav Sedov struct _krb5_checksum_type *ct;
441b528cefcSMark Murray
442ae771770SStanislav Sedov ct = _krb5_find_checksum(cksum->cksumtype);
44333f12199SDoug Rabson if (ct == NULL || (ct->flags & F_DISABLED)) {
444ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
445ae771770SStanislav Sedov N_("checksum type %d not supported", ""),
446c80b5a63SAssar Westerlund cksum->cksumtype);
447b528cefcSMark Murray return KRB5_PROG_SUMTYPE_NOSUPP;
448c80b5a63SAssar Westerlund }
449c80b5a63SAssar Westerlund if(ct->checksumsize != cksum->checksum.length) {
450ae771770SStanislav Sedov krb5_clear_error_message (context);
451ae771770SStanislav Sedov krb5_set_error_message(context, KRB5KRB_AP_ERR_BAD_INTEGRITY,
452ae771770SStanislav Sedov N_("Decrypt integrity check failed for checksum type %s, "
453ae771770SStanislav Sedov "length was %u, expected %u", ""),
454ae771770SStanislav Sedov ct->name, (unsigned)cksum->checksum.length,
455ae771770SStanislav Sedov (unsigned)ct->checksumsize);
456ae771770SStanislav Sedov
457b528cefcSMark Murray return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
458c80b5a63SAssar Westerlund }
459b528cefcSMark Murray keyed_checksum = (ct->flags & F_KEYED) != 0;
460ae771770SStanislav Sedov if(keyed_checksum) {
461ae771770SStanislav Sedov struct _krb5_checksum_type *kct;
462ae771770SStanislav Sedov if (crypto == NULL) {
463ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_PROG_SUMTYPE_NOSUPP,
464ae771770SStanislav Sedov N_("Checksum type %s is keyed but no "
465ae771770SStanislav Sedov "crypto context (key) was passed in", ""),
46633f12199SDoug Rabson ct->name);
467b528cefcSMark Murray return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
468c80b5a63SAssar Westerlund }
469ae771770SStanislav Sedov kct = crypto->et->keyed_checksum;
470cf771f22SStanislav Sedov if (kct == NULL || kct->type != ct->type) {
471ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_PROG_SUMTYPE_NOSUPP,
472ae771770SStanislav Sedov N_("Checksum type %s is keyed, but "
473ae771770SStanislav Sedov "the key type %s passed didnt have that checksum "
474ae771770SStanislav Sedov "type as the keyed type", ""),
475ae771770SStanislav Sedov ct->name, crypto->et->name);
476ae771770SStanislav Sedov return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
477ae771770SStanislav Sedov }
478ae771770SStanislav Sedov
479b528cefcSMark Murray ret = get_checksum_key(context, crypto, usage, ct, &dkey);
480ae771770SStanislav Sedov if (ret)
481ae771770SStanislav Sedov return ret;
482ae771770SStanislav Sedov } else
483b528cefcSMark Murray dkey = NULL;
484ae771770SStanislav Sedov
485ae771770SStanislav Sedov /*
486ae771770SStanislav Sedov * If checksum have a verify function, lets use that instead of
487ae771770SStanislav Sedov * calling ->checksum and then compare result.
488ae771770SStanislav Sedov */
489ae771770SStanislav Sedov
490ae771770SStanislav Sedov if(ct->verify) {
491ae771770SStanislav Sedov ret = (*ct->verify)(context, dkey, data, len, usage, cksum);
492ae771770SStanislav Sedov if (ret)
493ae771770SStanislav Sedov krb5_set_error_message(context, ret,
494ae771770SStanislav Sedov N_("Decrypt integrity check failed for checksum "
495ae771770SStanislav Sedov "type %s, key type %s", ""),
496ae771770SStanislav Sedov ct->name, (crypto != NULL)? crypto->et->name : "(none)");
497ae771770SStanislav Sedov return ret;
498ae771770SStanislav Sedov }
499b528cefcSMark Murray
500b528cefcSMark Murray ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
501b528cefcSMark Murray if (ret)
502b528cefcSMark Murray return ret;
503b528cefcSMark Murray
504ae771770SStanislav Sedov ret = (*ct->checksum)(context, dkey, data, len, usage, &c);
505ae771770SStanislav Sedov if (ret) {
506ae771770SStanislav Sedov krb5_data_free(&c.checksum);
507ae771770SStanislav Sedov return ret;
508ae771770SStanislav Sedov }
509b528cefcSMark Murray
510ae771770SStanislav Sedov if(krb5_data_ct_cmp(&c.checksum, &cksum->checksum) != 0) {
511b528cefcSMark Murray ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
512ae771770SStanislav Sedov krb5_set_error_message(context, ret,
513ae771770SStanislav Sedov N_("Decrypt integrity check failed for checksum "
514ae771770SStanislav Sedov "type %s, key type %s", ""),
515ae771770SStanislav Sedov ct->name, crypto ? crypto->et->name : "(unkeyed)");
516c80b5a63SAssar Westerlund } else {
517b528cefcSMark Murray ret = 0;
518c80b5a63SAssar Westerlund }
519b528cefcSMark Murray krb5_data_free (&c.checksum);
520b528cefcSMark Murray return ret;
521b528cefcSMark Murray }
522b528cefcSMark Murray
523ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_verify_checksum(krb5_context context,krb5_crypto crypto,krb5_key_usage usage,void * data,size_t len,Checksum * cksum)524b528cefcSMark Murray krb5_verify_checksum(krb5_context context,
525b528cefcSMark Murray krb5_crypto crypto,
526b528cefcSMark Murray krb5_key_usage usage,
527b528cefcSMark Murray void *data,
528b528cefcSMark Murray size_t len,
529b528cefcSMark Murray Checksum *cksum)
530b528cefcSMark Murray {
531ae771770SStanislav Sedov struct _krb5_checksum_type *ct;
532a0c37ec3SJacques Vidrine unsigned keyusage;
533a0c37ec3SJacques Vidrine
534ae771770SStanislav Sedov ct = _krb5_find_checksum(cksum->cksumtype);
535a0c37ec3SJacques Vidrine if(ct == NULL) {
536ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
537ae771770SStanislav Sedov N_("checksum type %d not supported", ""),
538a0c37ec3SJacques Vidrine cksum->cksumtype);
539a0c37ec3SJacques Vidrine return KRB5_PROG_SUMTYPE_NOSUPP;
540a0c37ec3SJacques Vidrine }
541a0c37ec3SJacques Vidrine
542a0c37ec3SJacques Vidrine if (arcfour_checksum_p(ct, crypto)) {
543a0c37ec3SJacques Vidrine keyusage = usage;
544ae771770SStanislav Sedov _krb5_usage2arcfour(context, &keyusage);
545a0c37ec3SJacques Vidrine } else
546a0c37ec3SJacques Vidrine keyusage = CHECKSUM_USAGE(usage);
547a0c37ec3SJacques Vidrine
548a0c37ec3SJacques Vidrine return verify_checksum(context, crypto, keyusage,
549a0c37ec3SJacques Vidrine data, len, cksum);
550b528cefcSMark Murray }
551b528cefcSMark Murray
552ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_get_checksum_type(krb5_context context,krb5_crypto crypto,krb5_cksumtype * type)55333f12199SDoug Rabson krb5_crypto_get_checksum_type(krb5_context context,
55433f12199SDoug Rabson krb5_crypto crypto,
55533f12199SDoug Rabson krb5_cksumtype *type)
55633f12199SDoug Rabson {
557ae771770SStanislav Sedov struct _krb5_checksum_type *ct = NULL;
55833f12199SDoug Rabson
55933f12199SDoug Rabson if (crypto != NULL) {
56033f12199SDoug Rabson ct = crypto->et->keyed_checksum;
56133f12199SDoug Rabson if (ct == NULL)
56233f12199SDoug Rabson ct = crypto->et->checksum;
56333f12199SDoug Rabson }
56433f12199SDoug Rabson
56533f12199SDoug Rabson if (ct == NULL) {
566ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
567ae771770SStanislav Sedov N_("checksum type not found", ""));
56833f12199SDoug Rabson return KRB5_PROG_SUMTYPE_NOSUPP;
56933f12199SDoug Rabson }
57033f12199SDoug Rabson
57133f12199SDoug Rabson *type = ct->type;
57233f12199SDoug Rabson
57333f12199SDoug Rabson return 0;
57433f12199SDoug Rabson }
57533f12199SDoug Rabson
57633f12199SDoug Rabson
577ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_checksumsize(krb5_context context,krb5_cksumtype type,size_t * size)578b528cefcSMark Murray krb5_checksumsize(krb5_context context,
579b528cefcSMark Murray krb5_cksumtype type,
580b528cefcSMark Murray size_t *size)
581b528cefcSMark Murray {
582ae771770SStanislav Sedov struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
583c80b5a63SAssar Westerlund if(ct == NULL) {
584ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
585ae771770SStanislav Sedov N_("checksum type %d not supported", ""),
586c80b5a63SAssar Westerlund type);
587b528cefcSMark Murray return KRB5_PROG_SUMTYPE_NOSUPP;
588c80b5a63SAssar Westerlund }
589b528cefcSMark Murray *size = ct->checksumsize;
590b528cefcSMark Murray return 0;
591b528cefcSMark Murray }
592b528cefcSMark Murray
593ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_checksum_is_keyed(krb5_context context,krb5_cksumtype type)594b528cefcSMark Murray krb5_checksum_is_keyed(krb5_context context,
595b528cefcSMark Murray krb5_cksumtype type)
596b528cefcSMark Murray {
597ae771770SStanislav Sedov struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
598c80b5a63SAssar Westerlund if(ct == NULL) {
59933f12199SDoug Rabson if (context)
600ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
601ae771770SStanislav Sedov N_("checksum type %d not supported", ""),
602c80b5a63SAssar Westerlund type);
603b528cefcSMark Murray return KRB5_PROG_SUMTYPE_NOSUPP;
604c80b5a63SAssar Westerlund }
605b528cefcSMark Murray return ct->flags & F_KEYED;
606b528cefcSMark Murray }
607b528cefcSMark Murray
608ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_checksum_is_collision_proof(krb5_context context,krb5_cksumtype type)609b528cefcSMark Murray krb5_checksum_is_collision_proof(krb5_context context,
610b528cefcSMark Murray krb5_cksumtype type)
611b528cefcSMark Murray {
612ae771770SStanislav Sedov struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
613c80b5a63SAssar Westerlund if(ct == NULL) {
61433f12199SDoug Rabson if (context)
615ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
616ae771770SStanislav Sedov N_("checksum type %d not supported", ""),
617c80b5a63SAssar Westerlund type);
618b528cefcSMark Murray return KRB5_PROG_SUMTYPE_NOSUPP;
619c80b5a63SAssar Westerlund }
620b528cefcSMark Murray return ct->flags & F_CPROOF;
621b528cefcSMark Murray }
622b528cefcSMark Murray
623ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_checksum_disable(krb5_context context,krb5_cksumtype type)62433f12199SDoug Rabson krb5_checksum_disable(krb5_context context,
62533f12199SDoug Rabson krb5_cksumtype type)
62633f12199SDoug Rabson {
627ae771770SStanislav Sedov struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
62833f12199SDoug Rabson if(ct == NULL) {
62933f12199SDoug Rabson if (context)
630ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
631ae771770SStanislav Sedov N_("checksum type %d not supported", ""),
63233f12199SDoug Rabson type);
63333f12199SDoug Rabson return KRB5_PROG_SUMTYPE_NOSUPP;
63433f12199SDoug Rabson }
63533f12199SDoug Rabson ct->flags |= F_DISABLED;
63633f12199SDoug Rabson return 0;
63733f12199SDoug Rabson }
63833f12199SDoug Rabson
639b528cefcSMark Murray /************************************************************
640b528cefcSMark Murray * *
641b528cefcSMark Murray ************************************************************/
642b528cefcSMark Murray
643ae771770SStanislav Sedov struct _krb5_encryption_type *
_krb5_find_enctype(krb5_enctype type)644ae771770SStanislav Sedov _krb5_find_enctype(krb5_enctype type)
645b528cefcSMark Murray {
646b528cefcSMark Murray int i;
647ae771770SStanislav Sedov for(i = 0; i < _krb5_num_etypes; i++)
648ae771770SStanislav Sedov if(_krb5_etypes[i]->type == type)
649ae771770SStanislav Sedov return _krb5_etypes[i];
650b528cefcSMark Murray return NULL;
651b528cefcSMark Murray }
652b528cefcSMark Murray
653b528cefcSMark Murray
654ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_enctype_to_string(krb5_context context,krb5_enctype etype,char ** string)655b528cefcSMark Murray krb5_enctype_to_string(krb5_context context,
656b528cefcSMark Murray krb5_enctype etype,
657b528cefcSMark Murray char **string)
658b528cefcSMark Murray {
659ae771770SStanislav Sedov struct _krb5_encryption_type *e;
660ae771770SStanislav Sedov e = _krb5_find_enctype(etype);
661c80b5a63SAssar Westerlund if(e == NULL) {
662ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
663ae771770SStanislav Sedov N_("encryption type %d not supported", ""),
664c80b5a63SAssar Westerlund etype);
66533f12199SDoug Rabson *string = NULL;
666b528cefcSMark Murray return KRB5_PROG_ETYPE_NOSUPP;
667c80b5a63SAssar Westerlund }
668b528cefcSMark Murray *string = strdup(e->name);
669c80b5a63SAssar Westerlund if(*string == NULL) {
670ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
671b528cefcSMark Murray return ENOMEM;
672c80b5a63SAssar Westerlund }
673b528cefcSMark Murray return 0;
674b528cefcSMark Murray }
675b528cefcSMark Murray
676ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_string_to_enctype(krb5_context context,const char * string,krb5_enctype * etype)677b528cefcSMark Murray krb5_string_to_enctype(krb5_context context,
678b528cefcSMark Murray const char *string,
679b528cefcSMark Murray krb5_enctype *etype)
680b528cefcSMark Murray {
681b528cefcSMark Murray int i;
682ae771770SStanislav Sedov for(i = 0; i < _krb5_num_etypes; i++)
683ae771770SStanislav Sedov if(strcasecmp(_krb5_etypes[i]->name, string) == 0){
684ae771770SStanislav Sedov *etype = _krb5_etypes[i]->type;
685b528cefcSMark Murray return 0;
686b528cefcSMark Murray }
687ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
688ae771770SStanislav Sedov N_("encryption type %s not supported", ""),
689c80b5a63SAssar Westerlund string);
690b528cefcSMark Murray return KRB5_PROG_ETYPE_NOSUPP;
691b528cefcSMark Murray }
692b528cefcSMark Murray
693ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_enctype_to_keytype(krb5_context context,krb5_enctype etype,krb5_keytype * keytype)694b528cefcSMark Murray krb5_enctype_to_keytype(krb5_context context,
695b528cefcSMark Murray krb5_enctype etype,
696b528cefcSMark Murray krb5_keytype *keytype)
697b528cefcSMark Murray {
698ae771770SStanislav Sedov struct _krb5_encryption_type *e = _krb5_find_enctype(etype);
699c80b5a63SAssar Westerlund if(e == NULL) {
700ae771770SStanislav Sedov return unsupported_enctype (context, etype);
701c80b5a63SAssar Westerlund }
702b528cefcSMark Murray *keytype = e->keytype->type; /* XXX */
703b528cefcSMark Murray return 0;
704b528cefcSMark Murray }
705b528cefcSMark Murray
706ae771770SStanislav Sedov /**
707ae771770SStanislav Sedov * Check if a enctype is valid, return 0 if it is.
708ae771770SStanislav Sedov *
709ae771770SStanislav Sedov * @param context Kerberos context
710ae771770SStanislav Sedov * @param etype enctype to check if its valid or not
711ae771770SStanislav Sedov *
712ae771770SStanislav Sedov * @return Return an error code for an failure or 0 on success (enctype valid).
713ae771770SStanislav Sedov * @ingroup krb5_crypto
714b528cefcSMark Murray */
715b528cefcSMark Murray
716ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_enctype_valid(krb5_context context,krb5_enctype etype)717b528cefcSMark Murray krb5_enctype_valid(krb5_context context,
718b528cefcSMark Murray krb5_enctype etype)
719b528cefcSMark Murray {
720ae771770SStanislav Sedov struct _krb5_encryption_type *e = _krb5_find_enctype(etype);
721ae771770SStanislav Sedov if(e && (e->flags & F_DISABLED) == 0)
722ae771770SStanislav Sedov return 0;
723ae771770SStanislav Sedov if (context == NULL)
72433f12199SDoug Rabson return KRB5_PROG_ETYPE_NOSUPP;
725ae771770SStanislav Sedov if(e == NULL) {
726ae771770SStanislav Sedov return unsupported_enctype (context, etype);
72733f12199SDoug Rabson }
728ae771770SStanislav Sedov /* Must be (e->flags & F_DISABLED) */
729ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
730ae771770SStanislav Sedov N_("encryption type %s is disabled", ""),
73133f12199SDoug Rabson e->name);
73233f12199SDoug Rabson return KRB5_PROG_ETYPE_NOSUPP;
73333f12199SDoug Rabson }
734ae771770SStanislav Sedov
735ae771770SStanislav Sedov /**
736ae771770SStanislav Sedov * Return the coresponding encryption type for a checksum type.
737ae771770SStanislav Sedov *
738ae771770SStanislav Sedov * @param context Kerberos context
739ae771770SStanislav Sedov * @param ctype The checksum type to get the result enctype for
740ae771770SStanislav Sedov * @param etype The returned encryption, when the matching etype is
741ae771770SStanislav Sedov * not found, etype is set to ETYPE_NULL.
742ae771770SStanislav Sedov *
743ae771770SStanislav Sedov * @return Return an error code for an failure or 0 on success.
744ae771770SStanislav Sedov * @ingroup krb5_crypto
745ae771770SStanislav Sedov */
746ae771770SStanislav Sedov
747ae771770SStanislav Sedov
748ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_cksumtype_to_enctype(krb5_context context,krb5_cksumtype ctype,krb5_enctype * etype)749ae771770SStanislav Sedov krb5_cksumtype_to_enctype(krb5_context context,
750ae771770SStanislav Sedov krb5_cksumtype ctype,
751ae771770SStanislav Sedov krb5_enctype *etype)
752ae771770SStanislav Sedov {
753ae771770SStanislav Sedov int i;
754ae771770SStanislav Sedov
755ae771770SStanislav Sedov *etype = ETYPE_NULL;
756ae771770SStanislav Sedov
757ae771770SStanislav Sedov for(i = 0; i < _krb5_num_etypes; i++) {
758ae771770SStanislav Sedov if(_krb5_etypes[i]->keyed_checksum &&
759ae771770SStanislav Sedov _krb5_etypes[i]->keyed_checksum->type == ctype)
760ae771770SStanislav Sedov {
761ae771770SStanislav Sedov *etype = _krb5_etypes[i]->type;
76233f12199SDoug Rabson return 0;
763b528cefcSMark Murray }
764ae771770SStanislav Sedov }
765b528cefcSMark Murray
766ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
767ae771770SStanislav Sedov N_("checksum type %d not supported", ""),
768ae771770SStanislav Sedov (int)ctype);
769ae771770SStanislav Sedov return KRB5_PROG_SUMTYPE_NOSUPP;
770ae771770SStanislav Sedov }
771ae771770SStanislav Sedov
772ae771770SStanislav Sedov
773ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_cksumtype_valid(krb5_context context,krb5_cksumtype ctype)77433f12199SDoug Rabson krb5_cksumtype_valid(krb5_context context,
77533f12199SDoug Rabson krb5_cksumtype ctype)
77633f12199SDoug Rabson {
777ae771770SStanislav Sedov struct _krb5_checksum_type *c = _krb5_find_checksum(ctype);
77833f12199SDoug Rabson if (c == NULL) {
779ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
780ae771770SStanislav Sedov N_("checksum type %d not supported", ""),
78133f12199SDoug Rabson ctype);
78233f12199SDoug Rabson return KRB5_PROG_SUMTYPE_NOSUPP;
78333f12199SDoug Rabson }
78433f12199SDoug Rabson if (c->flags & F_DISABLED) {
785ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
786ae771770SStanislav Sedov N_("checksum type %s is disabled", ""),
78733f12199SDoug Rabson c->name);
78833f12199SDoug Rabson return KRB5_PROG_SUMTYPE_NOSUPP;
78933f12199SDoug Rabson }
79033f12199SDoug Rabson return 0;
79133f12199SDoug Rabson }
79233f12199SDoug Rabson
79333f12199SDoug Rabson
794b528cefcSMark Murray static krb5_boolean
derived_crypto(krb5_context context,krb5_crypto crypto)795b528cefcSMark Murray derived_crypto(krb5_context context,
796b528cefcSMark Murray krb5_crypto crypto)
797b528cefcSMark Murray {
798b528cefcSMark Murray return (crypto->et->flags & F_DERIVED) != 0;
799b528cefcSMark Murray }
800b528cefcSMark Murray
80147085b17SAssar Westerlund static krb5_boolean
special_crypto(krb5_context context,krb5_crypto crypto)80247085b17SAssar Westerlund special_crypto(krb5_context context,
80347085b17SAssar Westerlund krb5_crypto crypto)
80447085b17SAssar Westerlund {
80547085b17SAssar Westerlund return (crypto->et->flags & F_SPECIAL) != 0;
80647085b17SAssar Westerlund }
807b528cefcSMark Murray
808b528cefcSMark Murray #define CHECKSUMSIZE(C) ((C)->checksumsize)
809b528cefcSMark Murray #define CHECKSUMTYPE(C) ((C)->type)
810b528cefcSMark Murray
811b528cefcSMark Murray static krb5_error_code
encrypt_internal_derived(krb5_context context,krb5_crypto crypto,unsigned usage,const void * data,size_t len,krb5_data * result,void * ivec)812b528cefcSMark Murray encrypt_internal_derived(krb5_context context,
813b528cefcSMark Murray krb5_crypto crypto,
814b528cefcSMark Murray unsigned usage,
81533f12199SDoug Rabson const void *data,
816b528cefcSMark Murray size_t len,
81747085b17SAssar Westerlund krb5_data *result,
81847085b17SAssar Westerlund void *ivec)
819b528cefcSMark Murray {
820bc865db6SJacques Vidrine size_t sz, block_sz, checksum_sz, total_sz;
821b528cefcSMark Murray Checksum cksum;
822b528cefcSMark Murray unsigned char *p, *q;
823b528cefcSMark Murray krb5_error_code ret;
824ae771770SStanislav Sedov struct _krb5_key_data *dkey;
825ae771770SStanislav Sedov const struct _krb5_encryption_type *et = crypto->et;
826b528cefcSMark Murray
827b528cefcSMark Murray checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
828b528cefcSMark Murray
829bc865db6SJacques Vidrine sz = et->confoundersize + len;
8302d485134SJacques Vidrine block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
831bc865db6SJacques Vidrine total_sz = block_sz + checksum_sz;
832bc865db6SJacques Vidrine p = calloc(1, total_sz);
833bc865db6SJacques Vidrine if(p == NULL) {
834ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
835b528cefcSMark Murray return ENOMEM;
836bc865db6SJacques Vidrine }
837b528cefcSMark Murray
838b528cefcSMark Murray q = p;
839b528cefcSMark Murray krb5_generate_random_block(q, et->confoundersize); /* XXX */
840b528cefcSMark Murray q += et->confoundersize;
841b528cefcSMark Murray memcpy(q, data, len);
842b528cefcSMark Murray
843b528cefcSMark Murray ret = create_checksum(context,
844a0c37ec3SJacques Vidrine et->keyed_checksum,
845b528cefcSMark Murray crypto,
846b528cefcSMark Murray INTEGRITY_USAGE(usage),
847b528cefcSMark Murray p,
848b528cefcSMark Murray block_sz,
849b528cefcSMark Murray &cksum);
85047085b17SAssar Westerlund if(ret == 0 && cksum.checksum.length != checksum_sz) {
85147085b17SAssar Westerlund free_Checksum (&cksum);
852ae771770SStanislav Sedov krb5_clear_error_message (context);
853b528cefcSMark Murray ret = KRB5_CRYPTO_INTERNAL;
85447085b17SAssar Westerlund }
855bc865db6SJacques Vidrine if(ret)
856bc865db6SJacques Vidrine goto fail;
857b528cefcSMark Murray memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
85847085b17SAssar Westerlund free_Checksum (&cksum);
859b528cefcSMark Murray ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
860bc865db6SJacques Vidrine if(ret)
861bc865db6SJacques Vidrine goto fail;
862b528cefcSMark Murray ret = _key_schedule(context, dkey);
863bc865db6SJacques Vidrine if(ret)
864bc865db6SJacques Vidrine goto fail;
865bc865db6SJacques Vidrine ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
866bc865db6SJacques Vidrine if (ret)
867bc865db6SJacques Vidrine goto fail;
868b528cefcSMark Murray result->data = p;
869bc865db6SJacques Vidrine result->length = total_sz;
870b528cefcSMark Murray return 0;
871bc865db6SJacques Vidrine fail:
872bc865db6SJacques Vidrine memset(p, 0, total_sz);
873bc865db6SJacques Vidrine free(p);
874bc865db6SJacques Vidrine return ret;
875b528cefcSMark Murray }
876b528cefcSMark Murray
877bc865db6SJacques Vidrine
878b528cefcSMark Murray static krb5_error_code
encrypt_internal(krb5_context context,krb5_crypto crypto,const void * data,size_t len,krb5_data * result,void * ivec)879b528cefcSMark Murray encrypt_internal(krb5_context context,
880b528cefcSMark Murray krb5_crypto crypto,
88133f12199SDoug Rabson const void *data,
882b528cefcSMark Murray size_t len,
88347085b17SAssar Westerlund krb5_data *result,
88447085b17SAssar Westerlund void *ivec)
885b528cefcSMark Murray {
886b528cefcSMark Murray size_t sz, block_sz, checksum_sz;
887b528cefcSMark Murray Checksum cksum;
888b528cefcSMark Murray unsigned char *p, *q;
889b528cefcSMark Murray krb5_error_code ret;
890ae771770SStanislav Sedov const struct _krb5_encryption_type *et = crypto->et;
891b528cefcSMark Murray
892c80b5a63SAssar Westerlund checksum_sz = CHECKSUMSIZE(et->checksum);
893b528cefcSMark Murray
894b528cefcSMark Murray sz = et->confoundersize + checksum_sz + len;
8952d485134SJacques Vidrine block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
896b528cefcSMark Murray p = calloc(1, block_sz);
897c80b5a63SAssar Westerlund if(p == NULL) {
898ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
899b528cefcSMark Murray return ENOMEM;
900c80b5a63SAssar Westerlund }
901b528cefcSMark Murray
902b528cefcSMark Murray q = p;
903b528cefcSMark Murray krb5_generate_random_block(q, et->confoundersize); /* XXX */
904b528cefcSMark Murray q += et->confoundersize;
905b528cefcSMark Murray memset(q, 0, checksum_sz);
906b528cefcSMark Murray q += checksum_sz;
907b528cefcSMark Murray memcpy(q, data, len);
908b528cefcSMark Murray
909b528cefcSMark Murray ret = create_checksum(context,
910a0c37ec3SJacques Vidrine et->checksum,
911c80b5a63SAssar Westerlund crypto,
912b528cefcSMark Murray 0,
913b528cefcSMark Murray p,
914b528cefcSMark Murray block_sz,
915b528cefcSMark Murray &cksum);
916b528cefcSMark Murray if(ret == 0 && cksum.checksum.length != checksum_sz) {
917ae771770SStanislav Sedov krb5_clear_error_message (context);
918bc865db6SJacques Vidrine free_Checksum(&cksum);
919b528cefcSMark Murray ret = KRB5_CRYPTO_INTERNAL;
920b528cefcSMark Murray }
921bc865db6SJacques Vidrine if(ret)
922bc865db6SJacques Vidrine goto fail;
923b528cefcSMark Murray memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
924b528cefcSMark Murray free_Checksum(&cksum);
925b528cefcSMark Murray ret = _key_schedule(context, &crypto->key);
926bc865db6SJacques Vidrine if(ret)
927bc865db6SJacques Vidrine goto fail;
928bc865db6SJacques Vidrine ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
929b528cefcSMark Murray if (ret) {
930b528cefcSMark Murray memset(p, 0, block_sz);
931b528cefcSMark Murray free(p);
932b528cefcSMark Murray return ret;
933b528cefcSMark Murray }
934b528cefcSMark Murray result->data = p;
935b528cefcSMark Murray result->length = block_sz;
936b528cefcSMark Murray return 0;
937bc865db6SJacques Vidrine fail:
938bc865db6SJacques Vidrine memset(p, 0, block_sz);
939bc865db6SJacques Vidrine free(p);
940bc865db6SJacques Vidrine return ret;
941b528cefcSMark Murray }
942b528cefcSMark Murray
943b528cefcSMark Murray static krb5_error_code
encrypt_internal_special(krb5_context context,krb5_crypto crypto,int usage,const void * data,size_t len,krb5_data * result,void * ivec)94447085b17SAssar Westerlund encrypt_internal_special(krb5_context context,
94547085b17SAssar Westerlund krb5_crypto crypto,
94647085b17SAssar Westerlund int usage,
94733f12199SDoug Rabson const void *data,
94847085b17SAssar Westerlund size_t len,
94947085b17SAssar Westerlund krb5_data *result,
95047085b17SAssar Westerlund void *ivec)
95147085b17SAssar Westerlund {
952ae771770SStanislav Sedov struct _krb5_encryption_type *et = crypto->et;
953c80b5a63SAssar Westerlund size_t cksum_sz = CHECKSUMSIZE(et->checksum);
95447085b17SAssar Westerlund size_t sz = len + cksum_sz + et->confoundersize;
95547085b17SAssar Westerlund char *tmp, *p;
956bc865db6SJacques Vidrine krb5_error_code ret;
95747085b17SAssar Westerlund
95847085b17SAssar Westerlund tmp = malloc (sz);
959c80b5a63SAssar Westerlund if (tmp == NULL) {
960ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
96147085b17SAssar Westerlund return ENOMEM;
962c80b5a63SAssar Westerlund }
96347085b17SAssar Westerlund p = tmp;
96447085b17SAssar Westerlund memset (p, 0, cksum_sz);
96547085b17SAssar Westerlund p += cksum_sz;
96647085b17SAssar Westerlund krb5_generate_random_block(p, et->confoundersize);
96747085b17SAssar Westerlund p += et->confoundersize;
96847085b17SAssar Westerlund memcpy (p, data, len);
969bc865db6SJacques Vidrine ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
970bc865db6SJacques Vidrine if (ret) {
971bc865db6SJacques Vidrine memset(tmp, 0, sz);
972bc865db6SJacques Vidrine free(tmp);
973bc865db6SJacques Vidrine return ret;
974bc865db6SJacques Vidrine }
97547085b17SAssar Westerlund result->data = tmp;
97647085b17SAssar Westerlund result->length = sz;
97747085b17SAssar Westerlund return 0;
97847085b17SAssar Westerlund }
97947085b17SAssar Westerlund
98047085b17SAssar Westerlund static krb5_error_code
decrypt_internal_derived(krb5_context context,krb5_crypto crypto,unsigned usage,void * data,size_t len,krb5_data * result,void * ivec)981b528cefcSMark Murray decrypt_internal_derived(krb5_context context,
982b528cefcSMark Murray krb5_crypto crypto,
983b528cefcSMark Murray unsigned usage,
984b528cefcSMark Murray void *data,
985b528cefcSMark Murray size_t len,
98647085b17SAssar Westerlund krb5_data *result,
98747085b17SAssar Westerlund void *ivec)
988b528cefcSMark Murray {
989b528cefcSMark Murray size_t checksum_sz;
990b528cefcSMark Murray Checksum cksum;
991b528cefcSMark Murray unsigned char *p;
992b528cefcSMark Murray krb5_error_code ret;
993ae771770SStanislav Sedov struct _krb5_key_data *dkey;
994ae771770SStanislav Sedov struct _krb5_encryption_type *et = crypto->et;
995b528cefcSMark Murray unsigned long l;
996b528cefcSMark Murray
99747085b17SAssar Westerlund checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
99833f12199SDoug Rabson if (len < checksum_sz + et->confoundersize) {
999ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_BAD_MSIZE,
1000ae771770SStanislav Sedov N_("Encrypted data shorter then "
1001ae771770SStanislav Sedov "checksum + confunder", ""));
100233f12199SDoug Rabson return KRB5_BAD_MSIZE;
1003c80b5a63SAssar Westerlund }
100447085b17SAssar Westerlund
1005a0c37ec3SJacques Vidrine if (((len - checksum_sz) % et->padsize) != 0) {
1006ae771770SStanislav Sedov krb5_clear_error_message(context);
1007a0c37ec3SJacques Vidrine return KRB5_BAD_MSIZE;
1008a0c37ec3SJacques Vidrine }
1009a0c37ec3SJacques Vidrine
1010b528cefcSMark Murray p = malloc(len);
1011c80b5a63SAssar Westerlund if(len != 0 && p == NULL) {
1012ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1013b528cefcSMark Murray return ENOMEM;
1014c80b5a63SAssar Westerlund }
1015b528cefcSMark Murray memcpy(p, data, len);
1016b528cefcSMark Murray
1017b528cefcSMark Murray len -= checksum_sz;
1018b528cefcSMark Murray
1019b528cefcSMark Murray ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1020b528cefcSMark Murray if(ret) {
1021b528cefcSMark Murray free(p);
1022b528cefcSMark Murray return ret;
1023b528cefcSMark Murray }
1024b528cefcSMark Murray ret = _key_schedule(context, dkey);
1025b528cefcSMark Murray if(ret) {
1026b528cefcSMark Murray free(p);
1027b528cefcSMark Murray return ret;
1028b528cefcSMark Murray }
1029bc865db6SJacques Vidrine ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
1030bc865db6SJacques Vidrine if (ret) {
1031bc865db6SJacques Vidrine free(p);
1032bc865db6SJacques Vidrine return ret;
1033bc865db6SJacques Vidrine }
1034b528cefcSMark Murray
1035b528cefcSMark Murray cksum.checksum.data = p + len;
1036b528cefcSMark Murray cksum.checksum.length = checksum_sz;
1037b528cefcSMark Murray cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
1038b528cefcSMark Murray
1039b528cefcSMark Murray ret = verify_checksum(context,
1040b528cefcSMark Murray crypto,
1041b528cefcSMark Murray INTEGRITY_USAGE(usage),
1042b528cefcSMark Murray p,
1043b528cefcSMark Murray len,
1044b528cefcSMark Murray &cksum);
1045b528cefcSMark Murray if(ret) {
1046b528cefcSMark Murray free(p);
1047b528cefcSMark Murray return ret;
1048b528cefcSMark Murray }
1049b528cefcSMark Murray l = len - et->confoundersize;
1050b528cefcSMark Murray memmove(p, p + et->confoundersize, l);
1051b528cefcSMark Murray result->data = realloc(p, l);
105233f12199SDoug Rabson if(result->data == NULL && l != 0) {
1053b528cefcSMark Murray free(p);
1054ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1055b528cefcSMark Murray return ENOMEM;
1056b528cefcSMark Murray }
1057b528cefcSMark Murray result->length = l;
1058b528cefcSMark Murray return 0;
1059b528cefcSMark Murray }
1060b528cefcSMark Murray
1061b528cefcSMark Murray static krb5_error_code
decrypt_internal(krb5_context context,krb5_crypto crypto,void * data,size_t len,krb5_data * result,void * ivec)1062b528cefcSMark Murray decrypt_internal(krb5_context context,
1063b528cefcSMark Murray krb5_crypto crypto,
1064b528cefcSMark Murray void *data,
1065b528cefcSMark Murray size_t len,
106647085b17SAssar Westerlund krb5_data *result,
106747085b17SAssar Westerlund void *ivec)
1068b528cefcSMark Murray {
1069b528cefcSMark Murray krb5_error_code ret;
1070b528cefcSMark Murray unsigned char *p;
1071b528cefcSMark Murray Checksum cksum;
1072b528cefcSMark Murray size_t checksum_sz, l;
1073ae771770SStanislav Sedov struct _krb5_encryption_type *et = crypto->et;
1074b528cefcSMark Murray
1075a0c37ec3SJacques Vidrine if ((len % et->padsize) != 0) {
1076ae771770SStanislav Sedov krb5_clear_error_message(context);
1077ae771770SStanislav Sedov return KRB5_BAD_MSIZE;
1078ae771770SStanislav Sedov }
1079ae771770SStanislav Sedov checksum_sz = CHECKSUMSIZE(et->checksum);
1080ae771770SStanislav Sedov if (len < checksum_sz + et->confoundersize) {
1081ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_BAD_MSIZE,
1082ae771770SStanislav Sedov N_("Encrypted data shorter then "
1083ae771770SStanislav Sedov "checksum + confunder", ""));
1084a0c37ec3SJacques Vidrine return KRB5_BAD_MSIZE;
1085a0c37ec3SJacques Vidrine }
1086a0c37ec3SJacques Vidrine
1087b528cefcSMark Murray p = malloc(len);
1088c80b5a63SAssar Westerlund if(len != 0 && p == NULL) {
1089ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1090b528cefcSMark Murray return ENOMEM;
1091c80b5a63SAssar Westerlund }
1092b528cefcSMark Murray memcpy(p, data, len);
1093b528cefcSMark Murray
1094b528cefcSMark Murray ret = _key_schedule(context, &crypto->key);
1095b528cefcSMark Murray if(ret) {
1096b528cefcSMark Murray free(p);
1097b528cefcSMark Murray return ret;
1098b528cefcSMark Murray }
1099bc865db6SJacques Vidrine ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
1100bc865db6SJacques Vidrine if (ret) {
1101bc865db6SJacques Vidrine free(p);
1102bc865db6SJacques Vidrine return ret;
1103bc865db6SJacques Vidrine }
1104b528cefcSMark Murray ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
1105b528cefcSMark Murray if(ret) {
1106b528cefcSMark Murray free(p);
1107b528cefcSMark Murray return ret;
1108b528cefcSMark Murray }
1109b528cefcSMark Murray memset(p + et->confoundersize, 0, checksum_sz);
1110c80b5a63SAssar Westerlund cksum.cksumtype = CHECKSUMTYPE(et->checksum);
1111b528cefcSMark Murray ret = verify_checksum(context, NULL, 0, p, len, &cksum);
1112b528cefcSMark Murray free_Checksum(&cksum);
1113b528cefcSMark Murray if(ret) {
1114b528cefcSMark Murray free(p);
1115b528cefcSMark Murray return ret;
1116b528cefcSMark Murray }
1117b528cefcSMark Murray l = len - et->confoundersize - checksum_sz;
1118b528cefcSMark Murray memmove(p, p + et->confoundersize + checksum_sz, l);
1119b528cefcSMark Murray result->data = realloc(p, l);
112033f12199SDoug Rabson if(result->data == NULL && l != 0) {
1121b528cefcSMark Murray free(p);
1122ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1123b528cefcSMark Murray return ENOMEM;
1124b528cefcSMark Murray }
1125b528cefcSMark Murray result->length = l;
1126b528cefcSMark Murray return 0;
1127b528cefcSMark Murray }
1128b528cefcSMark Murray
112947085b17SAssar Westerlund static krb5_error_code
decrypt_internal_special(krb5_context context,krb5_crypto crypto,int usage,void * data,size_t len,krb5_data * result,void * ivec)113047085b17SAssar Westerlund decrypt_internal_special(krb5_context context,
113147085b17SAssar Westerlund krb5_crypto crypto,
113247085b17SAssar Westerlund int usage,
113347085b17SAssar Westerlund void *data,
113447085b17SAssar Westerlund size_t len,
113547085b17SAssar Westerlund krb5_data *result,
113647085b17SAssar Westerlund void *ivec)
113747085b17SAssar Westerlund {
1138ae771770SStanislav Sedov struct _krb5_encryption_type *et = crypto->et;
1139c80b5a63SAssar Westerlund size_t cksum_sz = CHECKSUMSIZE(et->checksum);
114047085b17SAssar Westerlund size_t sz = len - cksum_sz - et->confoundersize;
1141a0c37ec3SJacques Vidrine unsigned char *p;
1142bc865db6SJacques Vidrine krb5_error_code ret;
114347085b17SAssar Westerlund
1144a0c37ec3SJacques Vidrine if ((len % et->padsize) != 0) {
1145ae771770SStanislav Sedov krb5_clear_error_message(context);
1146ae771770SStanislav Sedov return KRB5_BAD_MSIZE;
1147ae771770SStanislav Sedov }
1148ae771770SStanislav Sedov if (len < cksum_sz + et->confoundersize) {
1149ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_BAD_MSIZE,
1150ae771770SStanislav Sedov N_("Encrypted data shorter then "
1151ae771770SStanislav Sedov "checksum + confunder", ""));
1152a0c37ec3SJacques Vidrine return KRB5_BAD_MSIZE;
1153a0c37ec3SJacques Vidrine }
1154a0c37ec3SJacques Vidrine
1155a0c37ec3SJacques Vidrine p = malloc (len);
1156a0c37ec3SJacques Vidrine if (p == NULL) {
1157ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
115847085b17SAssar Westerlund return ENOMEM;
1159c80b5a63SAssar Westerlund }
1160a0c37ec3SJacques Vidrine memcpy(p, data, len);
116147085b17SAssar Westerlund
1162a0c37ec3SJacques Vidrine ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec);
1163bc865db6SJacques Vidrine if (ret) {
1164a0c37ec3SJacques Vidrine free(p);
1165bc865db6SJacques Vidrine return ret;
1166bc865db6SJacques Vidrine }
116747085b17SAssar Westerlund
1168a0c37ec3SJacques Vidrine memmove (p, p + cksum_sz + et->confoundersize, sz);
1169a0c37ec3SJacques Vidrine result->data = realloc(p, sz);
117033f12199SDoug Rabson if(result->data == NULL && sz != 0) {
1171a0c37ec3SJacques Vidrine free(p);
1172ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1173a0c37ec3SJacques Vidrine return ENOMEM;
1174a0c37ec3SJacques Vidrine }
117547085b17SAssar Westerlund result->length = sz;
117647085b17SAssar Westerlund return 0;
117747085b17SAssar Westerlund }
117847085b17SAssar Westerlund
1179ae771770SStanislav Sedov static krb5_crypto_iov *
find_iv(krb5_crypto_iov * data,size_t num_data,unsigned type)1180ae771770SStanislav Sedov find_iv(krb5_crypto_iov *data, size_t num_data, unsigned type)
1181ae771770SStanislav Sedov {
1182ae771770SStanislav Sedov size_t i;
1183ae771770SStanislav Sedov for (i = 0; i < num_data; i++)
1184ae771770SStanislav Sedov if (data[i].flags == type)
1185ae771770SStanislav Sedov return &data[i];
1186ae771770SStanislav Sedov return NULL;
1187ae771770SStanislav Sedov }
118847085b17SAssar Westerlund
1189ae771770SStanislav Sedov /**
1190ae771770SStanislav Sedov * Inline encrypt a kerberos message
1191ae771770SStanislav Sedov *
1192ae771770SStanislav Sedov * @param context Kerberos context
1193ae771770SStanislav Sedov * @param crypto Kerberos crypto context
1194ae771770SStanislav Sedov * @param usage Key usage for this buffer
1195ae771770SStanislav Sedov * @param data array of buffers to process
1196ae771770SStanislav Sedov * @param num_data length of array
1197ae771770SStanislav Sedov * @param ivec initial cbc/cts vector
1198ae771770SStanislav Sedov *
1199ae771770SStanislav Sedov * @return Return an error code or 0.
1200ae771770SStanislav Sedov * @ingroup krb5_crypto
1201ae771770SStanislav Sedov *
1202ae771770SStanislav Sedov * Kerberos encrypted data look like this:
1203ae771770SStanislav Sedov *
1204ae771770SStanislav Sedov * 1. KRB5_CRYPTO_TYPE_HEADER
1205ae771770SStanislav Sedov * 2. array [1,...] KRB5_CRYPTO_TYPE_DATA and array [0,...]
1206ae771770SStanislav Sedov * KRB5_CRYPTO_TYPE_SIGN_ONLY in any order, however the receiver
1207ae771770SStanislav Sedov * have to aware of the order. KRB5_CRYPTO_TYPE_SIGN_ONLY is
1208ae771770SStanislav Sedov * commonly used headers and trailers.
1209ae771770SStanislav Sedov * 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1
1210ae771770SStanislav Sedov * 4. KRB5_CRYPTO_TYPE_TRAILER
1211ae771770SStanislav Sedov */
1212ae771770SStanislav Sedov
1213ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_encrypt_iov_ivec(krb5_context context,krb5_crypto crypto,unsigned usage,krb5_crypto_iov * data,int num_data,void * ivec)1214ae771770SStanislav Sedov krb5_encrypt_iov_ivec(krb5_context context,
1215ae771770SStanislav Sedov krb5_crypto crypto,
1216ae771770SStanislav Sedov unsigned usage,
1217ae771770SStanislav Sedov krb5_crypto_iov *data,
1218ae771770SStanislav Sedov int num_data,
1219ae771770SStanislav Sedov void *ivec)
1220ae771770SStanislav Sedov {
1221ae771770SStanislav Sedov size_t headersz, trailersz, len;
1222ae771770SStanislav Sedov int i;
1223ae771770SStanislav Sedov size_t sz, block_sz, pad_sz;
1224ae771770SStanislav Sedov Checksum cksum;
1225ae771770SStanislav Sedov unsigned char *p, *q;
1226ae771770SStanislav Sedov krb5_error_code ret;
1227ae771770SStanislav Sedov struct _krb5_key_data *dkey;
1228ae771770SStanislav Sedov const struct _krb5_encryption_type *et = crypto->et;
1229ae771770SStanislav Sedov krb5_crypto_iov *tiv, *piv, *hiv;
1230ae771770SStanislav Sedov
1231ae771770SStanislav Sedov if (num_data < 0) {
1232ae771770SStanislav Sedov krb5_clear_error_message(context);
1233ae771770SStanislav Sedov return KRB5_CRYPTO_INTERNAL;
1234ae771770SStanislav Sedov }
1235ae771770SStanislav Sedov
1236ae771770SStanislav Sedov if(!derived_crypto(context, crypto)) {
1237ae771770SStanislav Sedov krb5_clear_error_message(context);
1238ae771770SStanislav Sedov return KRB5_CRYPTO_INTERNAL;
1239ae771770SStanislav Sedov }
1240ae771770SStanislav Sedov
1241ae771770SStanislav Sedov headersz = et->confoundersize;
1242ae771770SStanislav Sedov trailersz = CHECKSUMSIZE(et->keyed_checksum);
1243ae771770SStanislav Sedov
1244ae771770SStanislav Sedov for (len = 0, i = 0; i < num_data; i++) {
1245ae771770SStanislav Sedov if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1246ae771770SStanislav Sedov continue;
1247ae771770SStanislav Sedov len += data[i].data.length;
1248ae771770SStanislav Sedov }
1249ae771770SStanislav Sedov
1250ae771770SStanislav Sedov sz = headersz + len;
1251ae771770SStanislav Sedov block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
1252ae771770SStanislav Sedov
1253ae771770SStanislav Sedov pad_sz = block_sz - sz;
1254ae771770SStanislav Sedov
1255ae771770SStanislav Sedov /* header */
1256ae771770SStanislav Sedov
1257ae771770SStanislav Sedov hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
1258ae771770SStanislav Sedov if (hiv == NULL || hiv->data.length != headersz)
1259ae771770SStanislav Sedov return KRB5_BAD_MSIZE;
1260ae771770SStanislav Sedov
1261ae771770SStanislav Sedov krb5_generate_random_block(hiv->data.data, hiv->data.length);
1262ae771770SStanislav Sedov
1263ae771770SStanislav Sedov /* padding */
1264ae771770SStanislav Sedov piv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
1265ae771770SStanislav Sedov /* its ok to have no TYPE_PADDING if there is no padding */
1266ae771770SStanislav Sedov if (piv == NULL && pad_sz != 0)
1267ae771770SStanislav Sedov return KRB5_BAD_MSIZE;
1268ae771770SStanislav Sedov if (piv) {
1269ae771770SStanislav Sedov if (piv->data.length < pad_sz)
1270ae771770SStanislav Sedov return KRB5_BAD_MSIZE;
1271ae771770SStanislav Sedov piv->data.length = pad_sz;
1272ae771770SStanislav Sedov if (pad_sz)
1273ae771770SStanislav Sedov memset(piv->data.data, pad_sz, pad_sz);
1274ae771770SStanislav Sedov else
1275ae771770SStanislav Sedov piv = NULL;
1276ae771770SStanislav Sedov }
1277ae771770SStanislav Sedov
1278ae771770SStanislav Sedov /* trailer */
1279ae771770SStanislav Sedov tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
1280ae771770SStanislav Sedov if (tiv == NULL || tiv->data.length != trailersz)
1281ae771770SStanislav Sedov return KRB5_BAD_MSIZE;
1282ae771770SStanislav Sedov
1283ae771770SStanislav Sedov /*
1284ae771770SStanislav Sedov * XXX replace with EVP_Sign? at least make create_checksum an iov
1285ae771770SStanislav Sedov * function.
1286ae771770SStanislav Sedov * XXX CTS EVP is broken, can't handle multi buffers :(
1287ae771770SStanislav Sedov */
1288ae771770SStanislav Sedov
1289ae771770SStanislav Sedov len = block_sz;
1290ae771770SStanislav Sedov for (i = 0; i < num_data; i++) {
1291ae771770SStanislav Sedov if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1292ae771770SStanislav Sedov continue;
1293ae771770SStanislav Sedov len += data[i].data.length;
1294ae771770SStanislav Sedov }
1295ae771770SStanislav Sedov
1296ae771770SStanislav Sedov p = q = malloc(len);
1297ae771770SStanislav Sedov
1298ae771770SStanislav Sedov memcpy(q, hiv->data.data, hiv->data.length);
1299ae771770SStanislav Sedov q += hiv->data.length;
1300ae771770SStanislav Sedov for (i = 0; i < num_data; i++) {
1301ae771770SStanislav Sedov if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1302ae771770SStanislav Sedov data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1303ae771770SStanislav Sedov continue;
1304ae771770SStanislav Sedov memcpy(q, data[i].data.data, data[i].data.length);
1305ae771770SStanislav Sedov q += data[i].data.length;
1306ae771770SStanislav Sedov }
1307ae771770SStanislav Sedov if (piv)
1308ae771770SStanislav Sedov memset(q, 0, piv->data.length);
1309ae771770SStanislav Sedov
1310ae771770SStanislav Sedov ret = create_checksum(context,
1311ae771770SStanislav Sedov et->keyed_checksum,
1312ae771770SStanislav Sedov crypto,
1313ae771770SStanislav Sedov INTEGRITY_USAGE(usage),
1314ae771770SStanislav Sedov p,
1315ae771770SStanislav Sedov len,
1316ae771770SStanislav Sedov &cksum);
1317ae771770SStanislav Sedov free(p);
1318ae771770SStanislav Sedov if(ret == 0 && cksum.checksum.length != trailersz) {
1319ae771770SStanislav Sedov free_Checksum (&cksum);
1320ae771770SStanislav Sedov krb5_clear_error_message (context);
1321ae771770SStanislav Sedov ret = KRB5_CRYPTO_INTERNAL;
1322ae771770SStanislav Sedov }
1323ae771770SStanislav Sedov if(ret)
1324ae771770SStanislav Sedov return ret;
1325ae771770SStanislav Sedov
1326ae771770SStanislav Sedov /* save cksum at end */
1327ae771770SStanislav Sedov memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length);
1328ae771770SStanislav Sedov free_Checksum (&cksum);
1329ae771770SStanislav Sedov
1330ae771770SStanislav Sedov /* XXX replace with EVP_Cipher */
1331ae771770SStanislav Sedov p = q = malloc(block_sz);
1332ae771770SStanislav Sedov if(p == NULL)
1333ae771770SStanislav Sedov return ENOMEM;
1334ae771770SStanislav Sedov
1335ae771770SStanislav Sedov memcpy(q, hiv->data.data, hiv->data.length);
1336ae771770SStanislav Sedov q += hiv->data.length;
1337ae771770SStanislav Sedov
1338ae771770SStanislav Sedov for (i = 0; i < num_data; i++) {
1339ae771770SStanislav Sedov if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1340ae771770SStanislav Sedov continue;
1341ae771770SStanislav Sedov memcpy(q, data[i].data.data, data[i].data.length);
1342ae771770SStanislav Sedov q += data[i].data.length;
1343ae771770SStanislav Sedov }
1344ae771770SStanislav Sedov if (piv)
1345ae771770SStanislav Sedov memset(q, 0, piv->data.length);
1346ae771770SStanislav Sedov
1347ae771770SStanislav Sedov
1348ae771770SStanislav Sedov ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1349ae771770SStanislav Sedov if(ret) {
1350ae771770SStanislav Sedov free(p);
1351ae771770SStanislav Sedov return ret;
1352ae771770SStanislav Sedov }
1353ae771770SStanislav Sedov ret = _key_schedule(context, dkey);
1354ae771770SStanislav Sedov if(ret) {
1355ae771770SStanislav Sedov free(p);
1356ae771770SStanislav Sedov return ret;
1357ae771770SStanislav Sedov }
1358ae771770SStanislav Sedov
1359ae771770SStanislav Sedov ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
1360ae771770SStanislav Sedov if (ret) {
1361ae771770SStanislav Sedov free(p);
1362ae771770SStanislav Sedov return ret;
1363ae771770SStanislav Sedov }
1364ae771770SStanislav Sedov
1365ae771770SStanislav Sedov /* now copy data back to buffers */
1366ae771770SStanislav Sedov q = p;
1367ae771770SStanislav Sedov
1368ae771770SStanislav Sedov memcpy(hiv->data.data, q, hiv->data.length);
1369ae771770SStanislav Sedov q += hiv->data.length;
1370ae771770SStanislav Sedov
1371ae771770SStanislav Sedov for (i = 0; i < num_data; i++) {
1372ae771770SStanislav Sedov if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1373ae771770SStanislav Sedov continue;
1374ae771770SStanislav Sedov memcpy(data[i].data.data, q, data[i].data.length);
1375ae771770SStanislav Sedov q += data[i].data.length;
1376ae771770SStanislav Sedov }
1377ae771770SStanislav Sedov if (piv)
1378ae771770SStanislav Sedov memcpy(piv->data.data, q, pad_sz);
1379ae771770SStanislav Sedov
1380ae771770SStanislav Sedov free(p);
1381ae771770SStanislav Sedov
1382ae771770SStanislav Sedov return ret;
1383ae771770SStanislav Sedov }
1384ae771770SStanislav Sedov
1385ae771770SStanislav Sedov /**
1386ae771770SStanislav Sedov * Inline decrypt a Kerberos message.
1387ae771770SStanislav Sedov *
1388ae771770SStanislav Sedov * @param context Kerberos context
1389ae771770SStanislav Sedov * @param crypto Kerberos crypto context
1390ae771770SStanislav Sedov * @param usage Key usage for this buffer
1391ae771770SStanislav Sedov * @param data array of buffers to process
1392ae771770SStanislav Sedov * @param num_data length of array
1393ae771770SStanislav Sedov * @param ivec initial cbc/cts vector
1394ae771770SStanislav Sedov *
1395ae771770SStanislav Sedov * @return Return an error code or 0.
1396ae771770SStanislav Sedov * @ingroup krb5_crypto
1397ae771770SStanislav Sedov *
1398ae771770SStanislav Sedov * 1. KRB5_CRYPTO_TYPE_HEADER
1399ae771770SStanislav Sedov * 2. one KRB5_CRYPTO_TYPE_DATA and array [0,...] of KRB5_CRYPTO_TYPE_SIGN_ONLY in
1400ae771770SStanislav Sedov * any order, however the receiver have to aware of the
1401ae771770SStanislav Sedov * order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted
1402ae771770SStanislav Sedov * protocol headers and trailers. The output data will be of same
1403ae771770SStanislav Sedov * size as the input data or shorter.
1404ae771770SStanislav Sedov */
1405ae771770SStanislav Sedov
1406ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_decrypt_iov_ivec(krb5_context context,krb5_crypto crypto,unsigned usage,krb5_crypto_iov * data,unsigned int num_data,void * ivec)1407ae771770SStanislav Sedov krb5_decrypt_iov_ivec(krb5_context context,
1408ae771770SStanislav Sedov krb5_crypto crypto,
1409ae771770SStanislav Sedov unsigned usage,
1410ae771770SStanislav Sedov krb5_crypto_iov *data,
1411ae771770SStanislav Sedov unsigned int num_data,
1412ae771770SStanislav Sedov void *ivec)
1413ae771770SStanislav Sedov {
1414ae771770SStanislav Sedov unsigned int i;
1415ae771770SStanislav Sedov size_t headersz, trailersz, len;
1416ae771770SStanislav Sedov Checksum cksum;
1417ae771770SStanislav Sedov unsigned char *p, *q;
1418ae771770SStanislav Sedov krb5_error_code ret;
1419ae771770SStanislav Sedov struct _krb5_key_data *dkey;
1420ae771770SStanislav Sedov struct _krb5_encryption_type *et = crypto->et;
1421ae771770SStanislav Sedov krb5_crypto_iov *tiv, *hiv;
1422ae771770SStanislav Sedov
1423ae771770SStanislav Sedov if(!derived_crypto(context, crypto)) {
1424ae771770SStanislav Sedov krb5_clear_error_message(context);
1425ae771770SStanislav Sedov return KRB5_CRYPTO_INTERNAL;
1426ae771770SStanislav Sedov }
1427ae771770SStanislav Sedov
1428ae771770SStanislav Sedov headersz = et->confoundersize;
1429ae771770SStanislav Sedov
1430ae771770SStanislav Sedov hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
1431ae771770SStanislav Sedov if (hiv == NULL || hiv->data.length != headersz)
1432ae771770SStanislav Sedov return KRB5_BAD_MSIZE;
1433ae771770SStanislav Sedov
1434ae771770SStanislav Sedov /* trailer */
1435ae771770SStanislav Sedov trailersz = CHECKSUMSIZE(et->keyed_checksum);
1436ae771770SStanislav Sedov
1437ae771770SStanislav Sedov tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
1438ae771770SStanislav Sedov if (tiv->data.length != trailersz)
1439ae771770SStanislav Sedov return KRB5_BAD_MSIZE;
1440ae771770SStanislav Sedov
1441ae771770SStanislav Sedov /* Find length of data we will decrypt */
1442ae771770SStanislav Sedov
1443ae771770SStanislav Sedov len = headersz;
1444ae771770SStanislav Sedov for (i = 0; i < num_data; i++) {
1445ae771770SStanislav Sedov if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1446ae771770SStanislav Sedov continue;
1447ae771770SStanislav Sedov len += data[i].data.length;
1448ae771770SStanislav Sedov }
1449ae771770SStanislav Sedov
1450ae771770SStanislav Sedov if ((len % et->padsize) != 0) {
1451ae771770SStanislav Sedov krb5_clear_error_message(context);
1452ae771770SStanislav Sedov return KRB5_BAD_MSIZE;
1453ae771770SStanislav Sedov }
1454ae771770SStanislav Sedov
1455ae771770SStanislav Sedov /* XXX replace with EVP_Cipher */
1456ae771770SStanislav Sedov
1457ae771770SStanislav Sedov p = q = malloc(len);
1458ae771770SStanislav Sedov if (p == NULL)
1459ae771770SStanislav Sedov return ENOMEM;
1460ae771770SStanislav Sedov
1461ae771770SStanislav Sedov memcpy(q, hiv->data.data, hiv->data.length);
1462ae771770SStanislav Sedov q += hiv->data.length;
1463ae771770SStanislav Sedov
1464ae771770SStanislav Sedov for (i = 0; i < num_data; i++) {
1465ae771770SStanislav Sedov if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1466ae771770SStanislav Sedov continue;
1467ae771770SStanislav Sedov memcpy(q, data[i].data.data, data[i].data.length);
1468ae771770SStanislav Sedov q += data[i].data.length;
1469ae771770SStanislav Sedov }
1470ae771770SStanislav Sedov
1471ae771770SStanislav Sedov ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1472ae771770SStanislav Sedov if(ret) {
1473ae771770SStanislav Sedov free(p);
1474ae771770SStanislav Sedov return ret;
1475ae771770SStanislav Sedov }
1476ae771770SStanislav Sedov ret = _key_schedule(context, dkey);
1477ae771770SStanislav Sedov if(ret) {
1478ae771770SStanislav Sedov free(p);
1479ae771770SStanislav Sedov return ret;
1480ae771770SStanislav Sedov }
1481ae771770SStanislav Sedov
1482ae771770SStanislav Sedov ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
1483ae771770SStanislav Sedov if (ret) {
1484ae771770SStanislav Sedov free(p);
1485ae771770SStanislav Sedov return ret;
1486ae771770SStanislav Sedov }
1487ae771770SStanislav Sedov
1488ae771770SStanislav Sedov /* copy data back to buffers */
1489ae771770SStanislav Sedov memcpy(hiv->data.data, p, hiv->data.length);
1490ae771770SStanislav Sedov q = p + hiv->data.length;
1491ae771770SStanislav Sedov for (i = 0; i < num_data; i++) {
1492ae771770SStanislav Sedov if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1493ae771770SStanislav Sedov continue;
1494ae771770SStanislav Sedov memcpy(data[i].data.data, q, data[i].data.length);
1495ae771770SStanislav Sedov q += data[i].data.length;
1496ae771770SStanislav Sedov }
1497ae771770SStanislav Sedov
1498ae771770SStanislav Sedov free(p);
1499ae771770SStanislav Sedov
1500ae771770SStanislav Sedov /* check signature */
1501ae771770SStanislav Sedov for (i = 0; i < num_data; i++) {
1502ae771770SStanislav Sedov if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1503ae771770SStanislav Sedov continue;
1504ae771770SStanislav Sedov len += data[i].data.length;
1505ae771770SStanislav Sedov }
1506ae771770SStanislav Sedov
1507ae771770SStanislav Sedov p = q = malloc(len);
1508ae771770SStanislav Sedov if (p == NULL)
1509ae771770SStanislav Sedov return ENOMEM;
1510ae771770SStanislav Sedov
1511ae771770SStanislav Sedov memcpy(q, hiv->data.data, hiv->data.length);
1512ae771770SStanislav Sedov q += hiv->data.length;
1513ae771770SStanislav Sedov for (i = 0; i < num_data; i++) {
1514ae771770SStanislav Sedov if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1515ae771770SStanislav Sedov data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1516ae771770SStanislav Sedov continue;
1517ae771770SStanislav Sedov memcpy(q, data[i].data.data, data[i].data.length);
1518ae771770SStanislav Sedov q += data[i].data.length;
1519ae771770SStanislav Sedov }
1520ae771770SStanislav Sedov
1521ae771770SStanislav Sedov cksum.checksum.data = tiv->data.data;
1522ae771770SStanislav Sedov cksum.checksum.length = tiv->data.length;
1523ae771770SStanislav Sedov cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
1524ae771770SStanislav Sedov
1525ae771770SStanislav Sedov ret = verify_checksum(context,
1526ae771770SStanislav Sedov crypto,
1527ae771770SStanislav Sedov INTEGRITY_USAGE(usage),
1528ae771770SStanislav Sedov p,
1529ae771770SStanislav Sedov len,
1530ae771770SStanislav Sedov &cksum);
1531ae771770SStanislav Sedov free(p);
1532ae771770SStanislav Sedov return ret;
1533ae771770SStanislav Sedov }
1534ae771770SStanislav Sedov
1535ae771770SStanislav Sedov /**
1536ae771770SStanislav Sedov * Create a Kerberos message checksum.
1537ae771770SStanislav Sedov *
1538ae771770SStanislav Sedov * @param context Kerberos context
1539ae771770SStanislav Sedov * @param crypto Kerberos crypto context
1540ae771770SStanislav Sedov * @param usage Key usage for this buffer
1541ae771770SStanislav Sedov * @param data array of buffers to process
1542ae771770SStanislav Sedov * @param num_data length of array
1543ae771770SStanislav Sedov * @param type output data
1544ae771770SStanislav Sedov *
1545ae771770SStanislav Sedov * @return Return an error code or 0.
1546ae771770SStanislav Sedov * @ingroup krb5_crypto
1547ae771770SStanislav Sedov */
1548ae771770SStanislav Sedov
1549ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_create_checksum_iov(krb5_context context,krb5_crypto crypto,unsigned usage,krb5_crypto_iov * data,unsigned int num_data,krb5_cksumtype * type)1550ae771770SStanislav Sedov krb5_create_checksum_iov(krb5_context context,
1551ae771770SStanislav Sedov krb5_crypto crypto,
1552ae771770SStanislav Sedov unsigned usage,
1553ae771770SStanislav Sedov krb5_crypto_iov *data,
1554ae771770SStanislav Sedov unsigned int num_data,
1555ae771770SStanislav Sedov krb5_cksumtype *type)
1556ae771770SStanislav Sedov {
1557ae771770SStanislav Sedov Checksum cksum;
1558ae771770SStanislav Sedov krb5_crypto_iov *civ;
1559ae771770SStanislav Sedov krb5_error_code ret;
1560ae771770SStanislav Sedov size_t i;
1561ae771770SStanislav Sedov size_t len;
1562ae771770SStanislav Sedov char *p, *q;
1563ae771770SStanislav Sedov
1564ae771770SStanislav Sedov if(!derived_crypto(context, crypto)) {
1565ae771770SStanislav Sedov krb5_clear_error_message(context);
1566ae771770SStanislav Sedov return KRB5_CRYPTO_INTERNAL;
1567ae771770SStanislav Sedov }
1568ae771770SStanislav Sedov
1569ae771770SStanislav Sedov civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
1570ae771770SStanislav Sedov if (civ == NULL)
1571ae771770SStanislav Sedov return KRB5_BAD_MSIZE;
1572ae771770SStanislav Sedov
1573ae771770SStanislav Sedov len = 0;
1574ae771770SStanislav Sedov for (i = 0; i < num_data; i++) {
1575ae771770SStanislav Sedov if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1576ae771770SStanislav Sedov data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1577ae771770SStanislav Sedov continue;
1578ae771770SStanislav Sedov len += data[i].data.length;
1579ae771770SStanislav Sedov }
1580ae771770SStanislav Sedov
1581ae771770SStanislav Sedov p = q = malloc(len);
1582ae771770SStanislav Sedov
1583ae771770SStanislav Sedov for (i = 0; i < num_data; i++) {
1584ae771770SStanislav Sedov if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1585ae771770SStanislav Sedov data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1586ae771770SStanislav Sedov continue;
1587ae771770SStanislav Sedov memcpy(q, data[i].data.data, data[i].data.length);
1588ae771770SStanislav Sedov q += data[i].data.length;
1589ae771770SStanislav Sedov }
1590ae771770SStanislav Sedov
1591ae771770SStanislav Sedov ret = krb5_create_checksum(context, crypto, usage, 0, p, len, &cksum);
1592ae771770SStanislav Sedov free(p);
1593ae771770SStanislav Sedov if (ret)
1594ae771770SStanislav Sedov return ret;
1595ae771770SStanislav Sedov
1596ae771770SStanislav Sedov if (type)
1597ae771770SStanislav Sedov *type = cksum.cksumtype;
1598ae771770SStanislav Sedov
1599ae771770SStanislav Sedov if (cksum.checksum.length > civ->data.length) {
1600ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_BAD_MSIZE,
1601ae771770SStanislav Sedov N_("Checksum larger then input buffer", ""));
1602ae771770SStanislav Sedov free_Checksum(&cksum);
1603ae771770SStanislav Sedov return KRB5_BAD_MSIZE;
1604ae771770SStanislav Sedov }
1605ae771770SStanislav Sedov
1606ae771770SStanislav Sedov civ->data.length = cksum.checksum.length;
1607ae771770SStanislav Sedov memcpy(civ->data.data, cksum.checksum.data, civ->data.length);
1608ae771770SStanislav Sedov free_Checksum(&cksum);
1609ae771770SStanislav Sedov
1610ae771770SStanislav Sedov return 0;
1611ae771770SStanislav Sedov }
1612ae771770SStanislav Sedov
1613ae771770SStanislav Sedov /**
1614ae771770SStanislav Sedov * Verify a Kerberos message checksum.
1615ae771770SStanislav Sedov *
1616ae771770SStanislav Sedov * @param context Kerberos context
1617ae771770SStanislav Sedov * @param crypto Kerberos crypto context
1618ae771770SStanislav Sedov * @param usage Key usage for this buffer
1619ae771770SStanislav Sedov * @param data array of buffers to process
1620ae771770SStanislav Sedov * @param num_data length of array
1621ae771770SStanislav Sedov * @param type return checksum type if not NULL
1622ae771770SStanislav Sedov *
1623ae771770SStanislav Sedov * @return Return an error code or 0.
1624ae771770SStanislav Sedov * @ingroup krb5_crypto
1625ae771770SStanislav Sedov */
1626ae771770SStanislav Sedov
1627ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_verify_checksum_iov(krb5_context context,krb5_crypto crypto,unsigned usage,krb5_crypto_iov * data,unsigned int num_data,krb5_cksumtype * type)1628ae771770SStanislav Sedov krb5_verify_checksum_iov(krb5_context context,
1629ae771770SStanislav Sedov krb5_crypto crypto,
1630ae771770SStanislav Sedov unsigned usage,
1631ae771770SStanislav Sedov krb5_crypto_iov *data,
1632ae771770SStanislav Sedov unsigned int num_data,
1633ae771770SStanislav Sedov krb5_cksumtype *type)
1634ae771770SStanislav Sedov {
1635ae771770SStanislav Sedov struct _krb5_encryption_type *et = crypto->et;
1636ae771770SStanislav Sedov Checksum cksum;
1637ae771770SStanislav Sedov krb5_crypto_iov *civ;
1638ae771770SStanislav Sedov krb5_error_code ret;
1639ae771770SStanislav Sedov size_t i;
1640ae771770SStanislav Sedov size_t len;
1641ae771770SStanislav Sedov char *p, *q;
1642ae771770SStanislav Sedov
1643ae771770SStanislav Sedov if(!derived_crypto(context, crypto)) {
1644ae771770SStanislav Sedov krb5_clear_error_message(context);
1645ae771770SStanislav Sedov return KRB5_CRYPTO_INTERNAL;
1646ae771770SStanislav Sedov }
1647ae771770SStanislav Sedov
1648ae771770SStanislav Sedov civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
1649ae771770SStanislav Sedov if (civ == NULL)
1650ae771770SStanislav Sedov return KRB5_BAD_MSIZE;
1651ae771770SStanislav Sedov
1652ae771770SStanislav Sedov len = 0;
1653ae771770SStanislav Sedov for (i = 0; i < num_data; i++) {
1654ae771770SStanislav Sedov if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1655ae771770SStanislav Sedov data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1656ae771770SStanislav Sedov continue;
1657ae771770SStanislav Sedov len += data[i].data.length;
1658ae771770SStanislav Sedov }
1659ae771770SStanislav Sedov
1660ae771770SStanislav Sedov p = q = malloc(len);
1661ae771770SStanislav Sedov
1662ae771770SStanislav Sedov for (i = 0; i < num_data; i++) {
1663ae771770SStanislav Sedov if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1664ae771770SStanislav Sedov data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1665ae771770SStanislav Sedov continue;
1666ae771770SStanislav Sedov memcpy(q, data[i].data.data, data[i].data.length);
1667ae771770SStanislav Sedov q += data[i].data.length;
1668ae771770SStanislav Sedov }
1669ae771770SStanislav Sedov
1670ae771770SStanislav Sedov cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
1671ae771770SStanislav Sedov cksum.checksum.length = civ->data.length;
1672ae771770SStanislav Sedov cksum.checksum.data = civ->data.data;
1673ae771770SStanislav Sedov
1674ae771770SStanislav Sedov ret = krb5_verify_checksum(context, crypto, usage, p, len, &cksum);
1675ae771770SStanislav Sedov free(p);
1676ae771770SStanislav Sedov
1677ae771770SStanislav Sedov if (ret == 0 && type)
1678ae771770SStanislav Sedov *type = cksum.cksumtype;
1679ae771770SStanislav Sedov
1680ae771770SStanislav Sedov return ret;
1681ae771770SStanislav Sedov }
1682ae771770SStanislav Sedov
1683ae771770SStanislav Sedov
1684ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_length(krb5_context context,krb5_crypto crypto,int type,size_t * len)1685ae771770SStanislav Sedov krb5_crypto_length(krb5_context context,
1686ae771770SStanislav Sedov krb5_crypto crypto,
1687ae771770SStanislav Sedov int type,
1688ae771770SStanislav Sedov size_t *len)
1689ae771770SStanislav Sedov {
1690ae771770SStanislav Sedov if (!derived_crypto(context, crypto)) {
1691ae771770SStanislav Sedov krb5_set_error_message(context, EINVAL, "not a derived crypto");
1692ae771770SStanislav Sedov return EINVAL;
1693ae771770SStanislav Sedov }
1694ae771770SStanislav Sedov
1695ae771770SStanislav Sedov switch(type) {
1696ae771770SStanislav Sedov case KRB5_CRYPTO_TYPE_EMPTY:
1697ae771770SStanislav Sedov *len = 0;
1698ae771770SStanislav Sedov return 0;
1699ae771770SStanislav Sedov case KRB5_CRYPTO_TYPE_HEADER:
1700ae771770SStanislav Sedov *len = crypto->et->blocksize;
1701ae771770SStanislav Sedov return 0;
1702ae771770SStanislav Sedov case KRB5_CRYPTO_TYPE_DATA:
1703ae771770SStanislav Sedov case KRB5_CRYPTO_TYPE_SIGN_ONLY:
1704ae771770SStanislav Sedov /* len must already been filled in */
1705ae771770SStanislav Sedov return 0;
1706ae771770SStanislav Sedov case KRB5_CRYPTO_TYPE_PADDING:
1707ae771770SStanislav Sedov if (crypto->et->padsize > 1)
1708ae771770SStanislav Sedov *len = crypto->et->padsize;
1709ae771770SStanislav Sedov else
1710ae771770SStanislav Sedov *len = 0;
1711ae771770SStanislav Sedov return 0;
1712ae771770SStanislav Sedov case KRB5_CRYPTO_TYPE_TRAILER:
1713ae771770SStanislav Sedov *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
1714ae771770SStanislav Sedov return 0;
1715ae771770SStanislav Sedov case KRB5_CRYPTO_TYPE_CHECKSUM:
1716ae771770SStanislav Sedov if (crypto->et->keyed_checksum)
1717ae771770SStanislav Sedov *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
1718ae771770SStanislav Sedov else
1719ae771770SStanislav Sedov *len = CHECKSUMSIZE(crypto->et->checksum);
1720ae771770SStanislav Sedov return 0;
1721ae771770SStanislav Sedov }
1722ae771770SStanislav Sedov krb5_set_error_message(context, EINVAL,
1723ae771770SStanislav Sedov "%d not a supported type", type);
1724ae771770SStanislav Sedov return EINVAL;
1725ae771770SStanislav Sedov }
1726ae771770SStanislav Sedov
1727ae771770SStanislav Sedov
1728ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_length_iov(krb5_context context,krb5_crypto crypto,krb5_crypto_iov * data,unsigned int num_data)1729ae771770SStanislav Sedov krb5_crypto_length_iov(krb5_context context,
1730ae771770SStanislav Sedov krb5_crypto crypto,
1731ae771770SStanislav Sedov krb5_crypto_iov *data,
1732ae771770SStanislav Sedov unsigned int num_data)
1733ae771770SStanislav Sedov {
1734ae771770SStanislav Sedov krb5_error_code ret;
1735ae771770SStanislav Sedov size_t i;
1736ae771770SStanislav Sedov
1737ae771770SStanislav Sedov for (i = 0; i < num_data; i++) {
1738ae771770SStanislav Sedov ret = krb5_crypto_length(context, crypto,
1739ae771770SStanislav Sedov data[i].flags,
1740ae771770SStanislav Sedov &data[i].data.length);
1741ae771770SStanislav Sedov if (ret)
1742ae771770SStanislav Sedov return ret;
1743ae771770SStanislav Sedov }
1744ae771770SStanislav Sedov return 0;
1745ae771770SStanislav Sedov }
1746ae771770SStanislav Sedov
1747ae771770SStanislav Sedov
1748ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_encrypt_ivec(krb5_context context,krb5_crypto crypto,unsigned usage,const void * data,size_t len,krb5_data * result,void * ivec)174947085b17SAssar Westerlund krb5_encrypt_ivec(krb5_context context,
175047085b17SAssar Westerlund krb5_crypto crypto,
175147085b17SAssar Westerlund unsigned usage,
175233f12199SDoug Rabson const void *data,
175347085b17SAssar Westerlund size_t len,
175447085b17SAssar Westerlund krb5_data *result,
175547085b17SAssar Westerlund void *ivec)
175647085b17SAssar Westerlund {
175747085b17SAssar Westerlund if(derived_crypto(context, crypto))
175847085b17SAssar Westerlund return encrypt_internal_derived(context, crypto, usage,
175947085b17SAssar Westerlund data, len, result, ivec);
176047085b17SAssar Westerlund else if (special_crypto(context, crypto))
176147085b17SAssar Westerlund return encrypt_internal_special (context, crypto, usage,
176247085b17SAssar Westerlund data, len, result, ivec);
176347085b17SAssar Westerlund else
176447085b17SAssar Westerlund return encrypt_internal(context, crypto, data, len, result, ivec);
176547085b17SAssar Westerlund }
176647085b17SAssar Westerlund
1767ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_encrypt(krb5_context context,krb5_crypto crypto,unsigned usage,const void * data,size_t len,krb5_data * result)1768b528cefcSMark Murray krb5_encrypt(krb5_context context,
1769b528cefcSMark Murray krb5_crypto crypto,
1770b528cefcSMark Murray unsigned usage,
177133f12199SDoug Rabson const void *data,
1772b528cefcSMark Murray size_t len,
1773b528cefcSMark Murray krb5_data *result)
1774b528cefcSMark Murray {
177547085b17SAssar Westerlund return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
1776b528cefcSMark Murray }
1777b528cefcSMark Murray
1778ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_encrypt_EncryptedData(krb5_context context,krb5_crypto crypto,unsigned usage,void * data,size_t len,int kvno,EncryptedData * result)1779b528cefcSMark Murray krb5_encrypt_EncryptedData(krb5_context context,
1780b528cefcSMark Murray krb5_crypto crypto,
1781b528cefcSMark Murray unsigned usage,
1782b528cefcSMark Murray void *data,
1783b528cefcSMark Murray size_t len,
1784b528cefcSMark Murray int kvno,
1785b528cefcSMark Murray EncryptedData *result)
1786b528cefcSMark Murray {
1787b528cefcSMark Murray result->etype = CRYPTO_ETYPE(crypto);
1788b528cefcSMark Murray if(kvno){
1789b528cefcSMark Murray ALLOC(result->kvno, 1);
1790b528cefcSMark Murray *result->kvno = kvno;
1791b528cefcSMark Murray }else
1792b528cefcSMark Murray result->kvno = NULL;
1793b528cefcSMark Murray return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
1794b528cefcSMark Murray }
1795b528cefcSMark Murray
1796ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_decrypt_ivec(krb5_context context,krb5_crypto crypto,unsigned usage,void * data,size_t len,krb5_data * result,void * ivec)179747085b17SAssar Westerlund krb5_decrypt_ivec(krb5_context context,
179847085b17SAssar Westerlund krb5_crypto crypto,
179947085b17SAssar Westerlund unsigned usage,
180047085b17SAssar Westerlund void *data,
180147085b17SAssar Westerlund size_t len,
180247085b17SAssar Westerlund krb5_data *result,
180347085b17SAssar Westerlund void *ivec)
180447085b17SAssar Westerlund {
180547085b17SAssar Westerlund if(derived_crypto(context, crypto))
180647085b17SAssar Westerlund return decrypt_internal_derived(context, crypto, usage,
180747085b17SAssar Westerlund data, len, result, ivec);
180847085b17SAssar Westerlund else if (special_crypto (context, crypto))
180947085b17SAssar Westerlund return decrypt_internal_special(context, crypto, usage,
181047085b17SAssar Westerlund data, len, result, ivec);
181147085b17SAssar Westerlund else
181247085b17SAssar Westerlund return decrypt_internal(context, crypto, data, len, result, ivec);
181347085b17SAssar Westerlund }
181447085b17SAssar Westerlund
1815ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_decrypt(krb5_context context,krb5_crypto crypto,unsigned usage,void * data,size_t len,krb5_data * result)1816b528cefcSMark Murray krb5_decrypt(krb5_context context,
1817b528cefcSMark Murray krb5_crypto crypto,
1818b528cefcSMark Murray unsigned usage,
1819b528cefcSMark Murray void *data,
1820b528cefcSMark Murray size_t len,
1821b528cefcSMark Murray krb5_data *result)
1822b528cefcSMark Murray {
182347085b17SAssar Westerlund return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
182447085b17SAssar Westerlund NULL);
1825b528cefcSMark Murray }
1826b528cefcSMark Murray
1827ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_decrypt_EncryptedData(krb5_context context,krb5_crypto crypto,unsigned usage,const EncryptedData * e,krb5_data * result)1828b528cefcSMark Murray krb5_decrypt_EncryptedData(krb5_context context,
1829b528cefcSMark Murray krb5_crypto crypto,
1830b528cefcSMark Murray unsigned usage,
183147085b17SAssar Westerlund const EncryptedData *e,
1832b528cefcSMark Murray krb5_data *result)
1833b528cefcSMark Murray {
1834b528cefcSMark Murray return krb5_decrypt(context, crypto, usage,
1835b528cefcSMark Murray e->cipher.data, e->cipher.length, result);
1836b528cefcSMark Murray }
1837b528cefcSMark Murray
1838b528cefcSMark Murray /************************************************************
1839b528cefcSMark Murray * *
1840b528cefcSMark Murray ************************************************************/
1841b528cefcSMark Murray
1842ae771770SStanislav Sedov krb5_error_code
_krb5_derive_key(krb5_context context,struct _krb5_encryption_type * et,struct _krb5_key_data * key,const void * constant,size_t len)1843ae771770SStanislav Sedov _krb5_derive_key(krb5_context context,
1844ae771770SStanislav Sedov struct _krb5_encryption_type *et,
1845ae771770SStanislav Sedov struct _krb5_key_data *key,
1846c80b5a63SAssar Westerlund const void *constant,
1847b528cefcSMark Murray size_t len)
1848b528cefcSMark Murray {
1849ae771770SStanislav Sedov unsigned char *k = NULL;
1850b528cefcSMark Murray unsigned int nblocks = 0, i;
1851b528cefcSMark Murray krb5_error_code ret = 0;
1852ae771770SStanislav Sedov struct _krb5_key_type *kt = et->keytype;
185333f12199SDoug Rabson
1854b528cefcSMark Murray ret = _key_schedule(context, key);
1855b528cefcSMark Murray if(ret)
1856b528cefcSMark Murray return ret;
185733f12199SDoug Rabson if(et->blocksize * 8 < kt->bits || len != et->blocksize) {
1858b528cefcSMark Murray nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
1859b528cefcSMark Murray k = malloc(nblocks * et->blocksize);
1860c80b5a63SAssar Westerlund if(k == NULL) {
1861ae771770SStanislav Sedov ret = ENOMEM;
1862ae771770SStanislav Sedov krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1863ae771770SStanislav Sedov goto out;
1864c80b5a63SAssar Westerlund }
186533f12199SDoug Rabson ret = _krb5_n_fold(constant, len, k, et->blocksize);
186633f12199SDoug Rabson if (ret) {
1867ae771770SStanislav Sedov krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1868ae771770SStanislav Sedov goto out;
186933f12199SDoug Rabson }
1870ae771770SStanislav Sedov
1871b528cefcSMark Murray for(i = 0; i < nblocks; i++) {
1872b528cefcSMark Murray if(i > 0)
1873b528cefcSMark Murray memcpy(k + i * et->blocksize,
1874b528cefcSMark Murray k + (i - 1) * et->blocksize,
1875b528cefcSMark Murray et->blocksize);
1876c80b5a63SAssar Westerlund (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize,
1877c80b5a63SAssar Westerlund 1, 0, NULL);
1878b528cefcSMark Murray }
1879b528cefcSMark Murray } else {
188047085b17SAssar Westerlund /* this case is probably broken, but won't be run anyway */
1881b528cefcSMark Murray void *c = malloc(len);
1882b528cefcSMark Murray size_t res_len = (kt->bits + 7) / 8;
1883b528cefcSMark Murray
1884c80b5a63SAssar Westerlund if(len != 0 && c == NULL) {
1885ae771770SStanislav Sedov ret = ENOMEM;
1886ae771770SStanislav Sedov krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1887ae771770SStanislav Sedov goto out;
1888c80b5a63SAssar Westerlund }
1889b528cefcSMark Murray memcpy(c, constant, len);
1890c80b5a63SAssar Westerlund (*et->encrypt)(context, key, c, len, 1, 0, NULL);
1891b528cefcSMark Murray k = malloc(res_len);
1892c80b5a63SAssar Westerlund if(res_len != 0 && k == NULL) {
1893c80b5a63SAssar Westerlund free(c);
1894ae771770SStanislav Sedov ret = ENOMEM;
1895ae771770SStanislav Sedov krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1896ae771770SStanislav Sedov goto out;
1897c80b5a63SAssar Westerlund }
189833f12199SDoug Rabson ret = _krb5_n_fold(c, len, k, res_len);
1899b528cefcSMark Murray free(c);
1900ae771770SStanislav Sedov if (ret) {
1901ae771770SStanislav Sedov krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1902ae771770SStanislav Sedov goto out;
1903ae771770SStanislav Sedov }
1904b528cefcSMark Murray }
1905b528cefcSMark Murray
1906b528cefcSMark Murray /* XXX keytype dependent post-processing */
1907b528cefcSMark Murray switch(kt->type) {
1908ae771770SStanislav Sedov case ETYPE_OLD_DES3_CBC_SHA1:
1909ae771770SStanislav Sedov _krb5_DES3_random_to_key(context, key->key, k, nblocks * et->blocksize);
1910b528cefcSMark Murray break;
1911ae771770SStanislav Sedov case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
1912ae771770SStanislav Sedov case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
19132d485134SJacques Vidrine memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
19142d485134SJacques Vidrine break;
1915b528cefcSMark Murray default:
1916b528cefcSMark Murray ret = KRB5_CRYPTO_INTERNAL;
1917ae771770SStanislav Sedov krb5_set_error_message(context, ret,
1918ae771770SStanislav Sedov N_("derive_key() called with unknown keytype (%u)", ""),
1919ae771770SStanislav Sedov kt->type);
1920b528cefcSMark Murray break;
1921b528cefcSMark Murray }
1922ae771770SStanislav Sedov out:
192333f12199SDoug Rabson if (key->schedule) {
1924ae771770SStanislav Sedov free_key_schedule(context, key, et);
192533f12199SDoug Rabson key->schedule = NULL;
192633f12199SDoug Rabson }
1927ae771770SStanislav Sedov if (k) {
1928b528cefcSMark Murray memset(k, 0, nblocks * et->blocksize);
1929b528cefcSMark Murray free(k);
1930ae771770SStanislav Sedov }
1931b528cefcSMark Murray return ret;
1932b528cefcSMark Murray }
1933b528cefcSMark Murray
1934ae771770SStanislav Sedov static struct _krb5_key_data *
_new_derived_key(krb5_crypto crypto,unsigned usage)1935b528cefcSMark Murray _new_derived_key(krb5_crypto crypto, unsigned usage)
1936b528cefcSMark Murray {
1937ae771770SStanislav Sedov struct _krb5_key_usage *d = crypto->key_usage;
1938b528cefcSMark Murray d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
1939b528cefcSMark Murray if(d == NULL)
1940b528cefcSMark Murray return NULL;
1941b528cefcSMark Murray crypto->key_usage = d;
1942b528cefcSMark Murray d += crypto->num_key_usage++;
1943b528cefcSMark Murray memset(d, 0, sizeof(*d));
1944b528cefcSMark Murray d->usage = usage;
1945b528cefcSMark Murray return &d->key;
1946b528cefcSMark Murray }
1947b528cefcSMark Murray
1948ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_derive_key(krb5_context context,const krb5_keyblock * key,krb5_enctype etype,const void * constant,size_t constant_len,krb5_keyblock ** derived_key)1949c80b5a63SAssar Westerlund krb5_derive_key(krb5_context context,
1950c80b5a63SAssar Westerlund const krb5_keyblock *key,
1951c80b5a63SAssar Westerlund krb5_enctype etype,
1952c80b5a63SAssar Westerlund const void *constant,
1953c80b5a63SAssar Westerlund size_t constant_len,
1954c80b5a63SAssar Westerlund krb5_keyblock **derived_key)
1955c80b5a63SAssar Westerlund {
1956c80b5a63SAssar Westerlund krb5_error_code ret;
1957ae771770SStanislav Sedov struct _krb5_encryption_type *et;
1958ae771770SStanislav Sedov struct _krb5_key_data d;
1959c80b5a63SAssar Westerlund
196033f12199SDoug Rabson *derived_key = NULL;
196133f12199SDoug Rabson
1962ae771770SStanislav Sedov et = _krb5_find_enctype (etype);
1963c80b5a63SAssar Westerlund if (et == NULL) {
1964ae771770SStanislav Sedov return unsupported_enctype (context, etype);
1965c80b5a63SAssar Westerlund }
1966c80b5a63SAssar Westerlund
196733f12199SDoug Rabson ret = krb5_copy_keyblock(context, key, &d.key);
1968c80b5a63SAssar Westerlund if (ret)
1969c80b5a63SAssar Westerlund return ret;
1970c80b5a63SAssar Westerlund
1971c80b5a63SAssar Westerlund d.schedule = NULL;
1972ae771770SStanislav Sedov ret = _krb5_derive_key(context, et, &d, constant, constant_len);
197333f12199SDoug Rabson if (ret == 0)
1974c80b5a63SAssar Westerlund ret = krb5_copy_keyblock(context, d.key, derived_key);
1975ae771770SStanislav Sedov _krb5_free_key_data(context, &d, et);
1976c80b5a63SAssar Westerlund return ret;
1977c80b5a63SAssar Westerlund }
1978c80b5a63SAssar Westerlund
1979b528cefcSMark Murray static krb5_error_code
_get_derived_key(krb5_context context,krb5_crypto crypto,unsigned usage,struct _krb5_key_data ** key)1980b528cefcSMark Murray _get_derived_key(krb5_context context,
1981b528cefcSMark Murray krb5_crypto crypto,
1982b528cefcSMark Murray unsigned usage,
1983ae771770SStanislav Sedov struct _krb5_key_data **key)
1984b528cefcSMark Murray {
1985b528cefcSMark Murray int i;
1986ae771770SStanislav Sedov struct _krb5_key_data *d;
1987b528cefcSMark Murray unsigned char constant[5];
1988b528cefcSMark Murray
1989b528cefcSMark Murray for(i = 0; i < crypto->num_key_usage; i++)
1990b528cefcSMark Murray if(crypto->key_usage[i].usage == usage) {
1991b528cefcSMark Murray *key = &crypto->key_usage[i].key;
1992b528cefcSMark Murray return 0;
1993b528cefcSMark Murray }
1994b528cefcSMark Murray d = _new_derived_key(crypto, usage);
1995c80b5a63SAssar Westerlund if(d == NULL) {
1996ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1997b528cefcSMark Murray return ENOMEM;
1998c80b5a63SAssar Westerlund }
1999b528cefcSMark Murray krb5_copy_keyblock(context, crypto->key.key, &d->key);
2000b528cefcSMark Murray _krb5_put_int(constant, usage, 5);
2001ae771770SStanislav Sedov _krb5_derive_key(context, crypto->et, d, constant, sizeof(constant));
2002b528cefcSMark Murray *key = d;
2003b528cefcSMark Murray return 0;
2004b528cefcSMark Murray }
2005b528cefcSMark Murray
2006ae771770SStanislav Sedov /**
2007ae771770SStanislav Sedov * Create a crypto context used for all encryption and signature
2008ae771770SStanislav Sedov * operation. The encryption type to use is taken from the key, but
2009ae771770SStanislav Sedov * can be overridden with the enctype parameter. This can be useful
2010ae771770SStanislav Sedov * for encryptions types which is compatiable (DES for example).
2011ae771770SStanislav Sedov *
2012ae771770SStanislav Sedov * To free the crypto context, use krb5_crypto_destroy().
2013ae771770SStanislav Sedov *
2014ae771770SStanislav Sedov * @param context Kerberos context
2015ae771770SStanislav Sedov * @param key the key block information with all key data
2016ae771770SStanislav Sedov * @param etype the encryption type
2017ae771770SStanislav Sedov * @param crypto the resulting crypto context
2018ae771770SStanislav Sedov *
2019ae771770SStanislav Sedov * @return Return an error code or 0.
2020ae771770SStanislav Sedov *
2021ae771770SStanislav Sedov * @ingroup krb5_crypto
2022ae771770SStanislav Sedov */
2023b528cefcSMark Murray
2024ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_init(krb5_context context,const krb5_keyblock * key,krb5_enctype etype,krb5_crypto * crypto)2025b528cefcSMark Murray krb5_crypto_init(krb5_context context,
2026c80b5a63SAssar Westerlund const krb5_keyblock *key,
2027b528cefcSMark Murray krb5_enctype etype,
2028b528cefcSMark Murray krb5_crypto *crypto)
2029b528cefcSMark Murray {
2030b528cefcSMark Murray krb5_error_code ret;
2031b528cefcSMark Murray ALLOC(*crypto, 1);
2032c80b5a63SAssar Westerlund if(*crypto == NULL) {
2033ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2034b528cefcSMark Murray return ENOMEM;
2035c80b5a63SAssar Westerlund }
2036b528cefcSMark Murray if(etype == ETYPE_NULL)
2037b528cefcSMark Murray etype = key->keytype;
2038ae771770SStanislav Sedov (*crypto)->et = _krb5_find_enctype(etype);
203933f12199SDoug Rabson if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) {
2040b528cefcSMark Murray free(*crypto);
204133f12199SDoug Rabson *crypto = NULL;
2042ae771770SStanislav Sedov return unsupported_enctype(context, etype);
2043b528cefcSMark Murray }
20447b173f65SJacques Vidrine if((*crypto)->et->keytype->size != key->keyvalue.length) {
20457b173f65SJacques Vidrine free(*crypto);
204633f12199SDoug Rabson *crypto = NULL;
2047ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_BAD_KEYSIZE,
2048ae771770SStanislav Sedov "encryption key has bad length");
20497b173f65SJacques Vidrine return KRB5_BAD_KEYSIZE;
20507b173f65SJacques Vidrine }
2051b528cefcSMark Murray ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
2052b528cefcSMark Murray if(ret) {
2053b528cefcSMark Murray free(*crypto);
205433f12199SDoug Rabson *crypto = NULL;
2055b528cefcSMark Murray return ret;
2056b528cefcSMark Murray }
2057*476d63e0SCy Schubert ret = fbsd_ossl_provider_load();
2058*476d63e0SCy Schubert if (ret)
2059*476d63e0SCy Schubert return ret;
2060b528cefcSMark Murray (*crypto)->key.schedule = NULL;
2061b528cefcSMark Murray (*crypto)->num_key_usage = 0;
2062b528cefcSMark Murray (*crypto)->key_usage = NULL;
2063b528cefcSMark Murray return 0;
2064b528cefcSMark Murray }
2065b528cefcSMark Murray
2066b528cefcSMark Murray static void
free_key_schedule(krb5_context context,struct _krb5_key_data * key,struct _krb5_encryption_type * et)2067ae771770SStanislav Sedov free_key_schedule(krb5_context context,
2068ae771770SStanislav Sedov struct _krb5_key_data *key,
2069ae771770SStanislav Sedov struct _krb5_encryption_type *et)
2070ae771770SStanislav Sedov {
2071ae771770SStanislav Sedov if (et->keytype->cleanup)
2072ae771770SStanislav Sedov (*et->keytype->cleanup)(context, key);
2073ae771770SStanislav Sedov memset(key->schedule->data, 0, key->schedule->length);
2074ae771770SStanislav Sedov krb5_free_data(context, key->schedule);
2075ae771770SStanislav Sedov }
2076ae771770SStanislav Sedov
2077ae771770SStanislav Sedov void
_krb5_free_key_data(krb5_context context,struct _krb5_key_data * key,struct _krb5_encryption_type * et)2078ae771770SStanislav Sedov _krb5_free_key_data(krb5_context context, struct _krb5_key_data *key,
2079ae771770SStanislav Sedov struct _krb5_encryption_type *et)
2080b528cefcSMark Murray {
2081b528cefcSMark Murray krb5_free_keyblock(context, key->key);
2082b528cefcSMark Murray if(key->schedule) {
2083ae771770SStanislav Sedov free_key_schedule(context, key, et);
2084ae771770SStanislav Sedov key->schedule = NULL;
2085b528cefcSMark Murray }
2086b528cefcSMark Murray }
2087b528cefcSMark Murray
2088b528cefcSMark Murray static void
free_key_usage(krb5_context context,struct _krb5_key_usage * ku,struct _krb5_encryption_type * et)2089ae771770SStanislav Sedov free_key_usage(krb5_context context, struct _krb5_key_usage *ku,
2090ae771770SStanislav Sedov struct _krb5_encryption_type *et)
2091b528cefcSMark Murray {
2092ae771770SStanislav Sedov _krb5_free_key_data(context, &ku->key, et);
2093b528cefcSMark Murray }
2094b528cefcSMark Murray
2095ae771770SStanislav Sedov /**
2096ae771770SStanislav Sedov * Free a crypto context created by krb5_crypto_init().
2097ae771770SStanislav Sedov *
2098ae771770SStanislav Sedov * @param context Kerberos context
2099ae771770SStanislav Sedov * @param crypto crypto context to free
2100ae771770SStanislav Sedov *
2101ae771770SStanislav Sedov * @return Return an error code or 0.
2102ae771770SStanislav Sedov *
2103ae771770SStanislav Sedov * @ingroup krb5_crypto
2104ae771770SStanislav Sedov */
2105ae771770SStanislav Sedov
2106ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_destroy(krb5_context context,krb5_crypto crypto)2107b528cefcSMark Murray krb5_crypto_destroy(krb5_context context,
2108b528cefcSMark Murray krb5_crypto crypto)
2109b528cefcSMark Murray {
2110b528cefcSMark Murray int i;
2111b528cefcSMark Murray
2112b528cefcSMark Murray for(i = 0; i < crypto->num_key_usage; i++)
2113ae771770SStanislav Sedov free_key_usage(context, &crypto->key_usage[i], crypto->et);
2114b528cefcSMark Murray free(crypto->key_usage);
2115ae771770SStanislav Sedov _krb5_free_key_data(context, &crypto->key, crypto->et);
2116b528cefcSMark Murray free (crypto);
2117b528cefcSMark Murray return 0;
2118b528cefcSMark Murray }
2119b528cefcSMark Murray
2120ae771770SStanislav Sedov /**
2121ae771770SStanislav Sedov * Return the blocksize used algorithm referenced by the crypto context
2122ae771770SStanislav Sedov *
2123ae771770SStanislav Sedov * @param context Kerberos context
2124ae771770SStanislav Sedov * @param crypto crypto context to query
2125ae771770SStanislav Sedov * @param blocksize the resulting blocksize
2126ae771770SStanislav Sedov *
2127ae771770SStanislav Sedov * @return Return an error code or 0.
2128ae771770SStanislav Sedov *
2129ae771770SStanislav Sedov * @ingroup krb5_crypto
2130ae771770SStanislav Sedov */
2131ae771770SStanislav Sedov
2132ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_getblocksize(krb5_context context,krb5_crypto crypto,size_t * blocksize)213343a23712SJacques Vidrine krb5_crypto_getblocksize(krb5_context context,
213443a23712SJacques Vidrine krb5_crypto crypto,
213543a23712SJacques Vidrine size_t *blocksize)
213643a23712SJacques Vidrine {
213743a23712SJacques Vidrine *blocksize = crypto->et->blocksize;
213843a23712SJacques Vidrine return 0;
213943a23712SJacques Vidrine }
214043a23712SJacques Vidrine
2141ae771770SStanislav Sedov /**
2142ae771770SStanislav Sedov * Return the encryption type used by the crypto context
2143ae771770SStanislav Sedov *
2144ae771770SStanislav Sedov * @param context Kerberos context
2145ae771770SStanislav Sedov * @param crypto crypto context to query
2146ae771770SStanislav Sedov * @param enctype the resulting encryption type
2147ae771770SStanislav Sedov *
2148ae771770SStanislav Sedov * @return Return an error code or 0.
2149ae771770SStanislav Sedov *
2150ae771770SStanislav Sedov * @ingroup krb5_crypto
2151ae771770SStanislav Sedov */
2152ae771770SStanislav Sedov
2153ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_getenctype(krb5_context context,krb5_crypto crypto,krb5_enctype * enctype)215433f12199SDoug Rabson krb5_crypto_getenctype(krb5_context context,
215533f12199SDoug Rabson krb5_crypto crypto,
215633f12199SDoug Rabson krb5_enctype *enctype)
215733f12199SDoug Rabson {
215833f12199SDoug Rabson *enctype = crypto->et->type;
215933f12199SDoug Rabson return 0;
216033f12199SDoug Rabson }
216133f12199SDoug Rabson
2162ae771770SStanislav Sedov /**
2163ae771770SStanislav Sedov * Return the padding size used by the crypto context
2164ae771770SStanislav Sedov *
2165ae771770SStanislav Sedov * @param context Kerberos context
2166ae771770SStanislav Sedov * @param crypto crypto context to query
2167ae771770SStanislav Sedov * @param padsize the return padding size
2168ae771770SStanislav Sedov *
2169ae771770SStanislav Sedov * @return Return an error code or 0.
2170ae771770SStanislav Sedov *
2171ae771770SStanislav Sedov * @ingroup krb5_crypto
2172ae771770SStanislav Sedov */
2173ae771770SStanislav Sedov
2174ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_getpadsize(krb5_context context,krb5_crypto crypto,size_t * padsize)217533f12199SDoug Rabson krb5_crypto_getpadsize(krb5_context context,
217633f12199SDoug Rabson krb5_crypto crypto,
217733f12199SDoug Rabson size_t *padsize)
217833f12199SDoug Rabson {
217933f12199SDoug Rabson *padsize = crypto->et->padsize;
218033f12199SDoug Rabson return 0;
218133f12199SDoug Rabson }
218233f12199SDoug Rabson
2183ae771770SStanislav Sedov /**
2184ae771770SStanislav Sedov * Return the confounder size used by the crypto context
2185ae771770SStanislav Sedov *
2186ae771770SStanislav Sedov * @param context Kerberos context
2187ae771770SStanislav Sedov * @param crypto crypto context to query
2188ae771770SStanislav Sedov * @param confoundersize the returned confounder size
2189ae771770SStanislav Sedov *
2190ae771770SStanislav Sedov * @return Return an error code or 0.
2191ae771770SStanislav Sedov *
2192ae771770SStanislav Sedov * @ingroup krb5_crypto
2193ae771770SStanislav Sedov */
2194ae771770SStanislav Sedov
2195ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_getconfoundersize(krb5_context context,krb5_crypto crypto,size_t * confoundersize)219633f12199SDoug Rabson krb5_crypto_getconfoundersize(krb5_context context,
219733f12199SDoug Rabson krb5_crypto crypto,
219833f12199SDoug Rabson size_t *confoundersize)
219933f12199SDoug Rabson {
220033f12199SDoug Rabson *confoundersize = crypto->et->confoundersize;
220133f12199SDoug Rabson return 0;
220233f12199SDoug Rabson }
220333f12199SDoug Rabson
2204ae771770SStanislav Sedov
2205ae771770SStanislav Sedov /**
2206ae771770SStanislav Sedov * Disable encryption type
2207ae771770SStanislav Sedov *
2208ae771770SStanislav Sedov * @param context Kerberos 5 context
2209ae771770SStanislav Sedov * @param enctype encryption type to disable
2210ae771770SStanislav Sedov *
2211ae771770SStanislav Sedov * @return Return an error code or 0.
2212ae771770SStanislav Sedov *
2213ae771770SStanislav Sedov * @ingroup krb5_crypto
2214ae771770SStanislav Sedov */
2215ae771770SStanislav Sedov
2216ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_enctype_disable(krb5_context context,krb5_enctype enctype)221733f12199SDoug Rabson krb5_enctype_disable(krb5_context context,
221833f12199SDoug Rabson krb5_enctype enctype)
221933f12199SDoug Rabson {
2220ae771770SStanislav Sedov struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
222133f12199SDoug Rabson if(et == NULL) {
222233f12199SDoug Rabson if (context)
2223ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2224ae771770SStanislav Sedov N_("encryption type %d not supported", ""),
222533f12199SDoug Rabson enctype);
222633f12199SDoug Rabson return KRB5_PROG_ETYPE_NOSUPP;
222733f12199SDoug Rabson }
222833f12199SDoug Rabson et->flags |= F_DISABLED;
222933f12199SDoug Rabson return 0;
223033f12199SDoug Rabson }
223133f12199SDoug Rabson
2232ae771770SStanislav Sedov /**
2233ae771770SStanislav Sedov * Enable encryption type
2234ae771770SStanislav Sedov *
2235ae771770SStanislav Sedov * @param context Kerberos 5 context
2236ae771770SStanislav Sedov * @param enctype encryption type to enable
2237ae771770SStanislav Sedov *
2238ae771770SStanislav Sedov * @return Return an error code or 0.
2239ae771770SStanislav Sedov *
2240ae771770SStanislav Sedov * @ingroup krb5_crypto
2241ae771770SStanislav Sedov */
2242b528cefcSMark Murray
2243ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_enctype_enable(krb5_context context,krb5_enctype enctype)2244ae771770SStanislav Sedov krb5_enctype_enable(krb5_context context,
2245ae771770SStanislav Sedov krb5_enctype enctype)
2246ae771770SStanislav Sedov {
2247ae771770SStanislav Sedov struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
2248c80b5a63SAssar Westerlund if(et == NULL) {
2249ae771770SStanislav Sedov if (context)
2250ae771770SStanislav Sedov krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2251ae771770SStanislav Sedov N_("encryption type %d not supported", ""),
2252ae771770SStanislav Sedov enctype);
2253b528cefcSMark Murray return KRB5_PROG_ETYPE_NOSUPP;
2254c80b5a63SAssar Westerlund }
2255ae771770SStanislav Sedov et->flags &= ~F_DISABLED;
2256ae771770SStanislav Sedov return 0;
2257ae771770SStanislav Sedov }
225833f12199SDoug Rabson
2259ae771770SStanislav Sedov /**
2260ae771770SStanislav Sedov * Enable or disable all weak encryption types
2261ae771770SStanislav Sedov *
2262ae771770SStanislav Sedov * @param context Kerberos 5 context
2263ae771770SStanislav Sedov * @param enable true to enable, false to disable
2264ae771770SStanislav Sedov *
2265ae771770SStanislav Sedov * @return Return an error code or 0.
2266ae771770SStanislav Sedov *
2267ae771770SStanislav Sedov * @ingroup krb5_crypto
2268ae771770SStanislav Sedov */
2269ae771770SStanislav Sedov
2270ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_allow_weak_crypto(krb5_context context,krb5_boolean enable)2271ae771770SStanislav Sedov krb5_allow_weak_crypto(krb5_context context,
2272ae771770SStanislav Sedov krb5_boolean enable)
2273ae771770SStanislav Sedov {
2274ae771770SStanislav Sedov int i;
2275ae771770SStanislav Sedov
2276ae771770SStanislav Sedov for(i = 0; i < _krb5_num_etypes; i++)
2277ae771770SStanislav Sedov if(_krb5_etypes[i]->flags & F_WEAK) {
2278ae771770SStanislav Sedov if(enable)
2279ae771770SStanislav Sedov _krb5_etypes[i]->flags &= ~F_DISABLED;
2280ae771770SStanislav Sedov else
2281ae771770SStanislav Sedov _krb5_etypes[i]->flags |= F_DISABLED;
2282bc865db6SJacques Vidrine }
2283ae771770SStanislav Sedov return 0;
2284b528cefcSMark Murray }
2285b528cefcSMark Murray
228647085b17SAssar Westerlund static size_t
wrapped_length(krb5_context context,krb5_crypto crypto,size_t data_len)228747085b17SAssar Westerlund wrapped_length (krb5_context context,
228847085b17SAssar Westerlund krb5_crypto crypto,
228947085b17SAssar Westerlund size_t data_len)
229047085b17SAssar Westerlund {
2291ae771770SStanislav Sedov struct _krb5_encryption_type *et = crypto->et;
22922d485134SJacques Vidrine size_t padsize = et->padsize;
229333f12199SDoug Rabson size_t checksumsize = CHECKSUMSIZE(et->checksum);
229447085b17SAssar Westerlund size_t res;
229547085b17SAssar Westerlund
229633f12199SDoug Rabson res = et->confoundersize + checksumsize + data_len;
22972d485134SJacques Vidrine res = (res + padsize - 1) / padsize * padsize;
229847085b17SAssar Westerlund return res;
229947085b17SAssar Westerlund }
230047085b17SAssar Westerlund
230147085b17SAssar Westerlund static size_t
wrapped_length_dervied(krb5_context context,krb5_crypto crypto,size_t data_len)230247085b17SAssar Westerlund wrapped_length_dervied (krb5_context context,
230347085b17SAssar Westerlund krb5_crypto crypto,
230447085b17SAssar Westerlund size_t data_len)
230547085b17SAssar Westerlund {
2306ae771770SStanislav Sedov struct _krb5_encryption_type *et = crypto->et;
23072d485134SJacques Vidrine size_t padsize = et->padsize;
230847085b17SAssar Westerlund size_t res;
230947085b17SAssar Westerlund
231047085b17SAssar Westerlund res = et->confoundersize + data_len;
23112d485134SJacques Vidrine res = (res + padsize - 1) / padsize * padsize;
231233f12199SDoug Rabson if (et->keyed_checksum)
231333f12199SDoug Rabson res += et->keyed_checksum->checksumsize;
231433f12199SDoug Rabson else
2315c80b5a63SAssar Westerlund res += et->checksum->checksumsize;
231647085b17SAssar Westerlund return res;
231747085b17SAssar Westerlund }
231847085b17SAssar Westerlund
2319b528cefcSMark Murray /*
2320b528cefcSMark Murray * Return the size of an encrypted packet of length `data_len'
2321b528cefcSMark Murray */
2322b528cefcSMark Murray
2323ae771770SStanislav Sedov KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL
krb5_get_wrapped_length(krb5_context context,krb5_crypto crypto,size_t data_len)2324b528cefcSMark Murray krb5_get_wrapped_length (krb5_context context,
2325b528cefcSMark Murray krb5_crypto crypto,
2326b528cefcSMark Murray size_t data_len)
2327b528cefcSMark Murray {
232847085b17SAssar Westerlund if (derived_crypto (context, crypto))
232947085b17SAssar Westerlund return wrapped_length_dervied (context, crypto, data_len);
233047085b17SAssar Westerlund else
233147085b17SAssar Westerlund return wrapped_length (context, crypto, data_len);
2332b528cefcSMark Murray }
2333b528cefcSMark Murray
233433f12199SDoug Rabson /*
233533f12199SDoug Rabson * Return the size of an encrypted packet of length `data_len'
233633f12199SDoug Rabson */
233733f12199SDoug Rabson
233833f12199SDoug Rabson static size_t
crypto_overhead(krb5_context context,krb5_crypto crypto)233933f12199SDoug Rabson crypto_overhead (krb5_context context,
234033f12199SDoug Rabson krb5_crypto crypto)
234133f12199SDoug Rabson {
2342ae771770SStanislav Sedov struct _krb5_encryption_type *et = crypto->et;
234333f12199SDoug Rabson size_t res;
234433f12199SDoug Rabson
234533f12199SDoug Rabson res = CHECKSUMSIZE(et->checksum);
234633f12199SDoug Rabson res += et->confoundersize;
234733f12199SDoug Rabson if (et->padsize > 1)
234833f12199SDoug Rabson res += et->padsize;
234933f12199SDoug Rabson return res;
235033f12199SDoug Rabson }
235133f12199SDoug Rabson
235233f12199SDoug Rabson static size_t
crypto_overhead_dervied(krb5_context context,krb5_crypto crypto)235333f12199SDoug Rabson crypto_overhead_dervied (krb5_context context,
235433f12199SDoug Rabson krb5_crypto crypto)
235533f12199SDoug Rabson {
2356ae771770SStanislav Sedov struct _krb5_encryption_type *et = crypto->et;
235733f12199SDoug Rabson size_t res;
235833f12199SDoug Rabson
235933f12199SDoug Rabson if (et->keyed_checksum)
236033f12199SDoug Rabson res = CHECKSUMSIZE(et->keyed_checksum);
236133f12199SDoug Rabson else
236233f12199SDoug Rabson res = CHECKSUMSIZE(et->checksum);
236333f12199SDoug Rabson res += et->confoundersize;
236433f12199SDoug Rabson if (et->padsize > 1)
236533f12199SDoug Rabson res += et->padsize;
236633f12199SDoug Rabson return res;
236733f12199SDoug Rabson }
236833f12199SDoug Rabson
2369ae771770SStanislav Sedov KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL
krb5_crypto_overhead(krb5_context context,krb5_crypto crypto)237033f12199SDoug Rabson krb5_crypto_overhead (krb5_context context, krb5_crypto crypto)
237133f12199SDoug Rabson {
237233f12199SDoug Rabson if (derived_crypto (context, crypto))
237333f12199SDoug Rabson return crypto_overhead_dervied (context, crypto);
237433f12199SDoug Rabson else
237533f12199SDoug Rabson return crypto_overhead (context, crypto);
237633f12199SDoug Rabson }
237733f12199SDoug Rabson
2378ae771770SStanislav Sedov /**
2379ae771770SStanislav Sedov * Converts the random bytestring to a protocol key according to
2380ae771770SStanislav Sedov * Kerberos crypto frame work. It may be assumed that all the bits of
2381ae771770SStanislav Sedov * the input string are equally random, even though the entropy
2382ae771770SStanislav Sedov * present in the random source may be limited.
2383ae771770SStanislav Sedov *
2384ae771770SStanislav Sedov * @param context Kerberos 5 context
2385ae771770SStanislav Sedov * @param type the enctype resulting key will be of
2386ae771770SStanislav Sedov * @param data input random data to convert to a key
2387ae771770SStanislav Sedov * @param size size of input random data, at least krb5_enctype_keysize() long
2388ae771770SStanislav Sedov * @param key key, output key, free with krb5_free_keyblock_contents()
2389ae771770SStanislav Sedov *
2390ae771770SStanislav Sedov * @return Return an error code or 0.
2391ae771770SStanislav Sedov *
2392ae771770SStanislav Sedov * @ingroup krb5_crypto
2393ae771770SStanislav Sedov */
2394ae771770SStanislav Sedov
2395ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_random_to_key(krb5_context context,krb5_enctype type,const void * data,size_t size,krb5_keyblock * key)239633f12199SDoug Rabson krb5_random_to_key(krb5_context context,
239733f12199SDoug Rabson krb5_enctype type,
239833f12199SDoug Rabson const void *data,
239933f12199SDoug Rabson size_t size,
240033f12199SDoug Rabson krb5_keyblock *key)
240133f12199SDoug Rabson {
240233f12199SDoug Rabson krb5_error_code ret;
2403ae771770SStanislav Sedov struct _krb5_encryption_type *et = _krb5_find_enctype(type);
240433f12199SDoug Rabson if(et == NULL) {
2405ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
2406ae771770SStanislav Sedov N_("encryption type %d not supported", ""),
240733f12199SDoug Rabson type);
240833f12199SDoug Rabson return KRB5_PROG_ETYPE_NOSUPP;
240933f12199SDoug Rabson }
241033f12199SDoug Rabson if ((et->keytype->bits + 7) / 8 > size) {
2411ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
2412ae771770SStanislav Sedov N_("encryption key %s needs %d bytes "
2413ae771770SStanislav Sedov "of random to make an encryption key "
2414ae771770SStanislav Sedov "out of it", ""),
241533f12199SDoug Rabson et->name, (int)et->keytype->size);
241633f12199SDoug Rabson return KRB5_PROG_ETYPE_NOSUPP;
241733f12199SDoug Rabson }
241833f12199SDoug Rabson ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
241933f12199SDoug Rabson if(ret)
242033f12199SDoug Rabson return ret;
242133f12199SDoug Rabson key->keytype = type;
242233f12199SDoug Rabson if (et->keytype->random_to_key)
242333f12199SDoug Rabson (*et->keytype->random_to_key)(context, key, data, size);
242433f12199SDoug Rabson else
242533f12199SDoug Rabson memcpy(key->keyvalue.data, data, et->keytype->size);
242633f12199SDoug Rabson
242733f12199SDoug Rabson return 0;
242833f12199SDoug Rabson }
242933f12199SDoug Rabson
243033f12199SDoug Rabson
243133f12199SDoug Rabson
2432ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_prf_length(krb5_context context,krb5_enctype type,size_t * length)243333f12199SDoug Rabson krb5_crypto_prf_length(krb5_context context,
243433f12199SDoug Rabson krb5_enctype type,
243533f12199SDoug Rabson size_t *length)
243633f12199SDoug Rabson {
2437ae771770SStanislav Sedov struct _krb5_encryption_type *et = _krb5_find_enctype(type);
243833f12199SDoug Rabson
243933f12199SDoug Rabson if(et == NULL || et->prf_length == 0) {
2440ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
2441ae771770SStanislav Sedov N_("encryption type %d not supported", ""),
244233f12199SDoug Rabson type);
244333f12199SDoug Rabson return KRB5_PROG_ETYPE_NOSUPP;
244433f12199SDoug Rabson }
244533f12199SDoug Rabson
244633f12199SDoug Rabson *length = et->prf_length;
244733f12199SDoug Rabson return 0;
244833f12199SDoug Rabson }
244933f12199SDoug Rabson
2450ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_prf(krb5_context context,const krb5_crypto crypto,const krb5_data * input,krb5_data * output)245133f12199SDoug Rabson krb5_crypto_prf(krb5_context context,
245233f12199SDoug Rabson const krb5_crypto crypto,
245333f12199SDoug Rabson const krb5_data *input,
245433f12199SDoug Rabson krb5_data *output)
245533f12199SDoug Rabson {
2456ae771770SStanislav Sedov struct _krb5_encryption_type *et = crypto->et;
245733f12199SDoug Rabson
245833f12199SDoug Rabson krb5_data_zero(output);
245933f12199SDoug Rabson
246033f12199SDoug Rabson if(et->prf == NULL) {
2461ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
2462ae771770SStanislav Sedov "kerberos prf for %s not supported",
246333f12199SDoug Rabson et->name);
246433f12199SDoug Rabson return KRB5_PROG_ETYPE_NOSUPP;
246533f12199SDoug Rabson }
246633f12199SDoug Rabson
246733f12199SDoug Rabson return (*et->prf)(context, crypto, input, output);
246833f12199SDoug Rabson }
246933f12199SDoug Rabson
2470b528cefcSMark Murray static krb5_error_code
krb5_crypto_prfplus(krb5_context context,const krb5_crypto crypto,const krb5_data * input,size_t length,krb5_data * output)2471ae771770SStanislav Sedov krb5_crypto_prfplus(krb5_context context,
2472ae771770SStanislav Sedov const krb5_crypto crypto,
2473ae771770SStanislav Sedov const krb5_data *input,
2474ae771770SStanislav Sedov size_t length,
2475ae771770SStanislav Sedov krb5_data *output)
2476b528cefcSMark Murray {
247747085b17SAssar Westerlund krb5_error_code ret;
2478ae771770SStanislav Sedov krb5_data input2;
2479ae771770SStanislav Sedov unsigned char i = 1;
2480ae771770SStanislav Sedov unsigned char *p;
248147085b17SAssar Westerlund
2482ae771770SStanislav Sedov krb5_data_zero(&input2);
2483ae771770SStanislav Sedov krb5_data_zero(output);
2484ae771770SStanislav Sedov
2485ae771770SStanislav Sedov krb5_clear_error_message(context);
2486ae771770SStanislav Sedov
2487ae771770SStanislav Sedov ret = krb5_data_alloc(output, length);
2488ae771770SStanislav Sedov if (ret) goto out;
2489ae771770SStanislav Sedov ret = krb5_data_alloc(&input2, input->length + 1);
2490ae771770SStanislav Sedov if (ret) goto out;
2491ae771770SStanislav Sedov
2492ae771770SStanislav Sedov krb5_clear_error_message(context);
2493ae771770SStanislav Sedov
2494ae771770SStanislav Sedov memcpy(((unsigned char *)input2.data) + 1, input->data, input->length);
2495ae771770SStanislav Sedov
2496ae771770SStanislav Sedov p = output->data;
2497ae771770SStanislav Sedov
2498ae771770SStanislav Sedov while (length) {
2499ae771770SStanislav Sedov krb5_data block;
2500ae771770SStanislav Sedov
2501ae771770SStanislav Sedov ((unsigned char *)input2.data)[0] = i++;
2502ae771770SStanislav Sedov
2503ae771770SStanislav Sedov ret = krb5_crypto_prf(context, crypto, &input2, &block);
250447085b17SAssar Westerlund if (ret)
2505ae771770SStanislav Sedov goto out;
250647085b17SAssar Westerlund
2507ae771770SStanislav Sedov if (block.length < length) {
2508ae771770SStanislav Sedov memcpy(p, block.data, block.length);
2509ae771770SStanislav Sedov length -= block.length;
2510ae771770SStanislav Sedov } else {
2511ae771770SStanislav Sedov memcpy(p, block.data, length);
2512ae771770SStanislav Sedov length = 0;
251347085b17SAssar Westerlund }
2514ae771770SStanislav Sedov p += block.length;
2515ae771770SStanislav Sedov krb5_data_free(&block);
2516ae771770SStanislav Sedov }
2517ae771770SStanislav Sedov
2518ae771770SStanislav Sedov out:
2519ae771770SStanislav Sedov krb5_data_free(&input2);
2520ae771770SStanislav Sedov if (ret)
2521ae771770SStanislav Sedov krb5_data_free(output);
2522ae771770SStanislav Sedov return 0;
2523ae771770SStanislav Sedov }
2524ae771770SStanislav Sedov
2525ae771770SStanislav Sedov /**
2526ae771770SStanislav Sedov * The FX-CF2 key derivation function, used in FAST and preauth framework.
2527ae771770SStanislav Sedov *
2528ae771770SStanislav Sedov * @param context Kerberos 5 context
2529ae771770SStanislav Sedov * @param crypto1 first key to combine
2530ae771770SStanislav Sedov * @param crypto2 second key to combine
2531ae771770SStanislav Sedov * @param pepper1 factor to combine with first key to garante uniqueness
2532ae771770SStanislav Sedov * @param pepper2 factor to combine with second key to garante uniqueness
2533ae771770SStanislav Sedov * @param enctype the encryption type of the resulting key
2534ae771770SStanislav Sedov * @param res allocated key, free with krb5_free_keyblock_contents()
2535ae771770SStanislav Sedov *
2536ae771770SStanislav Sedov * @return Return an error code or 0.
2537ae771770SStanislav Sedov *
2538ae771770SStanislav Sedov * @ingroup krb5_crypto
2539ae771770SStanislav Sedov */
2540ae771770SStanislav Sedov
2541ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_fx_cf2(krb5_context context,const krb5_crypto crypto1,const krb5_crypto crypto2,krb5_data * pepper1,krb5_data * pepper2,krb5_enctype enctype,krb5_keyblock * res)2542ae771770SStanislav Sedov krb5_crypto_fx_cf2(krb5_context context,
2543ae771770SStanislav Sedov const krb5_crypto crypto1,
2544ae771770SStanislav Sedov const krb5_crypto crypto2,
2545ae771770SStanislav Sedov krb5_data *pepper1,
2546ae771770SStanislav Sedov krb5_data *pepper2,
2547ae771770SStanislav Sedov krb5_enctype enctype,
2548ae771770SStanislav Sedov krb5_keyblock *res)
2549ae771770SStanislav Sedov {
2550ae771770SStanislav Sedov krb5_error_code ret;
2551ae771770SStanislav Sedov krb5_data os1, os2;
2552ae771770SStanislav Sedov size_t i, keysize;
2553ae771770SStanislav Sedov
2554ae771770SStanislav Sedov memset(res, 0, sizeof(*res));
2555ae771770SStanislav Sedov
2556ae771770SStanislav Sedov ret = krb5_enctype_keysize(context, enctype, &keysize);
2557ae771770SStanislav Sedov if (ret)
2558ae771770SStanislav Sedov return ret;
2559ae771770SStanislav Sedov
2560ae771770SStanislav Sedov ret = krb5_data_alloc(&res->keyvalue, keysize);
2561ae771770SStanislav Sedov if (ret)
2562ae771770SStanislav Sedov goto out;
2563ae771770SStanislav Sedov ret = krb5_crypto_prfplus(context, crypto1, pepper1, keysize, &os1);
2564ae771770SStanislav Sedov if (ret)
2565ae771770SStanislav Sedov goto out;
2566ae771770SStanislav Sedov ret = krb5_crypto_prfplus(context, crypto2, pepper2, keysize, &os2);
2567ae771770SStanislav Sedov if (ret)
2568ae771770SStanislav Sedov goto out;
2569ae771770SStanislav Sedov
2570ae771770SStanislav Sedov res->keytype = enctype;
2571ae771770SStanislav Sedov {
2572ae771770SStanislav Sedov unsigned char *p1 = os1.data, *p2 = os2.data, *p3 = res->keyvalue.data;
2573ae771770SStanislav Sedov for (i = 0; i < keysize; i++)
2574ae771770SStanislav Sedov p3[i] = p1[i] ^ p2[i];
2575ae771770SStanislav Sedov }
2576ae771770SStanislav Sedov out:
2577ae771770SStanislav Sedov if (ret)
2578ae771770SStanislav Sedov krb5_data_free(&res->keyvalue);
2579ae771770SStanislav Sedov krb5_data_free(&os1);
2580ae771770SStanislav Sedov krb5_data_free(&os2);
2581ae771770SStanislav Sedov
2582ae771770SStanislav Sedov return ret;
2583ae771770SStanislav Sedov }
2584ae771770SStanislav Sedov
2585ae771770SStanislav Sedov
2586ae771770SStanislav Sedov
2587ae771770SStanislav Sedov #ifndef HEIMDAL_SMALLER
2588ae771770SStanislav Sedov
2589ae771770SStanislav Sedov /**
2590ae771770SStanislav Sedov * Deprecated: keytypes doesn't exists, they are really enctypes.
2591ae771770SStanislav Sedov *
2592ae771770SStanislav Sedov * @ingroup krb5_deprecated
2593ae771770SStanislav Sedov */
2594ae771770SStanislav Sedov
2595ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_keytype_to_enctypes(krb5_context context,krb5_keytype keytype,unsigned * len,krb5_enctype ** val)2596ae771770SStanislav Sedov krb5_keytype_to_enctypes (krb5_context context,
2597ae771770SStanislav Sedov krb5_keytype keytype,
2598ae771770SStanislav Sedov unsigned *len,
2599ae771770SStanislav Sedov krb5_enctype **val)
2600ae771770SStanislav Sedov KRB5_DEPRECATED_FUNCTION("Use X instead")
2601ae771770SStanislav Sedov {
2602ae771770SStanislav Sedov int i;
2603ae771770SStanislav Sedov unsigned n = 0;
2604ae771770SStanislav Sedov krb5_enctype *ret;
2605ae771770SStanislav Sedov
2606ae771770SStanislav Sedov for (i = _krb5_num_etypes - 1; i >= 0; --i) {
2607ae771770SStanislav Sedov if (_krb5_etypes[i]->keytype->type == keytype
2608ae771770SStanislav Sedov && !(_krb5_etypes[i]->flags & F_PSEUDO)
2609ae771770SStanislav Sedov && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0)
2610ae771770SStanislav Sedov ++n;
2611ae771770SStanislav Sedov }
2612ae771770SStanislav Sedov if (n == 0) {
2613ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
2614ae771770SStanislav Sedov "Keytype have no mapping");
2615ae771770SStanislav Sedov return KRB5_PROG_KEYTYPE_NOSUPP;
2616ae771770SStanislav Sedov }
2617ae771770SStanislav Sedov
2618ae771770SStanislav Sedov ret = malloc(n * sizeof(*ret));
2619ae771770SStanislav Sedov if (ret == NULL && n != 0) {
2620ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
2621ae771770SStanislav Sedov return ENOMEM;
2622ae771770SStanislav Sedov }
2623ae771770SStanislav Sedov n = 0;
2624ae771770SStanislav Sedov for (i = _krb5_num_etypes - 1; i >= 0; --i) {
2625ae771770SStanislav Sedov if (_krb5_etypes[i]->keytype->type == keytype
2626ae771770SStanislav Sedov && !(_krb5_etypes[i]->flags & F_PSEUDO)
2627ae771770SStanislav Sedov && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0)
2628ae771770SStanislav Sedov ret[n++] = _krb5_etypes[i]->type;
2629ae771770SStanislav Sedov }
2630ae771770SStanislav Sedov *len = n;
2631ae771770SStanislav Sedov *val = ret;
2632ae771770SStanislav Sedov return 0;
2633ae771770SStanislav Sedov }
2634ae771770SStanislav Sedov
2635ae771770SStanislav Sedov /**
2636ae771770SStanislav Sedov * Deprecated: keytypes doesn't exists, they are really enctypes.
2637ae771770SStanislav Sedov *
2638ae771770SStanislav Sedov * @ingroup krb5_deprecated
2639ae771770SStanislav Sedov */
2640ae771770SStanislav Sedov
2641ae771770SStanislav Sedov /* if two enctypes have compatible keys */
2642ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_enctypes_compatible_keys(krb5_context context,krb5_enctype etype1,krb5_enctype etype2)2643ae771770SStanislav Sedov krb5_enctypes_compatible_keys(krb5_context context,
2644ae771770SStanislav Sedov krb5_enctype etype1,
2645ae771770SStanislav Sedov krb5_enctype etype2)
2646ae771770SStanislav Sedov KRB5_DEPRECATED_FUNCTION("Use X instead")
2647ae771770SStanislav Sedov {
2648ae771770SStanislav Sedov struct _krb5_encryption_type *e1 = _krb5_find_enctype(etype1);
2649ae771770SStanislav Sedov struct _krb5_encryption_type *e2 = _krb5_find_enctype(etype2);
2650ae771770SStanislav Sedov return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
2651ae771770SStanislav Sedov }
2652ae771770SStanislav Sedov
2653ae771770SStanislav Sedov #endif /* HEIMDAL_SMALLER */
2654