From a644008679283325ba1b8abeee81fac015eb7f17 Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Tue, 4 Jun 2019 02:49:16 -0400 Subject: Cleanup ASN.1 encoders and decoders (GH #851) --- asn.cpp | 22 +++++++ asn.h | 215 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 222 insertions(+), 15 deletions(-) diff --git a/asn.cpp b/asn.cpp index 5d5cdaa5..ec5a097d 100644 --- a/asn.cpp +++ b/asn.cpp @@ -394,12 +394,24 @@ void EncodedObjectFilter::Put(const byte *inString, size_t length) } } +BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue) + : m_inQueue(inQueue), m_finished(false) +{ + Init(DefaultTag); +} + BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag) : m_inQueue(inQueue), m_finished(false) { Init(asnTag); } +BERGeneralDecoder::BERGeneralDecoder(BERGeneralDecoder &inQueue) + : m_inQueue(inQueue), m_finished(false) +{ + Init(DefaultTag); +} + BERGeneralDecoder::BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag) : m_inQueue(inQueue), m_finished(false) { @@ -501,11 +513,21 @@ lword BERGeneralDecoder::ReduceLength(lword delta) return delta; } +DERGeneralEncoder::DERGeneralEncoder(BufferedTransformation &outQueue) + : ByteQueue(), m_outQueue(outQueue), m_asnTag(DefaultTag), m_finished(false) +{ +} + DERGeneralEncoder::DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag) : ByteQueue(), m_outQueue(outQueue), m_asnTag(asnTag), m_finished(false) { } +DERGeneralEncoder::DERGeneralEncoder(DERGeneralEncoder &outQueue) + : ByteQueue(), m_outQueue(outQueue), m_asnTag(DefaultTag), m_finished(false) +{ +} + DERGeneralEncoder::DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag) : ByteQueue(), m_outQueue(outQueue), m_asnTag(asnTag), m_finished(false) { diff --git a/asn.h b/asn.h index 2eb6404d..4ce1fa35 100644 --- a/asn.h +++ b/asn.h @@ -255,24 +255,100 @@ private: }; /// \brief BER General Decoder -class CRYPTOPP_DLL BERGeneralDecoder : public Store +class CRYPTOPP_DLL BERGeneralDecoder : public Store, NotCopyable { public: + /// \brief Default ASN.1 tag + enum {DefaultTag = SEQUENCE | CONSTRUCTED}; + virtual ~BERGeneralDecoder(); + /// \brief Construct an ASN.1 decoder + /// \param inQueue input byte queue + /// \details BERGeneralDecoder uses DefaultTag + explicit BERGeneralDecoder(BufferedTransformation &inQueue); + + /// \brief Construct an ASN.1 decoder + /// \param inQueue input byte queue + /// \param asnTag ASN.1 tag explicit BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag); + + /// \brief Construct an ASN.1 decoder + /// \param inQueue input byte queue + /// \details BERGeneralDecoder uses DefaultTag + explicit BERGeneralDecoder(BERGeneralDecoder &inQueue); + + /// \brief Construct an ASN.1 decoder + /// \param inQueue input byte queue + /// \param asnTag ASN.1 tag explicit BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag); + /// \brief Determine length encoding + /// \returns true if the ASN.1 object is definite length encoded, false otherwise bool IsDefiniteLength() const {return m_definiteLength;} - lword RemainingLength() const {CRYPTOPP_ASSERT(m_definiteLength); return m_length;} + + /// \brief Determine remaining length + /// \returns number of octets that remain to be consumed + lword RemainingLength() const {return m_length;} + + /// \brief Determine end of stream + /// \returns true if all octets have been consumed, false otherwise bool EndReached() const; + + /// \brief Determine next octet + /// \returns next octet in the stream + /// \details PeekByte does not consume the octet. + /// \throws BERDecodeError if there are no octets remaining byte PeekByte() const; + + /// \brief Determine next octet + /// \details CheckByte reads the next byte in the stream and verifies + /// the octet matches b. + /// \throws BERDecodeError if the next octet is not b void CheckByte(byte b); + /// \brief Transfer bytes to another BufferedTransformation + /// \param target the destination BufferedTransformation + /// \param transferBytes the number of bytes to transfer + /// \param channel the channel on which the transfer should occur + /// \param blocking specifies whether the object should block when + /// processing input + /// \return the number of bytes that remain in the transfer block + /// (i.e., bytes not transferred) + /// \details TransferTo2() removes bytes and moves + /// them to the destination. Transfer begins at the index position + /// in the current stream, and not from an absolute position in the + /// stream. + /// \details transferBytes is an \a IN and \a OUT parameter. When + /// the call is made, transferBytes is the requested size of the + /// transfer. When the call returns, transferBytes is the number + /// of bytes that were transferred. size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); + + /// \brief Copy bytes to another BufferedTransformation + /// \param target the destination BufferedTransformation + /// \param begin the 0-based index of the first byte to copy in + /// the stream + /// \param end the 0-based index of the last byte to copy in + /// the stream + /// \param channel the channel on which the transfer should occur + /// \param blocking specifies whether the object should block when + /// processing input + /// \return the number of bytes that remain in the copy block + /// (i.e., bytes not copied) + /// \details CopyRangeTo2 copies bytes to the + /// destination. The bytes are not removed from this object. Copying + /// begins at the index position in the current stream, and not from + /// an absolute position in the stream. + /// \details begin is an \a IN and \a OUT parameter. When the call is + /// made, begin is the starting position of the copy. When the call + /// returns, begin is the position of the first byte that was \a not + /// copied (which may be different than end). begin can be used for + /// subsequent calls to CopyRangeTo2(). size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const; - // call this to denote end of sequence + /// \brief Signals the end of messages to the object + /// \details Call this to denote end of sequence void MessageEnd(); protected: @@ -288,15 +364,36 @@ private: }; /// \brief DER General Encoder -class CRYPTOPP_DLL DERGeneralEncoder : public ByteQueue +class CRYPTOPP_DLL DERGeneralEncoder : public ByteQueue, NotCopyable { public: + /// \brief Default ASN.1 tag + enum {DefaultTag = SEQUENCE | CONSTRUCTED}; + virtual ~DERGeneralEncoder(); - explicit DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED); - explicit DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED); + /// \brief Construct an ASN.1 encoder + /// \param outQueue output byte queue + /// \details DERGeneralEncoder uses DefaultTag + explicit DERGeneralEncoder(BufferedTransformation &outQueue); + + /// \brief Construct an ASN.1 encoder + /// \param outQueue output byte queue + /// \param asnTag ASN.1 tag + explicit DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag); - // call this to denote end of sequence + /// \brief Construct an ASN.1 encoder + /// \param outQueue output byte queue + /// \details DERGeneralEncoder uses DefaultTag + explicit DERGeneralEncoder(DERGeneralEncoder &outQueue); + + /// \brief Construct an ASN.1 encoder + /// \param outQueue output byte queue + /// \param asnTag ASN.1 tag + explicit DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag); + + /// \brief Signals the end of messages to the object + /// \details Call this to denote end of sequence void MessageEnd(); private: @@ -309,9 +406,31 @@ private: class CRYPTOPP_DLL BERSequenceDecoder : public BERGeneralDecoder { public: - explicit BERSequenceDecoder(BufferedTransformation &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED) + /// \brief Default ASN.1 tag + enum {DefaultTag = SEQUENCE | CONSTRUCTED}; + + /// \brief Construct an ASN.1 decoder + /// \param inQueue input byte queue + /// \details BERSequenceDecoder uses DefaultTag + explicit BERSequenceDecoder(BufferedTransformation &inQueue) + : BERGeneralDecoder(inQueue, DefaultTag) {} + + /// \brief Construct an ASN.1 decoder + /// \param inQueue input byte queue + /// \param asnTag ASN.1 tag + explicit BERSequenceDecoder(BufferedTransformation &inQueue, byte asnTag) : BERGeneralDecoder(inQueue, asnTag) {} - explicit BERSequenceDecoder(BERSequenceDecoder &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED) + + /// \brief Construct an ASN.1 decoder + /// \param inQueue input byte queue + /// \details BERSequenceDecoder uses DefaultTag + explicit BERSequenceDecoder(BERSequenceDecoder &inQueue) + : BERGeneralDecoder(inQueue, DefaultTag) {} + + /// \brief Construct an ASN.1 decoder + /// \param inQueue input byte queue + /// \param asnTag ASN.1 tag + explicit BERSequenceDecoder(BERSequenceDecoder &inQueue, byte asnTag) : BERGeneralDecoder(inQueue, asnTag) {} }; @@ -319,9 +438,31 @@ public: class CRYPTOPP_DLL DERSequenceEncoder : public DERGeneralEncoder { public: - explicit DERSequenceEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED) + /// \brief Default ASN.1 tag + enum {DefaultTag = SEQUENCE | CONSTRUCTED}; + + /// \brief Construct an ASN.1 encoder + /// \param outQueue output byte queue + /// \details DERSequenceEncoder uses DefaultTag + explicit DERSequenceEncoder(BufferedTransformation &outQueue) + : DERGeneralEncoder(outQueue, DefaultTag) {} + + /// \brief Construct an ASN.1 encoder + /// \param outQueue output byte queue + /// \param asnTag ASN.1 tag + explicit DERSequenceEncoder(BufferedTransformation &outQueue, byte asnTag) : DERGeneralEncoder(outQueue, asnTag) {} - explicit DERSequenceEncoder(DERSequenceEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED) + + /// \brief Construct an ASN.1 encoder + /// \param outQueue output byte queue + /// \details DERSequenceEncoder uses DefaultTag + explicit DERSequenceEncoder(DERSequenceEncoder &outQueue) + : DERGeneralEncoder(outQueue, DefaultTag) {} + + /// \brief Construct an ASN.1 encoder + /// \param outQueue output byte queue + /// \param asnTag ASN.1 tag + explicit DERSequenceEncoder(DERSequenceEncoder &outQueue, byte asnTag) : DERGeneralEncoder(outQueue, asnTag) {} }; @@ -329,9 +470,31 @@ public: class CRYPTOPP_DLL BERSetDecoder : public BERGeneralDecoder { public: - explicit BERSetDecoder(BufferedTransformation &inQueue, byte asnTag = SET | CONSTRUCTED) + /// \brief Default ASN.1 tag + enum {DefaultTag = SET | CONSTRUCTED}; + + /// \brief Construct an ASN.1 decoder + /// \param inQueue input byte queue + /// \details BERSetDecoder uses DefaultTag + explicit BERSetDecoder(BufferedTransformation &inQueue) + : BERGeneralDecoder(inQueue, DefaultTag) {} + + /// \brief Construct an ASN.1 decoder + /// \param inQueue input byte queue + /// \param asnTag ASN.1 tag + explicit BERSetDecoder(BufferedTransformation &inQueue, byte asnTag) : BERGeneralDecoder(inQueue, asnTag) {} - explicit BERSetDecoder(BERSetDecoder &inQueue, byte asnTag = SET | CONSTRUCTED) + + /// \brief Construct an ASN.1 decoder + /// \param inQueue input byte queue + /// \details BERSetDecoder uses DefaultTag + explicit BERSetDecoder(BERSetDecoder &inQueue) + : BERGeneralDecoder(inQueue, DefaultTag) {} + + /// \brief Construct an ASN.1 decoder + /// \param inQueue input byte queue + /// \param asnTag ASN.1 tag + explicit BERSetDecoder(BERSetDecoder &inQueue, byte asnTag) : BERGeneralDecoder(inQueue, asnTag) {} }; @@ -339,9 +502,31 @@ public: class CRYPTOPP_DLL DERSetEncoder : public DERGeneralEncoder { public: - explicit DERSetEncoder(BufferedTransformation &outQueue, byte asnTag = SET | CONSTRUCTED) + /// \brief Default ASN.1 tag + enum {DefaultTag = SET | CONSTRUCTED}; + + /// \brief Construct an ASN.1 encoder + /// \param outQueue output byte queue + /// \details DERSetEncoder uses DefaultTag + explicit DERSetEncoder(BufferedTransformation &outQueue) + : DERGeneralEncoder(outQueue, DefaultTag) {} + + /// \brief Construct an ASN.1 encoder + /// \param outQueue output byte queue + /// \param asnTag ASN.1 tag + explicit DERSetEncoder(BufferedTransformation &outQueue, byte asnTag) : DERGeneralEncoder(outQueue, asnTag) {} - explicit DERSetEncoder(DERSetEncoder &outQueue, byte asnTag = SET | CONSTRUCTED) + + /// \brief Construct an ASN.1 encoder + /// \param outQueue output byte queue + /// \details DERSetEncoder uses DefaultTag + explicit DERSetEncoder(DERSetEncoder &outQueue) + : DERGeneralEncoder(outQueue, DefaultTag) {} + + /// \brief Construct an ASN.1 encoder + /// \param outQueue output byte queue + /// \param asnTag ASN.1 tag + explicit DERSetEncoder(DERSetEncoder &outQueue, byte asnTag) : DERGeneralEncoder(outQueue, asnTag) {} }; -- cgit v1.2.1