xref: /freebsd/crypto/heimdal/lib/krb5/salt.c (revision 476d63e091c2e663b51d18acf6acb282e1f22bbc)
1ae771770SStanislav Sedov /*
2ae771770SStanislav Sedov  * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
3ae771770SStanislav Sedov  * (Royal Institute of Technology, Stockholm, Sweden).
4ae771770SStanislav Sedov  * All rights reserved.
5ae771770SStanislav Sedov  *
6ae771770SStanislav Sedov  * Redistribution and use in source and binary forms, with or without
7ae771770SStanislav Sedov  * modification, are permitted provided that the following conditions
8ae771770SStanislav Sedov  * are met:
9ae771770SStanislav Sedov  *
10ae771770SStanislav Sedov  * 1. Redistributions of source code must retain the above copyright
11ae771770SStanislav Sedov  *    notice, this list of conditions and the following disclaimer.
12ae771770SStanislav Sedov  *
13ae771770SStanislav Sedov  * 2. Redistributions in binary form must reproduce the above copyright
14ae771770SStanislav Sedov  *    notice, this list of conditions and the following disclaimer in the
15ae771770SStanislav Sedov  *    documentation and/or other materials provided with the distribution.
16ae771770SStanislav Sedov  *
17ae771770SStanislav Sedov  * 3. Neither the name of the Institute nor the names of its contributors
18ae771770SStanislav Sedov  *    may be used to endorse or promote products derived from this software
19ae771770SStanislav Sedov  *    without specific prior written permission.
20ae771770SStanislav Sedov  *
21ae771770SStanislav Sedov  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22ae771770SStanislav Sedov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23ae771770SStanislav Sedov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24ae771770SStanislav Sedov  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25ae771770SStanislav Sedov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26ae771770SStanislav Sedov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27ae771770SStanislav Sedov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28ae771770SStanislav Sedov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29ae771770SStanislav Sedov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30ae771770SStanislav Sedov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31ae771770SStanislav Sedov  * SUCH DAMAGE.
32ae771770SStanislav Sedov  */
33ae771770SStanislav Sedov 
34ae771770SStanislav Sedov #include "krb5_locl.h"
35ae771770SStanislav Sedov 
36ae771770SStanislav Sedov /* coverity[+alloc : arg-*3] */
37ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_salttype_to_string(krb5_context context,krb5_enctype etype,krb5_salttype stype,char ** string)38ae771770SStanislav Sedov krb5_salttype_to_string (krb5_context context,
39ae771770SStanislav Sedov 			 krb5_enctype etype,
40ae771770SStanislav Sedov 			 krb5_salttype stype,
41ae771770SStanislav Sedov 			 char **string)
42ae771770SStanislav Sedov {
43ae771770SStanislav Sedov     struct _krb5_encryption_type *e;
44ae771770SStanislav Sedov     struct salt_type *st;
45ae771770SStanislav Sedov 
46*476d63e0SCy Schubert     (void) fbsd_ossl_provider_load();
47*476d63e0SCy Schubert 
48ae771770SStanislav Sedov     e = _krb5_find_enctype (etype);
49ae771770SStanislav Sedov     if (e == NULL) {
50ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
51ae771770SStanislav Sedov 			       "encryption type %d not supported",
52ae771770SStanislav Sedov 			       etype);
53ae771770SStanislav Sedov 	return KRB5_PROG_ETYPE_NOSUPP;
54ae771770SStanislav Sedov     }
55ae771770SStanislav Sedov     for (st = e->keytype->string_to_key; st && st->type; st++) {
56ae771770SStanislav Sedov 	if (st->type == stype) {
57ae771770SStanislav Sedov 	    *string = strdup (st->name);
58ae771770SStanislav Sedov 	    if (*string == NULL) {
59ae771770SStanislav Sedov 		krb5_set_error_message (context, ENOMEM,
60ae771770SStanislav Sedov 					N_("malloc: out of memory", ""));
61ae771770SStanislav Sedov 		return ENOMEM;
62ae771770SStanislav Sedov 	    }
63ae771770SStanislav Sedov 	    return 0;
64ae771770SStanislav Sedov 	}
65ae771770SStanislav Sedov     }
66ae771770SStanislav Sedov     krb5_set_error_message (context, HEIM_ERR_SALTTYPE_NOSUPP,
67ae771770SStanislav Sedov 			    "salttype %d not supported", stype);
68ae771770SStanislav Sedov     return HEIM_ERR_SALTTYPE_NOSUPP;
69ae771770SStanislav Sedov }
70ae771770SStanislav Sedov 
71ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_string_to_salttype(krb5_context context,krb5_enctype etype,const char * string,krb5_salttype * salttype)72ae771770SStanislav Sedov krb5_string_to_salttype (krb5_context context,
73ae771770SStanislav Sedov 			 krb5_enctype etype,
74ae771770SStanislav Sedov 			 const char *string,
75ae771770SStanislav Sedov 			 krb5_salttype *salttype)
76ae771770SStanislav Sedov {
77ae771770SStanislav Sedov     struct _krb5_encryption_type *e;
78ae771770SStanislav Sedov     struct salt_type *st;
79ae771770SStanislav Sedov 
80*476d63e0SCy Schubert     (void) fbsd_ossl_provider_load();
81*476d63e0SCy Schubert 
82ae771770SStanislav Sedov     e = _krb5_find_enctype (etype);
83ae771770SStanislav Sedov     if (e == NULL) {
84ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
85ae771770SStanislav Sedov 			       N_("encryption type %d not supported", ""),
86ae771770SStanislav Sedov 			       etype);
87ae771770SStanislav Sedov 	return KRB5_PROG_ETYPE_NOSUPP;
88ae771770SStanislav Sedov     }
89ae771770SStanislav Sedov     for (st = e->keytype->string_to_key; st && st->type; st++) {
90ae771770SStanislav Sedov 	if (strcasecmp (st->name, string) == 0) {
91ae771770SStanislav Sedov 	    *salttype = st->type;
92ae771770SStanislav Sedov 	    return 0;
93ae771770SStanislav Sedov 	}
94ae771770SStanislav Sedov     }
95ae771770SStanislav Sedov     krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
96ae771770SStanislav Sedov 			   N_("salttype %s not supported", ""), string);
97ae771770SStanislav Sedov     return HEIM_ERR_SALTTYPE_NOSUPP;
98ae771770SStanislav Sedov }
99ae771770SStanislav Sedov 
100ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_get_pw_salt(krb5_context context,krb5_const_principal principal,krb5_salt * salt)101ae771770SStanislav Sedov krb5_get_pw_salt(krb5_context context,
102ae771770SStanislav Sedov 		 krb5_const_principal principal,
103ae771770SStanislav Sedov 		 krb5_salt *salt)
104ae771770SStanislav Sedov {
105ae771770SStanislav Sedov     size_t len;
106ae771770SStanislav Sedov     size_t i;
107ae771770SStanislav Sedov     krb5_error_code ret;
108ae771770SStanislav Sedov     char *p;
109ae771770SStanislav Sedov 
110ae771770SStanislav Sedov     salt->salttype = KRB5_PW_SALT;
111ae771770SStanislav Sedov     len = strlen(principal->realm);
112ae771770SStanislav Sedov     for (i = 0; i < principal->name.name_string.len; ++i)
113ae771770SStanislav Sedov 	len += strlen(principal->name.name_string.val[i]);
114ae771770SStanislav Sedov     ret = krb5_data_alloc (&salt->saltvalue, len);
115ae771770SStanislav Sedov     if (ret)
116ae771770SStanislav Sedov 	return ret;
117ae771770SStanislav Sedov     p = salt->saltvalue.data;
118ae771770SStanislav Sedov     memcpy (p, principal->realm, strlen(principal->realm));
119ae771770SStanislav Sedov     p += strlen(principal->realm);
120ae771770SStanislav Sedov     for (i = 0; i < principal->name.name_string.len; ++i) {
121ae771770SStanislav Sedov 	memcpy (p,
122ae771770SStanislav Sedov 		principal->name.name_string.val[i],
123ae771770SStanislav Sedov 		strlen(principal->name.name_string.val[i]));
124ae771770SStanislav Sedov 	p += strlen(principal->name.name_string.val[i]);
125ae771770SStanislav Sedov     }
126ae771770SStanislav Sedov     return 0;
127ae771770SStanislav Sedov }
128ae771770SStanislav Sedov 
129ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_free_salt(krb5_context context,krb5_salt salt)130ae771770SStanislav Sedov krb5_free_salt(krb5_context context,
131ae771770SStanislav Sedov 	       krb5_salt salt)
132ae771770SStanislav Sedov {
133ae771770SStanislav Sedov     krb5_data_free(&salt.saltvalue);
134ae771770SStanislav Sedov     return 0;
135ae771770SStanislav Sedov }
136ae771770SStanislav Sedov 
137ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_string_to_key_data(krb5_context context,krb5_enctype enctype,krb5_data password,krb5_principal principal,krb5_keyblock * key)138ae771770SStanislav Sedov krb5_string_to_key_data (krb5_context context,
139ae771770SStanislav Sedov 			 krb5_enctype enctype,
140ae771770SStanislav Sedov 			 krb5_data password,
141ae771770SStanislav Sedov 			 krb5_principal principal,
142ae771770SStanislav Sedov 			 krb5_keyblock *key)
143ae771770SStanislav Sedov {
144ae771770SStanislav Sedov     krb5_error_code ret;
145ae771770SStanislav Sedov     krb5_salt salt;
146ae771770SStanislav Sedov 
147ae771770SStanislav Sedov     ret = krb5_get_pw_salt(context, principal, &salt);
148ae771770SStanislav Sedov     if(ret)
149ae771770SStanislav Sedov 	return ret;
150ae771770SStanislav Sedov     ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
151ae771770SStanislav Sedov     krb5_free_salt(context, salt);
152ae771770SStanislav Sedov     return ret;
153ae771770SStanislav Sedov }
154ae771770SStanislav Sedov 
155ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_string_to_key(krb5_context context,krb5_enctype enctype,const char * password,krb5_principal principal,krb5_keyblock * key)156ae771770SStanislav Sedov krb5_string_to_key (krb5_context context,
157ae771770SStanislav Sedov 		    krb5_enctype enctype,
158ae771770SStanislav Sedov 		    const char *password,
159ae771770SStanislav Sedov 		    krb5_principal principal,
160ae771770SStanislav Sedov 		    krb5_keyblock *key)
161ae771770SStanislav Sedov {
162ae771770SStanislav Sedov     krb5_data pw;
163ae771770SStanislav Sedov     pw.data = rk_UNCONST(password);
164ae771770SStanislav Sedov     pw.length = strlen(password);
165ae771770SStanislav Sedov     return krb5_string_to_key_data(context, enctype, pw, principal, key);
166ae771770SStanislav Sedov }
167ae771770SStanislav Sedov 
168ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_string_to_key_data_salt(krb5_context context,krb5_enctype enctype,krb5_data password,krb5_salt salt,krb5_keyblock * key)169ae771770SStanislav Sedov krb5_string_to_key_data_salt (krb5_context context,
170ae771770SStanislav Sedov 			      krb5_enctype enctype,
171ae771770SStanislav Sedov 			      krb5_data password,
172ae771770SStanislav Sedov 			      krb5_salt salt,
173ae771770SStanislav Sedov 			      krb5_keyblock *key)
174ae771770SStanislav Sedov {
175ae771770SStanislav Sedov     krb5_data opaque;
176ae771770SStanislav Sedov     krb5_data_zero(&opaque);
177ae771770SStanislav Sedov     return krb5_string_to_key_data_salt_opaque(context, enctype, password,
178ae771770SStanislav Sedov 					       salt, opaque, key);
179ae771770SStanislav Sedov }
180ae771770SStanislav Sedov 
181ae771770SStanislav Sedov /*
182ae771770SStanislav Sedov  * Do a string -> key for encryption type `enctype' operation on
183ae771770SStanislav Sedov  * `password' (with salt `salt' and the enctype specific data string
184ae771770SStanislav Sedov  * `opaque'), returning the resulting key in `key'
185ae771770SStanislav Sedov  */
186ae771770SStanislav Sedov 
187ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_string_to_key_data_salt_opaque(krb5_context context,krb5_enctype enctype,krb5_data password,krb5_salt salt,krb5_data opaque,krb5_keyblock * key)188ae771770SStanislav Sedov krb5_string_to_key_data_salt_opaque (krb5_context context,
189ae771770SStanislav Sedov 				     krb5_enctype enctype,
190ae771770SStanislav Sedov 				     krb5_data password,
191ae771770SStanislav Sedov 				     krb5_salt salt,
192ae771770SStanislav Sedov 				     krb5_data opaque,
193ae771770SStanislav Sedov 				     krb5_keyblock *key)
194ae771770SStanislav Sedov {
195ae771770SStanislav Sedov     struct _krb5_encryption_type *et =_krb5_find_enctype(enctype);
196ae771770SStanislav Sedov     struct salt_type *st;
197ae771770SStanislav Sedov     if(et == NULL) {
198ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
199ae771770SStanislav Sedov 			       N_("encryption type %d not supported", ""),
200ae771770SStanislav Sedov 			       enctype);
201ae771770SStanislav Sedov 	return KRB5_PROG_ETYPE_NOSUPP;
202ae771770SStanislav Sedov     }
203*476d63e0SCy Schubert     (void) fbsd_ossl_provider_load();
204ae771770SStanislav Sedov     for(st = et->keytype->string_to_key; st && st->type; st++)
205ae771770SStanislav Sedov 	if(st->type == salt.salttype)
206ae771770SStanislav Sedov 	    return (*st->string_to_key)(context, enctype, password,
207ae771770SStanislav Sedov 					salt, opaque, key);
208ae771770SStanislav Sedov     krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
209ae771770SStanislav Sedov 			   N_("salt type %d not supported", ""),
210ae771770SStanislav Sedov 			   salt.salttype);
211ae771770SStanislav Sedov     return HEIM_ERR_SALTTYPE_NOSUPP;
212ae771770SStanislav Sedov }
213ae771770SStanislav Sedov 
214ae771770SStanislav Sedov /*
215ae771770SStanislav Sedov  * Do a string -> key for encryption type `enctype' operation on the
216ae771770SStanislav Sedov  * string `password' (with salt `salt'), returning the resulting key
217ae771770SStanislav Sedov  * in `key'
218ae771770SStanislav Sedov  */
219ae771770SStanislav Sedov 
220ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_string_to_key_salt(krb5_context context,krb5_enctype enctype,const char * password,krb5_salt salt,krb5_keyblock * key)221ae771770SStanislav Sedov krb5_string_to_key_salt (krb5_context context,
222ae771770SStanislav Sedov 			 krb5_enctype enctype,
223ae771770SStanislav Sedov 			 const char *password,
224ae771770SStanislav Sedov 			 krb5_salt salt,
225ae771770SStanislav Sedov 			 krb5_keyblock *key)
226ae771770SStanislav Sedov {
227ae771770SStanislav Sedov     krb5_data pw;
228ae771770SStanislav Sedov     pw.data = rk_UNCONST(password);
229ae771770SStanislav Sedov     pw.length = strlen(password);
230ae771770SStanislav Sedov     return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
231ae771770SStanislav Sedov }
232ae771770SStanislav Sedov 
233ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_string_to_key_salt_opaque(krb5_context context,krb5_enctype enctype,const char * password,krb5_salt salt,krb5_data opaque,krb5_keyblock * key)234ae771770SStanislav Sedov krb5_string_to_key_salt_opaque (krb5_context context,
235ae771770SStanislav Sedov 				krb5_enctype enctype,
236ae771770SStanislav Sedov 				const char *password,
237ae771770SStanislav Sedov 				krb5_salt salt,
238ae771770SStanislav Sedov 				krb5_data opaque,
239ae771770SStanislav Sedov 				krb5_keyblock *key)
240ae771770SStanislav Sedov {
241ae771770SStanislav Sedov     krb5_data pw;
242ae771770SStanislav Sedov     pw.data = rk_UNCONST(password);
243ae771770SStanislav Sedov     pw.length = strlen(password);
244ae771770SStanislav Sedov     return krb5_string_to_key_data_salt_opaque(context, enctype,
245ae771770SStanislav Sedov 					       pw, salt, opaque, key);
246ae771770SStanislav Sedov }
247ae771770SStanislav Sedov 
248ae771770SStanislav Sedov 
249ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_string_to_key_derived(krb5_context context,const void * str,size_t len,krb5_enctype etype,krb5_keyblock * key)250ae771770SStanislav Sedov krb5_string_to_key_derived(krb5_context context,
251ae771770SStanislav Sedov 			   const void *str,
252ae771770SStanislav Sedov 			   size_t len,
253ae771770SStanislav Sedov 			   krb5_enctype etype,
254ae771770SStanislav Sedov 			   krb5_keyblock *key)
255ae771770SStanislav Sedov {
256ae771770SStanislav Sedov     struct _krb5_encryption_type *et = _krb5_find_enctype(etype);
257ae771770SStanislav Sedov     krb5_error_code ret;
258ae771770SStanislav Sedov     struct _krb5_key_data kd;
259ae771770SStanislav Sedov     size_t keylen;
260ae771770SStanislav Sedov     u_char *tmp;
261ae771770SStanislav Sedov 
262ae771770SStanislav Sedov     if(et == NULL) {
263ae771770SStanislav Sedov 	krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
264ae771770SStanislav Sedov 				N_("encryption type %d not supported", ""),
265ae771770SStanislav Sedov 				etype);
266ae771770SStanislav Sedov 	return KRB5_PROG_ETYPE_NOSUPP;
267ae771770SStanislav Sedov     }
268ae771770SStanislav Sedov     keylen = et->keytype->bits / 8;
269ae771770SStanislav Sedov 
270ae771770SStanislav Sedov     ALLOC(kd.key, 1);
271ae771770SStanislav Sedov     if(kd.key == NULL) {
272ae771770SStanislav Sedov 	krb5_set_error_message (context, ENOMEM,
273ae771770SStanislav Sedov 				N_("malloc: out of memory", ""));
274ae771770SStanislav Sedov 	return ENOMEM;
275ae771770SStanislav Sedov     }
276ae771770SStanislav Sedov     ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
277ae771770SStanislav Sedov     if(ret) {
278ae771770SStanislav Sedov 	free(kd.key);
279ae771770SStanislav Sedov 	return ret;
280ae771770SStanislav Sedov     }
281ae771770SStanislav Sedov     kd.key->keytype = etype;
282ae771770SStanislav Sedov     tmp = malloc (keylen);
283ae771770SStanislav Sedov     if(tmp == NULL) {
284ae771770SStanislav Sedov 	krb5_free_keyblock(context, kd.key);
285ae771770SStanislav Sedov 	krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
286ae771770SStanislav Sedov 	return ENOMEM;
287ae771770SStanislav Sedov     }
288ae771770SStanislav Sedov     ret = _krb5_n_fold(str, len, tmp, keylen);
289ae771770SStanislav Sedov     if (ret) {
290ae771770SStanislav Sedov 	free(tmp);
291ae771770SStanislav Sedov 	krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
292ae771770SStanislav Sedov 	return ret;
293ae771770SStanislav Sedov     }
294ae771770SStanislav Sedov     kd.schedule = NULL;
295ae771770SStanislav Sedov     _krb5_DES3_random_to_key(context, kd.key, tmp, keylen);
296ae771770SStanislav Sedov     memset(tmp, 0, keylen);
297ae771770SStanislav Sedov     free(tmp);
298ae771770SStanislav Sedov     ret = _krb5_derive_key(context,
299ae771770SStanislav Sedov 			   et,
300ae771770SStanislav Sedov 			   &kd,
301ae771770SStanislav Sedov 			   "kerberos", /* XXX well known constant */
302ae771770SStanislav Sedov 			   strlen("kerberos"));
303ae771770SStanislav Sedov     if (ret) {
304ae771770SStanislav Sedov 	_krb5_free_key_data(context, &kd, et);
305ae771770SStanislav Sedov 	return ret;
306ae771770SStanislav Sedov     }
307ae771770SStanislav Sedov     ret = krb5_copy_keyblock_contents(context, kd.key, key);
308ae771770SStanislav Sedov     _krb5_free_key_data(context, &kd, et);
309ae771770SStanislav Sedov     return ret;
310ae771770SStanislav Sedov }
311