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.

726 lines
18 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: SIPObj.cpp
  8. //
  9. // Contents: Microsoft SIP Provider
  10. //
  11. // History: 15-Feb-1997 pberkman created
  12. //
  13. //--------------------------------------------------------------------------
  14. #include "global.hxx"
  15. #include "crypthlp.h"
  16. #include "sipobj.hxx"
  17. #include "sha.h"
  18. #include "md5.h"
  19. ////////////////////////////////////////////////////////////////////////////
  20. //
  21. // construct/destruct:
  22. //
  23. SIPObject_::SIPObject_(DWORD id)
  24. {
  25. hFile = INVALID_HANDLE_VALUE;
  26. hProv = NULL;
  27. uSubjectForm = MSSIP_SUBJECT_FORM_FILE;
  28. bCloseFile = FALSE;
  29. fUseFileMap = TRUE;
  30. hMappedFile = INVALID_HANDLE_VALUE;
  31. pbFileMap = NULL;
  32. cbFileMap = 0;
  33. }
  34. SIPObject_::~SIPObject_(void)
  35. {
  36. HRESULT lerr;
  37. lerr = GetLastError();
  38. if ((hFile != INVALID_HANDLE_VALUE) && (bCloseFile))
  39. {
  40. CloseHandle(hFile);
  41. }
  42. this->UnmapFile();
  43. SetLastError(lerr);
  44. }
  45. ////////////////////////////////////////////////////////////////////////////
  46. //
  47. // public:
  48. //
  49. BOOL SIPObject_::GetSignedDataMsg(SIP_SUBJECTINFO *pSI,DWORD dwIdx,
  50. DWORD *pdwDLen,BYTE *pbData,
  51. DWORD *pdwEncodeType)
  52. {
  53. if (!(pdwDLen))
  54. {
  55. SetLastError((DWORD)ERROR_INVALID_PARAMETER);
  56. return(FALSE);
  57. }
  58. if (this->FileHandleFromSubject(pSI))
  59. {
  60. DWORD dwOldError;
  61. dwOldError = GetLastError();
  62. if (*pdwDLen == 0)
  63. {
  64. pbData = NULL; // just to be sure for future WIN32 style calls!
  65. }
  66. if (this->GetMessageFromFile(pSI, (LPWIN_CERTIFICATE)pbData, dwIdx, pdwDLen))
  67. {
  68. if (pbData)
  69. {
  70. LPWIN_CERTIFICATE pCertHdr;
  71. pCertHdr = (LPWIN_CERTIFICATE)pbData;
  72. pSI->dwIntVersion = (DWORD)pCertHdr->wRevision;
  73. switch (pCertHdr->wCertificateType)
  74. {
  75. case WIN_CERT_TYPE_PKCS_SIGNED_DATA:
  76. *pdwEncodeType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
  77. break;
  78. case WIN_CERT_TYPE_X509:
  79. case WIN_CERT_TYPE_RESERVED_1:
  80. default:
  81. *pdwEncodeType = 0;
  82. }
  83. DWORD dwCert;
  84. BYTE *pszStart;
  85. BYTE *pszData;
  86. dwCert = pCertHdr->dwLength - OFFSETOF(WIN_CERTIFICATE,bCertificate);
  87. pszStart = (BYTE *)pCertHdr;
  88. pszData = pCertHdr->bCertificate;
  89. memcpy(pszStart, pszData, dwCert);
  90. *pdwDLen = dwCert;
  91. # if (DBG)
  92. HANDLE hDebug;
  93. DWORD dwDbgwr;
  94. hDebug = CreateFile("C:\\SIPOBJ.DBG",GENERIC_WRITE,FILE_SHARE_WRITE,
  95. NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL);
  96. if (hDebug != INVALID_HANDLE_VALUE)
  97. {
  98. WriteFile(hDebug, &pszData[0], dwCert, &dwDbgwr,NULL);
  99. CloseHandle(hDebug);
  100. }
  101. # endif // DBG
  102. }
  103. return(TRUE);
  104. }
  105. else if ((GetLastError() == ERROR_INSUFFICIENT_BUFFER) && (pbData == NULL))
  106. {
  107. // just getting length...
  108. SetLastError(dwOldError);
  109. return(TRUE);
  110. }
  111. }
  112. return(FALSE);
  113. }
  114. BOOL SIPObject_::PutSignedDataMsg(SIP_SUBJECTINFO *pSI,DWORD *pdwIdx,
  115. DWORD dwDLen,BYTE *pbData,
  116. DWORD dwEncodeType)
  117. {
  118. if (this->FileHandleFromSubject(pSI, GENERIC_READ | GENERIC_WRITE))
  119. {
  120. LPWIN_CERTIFICATE pCertHdr;
  121. DWORD dwData;
  122. DWORD cbCheck;
  123. dwData = OFFSETOF(WIN_CERTIFICATE, bCertificate) + dwDLen;
  124. dwData = (dwData + 7) & ~7; // allign on 8 byte
  125. if (!(pCertHdr = (LPWIN_CERTIFICATE)this->SIPNew(dwData)))
  126. {
  127. return(FALSE);
  128. }
  129. memset(pCertHdr, 0x00, dwData);
  130. pCertHdr->dwLength = dwData;
  131. pCertHdr->wRevision = WIN_CERT_REVISION_2_0;
  132. pCertHdr->wCertificateType = WIN_CERT_TYPE_PKCS_SIGNED_DATA;
  133. if (pbData)
  134. {
  135. fSizeFileOnly = FALSE;
  136. memcpy(&pCertHdr->bCertificate[0], &pbData[0], dwDLen);
  137. # if (DBG)
  138. HANDLE hDebug;
  139. DWORD dwDbgwr;
  140. hDebug = CreateFile("C:\\SIPOBJ.DBG",GENERIC_WRITE,FILE_SHARE_WRITE,
  141. NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL);
  142. if (hDebug != INVALID_HANDLE_VALUE)
  143. {
  144. WriteFile(hDebug,&pbData[0],dwDLen,&dwDbgwr,NULL);
  145. CloseHandle(hDebug);
  146. }
  147. # endif // DBG
  148. }
  149. else
  150. {
  151. fSizeFileOnly = TRUE;
  152. memset(&pCertHdr->bCertificate[0], 0x00, dwDLen);
  153. }
  154. if (!(this->PutMessageInFile(pSI, pCertHdr, pdwIdx)))
  155. {
  156. delete pCertHdr;
  157. return(FALSE);
  158. }
  159. delete pCertHdr;
  160. return(TRUE);
  161. }
  162. return(FALSE);
  163. }
  164. BOOL SIPObject_::CreateIndirectData(SIP_SUBJECTINFO *pSI,DWORD *pdwDLen,
  165. SIP_INDIRECT_DATA *psData)
  166. {
  167. HCRYPTPROV hProvT;
  168. hProvT = pSI->hProv;
  169. if (!(hProvT))
  170. {
  171. if (!(this->LoadDefaultProvider()))
  172. {
  173. return(FALSE);
  174. }
  175. hProvT = this->hProv;
  176. }
  177. BYTE *pbDigest;
  178. DWORD cbDigest;
  179. if (!(psData))
  180. {
  181. //
  182. // length only!
  183. //
  184. HCRYPTHASH hHash;
  185. DWORD dwRetLen;
  186. DWORD dwEncLen;
  187. DWORD dwAlgId;
  188. dwRetLen = sizeof(SIP_INDIRECT_DATA);
  189. // crypt_algorithm_identifier...
  190. // obj id
  191. dwRetLen += strlen(pSI->DigestAlgorithm.pszObjId);
  192. dwRetLen += 1; // null term.
  193. // parameters (none)...
  194. // crypt_attribute_type_value size...
  195. dwRetLen += strlen(this->GetDataObjectID());
  196. dwRetLen += 1; // null term.
  197. // size of the value (flags)....
  198. dwEncLen = 0;
  199. CryptEncodeObject( PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  200. this->GetDataOIDHint(),
  201. this->GetMyStructure(pSI),
  202. NULL,
  203. &dwEncLen);
  204. if (dwEncLen > 0)
  205. {
  206. dwRetLen += dwEncLen;
  207. // hash of subject
  208. if ((dwAlgId = CertOIDToAlgId(pSI->DigestAlgorithm.pszObjId)) == 0)
  209. {
  210. SetLastError((DWORD)NTE_BAD_ALGID);
  211. return(FALSE);
  212. }
  213. switch (dwAlgId)
  214. {
  215. case CALG_MD5:
  216. cbDigest = MD5DIGESTLEN;
  217. break;
  218. case CALG_SHA1:
  219. cbDigest = A_SHA_DIGEST_LEN;
  220. break;
  221. default:
  222. if (!(CryptCreateHash(hProvT, dwAlgId, NULL, 0, &hHash)))
  223. {
  224. return(FALSE);
  225. }
  226. // just to get hash length
  227. if (!(CryptHashData(hHash,(const BYTE *)" ",1,0)))
  228. {
  229. CryptDestroyHash(hHash);
  230. return(FALSE);
  231. }
  232. cbDigest = 0;
  233. CryptGetHashParam(hHash, HP_HASHVAL, NULL, &cbDigest,0);
  234. CryptDestroyHash(hHash);
  235. }
  236. if (cbDigest > 0)
  237. {
  238. dwRetLen += cbDigest;
  239. *pdwDLen = dwRetLen;
  240. return(TRUE);
  241. }
  242. }
  243. }
  244. else if (this->FileHandleFromSubject(pSI))
  245. {
  246. if (pbDigest = this->DigestFile(hProvT,
  247. this->GetDigestFlags(pSI),
  248. pSI->DigestAlgorithm.pszObjId,
  249. &cbDigest))
  250. {
  251. DWORD_PTR offset;
  252. DWORD dwRetLen;
  253. dwRetLen = 0;
  254. CryptEncodeObject( PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  255. this->GetDataOIDHint(),
  256. this->GetMyStructure(pSI),
  257. NULL,
  258. &dwRetLen);
  259. if (dwRetLen > 0)
  260. {
  261. BYTE *attrdata;
  262. attrdata = (BYTE *)this->SIPNew(dwRetLen);
  263. if (attrdata)
  264. {
  265. if (CryptEncodeObject( PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  266. this->GetDataOIDHint(),
  267. this->GetMyStructure(pSI),
  268. attrdata,
  269. &dwRetLen))
  270. {
  271. //
  272. // assign allocated memory to our structure
  273. //
  274. offset = (DWORD_PTR)psData + sizeof(SIP_INDIRECT_DATA);
  275. strcpy((char *)offset, this->GetDataObjectID());
  276. psData->Data.pszObjId = (LPSTR)offset;
  277. offset += (strlen(this->GetDataObjectID()) + 1);
  278. memcpy((void *)offset,attrdata,dwRetLen);
  279. psData->Data.Value.pbData = (BYTE *)offset;
  280. psData->Data.Value.cbData = dwRetLen;
  281. offset += dwRetLen;
  282. strcpy((char *)offset, (char *)pSI->DigestAlgorithm.pszObjId);
  283. psData->DigestAlgorithm.pszObjId = (char *)offset;
  284. psData->DigestAlgorithm.Parameters.cbData = 0;
  285. psData->DigestAlgorithm.Parameters.pbData = NULL;
  286. offset += (strlen(pSI->DigestAlgorithm.pszObjId) + 1);
  287. memcpy((void *)offset,pbDigest,cbDigest);
  288. psData->Digest.pbData = (BYTE *)offset;
  289. psData->Digest.cbData = cbDigest;
  290. delete pbDigest;
  291. delete attrdata;
  292. return(TRUE);
  293. }
  294. delete attrdata;
  295. }
  296. }
  297. delete pbDigest;
  298. }
  299. }
  300. return(FALSE);
  301. }
  302. BOOL SIPObject_::VerifyIndirectData(SIP_SUBJECTINFO *pSI,
  303. SIP_INDIRECT_DATA *psData)
  304. {
  305. if (!(psData))
  306. {
  307. if (this->FileHandleFromSubject(pSI)) // if the file exists, set bad parameter!
  308. {
  309. SetLastError((DWORD)ERROR_INVALID_PARAMETER);
  310. }
  311. return(FALSE);
  312. }
  313. if (this->FileHandleFromSubject(pSI))
  314. {
  315. DWORD cbDigest;
  316. BYTE *pbDigest;
  317. if (!(pbDigest = this->DigestFile( pSI->hProv,
  318. this->GetDigestFlags(pSI),
  319. psData->DigestAlgorithm.pszObjId,
  320. &cbDigest)))
  321. {
  322. return(FALSE);
  323. }
  324. if ((cbDigest != psData->Digest.cbData) ||
  325. (memcmp(pbDigest,psData->Digest.pbData,cbDigest) != 0))
  326. {
  327. delete pbDigest;
  328. SetLastError(TRUST_E_BAD_DIGEST);
  329. return(FALSE);
  330. }
  331. delete pbDigest;
  332. return(TRUE);
  333. }
  334. return(FALSE);
  335. }
  336. //////////////////////////////////////////////////////////////////////////////
  337. //
  338. // protected:
  339. //
  340. void *SIPObject_::SIPNew(DWORD cbytes)
  341. {
  342. void *pvRet;
  343. pvRet = (void *)new char[cbytes];
  344. if (!(pvRet))
  345. {
  346. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  347. }
  348. return(pvRet);
  349. }
  350. BOOL SIPObject_::OpenFile(LPCWSTR FileName, DWORD dwAccess, DWORD dwShared)
  351. {
  352. if ((this->hFile != INVALID_HANDLE_VALUE) && (this->hFile))
  353. {
  354. //
  355. // we've already opened it....
  356. //
  357. return(TRUE);
  358. }
  359. if ((this->hFile = CreateFileU( FileName,
  360. dwAccess,
  361. dwShared,
  362. NULL,
  363. OPEN_EXISTING,
  364. FILE_ATTRIBUTE_NORMAL,
  365. NULL)) == INVALID_HANDLE_VALUE)
  366. {
  367. return(FALSE);
  368. }
  369. this->bCloseFile = TRUE;
  370. return(TRUE);
  371. }
  372. BOOL SIPObject_::FileHandleFromSubject(SIP_SUBJECTINFO *pSubject, DWORD dwAccess, DWORD dwShared)
  373. {
  374. dwFileAccess = dwAccess;
  375. if ((pSubject->hFile == NULL) ||
  376. (pSubject->hFile == INVALID_HANDLE_VALUE))
  377. {
  378. if (!(this->OpenFile(pSubject->pwsFileName, dwAccess, dwShared)))
  379. {
  380. return(FALSE);
  381. }
  382. }
  383. else
  384. {
  385. this->hFile = pSubject->hFile;
  386. if (SetFilePointer(this->hFile, 0, NULL, FILE_BEGIN) == 0xFFFFFFFF)
  387. {
  388. return(FALSE);
  389. }
  390. }
  391. return(this->MapFile());
  392. }
  393. void SIPObject_::AllocateAndFillCryptBitBlob(CRYPT_BIT_BLOB *bb,DWORD Flags,
  394. DWORD cUnusedBits)
  395. {
  396. if (bb)
  397. {
  398. bb->cbData = 1;
  399. bb->pbData = new BYTE[1];
  400. bb->cUnusedBits = cUnusedBits;
  401. if(bb->pbData)
  402. bb->pbData[0] = (BYTE)(Flags & 0x000000ff);
  403. }
  404. }
  405. void SIPObject_::DestroyCryptBitBlob(CRYPT_BIT_BLOB *bb)
  406. {
  407. if (bb)
  408. {
  409. if (bb->pbData)
  410. {
  411. delete bb->pbData;
  412. bb->pbData = NULL;
  413. }
  414. }
  415. }
  416. DWORD SIPObject_::CryptBitBlobToFlags(CRYPT_BIT_BLOB *bb)
  417. {
  418. if ((bb) && (bb->pbData))
  419. {
  420. return((DWORD)bb->pbData[0]);
  421. }
  422. return(0);
  423. }
  424. BYTE *SIPObject_::DigestFile(HCRYPTPROV hProv, DWORD dwFlags, char *pszObjId, DWORD *pcbDigest)
  425. {
  426. DIGEST_DATA DigestData;
  427. A_SHA_CTX sShaCtx;
  428. MD5_CTX sMd5Ctx;
  429. *pcbDigest = 0;
  430. if ((DigestData.dwAlgId = CertOIDToAlgId(pszObjId)) == 0)
  431. {
  432. SetLastError((DWORD)NTE_BAD_ALGID);
  433. return(NULL);
  434. }
  435. DigestData.cbCache = 0;
  436. DigestData.hHash = 0;
  437. switch (DigestData.dwAlgId)
  438. {
  439. case CALG_MD5:
  440. DigestData.pvSHA1orMD5Ctx = &sMd5Ctx;
  441. break;
  442. case CALG_SHA1:
  443. DigestData.pvSHA1orMD5Ctx = &sShaCtx;
  444. break;
  445. default:
  446. DigestData.pvSHA1orMD5Ctx = NULL;
  447. }
  448. if (!(SipCreateHash(hProv, &DigestData)))
  449. {
  450. return(NULL);
  451. }
  452. if (!(this->GetDigestStream(&DigestData, (DIGEST_FUNCTION)DigestFileData, dwFlags)))
  453. {
  454. return(NULL);
  455. }
  456. // Data left over ?
  457. if (DigestData.cbCache > 0)
  458. {
  459. if (!(SipHashData(&DigestData, DigestData.pbCache, DigestData.cbCache)))
  460. {
  461. SipDestroyHash(&DigestData);
  462. return(NULL);
  463. }
  464. }
  465. BYTE *pbRet;
  466. pbRet = SipGetHashValue(&DigestData, pcbDigest);
  467. SipDestroyHash(&DigestData);
  468. return(pbRet);
  469. }
  470. BOOL SIPObject_::LoadDefaultProvider(void)
  471. {
  472. if (this->hProv)
  473. {
  474. return(TRUE);
  475. }
  476. this->hProv = I_CryptGetDefaultCryptProv(0); // get the default and DONT RELEASE IT!!!!
  477. if (this->hProv)
  478. {
  479. return(TRUE);
  480. }
  481. return(FALSE);
  482. }
  483. BOOL SIPObject_::SeekAndWriteFile(DWORD lFileOffset,BYTE *pb, DWORD cb)
  484. {
  485. DWORD cbWritten;
  486. if (SetFilePointer(this->hFile, lFileOffset, NULL, FILE_BEGIN) == 0xFFFFFFFF)
  487. {
  488. return(FALSE);
  489. }
  490. if (!(WriteFile(this->hFile, pb, cb, &cbWritten, NULL)) || (cbWritten != cb))
  491. {
  492. return(FALSE);
  493. }
  494. return(TRUE);
  495. }
  496. BOOL SIPObject_::SeekAndReadFile(DWORD lFileOffset, BYTE *pb, DWORD cb)
  497. {
  498. if (!(this->pbFileMap) ||
  499. (this->cbFileMap < (lFileOffset + cb)))
  500. {
  501. return(FALSE);
  502. }
  503. __try {
  504. memcpy(pb, &this->pbFileMap[lFileOffset], cb);
  505. }
  506. __except(EXCEPTION_EXECUTE_HANDLER) {
  507. SetLastError(GetExceptionCode());
  508. return(FALSE);
  509. }
  510. return(TRUE);
  511. }
  512. void SIPObject_::set_CertVersion(DWORD dwNewCertVersion)
  513. {
  514. uCertVersion = dwNewCertVersion;
  515. if (uCertVersion < WIN_CERT_REVISION_1_0) // just in case it hasn't been set yet.
  516. {
  517. uCertVersion = WIN_CERT_REVISION_2_0;
  518. }
  519. }
  520. BOOL SIPObject_::MapFile(void)
  521. {
  522. if (!(this->fUseFileMap))
  523. {
  524. return(TRUE);
  525. }
  526. BOOL fRet;
  527. if (this->pbFileMap)
  528. {
  529. this->UnmapFile();
  530. }
  531. hMappedFile = CreateFileMapping(this->hFile, NULL,
  532. (dwFileAccess & GENERIC_WRITE) ? PAGE_READWRITE : PAGE_READONLY, 0, 0, NULL);
  533. if (!(hMappedFile) || (hMappedFile == INVALID_HANDLE_VALUE))
  534. {
  535. goto FileMapFailed;
  536. }
  537. this->pbFileMap = (BYTE *)MapViewOfFile(hMappedFile,
  538. (dwFileAccess & GENERIC_WRITE) ? FILE_MAP_WRITE : FILE_MAP_READ, 0, 0, 0);
  539. if (!(this->pbFileMap))
  540. {
  541. goto FileViewFailed;
  542. }
  543. this->cbFileMap = GetFileSize(this->hFile, NULL);
  544. fRet = TRUE;
  545. CommonReturn:
  546. return(fRet);
  547. ErrorReturn:
  548. this->cbFileMap = 0;
  549. this->UnmapFile();
  550. fRet = FALSE;
  551. goto CommonReturn;
  552. TRACE_ERROR_EX(DBG_SS, FileMapFailed);
  553. TRACE_ERROR_EX(DBG_SS, FileViewFailed);
  554. }
  555. BOOL SIPObject_::UnmapFile(void)
  556. {
  557. if ((hMappedFile != INVALID_HANDLE_VALUE) && (hMappedFile))
  558. {
  559. CloseHandle(hMappedFile);
  560. hMappedFile = INVALID_HANDLE_VALUE;
  561. }
  562. if (this->pbFileMap)
  563. {
  564. UnmapViewOfFile(this->pbFileMap);
  565. this->pbFileMap = NULL;
  566. this->cbFileMap = 0;
  567. }
  568. return(TRUE);
  569. }