1 /**
2 * EAC11 CVC Request
3 * 
4 * Copyright:
5 * (C) 2008 Falko Strenzke
6 *     2010 Jack Lloyd
7 * (C) 2014-2015 Etienne Cimon
8 *
9 * License:
10 * Botan is released under the Simplified BSD License (see LICENSE.md)
11 */
12 module botan.cert.cvc.cvc_req;
13 
14 import botan.constants;
15 static if (BOTAN_HAS_CARD_VERIFIABLE_CERTIFICATES):
16 
17 import botan.cert.cvc.cvc_gen_cert;
18 import botan.asn1.oids;
19 import botan.asn1.ber_dec;
20 import botan.utils.types;
21 import botan.cert.cvc.cvc_cert;
22 import botan.cert.cvc.ecdsa_sig;
23 import botan.cert.cvc.signed_obj;
24 import botan.filters.pipe;
25 import botan.pubkey.x509_key;
26 import botan.pubkey.algo.ecdsa;
27 
28 alias EAC11Req = RefCounted!EAC11ReqImpl;
29 /**
30 * This class represents TR03110 v1.1 EAC CV Certificate Requests.
31 */
32 final class EAC11ReqImpl : EAC11genCVC!EAC11ReqImpl, SignedObject
33 {
34 public:
35 
36     /**
37     * Compare for equality with other
38     * Params:
39     *  rhs = compare for equality with this object
40     */
41     bool opEquals(in EAC11Req rhs) const
42     {
43         return (this.tbsData() == rhs.tbsData() &&
44                 this.getConcatSig() == rhs.getConcatSig());
45     }
46 
47     int opCmp(in EAC11ReqImpl rhs) const
48     {
49         if (this == rhs)
50             return 0;
51         else return -1;
52 
53     }
54     /**
55     * Construct a CVC request from a data source.
56     *
57     * Params:
58     *  source = the data source
59     */
60     this(DataSource source)
61     {
62         init(source);
63         m_self_signed = true;
64         doDecode();
65     }
66 
67     /**
68     * Construct a CVC request from a DER encoded CVC request file.
69     *
70     * Params:
71     *  str = the path to the DER encoded file
72     */
73     this(in string str)
74     {
75         auto stream = DataSourceStream(str, true);
76         init(cast(DataSource)stream);
77         m_self_signed = true;
78         doDecode();
79     }
80 
81     // copy
82     this(const ref EAC11Req other)
83     {
84         m_sig = other.m_sig.clone;
85         m_sig_algo = AlgorithmIdentifier(other.m_sig_algo);
86         m_tbs_bits = other.m_tbs_bits.clone;
87         m_PEM_labels_allowed = other.m_PEM_labels_allowed.clone;
88     
89         m_pk = cast(ECDSAPublicKey)other.m_pk; // no copy of this...
90         m_chr = ASN1Chr(other.m_chr);
91         m_self_signed = other.m_self_signed;
92     }
93 
94     // assign
95     void opAssign(ref EAC11Req other) {
96         m_sig = other.m_sig;
97         m_sig_algo = other.m_sig_algo;
98         m_tbs_bits = other.m_tbs_bits.clone; // move?
99         m_PEM_labels_allowed = other.m_PEM_labels_allowed;
100         m_pk = other.m_pk;
101         m_chr = other.m_chr;
102         m_self_signed = other.m_self_signed;
103     }
104 
105     // Interface fall-through
106     override const(Vector!ubyte) getConcatSig() const { return super.getConcatSig(); }
107     override void encode(Pipe pipe, X509Encoding encoding = PEM_) const { return super.encode(pipe, encoding); }
108     override const(Vector!ubyte) tbsData() const { return super.tbsData(); }
109 
110 protected:
111     override void forceDecode()
112     {
113         Vector!ubyte enc_pk;
114         BERDecoder tbs_cert = BERDecoder(m_tbs_bits);
115         size_t cpi;
116         tbs_cert.decode(cpi, (cast(ASN1Tag)41), ASN1Tag.APPLICATION)
117                 .startCons((cast(ASN1Tag)73), ASN1Tag.APPLICATION)
118                 .rawBytes(enc_pk)
119                 .endCons()
120                 .decode(m_chr)
121                 .verifyEnd();
122         
123         if (cpi != 0)
124             throw new DecodingError("EAC1_1 requests cpi was not 0");
125         
126         m_pk = decodeEac11Key(enc_pk, m_sig_algo);
127     }
128 }