Generated.
[shishi.git] / lib / safe.c
blob8f6fbda4bff5fa8414bab5480430ecf50d9116de
1 /* safe.c Application data integrity protection.
2 * Copyright (C) 2002, 2003 Simon Josefsson
4 * This file is part of Shishi.
6 * Shishi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Shishi is distributed in the hope that it will be useful,
12 * but 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, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "internal.h"
24 struct Shishi_safe
26 Shishi *handle;
27 Shishi_key *key;
28 Shishi_asn1 safe;
29 unsigned long seqnumber;
32 /**
33 * shishi_safe:
34 * @handle: shishi handle as allocated by shishi_init().
35 * @safe: pointer to new structure that holds information about SAFE exchange
37 * Create a new SAFE exchange.
39 * Return value: Returns SHISHI_OK iff successful.
40 **/
41 int
42 shishi_safe (Shishi * handle, Shishi_safe ** safe)
44 Shishi_safe *lsafe;
45 struct timeval tv;
46 struct timezone tz;
47 char usec[BUFSIZ];
48 int rc;
50 *safe = malloc (sizeof (**safe));
51 if (*safe == NULL)
52 return SHISHI_MALLOC_ERROR;
53 lsafe = *safe;
54 memset (lsafe, 0, sizeof (*lsafe));
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 gettimeofday (&tv, &tz);
79 sprintf (usec, "%ld", tv.tv_usec % 1000000);
80 rc = shishi_asn1_write (handle, lsafe->safe, "safe-body.usec", usec, 0);
81 if (rc != SHISHI_OK)
82 return rc;
84 rc = shishi_asn1_write (handle, lsafe->safe, "safe-body.timestamp",
85 shishi_generalize_time (handle, time (NULL)), 0);
86 if (rc != SHISHI_OK)
87 return rc;
89 rc = shishi_asn1_write (handle, lsafe->safe, "safe-body.s-address.addr-type", "3", 0); /* directional */
90 if (rc != SHISHI_OK)
91 return rc;
93 rc = shishi_asn1_write (handle, lsafe->safe, "safe-body.s-address.address", "\x00\x00\x00\x00", 4); /* sender */
94 if (rc != SHISHI_OK)
95 return rc;
97 rc = shishi_asn1_write (handle, lsafe->safe, "safe-body.r-address",
98 NULL, 0);
99 if (rc != SHISHI_OK)
100 return rc;
102 return SHISHI_OK;
106 * shishi_safe_key:
107 * @ap: structure that holds information about SAFE exchange
109 * Return value: Returns the key used in the SAFE exchange, or NULL if
110 * not yet set or an error occured.
112 Shishi_key *
113 shishi_safe_key (Shishi_safe * safe)
115 return safe->key;
119 * shishi_safe_key_set:
120 * @safe: structure that holds information about SAFE exchange
121 * @key: key to store in SAFE.
123 * Set the Key in the SAFE exchange.
125 void
126 shishi_safe_key_set (Shishi_safe * safe, Shishi_key * key)
128 shishi_key_copy (safe->key, key);
132 * shishi_safe_safe:
133 * @ap: structure that holds information about SAFE exchange
135 * Return value: Returns the ASN.1 safe in the SAFE exchange, or NULL if
136 * not yet set or an error occured.
138 Shishi_asn1
139 shishi_safe_safe (Shishi_safe * safe)
141 return safe->safe;
145 * shishi_safe_safe_set:
146 * @safe: structure that holds information about SAFE exchange
147 * @safe: KRB-SAFE to store in SAFE exchange.
149 * Set the KRB-SAFE in the SAFE exchange.
151 void
152 shishi_safe_safe_set (Shishi_safe * safe, Shishi_asn1 asn1safe)
154 if (safe->safe)
155 shishi_asn1_done (safe->handle, safe->safe);
156 safe->safe = asn1safe;
160 * shishi_safe_safe_der:
161 * @safe: safe as allocated by shishi_safe().
162 * @out: output array with der encoding of SAFE.
163 * @outlen: length of output array with der encoding of SAFE.
165 * DER encode SAFE structure. Typically shishi_safe_build() is used
166 * instead to build the SAFE structure first.
168 * Return value: Returns SHISHI_OK iff successful.
171 shishi_safe_safe_der (Shishi_safe * safe, char *out, int *outlen)
173 int rc;
175 rc = shishi_a2d (safe->handle, safe->safe, out, outlen);
176 if (rc != SHISHI_OK)
177 return rc;
179 return SHISHI_OK;
183 * shishi_safe_safe_der_set:
184 * @safe: safe as allocated by shishi_safe().
185 * @der: input array with DER encoded KRB-SAFE.
186 * @derlen: length of input array with DER encoded KRB-SAFE.
188 * DER decode KRB-SAFE and set it SAFE exchange. If decoding fails, the
189 * KRB-SAFE in the SAFE exchange remains.
191 * Return value: Returns SHISHI_OK.
194 shishi_safe_safe_der_set (Shishi_safe * safe, char *der, size_t derlen)
196 Shishi_asn1 asn1safe;
198 asn1safe = shishi_der2asn1_krbsafe (safe->handle, der, derlen);
200 if (asn1safe == NULL)
201 return SHISHI_ASN1_ERROR;
203 shishi_safe_safe_set (safe, asn1safe);
205 return SHISHI_OK;
209 * shishi_safe_print:
210 * @handle: shishi handle as allocated by shishi_init().
211 * @fh: file handle open for writing.
212 * @safe: SAFE to print.
214 * Print ASCII armored DER encoding of SAFE to file.
216 * Return value: Returns SHISHI_OK iff successful.
219 shishi_safe_print (Shishi * handle, FILE * fh, Shishi_asn1 safe)
221 return _shishi_print_armored_data (handle, fh, safe, "KRB-SAFE", NULL);
225 * shishi_safe_save:
226 * @handle: shishi handle as allocated by shishi_init().
227 * @fh: file handle open for writing.
228 * @safe: SAFE to save.
230 * Save DER encoding of SAFE to file.
232 * Return value: Returns SHISHI_OK iff successful.
235 shishi_safe_save (Shishi * handle, FILE * fh, Shishi_asn1 safe)
237 return _shishi_save_data (handle, fh, safe, "SAFE");
241 * shishi_safe_to_file:
242 * @handle: shishi handle as allocated by shishi_init().
243 * @safe: SAFE to save.
244 * @filetype: input variable specifying type of file to be written,
245 * see Shishi_filetype.
246 * @filename: input variable with filename to write to.
248 * Write SAFE to file in specified TYPE. The file will be
249 * truncated if it exists.
251 * Return value: Returns SHISHI_OK iff successful.
254 shishi_safe_to_file (Shishi * handle, Shishi_asn1 safe,
255 int filetype, char *filename)
257 FILE *fh;
258 int res;
260 if (VERBOSE (handle))
261 printf (_("Writing SAFE to %s...\n"), filename);
263 fh = fopen (filename, "w");
264 if (fh == NULL)
265 return SHISHI_FOPEN_ERROR;
267 if (VERBOSE (handle))
268 printf (_("Writing SAFE in %s format...\n"),
269 filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
271 if (filetype == SHISHI_FILETYPE_TEXT)
272 res = shishi_safe_print (handle, fh, safe);
273 else
274 res = shishi_safe_save (handle, fh, safe);
275 if (res != SHISHI_OK)
276 return res;
278 res = fclose (fh);
279 if (res != 0)
280 return SHISHI_FCLOSE_ERROR;
282 if (VERBOSE (handle))
283 printf (_("Writing SAFE to %s...done\n"), filename);
285 return SHISHI_OK;
289 * shishi_safe_parse:
290 * @handle: shishi handle as allocated by shishi_init().
291 * @fh: file handle open for reading.
292 * @safe: output variable with newly allocated SAFE.
294 * Read ASCII armored DER encoded SAFE from file and populate given
295 * variable.
297 * Return value: Returns SHISHI_OK iff successful.
300 shishi_safe_parse (Shishi * handle, FILE * fh, Shishi_asn1 * safe)
302 return _shishi_safe_input (handle, fh, safe, 0);
306 * shishi_safe_read:
307 * @handle: shishi handle as allocated by shishi_init().
308 * @fh: file handle open for reading.
309 * @safe: output variable with newly allocated SAFE.
311 * Read DER encoded SAFE from file and populate given variable.
313 * Return value: Returns SHISHI_OK iff successful.
316 shishi_safe_read (Shishi * handle, FILE * fh, Shishi_asn1 * safe)
318 return _shishi_safe_input (handle, fh, safe, 1);
322 * shishi_safe_from_file:
323 * @handle: shishi handle as allocated by shishi_init().
324 * @safe: output variable with newly allocated SAFE.
325 * @filetype: input variable specifying type of file to be read,
326 * see Shishi_filetype.
327 * @filename: input variable with filename to read from.
329 * Read SAFE from file in specified TYPE.
331 * Return value: Returns SHISHI_OK iff successful.
334 shishi_safe_from_file (Shishi * handle, Shishi_asn1 * safe,
335 int filetype, char *filename)
337 int res;
338 FILE *fh;
340 if (VERBOSE (handle))
341 printf (_("Reading SAFE from %s...\n"), filename);
343 fh = fopen (filename, "r");
344 if (fh == NULL)
345 return SHISHI_FOPEN_ERROR;
347 if (VERBOSE (handle))
348 printf (_("Reading SAFE in %s format...\n"),
349 filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
351 if (filetype == SHISHI_FILETYPE_TEXT)
352 res = shishi_safe_parse (handle, fh, safe);
353 else
354 res = shishi_safe_read (handle, fh, safe);
355 if (res != SHISHI_OK)
356 return res;
358 res = fclose (fh);
359 if (res != 0)
360 return SHISHI_FCLOSE_ERROR;
362 if (VERBOSE (handle))
363 printf (_("Reading SAFE from %s...done\n"), filename);
365 return SHISHI_OK;
369 * shishi_safe_cksum:
370 * @handle: shishi handle as allocated by shishi_init().
371 * @safe: safe as allocated by shishi_safe().
372 * @cksumtype: output checksum type.
373 * @cksum: output checksum data from SAFE.
374 * @cksumlen: on input, maximum size of output checksum data buffer,
375 * on output, actual size of output checksum data buffer.
377 * Read checksum value from KRB-SAFE.
379 * Return value: Returns SHISHI_OK iff successful.
382 shishi_safe_cksum (Shishi * handle,
383 Shishi_asn1 safe,
384 int32_t * cksumtype, char *cksum, size_t * cksumlen)
386 int res;
388 res = shishi_asn1_read_int32 (handle, safe, "cksum.cksumtype", cksumtype);
389 if (res != SHISHI_OK)
390 return res;
392 res = shishi_asn1_field (handle, safe, cksum, cksumlen, "cksum.checksum");
393 if (res != SHISHI_OK)
394 return res;
396 return SHISHI_OK;
400 * shishi_safe_set_cksum:
401 * @handle: shishi handle as allocated by shishi_init().
402 * @safe: safe as allocated by shishi_safe().
403 * @cksumtype: input checksum type to store in SAFE.
404 * @cksum: input checksum data to store in SAFE.
405 * @cksumlen: size of input checksum data to store in SAFE.
407 * Store checksum value in SAFE. A checksum is usually created by
408 * calling shishi_checksum() on some application specific data using
409 * the key from the ticket that is being used. To save time, you may
410 * want to use shishi_safe_build() instead, which calculates the
411 * checksum and calls this function in one step.
413 * Return value: Returns SHISHI_OK iff successful.
416 shishi_safe_set_cksum (Shishi * handle,
417 Shishi_asn1 safe,
418 int32_t cksumtype, char *cksum, size_t cksumlen)
420 int res;
422 res = shishi_asn1_write_int32 (handle, safe, "cksum.cksumtype", cksumtype);
423 if (res != SHISHI_OK)
424 return res;
426 res = shishi_asn1_write (handle, safe, "cksum.checksum", cksum, cksumlen);
427 if (res != SHISHI_OK)
428 return res;
430 return SHISHI_OK;
434 * shishi_safe_user_data:
435 * @handle: shishi handle as allocated by shishi_init().
436 * @safe: safe as allocated by shishi_safe().
437 * @userdata: output user data from KRB-SAFE.
438 * @userdatalen: on input, maximum size of output user data buffer,
439 * on output, actual size of output user data buffer.
441 * Read user data value from KRB-SAFE.
443 * Return value: Returns SHISHI_OK iff successful.
446 shishi_safe_user_data (Shishi * handle,
447 Shishi_asn1 safe, char *userdata, size_t * userdatalen)
449 int res;
451 res = shishi_asn1_read (handle, safe, "safe-body.user-data",
452 userdata, userdatalen);
453 if (res != SHISHI_OK)
454 return res;
456 return SHISHI_OK;
460 * shishi_safe_set_user_data:
461 * @handle: shishi handle as allocated by shishi_init().
462 * @safe: safe as allocated by shishi_safe().
463 * @userdata: input user application to store in SAFE.
464 * @userdatalen: size of input user application to store in SAFE.
466 * Set the application data in SAFE.
468 * Return value: Returns SHISHI_OK iff successful.
471 shishi_safe_set_user_data (Shishi * handle,
472 Shishi_asn1 safe,
473 char *userdata, size_t userdatalen)
475 int res;
477 res = shishi_asn1_write (handle, safe, "safe-body.user-data",
478 userdata, userdatalen);
479 if (res != SHISHI_OK)
480 return res;
482 return SHISHI_OK;
486 * shishi_safe_build:
487 * @safe: safe as allocated by shishi_safe().
488 * @key: key for session, used to compute checksum.
490 * Build checksum and set it in KRB-SAFE. Note that this follows RFC
491 * 1510bis and is incompatible with RFC 1510, although presumably few
492 * implementations use the RFC1510 algorithm.
494 * Return value: Returns SHISHI_OK iff successful.
497 shishi_safe_build (Shishi_safe * safe, Shishi_key * key)
499 int rc;
500 char buffer[BUFSIZ];
501 int buflen;
502 char *cksum;
503 int cksumlen;
504 int cksumtype = shishi_cipher_defaultcksumtype (shishi_key_type (key));
506 rc = shishi_safe_set_cksum (safe->handle, safe->safe, 0, "", 0);
507 if (rc != SHISHI_OK)
508 return rc;
510 buflen = sizeof (buffer);
511 rc = shishi_safe_safe_der (safe, buffer, &buflen);
512 if (rc != SHISHI_OK)
513 return rc;
515 /* XXX check if keytype/cksumtype is suitable for SAFE */
517 if (VERBOSEASN1 (safe->handle))
518 shishi_key_print (safe->handle, stdout, key);
520 rc =
521 shishi_checksum (safe->handle, key, SHISHI_KEYUSAGE_KRB_SAFE, cksumtype,
522 buffer, buflen, &cksum, &cksumlen);
523 if (rc != SHISHI_OK)
524 return rc;
526 rc = shishi_safe_set_cksum (safe->handle, safe->safe,
527 cksumtype, cksum, cksumlen);
528 if (rc != SHISHI_OK)
529 return rc;
531 return SHISHI_OK;
535 * shishi_safe_verify:
536 * @safe: safe as allocated by shishi_safe().
537 * @key: key for session, used to verify checksum.
539 * Verify checksum in KRB-SAFE. Note that this follows RFC 1510bis
540 * and is incompatible with RFC 1510, although presumably few
541 * implementations use the RFC1510 algorithm.
543 * Return value: Returns SHISHI_OK iff successful,
544 * SHISHI_SAFE_BAD_KEYTYPE if an incompatible key type
545 * is used, or SHISHI_SAFE_VERIFY_FAILED if the actual
546 * verification failed.
549 shishi_safe_verify (Shishi_safe * safe, Shishi_key * key)
551 char cksum[MAX_CKSUM_LEN];
552 size_t cksumlen;
553 int cksumtype;
554 char cksum2[MAX_CKSUM_LEN];
555 size_t cksum2len;
556 int cksumtype2;
557 int rc;
559 cksumlen = sizeof (cksum);
560 rc = shishi_safe_cksum (safe->handle, safe->safe,
561 &cksumtype, cksum, &cksumlen);
562 if (rc != SHISHI_OK)
563 return rc;
565 rc = shishi_safe_build (safe, key);
566 if (rc != SHISHI_OK)
567 return rc;
569 cksum2len = sizeof (cksum2);
570 rc = shishi_safe_cksum (safe->handle, safe->safe,
571 &cksumtype2, cksum2, &cksum2len);
572 if (rc != SHISHI_OK)
573 return rc;
575 if (cksumtype != cksumtype2)
576 return SHISHI_SAFE_BAD_KEYTYPE;
578 if (cksum2len != cksumlen || memcmp (cksum, cksum2, cksumlen) != 0)
579 return SHISHI_SAFE_VERIFY_FAILED;
581 return SHISHI_OK;