1505d05c7Sgtb /*
2*159d09a2SMark Phalan  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3505d05c7Sgtb  * Use is subject to license terms.
4505d05c7Sgtb  */
5505d05c7Sgtb 
67c478bd9Sstevel@tonic-gate /*
77c478bd9Sstevel@tonic-gate  * src/lib/krb5/asn.1/asn1_k_decode.c
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * Copyright 1994 by the Massachusetts Institute of Technology.
107c478bd9Sstevel@tonic-gate  * All Rights Reserved.
117c478bd9Sstevel@tonic-gate  *
127c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
137c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
147c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
157c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
167c478bd9Sstevel@tonic-gate  *
177c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
187c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
197c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
207c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
217c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
227c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
237c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
247c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
257c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
267c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
277c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
287c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
297c478bd9Sstevel@tonic-gate  * or implied warranty.
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include "asn1_k_decode.h"
337c478bd9Sstevel@tonic-gate #include "asn1_decode.h"
347c478bd9Sstevel@tonic-gate #include "asn1_get.h"
357c478bd9Sstevel@tonic-gate #include "asn1_misc.h"
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate /* Declare useful decoder variables. */
387c478bd9Sstevel@tonic-gate #define setup()					\
397c478bd9Sstevel@tonic-gate   asn1_error_code retval;			\
407c478bd9Sstevel@tonic-gate   asn1_class asn1class;				\
417c478bd9Sstevel@tonic-gate   asn1_construction construction;		\
427c478bd9Sstevel@tonic-gate   asn1_tagnum tagnum;				\
437c478bd9Sstevel@tonic-gate   unsigned int length, taglen
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate #define unused_var(x) if (0) { x = 0; x = x - x; }
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate /* This is used for prefetch of next tag in sequence. */
487c478bd9Sstevel@tonic-gate #define next_tag()								\
497c478bd9Sstevel@tonic-gate { taginfo t2;									\
507c478bd9Sstevel@tonic-gate   retval = asn1_get_tag_2(&subbuf, &t2);					\
517c478bd9Sstevel@tonic-gate   if (retval) return retval;							\
527c478bd9Sstevel@tonic-gate   /* Copy out to match previous functionality, until better integrated.  */	\
537c478bd9Sstevel@tonic-gate   asn1class = t2.asn1class;							\
547c478bd9Sstevel@tonic-gate   construction = t2.construction;						\
557c478bd9Sstevel@tonic-gate   tagnum = t2.tagnum;								\
567c478bd9Sstevel@tonic-gate   taglen = t2.length;								\
577c478bd9Sstevel@tonic-gate   indef = t2.indef;								\
587c478bd9Sstevel@tonic-gate }
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate /* Force check for EOC tag. */
617c478bd9Sstevel@tonic-gate #define get_eoc()									\
627c478bd9Sstevel@tonic-gate     {											\
637c478bd9Sstevel@tonic-gate 	taginfo t3;									\
647c478bd9Sstevel@tonic-gate 	retval = asn1_get_tag_2(&subbuf, &t3);						\
657c478bd9Sstevel@tonic-gate 	if(retval) return retval;							\
667c478bd9Sstevel@tonic-gate         if (t3.asn1class != UNIVERSAL || t3.tagnum || t3.indef)				\
677c478bd9Sstevel@tonic-gate 	    return ASN1_MISSING_EOC;							\
687c478bd9Sstevel@tonic-gate         /* Copy out to match previous functionality, until better integrated.  */	\
697c478bd9Sstevel@tonic-gate 	asn1class = t3.asn1class;							\
707c478bd9Sstevel@tonic-gate 	construction = t3.construction;							\
717c478bd9Sstevel@tonic-gate 	tagnum = t3.tagnum;								\
727c478bd9Sstevel@tonic-gate 	taglen = t3.length;								\
737c478bd9Sstevel@tonic-gate 	indef = t3.indef;								\
747c478bd9Sstevel@tonic-gate     }
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate #define alloc_field(var, type)			\
777c478bd9Sstevel@tonic-gate   var = (type*)calloc(1, sizeof(type));		\
787c478bd9Sstevel@tonic-gate   if ((var) == NULL) return ENOMEM
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate /* Fetch an expected APPLICATION class tag and verify. */
817c478bd9Sstevel@tonic-gate #define apptag(tagexpect)								\
827c478bd9Sstevel@tonic-gate   {											\
837c478bd9Sstevel@tonic-gate       taginfo t1;									\
847c478bd9Sstevel@tonic-gate       retval = asn1_get_tag_2(buf, &t1);						\
857c478bd9Sstevel@tonic-gate       if (retval) return retval;						   	\
867c478bd9Sstevel@tonic-gate       if (t1.asn1class != APPLICATION || t1.construction != CONSTRUCTED ||	   	\
877c478bd9Sstevel@tonic-gate 	  t1.tagnum != (tagexpect)) return ASN1_BAD_ID;					\
887c478bd9Sstevel@tonic-gate       /* Copy out to match previous functionality, until better integrated.  */		\
897c478bd9Sstevel@tonic-gate       asn1class = t1.asn1class;								\
907c478bd9Sstevel@tonic-gate       construction = t1.construction;							\
917c478bd9Sstevel@tonic-gate       tagnum = t1.tagnum;								\
927c478bd9Sstevel@tonic-gate       applen = t1.length;								\
937c478bd9Sstevel@tonic-gate   }
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate /**** normal fields ****/
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate /*
987c478bd9Sstevel@tonic-gate  * get_field_body
997c478bd9Sstevel@tonic-gate  *
1007c478bd9Sstevel@tonic-gate  * Get bare field.  This also prefetches the next tag.  The call to
1017c478bd9Sstevel@tonic-gate  * get_eoc() assumes that any values fetched by this macro are
1027c478bd9Sstevel@tonic-gate  * enclosed in a context-specific tag.
1037c478bd9Sstevel@tonic-gate  */
1047c478bd9Sstevel@tonic-gate #define get_field_body(var, decoder)		\
1057c478bd9Sstevel@tonic-gate   retval = decoder(&subbuf, &(var));		\
1067c478bd9Sstevel@tonic-gate   if (retval) return retval;			\
1077c478bd9Sstevel@tonic-gate   if (!taglen && indef) { get_eoc(); }		\
1087c478bd9Sstevel@tonic-gate   next_tag()
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate /*
1117c478bd9Sstevel@tonic-gate  * get_field
1127c478bd9Sstevel@tonic-gate  *
1137c478bd9Sstevel@tonic-gate  * Get field having an expected context specific tag.  This assumes
1147c478bd9Sstevel@tonic-gate  * that context-specific tags are monotonically increasing in its
1157c478bd9Sstevel@tonic-gate  * verification of tag numbers.
1167c478bd9Sstevel@tonic-gate  */
1177c478bd9Sstevel@tonic-gate #define get_field(var, tagexpect, decoder)				\
1187c478bd9Sstevel@tonic-gate   if (tagnum > (tagexpect)) return ASN1_MISSING_FIELD;			\
1197c478bd9Sstevel@tonic-gate   if (tagnum < (tagexpect)) return ASN1_MISPLACED_FIELD;		\
1207c478bd9Sstevel@tonic-gate   if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)	\
1217c478bd9Sstevel@tonic-gate       && (tagnum || taglen || asn1class != UNIVERSAL))			\
1227c478bd9Sstevel@tonic-gate     return ASN1_BAD_ID;							\
1237c478bd9Sstevel@tonic-gate   get_field_body(var,decoder)
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate /*
1267c478bd9Sstevel@tonic-gate  * opt_field
1277c478bd9Sstevel@tonic-gate  *
1287c478bd9Sstevel@tonic-gate  * Get an optional field with an expected context specific tag.
1297c478bd9Sstevel@tonic-gate  * Assumes that OPTVAL will have the default value, thus failing to
1307c478bd9Sstevel@tonic-gate  * distinguish between absent optional values and present optional
1317c478bd9Sstevel@tonic-gate  * values that happen to have the value of OPTVAL.
1327c478bd9Sstevel@tonic-gate  */
1337c478bd9Sstevel@tonic-gate #define opt_field(var, tagexpect, decoder, optvalue)			\
1347c478bd9Sstevel@tonic-gate   if (asn1buf_remains(&subbuf, seqindef)) {				\
1357c478bd9Sstevel@tonic-gate     if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)	\
1367c478bd9Sstevel@tonic-gate 	&& (tagnum || taglen || asn1class != UNIVERSAL))		\
1377c478bd9Sstevel@tonic-gate       return ASN1_BAD_ID;						\
1387c478bd9Sstevel@tonic-gate     if (tagnum == (tagexpect)) {					\
1397c478bd9Sstevel@tonic-gate       get_field_body(var, decoder);					\
1407c478bd9Sstevel@tonic-gate     } else var = optvalue;						\
1417c478bd9Sstevel@tonic-gate   }
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate /**** fields w/ length ****/
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate /* similar to get_field_body */
1467c478bd9Sstevel@tonic-gate #define get_lenfield_body(len, var, decoder)	\
1477c478bd9Sstevel@tonic-gate   retval = decoder(&subbuf, &(len), &(var));	\
1487c478bd9Sstevel@tonic-gate   if (retval) return retval;			\
1497c478bd9Sstevel@tonic-gate   if (!taglen && indef) { get_eoc(); }		\
1507c478bd9Sstevel@tonic-gate   next_tag()
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate /* similar to get_field_body */
1537c478bd9Sstevel@tonic-gate #define get_lenfield(len, var, tagexpect, decoder)			\
1547c478bd9Sstevel@tonic-gate   if (tagnum > (tagexpect)) return ASN1_MISSING_FIELD;			\
1557c478bd9Sstevel@tonic-gate   if (tagnum < (tagexpect)) return ASN1_MISPLACED_FIELD;		\
1567c478bd9Sstevel@tonic-gate   if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)	\
1577c478bd9Sstevel@tonic-gate       && (tagnum || taglen || asn1class != UNIVERSAL))			\
1587c478bd9Sstevel@tonic-gate     return ASN1_BAD_ID;							\
1597c478bd9Sstevel@tonic-gate   get_lenfield_body(len, var, decoder)
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate /* similar to opt_field */
1627c478bd9Sstevel@tonic-gate #define opt_lenfield(len, var, tagexpect, decoder)	\
1637c478bd9Sstevel@tonic-gate   if (tagnum == (tagexpect)) {				\
1647c478bd9Sstevel@tonic-gate     get_lenfield_body(len, var, decoder);		\
1657c478bd9Sstevel@tonic-gate   } else { len = 0; var = 0; }
1667c478bd9Sstevel@tonic-gate 
167*159d09a2SMark Phalan /*
168*159d09a2SMark Phalan  * Deal with implicitly tagged fields
169*159d09a2SMark Phalan  */
170*159d09a2SMark Phalan #define get_implicit_octet_string(len, var, tagexpect)		    \
171*159d09a2SMark Phalan   if (tagnum != (tagexpect)) return ASN1_MISSING_FIELD;		    \
172*159d09a2SMark Phalan   if (asn1class != CONTEXT_SPECIFIC || construction != PRIMITIVE)   \
173*159d09a2SMark Phalan      return ASN1_BAD_ID;					    \
174*159d09a2SMark Phalan   retval = asn1buf_remove_octetstring(&subbuf, taglen, &(var));	    \
175*159d09a2SMark Phalan   if (retval) return retval;					    \
176*159d09a2SMark Phalan   (len) = taglen;						    \
177*159d09a2SMark Phalan   next_tag()
178*159d09a2SMark Phalan 
179*159d09a2SMark Phalan #define opt_implicit_octet_string(len, var, tagexpect)		    \
180*159d09a2SMark Phalan   if (tagnum == (tagexpect)) {					    \
181*159d09a2SMark Phalan     if (asn1class != CONTEXT_SPECIFIC || construction != PRIMITIVE) \
182*159d09a2SMark Phalan 	return ASN1_BAD_ID;					    \
183*159d09a2SMark Phalan     retval = asn1buf_remove_octetstring(&subbuf, taglen, &(var));   \
184*159d09a2SMark Phalan     if (retval) return retval;					    \
185*159d09a2SMark Phalan     (len) = taglen;						    \
186*159d09a2SMark Phalan     next_tag();							    \
187*159d09a2SMark Phalan   } else { (len) = 0; (var) = NULL; }
188*159d09a2SMark Phalan 
1897c478bd9Sstevel@tonic-gate /*
1907c478bd9Sstevel@tonic-gate  * begin_structure
1917c478bd9Sstevel@tonic-gate  *
1927c478bd9Sstevel@tonic-gate  * Declares some variables for decoding SEQUENCE types.  This is meant
1937c478bd9Sstevel@tonic-gate  * to be called in an inner block that ends with a call to
1947c478bd9Sstevel@tonic-gate  * end_structure().
1957c478bd9Sstevel@tonic-gate  */
1967c478bd9Sstevel@tonic-gate #define begin_structure()					\
1977c478bd9Sstevel@tonic-gate   asn1buf subbuf;						\
1987c478bd9Sstevel@tonic-gate   int seqindef;							\
1997c478bd9Sstevel@tonic-gate   int indef;							\
2007c478bd9Sstevel@tonic-gate   retval = asn1_get_sequence(buf, &length, &seqindef);		\
2017c478bd9Sstevel@tonic-gate   if (retval) return retval;					\
2027c478bd9Sstevel@tonic-gate   retval = asn1buf_imbed(&subbuf, buf, length, seqindef);	\
2037c478bd9Sstevel@tonic-gate   if (retval) return retval;					\
2047c478bd9Sstevel@tonic-gate   next_tag()
2057c478bd9Sstevel@tonic-gate 
206*159d09a2SMark Phalan /*
207*159d09a2SMark Phalan  * This is used for structures which have no tagging.
208*159d09a2SMark Phalan  * It is the same as begin_structure() except next_tag()
209*159d09a2SMark Phalan  * is not called.
210*159d09a2SMark Phalan  */
211*159d09a2SMark Phalan #define begin_structure_no_tag()				\
212*159d09a2SMark Phalan   asn1buf subbuf;						\
213*159d09a2SMark Phalan   int seqindef;							\
214*159d09a2SMark Phalan   int indef;							\
215*159d09a2SMark Phalan   retval = asn1_get_sequence(buf, &length, &seqindef);		\
216*159d09a2SMark Phalan   if (retval) return retval;					\
217*159d09a2SMark Phalan   retval = asn1buf_imbed(&subbuf, buf, length, seqindef);	\
218*159d09a2SMark Phalan   if (retval) return retval
219*159d09a2SMark Phalan 
2207c478bd9Sstevel@tonic-gate /* skip trailing garbage */
2217c478bd9Sstevel@tonic-gate #define end_structure()						\
2227c478bd9Sstevel@tonic-gate   retval = asn1buf_sync(buf, &subbuf, asn1class, tagnum,	\
2237c478bd9Sstevel@tonic-gate 			length, indef, seqindef);		\
2247c478bd9Sstevel@tonic-gate   if (retval) return retval
2257c478bd9Sstevel@tonic-gate 
226*159d09a2SMark Phalan /*
227*159d09a2SMark Phalan  * begin_choice
228*159d09a2SMark Phalan  *
229*159d09a2SMark Phalan  * Declares some variables for decoding CHOICE types.  This is meant
230*159d09a2SMark Phalan  * to be called in an inner block that ends with a call to
231*159d09a2SMark Phalan  * end_choice().
232*159d09a2SMark Phalan  */
233*159d09a2SMark Phalan #define begin_choice()						\
234*159d09a2SMark Phalan   asn1buf subbuf;						\
235*159d09a2SMark Phalan   int seqindef;							\
236*159d09a2SMark Phalan   int indef;							\
237*159d09a2SMark Phalan   taginfo t;							\
238*159d09a2SMark Phalan   retval = asn1_get_tag_2(buf, &t);				\
239*159d09a2SMark Phalan   if (retval) return retval;					\
240*159d09a2SMark Phalan   tagnum = t.tagnum;                                            \
241*159d09a2SMark Phalan   taglen = t.length;                                            \
242*159d09a2SMark Phalan   indef = t.indef;                                              \
243*159d09a2SMark Phalan   length = t.length;                                            \
244*159d09a2SMark Phalan   seqindef = t.indef;                                           \
245*159d09a2SMark Phalan   asn1class = t.asn1class;					\
246*159d09a2SMark Phalan   construction = t.construction;				\
247*159d09a2SMark Phalan   retval = asn1buf_imbed(&subbuf, buf, length, seqindef);	\
248*159d09a2SMark Phalan   if (retval) return retval
249*159d09a2SMark Phalan 
250*159d09a2SMark Phalan /* skip trailing garbage */
251*159d09a2SMark Phalan #define end_choice()						\
252*159d09a2SMark Phalan   length -= t.length;						\
253*159d09a2SMark Phalan   retval = asn1buf_sync(buf, &subbuf, t.asn1class, t.tagnum,	\
254*159d09a2SMark Phalan 			length, t.indef, seqindef);		\
255*159d09a2SMark Phalan   if (retval) return retval
256*159d09a2SMark Phalan 
2577c478bd9Sstevel@tonic-gate /*
2587c478bd9Sstevel@tonic-gate  * sequence_of
2597c478bd9Sstevel@tonic-gate  *
2607c478bd9Sstevel@tonic-gate  * Declares some variables for decoding SEQUENCE OF types.  This is
2617c478bd9Sstevel@tonic-gate  * meant to be called in an inner block that ends with a call to
2627c478bd9Sstevel@tonic-gate  * end_sequence_of().
2637c478bd9Sstevel@tonic-gate  */
2647c478bd9Sstevel@tonic-gate #define sequence_of(buf)			\
2657c478bd9Sstevel@tonic-gate   unsigned int length, taglen;			\
2667c478bd9Sstevel@tonic-gate   asn1_class asn1class;				\
2677c478bd9Sstevel@tonic-gate   asn1_construction construction;		\
2687c478bd9Sstevel@tonic-gate   asn1_tagnum tagnum;				\
2697c478bd9Sstevel@tonic-gate   int indef;					\
2707c478bd9Sstevel@tonic-gate   sequence_of_common(buf)
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate /*
2737c478bd9Sstevel@tonic-gate  * sequence_of_no_tagvars
2747c478bd9Sstevel@tonic-gate  *
2757c478bd9Sstevel@tonic-gate  * This is meant for use inside decoder functions that have an outer
2767c478bd9Sstevel@tonic-gate  * sequence structure and thus declares variables of different names
2777c478bd9Sstevel@tonic-gate  * than does sequence_of() to avoid shadowing.
2787c478bd9Sstevel@tonic-gate  */
2797c478bd9Sstevel@tonic-gate #define sequence_of_no_tagvars(buf)		\
2807c478bd9Sstevel@tonic-gate   asn1_class eseqclass;				\
2817c478bd9Sstevel@tonic-gate   asn1_construction eseqconstr;			\
2827c478bd9Sstevel@tonic-gate   asn1_tagnum eseqnum;				\
2837c478bd9Sstevel@tonic-gate   unsigned int eseqlen;				\
2847c478bd9Sstevel@tonic-gate   int eseqindef;				\
2857c478bd9Sstevel@tonic-gate   sequence_of_common(buf)
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate /*
2887c478bd9Sstevel@tonic-gate  * sequence_of_common
2897c478bd9Sstevel@tonic-gate  *
2907c478bd9Sstevel@tonic-gate  * Fetches the outer SEQUENCE OF length info into {length,seqofindef}
2917c478bd9Sstevel@tonic-gate  * and imbeds an inner buffer seqbuf.  Unlike begin_structure(), it
2927c478bd9Sstevel@tonic-gate  * does not prefetch the next tag.
2937c478bd9Sstevel@tonic-gate  */
2947c478bd9Sstevel@tonic-gate #define sequence_of_common(buf)					\
2957c478bd9Sstevel@tonic-gate   int size = 0;							\
2967c478bd9Sstevel@tonic-gate   asn1buf seqbuf;						\
2977c478bd9Sstevel@tonic-gate   int seqofindef;						\
2987c478bd9Sstevel@tonic-gate   retval = asn1_get_sequence(buf, &length, &seqofindef);	\
2997c478bd9Sstevel@tonic-gate   if (retval) return retval;					\
3007c478bd9Sstevel@tonic-gate   retval = asn1buf_imbed(&seqbuf, buf, length, seqofindef);	\
3017c478bd9Sstevel@tonic-gate   if (retval) return retval
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate /*
3047c478bd9Sstevel@tonic-gate  * end_sequence_of
3057c478bd9Sstevel@tonic-gate  *
3067c478bd9Sstevel@tonic-gate  * Attempts to fetch an EOC tag, if any, and to sync over trailing
3077c478bd9Sstevel@tonic-gate  * garbage, if any.
3087c478bd9Sstevel@tonic-gate  */
3097c478bd9Sstevel@tonic-gate #define end_sequence_of(buf)							\
3107c478bd9Sstevel@tonic-gate   {										\
3117c478bd9Sstevel@tonic-gate       taginfo t4;								\
3127c478bd9Sstevel@tonic-gate       retval = asn1_get_tag_2(&seqbuf, &t4);					\
3137c478bd9Sstevel@tonic-gate       if (retval) return retval;						\
3147c478bd9Sstevel@tonic-gate       /* Copy out to match previous functionality, until better integrated.  */	\
3157c478bd9Sstevel@tonic-gate       asn1class = t4.asn1class;							\
3167c478bd9Sstevel@tonic-gate       construction = t4.construction;						\
3177c478bd9Sstevel@tonic-gate       tagnum = t4.tagnum;							\
3187c478bd9Sstevel@tonic-gate       taglen = t4.length;							\
3197c478bd9Sstevel@tonic-gate       indef = t4.indef;								\
3207c478bd9Sstevel@tonic-gate   }										\
3217c478bd9Sstevel@tonic-gate   retval = asn1buf_sync(buf, &seqbuf, asn1class, tagnum,			\
3227c478bd9Sstevel@tonic-gate 			length, indef, seqofindef);				\
3237c478bd9Sstevel@tonic-gate   if (retval) return retval;
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate /*
3267c478bd9Sstevel@tonic-gate  * end_sequence_of_no_tagvars
3277c478bd9Sstevel@tonic-gate  *
3287c478bd9Sstevel@tonic-gate  * Like end_sequence_of(), but uses the different (non-shadowing)
3297c478bd9Sstevel@tonic-gate  * variable names.
3307c478bd9Sstevel@tonic-gate  */
3317c478bd9Sstevel@tonic-gate #define end_sequence_of_no_tagvars(buf)						\
3327c478bd9Sstevel@tonic-gate   {										\
3337c478bd9Sstevel@tonic-gate       taginfo t5;								\
3347c478bd9Sstevel@tonic-gate       retval = asn1_get_tag_2(&seqbuf, &t5);					\
3357c478bd9Sstevel@tonic-gate       if (retval) return retval;						\
3367c478bd9Sstevel@tonic-gate       /* Copy out to match previous functionality, until better integrated.  */	\
3377c478bd9Sstevel@tonic-gate       eseqclass = t5.asn1class;							\
3387c478bd9Sstevel@tonic-gate       eseqconstr = t5.construction;						\
3397c478bd9Sstevel@tonic-gate       eseqnum = t5.tagnum;							\
3407c478bd9Sstevel@tonic-gate       eseqlen = t5.length;							\
3417c478bd9Sstevel@tonic-gate       eseqindef = t5.indef;							\
3427c478bd9Sstevel@tonic-gate   }										\
3437c478bd9Sstevel@tonic-gate   retval = asn1buf_sync(buf, &seqbuf, eseqclass, eseqnum,			\
3447c478bd9Sstevel@tonic-gate 			eseqlen, eseqindef, seqofindef);			\
3457c478bd9Sstevel@tonic-gate   if (retval) return retval;
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate #define cleanup()				\
3487c478bd9Sstevel@tonic-gate   return 0
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate /* scalars */
asn1_decode_kerberos_time(asn1buf * buf,krb5_timestamp * val)3517c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_kerberos_time(asn1buf *buf, krb5_timestamp *val)
3527c478bd9Sstevel@tonic-gate {
3537c478bd9Sstevel@tonic-gate     time_t	t;
3547c478bd9Sstevel@tonic-gate     asn1_error_code retval;
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate     retval =  asn1_decode_generaltime(buf,&t);
3577c478bd9Sstevel@tonic-gate     if (retval)
3587c478bd9Sstevel@tonic-gate 	return retval;
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate     *val = t;
3617c478bd9Sstevel@tonic-gate     return 0;
3627c478bd9Sstevel@tonic-gate }
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate #define integer_convert(fname,ktype)\
3657c478bd9Sstevel@tonic-gate asn1_error_code fname(asn1buf * buf, ktype * val)\
3667c478bd9Sstevel@tonic-gate {\
3677c478bd9Sstevel@tonic-gate   asn1_error_code retval;\
3687c478bd9Sstevel@tonic-gate   long n;\
3697c478bd9Sstevel@tonic-gate   retval = asn1_decode_integer(buf,&n);\
3707c478bd9Sstevel@tonic-gate   if(retval) return retval;\
3717c478bd9Sstevel@tonic-gate   *val = (ktype)n;\
3727c478bd9Sstevel@tonic-gate   return 0;\
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate #define unsigned_integer_convert(fname,ktype)\
3757c478bd9Sstevel@tonic-gate asn1_error_code fname(asn1buf * buf, ktype * val)\
3767c478bd9Sstevel@tonic-gate {\
3777c478bd9Sstevel@tonic-gate   asn1_error_code retval;\
3787c478bd9Sstevel@tonic-gate   unsigned long n;\
3797c478bd9Sstevel@tonic-gate   retval = asn1_decode_unsigned_integer(buf,&n);\
3807c478bd9Sstevel@tonic-gate   if(retval) return retval;\
3817c478bd9Sstevel@tonic-gate   *val = (ktype)n;\
3827c478bd9Sstevel@tonic-gate   return 0;\
3837c478bd9Sstevel@tonic-gate }
integer_convert(asn1_decode_int,int)3847c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_int,int)
3857c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_int32,krb5_int32)
3867c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_kvno,krb5_kvno)
3877c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_enctype,krb5_enctype)
3887c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_cksumtype,krb5_cksumtype)
3897c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_octet,krb5_octet)
3907c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_addrtype,krb5_addrtype)
3917c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_authdatatype,krb5_authdatatype)
3927c478bd9Sstevel@tonic-gate unsigned_integer_convert(asn1_decode_ui_2,krb5_ui_2)
3937c478bd9Sstevel@tonic-gate unsigned_integer_convert(asn1_decode_ui_4,krb5_ui_4)
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_seqnum(asn1buf *buf, krb5_ui_4 *val)
3967c478bd9Sstevel@tonic-gate {
3977c478bd9Sstevel@tonic-gate   asn1_error_code retval;
3987c478bd9Sstevel@tonic-gate   unsigned long n;
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate   retval = asn1_decode_maybe_unsigned(buf, &n);
4017c478bd9Sstevel@tonic-gate   if (retval) return retval;
4027c478bd9Sstevel@tonic-gate   *val = (krb5_ui_4)n & 0xffffffff;
4037c478bd9Sstevel@tonic-gate   return 0;
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate 
asn1_decode_msgtype(asn1buf * buf,krb5_msgtype * val)4067c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_msgtype(asn1buf *buf, krb5_msgtype *val)
4077c478bd9Sstevel@tonic-gate {
4087c478bd9Sstevel@tonic-gate   asn1_error_code retval;
4097c478bd9Sstevel@tonic-gate   unsigned long n;
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate   retval = asn1_decode_unsigned_integer(buf,&n);
4127c478bd9Sstevel@tonic-gate   if(retval) return retval;
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate   *val = (krb5_msgtype) n;
4157c478bd9Sstevel@tonic-gate   return 0;
4167c478bd9Sstevel@tonic-gate }
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate /* structures */
asn1_decode_realm(asn1buf * buf,krb5_principal * val)4207c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_realm(asn1buf *buf, krb5_principal *val)
4217c478bd9Sstevel@tonic-gate {
4227c478bd9Sstevel@tonic-gate   return asn1_decode_generalstring(buf,
423505d05c7Sgtb 				   &((*val)->realm.length),
4247c478bd9Sstevel@tonic-gate 				   &((*val)->realm.data));
4257c478bd9Sstevel@tonic-gate }
4267c478bd9Sstevel@tonic-gate 
asn1_decode_principal_name(asn1buf * buf,krb5_principal * val)4277c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_principal_name(asn1buf *buf, krb5_principal *val)
4287c478bd9Sstevel@tonic-gate {
4297c478bd9Sstevel@tonic-gate   setup();
4307c478bd9Sstevel@tonic-gate   { begin_structure();
4317c478bd9Sstevel@tonic-gate     get_field((*val)->type,0,asn1_decode_int32);
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate     { sequence_of_no_tagvars(&subbuf);
4347c478bd9Sstevel@tonic-gate       while(asn1buf_remains(&seqbuf,seqofindef) > 0){
4357c478bd9Sstevel@tonic-gate 	size++;
4367c478bd9Sstevel@tonic-gate 	if ((*val)->data == NULL)
4377c478bd9Sstevel@tonic-gate 	  (*val)->data = (krb5_data*)malloc(size*sizeof(krb5_data));
4387c478bd9Sstevel@tonic-gate 	else
4397c478bd9Sstevel@tonic-gate 	  (*val)->data = (krb5_data*)realloc((*val)->data,
4407c478bd9Sstevel@tonic-gate 					     size*sizeof(krb5_data));
4417c478bd9Sstevel@tonic-gate 	if((*val)->data == NULL) return ENOMEM;
4427c478bd9Sstevel@tonic-gate 	retval = asn1_decode_generalstring(&seqbuf,
443505d05c7Sgtb 					   &((*val)->data[size-1].length),
444*159d09a2SMark Phalan 					   &((*val)->data[size-1].data));
4457c478bd9Sstevel@tonic-gate 	if(retval) return retval;
4467c478bd9Sstevel@tonic-gate       }
4477c478bd9Sstevel@tonic-gate       (*val)->length = size;
4487c478bd9Sstevel@tonic-gate       end_sequence_of_no_tagvars(&subbuf);
4497c478bd9Sstevel@tonic-gate     }
4507c478bd9Sstevel@tonic-gate     if (indef) {
4517c478bd9Sstevel@tonic-gate 	get_eoc();
4527c478bd9Sstevel@tonic-gate     }
4537c478bd9Sstevel@tonic-gate     next_tag();
4547c478bd9Sstevel@tonic-gate     end_structure();
4557c478bd9Sstevel@tonic-gate     (*val)->magic = KV5M_PRINCIPAL;
4567c478bd9Sstevel@tonic-gate   }
4577c478bd9Sstevel@tonic-gate   cleanup();
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate 
asn1_decode_checksum(asn1buf * buf,krb5_checksum * val)4607c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_checksum(asn1buf *buf, krb5_checksum *val)
4617c478bd9Sstevel@tonic-gate {
4627c478bd9Sstevel@tonic-gate   setup();
4637c478bd9Sstevel@tonic-gate   { begin_structure();
4647c478bd9Sstevel@tonic-gate     get_field(val->checksum_type,0,asn1_decode_cksumtype);
4657c478bd9Sstevel@tonic-gate     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
4667c478bd9Sstevel@tonic-gate     end_structure();
4677c478bd9Sstevel@tonic-gate     val->magic = KV5M_CHECKSUM;
4687c478bd9Sstevel@tonic-gate   }
4697c478bd9Sstevel@tonic-gate   cleanup();
4707c478bd9Sstevel@tonic-gate }
4717c478bd9Sstevel@tonic-gate 
asn1_decode_encryption_key(asn1buf * buf,krb5_keyblock * val)4727c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_encryption_key(asn1buf *buf, krb5_keyblock *val)
4737c478bd9Sstevel@tonic-gate {
4747c478bd9Sstevel@tonic-gate   setup();
4757c478bd9Sstevel@tonic-gate   { begin_structure();
4767c478bd9Sstevel@tonic-gate     get_field(val->enctype,0,asn1_decode_enctype);
4777c478bd9Sstevel@tonic-gate     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
4787c478bd9Sstevel@tonic-gate     end_structure();
4797c478bd9Sstevel@tonic-gate     val->magic = KV5M_KEYBLOCK;
4807c478bd9Sstevel@tonic-gate   }
4817c478bd9Sstevel@tonic-gate   cleanup();
4827c478bd9Sstevel@tonic-gate }
4837c478bd9Sstevel@tonic-gate 
asn1_decode_encrypted_data(asn1buf * buf,krb5_enc_data * val)4847c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_encrypted_data(asn1buf *buf, krb5_enc_data *val)
4857c478bd9Sstevel@tonic-gate {
4867c478bd9Sstevel@tonic-gate   setup();
4877c478bd9Sstevel@tonic-gate   { begin_structure();
4887c478bd9Sstevel@tonic-gate     get_field(val->enctype,0,asn1_decode_enctype);
4897c478bd9Sstevel@tonic-gate     opt_field(val->kvno,1,asn1_decode_kvno,0);
4907c478bd9Sstevel@tonic-gate     get_lenfield(val->ciphertext.length,val->ciphertext.data,2,asn1_decode_charstring);
4917c478bd9Sstevel@tonic-gate     end_structure();
4927c478bd9Sstevel@tonic-gate     val->magic = KV5M_ENC_DATA;
4937c478bd9Sstevel@tonic-gate   }
4947c478bd9Sstevel@tonic-gate   cleanup();
4957c478bd9Sstevel@tonic-gate }
4967c478bd9Sstevel@tonic-gate 
asn1_decode_krb5_flags(asn1buf * buf,krb5_flags * val)4977c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_krb5_flags(asn1buf *buf, krb5_flags *val)
4987c478bd9Sstevel@tonic-gate {
4997c478bd9Sstevel@tonic-gate   asn1_error_code retval;
5007c478bd9Sstevel@tonic-gate   asn1_octet unused, o;
5017c478bd9Sstevel@tonic-gate   taginfo t;
5027c478bd9Sstevel@tonic-gate   int i;
5037c478bd9Sstevel@tonic-gate   krb5_flags f=0;
5047c478bd9Sstevel@tonic-gate   unsigned int length;
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate   retval = asn1_get_tag_2(buf, &t);
5077c478bd9Sstevel@tonic-gate   if (retval) return retval;
5087c478bd9Sstevel@tonic-gate   if (t.asn1class != UNIVERSAL || t.construction != PRIMITIVE ||
5097c478bd9Sstevel@tonic-gate       t.tagnum != ASN1_BITSTRING)
5107c478bd9Sstevel@tonic-gate       return ASN1_BAD_ID;
5117c478bd9Sstevel@tonic-gate   length = t.length;
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate   retval = asn1buf_remove_octet(buf,&unused); /* # of padding bits */
5147c478bd9Sstevel@tonic-gate   if(retval) return retval;
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate   /* Number of unused bits must be between 0 and 7. */
5177c478bd9Sstevel@tonic-gate   if (unused > 7) return ASN1_BAD_FORMAT;
5187c478bd9Sstevel@tonic-gate   length--;
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate   for(i = 0; i < length; i++) {
5217c478bd9Sstevel@tonic-gate     retval = asn1buf_remove_octet(buf,&o);
5227c478bd9Sstevel@tonic-gate     if(retval) return retval;
5237c478bd9Sstevel@tonic-gate     /* ignore bits past number 31 */
5247c478bd9Sstevel@tonic-gate     if (i < 4)
5257c478bd9Sstevel@tonic-gate       f = (f<<8) | ((krb5_flags)o&0xFF);
5267c478bd9Sstevel@tonic-gate   }
5277c478bd9Sstevel@tonic-gate   if (length <= 4) {
5287c478bd9Sstevel@tonic-gate     /* Mask out unused bits, but only if necessary. */
5297c478bd9Sstevel@tonic-gate     f &= ~(krb5_flags)0 << unused;
5307c478bd9Sstevel@tonic-gate   }
5317c478bd9Sstevel@tonic-gate   /* left-justify */
5327c478bd9Sstevel@tonic-gate   if (length < 4)
5337c478bd9Sstevel@tonic-gate     f <<= (4 - length) * 8;
5347c478bd9Sstevel@tonic-gate   *val = f;
5357c478bd9Sstevel@tonic-gate   return 0;
5367c478bd9Sstevel@tonic-gate }
5377c478bd9Sstevel@tonic-gate 
asn1_decode_ticket_flags(asn1buf * buf,krb5_flags * val)5387c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_ticket_flags(asn1buf *buf, krb5_flags *val)
5397c478bd9Sstevel@tonic-gate { return asn1_decode_krb5_flags(buf,val); }
5407c478bd9Sstevel@tonic-gate 
asn1_decode_ap_options(asn1buf * buf,krb5_flags * val)5417c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_ap_options(asn1buf *buf, krb5_flags *val)
5427c478bd9Sstevel@tonic-gate { return asn1_decode_krb5_flags(buf,val); }
5437c478bd9Sstevel@tonic-gate 
asn1_decode_kdc_options(asn1buf * buf,krb5_flags * val)5447c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_kdc_options(asn1buf *buf, krb5_flags *val)
5457c478bd9Sstevel@tonic-gate { return asn1_decode_krb5_flags(buf,val); }
5467c478bd9Sstevel@tonic-gate 
asn1_decode_transited_encoding(asn1buf * buf,krb5_transited * val)5477c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_transited_encoding(asn1buf *buf, krb5_transited *val)
5487c478bd9Sstevel@tonic-gate {
5497c478bd9Sstevel@tonic-gate   setup();
5507c478bd9Sstevel@tonic-gate   { begin_structure();
5517c478bd9Sstevel@tonic-gate     get_field(val->tr_type,0,asn1_decode_octet);
5527c478bd9Sstevel@tonic-gate     get_lenfield(val->tr_contents.length,val->tr_contents.data,1,asn1_decode_charstring);
5537c478bd9Sstevel@tonic-gate     end_structure();
5547c478bd9Sstevel@tonic-gate     val->magic = KV5M_TRANSITED;
5557c478bd9Sstevel@tonic-gate   }
5567c478bd9Sstevel@tonic-gate   cleanup();
5577c478bd9Sstevel@tonic-gate }
5587c478bd9Sstevel@tonic-gate 
asn1_decode_enc_kdc_rep_part(asn1buf * buf,krb5_enc_kdc_rep_part * val)5597c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_enc_kdc_rep_part(asn1buf *buf, krb5_enc_kdc_rep_part *val)
5607c478bd9Sstevel@tonic-gate {
5617c478bd9Sstevel@tonic-gate   setup();
5627c478bd9Sstevel@tonic-gate   { begin_structure();
5637c478bd9Sstevel@tonic-gate     alloc_field(val->session,krb5_keyblock);
5647c478bd9Sstevel@tonic-gate     get_field(*(val->session),0,asn1_decode_encryption_key);
5657c478bd9Sstevel@tonic-gate     get_field(val->last_req,1,asn1_decode_last_req);
5667c478bd9Sstevel@tonic-gate     get_field(val->nonce,2,asn1_decode_int32);
5677c478bd9Sstevel@tonic-gate     opt_field(val->key_exp,3,asn1_decode_kerberos_time,0);
5687c478bd9Sstevel@tonic-gate     get_field(val->flags,4,asn1_decode_ticket_flags);
5697c478bd9Sstevel@tonic-gate     get_field(val->times.authtime,5,asn1_decode_kerberos_time);
5707c478bd9Sstevel@tonic-gate     /* Set to authtime if missing */
5717c478bd9Sstevel@tonic-gate     opt_field(val->times.starttime,6,asn1_decode_kerberos_time,val->times.authtime);
5727c478bd9Sstevel@tonic-gate     get_field(val->times.endtime,7,asn1_decode_kerberos_time);
5737c478bd9Sstevel@tonic-gate     opt_field(val->times.renew_till,8,asn1_decode_kerberos_time,0);
5747c478bd9Sstevel@tonic-gate     alloc_field(val->server,krb5_principal_data);
5757c478bd9Sstevel@tonic-gate     get_field(val->server,9,asn1_decode_realm);
5767c478bd9Sstevel@tonic-gate     get_field(val->server,10,asn1_decode_principal_name);
5777c478bd9Sstevel@tonic-gate     opt_field(val->caddrs,11,asn1_decode_host_addresses,NULL);
5787c478bd9Sstevel@tonic-gate     end_structure();
5797c478bd9Sstevel@tonic-gate     val->magic = KV5M_ENC_KDC_REP_PART;
5807c478bd9Sstevel@tonic-gate   }
5817c478bd9Sstevel@tonic-gate   cleanup();
5827c478bd9Sstevel@tonic-gate }
5837c478bd9Sstevel@tonic-gate 
asn1_decode_ticket(asn1buf * buf,krb5_ticket * val)5847c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_ticket(asn1buf *buf, krb5_ticket *val)
5857c478bd9Sstevel@tonic-gate {
5867c478bd9Sstevel@tonic-gate   setup();
5877c478bd9Sstevel@tonic-gate   unsigned int applen;
5887c478bd9Sstevel@tonic-gate   apptag(1);
5897c478bd9Sstevel@tonic-gate   { begin_structure();
5907c478bd9Sstevel@tonic-gate     { krb5_kvno vno;
5917c478bd9Sstevel@tonic-gate       get_field(vno,0,asn1_decode_kvno);
5927c478bd9Sstevel@tonic-gate       if(vno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
5937c478bd9Sstevel@tonic-gate     alloc_field(val->server,krb5_principal_data);
5947c478bd9Sstevel@tonic-gate     get_field(val->server,1,asn1_decode_realm);
5957c478bd9Sstevel@tonic-gate     get_field(val->server,2,asn1_decode_principal_name);
5967c478bd9Sstevel@tonic-gate     get_field(val->enc_part,3,asn1_decode_encrypted_data);
5977c478bd9Sstevel@tonic-gate     end_structure();
5987c478bd9Sstevel@tonic-gate     val->magic = KV5M_TICKET;
5997c478bd9Sstevel@tonic-gate   }
6007c478bd9Sstevel@tonic-gate   if (!applen) {
6017c478bd9Sstevel@tonic-gate       taginfo t;
6027c478bd9Sstevel@tonic-gate       retval = asn1_get_tag_2(buf, &t);
603505d05c7Sgtb       if (retval) return retval;
604*159d09a2SMark Phalan   }
6057c478bd9Sstevel@tonic-gate   cleanup();
6067c478bd9Sstevel@tonic-gate }
6077c478bd9Sstevel@tonic-gate 
asn1_decode_kdc_req(asn1buf * buf,krb5_kdc_req * val)6087c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_kdc_req(asn1buf *buf, krb5_kdc_req *val)
6097c478bd9Sstevel@tonic-gate {
6107c478bd9Sstevel@tonic-gate   setup();
6117c478bd9Sstevel@tonic-gate   { begin_structure();
6127c478bd9Sstevel@tonic-gate     { krb5_kvno kvno;
6137c478bd9Sstevel@tonic-gate       get_field(kvno,1,asn1_decode_kvno);
6147c478bd9Sstevel@tonic-gate       if(kvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
6157c478bd9Sstevel@tonic-gate     get_field(val->msg_type,2,asn1_decode_msgtype);
6167c478bd9Sstevel@tonic-gate     opt_field(val->padata,3,asn1_decode_sequence_of_pa_data,NULL);
6177c478bd9Sstevel@tonic-gate     get_field(*val,4,asn1_decode_kdc_req_body);
6187c478bd9Sstevel@tonic-gate     end_structure();
6197c478bd9Sstevel@tonic-gate     val->magic = KV5M_KDC_REQ;
6207c478bd9Sstevel@tonic-gate   }
6217c478bd9Sstevel@tonic-gate   cleanup();
6227c478bd9Sstevel@tonic-gate }
6237c478bd9Sstevel@tonic-gate 
asn1_decode_kdc_req_body(asn1buf * buf,krb5_kdc_req * val)6247c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_kdc_req_body(asn1buf *buf, krb5_kdc_req *val)
6257c478bd9Sstevel@tonic-gate {
6267c478bd9Sstevel@tonic-gate   setup();
6277c478bd9Sstevel@tonic-gate   {
6287c478bd9Sstevel@tonic-gate     krb5_principal psave;
6297c478bd9Sstevel@tonic-gate     begin_structure();
6307c478bd9Sstevel@tonic-gate     get_field(val->kdc_options,0,asn1_decode_kdc_options);
6317c478bd9Sstevel@tonic-gate     if(tagnum == 1){ alloc_field(val->client,krb5_principal_data); }
6327c478bd9Sstevel@tonic-gate     opt_field(val->client,1,asn1_decode_principal_name,NULL);
6337c478bd9Sstevel@tonic-gate     alloc_field(val->server,krb5_principal_data);
6347c478bd9Sstevel@tonic-gate     get_field(val->server,2,asn1_decode_realm);
6357c478bd9Sstevel@tonic-gate     if(val->client != NULL){
6367c478bd9Sstevel@tonic-gate       retval = asn1_krb5_realm_copy(val->client,val->server);
637505d05c7Sgtb       if(retval) return retval; }
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate     /* If opt_field server is missing, memory reference to server is
6407c478bd9Sstevel@tonic-gate        lost and results in memory leak */
6417c478bd9Sstevel@tonic-gate     psave = val->server;
6427c478bd9Sstevel@tonic-gate     opt_field(val->server,3,asn1_decode_principal_name,NULL);
6437c478bd9Sstevel@tonic-gate     if(val->server == NULL){
6447c478bd9Sstevel@tonic-gate       if(psave->realm.data) {
6457c478bd9Sstevel@tonic-gate 	free(psave->realm.data);
6467c478bd9Sstevel@tonic-gate 	psave->realm.data = NULL;
6477c478bd9Sstevel@tonic-gate 	psave->realm.length=0;
6487c478bd9Sstevel@tonic-gate       }
6497c478bd9Sstevel@tonic-gate       free(psave);
6507c478bd9Sstevel@tonic-gate     }
6517c478bd9Sstevel@tonic-gate     opt_field(val->from,4,asn1_decode_kerberos_time,0);
6527c478bd9Sstevel@tonic-gate     get_field(val->till,5,asn1_decode_kerberos_time);
6537c478bd9Sstevel@tonic-gate     opt_field(val->rtime,6,asn1_decode_kerberos_time,0);
6547c478bd9Sstevel@tonic-gate     get_field(val->nonce,7,asn1_decode_int32);
6557c478bd9Sstevel@tonic-gate     get_lenfield(val->nktypes,val->ktype,8,asn1_decode_sequence_of_enctype);
6567c478bd9Sstevel@tonic-gate     opt_field(val->addresses,9,asn1_decode_host_addresses,0);
6577c478bd9Sstevel@tonic-gate     if(tagnum == 10){
6587c478bd9Sstevel@tonic-gate       get_field(val->authorization_data,10,asn1_decode_encrypted_data); }
6597c478bd9Sstevel@tonic-gate     else{
6607c478bd9Sstevel@tonic-gate       val->authorization_data.magic = KV5M_ENC_DATA;
6617c478bd9Sstevel@tonic-gate       val->authorization_data.enctype = 0;
6627c478bd9Sstevel@tonic-gate       val->authorization_data.kvno = 0;
6637c478bd9Sstevel@tonic-gate       val->authorization_data.ciphertext.data = NULL;
6647c478bd9Sstevel@tonic-gate       val->authorization_data.ciphertext.length = 0;
6657c478bd9Sstevel@tonic-gate     }
6667c478bd9Sstevel@tonic-gate     opt_field(val->second_ticket,11,asn1_decode_sequence_of_ticket,NULL);
6677c478bd9Sstevel@tonic-gate     end_structure();
6687c478bd9Sstevel@tonic-gate     val->magic = KV5M_KDC_REQ;
6697c478bd9Sstevel@tonic-gate   }
6707c478bd9Sstevel@tonic-gate   cleanup();
6717c478bd9Sstevel@tonic-gate }
6727c478bd9Sstevel@tonic-gate 
asn1_decode_krb_safe_body(asn1buf * buf,krb5_safe * val)6737c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_krb_safe_body(asn1buf *buf, krb5_safe *val)
6747c478bd9Sstevel@tonic-gate {
6757c478bd9Sstevel@tonic-gate   setup();
6767c478bd9Sstevel@tonic-gate   { begin_structure();
6777c478bd9Sstevel@tonic-gate     get_lenfield(val->user_data.length,val->user_data.data,0,asn1_decode_charstring);
6787c478bd9Sstevel@tonic-gate     opt_field(val->timestamp,1,asn1_decode_kerberos_time,0);
6797c478bd9Sstevel@tonic-gate     opt_field(val->usec,2,asn1_decode_int32,0);
6807c478bd9Sstevel@tonic-gate     opt_field(val->seq_number,3,asn1_decode_seqnum,0);
6817c478bd9Sstevel@tonic-gate     alloc_field(val->s_address,krb5_address);
6827c478bd9Sstevel@tonic-gate     get_field(*(val->s_address),4,asn1_decode_host_address);
6837c478bd9Sstevel@tonic-gate     if(tagnum == 5){
6847c478bd9Sstevel@tonic-gate       alloc_field(val->r_address,krb5_address);
6857c478bd9Sstevel@tonic-gate       get_field(*(val->r_address),5,asn1_decode_host_address);
6867c478bd9Sstevel@tonic-gate     } else val->r_address = NULL;
6877c478bd9Sstevel@tonic-gate     end_structure();
6887c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAFE;
6897c478bd9Sstevel@tonic-gate   }
6907c478bd9Sstevel@tonic-gate   cleanup();
6917c478bd9Sstevel@tonic-gate }
6927c478bd9Sstevel@tonic-gate 
asn1_decode_host_address(asn1buf * buf,krb5_address * val)6937c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_host_address(asn1buf *buf, krb5_address *val)
6947c478bd9Sstevel@tonic-gate {
6957c478bd9Sstevel@tonic-gate   setup();
6967c478bd9Sstevel@tonic-gate   { begin_structure();
6977c478bd9Sstevel@tonic-gate     get_field(val->addrtype,0,asn1_decode_addrtype);
6987c478bd9Sstevel@tonic-gate     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
6997c478bd9Sstevel@tonic-gate     end_structure();
7007c478bd9Sstevel@tonic-gate     val->magic = KV5M_ADDRESS;
7017c478bd9Sstevel@tonic-gate   }
7027c478bd9Sstevel@tonic-gate   cleanup();
7037c478bd9Sstevel@tonic-gate }
7047c478bd9Sstevel@tonic-gate 
asn1_decode_kdc_rep(asn1buf * buf,krb5_kdc_rep * val)7057c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_kdc_rep(asn1buf *buf, krb5_kdc_rep *val)
7067c478bd9Sstevel@tonic-gate {
7077c478bd9Sstevel@tonic-gate   setup();
7087c478bd9Sstevel@tonic-gate   { begin_structure();
7097c478bd9Sstevel@tonic-gate     { krb5_kvno pvno;
7107c478bd9Sstevel@tonic-gate       get_field(pvno,0,asn1_decode_kvno);
7117c478bd9Sstevel@tonic-gate       if(pvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
7127c478bd9Sstevel@tonic-gate     get_field(val->msg_type,1,asn1_decode_msgtype);
7137c478bd9Sstevel@tonic-gate     opt_field(val->padata,2,asn1_decode_sequence_of_pa_data,NULL);
7147c478bd9Sstevel@tonic-gate     alloc_field(val->client,krb5_principal_data);
7157c478bd9Sstevel@tonic-gate     get_field(val->client,3,asn1_decode_realm);
7167c478bd9Sstevel@tonic-gate     get_field(val->client,4,asn1_decode_principal_name);
7177c478bd9Sstevel@tonic-gate     alloc_field(val->ticket,krb5_ticket);
7187c478bd9Sstevel@tonic-gate     get_field(*(val->ticket),5,asn1_decode_ticket);
7197c478bd9Sstevel@tonic-gate     get_field(val->enc_part,6,asn1_decode_encrypted_data);
7207c478bd9Sstevel@tonic-gate     end_structure();
7217c478bd9Sstevel@tonic-gate     val->magic = KV5M_KDC_REP;
7227c478bd9Sstevel@tonic-gate   }
7237c478bd9Sstevel@tonic-gate   cleanup();
7247c478bd9Sstevel@tonic-gate }
7257c478bd9Sstevel@tonic-gate 
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate /* arrays */
7287c478bd9Sstevel@tonic-gate #define get_element(element,decoder)\
7297c478bd9Sstevel@tonic-gate retval = decoder(&seqbuf,element);\
7307c478bd9Sstevel@tonic-gate if(retval) return retval
7317c478bd9Sstevel@tonic-gate 
7327c478bd9Sstevel@tonic-gate #define array_append(array,size,element,type)\
7337c478bd9Sstevel@tonic-gate size++;\
7347c478bd9Sstevel@tonic-gate if (*(array) == NULL)\
7357c478bd9Sstevel@tonic-gate      *(array) = (type**)malloc((size+1)*sizeof(type*));\
7367c478bd9Sstevel@tonic-gate else\
7377c478bd9Sstevel@tonic-gate   *(array) = (type**)realloc(*(array),\
7387c478bd9Sstevel@tonic-gate 			     (size+1)*sizeof(type*));\
7397c478bd9Sstevel@tonic-gate if(*(array) == NULL) return ENOMEM;\
7407c478bd9Sstevel@tonic-gate (*(array))[(size)-1] = elt
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate #define decode_array_body(type,decoder)\
7437c478bd9Sstevel@tonic-gate   asn1_error_code retval;\
7447c478bd9Sstevel@tonic-gate   type *elt;\
7457c478bd9Sstevel@tonic-gate \
7467c478bd9Sstevel@tonic-gate   { sequence_of(buf);\
7477c478bd9Sstevel@tonic-gate     while(asn1buf_remains(&seqbuf,seqofindef) > 0){\
7487c478bd9Sstevel@tonic-gate       alloc_field(elt,type);\
7497c478bd9Sstevel@tonic-gate       get_element(elt,decoder);\
7507c478bd9Sstevel@tonic-gate       array_append(val,size,elt,type);\
7517c478bd9Sstevel@tonic-gate     }\
7527c478bd9Sstevel@tonic-gate     if (*val == NULL)\
7537c478bd9Sstevel@tonic-gate 	*val = (type **)malloc(sizeof(type*));\
7547c478bd9Sstevel@tonic-gate     (*val)[size] = NULL;\
7557c478bd9Sstevel@tonic-gate     end_sequence_of(buf);\
7567c478bd9Sstevel@tonic-gate   }\
7577c478bd9Sstevel@tonic-gate   cleanup()
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate 
asn1_decode_authorization_data(asn1buf * buf,krb5_authdata *** val)7607c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_authorization_data(asn1buf *buf, krb5_authdata ***val)
7617c478bd9Sstevel@tonic-gate {
7627c478bd9Sstevel@tonic-gate   decode_array_body(krb5_authdata,asn1_decode_authdata_elt);
7637c478bd9Sstevel@tonic-gate }
7647c478bd9Sstevel@tonic-gate 
asn1_decode_authdata_elt(asn1buf * buf,krb5_authdata * val)7657c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_authdata_elt(asn1buf *buf, krb5_authdata *val)
7667c478bd9Sstevel@tonic-gate {
7677c478bd9Sstevel@tonic-gate   setup();
7687c478bd9Sstevel@tonic-gate   { begin_structure();
7697c478bd9Sstevel@tonic-gate     get_field(val->ad_type,0,asn1_decode_authdatatype);
7707c478bd9Sstevel@tonic-gate     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
7717c478bd9Sstevel@tonic-gate     end_structure();
7727c478bd9Sstevel@tonic-gate     val->magic = KV5M_AUTHDATA;
7737c478bd9Sstevel@tonic-gate   }
7747c478bd9Sstevel@tonic-gate   cleanup();
7757c478bd9Sstevel@tonic-gate }
7767c478bd9Sstevel@tonic-gate 
asn1_decode_host_addresses(asn1buf * buf,krb5_address *** val)7777c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_host_addresses(asn1buf *buf, krb5_address ***val)
7787c478bd9Sstevel@tonic-gate {
7797c478bd9Sstevel@tonic-gate   decode_array_body(krb5_address,asn1_decode_host_address);
7807c478bd9Sstevel@tonic-gate }
7817c478bd9Sstevel@tonic-gate 
asn1_decode_sequence_of_ticket(asn1buf * buf,krb5_ticket *** val)7827c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_ticket(asn1buf *buf, krb5_ticket ***val)
7837c478bd9Sstevel@tonic-gate {
7847c478bd9Sstevel@tonic-gate   decode_array_body(krb5_ticket,asn1_decode_ticket);
7857c478bd9Sstevel@tonic-gate }
7867c478bd9Sstevel@tonic-gate 
asn1_decode_sequence_of_krb_cred_info(asn1buf * buf,krb5_cred_info *** val)7877c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_krb_cred_info(asn1buf *buf, krb5_cred_info ***val)
7887c478bd9Sstevel@tonic-gate {
7897c478bd9Sstevel@tonic-gate   decode_array_body(krb5_cred_info,asn1_decode_krb_cred_info);
7907c478bd9Sstevel@tonic-gate }
7917c478bd9Sstevel@tonic-gate 
asn1_decode_krb_cred_info(asn1buf * buf,krb5_cred_info * val)7927c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_krb_cred_info(asn1buf *buf, krb5_cred_info *val)
7937c478bd9Sstevel@tonic-gate {
7947c478bd9Sstevel@tonic-gate   setup();
7957c478bd9Sstevel@tonic-gate   { begin_structure();
7967c478bd9Sstevel@tonic-gate     alloc_field(val->session,krb5_keyblock);
7977c478bd9Sstevel@tonic-gate     get_field(*(val->session),0,asn1_decode_encryption_key);
7987c478bd9Sstevel@tonic-gate     if(tagnum == 1){
7997c478bd9Sstevel@tonic-gate       alloc_field(val->client,krb5_principal_data);
8007c478bd9Sstevel@tonic-gate       opt_field(val->client,1,asn1_decode_realm,NULL);
8017c478bd9Sstevel@tonic-gate       opt_field(val->client,2,asn1_decode_principal_name,NULL); }
8027c478bd9Sstevel@tonic-gate     opt_field(val->flags,3,asn1_decode_ticket_flags,0);
8037c478bd9Sstevel@tonic-gate     opt_field(val->times.authtime,4,asn1_decode_kerberos_time,0);
8047c478bd9Sstevel@tonic-gate     opt_field(val->times.starttime,5,asn1_decode_kerberos_time,0);
8057c478bd9Sstevel@tonic-gate     opt_field(val->times.endtime,6,asn1_decode_kerberos_time,0);
8067c478bd9Sstevel@tonic-gate     opt_field(val->times.renew_till,7,asn1_decode_kerberos_time,0);
8077c478bd9Sstevel@tonic-gate     if(tagnum == 8){
8087c478bd9Sstevel@tonic-gate       alloc_field(val->server,krb5_principal_data);
8097c478bd9Sstevel@tonic-gate       opt_field(val->server,8,asn1_decode_realm,NULL);
8107c478bd9Sstevel@tonic-gate       opt_field(val->server,9,asn1_decode_principal_name,NULL); }
8117c478bd9Sstevel@tonic-gate     opt_field(val->caddrs,10,asn1_decode_host_addresses,NULL);
8127c478bd9Sstevel@tonic-gate     end_structure();
8137c478bd9Sstevel@tonic-gate     val->magic = KV5M_CRED_INFO;
8147c478bd9Sstevel@tonic-gate   }
8157c478bd9Sstevel@tonic-gate   cleanup();
8167c478bd9Sstevel@tonic-gate }
8177c478bd9Sstevel@tonic-gate 
asn1_decode_sequence_of_pa_data(asn1buf * buf,krb5_pa_data *** val)8187c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_pa_data(asn1buf *buf, krb5_pa_data ***val)
8197c478bd9Sstevel@tonic-gate {
8207c478bd9Sstevel@tonic-gate   decode_array_body(krb5_pa_data,asn1_decode_pa_data);
8217c478bd9Sstevel@tonic-gate }
8227c478bd9Sstevel@tonic-gate 
asn1_decode_pa_data(asn1buf * buf,krb5_pa_data * val)8237c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_pa_data(asn1buf *buf, krb5_pa_data *val)
8247c478bd9Sstevel@tonic-gate {
8257c478bd9Sstevel@tonic-gate   setup();
8267c478bd9Sstevel@tonic-gate   { begin_structure();
8277c478bd9Sstevel@tonic-gate     get_field(val->pa_type,1,asn1_decode_int32);
8287c478bd9Sstevel@tonic-gate     get_lenfield(val->length,val->contents,2,asn1_decode_octetstring);
8297c478bd9Sstevel@tonic-gate     end_structure();
8307c478bd9Sstevel@tonic-gate     val->magic = KV5M_PA_DATA;
8317c478bd9Sstevel@tonic-gate   }
8327c478bd9Sstevel@tonic-gate   cleanup();
8337c478bd9Sstevel@tonic-gate }
8347c478bd9Sstevel@tonic-gate 
asn1_decode_last_req(asn1buf * buf,krb5_last_req_entry *** val)8357c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_last_req(asn1buf *buf, krb5_last_req_entry ***val)
8367c478bd9Sstevel@tonic-gate {
8377c478bd9Sstevel@tonic-gate   decode_array_body(krb5_last_req_entry,asn1_decode_last_req_entry);
8387c478bd9Sstevel@tonic-gate }
8397c478bd9Sstevel@tonic-gate 
asn1_decode_last_req_entry(asn1buf * buf,krb5_last_req_entry * val)8407c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_last_req_entry(asn1buf *buf, krb5_last_req_entry *val)
8417c478bd9Sstevel@tonic-gate {
8427c478bd9Sstevel@tonic-gate   setup();
8437c478bd9Sstevel@tonic-gate   { begin_structure();
8447c478bd9Sstevel@tonic-gate     get_field(val->lr_type,0,asn1_decode_int32);
8457c478bd9Sstevel@tonic-gate     get_field(val->value,1,asn1_decode_kerberos_time);
8467c478bd9Sstevel@tonic-gate     end_structure();
8477c478bd9Sstevel@tonic-gate     val->magic = KV5M_LAST_REQ_ENTRY;
8487c478bd9Sstevel@tonic-gate #ifdef KRB5_GENEROUS_LR_TYPE
8497c478bd9Sstevel@tonic-gate     /* If we are only a single byte wide and negative - fill in the
8507c478bd9Sstevel@tonic-gate        other bits */
8517c478bd9Sstevel@tonic-gate     if((val->lr_type & 0xffffff80U) == 0x80) val->lr_type |= 0xffffff00U;
8527c478bd9Sstevel@tonic-gate #endif
8537c478bd9Sstevel@tonic-gate   }
8547c478bd9Sstevel@tonic-gate   cleanup();
8557c478bd9Sstevel@tonic-gate }
8567c478bd9Sstevel@tonic-gate 
asn1_decode_sequence_of_enctype(asn1buf * buf,int * num,krb5_enctype ** val)8577c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_enctype(asn1buf *buf, int *num, krb5_enctype **val)
8587c478bd9Sstevel@tonic-gate {
8597c478bd9Sstevel@tonic-gate   asn1_error_code retval;
8607c478bd9Sstevel@tonic-gate   { sequence_of(buf);
8617c478bd9Sstevel@tonic-gate     while(asn1buf_remains(&seqbuf,seqofindef) > 0){
8627c478bd9Sstevel@tonic-gate       size++;
8637c478bd9Sstevel@tonic-gate       if (*val == NULL)
8647c478bd9Sstevel@tonic-gate         *val = (krb5_enctype*)malloc(size*sizeof(krb5_enctype));
8657c478bd9Sstevel@tonic-gate       else
8667c478bd9Sstevel@tonic-gate         *val = (krb5_enctype*)realloc(*val,size*sizeof(krb5_enctype));
8677c478bd9Sstevel@tonic-gate       if(*val == NULL) return ENOMEM;
8687c478bd9Sstevel@tonic-gate       retval = asn1_decode_enctype(&seqbuf,&((*val)[size-1]));
8697c478bd9Sstevel@tonic-gate       if(retval) return retval;
8707c478bd9Sstevel@tonic-gate     }
8717c478bd9Sstevel@tonic-gate     *num = size;
8727c478bd9Sstevel@tonic-gate     end_sequence_of(buf);
8737c478bd9Sstevel@tonic-gate   }
8747c478bd9Sstevel@tonic-gate   cleanup();
8757c478bd9Sstevel@tonic-gate }
8767c478bd9Sstevel@tonic-gate 
asn1_decode_sequence_of_checksum(asn1buf * buf,krb5_checksum *** val)8777c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_checksum(asn1buf *buf, krb5_checksum ***val)
8787c478bd9Sstevel@tonic-gate {
8797c478bd9Sstevel@tonic-gate   decode_array_body(krb5_checksum, asn1_decode_checksum);
8807c478bd9Sstevel@tonic-gate }
8817c478bd9Sstevel@tonic-gate 
asn1_decode_etype_info2_entry(asn1buf * buf,krb5_etype_info_entry * val)8827c478bd9Sstevel@tonic-gate static asn1_error_code asn1_decode_etype_info2_entry(asn1buf *buf, krb5_etype_info_entry *val )
8837c478bd9Sstevel@tonic-gate {
88486aa8097Smp   /*
88586aa8097Smp    * Solaris Kerberos:
88686aa8097Smp    * Use a temporary char* (tmpp) in place of val->salt when calling
88786aa8097Smp    * get_lenfield(). val->salt cannot be cast to a char* as casting will not
88886aa8097Smp    * produce an lvalue. Use the new value pointed to by tmpp as the value for
88986aa8097Smp    * val->salt.
89086aa8097Smp    */
891505d05c7Sgtb   char *tmpp;
8927c478bd9Sstevel@tonic-gate   setup();
8937c478bd9Sstevel@tonic-gate   { begin_structure();
8947c478bd9Sstevel@tonic-gate     get_field(val->etype,0,asn1_decode_enctype);
8957c478bd9Sstevel@tonic-gate     if (tagnum == 1) {
896