Fix a2d.
[shishi.git] / lib / aprep.c
blob9f29d9167cfa076d733dd06baaa2ae2d64b0898a
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, const char *buf, int buflen)
257 char format[BUFSIZ];
258 int res;
260 res = shishi_asn1_write (handle, aprep, "enc-part.cipher",
261 buf, buflen);
262 if (res != SHISHI_OK)
263 return res;
265 sprintf (format, "%d", etype);
266 res = shishi_asn1_write (handle, aprep, "enc-part.etype", format, 0);
267 if (res != SHISHI_OK)
268 return res;
270 return SHISHI_OK;
274 shishi_aprep_enc_part_add (Shishi * handle,
275 Shishi_asn1 aprep,
276 Shishi_asn1 encticketpart,
277 Shishi_asn1 encapreppart)
279 int res;
280 char buf[BUFSIZ];
281 size_t buflen;
282 char der[BUFSIZ];
283 int derlen = BUFSIZ;
284 Shishi_key *key;
286 res = shishi_encticketpart_get_key (handle, encticketpart, &key);
287 if (res != SHISHI_OK)
288 return res;
290 res = shishi_a2d (handle, encapreppart, der, &derlen);
291 if (res != SHISHI_OK)
293 shishi_error_printf (handle, "Could not DER encode authenticator: %s\n",
294 shishi_strerror (res));
295 return !SHISHI_OK;
298 while ((derlen % 8) != 0)
300 der[derlen] = '\0';
301 derlen++;
304 buflen = BUFSIZ;
305 res = shishi_encrypt (handle, key, SHISHI_KEYUSAGE_ENCAPREPPART,
306 der, derlen, buf, &buflen);
307 if (res != SHISHI_OK)
309 shishi_error_printf (handle, "des_encrypt fail\n");
310 return res;
313 res = shishi_aprep_enc_part_set (handle, aprep, shishi_key_type (key),
314 buf, buflen);
316 return res;
320 shishi_aprep_enc_part_make (Shishi * handle,
321 Shishi_asn1 aprep,
322 Shishi_asn1 authenticator,
323 Shishi_asn1 encticketpart)
325 Shishi_asn1 encapreppart = NULL;
326 int res;
328 encapreppart = shishi_encapreppart (handle);
329 if (encapreppart == NULL)
331 shishi_error_printf (handle, "Could not create EncAPRepPart: %s\n",
332 shishi_strerror_details (handle));
333 return SHISHI_ASN1_ERROR;
336 res = shishi_encapreppart_time_copy (handle, encapreppart, authenticator);
337 if (res != SHISHI_OK)
339 shishi_error_printf (handle, "Could not copy time: %s\n",
340 shishi_strerror_details (handle));
341 return res;
344 res = shishi_aprep_enc_part_add (handle, aprep, encticketpart,
345 encapreppart);
346 if (res != SHISHI_OK)
348 shishi_error_printf (handle, "Could not add encapreppart: %s\n",
349 shishi_strerror_details (handle));
350 return res;
353 return SHISHI_OK;
357 * shishi_aprep_get_enc_part_etype:
358 * @handle: shishi handle as allocated by shishi_init().
359 * @aprep: AP-REP variable to get value from.
360 * @etype: output variable that holds the value.
362 * Extract AP-REP.enc-part.etype.
364 * Return value: Returns SHISHI_OK iff successful.
367 shishi_aprep_get_enc_part_etype (Shishi * handle, Shishi_asn1 aprep,
368 int *etype)
370 return shishi_asn1_integer_field (handle, aprep, etype,
371 "enc-part.etype");
375 shishi_aprep_decrypt (Shishi * handle,
376 Shishi_asn1 aprep,
377 Shishi_key * key,
378 int keyusage, Shishi_asn1 * encapreppart)
380 int res;
381 int i;
382 size_t buflen = BUFSIZ;
383 char buf[BUFSIZ];
384 char cipher[BUFSIZ];
385 int cipherlen;
386 int etype;
388 res = shishi_aprep_get_enc_part_etype (handle, aprep, &etype);
389 if (res != SHISHI_OK)
390 return res;
392 if (etype != shishi_key_type (key))
393 return SHISHI_APREP_BAD_KEYTYPE;
395 cipherlen = BUFSIZ;
396 res = shishi_asn1_field (handle, aprep, cipher, &cipherlen,
397 "enc-part.cipher");
398 if (res != SHISHI_OK)
399 return res;
401 res = shishi_decrypt (handle, key, keyusage, cipher, cipherlen,
402 buf, &buflen);
403 if (res != SHISHI_OK)
405 if (VERBOSE (handle))
406 printf ("decrypt failed: %s\n", shishi_strerror_details (handle));
407 shishi_error_printf (handle,
408 "decrypt fail, most likely wrong password\n");
409 return res;
412 /* The crypto is so 1980; no length indicator. Trim off pad bytes
413 until we can parse it. */
414 for (i = 0; i < 8; i++)
416 if (VERBOSEASN1 (handle))
417 printf ("Trying with %d pad in enckdcrep...\n", i);
419 *encapreppart = shishi_der2asn1_encapreppart (handle, &buf[0],
420 buflen - i);
421 if (*encapreppart != NULL)
422 break;
425 if (*encapreppart == NULL)
427 shishi_error_printf (handle, "Could not DER decode EncAPRepPart. "
428 "Password probably correct (decrypt ok) though\n");
429 return SHISHI_ASN1_ERROR;
432 return SHISHI_OK;
436 shishi_aprep_verify (Shishi * handle,
437 Shishi_asn1 authenticator, Shishi_asn1 encapreppart)
439 char authenticatorctime[GENERALIZEDTIME_TIME_LEN + 1];
440 char encapreppartctime[GENERALIZEDTIME_TIME_LEN + 1];
441 int authenticatorcusec;
442 int encapreppartcusec;
443 int res;
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_get (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_get (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);
486 if (authenticatorcusec != encapreppartcusec ||
487 strcmp (authenticatorctime, encapreppartctime) != 0)
488 return SHISHI_APREP_VERIFY_FAILED;
490 return SHISHI_OK;