📄 asn.cpp
字号:
/* asn.cpp
*
* Copyright (C) 2003 Sawtooth Consulting Ltd.
*
* This file is part of yaSSL, an SSL implementation written by Todd A Ouska
* (todd at yassl.com, see www.yassl.com).
*
* yaSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to yaSSL. View the full text of the exception in the file
* FLOSS-EXCEPTIONS in the directory of this software distribution.
*
* yaSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
/* asn.cpp implements ASN1 BER, PublicKey, and x509v3 decoding
*/
#include "runtime.hpp"
#include "asn.hpp"
#include "file.hpp"
#include "integer.hpp"
#include "rsa.hpp"
#include "dsa.hpp"
#include "dh.hpp"
#include "md5.hpp"
#include "md2.hpp"
#include "sha.hpp"
#include "coding.hpp"
#include <time.h> // gmtime();
#include "memory.hpp" // some auto_ptr don't have reset, also need auto_array
namespace TaoCrypt {
namespace { // locals
// to the minute
bool operator>(tm& a, tm& b)
{
if (a.tm_year > b.tm_year)
return true;
if (a.tm_year == b.tm_year && a.tm_mon > b.tm_mon)
return true;
if (a.tm_year == b.tm_year && a.tm_mon == b.tm_mon && a.tm_mday >b.tm_mday)
return true;
if (a.tm_year == b.tm_year && a.tm_mon == b.tm_mon &&
a.tm_mday == b.tm_mday && a.tm_hour > b.tm_hour)
return true;
if (a.tm_year == b.tm_year && a.tm_mon == b.tm_mon &&
a.tm_mday == b.tm_mday && a.tm_hour == b.tm_hour &&
a.tm_min > b.tm_min)
return true;
return false;
}
bool operator<(tm& a, tm&b)
{
return !(a>b);
}
// like atoi but only use first byte
word32 btoi(byte b)
{
return b - 0x30;
}
// two byte date/time, add to value
void GetTime(int& value, const byte* date, int& i)
{
value += btoi(date[i++]) * 10;
value += btoi(date[i++]);
}
// Make sure before and after dates are valid
bool ValidateDate(const byte* date, byte format, CertDecoder::DateType dt)
{
tm certTime;
memset(&certTime, 0, sizeof(certTime));
int i = 0;
if (format == UTC_TIME) {
if (btoi(date[0]) >= 5)
certTime.tm_year = 1900;
else
certTime.tm_year = 2000;
}
else { // format == GENERALIZED_TIME
certTime.tm_year += btoi(date[i++]) * 1000;
certTime.tm_year += btoi(date[i++]) * 100;
}
GetTime(certTime.tm_year, date, i); certTime.tm_year -= 1900; // adjust
GetTime(certTime.tm_mon, date, i); certTime.tm_mon -= 1; // adjust
GetTime(certTime.tm_mday, date, i);
GetTime(certTime.tm_hour, date, i);
GetTime(certTime.tm_min, date, i);
GetTime(certTime.tm_sec, date, i);
assert(date[i] == 'Z'); // only Zulu supported for this profile
time_t ltime = time(0);
tm* localTime = gmtime(<ime);
if (dt == CertDecoder::BEFORE) {
if (*localTime < certTime)
return false;
}
else
if (*localTime > certTime)
return false;
return true;
}
class BadCertificate {};
} // local namespace
// used by Integer as well
word32 GetLength(Source& source)
{
word32 length = 0;
byte b = source.next();
if (b >= LONG_LENGTH) {
word32 bytes = b & 0x7F;
while (bytes--) {
b = source.next();
length = (length << 8) | b;
}
}
else
length = b;
return length;
}
word32 SetLength(word32 length, byte* output)
{
word32 i = 0;
if (length < LONG_LENGTH)
output[i++] = length;
else {
output[i++] = BytePrecision(length) | 0x80;
for (int j = BytePrecision(length); j; --j) {
output[i] = length >> (j - 1) * 8;
i++;
}
}
return i;
}
PublicKey::PublicKey(const byte* k, word32 s) : key_(0), sz_(0)
{
if (s) {
SetSize(s);
SetKey(k);
}
}
void PublicKey::SetSize(word32 s)
{
sz_ = s;
key_ = NEW_TC byte[sz_];
}
void PublicKey::SetKey(const byte* k)
{
memcpy(key_, k, sz_);
}
void PublicKey::AddToEnd(const byte* data, word32 len)
{
mySTL::auto_array<byte> tmp(NEW_TC byte[sz_ + len]);
memcpy(tmp.get(), key_, sz_);
memcpy(tmp.get() + sz_, data, len);
byte* del = 0;
STL::swap(del, key_);
tcArrayDelete(del);
key_ = tmp.release();
sz_ += len;
}
Signer::Signer(const byte* k, word32 kSz, const char* n, const byte* h)
: key_(k, kSz)
{
size_t sz = strlen(n);
memcpy(name_, n, sz);
name_[sz] = 0;
memcpy(hash_, h, SHA::DIGEST_SIZE);
}
Signer::~Signer()
{
}
Error BER_Decoder::GetError()
{
return source_.GetError();
}
Integer& BER_Decoder::GetInteger(Integer& integer)
{
if (!source_.GetError().What())
integer.Decode(source_);
return integer;
}
// Read a Sequence, return length
word32 BER_Decoder::GetSequence()
{
if (source_.GetError().What()) return 0;
byte b = source_.next();
if (b != (SEQUENCE | CONSTRUCTED)) {
source_.SetError(SEQUENCE_E);
return 0;
}
return GetLength(source_);
}
// Read a Sequence, return length
word32 BER_Decoder::GetSet()
{
if (source_.GetError().What()) return 0;
byte b = source_.next();
if (b != (SET | CONSTRUCTED)) {
source_.SetError(SET_E);
return 0;
}
return GetLength(source_);
}
// Read Version, return it
word32 BER_Decoder::GetVersion()
{
if (source_.GetError().What()) return 0;
byte b = source_.next();
if (b != INTEGER) {
source_.SetError(INTEGER_E);
return 0;
}
b = source_.next();
if (b != 0x01) {
source_.SetError(VERSION_E);
return 0;
}
return source_.next();
}
// Read ExplicitVersion, return it or 0 if not there (not an error)
word32 BER_Decoder::GetExplicitVersion()
{
if (source_.GetError().What()) return 0;
byte b = source_.next();
if (b == (CONTEXT_SPECIFIC | CONSTRUCTED)) { // not an error if not here
source_.next();
return GetVersion();
}
else
source_.prev(); // put back
return 0;
}
// Decode a BER encoded RSA Private Key
void RSA_Private_Decoder::Decode(RSA_PrivateKey& key)
{
ReadHeader();
if (source_.GetError().What()) return;
// public
key.SetModulus(GetInteger(Integer().Ref()));
key.SetPublicExponent(GetInteger(Integer().Ref()));
// private
key.SetPrivateExponent(GetInteger(Integer().Ref()));
key.SetPrime1(GetInteger(Integer().Ref()));
key.SetPrime2(GetInteger(Integer().Ref()));
key.SetModPrime1PrivateExponent(GetInteger(Integer().Ref()));
key.SetModPrime2PrivateExponent(GetInteger(Integer().Ref()));
key.SetMultiplicativeInverseOfPrime2ModPrime1(GetInteger(Integer().Ref()));
}
void RSA_Private_Decoder::ReadHeader()
{
GetSequence();
GetVersion();
}
// Decode a BER encoded DSA Private Key
void DSA_Private_Decoder::Decode(DSA_PrivateKey& key)
{
ReadHeader();
if (source_.GetError().What()) return;
// group parameters
key.SetModulus(GetInteger(Integer().Ref()));
key.SetSubGroupOrder(GetInteger(Integer().Ref()));
key.SetSubGroupGenerator(GetInteger(Integer().Ref()));
// key
key.SetPublicPart(GetInteger(Integer().Ref()));
key.SetPrivatePart(GetInteger(Integer().Ref()));
}
void DSA_Private_Decoder::ReadHeader()
{
GetSequence();
GetVersion();
}
// Decode a BER encoded RSA Public Key
void RSA_Public_Decoder::Decode(RSA_PublicKey& key)
{
ReadHeader();
if (source_.GetError().What()) return;
// public key
key.SetModulus(GetInteger(Integer().Ref()));
key.SetPublicExponent(GetInteger(Integer().Ref()));
}
void RSA_Public_Decoder::ReadHeader()
{
GetSequence();
}
// Decode a BER encoded DSA Public Key
void DSA_Public_Decoder::Decode(DSA_PublicKey& key)
{
ReadHeader();
if (source_.GetError().What()) return;
// group parameters
key.SetModulus(GetInteger(Integer().Ref()));
key.SetSubGroupOrder(GetInteger(Integer().Ref()));
key.SetSubGroupGenerator(GetInteger(Integer().Ref()));
// key
key.SetPublicPart(GetInteger(Integer().Ref()));
}
void DSA_Public_Decoder::ReadHeader()
{
GetSequence();
}
void DH_Decoder::ReadHeader()
{
GetSequence();
}
// Decode a BER encoded Diffie-Hellman Key
void DH_Decoder::Decode(DH& key)
{
ReadHeader();
if (source_.GetError().What()) return;
// group parms
key.SetP(GetInteger(Integer().Ref()));
key.SetG(GetInteger(Integer().Ref()));
}
CertDecoder::CertDecoder(Source& s, bool decode, SignerList* signers,
bool noVerify, CertType ct)
: BER_Decoder(s), certBegin_(0), sigIndex_(0), sigLength_(0),
signature_(0), verify_(!noVerify)
{
issuer_[0] = 0;
subject_[0] = 0;
if (decode)
Decode(signers, ct);
}
CertDecoder::~CertDecoder()
{
tcArrayDelete(signature_);
}
// process certificate header, set signature offset
void CertDecoder::ReadHeader()
{
if (source_.GetError().What()) return;
GetSequence(); // total
certBegin_ = source_.get_index();
sigIndex_ = GetSequence(); // this cert
sigIndex_ += source_.get_index();
GetExplicitVersion(); // version
GetInteger(Integer().Ref()); // serial number
}
// Decode a x509v3 Certificate
void CertDecoder::Decode(SignerList* signers, CertType ct)
{
if (source_.GetError().What()) return;
DecodeToKey();
if (source_.GetError().What()) return;
if (source_.get_index() != sigIndex_)
source_.set_index(sigIndex_);
word32 confirmOID = GetAlgoId();
GetSignature();
if (source_.GetError().What()) return;
if ( confirmOID != signatureOID_ ) {
source_.SetError(SIG_OID_E);
return;
}
if (ct != CA && verify_ && !ValidateSignature(signers))
source_.SetError(SIG_OTHER_E);
}
void CertDecoder::DecodeToKey()
{
ReadHeader();
signatureOID_ = GetAlgoId();
GetName(ISSUER);
GetValidity();
GetName(SUBJECT);
GetKey();
}
// Read public key
void CertDecoder::GetKey()
{
if (source_.GetError().What()) return;
GetSequence();
keyOID_ = GetAlgoId();
if (keyOID_ == RSAk) {
byte b = source_.next();
if (b != BIT_STRING) {
source_.SetError(BIT_STR_E);
return;
}
b = source_.next(); // length, future
b = source_.next();
while(b != 0)
b = source_.next();
}
else if (keyOID_ == DSAk)
; // do nothing
else {
source_.SetError(UNKNOWN_OID_E);
return;
}
StoreKey();
if (keyOID_ == DSAk)
AddDSA();
}
// Save public key
void CertDecoder::StoreKey()
{
if (source_.GetError().What()) return;
word32 read = source_.get_index();
word32 length = GetSequence();
read = source_.get_index() - read;
length += read;
while (read--) source_.prev();
key_.SetSize(length);
key_.SetKey(source_.get_current());
source_.advance(length);
}
// DSA has public key after group
void CertDecoder::AddDSA()
{
if (source_.GetError().What()) return;
byte b = source_.next();
if (b != BIT_STRING) {
source_.SetError(BIT_STR_E);
return;
}
b = source_.next(); // length, future
b = source_.next();
while(b != 0)
b = source_.next();
word32 idx = source_.get_index();
b = source_.next();
if (b != INTEGER) {
source_.SetError(INTEGER_E);
return;
}
word32 length = GetLength(source_);
length += source_.get_index() - idx;
key_.AddToEnd(source_.get_buffer() + idx, length);
}
// process algo OID by summing, return it
word32 CertDecoder::GetAlgoId()
{
if (source_.GetError().What()) return 0;
word32 length = GetSequence();
byte b = source_.next();
if (b != OBJECT_IDENTIFIER) {
source_.SetError(OBJECT_ID_E);
return 0;
}
length = GetLength(source_);
word32 oid = 0;
while(length--)
oid += source_.next(); // just sum it up for now
// could have NULL tag and 0 terminator, but may not
b = source_.next();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -