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
25 /* Get _shishi_print_armored_data, etc. */
33 unsigned long seqnumber
;
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.
46 shishi_safe (Shishi
* handle
, Shishi_safe
** safe
)
53 *safe
= xcalloc (1, sizeof (**safe
));
56 lsafe
->handle
= handle
;
57 rc
= shishi_key (handle
, &lsafe
->key
);
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);
69 rc
= shishi_asn1_write (handle
, lsafe
->safe
, "msg-type", "20", 0);
73 rc
= shishi_asn1_write (handle
, lsafe
->safe
, "safe-body.seq-number",
78 rc
= gettimeofday (&tv
, NULL
);
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);
88 rc
= shishi_asn1_write (handle
, lsafe
->safe
, "safe-body.timestamp",
89 shishi_generalize_time (handle
, time (NULL
)), 0);
93 rc
= shishi_asn1_write (handle
, lsafe
->safe
, "safe-body.s-address.addr-type", "3", 0); /* directional */
97 rc
= shishi_asn1_write (handle
, lsafe
->safe
, "safe-body.s-address.address", "\x00\x00\x00\x00", 4); /* sender */
101 rc
= shishi_asn1_write (handle
, lsafe
->safe
, "safe-body.r-address",
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.
118 shishi_safe_done (Shishi_safe
* safe
)
120 shishi_asn1_done (safe
->handle
, safe
->safe
);
121 shishi_key_done (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.
135 shishi_safe_key (Shishi_safe
* safe
)
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.
148 shishi_safe_key_set (Shishi_safe
* safe
, Shishi_key
* key
)
150 shishi_key_copy (safe
->key
, key
);
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.
163 shishi_safe_safe (Shishi_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.
176 shishi_safe_safe_set (Shishi_safe
* safe
, Shishi_asn1 asn1safe
)
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
)
200 rc
= shishi_asn1_to_der (safe
->handle
, safe
->safe
, out
, outlen
);
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
);
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
);
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
)
285 if (VERBOSE (handle
))
286 printf (_("Writing SAFE to %s...\n"), filename
);
288 fh
= fopen (filename
, "w");
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
);
299 res
= shishi_safe_save (handle
, fh
, safe
);
300 if (res
!= SHISHI_OK
)
305 return SHISHI_IO_ERROR
;
307 if (VERBOSE (handle
))
308 printf (_("Writing SAFE to %s...done\n"), filename
);
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
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);
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
)
365 if (VERBOSE (handle
))
366 printf (_("Reading SAFE from %s...\n"), filename
);
368 fh
= fopen (filename
, "r");
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
);
379 res
= shishi_safe_read (handle
, fh
, safe
);
380 if (res
!= SHISHI_OK
)
385 return SHISHI_IO_ERROR
;
387 if (VERBOSE (handle
))
388 printf (_("Reading SAFE from %s...done\n"), filename
);
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
,
409 int32_t * cksumtype
, char **cksum
, size_t * cksumlen
)
413 res
= shishi_asn1_read_int32 (handle
, safe
, "cksum.cksumtype", cksumtype
);
414 if (res
!= SHISHI_OK
)
417 res
= shishi_asn1_read (handle
, safe
, "cksum.checksum", cksum
, cksumlen
);
418 if (res
!= 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
,
443 int32_t cksumtype
, const char *cksum
, size_t cksumlen
)
447 res
= shishi_asn1_write_int32 (handle
, safe
, "cksum.cksumtype", cksumtype
);
448 if (res
!= SHISHI_OK
)
451 res
= shishi_asn1_write (handle
, safe
, "cksum.checksum", cksum
, cksumlen
);
452 if (res
!= 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
)
477 res
= shishi_asn1_read (handle
, safe
, "safe-body.user-data",
478 userdata
, userdatalen
);
479 if (res
!= 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
,
499 const char *userdata
, size_t userdatalen
)
503 res
= shishi_asn1_write (handle
, safe
, "safe-body.user-data",
504 userdata
, userdatalen
);
505 if (res
!= SHISHI_OK
)
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
)
530 int cksumtype
= shishi_cipher_defaultcksumtype (shishi_key_type (key
));
532 rc
= shishi_safe_set_cksum (safe
->handle
, safe
->safe
, 0, "", 0);
536 rc
= shishi_safe_safe_der (safe
, &buffer
, &buflen
);
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
);
551 rc
= shishi_safe_set_cksum (safe
->handle
, safe
->safe
,
552 cksumtype
, cksum
, cksumlen
);
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
)
578 char *safeder
= NULL
;
582 rc
= shishi_safe_cksum (safe
->handle
, safe
->safe
,
583 &cksumtype
, &cksum
, &cksumlen
);
587 rc
= shishi_safe_set_cksum (safe
->handle
, safe
->safe
, 0, "", 0);
591 rc
= shishi_safe_safe_der (safe
, &safeder
, &safederlen
);
595 rc
= shishi_verify (safe
->handle
, key
, SHISHI_KEYUSAGE_KRB_SAFE
,
596 cksumtype
, safeder
, safederlen
, cksum
, cksumlen
);