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
29 unsigned long seqnumber
;
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.
42 shishi_safe (Shishi
* handle
, Shishi_safe
** safe
)
50 *safe
= malloc (sizeof (**safe
));
52 return SHISHI_MALLOC_ERROR
;
54 memset (lsafe
, 0, sizeof (*lsafe
));
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 gettimeofday (&tv
, &tz
);
79 sprintf (usec
, "%ld", tv
.tv_usec
% 1000000);
80 rc
= shishi_asn1_write (handle
, lsafe
->safe
, "safe-body.usec", usec
, 0);
84 rc
= shishi_asn1_write (handle
, lsafe
->safe
, "safe-body.timestamp",
85 shishi_generalize_time (handle
, time (NULL
)), 0);
89 rc
= shishi_asn1_write (handle
, lsafe
->safe
, "safe-body.s-address.addr-type", "3", 0); /* directional */
93 rc
= shishi_asn1_write (handle
, lsafe
->safe
, "safe-body.s-address.address", "\x00\x00\x00\x00", 4); /* sender */
97 rc
= shishi_asn1_write (handle
, lsafe
->safe
, "safe-body.r-address",
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.
113 shishi_safe_key (Shishi_safe
* safe
)
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.
126 shishi_safe_key_set (Shishi_safe
* safe
, Shishi_key
* key
)
128 shishi_key_copy (safe
->key
, key
);
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.
139 shishi_safe_safe (Shishi_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.
152 shishi_safe_safe_set (Shishi_safe
* safe
, Shishi_asn1 asn1safe
)
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
)
175 rc
= shishi_a2d (safe
->handle
, safe
->safe
, out
, outlen
);
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
);
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
);
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
)
260 if (VERBOSE (handle
))
261 printf (_("Writing SAFE to %s...\n"), filename
);
263 fh
= fopen (filename
, "w");
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
);
274 res
= shishi_safe_save (handle
, fh
, safe
);
275 if (res
!= SHISHI_OK
)
280 return SHISHI_FCLOSE_ERROR
;
282 if (VERBOSE (handle
))
283 printf (_("Writing SAFE to %s...done\n"), filename
);
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
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);
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
)
340 if (VERBOSE (handle
))
341 printf (_("Reading SAFE from %s...\n"), filename
);
343 fh
= fopen (filename
, "r");
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
);
354 res
= shishi_safe_read (handle
, fh
, safe
);
355 if (res
!= SHISHI_OK
)
360 return SHISHI_FCLOSE_ERROR
;
362 if (VERBOSE (handle
))
363 printf (_("Reading SAFE from %s...done\n"), filename
);
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
,
384 int32_t * cksumtype
, char *cksum
, size_t * cksumlen
)
388 res
= shishi_asn1_read_int32 (handle
, safe
, "cksum.cksumtype", cksumtype
);
389 if (res
!= SHISHI_OK
)
392 res
= shishi_asn1_field (handle
, safe
, cksum
, cksumlen
, "cksum.checksum");
393 if (res
!= 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
,
418 int32_t cksumtype
, char *cksum
, size_t cksumlen
)
422 res
= shishi_asn1_write_int32 (handle
, safe
, "cksum.cksumtype", cksumtype
);
423 if (res
!= SHISHI_OK
)
426 res
= shishi_asn1_write (handle
, safe
, "cksum.checksum", cksum
, cksumlen
);
427 if (res
!= 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
)
451 res
= shishi_asn1_read (handle
, safe
, "safe-body.user-data",
452 userdata
, userdatalen
);
453 if (res
!= 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
,
473 char *userdata
, size_t userdatalen
)
477 res
= shishi_asn1_write (handle
, safe
, "safe-body.user-data",
478 userdata
, userdatalen
);
479 if (res
!= SHISHI_OK
)
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
)
504 int cksumtype
= shishi_cipher_defaultcksumtype (shishi_key_type (key
));
506 rc
= shishi_safe_set_cksum (safe
->handle
, safe
->safe
, 0, "", 0);
510 buflen
= sizeof (buffer
);
511 rc
= shishi_safe_safe_der (safe
, buffer
, &buflen
);
515 /* XXX check if keytype/cksumtype is suitable for SAFE */
517 if (VERBOSEASN1 (safe
->handle
))
518 shishi_key_print (safe
->handle
, stdout
, key
);
521 shishi_checksum (safe
->handle
, key
, SHISHI_KEYUSAGE_KRB_SAFE
, cksumtype
,
522 buffer
, buflen
, &cksum
, &cksumlen
);
526 rc
= shishi_safe_set_cksum (safe
->handle
, safe
->safe
,
527 cksumtype
, cksum
, cksumlen
);
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
];
554 char cksum2
[MAX_CKSUM_LEN
];
559 cksumlen
= sizeof (cksum
);
560 rc
= shishi_safe_cksum (safe
->handle
, safe
->safe
,
561 &cksumtype
, cksum
, &cksumlen
);
565 rc
= shishi_safe_build (safe
, key
);
569 cksum2len
= sizeof (cksum2
);
570 rc
= shishi_safe_cksum (safe
->handle
, safe
->safe
,
571 &cksumtype2
, cksum2
, &cksum2len
);
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
;