// RsaKPGen.cpp -- Rsa Key Pair Generator class definition // (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 "ForceLib.h" #include #include // for _alloca #include #include #include #include "RsaKPGen.h" #include "Blob.h" #include "AuxContext.h" #include "MsRsaPriKB.h" #include "PublicKeyHelper.h" using namespace std; using namespace cci; /////////////////////////// LOCAL/HELPER ///////////////////////////////// namespace { KeyType AsKeyType(RsaKey::StrengthType st) { KeyType kt; switch (st) { case 512: kt = ktRSA512; break; case 768: kt = ktRSA768; break; case 1024: kt = ktRSA1024; break; default: throw scu::OsException(ERROR_INVALID_PARAMETER); break; } return kt; } DWORD DefaultPublicExponent() { return 0x00010001; // same as Microsoft providers } pair KeyPair(CPrivateKey const &rhprikey, Blob const &rblbOrigModulus, // little endian Blob const &rblbOrigExponent) // little endian { CPublicKey hpubkey(AsPublicKey(rblbOrigModulus, rblbOrigExponent, rhprikey->Card())); return pair(rhprikey, hpubkey); } void ValidateCard(CCard const &rhcard) { if (!rhcard) throw scu::OsException(ERROR_INVALID_PARAMETER); } void ValidateStrength(RsaKey::StrengthType strength) { if (!IsValidRsaKeyStrength(strength)) throw scu::OsException(ERROR_INVALID_PARAMETER); } bool IsEmpty(std::pair const &rhs) { return !rhs.first || !rhs.second; } } /////////////////////////// PUBLIC ///////////////////////////////// // Types // C'tors/D'tors RsaKeyPairGenerator::RsaKeyPairGenerator(CCard const &rhcard, RsaKey::StrengthType strength) : m_hcard(rhcard), m_kp(), m_strength(strength) { ValidateParameters(); } RsaKeyPairGenerator::~RsaKeyPairGenerator() {} // Operators pair RsaKeyPairGenerator::operator()() const { if (IsEmpty(m_kp)) Generate(); return m_kp; } // Operations void RsaKeyPairGenerator::Card(CCard const &rhcard) { if (m_hcard != rhcard) { ValidateCard(rhcard); Reset(); m_hcard = rhcard; } } void RsaKeyPairGenerator::Reset() { m_kp = pair(); } void RsaKeyPairGenerator::Strength(RsaKey::StrengthType strength) { if (m_strength != strength) { ValidateStrength(strength); Reset(); m_strength = strength; } } // Access CCard RsaKeyPairGenerator::Card() const { return m_hcard; } bool RsaKeyPairGenerator::OnCard() const { return m_hcard->SupportedKeyFunction(AsKeyType(m_strength), coKeyGeneration); } RsaKey::StrengthType RsaKeyPairGenerator::Strength() const { return m_strength; } // Predicates // Static Variables /////////////////////////// PROTECTED ///////////////////////////////// // C'tors/D'tors // Operators // Operations // Access // Predicates // Static Variables /////////////////////////// PRIVATE ///////////////////////////////// // C'tors/D'tors // Operators // Operations void RsaKeyPairGenerator::Generate() const { KeyType kt = AsKeyType(m_strength); m_kp = OnCard() ? GenerateOnCard(kt) : GenerateInSoftware(); } pair RsaKeyPairGenerator::GenerateInSoftware() const { AuxContext auxcontext; DWORD dwFlags; // strength (bit length) is the high-order word dwFlags = m_strength; dwFlags = dwFlags << (numeric_limits::digits / 2); dwFlags |= CRYPT_EXPORTABLE; HCRYPTKEY hcryptkey; if (!CryptGenKey(auxcontext(), AT_SIGNATURE, dwFlags, &hcryptkey)) throw scu::OsException(GetLastError()); DWORD dwDataLength; if (!CryptExportKey(hcryptkey, NULL, PRIVATEKEYBLOB, 0, 0, &dwDataLength)) throw scu::OsException(GetLastError()); BYTE *pbData = reinterpret_cast(_alloca(dwDataLength)); if (!CryptExportKey(hcryptkey, NULL, PRIVATEKEYBLOB, 0, pbData, &dwDataLength)) throw scu::OsException(GetLastError()); MsRsaPrivateKeyBlob msprivatekeyblob(pbData, dwDataLength); if (msprivatekeyblob.BitLength() != m_strength) throw scu::OsException(NTE_BAD_LEN); CPrivateKey hprikey(m_hcard); hprikey->Value(*(AsPCciPrivateKeyBlob(msprivatekeyblob).get())); Blob blbModulus(msprivatekeyblob.Modulus(), msprivatekeyblob.Length()); MsRsaPrivateKeyBlob::PublicExponentType pet = msprivatekeyblob.PublicExponent(); Blob blbExponent(reinterpret_cast(&pet), sizeof pet); return KeyPair(hprikey, blbModulus, blbExponent); } pair RsaKeyPairGenerator::GenerateOnCard(KeyType kt) const { DWORD dwExponent = DefaultPublicExponent(); Blob blbExponent(reinterpret_cast(&dwExponent), sizeof dwExponent); pair ModulusKeyPair(m_hcard->GenerateKeyPair(kt, AsString(blbExponent))); CPrivateKey hprikey(ModulusKeyPair.second); Blob blbModulus(AsBlob(ModulusKeyPair.first)); return KeyPair(hprikey, blbModulus, blbExponent); } void RsaKeyPairGenerator::ValidateParameters() const { ValidateCard(m_hcard); ValidateStrength(m_strength); } // Access // Predicates // Static Variables