⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asn.cpp

📁 SSL加密库源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
  /* 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(&ltime);

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