Source code of Windows XP (NT5)
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.

620 lines
14 KiB

  1. // V1Card.cpp: implementation of the CV2Card class.
  2. //
  3. // (c) Copyright Schlumberger Technology Corp., unpublished work, created
  4. // 1999. This computer program includes Confidential, Proprietary
  5. // Information and is a Trade Secret of Schlumberger Technology Corp. All
  6. // use, disclosure, and/or reproduction is prohibited unless authorized
  7. // in writing. All Rights Reserved.
  8. //////////////////////////////////////////////////////////////////////
  9. #include "NoWarning.h"
  10. #include <algorithm>
  11. #include <functional>
  12. #include <memory> // for auto_ptr
  13. #include <scuArrayP.h>
  14. #include <SmartCard.h>
  15. #include "TransactionWrap.h"
  16. #include "cciExc.h"
  17. #include "MethodHelp.h"
  18. #include "cciCert.h"
  19. #include "cciKeyPair.h"
  20. #include "cciPriKey.h"
  21. #include "cciPubKey.h"
  22. #include "V1Cert.h"
  23. #include "V1Cont.h"
  24. #include "V1ContRec.h"
  25. #include "V1KeyPair.h"
  26. #include "V1PriKey.h"
  27. #include "V1PubKey.h"
  28. #include "V1Paths.h"
  29. #include "V1Card.h"
  30. using namespace std;
  31. using namespace cci;
  32. /////////////////////////// LOCAL/HELPER /////////////////////////////////
  33. namespace
  34. {
  35. // Enumerate T type objects in the exchange and signature key pair
  36. // using C::<Accessor> to get the T object, returning vector<T>
  37. // objects.
  38. template<class T>
  39. class EnumItems
  40. : std::unary_function<void, vector<T> >
  41. {
  42. public:
  43. EnumItems(CV1Card const &rv1card,
  44. ObjectAccess oa,
  45. AccessorMethod<T, CAbstractKeyPair>::AccessorPtr Accessor)
  46. : m_rv1card(rv1card),
  47. m_oa(oa),
  48. m_matAccess(Accessor),
  49. m_Result()
  50. {}
  51. result_type
  52. operator()(argument_type)
  53. {
  54. DoAppend(m_rv1card.DefaultContainer());
  55. return m_Result;
  56. }
  57. protected:
  58. void
  59. DoAppend(CContainer &rhcntr)
  60. {
  61. if (rhcntr)
  62. {
  63. AppendItem(rhcntr->ExchangeKeyPair());
  64. AppendItem(rhcntr->SignatureKeyPair());
  65. }
  66. }
  67. private:
  68. void
  69. AppendItem(CKeyPair &rhkp)
  70. {
  71. if (rhkp)
  72. {
  73. T hObject(m_matAccess(*rhkp));
  74. if (hObject && (m_oa == hObject->Access()))
  75. m_Result.push_back(hObject);
  76. }
  77. }
  78. CV1Card const &m_rv1card;
  79. ObjectAccess m_oa;
  80. MemberAccessorType<T, CAbstractKeyPair> m_matAccess;
  81. result_type m_Result;
  82. };
  83. bool
  84. IsSupported(iop::CSmartCard &rSmartCard) throw()
  85. {
  86. bool fSupported = false;
  87. try
  88. {
  89. rSmartCard.Select(CV1Paths::Chv());
  90. rSmartCard.Select(CV1Paths::IcFile());
  91. rSmartCard.Select(CV1Paths::RootContainers());
  92. rSmartCard.Select(CV1Paths::PrivateKeys());
  93. rSmartCard.Select(CV1Paths::PublicKeys());
  94. fSupported = true;
  95. }
  96. catch(scu::Exception &)
  97. {}
  98. return fSupported;
  99. }
  100. } // namespace
  101. /////////////////////////// PUBLIC /////////////////////////////////
  102. // Types
  103. // C'tors/D'tors
  104. CV1Card::~CV1Card() throw()
  105. {}
  106. // Operators
  107. // Operations
  108. void
  109. CV1Card::CardId(string const &rsNewCardId) const
  110. {
  111. CTransactionWrap(this);
  112. DWORD dwLen = OpenFile(CV1Paths::IcFile());
  113. if (0 == dwLen)
  114. throw scu::OsException(NTE_FAIL);
  115. if (rsNewCardId.length() > dwLen)
  116. throw scu::OsException(ERROR_INVALID_PARAMETER);
  117. if (rsNewCardId.length() < dwLen)
  118. SmartCard().WriteBinary(0, rsNewCardId.length() + 1,
  119. reinterpret_cast<BYTE const *>(rsNewCardId.c_str()));
  120. else
  121. SmartCard().WriteBinary(0,
  122. static_cast<WORD>(rsNewCardId.length()),
  123. reinterpret_cast<BYTE const *>(rsNewCardId.data()));
  124. RefreshCardId();
  125. }
  126. void
  127. CV1Card::ChangePIN(string const &rstrOldPIN,
  128. string const &rstrNewPIN)
  129. {
  130. CTransactionWrap wrap(this);
  131. SmartCard().Select(CV1Paths::Root());
  132. SuperClass::ChangePIN(rstrOldPIN, rstrNewPIN);
  133. }
  134. void
  135. CV1Card::DefaultContainer(CContainer const &rcont)
  136. {
  137. m_avhDefaultCntr.Value(rcont);
  138. if(!m_avhDefaultCntr.Value())
  139. m_avhDefaultCntr.Dirty();
  140. // Nothing more to do since, by definition, the one and only
  141. // container is already the default container.
  142. }
  143. pair<string, // interpreted as the public modulus
  144. CPrivateKey>
  145. CV1Card::GenerateKeyPair(KeyType kt,
  146. string const &rsExponent,
  147. ObjectAccess oaPrivateKey)
  148. {
  149. throw Exception(ccNotImplemented);
  150. return pair<string, CPrivateKey>();
  151. }
  152. void
  153. CV1Card::InitCard()
  154. {
  155. // We want to select /3f00/0015 (length 1744) and /3f00/3f11/0015 (length 300), and clear both files.
  156. CTransactionWrap wrap(this);
  157. BYTE bData[1744];
  158. memset(bData, 0, 1744);
  159. SmartCard().Select(CV1Paths::RootContainers());
  160. SmartCard().WriteBinary(0x0000, 0x06d0, bData);
  161. SmartCard().Select(CV1Paths::PublicKeys());
  162. SmartCard().WriteBinary(0x0000, 0x012c, bData);
  163. }
  164. void
  165. CV1Card::InvalidateCache()
  166. {
  167. m_avhDefaultCntr.Value(CContainer());
  168. m_avhDefaultCntr.Dirty();
  169. m_avhExchangeKeyPair.Value(CKeyPair());
  170. m_avhExchangeKeyPair.Dirty();
  171. m_avhSignatureKeyPair.Value(CKeyPair());
  172. m_avhSignatureKeyPair.Dirty();
  173. }
  174. void
  175. CV1Card::Label(string const &rLabel)
  176. {
  177. throw Exception(ccNotImplemented);
  178. }
  179. DWORD
  180. CV1Card::OpenFile(char const *szPath) const
  181. {
  182. iop::FILE_HEADER fh;
  183. SmartCard().Select(szPath, &fh);
  184. return fh.file_size;
  185. }
  186. void
  187. CV1Card::VerifyKey(string const &rstrKey,
  188. BYTE bKeyNum)
  189. {
  190. CTransactionWrap wrap(this);
  191. SmartCard().Select(CV1Paths::CryptoSys());
  192. SuperClass::VerifyKey(rstrKey, bKeyNum);
  193. }
  194. // Access
  195. size_t
  196. CV1Card::AvailableStringSpace(ObjectAccess oa) const
  197. {
  198. throw Exception(ccNotImplemented);
  199. return 0;
  200. }
  201. string
  202. CV1Card::CardId() const
  203. {
  204. return m_sCardId;
  205. }
  206. CContainer
  207. CV1Card::DefaultContainer() const
  208. {
  209. CTransactionWrap wrap(this);
  210. if (!m_avhDefaultCntr.IsCached())
  211. {
  212. auto_ptr<CV1Container> apv1cntr(new CV1Container(*this,
  213. CV1ContainerRecord::DefaultName(),
  214. false));
  215. if (apv1cntr->Exists())
  216. {
  217. CContainer hcntr;
  218. hcntr = CContainer(apv1cntr.get());
  219. apv1cntr.release();
  220. m_avhDefaultCntr.Value(hcntr);
  221. }
  222. }
  223. return m_avhDefaultCntr.Value();
  224. }
  225. vector<CContainer>
  226. CV1Card::EnumContainers() const
  227. {
  228. CContainer hcntr(0);
  229. auto_ptr<CV1Container> apv1cntr(new CV1Container(*this,
  230. CV1ContainerRecord::DefaultName(),
  231. false));
  232. if (apv1cntr->Exists())
  233. {
  234. hcntr = CContainer(apv1cntr.get());
  235. apv1cntr.release();
  236. }
  237. vector<CContainer> vhcntr;
  238. if (hcntr)
  239. vhcntr.push_back(hcntr);
  240. return vhcntr;
  241. }
  242. vector<CCertificate>
  243. CV1Card::EnumCertificates(ObjectAccess access) const
  244. {
  245. CTransactionWrap wrap(this);
  246. EnumItems<CCertificate> Enumerator(*this, access,
  247. CAbstractKeyPair::Certificate);
  248. return Enumerator();
  249. }
  250. vector<CPublicKey>
  251. CV1Card::EnumPublicKeys(ObjectAccess access) const
  252. {
  253. CTransactionWrap wrap(this);
  254. EnumItems<CPublicKey> Enumerator(*this, access,
  255. CAbstractKeyPair::PublicKey);
  256. return Enumerator();
  257. }
  258. vector<CPrivateKey>
  259. CV1Card::EnumPrivateKeys(ObjectAccess access) const
  260. {
  261. CTransactionWrap wrap(this);
  262. EnumItems<CPrivateKey> Enumerator(*this, access,
  263. CAbstractKeyPair::PrivateKey);
  264. return Enumerator();
  265. }
  266. vector<CDataObject>
  267. CV1Card::EnumDataObjects(ObjectAccess access) const
  268. {
  269. return vector<CDataObject>(); // can never have data objects
  270. }
  271. string
  272. CV1Card::Label() const
  273. {
  274. throw Exception(ccNotImplemented);
  275. return string();
  276. }
  277. CAbstractCertificate *
  278. CV1Card::MakeCertificate(ObjectAccess oa) const
  279. {
  280. CTransactionWrap wrap(this);
  281. if (oaPublicAccess != oa)
  282. throw Exception(ccInvalidParameter);
  283. return new CV1Certificate(*this, ksNone);
  284. }
  285. CAbstractContainer *
  286. CV1Card::MakeContainer() const
  287. {
  288. CTransactionWrap wrap(this);
  289. return new CV1Container(*this,
  290. CV1ContainerRecord::DefaultName(), true);
  291. }
  292. CAbstractDataObject *
  293. CV1Card::MakeDataObject(ObjectAccess oa) const
  294. {
  295. throw Exception(ccNotImplemented);
  296. return 0;
  297. }
  298. CAbstractKeyPair *
  299. CV1Card::MakeKeyPair(CContainer const &rhcont,
  300. KeySpec ks) const
  301. {
  302. CTransactionWrap wrap(this);
  303. // If the key pair is cached, return it; otherwise make a new one
  304. // and cache it.
  305. CArchivedValue<CKeyPair> *pavhkp = 0;
  306. switch (ks)
  307. {
  308. case ksExchange:
  309. pavhkp = &m_avhExchangeKeyPair;
  310. break;
  311. case ksSignature:
  312. pavhkp = &m_avhSignatureKeyPair;
  313. break;
  314. default:
  315. throw Exception(ccBadKeySpec);
  316. break;
  317. }
  318. if (!pavhkp->IsCached() || !pavhkp->Value())
  319. pavhkp->Value(CKeyPair(new CV1KeyPair(*this, rhcont, ks)));
  320. return pavhkp->Value().operator->(); // yuk!
  321. }
  322. CAbstractPrivateKey *
  323. CV1Card::MakePrivateKey(ObjectAccess oa) const
  324. {
  325. CTransactionWrap wrap(this);
  326. if (oaPrivateAccess != oa)
  327. throw Exception(ccInvalidParameter);
  328. return new CV1PrivateKey(*this, ksNone);
  329. }
  330. CAbstractPublicKey *
  331. CV1Card::MakePublicKey(ObjectAccess oa) const
  332. {
  333. CTransactionWrap wrap(this);
  334. if (oaPublicAccess != oa)
  335. throw Exception(ccInvalidParameter);
  336. return new CV1PublicKey(*this, ksNone);
  337. }
  338. BYTE
  339. CV1Card::MaxKeys(KeyType kt) const
  340. {
  341. BYTE bCount;
  342. switch (kt)
  343. {
  344. case ktRSA1024:
  345. bCount = 2;
  346. break;
  347. default:
  348. bCount = 0;
  349. break;
  350. }
  351. return bCount;
  352. }
  353. size_t
  354. CV1Card::MaxStringSpace(ObjectAccess oa) const
  355. {
  356. throw Exception(ccNotImplemented);
  357. return 0;
  358. }
  359. bool
  360. CV1Card::SupportedKeyFunction(KeyType kt,
  361. CardOperation oper) const
  362. {
  363. bool fSupported = false;
  364. switch (oper)
  365. {
  366. case coEncryption: // .. or public key operations
  367. break;
  368. case coDecryption: // .. or private key operations
  369. switch (kt)
  370. {
  371. case ktRSA1024:
  372. fSupported = true;
  373. break;
  374. default:
  375. break;
  376. }
  377. default:
  378. break;
  379. }
  380. return fSupported;
  381. }
  382. // Predicates
  383. bool
  384. CV1Card::IsCAPIEnabled() const
  385. {
  386. return true;
  387. }
  388. bool
  389. CV1Card::IsPKCS11Enabled() const
  390. {
  391. return false;
  392. }
  393. bool
  394. CV1Card::IsProtectedMode() const
  395. {
  396. return true;
  397. }
  398. bool
  399. CV1Card::IsKeyGenEnabled() const
  400. {
  401. return false;
  402. }
  403. bool
  404. CV1Card::IsEntrustEnabled() const
  405. {
  406. return false;
  407. }
  408. BYTE
  409. CV1Card::MajorVersion() const
  410. {
  411. return (BYTE)0;
  412. }
  413. // Static Variables
  414. /////////////////////////// PROTECTED /////////////////////////////////
  415. // C'tors/D'tors
  416. CV1Card::CV1Card(string const &rstrReaderName,
  417. auto_ptr<iop::CIOP> &rapiop,
  418. auto_ptr<iop::CSmartCard> &rapSmartCard)
  419. : SuperClass(rstrReaderName, rapiop, rapSmartCard),
  420. m_sCardId(),
  421. m_avhDefaultCntr(),
  422. m_avhExchangeKeyPair(),
  423. m_avhSignatureKeyPair()
  424. {}
  425. // Operators
  426. // Operations
  427. void
  428. CV1Card::DoSetup()
  429. {
  430. CAbstractCard::DoSetup();
  431. RefreshCardId();
  432. }
  433. // Access
  434. // Predicates
  435. // Static Variables
  436. /////////////////////////// PRIVATE /////////////////////////////////
  437. // C'tors/D'tors
  438. // Operators
  439. // Operations
  440. auto_ptr<CAbstractCard>
  441. CV1Card::DoMake(string const &rstrReaderName,
  442. auto_ptr<iop::CIOP> &rapiop,
  443. auto_ptr<iop::CSmartCard> &rapSmartCard)
  444. {
  445. return IsSupported(*rapSmartCard.get())
  446. ? auto_ptr<CAbstractCard>(new CV1Card(rstrReaderName, rapiop,
  447. rapSmartCard))
  448. : auto_ptr<CAbstractCard>(0);
  449. }
  450. string
  451. CV1Card::ReadCardId() const
  452. {
  453. string sCardId;
  454. // *** BEGIN WORKAROUND ***
  455. // The following SetContext and OpenFile call is made to
  456. // make sure the card and this system's current path are
  457. // synchronized, pointing to the right directory. Without
  458. // it, the subsequent call to ReadBinaryFile fails because
  459. // they appear to be out of synch. It's not clear why
  460. // this happens but this workaround avoids the problem.
  461. try
  462. {
  463. SmartCard().Select(CV1Paths::RootContainers());
  464. }
  465. catch (...)
  466. {
  467. }
  468. // *** END WORKAROUND ***
  469. try
  470. {
  471. iop::FILE_HEADER fh;
  472. SmartCard().Select(CV1Paths::IcFile(), &fh);
  473. DWORD dwLen = fh.file_size;
  474. scu::AutoArrayPtr<BYTE> aaCardId(new BYTE[dwLen + 1]);
  475. SmartCard().ReadBinary(0, dwLen, aaCardId.Get());
  476. aaCardId[dwLen] = '\0';
  477. sCardId.assign(reinterpret_cast<char *>(aaCardId.Get()));
  478. }
  479. catch (...)
  480. {
  481. }
  482. return sCardId;
  483. }
  484. void
  485. CV1Card::RefreshCardId() const
  486. {
  487. m_sCardId = ReadCardId();
  488. }
  489. // Access
  490. // Predicates
  491. // Static Variables