1/*
2 * Copyright (c) 2008-2010 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Portions Copyright (c) 2008-2010 Apple Inc. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of the Institute nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#define KRB5_OLD_CRYPTO 1
37
38#include "heim.h"
39#include <string.h>
40
41
42mit_krb5_error_code KRB5_CALLCONV
43krb5_c_string_to_key(mit_krb5_context context,
44		     mit_krb5_enctype enctype,
45		     const mit_krb5_data *string,
46		     const mit_krb5_data *salt,
47		     mit_krb5_keyblock *key)
48{
49    krb5_data hstring;
50    krb5_error_code ret;
51    krb5_salt hsalt;
52    krb5_keyblock hkey;
53
54    LOG_ENTRY();
55
56    mshim_mdata2hdata(string, &hstring);
57    hsalt.salttype = (krb5_salttype)KRB5_PADATA_PW_SALT;
58    mshim_mdata2hdata(salt, &hsalt.saltvalue);
59
60    ret = heim_krb5_string_to_key_data_salt(HC(context), enctype,
61					    hstring, hsalt, &hkey);
62    heim_krb5_data_free(&hstring);
63    heim_krb5_data_free(&hsalt.saltvalue);
64    if (ret)
65	return ret;
66
67    mshim_hkeyblock2mkeyblock(&hkey, key);
68    heim_krb5_free_keyblock_contents(HC(context), &hkey);
69    return 0;
70}
71
72mit_krb5_error_code KRB5_CALLCONV
73krb5_string_to_key(mit_krb5_context context,
74		   const mit_krb5_encrypt_block * eblock,
75		   mit_krb5_keyblock * keyblock,
76		   const mit_krb5_data * data,
77		   const mit_krb5_data * salt)
78{
79    LOG_ENTRY();
80    return krb5_c_string_to_key(context,
81				eblock->crypto_entry,
82				data,
83				salt,
84				keyblock);
85}
86
87
88mit_krb5_error_code KRB5_CALLCONV
89krb5_principal2salt(mit_krb5_context context,
90		    mit_krb5_const_principal principal,
91		    mit_krb5_data *salt)
92{
93    struct comb_principal *c =  (struct comb_principal *)principal;
94    krb5_error_code ret;
95    krb5_salt hsalt;
96
97    memset(salt, 0, sizeof(*salt));
98
99    ret = heim_krb5_get_pw_salt(HC(context), c->heim, &hsalt);
100    if (ret)
101	return ret;
102    mshim_hdata2mdata(&hsalt.saltvalue, salt);
103    heim_krb5_free_salt(HC(context), hsalt);
104    return 0;
105}
106
107
108mit_krb5_error_code  KRB5_CALLCONV
109krb5_set_default_tgs_ktypes(mit_krb5_context, const mit_krb5_enctype *);
110
111
112mit_krb5_error_code  KRB5_CALLCONV
113krb5_set_default_tgs_ktypes(mit_krb5_context context,
114			    const mit_krb5_enctype *enc)
115{
116    LOG_ENTRY();
117    return heim_krb5_set_default_in_tkt_etypes(HC(context), (krb5_enctype *)enc);
118}
119
120mit_krb5_error_code KRB5_CALLCONV
121krb5_set_default_tgs_enctypes(mit_krb5_context context,
122			      const mit_krb5_enctype *enc)
123{
124    LOG_ENTRY();
125    return heim_krb5_set_default_in_tkt_etypes(HC(context), (krb5_enctype *)enc);
126}
127
128krb5_error_code KRB5_CALLCONV
129krb5_use_enctype(mit_krb5_context context,
130		 mit_krb5_encrypt_block *encrypt_block,
131		 mit_krb5_enctype enctype)
132{
133    LOG_ENTRY();
134    encrypt_block->crypto_entry = enctype;
135    return 0;
136}
137
138mit_krb5_error_code KRB5_CALLCONV
139krb5_c_decrypt(mit_krb5_context context,
140	       const mit_krb5_keyblock *key,
141	       mit_krb5_keyusage usage,
142	       const mit_krb5_data *ivec,
143	       const mit_krb5_enc_data *input,
144	       mit_krb5_data *output)
145{
146    krb5_error_code ret;
147    krb5_crypto crypto;
148    krb5_keyblock keyblock;
149    krb5_data odata;
150
151    LOG_ENTRY();
152
153    mshim_mkeyblock2hkeyblock(key, &keyblock);
154
155    ret = heim_krb5_crypto_init(HC(context), &keyblock, input->enctype, &crypto);
156    heim_krb5_free_keyblock_contents(HC(context), &keyblock);
157    if (ret)
158	return ret;
159
160    if (ivec) {
161	size_t blocksize;
162
163	ret = heim_krb5_crypto_getblocksize(HC(context), crypto, &blocksize);
164	if (ret) {
165	    heim_krb5_crypto_destroy(HC(context), crypto);
166	    return ret;
167	}
168
169	if (blocksize > ivec->length) {
170	    heim_krb5_crypto_destroy(HC(context), crypto);
171	    return KRB5_BAD_MSIZE;
172	}
173    }
174
175    ret = heim_krb5_decrypt_ivec(HC(context), crypto, usage,
176			    input->ciphertext.data, input->ciphertext.length,
177			    &odata,
178			    ivec ? (void *)ivec->data : NULL);
179
180    heim_krb5_crypto_destroy(HC(context), crypto);
181    if (ret == 0) {
182	mshim_hdata2mdata(&odata, output);
183	heim_krb5_data_free(&odata);
184    }
185
186    return ret ;
187}
188
189mit_krb5_error_code KRB5_CALLCONV
190krb5_c_encrypt(mit_krb5_context context,
191	       const mit_krb5_keyblock *key,
192	       mit_krb5_keyusage usage,
193	       const mit_krb5_data *ivec,
194	       const mit_krb5_data *input,
195	       mit_krb5_enc_data *output)
196{
197    LOG_ENTRY();
198    krb5_error_code ret;
199    krb5_crypto crypto;
200    krb5_keyblock keyblock;
201    krb5_data odata;
202
203    mshim_mkeyblock2hkeyblock(key, &keyblock);
204
205    ret = heim_krb5_crypto_init(HC(context), &keyblock, 0, &crypto);
206    heim_krb5_free_keyblock_contents(HC(context), &keyblock);
207    if (ret)
208	return ret;
209
210    if (ivec) {
211	size_t blocksize;
212
213	ret = heim_krb5_crypto_getblocksize(HC(context), crypto, &blocksize);
214	if (ret) {
215	    heim_krb5_crypto_destroy(HC(context), crypto);
216	    return ret;
217	}
218
219	if (blocksize > ivec->length) {
220	    heim_krb5_crypto_destroy(HC(context), crypto);
221	    return KRB5_BAD_MSIZE;
222	}
223    }
224
225    ret = heim_krb5_encrypt_ivec(HC(context), crypto, usage,
226				    input->data, input->length,
227				    &odata,
228				    ivec ? ivec->data : NULL);
229//    output->magic = KV5M_ENC_DATA;
230    output->kvno = 0;
231    if (ret == 0) {
232	heim_krb5_crypto_getenctype(HC(context), crypto, &output->enctype);
233	mshim_hdata2mdata(&odata, &output->ciphertext);
234	heim_krb5_data_free(&odata);
235    }
236    heim_krb5_crypto_destroy(HC(context), crypto);
237
238    return ret ;
239}
240
241mit_krb5_error_code KRB5_CALLCONV
242krb5_c_encrypt_length(mit_krb5_context context,
243		      mit_krb5_enctype enctype,
244		      size_t inputlen, size_t *length)
245{
246    LOG_ENTRY();
247    krb5_error_code ret;
248    krb5_crypto crypto;
249    krb5_keyblock key;
250
251    ret = heim_krb5_generate_random_keyblock(HC(context), enctype, &key);
252    if (ret)
253	return ret;
254
255    ret = heim_krb5_crypto_init(HC(context), &key, 0, &crypto);
256    heim_krb5_free_keyblock_contents(HC(context), &key);
257    if (ret)
258	return ret;
259
260    *length = heim_krb5_get_wrapped_length(HC(context), crypto, inputlen);
261    heim_krb5_crypto_destroy(HC(context), crypto);
262
263    return 0;
264}
265
266mit_krb5_error_code KRB5_CALLCONV
267krb5_change_password(mit_krb5_context context,
268		     mit_krb5_creds *creds,
269		     char *newpw,
270		     int *result_code,
271		     mit_krb5_data *result_code_string,
272		     mit_krb5_data *result_string)
273{
274    LOG_ENTRY();
275    return krb5_set_password(context, creds, newpw, NULL, result_code, result_code_string, result_string);
276}
277