Crypto++
|
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