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().clone;
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 }