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.

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