1*0a6a1f1dSLionel Sambuc /* $NetBSD: crypto.c,v 1.1.1.2 2014/04/24 12:45:49 pettai Exp $ */
2ebfedea0SLionel Sambuc
3ebfedea0SLionel Sambuc /*
4ebfedea0SLionel Sambuc * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
5ebfedea0SLionel Sambuc * (Royal Institute of Technology, Stockholm, Sweden).
6ebfedea0SLionel Sambuc * All rights reserved.
7ebfedea0SLionel Sambuc *
8ebfedea0SLionel Sambuc * Redistribution and use in source and binary forms, with or without
9ebfedea0SLionel Sambuc * modification, are permitted provided that the following conditions
10ebfedea0SLionel Sambuc * are met:
11ebfedea0SLionel Sambuc *
12ebfedea0SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
13ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer.
14ebfedea0SLionel Sambuc *
15ebfedea0SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
16ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
17ebfedea0SLionel Sambuc * documentation and/or other materials provided with the distribution.
18ebfedea0SLionel Sambuc *
19ebfedea0SLionel Sambuc * 3. Neither the name of the Institute nor the names of its contributors
20ebfedea0SLionel Sambuc * may be used to endorse or promote products derived from this software
21ebfedea0SLionel Sambuc * without specific prior written permission.
22ebfedea0SLionel Sambuc *
23ebfedea0SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24ebfedea0SLionel Sambuc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ebfedea0SLionel Sambuc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ebfedea0SLionel Sambuc * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27ebfedea0SLionel Sambuc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ebfedea0SLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ebfedea0SLionel Sambuc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ebfedea0SLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31ebfedea0SLionel Sambuc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32ebfedea0SLionel Sambuc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33ebfedea0SLionel Sambuc * SUCH DAMAGE.
34ebfedea0SLionel Sambuc */
35ebfedea0SLionel Sambuc
36ebfedea0SLionel Sambuc #include "krb5_locl.h"
37ebfedea0SLionel Sambuc
38ebfedea0SLionel Sambuc struct _krb5_key_usage {
39ebfedea0SLionel Sambuc unsigned usage;
40ebfedea0SLionel Sambuc struct _krb5_key_data key;
41ebfedea0SLionel Sambuc };
42ebfedea0SLionel Sambuc
43ebfedea0SLionel Sambuc
44ebfedea0SLionel Sambuc #ifndef HEIMDAL_SMALLER
45ebfedea0SLionel Sambuc #define DES3_OLD_ENCTYPE 1
46ebfedea0SLionel Sambuc #endif
47ebfedea0SLionel Sambuc
48ebfedea0SLionel Sambuc static krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
49ebfedea0SLionel Sambuc unsigned, struct _krb5_key_data**);
50ebfedea0SLionel Sambuc static struct _krb5_key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
51ebfedea0SLionel Sambuc
52ebfedea0SLionel Sambuc static void free_key_schedule(krb5_context,
53ebfedea0SLionel Sambuc struct _krb5_key_data *,
54ebfedea0SLionel Sambuc struct _krb5_encryption_type *);
55ebfedea0SLionel Sambuc
56*0a6a1f1dSLionel Sambuc /*
57*0a6a1f1dSLionel Sambuc * Converts etype to a user readable string and sets as a side effect
58*0a6a1f1dSLionel Sambuc * the krb5_error_message containing this string. Returns
59*0a6a1f1dSLionel Sambuc * KRB5_PROG_ETYPE_NOSUPP in not the conversion of the etype failed in
60*0a6a1f1dSLionel Sambuc * which case the error code of the etype convesion is returned.
61*0a6a1f1dSLionel Sambuc */
62*0a6a1f1dSLionel Sambuc
63*0a6a1f1dSLionel Sambuc static krb5_error_code
unsupported_enctype(krb5_context context,krb5_enctype etype)64*0a6a1f1dSLionel Sambuc unsupported_enctype(krb5_context context, krb5_enctype etype)
65*0a6a1f1dSLionel Sambuc {
66*0a6a1f1dSLionel Sambuc krb5_error_code ret;
67*0a6a1f1dSLionel Sambuc char *name;
68*0a6a1f1dSLionel Sambuc
69*0a6a1f1dSLionel Sambuc ret = krb5_enctype_to_string(context, etype, &name);
70*0a6a1f1dSLionel Sambuc if (ret)
71*0a6a1f1dSLionel Sambuc return ret;
72*0a6a1f1dSLionel Sambuc
73*0a6a1f1dSLionel Sambuc krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
74*0a6a1f1dSLionel Sambuc N_("Encryption type %s not supported", ""),
75*0a6a1f1dSLionel Sambuc name);
76*0a6a1f1dSLionel Sambuc free(name);
77*0a6a1f1dSLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP;
78*0a6a1f1dSLionel Sambuc }
79*0a6a1f1dSLionel Sambuc
80*0a6a1f1dSLionel Sambuc /*
81*0a6a1f1dSLionel Sambuc *
82*0a6a1f1dSLionel Sambuc */
83ebfedea0SLionel Sambuc
84ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_enctype_keysize(krb5_context context,krb5_enctype type,size_t * keysize)85ebfedea0SLionel Sambuc krb5_enctype_keysize(krb5_context context,
86ebfedea0SLionel Sambuc krb5_enctype type,
87ebfedea0SLionel Sambuc size_t *keysize)
88ebfedea0SLionel Sambuc {
89ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = _krb5_find_enctype(type);
90ebfedea0SLionel Sambuc if(et == NULL) {
91*0a6a1f1dSLionel Sambuc return unsupported_enctype (context, type);
92ebfedea0SLionel Sambuc }
93ebfedea0SLionel Sambuc *keysize = et->keytype->size;
94ebfedea0SLionel Sambuc return 0;
95ebfedea0SLionel Sambuc }
96ebfedea0SLionel Sambuc
97ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_enctype_keybits(krb5_context context,krb5_enctype type,size_t * keybits)98ebfedea0SLionel Sambuc krb5_enctype_keybits(krb5_context context,
99ebfedea0SLionel Sambuc krb5_enctype type,
100ebfedea0SLionel Sambuc size_t *keybits)
101ebfedea0SLionel Sambuc {
102ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = _krb5_find_enctype(type);
103ebfedea0SLionel Sambuc if(et == NULL) {
104*0a6a1f1dSLionel Sambuc return unsupported_enctype (context, type);
105ebfedea0SLionel Sambuc }
106ebfedea0SLionel Sambuc *keybits = et->keytype->bits;
107ebfedea0SLionel Sambuc return 0;
108ebfedea0SLionel Sambuc }
109ebfedea0SLionel Sambuc
110ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_generate_random_keyblock(krb5_context context,krb5_enctype type,krb5_keyblock * key)111ebfedea0SLionel Sambuc krb5_generate_random_keyblock(krb5_context context,
112ebfedea0SLionel Sambuc krb5_enctype type,
113ebfedea0SLionel Sambuc krb5_keyblock *key)
114ebfedea0SLionel Sambuc {
115ebfedea0SLionel Sambuc krb5_error_code ret;
116ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = _krb5_find_enctype(type);
117ebfedea0SLionel Sambuc if(et == NULL) {
118*0a6a1f1dSLionel Sambuc return unsupported_enctype (context, type);
119ebfedea0SLionel Sambuc }
120ebfedea0SLionel Sambuc ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
121ebfedea0SLionel Sambuc if(ret)
122ebfedea0SLionel Sambuc return ret;
123ebfedea0SLionel Sambuc key->keytype = type;
124ebfedea0SLionel Sambuc if(et->keytype->random_key)
125ebfedea0SLionel Sambuc (*et->keytype->random_key)(context, key);
126ebfedea0SLionel Sambuc else
127ebfedea0SLionel Sambuc krb5_generate_random_block(key->keyvalue.data,
128ebfedea0SLionel Sambuc key->keyvalue.length);
129ebfedea0SLionel Sambuc return 0;
130ebfedea0SLionel Sambuc }
131ebfedea0SLionel Sambuc
132ebfedea0SLionel Sambuc static krb5_error_code
_key_schedule(krb5_context context,struct _krb5_key_data * key)133ebfedea0SLionel Sambuc _key_schedule(krb5_context context,
134ebfedea0SLionel Sambuc struct _krb5_key_data *key)
135ebfedea0SLionel Sambuc {
136ebfedea0SLionel Sambuc krb5_error_code ret;
137ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = _krb5_find_enctype(key->key->keytype);
138ebfedea0SLionel Sambuc struct _krb5_key_type *kt;
139ebfedea0SLionel Sambuc
140ebfedea0SLionel Sambuc if (et == NULL) {
141*0a6a1f1dSLionel Sambuc return unsupported_enctype (context,
142ebfedea0SLionel Sambuc key->key->keytype);
143ebfedea0SLionel Sambuc }
144ebfedea0SLionel Sambuc
145ebfedea0SLionel Sambuc kt = et->keytype;
146ebfedea0SLionel Sambuc
147ebfedea0SLionel Sambuc if(kt->schedule == NULL)
148ebfedea0SLionel Sambuc return 0;
149ebfedea0SLionel Sambuc if (key->schedule != NULL)
150ebfedea0SLionel Sambuc return 0;
151ebfedea0SLionel Sambuc ALLOC(key->schedule, 1);
152ebfedea0SLionel Sambuc if(key->schedule == NULL) {
153ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
154ebfedea0SLionel Sambuc return ENOMEM;
155ebfedea0SLionel Sambuc }
156ebfedea0SLionel Sambuc ret = krb5_data_alloc(key->schedule, kt->schedule_size);
157ebfedea0SLionel Sambuc if(ret) {
158ebfedea0SLionel Sambuc free(key->schedule);
159ebfedea0SLionel Sambuc key->schedule = NULL;
160ebfedea0SLionel Sambuc return ret;
161ebfedea0SLionel Sambuc }
162ebfedea0SLionel Sambuc (*kt->schedule)(context, kt, key);
163ebfedea0SLionel Sambuc return 0;
164ebfedea0SLionel Sambuc }
165ebfedea0SLionel Sambuc
166ebfedea0SLionel Sambuc /************************************************************
167ebfedea0SLionel Sambuc * *
168ebfedea0SLionel Sambuc ************************************************************/
169ebfedea0SLionel Sambuc
170ebfedea0SLionel Sambuc static krb5_error_code
SHA1_checksum(krb5_context context,struct _krb5_key_data * key,const void * data,size_t len,unsigned usage,Checksum * C)171ebfedea0SLionel Sambuc SHA1_checksum(krb5_context context,
172ebfedea0SLionel Sambuc struct _krb5_key_data *key,
173ebfedea0SLionel Sambuc const void *data,
174ebfedea0SLionel Sambuc size_t len,
175ebfedea0SLionel Sambuc unsigned usage,
176ebfedea0SLionel Sambuc Checksum *C)
177ebfedea0SLionel Sambuc {
178ebfedea0SLionel Sambuc if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_sha1(), NULL) != 1)
179ebfedea0SLionel Sambuc krb5_abortx(context, "sha1 checksum failed");
180ebfedea0SLionel Sambuc return 0;
181ebfedea0SLionel Sambuc }
182ebfedea0SLionel Sambuc
183ebfedea0SLionel Sambuc /* HMAC according to RFC2104 */
184ebfedea0SLionel Sambuc 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)185ebfedea0SLionel Sambuc _krb5_internal_hmac(krb5_context context,
186ebfedea0SLionel Sambuc struct _krb5_checksum_type *cm,
187ebfedea0SLionel Sambuc const void *data,
188ebfedea0SLionel Sambuc size_t len,
189ebfedea0SLionel Sambuc unsigned usage,
190ebfedea0SLionel Sambuc struct _krb5_key_data *keyblock,
191ebfedea0SLionel Sambuc Checksum *result)
192ebfedea0SLionel Sambuc {
193ebfedea0SLionel Sambuc unsigned char *ipad, *opad;
194ebfedea0SLionel Sambuc unsigned char *key;
195ebfedea0SLionel Sambuc size_t key_len;
196*0a6a1f1dSLionel Sambuc size_t i;
197ebfedea0SLionel Sambuc
198ebfedea0SLionel Sambuc ipad = malloc(cm->blocksize + len);
199ebfedea0SLionel Sambuc if (ipad == NULL)
200ebfedea0SLionel Sambuc return ENOMEM;
201ebfedea0SLionel Sambuc opad = malloc(cm->blocksize + cm->checksumsize);
202ebfedea0SLionel Sambuc if (opad == NULL) {
203ebfedea0SLionel Sambuc free(ipad);
204ebfedea0SLionel Sambuc return ENOMEM;
205ebfedea0SLionel Sambuc }
206ebfedea0SLionel Sambuc memset(ipad, 0x36, cm->blocksize);
207ebfedea0SLionel Sambuc memset(opad, 0x5c, cm->blocksize);
208ebfedea0SLionel Sambuc
209ebfedea0SLionel Sambuc if(keyblock->key->keyvalue.length > cm->blocksize){
210ebfedea0SLionel Sambuc (*cm->checksum)(context,
211ebfedea0SLionel Sambuc keyblock,
212ebfedea0SLionel Sambuc keyblock->key->keyvalue.data,
213ebfedea0SLionel Sambuc keyblock->key->keyvalue.length,
214ebfedea0SLionel Sambuc usage,
215ebfedea0SLionel Sambuc result);
216ebfedea0SLionel Sambuc key = result->checksum.data;
217ebfedea0SLionel Sambuc key_len = result->checksum.length;
218ebfedea0SLionel Sambuc } else {
219ebfedea0SLionel Sambuc key = keyblock->key->keyvalue.data;
220ebfedea0SLionel Sambuc key_len = keyblock->key->keyvalue.length;
221ebfedea0SLionel Sambuc }
222ebfedea0SLionel Sambuc for(i = 0; i < key_len; i++){
223ebfedea0SLionel Sambuc ipad[i] ^= key[i];
224ebfedea0SLionel Sambuc opad[i] ^= key[i];
225ebfedea0SLionel Sambuc }
226ebfedea0SLionel Sambuc memcpy(ipad + cm->blocksize, data, len);
227ebfedea0SLionel Sambuc (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len,
228ebfedea0SLionel Sambuc usage, result);
229ebfedea0SLionel Sambuc memcpy(opad + cm->blocksize, result->checksum.data,
230ebfedea0SLionel Sambuc result->checksum.length);
231ebfedea0SLionel Sambuc (*cm->checksum)(context, keyblock, opad,
232ebfedea0SLionel Sambuc cm->blocksize + cm->checksumsize, usage, result);
233ebfedea0SLionel Sambuc memset(ipad, 0, cm->blocksize + len);
234ebfedea0SLionel Sambuc free(ipad);
235ebfedea0SLionel Sambuc memset(opad, 0, cm->blocksize + cm->checksumsize);
236ebfedea0SLionel Sambuc free(opad);
237ebfedea0SLionel Sambuc
238ebfedea0SLionel Sambuc return 0;
239ebfedea0SLionel Sambuc }
240ebfedea0SLionel Sambuc
241ebfedea0SLionel Sambuc 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)242ebfedea0SLionel Sambuc krb5_hmac(krb5_context context,
243ebfedea0SLionel Sambuc krb5_cksumtype cktype,
244ebfedea0SLionel Sambuc const void *data,
245ebfedea0SLionel Sambuc size_t len,
246ebfedea0SLionel Sambuc unsigned usage,
247ebfedea0SLionel Sambuc krb5_keyblock *key,
248ebfedea0SLionel Sambuc Checksum *result)
249ebfedea0SLionel Sambuc {
250ebfedea0SLionel Sambuc struct _krb5_checksum_type *c = _krb5_find_checksum(cktype);
251ebfedea0SLionel Sambuc struct _krb5_key_data kd;
252ebfedea0SLionel Sambuc krb5_error_code ret;
253ebfedea0SLionel Sambuc
254ebfedea0SLionel Sambuc if (c == NULL) {
255ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
256ebfedea0SLionel Sambuc N_("checksum type %d not supported", ""),
257ebfedea0SLionel Sambuc cktype);
258ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP;
259ebfedea0SLionel Sambuc }
260ebfedea0SLionel Sambuc
261ebfedea0SLionel Sambuc kd.key = key;
262ebfedea0SLionel Sambuc kd.schedule = NULL;
263ebfedea0SLionel Sambuc
264ebfedea0SLionel Sambuc ret = _krb5_internal_hmac(context, c, data, len, usage, &kd, result);
265ebfedea0SLionel Sambuc
266ebfedea0SLionel Sambuc if (kd.schedule)
267ebfedea0SLionel Sambuc krb5_free_data(context, kd.schedule);
268ebfedea0SLionel Sambuc
269ebfedea0SLionel Sambuc return ret;
270ebfedea0SLionel Sambuc }
271ebfedea0SLionel Sambuc
272ebfedea0SLionel Sambuc 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)273ebfedea0SLionel Sambuc _krb5_SP_HMAC_SHA1_checksum(krb5_context context,
274ebfedea0SLionel Sambuc struct _krb5_key_data *key,
275ebfedea0SLionel Sambuc const void *data,
276ebfedea0SLionel Sambuc size_t len,
277ebfedea0SLionel Sambuc unsigned usage,
278ebfedea0SLionel Sambuc Checksum *result)
279ebfedea0SLionel Sambuc {
280ebfedea0SLionel Sambuc struct _krb5_checksum_type *c = _krb5_find_checksum(CKSUMTYPE_SHA1);
281ebfedea0SLionel Sambuc Checksum res;
282ebfedea0SLionel Sambuc char sha1_data[20];
283ebfedea0SLionel Sambuc krb5_error_code ret;
284ebfedea0SLionel Sambuc
285ebfedea0SLionel Sambuc res.checksum.data = sha1_data;
286ebfedea0SLionel Sambuc res.checksum.length = sizeof(sha1_data);
287ebfedea0SLionel Sambuc
288ebfedea0SLionel Sambuc ret = _krb5_internal_hmac(context, c, data, len, usage, key, &res);
289ebfedea0SLionel Sambuc if (ret)
290ebfedea0SLionel Sambuc krb5_abortx(context, "hmac failed");
291ebfedea0SLionel Sambuc memcpy(result->checksum.data, res.checksum.data, result->checksum.length);
292ebfedea0SLionel Sambuc return 0;
293ebfedea0SLionel Sambuc }
294ebfedea0SLionel Sambuc
295ebfedea0SLionel Sambuc struct _krb5_checksum_type _krb5_checksum_sha1 = {
296ebfedea0SLionel Sambuc CKSUMTYPE_SHA1,
297ebfedea0SLionel Sambuc "sha1",
298ebfedea0SLionel Sambuc 64,
299ebfedea0SLionel Sambuc 20,
300ebfedea0SLionel Sambuc F_CPROOF,
301ebfedea0SLionel Sambuc SHA1_checksum,
302ebfedea0SLionel Sambuc NULL
303ebfedea0SLionel Sambuc };
304ebfedea0SLionel Sambuc
305ebfedea0SLionel Sambuc struct _krb5_checksum_type *
_krb5_find_checksum(krb5_cksumtype type)306ebfedea0SLionel Sambuc _krb5_find_checksum(krb5_cksumtype type)
307ebfedea0SLionel Sambuc {
308ebfedea0SLionel Sambuc int i;
309ebfedea0SLionel Sambuc for(i = 0; i < _krb5_num_checksums; i++)
310ebfedea0SLionel Sambuc if(_krb5_checksum_types[i]->type == type)
311ebfedea0SLionel Sambuc return _krb5_checksum_types[i];
312ebfedea0SLionel Sambuc return NULL;
313ebfedea0SLionel Sambuc }
314ebfedea0SLionel Sambuc
315ebfedea0SLionel Sambuc 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)316ebfedea0SLionel Sambuc get_checksum_key(krb5_context context,
317ebfedea0SLionel Sambuc krb5_crypto crypto,
318ebfedea0SLionel Sambuc unsigned usage, /* not krb5_key_usage */
319ebfedea0SLionel Sambuc struct _krb5_checksum_type *ct,
320ebfedea0SLionel Sambuc struct _krb5_key_data **key)
321ebfedea0SLionel Sambuc {
322ebfedea0SLionel Sambuc krb5_error_code ret = 0;
323ebfedea0SLionel Sambuc
324ebfedea0SLionel Sambuc if(ct->flags & F_DERIVED)
325ebfedea0SLionel Sambuc ret = _get_derived_key(context, crypto, usage, key);
326ebfedea0SLionel Sambuc else if(ct->flags & F_VARIANT) {
327*0a6a1f1dSLionel Sambuc size_t i;
328ebfedea0SLionel Sambuc
329ebfedea0SLionel Sambuc *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
330ebfedea0SLionel Sambuc if(*key == NULL) {
331ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
332ebfedea0SLionel Sambuc return ENOMEM;
333ebfedea0SLionel Sambuc }
334ebfedea0SLionel Sambuc ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
335ebfedea0SLionel Sambuc if(ret)
336ebfedea0SLionel Sambuc return ret;
337ebfedea0SLionel Sambuc for(i = 0; i < (*key)->key->keyvalue.length; i++)
338ebfedea0SLionel Sambuc ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
339ebfedea0SLionel Sambuc } else {
340ebfedea0SLionel Sambuc *key = &crypto->key;
341ebfedea0SLionel Sambuc }
342ebfedea0SLionel Sambuc if(ret == 0)
343ebfedea0SLionel Sambuc ret = _key_schedule(context, *key);
344ebfedea0SLionel Sambuc return ret;
345ebfedea0SLionel Sambuc }
346ebfedea0SLionel Sambuc
347ebfedea0SLionel Sambuc 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)348ebfedea0SLionel Sambuc create_checksum (krb5_context context,
349ebfedea0SLionel Sambuc struct _krb5_checksum_type *ct,
350ebfedea0SLionel Sambuc krb5_crypto crypto,
351ebfedea0SLionel Sambuc unsigned usage,
352ebfedea0SLionel Sambuc void *data,
353ebfedea0SLionel Sambuc size_t len,
354ebfedea0SLionel Sambuc Checksum *result)
355ebfedea0SLionel Sambuc {
356ebfedea0SLionel Sambuc krb5_error_code ret;
357ebfedea0SLionel Sambuc struct _krb5_key_data *dkey;
358ebfedea0SLionel Sambuc int keyed_checksum;
359ebfedea0SLionel Sambuc
360ebfedea0SLionel Sambuc if (ct->flags & F_DISABLED) {
361ebfedea0SLionel Sambuc krb5_clear_error_message (context);
362ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP;
363ebfedea0SLionel Sambuc }
364ebfedea0SLionel Sambuc keyed_checksum = (ct->flags & F_KEYED) != 0;
365ebfedea0SLionel Sambuc if(keyed_checksum && crypto == NULL) {
366ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
367ebfedea0SLionel Sambuc N_("Checksum type %s is keyed but no "
368ebfedea0SLionel Sambuc "crypto context (key) was passed in", ""),
369ebfedea0SLionel Sambuc ct->name);
370ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
371ebfedea0SLionel Sambuc }
372ebfedea0SLionel Sambuc if(keyed_checksum) {
373ebfedea0SLionel Sambuc ret = get_checksum_key(context, crypto, usage, ct, &dkey);
374ebfedea0SLionel Sambuc if (ret)
375ebfedea0SLionel Sambuc return ret;
376ebfedea0SLionel Sambuc } else
377ebfedea0SLionel Sambuc dkey = NULL;
378ebfedea0SLionel Sambuc result->cksumtype = ct->type;
379ebfedea0SLionel Sambuc ret = krb5_data_alloc(&result->checksum, ct->checksumsize);
380ebfedea0SLionel Sambuc if (ret)
381ebfedea0SLionel Sambuc return (ret);
382ebfedea0SLionel Sambuc return (*ct->checksum)(context, dkey, data, len, usage, result);
383ebfedea0SLionel Sambuc }
384ebfedea0SLionel Sambuc
385ebfedea0SLionel Sambuc static int
arcfour_checksum_p(struct _krb5_checksum_type * ct,krb5_crypto crypto)386ebfedea0SLionel Sambuc arcfour_checksum_p(struct _krb5_checksum_type *ct, krb5_crypto crypto)
387ebfedea0SLionel Sambuc {
388ebfedea0SLionel Sambuc return (ct->type == CKSUMTYPE_HMAC_MD5) &&
389ebfedea0SLionel Sambuc (crypto->key.key->keytype == KEYTYPE_ARCFOUR);
390ebfedea0SLionel Sambuc }
391ebfedea0SLionel Sambuc
392ebfedea0SLionel Sambuc 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)393ebfedea0SLionel Sambuc krb5_create_checksum(krb5_context context,
394ebfedea0SLionel Sambuc krb5_crypto crypto,
395ebfedea0SLionel Sambuc krb5_key_usage usage,
396ebfedea0SLionel Sambuc int type,
397ebfedea0SLionel Sambuc void *data,
398ebfedea0SLionel Sambuc size_t len,
399ebfedea0SLionel Sambuc Checksum *result)
400ebfedea0SLionel Sambuc {
401ebfedea0SLionel Sambuc struct _krb5_checksum_type *ct = NULL;
402ebfedea0SLionel Sambuc unsigned keyusage;
403ebfedea0SLionel Sambuc
404ebfedea0SLionel Sambuc /* type 0 -> pick from crypto */
405ebfedea0SLionel Sambuc if (type) {
406ebfedea0SLionel Sambuc ct = _krb5_find_checksum(type);
407ebfedea0SLionel Sambuc } else if (crypto) {
408ebfedea0SLionel Sambuc ct = crypto->et->keyed_checksum;
409ebfedea0SLionel Sambuc if (ct == NULL)
410ebfedea0SLionel Sambuc ct = crypto->et->checksum;
411ebfedea0SLionel Sambuc }
412ebfedea0SLionel Sambuc
413ebfedea0SLionel Sambuc if(ct == NULL) {
414ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
415ebfedea0SLionel Sambuc N_("checksum type %d not supported", ""),
416ebfedea0SLionel Sambuc type);
417ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP;
418ebfedea0SLionel Sambuc }
419ebfedea0SLionel Sambuc
420ebfedea0SLionel Sambuc if (arcfour_checksum_p(ct, crypto)) {
421ebfedea0SLionel Sambuc keyusage = usage;
422ebfedea0SLionel Sambuc _krb5_usage2arcfour(context, &keyusage);
423ebfedea0SLionel Sambuc } else
424ebfedea0SLionel Sambuc keyusage = CHECKSUM_USAGE(usage);
425ebfedea0SLionel Sambuc
426ebfedea0SLionel Sambuc return create_checksum(context, ct, crypto, keyusage,
427ebfedea0SLionel Sambuc data, len, result);
428ebfedea0SLionel Sambuc }
429ebfedea0SLionel Sambuc
430ebfedea0SLionel Sambuc static krb5_error_code
verify_checksum(krb5_context context,krb5_crypto crypto,unsigned usage,void * data,size_t len,Checksum * cksum)431ebfedea0SLionel Sambuc verify_checksum(krb5_context context,
432ebfedea0SLionel Sambuc krb5_crypto crypto,
433ebfedea0SLionel Sambuc unsigned usage, /* not krb5_key_usage */
434ebfedea0SLionel Sambuc void *data,
435ebfedea0SLionel Sambuc size_t len,
436ebfedea0SLionel Sambuc Checksum *cksum)
437ebfedea0SLionel Sambuc {
438ebfedea0SLionel Sambuc krb5_error_code ret;
439ebfedea0SLionel Sambuc struct _krb5_key_data *dkey;
440ebfedea0SLionel Sambuc int keyed_checksum;
441ebfedea0SLionel Sambuc Checksum c;
442ebfedea0SLionel Sambuc struct _krb5_checksum_type *ct;
443ebfedea0SLionel Sambuc
444ebfedea0SLionel Sambuc ct = _krb5_find_checksum(cksum->cksumtype);
445ebfedea0SLionel Sambuc if (ct == NULL || (ct->flags & F_DISABLED)) {
446ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
447ebfedea0SLionel Sambuc N_("checksum type %d not supported", ""),
448ebfedea0SLionel Sambuc cksum->cksumtype);
449ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP;
450ebfedea0SLionel Sambuc }
451ebfedea0SLionel Sambuc if(ct->checksumsize != cksum->checksum.length) {
452ebfedea0SLionel Sambuc krb5_clear_error_message (context);
453ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5KRB_AP_ERR_BAD_INTEGRITY,
454ebfedea0SLionel Sambuc N_("Decrypt integrity check failed for checksum type %s, "
455ebfedea0SLionel Sambuc "length was %u, expected %u", ""),
456ebfedea0SLionel Sambuc ct->name, (unsigned)cksum->checksum.length,
457ebfedea0SLionel Sambuc (unsigned)ct->checksumsize);
458ebfedea0SLionel Sambuc
459ebfedea0SLionel Sambuc return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
460ebfedea0SLionel Sambuc }
461ebfedea0SLionel Sambuc keyed_checksum = (ct->flags & F_KEYED) != 0;
462ebfedea0SLionel Sambuc if(keyed_checksum) {
463ebfedea0SLionel Sambuc struct _krb5_checksum_type *kct;
464ebfedea0SLionel Sambuc if (crypto == NULL) {
465ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_PROG_SUMTYPE_NOSUPP,
466ebfedea0SLionel Sambuc N_("Checksum type %s is keyed but no "
467ebfedea0SLionel Sambuc "crypto context (key) was passed in", ""),
468ebfedea0SLionel Sambuc ct->name);
469ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
470ebfedea0SLionel Sambuc }
471ebfedea0SLionel Sambuc kct = crypto->et->keyed_checksum;
472*0a6a1f1dSLionel Sambuc if (kct == NULL || kct->type != ct->type) {
473ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_PROG_SUMTYPE_NOSUPP,
474ebfedea0SLionel Sambuc N_("Checksum type %s is keyed, but "
475ebfedea0SLionel Sambuc "the key type %s passed didnt have that checksum "
476ebfedea0SLionel Sambuc "type as the keyed type", ""),
477ebfedea0SLionel Sambuc ct->name, crypto->et->name);
478ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
479ebfedea0SLionel Sambuc }
480ebfedea0SLionel Sambuc
481ebfedea0SLionel Sambuc ret = get_checksum_key(context, crypto, usage, ct, &dkey);
482ebfedea0SLionel Sambuc if (ret)
483ebfedea0SLionel Sambuc return ret;
484ebfedea0SLionel Sambuc } else
485ebfedea0SLionel Sambuc dkey = NULL;
486ebfedea0SLionel Sambuc
487ebfedea0SLionel Sambuc /*
488ebfedea0SLionel Sambuc * If checksum have a verify function, lets use that instead of
489ebfedea0SLionel Sambuc * calling ->checksum and then compare result.
490ebfedea0SLionel Sambuc */
491ebfedea0SLionel Sambuc
492ebfedea0SLionel Sambuc if(ct->verify) {
493ebfedea0SLionel Sambuc ret = (*ct->verify)(context, dkey, data, len, usage, cksum);
494ebfedea0SLionel Sambuc if (ret)
495ebfedea0SLionel Sambuc krb5_set_error_message(context, ret,
496ebfedea0SLionel Sambuc N_("Decrypt integrity check failed for checksum "
497ebfedea0SLionel Sambuc "type %s, key type %s", ""),
498ebfedea0SLionel Sambuc ct->name, (crypto != NULL)? crypto->et->name : "(none)");
499ebfedea0SLionel Sambuc return ret;
500ebfedea0SLionel Sambuc }
501ebfedea0SLionel Sambuc
502ebfedea0SLionel Sambuc ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
503ebfedea0SLionel Sambuc if (ret)
504ebfedea0SLionel Sambuc return ret;
505ebfedea0SLionel Sambuc
506ebfedea0SLionel Sambuc ret = (*ct->checksum)(context, dkey, data, len, usage, &c);
507ebfedea0SLionel Sambuc if (ret) {
508ebfedea0SLionel Sambuc krb5_data_free(&c.checksum);
509ebfedea0SLionel Sambuc return ret;
510ebfedea0SLionel Sambuc }
511ebfedea0SLionel Sambuc
512ebfedea0SLionel Sambuc if(krb5_data_ct_cmp(&c.checksum, &cksum->checksum) != 0) {
513ebfedea0SLionel Sambuc ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
514ebfedea0SLionel Sambuc krb5_set_error_message(context, ret,
515ebfedea0SLionel Sambuc N_("Decrypt integrity check failed for checksum "
516ebfedea0SLionel Sambuc "type %s, key type %s", ""),
517ebfedea0SLionel Sambuc ct->name, crypto ? crypto->et->name : "(unkeyed)");
518ebfedea0SLionel Sambuc } else {
519ebfedea0SLionel Sambuc ret = 0;
520ebfedea0SLionel Sambuc }
521ebfedea0SLionel Sambuc krb5_data_free (&c.checksum);
522ebfedea0SLionel Sambuc return ret;
523ebfedea0SLionel Sambuc }
524ebfedea0SLionel Sambuc
525ebfedea0SLionel Sambuc 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)526ebfedea0SLionel Sambuc krb5_verify_checksum(krb5_context context,
527ebfedea0SLionel Sambuc krb5_crypto crypto,
528ebfedea0SLionel Sambuc krb5_key_usage usage,
529ebfedea0SLionel Sambuc void *data,
530ebfedea0SLionel Sambuc size_t len,
531ebfedea0SLionel Sambuc Checksum *cksum)
532ebfedea0SLionel Sambuc {
533ebfedea0SLionel Sambuc struct _krb5_checksum_type *ct;
534ebfedea0SLionel Sambuc unsigned keyusage;
535ebfedea0SLionel Sambuc
536ebfedea0SLionel Sambuc ct = _krb5_find_checksum(cksum->cksumtype);
537ebfedea0SLionel Sambuc if(ct == NULL) {
538ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
539ebfedea0SLionel Sambuc N_("checksum type %d not supported", ""),
540ebfedea0SLionel Sambuc cksum->cksumtype);
541ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP;
542ebfedea0SLionel Sambuc }
543ebfedea0SLionel Sambuc
544ebfedea0SLionel Sambuc if (arcfour_checksum_p(ct, crypto)) {
545ebfedea0SLionel Sambuc keyusage = usage;
546ebfedea0SLionel Sambuc _krb5_usage2arcfour(context, &keyusage);
547ebfedea0SLionel Sambuc } else
548ebfedea0SLionel Sambuc keyusage = CHECKSUM_USAGE(usage);
549ebfedea0SLionel Sambuc
550ebfedea0SLionel Sambuc return verify_checksum(context, crypto, keyusage,
551ebfedea0SLionel Sambuc data, len, cksum);
552ebfedea0SLionel Sambuc }
553ebfedea0SLionel Sambuc
554ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_get_checksum_type(krb5_context context,krb5_crypto crypto,krb5_cksumtype * type)555ebfedea0SLionel Sambuc krb5_crypto_get_checksum_type(krb5_context context,
556ebfedea0SLionel Sambuc krb5_crypto crypto,
557ebfedea0SLionel Sambuc krb5_cksumtype *type)
558ebfedea0SLionel Sambuc {
559ebfedea0SLionel Sambuc struct _krb5_checksum_type *ct = NULL;
560ebfedea0SLionel Sambuc
561ebfedea0SLionel Sambuc if (crypto != NULL) {
562ebfedea0SLionel Sambuc ct = crypto->et->keyed_checksum;
563ebfedea0SLionel Sambuc if (ct == NULL)
564ebfedea0SLionel Sambuc ct = crypto->et->checksum;
565ebfedea0SLionel Sambuc }
566ebfedea0SLionel Sambuc
567ebfedea0SLionel Sambuc if (ct == NULL) {
568ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
569ebfedea0SLionel Sambuc N_("checksum type not found", ""));
570ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP;
571ebfedea0SLionel Sambuc }
572ebfedea0SLionel Sambuc
573ebfedea0SLionel Sambuc *type = ct->type;
574ebfedea0SLionel Sambuc
575ebfedea0SLionel Sambuc return 0;
576ebfedea0SLionel Sambuc }
577ebfedea0SLionel Sambuc
578ebfedea0SLionel Sambuc
579ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_checksumsize(krb5_context context,krb5_cksumtype type,size_t * size)580ebfedea0SLionel Sambuc krb5_checksumsize(krb5_context context,
581ebfedea0SLionel Sambuc krb5_cksumtype type,
582ebfedea0SLionel Sambuc size_t *size)
583ebfedea0SLionel Sambuc {
584ebfedea0SLionel Sambuc struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
585ebfedea0SLionel Sambuc if(ct == NULL) {
586ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
587ebfedea0SLionel Sambuc N_("checksum type %d not supported", ""),
588ebfedea0SLionel Sambuc type);
589ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP;
590ebfedea0SLionel Sambuc }
591ebfedea0SLionel Sambuc *size = ct->checksumsize;
592ebfedea0SLionel Sambuc return 0;
593ebfedea0SLionel Sambuc }
594ebfedea0SLionel Sambuc
595ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_checksum_is_keyed(krb5_context context,krb5_cksumtype type)596ebfedea0SLionel Sambuc krb5_checksum_is_keyed(krb5_context context,
597ebfedea0SLionel Sambuc krb5_cksumtype type)
598ebfedea0SLionel Sambuc {
599ebfedea0SLionel Sambuc struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
600ebfedea0SLionel Sambuc if(ct == NULL) {
601ebfedea0SLionel Sambuc if (context)
602ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
603ebfedea0SLionel Sambuc N_("checksum type %d not supported", ""),
604ebfedea0SLionel Sambuc type);
605ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP;
606ebfedea0SLionel Sambuc }
607ebfedea0SLionel Sambuc return ct->flags & F_KEYED;
608ebfedea0SLionel Sambuc }
609ebfedea0SLionel Sambuc
610ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_checksum_is_collision_proof(krb5_context context,krb5_cksumtype type)611ebfedea0SLionel Sambuc krb5_checksum_is_collision_proof(krb5_context context,
612ebfedea0SLionel Sambuc krb5_cksumtype type)
613ebfedea0SLionel Sambuc {
614ebfedea0SLionel Sambuc struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
615ebfedea0SLionel Sambuc if(ct == NULL) {
616ebfedea0SLionel Sambuc if (context)
617ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
618ebfedea0SLionel Sambuc N_("checksum type %d not supported", ""),
619ebfedea0SLionel Sambuc type);
620ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP;
621ebfedea0SLionel Sambuc }
622ebfedea0SLionel Sambuc return ct->flags & F_CPROOF;
623ebfedea0SLionel Sambuc }
624ebfedea0SLionel Sambuc
625ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_checksum_disable(krb5_context context,krb5_cksumtype type)626ebfedea0SLionel Sambuc krb5_checksum_disable(krb5_context context,
627ebfedea0SLionel Sambuc krb5_cksumtype type)
628ebfedea0SLionel Sambuc {
629ebfedea0SLionel Sambuc struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
630ebfedea0SLionel Sambuc if(ct == NULL) {
631ebfedea0SLionel Sambuc if (context)
632ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
633ebfedea0SLionel Sambuc N_("checksum type %d not supported", ""),
634ebfedea0SLionel Sambuc type);
635ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP;
636ebfedea0SLionel Sambuc }
637ebfedea0SLionel Sambuc ct->flags |= F_DISABLED;
638ebfedea0SLionel Sambuc return 0;
639ebfedea0SLionel Sambuc }
640ebfedea0SLionel Sambuc
641ebfedea0SLionel Sambuc /************************************************************
642ebfedea0SLionel Sambuc * *
643ebfedea0SLionel Sambuc ************************************************************/
644ebfedea0SLionel Sambuc
645ebfedea0SLionel Sambuc struct _krb5_encryption_type *
_krb5_find_enctype(krb5_enctype type)646ebfedea0SLionel Sambuc _krb5_find_enctype(krb5_enctype type)
647ebfedea0SLionel Sambuc {
648ebfedea0SLionel Sambuc int i;
649ebfedea0SLionel Sambuc for(i = 0; i < _krb5_num_etypes; i++)
650ebfedea0SLionel Sambuc if(_krb5_etypes[i]->type == type)
651ebfedea0SLionel Sambuc return _krb5_etypes[i];
652ebfedea0SLionel Sambuc return NULL;
653ebfedea0SLionel Sambuc }
654ebfedea0SLionel Sambuc
655ebfedea0SLionel Sambuc
656ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_enctype_to_string(krb5_context context,krb5_enctype etype,char ** string)657ebfedea0SLionel Sambuc krb5_enctype_to_string(krb5_context context,
658ebfedea0SLionel Sambuc krb5_enctype etype,
659ebfedea0SLionel Sambuc char **string)
660ebfedea0SLionel Sambuc {
661ebfedea0SLionel Sambuc struct _krb5_encryption_type *e;
662ebfedea0SLionel Sambuc e = _krb5_find_enctype(etype);
663ebfedea0SLionel Sambuc if(e == NULL) {
664ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
665ebfedea0SLionel Sambuc N_("encryption type %d not supported", ""),
666ebfedea0SLionel Sambuc etype);
667ebfedea0SLionel Sambuc *string = NULL;
668ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP;
669ebfedea0SLionel Sambuc }
670ebfedea0SLionel Sambuc *string = strdup(e->name);
671ebfedea0SLionel Sambuc if(*string == NULL) {
672ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
673ebfedea0SLionel Sambuc return ENOMEM;
674ebfedea0SLionel Sambuc }
675ebfedea0SLionel Sambuc return 0;
676ebfedea0SLionel Sambuc }
677ebfedea0SLionel Sambuc
678ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_string_to_enctype(krb5_context context,const char * string,krb5_enctype * etype)679ebfedea0SLionel Sambuc krb5_string_to_enctype(krb5_context context,
680ebfedea0SLionel Sambuc const char *string,
681ebfedea0SLionel Sambuc krb5_enctype *etype)
682ebfedea0SLionel Sambuc {
683ebfedea0SLionel Sambuc int i;
684ebfedea0SLionel Sambuc for(i = 0; i < _krb5_num_etypes; i++)
685ebfedea0SLionel Sambuc if(strcasecmp(_krb5_etypes[i]->name, string) == 0){
686ebfedea0SLionel Sambuc *etype = _krb5_etypes[i]->type;
687ebfedea0SLionel Sambuc return 0;
688ebfedea0SLionel Sambuc }
689ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
690ebfedea0SLionel Sambuc N_("encryption type %s not supported", ""),
691ebfedea0SLionel Sambuc string);
692ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP;
693ebfedea0SLionel Sambuc }
694ebfedea0SLionel Sambuc
695ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_enctype_to_keytype(krb5_context context,krb5_enctype etype,krb5_keytype * keytype)696ebfedea0SLionel Sambuc krb5_enctype_to_keytype(krb5_context context,
697ebfedea0SLionel Sambuc krb5_enctype etype,
698ebfedea0SLionel Sambuc krb5_keytype *keytype)
699ebfedea0SLionel Sambuc {
700ebfedea0SLionel Sambuc struct _krb5_encryption_type *e = _krb5_find_enctype(etype);
701ebfedea0SLionel Sambuc if(e == NULL) {
702*0a6a1f1dSLionel Sambuc return unsupported_enctype (context, etype);
703ebfedea0SLionel Sambuc }
704ebfedea0SLionel Sambuc *keytype = e->keytype->type; /* XXX */
705ebfedea0SLionel Sambuc return 0;
706ebfedea0SLionel Sambuc }
707ebfedea0SLionel Sambuc
708*0a6a1f1dSLionel Sambuc /**
709*0a6a1f1dSLionel Sambuc * Check if a enctype is valid, return 0 if it is.
710*0a6a1f1dSLionel Sambuc *
711*0a6a1f1dSLionel Sambuc * @param context Kerberos context
712*0a6a1f1dSLionel Sambuc * @param etype enctype to check if its valid or not
713*0a6a1f1dSLionel Sambuc *
714*0a6a1f1dSLionel Sambuc * @return Return an error code for an failure or 0 on success (enctype valid).
715*0a6a1f1dSLionel Sambuc * @ingroup krb5_crypto
716*0a6a1f1dSLionel Sambuc */
717*0a6a1f1dSLionel Sambuc
718ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_enctype_valid(krb5_context context,krb5_enctype etype)719ebfedea0SLionel Sambuc krb5_enctype_valid(krb5_context context,
720ebfedea0SLionel Sambuc krb5_enctype etype)
721ebfedea0SLionel Sambuc {
722ebfedea0SLionel Sambuc struct _krb5_encryption_type *e = _krb5_find_enctype(etype);
723*0a6a1f1dSLionel Sambuc if(e && (e->flags & F_DISABLED) == 0)
724*0a6a1f1dSLionel Sambuc return 0;
725*0a6a1f1dSLionel Sambuc if (context == NULL)
726ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP;
727*0a6a1f1dSLionel Sambuc if(e == NULL) {
728*0a6a1f1dSLionel Sambuc return unsupported_enctype (context, etype);
729ebfedea0SLionel Sambuc }
730*0a6a1f1dSLionel Sambuc /* Must be (e->flags & F_DISABLED) */
731ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
732ebfedea0SLionel Sambuc N_("encryption type %s is disabled", ""),
733ebfedea0SLionel Sambuc e->name);
734ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP;
735ebfedea0SLionel Sambuc }
736ebfedea0SLionel Sambuc
737ebfedea0SLionel Sambuc /**
738ebfedea0SLionel Sambuc * Return the coresponding encryption type for a checksum type.
739ebfedea0SLionel Sambuc *
740ebfedea0SLionel Sambuc * @param context Kerberos context
741ebfedea0SLionel Sambuc * @param ctype The checksum type to get the result enctype for
742ebfedea0SLionel Sambuc * @param etype The returned encryption, when the matching etype is
743ebfedea0SLionel Sambuc * not found, etype is set to ETYPE_NULL.
744ebfedea0SLionel Sambuc *
745ebfedea0SLionel Sambuc * @return Return an error code for an failure or 0 on success.
746ebfedea0SLionel Sambuc * @ingroup krb5_crypto
747ebfedea0SLionel Sambuc */
748ebfedea0SLionel Sambuc
749ebfedea0SLionel Sambuc
750ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_cksumtype_to_enctype(krb5_context context,krb5_cksumtype ctype,krb5_enctype * etype)751ebfedea0SLionel Sambuc krb5_cksumtype_to_enctype(krb5_context context,
752ebfedea0SLionel Sambuc krb5_cksumtype ctype,
753ebfedea0SLionel Sambuc krb5_enctype *etype)
754ebfedea0SLionel Sambuc {
755ebfedea0SLionel Sambuc int i;
756ebfedea0SLionel Sambuc
757ebfedea0SLionel Sambuc *etype = ETYPE_NULL;
758ebfedea0SLionel Sambuc
759ebfedea0SLionel Sambuc for(i = 0; i < _krb5_num_etypes; i++) {
760ebfedea0SLionel Sambuc if(_krb5_etypes[i]->keyed_checksum &&
761ebfedea0SLionel Sambuc _krb5_etypes[i]->keyed_checksum->type == ctype)
762ebfedea0SLionel Sambuc {
763ebfedea0SLionel Sambuc *etype = _krb5_etypes[i]->type;
764ebfedea0SLionel Sambuc return 0;
765ebfedea0SLionel Sambuc }
766ebfedea0SLionel Sambuc }
767ebfedea0SLionel Sambuc
768ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
769ebfedea0SLionel Sambuc N_("checksum type %d not supported", ""),
770ebfedea0SLionel Sambuc (int)ctype);
771ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP;
772ebfedea0SLionel Sambuc }
773ebfedea0SLionel Sambuc
774ebfedea0SLionel Sambuc
775ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_cksumtype_valid(krb5_context context,krb5_cksumtype ctype)776ebfedea0SLionel Sambuc krb5_cksumtype_valid(krb5_context context,
777ebfedea0SLionel Sambuc krb5_cksumtype ctype)
778ebfedea0SLionel Sambuc {
779ebfedea0SLionel Sambuc struct _krb5_checksum_type *c = _krb5_find_checksum(ctype);
780ebfedea0SLionel Sambuc if (c == NULL) {
781ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
782ebfedea0SLionel Sambuc N_("checksum type %d not supported", ""),
783ebfedea0SLionel Sambuc ctype);
784ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP;
785ebfedea0SLionel Sambuc }
786ebfedea0SLionel Sambuc if (c->flags & F_DISABLED) {
787ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
788ebfedea0SLionel Sambuc N_("checksum type %s is disabled", ""),
789ebfedea0SLionel Sambuc c->name);
790ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP;
791ebfedea0SLionel Sambuc }
792ebfedea0SLionel Sambuc return 0;
793ebfedea0SLionel Sambuc }
794ebfedea0SLionel Sambuc
795ebfedea0SLionel Sambuc
796ebfedea0SLionel Sambuc static krb5_boolean
derived_crypto(krb5_context context,krb5_crypto crypto)797ebfedea0SLionel Sambuc derived_crypto(krb5_context context,
798ebfedea0SLionel Sambuc krb5_crypto crypto)
799ebfedea0SLionel Sambuc {
800ebfedea0SLionel Sambuc return (crypto->et->flags & F_DERIVED) != 0;
801ebfedea0SLionel Sambuc }
802ebfedea0SLionel Sambuc
803ebfedea0SLionel Sambuc static krb5_boolean
special_crypto(krb5_context context,krb5_crypto crypto)804ebfedea0SLionel Sambuc special_crypto(krb5_context context,
805ebfedea0SLionel Sambuc krb5_crypto crypto)
806ebfedea0SLionel Sambuc {
807ebfedea0SLionel Sambuc return (crypto->et->flags & F_SPECIAL) != 0;
808ebfedea0SLionel Sambuc }
809ebfedea0SLionel Sambuc
810ebfedea0SLionel Sambuc #define CHECKSUMSIZE(C) ((C)->checksumsize)
811ebfedea0SLionel Sambuc #define CHECKSUMTYPE(C) ((C)->type)
812ebfedea0SLionel Sambuc
813ebfedea0SLionel Sambuc 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)814ebfedea0SLionel Sambuc encrypt_internal_derived(krb5_context context,
815ebfedea0SLionel Sambuc krb5_crypto crypto,
816ebfedea0SLionel Sambuc unsigned usage,
817ebfedea0SLionel Sambuc const void *data,
818ebfedea0SLionel Sambuc size_t len,
819ebfedea0SLionel Sambuc krb5_data *result,
820ebfedea0SLionel Sambuc void *ivec)
821ebfedea0SLionel Sambuc {
822ebfedea0SLionel Sambuc size_t sz, block_sz, checksum_sz, total_sz;
823ebfedea0SLionel Sambuc Checksum cksum;
824ebfedea0SLionel Sambuc unsigned char *p, *q;
825ebfedea0SLionel Sambuc krb5_error_code ret;
826ebfedea0SLionel Sambuc struct _krb5_key_data *dkey;
827ebfedea0SLionel Sambuc const struct _krb5_encryption_type *et = crypto->et;
828ebfedea0SLionel Sambuc
829ebfedea0SLionel Sambuc checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
830ebfedea0SLionel Sambuc
831ebfedea0SLionel Sambuc sz = et->confoundersize + len;
832ebfedea0SLionel Sambuc block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
833ebfedea0SLionel Sambuc total_sz = block_sz + checksum_sz;
834ebfedea0SLionel Sambuc p = calloc(1, total_sz);
835ebfedea0SLionel Sambuc if(p == NULL) {
836ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
837ebfedea0SLionel Sambuc return ENOMEM;
838ebfedea0SLionel Sambuc }
839ebfedea0SLionel Sambuc
840ebfedea0SLionel Sambuc q = p;
841ebfedea0SLionel Sambuc krb5_generate_random_block(q, et->confoundersize); /* XXX */
842ebfedea0SLionel Sambuc q += et->confoundersize;
843ebfedea0SLionel Sambuc memcpy(q, data, len);
844ebfedea0SLionel Sambuc
845ebfedea0SLionel Sambuc ret = create_checksum(context,
846ebfedea0SLionel Sambuc et->keyed_checksum,
847ebfedea0SLionel Sambuc crypto,
848ebfedea0SLionel Sambuc INTEGRITY_USAGE(usage),
849ebfedea0SLionel Sambuc p,
850ebfedea0SLionel Sambuc block_sz,
851ebfedea0SLionel Sambuc &cksum);
852ebfedea0SLionel Sambuc if(ret == 0 && cksum.checksum.length != checksum_sz) {
853ebfedea0SLionel Sambuc free_Checksum (&cksum);
854ebfedea0SLionel Sambuc krb5_clear_error_message (context);
855ebfedea0SLionel Sambuc ret = KRB5_CRYPTO_INTERNAL;
856ebfedea0SLionel Sambuc }
857ebfedea0SLionel Sambuc if(ret)
858ebfedea0SLionel Sambuc goto fail;
859ebfedea0SLionel Sambuc memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
860ebfedea0SLionel Sambuc free_Checksum (&cksum);
861ebfedea0SLionel Sambuc ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
862ebfedea0SLionel Sambuc if(ret)
863ebfedea0SLionel Sambuc goto fail;
864ebfedea0SLionel Sambuc ret = _key_schedule(context, dkey);
865ebfedea0SLionel Sambuc if(ret)
866ebfedea0SLionel Sambuc goto fail;
867ebfedea0SLionel Sambuc ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
868ebfedea0SLionel Sambuc if (ret)
869ebfedea0SLionel Sambuc goto fail;
870ebfedea0SLionel Sambuc result->data = p;
871ebfedea0SLionel Sambuc result->length = total_sz;
872ebfedea0SLionel Sambuc return 0;
873ebfedea0SLionel Sambuc fail:
874ebfedea0SLionel Sambuc memset(p, 0, total_sz);
875ebfedea0SLionel Sambuc free(p);
876ebfedea0SLionel Sambuc return ret;
877ebfedea0SLionel Sambuc }
878ebfedea0SLionel Sambuc
879ebfedea0SLionel Sambuc
880ebfedea0SLionel Sambuc static krb5_error_code
encrypt_internal(krb5_context context,krb5_crypto crypto,const void * data,size_t len,krb5_data * result,void * ivec)881ebfedea0SLionel Sambuc encrypt_internal(krb5_context context,
882ebfedea0SLionel Sambuc krb5_crypto crypto,
883ebfedea0SLionel Sambuc const void *data,
884ebfedea0SLionel Sambuc size_t len,
885ebfedea0SLionel Sambuc krb5_data *result,
886ebfedea0SLionel Sambuc void *ivec)
887ebfedea0SLionel Sambuc {
888ebfedea0SLionel Sambuc size_t sz, block_sz, checksum_sz;
889ebfedea0SLionel Sambuc Checksum cksum;
890ebfedea0SLionel Sambuc unsigned char *p, *q;
891ebfedea0SLionel Sambuc krb5_error_code ret;
892ebfedea0SLionel Sambuc const struct _krb5_encryption_type *et = crypto->et;
893ebfedea0SLionel Sambuc
894ebfedea0SLionel Sambuc checksum_sz = CHECKSUMSIZE(et->checksum);
895ebfedea0SLionel Sambuc
896ebfedea0SLionel Sambuc sz = et->confoundersize + checksum_sz + len;
897ebfedea0SLionel Sambuc block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
898ebfedea0SLionel Sambuc p = calloc(1, block_sz);
899ebfedea0SLionel Sambuc if(p == NULL) {
900ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
901ebfedea0SLionel Sambuc return ENOMEM;
902ebfedea0SLionel Sambuc }
903ebfedea0SLionel Sambuc
904ebfedea0SLionel Sambuc q = p;
905ebfedea0SLionel Sambuc krb5_generate_random_block(q, et->confoundersize); /* XXX */
906ebfedea0SLionel Sambuc q += et->confoundersize;
907ebfedea0SLionel Sambuc memset(q, 0, checksum_sz);
908ebfedea0SLionel Sambuc q += checksum_sz;
909ebfedea0SLionel Sambuc memcpy(q, data, len);
910ebfedea0SLionel Sambuc
911ebfedea0SLionel Sambuc ret = create_checksum(context,
912ebfedea0SLionel Sambuc et->checksum,
913ebfedea0SLionel Sambuc crypto,
914ebfedea0SLionel Sambuc 0,
915ebfedea0SLionel Sambuc p,
916ebfedea0SLionel Sambuc block_sz,
917ebfedea0SLionel Sambuc &cksum);
918ebfedea0SLionel Sambuc if(ret == 0 && cksum.checksum.length != checksum_sz) {
919ebfedea0SLionel Sambuc krb5_clear_error_message (context);
920ebfedea0SLionel Sambuc free_Checksum(&cksum);
921ebfedea0SLionel Sambuc ret = KRB5_CRYPTO_INTERNAL;
922ebfedea0SLionel Sambuc }
923ebfedea0SLionel Sambuc if(ret)
924ebfedea0SLionel Sambuc goto fail;
925ebfedea0SLionel Sambuc memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
926ebfedea0SLionel Sambuc free_Checksum(&cksum);
927ebfedea0SLionel Sambuc ret = _key_schedule(context, &crypto->key);
928ebfedea0SLionel Sambuc if(ret)
929ebfedea0SLionel Sambuc goto fail;
930ebfedea0SLionel Sambuc ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
931ebfedea0SLionel Sambuc if (ret) {
932ebfedea0SLionel Sambuc memset(p, 0, block_sz);
933ebfedea0SLionel Sambuc free(p);
934ebfedea0SLionel Sambuc return ret;
935ebfedea0SLionel Sambuc }
936ebfedea0SLionel Sambuc result->data = p;
937ebfedea0SLionel Sambuc result->length = block_sz;
938ebfedea0SLionel Sambuc return 0;
939ebfedea0SLionel Sambuc fail:
940ebfedea0SLionel Sambuc memset(p, 0, block_sz);
941ebfedea0SLionel Sambuc free(p);
942ebfedea0SLionel Sambuc return ret;
943ebfedea0SLionel Sambuc }
944ebfedea0SLionel Sambuc
945ebfedea0SLionel Sambuc 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)946ebfedea0SLionel Sambuc encrypt_internal_special(krb5_context context,
947ebfedea0SLionel Sambuc krb5_crypto crypto,
948ebfedea0SLionel Sambuc int usage,
949ebfedea0SLionel Sambuc const void *data,
950ebfedea0SLionel Sambuc size_t len,
951ebfedea0SLionel Sambuc krb5_data *result,
952ebfedea0SLionel Sambuc void *ivec)
953ebfedea0SLionel Sambuc {
954ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = crypto->et;
955ebfedea0SLionel Sambuc size_t cksum_sz = CHECKSUMSIZE(et->checksum);
956ebfedea0SLionel Sambuc size_t sz = len + cksum_sz + et->confoundersize;
957ebfedea0SLionel Sambuc char *tmp, *p;
958ebfedea0SLionel Sambuc krb5_error_code ret;
959ebfedea0SLionel Sambuc
960ebfedea0SLionel Sambuc tmp = malloc (sz);
961ebfedea0SLionel Sambuc if (tmp == NULL) {
962ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
963ebfedea0SLionel Sambuc return ENOMEM;
964ebfedea0SLionel Sambuc }
965ebfedea0SLionel Sambuc p = tmp;
966ebfedea0SLionel Sambuc memset (p, 0, cksum_sz);
967ebfedea0SLionel Sambuc p += cksum_sz;
968ebfedea0SLionel Sambuc krb5_generate_random_block(p, et->confoundersize);
969ebfedea0SLionel Sambuc p += et->confoundersize;
970ebfedea0SLionel Sambuc memcpy (p, data, len);
971ebfedea0SLionel Sambuc ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
972ebfedea0SLionel Sambuc if (ret) {
973ebfedea0SLionel Sambuc memset(tmp, 0, sz);
974ebfedea0SLionel Sambuc free(tmp);
975ebfedea0SLionel Sambuc return ret;
976ebfedea0SLionel Sambuc }
977ebfedea0SLionel Sambuc result->data = tmp;
978ebfedea0SLionel Sambuc result->length = sz;
979ebfedea0SLionel Sambuc return 0;
980ebfedea0SLionel Sambuc }
981ebfedea0SLionel Sambuc
982ebfedea0SLionel Sambuc 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)983ebfedea0SLionel Sambuc decrypt_internal_derived(krb5_context context,
984ebfedea0SLionel Sambuc krb5_crypto crypto,
985ebfedea0SLionel Sambuc unsigned usage,
986ebfedea0SLionel Sambuc void *data,
987ebfedea0SLionel Sambuc size_t len,
988ebfedea0SLionel Sambuc krb5_data *result,
989ebfedea0SLionel Sambuc void *ivec)
990ebfedea0SLionel Sambuc {
991ebfedea0SLionel Sambuc size_t checksum_sz;
992ebfedea0SLionel Sambuc Checksum cksum;
993ebfedea0SLionel Sambuc unsigned char *p;
994ebfedea0SLionel Sambuc krb5_error_code ret;
995ebfedea0SLionel Sambuc struct _krb5_key_data *dkey;
996ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = crypto->et;
997ebfedea0SLionel Sambuc unsigned long l;
998ebfedea0SLionel Sambuc
999ebfedea0SLionel Sambuc checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
1000ebfedea0SLionel Sambuc if (len < checksum_sz + et->confoundersize) {
1001ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_BAD_MSIZE,
1002ebfedea0SLionel Sambuc N_("Encrypted data shorter then "
1003ebfedea0SLionel Sambuc "checksum + confunder", ""));
1004ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE;
1005ebfedea0SLionel Sambuc }
1006ebfedea0SLionel Sambuc
1007ebfedea0SLionel Sambuc if (((len - checksum_sz) % et->padsize) != 0) {
1008ebfedea0SLionel Sambuc krb5_clear_error_message(context);
1009ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE;
1010ebfedea0SLionel Sambuc }
1011ebfedea0SLionel Sambuc
1012ebfedea0SLionel Sambuc p = malloc(len);
1013ebfedea0SLionel Sambuc if(len != 0 && p == NULL) {
1014ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1015ebfedea0SLionel Sambuc return ENOMEM;
1016ebfedea0SLionel Sambuc }
1017ebfedea0SLionel Sambuc memcpy(p, data, len);
1018ebfedea0SLionel Sambuc
1019ebfedea0SLionel Sambuc len -= checksum_sz;
1020ebfedea0SLionel Sambuc
1021ebfedea0SLionel Sambuc ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1022ebfedea0SLionel Sambuc if(ret) {
1023ebfedea0SLionel Sambuc free(p);
1024ebfedea0SLionel Sambuc return ret;
1025ebfedea0SLionel Sambuc }
1026ebfedea0SLionel Sambuc ret = _key_schedule(context, dkey);
1027ebfedea0SLionel Sambuc if(ret) {
1028ebfedea0SLionel Sambuc free(p);
1029ebfedea0SLionel Sambuc return ret;
1030ebfedea0SLionel Sambuc }
1031ebfedea0SLionel Sambuc ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
1032ebfedea0SLionel Sambuc if (ret) {
1033ebfedea0SLionel Sambuc free(p);
1034ebfedea0SLionel Sambuc return ret;
1035ebfedea0SLionel Sambuc }
1036ebfedea0SLionel Sambuc
1037ebfedea0SLionel Sambuc cksum.checksum.data = p + len;
1038ebfedea0SLionel Sambuc cksum.checksum.length = checksum_sz;
1039ebfedea0SLionel Sambuc cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
1040ebfedea0SLionel Sambuc
1041ebfedea0SLionel Sambuc ret = verify_checksum(context,
1042ebfedea0SLionel Sambuc crypto,
1043ebfedea0SLionel Sambuc INTEGRITY_USAGE(usage),
1044ebfedea0SLionel Sambuc p,
1045ebfedea0SLionel Sambuc len,
1046ebfedea0SLionel Sambuc &cksum);
1047ebfedea0SLionel Sambuc if(ret) {
1048ebfedea0SLionel Sambuc free(p);
1049ebfedea0SLionel Sambuc return ret;
1050ebfedea0SLionel Sambuc }
1051ebfedea0SLionel Sambuc l = len - et->confoundersize;
1052ebfedea0SLionel Sambuc memmove(p, p + et->confoundersize, l);
1053ebfedea0SLionel Sambuc result->data = realloc(p, l);
1054ebfedea0SLionel Sambuc if(result->data == NULL && l != 0) {
1055ebfedea0SLionel Sambuc free(p);
1056ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1057ebfedea0SLionel Sambuc return ENOMEM;
1058ebfedea0SLionel Sambuc }
1059ebfedea0SLionel Sambuc result->length = l;
1060ebfedea0SLionel Sambuc return 0;
1061ebfedea0SLionel Sambuc }
1062ebfedea0SLionel Sambuc
1063ebfedea0SLionel Sambuc static krb5_error_code
decrypt_internal(krb5_context context,krb5_crypto crypto,void * data,size_t len,krb5_data * result,void * ivec)1064ebfedea0SLionel Sambuc decrypt_internal(krb5_context context,
1065ebfedea0SLionel Sambuc krb5_crypto crypto,
1066ebfedea0SLionel Sambuc void *data,
1067ebfedea0SLionel Sambuc size_t len,
1068ebfedea0SLionel Sambuc krb5_data *result,
1069ebfedea0SLionel Sambuc void *ivec)
1070ebfedea0SLionel Sambuc {
1071ebfedea0SLionel Sambuc krb5_error_code ret;
1072ebfedea0SLionel Sambuc unsigned char *p;
1073ebfedea0SLionel Sambuc Checksum cksum;
1074ebfedea0SLionel Sambuc size_t checksum_sz, l;
1075ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = crypto->et;
1076ebfedea0SLionel Sambuc
1077ebfedea0SLionel Sambuc if ((len % et->padsize) != 0) {
1078ebfedea0SLionel Sambuc krb5_clear_error_message(context);
1079ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE;
1080ebfedea0SLionel Sambuc }
1081ebfedea0SLionel Sambuc checksum_sz = CHECKSUMSIZE(et->checksum);
1082ebfedea0SLionel Sambuc if (len < checksum_sz + et->confoundersize) {
1083ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_BAD_MSIZE,
1084ebfedea0SLionel Sambuc N_("Encrypted data shorter then "
1085ebfedea0SLionel Sambuc "checksum + confunder", ""));
1086ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE;
1087ebfedea0SLionel Sambuc }
1088ebfedea0SLionel Sambuc
1089ebfedea0SLionel Sambuc p = malloc(len);
1090ebfedea0SLionel Sambuc if(len != 0 && p == NULL) {
1091ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1092ebfedea0SLionel Sambuc return ENOMEM;
1093ebfedea0SLionel Sambuc }
1094ebfedea0SLionel Sambuc memcpy(p, data, len);
1095ebfedea0SLionel Sambuc
1096ebfedea0SLionel Sambuc ret = _key_schedule(context, &crypto->key);
1097ebfedea0SLionel Sambuc if(ret) {
1098ebfedea0SLionel Sambuc free(p);
1099ebfedea0SLionel Sambuc return ret;
1100ebfedea0SLionel Sambuc }
1101ebfedea0SLionel Sambuc ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
1102ebfedea0SLionel Sambuc if (ret) {
1103ebfedea0SLionel Sambuc free(p);
1104ebfedea0SLionel Sambuc return ret;
1105ebfedea0SLionel Sambuc }
1106ebfedea0SLionel Sambuc ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
1107ebfedea0SLionel Sambuc if(ret) {
1108ebfedea0SLionel Sambuc free(p);
1109ebfedea0SLionel Sambuc return ret;
1110ebfedea0SLionel Sambuc }
1111ebfedea0SLionel Sambuc memset(p + et->confoundersize, 0, checksum_sz);
1112ebfedea0SLionel Sambuc cksum.cksumtype = CHECKSUMTYPE(et->checksum);
1113ebfedea0SLionel Sambuc ret = verify_checksum(context, NULL, 0, p, len, &cksum);
1114ebfedea0SLionel Sambuc free_Checksum(&cksum);
1115ebfedea0SLionel Sambuc if(ret) {
1116ebfedea0SLionel Sambuc free(p);
1117ebfedea0SLionel Sambuc return ret;
1118ebfedea0SLionel Sambuc }
1119ebfedea0SLionel Sambuc l = len - et->confoundersize - checksum_sz;
1120ebfedea0SLionel Sambuc memmove(p, p + et->confoundersize + checksum_sz, l);
1121ebfedea0SLionel Sambuc result->data = realloc(p, l);
1122ebfedea0SLionel Sambuc if(result->data == NULL && l != 0) {
1123ebfedea0SLionel Sambuc free(p);
1124ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1125ebfedea0SLionel Sambuc return ENOMEM;
1126ebfedea0SLionel Sambuc }
1127ebfedea0SLionel Sambuc result->length = l;
1128ebfedea0SLionel Sambuc return 0;
1129ebfedea0SLionel Sambuc }
1130ebfedea0SLionel Sambuc
1131ebfedea0SLionel Sambuc 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)1132ebfedea0SLionel Sambuc decrypt_internal_special(krb5_context context,
1133ebfedea0SLionel Sambuc krb5_crypto crypto,
1134ebfedea0SLionel Sambuc int usage,
1135ebfedea0SLionel Sambuc void *data,
1136ebfedea0SLionel Sambuc size_t len,
1137ebfedea0SLionel Sambuc krb5_data *result,
1138ebfedea0SLionel Sambuc void *ivec)
1139ebfedea0SLionel Sambuc {
1140ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = crypto->et;
1141ebfedea0SLionel Sambuc size_t cksum_sz = CHECKSUMSIZE(et->checksum);
1142ebfedea0SLionel Sambuc size_t sz = len - cksum_sz - et->confoundersize;
1143ebfedea0SLionel Sambuc unsigned char *p;
1144ebfedea0SLionel Sambuc krb5_error_code ret;
1145ebfedea0SLionel Sambuc
1146ebfedea0SLionel Sambuc if ((len % et->padsize) != 0) {
1147ebfedea0SLionel Sambuc krb5_clear_error_message(context);
1148ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE;
1149ebfedea0SLionel Sambuc }
1150ebfedea0SLionel Sambuc if (len < cksum_sz + et->confoundersize) {
1151ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_BAD_MSIZE,
1152ebfedea0SLionel Sambuc N_("Encrypted data shorter then "
1153ebfedea0SLionel Sambuc "checksum + confunder", ""));
1154ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE;
1155ebfedea0SLionel Sambuc }
1156ebfedea0SLionel Sambuc
1157ebfedea0SLionel Sambuc p = malloc (len);
1158ebfedea0SLionel Sambuc if (p == NULL) {
1159ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1160ebfedea0SLionel Sambuc return ENOMEM;
1161ebfedea0SLionel Sambuc }
1162ebfedea0SLionel Sambuc memcpy(p, data, len);
1163ebfedea0SLionel Sambuc
1164ebfedea0SLionel Sambuc ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec);
1165ebfedea0SLionel Sambuc if (ret) {
1166ebfedea0SLionel Sambuc free(p);
1167ebfedea0SLionel Sambuc return ret;
1168ebfedea0SLionel Sambuc }
1169ebfedea0SLionel Sambuc
1170ebfedea0SLionel Sambuc memmove (p, p + cksum_sz + et->confoundersize, sz);
1171ebfedea0SLionel Sambuc result->data = realloc(p, sz);
1172ebfedea0SLionel Sambuc if(result->data == NULL && sz != 0) {
1173ebfedea0SLionel Sambuc free(p);
1174ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1175ebfedea0SLionel Sambuc return ENOMEM;
1176ebfedea0SLionel Sambuc }
1177ebfedea0SLionel Sambuc result->length = sz;
1178ebfedea0SLionel Sambuc return 0;
1179ebfedea0SLionel Sambuc }
1180ebfedea0SLionel Sambuc
1181ebfedea0SLionel Sambuc static krb5_crypto_iov *
find_iv(krb5_crypto_iov * data,size_t num_data,unsigned type)1182*0a6a1f1dSLionel Sambuc find_iv(krb5_crypto_iov *data, size_t num_data, unsigned type)
1183ebfedea0SLionel Sambuc {
1184*0a6a1f1dSLionel Sambuc size_t i;
1185ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++)
1186ebfedea0SLionel Sambuc if (data[i].flags == type)
1187ebfedea0SLionel Sambuc return &data[i];
1188ebfedea0SLionel Sambuc return NULL;
1189ebfedea0SLionel Sambuc }
1190ebfedea0SLionel Sambuc
1191ebfedea0SLionel Sambuc /**
1192ebfedea0SLionel Sambuc * Inline encrypt a kerberos message
1193ebfedea0SLionel Sambuc *
1194ebfedea0SLionel Sambuc * @param context Kerberos context
1195ebfedea0SLionel Sambuc * @param crypto Kerberos crypto context
1196ebfedea0SLionel Sambuc * @param usage Key usage for this buffer
1197ebfedea0SLionel Sambuc * @param data array of buffers to process
1198ebfedea0SLionel Sambuc * @param num_data length of array
1199ebfedea0SLionel Sambuc * @param ivec initial cbc/cts vector
1200ebfedea0SLionel Sambuc *
1201ebfedea0SLionel Sambuc * @return Return an error code or 0.
1202ebfedea0SLionel Sambuc * @ingroup krb5_crypto
1203ebfedea0SLionel Sambuc *
1204ebfedea0SLionel Sambuc * Kerberos encrypted data look like this:
1205ebfedea0SLionel Sambuc *
1206ebfedea0SLionel Sambuc * 1. KRB5_CRYPTO_TYPE_HEADER
1207ebfedea0SLionel Sambuc * 2. array [1,...] KRB5_CRYPTO_TYPE_DATA and array [0,...]
1208ebfedea0SLionel Sambuc * KRB5_CRYPTO_TYPE_SIGN_ONLY in any order, however the receiver
1209ebfedea0SLionel Sambuc * have to aware of the order. KRB5_CRYPTO_TYPE_SIGN_ONLY is
1210ebfedea0SLionel Sambuc * commonly used headers and trailers.
1211ebfedea0SLionel Sambuc * 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1
1212ebfedea0SLionel Sambuc * 4. KRB5_CRYPTO_TYPE_TRAILER
1213ebfedea0SLionel Sambuc */
1214ebfedea0SLionel Sambuc
1215ebfedea0SLionel Sambuc 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)1216ebfedea0SLionel Sambuc krb5_encrypt_iov_ivec(krb5_context context,
1217ebfedea0SLionel Sambuc krb5_crypto crypto,
1218ebfedea0SLionel Sambuc unsigned usage,
1219ebfedea0SLionel Sambuc krb5_crypto_iov *data,
1220ebfedea0SLionel Sambuc int num_data,
1221ebfedea0SLionel Sambuc void *ivec)
1222ebfedea0SLionel Sambuc {
1223ebfedea0SLionel Sambuc size_t headersz, trailersz, len;
1224ebfedea0SLionel Sambuc int i;
1225ebfedea0SLionel Sambuc size_t sz, block_sz, pad_sz;
1226ebfedea0SLionel Sambuc Checksum cksum;
1227ebfedea0SLionel Sambuc unsigned char *p, *q;
1228ebfedea0SLionel Sambuc krb5_error_code ret;
1229ebfedea0SLionel Sambuc struct _krb5_key_data *dkey;
1230ebfedea0SLionel Sambuc const struct _krb5_encryption_type *et = crypto->et;
1231ebfedea0SLionel Sambuc krb5_crypto_iov *tiv, *piv, *hiv;
1232ebfedea0SLionel Sambuc
1233ebfedea0SLionel Sambuc if (num_data < 0) {
1234ebfedea0SLionel Sambuc krb5_clear_error_message(context);
1235ebfedea0SLionel Sambuc return KRB5_CRYPTO_INTERNAL;
1236ebfedea0SLionel Sambuc }
1237ebfedea0SLionel Sambuc
1238ebfedea0SLionel Sambuc if(!derived_crypto(context, crypto)) {
1239ebfedea0SLionel Sambuc krb5_clear_error_message(context);
1240ebfedea0SLionel Sambuc return KRB5_CRYPTO_INTERNAL;
1241ebfedea0SLionel Sambuc }
1242ebfedea0SLionel Sambuc
1243ebfedea0SLionel Sambuc headersz = et->confoundersize;
1244ebfedea0SLionel Sambuc trailersz = CHECKSUMSIZE(et->keyed_checksum);
1245ebfedea0SLionel Sambuc
1246ebfedea0SLionel Sambuc for (len = 0, i = 0; i < num_data; i++) {
1247ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1248ebfedea0SLionel Sambuc continue;
1249ebfedea0SLionel Sambuc len += data[i].data.length;
1250ebfedea0SLionel Sambuc }
1251ebfedea0SLionel Sambuc
1252ebfedea0SLionel Sambuc sz = headersz + len;
1253ebfedea0SLionel Sambuc block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
1254ebfedea0SLionel Sambuc
1255ebfedea0SLionel Sambuc pad_sz = block_sz - sz;
1256ebfedea0SLionel Sambuc
1257ebfedea0SLionel Sambuc /* header */
1258ebfedea0SLionel Sambuc
1259ebfedea0SLionel Sambuc hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
1260ebfedea0SLionel Sambuc if (hiv == NULL || hiv->data.length != headersz)
1261ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE;
1262ebfedea0SLionel Sambuc
1263ebfedea0SLionel Sambuc krb5_generate_random_block(hiv->data.data, hiv->data.length);
1264ebfedea0SLionel Sambuc
1265ebfedea0SLionel Sambuc /* padding */
1266ebfedea0SLionel Sambuc piv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
1267ebfedea0SLionel Sambuc /* its ok to have no TYPE_PADDING if there is no padding */
1268ebfedea0SLionel Sambuc if (piv == NULL && pad_sz != 0)
1269ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE;
1270ebfedea0SLionel Sambuc if (piv) {
1271ebfedea0SLionel Sambuc if (piv->data.length < pad_sz)
1272ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE;
1273ebfedea0SLionel Sambuc piv->data.length = pad_sz;
1274ebfedea0SLionel Sambuc if (pad_sz)
1275ebfedea0SLionel Sambuc memset(piv->data.data, pad_sz, pad_sz);
1276ebfedea0SLionel Sambuc else
1277ebfedea0SLionel Sambuc piv = NULL;
1278ebfedea0SLionel Sambuc }
1279ebfedea0SLionel Sambuc
1280ebfedea0SLionel Sambuc /* trailer */
1281ebfedea0SLionel Sambuc tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
1282ebfedea0SLionel Sambuc if (tiv == NULL || tiv->data.length != trailersz)
1283ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE;
1284ebfedea0SLionel Sambuc
1285ebfedea0SLionel Sambuc /*
1286ebfedea0SLionel Sambuc * XXX replace with EVP_Sign? at least make create_checksum an iov
1287ebfedea0SLionel Sambuc * function.
1288ebfedea0SLionel Sambuc * XXX CTS EVP is broken, can't handle multi buffers :(
1289ebfedea0SLionel Sambuc */
1290ebfedea0SLionel Sambuc
1291ebfedea0SLionel Sambuc len = block_sz;
1292ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) {
1293ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1294ebfedea0SLionel Sambuc continue;
1295ebfedea0SLionel Sambuc len += data[i].data.length;
1296ebfedea0SLionel Sambuc }
1297ebfedea0SLionel Sambuc
1298ebfedea0SLionel Sambuc p = q = malloc(len);
1299ebfedea0SLionel Sambuc
1300ebfedea0SLionel Sambuc memcpy(q, hiv->data.data, hiv->data.length);
1301ebfedea0SLionel Sambuc q += hiv->data.length;
1302ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) {
1303ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1304ebfedea0SLionel Sambuc data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1305ebfedea0SLionel Sambuc continue;
1306ebfedea0SLionel Sambuc memcpy(q, data[i].data.data, data[i].data.length);
1307ebfedea0SLionel Sambuc q += data[i].data.length;
1308ebfedea0SLionel Sambuc }
1309ebfedea0SLionel Sambuc if (piv)
1310ebfedea0SLionel Sambuc memset(q, 0, piv->data.length);
1311ebfedea0SLionel Sambuc
1312ebfedea0SLionel Sambuc ret = create_checksum(context,
1313ebfedea0SLionel Sambuc et->keyed_checksum,
1314ebfedea0SLionel Sambuc crypto,
1315ebfedea0SLionel Sambuc INTEGRITY_USAGE(usage),
1316ebfedea0SLionel Sambuc p,
1317ebfedea0SLionel Sambuc len,
1318ebfedea0SLionel Sambuc &cksum);
1319ebfedea0SLionel Sambuc free(p);
1320ebfedea0SLionel Sambuc if(ret == 0 && cksum.checksum.length != trailersz) {
1321ebfedea0SLionel Sambuc free_Checksum (&cksum);
1322ebfedea0SLionel Sambuc krb5_clear_error_message (context);
1323ebfedea0SLionel Sambuc ret = KRB5_CRYPTO_INTERNAL;
1324ebfedea0SLionel Sambuc }
1325ebfedea0SLionel Sambuc if(ret)
1326ebfedea0SLionel Sambuc return ret;
1327ebfedea0SLionel Sambuc
1328ebfedea0SLionel Sambuc /* save cksum at end */
1329ebfedea0SLionel Sambuc memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length);
1330ebfedea0SLionel Sambuc free_Checksum (&cksum);
1331ebfedea0SLionel Sambuc
1332ebfedea0SLionel Sambuc /* XXX replace with EVP_Cipher */
1333ebfedea0SLionel Sambuc p = q = malloc(block_sz);
1334ebfedea0SLionel Sambuc if(p == NULL)
1335ebfedea0SLionel Sambuc return ENOMEM;
1336ebfedea0SLionel Sambuc
1337ebfedea0SLionel Sambuc memcpy(q, hiv->data.data, hiv->data.length);
1338ebfedea0SLionel Sambuc q += hiv->data.length;
1339ebfedea0SLionel Sambuc
1340ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) {
1341ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1342ebfedea0SLionel Sambuc continue;
1343ebfedea0SLionel Sambuc memcpy(q, data[i].data.data, data[i].data.length);
1344ebfedea0SLionel Sambuc q += data[i].data.length;
1345ebfedea0SLionel Sambuc }
1346ebfedea0SLionel Sambuc if (piv)
1347ebfedea0SLionel Sambuc memset(q, 0, piv->data.length);
1348ebfedea0SLionel Sambuc
1349ebfedea0SLionel Sambuc
1350ebfedea0SLionel Sambuc ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1351ebfedea0SLionel Sambuc if(ret) {
1352ebfedea0SLionel Sambuc free(p);
1353ebfedea0SLionel Sambuc return ret;
1354ebfedea0SLionel Sambuc }
1355ebfedea0SLionel Sambuc ret = _key_schedule(context, dkey);
1356ebfedea0SLionel Sambuc if(ret) {
1357ebfedea0SLionel Sambuc free(p);
1358ebfedea0SLionel Sambuc return ret;
1359ebfedea0SLionel Sambuc }
1360ebfedea0SLionel Sambuc
1361ebfedea0SLionel Sambuc ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
1362ebfedea0SLionel Sambuc if (ret) {
1363ebfedea0SLionel Sambuc free(p);
1364ebfedea0SLionel Sambuc return ret;
1365ebfedea0SLionel Sambuc }
1366ebfedea0SLionel Sambuc
1367ebfedea0SLionel Sambuc /* now copy data back to buffers */
1368ebfedea0SLionel Sambuc q = p;
1369ebfedea0SLionel Sambuc
1370ebfedea0SLionel Sambuc memcpy(hiv->data.data, q, hiv->data.length);
1371ebfedea0SLionel Sambuc q += hiv->data.length;
1372ebfedea0SLionel Sambuc
1373ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) {
1374ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1375ebfedea0SLionel Sambuc continue;
1376ebfedea0SLionel Sambuc memcpy(data[i].data.data, q, data[i].data.length);
1377ebfedea0SLionel Sambuc q += data[i].data.length;
1378ebfedea0SLionel Sambuc }
1379ebfedea0SLionel Sambuc if (piv)
1380ebfedea0SLionel Sambuc memcpy(piv->data.data, q, pad_sz);
1381ebfedea0SLionel Sambuc
1382ebfedea0SLionel Sambuc free(p);
1383ebfedea0SLionel Sambuc
1384ebfedea0SLionel Sambuc return ret;
1385ebfedea0SLionel Sambuc }
1386ebfedea0SLionel Sambuc
1387ebfedea0SLionel Sambuc /**
1388ebfedea0SLionel Sambuc * Inline decrypt a Kerberos message.
1389ebfedea0SLionel Sambuc *
1390ebfedea0SLionel Sambuc * @param context Kerberos context
1391ebfedea0SLionel Sambuc * @param crypto Kerberos crypto context
1392ebfedea0SLionel Sambuc * @param usage Key usage for this buffer
1393ebfedea0SLionel Sambuc * @param data array of buffers to process
1394ebfedea0SLionel Sambuc * @param num_data length of array
1395ebfedea0SLionel Sambuc * @param ivec initial cbc/cts vector
1396ebfedea0SLionel Sambuc *
1397ebfedea0SLionel Sambuc * @return Return an error code or 0.
1398ebfedea0SLionel Sambuc * @ingroup krb5_crypto
1399ebfedea0SLionel Sambuc *
1400ebfedea0SLionel Sambuc * 1. KRB5_CRYPTO_TYPE_HEADER
1401ebfedea0SLionel Sambuc * 2. one KRB5_CRYPTO_TYPE_DATA and array [0,...] of KRB5_CRYPTO_TYPE_SIGN_ONLY in
1402ebfedea0SLionel Sambuc * any order, however the receiver have to aware of the
1403ebfedea0SLionel Sambuc * order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted
1404ebfedea0SLionel Sambuc * protocol headers and trailers. The output data will be of same
1405ebfedea0SLionel Sambuc * size as the input data or shorter.
1406ebfedea0SLionel Sambuc */
1407ebfedea0SLionel Sambuc
1408ebfedea0SLionel Sambuc 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)1409ebfedea0SLionel Sambuc krb5_decrypt_iov_ivec(krb5_context context,
1410ebfedea0SLionel Sambuc krb5_crypto crypto,
1411ebfedea0SLionel Sambuc unsigned usage,
1412ebfedea0SLionel Sambuc krb5_crypto_iov *data,
1413ebfedea0SLionel Sambuc unsigned int num_data,
1414ebfedea0SLionel Sambuc void *ivec)
1415ebfedea0SLionel Sambuc {
1416ebfedea0SLionel Sambuc unsigned int i;
1417ebfedea0SLionel Sambuc size_t headersz, trailersz, len;
1418ebfedea0SLionel Sambuc Checksum cksum;
1419ebfedea0SLionel Sambuc unsigned char *p, *q;
1420ebfedea0SLionel Sambuc krb5_error_code ret;
1421ebfedea0SLionel Sambuc struct _krb5_key_data *dkey;
1422ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = crypto->et;
1423ebfedea0SLionel Sambuc krb5_crypto_iov *tiv, *hiv;
1424ebfedea0SLionel Sambuc
1425ebfedea0SLionel Sambuc if(!derived_crypto(context, crypto)) {
1426ebfedea0SLionel Sambuc krb5_clear_error_message(context);
1427ebfedea0SLionel Sambuc return KRB5_CRYPTO_INTERNAL;
1428ebfedea0SLionel Sambuc }
1429ebfedea0SLionel Sambuc
1430ebfedea0SLionel Sambuc headersz = et->confoundersize;
1431ebfedea0SLionel Sambuc
1432ebfedea0SLionel Sambuc hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
1433ebfedea0SLionel Sambuc if (hiv == NULL || hiv->data.length != headersz)
1434ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE;
1435ebfedea0SLionel Sambuc
1436ebfedea0SLionel Sambuc /* trailer */
1437ebfedea0SLionel Sambuc trailersz = CHECKSUMSIZE(et->keyed_checksum);
1438ebfedea0SLionel Sambuc
1439ebfedea0SLionel Sambuc tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
1440ebfedea0SLionel Sambuc if (tiv->data.length != trailersz)
1441ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE;
1442ebfedea0SLionel Sambuc
1443ebfedea0SLionel Sambuc /* Find length of data we will decrypt */
1444ebfedea0SLionel Sambuc
1445ebfedea0SLionel Sambuc len = headersz;
1446ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) {
1447ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1448ebfedea0SLionel Sambuc continue;
1449ebfedea0SLionel Sambuc len += data[i].data.length;
1450ebfedea0SLionel Sambuc }
1451ebfedea0SLionel Sambuc
1452ebfedea0SLionel Sambuc if ((len % et->padsize) != 0) {
1453ebfedea0SLionel Sambuc krb5_clear_error_message(context);
1454ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE;
1455ebfedea0SLionel Sambuc }
1456ebfedea0SLionel Sambuc
1457ebfedea0SLionel Sambuc /* XXX replace with EVP_Cipher */
1458ebfedea0SLionel Sambuc
1459ebfedea0SLionel Sambuc p = q = malloc(len);
1460ebfedea0SLionel Sambuc if (p == NULL)
1461ebfedea0SLionel Sambuc return ENOMEM;
1462ebfedea0SLionel Sambuc
1463ebfedea0SLionel Sambuc memcpy(q, hiv->data.data, hiv->data.length);
1464ebfedea0SLionel Sambuc q += hiv->data.length;
1465ebfedea0SLionel Sambuc
1466ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) {
1467ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1468ebfedea0SLionel Sambuc continue;
1469ebfedea0SLionel Sambuc memcpy(q, data[i].data.data, data[i].data.length);
1470ebfedea0SLionel Sambuc q += data[i].data.length;
1471ebfedea0SLionel Sambuc }
1472ebfedea0SLionel Sambuc
1473ebfedea0SLionel Sambuc ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1474ebfedea0SLionel Sambuc if(ret) {
1475ebfedea0SLionel Sambuc free(p);
1476ebfedea0SLionel Sambuc return ret;
1477ebfedea0SLionel Sambuc }
1478ebfedea0SLionel Sambuc ret = _key_schedule(context, dkey);
1479ebfedea0SLionel Sambuc if(ret) {
1480ebfedea0SLionel Sambuc free(p);
1481ebfedea0SLionel Sambuc return ret;
1482ebfedea0SLionel Sambuc }
1483ebfedea0SLionel Sambuc
1484ebfedea0SLionel Sambuc ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
1485ebfedea0SLionel Sambuc if (ret) {
1486ebfedea0SLionel Sambuc free(p);
1487ebfedea0SLionel Sambuc return ret;
1488ebfedea0SLionel Sambuc }
1489ebfedea0SLionel Sambuc
1490ebfedea0SLionel Sambuc /* copy data back to buffers */
1491ebfedea0SLionel Sambuc memcpy(hiv->data.data, p, hiv->data.length);
1492ebfedea0SLionel Sambuc q = p + hiv->data.length;
1493ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) {
1494ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1495ebfedea0SLionel Sambuc continue;
1496ebfedea0SLionel Sambuc memcpy(data[i].data.data, q, data[i].data.length);
1497ebfedea0SLionel Sambuc q += data[i].data.length;
1498ebfedea0SLionel Sambuc }
1499ebfedea0SLionel Sambuc
1500ebfedea0SLionel Sambuc free(p);
1501ebfedea0SLionel Sambuc
1502ebfedea0SLionel Sambuc /* check signature */
1503ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) {
1504ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1505ebfedea0SLionel Sambuc continue;
1506ebfedea0SLionel Sambuc len += data[i].data.length;
1507ebfedea0SLionel Sambuc }
1508ebfedea0SLionel Sambuc
1509ebfedea0SLionel Sambuc p = q = malloc(len);
1510ebfedea0SLionel Sambuc if (p == NULL)
1511ebfedea0SLionel Sambuc return ENOMEM;
1512ebfedea0SLionel Sambuc
1513ebfedea0SLionel Sambuc memcpy(q, hiv->data.data, hiv->data.length);
1514ebfedea0SLionel Sambuc q += hiv->data.length;
1515ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) {
1516ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1517ebfedea0SLionel Sambuc data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1518ebfedea0SLionel Sambuc continue;
1519ebfedea0SLionel Sambuc memcpy(q, data[i].data.data, data[i].data.length);
1520ebfedea0SLionel Sambuc q += data[i].data.length;
1521ebfedea0SLionel Sambuc }
1522ebfedea0SLionel Sambuc
1523ebfedea0SLionel Sambuc cksum.checksum.data = tiv->data.data;
1524ebfedea0SLionel Sambuc cksum.checksum.length = tiv->data.length;
1525ebfedea0SLionel Sambuc cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
1526ebfedea0SLionel Sambuc
1527ebfedea0SLionel Sambuc ret = verify_checksum(context,
1528ebfedea0SLionel Sambuc crypto,
1529ebfedea0SLionel Sambuc INTEGRITY_USAGE(usage),
1530ebfedea0SLionel Sambuc p,
1531ebfedea0SLionel Sambuc len,
1532ebfedea0SLionel Sambuc &cksum);
1533ebfedea0SLionel Sambuc free(p);
1534ebfedea0SLionel Sambuc return ret;
1535ebfedea0SLionel Sambuc }
1536ebfedea0SLionel Sambuc
1537ebfedea0SLionel Sambuc /**
1538ebfedea0SLionel Sambuc * Create a Kerberos message checksum.
1539ebfedea0SLionel Sambuc *
1540ebfedea0SLionel Sambuc * @param context Kerberos context
1541ebfedea0SLionel Sambuc * @param crypto Kerberos crypto context
1542ebfedea0SLionel Sambuc * @param usage Key usage for this buffer
1543ebfedea0SLionel Sambuc * @param data array of buffers to process
1544ebfedea0SLionel Sambuc * @param num_data length of array
1545ebfedea0SLionel Sambuc * @param type output data
1546ebfedea0SLionel Sambuc *
1547ebfedea0SLionel Sambuc * @return Return an error code or 0.
1548ebfedea0SLionel Sambuc * @ingroup krb5_crypto
1549ebfedea0SLionel Sambuc */
1550ebfedea0SLionel Sambuc
1551ebfedea0SLionel Sambuc 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)1552ebfedea0SLionel Sambuc krb5_create_checksum_iov(krb5_context context,
1553ebfedea0SLionel Sambuc krb5_crypto crypto,
1554ebfedea0SLionel Sambuc unsigned usage,
1555ebfedea0SLionel Sambuc krb5_crypto_iov *data,
1556ebfedea0SLionel Sambuc unsigned int num_data,
1557ebfedea0SLionel Sambuc krb5_cksumtype *type)
1558ebfedea0SLionel Sambuc {
1559ebfedea0SLionel Sambuc Checksum cksum;
1560ebfedea0SLionel Sambuc krb5_crypto_iov *civ;
1561ebfedea0SLionel Sambuc krb5_error_code ret;
1562*0a6a1f1dSLionel Sambuc size_t i;
1563ebfedea0SLionel Sambuc size_t len;
1564ebfedea0SLionel Sambuc char *p, *q;
1565ebfedea0SLionel Sambuc
1566ebfedea0SLionel Sambuc if(!derived_crypto(context, crypto)) {
1567ebfedea0SLionel Sambuc krb5_clear_error_message(context);
1568ebfedea0SLionel Sambuc return KRB5_CRYPTO_INTERNAL;
1569ebfedea0SLionel Sambuc }
1570ebfedea0SLionel Sambuc
1571ebfedea0SLionel Sambuc civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
1572ebfedea0SLionel Sambuc if (civ == NULL)
1573ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE;
1574ebfedea0SLionel Sambuc
1575ebfedea0SLionel Sambuc len = 0;
1576ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) {
1577ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1578ebfedea0SLionel Sambuc data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1579ebfedea0SLionel Sambuc continue;
1580ebfedea0SLionel Sambuc len += data[i].data.length;
1581ebfedea0SLionel Sambuc }
1582ebfedea0SLionel Sambuc
1583ebfedea0SLionel Sambuc p = q = malloc(len);
1584ebfedea0SLionel Sambuc
1585ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) {
1586ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1587ebfedea0SLionel Sambuc data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1588ebfedea0SLionel Sambuc continue;
1589ebfedea0SLionel Sambuc memcpy(q, data[i].data.data, data[i].data.length);
1590ebfedea0SLionel Sambuc q += data[i].data.length;
1591ebfedea0SLionel Sambuc }
1592ebfedea0SLionel Sambuc
1593ebfedea0SLionel Sambuc ret = krb5_create_checksum(context, crypto, usage, 0, p, len, &cksum);
1594ebfedea0SLionel Sambuc free(p);
1595ebfedea0SLionel Sambuc if (ret)
1596ebfedea0SLionel Sambuc return ret;
1597ebfedea0SLionel Sambuc
1598ebfedea0SLionel Sambuc if (type)
1599ebfedea0SLionel Sambuc *type = cksum.cksumtype;
1600ebfedea0SLionel Sambuc
1601ebfedea0SLionel Sambuc if (cksum.checksum.length > civ->data.length) {
1602ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_BAD_MSIZE,
1603ebfedea0SLionel Sambuc N_("Checksum larger then input buffer", ""));
1604ebfedea0SLionel Sambuc free_Checksum(&cksum);
1605ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE;
1606ebfedea0SLionel Sambuc }
1607ebfedea0SLionel Sambuc
1608ebfedea0SLionel Sambuc civ->data.length = cksum.checksum.length;
1609ebfedea0SLionel Sambuc memcpy(civ->data.data, cksum.checksum.data, civ->data.length);
1610ebfedea0SLionel Sambuc free_Checksum(&cksum);
1611ebfedea0SLionel Sambuc
1612ebfedea0SLionel Sambuc return 0;
1613ebfedea0SLionel Sambuc }
1614ebfedea0SLionel Sambuc
1615ebfedea0SLionel Sambuc /**
1616ebfedea0SLionel Sambuc * Verify a Kerberos message checksum.
1617ebfedea0SLionel Sambuc *
1618ebfedea0SLionel Sambuc * @param context Kerberos context
1619ebfedea0SLionel Sambuc * @param crypto Kerberos crypto context
1620ebfedea0SLionel Sambuc * @param usage Key usage for this buffer
1621ebfedea0SLionel Sambuc * @param data array of buffers to process
1622ebfedea0SLionel Sambuc * @param num_data length of array
1623ebfedea0SLionel Sambuc * @param type return checksum type if not NULL
1624ebfedea0SLionel Sambuc *
1625ebfedea0SLionel Sambuc * @return Return an error code or 0.
1626ebfedea0SLionel Sambuc * @ingroup krb5_crypto
1627ebfedea0SLionel Sambuc */
1628ebfedea0SLionel Sambuc
1629ebfedea0SLionel Sambuc 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)1630ebfedea0SLionel Sambuc krb5_verify_checksum_iov(krb5_context context,
1631ebfedea0SLionel Sambuc krb5_crypto crypto,
1632ebfedea0SLionel Sambuc unsigned usage,
1633ebfedea0SLionel Sambuc krb5_crypto_iov *data,
1634ebfedea0SLionel Sambuc unsigned int num_data,
1635ebfedea0SLionel Sambuc krb5_cksumtype *type)
1636ebfedea0SLionel Sambuc {
1637ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = crypto->et;
1638ebfedea0SLionel Sambuc Checksum cksum;
1639ebfedea0SLionel Sambuc krb5_crypto_iov *civ;
1640ebfedea0SLionel Sambuc krb5_error_code ret;
1641*0a6a1f1dSLionel Sambuc size_t i;
1642ebfedea0SLionel Sambuc size_t len;
1643ebfedea0SLionel Sambuc char *p, *q;
1644ebfedea0SLionel Sambuc
1645ebfedea0SLionel Sambuc if(!derived_crypto(context, crypto)) {
1646ebfedea0SLionel Sambuc krb5_clear_error_message(context);
1647ebfedea0SLionel Sambuc return KRB5_CRYPTO_INTERNAL;
1648ebfedea0SLionel Sambuc }
1649ebfedea0SLionel Sambuc
1650ebfedea0SLionel Sambuc civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
1651ebfedea0SLionel Sambuc if (civ == NULL)
1652ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE;
1653ebfedea0SLionel Sambuc
1654ebfedea0SLionel Sambuc len = 0;
1655ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) {
1656ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1657ebfedea0SLionel Sambuc data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1658ebfedea0SLionel Sambuc continue;
1659ebfedea0SLionel Sambuc len += data[i].data.length;
1660ebfedea0SLionel Sambuc }
1661ebfedea0SLionel Sambuc
1662ebfedea0SLionel Sambuc p = q = malloc(len);
1663ebfedea0SLionel Sambuc
1664ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) {
1665ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1666ebfedea0SLionel Sambuc data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1667ebfedea0SLionel Sambuc continue;
1668ebfedea0SLionel Sambuc memcpy(q, data[i].data.data, data[i].data.length);
1669ebfedea0SLionel Sambuc q += data[i].data.length;
1670ebfedea0SLionel Sambuc }
1671ebfedea0SLionel Sambuc
1672ebfedea0SLionel Sambuc cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
1673ebfedea0SLionel Sambuc cksum.checksum.length = civ->data.length;
1674ebfedea0SLionel Sambuc cksum.checksum.data = civ->data.data;
1675ebfedea0SLionel Sambuc
1676ebfedea0SLionel Sambuc ret = krb5_verify_checksum(context, crypto, usage, p, len, &cksum);
1677ebfedea0SLionel Sambuc free(p);
1678ebfedea0SLionel Sambuc
1679ebfedea0SLionel Sambuc if (ret == 0 && type)
1680ebfedea0SLionel Sambuc *type = cksum.cksumtype;
1681ebfedea0SLionel Sambuc
1682ebfedea0SLionel Sambuc return ret;
1683ebfedea0SLionel Sambuc }
1684ebfedea0SLionel Sambuc
1685ebfedea0SLionel Sambuc
1686ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_length(krb5_context context,krb5_crypto crypto,int type,size_t * len)1687ebfedea0SLionel Sambuc krb5_crypto_length(krb5_context context,
1688ebfedea0SLionel Sambuc krb5_crypto crypto,
1689ebfedea0SLionel Sambuc int type,
1690ebfedea0SLionel Sambuc size_t *len)
1691ebfedea0SLionel Sambuc {
1692ebfedea0SLionel Sambuc if (!derived_crypto(context, crypto)) {
1693ebfedea0SLionel Sambuc krb5_set_error_message(context, EINVAL, "not a derived crypto");
1694ebfedea0SLionel Sambuc return EINVAL;
1695ebfedea0SLionel Sambuc }
1696ebfedea0SLionel Sambuc
1697ebfedea0SLionel Sambuc switch(type) {
1698ebfedea0SLionel Sambuc case KRB5_CRYPTO_TYPE_EMPTY:
1699ebfedea0SLionel Sambuc *len = 0;
1700ebfedea0SLionel Sambuc return 0;
1701ebfedea0SLionel Sambuc case KRB5_CRYPTO_TYPE_HEADER:
1702ebfedea0SLionel Sambuc *len = crypto->et->blocksize;
1703ebfedea0SLionel Sambuc return 0;
1704ebfedea0SLionel Sambuc case KRB5_CRYPTO_TYPE_DATA:
1705ebfedea0SLionel Sambuc case KRB5_CRYPTO_TYPE_SIGN_ONLY:
1706ebfedea0SLionel Sambuc /* len must already been filled in */
1707ebfedea0SLionel Sambuc return 0;
1708ebfedea0SLionel Sambuc case KRB5_CRYPTO_TYPE_PADDING:
1709ebfedea0SLionel Sambuc if (crypto->et->padsize > 1)
1710ebfedea0SLionel Sambuc *len = crypto->et->padsize;
1711ebfedea0SLionel Sambuc else
1712ebfedea0SLionel Sambuc *len = 0;
1713ebfedea0SLionel Sambuc return 0;
1714ebfedea0SLionel Sambuc case KRB5_CRYPTO_TYPE_TRAILER:
1715ebfedea0SLionel Sambuc *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
1716ebfedea0SLionel Sambuc return 0;
1717ebfedea0SLionel Sambuc case KRB5_CRYPTO_TYPE_CHECKSUM:
1718ebfedea0SLionel Sambuc if (crypto->et->keyed_checksum)
1719ebfedea0SLionel Sambuc *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
1720ebfedea0SLionel Sambuc else
1721ebfedea0SLionel Sambuc *len = CHECKSUMSIZE(crypto->et->checksum);
1722ebfedea0SLionel Sambuc return 0;
1723ebfedea0SLionel Sambuc }
1724ebfedea0SLionel Sambuc krb5_set_error_message(context, EINVAL,
1725ebfedea0SLionel Sambuc "%d not a supported type", type);
1726ebfedea0SLionel Sambuc return EINVAL;
1727ebfedea0SLionel Sambuc }
1728ebfedea0SLionel Sambuc
1729ebfedea0SLionel Sambuc
1730ebfedea0SLionel Sambuc 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)1731ebfedea0SLionel Sambuc krb5_crypto_length_iov(krb5_context context,
1732ebfedea0SLionel Sambuc krb5_crypto crypto,
1733ebfedea0SLionel Sambuc krb5_crypto_iov *data,
1734ebfedea0SLionel Sambuc unsigned int num_data)
1735ebfedea0SLionel Sambuc {
1736ebfedea0SLionel Sambuc krb5_error_code ret;
1737*0a6a1f1dSLionel Sambuc size_t i;
1738ebfedea0SLionel Sambuc
1739ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) {
1740ebfedea0SLionel Sambuc ret = krb5_crypto_length(context, crypto,
1741ebfedea0SLionel Sambuc data[i].flags,
1742ebfedea0SLionel Sambuc &data[i].data.length);
1743ebfedea0SLionel Sambuc if (ret)
1744ebfedea0SLionel Sambuc return ret;
1745ebfedea0SLionel Sambuc }
1746ebfedea0SLionel Sambuc return 0;
1747ebfedea0SLionel Sambuc }
1748ebfedea0SLionel Sambuc
1749ebfedea0SLionel Sambuc
1750ebfedea0SLionel Sambuc 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)1751ebfedea0SLionel Sambuc krb5_encrypt_ivec(krb5_context context,
1752ebfedea0SLionel Sambuc krb5_crypto crypto,
1753ebfedea0SLionel Sambuc unsigned usage,
1754ebfedea0SLionel Sambuc const void *data,
1755ebfedea0SLionel Sambuc size_t len,
1756ebfedea0SLionel Sambuc krb5_data *result,
1757ebfedea0SLionel Sambuc void *ivec)
1758ebfedea0SLionel Sambuc {
1759ebfedea0SLionel Sambuc if(derived_crypto(context, crypto))
1760ebfedea0SLionel Sambuc return encrypt_internal_derived(context, crypto, usage,
1761ebfedea0SLionel Sambuc data, len, result, ivec);
1762ebfedea0SLionel Sambuc else if (special_crypto(context, crypto))
1763ebfedea0SLionel Sambuc return encrypt_internal_special (context, crypto, usage,
1764ebfedea0SLionel Sambuc data, len, result, ivec);
1765ebfedea0SLionel Sambuc else
1766ebfedea0SLionel Sambuc return encrypt_internal(context, crypto, data, len, result, ivec);
1767ebfedea0SLionel Sambuc }
1768ebfedea0SLionel Sambuc
1769ebfedea0SLionel Sambuc 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)1770ebfedea0SLionel Sambuc krb5_encrypt(krb5_context context,
1771ebfedea0SLionel Sambuc krb5_crypto crypto,
1772ebfedea0SLionel Sambuc unsigned usage,
1773ebfedea0SLionel Sambuc const void *data,
1774ebfedea0SLionel Sambuc size_t len,
1775ebfedea0SLionel Sambuc krb5_data *result)
1776ebfedea0SLionel Sambuc {
1777ebfedea0SLionel Sambuc return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
1778ebfedea0SLionel Sambuc }
1779ebfedea0SLionel Sambuc
1780ebfedea0SLionel Sambuc 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)1781ebfedea0SLionel Sambuc krb5_encrypt_EncryptedData(krb5_context context,
1782ebfedea0SLionel Sambuc krb5_crypto crypto,
1783ebfedea0SLionel Sambuc unsigned usage,
1784ebfedea0SLionel Sambuc void *data,
1785ebfedea0SLionel Sambuc size_t len,
1786ebfedea0SLionel Sambuc int kvno,
1787ebfedea0SLionel Sambuc EncryptedData *result)
1788ebfedea0SLionel Sambuc {
1789ebfedea0SLionel Sambuc result->etype = CRYPTO_ETYPE(crypto);
1790ebfedea0SLionel Sambuc if(kvno){
1791ebfedea0SLionel Sambuc ALLOC(result->kvno, 1);
1792ebfedea0SLionel Sambuc *result->kvno = kvno;
1793ebfedea0SLionel Sambuc }else
1794ebfedea0SLionel Sambuc result->kvno = NULL;
1795ebfedea0SLionel Sambuc return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
1796ebfedea0SLionel Sambuc }
1797ebfedea0SLionel Sambuc
1798ebfedea0SLionel Sambuc 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)1799ebfedea0SLionel Sambuc krb5_decrypt_ivec(krb5_context context,
1800ebfedea0SLionel Sambuc krb5_crypto crypto,
1801ebfedea0SLionel Sambuc unsigned usage,
1802ebfedea0SLionel Sambuc void *data,
1803ebfedea0SLionel Sambuc size_t len,
1804ebfedea0SLionel Sambuc krb5_data *result,
1805ebfedea0SLionel Sambuc void *ivec)
1806ebfedea0SLionel Sambuc {
1807ebfedea0SLionel Sambuc if(derived_crypto(context, crypto))
1808ebfedea0SLionel Sambuc return decrypt_internal_derived(context, crypto, usage,
1809ebfedea0SLionel Sambuc data, len, result, ivec);
1810ebfedea0SLionel Sambuc else if (special_crypto (context, crypto))
1811ebfedea0SLionel Sambuc return decrypt_internal_special(context, crypto, usage,
1812ebfedea0SLionel Sambuc data, len, result, ivec);
1813ebfedea0SLionel Sambuc else
1814ebfedea0SLionel Sambuc return decrypt_internal(context, crypto, data, len, result, ivec);
1815ebfedea0SLionel Sambuc }
1816ebfedea0SLionel Sambuc
1817ebfedea0SLionel Sambuc 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)1818ebfedea0SLionel Sambuc krb5_decrypt(krb5_context context,
1819ebfedea0SLionel Sambuc krb5_crypto crypto,
1820ebfedea0SLionel Sambuc unsigned usage,
1821ebfedea0SLionel Sambuc void *data,
1822ebfedea0SLionel Sambuc size_t len,
1823ebfedea0SLionel Sambuc krb5_data *result)
1824ebfedea0SLionel Sambuc {
1825ebfedea0SLionel Sambuc return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
1826ebfedea0SLionel Sambuc NULL);
1827ebfedea0SLionel Sambuc }
1828ebfedea0SLionel Sambuc
1829ebfedea0SLionel Sambuc 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)1830ebfedea0SLionel Sambuc krb5_decrypt_EncryptedData(krb5_context context,
1831ebfedea0SLionel Sambuc krb5_crypto crypto,
1832ebfedea0SLionel Sambuc unsigned usage,
1833ebfedea0SLionel Sambuc const EncryptedData *e,
1834ebfedea0SLionel Sambuc krb5_data *result)
1835ebfedea0SLionel Sambuc {
1836ebfedea0SLionel Sambuc return krb5_decrypt(context, crypto, usage,
1837ebfedea0SLionel Sambuc e->cipher.data, e->cipher.length, result);
1838ebfedea0SLionel Sambuc }
1839ebfedea0SLionel Sambuc
1840ebfedea0SLionel Sambuc /************************************************************
1841ebfedea0SLionel Sambuc * *
1842ebfedea0SLionel Sambuc ************************************************************/
1843ebfedea0SLionel Sambuc
1844ebfedea0SLionel Sambuc 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)1845ebfedea0SLionel Sambuc _krb5_derive_key(krb5_context context,
1846ebfedea0SLionel Sambuc struct _krb5_encryption_type *et,
1847ebfedea0SLionel Sambuc struct _krb5_key_data *key,
1848ebfedea0SLionel Sambuc const void *constant,
1849ebfedea0SLionel Sambuc size_t len)
1850ebfedea0SLionel Sambuc {
1851ebfedea0SLionel Sambuc unsigned char *k = NULL;
1852ebfedea0SLionel Sambuc unsigned int nblocks = 0, i;
1853ebfedea0SLionel Sambuc krb5_error_code ret = 0;
1854ebfedea0SLionel Sambuc struct _krb5_key_type *kt = et->keytype;
1855ebfedea0SLionel Sambuc
1856ebfedea0SLionel Sambuc ret = _key_schedule(context, key);
1857ebfedea0SLionel Sambuc if(ret)
1858ebfedea0SLionel Sambuc return ret;
1859ebfedea0SLionel Sambuc if(et->blocksize * 8 < kt->bits || len != et->blocksize) {
1860ebfedea0SLionel Sambuc nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
1861ebfedea0SLionel Sambuc k = malloc(nblocks * et->blocksize);
1862ebfedea0SLionel Sambuc if(k == NULL) {
1863ebfedea0SLionel Sambuc ret = ENOMEM;
1864ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1865ebfedea0SLionel Sambuc goto out;
1866ebfedea0SLionel Sambuc }
1867ebfedea0SLionel Sambuc ret = _krb5_n_fold(constant, len, k, et->blocksize);
1868ebfedea0SLionel Sambuc if (ret) {
1869ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1870ebfedea0SLionel Sambuc goto out;
1871ebfedea0SLionel Sambuc }
1872ebfedea0SLionel Sambuc
1873ebfedea0SLionel Sambuc for(i = 0; i < nblocks; i++) {
1874ebfedea0SLionel Sambuc if(i > 0)
1875ebfedea0SLionel Sambuc memcpy(k + i * et->blocksize,
1876ebfedea0SLionel Sambuc k + (i - 1) * et->blocksize,
1877ebfedea0SLionel Sambuc et->blocksize);
1878ebfedea0SLionel Sambuc (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize,
1879ebfedea0SLionel Sambuc 1, 0, NULL);
1880ebfedea0SLionel Sambuc }
1881ebfedea0SLionel Sambuc } else {
1882ebfedea0SLionel Sambuc /* this case is probably broken, but won't be run anyway */
1883ebfedea0SLionel Sambuc void *c = malloc(len);
1884ebfedea0SLionel Sambuc size_t res_len = (kt->bits + 7) / 8;
1885ebfedea0SLionel Sambuc
1886ebfedea0SLionel Sambuc if(len != 0 && c == NULL) {
1887ebfedea0SLionel Sambuc ret = ENOMEM;
1888ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1889ebfedea0SLionel Sambuc goto out;
1890ebfedea0SLionel Sambuc }
1891ebfedea0SLionel Sambuc memcpy(c, constant, len);
1892ebfedea0SLionel Sambuc (*et->encrypt)(context, key, c, len, 1, 0, NULL);
1893ebfedea0SLionel Sambuc k = malloc(res_len);
1894ebfedea0SLionel Sambuc if(res_len != 0 && k == NULL) {
1895ebfedea0SLionel Sambuc free(c);
1896ebfedea0SLionel Sambuc ret = ENOMEM;
1897ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1898ebfedea0SLionel Sambuc goto out;
1899ebfedea0SLionel Sambuc }
1900ebfedea0SLionel Sambuc ret = _krb5_n_fold(c, len, k, res_len);
1901ebfedea0SLionel Sambuc free(c);
1902ebfedea0SLionel Sambuc if (ret) {
1903ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1904ebfedea0SLionel Sambuc goto out;
1905ebfedea0SLionel Sambuc }
1906ebfedea0SLionel Sambuc }
1907ebfedea0SLionel Sambuc
1908ebfedea0SLionel Sambuc /* XXX keytype dependent post-processing */
1909ebfedea0SLionel Sambuc switch(kt->type) {
1910*0a6a1f1dSLionel Sambuc case ETYPE_OLD_DES3_CBC_SHA1:
1911ebfedea0SLionel Sambuc _krb5_DES3_random_to_key(context, key->key, k, nblocks * et->blocksize);
1912ebfedea0SLionel Sambuc break;
1913*0a6a1f1dSLionel Sambuc case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
1914*0a6a1f1dSLionel Sambuc case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
1915ebfedea0SLionel Sambuc memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
1916ebfedea0SLionel Sambuc break;
1917ebfedea0SLionel Sambuc default:
1918ebfedea0SLionel Sambuc ret = KRB5_CRYPTO_INTERNAL;
1919ebfedea0SLionel Sambuc krb5_set_error_message(context, ret,
1920ebfedea0SLionel Sambuc N_("derive_key() called with unknown keytype (%u)", ""),
1921ebfedea0SLionel Sambuc kt->type);
1922ebfedea0SLionel Sambuc break;
1923ebfedea0SLionel Sambuc }
1924ebfedea0SLionel Sambuc out:
1925ebfedea0SLionel Sambuc if (key->schedule) {
1926ebfedea0SLionel Sambuc free_key_schedule(context, key, et);
1927ebfedea0SLionel Sambuc key->schedule = NULL;
1928ebfedea0SLionel Sambuc }
1929ebfedea0SLionel Sambuc if (k) {
1930ebfedea0SLionel Sambuc memset(k, 0, nblocks * et->blocksize);
1931ebfedea0SLionel Sambuc free(k);
1932ebfedea0SLionel Sambuc }
1933ebfedea0SLionel Sambuc return ret;
1934ebfedea0SLionel Sambuc }
1935ebfedea0SLionel Sambuc
1936ebfedea0SLionel Sambuc static struct _krb5_key_data *
_new_derived_key(krb5_crypto crypto,unsigned usage)1937ebfedea0SLionel Sambuc _new_derived_key(krb5_crypto crypto, unsigned usage)
1938ebfedea0SLionel Sambuc {
1939ebfedea0SLionel Sambuc struct _krb5_key_usage *d = crypto->key_usage;
1940ebfedea0SLionel Sambuc d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
1941ebfedea0SLionel Sambuc if(d == NULL)
1942ebfedea0SLionel Sambuc return NULL;
1943ebfedea0SLionel Sambuc crypto->key_usage = d;
1944ebfedea0SLionel Sambuc d += crypto->num_key_usage++;
1945ebfedea0SLionel Sambuc memset(d, 0, sizeof(*d));
1946ebfedea0SLionel Sambuc d->usage = usage;
1947ebfedea0SLionel Sambuc return &d->key;
1948ebfedea0SLionel Sambuc }
1949ebfedea0SLionel Sambuc
1950ebfedea0SLionel Sambuc 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)1951ebfedea0SLionel Sambuc krb5_derive_key(krb5_context context,
1952ebfedea0SLionel Sambuc const krb5_keyblock *key,
1953ebfedea0SLionel Sambuc krb5_enctype etype,
1954ebfedea0SLionel Sambuc const void *constant,
1955ebfedea0SLionel Sambuc size_t constant_len,
1956ebfedea0SLionel Sambuc krb5_keyblock **derived_key)
1957ebfedea0SLionel Sambuc {
1958ebfedea0SLionel Sambuc krb5_error_code ret;
1959ebfedea0SLionel Sambuc struct _krb5_encryption_type *et;
1960ebfedea0SLionel Sambuc struct _krb5_key_data d;
1961ebfedea0SLionel Sambuc
1962ebfedea0SLionel Sambuc *derived_key = NULL;
1963ebfedea0SLionel Sambuc
1964ebfedea0SLionel Sambuc et = _krb5_find_enctype (etype);
1965ebfedea0SLionel Sambuc if (et == NULL) {
1966*0a6a1f1dSLionel Sambuc return unsupported_enctype (context, etype);
1967ebfedea0SLionel Sambuc }
1968ebfedea0SLionel Sambuc
1969ebfedea0SLionel Sambuc ret = krb5_copy_keyblock(context, key, &d.key);
1970ebfedea0SLionel Sambuc if (ret)
1971ebfedea0SLionel Sambuc return ret;
1972ebfedea0SLionel Sambuc
1973ebfedea0SLionel Sambuc d.schedule = NULL;
1974ebfedea0SLionel Sambuc ret = _krb5_derive_key(context, et, &d, constant, constant_len);
1975ebfedea0SLionel Sambuc if (ret == 0)
1976ebfedea0SLionel Sambuc ret = krb5_copy_keyblock(context, d.key, derived_key);
1977ebfedea0SLionel Sambuc _krb5_free_key_data(context, &d, et);
1978ebfedea0SLionel Sambuc return ret;
1979ebfedea0SLionel Sambuc }
1980ebfedea0SLionel Sambuc
1981ebfedea0SLionel Sambuc static krb5_error_code
_get_derived_key(krb5_context context,krb5_crypto crypto,unsigned usage,struct _krb5_key_data ** key)1982ebfedea0SLionel Sambuc _get_derived_key(krb5_context context,
1983ebfedea0SLionel Sambuc krb5_crypto crypto,
1984ebfedea0SLionel Sambuc unsigned usage,
1985ebfedea0SLionel Sambuc struct _krb5_key_data **key)
1986ebfedea0SLionel Sambuc {
1987ebfedea0SLionel Sambuc int i;
1988ebfedea0SLionel Sambuc struct _krb5_key_data *d;
1989ebfedea0SLionel Sambuc unsigned char constant[5];
1990ebfedea0SLionel Sambuc
1991ebfedea0SLionel Sambuc for(i = 0; i < crypto->num_key_usage; i++)
1992ebfedea0SLionel Sambuc if(crypto->key_usage[i].usage == usage) {
1993ebfedea0SLionel Sambuc *key = &crypto->key_usage[i].key;
1994ebfedea0SLionel Sambuc return 0;
1995ebfedea0SLionel Sambuc }
1996ebfedea0SLionel Sambuc d = _new_derived_key(crypto, usage);
1997ebfedea0SLionel Sambuc if(d == NULL) {
1998ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1999ebfedea0SLionel Sambuc return ENOMEM;
2000ebfedea0SLionel Sambuc }
2001ebfedea0SLionel Sambuc krb5_copy_keyblock(context, crypto->key.key, &d->key);
2002ebfedea0SLionel Sambuc _krb5_put_int(constant, usage, 5);
2003ebfedea0SLionel Sambuc _krb5_derive_key(context, crypto->et, d, constant, sizeof(constant));
2004ebfedea0SLionel Sambuc *key = d;
2005ebfedea0SLionel Sambuc return 0;
2006ebfedea0SLionel Sambuc }
2007ebfedea0SLionel Sambuc
2008ebfedea0SLionel Sambuc /**
2009ebfedea0SLionel Sambuc * Create a crypto context used for all encryption and signature
2010ebfedea0SLionel Sambuc * operation. The encryption type to use is taken from the key, but
2011ebfedea0SLionel Sambuc * can be overridden with the enctype parameter. This can be useful
2012ebfedea0SLionel Sambuc * for encryptions types which is compatiable (DES for example).
2013ebfedea0SLionel Sambuc *
2014ebfedea0SLionel Sambuc * To free the crypto context, use krb5_crypto_destroy().
2015ebfedea0SLionel Sambuc *
2016ebfedea0SLionel Sambuc * @param context Kerberos context
2017ebfedea0SLionel Sambuc * @param key the key block information with all key data
2018ebfedea0SLionel Sambuc * @param etype the encryption type
2019ebfedea0SLionel Sambuc * @param crypto the resulting crypto context
2020ebfedea0SLionel Sambuc *
2021ebfedea0SLionel Sambuc * @return Return an error code or 0.
2022ebfedea0SLionel Sambuc *
2023ebfedea0SLionel Sambuc * @ingroup krb5_crypto
2024ebfedea0SLionel Sambuc */
2025ebfedea0SLionel Sambuc
2026ebfedea0SLionel Sambuc 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)2027ebfedea0SLionel Sambuc krb5_crypto_init(krb5_context context,
2028ebfedea0SLionel Sambuc const krb5_keyblock *key,
2029ebfedea0SLionel Sambuc krb5_enctype etype,
2030ebfedea0SLionel Sambuc krb5_crypto *crypto)
2031ebfedea0SLionel Sambuc {
2032ebfedea0SLionel Sambuc krb5_error_code ret;
2033ebfedea0SLionel Sambuc ALLOC(*crypto, 1);
2034ebfedea0SLionel Sambuc if(*crypto == NULL) {
2035ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2036ebfedea0SLionel Sambuc return ENOMEM;
2037ebfedea0SLionel Sambuc }
2038ebfedea0SLionel Sambuc if(etype == ETYPE_NULL)
2039ebfedea0SLionel Sambuc etype = key->keytype;
2040ebfedea0SLionel Sambuc (*crypto)->et = _krb5_find_enctype(etype);
2041ebfedea0SLionel Sambuc if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) {
2042ebfedea0SLionel Sambuc free(*crypto);
2043ebfedea0SLionel Sambuc *crypto = NULL;
2044*0a6a1f1dSLionel Sambuc return unsupported_enctype(context, etype);
2045ebfedea0SLionel Sambuc }
2046ebfedea0SLionel Sambuc if((*crypto)->et->keytype->size != key->keyvalue.length) {
2047ebfedea0SLionel Sambuc free(*crypto);
2048ebfedea0SLionel Sambuc *crypto = NULL;
2049ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_BAD_KEYSIZE,
2050ebfedea0SLionel Sambuc "encryption key has bad length");
2051ebfedea0SLionel Sambuc return KRB5_BAD_KEYSIZE;
2052ebfedea0SLionel Sambuc }
2053ebfedea0SLionel Sambuc ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
2054ebfedea0SLionel Sambuc if(ret) {
2055ebfedea0SLionel Sambuc free(*crypto);
2056ebfedea0SLionel Sambuc *crypto = NULL;
2057ebfedea0SLionel Sambuc return ret;
2058ebfedea0SLionel Sambuc }
2059ebfedea0SLionel Sambuc (*crypto)->key.schedule = NULL;
2060ebfedea0SLionel Sambuc (*crypto)->num_key_usage = 0;
2061ebfedea0SLionel Sambuc (*crypto)->key_usage = NULL;
2062ebfedea0SLionel Sambuc return 0;
2063ebfedea0SLionel Sambuc }
2064ebfedea0SLionel Sambuc
2065ebfedea0SLionel Sambuc static void
free_key_schedule(krb5_context context,struct _krb5_key_data * key,struct _krb5_encryption_type * et)2066ebfedea0SLionel Sambuc free_key_schedule(krb5_context context,
2067ebfedea0SLionel Sambuc struct _krb5_key_data *key,
2068ebfedea0SLionel Sambuc struct _krb5_encryption_type *et)
2069ebfedea0SLionel Sambuc {
2070ebfedea0SLionel Sambuc if (et->keytype->cleanup)
2071ebfedea0SLionel Sambuc (*et->keytype->cleanup)(context, key);
2072ebfedea0SLionel Sambuc memset(key->schedule->data, 0, key->schedule->length);
2073ebfedea0SLionel Sambuc krb5_free_data(context, key->schedule);
2074ebfedea0SLionel Sambuc }
2075ebfedea0SLionel Sambuc
2076ebfedea0SLionel Sambuc void
_krb5_free_key_data(krb5_context context,struct _krb5_key_data * key,struct _krb5_encryption_type * et)2077ebfedea0SLionel Sambuc _krb5_free_key_data(krb5_context context, struct _krb5_key_data *key,
2078ebfedea0SLionel Sambuc struct _krb5_encryption_type *et)
2079ebfedea0SLionel Sambuc {
2080ebfedea0SLionel Sambuc krb5_free_keyblock(context, key->key);
2081ebfedea0SLionel Sambuc if(key->schedule) {
2082ebfedea0SLionel Sambuc free_key_schedule(context, key, et);
2083ebfedea0SLionel Sambuc key->schedule = NULL;
2084ebfedea0SLionel Sambuc }
2085ebfedea0SLionel Sambuc }
2086ebfedea0SLionel Sambuc
2087ebfedea0SLionel Sambuc static void
free_key_usage(krb5_context context,struct _krb5_key_usage * ku,struct _krb5_encryption_type * et)2088ebfedea0SLionel Sambuc free_key_usage(krb5_context context, struct _krb5_key_usage *ku,
2089ebfedea0SLionel Sambuc struct _krb5_encryption_type *et)
2090ebfedea0SLionel Sambuc {
2091ebfedea0SLionel Sambuc _krb5_free_key_data(context, &ku->key, et);
2092ebfedea0SLionel Sambuc }
2093ebfedea0SLionel Sambuc
2094ebfedea0SLionel Sambuc /**
2095ebfedea0SLionel Sambuc * Free a crypto context created by krb5_crypto_init().
2096ebfedea0SLionel Sambuc *
2097ebfedea0SLionel Sambuc * @param context Kerberos context
2098ebfedea0SLionel Sambuc * @param crypto crypto context to free
2099ebfedea0SLionel Sambuc *
2100ebfedea0SLionel Sambuc * @return Return an error code or 0.
2101ebfedea0SLionel Sambuc *
2102ebfedea0SLionel Sambuc * @ingroup krb5_crypto
2103ebfedea0SLionel Sambuc */
2104ebfedea0SLionel Sambuc
2105ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_destroy(krb5_context context,krb5_crypto crypto)2106ebfedea0SLionel Sambuc krb5_crypto_destroy(krb5_context context,
2107ebfedea0SLionel Sambuc krb5_crypto crypto)
2108ebfedea0SLionel Sambuc {
2109ebfedea0SLionel Sambuc int i;
2110ebfedea0SLionel Sambuc
2111ebfedea0SLionel Sambuc for(i = 0; i < crypto->num_key_usage; i++)
2112ebfedea0SLionel Sambuc free_key_usage(context, &crypto->key_usage[i], crypto->et);
2113ebfedea0SLionel Sambuc free(crypto->key_usage);
2114ebfedea0SLionel Sambuc _krb5_free_key_data(context, &crypto->key, crypto->et);
2115ebfedea0SLionel Sambuc free (crypto);
2116ebfedea0SLionel Sambuc return 0;
2117ebfedea0SLionel Sambuc }
2118ebfedea0SLionel Sambuc
2119ebfedea0SLionel Sambuc /**
2120ebfedea0SLionel Sambuc * Return the blocksize used algorithm referenced by the crypto context
2121ebfedea0SLionel Sambuc *
2122ebfedea0SLionel Sambuc * @param context Kerberos context
2123ebfedea0SLionel Sambuc * @param crypto crypto context to query
2124ebfedea0SLionel Sambuc * @param blocksize the resulting blocksize
2125ebfedea0SLionel Sambuc *
2126ebfedea0SLionel Sambuc * @return Return an error code or 0.
2127ebfedea0SLionel Sambuc *
2128ebfedea0SLionel Sambuc * @ingroup krb5_crypto
2129ebfedea0SLionel Sambuc */
2130ebfedea0SLionel Sambuc
2131ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_getblocksize(krb5_context context,krb5_crypto crypto,size_t * blocksize)2132ebfedea0SLionel Sambuc krb5_crypto_getblocksize(krb5_context context,
2133ebfedea0SLionel Sambuc krb5_crypto crypto,
2134ebfedea0SLionel Sambuc size_t *blocksize)
2135ebfedea0SLionel Sambuc {
2136ebfedea0SLionel Sambuc *blocksize = crypto->et->blocksize;
2137ebfedea0SLionel Sambuc return 0;
2138ebfedea0SLionel Sambuc }
2139ebfedea0SLionel Sambuc
2140ebfedea0SLionel Sambuc /**
2141ebfedea0SLionel Sambuc * Return the encryption type used by the crypto context
2142ebfedea0SLionel Sambuc *
2143ebfedea0SLionel Sambuc * @param context Kerberos context
2144ebfedea0SLionel Sambuc * @param crypto crypto context to query
2145ebfedea0SLionel Sambuc * @param enctype the resulting encryption type
2146ebfedea0SLionel Sambuc *
2147ebfedea0SLionel Sambuc * @return Return an error code or 0.
2148ebfedea0SLionel Sambuc *
2149ebfedea0SLionel Sambuc * @ingroup krb5_crypto
2150ebfedea0SLionel Sambuc */
2151ebfedea0SLionel Sambuc
2152ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_getenctype(krb5_context context,krb5_crypto crypto,krb5_enctype * enctype)2153ebfedea0SLionel Sambuc krb5_crypto_getenctype(krb5_context context,
2154ebfedea0SLionel Sambuc krb5_crypto crypto,
2155ebfedea0SLionel Sambuc krb5_enctype *enctype)
2156ebfedea0SLionel Sambuc {
2157ebfedea0SLionel Sambuc *enctype = crypto->et->type;
2158ebfedea0SLionel Sambuc return 0;
2159ebfedea0SLionel Sambuc }
2160ebfedea0SLionel Sambuc
2161ebfedea0SLionel Sambuc /**
2162ebfedea0SLionel Sambuc * Return the padding size used by the crypto context
2163ebfedea0SLionel Sambuc *
2164ebfedea0SLionel Sambuc * @param context Kerberos context
2165ebfedea0SLionel Sambuc * @param crypto crypto context to query
2166ebfedea0SLionel Sambuc * @param padsize the return padding size
2167ebfedea0SLionel Sambuc *
2168ebfedea0SLionel Sambuc * @return Return an error code or 0.
2169ebfedea0SLionel Sambuc *
2170ebfedea0SLionel Sambuc * @ingroup krb5_crypto
2171ebfedea0SLionel Sambuc */
2172ebfedea0SLionel Sambuc
2173ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_getpadsize(krb5_context context,krb5_crypto crypto,size_t * padsize)2174ebfedea0SLionel Sambuc krb5_crypto_getpadsize(krb5_context context,
2175ebfedea0SLionel Sambuc krb5_crypto crypto,
2176ebfedea0SLionel Sambuc size_t *padsize)
2177ebfedea0SLionel Sambuc {
2178ebfedea0SLionel Sambuc *padsize = crypto->et->padsize;
2179ebfedea0SLionel Sambuc return 0;
2180ebfedea0SLionel Sambuc }
2181ebfedea0SLionel Sambuc
2182ebfedea0SLionel Sambuc /**
2183ebfedea0SLionel Sambuc * Return the confounder size used by the crypto context
2184ebfedea0SLionel Sambuc *
2185ebfedea0SLionel Sambuc * @param context Kerberos context
2186ebfedea0SLionel Sambuc * @param crypto crypto context to query
2187ebfedea0SLionel Sambuc * @param confoundersize the returned confounder size
2188ebfedea0SLionel Sambuc *
2189ebfedea0SLionel Sambuc * @return Return an error code or 0.
2190ebfedea0SLionel Sambuc *
2191ebfedea0SLionel Sambuc * @ingroup krb5_crypto
2192ebfedea0SLionel Sambuc */
2193ebfedea0SLionel Sambuc
2194ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_getconfoundersize(krb5_context context,krb5_crypto crypto,size_t * confoundersize)2195ebfedea0SLionel Sambuc krb5_crypto_getconfoundersize(krb5_context context,
2196ebfedea0SLionel Sambuc krb5_crypto crypto,
2197ebfedea0SLionel Sambuc size_t *confoundersize)
2198ebfedea0SLionel Sambuc {
2199ebfedea0SLionel Sambuc *confoundersize = crypto->et->confoundersize;
2200ebfedea0SLionel Sambuc return 0;
2201ebfedea0SLionel Sambuc }
2202ebfedea0SLionel Sambuc
2203ebfedea0SLionel Sambuc
2204ebfedea0SLionel Sambuc /**
2205ebfedea0SLionel Sambuc * Disable encryption type
2206ebfedea0SLionel Sambuc *
2207ebfedea0SLionel Sambuc * @param context Kerberos 5 context
2208ebfedea0SLionel Sambuc * @param enctype encryption type to disable
2209ebfedea0SLionel Sambuc *
2210ebfedea0SLionel Sambuc * @return Return an error code or 0.
2211ebfedea0SLionel Sambuc *
2212ebfedea0SLionel Sambuc * @ingroup krb5_crypto
2213ebfedea0SLionel Sambuc */
2214ebfedea0SLionel Sambuc
2215ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_enctype_disable(krb5_context context,krb5_enctype enctype)2216ebfedea0SLionel Sambuc krb5_enctype_disable(krb5_context context,
2217ebfedea0SLionel Sambuc krb5_enctype enctype)
2218ebfedea0SLionel Sambuc {
2219ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
2220ebfedea0SLionel Sambuc if(et == NULL) {
2221ebfedea0SLionel Sambuc if (context)
2222ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2223ebfedea0SLionel Sambuc N_("encryption type %d not supported", ""),
2224ebfedea0SLionel Sambuc enctype);
2225ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP;
2226ebfedea0SLionel Sambuc }
2227ebfedea0SLionel Sambuc et->flags |= F_DISABLED;
2228ebfedea0SLionel Sambuc return 0;
2229ebfedea0SLionel Sambuc }
2230ebfedea0SLionel Sambuc
2231ebfedea0SLionel Sambuc /**
2232ebfedea0SLionel Sambuc * Enable encryption type
2233ebfedea0SLionel Sambuc *
2234ebfedea0SLionel Sambuc * @param context Kerberos 5 context
2235ebfedea0SLionel Sambuc * @param enctype encryption type to enable
2236ebfedea0SLionel Sambuc *
2237ebfedea0SLionel Sambuc * @return Return an error code or 0.
2238ebfedea0SLionel Sambuc *
2239ebfedea0SLionel Sambuc * @ingroup krb5_crypto
2240ebfedea0SLionel Sambuc */
2241ebfedea0SLionel Sambuc
2242ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_enctype_enable(krb5_context context,krb5_enctype enctype)2243ebfedea0SLionel Sambuc krb5_enctype_enable(krb5_context context,
2244ebfedea0SLionel Sambuc krb5_enctype enctype)
2245ebfedea0SLionel Sambuc {
2246ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
2247ebfedea0SLionel Sambuc if(et == NULL) {
2248ebfedea0SLionel Sambuc if (context)
2249ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2250ebfedea0SLionel Sambuc N_("encryption type %d not supported", ""),
2251ebfedea0SLionel Sambuc enctype);
2252ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP;
2253ebfedea0SLionel Sambuc }
2254ebfedea0SLionel Sambuc et->flags &= ~F_DISABLED;
2255ebfedea0SLionel Sambuc return 0;
2256ebfedea0SLionel Sambuc }
2257ebfedea0SLionel Sambuc
2258ebfedea0SLionel Sambuc /**
2259ebfedea0SLionel Sambuc * Enable or disable all weak encryption types
2260ebfedea0SLionel Sambuc *
2261ebfedea0SLionel Sambuc * @param context Kerberos 5 context
2262ebfedea0SLionel Sambuc * @param enable true to enable, false to disable
2263ebfedea0SLionel Sambuc *
2264ebfedea0SLionel Sambuc * @return Return an error code or 0.
2265ebfedea0SLionel Sambuc *
2266ebfedea0SLionel Sambuc * @ingroup krb5_crypto
2267ebfedea0SLionel Sambuc */
2268ebfedea0SLionel Sambuc
2269ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_allow_weak_crypto(krb5_context context,krb5_boolean enable)2270ebfedea0SLionel Sambuc krb5_allow_weak_crypto(krb5_context context,
2271ebfedea0SLionel Sambuc krb5_boolean enable)
2272ebfedea0SLionel Sambuc {
2273ebfedea0SLionel Sambuc int i;
2274ebfedea0SLionel Sambuc
2275ebfedea0SLionel Sambuc for(i = 0; i < _krb5_num_etypes; i++)
2276ebfedea0SLionel Sambuc if(_krb5_etypes[i]->flags & F_WEAK) {
2277ebfedea0SLionel Sambuc if(enable)
2278ebfedea0SLionel Sambuc _krb5_etypes[i]->flags &= ~F_DISABLED;
2279ebfedea0SLionel Sambuc else
2280ebfedea0SLionel Sambuc _krb5_etypes[i]->flags |= F_DISABLED;
2281ebfedea0SLionel Sambuc }
2282ebfedea0SLionel Sambuc return 0;
2283ebfedea0SLionel Sambuc }
2284ebfedea0SLionel Sambuc
2285ebfedea0SLionel Sambuc static size_t
wrapped_length(krb5_context context,krb5_crypto crypto,size_t data_len)2286ebfedea0SLionel Sambuc wrapped_length (krb5_context context,
2287ebfedea0SLionel Sambuc krb5_crypto crypto,
2288ebfedea0SLionel Sambuc size_t data_len)
2289ebfedea0SLionel Sambuc {
2290ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = crypto->et;
2291ebfedea0SLionel Sambuc size_t padsize = et->padsize;
2292ebfedea0SLionel Sambuc size_t checksumsize = CHECKSUMSIZE(et->checksum);
2293ebfedea0SLionel Sambuc size_t res;
2294ebfedea0SLionel Sambuc
2295ebfedea0SLionel Sambuc res = et->confoundersize + checksumsize + data_len;
2296ebfedea0SLionel Sambuc res = (res + padsize - 1) / padsize * padsize;
2297ebfedea0SLionel Sambuc return res;
2298ebfedea0SLionel Sambuc }
2299ebfedea0SLionel Sambuc
2300ebfedea0SLionel Sambuc static size_t
wrapped_length_dervied(krb5_context context,krb5_crypto crypto,size_t data_len)2301ebfedea0SLionel Sambuc wrapped_length_dervied (krb5_context context,
2302ebfedea0SLionel Sambuc krb5_crypto crypto,
2303ebfedea0SLionel Sambuc size_t data_len)
2304ebfedea0SLionel Sambuc {
2305ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = crypto->et;
2306ebfedea0SLionel Sambuc size_t padsize = et->padsize;
2307ebfedea0SLionel Sambuc size_t res;
2308ebfedea0SLionel Sambuc
2309ebfedea0SLionel Sambuc res = et->confoundersize + data_len;
2310ebfedea0SLionel Sambuc res = (res + padsize - 1) / padsize * padsize;
2311ebfedea0SLionel Sambuc if (et->keyed_checksum)
2312ebfedea0SLionel Sambuc res += et->keyed_checksum->checksumsize;
2313ebfedea0SLionel Sambuc else
2314ebfedea0SLionel Sambuc res += et->checksum->checksumsize;
2315ebfedea0SLionel Sambuc return res;
2316ebfedea0SLionel Sambuc }
2317ebfedea0SLionel Sambuc
2318ebfedea0SLionel Sambuc /*
2319ebfedea0SLionel Sambuc * Return the size of an encrypted packet of length `data_len'
2320ebfedea0SLionel Sambuc */
2321ebfedea0SLionel Sambuc
2322ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL
krb5_get_wrapped_length(krb5_context context,krb5_crypto crypto,size_t data_len)2323ebfedea0SLionel Sambuc krb5_get_wrapped_length (krb5_context context,
2324ebfedea0SLionel Sambuc krb5_crypto crypto,
2325ebfedea0SLionel Sambuc size_t data_len)
2326ebfedea0SLionel Sambuc {
2327ebfedea0SLionel Sambuc if (derived_crypto (context, crypto))
2328ebfedea0SLionel Sambuc return wrapped_length_dervied (context, crypto, data_len);
2329ebfedea0SLionel Sambuc else
2330ebfedea0SLionel Sambuc return wrapped_length (context, crypto, data_len);
2331ebfedea0SLionel Sambuc }
2332ebfedea0SLionel Sambuc
2333ebfedea0SLionel Sambuc /*
2334ebfedea0SLionel Sambuc * Return the size of an encrypted packet of length `data_len'
2335ebfedea0SLionel Sambuc */
2336ebfedea0SLionel Sambuc
2337ebfedea0SLionel Sambuc static size_t
crypto_overhead(krb5_context context,krb5_crypto crypto)2338ebfedea0SLionel Sambuc crypto_overhead (krb5_context context,
2339ebfedea0SLionel Sambuc krb5_crypto crypto)
2340ebfedea0SLionel Sambuc {
2341ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = crypto->et;
2342ebfedea0SLionel Sambuc size_t res;
2343ebfedea0SLionel Sambuc
2344ebfedea0SLionel Sambuc res = CHECKSUMSIZE(et->checksum);
2345ebfedea0SLionel Sambuc res += et->confoundersize;
2346ebfedea0SLionel Sambuc if (et->padsize > 1)
2347ebfedea0SLionel Sambuc res += et->padsize;
2348ebfedea0SLionel Sambuc return res;
2349ebfedea0SLionel Sambuc }
2350ebfedea0SLionel Sambuc
2351ebfedea0SLionel Sambuc static size_t
crypto_overhead_dervied(krb5_context context,krb5_crypto crypto)2352ebfedea0SLionel Sambuc crypto_overhead_dervied (krb5_context context,
2353ebfedea0SLionel Sambuc krb5_crypto crypto)
2354ebfedea0SLionel Sambuc {
2355ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = crypto->et;
2356ebfedea0SLionel Sambuc size_t res;
2357ebfedea0SLionel Sambuc
2358ebfedea0SLionel Sambuc if (et->keyed_checksum)
2359ebfedea0SLionel Sambuc res = CHECKSUMSIZE(et->keyed_checksum);
2360ebfedea0SLionel Sambuc else
2361ebfedea0SLionel Sambuc res = CHECKSUMSIZE(et->checksum);
2362ebfedea0SLionel Sambuc res += et->confoundersize;
2363ebfedea0SLionel Sambuc if (et->padsize > 1)
2364ebfedea0SLionel Sambuc res += et->padsize;
2365ebfedea0SLionel Sambuc return res;
2366ebfedea0SLionel Sambuc }
2367ebfedea0SLionel Sambuc
2368ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL
krb5_crypto_overhead(krb5_context context,krb5_crypto crypto)2369ebfedea0SLionel Sambuc krb5_crypto_overhead (krb5_context context, krb5_crypto crypto)
2370ebfedea0SLionel Sambuc {
2371ebfedea0SLionel Sambuc if (derived_crypto (context, crypto))
2372ebfedea0SLionel Sambuc return crypto_overhead_dervied (context, crypto);
2373ebfedea0SLionel Sambuc else
2374ebfedea0SLionel Sambuc return crypto_overhead (context, crypto);
2375ebfedea0SLionel Sambuc }
2376ebfedea0SLionel Sambuc
2377ebfedea0SLionel Sambuc /**
2378ebfedea0SLionel Sambuc * Converts the random bytestring to a protocol key according to
2379ebfedea0SLionel Sambuc * Kerberos crypto frame work. It may be assumed that all the bits of
2380ebfedea0SLionel Sambuc * the input string are equally random, even though the entropy
2381ebfedea0SLionel Sambuc * present in the random source may be limited.
2382ebfedea0SLionel Sambuc *
2383ebfedea0SLionel Sambuc * @param context Kerberos 5 context
2384ebfedea0SLionel Sambuc * @param type the enctype resulting key will be of
2385ebfedea0SLionel Sambuc * @param data input random data to convert to a key
2386ebfedea0SLionel Sambuc * @param size size of input random data, at least krb5_enctype_keysize() long
2387ebfedea0SLionel Sambuc * @param key key, output key, free with krb5_free_keyblock_contents()
2388ebfedea0SLionel Sambuc *
2389ebfedea0SLionel Sambuc * @return Return an error code or 0.
2390ebfedea0SLionel Sambuc *
2391ebfedea0SLionel Sambuc * @ingroup krb5_crypto
2392ebfedea0SLionel Sambuc */
2393ebfedea0SLionel Sambuc
2394ebfedea0SLionel Sambuc 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)2395ebfedea0SLionel Sambuc krb5_random_to_key(krb5_context context,
2396ebfedea0SLionel Sambuc krb5_enctype type,
2397ebfedea0SLionel Sambuc const void *data,
2398ebfedea0SLionel Sambuc size_t size,
2399ebfedea0SLionel Sambuc krb5_keyblock *key)
2400ebfedea0SLionel Sambuc {
2401ebfedea0SLionel Sambuc krb5_error_code ret;
2402ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = _krb5_find_enctype(type);
2403ebfedea0SLionel Sambuc if(et == NULL) {
2404ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
2405ebfedea0SLionel Sambuc N_("encryption type %d not supported", ""),
2406ebfedea0SLionel Sambuc type);
2407ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP;
2408ebfedea0SLionel Sambuc }
2409ebfedea0SLionel Sambuc if ((et->keytype->bits + 7) / 8 > size) {
2410ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
2411ebfedea0SLionel Sambuc N_("encryption key %s needs %d bytes "
2412ebfedea0SLionel Sambuc "of random to make an encryption key "
2413ebfedea0SLionel Sambuc "out of it", ""),
2414ebfedea0SLionel Sambuc et->name, (int)et->keytype->size);
2415ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP;
2416ebfedea0SLionel Sambuc }
2417ebfedea0SLionel Sambuc ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
2418ebfedea0SLionel Sambuc if(ret)
2419ebfedea0SLionel Sambuc return ret;
2420ebfedea0SLionel Sambuc key->keytype = type;
2421ebfedea0SLionel Sambuc if (et->keytype->random_to_key)
2422ebfedea0SLionel Sambuc (*et->keytype->random_to_key)(context, key, data, size);
2423ebfedea0SLionel Sambuc else
2424ebfedea0SLionel Sambuc memcpy(key->keyvalue.data, data, et->keytype->size);
2425ebfedea0SLionel Sambuc
2426ebfedea0SLionel Sambuc return 0;
2427ebfedea0SLionel Sambuc }
2428ebfedea0SLionel Sambuc
2429ebfedea0SLionel Sambuc
2430ebfedea0SLionel Sambuc
2431ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_prf_length(krb5_context context,krb5_enctype type,size_t * length)2432ebfedea0SLionel Sambuc krb5_crypto_prf_length(krb5_context context,
2433ebfedea0SLionel Sambuc krb5_enctype type,
2434ebfedea0SLionel Sambuc size_t *length)
2435ebfedea0SLionel Sambuc {
2436ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = _krb5_find_enctype(type);
2437ebfedea0SLionel Sambuc
2438ebfedea0SLionel Sambuc if(et == NULL || et->prf_length == 0) {
2439ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
2440ebfedea0SLionel Sambuc N_("encryption type %d not supported", ""),
2441ebfedea0SLionel Sambuc type);
2442ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP;
2443ebfedea0SLionel Sambuc }
2444ebfedea0SLionel Sambuc
2445ebfedea0SLionel Sambuc *length = et->prf_length;
2446ebfedea0SLionel Sambuc return 0;
2447ebfedea0SLionel Sambuc }
2448ebfedea0SLionel Sambuc
2449ebfedea0SLionel Sambuc 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)2450ebfedea0SLionel Sambuc krb5_crypto_prf(krb5_context context,
2451ebfedea0SLionel Sambuc const krb5_crypto crypto,
2452ebfedea0SLionel Sambuc const krb5_data *input,
2453ebfedea0SLionel Sambuc krb5_data *output)
2454ebfedea0SLionel Sambuc {
2455ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = crypto->et;
2456ebfedea0SLionel Sambuc
2457ebfedea0SLionel Sambuc krb5_data_zero(output);
2458ebfedea0SLionel Sambuc
2459ebfedea0SLionel Sambuc if(et->prf == NULL) {
2460ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
2461ebfedea0SLionel Sambuc "kerberos prf for %s not supported",
2462ebfedea0SLionel Sambuc et->name);
2463ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP;
2464ebfedea0SLionel Sambuc }
2465ebfedea0SLionel Sambuc
2466ebfedea0SLionel Sambuc return (*et->prf)(context, crypto, input, output);
2467ebfedea0SLionel Sambuc }
2468ebfedea0SLionel Sambuc
2469ebfedea0SLionel Sambuc static krb5_error_code
krb5_crypto_prfplus(krb5_context context,const krb5_crypto crypto,const krb5_data * input,size_t length,krb5_data * output)2470ebfedea0SLionel Sambuc krb5_crypto_prfplus(krb5_context context,
2471ebfedea0SLionel Sambuc const krb5_crypto crypto,
2472ebfedea0SLionel Sambuc const krb5_data *input,
2473ebfedea0SLionel Sambuc size_t length,
2474ebfedea0SLionel Sambuc krb5_data *output)
2475ebfedea0SLionel Sambuc {
2476ebfedea0SLionel Sambuc krb5_error_code ret;
2477ebfedea0SLionel Sambuc krb5_data input2;
2478ebfedea0SLionel Sambuc unsigned char i = 1;
2479ebfedea0SLionel Sambuc unsigned char *p;
2480ebfedea0SLionel Sambuc
2481ebfedea0SLionel Sambuc krb5_data_zero(&input2);
2482ebfedea0SLionel Sambuc krb5_data_zero(output);
2483ebfedea0SLionel Sambuc
2484ebfedea0SLionel Sambuc krb5_clear_error_message(context);
2485ebfedea0SLionel Sambuc
2486ebfedea0SLionel Sambuc ret = krb5_data_alloc(output, length);
2487ebfedea0SLionel Sambuc if (ret) goto out;
2488ebfedea0SLionel Sambuc ret = krb5_data_alloc(&input2, input->length + 1);
2489ebfedea0SLionel Sambuc if (ret) goto out;
2490ebfedea0SLionel Sambuc
2491ebfedea0SLionel Sambuc krb5_clear_error_message(context);
2492ebfedea0SLionel Sambuc
2493ebfedea0SLionel Sambuc memcpy(((unsigned char *)input2.data) + 1, input->data, input->length);
2494ebfedea0SLionel Sambuc
2495ebfedea0SLionel Sambuc p = output->data;
2496ebfedea0SLionel Sambuc
2497ebfedea0SLionel Sambuc while (length) {
2498ebfedea0SLionel Sambuc krb5_data block;
2499ebfedea0SLionel Sambuc
2500ebfedea0SLionel Sambuc ((unsigned char *)input2.data)[0] = i++;
2501ebfedea0SLionel Sambuc
2502ebfedea0SLionel Sambuc ret = krb5_crypto_prf(context, crypto, &input2, &block);
2503ebfedea0SLionel Sambuc if (ret)
2504ebfedea0SLionel Sambuc goto out;
2505ebfedea0SLionel Sambuc
2506ebfedea0SLionel Sambuc if (block.length < length) {
2507ebfedea0SLionel Sambuc memcpy(p, block.data, block.length);
2508ebfedea0SLionel Sambuc length -= block.length;
2509ebfedea0SLionel Sambuc } else {
2510ebfedea0SLionel Sambuc memcpy(p, block.data, length);
2511ebfedea0SLionel Sambuc length = 0;
2512ebfedea0SLionel Sambuc }
2513ebfedea0SLionel Sambuc p += block.length;
2514ebfedea0SLionel Sambuc krb5_data_free(&block);
2515ebfedea0SLionel Sambuc }
2516ebfedea0SLionel Sambuc
2517ebfedea0SLionel Sambuc out:
2518ebfedea0SLionel Sambuc krb5_data_free(&input2);
2519ebfedea0SLionel Sambuc if (ret)
2520ebfedea0SLionel Sambuc krb5_data_free(output);
2521*0a6a1f1dSLionel Sambuc return ret;
2522ebfedea0SLionel Sambuc }
2523ebfedea0SLionel Sambuc
2524ebfedea0SLionel Sambuc /**
2525ebfedea0SLionel Sambuc * The FX-CF2 key derivation function, used in FAST and preauth framework.
2526ebfedea0SLionel Sambuc *
2527ebfedea0SLionel Sambuc * @param context Kerberos 5 context
2528ebfedea0SLionel Sambuc * @param crypto1 first key to combine
2529ebfedea0SLionel Sambuc * @param crypto2 second key to combine
2530ebfedea0SLionel Sambuc * @param pepper1 factor to combine with first key to garante uniqueness
2531ebfedea0SLionel Sambuc * @param pepper2 factor to combine with second key to garante uniqueness
2532ebfedea0SLionel Sambuc * @param enctype the encryption type of the resulting key
2533ebfedea0SLionel Sambuc * @param res allocated key, free with krb5_free_keyblock_contents()
2534ebfedea0SLionel Sambuc *
2535ebfedea0SLionel Sambuc * @return Return an error code or 0.
2536ebfedea0SLionel Sambuc *
2537ebfedea0SLionel Sambuc * @ingroup krb5_crypto
2538ebfedea0SLionel Sambuc */
2539ebfedea0SLionel Sambuc
2540ebfedea0SLionel Sambuc 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)2541ebfedea0SLionel Sambuc krb5_crypto_fx_cf2(krb5_context context,
2542ebfedea0SLionel Sambuc const krb5_crypto crypto1,
2543ebfedea0SLionel Sambuc const krb5_crypto crypto2,
2544ebfedea0SLionel Sambuc krb5_data *pepper1,
2545ebfedea0SLionel Sambuc krb5_data *pepper2,
2546ebfedea0SLionel Sambuc krb5_enctype enctype,
2547ebfedea0SLionel Sambuc krb5_keyblock *res)
2548ebfedea0SLionel Sambuc {
2549ebfedea0SLionel Sambuc krb5_error_code ret;
2550ebfedea0SLionel Sambuc krb5_data os1, os2;
2551ebfedea0SLionel Sambuc size_t i, keysize;
2552ebfedea0SLionel Sambuc
2553ebfedea0SLionel Sambuc memset(res, 0, sizeof(*res));
2554*0a6a1f1dSLionel Sambuc krb5_data_zero(&os1);
2555*0a6a1f1dSLionel Sambuc krb5_data_zero(&os2);
2556ebfedea0SLionel Sambuc
2557ebfedea0SLionel Sambuc ret = krb5_enctype_keysize(context, enctype, &keysize);
2558ebfedea0SLionel Sambuc if (ret)
2559ebfedea0SLionel Sambuc return ret;
2560ebfedea0SLionel Sambuc
2561ebfedea0SLionel Sambuc ret = krb5_data_alloc(&res->keyvalue, keysize);
2562ebfedea0SLionel Sambuc if (ret)
2563ebfedea0SLionel Sambuc goto out;
2564ebfedea0SLionel Sambuc ret = krb5_crypto_prfplus(context, crypto1, pepper1, keysize, &os1);
2565ebfedea0SLionel Sambuc if (ret)
2566ebfedea0SLionel Sambuc goto out;
2567ebfedea0SLionel Sambuc ret = krb5_crypto_prfplus(context, crypto2, pepper2, keysize, &os2);
2568ebfedea0SLionel Sambuc if (ret)
2569ebfedea0SLionel Sambuc goto out;
2570ebfedea0SLionel Sambuc
2571ebfedea0SLionel Sambuc res->keytype = enctype;
2572ebfedea0SLionel Sambuc {
2573ebfedea0SLionel Sambuc unsigned char *p1 = os1.data, *p2 = os2.data, *p3 = res->keyvalue.data;
2574ebfedea0SLionel Sambuc for (i = 0; i < keysize; i++)
2575ebfedea0SLionel Sambuc p3[i] = p1[i] ^ p2[i];
2576ebfedea0SLionel Sambuc }
2577ebfedea0SLionel Sambuc out:
2578ebfedea0SLionel Sambuc if (ret)
2579ebfedea0SLionel Sambuc krb5_data_free(&res->keyvalue);
2580ebfedea0SLionel Sambuc krb5_data_free(&os1);
2581ebfedea0SLionel Sambuc krb5_data_free(&os2);
2582ebfedea0SLionel Sambuc
2583ebfedea0SLionel Sambuc return ret;
2584ebfedea0SLionel Sambuc }
2585ebfedea0SLionel Sambuc
2586ebfedea0SLionel Sambuc
2587ebfedea0SLionel Sambuc
2588ebfedea0SLionel Sambuc #ifndef HEIMDAL_SMALLER
2589ebfedea0SLionel Sambuc
2590ebfedea0SLionel Sambuc /**
2591ebfedea0SLionel Sambuc * Deprecated: keytypes doesn't exists, they are really enctypes.
2592ebfedea0SLionel Sambuc *
2593ebfedea0SLionel Sambuc * @ingroup krb5_deprecated
2594ebfedea0SLionel Sambuc */
2595ebfedea0SLionel Sambuc
2596ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_keytype_to_enctypes(krb5_context context,krb5_keytype keytype,unsigned * len,krb5_enctype ** val)2597ebfedea0SLionel Sambuc krb5_keytype_to_enctypes (krb5_context context,
2598ebfedea0SLionel Sambuc krb5_keytype keytype,
2599ebfedea0SLionel Sambuc unsigned *len,
2600ebfedea0SLionel Sambuc krb5_enctype **val)
2601*0a6a1f1dSLionel Sambuc KRB5_DEPRECATED_FUNCTION("Use X instead")
2602ebfedea0SLionel Sambuc {
2603ebfedea0SLionel Sambuc int i;
2604ebfedea0SLionel Sambuc unsigned n = 0;
2605ebfedea0SLionel Sambuc krb5_enctype *ret;
2606ebfedea0SLionel Sambuc
2607ebfedea0SLionel Sambuc for (i = _krb5_num_etypes - 1; i >= 0; --i) {
2608ebfedea0SLionel Sambuc if (_krb5_etypes[i]->keytype->type == keytype
2609ebfedea0SLionel Sambuc && !(_krb5_etypes[i]->flags & F_PSEUDO)
2610ebfedea0SLionel Sambuc && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0)
2611ebfedea0SLionel Sambuc ++n;
2612ebfedea0SLionel Sambuc }
2613ebfedea0SLionel Sambuc if (n == 0) {
2614ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
2615ebfedea0SLionel Sambuc "Keytype have no mapping");
2616ebfedea0SLionel Sambuc return KRB5_PROG_KEYTYPE_NOSUPP;
2617ebfedea0SLionel Sambuc }
2618ebfedea0SLionel Sambuc
2619ebfedea0SLionel Sambuc ret = malloc(n * sizeof(*ret));
2620ebfedea0SLionel Sambuc if (ret == NULL && n != 0) {
2621ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
2622ebfedea0SLionel Sambuc return ENOMEM;
2623ebfedea0SLionel Sambuc }
2624ebfedea0SLionel Sambuc n = 0;
2625ebfedea0SLionel Sambuc for (i = _krb5_num_etypes - 1; i >= 0; --i) {
2626ebfedea0SLionel Sambuc if (_krb5_etypes[i]->keytype->type == keytype
2627ebfedea0SLionel Sambuc && !(_krb5_etypes[i]->flags & F_PSEUDO)
2628ebfedea0SLionel Sambuc && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0)
2629ebfedea0SLionel Sambuc ret[n++] = _krb5_etypes[i]->type;
2630ebfedea0SLionel Sambuc }
2631ebfedea0SLionel Sambuc *len = n;
2632ebfedea0SLionel Sambuc *val = ret;
2633ebfedea0SLionel Sambuc return 0;
2634ebfedea0SLionel Sambuc }
2635ebfedea0SLionel Sambuc
2636ebfedea0SLionel Sambuc /**
2637ebfedea0SLionel Sambuc * Deprecated: keytypes doesn't exists, they are really enctypes.
2638ebfedea0SLionel Sambuc *
2639ebfedea0SLionel Sambuc * @ingroup krb5_deprecated
2640ebfedea0SLionel Sambuc */
2641ebfedea0SLionel Sambuc
2642ebfedea0SLionel Sambuc /* if two enctypes have compatible keys */
2643ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_enctypes_compatible_keys(krb5_context context,krb5_enctype etype1,krb5_enctype etype2)2644ebfedea0SLionel Sambuc krb5_enctypes_compatible_keys(krb5_context context,
2645ebfedea0SLionel Sambuc krb5_enctype etype1,
2646ebfedea0SLionel Sambuc krb5_enctype etype2)
2647*0a6a1f1dSLionel Sambuc KRB5_DEPRECATED_FUNCTION("Use X instead")
2648ebfedea0SLionel Sambuc {
2649ebfedea0SLionel Sambuc struct _krb5_encryption_type *e1 = _krb5_find_enctype(etype1);
2650ebfedea0SLionel Sambuc struct _krb5_encryption_type *e2 = _krb5_find_enctype(etype2);
2651ebfedea0SLionel Sambuc return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
2652ebfedea0SLionel Sambuc }
2653ebfedea0SLionel Sambuc
2654ebfedea0SLionel Sambuc #endif /* HEIMDAL_SMALLER */
2655