2 * src/lib/krb5/asn.1/krb5_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.
25 #include "asn1_k_encode.h"
26 #include "asn1_encode.h"
29 #include "asn1_make.h"
31 /**************** Macros (these save a lot of typing) ****************/
33 /**** krb5 macros ****/
35 How to write a krb5 encoder function using these macros:
37 asn1_error_code encode_krb5_structure(const krb5_type *rep,
42 krb5_addfield(rep->last_field, n, asn1_type);
43 krb5_addfield(rep->next_to_last_field, n-1, asn1_type);
46 /* for OPTIONAL fields */
47 if(rep->field_i == should_not_be_omitted)
48 krb5_addfield(rep->field_i, i, asn1_type);
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);
54 /* if you really have to do things yourself... */
55 retval = asn1_encode_asn1_type(buf,rep->field,&length);
56 if(retval) return retval;
58 retval = asn1_make_etag(buf,
59 [UNIVERSAL/APPLICATION/CONTEXT_SPECIFIC/PRIVATE],
60 tag_number, length, &length);
61 if(retval) return retval;
65 krb5_addfield(rep->second_field, 1, asn1_type);
66 krb5_addfield(rep->first_field, 0, asn1_type);
68 krb5_apptag(tag_number);
74 /* setup() -- create and initialize bookkeeping variables
75 retval: stores error codes returned from subroutines
76 buf: the coding buffer
77 length: length of the most-recently produced encoding
78 sum: cumulative length of the entire encoding */
80 asn1_error_code retval;\
84 if(rep == NULL) return ASN1_MISSING_FIELD;\
86 retval = asn1buf_create(&buf);\
87 if(retval) return retval
89 /* krb5_addfield -- add a field, or component, to the encoding */
90 #define krb5_addfield(value,tag,encoder)\
91 { retval = encoder(buf,value,&length);\
93 asn1buf_destroy(&buf);\
96 retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\
98 asn1buf_destroy(&buf);\
102 /* krb5_addlenfield -- add a field whose length must be separately specified */
103 #define krb5_addlenfield(len,value,tag,encoder)\
104 { retval = encoder(buf,len,value,&length);\
106 asn1buf_destroy(&buf);\
109 retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\
111 asn1buf_destroy(&buf);\
115 /* form a sequence (by adding a sequence header to the current encoding) */
116 #define krb5_makeseq()\
117 retval = asn1_make_sequence(buf,sum,&length);\
119 asn1buf_destroy(&buf);\
123 /* add an APPLICATION class tag to the current encoding */
124 #define krb5_apptag(num)\
125 retval = asn1_make_etag(buf,APPLICATION,num,sum,&length);\
127 asn1buf_destroy(&buf);\
131 /* produce the final output and clean up the workspace */
132 #define krb5_cleanup()\
133 retval = asn12krb5_buf(buf,code);\
135 asn1buf_destroy(&buf);\
137 retval = asn1buf_destroy(&buf);\
139 asn1buf_destroy(&buf);\
144 krb5_error_code INTERFACE encode_krb5_authenticator(rep, code)
145 const krb5_authenticator * rep;
150 /* authorization-data[8] AuthorizationData OPTIONAL */
151 if(rep->authorization_data != NULL &&
152 rep->authorization_data[0] != NULL){
153 retval = asn1_encode_authorization_data(buf, (const krb5_authdata **)
154 rep->authorization_data,
157 asn1buf_destroy(&buf);
160 retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,8,length,&length);
162 asn1buf_destroy(&buf);
167 /* seq-number[7] INTEGER OPTIONAL */
168 if(rep->seq_number != 0)
169 krb5_addfield(rep->seq_number,7,asn1_encode_integer);
171 /* subkey[6] EncryptionKey OPTIONAL */
172 if(rep->subkey != NULL)
173 krb5_addfield(rep->subkey,6,asn1_encode_encryption_key);
175 /* ctime[5] KerberosTime */
176 krb5_addfield(rep->ctime,5,asn1_encode_kerberos_time);
178 /* cusec[4] INTEGER */
179 krb5_addfield(rep->cusec,4,asn1_encode_integer);
181 /* cksum[3] Checksum OPTIONAL */
182 if(rep->checksum != NULL)
183 krb5_addfield(rep->checksum,3,asn1_encode_checksum);
185 /* cname[2] PrincipalName */
186 krb5_addfield(rep->client,2,asn1_encode_principal_name);
188 /* crealm[1] Realm */
189 krb5_addfield(rep->client,1,asn1_encode_realm);
191 /* authenticator-vno[0] INTEGER */
192 krb5_addfield(KVNO,0,asn1_encode_integer);
194 /* Authenticator ::= [APPLICATION 2] SEQUENCE */
201 krb5_error_code INTERFACE encode_krb5_ticket(rep, code)
202 const krb5_ticket * rep;
207 /* enc-part[3] EncryptedData */
208 krb5_addfield(&(rep->enc_part),3,asn1_encode_encrypted_data);
210 /* sname [2] PrincipalName */
211 krb5_addfield(rep->server,2,asn1_encode_principal_name);
213 /* realm [1] Realm */
214 krb5_addfield(rep->server,1,asn1_encode_realm);
216 /* tkt-vno [0] INTEGER */
217 krb5_addfield(KVNO,0,asn1_encode_integer);
219 /* Ticket ::= [APPLICATION 1] SEQUENCE */
226 krb5_error_code INTERFACE encode_krb5_encryption_key(rep, code)
227 const krb5_keyblock * rep;
232 /* keyvalue[1] OCTET STRING */
233 krb5_addlenfield(rep->length,rep->contents,1,asn1_encode_octetstring);
235 /* keytype[0] INTEGER */
236 krb5_addfield(rep->keytype,0,asn1_encode_integer);
238 /* EncryptionKey ::= SEQUENCE */
244 krb5_error_code INTERFACE encode_krb5_enc_tkt_part(rep, code)
245 const krb5_enc_tkt_part * rep;
250 /* authorization-data[10] AuthorizationData OPTIONAL */
251 if(rep->authorization_data != NULL &&
252 rep->authorization_data[0] != NULL)
253 krb5_addfield((const krb5_authdata**)rep->authorization_data,
254 10,asn1_encode_authorization_data);
256 /* caddr[9] HostAddresses OPTIONAL */
257 if(rep->caddrs != NULL && rep->caddrs[0] != NULL)
258 krb5_addfield((const krb5_address**)rep->caddrs,9,asn1_encode_host_addresses);
260 /* renew-till[8] KerberosTime OPTIONAL */
261 if(rep->times.renew_till)
262 krb5_addfield(rep->times.renew_till,8,asn1_encode_kerberos_time);
264 /* endtime[7] KerberosTime */
265 krb5_addfield(rep->times.endtime,7,asn1_encode_kerberos_time);
267 /* starttime[6] KerberosTime OPTIONAL */
268 if(rep->times.starttime)
269 krb5_addfield(rep->times.starttime,6,asn1_encode_kerberos_time);
271 /* authtime[5] KerberosTime */
272 krb5_addfield(rep->times.authtime,5,asn1_encode_kerberos_time);
274 /* transited[4] TransitedEncoding */
275 krb5_addfield(&(rep->transited),4,asn1_encode_transited_encoding);
277 /* cname[3] PrincipalName */
278 krb5_addfield(rep->client,3,asn1_encode_principal_name);
280 /* crealm[2] Realm */
281 krb5_addfield(rep->client,2,asn1_encode_realm);
283 /* key[1] EncryptionKey */
284 krb5_addfield(rep->session,1,asn1_encode_encryption_key);
286 /* flags[0] TicketFlags */
287 krb5_addfield(rep->flags,0,asn1_encode_ticket_flags);
289 /* EncTicketPart ::= [APPLICATION 3] SEQUENCE */
296 krb5_error_code INTERFACE encode_krb5_enc_kdc_rep_part(rep, code)
297 const krb5_enc_kdc_rep_part * rep;
300 asn1_error_code retval;
304 if(rep == NULL) return ASN1_MISSING_FIELD;
306 retval = asn1buf_create(&buf);
307 if(retval) return retval;
309 retval = asn1_encode_enc_kdc_rep_part(buf,rep,&length);
310 if(retval) return retval;
313 #ifdef KRB5_ENCKRB5KDCREPPART_COMPAT
316 if (rep->msg_type == KRB5_AS_REP) { krb5_apptag(ASN1_KRB_AS_REP); }
317 else if (rep->msg_type == KRB5_TGS_REP) { krb5_apptag(ASN1_KRB_TGS_REP); }
318 else return KRB5_BADMSGTYPE;
323 /* yes, the translation is identical to that used for KDC__REP */
324 krb5_error_code INTERFACE encode_krb5_as_rep(rep, code)
325 const krb5_kdc_rep * rep;
330 /* AS-REP ::= [APPLICATION 11] KDC-REP */
331 retval = asn1_encode_kdc_rep(KRB5_AS_REP,buf,rep,&length);
332 if(retval) return retval;
340 /* yes, the translation is identical to that used for KDC__REP */
341 krb5_error_code INTERFACE encode_krb5_tgs_rep( rep, code)
342 const krb5_kdc_rep * rep;
347 /* TGS-REP ::= [APPLICATION 13] KDC-REP */
348 retval = asn1_encode_kdc_rep(KRB5_TGS_REP,buf,rep,&length);
349 if(retval) return retval;
357 krb5_error_code INTERFACE encode_krb5_ap_req(rep, code)
358 const krb5_ap_req * rep;
363 /* authenticator[4] EncryptedData */
364 krb5_addfield(&(rep->authenticator),4,asn1_encode_encrypted_data);
366 /* ticket[3] Ticket */
367 krb5_addfield(rep->ticket,3,asn1_encode_ticket);
369 /* ap-options[2] APOptions */
370 krb5_addfield(rep->ap_options,2,asn1_encode_ap_options);
372 /* msg-type[1] INTEGER */
373 krb5_addfield(ASN1_KRB_AP_REQ,1,asn1_encode_integer);
375 /* pvno[0] INTEGER */
376 krb5_addfield(KVNO,0,asn1_encode_integer);
378 /* AP-REQ ::= [APPLICATION 14] SEQUENCE */
385 krb5_error_code INTERFACE encode_krb5_ap_rep(rep, code)
386 const krb5_ap_rep * rep;
391 /* enc-part[2] EncryptedData */
392 krb5_addfield(&(rep->enc_part),2,asn1_encode_encrypted_data);
394 /* msg-type[1] INTEGER */
395 krb5_addfield(ASN1_KRB_AP_REP,1,asn1_encode_integer);
397 /* pvno[0] INTEGER */
398 krb5_addfield(KVNO,0,asn1_encode_integer);
400 /* AP-REP ::= [APPLICATION 15] SEQUENCE */
408 krb5_error_code INTERFACE encode_krb5_ap_rep_enc_part(rep, code)
409 const krb5_ap_rep_enc_part * rep;
414 /* seq-number[3] INTEGER OPTIONAL */
416 krb5_addfield(rep->seq_number,3,asn1_encode_integer);
418 /* subkey[2] EncryptionKey OPTIONAL */
419 if(rep->subkey != NULL)
420 krb5_addfield(rep->subkey,2,asn1_encode_encryption_key);
422 /* cusec[1] INTEGER */
423 krb5_addfield(rep->cusec,1,asn1_encode_integer);
425 /* ctime[0] KerberosTime */
426 krb5_addfield(rep->ctime,0,asn1_encode_kerberos_time);
428 /* EncAPRepPart ::= [APPLICATION 27] SEQUENCE */
435 krb5_error_code INTERFACE encode_krb5_as_req(rep, code)
436 const krb5_kdc_req * rep;
441 /* AS-REQ ::= [APPLICATION 10] KDC-REQ */
442 retval = asn1_encode_kdc_req(KRB5_AS_REQ,buf,rep,&length);
443 if(retval) return retval;
451 krb5_error_code INTERFACE encode_krb5_tgs_req(rep, code)
452 const krb5_kdc_req * rep;
457 /* TGS-REQ ::= [APPLICATION 12] KDC-REQ */
458 retval = asn1_encode_kdc_req(KRB5_TGS_REQ,buf,rep,&length);
459 if(retval) return retval;
467 krb5_error_code INTERFACE encode_krb5_kdc_req_body(rep, code)
468 const krb5_kdc_req * rep;
473 retval = asn1_encode_kdc_req_body(buf,rep,&length);
474 if(retval) return retval;
481 krb5_error_code INTERFACE encode_krb5_safe(rep, code)
482 const krb5_safe * rep;
487 /* cksum[3] Checksum */
488 krb5_addfield(rep->checksum,3,asn1_encode_checksum);
490 /* safe-body[2] KRB-SAFE-BODY */
491 krb5_addfield(rep,2,asn1_encode_krb_safe_body);
493 /* msg-type[1] INTEGER */
494 krb5_addfield(ASN1_KRB_SAFE,1,asn1_encode_integer);
496 /* pvno[0] INTEGER */
497 krb5_addfield(KVNO,0,asn1_encode_integer);
499 /* KRB-SAFE ::= [APPLICATION 20] SEQUENCE */
506 krb5_error_code INTERFACE encode_krb5_priv(rep, code)
507 const krb5_priv * rep;
512 /* enc-part[3] EncryptedData */
513 krb5_addfield(&(rep->enc_part),3,asn1_encode_encrypted_data);
515 /* msg-type[1] INTEGER */
516 krb5_addfield(ASN1_KRB_PRIV,1,asn1_encode_integer);
518 /* pvno[0] INTEGER */
519 krb5_addfield(KVNO,0,asn1_encode_integer);
521 /* KRB-PRIV ::= [APPLICATION 21] SEQUENCE */
528 krb5_error_code INTERFACE encode_krb5_enc_priv_part(rep, code)
529 const krb5_priv_enc_part * rep;
534 /* r-address[5] HostAddress OPTIONAL -- recip's addr */
536 krb5_addfield(rep->r_address,5,asn1_encode_host_address);
538 /* s-address[4] HostAddress -- sender's addr */
539 krb5_addfield(rep->s_address,4,asn1_encode_host_address);
541 /* seq-number[3] INTEGER OPTIONAL */
543 krb5_addfield(rep->seq_number,3,asn1_encode_integer);
545 /* usec[2] INTEGER OPTIONAL */
547 krb5_addfield(rep->usec,2,asn1_encode_integer);
548 /* timestamp[1] KerberosTime OPTIONAL */
549 krb5_addfield(rep->timestamp,1,asn1_encode_kerberos_time);
552 /* user-data[0] OCTET STRING */
553 krb5_addlenfield(rep->user_data.length,rep->user_data.data,0,asn1_encode_charstring);
555 /* EncKrbPrivPart ::= [APPLICATION 28] SEQUENCE */
562 krb5_error_code INTERFACE encode_krb5_cred(rep, code)
563 const krb5_cred * rep;
568 /* enc-part[3] EncryptedData */
569 krb5_addfield(&(rep->enc_part),3,asn1_encode_encrypted_data);
571 /* tickets[2] SEQUENCE OF Ticket */
572 krb5_addfield((const krb5_ticket**)rep->tickets,2,asn1_encode_sequence_of_ticket);
574 /* msg-type[1] INTEGER, -- KRB_CRED */
575 krb5_addfield(ASN1_KRB_CRED,1,asn1_encode_integer);
577 /* pvno[0] INTEGER */
578 krb5_addfield(KVNO,0,asn1_encode_integer);
580 /* KRB-CRED ::= [APPLICATION 22] SEQUENCE */
587 krb5_error_code INTERFACE encode_krb5_enc_cred_part(rep, code)
588 const krb5_cred_enc_part * rep;
593 /* r-address[5] HostAddress OPTIONAL */
594 if(rep->r_address != NULL)
595 krb5_addfield(rep->r_address,5,asn1_encode_host_address);
597 /* s-address[4] HostAddress OPTIONAL */
598 if(rep->s_address != NULL)
599 krb5_addfield(rep->s_address,4,asn1_encode_host_address);
601 /* usec[3] INTEGER OPTIONAL */
603 krb5_addfield(rep->usec,3,asn1_encode_integer);
604 /* timestamp[2] KerberosTime OPTIONAL */
605 krb5_addfield(rep->timestamp,2,asn1_encode_kerberos_time);
608 /* nonce[1] INTEGER OPTIONAL */
610 krb5_addfield(rep->nonce,1,asn1_encode_integer);
612 /* ticket-info[0] SEQUENCE OF KrbCredInfo */
613 krb5_addfield((const krb5_cred_info**)rep->ticket_info,
614 0,asn1_encode_sequence_of_krb_cred_info);
616 /* EncKrbCredPart ::= [APPLICATION 29] SEQUENCE */
623 krb5_error_code INTERFACE encode_krb5_error(rep, code)
624 const krb5_error * rep;
629 /* e-data[12] OCTET STRING OPTIONAL */
630 if(rep->e_data.data != NULL && rep->e_data.length > 0)
631 krb5_addlenfield(rep->e_data.length,rep->e_data.data,12,asn1_encode_charstring);
633 /* e-text[11] GeneralString OPTIONAL */
634 if(rep->text.data != NULL && rep->text.length > 0)
635 krb5_addlenfield(rep->text.length,rep->text.data,11,asn1_encode_generalstring);
637 /* sname[10] PrincipalName -- Correct name */
638 krb5_addfield(rep->server,10,asn1_encode_principal_name);
640 /* realm[9] Realm -- Correct realm */
641 krb5_addfield(rep->server,9,asn1_encode_realm);
643 /* cname[8] PrincipalName OPTIONAL */
644 if(rep->client != NULL){
645 krb5_addfield(rep->client,8,asn1_encode_principal_name);
646 /* crealm[7] Realm OPTIONAL */
647 krb5_addfield(rep->client,7,asn1_encode_realm);
650 /* error-code[6] INTEGER */
651 krb5_addfield(rep->error,6,asn1_encode_ui_4);
653 /* susec[5] INTEGER */
654 krb5_addfield(rep->susec,5,asn1_encode_integer);
656 /* stime[4] KerberosTime */
657 krb5_addfield(rep->stime,4,asn1_encode_kerberos_time);
659 /* cusec[3] INTEGER OPTIONAL */
661 krb5_addfield(rep->cusec,3,asn1_encode_integer);
663 /* ctime[2] KerberosTime OPTIONAL */
665 krb5_addfield(rep->ctime,2,asn1_encode_kerberos_time);
667 /* msg-type[1] INTEGER */
668 krb5_addfield(ASN1_KRB_ERROR,1,asn1_encode_integer);
670 /* pvno[0] INTEGER */
671 krb5_addfield(KVNO,0,asn1_encode_integer);
673 /* KRB-ERROR ::= [APPLICATION 30] SEQUENCE */
680 krb5_error_code INTERFACE encode_krb5_authdata(rep, code)
681 const krb5_authdata ** rep;
684 asn1_error_code retval;
688 if(rep == NULL) return ASN1_MISSING_FIELD;
690 retval = asn1buf_create(&buf);
691 if(retval) return retval;
693 retval = asn1_encode_authorization_data(buf,(const krb5_authdata**)rep,
695 if(retval) return retval;
700 /* Sandia Additions */
701 krb5_error_code INTERFACE encode_krb5_pwd_sequence( rep, code)
702 const passwd_phrase_element * rep;
706 retval = asn1_encode_passwdsequence(buf,rep,&length);
707 if(retval) return retval;
712 krb5_error_code INTERFACE encode_krb5_pwd_data(rep, code)
713 const krb5_pwd_data * rep;
717 krb5_addfield((const passwd_phrase_element**)rep->element,1,asn1_encode_sequence_of_passwdsequence);
718 krb5_addfield(rep->sequence_count,0,asn1_encode_integer);