Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

730 lines
18 KiB

// V2Card.cpp: implementation of the CV2Card class.
//
// (c) Copyright Schlumberger Technology Corp., unpublished work, created
// 1999. This computer program includes Confidential, Proprietary
// Information and is a Trade Secret of Schlumberger Technology Corp. All
// use, disclosure, and/or reproduction is prohibited unless authorized
// in writing. All Rights Reserved.
//////////////////////////////////////////////////////////////////////
#include "NoWarning.h"
#include <scuCast.h>
#include "TransactionWrap.h"
#include "V2Card.h"
#include "V2Cert.h"
#include "V2Cont.h"
#include "V2PriKey.h"
#include "V2PubKey.h"
#include "V2KeyPair.h"
#include "V2DataObj.h"
using namespace std;
using namespace cci;
using namespace scu;
/////////////////////////// LOCAL/HELPER /////////////////////////////////
namespace
{
// Functors to make a T for a given symbol id (handle/symbol id)
template<class T>
class MakerFunction
{
public:
typedef T ValueType;
virtual
~MakerFunction() throw()
{}
virtual auto_ptr<T>
operator()(SymbolID sid) const = 0;
protected:
MakerFunction(CV2Card const &rv2card)
: m_rv2card(rv2card)
{}
CV2Card const &m_rv2card;
};
template<class T>
class Maker2
: public MakerFunction<T>
{
public:
Maker2(CV2Card const &rv2card)
: MakerFunction<T>(rv2card)
{}
auto_ptr<T>
operator()(SymbolID sid) const
{
return auto_ptr<T>(new T(m_rv2card, sid));
}
};
template<class T>
class Maker3
: public MakerFunction<T>
{
public:
Maker3(CV2Card const &rv2card,
ObjectAccess oa)
: MakerFunction<T>(rv2card),
m_oa(oa)
{}
auto_ptr<T>
operator()(SymbolID sid) const
{
return auto_ptr<T>(new T(m_rv2card, sid, m_oa));
}
private:
ObjectAccess m_oa;
};
// Enumerate objects in the object info file of object type OT,
// returning a vector of R(object)
template<class R, ObjectType OT, class T>
vector<R>
EnumPriviledgedObjects(CObjectInfoFile &rObjInfo,
MakerFunction<T> &rMaker)
{
SymbolID sid = rObjInfo.FirstObject(OT);
vector<R> vResult;
while (sid)
{
auto_ptr<MakerFunction<T>::ValueType> apObject(rMaker(sid));
R Handle(apObject.get());
apObject.release(); // transfer ownership to handle
vResult.push_back(Handle);
sid = rObjInfo.NextObject(sid);
}
return vResult;
}
bool
IsSupported(iop::CSmartCard &rSmartCard) throw()
{
bool fSupported = false;
try
{
rSmartCard.Select("/3f00/0000");
rSmartCard.Select("/3f00/3f11/0020");
rSmartCard.Select("/3f00/3f11/0030");
rSmartCard.Select("/3f00/3f11/0031");
fSupported = true;
}
catch(scu::Exception &)
{}
return fSupported;
}
} // namespace
/////////////////////////// PUBLIC /////////////////////////////////
// Types
// C'tors/D'tors
CV2Card::~CV2Card() throw()
{}
// Operators
// Operations
void
CV2Card::ChangePIN(SecureArray<BYTE> const &rstrOldPIN,
SecureArray<BYTE> const &rstrNewPIN)
{
CTransactionWrap wrap(this);
SmartCard().Select(RootPath().c_str());
SuperClass::ChangePIN(rstrOldPIN, rstrNewPIN);
}
void
CV2Card::DefaultContainer(CContainer const &rcont)
{
SymbolID sid = 0;
if (rcont)
{
CV2Container &rv2cont = scu::DownCast<CV2Container &, CAbstractContainer &>(*rcont);
sid = rv2cont.Handle();
}
ObjectInfoFile(oaPublicAccess).DefaultContainer(sid);
}
pair<string, // interpreted as the public modulus
CPrivateKey>
CV2Card::GenerateKeyPair(KeyType kt,
string const &rsExponent,
ObjectAccess oaPrivateKey)
{
CTransactionWrap wrap(this);
// For the time being, assume this is implict RSA only....
string::size_type const cExponentLength = rsExponent.size();
if ((cExponentLength < 1) || (cExponentLength > 4))
throw Exception(ccInvalidParameter);
BYTE bKeyType;
switch (kt)
{
case ktRSA512:
bKeyType = CardKeyTypeRSA512;
break;
case ktRSA768:
bKeyType = CardKeyTypeRSA768;
break;
case ktRSA1024:
bKeyType = CardKeyTypeRSA1024;
break;
default:
throw Exception(ccBadKeySpec);
break;
}
// Allocated a slot in the key file, unless a correct one is
// already allocated?
CCardInfo &rci = this->CardInfo();
BYTE bKeyNum = rci.AllocatePrivateKey(bKeyType);
// Generate private key
this->SmartCard().Select(PrivateKeyPath(kt).c_str());
iop::CPublicKeyBlob pubkb(this->SmartCard().GenerateKeyPair(reinterpret_cast<BYTE const *>(rsExponent.data()),
static_cast<WORD>(cExponentLength),
bKeyNum,
kt));
this->SmartCard().Select(RootPath().c_str());
auto_ptr<CV2PrivateKey> apv2prikey(new CV2PrivateKey(*this,
bKeyType,
bKeyNum,
oaPrivateKey));
string sModulus(reinterpret_cast<char *>(pubkb.bModulus),
pubkb.bModulusLength);
return pair<string, CPrivateKey>(sModulus, apv2prikey.release());
}
void
CV2Card::InitCard()
{
CTransactionWrap wrap(this);
m_apCardInfo->Reset();
ObjectInfoFile(oaPublicAccess).Reset();
ObjectInfoFile(oaPrivateAccess).Reset();
}
void
CV2Card::InvalidateCache()
{
CTransactionWrap wrap(this);
m_apCardInfo->UpdateCache();
m_asLabel.Dirty();
m_apPublicObjectInfoFile = auto_ptr<CObjectInfoFile>(0);
m_apPrivateObjectInfoFile = auto_ptr<CObjectInfoFile>(0);
}
void
CV2Card::Label(string const &rLabel)
{
CTransactionWrap wrap(this);
m_apCardInfo->Label(rLabel);
m_asLabel.Value(rLabel);
}
void
CV2Card::VerifyKey(string const &rstrKey,
BYTE bKeyNum)
{
CTransactionWrap wrap(this);
SmartCard().Select(RootPath().c_str());
SuperClass::VerifyKey(rstrKey, bKeyNum);
}
// Access
size_t
CV2Card::AvailableStringSpace(ObjectAccess oa) const
{
CTransactionWrap wrap(this);
return ObjectInfoFile(oa).FreeSpace();
}
CCardInfo &
CV2Card::CardInfo() const
{
return *m_apCardInfo;
}
CContainer
CV2Card::DefaultContainer() const
{
CTransactionWrap wrap(this);
SymbolID sid = ObjectInfoFile(oaPublicAccess).DefaultContainer();
return sid
? CContainer(CV2Container::Make(*this, sid))
: CContainer();
}
vector<CContainer>
CV2Card::EnumContainers() const
{
CTransactionWrap wrap(this);
Maker2<CV2Container> Maker(*this);
return
EnumPriviledgedObjects<CContainer,
otContainerObject>(ObjectInfoFile(oaPublicAccess),
Maker);
}
vector<CCertificate>
CV2Card::EnumCertificates(ObjectAccess access) const
{
CTransactionWrap wrap(this);
Maker3<CV2Certificate> Maker(*this, access);
return
EnumPriviledgedObjects<CCertificate,
otCertificateObject>(ObjectInfoFile(access),
Maker);
}
vector<CPublicKey>
CV2Card::EnumPublicKeys(ObjectAccess access) const
{
CTransactionWrap wrap(this);
Maker3<CV2PublicKey> Maker(*this, access);
return
EnumPriviledgedObjects<CPublicKey,
otPublicKeyObject>(ObjectInfoFile(access),
Maker);
}
vector<CPrivateKey>
CV2Card::EnumPrivateKeys(ObjectAccess access) const
{
CTransactionWrap wrap(this);
Maker3<CV2PrivateKey> Maker(*this, access);
return
EnumPriviledgedObjects<CPrivateKey,
otPrivateKeyObject>(ObjectInfoFile(access),
Maker);
}
vector<CDataObject>
CV2Card::EnumDataObjects(ObjectAccess access) const
{
CTransactionWrap wrap(this);
Maker3<CV2DataObject> Maker(*this, access);
return
EnumPriviledgedObjects<CDataObject,
otDataObjectObject>(ObjectInfoFile(access),
Maker);
}
string
CV2Card::Label() const
{
CTransactionWrap wrap(this);
if (!m_asLabel.IsCached())
m_asLabel.Value(m_apCardInfo->Label());
return m_asLabel.Value();
}
CAbstractCertificate *
CV2Card::MakeCertificate(ObjectAccess oa) const
{
CTransactionWrap wrap(this);
return new CV2Certificate(*this, oa);
}
CAbstractContainer *
CV2Card::MakeContainer() const
{
CTransactionWrap wrap(this);
return new CV2Container(*this);
}
CAbstractDataObject *
CV2Card::MakeDataObject(ObjectAccess oa) const
{
CTransactionWrap wrap(this);
return new CV2DataObject(*this, oa);
}
CAbstractKeyPair *
CV2Card::MakeKeyPair(CContainer const &rhcont,
KeySpec ks) const
{
CTransactionWrap wrap(this);
return new CV2KeyPair(*this, rhcont, ks);
}
CAbstractPrivateKey *
CV2Card::MakePrivateKey(ObjectAccess oa) const
{
CTransactionWrap wrap(this);
return new CV2PrivateKey(*this, oa);
}
CAbstractPublicKey *
CV2Card::MakePublicKey(ObjectAccess oa) const
{
CTransactionWrap wrap(this);
return new CV2PublicKey(*this, oa);
}
BYTE
CV2Card::MaxKeys(KeyType kt) const
{
BYTE bCount;
switch (kt)
{
case ktRSA512:
bCount = m_apCardInfo->NumRSA512Keys();
break;
case ktRSA768:
bCount = m_apCardInfo->NumRSA768Keys();
break;
case ktRSA1024:
bCount = m_apCardInfo->NumRSA1024Keys();
break;
default:
bCount = 0;
break;
}
return bCount;
}
size_t
CV2Card::MaxStringSpace(ObjectAccess oa) const
{
return ObjectInfoFile(oa).TableSize();
}
string
CV2Card::PrivateKeyPath(KeyType kt) const
{
string sPrivateKeyPath(RootPath());
switch (kt)
{
case ktRSA512:
sPrivateKeyPath += "3f01";
break;
case ktRSA768:
sPrivateKeyPath += "3f02";
break;
case ktRSA1024:
sPrivateKeyPath += "3f03";
break;
default:
throw Exception(ccBadKeySpec);
break;
}
return sPrivateKeyPath;
}
string const &
CV2Card::RootPath() const
{
static string const sRootPath("/3f00/3f11/");
return sRootPath;
}
bool
CV2Card::SupportedKeyFunction(KeyType kt,
CardOperation oper) const
{
bool fSupported = false;
switch (oper)
{
case coEncryption: // .. or public key operations
switch (kt)
{
case ktRSA512:
case ktRSA768:
case ktRSA1024:
fSupported = false;
break;
default:
fSupported = false;
break;
}
case coDecryption: // .. or private key operations
switch (kt)
{
case ktRSA512:
case ktRSA768:
case ktRSA1024:
fSupported = true;
break;
default:
fSupported = false;
break;
}
case coKeyGeneration:
switch (kt)
{
case ktRSA512:
case ktRSA768:
case ktRSA1024:
{
BYTE flag = m_apCardInfo->UsagePolicy();
fSupported = BitSet(&flag, CardKeyGenSupportedFlag);
break;
}
default:
break;
}
default:
break;
}
return fSupported;
}
scu::Marker<unsigned int>
CV2Card::MarkerOnCard() const
{
// Security: in order to avoid using the insecure mapped file
// object we use a marker on the card. This reduces efficiency but
// improves security. We use the last 4 butes (RFU) from the
// object info file of the 0030 file. The 0030 file is readable
// but write protected by the user pin.
WORD wOffset = 6;// the last 4 out of 10 bytes will be used
unsigned int nMarker = 0;
const WORD wBufLength = 4;
CTransactionWrap wrap(this);
this->SmartCard().Select("/3f00/3f11/0030");
this->SmartCard().ReadBinary(wOffset,
wBufLength,
(BYTE*)&nMarker);
if(this->SmartCard().Dirty())
{
// Information was written to the card. Update the marker
nMarker++;
this->SmartCard().WriteBinary(wOffset,
wBufLength,
(BYTE*)&nMarker);
}
return scu::Marker<unsigned int>(nMarker);
}
// Predicates
bool
CV2Card::IsCAPIEnabled() const
{
BYTE flag = m_apCardInfo->UsagePolicy();
return BitSet(&flag,CardCryptoAPIEnabledFlag);
}
bool
CV2Card::IsPKCS11Enabled() const
{
BYTE flag = m_apCardInfo->UsagePolicy();
return BitSet(&flag,CardPKCS11EnabledFlag);
}
bool
CV2Card::IsProtectedMode() const
{
BYTE flag = m_apCardInfo->UsagePolicy();
return BitSet(&flag,CardProtectedWriteFlag);
}
bool
CV2Card::IsKeyGenEnabled() const
{
BYTE flag = m_apCardInfo->UsagePolicy();
return BitSet(&flag,CardKeyGenSupportedFlag);
}
bool
CV2Card::IsEntrustEnabled() const
{
BYTE flag = m_apCardInfo->UsagePolicy();
return BitSet(&flag,CardEntrustEnabledFlag);
}
BYTE
CV2Card::MajorVersion() const
{
return m_apCardInfo->FormatVersion().bMajor;
}
bool
CV2Card::IsMarkerOnCard() const
{
return true;
}
// Static Variables
/////////////////////////// PROTECTED /////////////////////////////////
// C'tors/D'tors
CV2Card::CV2Card(string const &rstrReaderName,
auto_ptr<iop::CIOP> &rapiop,
auto_ptr<iop::CSmartCard> &rapSmartCard)
: SuperClass(rstrReaderName, rapiop, rapSmartCard),
m_apCardInfo(auto_ptr<CCardInfo>(new CCardInfo(*rapSmartCard.get()))),
m_apPublicObjectInfoFile(),
m_apPrivateObjectInfoFile(),
m_asLabel()
{}
// Operators
// Operations
void
CV2Card::DoSetup()
{
CAbstractCard::DoSetup();
m_apCardInfo->UpdateCache();
}
// Access
// Predicates
// Static Variables
/////////////////////////// PRIVATE /////////////////////////////////
// C'tors/D'tors
// Operators
// Operations
auto_ptr<CAbstractCard>
CV2Card::DoMake(string const &rstrReaderName,
auto_ptr<iop::CIOP> &rapiop,
auto_ptr<iop::CSmartCard> &rapSmartCard)
{
return IsSupported(*rapSmartCard.get())
? auto_ptr<CAbstractCard>(new CV2Card(rstrReaderName, rapiop,
rapSmartCard))
: auto_ptr<CAbstractCard>(0);
}
// Access
CObjectInfoFile &
CV2Card::ObjectInfoFile(ObjectAccess oa) const
{
CObjectInfoFile *poif;
switch (oa)
{
case oaPublicAccess:
if (!m_apPublicObjectInfoFile.get())
{
m_apPublicObjectInfoFile =
auto_ptr<CObjectInfoFile>(new
CObjectInfoFile(SmartCard(),
"/3f00/3f11/0030",
oa));
m_apPublicObjectInfoFile->UpdateCache();
}
poif = m_apPublicObjectInfoFile.get();
break;
case oaPrivateAccess:
if (!m_apPrivateObjectInfoFile.get())
{
m_apPrivateObjectInfoFile =
auto_ptr<CObjectInfoFile>(new
CObjectInfoFile(SmartCard(),
"/3f00/3f11/0031",
oa));
m_apPrivateObjectInfoFile->UpdateCache();
}
poif = m_apPrivateObjectInfoFile.get();
break;
default:
throw Exception(ccBadAccessSpec);
}
return *poif;
}
// Predicates
// Static Variables