xref: /illumos-gate/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_k_encode.c (revision 257873cfc1dd3337766407f80397db60a56f2f5a)
1 /*
2  * src/lib/krb5/asn.1/asn1_k_encode.c
3  *
4  * Copyright 1994 by the Massachusetts Institute of Technology.
5  * All Rights Reserved.
6  *
7  * Export of this software from the United States of America may
8  *   require a specific license from the United States Government.
9  *   It is the responsibility of any person or organization contemplating
10  *   export to obtain such a license before exporting.
11  *
12  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13  * distribute this software and its documentation for any purpose and
14  * without fee is hereby granted, provided that the above copyright
15  * notice appear in all copies and that both that copyright notice and
16  * this permission notice appear in supporting documentation, and that
17  * the name of M.I.T. not be used in advertising or publicity pertaining
18  * to distribution of the software without specific, written prior
19  * permission.  Furthermore if you modify this software you must label
20  * your software as modified software and not distribute it in such a
21  * fashion that it might be confused with the original M.I.T. software.
22  * M.I.T. makes no representations about the suitability of
23  * this software for any purpose.  It is provided "as is" without express
24  * or implied warranty.
25  */
26 
27 #include "asn1_k_encode.h"
28 #include "asn1_make.h"
29 #include "asn1_encode.h"
30 #include <assert.h>
31 
32 /**** asn1 macros ****/
33 #if 0
34    How to write an asn1 encoder function using these macros:
35 
36    asn1_error_code asn1_encode_krb5_substructure(asn1buf *buf,
37                                                  const krb5_type *val,
38                                                  int *retlen)
39    {
40      asn1_setup();
41 
42      asn1_addfield(val->last_field, n, asn1_type);
43      asn1_addfield(rep->next_to_last_field, n-1, asn1_type);
44      ...
45 
46      /* for OPTIONAL fields */
47      if(rep->field_i == should_not_be_omitted)
48        asn1_addfield(rep->field_i, i, asn1_type);
49 
50      /* for string fields (these encoders take an additional argument,
51 	the length of the string) */
52      addlenfield(rep->field_length, rep->field, i-1, asn1_type);
53 
54      /* if you really have to do things yourself... */
55      retval = asn1_encode_asn1_type(buf,rep->field,&length);
56      if(retval) return retval;
57      sum += length;
58      retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, tag_number, length,
59 			     &length);
60      if(retval) return retval;
61      sum += length;
62 
63      ...
64      asn1_addfield(rep->second_field, 1, asn1_type);
65      asn1_addfield(rep->first_field, 0, asn1_type);
66      asn1_makeseq();
67 
68      asn1_cleanup();
69    }
70 #endif
71 
72 /* setup() -- create and initialize bookkeeping variables
73      retval: stores error codes returned from subroutines
74      length: length of the most-recently produced encoding
75      sum: cumulative length of the entire encoding */
76 #define asn1_setup()\
77   asn1_error_code retval;\
78   unsigned int length, sum=0
79 
80 /* asn1_addfield -- add a field, or component, to the encoding */
81 #define asn1_addfield(value,tag,encoder)\
82 { retval = encoder(buf,value,&length);\
83   if(retval){\
84     asn1buf_destroy(&buf);\
85     return retval; }\
86   sum += length;\
87   retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\
88   if(retval){\
89     asn1buf_destroy(&buf);\
90     return retval; }\
91   sum += length; }
92 
93 /* asn1_addlenfield -- add a field whose length must be separately specified */
94 #define asn1_addlenfield(len,value,tag,encoder)\
95 { retval = encoder(buf,len,value,&length);\
96   if(retval){\
97     asn1buf_destroy(&buf);\
98     return retval; }\
99   sum += length;\
100   retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\
101   if(retval){\
102     asn1buf_destroy(&buf);\
103     return retval; }\
104   sum += length; }
105 
106 /* asn1_addfield_implicit -- add an implicitly tagged field, or component, to the encoding */
107 #define asn1_addfield_implicit(value,tag,encoder)\
108 { retval = encoder(buf,value,&length);\
109   if(retval){\
110     asn1buf_destroy(&buf);\
111     return retval; }\
112   sum += length;\
113   retval = asn1_make_tag(buf,CONTEXT_SPECIFIC,PRIMITIVE,tag,length,&length); \
114   if(retval){\
115     asn1buf_destroy(&buf);\
116     return retval; }\
117   sum += length; }
118 
119 /* asn1_insert_implicit_octetstring -- add an octet string with implicit tagging */
120 #define asn1_insert_implicit_octetstring(len,value,tag)\
121 { retval = asn1buf_insert_octetstring(buf,len,value);\
122   if(retval){\
123     asn1buf_destroy(&buf);\
124     return retval; }\
125   sum += len;\
126   retval = asn1_make_tag(buf,CONTEXT_SPECIFIC,PRIMITIVE,tag,len,&length); \
127   if(retval){\
128     asn1buf_destroy(&buf);\
129     return retval; }\
130   sum += length; }
131 
132 /* asn1_insert_implicit_bitstring -- add a bitstring with implicit tagging */
133 #define asn1_insert_implicit_bitstring(len,value,tag)\
134 { retval = asn1buf_insert_octetstring(buf,len,value);\
135   if(retval){\
136     asn1buf_destroy(&buf);\
137     return retval; }\
138   sum += len;\
139   retval = asn1buf_insert_octet(buf, 0);\
140   if(retval){\
141     asn1buf_destroy(&buf);\
142     return retval; }\
143   sum++;\
144   retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,tag,len+1,&length); \
145   if(retval){\
146     asn1buf_destroy(&buf);\
147     return retval; }\
148   sum += length; }
149 
150 /* form a sequence (by adding a sequence header to the current encoding) */
151 #define asn1_makeseq()\
152   retval = asn1_make_sequence(buf,sum,&length);\
153   if(retval){\
154     asn1buf_destroy(&buf);\
155     return retval; }\
156   sum += length
157 
158 /* add an APPLICATION class tag to the current encoding */
159 #define asn1_apptag(num)\
160   retval = asn1_make_etag(buf,APPLICATION,num,sum,&length);\
161   if(retval){\
162     asn1buf_destroy(&buf);\
163     return retval; }\
164   sum += length
165 
166 /* produce the final output and clean up the workspace */
167 #define asn1_cleanup()\
168   *retlen = sum;\
169   return 0
170 
171 asn1_error_code asn1_encode_ui_4(asn1buf *buf, const krb5_ui_4 val, unsigned int *retlen)
172 {
173   return asn1_encode_unsigned_integer(buf,val,retlen);
174 }
175 
176 
177 asn1_error_code asn1_encode_realm(asn1buf *buf, const krb5_principal val, unsigned int *retlen)
178 {
179   if (val == NULL ||
180       (val->realm.length && val->realm.data == NULL))
181 	  return ASN1_MISSING_FIELD;
182   return asn1_encode_generalstring(buf,val->realm.length,val->realm.data,
183 				   retlen);
184 }
185 
186 asn1_error_code asn1_encode_principal_name(asn1buf *buf, const krb5_principal val, unsigned int *retlen)
187 {
188   asn1_setup();
189   int n;
190 
191   if (val == NULL || val->data == NULL) return ASN1_MISSING_FIELD;
192 
193   for(n = (int) ((val->length)-1); n >= 0; n--){
194     if (val->data[n].length &&
195 	val->data[n].data == NULL)
196 	    return ASN1_MISSING_FIELD;
197     retval = asn1_encode_generalstring(buf,
198 				       (val->data)[n].length,
199 				       (val->data)[n].data,
200 				       &length);
201     if(retval) return retval;
202     sum += length;
203   }
204   asn1_makeseq();
205   retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,1,sum,&length);
206   if(retval) return retval;
207   sum += length;
208 
209   asn1_addfield(val->type,0,asn1_encode_integer);
210 
211   asn1_makeseq();
212 
213   asn1_cleanup();
214 }
215 
216 asn1_error_code asn1_encode_kerberos_time(asn1buf *buf, const krb5_timestamp val, unsigned int *retlen)
217 {
218   return asn1_encode_generaltime(buf,val,retlen);
219 }
220 
221 asn1_error_code asn1_encode_host_address(asn1buf *buf, const krb5_address *val, unsigned int *retlen)
222 {
223   asn1_setup();
224 
225   if (val == NULL || val->contents == NULL) return ASN1_MISSING_FIELD;
226 
227   asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring);
228   asn1_addfield(val->addrtype,0,asn1_encode_integer);
229   asn1_makeseq();
230 
231   asn1_cleanup();
232 }
233 
234 asn1_error_code asn1_encode_host_addresses(asn1buf *buf, const krb5_address **val, unsigned int *retlen)
235 {
236   asn1_setup();
237   int i;
238 
239   if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
240 
241   for(i=0; val[i] != NULL; i++); /* go to end of array */
242   for(i--; i>=0; i--){
243     retval = asn1_encode_host_address(buf,val[i],&length);
244     if(retval) return retval;
245     sum += length;
246   }
247   asn1_makeseq();
248 
249   asn1_cleanup();
250 }
251 
252 asn1_error_code asn1_encode_encrypted_data(asn1buf *buf, const krb5_enc_data *val, unsigned int *retlen)
253 {
254   asn1_setup();
255 
256   if(val == NULL ||
257      (val->ciphertext.length && val->ciphertext.data == NULL))
258 	  return ASN1_MISSING_FIELD;
259 
260   asn1_addlenfield(val->ciphertext.length,val->ciphertext.data,2,asn1_encode_charstring);
261   /* krb5_kvno should be int */
262   if(val->kvno)
263     asn1_addfield((int) val->kvno,1,asn1_encode_integer);
264   asn1_addfield(val->enctype,0,asn1_encode_integer);
265 
266   asn1_makeseq();
267 
268   asn1_cleanup();
269 }
270 
271 asn1_error_code asn1_encode_krb5_flags(asn1buf *buf, const krb5_flags val, unsigned int *retlen)
272 {
273   asn1_setup();
274   krb5_flags valcopy = val;
275   int i;
276 
277   for(i=0; i<4; i++){
278     retval = asn1buf_insert_octet(buf,(asn1_octet) (valcopy&0xFF));
279     if(retval) return retval;
280     valcopy >>= 8;
281   }
282   retval = asn1buf_insert_octet(buf,0);	/* 0 padding bits */
283   if(retval) return retval;
284   sum = 5;
285 
286   retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_BITSTRING,sum,
287 			 &length);
288   if(retval) return retval;
289   sum += length;
290 
291   *retlen = sum;
292   return 0;
293 }
294 
295 asn1_error_code asn1_encode_ap_options(asn1buf *buf, const krb5_flags val, unsigned int *retlen)
296 {
297   return asn1_encode_krb5_flags(buf,val,retlen);
298 }
299 
300 asn1_error_code asn1_encode_ticket_flags(asn1buf *buf, const krb5_flags val, unsigned int *retlen)
301 {
302   return asn1_encode_krb5_flags(buf,val,retlen);
303 }
304 
305 asn1_error_code asn1_encode_kdc_options(asn1buf *buf, const krb5_flags val, unsigned int *retlen)
306 {
307   return asn1_encode_krb5_flags(buf,val,retlen);
308 }
309 
310 asn1_error_code asn1_encode_authorization_data(asn1buf *buf, const krb5_authdata **val, unsigned int *retlen)
311 {
312   asn1_setup();
313   int i;
314 
315   if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
316 
317   for(i=0; val[i] != NULL; i++); /* get to the end of the array */
318   for(i--; i>=0; i--){
319     retval = asn1_encode_krb5_authdata_elt(buf,val[i],&length);
320     if(retval) return retval;
321     sum += length;
322   }
323   asn1_makeseq();
324 
325   asn1_cleanup();
326 }
327 
328 asn1_error_code asn1_encode_krb5_authdata_elt(asn1buf *buf, const krb5_authdata *val, unsigned int *retlen)
329 {
330   asn1_setup();
331 
332   if (val == NULL ||
333      (val->length && val->contents == NULL))
334 	  return ASN1_MISSING_FIELD;
335 
336   /* ad-data[1]		OCTET STRING */
337   asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring);
338   /* ad-type[0]		INTEGER */
339   asn1_addfield(val->ad_type,0,asn1_encode_integer);
340   /* SEQUENCE */
341   asn1_makeseq();
342 
343   asn1_cleanup();
344 }
345 
346 asn1_error_code asn1_encode_kdc_rep(int msg_type, asn1buf *buf, const krb5_kdc_rep *val, unsigned int *retlen)
347 {
348   asn1_setup();
349 
350   if(val == NULL) return ASN1_MISSING_FIELD;
351 
352   asn1_addfield(&(val->enc_part),6,asn1_encode_encrypted_data);
353   asn1_addfield(val->ticket,5,asn1_encode_ticket);
354   asn1_addfield(val->client,4,asn1_encode_principal_name);
355   asn1_addfield(val->client,3,asn1_encode_realm);
356   if(val->padata != NULL && val->padata[0] != NULL)
357     asn1_addfield((const krb5_pa_data**)val->padata,2,asn1_encode_sequence_of_pa_data);
358   if (msg_type != KRB5_AS_REP && msg_type != KRB5_TGS_REP)
359 	  return KRB5_BADMSGTYPE;
360   asn1_addfield(msg_type,1,asn1_encode_integer);
361   asn1_addfield(KVNO,0,asn1_encode_integer);
362   asn1_makeseq();
363 
364   asn1_cleanup();
365 }
366 
367 asn1_error_code asn1_encode_enc_kdc_rep_part(asn1buf *buf, const krb5_enc_kdc_rep_part *val, unsigned int *retlen)
368 {
369   asn1_setup();
370 
371   if(val == NULL) return ASN1_MISSING_FIELD;
372 
373   /* caddr[11]		HostAddresses OPTIONAL */
374   if(val->caddrs != NULL && val->caddrs[0] != NULL)
375     asn1_addfield((const krb5_address**)(val->caddrs),11,asn1_encode_host_addresses);
376 
377   /* sname[10]		PrincipalName */
378   asn1_addfield(val->server,10,asn1_encode_principal_name);
379 
380   /* srealm[9]		Realm */
381   asn1_addfield(val->server,9,asn1_encode_realm);
382 
383   /* renew-till[8]	KerberosTime OPTIONAL */
384   if(val->flags & TKT_FLG_RENEWABLE)
385     asn1_addfield(val->times.renew_till,8,asn1_encode_kerberos_time);
386 
387   /* endtime[7]		KerberosTime */
388   asn1_addfield(val->times.endtime,7,asn1_encode_kerberos_time);
389 
390   /* starttime[6]	KerberosTime OPTIONAL */
391   if(val->times.starttime)
392     asn1_addfield(val->times.starttime,6,asn1_encode_kerberos_time);
393 
394   /* authtime[5]	KerberosTime */
395   asn1_addfield(val->times.authtime,5,asn1_encode_kerberos_time);
396 
397   /* flags[4]		TicketFlags */
398   asn1_addfield(val->flags,4,asn1_encode_ticket_flags);
399 
400   /* key-expiration[3]	KerberosTime OPTIONAL */
401   if(val->key_exp)
402     asn1_addfield(val->key_exp,3,asn1_encode_kerberos_time);
403 
404   /* nonce[2]		INTEGER */
405   asn1_addfield(val->nonce,2,asn1_encode_integer);
406 
407   /* last-req[1]	LastReq */
408   asn1_addfield((const krb5_last_req_entry**)val->last_req,1,asn1_encode_last_req);
409 
410   /* key[0]		EncryptionKey */
411   asn1_addfield(val->session,0,asn1_encode_encryption_key);
412 
413   /* EncKDCRepPart ::= SEQUENCE */
414   asn1_makeseq();
415 
416   asn1_cleanup();
417 }
418 
419 asn1_error_code asn1_encode_sequence_of_checksum(asn1buf *buf, const krb5_checksum ** val, unsigned int *retlen)
420 {
421   asn1_setup();
422   int i;
423 
424   if(val == NULL) return ASN1_MISSING_FIELD;
425 
426   for (i=0; val[i] != NULL; i++);
427   for (i--; i>=0; i--){
428     retval = asn1_encode_checksum(buf,val[i],&length);
429     if(retval) return retval;
430     sum += length;
431   }
432   asn1_makeseq();
433 
434   asn1_cleanup();
435 }
436 
437 asn1_error_code asn1_encode_kdc_req_body(asn1buf *buf, const krb5_kdc_req *rep, unsigned int *retlen)
438 {
439   asn1_setup();
440 
441   if(rep == NULL) return ASN1_MISSING_FIELD;
442 
443   /* additional-tickets[11]	SEQUENCE OF Ticket OPTIONAL */
444   if(rep->second_ticket != NULL && rep->second_ticket[0] != NULL)
445     asn1_addfield((const krb5_ticket**)rep->second_ticket,
446 		  11,asn1_encode_sequence_of_ticket);
447 
448   /* enc-authorization-data[10]	EncryptedData OPTIONAL, */
449   /* 				-- Encrypted AuthorizationData encoding */
450   if(rep->authorization_data.ciphertext.data != NULL)
451     asn1_addfield(&(rep->authorization_data),10,asn1_encode_encrypted_data);
452 
453   /* addresses[9]		HostAddresses OPTIONAL, */
454   if(rep->addresses != NULL && rep->addresses[0] != NULL)
455     asn1_addfield((const krb5_address**)rep->addresses,9,asn1_encode_host_addresses);
456 
457   /* etype[8]			SEQUENCE OF INTEGER, -- EncryptionType, */
458   /* 				-- in preference order */
459   asn1_addlenfield(rep->nktypes,rep->ktype,8,asn1_encode_sequence_of_enctype);
460 
461   /* nonce[7]			INTEGER, */
462   asn1_addfield(rep->nonce,7,asn1_encode_integer);
463 
464   /* rtime[6]			KerberosTime OPTIONAL, */
465   if(rep->rtime)
466     asn1_addfield(rep->rtime,6,asn1_encode_kerberos_time);
467 
468   /* till[5]			KerberosTime, */
469   asn1_addfield(rep->till,5,asn1_encode_kerberos_time);
470 
471   /* from[4]			KerberosTime OPTIONAL, */
472   if(rep->from)
473   asn1_addfield(rep->from,4,asn1_encode_kerberos_time);
474 
475   /* sname[3]			PrincipalName OPTIONAL, */
476   if(rep->server != NULL)
477     asn1_addfield(rep->server,3,asn1_encode_principal_name);
478 
479   /* realm[2]			Realm, -- Server's realm */
480   /* 				-- Also client's in AS-REQ */
481   if(rep->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY){
482     if(rep->second_ticket != NULL && rep->second_ticket[0] != NULL){
483       asn1_addfield(rep->second_ticket[0]->server,2,asn1_encode_realm)
484     } else return ASN1_MISSING_FIELD;
485   }else if(rep->server != NULL){
486     asn1_addfield(rep->server,2,asn1_encode_realm);
487   }else return ASN1_MISSING_FIELD;
488 
489   /* cname[1]			PrincipalName OPTIONAL, */
490   /* 				-- Used only in AS-REQ */
491   if(rep->client != NULL)
492     asn1_addfield(rep->client,1,asn1_encode_principal_name);
493 
494   /* kdc-options[0]		KDCOptions, */
495   asn1_addfield(rep->kdc_options,0,asn1_encode_kdc_options);
496 
497   /* KDC-REQ-BODY ::= SEQUENCE */
498   asn1_makeseq();
499 
500   asn1_cleanup();
501 }
502 
503 asn1_error_code asn1_encode_encryption_key(asn1buf *buf, const krb5_keyblock *val, unsigned int *retlen)
504 {
505   asn1_setup();
506 
507   if (val == NULL ||
508       (val->length && val->contents == NULL))
509 	  return ASN1_MISSING_FIELD;
510 
511   asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring);
512   asn1_addfield(val->enctype,0,asn1_encode_integer);
513   asn1_makeseq();
514 
515   asn1_cleanup();
516 }
517 
518 asn1_error_code asn1_encode_checksum(asn1buf *buf, const krb5_checksum *val, unsigned int *retlen)
519 {
520   asn1_setup();
521 
522   if (val == NULL ||
523      (val->length && val->contents == NULL))
524 	  return ASN1_MISSING_FIELD;
525 
526   asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring);
527   asn1_addfield(val->checksum_type,0,asn1_encode_integer);
528   asn1_makeseq();
529 
530   asn1_cleanup();
531 }
532 
533 asn1_error_code asn1_encode_transited_encoding(asn1buf *buf, const krb5_transited *val, unsigned int *retlen)
534 {
535   asn1_setup();
536 
537   if(val == NULL ||
538      (val->tr_contents.length != 0 && val->tr_contents.data == NULL))
539     return ASN1_MISSING_FIELD;
540 
541   asn1_addlenfield(val->tr_contents.length,val->tr_contents.data,
542 		   1,asn1_encode_charstring);
543   asn1_addfield(val->tr_type,0,asn1_encode_integer);
544   asn1_makeseq();
545 
546   asn1_cleanup();
547 }
548 
549 asn1_error_code asn1_encode_last_req(asn1buf *buf, const krb5_last_req_entry **val, unsigned int *retlen)
550 {
551   asn1_setup();
552   int i;
553 
554   if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
555 
556   for(i=0; val[i] != NULL; i++); /* go to end of array */
557   for(i--; i>=0; i--){
558     retval = asn1_encode_last_req_entry(buf,val[i],&length);
559     if(retval) return retval;
560     sum += length;
561   }
562   asn1_makeseq();
563 
564   asn1_cleanup();
565 }
566 
567 asn1_error_code asn1_encode_last_req_entry(asn1buf *buf, const krb5_last_req_entry *val, unsigned int *retlen)
568 {
569   asn1_setup();
570 
571   if(val == NULL) return ASN1_MISSING_FIELD;
572 
573   asn1_addfield(val->value,1,asn1_encode_kerberos_time);
574   asn1_addfield(val->lr_type,0,asn1_encode_integer);
575   asn1_makeseq();
576 
577   asn1_cleanup();
578 }
579 
580 asn1_error_code asn1_encode_sequence_of_pa_data(asn1buf *buf, const krb5_pa_data **val, unsigned int *retlen)
581 {
582   asn1_setup();
583   int i;
584 
585   if (val == NULL) return ASN1_MISSING_FIELD;
586 
587   for(i=0; val[i] != NULL; i++);
588   for(i--; i>=0; i--){
589     retval = asn1_encode_pa_data(buf,val[i],&length);
590     if(retval) return retval;
591     sum += length;
592   }
593   asn1_makeseq();
594 
595   asn1_cleanup();
596 }
597 
598 asn1_error_code asn1_encode_pa_data(asn1buf *buf, const krb5_pa_data *val, unsigned int *retlen)
599 {
600   asn1_setup();
601 
602   if(val == NULL || (val->length != 0 && val->contents == NULL))
603      return ASN1_MISSING_FIELD;
604 
605   asn1_addlenfield(val->length,val->contents,2,asn1_encode_octetstring);
606   asn1_addfield(val->pa_type,1,asn1_encode_integer);
607   asn1_makeseq();
608 
609   asn1_cleanup();
610 }
611 
612 asn1_error_code asn1_encode_sequence_of_ticket(asn1buf *buf, const krb5_ticket **val, unsigned int *retlen)
613 {
614   asn1_setup();
615   int i;
616 
617   if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
618 
619   for(i=0; val[i] != NULL; i++);
620   for(i--; i>=0; i--){
621     retval = asn1_encode_ticket(buf,val[i],&length);
622     if(retval) return retval;
623     sum += length;
624   }
625   asn1_makeseq();
626 
627   asn1_cleanup();
628 }
629 
630 asn1_error_code asn1_encode_ticket(asn1buf *buf, const krb5_ticket *val, unsigned int *retlen)
631 {
632   asn1_setup();
633 
634   if(val == NULL) return ASN1_MISSING_FIELD;
635 
636   asn1_addfield(&(val->enc_part),3,asn1_encode_encrypted_data);
637   asn1_addfield(val->server,2,asn1_encode_principal_name);
638   asn1_addfield(val->server,1,asn1_encode_realm);
639   asn1_addfield(KVNO,0,asn1_encode_integer);
640   asn1_makeseq();
641   asn1_apptag(1);
642 
643   asn1_cleanup();
644 }
645 
646 asn1_error_code asn1_encode_sequence_of_enctype(asn1buf *buf, const int len, const krb5_enctype *val, unsigned int *retlen)
647 {
648   asn1_setup();
649   int i;
650 
651   if(val == NULL) return ASN1_MISSING_FIELD;
652 
653   for(i=len-1; i>=0; i--){
654     retval = asn1_encode_integer(buf,val[i],&length);
655     if(retval) return retval;
656     sum += length;
657   }
658   asn1_makeseq();
659 
660   asn1_cleanup();
661 }
662 
663 asn1_error_code asn1_encode_kdc_req(int msg_type, asn1buf *buf, const krb5_kdc_req *val, unsigned int *retlen)
664 {
665   asn1_setup();
666 
667   if(val == NULL) return ASN1_MISSING_FIELD;
668 
669   asn1_addfield(val,4,asn1_encode_kdc_req_body);
670   if(val->padata != NULL && val->padata[0] != NULL)
671     asn1_addfield((const krb5_pa_data**)val->padata,3,asn1_encode_sequence_of_pa_data);
672   if (msg_type != KRB5_AS_REQ && msg_type != KRB5_TGS_REQ)
673 	  return KRB5_BADMSGTYPE;
674   asn1_addfield(msg_type,2,asn1_encode_integer);
675   asn1_addfield(KVNO,1,asn1_encode_integer);
676   asn1_makeseq();
677 
678   asn1_cleanup();
679 }
680 
681 asn1_error_code asn1_encode_krb_safe_body(asn1buf *buf, const krb5_safe *val, unsigned int *retlen)
682 {
683   asn1_setup();
684 
685   if(val == NULL) return ASN1_MISSING_FIELD;
686 
687   if(val->r_address != NULL)
688     asn1_addfield(val->r_address,5,asn1_encode_host_address);
689   asn1_addfield(val->s_address,4,asn1_encode_host_address);
690   if(val->seq_number)
691     asn1_addfield(val->seq_number,3,asn1_encode_unsigned_integer);
692   if(val->timestamp){
693     asn1_addfield(val->usec,2,asn1_encode_integer);
694     asn1_addfield(val->timestamp,1,asn1_encode_kerberos_time);
695   }
696   if (val->user_data.length && val->user_data.data == NULL)
697 	  return ASN1_MISSING_FIELD;
698   asn1_addlenfield(val->user_data.length,val->user_data.data,0,asn1_encode_charstring)
699 ;
700 
701   asn1_makeseq();
702   asn1_cleanup();
703 }
704 
705 asn1_error_code asn1_encode_sequence_of_krb_cred_info(asn1buf *buf, const krb5_cred_info **val, unsigned int *retlen)
706 {
707   asn1_setup();
708   int i;
709 
710   if(val == NULL) return ASN1_MISSING_FIELD;
711 
712   for(i=0; val[i] != NULL; i++);
713   for(i--; i>=0; i--){
714     retval = asn1_encode_krb_cred_info(buf,val[i],&length);
715     if(retval) return retval;
716     sum += length;
717   }
718   asn1_makeseq();
719 
720   asn1_cleanup();
721 }
722 
723 asn1_error_code asn1_encode_krb_cred_info(asn1buf *buf, const krb5_cred_info *val, unsigned int *retlen)
724 {
725   asn1_setup();
726 
727   if(val == NULL) return ASN1_MISSING_FIELD;
728 
729   if(val->caddrs != NULL && val->caddrs[0] != NULL)
730     asn1_addfield((const krb5_address**)val->caddrs,10,asn1_encode_host_addresses);
731   if(val->server != NULL){
732     asn1_addfield(val->server,9,asn1_encode_principal_name);
733     asn1_addfield(val->server,8,asn1_encode_realm);
734   }
735   if(val->times.renew_till)
736     asn1_addfield(val->times.renew_till,7,asn1_encode_kerberos_time);
737   if(val->times.endtime)
738     asn1_addfield(val->times.endtime,6,asn1_encode_kerberos_time);
739   if(val->times.starttime)
740     asn1_addfield(val->times.starttime,5,asn1_encode_kerberos_time);
741   if(val->times.authtime)
742     asn1_addfield(val->times.authtime,4,asn1_encode_kerberos_time);
743   if(val->flags)
744     asn1_addfield(val->flags,3,asn1_encode_ticket_flags);
745   if(val->client != NULL){
746     asn1_addfield(val->client,2,asn1_encode_principal_name);
747     asn1_addfield(val->client,1,asn1_encode_realm);
748   }
749   asn1_addfield(val->session,0,asn1_encode_encryption_key);
750 
751   asn1_makeseq();
752 
753   asn1_cleanup();
754 }
755 
756 asn1_error_code asn1_encode_etype_info_entry(asn1buf *buf, const krb5_etype_info_entry *val,
757 					     unsigned int *retlen, int etype_info2)
758 {
759   asn1_setup();
760 
761   assert(val->s2kparams.data == NULL || etype_info2);
762   if(val == NULL || (val->length > 0 && val->length != KRB5_ETYPE_NO_SALT &&
763 		     val->salt == NULL))
764      return ASN1_MISSING_FIELD;
765   if(val->s2kparams.data != NULL) {
766       /* Solaris Kerberos */
767       asn1_addlenfield(val->s2kparams.length, (const uchar_t *)val->s2kparams.data, 2,
768 		       asn1_encode_octetstring);
769   }
770   if (val->length >= 0 && val->length != KRB5_ETYPE_NO_SALT){
771       if (etype_info2) {
772           /* Solaris Kerberos */
773 	  asn1_addlenfield(val->length, (const char *)val->salt,1,
774 			   asn1_encode_generalstring)
775       }
776       else 	  asn1_addlenfield(val->length,val->salt,1,
777 				   asn1_encode_octetstring);
778   }
779 asn1_addfield(val->etype,0,asn1_encode_integer);
780   asn1_makeseq();
781 
782   asn1_cleanup();
783 }
784 
785 asn1_error_code asn1_encode_etype_info(asn1buf *buf, const krb5_etype_info_entry **val,
786 				       unsigned int *retlen, int etype_info2)
787 {
788     asn1_setup();
789     int i;
790 
791     if (val == NULL) return ASN1_MISSING_FIELD;
792 
793     for(i=0; val[i] != NULL; i++); /* get to the end of the array */
794     for(i--; i>=0; i--){
795 	retval = asn1_encode_etype_info_entry(buf,val[i],&length, etype_info2);
796 	if(retval) return retval;
797 	sum += length;
798     }
799     asn1_makeseq();
800     asn1_cleanup();
801 }
802 
803 asn1_error_code asn1_encode_sequence_of_passwdsequence(asn1buf *buf, const passwd_phrase_element **val, unsigned int *retlen)
804 {
805   asn1_setup();
806   int i;
807 
808   if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
809 
810   for(i=0; val[i] != NULL; i++); /* get to the end of the array */
811   for(i--; i>=0; i--){
812     retval = asn1_encode_passwdsequence(buf,val[i],&length);
813     if(retval) return retval;
814     sum += length;
815   }
816   asn1_makeseq();
817   asn1_cleanup();
818 }
819 
820 asn1_error_code asn1_encode_passwdsequence(asn1buf *buf, const passwd_phrase_element *val, unsigned int *retlen)
821 {
822   asn1_setup();
823   asn1_addlenfield(val->phrase->length,val->phrase->data,1,asn1_encode_charstring);
824   asn1_addlenfield(val->passwd->length,val->passwd->data,0,asn1_encode_charstring);
825   asn1_makeseq();
826   asn1_cleanup();
827 }
828 
829 asn1_error_code asn1_encode_sam_flags(asn1buf *buf, const krb5_flags val, unsigned int *retlen)
830 {
831   return asn1_encode_krb5_flags(buf,val,retlen);
832 }
833 
834 #define add_optstring(val,n,fn) \
835      if ((val).length > 0) {asn1_addlenfield((val).length,(val).data,n,fn);}
836 
837 asn1_error_code asn1_encode_sam_challenge(asn1buf *buf, const krb5_sam_challenge *val, unsigned int *retlen)
838 {
839   asn1_setup();
840   /* possibly wrong */
841   if (val->sam_cksum.length)
842     asn1_addfield(&(val->sam_cksum),9,asn1_encode_checksum);
843 
844   if (val->sam_nonce)
845     asn1_addfield(val->sam_nonce,8,asn1_encode_integer);
846 
847   add_optstring(val->sam_pk_for_sad,7,asn1_encode_charstring);
848   add_optstring(val->sam_response_prompt,6,asn1_encode_charstring);
849   add_optstring(val->sam_challenge,5,asn1_encode_charstring);
850   add_optstring(val->sam_challenge_label,4,asn1_encode_charstring);
851   add_optstring(val->sam_track_id,3,asn1_encode_charstring);
852   add_optstring(val->sam_type_name,2,asn1_encode_charstring);
853 
854   asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags);
855   asn1_addfield(val->sam_type,0,asn1_encode_integer);
856 
857   asn1_makeseq();
858   asn1_cleanup();
859 }
860 
861 asn1_error_code asn1_encode_sam_challenge_2(asn1buf *buf, const krb5_sam_challenge_2 *val, unsigned int *retlen)
862 {
863   asn1_setup();
864   if ( (!val) || (!val->sam_cksum) || (!val->sam_cksum[0]))
865       return ASN1_MISSING_FIELD;
866 
867   asn1_addfield((const krb5_checksum **) val->sam_cksum, 1, asn1_encode_sequence_of_checksum);
868   retval = asn1buf_insert_octetstring(buf, val->sam_challenge_2_body.length,
869 				      (unsigned char *)val->sam_challenge_2_body.data);
870   if(retval){
871 	  asn1buf_destroy(&buf);
872 	  return retval;
873   }
874   sum += val->sam_challenge_2_body.length;
875   retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0,
876 			  val->sam_challenge_2_body.length, &length);
877   if(retval) {
878 	  asn1buf_destroy(&buf);
879 	  return retval;
880   }
881   sum += length;
882 
883   asn1_makeseq();
884   asn1_cleanup();
885 }
886 
887 asn1_error_code asn1_encode_sam_challenge_2_body(asn1buf *buf, const krb5_sam_challenge_2_body *val, unsigned int *retlen)
888 {
889   asn1_setup();
890 
891   asn1_addfield(val->sam_etype, 9, asn1_encode_integer);
892   asn1_addfield(val->sam_nonce,8,asn1_encode_integer);
893   add_optstring(val->sam_pk_for_sad,7,asn1_encode_charstring);
894   add_optstring(val->sam_response_prompt,6,asn1_encode_charstring);
895   add_optstring(val->sam_challenge,5,asn1_encode_charstring);
896   add_optstring(val->sam_challenge_label,4,asn1_encode_charstring);
897   add_optstring(val->sam_track_id,3,asn1_encode_charstring);
898   add_optstring(val->sam_type_name,2,asn1_encode_charstring);
899 
900   asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags);
901   asn1_addfield(val->sam_type,0,asn1_encode_integer);
902 
903   asn1_makeseq();
904   asn1_cleanup();
905 }
906 
907 asn1_error_code asn1_encode_sam_key(asn1buf *buf, const krb5_sam_key *val, unsigned int *retlen)
908 {
909   asn1_setup();
910   asn1_addfield(&(val->sam_key),0,asn1_encode_encryption_key);
911 
912   asn1_makeseq();
913 
914   asn1_cleanup();
915 }
916 
917 
918 asn1_error_code asn1_encode_enc_sam_response_enc(asn1buf *buf, const krb5_enc_sam_response_enc *val, unsigned int *retlen)
919 {
920   asn1_setup();
921   add_optstring(val->sam_sad,3,asn1_encode_charstring);
922   asn1_addfield(val->sam_usec,2,asn1_encode_integer);
923   asn1_addfield(val->sam_timestamp,1,asn1_encode_kerberos_time);
924   asn1_addfield(val->sam_nonce,0,asn1_encode_integer);
925 
926   asn1_makeseq();
927 
928   asn1_cleanup();
929 }
930 
931 asn1_error_code asn1_encode_enc_sam_response_enc_2(asn1buf *buf, const krb5_enc_sam_response_enc_2 *val, unsigned int *retlen)
932 {
933   asn1_setup();
934   add_optstring(val->sam_sad,1,asn1_encode_charstring);
935   asn1_addfield(val->sam_nonce,0,asn1_encode_integer);
936 
937   asn1_makeseq();
938 
939   asn1_cleanup();
940 }
941 
942 asn1_error_code asn1_encode_sam_response(asn1buf *buf, const krb5_sam_response *val, unsigned int *retlen)
943 {
944   asn1_setup();
945 
946   if (val->sam_patimestamp)
947     asn1_addfield(val->sam_patimestamp,6,asn1_encode_kerberos_time);
948   if (val->sam_nonce)
949     asn1_addfield(val->sam_nonce,5,asn1_encode_integer);
950   asn1_addfield(&(val->sam_enc_nonce_or_ts),4,asn1_encode_encrypted_data);
951   if (val->sam_enc_key.ciphertext.length)
952     asn1_addfield(&(val->sam_enc_key),3,asn1_encode_encrypted_data);
953   add_optstring(val->sam_track_id,2,asn1_encode_charstring);
954   asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags);
955   asn1_addfield(val->sam_type,0,asn1_encode_integer);
956 
957   asn1_makeseq();
958 
959   asn1_cleanup();
960 }
961 
962 asn1_error_code asn1_encode_sam_response_2(asn1buf *buf, const krb5_sam_response_2 *val, unsigned int *retlen)
963 {
964   asn1_setup();
965 
966   asn1_addfield(val->sam_nonce,4,asn1_encode_integer);
967   asn1_addfield(&(val->sam_enc_nonce_or_sad),3,asn1_encode_encrypted_data);
968   add_optstring(val->sam_track_id,2,asn1_encode_charstring);
969   asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags);
970   asn1_addfield(val->sam_type,0,asn1_encode_integer);
971 
972   asn1_makeseq();
973 
974   asn1_cleanup();
975 }
976 
977 asn1_error_code asn1_encode_predicted_sam_response(asn1buf *buf, const krb5_predicted_sam_response *val, unsigned int *retlen)
978 {
979   asn1_setup();
980 
981   add_optstring(val->msd,6,asn1_encode_charstring);
982   asn1_addfield(val->client,5,asn1_encode_principal_name);
983   asn1_addfield(val->client,4,asn1_encode_realm);
984   asn1_addfield(val->susec,3,asn1_encode_integer);
985   asn1_addfield(val->stime,2,asn1_encode_kerberos_time);
986   asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags);
987   asn1_addfield(&(val->sam_key),0,asn1_encode_encryption_key);
988 
989   asn1_makeseq();
990 
991   asn1_cleanup();
992 }
993 
994 /*
995  * Do some ugliness to insert a raw pre-encoded KRB-SAFE-BODY.
996  */
997 asn1_error_code asn1_encode_krb_saved_safe_body(asn1buf *buf, const krb5_data *body, unsigned int *retlen)
998 {
999   asn1_error_code retval;
1000 
1001   retval = asn1buf_insert_octetstring(buf, body->length,
1002 				      (krb5_octet *)body->data);
1003   if (retval){
1004     asn1buf_destroy(&buf);
1005     return retval;
1006   }
1007   *retlen = body->length;
1008   return 0;
1009 }
1010 
1011 /*
1012  * PKINIT
1013  */
1014 
1015 asn1_error_code asn1_encode_pk_authenticator(asn1buf *buf, const krb5_pk_authenticator *val, unsigned int *retlen)
1016 {
1017   asn1_setup();
1018   asn1_addlenfield(val->paChecksum.length, val->paChecksum.contents, 3, asn1_encode_octetstring);
1019   asn1_addfield(val->nonce, 2, asn1_encode_integer);
1020   asn1_addfield(val->ctime, 1, asn1_encode_kerberos_time);
1021   asn1_addfield(val->cusec, 0, asn1_encode_integer);
1022 
1023   asn1_makeseq();
1024   asn1_cleanup();
1025 }
1026 
1027 asn1_error_code asn1_encode_pk_authenticator_draft9(asn1buf *buf, const krb5_pk_authenticator_draft9 *val, unsigned int *retlen)
1028 {
1029   asn1_setup();
1030 
1031   asn1_addfield(val->nonce, 4, asn1_encode_integer);
1032   asn1_addfield(val->ctime, 3, asn1_encode_kerberos_time);
1033   asn1_addfield(val->cusec, 2, asn1_encode_integer);
1034   asn1_addfield(val->kdcName, 1, asn1_encode_realm);
1035   asn1_addfield(val->kdcName, 0, asn1_encode_principal_name);
1036 
1037   asn1_makeseq();
1038   asn1_cleanup();
1039 }
1040 
1041 
1042 asn1_error_code asn1_encode_algorithm_identifier(asn1buf *buf, const krb5_algorithm_identifier *val, unsigned int *retlen)
1043 {
1044   asn1_setup();
1045 
1046   if (val->parameters.length != 0) {
1047     retval = asn1buf_insert_octetstring(buf, val->parameters.length,
1048 					val->parameters.data);
1049     if(retval) {
1050       asn1buf_destroy(&buf);
1051       return retval;
1052     }
1053     sum += val->parameters.length;
1054   }
1055 
1056   retval = asn1_encode_oid(buf, val->algorithm.length,
1057 			   val->algorithm.data,
1058 			   &length);
1059 
1060   if(retval) {
1061     asn1buf_destroy(&buf);
1062     return retval;
1063   }
1064   sum += length;
1065 
1066   asn1_makeseq();
1067   asn1_cleanup();
1068 }
1069 
1070 asn1_error_code asn1_encode_subject_pk_info(asn1buf *buf, const krb5_subject_pk_info *val, unsigned int *retlen)
1071 {
1072   asn1_setup();
1073 
1074   asn1_insert_implicit_bitstring(val->subjectPublicKey.length,val->subjectPublicKey.data,ASN1_BITSTRING);
1075 
1076   if (val->algorithm.parameters.length != 0) {
1077     retval = asn1buf_insert_octetstring(buf, val->algorithm.parameters.length,
1078 					val->algorithm.parameters.data);
1079     if(retval) {
1080       asn1buf_destroy(&buf);
1081       return retval;
1082     }
1083     sum += val->algorithm.parameters.length;
1084   }
1085 
1086   retval = asn1_encode_oid(buf, val->algorithm.algorithm.length,
1087 			   val->algorithm.algorithm.data,
1088 			   &length);
1089 
1090   if(retval) {
1091     asn1buf_destroy(&buf);
1092     return retval;
1093   }
1094   sum += length;
1095 
1096   retval = asn1_make_etag(buf, UNIVERSAL, ASN1_SEQUENCE,
1097 			  val->algorithm.parameters.length + length,
1098 			  &length);
1099 
1100   if(retval) {
1101     asn1buf_destroy(&buf);
1102     return retval;
1103   }
1104   sum += length;
1105 
1106   asn1_makeseq();
1107   asn1_cleanup();
1108 }
1109 
1110 asn1_error_code asn1_encode_sequence_of_algorithm_identifier(asn1buf *buf, const krb5_algorithm_identifier **val, unsigned int *retlen)
1111 {
1112   asn1_setup();
1113   int i;
1114 
1115   if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
1116 
1117   for(i=0; val[i] != NULL; i++);
1118   for(i--; i>=0; i--){
1119     retval = asn1_encode_algorithm_identifier(buf,val[i],&length);
1120     if(retval) return retval;
1121     sum += length;
1122   }
1123   asn1_makeseq();
1124 
1125   asn1_cleanup();
1126 }
1127 
1128 asn1_error_code asn1_encode_auth_pack(asn1buf *buf, const krb5_auth_pack *val, unsigned int *retlen)
1129 {
1130   asn1_setup();
1131 
1132   if (val->clientDHNonce.length != 0)
1133     asn1_addlenfield(val->clientDHNonce.length, val->clientDHNonce.data, 3, asn1_encode_octetstring);
1134   if (val->supportedCMSTypes != NULL)
1135     asn1_addfield((const krb5_algorithm_identifier **)val->supportedCMSTypes,2,asn1_encode_sequence_of_algorithm_identifier);
1136   if (val->clientPublicValue != NULL)
1137     asn1_addfield(val->clientPublicValue,1,asn1_encode_subject_pk_info);
1138   asn1_addfield(&(val->pkAuthenticator),0,asn1_encode_pk_authenticator);
1139 
1140   asn1_makeseq();
1141   asn1_cleanup();
1142 }
1143 
1144 asn1_error_code asn1_encode_auth_pack_draft9(asn1buf *buf, const krb5_auth_pack_draft9 *val, unsigned int *retlen)
1145 {
1146   asn1_setup();
1147 
1148   if (val->clientPublicValue != NULL)
1149     asn1_addfield(val->clientPublicValue, 1, asn1_encode_subject_pk_info);
1150   asn1_addfield(&(val->pkAuthenticator), 0, asn1_encode_pk_authenticator_draft9);
1151 
1152   asn1_makeseq();
1153   asn1_cleanup();
1154 }
1155 
1156 asn1_error_code asn1_encode_external_principal_identifier(asn1buf *buf, const krb5_external_principal_identifier *val, unsigned int *retlen)
1157 {
1158   asn1_setup();
1159 
1160   /* Verify there is something to encode */
1161   if (val->subjectKeyIdentifier.length == 0 && val->issuerAndSerialNumber.length == 0 && val->subjectName.length == 0)
1162     return ASN1_MISSING_FIELD;
1163 
1164   if (val->subjectKeyIdentifier.length != 0)
1165     asn1_insert_implicit_octetstring(val->subjectKeyIdentifier.length,val->subjectKeyIdentifier.data,2);
1166 
1167   if (val->issuerAndSerialNumber.length != 0)
1168     asn1_insert_implicit_octetstring(val->issuerAndSerialNumber.length,val->issuerAndSerialNumber.data,1);
1169 
1170   if (val->subjectName.length != 0)
1171     asn1_insert_implicit_octetstring(val->subjectName.length,val->subjectName.data,0);
1172 
1173   asn1_makeseq();
1174   asn1_cleanup();
1175 }
1176 
1177 asn1_error_code asn1_encode_sequence_of_external_principal_identifier(asn1buf *buf, const krb5_external_principal_identifier **val, unsigned int *retlen)
1178 {
1179   asn1_setup();
1180   int i;
1181 
1182   if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
1183 
1184   for(i=0; val[i] != NULL; i++);
1185   for(i--; i>=0; i--){
1186     retval = asn1_encode_external_principal_identifier(buf,val[i],&length);
1187     if(retval) return retval;
1188     sum += length;
1189   }
1190   asn1_makeseq();
1191 
1192   asn1_cleanup();
1193 }
1194 
1195 asn1_error_code asn1_encode_pa_pk_as_req(asn1buf *buf, const krb5_pa_pk_as_req *val, unsigned int *retlen)
1196 {
1197   asn1_setup();
1198 
1199   if (val->kdcPkId.length != 0)
1200     asn1_insert_implicit_octetstring(val->kdcPkId.length,val->kdcPkId.data,2);
1201 
1202   if (val->trustedCertifiers != NULL)
1203     asn1_addfield((const krb5_external_principal_identifier **)val->trustedCertifiers,1,asn1_encode_sequence_of_external_principal_identifier);
1204 
1205   asn1_insert_implicit_octetstring(val->signedAuthPack.length,val->signedAuthPack.data,0);
1206 
1207   asn1_makeseq();
1208   asn1_cleanup();
1209 }
1210 
1211 asn1_error_code asn1_encode_trusted_ca(asn1buf *buf, const krb5_trusted_ca *val, unsigned int *retlen)
1212 {
1213   asn1_setup();
1214 
1215   switch (val->choice) {
1216     case choice_trusted_cas_issuerAndSerial:
1217       asn1_insert_implicit_octetstring(val->u.issuerAndSerial.length,val->u.issuerAndSerial.data,2);
1218       break;
1219     case choice_trusted_cas_caName:
1220       asn1_insert_implicit_octetstring(val->u.caName.length,val->u.caName.data,1);
1221       break;
1222     case choice_trusted_cas_principalName:
1223       asn1_addfield_implicit(val->u.principalName,0,asn1_encode_principal_name);
1224       break;
1225     default:
1226       return ASN1_MISSING_FIELD;
1227   }
1228 
1229   asn1_cleanup();
1230 }
1231 
1232 asn1_error_code asn1_encode_sequence_of_trusted_ca(asn1buf *buf, const krb5_trusted_ca **val, unsigned int *retlen)
1233 {
1234   asn1_setup();
1235   int i;
1236 
1237   if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
1238 
1239   for(i=0; val[i] != NULL; i++);
1240   for(i--; i>=0; i--){
1241     retval = asn1_encode_trusted_ca(buf,val[i],&length);
1242     if(retval) return retval;
1243     sum += length;
1244   }
1245   asn1_makeseq();
1246   asn1_cleanup();
1247 }
1248 
1249 asn1_error_code asn1_encode_pa_pk_as_req_draft9(asn1buf *buf, const krb5_pa_pk_as_req_draft9 *val, unsigned int *retlen)
1250 {
1251   asn1_setup();
1252 
1253   if (val->encryptionCert.length != 0)
1254     asn1_insert_implicit_octetstring(val->encryptionCert.length,val->encryptionCert.data,3);
1255 
1256   if (val->kdcCert.length != 0)
1257     asn1_insert_implicit_octetstring(val->kdcCert.length,val->kdcCert.data,2);
1258 
1259   if (val->trustedCertifiers != NULL)
1260     asn1_addfield((const krb5_trusted_ca **)val->trustedCertifiers,1,asn1_encode_sequence_of_trusted_ca);
1261 
1262   asn1_insert_implicit_octetstring(val->signedAuthPack.length,val->signedAuthPack.data,0);
1263 
1264   asn1_makeseq();
1265   asn1_cleanup();
1266 }
1267 
1268 asn1_error_code asn1_encode_dh_rep_info(asn1buf *buf, const krb5_dh_rep_info *val, unsigned int *retlen)
1269 {
1270   asn1_setup();
1271 
1272   if (val->serverDHNonce.length != 0)
1273     asn1_insert_implicit_octetstring(val->serverDHNonce.length,val->serverDHNonce.data,1);
1274 
1275   asn1_insert_implicit_octetstring(val->dhSignedData.length,val->dhSignedData.data,0);
1276 
1277   asn1_makeseq();
1278   asn1_cleanup();
1279 }
1280 
1281 asn1_error_code asn1_encode_kdc_dh_key_info(asn1buf *buf, const krb5_kdc_dh_key_info *val, unsigned int *retlen)
1282 {
1283   asn1_setup();
1284 
1285   if (val->dhKeyExpiration != 0)
1286     asn1_addfield(val->dhKeyExpiration, 2, asn1_encode_kerberos_time);
1287   asn1_addfield(val->nonce, 1, asn1_encode_integer);
1288 
1289   asn1_insert_implicit_bitstring(val->subjectPublicKey.length,val->subjectPublicKey.data,3);
1290   retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0,
1291 			  val->subjectPublicKey.length + 1 + length,
1292 			  &length);
1293   if(retval) {
1294     asn1buf_destroy(&buf);
1295     return retval;
1296   }
1297   sum += length;
1298 
1299   asn1_makeseq();
1300   asn1_cleanup();
1301 }
1302 
1303 asn1_error_code asn1_encode_reply_key_pack(asn1buf *buf, const krb5_reply_key_pack *val, unsigned int *retlen)
1304 {
1305   asn1_setup();
1306 
1307   asn1_addfield(&(val->asChecksum), 1, asn1_encode_checksum);
1308   asn1_addfield(&(val->replyKey), 0, asn1_encode_encryption_key);
1309 
1310   asn1_makeseq();
1311   asn1_cleanup();
1312 }
1313 
1314 asn1_error_code asn1_encode_reply_key_pack_draft9(asn1buf *buf, const krb5_reply_key_pack_draft9 *val, unsigned int *retlen)
1315 {
1316   asn1_setup();
1317 
1318   asn1_addfield(val->nonce, 1, asn1_encode_integer);
1319   asn1_addfield(&(val->replyKey), 0, asn1_encode_encryption_key);
1320 
1321   asn1_makeseq();
1322   asn1_cleanup();
1323 }
1324 
1325 asn1_error_code asn1_encode_pa_pk_as_rep(asn1buf *buf, const krb5_pa_pk_as_rep *val, unsigned int *retlen)
1326 {
1327   asn1_setup();
1328 
1329   switch (val->choice)
1330   {
1331     case choice_pa_pk_as_rep_dhInfo:
1332       asn1_addfield(&(val->u.dh_Info), choice_pa_pk_as_rep_dhInfo, asn1_encode_dh_rep_info);
1333       break;
1334     case choice_pa_pk_as_rep_encKeyPack:
1335       asn1_insert_implicit_octetstring(val->u.encKeyPack.length,val->u.encKeyPack.data,1);
1336       break;
1337     default:
1338       return ASN1_MISSING_FIELD;
1339   }
1340 
1341   asn1_cleanup();
1342 }
1343 
1344 asn1_error_code asn1_encode_pa_pk_as_rep_draft9(asn1buf *buf, const krb5_pa_pk_as_rep_draft9 *val, unsigned int *retlen)
1345 {
1346   asn1_setup();
1347 
1348   switch (val->choice)
1349   {
1350     case choice_pa_pk_as_rep_draft9_dhSignedData:
1351       asn1_insert_implicit_octetstring(val->u.dhSignedData.length,val->u.dhSignedData.data,0);
1352       break;
1353     case choice_pa_pk_as_rep_encKeyPack:
1354       asn1_insert_implicit_octetstring(val->u.encKeyPack.length,val->u.encKeyPack.data,1);
1355       break;
1356     default:
1357       return ASN1_MISSING_FIELD;
1358   }
1359 
1360   asn1_cleanup();
1361 }
1362 
1363 asn1_error_code asn1_encode_td_trusted_certifiers(asn1buf *buf, const krb5_external_principal_identifier **val, unsigned int *retlen)
1364 {
1365   asn1_setup();
1366   retval = asn1_encode_sequence_of_external_principal_identifier(buf, val, &length);
1367   if (retval) {
1368     asn1buf_destroy(&buf);
1369     return retval;
1370   }
1371   asn1_cleanup();
1372 }
1373 
1374 asn1_error_code asn1_encode_sequence_of_typed_data(asn1buf *buf, const krb5_typed_data **val, unsigned int *retlen)
1375 {
1376   asn1_setup();
1377   int i;
1378 
1379   if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
1380 
1381   for(i=0; val[i] != NULL; i++);
1382   for(i--; i>=0; i--){
1383     retval = asn1_encode_typed_data(buf,val[i],&length);
1384     if(retval) return retval;
1385     sum += length;
1386   }
1387   asn1_makeseq();
1388 
1389   asn1_cleanup();
1390 }
1391 
1392 asn1_error_code asn1_encode_typed_data(asn1buf *buf, const krb5_typed_data *val, unsigned int *retlen)
1393 {
1394   asn1_setup();
1395   asn1_addlenfield(val->length, val->data, 1, asn1_encode_octetstring);
1396   asn1_addfield(val->type, 0, asn1_encode_integer);
1397   asn1_makeseq();
1398   asn1_cleanup();
1399 }
1400