1 /* priv.c --- Application data privacy protection.
2  * Copyright (C) 2002-2013 Simon Josefsson
3  *
4  * This file is part of Shishi.
5  *
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.
10  *
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.
15  *
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
20  *
21  */
22 
23 #include "internal.h"
24 
25 /* Get _shishi_print_armored_data, etc. */
26 #include "diskio.h"
27 
28 struct Shishi_priv
29 {
30   Shishi *handle;
31   Shishi_key *key;
32   Shishi_asn1 priv;
33   Shishi_asn1 encprivpart;
34   unsigned long seqnumber;
35 };
36 
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
41  *
42  * Create a new PRIV exchange.
43  *
44  * Return value: Returns SHISHI_OK iff successful.
45  **/
46 int
shishi_priv(Shishi * handle,Shishi_priv ** priv)47 shishi_priv (Shishi * handle, Shishi_priv ** priv)
48 {
49   Shishi_priv *lpriv;
50   struct timeval tv;
51   char *usec;
52   int rc;
53 
54   *priv = xcalloc (1, sizeof (**priv));
55   lpriv = *priv;
56 
57   lpriv->handle = handle;
58   rc = shishi_key (handle, &lpriv->key);
59   if (rc != SHISHI_OK)
60     return rc;
61 
62   lpriv->priv = shishi_asn1_priv (handle);
63   if (lpriv->priv == NULL)
64     return SHISHI_ASN1_ERROR;
65 
66   rc = shishi_asn1_write (handle, lpriv->priv, "pvno", "5", 0);
67   if (rc != SHISHI_OK)
68     return rc;
69 
70   rc = shishi_asn1_write (handle, lpriv->priv, "msg-type", "21", 0);
71   if (rc != SHISHI_OK)
72     return rc;
73 
74   rc = shishi_asn1_write (handle, lpriv->priv, "enc-part.kvno", "0", 0);
75   if (rc != SHISHI_OK)
76     return rc;
77 
78   lpriv->encprivpart = shishi_asn1_encprivpart (handle);
79   if (lpriv->priv == NULL)
80     return SHISHI_ASN1_ERROR;
81 
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;
86 
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;
95 
96   rc = shishi_asn1_write (handle, lpriv->encprivpart, "seq-number", NULL, 0);
97   if (rc != SHISHI_OK)
98     return rc;
99 
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;
105 
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;
111 
112   rc = shishi_asn1_write (handle, lpriv->encprivpart, "r-address", NULL, 0);
113   if (rc != SHISHI_OK)
114     return rc;
115 
116   return SHISHI_OK;
117 }
118 
119 /**
120  * shishi_priv_done:
121  * @priv: structure that holds information about PRIV exchange
122  *
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.
126  **/
127 void
shishi_priv_done(Shishi_priv * priv)128 shishi_priv_done (Shishi_priv * priv)
129 {
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);
134 }
135 
136 /**
137  * shishi_priv_key:
138  * @priv: structure that holds information about PRIV exchange
139  *
140  * Get key from PRIV exchange.
141  *
142  * Return value: Returns the key used in the PRIV exchange, or NULL if
143  *               not yet set or an error occured.
144  **/
145 Shishi_key *
shishi_priv_key(Shishi_priv * priv)146 shishi_priv_key (Shishi_priv * priv)
147 {
148   return priv->key;
149 }
150 
151 /**
152  * shishi_priv_key_set:
153  * @priv: structure that holds information about PRIV exchange
154  * @key: key to store in PRIV.
155  *
156  * Set the Key in the PRIV exchange.
157  **/
158 void
shishi_priv_key_set(Shishi_priv * priv,Shishi_key * key)159 shishi_priv_key_set (Shishi_priv * priv, Shishi_key * key)
160 {
161   shishi_key_copy (priv->key, key);
162 }
163 
164 /**
165  * shishi_priv_priv:
166  * @priv: structure that holds information about PRIV exchange
167  *
168  * Get ASN.1 PRIV structure in PRIV exchange.
169  *
170  * Return value: Returns the ASN.1 priv in the PRIV exchange, or NULL if
171  *               not yet set or an error occured.
172  **/
173 Shishi_asn1
shishi_priv_priv(Shishi_priv * priv)174 shishi_priv_priv (Shishi_priv * priv)
175 {
176   return priv->priv;
177 }
178 
179 /**
180  * shishi_priv_priv_set:
181  * @priv: structure that holds information about PRIV exchange
182  * @asn1priv: KRB-PRIV to store in PRIV exchange.
183  *
184  * Set the KRB-PRIV in the PRIV exchange.
185  **/
186 void
shishi_priv_priv_set(Shishi_priv * priv,Shishi_asn1 asn1priv)187 shishi_priv_priv_set (Shishi_priv * priv, Shishi_asn1 asn1priv)
188 {
189   if (priv->priv)
190     shishi_asn1_done (priv->handle, priv->priv);
191   priv->priv = asn1priv;
192 }
193 
194 /**
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.
199  *
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.
203  *
204  * Return value: Returns SHISHI_OK iff successful.
205  **/
206 int
shishi_priv_priv_der(Shishi_priv * priv,char ** out,size_t * outlen)207 shishi_priv_priv_der (Shishi_priv * priv, char **out, size_t * outlen)
208 {
209   int rc;
210 
211   rc = shishi_asn1_to_der (priv->handle, priv->priv, out, outlen);
212   if (rc != SHISHI_OK)
213     return rc;
214 
215   return SHISHI_OK;
216 }
217 
218 /**
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.
223  *
224  * DER decode KRB-PRIV and set it PRIV exchange.  If decoding fails, the
225  * KRB-PRIV in the PRIV exchange remains.
226  *
227  * Return value: Returns SHISHI_OK.
228  **/
229 int
shishi_priv_priv_der_set(Shishi_priv * priv,char * der,size_t derlen)230 shishi_priv_priv_der_set (Shishi_priv * priv, char *der, size_t derlen)
231 {
232   Shishi_asn1 asn1priv;
233 
234   asn1priv = shishi_der2asn1_priv (priv->handle, der, derlen);
235 
236   if (asn1priv == NULL)
237     return SHISHI_ASN1_ERROR;
238 
239   shishi_priv_priv_set (priv, asn1priv);
240 
241   return SHISHI_OK;
242 }
243 
244 /**
245  * shishi_priv_encprivpart:
246  * @priv: structure that holds information about PRIV exchange
247  *
248  * Get ASN.1 EncPrivPart structure from PRIV exchange.
249  *
250  * Return value: Returns the ASN.1 encprivpart in the PRIV exchange, or NULL if
251  *               not yet set or an error occured.
252  **/
253 Shishi_asn1
shishi_priv_encprivpart(Shishi_priv * priv)254 shishi_priv_encprivpart (Shishi_priv * priv)
255 {
256   return priv->encprivpart;
257 }
258 
259 /**
260  * shishi_priv_encprivpart_set:
261  * @priv: structure that holds information about PRIV exchange
262  * @asn1encprivpart: ENCPRIVPART to store in PRIV exchange.
263  *
264  * Set the ENCPRIVPART in the PRIV exchange.
265  **/
266 void
shishi_priv_encprivpart_set(Shishi_priv * priv,Shishi_asn1 asn1encprivpart)267 shishi_priv_encprivpart_set (Shishi_priv * priv, Shishi_asn1 asn1encprivpart)
268 {
269   if (priv->encprivpart)
270     shishi_asn1_done (priv->handle, priv->encprivpart);
271   priv->encprivpart = asn1encprivpart;
272 }
273 
274 /**
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.
279  *
280  * DER encode ENCPRIVPART structure.  @out is allocated by this
281  * function, and it is the responsibility of caller to deallocate it.
282  *
283  * Return value: Returns SHISHI_OK iff successful.
284  **/
285 int
shishi_priv_encprivpart_der(Shishi_priv * priv,char ** out,size_t * outlen)286 shishi_priv_encprivpart_der (Shishi_priv * priv, char **out, size_t * outlen)
287 {
288   int rc;
289 
290   rc = shishi_asn1_to_der (priv->handle, priv->encprivpart, out, outlen);
291   if (rc != SHISHI_OK)
292     return rc;
293 
294   return SHISHI_OK;
295 }
296 
297 /**
298  * shishi_priv_encprivpart_der_set:
299  * @priv: priv as allocated by shishi_priv().
300  * @der: input array with DER encoded ENCPRIVPART.
301  * @derlen: length of input array with DER encoded ENCPRIVPART.
302  *
303  * DER decode ENCPRIVPART and set it PRIV exchange.  If decoding
304  * fails, the ENCPRIVPART in the PRIV exchange remains.
305  *
306  * Return value: Returns SHISHI_OK.
307  **/
308 int
shishi_priv_encprivpart_der_set(Shishi_priv * priv,char * der,size_t derlen)309 shishi_priv_encprivpart_der_set (Shishi_priv * priv, char *der, size_t derlen)
310 {
311   Shishi_asn1 asn1encprivpart;
312 
313   asn1encprivpart = shishi_der2asn1_encprivpart (priv->handle, der, derlen);
314 
315   if (asn1encprivpart == NULL)
316     return SHISHI_ASN1_ERROR;
317 
318   shishi_priv_encprivpart_set (priv, asn1encprivpart);
319 
320   return SHISHI_OK;
321 }
322 
323 /**
324  * shishi_priv_print:
325  * @handle: shishi handle as allocated by shishi_init().
326  * @fh: file handle open for writing.
327  * @priv: PRIV to print.
328  *
329  * Print ASCII armored DER encoding of PRIV to file.
330  *
331  * Return value: Returns SHISHI_OK iff successful.
332  **/
333 int
shishi_priv_print(Shishi * handle,FILE * fh,Shishi_asn1 priv)334 shishi_priv_print (Shishi * handle, FILE * fh, Shishi_asn1 priv)
335 {
336   return _shishi_print_armored_data (handle, fh, priv, "KRB-PRIV", NULL);
337 }
338 
339 /**
340  * shishi_priv_save:
341  * @handle: shishi handle as allocated by shishi_init().
342  * @fh: file handle open for writing.
343  * @priv: PRIV to save.
344  *
345  * Save DER encoding of PRIV to file.
346  *
347  * Return value: Returns SHISHI_OK iff successful.
348  **/
349 int
shishi_priv_save(Shishi * handle,FILE * fh,Shishi_asn1 priv)350 shishi_priv_save (Shishi * handle, FILE * fh, Shishi_asn1 priv)
351 {
352   return _shishi_save_data (handle, fh, priv, "PRIV");
353 }
354 
355 /**
356  * shishi_priv_to_file:
357  * @handle: shishi handle as allocated by shishi_init().
358  * @priv: PRIV to save.
359  * @filetype: input variable specifying type of file to be written,
360  *            see Shishi_filetype.
361  * @filename: input variable with filename to write to.
362  *
363  * Write PRIV to file in specified TYPE.  The file will be
364  * truncated if it exists.
365  *
366  * Return value: Returns SHISHI_OK iff successful.
367  **/
368 int
shishi_priv_to_file(Shishi * handle,Shishi_asn1 priv,int filetype,const char * filename)369 shishi_priv_to_file (Shishi * handle, Shishi_asn1 priv,
370 		     int filetype, const char *filename)
371 {
372   FILE *fh;
373   int res;
374 
375   if (VERBOSE (handle))
376     printf (_("Writing PRIV to %s...\n"), filename);
377 
378   fh = fopen (filename, "w");
379   if (fh == NULL)
380     return SHISHI_FOPEN_ERROR;
381 
382   if (VERBOSE (handle))
383     printf (_("Writing PRIV in %s format...\n"),
384 	    filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
385 
386   if (filetype == SHISHI_FILETYPE_TEXT)
387     res = shishi_priv_print (handle, fh, priv);
388   else
389     res = shishi_priv_save (handle, fh, priv);
390   if (res != SHISHI_OK)
391     return res;
392 
393   res = fclose (fh);
394   if (res != 0)
395     return SHISHI_IO_ERROR;
396 
397   if (VERBOSE (handle))
398     printf (_("Writing PRIV to %s...done\n"), filename);
399 
400   return SHISHI_OK;
401 }
402 
403 /**
404  * shishi_priv_parse:
405  * @handle: shishi handle as allocated by shishi_init().
406  * @fh: file handle open for reading.
407  * @priv: output variable with newly allocated PRIV.
408  *
409  * Read ASCII armored DER encoded PRIV from file and populate given
410  * variable.
411  *
412  * Return value: Returns SHISHI_OK iff successful.
413  **/
414 int
shishi_priv_parse(Shishi * handle,FILE * fh,Shishi_asn1 * priv)415 shishi_priv_parse (Shishi * handle, FILE * fh, Shishi_asn1 * priv)
416 {
417   return _shishi_priv_input (handle, fh, priv, 0);
418 }
419 
420 /**
421  * shishi_priv_read:
422  * @handle: shishi handle as allocated by shishi_init().
423  * @fh: file handle open for reading.
424  * @priv: output variable with newly allocated PRIV.
425  *
426  * Read DER encoded PRIV from file and populate given variable.
427  *
428  * Return value: Returns SHISHI_OK iff successful.
429  **/
430 int
shishi_priv_read(Shishi * handle,FILE * fh,Shishi_asn1 * priv)431 shishi_priv_read (Shishi * handle, FILE * fh, Shishi_asn1 * priv)
432 {
433   return _shishi_priv_input (handle, fh, priv, 1);
434 }
435 
436 /**
437  * shishi_priv_from_file:
438  * @handle: shishi handle as allocated by shishi_init().
439  * @priv: output variable with newly allocated PRIV.
440  * @filetype: input variable specifying type of file to be read,
441  *            see Shishi_filetype.
442  * @filename: input variable with filename to read from.
443  *
444  * Read PRIV from file in specified TYPE.
445  *
446  * Return value: Returns SHISHI_OK iff successful.
447  **/
448 int
shishi_priv_from_file(Shishi * handle,Shishi_asn1 * priv,int filetype,const char * filename)449 shishi_priv_from_file (Shishi * handle, Shishi_asn1 * priv,
450 		       int filetype, const char *filename)
451 {
452   int res;
453   FILE *fh;
454 
455   if (VERBOSE (handle))
456     printf (_("Reading PRIV from %s...\n"), filename);
457 
458   fh = fopen (filename, "r");
459   if (fh == NULL)
460     return SHISHI_FOPEN_ERROR;
461 
462   if (VERBOSE (handle))
463     printf (_("Reading PRIV in %s format...\n"),
464 	    filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
465 
466   if (filetype == SHISHI_FILETYPE_TEXT)
467     res = shishi_priv_parse (handle, fh, priv);
468   else
469     res = shishi_priv_read (handle, fh, priv);
470   if (res != SHISHI_OK)
471     return res;
472 
473   res = fclose (fh);
474   if (res != 0)
475     return SHISHI_IO_ERROR;
476 
477   if (VERBOSE (handle))
478     printf (_("Reading PRIV from %s...done\n"), filename);
479 
480   return SHISHI_OK;
481 }
482 
483 /**
484  * shishi_priv_enc_part_etype:
485  * @handle: shishi handle as allocated by shishi_init().
486  * @priv: PRIV variable to get value from.
487  * @etype: output variable that holds the value.
488  *
489  * Extract PRIV.enc-part.etype.
490  *
491  * Return value: Returns SHISHI_OK iff successful.
492  **/
493 int
shishi_priv_enc_part_etype(Shishi * handle,Shishi_asn1 priv,int32_t * etype)494 shishi_priv_enc_part_etype (Shishi * handle,
495 			    Shishi_asn1 priv, int32_t * etype)
496 {
497   return shishi_asn1_read_int32 (handle, priv, "enc-part.etype", etype);
498 }
499 
500 /**
501  * shishi_priv_set_enc_part:
502  * @handle: shishi handle as allocated by shishi_init().
503  * @priv: priv as allocated by shishi_priv().
504  * @etype: input encryption type to store in PRIV.
505  * @encpart: input encrypted data to store in PRIV.
506  * @encpartlen: size of input encrypted data to store in PRIV.
507  *
508  * Store encrypted data in PRIV.  The encrypted data is usually
509  * created by calling shishi_encrypt() on some application specific
510  * data using the key from the ticket that is being used.  To save
511  * time, you may want to use shishi_priv_build() instead, which
512  * encryptes the data and calls this function in one step.
513  *
514  * Return value: Returns SHISHI_OK iff successful.
515  **/
516 int
shishi_priv_set_enc_part(Shishi * handle,Shishi_asn1 priv,int32_t etype,const char * encpart,size_t encpartlen)517 shishi_priv_set_enc_part (Shishi * handle,
518 			  Shishi_asn1 priv,
519 			  int32_t etype,
520 			  const char *encpart, size_t encpartlen)
521 {
522   int res;
523 
524   res = shishi_asn1_write_integer (handle, priv, "enc-part.etype", etype);
525   if (res != SHISHI_OK)
526     return res;
527 
528   res = shishi_asn1_write (handle, priv, "enc-part.cipher",
529 			   encpart, encpartlen);
530   if (res != SHISHI_OK)
531     return res;
532 
533   return SHISHI_OK;
534 }
535 
536 /**
537  * shishi_encprivpart_user_data:
538  * @handle: shishi handle as allocated by shishi_init().
539  * @encprivpart: encprivpart as allocated by shishi_priv().
540  * @userdata: output array with newly allocated user data from KRB-PRIV.
541  * @userdatalen: output size of output user data buffer.
542  *
543  * Read user data value from KRB-PRIV.  @userdata is allocated by this
544  * function, and it is the responsibility of caller to deallocate it.
545  *
546  * Return value: Returns SHISHI_OK iff successful.
547  **/
548 int
shishi_encprivpart_user_data(Shishi * handle,Shishi_asn1 encprivpart,char ** userdata,size_t * userdatalen)549 shishi_encprivpart_user_data (Shishi * handle,
550 			      Shishi_asn1 encprivpart,
551 			      char **userdata, size_t * userdatalen)
552 {
553   int res;
554 
555   res = shishi_asn1_read (handle, encprivpart, "user-data",
556 			  userdata, userdatalen);
557   if (res != SHISHI_OK)
558     return res;
559 
560   return SHISHI_OK;
561 }
562 
563 /**
564  * shishi_encprivpart_set_user_data:
565  * @handle: shishi handle as allocated by shishi_init().
566  * @encprivpart: encprivpart as allocated by shishi_priv().
567  * @userdata: input user application to store in PRIV.
568  * @userdatalen: size of input user application to store in PRIV.
569  *
570  * Set the application data in PRIV.
571  *
572  * Return value: Returns SHISHI_OK iff successful.
573  **/
574 int
shishi_encprivpart_set_user_data(Shishi * handle,Shishi_asn1 encprivpart,const char * userdata,size_t userdatalen)575 shishi_encprivpart_set_user_data (Shishi * handle,
576 				  Shishi_asn1 encprivpart,
577 				  const char *userdata, size_t userdatalen)
578 {
579   int res;
580 
581   res = shishi_asn1_write (handle, encprivpart, "user-data",
582 			   userdata, userdatalen);
583   if (res != SHISHI_OK)
584     return res;
585 
586   return SHISHI_OK;
587 }
588 
589 /**
590  * shishi_priv_build:
591  * @priv: priv as allocated by shishi_priv().
592  * @key: key for session, used to encrypt data.
593  *
594  * Build checksum and set it in KRB-PRIV.  Note that this follows RFC
595  * 1510bis and is incompatible with RFC 1510, although presumably few
596  * implementations use the RFC1510 algorithm.
597  *
598  * Return value: Returns SHISHI_OK iff successful.
599  **/
600 int
shishi_priv_build(Shishi_priv * priv,Shishi_key * key)601 shishi_priv_build (Shishi_priv * priv, Shishi_key * key)
602 {
603   int res;
604   char *buf;
605   size_t buflen;
606   char *der;
607   size_t derlen;
608 
609   res = shishi_asn1_to_der (priv->handle, priv->encprivpart, &der, &derlen);
610   if (res != SHISHI_OK)
611     {
612       shishi_error_printf (priv->handle,
613 			   "Could not DER encode EncPrivPart: %s\n",
614 			   shishi_strerror (res));
615       return res;
616     }
617 
618   res = shishi_encrypt (priv->handle, key, SHISHI_KEYUSAGE_KRB_PRIV,
619 			der, derlen, &buf, &buflen);
620 
621   free (der);
622 
623   if (res != SHISHI_OK)
624     {
625       shishi_error_printf (priv->handle, "Cannot encrypt EncPrivPart.\n");
626       return res;
627     }
628 
629   res = shishi_priv_set_enc_part (priv->handle, priv->priv,
630 				  shishi_key_type (key), buf, buflen);
631   if (res != SHISHI_OK)
632     return res;
633 
634   return SHISHI_OK;
635 }
636 
637 /**
638  * shishi_priv_process:
639  * @priv: priv as allocated by shishi_priv().
640  * @key: key to use to decrypt EncPrivPart.
641  *
642  * Decrypt encrypted data in KRB-PRIV and set the EncPrivPart in the
643  * PRIV exchange.
644  *
645  * Return value: Returns SHISHI_OK iff successful,
646  *   SHISHI_PRIV_BAD_KEYTYPE if an incompatible key type is used, or
647  *   SHISHI_CRYPTO_ERROR if the actual decryption failed.
648  **/
649 int
shishi_priv_process(Shishi_priv * priv,Shishi_key * key)650 shishi_priv_process (Shishi_priv * priv, Shishi_key * key)
651 {
652   int res;
653   int i;
654   char *buf;
655   size_t buflen;
656   char *cipher;
657   size_t cipherlen;
658   int32_t etype;
659 
660   res = shishi_priv_enc_part_etype (priv->handle, priv->priv, &etype);
661   if (res != SHISHI_OK)
662     return res;
663 
664   if (etype != shishi_key_type (key))
665     return SHISHI_PRIV_BAD_KEYTYPE;
666 
667   res = shishi_asn1_read (priv->handle, priv->priv, "enc-part.cipher",
668 			  &cipher, &cipherlen);
669   if (res != SHISHI_OK)
670     return res;
671 
672   res = shishi_decrypt (priv->handle, key, SHISHI_KEYUSAGE_KRB_PRIV,
673 			cipher, cipherlen, &buf, &buflen);
674   free (cipher);
675   if (res != SHISHI_OK)
676     {
677       shishi_error_printf (priv->handle,
678 			   "PRIV decryption failed, bad key?\n");
679       return res;
680     }
681 
682   /* The crypto is so 1980; no length indicator. Trim off pad bytes
683      until we can parse it. */
684   for (i = 0; i < 8; i++)
685     {
686       if (VERBOSEASN1 (priv->handle))
687 	printf ("Trying with %d pad in enckdcrep...\n", i);
688 
689       priv->encprivpart = shishi_der2asn1_encprivpart (priv->handle, &buf[0],
690 						       buflen - i);
691       if (priv->encprivpart != NULL)
692 	break;
693     }
694 
695   free (buf);
696 
697   if (priv->encprivpart == NULL)
698     {
699       shishi_error_printf (priv->handle, "Could not DER decode EncPrivPart. "
700 			   "Key probably correct (decrypt ok) though\n");
701       return SHISHI_ASN1_ERROR;
702     }
703 
704   return SHISHI_OK;
705 }
706