/* * Copyright (c) 2000-2009,2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ * * CertExtensions.h -- X.509 Cert Extensions as C structs */ #ifndef _CERT_EXTENSIONS_H_ #define _CERT_EXTENSIONS_H_ #include <stdbool.h> #include <libDER/libDER.h> //#include <Security/x509defs.h> /*** *** Structs for declaring extension-specific data. ***/ /* * GeneralName, used in AuthorityKeyID, SubjectAltName, and * IssuerAltName. * * For now, we just provide explicit support for the types which are * represented as IA5Strings, OIDs, and octet strings. Constructed types * such as EDIPartyName and x400Address are not explicitly handled * right now and must be encoded and decoded by the caller. (See exception * for Name and OtherName, below). In those cases the SecCEGeneralName.name.Data field * represents the BER contents octets; SecCEGeneralName.name.Length is the * length of the contents; the tag of the field is not needed - the BER * encoding uses context-specific implicit tagging. The berEncoded field * is set to true in these case. Simple types have berEncoded = false. * * In the case of a GeneralName in the form of a Name, we parse the Name * into a CSSM_X509_NAME and place a pointer to the CSSM_X509_NAME in the * SecCEGeneralName.name.Data field. SecCEGeneralName.name.Length is set to * sizeof(CSSM_X509_NAME). In this case berEncoded is false. * * In the case of a GeneralName in the form of a OtherName, we parse the fields * into a SecCEOtherName and place a pointer to the SecCEOtherName in the * SecCEGeneralName.name.Data field. SecCEGeneralName.name.Length is set to * sizeof(SecCEOtherName). In this case berEncoded is false. * * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName * * GeneralName ::= CHOICE { * otherName [0] OtherName * rfc822Name [1] IA5String, * dNSName [2] IA5String, * x400Address [3] ORAddress, * directoryName [4] Name, * ediPartyName [5] EDIPartyName, * uniformResourceIdentifier [6] IA5String, * iPAddress [7] OCTET STRING, * registeredID [8] OBJECT IDENTIFIER} * * OtherName ::= SEQUENCE { * type-id OBJECT IDENTIFIER, * value [0] EXPLICIT ANY DEFINED BY type-id } * * EDIPartyName ::= SEQUENCE { * nameAssigner [0] DirectoryString OPTIONAL, * partyName [1] DirectoryString } */ typedef enum { GNT_OtherName = 0, GNT_RFC822Name, GNT_DNSName, GNT_X400Address, GNT_DirectoryName, GNT_EdiPartyName, GNT_URI, GNT_IPAddress, GNT_RegisteredID } SecCEGeneralNameType; typedef struct { DERItem typeId; DERItem value; // unparsed, BER-encoded } SecCEOtherName; typedef struct { SecCEGeneralNameType nameType; // GNT_RFC822Name, etc. bool berEncoded; DERItem name; } SecCEGeneralName; typedef struct { uint32_t numNames; SecCEGeneralName *generalName; } SecCEGeneralNames; /* * id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } * * AuthorityKeyIdentifier ::= SEQUENCE { * keyIdentifier [0] KeyIdentifier OPTIONAL, * authorityCertIssuer [1] GeneralNames OPTIONAL, * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } * * KeyIdentifier ::= OCTET STRING * * CSSM OID = CSSMOID_AuthorityKeyIdentifier */ typedef struct { bool keyIdentifierPresent; DERItem keyIdentifier; bool generalNamesPresent; SecCEGeneralNames *generalNames; bool serialNumberPresent; DERItem serialNumber; } SecCEAuthorityKeyID; /* * id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } * SubjectKeyIdentifier ::= KeyIdentifier * * CSSM OID = CSSMOID_SubjectKeyIdentifier */ typedef DERItem SecCESubjectKeyID; /* * id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } * * KeyUsage ::= BIT STRING { * digitalSignature (0), * nonRepudiation (1), * keyEncipherment (2), * dataEncipherment (3), * keyAgreement (4), * keyCertSign (5), * cRLSign (6), * encipherOnly (7), * decipherOnly (8) } * * CSSM OID = CSSMOID_KeyUsage * */ typedef uint16_t SecCEKeyUsage; #define SecCEKU_DigitalSignature 0x8000 #define SecCEKU_NonRepudiation 0x4000 #define SecCEKU_KeyEncipherment 0x2000 #define SecCEKU_DataEncipherment 0x1000 #define SecCEKU_KeyAgreement 0x0800 #define SecCEKU_KeyCertSign 0x0400 #define SecCEKU_CRLSign 0x0200 #define SecCEKU_EncipherOnly 0x0100 #define SecCEKU_DecipherOnly 0x0080 /* * id-ce-cRLReason OBJECT IDENTIFIER ::= { id-ce 21 } * * -- reasonCode ::= { CRLReason } * * CRLReason ::= ENUMERATED { * unspecified (0), * keyCompromise (1), * cACompromise (2), * affiliationChanged (3), * superseded (4), * cessationOfOperation (5), * certificateHold (6), * removeFromCRL (8) } * * CSSM OID = CSSMOID_CrlReason * */ typedef uint32_t SecCECrlReason; #define SecCECR_Unspecified 0 #define SecCECR_KeyCompromise 1 #define SecCECR_CACompromise 2 #define SecCECR_AffiliationChanged 3 #define SecCECR_Superseded 4 #define SecCECR_CessationOfOperation 5 #define SecCECR_CertificateHold 6 #define SecCECR_RemoveFromCRL 8 /* * id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } * * SubjectAltName ::= GeneralNames * * CSSM OID = CSSMOID_SubjectAltName * * GeneralNames defined above. */ /* * id-ce-extKeyUsage OBJECT IDENTIFIER ::= {id-ce 37} * * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId* * * KeyPurposeId ::= OBJECT IDENTIFIER * * CSSM OID = CSSMOID_ExtendedKeyUsage */ typedef struct { uint32_t numPurposes; DERItem *purposes; // in Intel pre-encoded format } SecCEExtendedKeyUsage; /* * id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } * * BasicConstraints ::= SEQUENCE { * cA BOOLEAN DEFAULT FALSE, * pathLenConstraint INTEGER (0..MAX) OPTIONAL } * * CSSM OID = CSSMOID_BasicConstraints */ typedef struct { bool present; bool critical; bool isCA; bool pathLenConstraintPresent; uint32_t pathLenConstraint; } SecCEBasicConstraints; typedef struct { bool present; bool critical; bool requireExplicitPolicyPresent; uint32_t requireExplicitPolicy; bool inhibitPolicyMappingPresent; uint32_t inhibitPolicyMapping; } SecCEPolicyConstraints; /* * id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } * * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation * * PolicyInformation ::= SEQUENCE { * policyIdentifier CertPolicyId, * policyQualifiers SEQUENCE SIZE (1..MAX) OF * PolicyQualifierInfo OPTIONAL } * * CertPolicyId ::= OBJECT IDENTIFIER * * PolicyQualifierInfo ::= SEQUENCE { * policyQualifierId PolicyQualifierId, * qualifier ANY DEFINED BY policyQualifierId } * * -- policyQualifierIds for Internet policy qualifiers * * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 } * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 } * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 } * * PolicyQualifierId ::= * OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice ) * * Qualifier ::= CHOICE { * cPSuri CPSuri, * userNotice UserNotice } * * CPSuri ::= IA5String * * UserNotice ::= SEQUENCE { * noticeRef NoticeReference OPTIONAL, * explicitText DisplayText OPTIONAL} * * NoticeReference ::= SEQUENCE { * organization DisplayText, * noticeNumbers SEQUENCE OF INTEGER } * * DisplayText ::= CHOICE { * visibleString VisibleString (SIZE (1..200)), * bmpString BMPString (SIZE (1..200)), * utf8String UTF8String (SIZE (1..200)) } * * CSSM OID = CSSMOID_CertificatePolicies * * We only support down to the level of Qualifier, and then only the CPSuri * choice. UserNotice is transmitted to and from this library as a raw * CSSM_DATA containing the BER-encoded UserNotice sequence. */ #if 0 typedef struct { DERItem policyQualifierId; // CSSMOID_QT_CPS, CSSMOID_QT_UNOTICE DERItem qualifier; // CSSMOID_QT_CPS: IA5String contents // CSSMOID_QT_UNOTICE : Sequence contents } SecCEPolicyQualifierInfo; #endif typedef struct { DERItem policyIdentifier; DERItem policyQualifiers; } SecCEPolicyInformation; typedef struct { bool present; bool critical; size_t numPolicies; // size of *policies; SecCEPolicyInformation *policies; } SecCECertificatePolicies; typedef struct { DERItem issuerDomainPolicy; DERItem subjectDomainPolicy; } SecCEPolicyMapping; /* PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE { issuerDomainPolicy CertPolicyId, subjectDomainPolicy CertPolicyId } */ typedef struct { bool present; bool critical; uint32_t numMappings; // size of *mappings; SecCEPolicyMapping *mappings; } SecCEPolicyMappings; #if 0 typedef struct { bool present; bool critical; uint32_t skipCerts; } SecCEInhibitAnyPolicy; /* * netscape-cert-type, a bit string. * * CSSM OID = CSSMOID_NetscapeCertType * * Bit fields defined in oidsattr.h: SecCENCT_SSL_Client, etc. */ typedef uint16_t SecCENetscapeCertType; /* * CRLDistributionPoints. * * id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } * * cRLDistributionPoints ::= { * CRLDistPointsSyntax } * * CRLDistPointsSyntax ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint * * NOTE: RFC 2459 claims that the tag for the optional DistributionPointName * is IMPLICIT as shown here, but in practice it is EXPLICIT. It has to be - * because the underlying type also uses an implicit tag for distinguish * between CHOICEs. * * DistributionPoint ::= SEQUENCE { * distributionPoint [0] DistributionPointName OPTIONAL, * reasons [1] ReasonFlags OPTIONAL, * cRLIssuer [2] GeneralNames OPTIONAL } * * DistributionPointName ::= CHOICE { * fullName [0] GeneralNames, * nameRelativeToCRLIssuer [1] RelativeDistinguishedName } * * ReasonFlags ::= BIT STRING { * unused (0), * keyCompromise (1), * cACompromise (2), * affiliationChanged (3), * superseded (4), * cessationOfOperation (5), * certificateHold (6) } * * CSSM OID = CSSMOID_CrlDistributionPoints */ /* * Note that this looks similar to SecCECrlReason, but that's an enum and this * is an OR-able bit string. */ typedef uint8_t SecCECrlDistReasonFlags; #define SecCECD_Unspecified 0x80 #define SecCECD_KeyCompromise 0x40 #define SecCECD_CACompromise 0x20 #define SecCECD_AffiliationChanged 0x10 #define SecCECD_Superseded 0x08 #define SecCECD_CessationOfOperation 0x04 #define SecCECD_CertificateHold 0x02 typedef enum { SecCECDNT_FullName, SecCECDNT_NameRelativeToCrlIssuer } SecCECrlDistributionPointNameType; typedef struct { SecCECrlDistributionPointNameType nameType; union { SecCEGeneralNames *fullName; CSSM_X509_RDN_PTR rdn; } dpn; } SecCEDistributionPointName; /* * The top-level CRLDistributionPoint. * All fields are optional; NULL pointers indicate absence. */ typedef struct { SecCEDistributionPointName *distPointName; bool reasonsPresent; SecCECrlDistReasonFlags reasons; SecCEGeneralNames *crlIssuer; } SecCECRLDistributionPoint; typedef struct { uint32_t numDistPoints; SecCECRLDistributionPoint *distPoints; } SecCECRLDistPointsSyntax; /* * Authority Information Access and Subject Information Access. * * CSSM OID = CSSMOID_AuthorityInfoAccess * CSSM OID = CSSMOID_SubjectInfoAccess * * SubjAuthInfoAccessSyntax ::= * SEQUENCE SIZE (1..MAX) OF AccessDescription * * AccessDescription ::= SEQUENCE { * accessMethod OBJECT IDENTIFIER, * accessLocation GeneralName } */ typedef struct { DERItem accessMethod; SecCEGeneralName accessLocation; } SecCEAccessDescription; typedef struct { uint32_t numAccessDescriptions; SecCEAccessDescription *accessDescriptions; } SecCEAuthorityInfoAccess; /*** CRL extensions ***/ /* * cRLNumber, an integer. * * CSSM OID = CSSMOID_CrlNumber */ typedef uint32_t SecCECrlNumber; /* * deltaCRLIndicator, an integer. * * CSSM OID = CSSMOID_DeltaCrlIndicator */ typedef uint32_t SecCEDeltaCrl; /* * IssuingDistributionPoint * * id-ce-issuingDistributionPoint OBJECT IDENTIFIER ::= { id-ce 28 } * * issuingDistributionPoint ::= SEQUENCE { * distributionPoint [0] DistributionPointName OPTIONAL, * onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE, * onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE, * onlySomeReasons [3] ReasonFlags OPTIONAL, * indirectCRL [4] BOOLEAN DEFAULT FALSE } * * CSSM OID = CSSMOID_IssuingDistributionPoint */ typedef struct { SecCEDistributionPointName *distPointName; // optional bool onlyUserCertsPresent; bool onlyUserCerts; bool onlyCACertsPresent; bool onlyCACerts; bool onlySomeReasonsPresent; SecCECrlDistReasonFlags onlySomeReasons; bool indirectCrlPresent; bool indirectCrl; } SecCEIssuingDistributionPoint; /* * An enumerated list identifying one of the above per-extension * structs. */ typedef enum { DT_AuthorityKeyID, // SecCEAuthorityKeyID DT_SubjectKeyID, // SecCESubjectKeyID DT_KeyUsage, // SecCEKeyUsage DT_SubjectAltName, // implies SecCEGeneralName DT_IssuerAltName, // implies SecCEGeneralName DT_ExtendedKeyUsage, // SecCEExtendedKeyUsage DT_BasicConstraints, // SecCEBasicConstraints DT_CertPolicies, // SecCECertPolicies DT_NetscapeCertType, // SecCENetscapeCertType DT_CrlNumber, // SecCECrlNumber DT_DeltaCrl, // SecCEDeltaCrl DT_CrlReason, // SecCECrlReason DT_CrlDistributionPoints, // SecCECRLDistPointsSyntax DT_IssuingDistributionPoint,// SecCEIssuingDistributionPoint DT_AuthorityInfoAccess, // SecCEAuthorityInfoAccess DT_Other // unknown, raw data as a CSSM_DATA } SecCEDataType; /* * One unified representation of all the cert adn CRL extensions we know about. */ typedef union { SecCEAuthorityKeyID authorityKeyID; SecCESubjectKeyID subjectKeyID; SecCEKeyUsage keyUsage; SecCEGeneralNames subjectAltName; SecCEGeneralNames issuerAltName; SecCEExtendedKeyUsage extendedKeyUsage; SecCEBasicConstraints basicConstraints; SecCECertPolicies certPolicies; SecCENetscapeCertType netscapeCertType; SecCECrlNumber crlNumber; SecCEDeltaCrl deltaCrl; SecCECrlReason crlReason; SecCECRLDistPointsSyntax crlDistPoints; SecCEIssuingDistributionPoint issuingDistPoint; SecCEAuthorityInfoAccess authorityInfoAccess; DERItem rawData; // unknown, not decoded } SecCEData; typedef struct { SecCEDataType type; SecCEData extension; bool critical; } SecCEDataAndType; #endif /* 0 */ #endif /* _CERT_EXTENSIONS_H_ */