1 /* key.c --- Key related functions.
2 * Copyright (C) 2002-2013 Simon Josefsson
3 *
4 * This file is part of Shishi.
5 *
6 * Shishi is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Shishi is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Shishi; if not, see http://www.gnu.org/licenses or write
18 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
19 * Floor, Boston, MA 02110-1301, USA
20 *
21 */
22
23 #include "internal.h"
24
25 struct Shishi_key
26 {
27 Shishi *handle;
28 char *principal;
29 char *realm;
30 int type;
31 char value[MAX_KEY_LEN];
32 uint32_t kvno; /* UINT32_MAX means undefined kvno */
33 time_t timestamp; /* Only used by keytab code. */
34 /* If you add anything here, check the functions shishi_key,
35 shishi_key_done and shishi_key_copy. */
36 };
37
38 /**
39 * shishi_key_principal:
40 * @key: structure that holds key information
41 *
42 * Get the principal part of the key owner principal name, i.e.,
43 * except the realm.
44 *
45 * Return value: Returns the principal owning the key. (Not a copy of
46 * it, so don't modify or deallocate it.)
47 **/
48 const char *
shishi_key_principal(const Shishi_key * key)49 shishi_key_principal (const Shishi_key * key)
50 {
51 return key->principal;
52 }
53
54 /**
55 * shishi_key_principal_set:
56 * @key: structure that holds key information
57 * @principal: string with new principal name.
58 *
59 * Set the principal owning the key. The string is copied into the
60 * key, so you can dispose of the variable immediately after calling
61 * this function.
62 **/
63 void
shishi_key_principal_set(Shishi_key * key,const char * principal)64 shishi_key_principal_set (Shishi_key * key, const char *principal)
65 {
66 free (key->principal);
67 if (principal)
68 key->principal = xstrdup (principal);
69 else
70 key->principal = NULL;
71 }
72
73 /**
74 * shishi_key_realm:
75 * @key: structure that holds key information
76 *
77 * Get the realm part of the key owner principal name.
78 *
79 * Return value: Returns the realm for the principal owning the key.
80 * (Not a copy of it, so don't modify or deallocate it.)
81 **/
82 const char *
shishi_key_realm(const Shishi_key * key)83 shishi_key_realm (const Shishi_key * key)
84 {
85 return key->realm;
86 }
87
88 /**
89 * shishi_key_realm_set:
90 * @key: structure that holds key information
91 * @realm: string with new realm name.
92 *
93 * Set the realm for the principal owning the key. The string is
94 * copied into the key, so you can dispose of the variable immediately
95 * after calling this function.
96 **/
97 void
shishi_key_realm_set(Shishi_key * key,const char * realm)98 shishi_key_realm_set (Shishi_key * key, const char *realm)
99 {
100 free (key->realm);
101 if (realm)
102 key->realm = xstrdup (realm);
103 else
104 key->realm = NULL;
105 }
106
107 /**
108 * shishi_key_type:
109 * @key: structure that holds key information
110 *
111 * Get key type.
112 *
113 * Return value: Returns the type of key as an integer as described in
114 * the standard.
115 **/
116 int
shishi_key_type(const Shishi_key * key)117 shishi_key_type (const Shishi_key * key)
118 {
119 return key->type;
120 }
121
122 /**
123 * shishi_key_type_set:
124 * @key: structure that holds key information
125 * @type: type to set in key.
126 *
127 * Set the type of key in key structure.
128 **/
129 void
shishi_key_type_set(Shishi_key * key,int32_t type)130 shishi_key_type_set (Shishi_key * key, int32_t type)
131 {
132 key->type = type;
133 }
134
135 /**
136 * shishi_key_value:
137 * @key: structure that holds key information
138 *
139 * Get the raw key bytes.
140 *
141 * Return value: Returns the key value as a pointer which is valid
142 * throughout the lifetime of the key structure.
143 **/
144 const char *
shishi_key_value(const Shishi_key * key)145 shishi_key_value (const Shishi_key * key)
146 {
147 return key->value;
148 }
149
150 /**
151 * shishi_key_value_set:
152 * @key: structure that holds key information
153 * @value: input array with key data.
154 *
155 * Set the key value and length in key structure. The value is copied
156 * into the key (in other words, you can deallocate @value right after
157 * calling this function without modifying the value inside the key).
158 **/
159 void
shishi_key_value_set(Shishi_key * key,const char * value)160 shishi_key_value_set (Shishi_key * key, const char *value)
161 {
162 if (value &&
163 shishi_cipher_keylen (key->type) > 0 &&
164 shishi_cipher_keylen (key->type) <= MAX_KEY_LEN)
165 memcpy (key->value, value, shishi_cipher_keylen (key->type));
166 }
167
168 /**
169 * shishi_key_version:
170 * @key: structure that holds key information
171 *
172 * Get the "kvno" (key version) of key. It will be UINT32_MAX if the
173 * key is not long-lived.
174 *
175 * Return value: Returns the version of key ("kvno").
176 **/
177 uint32_t
shishi_key_version(const Shishi_key * key)178 shishi_key_version (const Shishi_key * key)
179 {
180 return key->kvno;
181 }
182
183 /**
184 * shishi_key_version_set:
185 * @key: structure that holds key information
186 * @kvno: new version integer.
187 *
188 * Set the version of key ("kvno") in key structure. Use UINT32_MAX
189 * for non-ptermanent keys.
190 **/
191 void
shishi_key_version_set(Shishi_key * key,uint32_t kvno)192 shishi_key_version_set (Shishi_key * key, uint32_t kvno)
193 {
194 key->kvno = kvno;
195 }
196
197 /**
198 * shishi_key_timestamp:
199 * @key: structure that holds key information
200 *
201 * Get the time the key was established. Typically only present when
202 * the key was imported from a keytab format.
203 *
204 * Return value: Returns the time the key was established, or
205 * (time_t)-1 if not available.
206 *
207 * Since: 0.0.42
208 **/
209 time_t
shishi_key_timestamp(const Shishi_key * key)210 shishi_key_timestamp (const Shishi_key * key)
211 {
212 return key->timestamp;
213 }
214
215 /**
216 * shishi_key_timestamp_set:
217 * @key: structure that holds key information
218 * @timestamp: new timestamp.
219 *
220 * Set the time the key was established. Typically only relevant when
221 * exporting the key to keytab format.
222 *
223 * Since: 0.0.42
224 **/
225 void
shishi_key_timestamp_set(Shishi_key * key,time_t timestamp)226 shishi_key_timestamp_set (Shishi_key * key, time_t timestamp)
227 {
228 key->timestamp = timestamp;
229 }
230
231 /**
232 * shishi_key_name:
233 * @key: structure that holds key information
234 *
235 * Calls shishi_cipher_name for key type.
236 *
237 * Return value: Return name of key.
238 **/
239 const char *
shishi_key_name(Shishi_key * key)240 shishi_key_name (Shishi_key * key)
241 {
242 return shishi_cipher_name (key->type);
243 }
244
245 /**
246 * shishi_key_length:
247 * @key: structure that holds key information
248 *
249 * Calls shishi_cipher_keylen for key type.
250 *
251 * Return value: Returns the length of the key value.
252 **/
253 size_t
shishi_key_length(const Shishi_key * key)254 shishi_key_length (const Shishi_key * key)
255 {
256 return shishi_cipher_keylen (key->type);
257 }
258
259 /**
260 * shishi_key:
261 * @handle: Shishi library handle create by shishi_init().
262 * @key: pointer to structure that will hold newly created key information
263 *
264 * Create a new Key information structure.
265 *
266 * Return value: Returns SHISHI_OK iff successful.
267 **/
268 int
shishi_key(Shishi * handle,Shishi_key ** key)269 shishi_key (Shishi * handle, Shishi_key ** key)
270 {
271 *key = xcalloc (1, sizeof (**key));
272
273 (*key)->handle = handle;
274 (*key)->kvno = UINT32_MAX;
275
276 return SHISHI_OK;
277 }
278
279 /**
280 * shishi_key_done:
281 * @key: pointer to structure that holds key information.
282 *
283 * Deallocates key information structure.
284 **/
285 void
shishi_key_done(Shishi_key * key)286 shishi_key_done (Shishi_key * key)
287 {
288 free (key->realm);
289 free (key->principal);
290 free (key);
291 }
292
293 /**
294 * shishi_key_copy:
295 * @dstkey: structure that holds destination key information
296 * @srckey: structure that holds source key information
297 *
298 * Copies source key into existing allocated destination key.
299 **/
300 void
shishi_key_copy(Shishi_key * dstkey,Shishi_key * srckey)301 shishi_key_copy (Shishi_key * dstkey, Shishi_key * srckey)
302 {
303 shishi_key_principal_set (dstkey, shishi_key_principal (srckey));
304 shishi_key_realm_set (dstkey, shishi_key_realm (srckey));
305 shishi_key_type_set (dstkey, shishi_key_type (srckey));
306 shishi_key_value_set (dstkey, shishi_key_value (srckey));
307 shishi_key_version_set (dstkey, shishi_key_version (srckey));
308 shishi_key_timestamp_set (dstkey, shishi_key_timestamp (srckey));
309 }
310
311 /**
312 * shishi_key_from_value:
313 * @handle: Shishi library handle create by shishi_init().
314 * @type: type of key.
315 * @value: input array with key value, or NULL.
316 * @key: pointer to structure that will hold newly created key information
317 *
318 * Create a new Key information structure, and set the key type and
319 * key value. KEY contains a newly allocated structure only if this
320 * function is successful.
321 *
322 * Return value: Returns SHISHI_OK iff successful.
323 **/
324 int
shishi_key_from_value(Shishi * handle,int32_t type,const char * value,Shishi_key ** key)325 shishi_key_from_value (Shishi * handle,
326 int32_t type, const char *value, Shishi_key ** key)
327 {
328 int rc;
329
330 rc = shishi_key (handle, key);
331 if (rc != SHISHI_OK)
332 return rc;
333
334 shishi_key_type_set (*key, type);
335 if (value)
336 shishi_key_value_set (*key, value);
337
338 return SHISHI_OK;
339 }
340
341 /**
342 * shishi_key_from_base64:
343 * @handle: Shishi library handle create by shishi_init().
344 * @type: type of key.
345 * @value: input string with base64 encoded key value, or NULL.
346 * @key: pointer to structure that will hold newly created key information
347 *
348 * Create a new Key information structure, and set the key type and
349 * key value. KEY contains a newly allocated structure only if this
350 * function is successful.
351 *
352 * Return value: Returns SHISHI_INVALID_KEY if the base64 encoded key
353 * length doesn't match the key type, and SHISHI_OK on
354 * success.
355 **/
356 int
shishi_key_from_base64(Shishi * handle,int32_t type,const char * value,Shishi_key ** key)357 shishi_key_from_base64 (Shishi * handle,
358 int32_t type, const char *value, Shishi_key ** key)
359 {
360 int rc;
361
362 rc = shishi_key (handle, key);
363 if (rc != SHISHI_OK)
364 return rc;
365
366 shishi_key_type_set (*key, type);
367
368 if (value)
369 {
370 size_t len = MAX_KEY_LEN;
371
372 if (!base64_decode (value, strlen (value), (*key)->value, &len))
373 {
374 shishi_key_done (*key);
375 return SHISHI_BASE64_ERROR;
376 }
377
378 if (len != shishi_key_length (*key))
379 {
380 shishi_key_done (*key);
381 return SHISHI_INVALID_KEY;
382 }
383 }
384
385 return SHISHI_OK;
386 }
387
388 /**
389 * shishi_key_random
390 * @handle: Shishi library handle create by shishi_init().
391 * @type: type of key.
392 * @key: pointer to structure that will hold newly created key information
393 *
394 * Create a new Key information structure for the key type and some
395 * random data. KEY contains a newly allocated structure only if this
396 * function is successful.
397 *
398 * Return value: Returns SHISHI_OK iff successful.
399 **/
400 int
shishi_key_random(Shishi * handle,int32_t type,Shishi_key ** key)401 shishi_key_random (Shishi * handle, int32_t type, Shishi_key ** key)
402 {
403 char buf[MAX_RANDOM_LEN];
404 int len = shishi_cipher_randomlen (type);
405 int rc;
406
407 rc = shishi_randomize (handle, 1, buf, len);
408 if (rc != SHISHI_OK)
409 return rc;
410
411 rc = shishi_key (handle, key);
412 if (rc != SHISHI_OK)
413 return rc;
414
415 rc = shishi_random_to_key (handle, type, buf, len, *key);
416 if (rc != SHISHI_OK)
417 {
418 shishi_key_done (*key);
419 return rc;
420 }
421
422 return SHISHI_OK;
423 }
424
425 /**
426 * shishi_key_from_random
427 * @handle: Shishi library handle create by shishi_init().
428 * @type: type of key.
429 * @rnd: random data.
430 * @rndlen: length of random data.
431 * @outkey: pointer to structure that will hold newly created key information
432 *
433 * Create a new Key information structure, and set the key type and
434 * key value using shishi_random_to_key(). KEY contains a newly
435 * allocated structure only if this function is successful.
436 *
437 * Return value: Returns SHISHI_OK iff successful.
438 **/
439 int
shishi_key_from_random(Shishi * handle,int32_t type,const char * rnd,size_t rndlen,Shishi_key ** outkey)440 shishi_key_from_random (Shishi * handle,
441 int32_t type,
442 const char *rnd, size_t rndlen, Shishi_key ** outkey)
443 {
444 int rc;
445
446 rc = shishi_key (handle, outkey);
447 if (rc != SHISHI_OK)
448 return rc;
449
450 rc = shishi_random_to_key (handle, type, rnd, rndlen, *outkey);
451
452 return rc;
453 }
454
455 /**
456 * shishi_key_from_string
457 * @handle: Shishi library handle create by shishi_init().
458 * @type: type of key.
459 * @password: input array containing password.
460 * @passwordlen: length of input array containing password.
461 * @salt: input array containing salt.
462 * @saltlen: length of input array containing salt.
463 * @parameter: input array with opaque encryption type specific information.
464 * @outkey: pointer to structure that will hold newly created key information
465 *
466 * Create a new Key information structure, and set the key type and
467 * key value using shishi_string_to_key(). KEY contains a newly
468 * allocated structure only if this function is successful.
469 *
470 * Return value: Returns SHISHI_OK iff successful.
471 **/
472 int
shishi_key_from_string(Shishi * handle,int32_t type,const char * password,size_t passwordlen,const char * salt,size_t saltlen,const char * parameter,Shishi_key ** outkey)473 shishi_key_from_string (Shishi * handle,
474 int32_t type,
475 const char *password, size_t passwordlen,
476 const char *salt, size_t saltlen,
477 const char *parameter, Shishi_key ** outkey)
478 {
479 int rc;
480
481 rc = shishi_key (handle, outkey);
482 if (rc != SHISHI_OK)
483 return rc;
484
485 rc = shishi_string_to_key (handle, type, password, passwordlen,
486 salt, saltlen, parameter, *outkey);
487 if (rc != SHISHI_OK)
488 {
489 shishi_key_done (*outkey);
490 return rc;
491 }
492
493 return SHISHI_OK;
494 }
495
496 /**
497 * shishi_key_from_name:
498 * @handle: Shishi library handle create by shishi_init().
499 * @type: type of key.
500 * @name: principal name of user.
501 * @password: input array containing password.
502 * @passwordlen: length of input array containing password.
503 * @parameter: input array with opaque encryption type specific information.
504 * @outkey: pointer to structure that will hold newly created key information
505 *
506 * Create a new Key information structure, and derive the key from
507 * principal name and password using shishi_key_from_name(). The salt
508 * is derived from the principal name by concatenating the decoded
509 * realm and principal.
510 *
511 * Return value: Returns SHISHI_OK iff successful.
512 **/
513 int
shishi_key_from_name(Shishi * handle,int32_t type,const char * name,const char * password,size_t passwordlen,const char * parameter,Shishi_key ** outkey)514 shishi_key_from_name (Shishi * handle,
515 int32_t type,
516 const char *name,
517 const char *password, size_t passwordlen,
518 const char *parameter, Shishi_key ** outkey)
519 {
520 int rc;
521 char *salt;
522
523 rc = shishi_derive_default_salt (handle, name, &salt);
524 if (rc != SHISHI_OK)
525 return rc;
526
527 rc = shishi_key_from_string (handle, type, password, passwordlen,
528 salt, strlen (salt), parameter, outkey);
529 if (rc == SHISHI_OK)
530 {
531 char *principal;
532 char *realm;
533
534 rc = shishi_parse_name (handle, name, &principal, &realm);
535 if (rc == SHISHI_OK)
536 {
537 shishi_key_principal_set (*outkey, principal);
538 shishi_key_realm_set (*outkey, realm);
539
540 free (realm);
541 free (principal);
542 }
543 }
544
545 free (salt);
546
547 return rc;
548 }
549