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 }