1505d05c7Sgtb /*
2159d09a2SMark 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
855fea89dSDan Cross  *
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.
1655fea89dSDan Cross  *
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   }
14255fea89dSDan Cross 
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 
167159d09a2SMark Phalan /*
168159d09a2SMark Phalan  * Deal with implicitly tagged fields
169159d09a2SMark Phalan  */
170159d09a2SMark Phalan #define get_implicit_octet_string(len, var, tagexpect)		    \
171159d09a2SMark Phalan   if (tagnum != (tagexpect)) return ASN1_MISSING_FIELD;		    \
172159d09a2SMark Phalan   if (asn1class != CONTEXT_SPECIFIC || construction != PRIMITIVE)   \
173159d09a2SMark Phalan      return ASN1_BAD_ID;					    \
174159d09a2SMark Phalan   retval = asn1buf_remove_octetstring(&subbuf, taglen, &(var));	    \
175159d09a2SMark Phalan   if (retval) return retval;					    \
176159d09a2SMark Phalan   (len) = taglen;						    \
177159d09a2SMark Phalan   next_tag()
178159d09a2SMark Phalan 
179159d09a2SMark Phalan #define opt_implicit_octet_string(len, var, tagexpect)		    \
180159d09a2SMark Phalan   if (tagnum == (tagexpect)) {					    \
181159d09a2SMark Phalan     if (asn1class != CONTEXT_SPECIFIC || construction != PRIMITIVE) \
182159d09a2SMark Phalan 	return ASN1_BAD_ID;					    \
183159d09a2SMark Phalan     retval = asn1buf_remove_octetstring(&subbuf, taglen, &(var));   \
184159d09a2SMark Phalan     if (retval) return retval;					    \
185159d09a2SMark Phalan     (len) = taglen;						    \
186159d09a2SMark Phalan     next_tag();							    \
187159d09a2SMark Phalan   } else { (len) = 0; (var) = NULL; }
188159d09a2SMark 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 
206159d09a2SMark Phalan /*
207159d09a2SMark Phalan  * This is used for structures which have no tagging.
208159d09a2SMark Phalan  * It is the same as begin_structure() except next_tag()
209159d09a2SMark Phalan  * is not called.
210159d09a2SMark Phalan  */
211159d09a2SMark Phalan #define begin_structure_no_tag()				\
212159d09a2SMark Phalan   asn1buf subbuf;						\
213159d09a2SMark Phalan   int seqindef;							\
214159d09a2SMark Phalan   int indef;							\
215159d09a2SMark Phalan   retval = asn1_get_sequence(buf, &length, &seqindef);		\
216159d09a2SMark Phalan   if (retval) return retval;					\
217159d09a2SMark Phalan   retval = asn1buf_imbed(&subbuf, buf, length, seqindef);	\
218159d09a2SMark Phalan   if (retval) return retval
219159d09a2SMark 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 
226159d09a2SMark Phalan /*
227159d09a2SMark Phalan  * begin_choice
228159d09a2SMark Phalan  *
229159d09a2SMark Phalan  * Declares some variables for decoding CHOICE types.  This is meant
230159d09a2SMark Phalan  * to be called in an inner block that ends with a call to
231159d09a2SMark Phalan  * end_choice().
232159d09a2SMark Phalan  */
233159d09a2SMark Phalan #define begin_choice()						\
234159d09a2SMark Phalan   asn1buf subbuf;						\
235159d09a2SMark Phalan   int seqindef;							\
236159d09a2SMark Phalan   int indef;							\
237159d09a2SMark Phalan   taginfo t;							\
238159d09a2SMark Phalan   retval = asn1_get_tag_2(buf, &t);				\
239159d09a2SMark Phalan   if (retval) return retval;					\
240159d09a2SMark Phalan   tagnum = t.tagnum;                                            \
241159d09a2SMark Phalan   taglen = t.length;                                            \
242159d09a2SMark Phalan   indef = t.indef;                                              \
243159d09a2SMark Phalan   length = t.length;                                            \
244159d09a2SMark Phalan   seqindef = t.indef;                                           \
245159d09a2SMark Phalan   asn1class = t.asn1class;					\
246159d09a2SMark Phalan   construction = t.construction;				\
247159d09a2SMark Phalan   retval = asn1buf_imbed(&subbuf, buf, length, seqindef);	\
248159d09a2SMark Phalan   if (retval) return retval
249159d09a2SMark Phalan 
250159d09a2SMark Phalan /* skip trailing garbage */
251159d09a2SMark Phalan #define end_choice()						\
252159d09a2SMark Phalan   length -= t.length;						\
253159d09a2SMark Phalan   retval = asn1buf_sync(buf, &subbuf, t.asn1class, t.tagnum,	\
254159d09a2SMark Phalan 			length, t.indef, seqindef);		\
255159d09a2SMark Phalan   if (retval) return retval
256159d09a2SMark 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;
35555fea89dSDan Cross 
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;
41055fea89dSDan Cross 
4117c478bd9Sstevel@tonic-gate   retval = asn1_decode_unsigned_integer(buf,&n);
4127c478bd9Sstevel@tonic-gate   if(retval) return retval;
41355fea89dSDan Cross 
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);
43255fea89dSDan Cross 
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),
444159d09a2SMark 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. */
529*446697a6SToomas Soome     f &= VALID_UINT_BITS << 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;
604159d09a2SMark 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();
62755fea89dSDan Cross   {
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
73155fea89dSDan Cross 
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
74155fea89dSDan Cross 
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) {
896505d05c7Sgtb       get_lenfield(val->length,tmpp,1,asn1_decode_generalstring);
89786aa8097Smp       val->salt = (krb5_octet*)tmpp;	/* SUNW14resync hack */
8987c478bd9Sstevel@tonic-gate     } else {
8997c478bd9Sstevel@tonic-gate 	    val->length = KRB5_ETYPE_NO_SALT;
9007c478bd9Sstevel@tonic-gate 	    val->salt = 0;
9017c478bd9Sstevel@tonic-gate     }
9027c478bd9Sstevel@tonic-gate     if ( tagnum ==2) {
9037c478bd9Sstevel@tonic-gate       krb5_octet *params ;
9047c478bd9Sstevel@tonic-gate       get_lenfield( val->s2kparams.length, params,
9057c478bd9Sstevel@tonic-gate 		      2, asn1_decode_octetstring);
9067c478bd9Sstevel@tonic-gate       val->s2kparams.data = ( char *) params;
9077c478bd9Sstevel@tonic-gate     } else {
9087c478bd9Sstevel@tonic-gate 	val->s2kparams.data = NULL;
9097c478bd9Sstevel@tonic-gate 	val->s2kparams.length = 0;
9107c478bd9Sstevel@tonic-gate     }
9117c478bd9Sstevel@tonic-gate     end_structure();
9127c478bd9Sstevel@tonic-gate     val->magic = KV5M_ETYPE_INFO_ENTRY;
9137c478bd9Sstevel@tonic-gate   }
9147c478bd9Sstevel@tonic-gate   cleanup();
9157c478bd9Sstevel@tonic-gate }
9167c478bd9Sstevel@tonic-gate 
asn1_decode_etype_info2_entry_1_3(asn1buf * buf,krb5_etype_info_entry * val)9177c478bd9Sstevel@tonic-gate static asn1_error_code asn1_decode_etype_info2_entry_1_3(asn1buf *buf, krb5_etype_info_entry *val )
9187c478bd9Sstevel@tonic-gate {
9197c478bd9Sstevel@tonic-gate   setup();
9207c478bd9Sstevel@tonic-gate   { begin_structure();
9217c478bd9Sstevel@tonic-gate     get_field(val->etype,0,asn1_decode_enctype);
9227c478bd9Sstevel@tonic-gate     if (tagnum == 1) {
9237c478bd9Sstevel@tonic-gate 	    get_lenfield(val->length,val->salt,1,asn1_decode_octetstring);
9247c478bd9Sstevel@tonic-gate     } else {
9257c478bd9Sstevel@tonic-gate 	    val->length = KRB5_ETYPE_NO_SALT;
9267c478bd9Sstevel@tonic-gate 	    val->salt = 0;
9277c478bd9Sstevel@tonic-gate     }
9287c478bd9Sstevel@tonic-gate     if ( tagnum ==2) {
9297c478bd9Sstevel@tonic-gate       krb5_octet *params ;
9307c478bd9Sstevel@tonic-gate       get_lenfield( val->s2kparams.length, params,
9317c478bd9Sstevel@tonic-gate 		      2, asn1_decode_octetstring);
9327c478bd9Sstevel@tonic-gate       val->s2kparams.data = ( char *) params;
9337c478bd9Sstevel@tonic-gate     } else {
9347c478bd9Sstevel@tonic-gate 	val->s2kparams.data = NULL;
9357c478bd9Sstevel@tonic-gate 	val->s2kparams.length = 0;
9367c478bd9Sstevel@tonic-gate     }
9377c478bd9Sstevel@tonic-gate     end_structure();
9387c478bd9Sstevel@tonic-gate     val->magic = KV5M_ETYPE_INFO_ENTRY;
9397c478bd9Sstevel@tonic-gate   }
9407c478bd9Sstevel@tonic-gate   cleanup();
9417c478bd9Sstevel@tonic-gate }
9427c478bd9Sstevel@tonic-gate 
943505d05c7Sgtb 
asn1_decode_etype_info_entry(asn1buf * buf,krb5_etype_info_entry * val)944505d05c7Sgtb static asn1_error_code asn1_decode_etype_info_entry(asn1buf *buf, krb5_etype_info_entry *val )
9457c478bd9Sstevel@tonic-gate {
9467c478bd9Sstevel@tonic-gate   setup();
9477c478bd9Sstevel@tonic-gate   { begin_structure();
9487c478bd9Sstevel@tonic-gate     get_field(val->etype,0,asn1_decode_enctype);
9497c478bd9Sstevel@tonic-gate     if (tagnum == 1) {
9507c478bd9Sstevel@tonic-gate 	    get_lenfield(val->length,val->salt,1,asn1_decode_octetstring);
9517c478bd9Sstevel@tonic-gate     } else {
9527c478bd9Sstevel@tonic-gate 	    val->length = KRB5_ETYPE_NO_SALT;
9537c478bd9Sstevel@tonic-gate 	    val->salt = 0;
9547c478bd9Sstevel@tonic-gate     }
9557c478bd9Sstevel@tonic-gate     val->s2kparams.data = NULL;
9567c478bd9Sstevel@tonic-gate     val->s2kparams.length = 0;
95755fea89dSDan Cross 
9587c478bd9Sstevel@tonic-gate     end_structure();
9597c478bd9Sstevel@tonic-gate     val->magic = KV5M_ETYPE_INFO_ENTRY;
9607c478bd9Sstevel@tonic-gate   }
9617c478bd9Sstevel@tonic-gate   cleanup();
9627c478bd9Sstevel@tonic-gate }
9637c478bd9Sstevel@tonic-gate 
asn1_decode_etype_info(asn1buf * buf,krb5_etype_info_entry *** val)9647c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_etype_info(asn1buf *buf, krb5_etype_info_entry ***val )
9657c478bd9Sstevel@tonic-gate {
9667c478bd9Sstevel@tonic-gate   decode_array_body(krb5_etype_info_entry,asn1_decode_etype_info_entry);
9677c478bd9Sstevel@tonic-gate }
9687c478bd9Sstevel@tonic-gate 
asn1_decode_etype_info2(asn1buf * buf,krb5_etype_info_entry *** val,krb5_boolean v1_3_behavior)9697c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_etype_info2(asn1buf *buf, krb5_etype_info_entry ***val ,
9707c478bd9Sstevel@tonic-gate 					krb5_boolean v1_3_behavior)
9717c478bd9Sstevel@tonic-gate {
9727c478bd9Sstevel@tonic-gate     if (v1_3_behavior) {
9737c478bd9Sstevel@tonic-gate 	decode_array_body(krb5_etype_info_entry,
9747c478bd9Sstevel@tonic-gate 			  asn1_decode_etype_info2_entry_1_3);
9757c478bd9Sstevel@tonic-gate     } else {
9767c478bd9Sstevel@tonic-gate 	decode_array_body(krb5_etype_info_entry,
9777c478bd9Sstevel@tonic-gate 			  asn1_decode_etype_info2_entry);
9787c478bd9Sstevel@tonic-gate     }
9797c478bd9Sstevel@tonic-gate }
9807c478bd9Sstevel@tonic-gate 
asn1_decode_passwdsequence(asn1buf * buf,passwd_phrase_element * val)9817c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_passwdsequence(asn1buf *buf, passwd_phrase_element *val)
9827c478bd9Sstevel@tonic-gate {
9837c478bd9Sstevel@tonic-gate   setup();
9847c478bd9Sstevel@tonic-gate   { begin_structure();
9857c478bd9Sstevel@tonic-gate     alloc_field(val->passwd,krb5_data);
9867c478bd9Sstevel@tonic-gate     get_lenfield(val->passwd->length,val->passwd->data,
9877c478bd9Sstevel@tonic-gate 		 0,asn1_decode_charstring);
9887c478bd9Sstevel@tonic-gate     val->passwd->magic = KV5M_DATA;
9897c478bd9Sstevel@tonic-gate     alloc_field(val->phrase,krb5_data);
9907c478bd9Sstevel@tonic-gate     get_lenfield(val->phrase->length,val->phrase->data,
9917c478bd9Sstevel@tonic-gate 		 1,asn1_decode_charstring);
9927c478bd9Sstevel@tonic-gate     val->phrase->magic = KV5M_DATA;
9937c478bd9Sstevel@tonic-gate     end_structure();
9947c478bd9Sstevel@tonic-gate     val->magic = KV5M_PASSWD_PHRASE_ELEMENT;
9957c478bd9Sstevel@tonic-gate   }
9967c478bd9Sstevel@tonic-gate   cleanup();
9977c478bd9Sstevel@tonic-gate }
9987c478bd9Sstevel@tonic-gate 
asn1_decode_sequence_of_passwdsequence(asn1buf * buf,passwd_phrase_element *** val)9997c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_passwdsequence(asn1buf *buf, passwd_phrase_element ***val)
10007c478bd9Sstevel@tonic-gate {
10017c478bd9Sstevel@tonic-gate   decode_array_body(passwd_phrase_element,asn1_decode_passwdsequence);
10027c478bd9Sstevel@tonic-gate }
10037c478bd9Sstevel@tonic-gate 
asn1_decode_sam_flags(asn1buf * buf,krb5_flags * val)10047c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_flags(asn1buf *buf, krb5_flags *val)
10057c478bd9Sstevel@tonic-gate { return asn1_decode_krb5_flags(buf,val); }
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate #define opt_string(val,n,fn) opt_lenfield((val).length,(val).data,n,fn)
10087c478bd9Sstevel@tonic-gate #define opt_cksum(var,tagexpect,decoder)\
10097c478bd9Sstevel@tonic-gate if(tagnum == (tagexpect)){\
10107c478bd9Sstevel@tonic-gate   get_field_body(var,decoder); }\
10117c478bd9Sstevel@tonic-gate else var.length = 0
10127c478bd9Sstevel@tonic-gate 
asn1_decode_sam_challenge(asn1buf * buf,krb5_sam_challenge * val)10137c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_challenge(asn1buf *buf, krb5_sam_challenge *val)
10147c478bd9Sstevel@tonic-gate {
10157c478bd9Sstevel@tonic-gate   setup();
10167c478bd9Sstevel@tonic-gate   { begin_structure();
10177c478bd9Sstevel@tonic-gate     get_field(val->sam_type,0,asn1_decode_int32);
10187c478bd9Sstevel@tonic-gate     get_field(val->sam_flags,1,asn1_decode_sam_flags);
10197c478bd9Sstevel@tonic-gate     opt_string(val->sam_type_name,2,asn1_decode_charstring);
10207c478bd9Sstevel@tonic-gate     opt_string(val->sam_track_id,3,asn1_decode_charstring);
10217c478bd9Sstevel@tonic-gate     opt_string(val->sam_challenge_label,4,asn1_decode_charstring);
10227c478bd9Sstevel@tonic-gate     opt_string(val->sam_challenge,5,asn1_decode_charstring);
10237c478bd9Sstevel@tonic-gate     opt_string(val->sam_response_prompt,6,asn1_decode_charstring);
10247c478bd9Sstevel@tonic-gate     opt_string(val->sam_pk_for_sad,7,asn1_decode_charstring);
10257c478bd9Sstevel@tonic-gate     opt_field(val->sam_nonce,8,asn1_decode_int32,0);
10267c478bd9Sstevel@tonic-gate     opt_cksum(val->sam_cksum,9,asn1_decode_checksum);
10277c478bd9Sstevel@tonic-gate     end_structure();
10287c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAM_CHALLENGE;
10297c478bd9Sstevel@tonic-gate   }
10307c478bd9Sstevel@tonic-gate   cleanup();
10317c478bd9Sstevel@tonic-gate }
asn1_decode_sam_challenge_2(asn1buf * buf,krb5_sam_challenge_2 * val)10327c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_challenge_2(asn1buf *buf, krb5_sam_challenge_2 *val)
10337c478bd9Sstevel@tonic-gate {
10347c478bd9Sstevel@tonic-gate   setup();
10357c478bd9Sstevel@tonic-gate   { char *save, *end;
10367c478bd9Sstevel@tonic-gate     size_t alloclen;
10377c478bd9Sstevel@tonic-gate     begin_structure();
10387c478bd9Sstevel@tonic-gate     if (tagnum != 0) return ASN1_MISSING_FIELD;
103955fea89dSDan Cross     if (asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)
10407c478bd9Sstevel@tonic-gate       return ASN1_BAD_ID;
10417c478bd9Sstevel@tonic-gate     save = subbuf.next;
10427c478bd9Sstevel@tonic-gate     { sequence_of_no_tagvars(&subbuf);
10437c478bd9Sstevel@tonic-gate       unused_var(size);
10447c478bd9Sstevel@tonic-gate       end_sequence_of_no_tagvars(&subbuf);
10457c478bd9Sstevel@tonic-gate     }
10467c478bd9Sstevel@tonic-gate     end = subbuf.next;
10477c478bd9Sstevel@tonic-gate     alloclen = end - save;
10487c478bd9Sstevel@tonic-gate     if ((val->sam_challenge_2_body.data = (char *) malloc(alloclen)) == NULL)
10497c478bd9Sstevel@tonic-gate       return ENOMEM;
10507c478bd9Sstevel@tonic-gate     val->sam_challenge_2_body.length = alloclen;
10517c478bd9Sstevel@tonic-gate     memcpy(val->sam_challenge_2_body.data, save, alloclen);
10527c478bd9Sstevel@tonic-gate     next_tag();
10537c478bd9Sstevel@tonic-gate     get_field(val->sam_cksum, 1, asn1_decode_sequence_of_checksum);
10547c478bd9Sstevel@tonic-gate     end_structure();
10557c478bd9Sstevel@tonic-gate   }
10567c478bd9Sstevel@tonic-gate   cleanup();
10577c478bd9Sstevel@tonic-gate }
asn1_decode_sam_challenge_2_body(asn1buf * buf,krb5_sam_challenge_2_body * val)10587c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_challenge_2_body(asn1buf *buf, krb5_sam_challenge_2_body *val)
10597c478bd9Sstevel@tonic-gate {
10607c478bd9Sstevel@tonic-gate   setup();
10617c478bd9Sstevel@tonic-gate   { begin_structure();
10627c478bd9Sstevel@tonic-gate     get_field(val->sam_type,0,asn1_decode_int32);
10637c478bd9Sstevel@tonic-gate     get_field(val->sam_flags,1,asn1_decode_sam_flags);
10647c478bd9Sstevel@tonic-gate     opt_string(val->sam_type_name,2,asn1_decode_charstring);
10657c478bd9Sstevel@tonic-gate     opt_string(val->sam_track_id,3,asn1_decode_charstring);
10667c478bd9Sstevel@tonic-gate     opt_string(val->sam_challenge_label,4,asn1_decode_charstring);
10677c478bd9Sstevel@tonic-gate     opt_string(val->sam_challenge,5,asn1_decode_charstring);
10687c478bd9Sstevel@tonic-gate     opt_string(val->sam_response_prompt,6,asn1_decode_charstring);
10697c478bd9Sstevel@tonic-gate     opt_string(val->sam_pk_for_sad,7,asn1_decode_charstring);
10707c478bd9Sstevel@tonic-gate     get_field(val->sam_nonce,8,asn1_decode_int32);
10717c478bd9Sstevel@tonic-gate     get_field(val->sam_etype, 9, asn1_decode_int32);
10727c478bd9Sstevel@tonic-gate     end_structure();
10737c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAM_CHALLENGE;
10747c478bd9Sstevel@tonic-gate   }
10757c478bd9Sstevel@tonic-gate   cleanup();
10767c478bd9Sstevel@tonic-gate }
asn1_decode_enc_sam_key(asn1buf * buf,krb5_sam_key * val)10777c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_enc_sam_key(asn1buf *buf, krb5_sam_key *val)
10787c478bd9Sstevel@tonic-gate {
10797c478bd9Sstevel@tonic-gate   setup();
10807c478bd9Sstevel@tonic-gate   { begin_structure();
10817c478bd9Sstevel@tonic-gate     /* alloc_field(val->sam_key,krb5_keyblock); */
10827c478bd9Sstevel@tonic-gate     get_field(val->sam_key,0,asn1_decode_encryption_key);
10837c478bd9Sstevel@tonic-gate     end_structure();
10847c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAM_KEY;
10857c478bd9Sstevel@tonic-gate   }
10867c478bd9Sstevel@tonic-gate   cleanup();
10877c478bd9Sstevel@tonic-gate }
10887c478bd9Sstevel@tonic-gate 
asn1_decode_enc_sam_response_enc(asn1buf * buf,krb5_enc_sam_response_enc * val)10897c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_enc_sam_response_enc(asn1buf *buf, krb5_enc_sam_response_enc *val)
10907c478bd9Sstevel@tonic-gate {
10917c478bd9Sstevel@tonic-gate   setup();
10927c478bd9Sstevel@tonic-gate   { begin_structure();
10937c478bd9Sstevel@tonic-gate     opt_field(val->sam_nonce,0,asn1_decode_int32,0);
10947c478bd9Sstevel@tonic-gate     opt_field(val->sam_timestamp,1,asn1_decode_kerberos_time,0);
10957c478bd9Sstevel@tonic-gate     opt_field(val->sam_usec,2,asn1_decode_int32,0);
10967c478bd9Sstevel@tonic-gate     opt_string(val->sam_sad,3,asn1_decode_charstring);
10977c478bd9Sstevel@tonic-gate     end_structure();
10987c478bd9Sstevel@tonic-gate     val->magic = KV5M_ENC_SAM_RESPONSE_ENC;
10997c478bd9Sstevel@tonic-gate   }
11007c478bd9Sstevel@tonic-gate   cleanup();
11017c478bd9Sstevel@tonic-gate }
11027c478bd9Sstevel@tonic-gate 
asn1_decode_enc_sam_response_enc_2(asn1buf * buf,krb5_enc_sam_response_enc_2 * val)11037c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_enc_sam_response_enc_2(asn1buf *buf, krb5_enc_sam_response_enc_2 *val)
11047c478bd9Sstevel@tonic-gate {
11057c478bd9Sstevel@tonic-gate   setup();
11067c478bd9Sstevel@tonic-gate   { begin_structure();
11077c478bd9Sstevel@tonic-gate     get_field(val->sam_nonce,0,asn1_decode_int32);
11087c478bd9Sstevel@tonic-gate     opt_string(val->sam_sad,1,asn1_decode_charstring);
11097c478bd9Sstevel@tonic-gate     end_structure();
11107c478bd9Sstevel@tonic-gate     val->magic = KV5M_ENC_SAM_RESPONSE_ENC_2;
11117c478bd9Sstevel@tonic-gate   }
11127c478bd9Sstevel@tonic-gate   cleanup();
11137c478bd9Sstevel@tonic-gate }
11147c478bd9Sstevel@tonic-gate 
11157c478bd9Sstevel@tonic-gate #define opt_encfield(fld,tag,fn) \
11167c478bd9Sstevel@tonic-gate     if(tagnum == tag){ \
11177c478bd9Sstevel@tonic-gate       get_field(fld,tag,fn); } \
11187c478bd9Sstevel@tonic-gate     else{\
11197c478bd9Sstevel@tonic-gate       fld.magic = 0;\
11207c478bd9Sstevel@tonic-gate       fld.enctype = 0;\
11217c478bd9Sstevel@tonic-gate       fld.kvno = 0;\
11227c478bd9Sstevel@tonic-gate       fld.ciphertext.data = NULL;\
11237c478bd9Sstevel@tonic-gate       fld.ciphertext.length = 0;\
11247c478bd9Sstevel@tonic-gate     }
11257c478bd9Sstevel@tonic-gate 
asn1_decode_sam_response(asn1buf * buf,krb5_sam_response * val)11267c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_response(asn1buf *buf, krb5_sam_response *val)
11277c478bd9Sstevel@tonic-gate {
11287c478bd9Sstevel@tonic-gate   setup();
11297c478bd9Sstevel@tonic-gate   { begin_structure();
11307c478bd9Sstevel@tonic-gate     get_field(val->sam_type,0,asn1_decode_int32);
11317c478bd9Sstevel@tonic-gate     get_field(val->sam_flags,1,asn1_decode_sam_flags);
11327c478bd9Sstevel@tonic-gate     opt_string(val->sam_track_id,2,asn1_decode_charstring);
11337c478bd9Sstevel@tonic-gate     opt_encfield(val->sam_enc_key,3,asn1_decode_encrypted_data);
11347c478bd9Sstevel@tonic-gate     get_field(val->sam_enc_nonce_or_ts,4,asn1_decode_encrypted_data);
11357c478bd9Sstevel@tonic-gate     opt_field(val->sam_nonce,5,asn1_decode_int32,0);
11367c478bd9Sstevel@tonic-gate     opt_field(val->sam_patimestamp,6,asn1_decode_kerberos_time,0);
11377c478bd9Sstevel@tonic-gate     end_structure();
11387c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAM_RESPONSE;
11397c478bd9Sstevel@tonic-gate   }
11407c478bd9Sstevel@tonic-gate   cleanup();
11417c478bd9Sstevel@tonic-gate }
11427c478bd9Sstevel@tonic-gate 
asn1_decode_sam_response_2(asn1buf * buf,krb5_sam_response_2 * val)11437c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_response_2(asn1buf *buf, krb5_sam_response_2 *val)
11447c478bd9Sstevel@tonic-gate {
11457c478bd9Sstevel@tonic-gate   setup();
11467c478bd9Sstevel@tonic-gate   { begin_structure();
11477c478bd9Sstevel@tonic-gate     get_field(val->sam_type,0,asn1_decode_int32);
11487c478bd9Sstevel@tonic-gate     get_field(val->sam_flags,1,asn1_decode_sam_flags);
11497c478bd9Sstevel@tonic-gate     opt_string(val->sam_track_id,2,asn1_decode_charstring);
11507c478bd9Sstevel@tonic-gate     get_field(val->sam_enc_nonce_or_sad,3,asn1_decode_encrypted_data);
11517c478bd9Sstevel@tonic-gate     get_field(val->sam_nonce,4,asn1_decode_int32);
11527c478bd9Sstevel@tonic-gate     end_structure();
11537c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAM_RESPONSE;
11547c478bd9Sstevel@tonic-gate   }
11557c478bd9Sstevel@tonic-gate   cleanup();
11567c478bd9Sstevel@tonic-gate }
11577c478bd9Sstevel@tonic-gate 
11587c478bd9Sstevel@tonic-gate 
asn1_decode_predicted_sam_response(asn1buf * buf,krb5_predicted_sam_response * val)11597c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_predicted_sam_response(asn1buf *buf, krb5_predicted_sam_response *val)
11607c478bd9Sstevel@tonic-gate {
11617c478bd9Sstevel@tonic-gate   setup();
11627c478bd9Sstevel@tonic-gate   { begin_structure();
11637c478bd9Sstevel@tonic-gate     get_field(val->sam_key,0,asn1_decode_encryption_key);
11647c478bd9Sstevel@tonic-gate     get_field(val->sam_flags,1,asn1_decode_sam_flags);
11657c478bd9Sstevel@tonic-gate     get_field(val->stime,2,asn1_decode_kerberos_time);
11667c478bd9Sstevel@tonic-gate     get_field(val->susec,3,asn1_decode_int32);
11677c478bd9Sstevel@tonic-gate     alloc_field(val->client,krb5_principal_data);
11687c478bd9Sstevel@tonic-gate     get_field(val->client,4,asn1_decode_realm);
11697c478bd9Sstevel@tonic-gate     get_field(val->client,5,asn1_decode_principal_name);
11707c478bd9Sstevel@tonic-gate     opt_string(val->msd,6,asn1_decode_charstring); /* should be octet */
11717c478bd9Sstevel@tonic-gate     end_structure();
11727c478bd9Sstevel@tonic-gate     val->magic = KV5M_PREDICTED_SAM_RESPONSE;
11737c478bd9Sstevel@tonic-gate   }
11747c478bd9Sstevel@tonic-gate   cleanup();
11757c478bd9Sstevel@tonic-gate }
1176159d09a2SMark Phalan 
1177159d09a2SMark Phalan /* PKINIT */
1178159d09a2SMark Phalan 
asn1_decode_external_principal_identifier(asn1buf * buf,krb5_external_principal_identifier * val)1179159d09a2SMark Phalan asn1_error_code asn1_decode_external_principal_identifier(asn1buf *buf, krb5_external_principal_identifier *val)
1180159d09a2SMark Phalan {
1181159d09a2SMark Phalan     setup();
1182159d09a2SMark Phalan     {
1183159d09a2SMark Phalan       begin_structure();
1184159d09a2SMark Phalan       opt_implicit_octet_string(val->subjectName.length, val->subjectName.data, 0);
1185159d09a2SMark Phalan       opt_implicit_octet_string(val->issuerAndSerialNumber.length, val->issuerAndSerialNumber.data, 1);
1186159d09a2SMark Phalan       opt_implicit_octet_string(val->subjectKeyIdentifier.length, val->subjectKeyIdentifier.data, 2);
1187159d09a2SMark Phalan       end_structure();
1188159d09a2SMark Phalan     }
1189159d09a2SMark Phalan     cleanup();
1190159d09a2SMark Phalan }
1191159d09a2SMark Phalan 
asn1_decode_sequence_of_external_principal_identifier(asn1buf * buf,krb5_external_principal_identifier *** val)1192159d09a2SMark Phalan asn1_error_code asn1_decode_sequence_of_external_principal_identifier(asn1buf *buf, krb5_external_principal_identifier ***val)
1193159d09a2SMark Phalan {
1194159d09a2SMark Phalan     decode_array_body(krb5_external_principal_identifier,asn1_decode_external_principal_identifier);
1195159d09a2SMark Phalan }
1196159d09a2SMark Phalan 
asn1_decode_pa_pk_as_req(asn1buf * buf,krb5_pa_pk_as_req * val)1197159d09a2SMark Phalan asn1_error_code asn1_decode_pa_pk_as_req(asn1buf *buf, krb5_pa_pk_as_req *val)
1198159d09a2SMark Phalan {
1199159d09a2SMark Phalan   setup();
1200159d09a2SMark Phalan   {
1201159d09a2SMark Phalan     begin_structure();
1202159d09a2SMark Phalan     get_implicit_octet_string(val->signedAuthPack.length, val->signedAuthPack.data, 0);
1203159d09a2SMark Phalan     opt_field(val->trustedCertifiers, 1, asn1_decode_sequence_of_external_principal_identifier, NULL);
1204159d09a2SMark Phalan     opt_implicit_octet_string(val->kdcPkId.length, val->kdcPkId.data, 2);
1205159d09a2SMark Phalan     end_structure();
1206159d09a2SMark Phalan   }
1207159d09a2SMark Phalan   cleanup();
1208159d09a2SMark Phalan }
1209159d09a2SMark Phalan 
1210159d09a2SMark Phalan #if 0	/* XXX   This needs to be tested!!! XXX */
1211159d09a2SMark Phalan asn1_error_code asn1_decode_trusted_ca(asn1buf *buf, krb5_trusted_ca *val)
1212159d09a2SMark Phalan {
1213159d09a2SMark Phalan     setup();
121455fea89dSDan Cross     {
1215159d09a2SMark Phalan       char *start, *end;
1216159d09a2SMark Phalan       size_t alloclen;
1217159d09a2SMark Phalan 
1218159d09a2SMark Phalan       begin_explicit_choice();
1219159d09a2SMark Phalan       if (t.tagnum == choice_trusted_cas_principalName) {
1220159d09a2SMark Phalan 	val->choice = choice_trusted_cas_principalName;
1221159d09a2SMark Phalan       } else if (t.tagnum == choice_trusted_cas_caName) {
1222159d09a2SMark Phalan 	val->choice = choice_trusted_cas_caName;
1223159d09a2SMark Phalan 	start = subbuf.next;
1224159d09a2SMark Phalan 	{
1225159d09a2SMark Phalan 	  sequence_of_no_tagvars(&subbuf);
1226159d09a2SMark Phalan 	  unused_var(size);
1227159d09a2SMark Phalan 	  end_sequence_of_no_tagvars(&subbuf);
1228159d09a2SMark Phalan 	}
1229159d09a2SMark Phalan 	end = subbuf.next;
1230159d09a2SMark Phalan 	alloclen = end - start;
1231159d09a2SMark Phalan 	val->u.caName.data = malloc(alloclen);
1232159d09a2SMark Phalan 	if (val->u.caName.data == NULL)
1233159d09a2SMark Phalan 	  return ENOMEM;
1234159d09a2SMark Phalan 	memcpy(val->u.caName.data, start, alloclen);
1235159d09a2SMark Phalan 	val->u.caName.length = alloclen;
1236159d09a2SMark Phalan 	next_tag();
1237159d09a2SMark Phalan       } else if (t.tagnum == choice_trusted_cas_issuerAndSerial) {
1238159d09a2SMark Phalan 	val->choice = choice_trusted_cas_issuerAndSerial;
1239159d09a2SMark Phalan 	start = subbuf.next;
1240159d09a2SMark Phalan 	{
1241159d09a2SMark Phalan 	  sequence_of_no_tagvars(&subbuf);
1242159d09a2SMark Phalan 	  unused_var(size);
1243159d09a2SMark Phalan 	  end_sequence_of_no_tagvars(&subbuf);
1244159d09a2SMark Phalan 	}
1245159d09a2SMark Phalan 	end = subbuf.next;
1246159d09a2SMark Phalan 	alloclen = end - start;
1247159d09a2SMark Phalan 	val->u.issuerAndSerial.data = malloc(alloclen);
1248159d09a2SMark Phalan 	if (val->u.issuerAndSerial.data == NULL)
1249159d09a2SMark Phalan 	  return ENOMEM;
1250159d09a2SMark Phalan 	memcpy(val->u.issuerAndSerial.data, start, alloclen);
1251159d09a2SMark Phalan 	val->u.issuerAndSerial.length = alloclen;
1252159d09a2SMark Phalan 	next_tag();
1253159d09a2SMark Phalan       } else return ASN1_BAD_ID;
1254159d09a2SMark Phalan       end_explicit_choice();
1255159d09a2SMark Phalan     }
1256159d09a2SMark Phalan     cleanup();
1257159d09a2SMark Phalan }
1258159d09a2SMark Phalan #else
asn1_decode_trusted_ca(asn1buf * buf,krb5_trusted_ca * val)1259159d09a2SMark Phalan asn1_error_code asn1_decode_trusted_ca(asn1buf *buf, krb5_trusted_ca *val)
1260159d09a2SMark Phalan {
1261159d09a2SMark Phalan     setup();
1262159d09a2SMark Phalan     { begin_choice();
1263159d09a2SMark Phalan       if (tagnum == choice_trusted_cas_principalName) {
1264159d09a2SMark Phalan 	val->choice = choice_trusted_cas_principalName;
1265159d09a2SMark Phalan 	asn1_decode_krb5_principal_name(&subbuf, &(val->u.principalName));
1266159d09a2SMark Phalan       } else if (tagnum == choice_trusted_cas_caName) {
1267159d09a2SMark Phalan 	val->choice = choice_trusted_cas_caName;
1268159d09a2SMark Phalan 	get_implicit_octet_string(val->u.caName.length, val->u.caName.data, choice_trusted_cas_caName);
1269159d09a2SMark Phalan       } else if (tagnum == choice_trusted_cas_issuerAndSerial) {
1270159d09a2SMark Phalan 	val->choice = choice_trusted_cas_issuerAndSerial;
1271159d09a2SMark Phalan 	get_implicit_octet_string(val->u.issuerAndSerial.length, val->u.issuerAndSerial.data,
1272159d09a2SMark Phalan 				  choice_trusted_cas_issuerAndSerial);
1273159d09a2SMark Phalan       } else return ASN1_BAD_ID;
1274159d09a2SMark Phalan       end_choice();
1275159d09a2SMark Phalan     }
1276159d09a2SMark Phalan     cleanup();
1277159d09a2SMark Phalan }
1278159d09a2SMark Phalan #endif
1279159d09a2SMark Phalan 
asn1_decode_sequence_of_trusted_ca(asn1buf * buf,krb5_trusted_ca *** val)1280159d09a2SMark Phalan asn1_error_code asn1_decode_sequence_of_trusted_ca(asn1buf *buf, krb5_trusted_ca ***val)
1281159d09a2SMark Phalan {
1282159d09a2SMark Phalan     decode_array_body(krb5_trusted_ca, asn1_decode_trusted_ca);
1283159d09a2SMark Phalan }
1284159d09a2SMark Phalan 
asn1_decode_pa_pk_as_req_draft9(asn1buf * buf,krb5_pa_pk_as_req_draft9 * val)1285159d09a2SMark Phalan asn1_error_code asn1_decode_pa_pk_as_req_draft9(asn1buf *buf, krb5_pa_pk_as_req_draft9 *val)
1286159d09a2SMark Phalan {
1287159d09a2SMark Phalan   setup();
1288159d09a2SMark Phalan   { begin_structure();
1289159d09a2SMark Phalan     get_implicit_octet_string(val->signedAuthPack.length, val->signedAuthPack.data, 0);
1290159d09a2SMark Phalan     opt_field(val->trustedCertifiers, 1, asn1_decode_sequence_of_trusted_ca, NULL);
1291159d09a2SMark Phalan     opt_lenfield(val->kdcCert.length, val->kdcCert.data, 2, asn1_decode_octetstring);
1292159d09a2SMark Phalan     opt_lenfield(val->encryptionCert.length, val->encryptionCert.data, 2, asn1_decode_octetstring);
1293159d09a2SMark Phalan     end_structure();
1294159d09a2SMark Phalan   }
1295159d09a2SMark Phalan   cleanup();
1296159d09a2SMark Phalan }
1297159d09a2SMark Phalan 
asn1_decode_dh_rep_info(asn1buf * buf,krb5_dh_rep_info * val)1298159d09a2SMark Phalan asn1_error_code asn1_decode_dh_rep_info(asn1buf *buf, krb5_dh_rep_info *val)
1299159d09a2SMark Phalan {
1300159d09a2SMark Phalan     setup();
1301159d09a2SMark Phalan     { begin_structure();
1302159d09a2SMark Phalan       get_implicit_octet_string(val->dhSignedData.length, val->dhSignedData.data, 0);
1303159d09a2SMark Phalan 
1304159d09a2SMark Phalan       opt_lenfield(val->serverDHNonce.length, val->serverDHNonce.data, 1, asn1_decode_octetstring);
1305159d09a2SMark Phalan       end_structure();
1306159d09a2SMark Phalan     }
1307159d09a2SMark Phalan     cleanup();
1308159d09a2SMark Phalan }
1309159d09a2SMark Phalan 
asn1_decode_pk_authenticator(asn1buf * buf,krb5_pk_authenticator * val)1310159d09a2SMark Phalan asn1_error_code asn1_decode_pk_authenticator(asn1buf *buf, krb5_pk_authenticator *val)
1311159d09a2SMark Phalan {
1312159d09a2SMark Phalan     setup();
1313159d09a2SMark Phalan     { begin_structure();
1314159d09a2SMark Phalan       get_field(val->cusec, 0, asn1_decode_int32);
1315159d09a2SMark Phalan       get_field(val->ctime, 1, asn1_decode_kerberos_time);
1316159d09a2SMark Phalan       get_field(val->nonce, 2, asn1_decode_int32);
1317159d09a2SMark Phalan       opt_lenfield(val->paChecksum.length, val->paChecksum.contents, 3, asn1_decode_octetstring);
1318159d09a2SMark Phalan       end_structure();
1319159d09a2SMark Phalan     }
1320159d09a2SMark Phalan     cleanup();
1321159d09a2SMark Phalan }
1322159d09a2SMark Phalan 
asn1_decode_pk_authenticator_draft9(asn1buf * buf,krb5_pk_authenticator_draft9 * val)1323159d09a2SMark Phalan asn1_error_code asn1_decode_pk_authenticator_draft9(asn1buf *buf, krb5_pk_authenticator_draft9 *val)
1324159d09a2SMark Phalan {
1325159d09a2SMark Phalan     setup();
1326159d09a2SMark Phalan     { begin_structure();
1327159d09a2SMark Phalan       alloc_field(val->kdcName,krb5_principal_data);
132855fea89dSDan Cross       get_field(val->kdcName, 0, asn1_decode_principal_name);
132955fea89dSDan Cross       get_field(val->kdcName, 1, asn1_decode_realm);
1330159d09a2SMark Phalan       get_field(val->cusec, 2, asn1_decode_int32);
1331159d09a2SMark Phalan       get_field(val->ctime, 3, asn1_decode_kerberos_time);
1332159d09a2SMark Phalan       get_field(val->nonce, 4, asn1_decode_int32);
1333159d09a2SMark Phalan       end_structure();
1334159d09a2SMark Phalan     }
1335159d09a2SMark Phalan     cleanup();
1336159d09a2SMark Phalan }
1337159d09a2SMark Phalan 
asn1_decode_algorithm_identifier(asn1buf * buf,krb5_algorithm_identifier * val)1338159d09a2SMark Phalan asn1_error_code asn1_decode_algorithm_identifier(asn1buf *buf,  krb5_algorithm_identifier *val) {
1339159d09a2SMark Phalan 
1340159d09a2SMark Phalan   setup();
1341159d09a2SMark Phalan   { begin_structure_no_tag();
1342159d09a2SMark Phalan     /*
1343159d09a2SMark Phalan      * Forbid indefinite encoding because we don't read enough tag
1344159d09a2SMark Phalan      * information from the trailing octets ("ANY DEFINED BY") to
1345159d09a2SMark Phalan      * synchronize EOC tags, etc.
1346159d09a2SMark Phalan      */
1347159d09a2SMark Phalan     if (seqindef) return ASN1_BAD_FORMAT;
1348159d09a2SMark Phalan     /*
1349159d09a2SMark Phalan      * Set up tag variables because we don't actually call anything
1350159d09a2SMark Phalan      * that fetches tag info for us; it's all buried in the decoder
1351159d09a2SMark Phalan      * primitives.
1352159d09a2SMark Phalan      */
1353159d09a2SMark Phalan     tagnum = ASN1_TAGNUM_CEILING;
1354159d09a2SMark Phalan     asn1class = UNIVERSAL;
1355159d09a2SMark Phalan     construction = PRIMITIVE;
1356159d09a2SMark Phalan     taglen = 0;
1357159d09a2SMark Phalan     indef = 0;
135855fea89dSDan Cross     retval = asn1_decode_oid(&subbuf, &val->algorithm.length,
1359159d09a2SMark Phalan 			     &val->algorithm.data);
1360159d09a2SMark Phalan     if(retval) return retval;
1361159d09a2SMark Phalan     val->parameters.length = 0;
1362159d09a2SMark Phalan     val->parameters.data = NULL;
1363159d09a2SMark Phalan 
1364159d09a2SMark Phalan     if(length > subbuf.next - subbuf.base) {
1365159d09a2SMark Phalan       unsigned int size = length - (subbuf.next - subbuf.base);
136655fea89dSDan Cross       retval = asn1buf_remove_octetstring(&subbuf, size,
1367159d09a2SMark Phalan 					  &val->parameters.data);
1368159d09a2SMark Phalan       if(retval) return retval;
1369159d09a2SMark Phalan       val->parameters.length = size;
1370159d09a2SMark Phalan     }
137155fea89dSDan Cross 
1372159d09a2SMark Phalan     end_structure();
1373159d09a2SMark Phalan   }
137455fea89dSDan Cross   cleanup();
1375159d09a2SMark Phalan }
1376159d09a2SMark Phalan 
asn1_decode_subject_pk_info(asn1buf * buf,krb5_subject_pk_info * val)1377159d09a2SMark Phalan asn1_error_code asn1_decode_subject_pk_info(asn1buf *buf, krb5_subject_pk_info *val)
1378159d09a2SMark Phalan {
1379159d09a2SMark Phalan     asn1_octet unused;
1380159d09a2SMark Phalan     setup();
1381159d09a2SMark Phalan     { begin_structure_no_tag();
1382159d09a2SMark Phalan 
1383159d09a2SMark Phalan       retval = asn1_decode_algorithm_identifier(&subbuf, &val->algorithm);
1384159d09a2SMark Phalan       if (retval) return retval;
1385159d09a2SMark Phalan 
1386159d09a2SMark Phalan       /* SubjectPublicKey encoded as a BIT STRING */
1387159d09a2SMark Phalan       next_tag();
1388159d09a2SMark Phalan       if (asn1class != UNIVERSAL || construction != PRIMITIVE ||
1389159d09a2SMark Phalan           tagnum != ASN1_BITSTRING)
1390159d09a2SMark Phalan         return ASN1_BAD_ID;
1391159d09a2SMark Phalan 
1392159d09a2SMark Phalan       retval = asn1buf_remove_octet(&subbuf, &unused);
1393159d09a2SMark Phalan       if(retval) return retval;
1394159d09a2SMark Phalan 
1395159d09a2SMark Phalan       /* Number of unused bits must be between 0 and 7. */
1396159d09a2SMark Phalan       /* What to do if unused is not zero? */
1397159d09a2SMark Phalan       if (unused > 7) return ASN1_BAD_FORMAT;
1398159d09a2SMark Phalan       taglen--;
1399159d09a2SMark Phalan 
1400159d09a2SMark Phalan       val->subjectPublicKey.length = 0;
1401159d09a2SMark Phalan       val->subjectPublicKey.data = NULL;
140255fea89dSDan Cross       retval = asn1buf_remove_octetstring(&subbuf, taglen,
1403159d09a2SMark Phalan 					  &val->subjectPublicKey.data);
1404159d09a2SMark Phalan       if(retval) return retval;
1405159d09a2SMark Phalan       val->subjectPublicKey.length = taglen;
1406159d09a2SMark Phalan       /*
1407159d09a2SMark Phalan        * We didn't call any macro that does next_tag(); do so now to
1408159d09a2SMark Phalan        * preload tag of any trailing encodings.
1409159d09a2SMark Phalan        */
1410159d09a2SMark Phalan       next_tag();
1411159d09a2SMark Phalan       end_structure();
1412159d09a2SMark Phalan     }
1413159d09a2SMark Phalan     cleanup();
1414159d09a2SMark Phalan }
1415159d09a2SMark Phalan 
asn1_decode_sequence_of_algorithm_identifier(asn1buf * buf,krb5_algorithm_identifier *** val)1416159d09a2SMark Phalan asn1_error_code asn1_decode_sequence_of_algorithm_identifier(asn1buf *buf, krb5_algorithm_identifier ***val)
1417159d09a2SMark Phalan {
1418159d09a2SMark Phalan     decode_array_body(krb5_algorithm_identifier, asn1_decode_algorithm_identifier);
1419159d09a2SMark Phalan }
1420159d09a2SMark Phalan 
asn1_decode_kdc_dh_key_info(asn1buf * buf,krb5_kdc_dh_key_info * val)1421159d09a2SMark Phalan asn1_error_code asn1_decode_kdc_dh_key_info (asn1buf *buf, krb5_kdc_dh_key_info *val)
1422159d09a2SMark Phalan {
1423159d09a2SMark Phalan     setup();
1424159d09a2SMark Phalan     { begin_structure();
1425159d09a2SMark Phalan       retval = asn1buf_remove_octetstring(&subbuf, taglen, &val->subjectPublicKey.data);
1426159d09a2SMark Phalan       if(retval) return retval;
1427159d09a2SMark Phalan       val->subjectPublicKey.length = taglen;
1428159d09a2SMark Phalan       next_tag();
1429159d09a2SMark Phalan       get_field(val->nonce, 1, asn1_decode_int32);
1430159d09a2SMark Phalan       opt_field(val->dhKeyExpiration, 2, asn1_decode_kerberos_time, 0);
1431159d09a2SMark Phalan       end_structure();
1432159d09a2SMark Phalan     }
1433159d09a2SMark Phalan     cleanup();
1434159d09a2SMark Phalan }
1435159d09a2SMark Phalan 
asn1_decode_reply_key_pack(asn1buf * buf,krb5_reply_key_pack * val)1436159d09a2SMark Phalan asn1_error_code asn1_decode_reply_key_pack (asn1buf *buf, krb5_reply_key_pack *val)
1437159d09a2SMark Phalan {
1438159d09a2SMark Phalan     setup();
1439159d09a2SMark Phalan     { begin_structure();
1440159d09a2SMark Phalan       get_field(val->replyKey, 0, asn1_decode_encryption_key);
144155fea89dSDan Cross       get_field(val->asChecksum, 1, asn1_decode_checksum);
1442159d09a2SMark Phalan       end_structure();
1443159d09a2SMark Phalan     }
1444159d09a2SMark Phalan     cleanup();
1445159d09a2SMark Phalan }
1446159d09a2SMark Phalan 
asn1_decode_reply_key_pack_draft9(asn1buf * buf,krb5_reply_key_pack_draft9 * val)1447159d09a2SMark Phalan asn1_error_code asn1_decode_reply_key_pack_draft9 (asn1buf *buf, krb5_reply_key_pack_draft9 *val)
1448159d09a2SMark Phalan {
1449159d09a2SMark Phalan     setup();
1450159d09a2SMark Phalan     { begin_structure();
1451159d09a2SMark Phalan       get_field(val->replyKey, 0, asn1_decode_encryption_key);
145255fea89dSDan Cross       get_field(val->nonce, 1, asn1_decode_int32);
1453159d09a2SMark Phalan       end_structure();
1454159d09a2SMark Phalan     }
1455159d09a2SMark Phalan     cleanup();
1456159d09a2SMark Phalan }
1457159d09a2SMark Phalan 
1458159d09a2SMark Phalan 
asn1_decode_krb5_principal_name(asn1buf * buf,krb5_principal * val)1459159d09a2SMark Phalan asn1_error_code asn1_decode_krb5_principal_name (asn1buf *buf, krb5_principal *val)
1460159d09a2SMark Phalan {
1461159d09a2SMark Phalan     setup();
1462159d09a2SMark Phalan     { begin_structure();
1463159d09a2SMark Phalan       get_field(*val, 0, asn1_decode_realm);
1464159d09a2SMark Phalan       get_field(*val, 1, asn1_decode_principal_name);
1465159d09a2SMark Phalan       end_structure();
1466159d09a2SMark Phalan     }
1467159d09a2SMark Phalan     cleanup();
1468159d09a2SMark Phalan }
1469159d09a2SMark Phalan 
asn1_decode_auth_pack(asn1buf * buf,krb5_auth_pack * val)1470159d09a2SMark Phalan asn1_error_code asn1_decode_auth_pack(asn1buf *buf, krb5_auth_pack *val)
1471159d09a2SMark Phalan {
1472159d09a2SMark Phalan     setup();
1473159d09a2SMark Phalan     { begin_structure();
1474159d09a2SMark Phalan       get_field(val->pkAuthenticator, 0, asn1_decode_pk_authenticator);
147555fea89dSDan Cross       if (tagnum == 1) { alloc_field(val->clientPublicValue, krb5_subject_pk_info); }
1476159d09a2SMark Phalan       /* can't call opt_field because it does decoder(&subbuf, &(val)); */
147755fea89dSDan Cross       if (asn1buf_remains(&subbuf, seqindef)) {
147855fea89dSDan Cross 	if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)
147955fea89dSDan Cross 	    && (tagnum || taglen || asn1class != UNIVERSAL))
148055fea89dSDan Cross 	  return ASN1_BAD_ID;
148155fea89dSDan Cross 	if (tagnum == 1) {
148255fea89dSDan Cross 	  retval = asn1_decode_subject_pk_info(&subbuf,
1483159d09a2SMark Phalan 					       val->clientPublicValue);
1484159d09a2SMark Phalan 	  if (!taglen && indef) { get_eoc(); }
1485159d09a2SMark Phalan 	  next_tag();
148655fea89dSDan Cross 	} else val->clientPublicValue = NULL;
148755fea89dSDan Cross       }
1488159d09a2SMark Phalan       /* can't call opt_field because it does decoder(&subbuf, &(val)); */
1489159d09a2SMark Phalan       if (asn1buf_remains(&subbuf, seqindef)) {
1490159d09a2SMark Phalan         if (tagnum == 2) {
1491159d09a2SMark Phalan 	  asn1_decode_sequence_of_algorithm_identifier(&subbuf, &val->supportedCMSTypes);
1492159d09a2SMark Phalan 	  if (!taglen && indef) { get_eoc(); }
1493159d09a2SMark Phalan 	  next_tag();
1494159d09a2SMark Phalan 	} else val->supportedCMSTypes = NULL;
1495159d09a2SMark Phalan       }
1496159d09a2SMark Phalan       opt_lenfield(val->clientDHNonce.length, val->clientDHNonce.data, 3, asn1_decode_octetstring);
1497159d09a2SMark Phalan       end_structure();
1498159d09a2SMark Phalan     }
1499159d09a2SMark Phalan     cleanup();
1500159d09a2SMark Phalan }
1501159d09a2SMark Phalan 
asn1_decode_auth_pack_draft9(asn1buf * buf,krb5_auth_pack_draft9 * val)1502159d09a2SMark Phalan asn1_error_code asn1_decode_auth_pack_draft9(asn1buf *buf, krb5_auth_pack_draft9 *val)
1503159d09a2SMark Phalan {
1504159d09a2SMark Phalan     setup();
1505159d09a2SMark Phalan     { begin_structure();
1506159d09a2SMark Phalan       get_field(val->pkAuthenticator, 0, asn1_decode_pk_authenticator_draft9);
1507159d09a2SMark Phalan       if (tagnum == 1) {
150855fea89dSDan Cross 	alloc_field(val->clientPublicValue, krb5_subject_pk_info);
1509159d09a2SMark Phalan 	/* can't call opt_field because it does decoder(&subbuf, &(val)); */
151055fea89dSDan Cross 	if (asn1buf_remains(&subbuf, seqindef)) {
151155fea89dSDan Cross 	  if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)
151255fea89dSDan Cross 	    && (tagnum || taglen || asn1class != UNIVERSAL))
151355fea89dSDan Cross 	    return ASN1_BAD_ID;
151455fea89dSDan Cross 	  if (tagnum == 1) {
151555fea89dSDan Cross 	    retval = asn1_decode_subject_pk_info(&subbuf,
1516159d09a2SMark Phalan 					         val->clientPublicValue);
1517159d09a2SMark Phalan 	    if (!taglen && indef) { get_eoc(); }
1518159d09a2SMark Phalan 	    next_tag();
151955fea89dSDan Cross 	  } else val->clientPublicValue = NULL;
1520159d09a2SMark Phalan 	}
1521159d09a2SMark Phalan       }
1522159d09a2SMark Phalan       end_structure();
1523159d09a2SMark Phalan     }
1524159d09a2SMark Phalan     cleanup();
1525159d09a2SMark Phalan }
1526159d09a2SMark Phalan 
asn1_decode_pa_pk_as_rep(asn1buf * buf,krb5_pa_pk_as_rep * val)1527159d09a2SMark Phalan asn1_error_code asn1_decode_pa_pk_as_rep(asn1buf *buf, krb5_pa_pk_as_rep *val)
1528159d09a2SMark Phalan {
1529159d09a2SMark Phalan   setup();
1530159d09a2SMark Phalan   { begin_choice();
1531159d09a2SMark Phalan     if (tagnum == choice_pa_pk_as_rep_dhInfo) {
1532159d09a2SMark Phalan       val->choice = choice_pa_pk_as_rep_dhInfo;
1533159d09a2SMark Phalan       get_field_body(val->u.dh_Info, asn1_decode_dh_rep_info);
1534159d09a2SMark Phalan     } else if (tagnum == choice_pa_pk_as_rep_encKeyPack) {
1535159d09a2SMark Phalan       val->choice = choice_pa_pk_as_rep_encKeyPack;
1536159d09a2SMark Phalan       get_implicit_octet_string(val->u.encKeyPack.length, val->u.encKeyPack.data,
1537159d09a2SMark Phalan 				choice_pa_pk_as_rep_encKeyPack);
1538159d09a2SMark Phalan     } else {
1539159d09a2SMark Phalan       val->choice = choice_pa_pk_as_rep_UNKNOWN;
1540159d09a2SMark Phalan     }
1541159d09a2SMark Phalan     end_choice();
1542159d09a2SMark Phalan   }
1543159d09a2SMark Phalan   cleanup();
1544159d09a2SMark Phalan }
1545159d09a2SMark Phalan 
asn1_decode_pa_pk_as_rep_draft9(asn1buf * buf,krb5_pa_pk_as_rep_draft9 * val)1546159d09a2SMark Phalan asn1_error_code asn1_decode_pa_pk_as_rep_draft9(asn1buf *buf, krb5_pa_pk_as_rep_draft9 *val)
1547159d09a2SMark Phalan {
1548159d09a2SMark Phalan   setup();
1549159d09a2SMark Phalan   { begin_structure();
1550159d09a2SMark Phalan     if (tagnum == choice_pa_pk_as_rep_draft9_dhSignedData) {
1551159d09a2SMark Phalan       val->choice = choice_pa_pk_as_rep_draft9_dhSignedData;
1552159d09a2SMark Phalan       get_lenfield(val->u.dhSignedData.length, val->u.dhSignedData.data,
1553159d09a2SMark Phalan 		    choice_pa_pk_as_rep_draft9_dhSignedData, asn1_decode_octetstring);
1554159d09a2SMark Phalan     } else if (tagnum == choice_pa_pk_as_rep_draft9_encKeyPack) {
1555159d09a2SMark Phalan       val->choice = choice_pa_pk_as_rep_draft9_encKeyPack;
1556159d09a2SMark Phalan       get_lenfield(val->u.encKeyPack.length, val->u.encKeyPack.data,
1557159d09a2SMark Phalan 		    choice_pa_pk_as_rep_draft9_encKeyPack, asn1_decode_octetstring);
1558159d09a2SMark Phalan     } else {
1559159d09a2SMark Phalan       val->choice = choice_pa_pk_as_rep_draft9_UNKNOWN;
1560159d09a2SMark Phalan     }
1561159d09a2SMark Phalan     end_structure();
1562159d09a2SMark Phalan   }
1563159d09a2SMark Phalan   cleanup();
1564159d09a2SMark Phalan }
1565159d09a2SMark Phalan 
asn1_decode_sequence_of_typed_data(asn1buf * buf,krb5_typed_data *** val)1566159d09a2SMark Phalan asn1_error_code asn1_decode_sequence_of_typed_data(asn1buf *buf, krb5_typed_data ***val)
1567159d09a2SMark Phalan {
1568159d09a2SMark Phalan     decode_array_body(krb5_typed_data,asn1_decode_typed_data);
1569159d09a2SMark Phalan }
1570159d09a2SMark Phalan 
asn1_decode_typed_data(asn1buf * buf,krb5_typed_data * val)157155fea89dSDan Cross asn1_error_code asn1_decode_typed_data(asn1buf *buf, krb5_typed_data *val)
1572159d09a2SMark Phalan {
1573159d09a2SMark Phalan   setup();
1574159d09a2SMark Phalan   { begin_structure();
1575159d09a2SMark Phalan     get_field(val->type,0,asn1_decode_int32);
1576159d09a2SMark Phalan     get_lenfield(val->length,val->data,1,asn1_decode_octetstring);
1577159d09a2SMark Phalan     end_structure();
1578159d09a2SMark Phalan   }
1579159d09a2SMark Phalan   cleanup();
1580159d09a2SMark Phalan }
1581