- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# asn.cpp

    00001 // asn.cpp - written and placed in the public domain by Wei Dai
    00002
    00003 #include "pch.h"
    00004
    00005 #ifndef CRYPTOPP_IMPORTS
    00006
    00007 #include "asn.h"
    00008
    00009 #include <iomanip>
    00010 #include <time.h>
    00011
    00012 NAMESPACE_BEGIN(CryptoPP)
    00013 USING_NAMESPACE(std)
    00014
    00015 /// DER Length
    00016 size_t DERLengthEncode(BufferedTransformation &bt, lword length)
    00017 {
    00018         size_t i=0;
    00019         if (length <= 0x7f)
    00020         {
    00021                 bt.Put(byte(length));
    00022                 i++;
    00023         }
    00024         else
    00025         {
    00026                 bt.Put(byte(BytePrecision(length) | 0x80));
    00027                 i++;
    00028                 for (int j=BytePrecision(length); j; --j)
    00029                 {
    00030                         bt.Put(byte(length >> (j-1)*8));
    00031                         i++;
    00032                 }
    00033         }
    00034         return i;
    00035 }
    00036
    00037 bool BERLengthDecode(BufferedTransformation &bt, lword &length, bool &definiteLength)
    00038 {
    00039         byte b;
    00040
    00041         if (!bt.Get(b))
    00042                 return false;
    00043
    00044         if (!(b & 0x80))
    00045         {
    00046                 definiteLength = true;
    00047                 length = b;
    00048         }
    00049         else
    00050         {
    00051                 unsigned int lengthBytes = b & 0x7f;
    00052
    00053                 if (lengthBytes == 0)
    00054                 {
    00055                         definiteLength = false;
    00056                         return true;
    00057                 }
    00058
    00059                 definiteLength = true;
    00060                 length = 0;
    00061                 while (lengthBytes--)
    00062                 {
    00063                         if (length >> (8*(sizeof(length)-1)))
    00064                                 BERDecodeError();       // length about to overflow
    00065
    00066                         if (!bt.Get(b))
    00067                                 return false;
    00068
    00069                         length = (length << 8) | b;
    00070                 }
    00071         }
    00072         return true;
    00073 }
    00074
    00075 bool BERLengthDecode(BufferedTransformation &bt, size_t &length)
    00076 {
    00077         lword lw;
    00078         bool definiteLength;
    00079         if (!BERLengthDecode(bt, lw, definiteLength))
    00080                 BERDecodeError();
    00081         if (!SafeConvert(lw, length))
    00082                 BERDecodeError();
    00083         return definiteLength;
    00084 }
    00085
    00086 void DEREncodeNull(BufferedTransformation &out)
    00087 {
    00088         out.Put(TAG_NULL);
    00089         out.Put(0);
    00090 }
    00091
    00092 void BERDecodeNull(BufferedTransformation &in)
    00093 {
    00094         byte b;
    00095         if (!in.Get(b) || b != TAG_NULL)
    00096                 BERDecodeError();
    00097         size_t length;
    00098         if (!BERLengthDecode(in, length) || length != 0)
    00099                 BERDecodeError();
    00100 }
    00101
    00102 /// ASN Strings
    00103 size_t DEREncodeOctetString(BufferedTransformation &bt, const byte *str, size_t strLen)
    00104 {
    00105         bt.Put(OCTET_STRING);
    00106         size_t lengthBytes = DERLengthEncode(bt, strLen);
    00107         bt.Put(str, strLen);
    00108         return 1+lengthBytes+strLen;
    00109 }
    00110
    00111 size_t DEREncodeOctetString(BufferedTransformation &bt, const SecByteBlock &str)
    00112 {
    00113         return DEREncodeOctetString(bt, str.begin(), str.size());
    00114 }
    00115
    00116 size_t BERDecodeOctetString(BufferedTransformation &bt, SecByteBlock &str)
    00117 {
    00118         byte b;
    00119         if (!bt.Get(b) || b != OCTET_STRING)
    00120                 BERDecodeError();
    00121
    00122         size_t bc;
    00123         if (!BERLengthDecode(bt, bc))
    00124                 BERDecodeError();
    00125
    00126         str.resize(bc);
    00127         if (bc != bt.Get(str, bc))
    00128                 BERDecodeError();
    00129         return bc;
    00130 }
    00131
    00132 size_t BERDecodeOctetString(BufferedTransformation &bt, BufferedTransformation &str)
    00133 {
    00134         byte b;
    00135         if (!bt.Get(b) || b != OCTET_STRING)
    00136                 BERDecodeError();
    00137
    00138         size_t bc;
    00139         if (!BERLengthDecode(bt, bc))
    00140                 BERDecodeError();
    00141
    00142         bt.TransferTo(str, bc);
    00143         return bc;
    00144 }
    00145
    00146 size_t DEREncodeTextString(BufferedTransformation &bt, const std::string &str, byte asnTag)
    00147 {
    00148         bt.Put(asnTag);
    00149         size_t lengthBytes = DERLengthEncode(bt, str.size());
    00150         bt.Put((const byte *)str.data(), str.size());
    00151         return 1+lengthBytes+str.size();
    00152 }
    00153
    00154 size_t BERDecodeTextString(BufferedTransformation &bt, std::string &str, byte asnTag)
    00155 {
    00156         byte b;
    00157         if (!bt.Get(b) || b != asnTag)
    00158                 BERDecodeError();
    00159
    00160         size_t bc;
    00161         if (!BERLengthDecode(bt, bc))
    00162                 BERDecodeError();
    00163
    00164         SecByteBlock temp(bc);
    00165         if (bc != bt.Get(temp, bc))
    00166                 BERDecodeError();
    00167         str.assign((char *)temp.begin(), bc);
    00168         return bc;
    00169 }
    00170
    00171 /// ASN BitString
    00172 size_t DEREncodeBitString(BufferedTransformation &bt, const byte *str, size_t strLen, unsigned int unusedBits)
    00173 {
    00174         bt.Put(BIT_STRING);
    00175         size_t lengthBytes = DERLengthEncode(bt, strLen+1);
    00176         bt.Put((byte)unusedBits);
    00177         bt.Put(str, strLen);
    00178         return 2+lengthBytes+strLen;
    00179 }
    00180
    00181 size_t BERDecodeBitString(BufferedTransformation &bt, SecByteBlock &str, unsigned int &unusedBits)
    00182 {
    00183         byte b;
    00184         if (!bt.Get(b) || b != BIT_STRING)
    00185                 BERDecodeError();
    00186
    00187         size_t bc;
    00188         if (!BERLengthDecode(bt, bc))
    00189                 BERDecodeError();
    00190
    00191         byte unused;
    00192         if (!bt.Get(unused))
    00193                 BERDecodeError();
    00194         unusedBits = unused;
    00195         str.resize(bc-1);
    00196         if ((bc-1) != bt.Get(str, bc-1))
    00197                 BERDecodeError();
    00198         return bc-1;
    00199 }
    00200
    00201 void DERReencode(BufferedTransformation &source, BufferedTransformation &dest)
    00202 {
    00203         byte tag;
    00204         source.Peek(tag);
    00205         BERGeneralDecoder decoder(source, tag);
    00206         DERGeneralEncoder encoder(dest, tag);
    00207         if (decoder.IsDefiniteLength())
    00208                 decoder.TransferTo(encoder, decoder.RemainingLength());
    00209         else
    00210         {
    00211                 while (!decoder.EndReached())
    00212                         DERReencode(decoder, encoder);
    00213         }
    00214         decoder.MessageEnd();
    00215         encoder.MessageEnd();
    00216 }
    00217
    00218 void OID::EncodeValue(BufferedTransformation &bt, word32 v)
    00219 {
    00220         for (unsigned int i=RoundUpToMultipleOf(STDMAX(7U,BitPrecision(v)), 7U)-7; i != 0; i-=7)
    00221                 bt.Put((byte)(0x80 | ((v >> i) & 0x7f)));
    00222         bt.Put((byte)(v & 0x7f));
    00223 }
    00224
    00225 size_t OID::DecodeValue(BufferedTransformation &bt, word32 &v)
    00226 {
    00227         byte b;
    00228         size_t i=0;
    00229         v = 0;
    00230         while (true)
    00231         {
    00232                 if (!bt.Get(b))
    00233                         BERDecodeError();
    00234                 i++;
    00235                 v <<= 7;
    00236                 v += b & 0x7f;
    00237                 if (!(b & 0x80))
    00238                         return i;
    00239         }
    00240 }
    00241
    00242 void OID::DEREncode(BufferedTransformation &bt) const
    00243 {
    00244         assert(m_values.size() >= 2);
    00245         ByteQueue temp;
    00246         temp.Put(byte(m_values[0] * 40 + m_values[1]));
    00247         for (size_t i=2; i<m_values.size(); i++)
    00248                 EncodeValue(temp, m_values[i]);
    00249         bt.Put(OBJECT_IDENTIFIER);
    00250         DERLengthEncode(bt, temp.CurrentSize());
    00251         temp.TransferTo(bt);
    00252 }
    00253
    00254 void OID::BERDecode(BufferedTransformation &bt)
    00255 {
    00256         byte b;
    00257         if (!bt.Get(b) || b != OBJECT_IDENTIFIER)
    00258                 BERDecodeError();
    00259
    00260         size_t length;
    00261         if (!BERLengthDecode(bt, length) || length < 1)
    00262                 BERDecodeError();
    00263
    00264         if (!bt.Get(b))
    00265                 BERDecodeError();
    00266
    00267         length--;
    00268         m_values.resize(2);
    00269         m_values[0] = b / 40;
    00270         m_values[1] = b % 40;
    00271
    00272         while (length > 0)
    00273         {
    00274                 word32 v;
    00275                 size_t valueLen = DecodeValue(bt, v);
    00276                 if (valueLen > length)
    00277                         BERDecodeError();
    00278                 m_values.push_back(v);
    00279                 length -= valueLen;
    00280         }
    00281 }
    00282
    00283 void OID::BERDecodeAndCheck(BufferedTransformation &bt) const
    00284 {
    00285         OID oid(bt);
    00286         if (*this != oid)
    00287                 BERDecodeError();
    00288 }
    00289
    00290 inline BufferedTransformation & EncodedObjectFilter::CurrentTarget()
    00291 {
    00292         if (m_flags & PUT_OBJECTS)
    00293                 return *AttachedTransformation();
    00294         else
    00295                 return TheBitBucket();
    00296 }
    00297
    00298 void EncodedObjectFilter::Put(const byte *inString, size_t length)
    00299 {
    00300         if (m_nCurrentObject == m_nObjects)
    00301         {
    00302                 AttachedTransformation()->Put(inString, length);
    00303                 return;
    00304         }
    00305
    00306         LazyPutter lazyPutter(m_queue, inString, length);
    00307
    00308         while (m_queue.AnyRetrievable())
    00309         {
    00310                 switch (m_state)
    00311                 {
    00312                 case IDENTIFIER:
    00313                         if (!m_queue.Get(m_id))
    00314                                 return;
    00315                         m_queue.TransferTo(CurrentTarget(), 1);
    00316                         m_state = LENGTH;       // fall through
    00317                 case LENGTH:
    00318                 {
    00319                         byte b;
    00320                         if (m_level > 0 && m_id == 0 && m_queue.Peek(b) && b == 0)
    00321                         {
    00322                                 m_queue.TransferTo(CurrentTarget(), 1);
    00323                                 m_level--;
    00324                                 m_state = IDENTIFIER;
    00325                                 break;
    00326                         }
    00327                         ByteQueue::Walker walker(m_queue);
    00328                         bool definiteLength;
    00329                         if (!BERLengthDecode(walker, m_lengthRemaining, definiteLength))
    00330                                 return;
    00331                         m_queue.TransferTo(CurrentTarget(), walker.GetCurrentPosition());
    00332                         if (!((m_id & CONSTRUCTED) || definiteLength))
    00333                                 BERDecodeError();
    00334                         if (!definiteLength)
    00335                         {
    00336                                 if (!(m_id & CONSTRUCTED))
    00337                                         BERDecodeError();
    00338                                 m_level++;
    00339                                 m_state = IDENTIFIER;
    00340                                 break;
    00341                         }
    00342                         m_state = BODY;         // fall through
    00343                 }
    00344                 case BODY:
    00345                         m_lengthRemaining -= m_queue.TransferTo(CurrentTarget(), m_lengthRemaining);
    00346
    00347                         if (m_lengthRemaining == 0)
    00348                                 m_state = IDENTIFIER;
    00349                 }
    00350
    00351                 if (m_state == IDENTIFIER && m_level == 0)
    00352                 {
    00353                         // just finished processing a level 0 object
    00354                         ++m_nCurrentObject;
    00355
    00356                         if (m_flags & PUT_MESSANGE_END_AFTER_EACH_OBJECT)
    00357                                 AttachedTransformation()->MessageEnd();
    00358
    00359                         if (m_nCurrentObject == m_nObjects)
    00360                         {
    00361                                 if (m_flags & PUT_MESSANGE_END_AFTER_ALL_OBJECTS)
    00362                                         AttachedTransformation()->MessageEnd();
    00363
    00364                                 if (m_flags & PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS)
    00365                                         AttachedTransformation()->MessageSeriesEnd();
    00366
    00367                                 m_queue.TransferAllTo(*AttachedTransformation());
    00368                                 return;
    00369                         }
    00370                 }
    00371         }
    00372 }
    00373
    00374 BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag)
    00375         : m_inQueue(inQueue), m_finished(false)
    00376 {
    00377         Init(asnTag);
    00378 }
    00379
    00380 BERGeneralDecoder::BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag)
    00381         : m_inQueue(inQueue), m_finished(false)
    00382 {
    00383         Init(asnTag);
    00384 }
    00385
    00386 void BERGeneralDecoder::Init(byte asnTag)
    00387 {
    00388         byte b;
    00389         if (!m_inQueue.Get(b) || b != asnTag)
    00390                 BERDecodeError();
    00391
    00392         if (!BERLengthDecode(m_inQueue, m_length, m_definiteLength))
    00393                 BERDecodeError();
    00394
    00395         if (!m_definiteLength && !(asnTag & CONSTRUCTED))
    00396                 BERDecodeError();       // cannot be primitive and have indefinite length
    00397 }
    00398
    00399 BERGeneralDecoder::~BERGeneralDecoder()
    00400 {
    00401         try     // avoid throwing in constructor
    00402         {
    00403                 if (!m_finished)
    00404                         MessageEnd();
    00405         }
    00406         catch (...)
    00407         {
    00408         }
    00409 }
    00410
    00411 bool BERGeneralDecoder::EndReached() const
    00412 {
    00413         if (m_definiteLength)
    00414                 return m_length == 0;
    00415         else
    00416         {       // check end-of-content octets
    00417                 word16 i;
    00418                 return (m_inQueue.PeekWord16(i)==2 && i==0);
    00419         }
    00420 }
    00421
    00422 byte BERGeneralDecoder::PeekByte() const
    00423 {
    00424         byte b;
    00425         if (!Peek(b))
    00426                 BERDecodeError();
    00427         return b;
    00428 }
    00429
    00430 void BERGeneralDecoder::CheckByte(byte check)
    00431 {
    00432         byte b;
    00433         if (!Get(b) || b != check)
    00434                 BERDecodeError();
    00435 }
    00436
    00437 void BERGeneralDecoder::MessageEnd()
    00438 {
    00439         m_finished = true;
    00440         if (m_definiteLength)
    00441         {
    00442                 if (m_length != 0)
    00443                         BERDecodeError();
    00444         }
    00445         else
    00446         {       // remove end-of-content octets
    00447                 word16 i;
    00448                 if (m_inQueue.GetWord16(i) != 2 || i != 0)
    00449                         BERDecodeError();
    00450         }
    00451 }
    00452
    00453 size_t BERGeneralDecoder::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
    00454 {
    00455         if (m_definiteLength && transferBytes > m_length)
    00456                 transferBytes = m_length;
    00457         size_t blockedBytes = m_inQueue.TransferTo2(target, transferBytes, channel, blocking);
    00458         ReduceLength(transferBytes);
    00459         return blockedBytes;
    00460 }
    00461
    00462 size_t BERGeneralDecoder::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
    00463 {
    00464         if (m_definiteLength)
    00465                 end = STDMIN(m_length, end);
    00466         return m_inQueue.CopyRangeTo2(target, begin, end, channel, blocking);
    00467 }
    00468
    00469 lword BERGeneralDecoder::ReduceLength(lword delta)
    00470 {
    00471         if (m_definiteLength)
    00472         {
    00473                 if (m_length < delta)
    00474                         BERDecodeError();
    00475                 m_length -= delta;
    00476         }
    00477         return delta;
    00478 }
    00479
    00480 DERGeneralEncoder::DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag)
    00481         : m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
    00482 {
    00483 }
    00484
    00485 DERGeneralEncoder::DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag)
    00486         : m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
    00487 {
    00488 }
    00489
    00490 DERGeneralEncoder::~DERGeneralEncoder()
    00491 {
    00492         try     // avoid throwing in constructor
    00493         {
    00494                 if (!m_finished)
    00495                         MessageEnd();
    00496         }
    00497         catch (...)
    00498         {
    00499         }
    00500 }
    00501
    00502 void DERGeneralEncoder::MessageEnd()
    00503 {
    00504         m_finished = true;
    00505         lword length = CurrentSize();
    00506         m_outQueue.Put(m_asnTag);
    00507         DERLengthEncode(m_outQueue, length);
    00508         TransferTo(m_outQueue);
    00509 }
    00510
    00511 // *************************************************************
    00512
    00513 void X509PublicKey::BERDecode(BufferedTransformation &bt)
    00514 {
    00515         BERSequenceDecoder subjectPublicKeyInfo(bt);
    00516                 BERSequenceDecoder algorithm(subjectPublicKeyInfo);
    00517                         GetAlgorithmID().BERDecodeAndCheck(algorithm);
    00518                         bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);
    00519                 algorithm.MessageEnd();
    00520
    00521                 BERGeneralDecoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);
    00522                         subjectPublicKey.CheckByte(0);  // unused bits
    00523                         BERDecodePublicKey(subjectPublicKey, parametersPresent, (size_t)subjectPublicKey.RemainingLength());
    00524                 subjectPublicKey.MessageEnd();
    00525         subjectPublicKeyInfo.MessageEnd();
    00526 }
    00527
    00528 void X509PublicKey::DEREncode(BufferedTransformation &bt) const
    00529 {
    00530         DERSequenceEncoder subjectPublicKeyInfo(bt);
    00531
    00532                 DERSequenceEncoder algorithm(subjectPublicKeyInfo);
    00533                         GetAlgorithmID().DEREncode(algorithm);
    00534                         DEREncodeAlgorithmParameters(algorithm);
    00535                 algorithm.MessageEnd();
    00536
    00537                 DERGeneralEncoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);
    00538                         subjectPublicKey.Put(0);        // unused bits
    00539                         DEREncodePublicKey(subjectPublicKey);
    00540                 subjectPublicKey.MessageEnd();
    00541
    00542         subjectPublicKeyInfo.MessageEnd();
    00543 }
    00544
    00545 void PKCS8PrivateKey::BERDecode(BufferedTransformation &bt)
    00546 {
    00547         BERSequenceDecoder privateKeyInfo(bt);
    00548                 word32 version;
    00549                 BERDecodeUnsigned<word32>(privateKeyInfo, version, INTEGER, 0, 0);      // check version
    00550
    00551                 BERSequenceDecoder algorithm(privateKeyInfo);
    00552                         GetAlgorithmID().BERDecodeAndCheck(algorithm);
    00553                         bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);
    00554                 algorithm.MessageEnd();
    00555
    00556                 BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING);
    00557                         BERDecodePrivateKey(octetString, parametersPresent, (size_t)privateKeyInfo.RemainingLength());
    00558                 octetString.MessageEnd();
    00559
    00560                 if (!privateKeyInfo.EndReached())
    00561                         BERDecodeOptionalAttributes(privateKeyInfo);
    00562         privateKeyInfo.MessageEnd();
    00563 }
    00564
    00565 void PKCS8PrivateKey::DEREncode(BufferedTransformation &bt) const
    00566 {
    00567         DERSequenceEncoder privateKeyInfo(bt);
    00568                 DEREncodeUnsigned<word32>(privateKeyInfo, 0);   // version
    00569
    00570                 DERSequenceEncoder algorithm(privateKeyInfo);
    00571                         GetAlgorithmID().DEREncode(algorithm);
    00572                         DEREncodeAlgorithmParameters(algorithm);
    00573                 algorithm.MessageEnd();
    00574
    00575                 DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING);
    00576                         DEREncodePrivateKey(octetString);
    00577                 octetString.MessageEnd();
    00578
    00579                 DEREncodeOptionalAttributes(privateKeyInfo);
    00580         privateKeyInfo.MessageEnd();
    00581 }
    00582
    00583 void PKCS8PrivateKey::BERDecodeOptionalAttributes(BufferedTransformation &bt)
    00584 {
    00585         DERReencode(bt, m_optionalAttributes);
    00586 }
    00587
    00588 void PKCS8PrivateKey::DEREncodeOptionalAttributes(BufferedTransformation &bt) const
    00589 {
    00590         m_optionalAttributes.CopyTo(bt);
    00591 }
    00592
    00593 NAMESPACE_END
    00594
    00595 #endif