Path: blob/a-new-beginning/SharedDependencies/Sources/cryptopp/asn.cpp
2 views
// asn.cpp - originally written and placed in the public domain by Wei Dai1// CryptoPP::Test namespace added by JW in February 201723#include "pch.h"4#include "config.h"56#ifndef CRYPTOPP_IMPORTS78#include "cryptlib.h"9#include "asn.h"10#include "misc.h"1112#include <iostream>13#include <iomanip>14#include <sstream>15#include <time.h>1617NAMESPACE_BEGIN(CryptoPP)1819size_t DERLengthEncode(BufferedTransformation &bt, lword length)20{21size_t i=0;22if (length <= 0x7f)23{24bt.Put(byte(length));25i++;26}27else28{29bt.Put(byte(BytePrecision(length) | 0x80));30i++;31for (int j=BytePrecision(length); j; --j)32{33bt.Put(byte(length >> (j-1)*8));34i++;35}36}37return i;38}3940bool BERLengthDecode(BufferedTransformation &bt, lword &length, bool &definiteLength)41{42byte b;4344if (!bt.Get(b))45return false;4647if (!(b & 0x80))48{49definiteLength = true;50length = b;51}52else53{54unsigned int lengthBytes = b & 0x7f;5556if (lengthBytes == 0)57{58definiteLength = false;59return true;60}6162definiteLength = true;63length = 0;64while (lengthBytes--)65{66if (length >> (8*(sizeof(length)-1)))67BERDecodeError(); // length about to overflow6869if (!bt.Get(b))70return false;7172length = (length << 8) | b;73}74}75return true;76}7778bool BERLengthDecode(BufferedTransformation &bt, size_t &length)79{80lword lw = 0;81bool definiteLength = false;82if (!BERLengthDecode(bt, lw, definiteLength))83BERDecodeError();84if (!SafeConvert(lw, length))85BERDecodeError();86return definiteLength;87}8889void DEREncodeNull(BufferedTransformation &out)90{91out.Put(TAG_NULL);92out.Put(0);93}9495void BERDecodeNull(BufferedTransformation &in)96{97byte b;98if (!in.Get(b) || b != TAG_NULL)99BERDecodeError();100size_t length;101if (!BERLengthDecode(in, length) || length != 0)102BERDecodeError();103}104105/// ASN Strings106size_t DEREncodeOctetString(BufferedTransformation &bt, const byte *str, size_t strLen)107{108bt.Put(OCTET_STRING);109size_t lengthBytes = DERLengthEncode(bt, strLen);110bt.Put(str, strLen);111return 1+lengthBytes+strLen;112}113114size_t DEREncodeOctetString(BufferedTransformation &bt, const SecByteBlock &str)115{116return DEREncodeOctetString(bt, ConstBytePtr(str), BytePtrSize(str));117}118119size_t BERDecodeOctetString(BufferedTransformation &bt, SecByteBlock &str)120{121byte b;122if (!bt.Get(b) || b != OCTET_STRING)123BERDecodeError();124125size_t bc;126if (!BERLengthDecode(bt, bc))127BERDecodeError();128if (bc > bt.MaxRetrievable()) // Issue 346129BERDecodeError();130131str.New(bc);132if (bc != bt.Get(BytePtr(str), bc))133BERDecodeError();134return bc;135}136137size_t BERDecodeOctetString(BufferedTransformation &bt, BufferedTransformation &str)138{139byte b;140if (!bt.Get(b) || b != OCTET_STRING)141BERDecodeError();142143size_t bc;144if (!BERLengthDecode(bt, bc))145BERDecodeError();146if (bc > bt.MaxRetrievable()) // Issue 346147BERDecodeError();148149bt.TransferTo(str, bc);150return bc;151}152153size_t DEREncodeTextString(BufferedTransformation &bt, const byte* str, size_t strLen, byte asnTag)154{155bt.Put(asnTag);156size_t lengthBytes = DERLengthEncode(bt, strLen);157bt.Put(str, strLen);158return 1+lengthBytes+strLen;159}160161size_t DEREncodeTextString(BufferedTransformation &bt, const SecByteBlock &str, byte asnTag)162{163return DEREncodeTextString(bt, ConstBytePtr(str), BytePtrSize(str), asnTag);164}165166size_t DEREncodeTextString(BufferedTransformation &bt, const std::string &str, byte asnTag)167{168return DEREncodeTextString(bt, ConstBytePtr(str), BytePtrSize(str), asnTag);169}170171size_t BERDecodeTextString(BufferedTransformation &bt, SecByteBlock &str, byte asnTag)172{173byte b;174if (!bt.Get(b) || b != asnTag)175BERDecodeError();176177size_t bc;178if (!BERLengthDecode(bt, bc))179BERDecodeError();180if (bc > bt.MaxRetrievable()) // Issue 346181BERDecodeError();182183str.resize(bc);184if (bc != bt.Get(BytePtr(str), BytePtrSize(str)))185BERDecodeError();186187return bc;188}189190size_t BERDecodeTextString(BufferedTransformation &bt, std::string &str, byte asnTag)191{192byte b;193if (!bt.Get(b) || b != asnTag)194BERDecodeError();195196size_t bc;197if (!BERLengthDecode(bt, bc))198BERDecodeError();199if (bc > bt.MaxRetrievable()) // Issue 346200BERDecodeError();201202str.resize(bc);203if (bc != bt.Get(BytePtr(str), BytePtrSize(str)))204BERDecodeError();205206return bc;207}208209size_t DEREncodeDate(BufferedTransformation &bt, const SecByteBlock &str, byte asnTag)210{211bt.Put(asnTag);212size_t lengthBytes = DERLengthEncode(bt, str.size());213bt.Put(ConstBytePtr(str), BytePtrSize(str));214return 1+lengthBytes+str.size();215}216217size_t BERDecodeDate(BufferedTransformation &bt, SecByteBlock &str, byte asnTag)218{219byte b;220if (!bt.Get(b) || b != asnTag)221BERDecodeError();222223size_t bc;224if (!BERLengthDecode(bt, bc))225BERDecodeError();226if (bc > bt.MaxRetrievable()) // Issue 346227BERDecodeError();228229str.resize(bc);230if (bc != bt.Get(BytePtr(str), BytePtrSize(str)))231BERDecodeError();232233return bc;234}235236size_t DEREncodeBitString(BufferedTransformation &bt, const byte *str, size_t strLen, unsigned int unusedBits)237{238bt.Put(BIT_STRING);239size_t lengthBytes = DERLengthEncode(bt, strLen+1);240bt.Put((byte)unusedBits);241bt.Put(str, strLen);242return 2+lengthBytes+strLen;243}244245size_t BERDecodeBitString(BufferedTransformation &bt, SecByteBlock &str, unsigned int &unusedBits)246{247byte b;248if (!bt.Get(b) || b != BIT_STRING)249BERDecodeError();250251size_t bc;252if (!BERLengthDecode(bt, bc))253BERDecodeError();254if (bc == 0)255BERDecodeError();256if (bc > bt.MaxRetrievable()) // Issue 346257BERDecodeError();258259// X.690, 8.6.2.2: "The number [of unused bits] shall be in the range zero to seven"260byte unused;261if (!bt.Get(unused) || unused > 7)262BERDecodeError();263unusedBits = unused;264str.resize(bc-1);265if ((bc-1) != bt.Get(BytePtr(str), bc-1))266BERDecodeError();267return bc-1;268}269270void DERReencode(BufferedTransformation &source, BufferedTransformation &dest)271{272byte tag;273source.Peek(tag);274BERGeneralDecoder decoder(source, tag);275DERGeneralEncoder encoder(dest, tag);276if (decoder.IsDefiniteLength())277decoder.TransferTo(encoder, decoder.RemainingLength());278else279{280while (!decoder.EndReached())281DERReencode(decoder, encoder);282}283decoder.MessageEnd();284encoder.MessageEnd();285}286287size_t BERDecodePeekLength(const BufferedTransformation &bt)288{289lword count = (std::min)(bt.MaxRetrievable(), static_cast<lword>(16));290if (count == 0) return 0;291292ByteQueue tagAndLength;293bt.CopyTo(tagAndLength, count);294295// Skip tag296tagAndLength.Skip(1);297298// BERLengthDecode fails for indefinite length.299size_t length;300if (!BERLengthDecode(tagAndLength, length))301return 0;302303return length;304}305306void OID::EncodeValue(BufferedTransformation &bt, word32 v)307{308for (unsigned int i=RoundUpToMultipleOf(STDMAX(7U,BitPrecision(v)), 7U)-7; i != 0; i-=7)309bt.Put((byte)(0x80 | ((v >> i) & 0x7f)));310bt.Put((byte)(v & 0x7f));311}312313size_t OID::DecodeValue(BufferedTransformation &bt, word32 &v)314{315byte b;316size_t i=0;317v = 0;318while (true)319{320if (!bt.Get(b))321BERDecodeError();322i++;323if (v >> (8*sizeof(v)-7)) // v about to overflow324BERDecodeError();325v <<= 7;326v += b & 0x7f;327if (!(b & 0x80))328return i;329}330}331332void OID::DEREncode(BufferedTransformation &bt) const333{334CRYPTOPP_ASSERT(m_values.size() >= 2);335ByteQueue temp;336temp.Put(byte(m_values[0] * 40 + m_values[1]));337for (size_t i=2; i<m_values.size(); i++)338EncodeValue(temp, m_values[i]);339bt.Put(OBJECT_IDENTIFIER);340DERLengthEncode(bt, temp.CurrentSize());341temp.TransferTo(bt);342}343344void OID::BERDecode(BufferedTransformation &bt)345{346byte b;347if (!bt.Get(b) || b != OBJECT_IDENTIFIER)348BERDecodeError();349350size_t length;351if (!BERLengthDecode(bt, length) || length < 1)352BERDecodeError();353354if (!bt.Get(b))355BERDecodeError();356357length--;358m_values.resize(2);359m_values[0] = b / 40;360m_values[1] = b % 40;361362while (length > 0)363{364word32 v;365size_t valueLen = DecodeValue(bt, v);366if (valueLen > length)367BERDecodeError();368m_values.push_back(v);369length -= valueLen;370}371}372373void OID::BERDecodeAndCheck(BufferedTransformation &bt) const374{375OID oid(bt);376if (*this != oid)377BERDecodeError();378}379380std::ostream& OID::Print(std::ostream& out) const381{382std::ostringstream oss;383for (size_t i = 0; i < m_values.size(); ++i)384{385oss << m_values[i];386if (i+1 < m_values.size())387oss << ".";388}389return out << oss.str();390}391392inline BufferedTransformation & EncodedObjectFilter::CurrentTarget()393{394if (m_flags & PUT_OBJECTS)395return *AttachedTransformation();396else397return TheBitBucket();398}399400void EncodedObjectFilter::Put(const byte *inString, size_t length)401{402if (m_nCurrentObject == m_nObjects)403{404AttachedTransformation()->Put(inString, length);405return;406}407408LazyPutter lazyPutter(m_queue, inString, length);409410while (m_queue.AnyRetrievable())411{412switch (m_state)413{414case IDENTIFIER:415if (!m_queue.Get(m_id))416return;417m_queue.TransferTo(CurrentTarget(), 1);418m_state = LENGTH;419// fall through420case LENGTH:421{422byte b;423if (m_level > 0 && m_id == 0 && m_queue.Peek(b) && b == 0)424{425m_queue.TransferTo(CurrentTarget(), 1);426m_level--;427m_state = IDENTIFIER;428break;429}430ByteQueue::Walker walker(m_queue);431bool definiteLength = false;432if (!BERLengthDecode(walker, m_lengthRemaining, definiteLength))433return;434m_queue.TransferTo(CurrentTarget(), walker.GetCurrentPosition());435if (!((m_id & CONSTRUCTED) || definiteLength))436BERDecodeError();437if (!definiteLength)438{439if (!(m_id & CONSTRUCTED))440BERDecodeError();441m_level++;442m_state = IDENTIFIER;443break;444}445m_state = BODY;446}447// fall through448case BODY:449m_lengthRemaining -= m_queue.TransferTo(CurrentTarget(), m_lengthRemaining);450451if (m_lengthRemaining == 0)452m_state = IDENTIFIER;453// fall through454case TAIL:455case ALL_DONE:456default: ;457}458459if (m_state == IDENTIFIER && m_level == 0)460{461// just finished processing a level 0 object462++m_nCurrentObject;463464if (m_flags & PUT_MESSANGE_END_AFTER_EACH_OBJECT)465AttachedTransformation()->MessageEnd();466467if (m_nCurrentObject == m_nObjects)468{469if (m_flags & PUT_MESSANGE_END_AFTER_ALL_OBJECTS)470AttachedTransformation()->MessageEnd();471472if (m_flags & PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS)473AttachedTransformation()->MessageSeriesEnd();474475m_queue.TransferAllTo(*AttachedTransformation());476return;477}478}479}480}481482BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue)483: m_inQueue(inQueue), m_length(0), m_finished(false)484{485Init(DefaultTag);486}487488BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag)489: m_inQueue(inQueue), m_length(0), m_finished(false)490{491Init(asnTag);492}493494BERGeneralDecoder::BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag)495: m_inQueue(inQueue), m_length(0), m_finished(false)496{497Init(asnTag);498}499500void BERGeneralDecoder::Init(byte asnTag)501{502byte b;503if (!m_inQueue.Get(b) || b != asnTag)504BERDecodeError();505506if (!BERLengthDecode(m_inQueue, m_length, m_definiteLength))507BERDecodeError();508509if (!m_definiteLength && !(asnTag & CONSTRUCTED))510BERDecodeError(); // cannot be primitive and have indefinite length511}512513BERGeneralDecoder::~BERGeneralDecoder()514{515try // avoid throwing in destructor516{517if (!m_finished)518MessageEnd();519}520catch (const Exception&)521{522// CRYPTOPP_ASSERT(0);523}524}525526bool BERGeneralDecoder::EndReached() const527{528if (m_definiteLength)529return m_length == 0;530else531{ // check end-of-content octets532word16 i;533return (m_inQueue.PeekWord16(i)==2 && i==0);534}535}536537byte BERGeneralDecoder::PeekByte() const538{539byte b;540if (!Peek(b))541BERDecodeError();542return b;543}544545void BERGeneralDecoder::CheckByte(byte check)546{547byte b;548if (!Get(b) || b != check)549BERDecodeError();550}551552void BERGeneralDecoder::MessageEnd()553{554m_finished = true;555if (m_definiteLength)556{557if (m_length != 0)558BERDecodeError();559}560else561{ // remove end-of-content octets562word16 i;563if (m_inQueue.GetWord16(i) != 2 || i != 0)564BERDecodeError();565}566}567568size_t BERGeneralDecoder::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)569{570if (m_definiteLength && transferBytes > m_length)571transferBytes = m_length;572size_t blockedBytes = m_inQueue.TransferTo2(target, transferBytes, channel, blocking);573ReduceLength(transferBytes);574return blockedBytes;575}576577size_t BERGeneralDecoder::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const578{579if (m_definiteLength)580end = STDMIN(m_length, end);581return m_inQueue.CopyRangeTo2(target, begin, end, channel, blocking);582}583584lword BERGeneralDecoder::ReduceLength(lword delta)585{586if (m_definiteLength)587{588if (m_length < delta)589BERDecodeError();590m_length -= delta;591}592return delta;593}594595DERGeneralEncoder::DERGeneralEncoder(BufferedTransformation &outQueue)596: m_outQueue(outQueue), m_asnTag(DefaultTag), m_finished(false)597{598}599600DERGeneralEncoder::DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag)601: m_outQueue(outQueue), m_asnTag(asnTag), m_finished(false)602{603}604605DERGeneralEncoder::DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag)606: m_outQueue(outQueue), m_asnTag(asnTag), m_finished(false)607{608}609610DERGeneralEncoder::~DERGeneralEncoder()611{612try // avoid throwing in constructor613{614if (!m_finished)615MessageEnd();616}617catch (const Exception&)618{619CRYPTOPP_ASSERT(0);620}621}622623void DERGeneralEncoder::MessageEnd()624{625m_finished = true;626lword length = CurrentSize();627m_outQueue.Put(m_asnTag);628DERLengthEncode(m_outQueue, length);629TransferTo(m_outQueue);630}631632// *************************************************************633634void X509PublicKey::BERDecode(BufferedTransformation &bt)635{636BERSequenceDecoder subjectPublicKeyInfo(bt);637BERSequenceDecoder algorithm(subjectPublicKeyInfo);638GetAlgorithmID().BERDecodeAndCheck(algorithm);639bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);640algorithm.MessageEnd();641642BERGeneralDecoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);643subjectPublicKey.CheckByte(0); // unused bits644BERDecodePublicKey(subjectPublicKey, parametersPresent, (size_t)subjectPublicKey.RemainingLength());645subjectPublicKey.MessageEnd();646subjectPublicKeyInfo.MessageEnd();647}648649void X509PublicKey::DEREncode(BufferedTransformation &bt) const650{651DERSequenceEncoder subjectPublicKeyInfo(bt);652653DERSequenceEncoder algorithm(subjectPublicKeyInfo);654GetAlgorithmID().DEREncode(algorithm);655DEREncodeAlgorithmParameters(algorithm);656algorithm.MessageEnd();657658DERGeneralEncoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);659subjectPublicKey.Put(0); // unused bits660DEREncodePublicKey(subjectPublicKey);661subjectPublicKey.MessageEnd();662663subjectPublicKeyInfo.MessageEnd();664}665666void PKCS8PrivateKey::BERDecode(BufferedTransformation &bt)667{668BERSequenceDecoder privateKeyInfo(bt);669word32 version;670BERDecodeUnsigned<word32>(privateKeyInfo, version, INTEGER, 0, 0); // check version671672BERSequenceDecoder algorithm(privateKeyInfo);673GetAlgorithmID().BERDecodeAndCheck(algorithm);674bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);675algorithm.MessageEnd();676677BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING);678BERDecodePrivateKey(octetString, parametersPresent, (size_t)privateKeyInfo.RemainingLength());679octetString.MessageEnd();680681if (!privateKeyInfo.EndReached())682BERDecodeOptionalAttributes(privateKeyInfo);683privateKeyInfo.MessageEnd();684}685686void PKCS8PrivateKey::DEREncode(BufferedTransformation &bt) const687{688DERSequenceEncoder privateKeyInfo(bt);689DEREncodeUnsigned<word32>(privateKeyInfo, 0); // version690691DERSequenceEncoder algorithm(privateKeyInfo);692GetAlgorithmID().DEREncode(algorithm);693DEREncodeAlgorithmParameters(algorithm);694algorithm.MessageEnd();695696DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING);697DEREncodePrivateKey(octetString);698octetString.MessageEnd();699700DEREncodeOptionalAttributes(privateKeyInfo);701privateKeyInfo.MessageEnd();702}703704void PKCS8PrivateKey::BERDecodeOptionalAttributes(BufferedTransformation &bt)705{706DERReencode(bt, m_optionalAttributes);707}708709void PKCS8PrivateKey::DEREncodeOptionalAttributes(BufferedTransformation &bt) const710{711m_optionalAttributes.CopyTo(bt);712}713714NAMESPACE_END715716#endif717718719