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