1 /**
2 * EAC11 general CVC
3 * 
4 * Copyright:
5 * (C) 2008 Falko Strenzke
6 *     2008-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_gen_cert;
13 
14 import botan.constants;
15 static if (BOTAN_HAS_CARD_VERIFIABLE_CERTIFICATES):
16 
17 import botan.asn1.ber_dec;
18 import botan.cert.cvc.eac_obj;
19 import botan.cert.cvc.eac_asn_obj;
20 import botan.cert.cvc.signed_obj;
21 import botan.filters.pipe;
22 import botan.pubkey.x509_key;
23 import botan.filters.data_src;
24 import botan.pubkey.algo.ecdsa;
25 import botan.pubkey.pubkey;
26 import botan.cert.cvc.ecdsa_sig;
27 import botan.utils.types;
28 
29 /**
30 *  This class represents TR03110 (EAC) v1.1 generalized CV Certificates
31 */
32 abstract class EAC11genCVC(Derived) : EAC11obj!Derived, SignedObject // CRTP continuation from EAC11obj
33 {
34 public:
35     override const(Vector!ubyte) getConcatSig() const { return super.getConcatSig(); }
36     /**
37     * Get this certificates public key.
38     * Returns: this certificates public key
39     */
40     final const(PublicKey) subjectPublicKey() const
41     {
42         return m_pk;
43     }
44 
45     /**
46     * Find out whether this object is self signed.
47     * Returns: true if this object is self signed
48     */
49     final bool isSelfSigned() const
50     {
51         return m_self_signed;
52     }
53 
54 
55     /**
56     * Get the CHR of the certificate.
57     * Returns: the CHR of the certificate
58     */
59     final const(ASN1Chr) getChr() const {
60         return m_chr;
61     }
62 
63     /**
64     * Put the DER encoded version of this object into a pipe. PEM
65     * is not supported.
66     *
67     * Params:
68     *  output = the pipe to push the DER encoded version into
69     *  encoding = the encoding to use. Must be DER.
70     */
71     override void encode(Pipe output, X509Encoding encoding) const
72     {
73         const(Vector!ubyte) concat_sig = EAC11obj!Derived.m_sig.getConcatenation();
74         auto tbsdata = tbsData();
75         Vector!ubyte der = DEREncoder()
76                             .startCons((cast(ASN1Tag)33), ASN1Tag.APPLICATION)
77                             .startCons((cast(ASN1Tag)78), ASN1Tag.APPLICATION)
78                             .rawBytes(tbsdata)
79                             .endCons()
80                             .encode(concat_sig, ASN1Tag.OCTET_STRING, (cast(ASN1Tag)55), ASN1Tag.APPLICATION)
81                             .endCons()
82                             .getContentsUnlocked();
83         
84         if (encoding == PEM_)
85             throw new InvalidArgument("EAC11genCVC::encode() cannot PEM encode an EAC object");
86         else
87             output.write(der);
88     }
89 
90     /**
91     * Get the to-be-signed (TBS) data of this object.
92     * Returns: the TBS data of this object
93     */
94     override const(Vector!ubyte) tbsData() const
95     {
96         return buildCertBody(m_tbs_bits);
97     }
98 
99 
100     /**
101     * Build the DER encoded certifcate body of an object
102     * Params:
103     *  tbs = the data to be signed
104     * Returns: the correctly encoded body of the object
105     */
106     static Vector!ubyte buildCertBody(ALLOC)(auto const ref Vector!(ubyte, ALLOC) tbs)
107     {
108         return DEREncoder()
109                 .startCons((cast(ASN1Tag)78), ASN1Tag.APPLICATION)
110                 .rawBytes(tbs)
111                 .endCons().getContentsUnlocked();
112     }
113 
114     /**
115     * Create a signed generalized CVC object.
116     *
117     * Params:
118     *  signer = the signer used to sign this object
119     *  tbs_bits = the body the generalized CVC object to be signed
120     *  rng = a random number generator
121     * Returns: the DER encoded signed generalized CVC object
122     */
123     static Vector!ubyte makeSigned(ALLOC)(ref PKSigner signer,
124                                           auto const ref Vector!(ubyte, ALLOC) tbs_bits,
125                                           RandomNumberGenerator rng)
126     {
127         const auto concat_sig = signer.signMessage(tbs_bits, rng);
128         return DEREncoder()
129                 .startCons((cast(ASN1Tag)33), ASN1Tag.APPLICATION)
130                 .rawBytes(tbs_bits)
131                 .encode(concat_sig, ASN1Tag.OCTET_STRING, (cast(ASN1Tag)55), ASN1Tag.APPLICATION)
132                 .endCons()
133                 .getContentsUnlocked();
134     }
135 
136     static Vector!ubyte makeSigned(ALLOC)(ref PKSigner signer,
137                                           auto const ref RefCounted!(Vector!(ubyte, ALLOC), ALLOC) tbs_bits,
138                                           RandomNumberGenerator rng)
139     {
140         return makeSigned(signer, *tbs_bits, rng);
141     }
142 
143 protected:
144     ECDSAPublicKey m_pk;
145     ASN1Chr m_chr;
146     bool m_self_signed;
147     abstract void forceDecode();
148 package:
149     static void decodeInfo(ALLOC)(DataSource source,
150                                       ref Vector!(ubyte, ALLOC) res_tbs_bits,
151                                       ECDSASignature res_sig)
152     {
153         Vector!ubyte concat_sig;
154         BERDecoder(source)
155                 .startCons((cast(ASN1Tag)33), ASN1Tag.APPLICATION)
156                 .startCons((cast(ASN1Tag)78), ASN1Tag.APPLICATION)
157                 .rawBytes(res_tbs_bits)
158                 .endCons()
159                 .decode(concat_sig, ASN1Tag.OCTET_STRING, (cast(ASN1Tag)55), ASN1Tag.APPLICATION)
160                 .endCons();
161         res_sig = decodeConcatenation(concat_sig);
162     }
163 
164     static void decodeInfo(ALLOC)(DataSource source,
165                                   ref RefCounted!(Vector!(ubyte, ALLOC), ALLOC) res_tbs_bits,
166                                   ECDSASignature res_sig)
167     {
168         return decodeInfo(source, *res_tbs_bits, res_sig);
169     }
170 }