/* ***************************************************************** *
 * Copyright 1998 International Business Machines Corporation. All   *
 * Rights Reserved.                                                  *
 *                                                                   *
 * Please read this carefully.  Your use of this reference           *
 * implementation of certain of the IETF public-key infrastructure   *
 * specifications ("Software") indicates your acceptance of the      *
 * following.  If you do not agree to the following, do not install  *
 * or use any of the Software.                                       *
 *                                                                   *
 * Permission to use, reproduce, distribute and create derivative    *
 * works from the Software ("Software Derivative Works"), and to     *
 * distribute such Software Derivative Works is hereby granted to    *
 * you by International Business Machines Corporation ("IBM").  This *
 * permission includes a license under the patents of IBM that are   *
 * necessarily infringed by your use of the Software as provided by  *
 * IBM.                                                              *
 *                                                                   *
 * IBM licenses the Software to you on an "AS IS" basis, without     *
 * warranty of any kind.  IBM HEREBY EXPRESSLY DISCLAIMS ALL         *
 * WARRANTIES OR CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING,   *
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OR CONDITIONS OF       *
 * MERCHANTABILITY, NON INFRINGEMENT AND FITNESS FOR A PARTICULAR    *
 * PURPOSE.  You are solely responsible for determining the          *
 * appropriateness of using this Software and assume all risks       *
 * associated with the use of this Software, including but not       *
 * limited to the risks of program errors, damage to or loss of      *
 * data, programs or equipment, and unavailability or interruption   *
 * of operations.                                                    *
 *                                                                   *
 * IBM WILL NOT BE LIABLE FOR ANY DIRECT DAMAGES OR FOR ANY SPECIAL, *
 * INCIDENTAL, OR  INDIRECT DAMAGES OR FOR ANY ECONOMIC              *
 * CONSEQUENTIAL DAMAGES (INCLUDING LOST PROFITS OR SAVINGS), EVEN   *
 * IF IBM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.  IBM  *
 * will not be liable for the loss of, or damage to, your records or *
 * data, or any damages claimed by you based on a third party claim. *
 *                                                                   *
 * IBM wishes to obtain your feedback to assist in improving the     *
 * Software.  You grant IBM a world-wide, royalty-free right to use, *
 * copy, distribute, sublicense and prepare derivative works based   *
 * upon any feedback, including materials, error corrections,        *
 * Software Derivatives, enhancements, suggestions and the like that *
 * you provide to IBM relating to the Software (this does not        *
 * include products for which you charge a royalty and distribute to *
 * IBM under other terms and conditions).                            *
 *                                                                   *
 * You agree to distribute the Software and any Software Derivatives *
 * under a license agreement that: 1) is sufficient to notify all    *
 * licensees of the Software and Software Derivatives that IBM       *
 * assumes no liability for any claim that may arise regarding the   *
 * Software or Software Derivatives, and 2) that disclaims all       *
 * warranties, both express and implied, from IBM regarding the      *
 * Software and Software Derivatives.  (If you include this          *
 * Agreement with any distribution of the Software or Software       *
 * Derivatives you will have met this requirement.)  You agree that  *
 * you will not delete any copyright notices in the Software.        *
 *                                                                   *
 * This Agreement is the exclusive statement of your rights in the   *
 * Software as provided by IBM.   Except for the rights granted to   *
 * you in the second paragraph above, You are not granted any other  *
 * patent rights, including but not limited to the right to make     *
 * combinations of the Software with products that infringe IBM      *
 * patents. You agree to comply with all applicable laws and         *
 * regulations, including all export and import laws and regulation. *
 * This Agreement is governed by the laws of the State of New York.  *
 * This Agreement supersedes all other communications,               *
 * understandings or agreements we may have had prior to this        *
 * Agreement.                                                        *
 * ***************************************************************** */

#ifndef X509_H_
#define X509_H_

#include <asnbase.h>
#include <asnstrng.h>
#include <asnnames.h>

typedef enum {X509_V1, X509_V2, X509_V3} x509_version_t;



template class EXPORTCLASS asn_explicit<asn_integer, CLASS_CONTEXT_SPECIFIC, 0>;

class EXPORTCLASS Version : public asn_explicit<asn_integer, CLASS_CONTEXT_SPECIFIC, 0> {
public:
  Version(security_t s = ASN_PUBLIC) 
  : asn_explicit<asn_integer, CLASS_CONTEXT_SPECIFIC, 0>(s) {
    strcpy(objType, "Version");
    value.set_default_value(0); // Default version is V1(0)
  };

  virtual int set_value(x509_version_t v) {
    switch (v) {
      case X509_V1 : return value.set_value(0l);
      case X509_V2 : return value.set_value(1l);
      case X509_V3 : return value.set_value(2l);
    };
    return ASN_INVALID_VALUE;
  };

  virtual int get_value(x509_version_t &v) const {
    long vi; int res;
    res = value.get_value(vi);
    if (res != 0) return res;
    switch(vi) {
      case 0 : v = X509_V1; return 0;
      case 1 : v = X509_V2; return 0;
      case 2 : v = X509_V3; return 0;
    };
    return ASN_INVALID_VALUE;
  };
};

class EXPORTCLASS AlgorithmIdentifier : public asn_sequence {
public:
  asn_oid algorithm;
  asn_any parameters;
  
  AlgorithmIdentifier(security_t s = ASN_PUBLIC) : asn_sequence(s) {
    strcpy(objType, "AlgIdent");
    parameters.set_optional();
    register_child(&algorithm);
    register_child(&parameters);
  };
};

class EXPORTCLASS Time : public asn_choice {
public:
  asn_UTCtime utcTime;
  asn_generalizedtime generalizedTime;
  Time(security_t s = ASN_PUBLIC) : asn_choice(s) {
    strcpy(objType, "Time");
    register_child(&utcTime);
    register_child(&generalizedTime);
  }
};


class EXPORTCLASS Validity : public asn_sequence {
public:
  Time notBefore;
  Time notAfter;

  Validity(security_t s = ASN_PUBLIC) : asn_sequence(s) {
    strcpy(objType, "Validity");
    register_child(&notBefore);
    register_child(&notAfter);
  }
};

class EXPORTCLASS SubjectPublicKeyInfo : public asn_sequence {
public:
  AlgorithmIdentifier algorithm;
  asn_bitstring subjectPublicKey;

  SubjectPublicKeyInfo(security_t s = ASN_PUBLIC) : asn_sequence(s) {
    strcpy(objType, "SubPubKeyInfo");
    register_child(&algorithm);
    register_child(&subjectPublicKey);
  };
};


class EXPORTCLASS x509_Extension : public asn_sequence {
public:
  asn_oid extnID;
  asn_boolean critical;
  asn_octetstring extnValue;

  x509_Extension(security_t s = ASN_PUBLIC) : asn_sequence(s) {
    strcpy(objType, "X509Extension");
    critical.set_default_value(false);
    register_child(&extnID);
    register_child(&critical);
    register_child(&extnValue);
  };
};


template class EXPORTCLASS asn_sequenceof<x509_Extension>;

class EXPORTCLASS x509_Extensions : public asn_sequenceof<x509_Extension> {
public:
  x509_Extensions(security_t s = ASN_PUBLIC) : asn_sequenceof<x509_Extension> (s) {
    strcpy(objType, "X509Extensions");
  };
};



template class EXPORTCLASS asn_implicit<asn_bitstring, CLASS_CONTEXT_SPECIFIC, 1>;
template class EXPORTCLASS asn_implicit<asn_bitstring, CLASS_CONTEXT_SPECIFIC, 2>;
template class EXPORTCLASS asn_explicit<x509_Extensions, CLASS_CONTEXT_SPECIFIC, 3>;

class EXPORTCLASS TBSCertificate : public asn_sequence {
public:
  Version version;
  asn_integer serialNumber;
  AlgorithmIdentifier signature;
  asn_x500name issuer;
  Validity validity;
  asn_x500name subject;
  SubjectPublicKeyInfo subjectPublicKeyInfo;
  asn_implicit<asn_bitstring, CLASS_CONTEXT_SPECIFIC, 1> issuerUniqueID;
  asn_implicit<asn_bitstring, CLASS_CONTEXT_SPECIFIC, 2> subjectUniqueID;
  asn_explicit<x509_Extensions, CLASS_CONTEXT_SPECIFIC, 3> extensions;

  TBSCertificate(security_t s = ASN_PUBLIC) : asn_sequence(s) {
    strcpy(objType, "TBSCert");
    issuerUniqueID.set_optional();
    subjectUniqueID.set_optional();
    extensions.set_optional();

    register_child(&version);
    register_child(&serialNumber);
    register_child(&signature);
    register_child(&issuer);
    register_child(&validity);
    register_child(&subject);
    register_child(&subjectPublicKeyInfo);
    register_child(&issuerUniqueID);
    register_child(&subjectUniqueID);
    register_child(&extensions);
  }
};


// The basic certificate...

class EXPORTCLASS x509_certificate : public asn_sequence {
public:
  TBSCertificate tbsCertificate ;
  AlgorithmIdentifier signatureAlgorithm;
  asn_bitstring signature;
  x509_certificate(security_t s = ASN_PUBLIC) : asn_sequence(s) {
    strcpy(objType, "X509Cert");
    register_child(&tbsCertificate);
    register_child(&signatureAlgorithm);
    register_child(&signature);
  };
};



// Standard extensions...

/* 
 * NB: The definition of GeneralName below is rather more constrained than
 *     that given in the PKIX-1 spec.  In particular, the INSTANCE OF OTHER-NAME
 *     form isn't supported, nor is the X.400 name-type.
 */

template class EXPORTCLASS asn_implicit<asn_directoryString, CLASS_CONTEXT_SPECIFIC, 0>;
template class EXPORTCLASS asn_implicit<asn_directoryString, CLASS_CONTEXT_SPECIFIC, 1>;

class EXPORTCLASS EDIPartyName : public asn_sequence {
public:
  asn_implicit<asn_directoryString, CLASS_CONTEXT_SPECIFIC, 0> nameAssigner;
  asn_implicit<asn_directoryString, CLASS_CONTEXT_SPECIFIC, 1> partyName;
  EDIPartyName(security_t s = ASN_PUBLIC) : asn_sequence(s) {
    strcpy(objType, "EDIPartyName");
    nameAssigner.set_optional();
    register_child(&nameAssigner);
    register_child(&partyName);
  };
};

template class EXPORTCLASS asn_implicit<asn_ia5String, CLASS_CONTEXT_SPECIFIC, 1>;
template class EXPORTCLASS asn_implicit<asn_ia5String, CLASS_CONTEXT_SPECIFIC, 2>;
// template class EXPORTCLASS asn_implicit<ORAddress, CLASS_CONTEXT_SPECIFIC, 3>;
template class EXPORTCLASS asn_implicit<asn_x500name, CLASS_CONTEXT_SPECIFIC, 4>;
template class EXPORTCLASS asn_implicit<EDIPartyName, CLASS_CONTEXT_SPECIFIC, 5>;
template class EXPORTCLASS asn_implicit<asn_ia5String, CLASS_CONTEXT_SPECIFIC, 6>;
template class EXPORTCLASS asn_implicit<asn_octetstring, CLASS_CONTEXT_SPECIFIC, 7>;
template class EXPORTCLASS asn_implicit<asn_oid, CLASS_CONTEXT_SPECIFIC, 8>;

class EXPORTCLASS GeneralName : public asn_choice {
private:
	unsigned char toupper_IA5(unsigned char c) const ; 
	bool nocaseIa5Equal(const asn_ia5String &name1, const asn_ia5String &name2) const ;
public:
  asn_implicit<asn_ia5String, CLASS_CONTEXT_SPECIFIC, 1> rfc822Name;
  asn_implicit<asn_ia5String, CLASS_CONTEXT_SPECIFIC, 2> dNSName;
//  asn_implicit<ORAddress, CLASS_CONTEXT_SPECIFIC, 3> x400Address;
  asn_implicit<asn_x500name, CLASS_CONTEXT_SPECIFIC, 4> directoryname;
  asn_implicit<EDIPartyName, CLASS_CONTEXT_SPECIFIC, 5> ediPartyName;
  asn_implicit<asn_ia5String, CLASS_CONTEXT_SPECIFIC, 6> uniformResourceIdentifier;
  asn_implicit<asn_octetstring, CLASS_CONTEXT_SPECIFIC, 7> iPAddress;
  asn_implicit<asn_oid, CLASS_CONTEXT_SPECIFIC, 8> registeredID;
  GeneralName(security_t s = ASN_PUBLIC) : asn_choice(s) {
    strcpy(objType, "GeneralName");
    register_child(&rfc822Name);
    register_child(&dNSName);
//    register_child(&x400Address);
    register_child(&directoryname);
    register_child(&ediPartyName);
    register_child(&uniformResourceIdentifier);
    register_child(&iPAddress);
    register_child(&registeredID);
  };  
  bool rfc822Equal(const asn_ia5String &name1, const asn_ia5String &name2) const ;
  bool dNSNameEqual(const asn_ia5String &name1, const asn_ia5String &name2) const ;
  bool uRIEqual(const asn_ia5String &name1, const asn_ia5String &name2) const ;
  operator==(const GeneralName &gname) const; 
  operator==(const asn_x500name &dirname) const;
};

template class EXPORTCLASS asn_sequenceof<GeneralName>;
typedef asn_sequenceof<GeneralName> GeneralNames;

template class EXPORTCLASS asn_implicit<asn_octetstring, CLASS_CONTEXT_SPECIFIC, 0>;
template class EXPORTCLASS asn_implicit<GeneralNames, CLASS_CONTEXT_SPECIFIC, 1>;
template class EXPORTCLASS asn_implicit<asn_integer, CLASS_CONTEXT_SPECIFIC, 2>;

class EXPORTCLASS XAuthorityKeyIdentifier : public asn_sequence {
public:
  asn_implicit<asn_octetstring, CLASS_CONTEXT_SPECIFIC, 0> keyIdentifier;
  asn_implicit<GeneralNames, CLASS_CONTEXT_SPECIFIC, 1> authorityIdentifier;
  asn_implicit<asn_integer, CLASS_CONTEXT_SPECIFIC, 2> authorityCertSerialNumber;

  XAuthorityKeyIdentifier(security_t s = ASN_PUBLIC) {
    strcpy(objType, "XAuthKeyIdent");
    keyIdentifier.set_optional();
    authorityIdentifier.set_optional();
    authorityCertSerialNumber.set_optional();

    register_child(&keyIdentifier);
    register_child(&authorityIdentifier);
    register_child(&authorityCertSerialNumber);
  };
};


typedef asn_octetstring XSubjectKeyIdentifier;

#define USAGE_none 0
#define USAGE_digitalSignature 1
#define USAGE_nonRepudiation 2
#define USAGE_keyEncipherment 4
#define USAGE_dataEncipherment 8
#define USAGE_keyAgreement 16
#define USAGE_keyCertSign 32
#define USAGE_cRLSign 64
#define USAGE_encipherOnly 128
#define USAGE_decipherOnly 256

class EXPORTCLASS XKeyUsage : public asn_bitstring {
public:
  XKeyUsage(security_t s = ASN_PUBLIC) : asn_bitstring(s) {
    strcpy(objType, "XKeyUsage");
  };

  virtual int set_value(long u) {
    unsigned char v[2];
    v[0] = 0; v[1] = 0;
    if (u & USAGE_digitalSignature) v[0] |= 0x80;
    if (u & USAGE_nonRepudiation) v[0] |= 0x40;
    if (u & USAGE_keyEncipherment) v[0] |= 0x20;
    if (u & USAGE_dataEncipherment) v[0] |= 0x10;
    if (u & USAGE_keyAgreement) v[0] |= 0x08;
    if (u & USAGE_keyCertSign) v[0] |= 0x04;
    if (u & USAGE_cRLSign) v[0] |= 0x02;
    if (u & USAGE_encipherOnly) v[0] |= 0x01;
    if (u & USAGE_decipherOnly) v[1] |= 0x80;
    return asn_bitstring::set_value(v, 9);
  }

  virtual int get_value(long &u) const {
    unsigned char * v;
    uint32 vc;
    int res;

    res = asn_bitstring::get_value(v, vc);
    if (res != 0) return res;

    u = 0;
    if ((vc > 0) && (v[0] & 0x80)) u |= USAGE_digitalSignature;
    if ((vc > 1) && (v[0] & 0x40)) u |= USAGE_nonRepudiation;
    if ((vc > 2) && (v[0] & 0x20)) u |= USAGE_keyEncipherment;
    if ((vc > 3) && (v[0] & 0x10)) u |= USAGE_dataEncipherment;
    if ((vc > 4) && (v[0] & 0x08)) u |= USAGE_keyAgreement;
    if ((vc > 5) && (v[0] & 0x04)) u |= USAGE_keyCertSign;
    if ((vc > 6) && (v[0] & 0x02)) u |= USAGE_cRLSign;
    if ((vc > 7) && (v[0] & 0x01)) u |= USAGE_encipherOnly;
    if ((vc > 8) && (v[1] & 0x80)) u |= USAGE_decipherOnly;

    return 0;
  }
};

template class EXPORTCLASS asn_implicit<asn_generalizedtime, CLASS_CONTEXT_SPECIFIC, 0>;
template class EXPORTCLASS asn_implicit<asn_generalizedtime, CLASS_CONTEXT_SPECIFIC, 1>;

class EXPORTCLASS XPrivateKeyUsagePeriod : public asn_sequence {
public:
  asn_implicit<asn_generalizedtime, CLASS_CONTEXT_SPECIFIC, 0> notBefore;
  asn_implicit<asn_generalizedtime, CLASS_CONTEXT_SPECIFIC, 1> notAfter;

  XPrivateKeyUsagePeriod(security_t s = ASN_PUBLIC) : asn_sequence(s) {
    strcpy(objType, "XPrvKeyUsPer");
    notBefore.set_optional();
    notAfter.set_optional();
    register_child(&notBefore);
    register_child(&notAfter);
  };
};

/*
 * NB: The definition below, specifying the policy qualifier as an ANY object, is
 *     not used.  Instead, the qualifier is constrained to be either a URI or an
 *     explicit user notice, as per the PKIX-1 spec.

class PolicyQualifierInfo : public asn_sequence {
public:
  asn_oid policyQualifierId;
  asn_any qualifier;
  PolicyQualifierInfo(security_t s = ASN_PUBLIC) : asn_sequence(s) {
    register_child(&policyQualifierId);
    register_child(&qualifier);
  };
};
*/


class EXPORTCLASS DisplayText : public asn_charstring {
protected:
  virtual bool check_type(uint32 tagRead, int classRead) const;
  virtual bool check_codeset(uint32 codeset) const;
public:
  DisplayText(security_t s = ASN_PUBLIC) : asn_charstring(s) {
    strcpy(objType, "DisplayText");
  };
};


template class EXPORTCLASS asn_sequenceof<asn_integer>;

class EXPORTCLASS NoticeReference : public asn_sequence {
public:
  asn_ia5String organization;
  asn_sequenceof<asn_integer> noticeNumbers;
  NoticeReference(security_t s = ASN_PUBLIC) : asn_sequence(s) {
    strcpy(objType, "NoticeRef");
    register_child(&organization);
    register_child(&noticeNumbers);
  };
};

class EXPORTCLASS UserNotice : public asn_sequence {
public:
  NoticeReference noticeRef;
  DisplayText explicitText;
  UserNotice(security_t s = ASN_PUBLIC) : asn_sequence(s) {
    strcpy(objType, "UserNotice");
    noticeRef.set_optional();
    explicitText.set_optional();

    register_child(&noticeRef);
    register_child(&explicitText);
  };
};

class EXPORTCLASS PolicyQualifier : public asn_choice {
public:
  asn_ia5String cPSuri;
  UserNotice userNotice;
  PolicyQualifier(security_t s = ASN_PUBLIC) : asn_choice(s) {
    strcpy(objType, "PolicyQual");
    register_child(&cPSuri);
    register_child(&userNotice);
  };
};

class EXPORTCLASS PolicyQualifierInfo : public asn_sequence {
public:
  asn_oid policyQualifierId;
  PolicyQualifier qualifier;
  PolicyQualifierInfo(security_t s = ASN_PUBLIC) : asn_sequence(s) {
    strcpy(objType, "PolicyQualInfo");
    register_child(&policyQualifierId);
    register_child(&qualifier);
  };
};


template class EXPORTCLASS asn_sequenceof<PolicyQualifierInfo>;

class EXPORTCLASS PolicyInformation : public asn_sequence {
public:
  asn_oid policyIdentifier;
  asn_sequenceof<PolicyQualifierInfo> policyQualifiers;
  PolicyInformation(security_t s = ASN_PUBLIC) : asn_sequence(s) {
    strcpy(objType, "PolicyInfo");
    policyQualifiers.set_optional();
    register_child(&policyIdentifier);
    register_child(&policyQualifiers);
  };
};

template class EXPORTCLASS asn_sequenceof<PolicyInformation>;
typedef asn_sequenceof<PolicyInformation> XCertificatePolicies;

class EXPORTCLASS PolicyMapping : public asn_sequence {
public:
  asn_oid issuerDomainPolicy;
  asn_oid subjectDomainPolicy;
  PolicyMapping(security_t s = ASN_PUBLIC) : asn_sequence(s) {
    strcpy(objType, "PolicyMapping");
    register_child(&issuerDomainPolicy);
    register_child(&subjectDomainPolicy);
  };
};

template class EXPORTCLASS asn_sequenceof<PolicyMapping>;
typedef asn_sequenceof<PolicyMapping> XPolicyMappings;

typedef GeneralNames XsubjectAltName;

typedef GeneralNames XIssuerAltName;

class EXPORTCLASS XBasicConstraints : public asn_sequence {
public:
  asn_boolean cA;
  asn_integer pathLenConstraints;
  XBasicConstraints(security_t s = ASN_PUBLIC) : asn_sequence(s) {
    strcpy(objType, "BasCnstrnts");
    pathLenConstraints.set_optional();
    register_child(&cA);
    register_child(&pathLenConstraints);
  };
};

template class EXPORTCLASS asn_implicit<asn_integer, CLASS_CONTEXT_SPECIFIC, 0>;
template class EXPORTCLASS asn_implicit<asn_integer, CLASS_CONTEXT_SPECIFIC, 1>;
class EXPORTCLASS GeneralSubtree : public asn_sequence {
public:
  GeneralName base;
  asn_implicit<asn_integer, CLASS_CONTEXT_SPECIFIC, 0> minimum;
  asn_implicit<asn_integer, CLASS_CONTEXT_SPECIFIC, 1> maximum;
  GeneralSubtree(security_t s = ASN_PUBLIC) : asn_sequence(s) {
    strcpy(objType, "GenSubtree");
    minimum.set_default_value(0);
    maximum.set_optional();
    register_child(&base);
    register_child(&minimum);
    register_child(&maximum);
  };
};

template class EXPORTCLASS asn_sequenceof<GeneralSubtree>;
typedef asn_sequenceof<GeneralSubtree> GeneralSubtrees;

template class EXPORTCLASS asn_implicit<GeneralSubtrees, CLASS_CONTEXT_SPECIFIC, 0>;
template class EXPORTCLASS asn_implicit<GeneralSubtrees, CLASS_CONTEXT_SPECIFIC, 1>;

class EXPORTCLASS XNameConstraints : public asn_sequence {
public:
  asn_implicit<GeneralSubtrees, CLASS_CONTEXT_SPECIFIC, 0> permittedSubtrees;
  asn_implicit<GeneralSubtrees, CLASS_CONTEXT_SPECIFIC, 1> excludedSubtrees;
  XNameConstraints(security_t s = ASN_PUBLIC) : asn_sequence(s) {
    strcpy(objType, "NameCnstrnts");
    permittedSubtrees.set_optional();
    excludedSubtrees.set_optional();
    register_child(&permittedSubtrees);
    register_child(&excludedSubtrees);
  };
};


class EXPORTCLASS PolicyConstraint : public asn_sequence {
public:
  asn_integer requireExplicitPolicy;
  asn_integer inhibitPolicyMapping;
  PolicyConstraint(security_t s = ASN_PUBLIC) : asn_sequence(s) {
    strcpy(objType, "PolCnstrnts");
    requireExplicitPolicy.set_optional();
    inhibitPolicyMapping.set_optional();
    register_child(&requireExplicitPolicy);
    register_child(&inhibitPolicyMapping);
  };
};

template class EXPORTCLASS asn_sequenceof<PolicyConstraint> ;
typedef asn_sequenceof<PolicyConstraint> XPolicyConstraints;

#define REASON_none 0
#define REASON_unused 1
#define REASON_keyCompromise 2
#define REASON_cACompromise 4
#define REASON_affiliationChanged 8
#define REASON_superseded 16
#define REASON_cessationOfOperation 32
#define REASON_certificateHold 64



class EXPORTCLASS ReasonFlags : public asn_bitstring {
public:
  ReasonFlags(security_t s = ASN_PUBLIC) : asn_bitstring(s) {
    strcpy(objType, "ReasonFlags");
  };

  virtual int set_value(long u) {
    unsigned char v[1];
    v[0] = 0;
    if (u & REASON_unused) v[0] |= 0x80;
    if (u & REASON_keyCompromise) v[0] |= 0x40;
    if (u & REASON_cACompromise) v[0] |= 0x20;
    if (u & REASON_affiliationChanged) v[0] |= 0x10;
    if (u & REASON_superseded) v[0] |= 0x08;
    if (u & REASON_cessationOfOperation) v[0] |= 0x04;
    if (u & REASON_certificateHold) v[0] |= 0x02;
    return asn_bitstring::set_value(v, 7);
  };

  virtual int get_value(long &u) const {
    unsigned char * v;
    uint32 vc;
    int res;
    res = asn_bitstring::get_value(v, vc);
    if (res != 0) return res;
    u = 0;
    if ((vc > 0) && (v[0] & 0x80)) u |= REASON_unused;
    if ((vc > 1) && (v[0] & 0x40)) u |= REASON_keyCompromise;
    if ((vc > 2) && (v[0] & 0x20)) u |= REASON_cACompromise;
    if ((vc > 3) && (v[0] & 0x10)) u |= REASON_affiliationChanged;
    if ((vc > 4) && (v[0] & 0x08)) u |= REASON_superseded;
    if ((vc > 5) && (v[0] & 0x04)) u |= REASON_cessationOfOperation;
    if ((vc > 6) && (v[0] & 0x02)) u |= REASON_certificateHold;
  
    return 0;
  };
};


template class EXPORTCLASS asn_implicit<GeneralNames, CLASS_CONTEXT_SPECIFIC, 0> ;    
template class EXPORTCLASS asn_implicit<asn_RDN, CLASS_CONTEXT_SPECIFIC, 1> ;   
class EXPORTCLASS DistributionPointName : public asn_choice {
public:
  asn_implicit<GeneralNames, CLASS_CONTEXT_SPECIFIC, 0> fullName;   
  asn_implicit<asn_RDN, CLASS_CONTEXT_SPECIFIC, 1> nameRelativeToCRLIssuer;   
  DistributionPointName(security_t s = ASN_PUBLIC) : asn_choice(s) {
    strcpy(objType, "DistPtName");
    register_child(&fullName);
    register_child(&nameRelativeToCRLIssuer);
  };
};

template class EXPORTCLASS asn_implicit<DistributionPointName, CLASS_CONTEXT_SPECIFIC, 0> ;
template class EXPORTCLASS asn_implicit<ReasonFlags, CLASS_CONTEXT_SPECIFIC, 1> ;
template class EXPORTCLASS asn_implicit<GeneralNames, CLASS_CONTEXT_SPECIFIC, 2> ;
class EXPORTCLASS DistributionPoint : public asn_sequence {
public:
  asn_implicit<DistributionPointName, CLASS_CONTEXT_SPECIFIC, 0> distributionPoint;
  asn_implicit<ReasonFlags, CLASS_CONTEXT_SPECIFIC, 1> reasons;
  asn_implicit<GeneralNames, CLASS_CONTEXT_SPECIFIC, 2> cRLIssuer;
  DistributionPoint(security_t s = ASN_PUBLIC) : asn_sequence(s) {
    strcpy(objType, "DistPt");
    distributionPoint.set_optional();
    reasons.set_optional();
    cRLIssuer.set_optional();
    register_child(&distributionPoint);
    register_child(&reasons);
    register_child(&cRLIssuer);
  };
};

typedef asn_sequenceof<DistributionPoint> CRLDistributionPoints;

typedef asn_sequenceof<asn_oid> XExtKeyUsage; 

class EXPORTCLASS AccessDescription : public asn_sequence {
public:
  asn_oid accessMethod;
  GeneralName accessLocation;
  AccessDescription(security_t s = ASN_PUBLIC) : asn_sequence(s) {
    strcpy(objType, "AccessDesc");
    register_child(&accessMethod);
    register_child(&accessLocation);
  };
};

typedef asn_sequenceof<AccessDescription> XAuthorityInfoAccess;

class EXPORTCLASS RevokedCertificate : public asn_sequence {
public:
  asn_integer		userCertificate;
  Time				revocationDate;
  x509_Extensions	crlEntryExtensions;
  RevokedCertificate(security_t s = ASN_PUBLIC) : asn_sequence() {
    strcpy(objType, "RevokedCert");
    crlEntryExtensions.set_optional();
    register_child(&userCertificate);
    register_child(&revocationDate);
    register_child(&crlEntryExtensions);
  };
};

template class EXPORTCLASS asn_sequenceof<RevokedCertificate>;
class EXPORTCLASS RevokedCertificates : public asn_sequenceof<RevokedCertificate> {
public:
  RevokedCertificates(security_t s = ASN_PUBLIC) : asn_sequenceof<RevokedCertificate> (s) {
    strcpy(objType, "RevokedCerts");
  };
};

//
// CRL Extensions
//

// CRL Number
typedef asn_integer 	XCRLNumber;

// Delta CRL
typedef XCRLNumber  		BaseCRLNumber;
typedef BaseCRLNumber	XDeltaCRLIndicator;

//
// CRL Entry Extensions
//

// Certificate Issuer
typedef GeneralNames	XCertificateIssuer;

// Reason Code
typedef ReasonFlags	XCRLReason;

// Hold Instruction
typedef asn_oid		XHoldInstructionCode;

// Invalidity Date
typedef	Time		XInvalidityDate;


template class EXPORTCLASS asn_explicit<x509_Extensions, CLASS_CONTEXT_SPECIFIC, 0>;

class EXPORTCLASS TBSCertList : public asn_sequence {
public:
  asn_integer		version;
  AlgorithmIdentifier	signature;
  asn_x500name		issuer;
  Time			thisUpdate;
  Time			nextUpdate;
  RevokedCertificates	revokedCertificates;
  asn_explicit<x509_Extensions, CLASS_CONTEXT_SPECIFIC, 0> crlExtensions;
  TBSCertList(security_t s = ASN_PUBLIC) : asn_sequence() {
    strcpy(objType, "TBSCertList");
    version.set_optional();
    nextUpdate.set_optional();
    revokedCertificates.set_optional();
    crlExtensions.set_optional();
    register_child(&version);
    register_child(&signature);
    register_child(&issuer);
    register_child(&thisUpdate);
    register_child(&nextUpdate);
    register_child(&revokedCertificates);
    register_child(&crlExtensions);
  };
};

class EXPORTCLASS CertificateList : public asn_sequence {
public:
  TBSCertList		tbsCertList;
  AlgorithmIdentifier	signatureAlgorithm;
  asn_bitstring		signature;
  CertificateList(security_t s = ASN_PUBLIC) : asn_sequence() {
    strcpy(objType, "CertList");
    register_child(&tbsCertList);
    register_child(&signatureAlgorithm);
    register_child(&signature);
  };
};

#endif
