2 * src/lib/krb5/asn.1/asn1_k_encode.c
4 * Copyright 1994 by the Massachusetts Institute of Technology.
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.
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. M.I.T. makes no representations about the suitability of
20 * this software for any purpose. It is provided "as is" without express
21 * or implied warranty.
24 #include "asn1_k_encode.h"
25 #include "asn1_make.h"
26 #include "asn1_encode.h"
28 /**** asn1 macros ****/
30 How to write an asn1 encoder function using these macros:
32 asn1_error_code asn1_encode_krb5_substructure(asn1buf *buf,
38 asn1_addfield(val->last_field, n, asn1_type);
39 asn1_addfield(rep->next_to_last_field, n-1, asn1_type);
42 /* for OPTIONAL fields */
43 if(rep->field_i == should_not_be_omitted)
44 asn1_addfield(rep->field_i, i, asn1_type);
46 /* for string fields (these encoders take an additional argument,
47 the length of the string) */
48 addlenfield(rep->field_length, rep->field, i-1, asn1_type);
50 /* if you really have to do things yourself... */
51 retval = asn1_encode_asn1_type(buf,rep->field,&length);
52 if(retval) return retval;
54 retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, tag_number, length,
56 if(retval) return retval;
60 asn1_addfield(rep->second_field, 1, asn1_type);
61 asn1_addfield(rep->first_field, 0, asn1_type);
68 /* setup() -- create and initialize bookkeeping variables
69 retval: stores error codes returned from subroutines
70 length: length of the most-recently produced encoding
71 sum: cumulative length of the entire encoding */
73 asn1_error_code retval;\
76 /* asn1_addfield -- add a field, or component, to the encoding */
77 #define asn1_addfield(value,tag,encoder)\
78 { retval = encoder(buf,value,&length);\
80 asn1buf_destroy(&buf);\
83 retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\
85 asn1buf_destroy(&buf);\
89 /* asn1_addlenfield -- add a field whose length must be separately specified */
90 #define asn1_addlenfield(len,value,tag,encoder)\
91 { retval = encoder(buf,len,value,&length);\
93 asn1buf_destroy(&buf);\
96 retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\
98 asn1buf_destroy(&buf);\
102 /* form a sequence (by adding a sequence header to the current encoding) */
103 #define asn1_makeseq()\
104 retval = asn1_make_sequence(buf,sum,&length);\
106 asn1buf_destroy(&buf);\
110 /* add an APPLICATION class tag to the current encoding */
111 #define asn1_apptag(num)\
112 retval = asn1_make_etag(buf,APPLICATION,num,sum,&length);\
114 asn1buf_destroy(&buf);\
118 /* produce the final output and clean up the workspace */
119 #define asn1_cleanup()\
123 asn1_error_code asn1_encode_ui_4(buf, val, retlen)
128 return asn1_encode_unsigned_integer(buf,val,retlen);
132 asn1_error_code asn1_encode_realm(buf, val, retlen)
134 const krb5_principal val;
137 if(val == NULL || val->realm.data == NULL) return ASN1_MISSING_FIELD;
138 return asn1_encode_generalstring(buf,val->realm.length,val->realm.data,
142 asn1_error_code asn1_encode_principal_name(buf, val, retlen)
144 const krb5_principal val;
150 if(val == NULL || val->data == NULL) return ASN1_MISSING_FIELD;
152 for(n = (int) ((val->length)-1); n >= 0; n--){
153 if(val->data[n].data == NULL) return ASN1_MISSING_FIELD;
154 retval = asn1_encode_generalstring(buf,
155 (val->data)[n].length,
158 if(retval) return retval;
162 retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,1,sum,&length);
163 if(retval) return retval;
166 asn1_addfield(val->type,0,asn1_encode_integer);
173 asn1_error_code asn1_encode_kerberos_time(buf, val, retlen)
175 const krb5_timestamp val;
179 return asn1_encode_generaltime(buf,val,retlen);
182 asn1_error_code asn1_encode_host_address(buf, val, retlen)
184 const krb5_address * val;
189 if(val == NULL || val->contents == NULL) return ASN1_MISSING_FIELD;
191 asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring);
192 asn1_addfield(val->addrtype,0,asn1_encode_integer);
198 asn1_error_code asn1_encode_host_addresses(buf, val, retlen)
200 const krb5_address ** val;
206 if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
208 for(i=0; val[i] != NULL; i++); /* go to end of array */
210 retval = asn1_encode_host_address(buf,val[i],&length);
211 if(retval) return retval;
219 asn1_error_code asn1_encode_encrypted_data(buf, val, retlen)
221 const krb5_enc_data * val;
226 if(val == NULL || val->ciphertext.data == NULL) return ASN1_MISSING_FIELD;
228 asn1_addlenfield(val->ciphertext.length,val->ciphertext.data,2,asn1_encode_charstring);
230 asn1_addfield(val->kvno,1,asn1_encode_integer);
231 asn1_addfield(val->enctype,0,asn1_encode_integer);
238 asn1_error_code asn1_encode_krb5_flags(buf, val, retlen)
240 const krb5_flags val;
244 krb5_flags valcopy = val;
248 retval = asn1buf_insert_octet(buf,(asn1_octet) (valcopy&0xFF));
249 if(retval) return retval;
252 retval = asn1buf_insert_octet(buf,0); /* 0 padding bits */
253 if(retval) return retval;
256 retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_BITSTRING,sum,
258 if(retval) return retval;
265 asn1_error_code asn1_encode_ap_options(buf, val, retlen)
267 const krb5_flags val;
270 return asn1_encode_krb5_flags(buf,val,retlen);
273 asn1_error_code asn1_encode_ticket_flags(buf, val, retlen)
275 const krb5_flags val;
278 return asn1_encode_krb5_flags(buf,val,retlen);
281 asn1_error_code asn1_encode_kdc_options(buf, val, retlen)
283 const krb5_flags val;
286 return asn1_encode_krb5_flags(buf,val,retlen);
289 asn1_error_code asn1_encode_authorization_data(buf, val, retlen)
291 const krb5_authdata ** val;
297 if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
299 for(i=0; val[i] != NULL; i++); /* get to the end of the array */
301 retval = asn1_encode_krb5_authdata_elt(buf,val[i],&length);
302 if(retval) return retval;
310 asn1_error_code asn1_encode_krb5_authdata_elt(buf, val, retlen)
312 const krb5_authdata * val;
317 if(val == NULL || val->contents == NULL) return ASN1_MISSING_FIELD;
319 /* ad-data[1] OCTET STRING */
320 asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring);
321 /* ad-type[0] INTEGER */
322 asn1_addfield(val->ad_type,0,asn1_encode_integer);
329 asn1_error_code asn1_encode_kdc_rep(msg_type, buf, val, retlen)
332 const krb5_kdc_rep * val;
337 if(val == NULL) return ASN1_MISSING_FIELD;
339 asn1_addfield(&(val->enc_part),6,asn1_encode_encrypted_data);
340 asn1_addfield(val->ticket,5,asn1_encode_ticket);
341 asn1_addfield(val->client,4,asn1_encode_principal_name);
342 asn1_addfield(val->client,3,asn1_encode_realm);
343 if(val->padata != NULL && val->padata[0] != NULL)
344 asn1_addfield((const krb5_pa_data**)val->padata,2,asn1_encode_sequence_of_pa_data);
345 if (msg_type != KRB5_AS_REP && msg_type != KRB5_TGS_REP)
346 return KRB5_BADMSGTYPE;
347 asn1_addfield(msg_type,1,asn1_encode_integer);
348 asn1_addfield(KVNO,0,asn1_encode_integer);
354 asn1_error_code asn1_encode_enc_kdc_rep_part(buf, val, retlen)
356 const krb5_enc_kdc_rep_part * val;
361 if(val == NULL) return ASN1_MISSING_FIELD;
363 /* caddr[11] HostAddresses OPTIONAL */
364 if(val->caddrs != NULL && val->caddrs[0] != NULL)
365 asn1_addfield((const krb5_address**)(val->caddrs),11,asn1_encode_host_addresses);
367 /* sname[10] PrincipalName */
368 asn1_addfield(val->server,10,asn1_encode_principal_name);
370 /* srealm[9] Realm */
371 asn1_addfield(val->server,9,asn1_encode_realm);
373 /* renew-till[8] KerberosTime OPTIONAL */
374 if(val->flags & TKT_FLG_RENEWABLE)
375 asn1_addfield(val->times.renew_till,8,asn1_encode_kerberos_time);
377 /* endtime[7] KerberosTime */
378 asn1_addfield(val->times.endtime,7,asn1_encode_kerberos_time);
380 /* starttime[6] KerberosTime OPTIONAL */
381 if(val->times.starttime)
382 asn1_addfield(val->times.starttime,6,asn1_encode_kerberos_time);
384 /* authtime[5] KerberosTime */
385 asn1_addfield(val->times.authtime,5,asn1_encode_kerberos_time);
387 /* flags[4] TicketFlags */
388 asn1_addfield(val->flags,4,asn1_encode_ticket_flags);
390 /* key-expiration[3] KerberosTime OPTIONAL */
392 asn1_addfield(val->key_exp,3,asn1_encode_kerberos_time);
394 /* nonce[2] INTEGER */
395 asn1_addfield(val->nonce,2,asn1_encode_integer);
397 /* last-req[1] LastReq */
398 asn1_addfield((const krb5_last_req_entry**)val->last_req,1,asn1_encode_last_req);
400 /* key[0] EncryptionKey */
401 asn1_addfield(val->session,0,asn1_encode_encryption_key);
403 /* EncKDCRepPart ::= SEQUENCE */
409 asn1_error_code asn1_encode_kdc_req_body(buf, rep, retlen)
411 const krb5_kdc_req * rep;
416 if(rep == NULL) return ASN1_MISSING_FIELD;
418 /* additional-tickets[11] SEQUENCE OF Ticket OPTIONAL */
419 if(rep->second_ticket != NULL && rep->second_ticket[0] != NULL)
420 asn1_addfield((const krb5_ticket**)rep->second_ticket,
421 11,asn1_encode_sequence_of_ticket);
423 /* enc-authorization-data[10] EncryptedData OPTIONAL, */
424 /* -- Encrypted AuthorizationData encoding */
425 if(rep->authorization_data.ciphertext.data != NULL)
426 asn1_addfield(&(rep->authorization_data),10,asn1_encode_encrypted_data);
428 /* addresses[9] HostAddresses OPTIONAL, */
429 if(rep->addresses != NULL && rep->addresses[0] != NULL)
430 asn1_addfield((const krb5_address**)rep->addresses,9,asn1_encode_host_addresses);
432 /* etype[8] SEQUENCE OF INTEGER, -- EncryptionType, */
433 /* -- in preference order */
434 asn1_addlenfield(rep->nktypes,rep->ktype,8,asn1_encode_sequence_of_enctype);
436 /* nonce[7] INTEGER, */
437 asn1_addfield(rep->nonce,7,asn1_encode_integer);
439 /* rtime[6] KerberosTime OPTIONAL, */
441 asn1_addfield(rep->rtime,6,asn1_encode_kerberos_time);
443 /* till[5] KerberosTime, */
444 asn1_addfield(rep->till,5,asn1_encode_kerberos_time);
446 /* from[4] KerberosTime OPTIONAL, */
448 asn1_addfield(rep->from,4,asn1_encode_kerberos_time);
450 /* sname[3] PrincipalName OPTIONAL, */
451 if(rep->server != NULL)
452 asn1_addfield(rep->server,3,asn1_encode_principal_name);
454 /* realm[2] Realm, -- Server's realm */
455 /* -- Also client's in AS-REQ */
456 if(rep->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY){
457 if(rep->second_ticket != NULL && rep->second_ticket[0] != NULL){
458 asn1_addfield(rep->second_ticket[0]->server,2,asn1_encode_realm)
459 } else return ASN1_MISSING_FIELD;
460 }else if(rep->server != NULL){
461 asn1_addfield(rep->server,2,asn1_encode_realm);
462 }else return ASN1_MISSING_FIELD;
464 /* cname[1] PrincipalName OPTIONAL, */
465 /* -- Used only in AS-REQ */
466 if(rep->client != NULL)
467 asn1_addfield(rep->client,1,asn1_encode_principal_name);
469 /* kdc-options[0] KDCOptions, */
470 asn1_addfield(rep->kdc_options,0,asn1_encode_kdc_options);
472 /* KDC-REQ-BODY ::= SEQUENCE */
478 asn1_error_code asn1_encode_encryption_key(buf, val, retlen)
480 const krb5_keyblock * val;
485 if(val == NULL || val->contents == NULL) return ASN1_MISSING_FIELD;
487 asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring);
488 asn1_addfield(val->enctype,0,asn1_encode_integer);
494 asn1_error_code asn1_encode_checksum(buf, val, retlen)
496 const krb5_checksum * val;
501 if(val == NULL || val->contents == NULL) return ASN1_MISSING_FIELD;
503 asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring);
504 asn1_addfield(val->checksum_type,0,asn1_encode_integer);
510 asn1_error_code asn1_encode_transited_encoding(buf, val, retlen)
512 const krb5_transited * val;
518 (val->tr_contents.length != 0 && val->tr_contents.data == NULL))
519 return ASN1_MISSING_FIELD;
521 asn1_addlenfield(val->tr_contents.length,val->tr_contents.data,
522 1,asn1_encode_charstring);
523 asn1_addfield(val->tr_type,0,asn1_encode_integer);
529 asn1_error_code asn1_encode_last_req(buf, val, retlen)
531 const krb5_last_req_entry ** val;
537 if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
539 for(i=0; val[i] != NULL; i++); /* go to end of array */
541 retval = asn1_encode_last_req_entry(buf,val[i],&length);
542 if(retval) return retval;
550 asn1_error_code asn1_encode_last_req_entry(buf, val, retlen)
552 const krb5_last_req_entry * val;
557 if(val == NULL) return ASN1_MISSING_FIELD;
559 asn1_addfield(val->value,1,asn1_encode_kerberos_time);
560 asn1_addfield(val->lr_type,0,asn1_encode_integer);
566 asn1_error_code asn1_encode_sequence_of_pa_data(buf, val, retlen)
568 const krb5_pa_data ** val;
574 if (val == NULL) return ASN1_MISSING_FIELD;
576 for(i=0; val[i] != NULL; i++);
578 retval = asn1_encode_pa_data(buf,val[i],&length);
579 if(retval) return retval;
587 asn1_error_code asn1_encode_pa_data(buf, val, retlen)
589 const krb5_pa_data * val;
594 if(val == NULL || (val->length != 0 && val->contents == NULL))
595 return ASN1_MISSING_FIELD;
597 asn1_addlenfield(val->length,val->contents,2,asn1_encode_octetstring);
598 asn1_addfield(val->pa_type,1,asn1_encode_integer);
604 asn1_error_code asn1_encode_sequence_of_ticket(buf, val, retlen)
606 const krb5_ticket ** val;
612 if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
614 for(i=0; val[i] != NULL; i++);
616 retval = asn1_encode_ticket(buf,val[i],&length);
617 if(retval) return retval;
625 asn1_error_code asn1_encode_ticket(buf, val, retlen)
627 const krb5_ticket * val;
632 if(val == NULL) return ASN1_MISSING_FIELD;
634 asn1_addfield(&(val->enc_part),3,asn1_encode_encrypted_data);
635 asn1_addfield(val->server,2,asn1_encode_principal_name);
636 asn1_addfield(val->server,1,asn1_encode_realm);
637 asn1_addfield(KVNO,0,asn1_encode_integer);
644 asn1_error_code asn1_encode_sequence_of_enctype(buf, len, val, retlen)
647 const krb5_enctype * val;
653 if(val == NULL) return ASN1_MISSING_FIELD;
655 for(i=len-1; i>=0; i--){
656 retval = asn1_encode_integer(buf,val[i],&length);
657 if(retval) return retval;
665 asn1_error_code asn1_encode_kdc_req(msg_type, buf, val, retlen)
668 const krb5_kdc_req * val;
673 if(val == NULL) return ASN1_MISSING_FIELD;
675 asn1_addfield(val,4,asn1_encode_kdc_req_body);
676 if(val->padata != NULL && val->padata[0] != NULL)
677 asn1_addfield((const krb5_pa_data**)val->padata,3,asn1_encode_sequence_of_pa_data);
678 if (msg_type != KRB5_AS_REQ && msg_type != KRB5_TGS_REQ)
679 return KRB5_BADMSGTYPE;
680 asn1_addfield(msg_type,2,asn1_encode_integer);
681 asn1_addfield(KVNO,1,asn1_encode_integer);
687 asn1_error_code asn1_encode_krb_safe_body(buf, val, retlen)
689 const krb5_safe * val;
694 if(val == NULL) return ASN1_MISSING_FIELD;
696 if(val->r_address != NULL)
697 asn1_addfield(val->r_address,5,asn1_encode_host_address);
698 asn1_addfield(val->s_address,4,asn1_encode_host_address);
700 asn1_addfield(val->seq_number,3,asn1_encode_integer);
702 asn1_addfield(val->usec,2,asn1_encode_integer);
703 asn1_addfield(val->timestamp,1,asn1_encode_kerberos_time);
705 if(val->user_data.data == NULL) return ASN1_MISSING_FIELD;
706 asn1_addlenfield(val->user_data.length,val->user_data.data,0,asn1_encode_charstring)
713 asn1_error_code asn1_encode_sequence_of_krb_cred_info(buf, val, retlen)
715 const krb5_cred_info ** val;
721 if(val == NULL) return ASN1_MISSING_FIELD;
723 for(i=0; val[i] != NULL; i++);
725 retval = asn1_encode_krb_cred_info(buf,val[i],&length);
726 if(retval) return retval;
734 asn1_error_code asn1_encode_krb_cred_info(buf, val, retlen)
736 const krb5_cred_info * val;
741 if(val == NULL) return ASN1_MISSING_FIELD;
743 if(val->caddrs != NULL && val->caddrs[0] != NULL)
744 asn1_addfield((const krb5_address**)val->caddrs,10,asn1_encode_host_addresses);
745 if(val->server != NULL){
746 asn1_addfield(val->server,9,asn1_encode_principal_name);
747 asn1_addfield(val->server,8,asn1_encode_realm);
749 if(val->times.renew_till)
750 asn1_addfield(val->times.renew_till,7,asn1_encode_kerberos_time);
751 if(val->times.endtime)
752 asn1_addfield(val->times.endtime,6,asn1_encode_kerberos_time);
753 if(val->times.starttime)
754 asn1_addfield(val->times.starttime,5,asn1_encode_kerberos_time);
755 if(val->times.authtime)
756 asn1_addfield(val->times.authtime,4,asn1_encode_kerberos_time);
758 asn1_addfield(val->flags,3,asn1_encode_ticket_flags);
759 if(val->client != NULL){
760 asn1_addfield(val->client,2,asn1_encode_principal_name);
761 asn1_addfield(val->client,1,asn1_encode_realm);
763 asn1_addfield(val->session,0,asn1_encode_encryption_key);
770 asn1_error_code asn1_encode_etype_info_entry(buf, val, retlen)
772 const krb5_etype_info_entry * val;
777 if(val == NULL || (val->length >= 0 && val->salt == NULL))
778 return ASN1_MISSING_FIELD;
780 if (val->length >= 0)
781 asn1_addlenfield((int) val->length,val->salt,1,
782 asn1_encode_octetstring);
783 asn1_addfield(val->etype,0,asn1_encode_integer);
789 asn1_error_code asn1_encode_etype_info(buf, val, retlen)
791 const krb5_etype_info_entry ** val;
797 if (val == NULL) return ASN1_MISSING_FIELD;
799 for(i=0; val[i] != NULL; i++); /* get to the end of the array */
801 retval = asn1_encode_etype_info_entry(buf,val[i],&length);
802 if(retval) return retval;
809 asn1_error_code asn1_encode_sequence_of_passwdsequence(buf, val, retlen)
811 const passwd_phrase_element ** val;
817 if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
819 for(i=0; val[i] != NULL; i++); /* get to the end of the array */
821 retval = asn1_encode_passwdsequence(buf,val[i],&length);
822 if(retval) return retval;
829 asn1_error_code asn1_encode_passwdsequence(buf, val, retlen)
831 const passwd_phrase_element * val;
835 asn1_addlenfield(val->phrase->length,val->phrase->data,1,asn1_encode_charstring);
836 asn1_addlenfield(val->passwd->length,val->passwd->data,0,asn1_encode_charstring);