1 /**
2 * EAC SIGNED Object
3 * 
4 * Copyright:
5 * (C) 2007 FlexSecure GmbH
6 *     2008 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.signed_obj;
13 
14 import botan.constants;
15 static if (BOTAN_HAS_CARD_VERIFIABLE_CERTIFICATES):
16 
17 import botan.asn1.asn1_obj;
18 import botan.cert.x509.key_constraint;
19 import botan.pubkey.x509_key;
20 import botan.filters.pipe;
21 import botan.pubkey.pubkey;
22 import botan.asn1.oids;
23 import botan.utils.types;
24 import botan.utils.exceptn;
25 import botan.codec.pem;
26 import botan.utils.mem_ops;
27 
28 import std.algorithm : splitter;
29 
30 interface SignedObject {
31     /**
32     * Get the TBS (to-be-signed) data in this object.
33     * Returns: DER encoded TBS data of this object
34     */
35     const(Vector!ubyte) tbsData() const;
36     
37     /**
38     * Get the signature of this object as a concatenation, i.e. if the
39     * signature consists of multiple parts (like in the case of ECDSA)
40     * these will be concatenated.
41     * Returns: signature as a concatenation of its parts
42     */
43     const(Vector!ubyte) getConcatSig() const;
44     /**
45     * Write this object DER encoded into a specified pipe.
46     *
47     * Params:
48     *  pipe = the pipe to write the encoded object to
49     *  encoding = the encoding type to use
50     */
51     void encode(Pipe pipe, X509Encoding encoding = PEM_) const;
52 protected:
53     abstract void forceDecode();
54 }
55 
56 /**
57 * This class represents abstract signed EAC object
58 */
59 abstract class EACSignedObject : SignedObject
60 {
61 public:
62 
63 
64     /**
65     * Get the signature algorithm identifier used to sign this object.
66     * Returns: the signature algorithm identifier
67     */
68     const(AlgorithmIdentifier) signatureAlgorithm() const
69     {
70         return m_sig_algo;
71     }
72 
73     /**
74     * Check the signature of this object.
75     *
76     * Params:
77     *  pub_key = the public key associated with this signed object
78     *  sig = the signature we are checking
79     * Returns: true if the signature was created by the private key
80     * associated with this public key
81     */
82     bool checkSignature(ALLOC)(PublicKey pub_key, auto ref Vector!(ubyte, ALLOC) sig) const
83     {
84         try
85         {
86             Vector!string sig_info = splitter(OIDS.lookup(m_sig_algo.oid), '/');
87             
88             if (sig_info.length != 2 || sig_info[0] != pub_key.algoName)
89             {
90                 return false;
91             }
92             
93             string padding = sig_info[1];
94             SignatureFormat format = (pub_key.messageParts() >= 2) ? DER_SEQUENCE : IEEE_1363;
95             
96             const(Vector!ubyte) to_sign = tbsData();
97             
98             PKVerifier verifier = PKVerifier(pub_key, padding, format);
99             return verifier.verifyMessage(to_sign, sig);
100         }
101         catch (Exception)
102         {
103             return false;
104         }
105     }
106 
107 
108 
109     /**
110     * BER encode this object.
111     * Returns: result containing the BER representation of this object.
112     */
113     Vector!ubyte BER_encode() const
114     {
115         Pipe ber;
116         ber.startMsg();
117         encode(ber, RAW_BER);
118         ber.endMsg();
119         return unlock(ber.readAll());
120     }
121 
122     /**
123     * PEM encode this object.
124     * Returns: result containing the PEM representation of this object.
125     */
126     string PEM_encode() const
127     {
128         Pipe pem;
129         pem.startMsg();
130         encode(pem, PEM_);
131         pem.endMsg();
132         return pem.toString();
133     }
134 
135     ~this() {}
136 protected:
137 
138     /*
139     * Try to decode the actual information
140     */
141     void doDecode()
142     {
143         try {
144             forceDecode();
145         }
146         catch(DecodingError e)
147         {
148             const string what = e.msg;
149             throw new DecodingError("EACSignedObject decoding failed (" ~ what ~ ")");
150         }
151         catch(InvalidArgument e)
152         {
153             const string what = e.msg;
154             throw new DecodingError("EACSignedObject decoding failed (" ~ what ~ ")");
155         }
156     }
157 
158     this() {}
159 
160     AlgorithmIdentifier m_sig_algo;
161     Vector!ubyte m_tbs_bits;
162     string[] m_PEM_labels_allowed;
163 }