Crypto++  5.6.3
Free C++ class library of cryptographic schemes
asn.h
Go to the documentation of this file.
1 // asn.h - written and placed in the public domain by Wei Dai
2 
3 //! \file
4 //! \headerfile asn.h
5 //! \brief Classes and functions for working with ANS.1 objects
6 
7 #ifndef CRYPTOPP_ASN_H
8 #define CRYPTOPP_ASN_H
9 
10 #include "cryptlib.h"
11 #include "filters.h"
12 #include "smartptr.h"
13 #include "stdcpp.h"
14 #include "queue.h"
15 #include "misc.h"
16 
17 NAMESPACE_BEGIN(CryptoPP)
18 
19 // these tags and flags are not complete
20 enum ASNTag
21 {
22  BOOLEAN = 0x01,
23  INTEGER = 0x02,
24  BIT_STRING = 0x03,
25  OCTET_STRING = 0x04,
26  TAG_NULL = 0x05,
27  OBJECT_IDENTIFIER = 0x06,
28  OBJECT_DESCRIPTOR = 0x07,
29  EXTERNAL = 0x08,
30  REAL = 0x09,
31  ENUMERATED = 0x0a,
32  UTF8_STRING = 0x0c,
33  SEQUENCE = 0x10,
34  SET = 0x11,
35  NUMERIC_STRING = 0x12,
36  PRINTABLE_STRING = 0x13,
37  T61_STRING = 0x14,
38  VIDEOTEXT_STRING = 0x15,
39  IA5_STRING = 0x16,
40  UTC_TIME = 0x17,
41  GENERALIZED_TIME = 0x18,
42  GRAPHIC_STRING = 0x19,
43  VISIBLE_STRING = 0x1a,
44  GENERAL_STRING = 0x1b
45 };
46 
47 enum ASNIdFlag
48 {
49  UNIVERSAL = 0x00,
50 // DATA = 0x01,
51 // HEADER = 0x02,
52  CONSTRUCTED = 0x20,
53  APPLICATION = 0x40,
54  CONTEXT_SPECIFIC = 0x80,
55  PRIVATE = 0xc0
56 };
57 
58 inline void BERDecodeError() {throw BERDecodeErr();}
59 
60 class CRYPTOPP_DLL UnknownOID : public BERDecodeErr
61 {
62 public:
63  UnknownOID() : BERDecodeErr("BER decode error: unknown object identifier") {}
64  UnknownOID(const char *err) : BERDecodeErr(err) {}
65 };
66 
67 // unsigned int DERLengthEncode(unsigned int length, byte *output=0);
68 CRYPTOPP_DLL size_t CRYPTOPP_API DERLengthEncode(BufferedTransformation &out, lword length);
69 // returns false if indefinite length
70 CRYPTOPP_DLL bool CRYPTOPP_API BERLengthDecode(BufferedTransformation &in, size_t &length);
71 
72 CRYPTOPP_DLL void CRYPTOPP_API DEREncodeNull(BufferedTransformation &out);
73 CRYPTOPP_DLL void CRYPTOPP_API BERDecodeNull(BufferedTransformation &in);
74 
75 CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &out, const byte *str, size_t strLen);
76 CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &out, const SecByteBlock &str);
77 CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &in, SecByteBlock &str);
78 CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &in, BufferedTransformation &str);
79 
80 // for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
81 CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeTextString(BufferedTransformation &out, const std::string &str, byte asnTag);
82 CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeTextString(BufferedTransformation &in, std::string &str, byte asnTag);
83 
84 CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeBitString(BufferedTransformation &out, const byte *str, size_t strLen, unsigned int unusedBits=0);
85 CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeBitString(BufferedTransformation &in, SecByteBlock &str, unsigned int &unusedBits);
86 
87 // BER decode from source and DER reencode into dest
88 CRYPTOPP_DLL void CRYPTOPP_API DERReencode(BufferedTransformation &source, BufferedTransformation &dest);
89 
90 //! Object Identifier
91 class CRYPTOPP_DLL OID
92 {
93 public:
94  OID() {}
95  OID(word32 v) : m_values(1, v) {}
96  OID(BufferedTransformation &bt) {BERDecode(bt);}
97 
98  inline OID & operator+=(word32 rhs) {m_values.push_back(rhs); return *this;}
99 
100  void DEREncode(BufferedTransformation &bt) const;
101  void BERDecode(BufferedTransformation &bt);
102 
103  // throw BERDecodeErr() if decoded value doesn't equal this OID
104  void BERDecodeAndCheck(BufferedTransformation &bt) const;
105 
106  std::vector<word32> m_values;
107 
108 private:
109  static void EncodeValue(BufferedTransformation &bt, word32 v);
110  static size_t DecodeValue(BufferedTransformation &bt, word32 &v);
111 };
112 
114 {
115 public:
116  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};
117  EncodedObjectFilter(BufferedTransformation *attachment = NULL, unsigned int nObjects = 1, word32 flags = 0);
118 
119  void Put(const byte *inString, size_t length);
120 
121  unsigned int GetNumberOfCompletedObjects() const {return m_nCurrentObject;}
122  unsigned long GetPositionOfObject(unsigned int i) const {return m_positions[i];}
123 
124 private:
125  BufferedTransformation & CurrentTarget();
126 
127  word32 m_flags;
128  unsigned int m_nObjects, m_nCurrentObject, m_level;
129  std::vector<unsigned int> m_positions;
130  ByteQueue m_queue;
131  enum State {IDENTIFIER, LENGTH, BODY, TAIL, ALL_DONE} m_state;
132  byte m_id;
133  lword m_lengthRemaining;
134 };
135 
136 //! BER General Decoder
137 class CRYPTOPP_DLL BERGeneralDecoder : public Store
138 {
139 public:
140  explicit BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag);
141  explicit BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag);
143 
144  bool IsDefiniteLength() const {return m_definiteLength;}
145  lword RemainingLength() const {assert(m_definiteLength); return m_length;}
146  bool EndReached() const;
147  byte PeekByte() const;
148  void CheckByte(byte b);
149 
150  size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
151  size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
152 
153  // call this to denote end of sequence
154  void MessageEnd();
155 
156 protected:
157  BufferedTransformation &m_inQueue;
158  bool m_finished, m_definiteLength;
159  lword m_length;
160 
161 private:
162  void Init(byte asnTag);
163  void StoreInitialize(const NameValuePairs &parameters)
164  {CRYPTOPP_UNUSED(parameters); assert(false);}
165  lword ReduceLength(lword delta);
166 };
167 
168 // GCC (and likely other compilers) identify the explicit DERGeneralEncoder as a copy constructor;
169 // and not a constructor. We had to remove the default asnTag value to point the compiler in the
170 // proper direction. We did not break the library or versioning based on the output of
171 // `nm --demangle libcryptopp.a | grep DERGeneralEncoder::DERGeneralEncoder | grep -v " U "`.
172 
173 //! DER General Encoder
174 class CRYPTOPP_DLL DERGeneralEncoder : public ByteQueue
175 {
176 public:
177 #if defined(CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562)
178  explicit DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED);
179  explicit DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED);
180 #else
181  explicit DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag /*= SEQUENCE | CONSTRUCTED*/);
182  explicit DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag /*= SEQUENCE | CONSTRUCTED*/);
183 #endif
185 
186  // call this to denote end of sequence
187  void MessageEnd();
188 
189 private:
190  BufferedTransformation &m_outQueue;
191  bool m_finished;
192 
193  byte m_asnTag;
194 };
195 
196 //! BER Sequence Decoder
197 class CRYPTOPP_DLL BERSequenceDecoder : public BERGeneralDecoder
198 {
199 public:
200  explicit BERSequenceDecoder(BufferedTransformation &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
201  : BERGeneralDecoder(inQueue, asnTag) {}
202  explicit BERSequenceDecoder(BERSequenceDecoder &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
203  : BERGeneralDecoder(inQueue, asnTag) {}
204 };
205 
206 //! DER Sequence Encoder
207 class CRYPTOPP_DLL DERSequenceEncoder : public DERGeneralEncoder
208 {
209 public:
210  explicit DERSequenceEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
211  : DERGeneralEncoder(outQueue, asnTag) {}
212  explicit DERSequenceEncoder(DERSequenceEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
213  : DERGeneralEncoder(outQueue, asnTag) {}
214 };
215 
216 //! BER Set Decoder
217 class CRYPTOPP_DLL BERSetDecoder : public BERGeneralDecoder
218 {
219 public:
220  explicit BERSetDecoder(BufferedTransformation &inQueue, byte asnTag = SET | CONSTRUCTED)
221  : BERGeneralDecoder(inQueue, asnTag) {}
222  explicit BERSetDecoder(BERSetDecoder &inQueue, byte asnTag = SET | CONSTRUCTED)
223  : BERGeneralDecoder(inQueue, asnTag) {}
224 };
225 
226 //! DER Set Encoder
227 class CRYPTOPP_DLL DERSetEncoder : public DERGeneralEncoder
228 {
229 public:
230  explicit DERSetEncoder(BufferedTransformation &outQueue, byte asnTag = SET | CONSTRUCTED)
231  : DERGeneralEncoder(outQueue, asnTag) {}
232  explicit DERSetEncoder(DERSetEncoder &outQueue, byte asnTag = SET | CONSTRUCTED)
233  : DERGeneralEncoder(outQueue, asnTag) {}
234 };
235 
236 template <class T>
237 class ASNOptional : public member_ptr<T>
238 {
239 public:
240  void BERDecode(BERSequenceDecoder &seqDecoder, byte tag, byte mask = ~CONSTRUCTED)
241  {
242  byte b;
243  if (seqDecoder.Peek(b) && (b & mask) == tag)
244  reset(new T(seqDecoder));
245  }
246  void DEREncode(BufferedTransformation &out)
247  {
248  if (this->get() != NULL)
249  this->get()->DEREncode(out);
250  }
251 };
252 
253 //! _
254 template <class BASE>
255 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ASN1CryptoMaterial : public ASN1Object, public BASE
256 {
257 public:
258  void Save(BufferedTransformation &bt) const
259  {BEREncode(bt);}
260  void Load(BufferedTransformation &bt)
261  {BERDecode(bt);}
262 };
263 
264 //! encodes/decodes subjectPublicKeyInfo
265 class CRYPTOPP_DLL X509PublicKey : public ASN1CryptoMaterial<PublicKey>
266 {
267 public:
269  void DEREncode(BufferedTransformation &bt) const;
270 
271  virtual OID GetAlgorithmID() const =0;
272  virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
273  {BERDecodeNull(bt); return false;}
274  virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
275  {DEREncodeNull(bt); return false;} // see RFC 2459, section 7.3.1
276 
277  //! decode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header
278  virtual void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0;
279  //! encode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header
280  virtual void DEREncodePublicKey(BufferedTransformation &bt) const =0;
281 };
282 
283 //! encodes/decodes privateKeyInfo
284 class CRYPTOPP_DLL PKCS8PrivateKey : public ASN1CryptoMaterial<PrivateKey>
285 {
286 public:
288  void DEREncode(BufferedTransformation &bt) const;
289 
290  virtual OID GetAlgorithmID() const =0;
291  virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
292  {BERDecodeNull(bt); return false;}
293  virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
294  {DEREncodeNull(bt); return false;} // see RFC 2459, section 7.3.1
295 
296  //! decode privateKey part of privateKeyInfo, without the OCTET STRING header
297  virtual void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0;
298  //! encode privateKey part of privateKeyInfo, without the OCTET STRING header
299  virtual void DEREncodePrivateKey(BufferedTransformation &bt) const =0;
300 
301  //! decode optional attributes including context-specific tag
302  /*! /note default implementation stores attributes to be output in DEREncodeOptionalAttributes */
303  virtual void BERDecodeOptionalAttributes(BufferedTransformation &bt);
304  //! encode optional attributes including context-specific tag
305  virtual void DEREncodeOptionalAttributes(BufferedTransformation &bt) const;
306 
307 protected:
308  ByteQueue m_optionalAttributes;
309 };
310 
311 // ********************************************************
312 
313 //! DER Encode Unsigned
314 /*! for INTEGER, BOOLEAN, and ENUM */
315 template <class T>
316 size_t DEREncodeUnsigned(BufferedTransformation &out, T w, byte asnTag = INTEGER)
317 {
318  byte buf[sizeof(w)+1];
319  unsigned int bc;
320  if (asnTag == BOOLEAN)
321  {
322  buf[sizeof(w)] = w ? 0xff : 0;
323  bc = 1;
324  }
325  else
326  {
327  buf[0] = 0;
328  for (unsigned int i=0; i<sizeof(w); i++)
329  buf[i+1] = byte(w >> (sizeof(w)-1-i)*8);
330  bc = sizeof(w);
331  while (bc > 1 && buf[sizeof(w)+1-bc] == 0)
332  --bc;
333  if (buf[sizeof(w)+1-bc] & 0x80)
334  ++bc;
335  }
336  out.Put(asnTag);
337  size_t lengthBytes = DERLengthEncode(out, bc);
338  out.Put(buf+sizeof(w)+1-bc, bc);
339  return 1+lengthBytes+bc;
340 }
341 
342 //! BER Decode Unsigned
343 template <class T>
344 void BERDecodeUnsigned(BufferedTransformation &in, T &w, byte asnTag = INTEGER,
345  T minValue = 0, T maxValue = ((std::numeric_limits<T>::max)()))
346 {
347  byte b;
348  if (!in.Get(b) || b != asnTag)
349  BERDecodeError();
350 
351  size_t bc;
352  bool definite = BERLengthDecode(in, bc);
353  if (!definite)
354  BERDecodeError();
355 
356  SecByteBlock buf(bc);
357 
358  if (bc != in.Get(buf, bc))
359  BERDecodeError();
360 
361  const byte *ptr = buf;
362  while (bc > sizeof(w) && *ptr == 0)
363  {
364  bc--;
365  ptr++;
366  }
367  if (bc > sizeof(w))
368  BERDecodeError();
369 
370  w = 0;
371  for (unsigned int i=0; i<bc; i++)
372  w = (w << 8) | ptr[i];
373 
374  if (w < minValue || w > maxValue)
375  BERDecodeError();
376 }
377 
378 inline bool operator==(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
379  {return lhs.m_values == rhs.m_values;}
380 inline bool operator!=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
381  {return lhs.m_values != rhs.m_values;}
382 inline bool operator<(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
383  {return std::lexicographical_compare(lhs.m_values.begin(), lhs.m_values.end(), rhs.m_values.begin(), rhs.m_values.end());}
384 inline ::CryptoPP::OID operator+(const ::CryptoPP::OID &lhs, unsigned long rhs)
385  {return ::CryptoPP::OID(lhs)+=rhs;}
386 
387 NAMESPACE_END
388 
389 #endif
Utility functions for the Crypto++ library.
virtual size_t Peek(byte &outByte) const
Peek a 8-bit byte.
Definition: cryptlib.cpp:537
size_t DEREncodeUnsigned(BufferedTransformation &out, T w, byte asnTag=INTEGER)
DER Encode Unsigned.
Definition: asn.h:316
encodes/decodes privateKeyInfo
Definition: asn.h:284
Abstract base classes that provide a uniform interface to this library.
size_t DERLengthEncode(BufferedTransformation &out, lword length)
DER Length.
Definition: asn.cpp:17
Classes for automatic resource management.
virtual size_t TransferTo2(BufferedTransformation &target, lword &byteCount, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true)=0
Transfer bytes from this object to another BufferedTransformation.
Acts as a Source for pre-existing, static data.
Definition: simple.h:228
BER Set Decoder.
Definition: asn.h:217
SecBlock typedef.
Definition: secblock.h:723
BER Sequence Decoder.
Definition: asn.h:197
Interface for buffered transformations.
Definition: cryptlib.h:1342
Pointer that overloads operator→
Definition: smartptr.h:39
bool MessageEnd(int propagation=-1, bool blocking=true)
Signals the end of messages to the object.
Definition: cryptlib.h:1421
Classes for an unlimited queue to store bytes.
size_t Put(byte inByte, bool blocking=true)
Input a byte for processing.
Definition: cryptlib.h:1363
const std::string DEFAULT_CHANNEL
Default channel for BufferedTransformation.
Definition: cryptlib.cpp:41
virtual void BERDecode(BufferedTransformation &bt)=0
Decode this object from a BufferedTransformation.
size_t DEREncodeBitString(BufferedTransformation &out, const byte *str, size_t strLen, unsigned int unusedBits=0)
ASN BitString.
Definition: asn.cpp:173
Interface for encoding and decoding ASN1 objects.
Definition: cryptlib.h:2952
DER Set Encoder.
Definition: asn.h:227
bool operator<(const ::PolynomialMod2 &a, const ::PolynomialMod2 &b)
compares degree
Definition: gf2n.h:253
void BERDecodeUnsigned(BufferedTransformation &in, T &w, byte asnTag=INTEGER, T minValue=0, T maxValue=((std::numeric_limits< T >::max)()))
BER Decode Unsigned.
Definition: asn.h:344
Data structure used to store byte strings.
Definition: queue.h:20
Implementation of BufferedTransformation's attachment interface.
virtual void BEREncode(BufferedTransformation &bt) const
Encode this object into a BufferedTransformation.
Definition: cryptlib.h:2971
size_t DEREncodeOctetString(BufferedTransformation &out, const byte *str, size_t strLen)
ASN Strings.
Definition: asn.cpp:104
DER Sequence Encoder.
Definition: asn.h:207
DER General Encoder.
Definition: asn.h:174
Definition: asn.h:60
Implementation of BufferedTransformation's attachment interface.
Definition: filters.h:36
virtual size_t Get(byte &outByte)
Retrieve a 8-bit byte.
Definition: cryptlib.cpp:518
Crypto++ library namespace.
virtual size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const =0
Copy bytes from this object to another BufferedTransformation.
encodes/decodes subjectPublicKeyInfo
Definition: asn.h:265
BER General Decoder.
Definition: asn.h:137
virtual void DEREncode(BufferedTransformation &bt) const =0
Encode this object into a BufferedTransformation.
Object Identifier.
Definition: asn.h:91
Interface for retrieving values given their names.
Definition: cryptlib.h:277
Exception thrown when an ASN.1 BER decoing error is encountered.
Definition: cryptlib.h:2941