1 // asn.h - written and placed in the public domain by Wei Dai
2 
3 //! \file asn.h
4 //! \brief Classes and functions for working with ANS.1 objects
5 
6 #ifndef CRYPTOPP_ASN_H
7 #define CRYPTOPP_ASN_H
8 
9 #include "cryptlib.h"
10 #include "filters.h"
11 #include "smartptr.h"
12 #include "stdcpp.h"
13 #include "queue.h"
14 #include "misc.h"
15 
16 // Issue 340
17 #if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
18 # pragma GCC diagnostic push
19 # pragma GCC diagnostic ignored "-Wconversion"
20 # pragma GCC diagnostic ignored "-Wsign-conversion"
21 #endif
22 
23 NAMESPACE_BEGIN(CryptoPP)
24 
25 //! \brief ASN.1 types
26 //! \note These tags and flags are not complete
27 enum ASNTag
28 {
29 	BOOLEAN 			= 0x01,
30 	INTEGER 			= 0x02,
31 	BIT_STRING			= 0x03,
32 	OCTET_STRING		= 0x04,
33 	TAG_NULL			= 0x05,
34 	OBJECT_IDENTIFIER	= 0x06,
35 	OBJECT_DESCRIPTOR	= 0x07,
36 	EXTERNAL			= 0x08,
37 	REAL				= 0x09,
38 	ENUMERATED			= 0x0a,
39 	UTF8_STRING			= 0x0c,
40 	SEQUENCE			= 0x10,
41 	SET 				= 0x11,
42 	NUMERIC_STRING		= 0x12,
43 	PRINTABLE_STRING 	= 0x13,
44 	T61_STRING			= 0x14,
45 	VIDEOTEXT_STRING 	= 0x15,
46 	IA5_STRING			= 0x16,
47 	UTC_TIME 			= 0x17,
48 	GENERALIZED_TIME 	= 0x18,
49 	GRAPHIC_STRING		= 0x19,
50 	VISIBLE_STRING		= 0x1a,
51 	GENERAL_STRING		= 0x1b
52 };
53 
54 //! \brief ASN.1 flags
55 //! \note These tags and flags are not complete
56 enum ASNIdFlag
57 {
58 	UNIVERSAL           = 0x00,
59 //	DATA                = 0x01,
60 //	HEADER              = 0x02,
61 	PRIMITIVE           = 0x00,
62 	CONSTRUCTED         = 0x20,
63 	APPLICATION         = 0x40,
64 	CONTEXT_SPECIFIC    = 0x80,
65 	PRIVATE             = 0xc0
66 };
67 
68 //! \brief Raises a BERDecodeErr
BERDecodeError()69 inline void BERDecodeError() {throw BERDecodeErr();}
70 
71 //! \brief Exception thrown when an unknown object identifier is encountered
72 class CRYPTOPP_DLL UnknownOID : public BERDecodeErr
73 {
74 public:
75 	//! \brief Construct an UnknownOID
UnknownOID()76 	UnknownOID() : BERDecodeErr("BER decode error: unknown object identifier") {}
77 	//! \brief Construct an UnknownOID
78 	//! \param err error message to use for the execption
UnknownOID(const char * err)79 	UnknownOID(const char *err) : BERDecodeErr(err) {}
80 };
81 
82 // unsigned int DERLengthEncode(unsigned int length, byte *output=0);
83 
84 //! \brief DER encode a length
85 //! \param bt BufferedTransformation object for writing
86 //! \param length the size to encode
87 //! \returns the number of octets used for the encoding
88 CRYPTOPP_DLL size_t CRYPTOPP_API DERLengthEncode(BufferedTransformation &bt, lword length);
89 
90 //! \brief BER decode a length
91 //! \param bt BufferedTransformation object for reading
92 //! \param length the decoded size
93 //! \returns true if the value was decoded
94 //! \throws BERDecodeError if the value fails to decode or is too large for size_t
95 //! \details BERLengthDecode() returns false if the encoding is indefinite length.
96 CRYPTOPP_DLL bool CRYPTOPP_API BERLengthDecode(BufferedTransformation &bt, size_t &length);
97 
98 //! \brief DER encode NULL
99 //! \param bt BufferedTransformation object for writing
100 CRYPTOPP_DLL void CRYPTOPP_API DEREncodeNull(BufferedTransformation &bt);
101 
102 //! \brief BER decode NULL
103 //! \param bt BufferedTransformation object for reading
104 CRYPTOPP_DLL void CRYPTOPP_API BERDecodeNull(BufferedTransformation &bt);
105 
106 //! \brief DER encode octet string
107 //! \param bt BufferedTransformation object for writing
108 //! \param str the string to encode
109 //! \param strLen the length of the string
110 //! \returns the number of octets used for the encoding
111 CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &bt, const byte *str, size_t strLen);
112 
113 //! \brief DER encode octet string
114 //! \param bt BufferedTransformation object for reading
115 //! \param str the string to encode
116 //! \returns the number of octets used for the encoding
117 CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &bt, const SecByteBlock &str);
118 
119 //! \brief BER decode octet string
120 //! \param bt BufferedTransformation object for reading
121 //! \param str the decoded string
122 //! \returns the number of octets used for the encoding
123 CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &bt, SecByteBlock &str);
124 
125 //! \brief BER decode octet string
126 //! \param bt BufferedTransformation object for reading
127 //! \param str the decoded string
128 //! \returns the number of octets used for the encoding
129 CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &bt, BufferedTransformation &str);
130 
131 //! \brief DER encode text string
132 //! \param bt BufferedTransformation object for writing
133 //! \param str the string to encode
134 //! \param asnTag the ASN.1 type
135 //! \returns the number of octets used for the encoding
136 //! \details DEREncodeTextString() can be used for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
137 CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeTextString(BufferedTransformation &bt, const std::string &str, byte asnTag);
138 
139 //! \brief BER decode text string
140 //! \param bt BufferedTransformation object for reading
141 //! \param str the string to encode
142 //! \param asnTag the ASN.1 type
143 //! \details DEREncodeTextString() can be used for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
144 CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeTextString(BufferedTransformation &bt, std::string &str, byte asnTag);
145 
146 //! \brief DER encode bit string
147 //! \param bt BufferedTransformation object for writing
148 //! \param str the string to encode
149 //! \param strLen the length of the string
150 //! \param unusedBits the number of unused bits
151 //! \returns the number of octets used for the encoding
152 CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeBitString(BufferedTransformation &bt, const byte *str, size_t strLen, unsigned int unusedBits=0);
153 
154 //! \brief DER decode bit string
155 //! \param bt BufferedTransformation object for reading
156 //! \param str the decoded string
157 //! \param unusedBits the number of unused bits
158 CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeBitString(BufferedTransformation &bt, SecByteBlock &str, unsigned int &unusedBits);
159 
160 //! \brief BER decode and DER re-encode
161 //! \param bt BufferedTransformation object for writing
162 //! \param dest BufferedTransformation object
163 CRYPTOPP_DLL void CRYPTOPP_API DERReencode(BufferedTransformation &bt, BufferedTransformation &dest);
164 
165 //! \brief Object Identifier
166 class CRYPTOPP_DLL OID
167 {
168 public:
~OID()169 	virtual ~OID() {}
170 
171 	//! \brief Construct an OID
OID()172 	OID() {}
173 	//! \brief Construct an OID
174 	//! \param v value to initialize the OID
OID(word32 v)175 	OID(word32 v) : m_values(1, v) {}
176 	//! \brief Construct an OID
177 	//! \param bt BufferedTransformation object
OID(BufferedTransformation & bt)178 	OID(BufferedTransformation &bt) {BERDecode(bt);}
179 
180 	//! \brief Append a value to an OID
181 	//! \param rhs the value to append
182 	inline OID & operator+=(word32 rhs) {m_values.push_back(rhs); return *this;}
183 
184 	//! \brief DER encode this OID
185 	//! \param bt BufferedTransformation object
186 	void DEREncode(BufferedTransformation &bt) const;
187 
188 	//! \brief BER decode an OID
189 	//! \param bt BufferedTransformation object
190 	void BERDecode(BufferedTransformation &bt);
191 
192 	//! \brief BER decode an OID
193 	//! \param bt BufferedTransformation object
194 	//! \throws BERDecodeErr() if decoded value doesn't match an expected OID
195 	//! \details BERDecodeAndCheck() can be used to parse an OID and verify it matches an expected.
196 	//! <pre>
197 	//!   BERSequenceDecoder key(bt);
198 	//!   ...
199 	//!   BERSequenceDecoder algorithm(key);
200 	//!   GetAlgorithmID().BERDecodeAndCheck(algorithm);
201 	//! </pre>
202 	void BERDecodeAndCheck(BufferedTransformation &bt) const;
203 
204 	std::vector<word32> m_values;
205 
206 private:
207 	static void EncodeValue(BufferedTransformation &bt, word32 v);
208 	static size_t DecodeValue(BufferedTransformation &bt, word32 &v);
209 };
210 
211 //! \brief ASN.1 encoded object filter
212 class EncodedObjectFilter : public Filter
213 {
214 public:
215 	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};
216 
~EncodedObjectFilter()217 	virtual ~EncodedObjectFilter() {}
218 
219 	//! \brief Construct an EncodedObjectFilter
220 	//! \param attachment a BufferedTrasformation to attach to this object
221 	//! \param nObjects
222 	//! \param flags bitwise OR of EncodedObjectFilter::Flag
223 	EncodedObjectFilter(BufferedTransformation *attachment = NULL, unsigned int nObjects = 1, word32 flags = 0);
224 
225 	//! \brief Input a byte buffer for processing
226 	//! \param inString the byte buffer to process
227 	//! \param length the size of the string, in bytes
228 	void Put(const byte *inString, size_t length);
229 
GetNumberOfCompletedObjects()230 	unsigned int GetNumberOfCompletedObjects() const {return m_nCurrentObject;}
GetPositionOfObject(unsigned int i)231 	unsigned long GetPositionOfObject(unsigned int i) const {return m_positions[i];}
232 
233 private:
234 	BufferedTransformation & CurrentTarget();
235 
236 	word32 m_flags;
237 	unsigned int m_nObjects, m_nCurrentObject, m_level;
238 	std::vector<unsigned int> m_positions;
239 	ByteQueue m_queue;
240 	enum State {IDENTIFIER, LENGTH, BODY, TAIL, ALL_DONE} m_state;
241 	byte m_id;
242 	lword m_lengthRemaining;
243 };
244 
245 //! \brief BER General Decoder
246 class CRYPTOPP_DLL BERGeneralDecoder : public Store
247 {
248 public:
249 	virtual ~BERGeneralDecoder();
250 
251 	explicit BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag);
252 	explicit BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag);
253 
IsDefiniteLength()254 	bool IsDefiniteLength() const {return m_definiteLength;}
RemainingLength()255 	lword RemainingLength() const {CRYPTOPP_ASSERT(m_definiteLength); return m_length;}
256 	bool EndReached() const;
257 	byte PeekByte() const;
258 	void CheckByte(byte b);
259 
260 	size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
261 	size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
262 
263 	// call this to denote end of sequence
264 	void MessageEnd();
265 
266 protected:
267 	BufferedTransformation &m_inQueue;
268 	bool m_finished, m_definiteLength;
269 	lword m_length;
270 
271 private:
272 	void Init(byte asnTag);
StoreInitialize(const NameValuePairs & parameters)273 	void StoreInitialize(const NameValuePairs &parameters)
274 		{CRYPTOPP_UNUSED(parameters); CRYPTOPP_ASSERT(false);}
275 	lword ReduceLength(lword delta);
276 };
277 
278 // GCC (and likely other compilers) identify the explicit DERGeneralEncoder as a copy constructor;
279 // and not a constructor. We had to remove the default asnTag value to point the compiler in the
280 // proper direction. We did not break the library or versioning based on the output of
281 // `nm --demangle libcryptopp.a | grep DERGeneralEncoder::DERGeneralEncoder | grep -v " U "`.
282 
283 //! \brief DER General Encoder
284 class CRYPTOPP_DLL DERGeneralEncoder : public ByteQueue
285 {
286 public:
287 	virtual ~DERGeneralEncoder();
288 
289 	explicit DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED);
290 	explicit DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED);
291 
292 	// call this to denote end of sequence
293 	void MessageEnd();
294 
295 private:
296 	BufferedTransformation &m_outQueue;
297 	bool m_finished;
298 
299 	byte m_asnTag;
300 };
301 
302 //! \brief BER Sequence Decoder
303 class CRYPTOPP_DLL BERSequenceDecoder : public BERGeneralDecoder
304 {
305 public:
306 	explicit BERSequenceDecoder(BufferedTransformation &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
BERGeneralDecoder(inQueue,asnTag)307 		: BERGeneralDecoder(inQueue, asnTag) {}
308 	explicit BERSequenceDecoder(BERSequenceDecoder &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
BERGeneralDecoder(inQueue,asnTag)309 		: BERGeneralDecoder(inQueue, asnTag) {}
310 };
311 
312 //! \brief DER Sequence Encoder
313 class CRYPTOPP_DLL DERSequenceEncoder : public DERGeneralEncoder
314 {
315 public:
316 	explicit DERSequenceEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
DERGeneralEncoder(outQueue,asnTag)317 		: DERGeneralEncoder(outQueue, asnTag) {}
318 	explicit DERSequenceEncoder(DERSequenceEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
DERGeneralEncoder(outQueue,asnTag)319 		: DERGeneralEncoder(outQueue, asnTag) {}
320 };
321 
322 //! \brief BER Set Decoder
323 class CRYPTOPP_DLL BERSetDecoder : public BERGeneralDecoder
324 {
325 public:
326 	explicit BERSetDecoder(BufferedTransformation &inQueue, byte asnTag = SET | CONSTRUCTED)
BERGeneralDecoder(inQueue,asnTag)327 		: BERGeneralDecoder(inQueue, asnTag) {}
328 	explicit BERSetDecoder(BERSetDecoder &inQueue, byte asnTag = SET | CONSTRUCTED)
BERGeneralDecoder(inQueue,asnTag)329 		: BERGeneralDecoder(inQueue, asnTag) {}
330 };
331 
332 //! \brief DER Set Encoder
333 class CRYPTOPP_DLL DERSetEncoder : public DERGeneralEncoder
334 {
335 public:
336 	explicit DERSetEncoder(BufferedTransformation &outQueue, byte asnTag = SET | CONSTRUCTED)
DERGeneralEncoder(outQueue,asnTag)337 		: DERGeneralEncoder(outQueue, asnTag) {}
338 	explicit DERSetEncoder(DERSetEncoder &outQueue, byte asnTag = SET | CONSTRUCTED)
DERGeneralEncoder(outQueue,asnTag)339 		: DERGeneralEncoder(outQueue, asnTag) {}
340 };
341 
342 //! \brief Optional data encoder and decoder
343 //! \tparam T class or type
344 template <class T>
345 class ASNOptional : public member_ptr<T>
346 {
347 public:
348 	//! \brief BER decode optional data
349 	//! \param seqDecoder sequence with the optional ASN.1 data
350 	//! \param tag ASN.1 tag to match as optional data
351 	//! \param mask the mask to apply when matching the tag
352 	//! \sa ASNTag and ASNIdFlag
353 	void BERDecode(BERSequenceDecoder &seqDecoder, byte tag, byte mask = ~CONSTRUCTED)
354 	{
355 		byte b;
356 		if (seqDecoder.Peek(b) && (b & mask) == tag)
357 			reset(new T(seqDecoder));
358 	}
359 
360 	//! \brief DER encode optional data
361 	//! \param out BufferedTransformation object
DEREncode(BufferedTransformation & out)362 	void DEREncode(BufferedTransformation &out)
363 	{
364 		if (this->get() != NULL)
365 			this->get()->DEREncode(out);
366 	}
367 };
368 
369 //! \brief Encode and decode ASN.1 objects with additional information
370 //! \tparam BASE base class or type
371 //! \details Encodes and decodes public keys, private keys and group
372 //!   parameters with OID identifying the algorithm or scheme.
373 template <class BASE>
374 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ASN1CryptoMaterial : public ASN1Object, public BASE
375 {
376 public:
377 	//! \brief DER encode ASN.1 object
378 	//! \param bt BufferedTransformation object
379 	//! \details Save() will write the OID associated with algorithm or scheme.
380 	//!   In the case of public and private keys, this function writes the
381 	//!   subjectPubicKeyInfo and privateKeyInfo parts.
Save(BufferedTransformation & bt)382 	void Save(BufferedTransformation &bt) const
383 		{BEREncode(bt);}
384 
385 	//! \brief BER decode ASN.1 object
386 	//! \param bt BufferedTransformation object
Load(BufferedTransformation & bt)387 	void Load(BufferedTransformation &bt)
388 		{BERDecode(bt);}
389 };
390 
391 //! \brief Encodes and decodes subjectPublicKeyInfo
392 class CRYPTOPP_DLL X509PublicKey : public ASN1CryptoMaterial<PublicKey>
393 {
394 public:
~X509PublicKey()395 	virtual ~X509PublicKey() {}
396 
397 	void BERDecode(BufferedTransformation &bt);
398 	void DEREncode(BufferedTransformation &bt) const;
399 
400 	//! \brief Retrieves the OID of the algorithm
401 	//! \returns OID of the algorithm
402 	virtual OID GetAlgorithmID() const =0;
BERDecodeAlgorithmParameters(BufferedTransformation & bt)403 	virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
404 		{BERDecodeNull(bt); return false;}
DEREncodeAlgorithmParameters(BufferedTransformation & bt)405 	virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
406 		{DEREncodeNull(bt); return false;}	// see RFC 2459, section 7.3.1
407 
408 	//! decode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header
409 	virtual void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0;
410 	//! encode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header
411 	virtual void DEREncodePublicKey(BufferedTransformation &bt) const =0;
412 };
413 
414 //! \brief Encodes and decodesprivateKeyInfo
415 class CRYPTOPP_DLL PKCS8PrivateKey : public ASN1CryptoMaterial<PrivateKey>
416 {
417 public:
~PKCS8PrivateKey()418 	virtual ~PKCS8PrivateKey() {}
419 
420 	void BERDecode(BufferedTransformation &bt);
421 	void DEREncode(BufferedTransformation &bt) const;
422 
423 	//! \brief Retrieves the OID of the algorithm
424 	//! \returns OID of the algorithm
425 	virtual OID GetAlgorithmID() const =0;
BERDecodeAlgorithmParameters(BufferedTransformation & bt)426 	virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
427 		{BERDecodeNull(bt); return false;}
DEREncodeAlgorithmParameters(BufferedTransformation & bt)428 	virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
429 		{DEREncodeNull(bt); return false;}	// see RFC 2459, section 7.3.1
430 
431 	//! decode privateKey part of privateKeyInfo, without the OCTET STRING header
432 	virtual void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0;
433 	//! encode privateKey part of privateKeyInfo, without the OCTET STRING header
434 	virtual void DEREncodePrivateKey(BufferedTransformation &bt) const =0;
435 
436 	//! decode optional attributes including context-specific tag
437 	/*! /note default implementation stores attributes to be output in DEREncodeOptionalAttributes */
438 	virtual void BERDecodeOptionalAttributes(BufferedTransformation &bt);
439 	//! encode optional attributes including context-specific tag
440 	virtual void DEREncodeOptionalAttributes(BufferedTransformation &bt) const;
441 
442 protected:
443 	ByteQueue m_optionalAttributes;
444 };
445 
446 // ********************************************************
447 
448 //! \brief DER Encode unsigned value
449 //! \tparam T class or type
450 //! \param out BufferedTransformation object
451 //! \param w unsigned value to encode
452 //! \param asnTag the ASN.1 type
453 //! \details DEREncodeUnsigned() can be used with INTEGER, BOOLEAN, and ENUM
454 template <class T>
455 size_t DEREncodeUnsigned(BufferedTransformation &out, T w, byte asnTag = INTEGER)
456 {
457 	byte buf[sizeof(w)+1];
458 	unsigned int bc;
459 	if (asnTag == BOOLEAN)
460 	{
461 		buf[sizeof(w)] = w ? 0xff : 0;
462 		bc = 1;
463 	}
464 	else
465 	{
466 		buf[0] = 0;
467 		for (unsigned int i=0; i<sizeof(w); i++)
468 			buf[i+1] = byte(w >> (sizeof(w)-1-i)*8);
469 		bc = sizeof(w);
470 		while (bc > 1 && buf[sizeof(w)+1-bc] == 0)
471 			--bc;
472 		if (buf[sizeof(w)+1-bc] & 0x80)
473 			++bc;
474 	}
475 	out.Put(asnTag);
476 	size_t lengthBytes = DERLengthEncode(out, bc);
477 	out.Put(buf+sizeof(w)+1-bc, bc);
478 	return 1+lengthBytes+bc;
479 }
480 
481 //! \brief BER Decode unsigned value
482 //! \tparam T fundamental C++ type
483 //! \param in BufferedTransformation object
484 //! \param w the decoded value
485 //! \param asnTag the ASN.1 type
486 //! \param minValue the minimum expected value
487 //! \param maxValue the maximum expected value
488 //! \throws BERDecodeErr() if the value cannot be parsed or the decoded value is not within range.
489 //! \details DEREncodeUnsigned() can be used with INTEGER, BOOLEAN, and ENUM
490 template <class T>
491 void BERDecodeUnsigned(BufferedTransformation &in, T &w, byte asnTag = INTEGER,
492 					   T minValue = 0, T maxValue = T(0xffffffff))
493 {
494 	byte b;
495 	if (!in.Get(b) || b != asnTag)
496 		BERDecodeError();
497 
498 	size_t bc;
499 	bool definite = BERLengthDecode(in, bc);
500 	if (!definite)
501 		BERDecodeError();
502 	if (bc > in.MaxRetrievable())  // Issue 346
503 		BERDecodeError();
504 	if (asnTag == BOOLEAN && bc != 1) // X.690, 8.2.1
505 		BERDecodeError();
506 	if ((asnTag == INTEGER || asnTag == ENUMERATED) && bc == 0) // X.690, 8.3.1 and 8.4
507 		BERDecodeError();
508 
509 	SecByteBlock buf(bc);
510 
511 	if (bc != in.Get(buf, bc))
512 		BERDecodeError();
513 
514 	// This consumes leading 0 octets. According to X.690, 8.3.2, it could be non-conforming behavior.
515 	//  X.690, 8.3.2 says "the bits of the first octet and bit 8 of the second octet ... (a) shall
516 	//  not all be ones and (b) shall not all be zeros ... These rules ensure that an integer value
517 	//  is always encoded in the smallest possible number of octet".
518 	// We invented AER (Alternate Encoding Rules), which is more relaxed than BER, CER, and DER.
519 	const byte *ptr = buf;
520 	while (bc > sizeof(w) && *ptr == 0)
521 	{
522 		bc--;
523 		ptr++;
524 	}
525 	if (bc > sizeof(w))
526 		BERDecodeError();
527 
528 	w = 0;
529 	for (unsigned int i=0; i<bc; i++)
530 		w = (w << 8) | ptr[i];
531 
532 	if (w < minValue || w > maxValue)
533 		BERDecodeError();
534 }
535 
536 #ifdef CRYPTOPP_DOXYGEN_PROCESSING
537 //! \brief Compare two OIDs for equality
538 //! \param lhs the first OID
539 //! \param rhs the second OID
540 //! \returns true if the OIDs are equal, false otherwise
541 inline bool operator==(const OID &lhs, const OID &rhs);
542 //! \brief Compare two OIDs for inequality
543 //! \param lhs the first OID
544 //! \param rhs the second OID
545 //! \returns true if the OIDs are not equal, false otherwise
546 inline bool operator!=(const OID &lhs, const OID &rhs);
547 //! \brief Compare two OIDs for ordering
548 //! \param lhs the first OID
549 //! \param rhs the second OID
550 //! \returns true if the first OID is less than the second OID, false otherwise
551 //! \details operator<() calls std::lexicographical_compare() on each element in the array of values.
552 inline bool operator<(const OID &lhs, const OID &rhs);
553 //! \brief Append a value to an OID
554 //! \param lhs the OID
555 //! \param rhs the value to append
556 inline OID operator+(const OID &lhs, unsigned long rhs);
557 #else
558 inline bool operator==(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
559 	{return lhs.m_values == rhs.m_values;}
560 inline bool operator!=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
561 	{return lhs.m_values != rhs.m_values;}
562 inline bool operator<(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
563 	{return std::lexicographical_compare(lhs.m_values.begin(), lhs.m_values.end(), rhs.m_values.begin(), rhs.m_values.end());}
564 inline ::CryptoPP::OID operator+(const ::CryptoPP::OID &lhs, unsigned long rhs)
565 	{return ::CryptoPP::OID(lhs)+=rhs;}
566 #endif
567 
568 NAMESPACE_END
569 
570 // Issue 340
571 #if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
572 # pragma GCC diagnostic pop
573 #endif
574 
575 #endif
576