Update gnulib files.
[shishi.git] / lib / priv.c
blob776f6cce0a15cd1033616c8439b48a4c365986fc
1 /* priv.c --- Application data privacy 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_priv
30 Shishi *handle;
31 Shishi_key *key;
32 Shishi_asn1 priv;
33 Shishi_asn1 encprivpart;
34 unsigned long seqnumber;
37 /**
38 * shishi_priv:
39 * @handle: shishi handle as allocated by shishi_init().
40 * @priv: pointer to new structure that holds information about PRIV exchange
42 * Create a new PRIV exchange.
44 * Return value: Returns SHISHI_OK iff successful.
45 **/
46 int
47 shishi_priv (Shishi * handle, Shishi_priv ** priv)
49 Shishi_priv *lpriv;
50 struct timeval tv;
51 char *usec;
52 int rc;
54 *priv = xcalloc (1, sizeof (**priv));
55 lpriv = *priv;
57 lpriv->handle = handle;
58 rc = shishi_key (handle, &lpriv->key);
59 if (rc != SHISHI_OK)
60 return rc;
62 lpriv->priv = shishi_asn1_priv (handle);
63 if (lpriv->priv == NULL)
64 return SHISHI_ASN1_ERROR;
66 rc = shishi_asn1_write (handle, lpriv->priv, "pvno", "5", 0);
67 if (rc != SHISHI_OK)
68 return rc;
70 rc = shishi_asn1_write (handle, lpriv->priv, "msg-type", "21", 0);
71 if (rc != SHISHI_OK)
72 return rc;
74 rc = shishi_asn1_write (handle, lpriv->priv, "enc-part.kvno", "0", 0);
75 if (rc != SHISHI_OK)
76 return rc;
78 lpriv->encprivpart = shishi_asn1_encprivpart (handle);
79 if (lpriv->priv == NULL)
80 return SHISHI_ASN1_ERROR;
82 rc = shishi_asn1_write (handle, lpriv->encprivpart, "timestamp",
83 shishi_generalize_time (handle, time (NULL)), 0);
84 if (rc != SHISHI_OK)
85 return rc;
87 rc = gettimeofday (&tv, NULL);
88 if (rc != 0)
89 return SHISHI_GETTIMEOFDAY_ERROR;
90 usec = xasprintf ("%ld", tv.tv_usec % 1000000);
91 rc = shishi_asn1_write (handle, lpriv->encprivpart, "usec", usec, 0);
92 free (usec);
93 if (rc != SHISHI_OK)
94 return rc;
96 rc = shishi_asn1_write (handle, lpriv->encprivpart, "seq-number", NULL, 0);
97 if (rc != SHISHI_OK)
98 return rc;
100 rc = shishi_asn1_write (handle, lpriv->encprivpart, "s-address.addr-type",
101 /* directional */
102 "3", 0);
103 if (rc != SHISHI_OK)
104 return rc;
106 rc = shishi_asn1_write (handle, lpriv->encprivpart, "s-address.address",
107 /* sender */
108 "\x00\x00\x00\x00", 4);
109 if (rc != SHISHI_OK)
110 return rc;
112 rc = shishi_asn1_write (handle, lpriv->encprivpart, "r-address", NULL, 0);
113 if (rc != SHISHI_OK)
114 return rc;
116 return SHISHI_OK;
120 * shishi_priv_done:
121 * @priv: structure that holds information about PRIV exchange
123 * Deallocate resources associated with PRIV exchange. This should be
124 * called by the application when it no longer need to utilize the
125 * PRIV exchange handle.
127 void
128 shishi_priv_done (Shishi_priv * priv)
130 shishi_asn1_done (priv->handle, priv->priv);
131 shishi_asn1_done (priv->handle, priv->encprivpart);
132 shishi_key_done (priv->key);
133 free (priv);
137 * shishi_priv_key:
138 * @priv: structure that holds information about PRIV exchange
140 * Get key from PRIV exchange.
142 * Return value: Returns the key used in the PRIV exchange, or NULL if
143 * not yet set or an error occured.
145 Shishi_key *
146 shishi_priv_key (Shishi_priv * priv)
148 return priv->key;
152 * shishi_priv_key_set:
153 * @priv: structure that holds information about PRIV exchange
154 * @key: key to store in PRIV.
156 * Set the Key in the PRIV exchange.
158 void
159 shishi_priv_key_set (Shishi_priv * priv, Shishi_key * key)
161 shishi_key_copy (priv->key, key);
165 * shishi_priv_priv:
166 * @priv: structure that holds information about PRIV exchange
168 * Get ASN.1 PRIV structure in PRIV exchange.
170 * Return value: Returns the ASN.1 priv in the PRIV exchange, or NULL if
171 * not yet set or an error occured.
173 Shishi_asn1
174 shishi_priv_priv (Shishi_priv * priv)
176 return priv->priv;
180 * shishi_priv_priv_set:
181 * @priv: structure that holds information about PRIV exchange
182 * @asn1priv: KRB-PRIV to store in PRIV exchange.
184 * Set the KRB-PRIV in the PRIV exchange.
186 void
187 shishi_priv_priv_set (Shishi_priv * priv, Shishi_asn1 asn1priv)
189 if (priv->priv)
190 shishi_asn1_done (priv->handle, priv->priv);
191 priv->priv = asn1priv;
195 * shishi_priv_priv_der:
196 * @priv: priv as allocated by shishi_priv().
197 * @out: output array with newly allocated DER encoding of PRIV.
198 * @outlen: length of output array with DER encoding of PRIV.
200 * DER encode PRIV structure. Typically shishi_priv_build() is used
201 * to build the PRIV structure first. @out is allocated by this
202 * function, and it is the responsibility of caller to deallocate it.
204 * Return value: Returns SHISHI_OK iff successful.
207 shishi_priv_priv_der (Shishi_priv * priv, char **out, size_t * outlen)
209 int rc;
211 rc = shishi_asn1_to_der (priv->handle, priv->priv, out, outlen);
212 if (rc != SHISHI_OK)
213 return rc;
215 return SHISHI_OK;
219 * shishi_priv_priv_der_set:
220 * @priv: priv as allocated by shishi_priv().
221 * @der: input array with DER encoded KRB-PRIV.
222 * @derlen: length of input array with DER encoded KRB-PRIV.
224 * DER decode KRB-PRIV and set it PRIV exchange. If decoding fails, the
225 * KRB-PRIV in the PRIV exchange remains.
227 * Return value: Returns SHISHI_OK.
230 shishi_priv_priv_der_set (Shishi_priv * priv, char *der, size_t derlen)
232 Shishi_asn1 asn1priv;
234 asn1priv = shishi_der2asn1_priv (priv->handle, der, derlen);
236 if (asn1priv == NULL)
237 return SHISHI_ASN1_ERROR;
239 shishi_priv_priv_set (priv, asn1priv);
241 return SHISHI_OK;
245 * shishi_priv_encprivpart:
246 * @priv: structure that holds information about PRIV exchange
248 * Get ASN.1 EncPrivPart structure from PRIV exchange.
250 * Return value: Returns the ASN.1 encprivpart in the PRIV exchange, or NULL if
251 * not yet set or an error occured.
253 Shishi_asn1
254 shishi_priv_encprivpart (Shishi_priv * priv)
256 return priv->encprivpart;
260 * shishi_priv_encprivpart_set:
261 * @priv: structure that holds information about PRIV exchange
262 * @asn1encprivpart: ENCPRIVPART to store in PRIV exchange.
264 * Set the ENCPRIVPART in the PRIV exchange.
266 void
267 shishi_priv_encprivpart_set (Shishi_priv * priv, Shishi_asn1 asn1encprivpart)
269 if (priv->encprivpart)
270 shishi_asn1_done (priv->handle, priv->encprivpart);
271 priv->encprivpart = asn1encprivpart;
275 * shishi_priv_encprivpart_der:
276 * @priv: priv as allocated by shishi_priv().
277 * @out: output array with newly allocated DER encoding of ENCPRIVPART.
278 * @outlen: length of output array with DER encoding of ENCPRIVPART.
280 * DER encode ENCPRIVPART structure. Typically
281 * shishi_encprivpart_build() is used to build the ENCPRIVPART
282 * structure first. @out is allocated by this function, and it is the
283 * responsibility of caller to deallocate it.
285 * Return value: Returns SHISHI_OK iff successful.
288 shishi_priv_encprivpart_der (Shishi_priv * priv, char **out, size_t * outlen)
290 int rc;
292 rc = shishi_asn1_to_der (priv->handle, priv->encprivpart, out, outlen);
293 if (rc != SHISHI_OK)
294 return rc;
296 return SHISHI_OK;
300 * shishi_priv_encprivpart_der_set:
301 * @priv: priv as allocated by shishi_priv().
302 * @der: input array with DER encoded ENCPRIVPART.
303 * @derlen: length of input array with DER encoded ENCPRIVPART.
305 * DER decode ENCPRIVPART and set it PRIV exchange. If decoding
306 * fails, the ENCPRIVPART in the PRIV exchange remains.
308 * Return value: Returns SHISHI_OK.
311 shishi_priv_encprivpart_der_set (Shishi_priv * priv, char *der, size_t derlen)
313 Shishi_asn1 asn1encprivpart;
315 asn1encprivpart = shishi_der2asn1_encprivpart (priv->handle, der, derlen);
317 if (asn1encprivpart == NULL)
318 return SHISHI_ASN1_ERROR;
320 shishi_priv_encprivpart_set (priv, asn1encprivpart);
322 return SHISHI_OK;
326 * shishi_priv_print:
327 * @handle: shishi handle as allocated by shishi_init().
328 * @fh: file handle open for writing.
329 * @priv: PRIV to print.
331 * Print ASCII armored DER encoding of PRIV to file.
333 * Return value: Returns SHISHI_OK iff successful.
336 shishi_priv_print (Shishi * handle, FILE * fh, Shishi_asn1 priv)
338 return _shishi_print_armored_data (handle, fh, priv, "KRB-PRIV", NULL);
342 * shishi_priv_save:
343 * @handle: shishi handle as allocated by shishi_init().
344 * @fh: file handle open for writing.
345 * @priv: PRIV to save.
347 * Save DER encoding of PRIV to file.
349 * Return value: Returns SHISHI_OK iff successful.
352 shishi_priv_save (Shishi * handle, FILE * fh, Shishi_asn1 priv)
354 return _shishi_save_data (handle, fh, priv, "PRIV");
358 * shishi_priv_to_file:
359 * @handle: shishi handle as allocated by shishi_init().
360 * @priv: PRIV to save.
361 * @filetype: input variable specifying type of file to be written,
362 * see Shishi_filetype.
363 * @filename: input variable with filename to write to.
365 * Write PRIV to file in specified TYPE. The file will be
366 * truncated if it exists.
368 * Return value: Returns SHISHI_OK iff successful.
371 shishi_priv_to_file (Shishi * handle, Shishi_asn1 priv,
372 int filetype, const char *filename)
374 FILE *fh;
375 int res;
377 if (VERBOSE (handle))
378 printf (_("Writing PRIV to %s...\n"), filename);
380 fh = fopen (filename, "w");
381 if (fh == NULL)
382 return SHISHI_FOPEN_ERROR;
384 if (VERBOSE (handle))
385 printf (_("Writing PRIV in %s format...\n"),
386 filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
388 if (filetype == SHISHI_FILETYPE_TEXT)
389 res = shishi_priv_print (handle, fh, priv);
390 else
391 res = shishi_priv_save (handle, fh, priv);
392 if (res != SHISHI_OK)
393 return res;
395 res = fclose (fh);
396 if (res != 0)
397 return SHISHI_IO_ERROR;
399 if (VERBOSE (handle))
400 printf (_("Writing PRIV to %s...done\n"), filename);
402 return SHISHI_OK;
406 * shishi_priv_parse:
407 * @handle: shishi handle as allocated by shishi_init().
408 * @fh: file handle open for reading.
409 * @priv: output variable with newly allocated PRIV.
411 * Read ASCII armored DER encoded PRIV from file and populate given
412 * variable.
414 * Return value: Returns SHISHI_OK iff successful.
417 shishi_priv_parse (Shishi * handle, FILE * fh, Shishi_asn1 * priv)
419 return _shishi_priv_input (handle, fh, priv, 0);
423 * shishi_priv_read:
424 * @handle: shishi handle as allocated by shishi_init().
425 * @fh: file handle open for reading.
426 * @priv: output variable with newly allocated PRIV.
428 * Read DER encoded PRIV from file and populate given variable.
430 * Return value: Returns SHISHI_OK iff successful.
433 shishi_priv_read (Shishi * handle, FILE * fh, Shishi_asn1 * priv)
435 return _shishi_priv_input (handle, fh, priv, 1);
439 * shishi_priv_from_file:
440 * @handle: shishi handle as allocated by shishi_init().
441 * @priv: output variable with newly allocated PRIV.
442 * @filetype: input variable specifying type of file to be read,
443 * see Shishi_filetype.
444 * @filename: input variable with filename to read from.
446 * Read PRIV from file in specified TYPE.
448 * Return value: Returns SHISHI_OK iff successful.
451 shishi_priv_from_file (Shishi * handle, Shishi_asn1 * priv,
452 int filetype, const char *filename)
454 int res;
455 FILE *fh;
457 if (VERBOSE (handle))
458 printf (_("Reading PRIV from %s...\n"), filename);
460 fh = fopen (filename, "r");
461 if (fh == NULL)
462 return SHISHI_FOPEN_ERROR;
464 if (VERBOSE (handle))
465 printf (_("Reading PRIV in %s format...\n"),
466 filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
468 if (filetype == SHISHI_FILETYPE_TEXT)
469 res = shishi_priv_parse (handle, fh, priv);
470 else
471 res = shishi_priv_read (handle, fh, priv);
472 if (res != SHISHI_OK)
473 return res;
475 res = fclose (fh);
476 if (res != 0)
477 return SHISHI_IO_ERROR;
479 if (VERBOSE (handle))
480 printf (_("Reading PRIV from %s...done\n"), filename);
482 return SHISHI_OK;
486 * shishi_priv_enc_part_etype:
487 * @handle: shishi handle as allocated by shishi_init().
488 * @priv: PRIV variable to get value from.
489 * @etype: output variable that holds the value.
491 * Extract PRIV.enc-part.etype.
493 * Return value: Returns SHISHI_OK iff successful.
496 shishi_priv_enc_part_etype (Shishi * handle,
497 Shishi_asn1 priv, int32_t * etype)
499 return shishi_asn1_read_int32 (handle, priv, "enc-part.etype", etype);
503 * shishi_priv_set_enc_part:
504 * @handle: shishi handle as allocated by shishi_init().
505 * @priv: priv as allocated by shishi_priv().
506 * @etype: input encryption type to store in PRIV.
507 * @encpart: input encrypted data to store in PRIV.
508 * @encpartlen: size of input encrypted data to store in PRIV.
510 * Store encrypted data in PRIV. The encrypted data is usually
511 * created by calling shishi_encrypt() on some application specific
512 * data using the key from the ticket that is being used. To save
513 * time, you may want to use shishi_priv_build() instead, which
514 * encryptes the data and calls this function in one step.
516 * Return value: Returns SHISHI_OK iff successful.
519 shishi_priv_set_enc_part (Shishi * handle,
520 Shishi_asn1 priv,
521 int32_t etype,
522 const char *encpart, size_t encpartlen)
524 int res;
526 res = shishi_asn1_write_integer (handle, priv, "enc-part.etype", etype);
527 if (res != SHISHI_OK)
528 return res;
530 res = shishi_asn1_write (handle, priv, "enc-part.cipher",
531 encpart, encpartlen);
532 if (res != SHISHI_OK)
533 return res;
535 return SHISHI_OK;
539 * shishi_encprivpart_user_data:
540 * @handle: shishi handle as allocated by shishi_init().
541 * @encprivpart: encprivpart as allocated by shishi_priv().
542 * @userdata: output array with newly allocated user data from KRB-PRIV.
543 * @userdatalen: output size of output user data buffer.
545 * Read user data value from KRB-PRIV. @userdata is allocated by this
546 * function, and it is the responsibility of caller to deallocate it.
548 * Return value: Returns SHISHI_OK iff successful.
551 shishi_encprivpart_user_data (Shishi * handle,
552 Shishi_asn1 encprivpart,
553 char **userdata, size_t * userdatalen)
555 int res;
557 res = shishi_asn1_read (handle, encprivpart, "user-data",
558 userdata, userdatalen);
559 if (res != SHISHI_OK)
560 return res;
562 return SHISHI_OK;
566 * shishi_encprivpart_set_user_data:
567 * @handle: shishi handle as allocated by shishi_init().
568 * @encprivpart: encprivpart as allocated by shishi_priv().
569 * @userdata: input user application to store in PRIV.
570 * @userdatalen: size of input user application to store in PRIV.
572 * Set the application data in PRIV.
574 * Return value: Returns SHISHI_OK iff successful.
577 shishi_encprivpart_set_user_data (Shishi * handle,
578 Shishi_asn1 encprivpart,
579 const char *userdata, size_t userdatalen)
581 int res;
583 res = shishi_asn1_write (handle, encprivpart, "user-data",
584 userdata, userdatalen);
585 if (res != SHISHI_OK)
586 return res;
588 return SHISHI_OK;
592 * shishi_priv_build:
593 * @priv: priv as allocated by shishi_priv().
594 * @key: key for session, used to encrypt data.
596 * Build checksum and set it in KRB-PRIV. Note that this follows RFC
597 * 1510bis and is incompatible with RFC 1510, although presumably few
598 * implementations use the RFC1510 algorithm.
600 * Return value: Returns SHISHI_OK iff successful.
603 shishi_priv_build (Shishi_priv * priv, Shishi_key * key)
605 int res;
606 char *buf;
607 size_t buflen;
608 char *der;
609 size_t derlen;
611 res = shishi_asn1_to_der (priv->handle, priv->encprivpart, &der, &derlen);
612 if (res != SHISHI_OK)
614 shishi_error_printf (priv->handle,
615 "Could not DER encode EncPrivPart: %s\n",
616 shishi_strerror (res));
617 return res;
620 res = shishi_encrypt (priv->handle, key, SHISHI_KEYUSAGE_KRB_PRIV,
621 der, derlen, &buf, &buflen);
623 free (der);
625 if (res != SHISHI_OK)
627 shishi_error_printf (priv->handle, "Cannot encrypt EncPrivPart.\n");
628 return res;
631 res = shishi_priv_set_enc_part (priv->handle, priv->priv,
632 shishi_key_type (key), buf, buflen);
633 if (res != SHISHI_OK)
634 return res;
636 return SHISHI_OK;
640 * shishi_priv_process:
641 * @priv: priv as allocated by shishi_priv().
642 * @key: key to use to decrypt EncPrivPart.
644 * Decrypt encrypted data in KRB-PRIV and set the EncPrivPart in the
645 * PRIV exchange.
647 * Return value: Returns SHISHI_OK iff successful,
648 * SHISHI_PRIV_BAD_KEYTYPE if an incompatible key type is used, or
649 * SHISHI_CRYPTO_ERROR if the actual decryption failed.
652 shishi_priv_process (Shishi_priv * priv, Shishi_key * key)
654 int res;
655 int i;
656 char *buf;
657 size_t buflen;
658 char *cipher;
659 size_t cipherlen;
660 int32_t etype;
662 res = shishi_priv_enc_part_etype (priv->handle, priv->priv, &etype);
663 if (res != SHISHI_OK)
664 return res;
666 if (etype != shishi_key_type (key))
667 return SHISHI_PRIV_BAD_KEYTYPE;
669 res = shishi_asn1_read (priv->handle, priv->priv, "enc-part.cipher",
670 &cipher, &cipherlen);
671 if (res != SHISHI_OK)
672 return res;
674 res = shishi_decrypt (priv->handle, key, SHISHI_KEYUSAGE_KRB_PRIV,
675 cipher, cipherlen, &buf, &buflen);
676 free (cipher);
677 if (res != SHISHI_OK)
679 shishi_error_printf (priv->handle,
680 "PRIV decryption failed, bad key?\n");
681 return res;
684 /* The crypto is so 1980; no length indicator. Trim off pad bytes
685 until we can parse it. */
686 for (i = 0; i < 8; i++)
688 if (VERBOSEASN1 (priv->handle))
689 printf ("Trying with %d pad in enckdcrep...\n", i);
691 priv->encprivpart = shishi_der2asn1_encprivpart (priv->handle, &buf[0],
692 buflen - i);
693 if (priv->encprivpart != NULL)
694 break;
697 free (buf);
699 if (priv->encprivpart == NULL)
701 shishi_error_printf (priv->handle, "Could not DER decode EncPrivPart. "
702 "Key probably correct (decrypt ok) though\n");
703 return SHISHI_ASN1_ERROR;
706 return SHISHI_OK;