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 }