Update gnulib files.
[shishi.git] / lib / safe.c
blobafa2c0639effeb58ecd13abc4ce2632527ee2746
1 /* safe.c --- Application data integrity protection.
2 * Copyright (C) 2002, 2003, 2004, 2006, 2007 Simon Josefsson
4 * This file is part of Shishi.
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.
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.
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
23 #include "internal.h"
25 /* Get _shishi_print_armored_data, etc. */
26 #include "diskio.h"
28 struct Shishi_safe
30 Shishi *handle;
31 Shishi_key *key;
32 Shishi_asn1 safe;
33 unsigned long seqnumber;
36 /**
37 * shishi_safe:
38 * @handle: shishi handle as allocated by shishi_init().
39 * @safe: pointer to new structure that holds information about SAFE exchange
41 * Create a new SAFE exchange.
43 * Return value: Returns SHISHI_OK iff successful.
44 **/
45 int
46 shishi_safe (Shishi * handle, Shishi_safe ** safe)
48 Shishi_safe *lsafe;
49 struct timeval tv;
50 char *usec;
51 int rc;
53 *safe = xcalloc (1, sizeof (**safe));
54 lsafe = *safe;
56 lsafe->handle = handle;
57 rc = shishi_key (handle, &lsafe->key);
58 if (rc != SHISHI_OK)
59 return rc;
61 lsafe->safe = shishi_asn1_krbsafe (handle);
62 if (lsafe->safe == NULL)
63 return SHISHI_ASN1_ERROR;
65 rc = shishi_asn1_write (handle, lsafe->safe, "pvno", "5", 0);
66 if (rc != SHISHI_OK)
67 return rc;
69 rc = shishi_asn1_write (handle, lsafe->safe, "msg-type", "20", 0);
70 if (rc != SHISHI_OK)
71 return rc;
73 rc = shishi_asn1_write (handle, lsafe->safe, "safe-body.seq-number",
74 NULL, 0);
75 if (rc != SHISHI_OK)
76 return rc;
78 rc = gettimeofday (&tv, NULL);
79 if (rc != 0)
80 return SHISHI_GETTIMEOFDAY_ERROR;
82 asprintf (&usec, "%ld", tv.tv_usec % 1000000);
83 rc = shishi_asn1_write (handle, lsafe->safe, "safe-body.usec", usec, 0);
84 free (usec);
85 if (rc != SHISHI_OK)
86 return rc;
88 rc = shishi_asn1_write (handle, lsafe->safe, "safe-body.timestamp",
89 shishi_generalize_time (handle, time (NULL)), 0);
90 if (rc != SHISHI_OK)
91 return rc;
93 rc = shishi_asn1_write (handle, lsafe->safe, "safe-body.s-address.addr-type", "3", 0); /* directional */
94 if (rc != SHISHI_OK)
95 return rc;
97 rc = shishi_asn1_write (handle, lsafe->safe, "safe-body.s-address.address", "\x00\x00\x00\x00", 4); /* sender */
98 if (rc != SHISHI_OK)
99 return rc;
101 rc = shishi_asn1_write (handle, lsafe->safe, "safe-body.r-address",
102 NULL, 0);
103 if (rc != SHISHI_OK)
104 return rc;
106 return SHISHI_OK;
110 * shishi_safe_done:
111 * @safe: structure that holds information about SAFE exchange
113 * Deallocate resources associated with SAFE exchange. This should be
114 * called by the application when it no longer need to utilize the
115 * SAFE exchange handle.
117 void
118 shishi_safe_done (Shishi_safe * safe)
120 shishi_asn1_done (safe->handle, safe->safe);
121 shishi_key_done (safe->key);
122 free (safe);
126 * shishi_safe_key:
127 * @safe: structure that holds information about SAFE exchange
129 * Get key structured from SAFE exchange.
131 * Return value: Returns the key used in the SAFE exchange, or NULL if
132 * not yet set or an error occured.
134 Shishi_key *
135 shishi_safe_key (Shishi_safe * safe)
137 return safe->key;
141 * shishi_safe_key_set:
142 * @safe: structure that holds information about SAFE exchange
143 * @key: key to store in SAFE.
145 * Set the Key in the SAFE exchange.
147 void
148 shishi_safe_key_set (Shishi_safe * safe, Shishi_key * key)
150 shishi_key_copy (safe->key, key);
154 * shishi_safe_safe:
155 * @safe: structure that holds information about SAFE exchange
157 * Get ASN.1 SAFE structured from SAFE exchange.
159 * Return value: Returns the ASN.1 safe in the SAFE exchange, or NULL if
160 * not yet set or an error occured.
162 Shishi_asn1
163 shishi_safe_safe (Shishi_safe * safe)
165 return safe->safe;
169 * shishi_safe_safe_set:
170 * @safe: structure that holds information about SAFE exchange
171 * @asn1safe: KRB-SAFE to store in SAFE exchange.
173 * Set the KRB-SAFE in the SAFE exchange.
175 void
176 shishi_safe_safe_set (Shishi_safe * safe, Shishi_asn1 asn1safe)
178 if (safe->safe)
179 shishi_asn1_done (safe->handle, safe->safe);
180 safe->safe = asn1safe;
184 * shishi_safe_safe_der:
185 * @safe: safe as allocated by shishi_safe().
186 * @out: output array with newly allocated DER encoding of SAFE.
187 * @outlen: length of output array with DER encoding of SAFE.
189 * DER encode SAFE structure. Typically shishi_safe_build() is used
190 * to build the SAFE structure first. @out is allocated by this
191 * function, and it is the responsibility of caller to deallocate it.
193 * Return value: Returns SHISHI_OK iff successful.
196 shishi_safe_safe_der (Shishi_safe * safe, char **out, size_t * outlen)
198 int rc;
200 rc = shishi_asn1_to_der (safe->handle, safe->safe, out, outlen);
201 if (rc != SHISHI_OK)
202 return rc;
204 return SHISHI_OK;
208 * shishi_safe_safe_der_set:
209 * @safe: safe as allocated by shishi_safe().
210 * @der: input array with DER encoded KRB-SAFE.
211 * @derlen: length of input array with DER encoded KRB-SAFE.
213 * DER decode KRB-SAFE and set it SAFE exchange. If decoding fails, the
214 * KRB-SAFE in the SAFE exchange remains.
216 * Return value: Returns SHISHI_OK.
219 shishi_safe_safe_der_set (Shishi_safe * safe, char *der, size_t derlen)
221 Shishi_asn1 asn1safe;
223 asn1safe = shishi_der2asn1_krbsafe (safe->handle, der, derlen);
225 if (asn1safe == NULL)
226 return SHISHI_ASN1_ERROR;
228 shishi_safe_safe_set (safe, asn1safe);
230 return SHISHI_OK;
234 * shishi_safe_print:
235 * @handle: shishi handle as allocated by shishi_init().
236 * @fh: file handle open for writing.
237 * @safe: SAFE to print.
239 * Print ASCII armored DER encoding of SAFE to file.
241 * Return value: Returns SHISHI_OK iff successful.
244 shishi_safe_print (Shishi * handle, FILE * fh, Shishi_asn1 safe)
246 return _shishi_print_armored_data (handle, fh, safe, "KRB-SAFE", NULL);
250 * shishi_safe_save:
251 * @handle: shishi handle as allocated by shishi_init().
252 * @fh: file handle open for writing.
253 * @safe: SAFE to save.
255 * Save DER encoding of SAFE to file.
257 * Return value: Returns SHISHI_OK iff successful.
260 shishi_safe_save (Shishi * handle, FILE * fh, Shishi_asn1 safe)
262 return _shishi_save_data (handle, fh, safe, "SAFE");
266 * shishi_safe_to_file:
267 * @handle: shishi handle as allocated by shishi_init().
268 * @safe: SAFE to save.
269 * @filetype: input variable specifying type of file to be written,
270 * see Shishi_filetype.
271 * @filename: input variable with filename to write to.
273 * Write SAFE to file in specified TYPE. The file will be
274 * truncated if it exists.
276 * Return value: Returns SHISHI_OK iff successful.
279 shishi_safe_to_file (Shishi * handle, Shishi_asn1 safe,
280 int filetype, const char *filename)
282 FILE *fh;
283 int res;
285 if (VERBOSE (handle))
286 printf (_("Writing SAFE to %s...\n"), filename);
288 fh = fopen (filename, "w");
289 if (fh == NULL)
290 return SHISHI_FOPEN_ERROR;
292 if (VERBOSE (handle))
293 printf (_("Writing SAFE in %s format...\n"),
294 filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
296 if (filetype == SHISHI_FILETYPE_TEXT)
297 res = shishi_safe_print (handle, fh, safe);
298 else
299 res = shishi_safe_save (handle, fh, safe);
300 if (res != SHISHI_OK)
301 return res;
303 res = fclose (fh);
304 if (res != 0)
305 return SHISHI_IO_ERROR;
307 if (VERBOSE (handle))
308 printf (_("Writing SAFE to %s...done\n"), filename);
310 return SHISHI_OK;
314 * shishi_safe_parse:
315 * @handle: shishi handle as allocated by shishi_init().
316 * @fh: file handle open for reading.
317 * @safe: output variable with newly allocated SAFE.
319 * Read ASCII armored DER encoded SAFE from file and populate given
320 * variable.
322 * Return value: Returns SHISHI_OK iff successful.
325 shishi_safe_parse (Shishi * handle, FILE * fh, Shishi_asn1 * safe)
327 return _shishi_safe_input (handle, fh, safe, 0);
331 * shishi_safe_read:
332 * @handle: shishi handle as allocated by shishi_init().
333 * @fh: file handle open for reading.
334 * @safe: output variable with newly allocated SAFE.
336 * Read DER encoded SAFE from file and populate given variable.
338 * Return value: Returns SHISHI_OK iff successful.
341 shishi_safe_read (Shishi * handle, FILE * fh, Shishi_asn1 * safe)
343 return _shishi_safe_input (handle, fh, safe, 1);
347 * shishi_safe_from_file:
348 * @handle: shishi handle as allocated by shishi_init().
349 * @safe: output variable with newly allocated SAFE.
350 * @filetype: input variable specifying type of file to be read,
351 * see Shishi_filetype.
352 * @filename: input variable with filename to read from.
354 * Read SAFE from file in specified TYPE.
356 * Return value: Returns SHISHI_OK iff successful.
359 shishi_safe_from_file (Shishi * handle, Shishi_asn1 * safe,
360 int filetype, const char *filename)
362 int res;
363 FILE *fh;
365 if (VERBOSE (handle))
366 printf (_("Reading SAFE from %s...\n"), filename);
368 fh = fopen (filename, "r");
369 if (fh == NULL)
370 return SHISHI_FOPEN_ERROR;
372 if (VERBOSE (handle))
373 printf (_("Reading SAFE in %s format...\n"),
374 filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
376 if (filetype == SHISHI_FILETYPE_TEXT)
377 res = shishi_safe_parse (handle, fh, safe);
378 else
379 res = shishi_safe_read (handle, fh, safe);
380 if (res != SHISHI_OK)
381 return res;
383 res = fclose (fh);
384 if (res != 0)
385 return SHISHI_IO_ERROR;
387 if (VERBOSE (handle))
388 printf (_("Reading SAFE from %s...done\n"), filename);
390 return SHISHI_OK;
394 * shishi_safe_cksum:
395 * @handle: shishi handle as allocated by shishi_init().
396 * @safe: safe as allocated by shishi_safe().
397 * @cksumtype: output checksum type.
398 * @cksum: output array with newly allocated checksum data from SAFE.
399 * @cksumlen: output size of output checksum data buffer.
401 * Read checksum value from KRB-SAFE. @cksum is allocated by this
402 * function, and it is the responsibility of caller to deallocate it.
404 * Return value: Returns SHISHI_OK iff successful.
407 shishi_safe_cksum (Shishi * handle,
408 Shishi_asn1 safe,
409 int32_t * cksumtype, char **cksum, size_t * cksumlen)
411 int res;
413 res = shishi_asn1_read_int32 (handle, safe, "cksum.cksumtype", cksumtype);
414 if (res != SHISHI_OK)
415 return res;
417 res = shishi_asn1_read (handle, safe, "cksum.checksum", cksum, cksumlen);
418 if (res != SHISHI_OK)
419 return res;
421 return SHISHI_OK;
425 * shishi_safe_set_cksum:
426 * @handle: shishi handle as allocated by shishi_init().
427 * @safe: safe as allocated by shishi_safe().
428 * @cksumtype: input checksum type to store in SAFE.
429 * @cksum: input checksum data to store in SAFE.
430 * @cksumlen: size of input checksum data to store in SAFE.
432 * Store checksum value in SAFE. A checksum is usually created by
433 * calling shishi_checksum() on some application specific data using
434 * the key from the ticket that is being used. To save time, you may
435 * want to use shishi_safe_build() instead, which calculates the
436 * checksum and calls this function in one step.
438 * Return value: Returns SHISHI_OK iff successful.
441 shishi_safe_set_cksum (Shishi * handle,
442 Shishi_asn1 safe,
443 int32_t cksumtype, const char *cksum, size_t cksumlen)
445 int res;
447 res = shishi_asn1_write_int32 (handle, safe, "cksum.cksumtype", cksumtype);
448 if (res != SHISHI_OK)
449 return res;
451 res = shishi_asn1_write (handle, safe, "cksum.checksum", cksum, cksumlen);
452 if (res != SHISHI_OK)
453 return res;
455 return SHISHI_OK;
459 * shishi_safe_user_data:
460 * @handle: shishi handle as allocated by shishi_init().
461 * @safe: safe as allocated by shishi_safe().
462 * @userdata: output array with newly allocated user data from KRB-SAFE.
463 * @userdatalen: output size of output user data buffer.
465 * Read user data value from KRB-SAFE. @userdata is allocated by this
466 * function, and it is the responsibility of caller to deallocate it.
468 * Return value: Returns SHISHI_OK iff successful.
471 shishi_safe_user_data (Shishi * handle,
472 Shishi_asn1 safe, char **userdata,
473 size_t * userdatalen)
475 int res;
477 res = shishi_asn1_read (handle, safe, "safe-body.user-data",
478 userdata, userdatalen);
479 if (res != SHISHI_OK)
480 return res;
482 return SHISHI_OK;
486 * shishi_safe_set_user_data:
487 * @handle: shishi handle as allocated by shishi_init().
488 * @safe: safe as allocated by shishi_safe().
489 * @userdata: input user application to store in SAFE.
490 * @userdatalen: size of input user application to store in SAFE.
492 * Set the application data in SAFE.
494 * Return value: Returns SHISHI_OK iff successful.
497 shishi_safe_set_user_data (Shishi * handle,
498 Shishi_asn1 safe,
499 const char *userdata, size_t userdatalen)
501 int res;
503 res = shishi_asn1_write (handle, safe, "safe-body.user-data",
504 userdata, userdatalen);
505 if (res != SHISHI_OK)
506 return res;
508 return SHISHI_OK;
512 * shishi_safe_build:
513 * @safe: safe as allocated by shishi_safe().
514 * @key: key for session, used to compute checksum.
516 * Build checksum and set it in KRB-SAFE. Note that this follows RFC
517 * 1510bis and is incompatible with RFC 1510, although presumably few
518 * implementations use the RFC1510 algorithm.
520 * Return value: Returns SHISHI_OK iff successful.
523 shishi_safe_build (Shishi_safe * safe, Shishi_key * key)
525 int rc;
526 char *buffer;
527 size_t buflen;
528 char *cksum;
529 size_t cksumlen;
530 int cksumtype = shishi_cipher_defaultcksumtype (shishi_key_type (key));
532 rc = shishi_safe_set_cksum (safe->handle, safe->safe, 0, "", 0);
533 if (rc != SHISHI_OK)
534 return rc;
536 rc = shishi_safe_safe_der (safe, &buffer, &buflen);
537 if (rc != SHISHI_OK)
538 return rc;
540 /* XXX check if keytype/cksumtype is suitable for SAFE */
542 if (VERBOSEASN1 (safe->handle))
543 shishi_key_print (safe->handle, stdout, key);
545 rc = shishi_checksum (safe->handle, key, SHISHI_KEYUSAGE_KRB_SAFE,
546 cksumtype, buffer, buflen, &cksum, &cksumlen);
547 free (buffer);
548 if (rc != SHISHI_OK)
549 return rc;
551 rc = shishi_safe_set_cksum (safe->handle, safe->safe,
552 cksumtype, cksum, cksumlen);
553 if (rc != SHISHI_OK)
554 return rc;
556 return SHISHI_OK;
560 * shishi_safe_verify:
561 * @safe: safe as allocated by shishi_safe().
562 * @key: key for session, used to verify checksum.
564 * Verify checksum in KRB-SAFE. Note that this follows RFC 1510bis
565 * and is incompatible with RFC 1510, although presumably few
566 * implementations use the RFC1510 algorithm.
568 * Return value: Returns SHISHI_OK iff successful,
569 * SHISHI_SAFE_BAD_KEYTYPE if an incompatible key type is used, or
570 * SHISHI_SAFE_VERIFY_FAILED if the actual verification failed.
573 shishi_safe_verify (Shishi_safe * safe, Shishi_key * key)
575 char *cksum = NULL;
576 size_t cksumlen;
577 int cksumtype;
578 char *safeder = NULL;
579 size_t safederlen;
580 int rc;
582 rc = shishi_safe_cksum (safe->handle, safe->safe,
583 &cksumtype, &cksum, &cksumlen);
584 if (rc != SHISHI_OK)
585 goto done;
587 rc = shishi_safe_set_cksum (safe->handle, safe->safe, 0, "", 0);
588 if (rc != SHISHI_OK)
589 goto done;
591 rc = shishi_safe_safe_der (safe, &safeder, &safederlen);
592 if (rc != SHISHI_OK)
593 goto done;
595 rc = shishi_verify (safe->handle, key, SHISHI_KEYUSAGE_KRB_SAFE,
596 cksumtype, safeder, safederlen, cksum, cksumlen);
597 if (rc != SHISHI_OK)
598 goto done;
600 rc = SHISHI_OK;
602 done:
603 if (cksum)
604 free (cksum);
605 if (safeder)
606 free (safeder);
607 return rc;