Crypto++
|
00001 #ifndef CRYPTOPP_ASN_H 00002 #define CRYPTOPP_ASN_H 00003 00004 #include "filters.h" 00005 #include "queue.h" 00006 #include <vector> 00007 00008 NAMESPACE_BEGIN(CryptoPP) 00009 00010 // these tags and flags are not complete 00011 enum ASNTag 00012 { 00013 BOOLEAN = 0x01, 00014 INTEGER = 0x02, 00015 BIT_STRING = 0x03, 00016 OCTET_STRING = 0x04, 00017 TAG_NULL = 0x05, 00018 OBJECT_IDENTIFIER = 0x06, 00019 OBJECT_DESCRIPTOR = 0x07, 00020 EXTERNAL = 0x08, 00021 REAL = 0x09, 00022 ENUMERATED = 0x0a, 00023 UTF8_STRING = 0x0c, 00024 SEQUENCE = 0x10, 00025 SET = 0x11, 00026 NUMERIC_STRING = 0x12, 00027 PRINTABLE_STRING = 0x13, 00028 T61_STRING = 0x14, 00029 VIDEOTEXT_STRING = 0x15, 00030 IA5_STRING = 0x16, 00031 UTC_TIME = 0x17, 00032 GENERALIZED_TIME = 0x18, 00033 GRAPHIC_STRING = 0x19, 00034 VISIBLE_STRING = 0x1a, 00035 GENERAL_STRING = 0x1b 00036 }; 00037 00038 enum ASNIdFlag 00039 { 00040 UNIVERSAL = 0x00, 00041 // DATA = 0x01, 00042 // HEADER = 0x02, 00043 CONSTRUCTED = 0x20, 00044 APPLICATION = 0x40, 00045 CONTEXT_SPECIFIC = 0x80, 00046 PRIVATE = 0xc0 00047 }; 00048 00049 inline void BERDecodeError() {throw BERDecodeErr();} 00050 00051 class CRYPTOPP_DLL UnknownOID : public BERDecodeErr 00052 { 00053 public: 00054 UnknownOID() : BERDecodeErr("BER decode error: unknown object identifier") {} 00055 UnknownOID(const char *err) : BERDecodeErr(err) {} 00056 }; 00057 00058 // unsigned int DERLengthEncode(unsigned int length, byte *output=0); 00059 CRYPTOPP_DLL size_t CRYPTOPP_API DERLengthEncode(BufferedTransformation &out, lword length); 00060 // returns false if indefinite length 00061 CRYPTOPP_DLL bool CRYPTOPP_API BERLengthDecode(BufferedTransformation &in, size_t &length); 00062 00063 CRYPTOPP_DLL void CRYPTOPP_API DEREncodeNull(BufferedTransformation &out); 00064 CRYPTOPP_DLL void CRYPTOPP_API BERDecodeNull(BufferedTransformation &in); 00065 00066 CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &out, const byte *str, size_t strLen); 00067 CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &out, const SecByteBlock &str); 00068 CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &in, SecByteBlock &str); 00069 CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &in, BufferedTransformation &str); 00070 00071 // for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING 00072 CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeTextString(BufferedTransformation &out, const std::string &str, byte asnTag); 00073 CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeTextString(BufferedTransformation &in, std::string &str, byte asnTag); 00074 00075 CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeBitString(BufferedTransformation &out, const byte *str, size_t strLen, unsigned int unusedBits=0); 00076 CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeBitString(BufferedTransformation &in, SecByteBlock &str, unsigned int &unusedBits); 00077 00078 // BER decode from source and DER reencode into dest 00079 CRYPTOPP_DLL void CRYPTOPP_API DERReencode(BufferedTransformation &source, BufferedTransformation &dest); 00080 00081 //! Object Identifier 00082 class CRYPTOPP_DLL OID 00083 { 00084 public: 00085 OID() {} 00086 OID(word32 v) : m_values(1, v) {} 00087 OID(BufferedTransformation &bt) {BERDecode(bt);} 00088 00089 inline OID & operator+=(word32 rhs) {m_values.push_back(rhs); return *this;} 00090 00091 void DEREncode(BufferedTransformation &bt) const; 00092 void BERDecode(BufferedTransformation &bt); 00093 00094 // throw BERDecodeErr() if decoded value doesn't equal this OID 00095 void BERDecodeAndCheck(BufferedTransformation &bt) const; 00096 00097 std::vector<word32> m_values; 00098 00099 private: 00100 static void EncodeValue(BufferedTransformation &bt, word32 v); 00101 static size_t DecodeValue(BufferedTransformation &bt, word32 &v); 00102 }; 00103 00104 class EncodedObjectFilter : public Filter 00105 { 00106 public: 00107 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}; 00108 EncodedObjectFilter(BufferedTransformation *attachment = NULL, unsigned int nObjects = 1, word32 flags = 0); 00109 00110 void Put(const byte *inString, size_t length); 00111 00112 unsigned int GetNumberOfCompletedObjects() const {return m_nCurrentObject;} 00113 unsigned long GetPositionOfObject(unsigned int i) const {return m_positions[i];} 00114 00115 private: 00116 BufferedTransformation & CurrentTarget(); 00117 00118 word32 m_flags; 00119 unsigned int m_nObjects, m_nCurrentObject, m_level; 00120 std::vector<unsigned int> m_positions; 00121 ByteQueue m_queue; 00122 enum State {IDENTIFIER, LENGTH, BODY, TAIL, ALL_DONE} m_state; 00123 byte m_id; 00124 lword m_lengthRemaining; 00125 }; 00126 00127 //! BER General Decoder 00128 class CRYPTOPP_DLL BERGeneralDecoder : public Store 00129 { 00130 public: 00131 explicit BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag); 00132 explicit BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag); 00133 ~BERGeneralDecoder(); 00134 00135 bool IsDefiniteLength() const {return m_definiteLength;} 00136 lword RemainingLength() const {assert(m_definiteLength); return m_length;} 00137 bool EndReached() const; 00138 byte PeekByte() const; 00139 void CheckByte(byte b); 00140 00141 size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); 00142 size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const; 00143 00144 // call this to denote end of sequence 00145 void MessageEnd(); 00146 00147 protected: 00148 BufferedTransformation &m_inQueue; 00149 bool m_finished, m_definiteLength; 00150 lword m_length; 00151 00152 private: 00153 void Init(byte asnTag); 00154 void StoreInitialize(const NameValuePairs ¶meters) {assert(false);} 00155 lword ReduceLength(lword delta); 00156 }; 00157 00158 //! DER General Encoder 00159 class CRYPTOPP_DLL DERGeneralEncoder : public ByteQueue 00160 { 00161 public: 00162 explicit DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED); 00163 explicit DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED); 00164 ~DERGeneralEncoder(); 00165 00166 // call this to denote end of sequence 00167 void MessageEnd(); 00168 00169 private: 00170 BufferedTransformation &m_outQueue; 00171 bool m_finished; 00172 00173 byte m_asnTag; 00174 }; 00175 00176 //! BER Sequence Decoder 00177 class CRYPTOPP_DLL BERSequenceDecoder : public BERGeneralDecoder 00178 { 00179 public: 00180 explicit BERSequenceDecoder(BufferedTransformation &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED) 00181 : BERGeneralDecoder(inQueue, asnTag) {} 00182 explicit BERSequenceDecoder(BERSequenceDecoder &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED) 00183 : BERGeneralDecoder(inQueue, asnTag) {} 00184 }; 00185 00186 //! DER Sequence Encoder 00187 class CRYPTOPP_DLL DERSequenceEncoder : public DERGeneralEncoder 00188 { 00189 public: 00190 explicit DERSequenceEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED) 00191 : DERGeneralEncoder(outQueue, asnTag) {} 00192 explicit DERSequenceEncoder(DERSequenceEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED) 00193 : DERGeneralEncoder(outQueue, asnTag) {} 00194 }; 00195 00196 //! BER Set Decoder 00197 class CRYPTOPP_DLL BERSetDecoder : public BERGeneralDecoder 00198 { 00199 public: 00200 explicit BERSetDecoder(BufferedTransformation &inQueue, byte asnTag = SET | CONSTRUCTED) 00201 : BERGeneralDecoder(inQueue, asnTag) {} 00202 explicit BERSetDecoder(BERSetDecoder &inQueue, byte asnTag = SET | CONSTRUCTED) 00203 : BERGeneralDecoder(inQueue, asnTag) {} 00204 }; 00205 00206 //! DER Set Encoder 00207 class CRYPTOPP_DLL DERSetEncoder : public DERGeneralEncoder 00208 { 00209 public: 00210 explicit DERSetEncoder(BufferedTransformation &outQueue, byte asnTag = SET | CONSTRUCTED) 00211 : DERGeneralEncoder(outQueue, asnTag) {} 00212 explicit DERSetEncoder(DERSetEncoder &outQueue, byte asnTag = SET | CONSTRUCTED) 00213 : DERGeneralEncoder(outQueue, asnTag) {} 00214 }; 00215 00216 template <class T> 00217 class ASNOptional : public member_ptr<T> 00218 { 00219 public: 00220 void BERDecode(BERSequenceDecoder &seqDecoder, byte tag, byte mask = ~CONSTRUCTED) 00221 { 00222 byte b; 00223 if (seqDecoder.Peek(b) && (b & mask) == tag) 00224 reset(new T(seqDecoder)); 00225 } 00226 void DEREncode(BufferedTransformation &out) 00227 { 00228 if (this->get() != NULL) 00229 this->get()->DEREncode(out); 00230 } 00231 }; 00232 00233 //! _ 00234 template <class BASE> 00235 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ASN1CryptoMaterial : public ASN1Object, public BASE 00236 { 00237 public: 00238 void Save(BufferedTransformation &bt) const 00239 {BEREncode(bt);} 00240 void Load(BufferedTransformation &bt) 00241 {BERDecode(bt);} 00242 }; 00243 00244 //! encodes/decodes subjectPublicKeyInfo 00245 class CRYPTOPP_DLL X509PublicKey : public ASN1CryptoMaterial<PublicKey> 00246 { 00247 public: 00248 void BERDecode(BufferedTransformation &bt); 00249 void DEREncode(BufferedTransformation &bt) const; 00250 00251 virtual OID GetAlgorithmID() const =0; 00252 virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt) 00253 {BERDecodeNull(bt); return false;} 00254 virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const 00255 {DEREncodeNull(bt); return false;} // see RFC 2459, section 7.3.1 00256 00257 //! decode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header 00258 virtual void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0; 00259 //! encode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header 00260 virtual void DEREncodePublicKey(BufferedTransformation &bt) const =0; 00261 }; 00262 00263 //! encodes/decodes privateKeyInfo 00264 class CRYPTOPP_DLL PKCS8PrivateKey : public ASN1CryptoMaterial<PrivateKey> 00265 { 00266 public: 00267 void BERDecode(BufferedTransformation &bt); 00268 void DEREncode(BufferedTransformation &bt) const; 00269 00270 virtual OID GetAlgorithmID() const =0; 00271 virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt) 00272 {BERDecodeNull(bt); return false;} 00273 virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const 00274 {DEREncodeNull(bt); return false;} // see RFC 2459, section 7.3.1 00275 00276 //! decode privateKey part of privateKeyInfo, without the OCTET STRING header 00277 virtual void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0; 00278 //! encode privateKey part of privateKeyInfo, without the OCTET STRING header 00279 virtual void DEREncodePrivateKey(BufferedTransformation &bt) const =0; 00280 00281 //! decode optional attributes including context-specific tag 00282 /*! /note default implementation stores attributes to be output in DEREncodeOptionalAttributes */ 00283 virtual void BERDecodeOptionalAttributes(BufferedTransformation &bt); 00284 //! encode optional attributes including context-specific tag 00285 virtual void DEREncodeOptionalAttributes(BufferedTransformation &bt) const; 00286 00287 protected: 00288 ByteQueue m_optionalAttributes; 00289 }; 00290 00291 // ******************************************************** 00292 00293 //! DER Encode Unsigned 00294 /*! for INTEGER, BOOLEAN, and ENUM */ 00295 template <class T> 00296 size_t DEREncodeUnsigned(BufferedTransformation &out, T w, byte asnTag = INTEGER) 00297 { 00298 byte buf[sizeof(w)+1]; 00299 unsigned int bc; 00300 if (asnTag == BOOLEAN) 00301 { 00302 buf[sizeof(w)] = w ? 0xff : 0; 00303 bc = 1; 00304 } 00305 else 00306 { 00307 buf[0] = 0; 00308 for (unsigned int i=0; i<sizeof(w); i++) 00309 buf[i+1] = byte(w >> (sizeof(w)-1-i)*8); 00310 bc = sizeof(w); 00311 while (bc > 1 && buf[sizeof(w)+1-bc] == 0) 00312 --bc; 00313 if (buf[sizeof(w)+1-bc] & 0x80) 00314 ++bc; 00315 } 00316 out.Put(asnTag); 00317 size_t lengthBytes = DERLengthEncode(out, bc); 00318 out.Put(buf+sizeof(w)+1-bc, bc); 00319 return 1+lengthBytes+bc; 00320 } 00321 00322 //! BER Decode Unsigned 00323 // VC60 workaround: std::numeric_limits<T>::max conflicts with MFC max macro 00324 // CW41 workaround: std::numeric_limits<T>::max causes a template error 00325 template <class T> 00326 void BERDecodeUnsigned(BufferedTransformation &in, T &w, byte asnTag = INTEGER, 00327 T minValue = 0, T maxValue = 0xffffffff) 00328 { 00329 byte b; 00330 if (!in.Get(b) || b != asnTag) 00331 BERDecodeError(); 00332 00333 size_t bc; 00334 BERLengthDecode(in, bc); 00335 00336 SecByteBlock buf(bc); 00337 00338 if (bc != in.Get(buf, bc)) 00339 BERDecodeError(); 00340 00341 const byte *ptr = buf; 00342 while (bc > sizeof(w) && *ptr == 0) 00343 { 00344 bc--; 00345 ptr++; 00346 } 00347 if (bc > sizeof(w)) 00348 BERDecodeError(); 00349 00350 w = 0; 00351 for (unsigned int i=0; i<bc; i++) 00352 w = (w << 8) | ptr[i]; 00353 00354 if (w < minValue || w > maxValue) 00355 BERDecodeError(); 00356 } 00357 00358 inline bool operator==(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs) 00359 {return lhs.m_values == rhs.m_values;} 00360 inline bool operator!=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs) 00361 {return lhs.m_values != rhs.m_values;} 00362 inline bool operator<(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs) 00363 {return std::lexicographical_compare(lhs.m_values.begin(), lhs.m_values.end(), rhs.m_values.begin(), rhs.m_values.end());} 00364 inline ::CryptoPP::OID operator+(const ::CryptoPP::OID &lhs, unsigned long rhs) 00365 {return ::CryptoPP::OID(lhs)+=rhs;} 00366 00367 NAMESPACE_END 00368 00369 #endif