• 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                 if (v >> (8*sizeof(v)-7))       // v about to overflow
00236                         BERDecodeError();
00237                 v <<= 7;
00238                 v += b & 0x7f;
00239                 if (!(b & 0x80))
00240                         return i;
00241         }
00242 }
00243 
00244 void OID::DEREncode(BufferedTransformation &bt) const
00245 {
00246         assert(m_values.size() >= 2);
00247         ByteQueue temp;
00248         temp.Put(byte(m_values[0] * 40 + m_values[1]));
00249         for (size_t i=2; i<m_values.size(); i++)
00250                 EncodeValue(temp, m_values[i]);
00251         bt.Put(OBJECT_IDENTIFIER);
00252         DERLengthEncode(bt, temp.CurrentSize());
00253         temp.TransferTo(bt);
00254 }
00255 
00256 void OID::BERDecode(BufferedTransformation &bt)
00257 {
00258         byte b;
00259         if (!bt.Get(b) || b != OBJECT_IDENTIFIER)
00260                 BERDecodeError();
00261 
00262         size_t length;
00263         if (!BERLengthDecode(bt, length) || length < 1)
00264                 BERDecodeError();
00265 
00266         if (!bt.Get(b))
00267                 BERDecodeError();
00268         
00269         length--;
00270         m_values.resize(2);
00271         m_values[0] = b / 40;
00272         m_values[1] = b % 40;
00273 
00274         while (length > 0)
00275         {
00276                 word32 v;
00277                 size_t valueLen = DecodeValue(bt, v);
00278                 if (valueLen > length)
00279                         BERDecodeError();
00280                 m_values.push_back(v);
00281                 length -= valueLen;
00282         }
00283 }
00284 
00285 void OID::BERDecodeAndCheck(BufferedTransformation &bt) const
00286 {
00287         OID oid(bt);
00288         if (*this != oid)
00289                 BERDecodeError();
00290 }
00291 
00292 inline BufferedTransformation & EncodedObjectFilter::CurrentTarget()
00293 {
00294         if (m_flags & PUT_OBJECTS) 
00295                 return *AttachedTransformation();
00296         else
00297                 return TheBitBucket();
00298 }
00299 
00300 void EncodedObjectFilter::Put(const byte *inString, size_t length)
00301 {
00302         if (m_nCurrentObject == m_nObjects)
00303         {
00304                 AttachedTransformation()->Put(inString, length);
00305                 return;
00306         }
00307 
00308         LazyPutter lazyPutter(m_queue, inString, length);
00309 
00310         while (m_queue.AnyRetrievable())
00311         {
00312                 switch (m_state)
00313                 {
00314                 case IDENTIFIER:
00315                         if (!m_queue.Get(m_id))
00316                                 return;
00317                         m_queue.TransferTo(CurrentTarget(), 1);
00318                         m_state = LENGTH;       // fall through
00319                 case LENGTH:
00320                 {
00321                         byte b;
00322                         if (m_level > 0 && m_id == 0 && m_queue.Peek(b) && b == 0)
00323                         {
00324                                 m_queue.TransferTo(CurrentTarget(), 1);
00325                                 m_level--;
00326                                 m_state = IDENTIFIER;
00327                                 break;
00328                         }
00329                         ByteQueue::Walker walker(m_queue);
00330                         bool definiteLength;
00331                         if (!BERLengthDecode(walker, m_lengthRemaining, definiteLength))
00332                                 return;
00333                         m_queue.TransferTo(CurrentTarget(), walker.GetCurrentPosition());
00334                         if (!((m_id & CONSTRUCTED) || definiteLength))
00335                                 BERDecodeError();
00336                         if (!definiteLength)
00337                         {
00338                                 if (!(m_id & CONSTRUCTED))
00339                                         BERDecodeError();
00340                                 m_level++;
00341                                 m_state = IDENTIFIER;
00342                                 break;
00343                         }
00344                         m_state = BODY;         // fall through
00345                 }
00346                 case BODY:
00347                         m_lengthRemaining -= m_queue.TransferTo(CurrentTarget(), m_lengthRemaining);
00348 
00349                         if (m_lengthRemaining == 0)
00350                                 m_state = IDENTIFIER;
00351                 }
00352 
00353                 if (m_state == IDENTIFIER && m_level == 0)
00354                 {
00355                         // just finished processing a level 0 object
00356                         ++m_nCurrentObject;
00357 
00358                         if (m_flags & PUT_MESSANGE_END_AFTER_EACH_OBJECT)
00359                                 AttachedTransformation()->MessageEnd();
00360 
00361                         if (m_nCurrentObject == m_nObjects)
00362                         {
00363                                 if (m_flags & PUT_MESSANGE_END_AFTER_ALL_OBJECTS)
00364                                         AttachedTransformation()->MessageEnd();
00365 
00366                                 if (m_flags & PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS)
00367                                         AttachedTransformation()->MessageSeriesEnd();
00368 
00369                                 m_queue.TransferAllTo(*AttachedTransformation());
00370                                 return;
00371                         }
00372                 }
00373         }
00374 }
00375 
00376 BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag)
00377         : m_inQueue(inQueue), m_finished(false)
00378 {
00379         Init(asnTag);
00380 }
00381 
00382 BERGeneralDecoder::BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag)
00383         : m_inQueue(inQueue), m_finished(false)
00384 {
00385         Init(asnTag);
00386 }
00387 
00388 void BERGeneralDecoder::Init(byte asnTag)
00389 {
00390         byte b;
00391         if (!m_inQueue.Get(b) || b != asnTag)
00392                 BERDecodeError();
00393 
00394         if (!BERLengthDecode(m_inQueue, m_length, m_definiteLength))
00395                 BERDecodeError();
00396 
00397         if (!m_definiteLength && !(asnTag & CONSTRUCTED))
00398                 BERDecodeError();       // cannot be primitive and have indefinite length
00399 }
00400 
00401 BERGeneralDecoder::~BERGeneralDecoder()
00402 {
00403         try     // avoid throwing in constructor
00404         {
00405                 if (!m_finished)
00406                         MessageEnd();
00407         }
00408         catch (...)
00409         {
00410         }
00411 }
00412 
00413 bool BERGeneralDecoder::EndReached() const
00414 {
00415         if (m_definiteLength)
00416                 return m_length == 0;
00417         else
00418         {       // check end-of-content octets
00419                 word16 i;
00420                 return (m_inQueue.PeekWord16(i)==2 && i==0);
00421         }
00422 }
00423 
00424 byte BERGeneralDecoder::PeekByte() const
00425 {
00426         byte b;
00427         if (!Peek(b))
00428                 BERDecodeError();
00429         return b;
00430 }
00431 
00432 void BERGeneralDecoder::CheckByte(byte check)
00433 {
00434         byte b;
00435         if (!Get(b) || b != check)
00436                 BERDecodeError();
00437 }
00438 
00439 void BERGeneralDecoder::MessageEnd()
00440 {
00441         m_finished = true;
00442         if (m_definiteLength)
00443         {
00444                 if (m_length != 0)
00445                         BERDecodeError();
00446         }
00447         else
00448         {       // remove end-of-content octets
00449                 word16 i;
00450                 if (m_inQueue.GetWord16(i) != 2 || i != 0)
00451                         BERDecodeError();
00452         }
00453 }
00454 
00455 size_t BERGeneralDecoder::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
00456 {
00457         if (m_definiteLength && transferBytes > m_length)
00458                 transferBytes = m_length;
00459         size_t blockedBytes = m_inQueue.TransferTo2(target, transferBytes, channel, blocking);
00460         ReduceLength(transferBytes);
00461         return blockedBytes;
00462 }
00463 
00464 size_t BERGeneralDecoder::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
00465 {
00466         if (m_definiteLength)
00467                 end = STDMIN(m_length, end);
00468         return m_inQueue.CopyRangeTo2(target, begin, end, channel, blocking);
00469 }
00470 
00471 lword BERGeneralDecoder::ReduceLength(lword delta)
00472 {
00473         if (m_definiteLength)
00474         {
00475                 if (m_length < delta)
00476                         BERDecodeError();
00477                 m_length -= delta;
00478         }
00479         return delta;
00480 }
00481 
00482 DERGeneralEncoder::DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag)
00483         : m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
00484 {
00485 }
00486 
00487 DERGeneralEncoder::DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag)
00488         : m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
00489 {
00490 }
00491 
00492 DERGeneralEncoder::~DERGeneralEncoder()
00493 {
00494         try     // avoid throwing in constructor
00495         {
00496                 if (!m_finished)
00497                         MessageEnd();
00498         }
00499         catch (...)
00500         {
00501         }
00502 }
00503 
00504 void DERGeneralEncoder::MessageEnd()
00505 {
00506         m_finished = true;
00507         lword length = CurrentSize();
00508         m_outQueue.Put(m_asnTag);
00509         DERLengthEncode(m_outQueue, length);
00510         TransferTo(m_outQueue);
00511 }
00512 
00513 // *************************************************************
00514 
00515 void X509PublicKey::BERDecode(BufferedTransformation &bt)
00516 {
00517         BERSequenceDecoder subjectPublicKeyInfo(bt);
00518                 BERSequenceDecoder algorithm(subjectPublicKeyInfo);
00519                         GetAlgorithmID().BERDecodeAndCheck(algorithm);
00520                         bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);
00521                 algorithm.MessageEnd();
00522 
00523                 BERGeneralDecoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);
00524                         subjectPublicKey.CheckByte(0);  // unused bits
00525                         BERDecodePublicKey(subjectPublicKey, parametersPresent, (size_t)subjectPublicKey.RemainingLength());
00526                 subjectPublicKey.MessageEnd();
00527         subjectPublicKeyInfo.MessageEnd();
00528 }
00529 
00530 void X509PublicKey::DEREncode(BufferedTransformation &bt) const
00531 {
00532         DERSequenceEncoder subjectPublicKeyInfo(bt);
00533 
00534                 DERSequenceEncoder algorithm(subjectPublicKeyInfo);
00535                         GetAlgorithmID().DEREncode(algorithm);
00536                         DEREncodeAlgorithmParameters(algorithm);
00537                 algorithm.MessageEnd();
00538 
00539                 DERGeneralEncoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);
00540                         subjectPublicKey.Put(0);        // unused bits
00541                         DEREncodePublicKey(subjectPublicKey);
00542                 subjectPublicKey.MessageEnd();
00543 
00544         subjectPublicKeyInfo.MessageEnd();
00545 }
00546 
00547 void PKCS8PrivateKey::BERDecode(BufferedTransformation &bt)
00548 {
00549         BERSequenceDecoder privateKeyInfo(bt);
00550                 word32 version;
00551                 BERDecodeUnsigned<word32>(privateKeyInfo, version, INTEGER, 0, 0);      // check version
00552 
00553                 BERSequenceDecoder algorithm(privateKeyInfo);
00554                         GetAlgorithmID().BERDecodeAndCheck(algorithm);
00555                         bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);
00556                 algorithm.MessageEnd();
00557 
00558                 BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING);
00559                         BERDecodePrivateKey(octetString, parametersPresent, (size_t)privateKeyInfo.RemainingLength());
00560                 octetString.MessageEnd();
00561 
00562                 if (!privateKeyInfo.EndReached())
00563                         BERDecodeOptionalAttributes(privateKeyInfo);
00564         privateKeyInfo.MessageEnd();
00565 }
00566 
00567 void PKCS8PrivateKey::DEREncode(BufferedTransformation &bt) const
00568 {
00569         DERSequenceEncoder privateKeyInfo(bt);
00570                 DEREncodeUnsigned<word32>(privateKeyInfo, 0);   // version
00571 
00572                 DERSequenceEncoder algorithm(privateKeyInfo);
00573                         GetAlgorithmID().DEREncode(algorithm);
00574                         DEREncodeAlgorithmParameters(algorithm);
00575                 algorithm.MessageEnd();
00576 
00577                 DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING);
00578                         DEREncodePrivateKey(octetString);
00579                 octetString.MessageEnd();
00580 
00581                 DEREncodeOptionalAttributes(privateKeyInfo);
00582         privateKeyInfo.MessageEnd();
00583 }
00584 
00585 void PKCS8PrivateKey::BERDecodeOptionalAttributes(BufferedTransformation &bt)
00586 {
00587         DERReencode(bt, m_optionalAttributes);
00588 }
00589 
00590 void PKCS8PrivateKey::DEREncodeOptionalAttributes(BufferedTransformation &bt) const
00591 {
00592         m_optionalAttributes.CopyTo(bt);
00593 }
00594 
00595 NAMESPACE_END
00596 
00597 #endif

Generated on Mon Aug 9 2010 15:56:32 for Crypto++ by  doxygen 1.7.1