Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

# asn.h

    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 unsigned int DERLengthEncode(BufferedTransformation &out, unsigned int length);
    00060 // returns false if indefinite length
    00061 CRYPTOPP_DLL bool BERLengthDecode(BufferedTransformation &in, unsigned int &length);
    00062
    00063 CRYPTOPP_DLL void DEREncodeNull(BufferedTransformation &out);
    00064 CRYPTOPP_DLL void BERDecodeNull(BufferedTransformation &in);
    00065
    00066 CRYPTOPP_DLL unsigned int DEREncodeOctetString(BufferedTransformation &out, const byte *str, unsigned int strLen);
    00067 CRYPTOPP_DLL unsigned int DEREncodeOctetString(BufferedTransformation &out, const SecByteBlock &str);
    00068 CRYPTOPP_DLL unsigned int BERDecodeOctetString(BufferedTransformation &in, SecByteBlock &str);
    00069 CRYPTOPP_DLL unsigned int BERDecodeOctetString(BufferedTransformation &in, BufferedTransformation &str);
    00070
    00071 // for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
    00072 CRYPTOPP_DLL unsigned int DEREncodeTextString(BufferedTransformation &out, const std::string &str, byte asnTag);
    00073 CRYPTOPP_DLL unsigned int BERDecodeTextString(BufferedTransformation &in, std::string &str, byte asnTag);
    00074
    00075 CRYPTOPP_DLL unsigned int DEREncodeBitString(BufferedTransformation &out, const byte *str, unsigned int strLen, unsigned int unusedBits=0);
    00076 CRYPTOPP_DLL unsigned int BERDecodeBitString(BufferedTransformation &in, SecByteBlock &str, unsigned int &unusedBits);
    00077
    00078 //! Object Identifier
    00079 class CRYPTOPP_DLL OID
    00080 {
    00081 public:
    00082         OID() {}
    00083         OID(unsigned long v) : m_values(1, v) {}
    00084         OID(BufferedTransformation &bt) {BERDecode(bt);}
    00085
    00086         inline OID & operator+=(unsigned long rhs) {m_values.push_back(rhs); return *this;}
    00087
    00088         void DEREncode(BufferedTransformation &bt) const;
    00089         void BERDecode(BufferedTransformation &bt);
    00090
    00091         // throw BERDecodeErr() if decoded value doesn't equal this OID
    00092         void BERDecodeAndCheck(BufferedTransformation &bt) const;
    00093
    00094         std::vector<unsigned long> m_values;
    00095
    00096 private:
    00097         static void EncodeValue(BufferedTransformation &bt, unsigned long v);
    00098         static unsigned int DecodeValue(BufferedTransformation &bt, unsigned long &v);
    00099 };
    00100
    00101 class EncodedObjectFilter : public Filter
    00102 {
    00103 public:
    00104         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};
    00105         EncodedObjectFilter(BufferedTransformation *attachment = NULL, unsigned int nObjects = 1, word32 flags = 0);
    00106
    00107         void Put(const byte *inString, unsigned int length);
    00108
    00109         unsigned int GetNumberOfCompletedObjects() const {return m_nCurrentObject;}
    00110         unsigned long GetPositionOfObject(unsigned int i) const {return m_positions[i];}
    00111
    00112 private:
    00113         BufferedTransformation & CurrentTarget();
    00114
    00115         word32 m_flags;
    00116         unsigned int m_nObjects, m_nCurrentObject, m_level;
    00117         std::vector<unsigned int> m_positions;
    00118         ByteQueue m_queue;
    00119         enum State {IDENTIFIER, LENGTH, BODY, TAIL, ALL_DONE} m_state;
    00120         byte m_id;
    00121         unsigned int m_lengthRemaining;
    00122 };
    00123
    00124 //! BER General Decoder
    00125 class CRYPTOPP_DLL BERGeneralDecoder : public Store
    00126 {
    00127 public:
    00128         explicit BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag);
    00129         explicit BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag);
    00130         ~BERGeneralDecoder();
    00131
    00132         bool IsDefiniteLength() const {return m_definiteLength;}
    00133         unsigned int RemainingLength() const {assert(m_definiteLength); return m_length;}
    00134         bool EndReached() const;
    00135         byte PeekByte() const;
    00136         void CheckByte(byte b);
    00137
    00138         unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true);
    00139         unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const;
    00140
    00141         // call this to denote end of sequence
    00142         void MessageEnd();
    00143
    00144 protected:
    00145         BufferedTransformation &m_inQueue;
    00146         bool m_finished, m_definiteLength;
    00147         unsigned int m_length;
    00148
    00149 private:
    00150         void StoreInitialize(const NameValuePairs &parameters) {assert(false);}
    00151         unsigned int ReduceLength(unsigned int delta);
    00152 };
    00153
    00154 //! DER General Encoder
    00155 class CRYPTOPP_DLL DERGeneralEncoder : public ByteQueue
    00156 {
    00157 public:
    00158         explicit DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED);
    00159         explicit DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED);
    00160         ~DERGeneralEncoder();
    00161
    00162         // call this to denote end of sequence
    00163         void MessageEnd();
    00164
    00165 private:
    00166         BufferedTransformation &m_outQueue;
    00167         bool m_finished;
    00168
    00169         byte m_asnTag;
    00170 };
    00171
    00172 //! BER Sequence Decoder
    00173 class CRYPTOPP_DLL BERSequenceDecoder : public BERGeneralDecoder
    00174 {
    00175 public:
    00176         explicit BERSequenceDecoder(BufferedTransformation &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
    00177                 : BERGeneralDecoder(inQueue, asnTag) {}
    00178         explicit BERSequenceDecoder(BERSequenceDecoder &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
    00179                 : BERGeneralDecoder(inQueue, asnTag) {}
    00180 };
    00181
    00182 //! DER Sequence Encoder
    00183 class CRYPTOPP_DLL DERSequenceEncoder : public DERGeneralEncoder
    00184 {
    00185 public:
    00186         explicit DERSequenceEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
    00187                 : DERGeneralEncoder(outQueue, asnTag) {}
    00188         explicit DERSequenceEncoder(DERSequenceEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
    00189                 : DERGeneralEncoder(outQueue, asnTag) {}
    00190 };
    00191
    00192 //! BER Set Decoder
    00193 class CRYPTOPP_DLL BERSetDecoder : public BERGeneralDecoder
    00194 {
    00195 public:
    00196         explicit BERSetDecoder(BufferedTransformation &inQueue, byte asnTag = SET | CONSTRUCTED)
    00197                 : BERGeneralDecoder(inQueue, asnTag) {}
    00198         explicit BERSetDecoder(BERSetDecoder &inQueue, byte asnTag = SET | CONSTRUCTED)
    00199                 : BERGeneralDecoder(inQueue, asnTag) {}
    00200 };
    00201
    00202 //! DER Set Encoder
    00203 class CRYPTOPP_DLL DERSetEncoder : public DERGeneralEncoder
    00204 {
    00205 public:
    00206         explicit DERSetEncoder(BufferedTransformation &outQueue, byte asnTag = SET | CONSTRUCTED)
    00207                 : DERGeneralEncoder(outQueue, asnTag) {}
    00208         explicit DERSetEncoder(DERSetEncoder &outQueue, byte asnTag = SET | CONSTRUCTED)
    00209                 : DERGeneralEncoder(outQueue, asnTag) {}
    00210 };
    00211
    00212 template <class T>
    00213 class ASNOptional : public member_ptr<T>
    00214 {
    00215 public:
    00216         void BERDecode(BERSequenceDecoder &seqDecoder, byte tag, byte mask = ~CONSTRUCTED)
    00217         {
    00218                 byte b;
    00219                 if (seqDecoder.Peek(b) && (b & mask) == tag)
    00220                         reset(new T(seqDecoder));
    00221         }
    00222         void DEREncode(BufferedTransformation &out)
    00223         {
    00224                 if (get() != NULL)
    00225                         get()->DEREncode(out);
    00226         }
    00227 };
    00228
    00229 //! .
    00230 class CRYPTOPP_DLL ASN1Key : public ASN1CryptoMaterial
    00231 {
    00232 public:
    00233         virtual OID GetAlgorithmID() const =0;
    00234         virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
    00235                 {BERDecodeNull(bt); return false;}
    00236         virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
    00237                 {DEREncodeNull(bt); return false;}      // see RFC 2459, section 7.3.1
    00238         // one of the following two should be overriden
    00239         virtual void BERDecodeKey(BufferedTransformation &bt) {assert(false);}
    00240         virtual void BERDecodeKey2(BufferedTransformation &bt, bool parametersPresent, unsigned int size)
    00241                 {BERDecodeKey(bt);}
    00242         virtual void DEREncodeKey(BufferedTransformation &bt) const =0;
    00243 };
    00244
    00245 //! .
    00246 class CRYPTOPP_DLL X509PublicKey : virtual public ASN1Key, public PublicKey
    00247 {
    00248 public:
    00249         void BERDecode(BufferedTransformation &bt);
    00250         void DEREncode(BufferedTransformation &bt) const;
    00251 };
    00252
    00253 //! .
    00254 class CRYPTOPP_DLL PKCS8PrivateKey : virtual public ASN1Key, public PrivateKey
    00255 {
    00256 public:
    00257         void BERDecode(BufferedTransformation &bt);
    00258         void DEREncode(BufferedTransformation &bt) const;
    00259
    00260         virtual void BERDecodeOptionalAttributes(BufferedTransformation &bt)
    00261                 {}      // TODO: skip optional attributes if present
    00262         virtual void DEREncodeOptionalAttributes(BufferedTransformation &bt) const
    00263                 {}
    00264 };
    00265
    00266 // ********************************************************
    00267
    00268 //! DER Encode Unsigned
    00269 /*! for INTEGER, BOOLEAN, and ENUM */
    00270 template <class T>
    00271 unsigned int DEREncodeUnsigned(BufferedTransformation &out, T w, byte asnTag = INTEGER)
    00272 {
    00273         byte buf[sizeof(w)+1];
    00274         unsigned int bc;
    00275         if (asnTag == BOOLEAN)
    00276         {
    00277                 buf[sizeof(w)] = w ? 0xff : 0;
    00278                 bc = 1;
    00279         }
    00280         else
    00281         {
    00282                 buf[0] = 0;
    00283                 for (unsigned int i=0; i<sizeof(w); i++)
    00284                         buf[i+1] = byte(w >> (sizeof(w)-1-i)*8);
    00285                 bc = sizeof(w);
    00286                 while (bc > 1 && buf[sizeof(w)+1-bc] == 0)
    00287                         --bc;
    00288                 if (buf[sizeof(w)+1-bc] & 0x80)
    00289                         ++bc;
    00290         }
    00291         out.Put(asnTag);
    00292         unsigned int lengthBytes = DERLengthEncode(out, bc);
    00293         out.Put(buf+sizeof(w)+1-bc, bc);
    00294         return 1+lengthBytes+bc;
    00295 }
    00296
    00297 //! BER Decode Unsigned
    00298 // VC60 workaround: std::numeric_limits<T>::max conflicts with MFC max macro
    00299 // CW41 workaround: std::numeric_limits<T>::max causes a template error
    00300 template <class T>
    00301 void BERDecodeUnsigned(BufferedTransformation &in, T &w, byte asnTag = INTEGER,
    00302                                            T minValue = 0, T maxValue = 0xffffffff)
    00303 {
    00304         byte b;
    00305         if (!in.Get(b) || b != asnTag)
    00306                 BERDecodeError();
    00307
    00308         unsigned int bc;
    00309         BERLengthDecode(in, bc);
    00310
    00311         SecByteBlock buf(bc);
    00312
    00313         if (bc != in.Get(buf, bc))
    00314                 BERDecodeError();
    00315
    00316         const byte *ptr = buf;
    00317         while (bc > sizeof(w) && *ptr == 0)
    00318         {
    00319                 bc--;
    00320                 ptr++;
    00321         }
    00322         if (bc > sizeof(w))
    00323                 BERDecodeError();
    00324
    00325         w = 0;
    00326         for (unsigned int i=0; i<bc; i++)
    00327                 w = (w << 8) | ptr[i];
    00328
    00329         if (w < minValue || w > maxValue)
    00330                 BERDecodeError();
    00331 }
    00332
    00333 inline bool operator==(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
    00334         {return lhs.m_values == rhs.m_values;}
    00335 inline bool operator!=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
    00336         {return lhs.m_values != rhs.m_values;}
    00337 inline bool operator<(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
    00338         {return std::lexicographical_compare(lhs.m_values.begin(), lhs.m_values.end(), rhs.m_values.begin(), rhs.m_values.end());}
    00339 inline ::CryptoPP::OID operator+(const ::CryptoPP::OID &lhs, unsigned long rhs)
    00340         {return ::CryptoPP::OID(lhs)+=rhs;}
    00341
    00342 NAMESPACE_END
    00343
    00344 #endif