1#ifndef CRYPTOPP_ASN_H 2#define CRYPTOPP_ASN_H 3 4#include "filters.h" 5#include "queue.h" 6#include <vector> 7 8NAMESPACE_BEGIN(CryptoPP) 9 10// these tags and flags are not complete 11enum ASNTag 12{ 13 BOOLEAN = 0x01, 14 INTEGER = 0x02, 15 BIT_STRING = 0x03, 16 OCTET_STRING = 0x04, 17 TAG_NULL = 0x05, 18 OBJECT_IDENTIFIER = 0x06, 19 OBJECT_DESCRIPTOR = 0x07, 20 EXTERNAL = 0x08, 21 REAL = 0x09, 22 ENUMERATED = 0x0a, 23 UTF8_STRING = 0x0c, 24 SEQUENCE = 0x10, 25 SET = 0x11, 26 NUMERIC_STRING = 0x12, 27 PRINTABLE_STRING = 0x13, 28 T61_STRING = 0x14, 29 VIDEOTEXT_STRING = 0x15, 30 IA5_STRING = 0x16, 31 UTC_TIME = 0x17, 32 GENERALIZED_TIME = 0x18, 33 GRAPHIC_STRING = 0x19, 34 VISIBLE_STRING = 0x1a, 35 GENERAL_STRING = 0x1b 36}; 37 38enum ASNIdFlag 39{ 40 UNIVERSAL = 0x00, 41// DATA = 0x01, 42// HEADER = 0x02, 43 CONSTRUCTED = 0x20, 44 APPLICATION = 0x40, 45 CONTEXT_SPECIFIC = 0x80, 46 PRIVATE = 0xc0 47}; 48 49inline void BERDecodeError() {throw BERDecodeErr();} 50 51class CRYPTOPP_DLL UnknownOID : public BERDecodeErr 52{ 53public: 54 UnknownOID() : BERDecodeErr("BER decode error: unknown object identifier") {} 55 UnknownOID(const char *err) : BERDecodeErr(err) {} 56}; 57 58// unsigned int DERLengthEncode(unsigned int length, byte *output=0); 59CRYPTOPP_DLL size_t CRYPTOPP_API DERLengthEncode(BufferedTransformation &out, lword length); 60// returns false if indefinite length 61CRYPTOPP_DLL bool CRYPTOPP_API BERLengthDecode(BufferedTransformation &in, size_t &length); 62 63CRYPTOPP_DLL void CRYPTOPP_API DEREncodeNull(BufferedTransformation &out); 64CRYPTOPP_DLL void CRYPTOPP_API BERDecodeNull(BufferedTransformation &in); 65 66CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &out, const byte *str, size_t strLen); 67CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &out, const SecByteBlock &str); 68CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &in, SecByteBlock &str); 69CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &in, BufferedTransformation &str); 70 71// for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING 72CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeTextString(BufferedTransformation &out, const std::string &str, byte asnTag); 73CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeTextString(BufferedTransformation &in, std::string &str, byte asnTag); 74 75CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeBitString(BufferedTransformation &out, const byte *str, size_t strLen, unsigned int unusedBits=0); 76CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeBitString(BufferedTransformation &in, SecByteBlock &str, unsigned int &unusedBits); 77 78// BER decode from source and DER reencode into dest 79CRYPTOPP_DLL void CRYPTOPP_API DERReencode(BufferedTransformation &source, BufferedTransformation &dest); 80 81//! Object Identifier 82class CRYPTOPP_DLL OID 83{ 84public: 85 OID() {} 86 OID(word32 v) : m_values(1, v) {} 87 OID(BufferedTransformation &bt) {BERDecode(bt);} 88 89 inline OID & operator+=(word32 rhs) {m_values.push_back(rhs); return *this;} 90 91 void DEREncode(BufferedTransformation &bt) const; 92 void BERDecode(BufferedTransformation &bt); 93 94 // throw BERDecodeErr() if decoded value doesn't equal this OID 95 void BERDecodeAndCheck(BufferedTransformation &bt) const; 96 97 std::vector<word32> m_values; 98 99private: 100 static void EncodeValue(BufferedTransformation &bt, word32 v); 101 static size_t DecodeValue(BufferedTransformation &bt, word32 &v); 102}; 103 104class EncodedObjectFilter : public Filter 105{ 106public: 107 enum Flag {PUT_OBJECTS=1, PUT_MESSANGE_END_AFTER_EACH_OBJECT=2, PUT_MESSANGE_END_AFTER_ALL_OBJECTS=4, PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS=8}; 108 EncodedObjectFilter(BufferedTransformation *attachment = NULL, unsigned int nObjects = 1, word32 flags = 0); 109 110 void Put(const byte *inString, size_t length); 111 112 unsigned int GetNumberOfCompletedObjects() const {return m_nCurrentObject;} 113 unsigned long GetPositionOfObject(unsigned int i) const {return m_positions[i];} 114 115private: 116 BufferedTransformation & CurrentTarget(); 117 118 word32 m_flags; 119 unsigned int m_nObjects, m_nCurrentObject, m_level; 120 std::vector<unsigned int> m_positions; 121 ByteQueue m_queue; 122 enum State {IDENTIFIER, LENGTH, BODY, TAIL, ALL_DONE} m_state; 123 byte m_id; 124 lword m_lengthRemaining; 125}; 126 127//! BER General Decoder 128class CRYPTOPP_DLL BERGeneralDecoder : public Store 129{ 130public: 131 explicit BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag); 132 explicit BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag); 133 ~BERGeneralDecoder(); 134 135 bool IsDefiniteLength() const {return m_definiteLength;} 136 lword RemainingLength() const {assert(m_definiteLength); return m_length;} 137 bool EndReached() const; 138 byte PeekByte() const; 139 void CheckByte(byte b); 140 141 size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); 142 size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const; 143 144 // call this to denote end of sequence 145 void MessageEnd(); 146 147protected: 148 BufferedTransformation &m_inQueue; 149 bool m_finished, m_definiteLength; 150 lword m_length; 151 152private: 153 void Init(byte asnTag); 154 void StoreInitialize(const NameValuePairs ¶meters) {assert(false);} 155 lword ReduceLength(lword delta); 156}; 157 158//! DER General Encoder 159class CRYPTOPP_DLL DERGeneralEncoder : public ByteQueue 160{ 161public: 162 explicit DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED); 163 explicit DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED); 164 ~DERGeneralEncoder(); 165 166 // call this to denote end of sequence 167 void MessageEnd(); 168 169private: 170 BufferedTransformation &m_outQueue; 171 bool m_finished; 172 173 byte m_asnTag; 174}; 175 176//! BER Sequence Decoder 177class CRYPTOPP_DLL BERSequenceDecoder : public BERGeneralDecoder 178{ 179public: 180 explicit BERSequenceDecoder(BufferedTransformation &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED) 181 : BERGeneralDecoder(inQueue, asnTag) {} 182 explicit BERSequenceDecoder(BERSequenceDecoder &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED) 183 : BERGeneralDecoder(inQueue, asnTag) {} 184}; 185 186//! DER Sequence Encoder 187class CRYPTOPP_DLL DERSequenceEncoder : public DERGeneralEncoder 188{ 189public: 190 explicit DERSequenceEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED) 191 : DERGeneralEncoder(outQueue, asnTag) {} 192 explicit DERSequenceEncoder(DERSequenceEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED) 193 : DERGeneralEncoder(outQueue, asnTag) {} 194}; 195 196//! BER Set Decoder 197class CRYPTOPP_DLL BERSetDecoder : public BERGeneralDecoder 198{ 199public: 200 explicit BERSetDecoder(BufferedTransformation &inQueue, byte asnTag = SET | CONSTRUCTED) 201 : BERGeneralDecoder(inQueue, asnTag) {} 202 explicit BERSetDecoder(BERSetDecoder &inQueue, byte asnTag = SET | CONSTRUCTED) 203 : BERGeneralDecoder(inQueue, asnTag) {} 204}; 205 206//! DER Set Encoder 207class CRYPTOPP_DLL DERSetEncoder : public DERGeneralEncoder 208{ 209public: 210 explicit DERSetEncoder(BufferedTransformation &outQueue, byte asnTag = SET | CONSTRUCTED) 211 : DERGeneralEncoder(outQueue, asnTag) {} 212 explicit DERSetEncoder(DERSetEncoder &outQueue, byte asnTag = SET | CONSTRUCTED) 213 : DERGeneralEncoder(outQueue, asnTag) {} 214}; 215 216template <class T> 217class ASNOptional : public member_ptr<T> 218{ 219public: 220 void BERDecode(BERSequenceDecoder &seqDecoder, byte tag, byte mask = ~CONSTRUCTED) 221 { 222 byte b; 223 if (seqDecoder.Peek(b) && (b & mask) == tag) 224 reset(new T(seqDecoder)); 225 } 226 void DEREncode(BufferedTransformation &out) 227 { 228 if (this->get() != NULL) 229 this->get()->DEREncode(out); 230 } 231}; 232 233//! _ 234template <class BASE> 235class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ASN1CryptoMaterial : public ASN1Object, public BASE 236{ 237public: 238 void Save(BufferedTransformation &bt) const 239 {BEREncode(bt);} 240 void Load(BufferedTransformation &bt) 241 {BERDecode(bt);} 242}; 243 244//! encodes/decodes subjectPublicKeyInfo 245class CRYPTOPP_DLL X509PublicKey : public ASN1CryptoMaterial<PublicKey> 246{ 247public: 248 void BERDecode(BufferedTransformation &bt); 249 void DEREncode(BufferedTransformation &bt) const; 250 251 virtual OID GetAlgorithmID() const =0; 252 virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt) 253 {BERDecodeNull(bt); return false;} 254 virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const 255 {DEREncodeNull(bt); return false;} // see RFC 2459, section 7.3.1 256 257 //! decode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header 258 virtual void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0; 259 //! encode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header 260 virtual void DEREncodePublicKey(BufferedTransformation &bt) const =0; 261}; 262 263//! encodes/decodes privateKeyInfo 264class CRYPTOPP_DLL PKCS8PrivateKey : public ASN1CryptoMaterial<PrivateKey> 265{ 266public: 267 void BERDecode(BufferedTransformation &bt); 268 void DEREncode(BufferedTransformation &bt) const; 269 270 virtual OID GetAlgorithmID() const =0; 271 virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt) 272 {BERDecodeNull(bt); return false;} 273 virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const 274 {DEREncodeNull(bt); return false;} // see RFC 2459, section 7.3.1 275 276 //! decode privateKey part of privateKeyInfo, without the OCTET STRING header 277 virtual void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0; 278 //! encode privateKey part of privateKeyInfo, without the OCTET STRING header 279 virtual void DEREncodePrivateKey(BufferedTransformation &bt) const =0; 280 281 //! decode optional attributes including context-specific tag 282 /*! /note default implementation stores attributes to be output in DEREncodeOptionalAttributes */ 283 virtual void BERDecodeOptionalAttributes(BufferedTransformation &bt); 284 //! encode optional attributes including context-specific tag 285 virtual void DEREncodeOptionalAttributes(BufferedTransformation &bt) const; 286 287protected: 288 ByteQueue m_optionalAttributes; 289}; 290 291// ******************************************************** 292 293//! DER Encode Unsigned 294/*! for INTEGER, BOOLEAN, and ENUM */ 295template <class T> 296size_t DEREncodeUnsigned(BufferedTransformation &out, T w, byte asnTag = INTEGER) 297{ 298 byte buf[sizeof(w)+1]; 299 unsigned int bc; 300 if (asnTag == BOOLEAN) 301 { 302 buf[sizeof(w)] = w ? 0xff : 0; 303 bc = 1; 304 } 305 else 306 { 307 buf[0] = 0; 308 for (unsigned int i=0; i<sizeof(w); i++) 309 buf[i+1] = byte(w >> (sizeof(w)-1-i)*8); 310 bc = sizeof(w); 311 while (bc > 1 && buf[sizeof(w)+1-bc] == 0) 312 --bc; 313 if (buf[sizeof(w)+1-bc] & 0x80) 314 ++bc; 315 } 316 out.Put(asnTag); 317 size_t lengthBytes = DERLengthEncode(out, bc); 318 out.Put(buf+sizeof(w)+1-bc, bc); 319 return 1+lengthBytes+bc; 320} 321 322//! BER Decode Unsigned 323// VC60 workaround: std::numeric_limits<T>::max conflicts with MFC max macro 324// CW41 workaround: std::numeric_limits<T>::max causes a template error 325template <class T> 326void BERDecodeUnsigned(BufferedTransformation &in, T &w, byte asnTag = INTEGER, 327 T minValue = 0, T maxValue = 0xffffffff) 328{ 329 byte b; 330 if (!in.Get(b) || b != asnTag) 331 BERDecodeError(); 332 333 size_t bc; 334 BERLengthDecode(in, bc); 335 336 SecByteBlock buf(bc); 337 338 if (bc != in.Get(buf, bc)) 339 BERDecodeError(); 340 341 const byte *ptr = buf; 342 while (bc > sizeof(w) && *ptr == 0) 343 { 344 bc--; 345 ptr++; 346 } 347 if (bc > sizeof(w)) 348 BERDecodeError(); 349 350 w = 0; 351 for (unsigned int i=0; i<bc; i++) 352 w = (w << 8) | ptr[i]; 353 354 if (w < minValue || w > maxValue) 355 BERDecodeError(); 356} 357 358inline bool operator==(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs) 359 {return lhs.m_values == rhs.m_values;} 360inline bool operator!=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs) 361 {return lhs.m_values != rhs.m_values;} 362inline bool operator<(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs) 363 {return std::lexicographical_compare(lhs.m_values.begin(), lhs.m_values.end(), rhs.m_values.begin(), rhs.m_values.end());} 364inline ::CryptoPP::OID operator+(const ::CryptoPP::OID &lhs, unsigned long rhs) 365 {return ::CryptoPP::OID(lhs)+=rhs;} 366 367NAMESPACE_END 368 369#endif 370