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 = 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

Generated on Sat Dec 23 02:07:05 2006 for Crypto++ by  doxygen 1.5.1-p1