Fix API.
[shishi.git] / lib / aprep.c
blob0d4668b2ecf323ae2b5d7ee1546a35df2a5b5b2a
1 /* aprep.c AP-REP functions
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 #define SHISHI_APREP_DEFAULT_PVNO "5"
25 #define SHISHI_APREP_DEFAULT_PVNO_LEN 0
26 #define SHISHI_APREP_DEFAULT_MSG_TYPE "15" /* KRB_AP_REP */
27 #define SHISHI_APREP_DEFAULT_MSG_TYPE_LEN 0
28 #define SHISHI_APREP_DEFAULT_ENC_PART_ETYPE "0"
29 #define SHISHI_APREP_DEFAULT_ENC_PART_ETYPE_LEN 0
30 #define SHISHI_APREP_DEFAULT_ENC_PART_KVNO "0"
31 #define SHISHI_APREP_DEFAULT_ENC_PART_KVNO_LEN 0
32 #define SHISHI_APREP_DEFAULT_ENC_PART_CIPHER ""
33 #define SHISHI_APREP_DEFAULT_ENC_PART_CIPHER_LEN 0
35 /**
36 * shishi_aprep:
37 * @handle: shishi handle as allocated by shishi_init().
39 * This function creates a new AP-REP, populated with some default
40 * values.
42 * Return value: Returns the authenticator or NULL on
43 * failure.
44 **/
45 Shishi_asn1
46 shishi_aprep (Shishi * handle)
48 Shishi_asn1 node;
49 int res;
51 node = shishi_asn1_aprep (handle);
52 if (!node)
53 return NULL;
55 res = shishi_asn1_write (handle, node, "pvno",
56 SHISHI_APREP_DEFAULT_PVNO,
57 SHISHI_APREP_DEFAULT_PVNO_LEN);
58 if (res != SHISHI_OK)
59 goto error;
61 res = shishi_asn1_write (handle, node, "msg-type",
62 SHISHI_APREP_DEFAULT_MSG_TYPE,
63 SHISHI_APREP_DEFAULT_MSG_TYPE_LEN);
64 if (res != SHISHI_OK)
65 goto error;
67 res = shishi_asn1_write (handle, node, "enc-part.etype",
68 SHISHI_APREP_DEFAULT_ENC_PART_ETYPE,
69 SHISHI_APREP_DEFAULT_ENC_PART_ETYPE_LEN);
70 if (res != SHISHI_OK)
71 goto error;
73 res = shishi_asn1_write (handle, node, "enc-part.kvno",
74 SHISHI_APREP_DEFAULT_ENC_PART_KVNO,
75 SHISHI_APREP_DEFAULT_ENC_PART_KVNO_LEN);
76 if (res != SHISHI_OK)
77 goto error;
79 res = shishi_asn1_write (handle, node, "enc-part.cipher",
80 SHISHI_APREP_DEFAULT_ENC_PART_CIPHER,
81 SHISHI_APREP_DEFAULT_ENC_PART_CIPHER_LEN);
82 if (res != SHISHI_OK)
83 goto error;
85 return node;
87 error:
88 shishi_asn1_done (handle, node);
89 return NULL;
92 /**
93 * shishi_aprep_print:
94 * @handle: shishi handle as allocated by shishi_init().
95 * @fh: file handle open for writing.
96 * @aprep: AP-REP to print.
98 * Print ASCII armored DER encoding of AP-REP to file.
100 * Return value: Returns SHISHI_OK iff successful.
103 shishi_aprep_print (Shishi * handle, FILE * fh, Shishi_asn1 aprep)
105 return _shishi_print_armored_data (handle, fh, aprep, "AP-REP", NULL);
109 * shishi_aprep_save:
110 * @handle: shishi handle as allocated by shishi_init().
111 * @fh: file handle open for writing.
112 * @aprep: AP-REP to save.
114 * Save DER encoding of AP-REP to file.
116 * Return value: Returns SHISHI_OK iff successful.
119 shishi_aprep_save (Shishi * handle, FILE * fh, Shishi_asn1 aprep)
121 return _shishi_save_data (handle, fh, aprep, "AP-REP");
125 * shishi_aprep_to_file:
126 * @handle: shishi handle as allocated by shishi_init().
127 * @aprep: AP-REP to save.
128 * @filetype: input variable specifying type of file to be written,
129 * see Shishi_filetype.
130 * @filename: input variable with filename to write to.
132 * Write AP-REP to file in specified TYPE. The file will be
133 * truncated if it exists.
135 * Return value: Returns SHISHI_OK iff successful.
138 shishi_aprep_to_file (Shishi * handle, Shishi_asn1 aprep,
139 int filetype, char *filename)
141 FILE *fh;
142 int res;
144 if (VERBOSE (handle))
145 printf (_("Writing AP-REP to %s...\n"), filename);
147 fh = fopen (filename, "w");
148 if (fh == NULL)
149 return SHISHI_FOPEN_ERROR;
151 if (VERBOSE (handle))
152 printf (_("Writing AP-REP in %s format...\n"),
153 filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
155 if (filetype == SHISHI_FILETYPE_TEXT)
156 res = shishi_aprep_print (handle, fh, aprep);
157 else
158 res = shishi_aprep_save (handle, fh, aprep);
159 if (res != SHISHI_OK)
160 return res;
162 res = fclose (fh);
163 if (res != 0)
164 return SHISHI_FCLOSE_ERROR;
166 if (VERBOSE (handle))
167 printf (_("Writing AP-REP to %s...done\n"), filename);
169 return SHISHI_OK;
173 * shishi_aprep_parse:
174 * @handle: shishi handle as allocated by shishi_init().
175 * @fh: file handle open for reading.
176 * @aprep: output variable with newly allocated AP-REP.
178 * Read ASCII armored DER encoded AP-REP from file and populate given
179 * variable.
181 * Return value: Returns SHISHI_OK iff successful.
184 shishi_aprep_parse (Shishi * handle, FILE * fh, Shishi_asn1 * aprep)
186 return _shishi_aprep_input (handle, fh, aprep, 0);
190 * shishi_aprep_read:
191 * @handle: shishi handle as allocated by shishi_init().
192 * @fh: file handle open for reading.
193 * @aprep: output variable with newly allocated AP-REP.
195 * Read DER encoded AP-REP from file and populate given variable.
197 * Return value: Returns SHISHI_OK iff successful.
200 shishi_aprep_read (Shishi * handle, FILE * fh, Shishi_asn1 * aprep)
202 return _shishi_aprep_input (handle, fh, aprep, 1);
206 * shishi_aprep_from_file:
207 * @handle: shishi handle as allocated by shishi_init().
208 * @aprep: output variable with newly allocated AP-REP.
209 * @filetype: input variable specifying type of file to be read,
210 * see Shishi_filetype.
211 * @filename: input variable with filename to read from.
213 * Read AP-REP from file in specified TYPE.
215 * Return value: Returns SHISHI_OK iff successful.
218 shishi_aprep_from_file (Shishi * handle, Shishi_asn1 * aprep,
219 int filetype, char *filename)
221 int res;
222 FILE *fh;
224 if (VERBOSE (handle))
225 printf (_("Reading AP-REP from %s...\n"), filename);
227 fh = fopen (filename, "r");
228 if (fh == NULL)
229 return SHISHI_FOPEN_ERROR;
231 if (VERBOSE (handle))
232 printf (_("Reading AP-REP in %s format...\n"),
233 filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
235 if (filetype == SHISHI_FILETYPE_TEXT)
236 res = shishi_aprep_parse (handle, fh, aprep);
237 else
238 res = shishi_aprep_read (handle, fh, aprep);
239 if (res != SHISHI_OK)
240 return res;
242 res = fclose (fh);
243 if (res != 0)
244 return SHISHI_FCLOSE_ERROR;
246 if (VERBOSE (handle))
247 printf (_("Reading AP-REP from %s...done\n"), filename);
249 return SHISHI_OK;
253 shishi_aprep_enc_part_set (Shishi * handle,
254 Shishi_asn1 aprep,
255 int etype,
256 const char *buf, size_t buflen)
258 int res;
260 res = shishi_asn1_write (handle, aprep, "enc-part.cipher", buf, buflen);
261 if (res != SHISHI_OK)
262 return res;
264 res = shishi_asn1_write_integer (handle, aprep, "enc-part.etype", etype);
265 if (res != SHISHI_OK)
266 return res;
268 return SHISHI_OK;
272 shishi_aprep_enc_part_add (Shishi * handle,
273 Shishi_asn1 aprep,
274 Shishi_asn1 encticketpart,
275 Shishi_asn1 encapreppart)
277 int res;
278 char *buf;
279 size_t buflen;
280 char *der;
281 size_t derlen;
282 Shishi_key *key;
284 res = shishi_encticketpart_get_key (handle, encticketpart, &key);
285 if (res != SHISHI_OK)
286 return res;
288 res = shishi_new_a2d (handle, encapreppart, &der, &derlen);
289 if (res != SHISHI_OK)
291 shishi_error_printf (handle, "Could not DER encode authenticator: %s\n",
292 shishi_strerror (res));
293 return !SHISHI_OK;
296 while ((derlen % 8) != 0)
298 der[derlen] = '\0';
299 derlen++;
302 res = shishi_encrypt (handle, key, SHISHI_KEYUSAGE_ENCAPREPPART,
303 der, derlen, &buf, &buflen);
305 free (der);
307 if (res != SHISHI_OK)
309 shishi_error_printf (handle, "APRep encryption failed\n");
310 return res;
313 res = shishi_aprep_enc_part_set (handle, aprep, shishi_key_type (key),
314 buf, buflen);
316 free (buf);
318 return res;
322 shishi_aprep_enc_part_make (Shishi * handle,
323 Shishi_asn1 aprep,
324 Shishi_asn1 authenticator,
325 Shishi_asn1 encticketpart)
327 Shishi_asn1 encapreppart = NULL;
328 int res;
330 encapreppart = shishi_encapreppart (handle);
331 if (encapreppart == NULL)
333 shishi_error_printf (handle, "Could not create EncAPRepPart: %s\n",
334 shishi_error (handle));
335 return SHISHI_ASN1_ERROR;
338 res = shishi_encapreppart_time_copy (handle, encapreppart, authenticator);
339 if (res != SHISHI_OK)
341 shishi_error_printf (handle, "Could not copy time: %s\n",
342 shishi_error (handle));
343 return res;
346 res = shishi_aprep_enc_part_add (handle, aprep, encticketpart,
347 encapreppart);
348 if (res != SHISHI_OK)
350 shishi_error_printf (handle, "Could not add encapreppart: %s\n",
351 shishi_error (handle));
352 return res;
355 return SHISHI_OK;
359 * shishi_aprep_get_enc_part_etype:
360 * @handle: shishi handle as allocated by shishi_init().
361 * @aprep: AP-REP variable to get value from.
362 * @etype: output variable that holds the value.
364 * Extract AP-REP.enc-part.etype.
366 * Return value: Returns SHISHI_OK iff successful.
369 shishi_aprep_get_enc_part_etype (Shishi * handle,
370 Shishi_asn1 aprep, int32_t * etype)
372 return shishi_asn1_read_int32 (handle, aprep, "enc-part.etype", etype);
376 shishi_aprep_decrypt (Shishi * handle,
377 Shishi_asn1 aprep,
378 Shishi_key * key,
379 int keyusage, Shishi_asn1 * encapreppart)
381 int res;
382 int i;
383 char *buf;
384 size_t buflen;
385 char *cipher;
386 size_t cipherlen;
387 int etype;
389 res = shishi_aprep_get_enc_part_etype (handle, aprep, &etype);
390 if (res != SHISHI_OK)
391 return res;
393 if (etype != shishi_key_type (key))
394 return SHISHI_APREP_BAD_KEYTYPE;
396 res = shishi_asn1_read2 (handle, aprep, "enc-part.cipher",
397 &cipher, &cipherlen);
398 if (res != SHISHI_OK)
399 return res;
401 res = shishi_decrypt (handle, key, keyusage, cipher, cipherlen,
402 &buf, &buflen);
403 free (cipher);
404 if (res != SHISHI_OK)
406 shishi_error_printf (handle,
407 "APRep decryption failed, wrong password?\n");
408 return res;
411 /* The crypto is so 1980; no length indicator. Trim off pad bytes
412 until we can parse it. */
413 for (i = 0; i < 8; i++)
415 if (VERBOSEASN1 (handle))
416 printf ("Trying with %d pad in enckdcrep...\n", i);
418 *encapreppart = shishi_der2asn1_encapreppart (handle, &buf[0],
419 buflen - i);
420 if (*encapreppart != NULL)
421 break;
424 if (*encapreppart == NULL)
426 shishi_error_printf (handle, "Could not DER decode EncAPRepPart. "
427 "Password probably correct (decrypt ok) though\n");
428 return SHISHI_ASN1_ERROR;
431 return SHISHI_OK;
435 shishi_aprep_verify (Shishi * handle,
436 Shishi_asn1 authenticator, Shishi_asn1 encapreppart)
438 char *authenticatorctime;
439 char *encapreppartctime;
440 int authenticatorcusec;
441 int encapreppartcusec;
442 int res;
443 int different;
446 3.2.5. Receipt of KRB_AP_REP message
448 If a KRB_AP_REP message is returned, the client uses the session key from
449 the credentials obtained for the server[3.10] to decrypt the message, and
450 verifies that the timestamp and microsecond fields match those in the
451 Authenticator it sent to the server. If they match, then the client is
452 assured that the server is genuine. The sequence number and subkey (if
453 present) are retained for later use.
457 res = shishi_authenticator_ctime (handle, authenticator,
458 &authenticatorctime);
459 if (res != SHISHI_OK)
460 return res;
462 res = shishi_authenticator_cusec_get (handle, authenticator,
463 &authenticatorcusec);
464 if (res != SHISHI_OK)
465 return res;
467 res = shishi_encapreppart_ctime (handle, encapreppart,
468 &encapreppartctime);
469 if (res != SHISHI_OK)
470 return res;
472 res = shishi_encapreppart_cusec_get (handle, encapreppart,
473 &encapreppartcusec);
474 if (res != SHISHI_OK)
475 return res;
477 if (VERBOSE (handle))
479 printf ("authenticator cusec %08x ctime %s\n", authenticatorcusec,
480 authenticatorctime);
481 printf ("encapreppart cusec %08x ctime %s\n", encapreppartcusec,
482 encapreppartctime);
485 different = authenticatorcusec != encapreppartcusec ||
486 strcmp (authenticatorctime, encapreppartctime) != 0;
488 free (authenticatorctime);
489 free (encapreppartctime);
491 if (different)
492 return SHISHI_APREP_VERIFY_FAILED;
494 return SHISHI_OK;