1 /** 2 * CRL Entry 3 * 4 * Copyright: 5 * (C) 1999-2007 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 module botan.cert.x509.crl_ent; 12 13 import botan.constants; 14 static if (BOTAN_HAS_X509_CERTIFICATES): 15 16 import botan.cert.x509.x509cert; 17 import botan.asn1.asn1_time; 18 import botan.cert.x509.x509_ext; 19 import botan.asn1.der_enc; 20 import botan.asn1.ber_dec; 21 import botan.math.bigint.bigint; 22 import botan.asn1.oids; 23 import botan.utils.types; 24 import std.datetime; 25 26 alias CRLEntry = RefCounted!CRLEntryImpl; 27 28 alias CRLCode = uint; 29 /** 30 * X.509v2 CRL Reason Code. 31 */ 32 enum : CRLCode { 33 UNSPECIFIED = 0, 34 KEY_COMPROMISE = 1, 35 CA_COMPROMISE = 2, 36 AFFILIATION_CHANGED = 3, 37 SUPERSEDED = 4, 38 CESSATION_OF_OPERATION = 5, 39 CERTIFICATE_HOLD = 6, 40 REMOVE_FROM_CRL = 8, 41 PRIVLEDGE_WITHDRAWN = 9, 42 AA_COMPROMISE = 10, 43 44 DELETE_CRL_ENTRY = 0xFF00, 45 OCSP_GOOD = 0xFF01, 46 OCSP_UNKNOWN = 0xFF02 47 } 48 49 /** 50 * This class represents CRL entries 51 */ 52 final class CRLEntryImpl : ASN1Object 53 { 54 public: 55 /* 56 * DER encode a CRLEntry 57 */ 58 override void encodeInto(ref DEREncoder to_) const 59 { 60 X509Extensions extensions; 61 62 extensions.add(new CRLReasonCode(m_reason)); 63 64 to_.startCons(ASN1Tag.SEQUENCE) 65 .encode(BigInt.decode(m_serial)) 66 .encode(m_time) 67 .startCons(ASN1Tag.SEQUENCE) 68 .encode(extensions) 69 .endCons() 70 .endCons(); 71 } 72 73 74 /* 75 * Decode a BER encoded CRLEntry 76 */ 77 override void decodeFrom(ref BERDecoder source) 78 { 79 BigInt serial_number_bn; 80 m_reason = UNSPECIFIED; 81 82 BERDecoder entry = source.startCons(ASN1Tag.SEQUENCE); 83 84 entry.decode(serial_number_bn).decode(m_time); 85 86 if (entry.moreItems()) 87 { 88 X509Extensions extensions = X509Extensions(m_throw_on_unknown_critical); 89 entry.decode(extensions); 90 DataStore info; 91 extensions.contentsTo(info, info); 92 m_reason = cast(CRLCode)(info.get1Uint("X509v3.CRLReasonCode")); 93 } 94 95 entry.endCons(); 96 97 m_serial = BigInt.encode(serial_number_bn); 98 } 99 100 /** 101 * Get the serial number of the certificate associated with this entry. 102 * Returns: certificate's serial number 103 */ 104 ref const(Vector!ubyte) serialNumber() const { return m_serial; } 105 106 /** 107 * Get the revocation date of the certificate associated with this entry 108 * Returns: certificate's revocation date 109 */ 110 const(X509Time) expireTime() const { return m_time; } 111 112 /** 113 * Get the entries reason code 114 * Returns: reason code 115 */ 116 CRLCode reasonCode() const { return m_reason; } 117 118 /** 119 * Construct an empty CRL entry. 120 */ 121 this(bool throw_on_unknown_critical_extension) 122 { 123 m_throw_on_unknown_critical = throw_on_unknown_critical_extension; 124 m_reason = UNSPECIFIED; 125 } 126 127 /** 128 * Construct an CRL entry. 129 * 130 * Params: 131 * cert = the certificate to revoke 132 * why = the reason code to set in the entry 133 */ 134 this(in X509CertificateImpl cert, CRLCode why = UNSPECIFIED) 135 { 136 m_throw_on_unknown_critical = false; 137 m_serial = cert.serialNumber().dup; 138 m_time = X509Time(Clock.currTime(UTC())); 139 m_reason = why; 140 } 141 142 /* 143 * Compare two CRL_Entrys for equality 144 */ 145 bool opEquals(in CRLEntry a2) const 146 { 147 if (serialNumber() != a2.serialNumber()) 148 return false; 149 if (expireTime() != a2.expireTime()) 150 return false; 151 if (reasonCode() != a2.reasonCode()) 152 return false; 153 return true; 154 } 155 156 /* 157 * Compare two CRL_Entrys for inequality 158 */ 159 int opCmp(in CRLEntry a2) const 160 { 161 if (this == a2) return 0; 162 else return -1; 163 } 164 165 166 private: 167 bool m_throw_on_unknown_critical; 168 Vector!ubyte m_serial; 169 X509Time m_time; 170 CRLCode m_reason; 171 }