1 /** 2 * EAC11 CVC ADO 3 * 4 * Copyright: 5 * (C) 2008 Falko Strenzke 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.cvc.cvc_ado; 12 13 import botan.constants; 14 static if (BOTAN_HAS_CARD_VERIFIABLE_CERTIFICATES): 15 16 import botan.cert.cvc.eac_obj; 17 import botan.cert.cvc.signed_obj; 18 import botan.cert.cvc.eac_asn_obj; 19 import botan.cert.cvc.cvc_req; 20 import botan.cert.cvc.ecdsa_sig; 21 import botan.rng.rng; 22 import botan.pubkey.pubkey; 23 import botan.filters.data_src; 24 import botan.filters.pipe; 25 import botan.pubkey.x509_key; 26 import botan.asn1.asn1_obj; 27 import botan.utils.types; 28 import std.typecons : scoped; 29 30 alias EAC11ADO = RefCounted!EAC11ADOImpl; 31 /** 32 * This class represents a TR03110 (EAC) v1.1 CVC ADO request 33 */ 34 35 // CRTP continuation from EAC11obj 36 final class EAC11ADOImpl : EAC11obj!EAC11ADOImpl, SignedObject 37 { 38 public: 39 override const(Vector!ubyte) getConcatSig() const { return super.getConcatSig(); } 40 /** 41 * Construct a CVC ADO request from a DER encoded CVC ADO request file. 42 * 43 * Params: 44 * input = the path to the DER encoded file 45 */ 46 this(in string input) 47 { 48 auto stream = DataSourceStream(input, true); 49 init(cast(DataSource)stream); 50 doDecode(); 51 } 52 53 /** 54 * Construct a CVC ADO request from a data source 55 * Params: 56 * input = the data source 57 */ 58 this(DataSource input) 59 { 60 init(input); 61 doDecode(); 62 } 63 64 /** 65 * Create a signed CVC ADO request from to be signed (TBS) data 66 * Params: 67 * signer = the signer used to sign the CVC ADO request 68 * tbs_bits = the TBS data to sign 69 * rng = a random number generator 70 */ 71 static Vector!ubyte makeSigned(ALLOC)(ref PKSigner signer, 72 auto const ref Vector!(ubyte, ALLOC) tbs_bits, 73 RandomNumberGenerator rng) 74 { 75 const Vector!ubyte concat_sig = signer.signMessage(tbs_bits, rng); 76 77 return DEREncoder() 78 .startCons((cast(ASN1Tag)7), ASN1Tag.APPLICATION) 79 .rawBytes(tbs_bits) 80 .encode(concat_sig, ASN1Tag.OCTET_STRING, (cast(ASN1Tag)55), ASN1Tag.APPLICATION) 81 .endCons() 82 .getContentsUnlocked(); 83 } 84 85 static Vector!ubyte makeSigned(ALLOC)(ref PKSigner signer, 86 auto const ref RefCounted!(Vector!(ubyte, ALLOC), ALLOC) tbs_bits, 87 RandomNumberGenerator rng) 88 { 89 return makeSigned(signer, **tbs_bits, rng); 90 } 91 92 /** 93 * Get the CAR of this CVC ADO request 94 * Returns: the CAR of this CVC ADO request 95 */ 96 const(ASN1Car) getCar() const 97 { 98 return m_car; 99 } 100 101 /** 102 * Get the CVC request contained in this object. 103 * Returns: the CVC request inside this CVC ADO request 104 */ 105 const(EAC11Req) getRequest() const 106 { 107 return m_req; 108 } 109 110 /** 111 * Encode this object into a pipe. Only DER is supported. 112 * 113 * Params: 114 * output = the pipe to encode this object into 115 * encoding = the encoding type to use, must be DER 116 */ 117 override void encode(Pipe output, X509Encoding encoding) const 118 { 119 if (encoding == PEM_) 120 throw new InvalidArgument("encode() cannot PEM encode an EAC object"); 121 122 auto concat_sig = m_sig.getConcatenation(); 123 124 output.write(DEREncoder() 125 .startCons((cast(ASN1Tag)7), ASN1Tag.APPLICATION) 126 .rawBytes(m_tbs_bits) 127 .encode(concat_sig, ASN1Tag.OCTET_STRING, (cast(ASN1Tag)55), ASN1Tag.APPLICATION) 128 .endCons() 129 .getContents()); 130 } 131 132 bool opEquals(in EAC11ADO rhs) const 133 { 134 return (getConcatSig() == rhs.getConcatSig() 135 && tbsData() == rhs.tbsData() 136 && getCar() == rhs.getCar()); 137 } 138 139 /** 140 * Get the TBS data of this CVC ADO request. 141 * Returns: the TBS data 142 */ 143 override const(Vector!ubyte) tbsData() const 144 { 145 return m_tbs_bits.dup; 146 } 147 148 149 int opCmp(in EAC11ADOImpl rhs) const 150 { 151 if (this == rhs) 152 return 0; 153 else return -1; // no comparison support 154 } 155 156 /** 157 * Construct a CVC ADO request from a copy of another ADO object 158 * Params: 159 * other = the other object 160 */ 161 this(ref EAC11ADO other) 162 { 163 m_sig = other.m_sig.dup; 164 m_sig_algo = AlgorithmIdentifier(other.m_sig_algo); 165 m_tbs_bits = other.m_tbs_bits.dup; 166 m_PEM_labels_allowed = other.m_PEM_labels_allowed; 167 168 m_car = ASN1Car(other.m_car); 169 m_req = EAC11Req(other.m_req); 170 } 171 172 /** 173 * Replace this ADO request with references to another one 174 * Params: 175 * other = the other object 176 */ 177 void opAssign(ref EAC11ADO other) 178 { 179 m_sig = other.m_sig; 180 m_sig_algo = other.m_sig_algo; 181 m_tbs_bits = other.m_tbs_bits.dup; 182 m_PEM_labels_allowed = other.m_PEM_labels_allowed; 183 184 m_car = other.m_car; 185 m_req = other.m_req; 186 } 187 188 protected: 189 ASN1Car m_car; 190 EAC11Req m_req; 191 192 override void forceDecode() 193 { 194 Vector!ubyte inner_cert; 195 BERDecoder(m_tbs_bits) 196 .startCons((cast(ASN1Tag)33), ASN1Tag.APPLICATION) 197 .rawBytes(inner_cert) 198 .endCons() 199 .decode(m_car) 200 .verifyEnd(); 201 202 Vector!ubyte req_bits = DEREncoder() 203 .startCons((cast(ASN1Tag)33), ASN1Tag.APPLICATION) 204 .rawBytes(inner_cert) 205 .endCons() 206 .getContentsUnlocked(); 207 208 auto req_source = DataSourceMemory(&req_bits); 209 m_req = EAC11Req(cast(DataSource)req_source); 210 m_sig_algo = cast(AlgorithmIdentifier) m_req.signatureAlgorithm(); 211 } 212 213 214 package: 215 static void decodeInfo(ALLOC)(DataSource source, 216 auto ref RefCounted!(Vector!(ubyte, ALLOC), ALLOC) res_tbs_bits, 217 ref ECDSASignature res_sig) 218 { 219 return decodeInfo(source, **res_tbs_bits, res_sig); 220 } 221 222 static void decodeInfo(ALLOC)(DataSource source, 223 auto ref Vector!(ubyte, ALLOC) res_tbs_bits, 224 ref ECDSASignature res_sig) 225 { 226 Vector!ubyte concat_sig; 227 Vector!ubyte cert_inner_bits; 228 ASN1Car car; 229 230 BERDecoder(source) 231 .startCons((cast(ASN1Tag)7), ASN1Tag.APPLICATION) 232 .startCons((cast(ASN1Tag)33), ASN1Tag.APPLICATION) 233 .rawBytes(cert_inner_bits) 234 .endCons() 235 .decode(car) 236 .decode(concat_sig, ASN1Tag.OCTET_STRING, (cast(ASN1Tag)55), ASN1Tag.APPLICATION) 237 .endCons(); 238 239 Vector!ubyte enc_cert = DEREncoder() 240 .startCons((cast(ASN1Tag)33), ASN1Tag.APPLICATION) 241 .rawBytes(cert_inner_bits) 242 .endCons() 243 .getContentsUnlocked(); 244 245 res_tbs_bits = enc_cert.move(); 246 res_tbs_bits ~= DEREncoder().encode(car).getContentsUnlocked(); 247 res_sig = decodeConcatenation(concat_sig); 248 } 249 }