/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* -*- mode: c; indent-tabs-mode: nil -*- */
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
*
* Copyright 1994, 2008 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
* require a specific license from the United States Government.
* It is the responsibility of any person or organization contemplating
* export to obtain such a license before exporting.
*
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
* distribute this software and its documentation for any purpose and
* without fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation, and that
* the name of M.I.T. not be used in advertising or publicity pertaining
* to distribution of the software without specific, written prior
* permission. Furthermore if you modify this software you must label
* your software as modified software and not distribute it in such a
* fashion that it might be confused with the original M.I.T. software.
* M.I.T. makes no representations about the suitability of
* this software for any purpose. It is provided "as is" without express
* or implied warranty.
*/
#include "asn1_k_encode.h"
#include "asn1_make.h"
#include "asn1_encode.h"
#include <assert.h>
#include "k5-platform-store_32.h" /* Solaris Kerberos */
/* helper macros
These are mostly only needed for PKINIT, but there are three
basic-krb5 encoders not converted yet. */
/* setup() -- create and initialize bookkeeping variables
retval: stores error codes returned from subroutines
length: length of the most-recently produced encoding
sum: cumulative length of the entire encoding */
#define asn1_setup()\
unsigned int sum=0
/* form a sequence (by adding a sequence header to the current encoding) */
#define asn1_makeseq()\
{ unsigned int length;\
if (retval) {\
return retval; }\
/* produce the final output and clean up the workspace */
#define asn1_cleanup()\
return 0
/* asn1_addfield -- add a field, or component, to the encoding */
{ unsigned int length; \
if (retval) {\
return retval; }\
if (retval) {\
return retval; }\
DEFUINTTYPE(uint, unsigned int);
};
/* krb5_principal is a typedef for krb5_principal_data*, so this is
effectively "encode_principal_data_at" with an address arg. */
static asn1_error_code
unsigned int *retlen)
{
/* Range checking for time_t vs krb5_timestamp? */
}
};
static unsigned int
{
unsigned int optional = 0;
return optional;
}
};
/* The encode_bitstring function wants an array of bytes (since PKINIT
may provide something that isn't 32 bits), but krb5_flags is stored
as a 32-bit integer in host order. */
static asn1_error_code
unsigned int *retlen)
{
}
/* ad-type[0] INTEGER */
/* ad-data[1] OCTET STRING */
};
};
};
};
FIELD_INT_IMM(KVNO, 0),
};
};
/* EncKDCRepPart ::= SEQUENCE */
/* key[0] EncryptionKey */
/* last-req[1] LastReq */
/* nonce[2] INTEGER */
/* key-expiration[3] KerberosTime OPTIONAL */
/* flags[4] TicketFlags */
/* authtime[5] KerberosTime */
/* starttime[6] KerberosTime OPTIONAL */
/* endtime[7] KerberosTime */
/* renew-till[8] KerberosTime OPTIONAL */
/* srealm[9] Realm */
/* sname[10] PrincipalName */
/* caddr[11] HostAddresses OPTIONAL */
11, 11),
/* encrypted-pa-data[12] SEQUENCE OF PA-DATA OPTIONAL */
};
static unsigned int optional_enc_kdc_rep_part(const void *p)
{
unsigned int optional = 0;
return optional;
}
/* Yuck! Eventually push this *up* above the encoder API and make the
rest of the library put the realm name in one consistent place. At
the same time, might as well add the msg-type field and encode both
AS-REQ and TGS-REQ through the same descriptor. */
struct kdc_req_hack {
krb5_kdc_req v;
};
};
static unsigned int optional_kdc_req_hack(const void *p)
{
unsigned int optional = 0;
return optional;
}
static asn1_error_code
unsigned int *);
static asn1_error_code
unsigned int *retlen)
{
} else return ASN1_MISSING_FIELD;
} else return ASN1_MISSING_FIELD;
}
/* end ugly hack */
};
};
static unsigned int optional_krb_safe_body(const void *p)
{
unsigned int optional = 0;
}
if (val->seq_number)
return optional;
}
};
static unsigned int optional_krb_cred_info(const void *p)
{
unsigned int optional = 0;
}
}
return optional;
}
static unsigned int
{
unsigned int optional = 0;
return optional;
}
};
static unsigned int
{
unsigned int optional = 0;
return optional;
}
1, 1),
};
};
};
static unsigned int optional_sam_challenge(const void *p)
{
unsigned int optional = 0;
return optional;
}
#if 0 /* encoders not used! */
static asn1_error_code
unsigned int *retlen)
{
asn1_setup();
return ASN1_MISSING_FIELD;
{
unsigned int length;
if (retval) {
return retval;
}
if (retval) {
return retval;
}
}
asn1_makeseq();
asn1_cleanup();
}
static const struct field_info sam_challenge_2_body_fields[] = {
};
static unsigned int optional_sam_challenge_2_body(const void *p)
{
const krb5_sam_challenge_2_body *val = p;
unsigned int optional = 0;
return optional;
}
#endif
};
};
static unsigned int optional_enc_sam_response_enc(const void *p)
{
unsigned int optional = 0;
return optional;
}
};
static unsigned int optional_enc_sam_response_enc_2(const void *p)
{
unsigned int optional = 0;
return optional;
}
};
static unsigned int optional_sam_response(const void *p)
{
unsigned int optional = 0;
if (val->sam_patimestamp)
return optional;
}
};
static unsigned int optional_sam_response_2(const void *p)
{
unsigned int optional = 0;
return optional;
}
};
static unsigned int optional_predicted_sam_response(const void *p)
{
unsigned int optional = 0;
return optional;
}
/* Authenticator ::= [APPLICATION 2] SEQUENCE */
/* authenticator-vno[0] INTEGER */
FIELD_INT_IMM(KVNO, 0),
/* crealm[1] Realm */
/* cname[2] PrincipalName */
/* cksum[3] Checksum OPTIONAL */
/* cusec[4] INTEGER */
/* ctime[5] KerberosTime */
/* subkey[6] EncryptionKey OPTIONAL */
/* seq-number[7] INTEGER OPTIONAL */
/* authorization-data[8] AuthorizationData OPTIONAL */
};
static unsigned int optional_krb5_authenticator(const void *p)
{
unsigned int optional = 0;
if (val->seq_number != 0)
return optional;
}
/* EncTicketPart ::= [APPLICATION 3] SEQUENCE */
/* flags[0] TicketFlags */
/* key[1] EncryptionKey */
/* crealm[2] Realm */
/* cname[3] PrincipalName */
/* transited[4] TransitedEncoding */
/* authtime[5] KerberosTime */
/* starttime[6] KerberosTime OPTIONAL */
/* endtime[7] KerberosTime */
/* renew-till[8] KerberosTime OPTIONAL */
/* caddr[9] HostAddresses OPTIONAL */
/* authorization-data[10] AuthorizationData OPTIONAL */
};
static unsigned int optional_enc_tkt_part(const void *p)
{
unsigned int optional = 0;
return optional;
}
/* AS-REP ::= [APPLICATION 11] KDC-REP */
/* But KDC-REP needs to know what type it's being encapsulated
in, so expand each version. */
FIELD_INT_IMM(KVNO, 0),
};
static unsigned int optional_as_rep(const void *p)
{
unsigned int optional = 0;
return optional;
}
/* TGS-REP ::= [APPLICATION 13] KDC-REP */
/* But KDC-REP needs to know what type it's being encapsulated
in, so expand each version. */
FIELD_INT_IMM(KVNO, 0),
};
static unsigned int optional_tgs_rep(const void *p)
{
unsigned int optional = 0;
return optional;
}
/* AP-REQ ::= [APPLICATION 14] SEQUENCE */
/* pvno[0] INTEGER */
FIELD_INT_IMM(KVNO, 0),
/* msg-type[1] INTEGER */
/* ap-options[2] APOptions */
/* ticket[3] Ticket */
/* authenticator[4] EncryptedData */
};
/* AP-REP ::= [APPLICATION 15] SEQUENCE */
/* pvno[0] INTEGER */
FIELD_INT_IMM(KVNO, 0),
/* msg-type[1] INTEGER */
/* enc-part[2] EncryptedData */
};
/* EncAPRepPart ::= [APPLICATION 27] SEQUENCE */
/* ctime[0] KerberosTime */
/* cusec[1] INTEGER */
/* subkey[2] EncryptionKey OPTIONAL */
/* seq-number[3] INTEGER OPTIONAL */
};
static unsigned int optional_ap_rep_enc_part(const void *p)
{
unsigned int optional = 0;
if (val->seq_number)
return optional;
}
/* AS-REQ ::= [APPLICATION 10] KDC-REQ */
};
static unsigned int optional_as_req(const void *p)
{
unsigned int optional = 0;
return optional;
}
/* TGS-REQ ::= [APPLICATION 12] KDC-REQ */
};
static unsigned int optional_tgs_req(const void *p)
{
unsigned int optional = 0;
return optional;
}
FIELD_INT_IMM(KVNO, 0),
};
FIELD_INT_IMM(KVNO, 0),
};
FIELD_INT_IMM(KVNO, 0),
};
};
static unsigned int optional_priv_enc_part(const void *p)
{
unsigned int optional = 0;
}
if (val->seq_number)
return optional;
}
/* KRB-CRED ::= [APPLICATION 22] SEQUENCE */
/* pvno[0] INTEGER */
FIELD_INT_IMM(KVNO, 0),
/* msg-type[1] INTEGER, -- KRB_CRED */
/* tickets[2] SEQUENCE OF Ticket */
/* enc-part[3] EncryptedData */
};
/* EncKrbCredPart ::= [APPLICATION 29] SEQUENCE */
/* ticket-info[0] SEQUENCE OF KrbCredInfo */
/* nonce[1] INTEGER OPTIONAL */
/* timestamp[2] KerberosTime OPTIONAL */
/* usec[3] INTEGER OPTIONAL */
/* s-address[4] HostAddress OPTIONAL */
/* r-address[5] HostAddress OPTIONAL */
};
static unsigned int optional_enc_cred_part(const void *p)
{
unsigned int optional = 0;
}
return optional;
}
/* KRB-ERROR ::= [APPLICATION 30] SEQUENCE */
/* pvno[0] INTEGER */
FIELD_INT_IMM(KVNO, 0),
/* msg-type[1] INTEGER */
/* ctime[2] KerberosTime OPTIONAL */
/* cusec[3] INTEGER OPTIONAL */
/* stime[4] KerberosTime */
/* susec[5] INTEGER */
/* error-code[6] INTEGER */
/* crealm[7] Realm OPTIONAL */
/* cname[8] PrincipalName OPTIONAL */
/* realm[9] Realm -- Correct realm */
/* sname[10] PrincipalName -- Correct name */
/* e-text[11] GeneralString OPTIONAL */
/* e-data[12] OCTET STRING OPTIONAL */
};
static unsigned int optional_error(const void *p)
{
unsigned int optional = 0;
}
return optional;
}
};
static unsigned int
optional_alt_method(const void *p)
{
const krb5_alt_method *a = p;
unsigned int optional = 0;
return optional;
}
};
static unsigned int
optional_pa_enc_ts(const void *p)
{
unsigned int optional = 0;
return optional;
}
};
};
/* [MS-SFU] Section 2.2.1. */
};
/* draft-ietf-krb-wg-kerberos-referrals Appendix A. */
};
/* draft-ietf-krb-wg-kerberos-referrals Section 8. */
};
DEFSEQTYPE(pa_server_referral_data, krb5_pa_server_referral_data, pa_server_referral_data_fields, 0);
#if 0
/* draft-brezak-win2k-krb-authz Section 6. */
static const struct field_info pa_pac_request_fields[] = {
};
#endif
/* RFC 4537 */
/* draft-ietf-krb-wg-preauth-framework-09 */
};
};
static unsigned int fast_armored_req_optional (const void *p) {
unsigned int optional = 0;
optional |= (1u)<<0;
return optional;
}
DEFSEQTYPE( fast_armored_req, krb5_fast_armored_req, fast_armored_req_fields, fast_armored_req_optional);
};
};
};
static unsigned int fast_response_optional (const void *p)
{
unsigned int optional = 0;
if (val->strengthen_key)
return optional;
}
};
/* Exported complete encoders -- these produce a krb5_data with
the encoding in the correct byte order. */
/* XXX We currently (for backwards compatibility) encode both
EncASRepPart and EncTGSRepPart with application tag 26. */
/*
* encode_krb5_safe_with_body
*
* Like encode_krb5_safe(), except takes a saved KRB-SAFE-BODY
* encoding to avoid problems with re-encoding.
*/
/* Sandia Additions */
/* sam preauth additions */
#if 0 /* encoders not used! */
#endif
/*
* PKINIT
*/
/* This code hasn't been converted to use the above framework yet,
because we currently have no test cases to validate the new
version. It *also* appears that some of the encodings may disagree
with the specifications, but that's a separate problem. */
/**** asn1 macros ****/
#if 0
int *retlen)
{
asn1_setup();
...
/* for OPTIONAL fields */
/* for string fields (these encoders take an additional argument,
the length of the string) */
/* if you really have to do things yourself... */
&length);
...
asn1_makeseq();
asn1_cleanup();
}
#endif
/* asn1_addlenfield -- add a field whose length must be separately specified */
{ unsigned int length; \
if (retval) {\
return retval; }\
if (retval) {\
return retval; }\
/* asn1_addfield_implicit -- add an implicitly tagged field, or component, to the encoding */
{ unsigned int length;\
if (retval) {\
return retval; }\
if (retval) {\
return retval; }\
/* asn1_insert_implicit_octetstring -- add an octet string with implicit tagging */
{ unsigned int length;\
if (retval) {\
return retval; }\
if (retval) {\
return retval; }\
/* asn1_insert_implicit_bitstring -- add a bitstring with implicit tagging */
/* needs "length" declared in enclosing context */
if (retval) {\
return retval; }\
if (retval) {\
return retval; }\
sum++;\
if (retval) {\
return retval; }\
#ifndef DISABLE_PKINIT
/* Callable encoders for the types defined above, until the PKINIT
encoders get converted. */
static asn1_error_code
unsigned int *retlen)
{
}
/* Now the real PKINIT encoder functions. */
asn1_error_code asn1_encode_pk_authenticator(asn1buf *buf, const krb5_pk_authenticator *val, unsigned int *retlen)
{
asn1_setup();
asn1_makeseq();
asn1_cleanup();
}
asn1_error_code asn1_encode_pk_authenticator_draft9(asn1buf *buf, const krb5_pk_authenticator_draft9 *val, unsigned int *retlen)
{
asn1_setup();
asn1_makeseq();
asn1_cleanup();
}
asn1_error_code asn1_encode_algorithm_identifier(asn1buf *buf, const krb5_algorithm_identifier *val, unsigned int *retlen)
{
asn1_setup();
if (retval)
return retval;
}
{
unsigned int length;
&length);
if (retval)
return retval;
}
asn1_makeseq();
asn1_cleanup();
}
asn1_error_code asn1_encode_subject_pk_info(asn1buf *buf, const krb5_subject_pk_info *val, unsigned int *retlen)
{
asn1_setup();
{
unsigned int length;
asn1_insert_implicit_bitstring(val->subjectPublicKey.length,val->subjectPublicKey.data,ASN1_BITSTRING);
}
unsigned int length;
if (retval)
return retval;
&length);
if (retval)
return retval;
&length);
if (retval)
return retval;
}
asn1_makeseq();
asn1_cleanup();
}
asn1_error_code asn1_encode_sequence_of_algorithm_identifier(asn1buf *buf, const krb5_algorithm_identifier **val, unsigned int *retlen)
{
asn1_setup();
int i;
for (i--; i>=0; i--) {
unsigned int length;
}
asn1_makeseq();
asn1_cleanup();
}
asn1_error_code asn1_encode_auth_pack(asn1buf *buf, const krb5_auth_pack *val, unsigned int *retlen)
{
asn1_setup();
asn1_addfield((const krb5_algorithm_identifier **)val->supportedCMSTypes,2,asn1_encode_sequence_of_algorithm_identifier);
asn1_makeseq();
asn1_cleanup();
}
asn1_error_code asn1_encode_auth_pack_draft9(asn1buf *buf, const krb5_auth_pack_draft9 *val, unsigned int *retlen)
{
asn1_setup();
asn1_makeseq();
asn1_cleanup();
}
asn1_error_code asn1_encode_external_principal_identifier(asn1buf *buf, const krb5_external_principal_identifier *val, unsigned int *retlen)
{
asn1_setup();
/* Verify there is something to encode */
if (val->subjectKeyIdentifier.length == 0 && val->issuerAndSerialNumber.length == 0 && val->subjectName.length == 0)
return ASN1_MISSING_FIELD;
asn1_insert_implicit_octetstring(val->subjectKeyIdentifier.length,val->subjectKeyIdentifier.data,2);
asn1_insert_implicit_octetstring(val->issuerAndSerialNumber.length,val->issuerAndSerialNumber.data,1);
asn1_makeseq();
asn1_cleanup();
}
asn1_error_code asn1_encode_sequence_of_external_principal_identifier(asn1buf *buf, const krb5_external_principal_identifier **val, unsigned int *retlen)
{
asn1_setup();
int i;
for (i--; i>=0; i--) {
unsigned int length;
}
asn1_makeseq();
asn1_cleanup();
}
asn1_error_code asn1_encode_pa_pk_as_req(asn1buf *buf, const krb5_pa_pk_as_req *val, unsigned int *retlen)
{
asn1_setup();
asn1_addfield((const krb5_external_principal_identifier **)val->trustedCertifiers,1,asn1_encode_sequence_of_external_principal_identifier);
asn1_makeseq();
asn1_cleanup();
}
asn1_error_code asn1_encode_trusted_ca(asn1buf *buf, const krb5_trusted_ca *val, unsigned int *retlen)
{
asn1_setup();
break;
break;
break;
default:
return ASN1_MISSING_FIELD;
}
asn1_cleanup();
}
asn1_error_code asn1_encode_sequence_of_trusted_ca(asn1buf *buf, const krb5_trusted_ca **val, unsigned int *retlen)
{
asn1_setup();
int i;
for (i--; i>=0; i--) {
unsigned int length;
}
asn1_makeseq();
asn1_cleanup();
}
asn1_error_code asn1_encode_pa_pk_as_req_draft9(asn1buf *buf, const krb5_pa_pk_as_req_draft9 *val, unsigned int *retlen)
{
asn1_setup();
asn1_addfield((const krb5_trusted_ca **)val->trustedCertifiers,1,asn1_encode_sequence_of_trusted_ca);
asn1_makeseq();
asn1_cleanup();
}
asn1_error_code asn1_encode_dh_rep_info(asn1buf *buf, const krb5_dh_rep_info *val, unsigned int *retlen)
{
asn1_setup();
asn1_makeseq();
asn1_cleanup();
}
asn1_error_code asn1_encode_kdc_dh_key_info(asn1buf *buf, const krb5_kdc_dh_key_info *val, unsigned int *retlen)
{
asn1_setup();
if (val->dhKeyExpiration != 0)
{
unsigned int length;
&length);
if (retval)
return retval;
}
asn1_makeseq();
asn1_cleanup();
}
asn1_error_code asn1_encode_reply_key_pack(asn1buf *buf, const krb5_reply_key_pack *val, unsigned int *retlen)
{
asn1_setup();
asn1_makeseq();
asn1_cleanup();
}
asn1_error_code asn1_encode_reply_key_pack_draft9(asn1buf *buf, const krb5_reply_key_pack_draft9 *val, unsigned int *retlen)
{
asn1_setup();
asn1_makeseq();
asn1_cleanup();
}
asn1_error_code asn1_encode_pa_pk_as_rep(asn1buf *buf, const krb5_pa_pk_as_rep *val, unsigned int *retlen)
{
asn1_setup();
{
break;
break;
default:
return ASN1_MISSING_FIELD;
}
asn1_cleanup();
}
asn1_error_code asn1_encode_pa_pk_as_rep_draft9(asn1buf *buf, const krb5_pa_pk_as_rep_draft9 *val, unsigned int *retlen)
{
asn1_setup();
{
break;
break;
default:
return ASN1_MISSING_FIELD;
}
asn1_cleanup();
}
asn1_error_code asn1_encode_td_trusted_certifiers(asn1buf *buf, const krb5_external_principal_identifier **val, unsigned int *retlen)
{
asn1_setup();
{
unsigned int length;
if (retval)
return retval;
/* length set but ignored? sum not updated? */
}
asn1_cleanup();
}
#endif /* DISABLE_PKINIT */
asn1_error_code asn1_encode_sequence_of_typed_data(asn1buf *buf, const krb5_typed_data **val, unsigned int *retlen)
{
asn1_setup();
int i;
for (i--; i>=0; i--) {
unsigned int length;
}
asn1_makeseq();
asn1_cleanup();
}
asn1_error_code asn1_encode_typed_data(asn1buf *buf, const krb5_typed_data *val, unsigned int *retlen)
{
asn1_setup();
asn1_makeseq();
asn1_cleanup();
}