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.

1287 lines
36 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: pct1pckl.c
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History:
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <spbase.h>
  18. #include <pct1msg.h>
  19. #include <pct1prot.h>
  20. #define PCT_OFFSET_OF(t, v) ((DWORD)(ULONG_PTR)&(((t)NULL)->v))
  21. #define SIZEOF(pMessage) (Pct1RecordSize((PPCT1_MESSAGE_HEADER) pMessage ) )
  22. DWORD MapCipherToExternal(CipherSpec Internal, ExtCipherSpec UNALIGNED *External)
  23. {
  24. *External = htonl(Internal);
  25. return TRUE;
  26. }
  27. DWORD MapHashToExternal(HashSpec Internal, ExtHashSpec UNALIGNED *External)
  28. {
  29. *External = htons((ExtHashSpec)Internal);
  30. return TRUE;
  31. }
  32. DWORD MapCertToExternal(CertSpec Internal, ExtCertSpec UNALIGNED *External)
  33. {
  34. *External = htons((ExtCertSpec)Internal);
  35. return TRUE;
  36. }
  37. DWORD MapExchToExternal(ExchSpec Internal, ExtExchSpec UNALIGNED *External)
  38. {
  39. *External = htons((ExtExchSpec)Internal);
  40. return TRUE;
  41. }
  42. DWORD MapSigToExternal(SigSpec Internal, ExtSigSpec UNALIGNED *External)
  43. {
  44. *External = htons((ExtSigSpec)Internal);
  45. return TRUE;
  46. }
  47. CipherSpec MapCipherFromExternal(ExtCipherSpec External)
  48. {
  49. return (CipherSpec)ntohl(External);
  50. }
  51. HashSpec MapHashFromExternal(ExtHashSpec External)
  52. {
  53. return (HashSpec)ntohs(External);
  54. }
  55. CertSpec MapCertFromExternal(ExtCertSpec External)
  56. {
  57. return (CertSpec)ntohs(External);
  58. }
  59. ExchSpec MapExchFromExternal(ExtExchSpec External)
  60. {
  61. return (ExchSpec)ntohs(External);
  62. }
  63. SigSpec MapSigFromExternal(ExtSigSpec External)
  64. {
  65. return (SigSpec)ntohs(External);
  66. }
  67. DWORD
  68. Pct1RecordSize(
  69. PPCT1_MESSAGE_HEADER pHeader)
  70. {
  71. DWORD Size;
  72. if (pHeader->Byte0 & 0x80)
  73. {
  74. Size = COMBINEBYTES(pHeader->Byte0, pHeader->Byte1) & 0x7FFF;
  75. }
  76. else
  77. {
  78. Size = COMBINEBYTES(pHeader->Byte0, pHeader->Byte1) & 0x3FFF;
  79. }
  80. return(Size);
  81. }
  82. SP_STATUS
  83. Pct1PackClientHello(
  84. PPct1_Client_Hello pCanonical,
  85. PSPBuffer pCommOutput)
  86. {
  87. DWORD cbMessage;
  88. PPCT1_CLIENT_HELLO pMessage;
  89. DWORD Size;
  90. PUCHAR pBuffer;
  91. DWORD i, iBuff;
  92. SP_BEGIN("Pct1PackClientHello");
  93. if(pCanonical == NULL || pCommOutput == NULL)
  94. {
  95. SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
  96. }
  97. pCommOutput->cbData = 0;
  98. if(pCanonical->cbSessionID != PCT_SESSION_ID_SIZE ||
  99. pCanonical->cbChallenge != PCT_CHALLENGE_SIZE)
  100. {
  101. SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
  102. }
  103. pCommOutput->cbData = PCT_OFFSET_OF(PPCT1_CLIENT_HELLO, VariantData) +
  104. pCanonical->cCipherSpecs * sizeof(ExtCipherSpec) +
  105. pCanonical->cHashSpecs * sizeof(ExtHashSpec) +
  106. pCanonical->cCertSpecs * sizeof(ExtCertSpec) +
  107. pCanonical->cExchSpecs * sizeof(ExtExchSpec) +
  108. pCanonical->cbKeyArgSize;
  109. cbMessage = pCommOutput->cbData - sizeof(PCT1_MESSAGE_HEADER);
  110. if (cbMessage > PCT_MAX_SHAKE_LEN)
  111. {
  112. SP_RETURN(SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW));
  113. }
  114. /* are we allocating our own memory? */
  115. if(pCommOutput->pvBuffer == NULL)
  116. {
  117. pCommOutput->pvBuffer = SPExternalAlloc(pCommOutput->cbData);
  118. if (NULL == pCommOutput->pvBuffer)
  119. {
  120. SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
  121. }
  122. pCommOutput->cbBuffer = pCommOutput->cbData;
  123. }
  124. if(pCommOutput->cbData > pCommOutput->cbBuffer)
  125. {
  126. // Required size returned in pCommOutput->cbData.
  127. SP_RETURN(PCT_INT_BUFF_TOO_SMALL);
  128. }
  129. pMessage = pCommOutput->pvBuffer;
  130. pMessage->MessageId = PCT1_MSG_CLIENT_HELLO;
  131. pMessage->VersionMsb = MSBOF(PCT_VERSION_1);
  132. pMessage->VersionLsb = LSBOF(PCT_VERSION_1);
  133. pMessage->OffsetMsb = MSBOF(PCT_CH_OFFSET_V1);
  134. pMessage->OffsetLsb = LSBOF(PCT_CH_OFFSET_V1);
  135. pMessage->KeyArgLenMsb = MSBOF(pCanonical->cbKeyArgSize);
  136. pMessage->KeyArgLenLsb = LSBOF(pCanonical->cbKeyArgSize);
  137. CopyMemory( pMessage->SessionIdData,
  138. pCanonical->SessionID,
  139. pCanonical->cbSessionID);
  140. CopyMemory( pMessage->ChallengeData,
  141. pCanonical->Challenge,
  142. pCanonical->cbChallenge);
  143. pBuffer = pMessage->VariantData;
  144. iBuff = 0;
  145. for (i = 0; i < pCanonical->cCipherSpecs ; i++ )
  146. {
  147. if (MapCipherToExternal(pCanonical->pCipherSpecs[i],
  148. &((ExtCipherSpec UNALIGNED *) pBuffer)[iBuff]) )
  149. {
  150. iBuff++;
  151. }
  152. }
  153. Size = iBuff*sizeof(ExtCipherSpec);
  154. pMessage->CipherSpecsLenMsb = MSBOF(Size);
  155. pMessage->CipherSpecsLenLsb = LSBOF(Size);
  156. pBuffer += Size;
  157. cbMessage -= (pCanonical->cCipherSpecs - iBuff)*sizeof(ExtCipherSpec);
  158. iBuff = 0;
  159. for (i = 0; i < pCanonical->cHashSpecs ; i++ )
  160. {
  161. if (MapHashToExternal(pCanonical->pHashSpecs[i],
  162. &((ExtHashSpec UNALIGNED *) pBuffer)[iBuff]) )
  163. {
  164. iBuff++;
  165. }
  166. }
  167. Size = iBuff*sizeof(ExtHashSpec);
  168. pBuffer += Size;
  169. pMessage->HashSpecsLenMsb = MSBOF(Size);
  170. pMessage->HashSpecsLenLsb = LSBOF(Size);
  171. cbMessage -= (pCanonical->cHashSpecs - iBuff)*sizeof(ExtHashSpec);
  172. iBuff = 0;
  173. for (i = 0; i < pCanonical->cCertSpecs ; i++ )
  174. {
  175. if (MapCertToExternal(pCanonical->pCertSpecs[i],
  176. &((ExtCertSpec UNALIGNED *) pBuffer)[iBuff]))
  177. {
  178. iBuff ++;
  179. }
  180. }
  181. Size = iBuff*sizeof(ExtCertSpec);
  182. pBuffer += Size;
  183. pMessage->CertSpecsLenMsb = MSBOF(Size);
  184. pMessage->CertSpecsLenLsb = LSBOF(Size);
  185. cbMessage -= (pCanonical->cCertSpecs - iBuff)*sizeof(ExtCertSpec);
  186. iBuff = 0;
  187. for (i = 0; i < pCanonical->cExchSpecs ; i++ )
  188. {
  189. if (MapExchToExternal(pCanonical->pExchSpecs[i],
  190. &((ExtExchSpec UNALIGNED *) pBuffer)[iBuff]) )
  191. {
  192. iBuff++;
  193. }
  194. }
  195. Size = iBuff*sizeof(ExtExchSpec);
  196. pBuffer += Size;
  197. pMessage->ExchSpecsLenMsb = MSBOF(Size);
  198. pMessage->ExchSpecsLenLsb = LSBOF(Size);
  199. cbMessage -= (pCanonical->cExchSpecs - iBuff)*sizeof(ExtExchSpec);
  200. if(pCanonical->pKeyArg)
  201. {
  202. CopyMemory(pBuffer, pCanonical->pKeyArg, pCanonical->cbKeyArgSize);
  203. pBuffer += pCanonical->cbKeyArgSize;
  204. }
  205. pCommOutput->cbData = cbMessage + 2;
  206. pMessage->Header.Byte0 = MSBOF(cbMessage) | 0x80;
  207. pMessage->Header.Byte1 = LSBOF(cbMessage);
  208. SP_RETURN(PCT_ERR_OK);
  209. }
  210. SP_STATUS
  211. Pct1UnpackClientHello(
  212. PSPBuffer pInput,
  213. PPct1_Client_Hello * ppClient)
  214. {
  215. PPCT1_CLIENT_HELLO pMessage;
  216. DWORD ReportedSize;
  217. DWORD CipherSpecsSize, HashSpecsSize, CertSpecsSize;
  218. DWORD ExchSpecsSize;
  219. DWORD cCipherSpecs, cHashSpecs, cCertSpecs, cExchSpecs;
  220. DWORD cOffsetBytes, KeyArgSize;
  221. PPct1_Client_Hello pCanonical;
  222. PUCHAR pBuffer;
  223. DWORD i;
  224. SP_BEGIN("Pct1UnpackClientHello");
  225. if(pInput == NULL ||
  226. ppClient == NULL ||
  227. pInput->pvBuffer == NULL)
  228. {
  229. SP_RETURN(PCT_INT_INTERNAL_ERROR);
  230. }
  231. pMessage = pInput->pvBuffer;
  232. if(pInput->cbData < 2)
  233. {
  234. pInput->cbData = 2;
  235. SP_RETURN(PCT_INT_INCOMPLETE_MSG);
  236. }
  237. ReportedSize = SIZEOF(pMessage);
  238. if ((ReportedSize+2) > pInput->cbData)
  239. {
  240. pInput->cbData = ReportedSize+2;
  241. SP_RETURN(PCT_INT_INCOMPLETE_MSG);
  242. }
  243. if(ReportedSize < PCT_OFFSET_OF(PPCT1_CLIENT_HELLO, VariantData))
  244. {
  245. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  246. }
  247. if(ReportedSize > PCT_MAX_SHAKE_LEN)
  248. {
  249. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  250. }
  251. if ((pMessage->VersionMsb & 0x80) == 0)
  252. {
  253. SP_RETURN (PCT_ERR_SSL_STYLE_MSG);
  254. }
  255. /* We don't recognize hello messages of less version than ourselves,
  256. * those will be handled by a previous version of the code */
  257. if ((pMessage->MessageId != PCT1_MSG_CLIENT_HELLO) ||
  258. ((pMessage->VersionMsb << 8 | pMessage->VersionLsb) < PCT_VERSION_1))
  259. {
  260. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  261. }
  262. cOffsetBytes = COMBINEBYTES( pMessage->OffsetMsb,
  263. pMessage->OffsetLsb );
  264. if(cOffsetBytes < PCT_CH_OFFSET_V1)
  265. {
  266. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  267. }
  268. *ppClient = NULL;
  269. CipherSpecsSize = COMBINEBYTES( pMessage->CipherSpecsLenMsb,
  270. pMessage->CipherSpecsLenLsb );
  271. HashSpecsSize = COMBINEBYTES( pMessage->HashSpecsLenMsb,
  272. pMessage->HashSpecsLenLsb );
  273. CertSpecsSize = COMBINEBYTES( pMessage->CertSpecsLenMsb,
  274. pMessage->CertSpecsLenLsb );
  275. ExchSpecsSize = COMBINEBYTES( pMessage->ExchSpecsLenMsb,
  276. pMessage->ExchSpecsLenLsb );
  277. KeyArgSize = COMBINEBYTES( pMessage->KeyArgLenMsb,
  278. pMessage->KeyArgLenLsb );
  279. /* check that this all fits into the message */
  280. if (PCT_OFFSET_OF(PPCT1_CLIENT_HELLO, VariantData)
  281. - sizeof(PCT1_MESSAGE_HEADER) /* don't count the header */
  282. + cOffsetBytes - PCT_CH_OFFSET_V1
  283. + CipherSpecsSize
  284. + HashSpecsSize
  285. + CertSpecsSize
  286. + ExchSpecsSize
  287. + KeyArgSize != ReportedSize)
  288. {
  289. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  290. }
  291. cCipherSpecs = CipherSpecsSize / sizeof(ExtCipherSpec);
  292. cHashSpecs = HashSpecsSize / sizeof(ExtHashSpec);
  293. cExchSpecs = ExchSpecsSize / sizeof(ExtExchSpec);
  294. cCertSpecs = CertSpecsSize / sizeof(ExtCertSpec);
  295. if(KeyArgSize > SP_MAX_KEY_ARGS)
  296. {
  297. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  298. }
  299. /* Allocate a buffer for the canonical client hello */
  300. pCanonical = (PPct1_Client_Hello)SPExternalAlloc(
  301. sizeof(Pct1_Client_Hello) +
  302. cCipherSpecs * sizeof(CipherSpec) +
  303. cHashSpecs * sizeof(HashSpec) +
  304. cCertSpecs * sizeof(CertSpec) +
  305. cExchSpecs * sizeof(ExchSpec) +
  306. KeyArgSize);
  307. if (!pCanonical)
  308. {
  309. SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
  310. }
  311. pCanonical->cbKeyArgSize = KeyArgSize;
  312. pCanonical->pCipherSpecs = (PCipherSpec) (pCanonical + 1);
  313. pCanonical->pHashSpecs = (PHashSpec) (pCanonical->pCipherSpecs +
  314. cCipherSpecs);
  315. pCanonical->pCertSpecs = (PCertSpec) (pCanonical->pHashSpecs +
  316. cHashSpecs);
  317. pCanonical->pExchSpecs = (PExchSpec) (pCanonical->pCertSpecs +
  318. cCertSpecs);
  319. pCanonical->pKeyArg = (PUCHAR)(pCanonical->pExchSpecs + cExchSpecs);
  320. CopyMemory( pCanonical->SessionID,
  321. pMessage->SessionIdData,
  322. PCT_SESSION_ID_SIZE);
  323. pCanonical->cbSessionID = PCT_SESSION_ID_SIZE;
  324. CopyMemory( pCanonical->Challenge,
  325. pMessage->ChallengeData,
  326. PCT_CHALLENGE_SIZE );
  327. pCanonical->cbChallenge = PCT_CHALLENGE_SIZE;
  328. pBuffer = &pMessage->OffsetLsb + 1 + cOffsetBytes;
  329. pCanonical->cCipherSpecs = cCipherSpecs;
  330. for (i = 0 ; i < cCipherSpecs ; i++ )
  331. {
  332. pCanonical->pCipherSpecs[i] = MapCipherFromExternal(*(ExtCipherSpec UNALIGNED *)
  333. pBuffer);
  334. pBuffer += sizeof(ExtCipherSpec);
  335. }
  336. pCanonical->cHashSpecs = cHashSpecs;
  337. for (i = 0 ; i < cHashSpecs ; i++ )
  338. {
  339. pCanonical->pHashSpecs[i] = MapHashFromExternal(*(ExtHashSpec UNALIGNED *)
  340. pBuffer);
  341. pBuffer += sizeof(ExtHashSpec);
  342. }
  343. pCanonical->cCertSpecs = cCertSpecs;
  344. for (i = 0 ; i < cCertSpecs ; i++ )
  345. {
  346. pCanonical->pCertSpecs[i] = MapCertFromExternal(*(ExtCertSpec UNALIGNED *)
  347. pBuffer);
  348. pBuffer += sizeof(ExtCertSpec);
  349. }
  350. pCanonical->cExchSpecs = cExchSpecs;
  351. for (i = 0 ; i < cExchSpecs ; i++ )
  352. {
  353. pCanonical->pExchSpecs[i] = MapExchFromExternal(*(ExtExchSpec UNALIGNED *)
  354. pBuffer);
  355. pBuffer += sizeof(ExtExchSpec);
  356. }
  357. CopyMemory(pCanonical->pKeyArg, pBuffer, KeyArgSize);
  358. *ppClient = pCanonical;
  359. pInput->cbData = ReportedSize + sizeof(PCT1_MESSAGE_HEADER);
  360. SP_RETURN(PCT_ERR_OK);
  361. }
  362. SP_STATUS
  363. Pct1PackServerHello(
  364. PPct1_Server_Hello pCanonical,
  365. PSPBuffer pCommOutput)
  366. {
  367. DWORD cbMessage;
  368. PPCT1_SERVER_HELLO pMessage;
  369. DWORD Size;
  370. PUCHAR pBuffer;
  371. DWORD i, iBuff;
  372. SP_BEGIN("Pct1PackServerHello");
  373. if(pCanonical == NULL || pCommOutput == NULL)
  374. {
  375. SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
  376. }
  377. pCommOutput->cbData = 0;
  378. if(pCanonical->cbConnectionID != PCT_SESSION_ID_SIZE)
  379. {
  380. SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
  381. }
  382. cbMessage = pCanonical->CertificateLen +
  383. pCanonical->cCertSpecs * sizeof(ExtCertSpec) +
  384. pCanonical->cSigSpecs * sizeof(ExtSigSpec) +
  385. pCanonical->ResponseLen +
  386. PCT_OFFSET_OF(PPCT1_SERVER_HELLO, VariantData) -
  387. sizeof(PCT1_MESSAGE_HEADER);
  388. if (cbMessage > PCT_MAX_SHAKE_LEN)
  389. {
  390. SP_RETURN(SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW));
  391. }
  392. pCommOutput->cbData = cbMessage + 2;
  393. /* are we allocating our own memory? */
  394. if(pCommOutput->pvBuffer == NULL)
  395. {
  396. pCommOutput->pvBuffer = SPExternalAlloc(pCommOutput->cbData);
  397. if (NULL == pCommOutput->pvBuffer)
  398. {
  399. SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
  400. }
  401. pCommOutput->cbBuffer = pCommOutput->cbData;
  402. }
  403. if(pCommOutput->cbData > pCommOutput->cbBuffer)
  404. {
  405. // Required size returned in pCommOutput->cbData.
  406. SP_RETURN(PCT_INT_BUFF_TOO_SMALL);
  407. }
  408. pMessage = pCommOutput->pvBuffer;
  409. pMessage->MessageId = PCT1_MSG_SERVER_HELLO;
  410. pMessage->ServerVersionMsb = MSBOF(PCT_VERSION_1);
  411. pMessage->ServerVersionLsb = LSBOF(PCT_VERSION_1);
  412. pMessage->RestartSessionOK = (UCHAR) pCanonical->RestartOk;
  413. pMessage->ClientAuthReq = (UCHAR)pCanonical->ClientAuthReq;
  414. MapCipherToExternal(pCanonical->SrvCipherSpec, &pMessage->CipherSpecData);
  415. MapHashToExternal(pCanonical->SrvHashSpec, &pMessage->HashSpecData);
  416. MapCertToExternal(pCanonical->SrvCertSpec, &pMessage->CertSpecData);
  417. MapExchToExternal(pCanonical->SrvExchSpec, &pMessage->ExchSpecData);
  418. CopyMemory(pMessage->ConnectionIdData, pCanonical->ConnectionID,
  419. pCanonical->cbConnectionID);
  420. pBuffer = pMessage->VariantData;
  421. /* Pack certificate if present */
  422. pMessage->CertificateLenMsb = MSBOF(pCanonical->CertificateLen);
  423. pMessage->CertificateLenLsb = LSBOF(pCanonical->CertificateLen);
  424. if (pCanonical->CertificateLen)
  425. {
  426. CopyMemory( pBuffer,
  427. pCanonical->pCertificate,
  428. pCanonical->CertificateLen);
  429. pBuffer += pCanonical->CertificateLen ;
  430. }
  431. iBuff = 0;
  432. for (i = 0; i < pCanonical->cCertSpecs ; i++ )
  433. {
  434. if (MapCertToExternal(pCanonical->pClientCertSpecs[i],
  435. &((ExtCertSpec UNALIGNED *) pBuffer)[iBuff]))
  436. {
  437. iBuff ++;
  438. }
  439. }
  440. Size = iBuff*sizeof(ExtCertSpec);
  441. pBuffer += Size;
  442. pMessage->CertSpecsLenMsb = MSBOF(Size);
  443. pMessage->CertSpecsLenLsb = LSBOF(Size);
  444. cbMessage -= (pCanonical->cCertSpecs - iBuff)*sizeof(ExtCertSpec);
  445. iBuff = 0;
  446. for (i = 0; i < pCanonical->cSigSpecs ; i++ )
  447. {
  448. if (MapSigToExternal(pCanonical->pClientSigSpecs[i],
  449. &((ExtSigSpec UNALIGNED *) pBuffer)[iBuff]) )
  450. {
  451. iBuff++;
  452. }
  453. }
  454. Size = iBuff*sizeof(ExtSigSpec);
  455. pBuffer += Size;
  456. pMessage->ClientSigSpecsLenMsb = MSBOF(Size);
  457. pMessage->ClientSigSpecsLenLsb = LSBOF(Size);
  458. cbMessage -= (pCanonical->cSigSpecs - iBuff)*sizeof(ExtSigSpec);
  459. pMessage->ResponseLenMsb = MSBOF(pCanonical->ResponseLen);
  460. pMessage->ResponseLenLsb = LSBOF(pCanonical->ResponseLen);
  461. CopyMemory( pBuffer,
  462. pCanonical->Response,
  463. pCanonical->ResponseLen);
  464. pBuffer += pCanonical->ResponseLen;
  465. pCommOutput->cbData = cbMessage + 2;
  466. pMessage->Header.Byte0 = MSBOF(cbMessage) | 0x80;
  467. pMessage->Header.Byte1 = LSBOF(cbMessage);
  468. SP_RETURN(PCT_ERR_OK);
  469. }
  470. SP_STATUS
  471. Pct1UnpackServerHello(
  472. PSPBuffer pInput,
  473. PPct1_Server_Hello * ppServer)
  474. {
  475. PPct1_Server_Hello pCanonical;
  476. PPCT1_SERVER_HELLO pMessage;
  477. PUCHAR pBuffer;
  478. DWORD cbCertificate, cbResponse;
  479. DWORD cCertSpecs, cSigSpecs;
  480. DWORD i;
  481. DWORD ReportedSize;
  482. SP_BEGIN("Pct1UnpackServerHello");
  483. if(pInput == NULL ||
  484. ppServer == NULL ||
  485. pInput->pvBuffer == NULL)
  486. {
  487. SP_RETURN(PCT_INT_INTERNAL_ERROR);
  488. }
  489. pMessage = pInput->pvBuffer;
  490. if(pInput->cbData < 2)
  491. {
  492. pInput->cbData = 2;
  493. SP_RETURN(PCT_INT_INCOMPLETE_MSG);
  494. }
  495. ReportedSize = SIZEOF(pMessage);
  496. if(ReportedSize > PCT_MAX_SHAKE_LEN)
  497. {
  498. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  499. }
  500. if ((ReportedSize+2) > pInput->cbData)
  501. {
  502. pInput->cbData = ReportedSize+2;
  503. SP_RETURN(PCT_INT_INCOMPLETE_MSG);
  504. }
  505. if(ReportedSize < PCT_OFFSET_OF(PPCT1_SERVER_HELLO, VariantData) )
  506. {
  507. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  508. }
  509. /* Verify Header: */
  510. /* we don't handle server hello messages of latter version than ourselves,
  511. * those will be handled by latter verisions of the protocol */
  512. if ((pMessage->MessageId != PCT1_MSG_SERVER_HELLO) ||
  513. ((pMessage->ServerVersionMsb << 8 | pMessage->ServerVersionLsb) != PCT_VERSION_1))
  514. {
  515. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  516. }
  517. *ppServer = NULL;
  518. cbCertificate = COMBINEBYTES(pMessage->CertificateLenMsb,
  519. pMessage->CertificateLenLsb);
  520. cCertSpecs = COMBINEBYTES(pMessage->CertSpecsLenMsb,
  521. pMessage->CertSpecsLenLsb);
  522. cCertSpecs /= sizeof(ExtCertSpec);
  523. cSigSpecs = COMBINEBYTES(pMessage->ClientSigSpecsLenMsb,
  524. pMessage->ClientSigSpecsLenLsb);
  525. cSigSpecs /= sizeof(ExtSigSpec);
  526. cbResponse = COMBINEBYTES(pMessage->ResponseLenMsb,
  527. pMessage->ResponseLenLsb);
  528. if(cbResponse > PCT1_RESPONSE_SIZE)
  529. {
  530. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  531. }
  532. /* check that this all fits into the message */
  533. if (PCT_OFFSET_OF(PPCT1_SERVER_HELLO, VariantData)
  534. - sizeof(PCT1_MESSAGE_HEADER) /* don't count the header */
  535. + cbCertificate
  536. + cCertSpecs*sizeof(ExtCertSpec)
  537. + cSigSpecs*sizeof(ExtSigSpec)
  538. + cbResponse != ReportedSize)
  539. {
  540. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  541. }
  542. pCanonical = (PPct1_Server_Hello)SPExternalAlloc(
  543. sizeof(Pct1_Server_Hello) +
  544. cCertSpecs * sizeof(CertSpec) +
  545. cSigSpecs * sizeof(SigSpec) +
  546. cbCertificate);
  547. if (!pCanonical)
  548. {
  549. SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
  550. }
  551. /* Set up pointers to be in this memory allocation. */
  552. pCanonical->pClientCertSpecs = (PCertSpec) (pCanonical + 1);
  553. pCanonical->pClientSigSpecs = (PSigSpec)(pCanonical->pClientCertSpecs +
  554. cCertSpecs);
  555. pCanonical->pCertificate = (PUCHAR) (pCanonical->pClientSigSpecs +
  556. cSigSpecs);
  557. /* Expand out: */
  558. pCanonical->RestartOk = (DWORD) pMessage->RestartSessionOK;
  559. pCanonical->ClientAuthReq = (DWORD)pMessage->ClientAuthReq;
  560. pCanonical->SrvCertSpec = MapCertFromExternal(pMessage->CertSpecData);
  561. pCanonical->SrvCipherSpec =MapCipherFromExternal(pMessage->CipherSpecData);
  562. pCanonical->SrvHashSpec = MapHashFromExternal(pMessage->HashSpecData);
  563. pCanonical->SrvExchSpec = MapExchFromExternal(pMessage->ExchSpecData);
  564. pCanonical->CertificateLen = cbCertificate;
  565. pCanonical->ResponseLen = cbResponse;
  566. pCanonical->cCertSpecs = cCertSpecs;
  567. pCanonical->cSigSpecs = cSigSpecs;
  568. CopyMemory(pCanonical->ConnectionID,
  569. pMessage->ConnectionIdData,
  570. PCT_SESSION_ID_SIZE);
  571. pCanonical->cbConnectionID= PCT_SESSION_ID_SIZE;
  572. pBuffer = pMessage->VariantData;
  573. CopyMemory(pCanonical->pCertificate, pBuffer, cbCertificate);
  574. pBuffer += cbCertificate;
  575. for (i = 0 ; i < cCertSpecs ; i++ )
  576. {
  577. pCanonical->pClientCertSpecs[i] = MapCertFromExternal(
  578. *(ExtCertSpec UNALIGNED *)pBuffer);
  579. pBuffer += sizeof(ExtCertSpec);
  580. }
  581. for (i = 0 ; i < cSigSpecs ; i++ )
  582. {
  583. pCanonical->pClientSigSpecs[i] = MapSigFromExternal(
  584. *(ExtSigSpec UNALIGNED *)pBuffer);
  585. pBuffer += sizeof(ExtSigSpec);
  586. }
  587. CopyMemory(pCanonical->Response, pBuffer, cbResponse);
  588. *ppServer = pCanonical;
  589. pInput->cbData = ReportedSize + sizeof(PCT1_MESSAGE_HEADER);
  590. SP_RETURN(PCT_ERR_OK);
  591. }
  592. SP_STATUS
  593. Pct1PackClientMasterKey(
  594. PPct1_Client_Master_Key pCanonical,
  595. PSPBuffer pCommOutput)
  596. {
  597. DWORD cbMessage;
  598. PPCT1_CLIENT_MASTER_KEY pMessage;
  599. PUCHAR pBuffer;
  600. SP_BEGIN("Pct1PackClientMasterKey");
  601. if(pCanonical == NULL || pCommOutput == NULL)
  602. {
  603. SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
  604. }
  605. pCommOutput->cbData = 0;
  606. cbMessage = pCanonical->ClearKeyLen +
  607. pCanonical->EncryptedKeyLen +
  608. pCanonical->KeyArgLen +
  609. pCanonical->VerifyPreludeLen +
  610. pCanonical->ClientCertLen +
  611. pCanonical->ResponseLen +
  612. PCT_OFFSET_OF(PPCT1_CLIENT_MASTER_KEY, VariantData) -
  613. sizeof(PCT1_MESSAGE_HEADER);
  614. if (cbMessage > PCT_MAX_SHAKE_LEN)
  615. {
  616. SP_RETURN(SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW));
  617. }
  618. pCommOutput->cbData = cbMessage + 2;
  619. /* are we allocating our own memory? */
  620. if(pCommOutput->pvBuffer == NULL)
  621. {
  622. pCommOutput->pvBuffer = SPExternalAlloc(pCommOutput->cbData);
  623. if (NULL == pCommOutput->pvBuffer)
  624. {
  625. SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
  626. }
  627. pCommOutput->cbBuffer = pCommOutput->cbData;
  628. }
  629. if(pCommOutput->cbData > pCommOutput->cbBuffer)
  630. {
  631. // Required size returned in pCommOutput->cbData.
  632. SP_RETURN(PCT_INT_BUFF_TOO_SMALL);
  633. }
  634. pMessage = pCommOutput->pvBuffer;
  635. pBuffer = pMessage->VariantData;
  636. pMessage->Header.Byte0 = MSBOF(cbMessage) | 0x80;
  637. pMessage->Header.Byte1 = LSBOF(cbMessage);
  638. pMessage->MessageId = PCT1_MSG_CLIENT_MASTER_KEY;
  639. pMessage->ClearKeyLenMsb = MSBOF(pCanonical->ClearKeyLen);
  640. pMessage->ClearKeyLenLsb = LSBOF(pCanonical->ClearKeyLen);
  641. MapSigToExternal(pCanonical->ClientSigSpec, &pMessage->ClientSigSpecData);
  642. MapCertToExternal(pCanonical->ClientCertSpec, &pMessage->ClientCertSpecData);
  643. CopyMemory(pBuffer, pCanonical->ClearKey, pCanonical->ClearKeyLen);
  644. pBuffer += pCanonical->ClearKeyLen;
  645. pMessage->EncryptedKeyLenMsb = MSBOF(pCanonical->EncryptedKeyLen);
  646. pMessage->EncryptedKeyLenLsb = LSBOF(pCanonical->EncryptedKeyLen);
  647. CopyMemory(pBuffer, pCanonical->pbEncryptedKey, pCanonical->EncryptedKeyLen);
  648. pBuffer += pCanonical->EncryptedKeyLen;
  649. pMessage->KeyArgLenMsb = MSBOF(pCanonical->KeyArgLen);
  650. pMessage->KeyArgLenLsb = LSBOF(pCanonical->KeyArgLen);
  651. CopyMemory(pBuffer, pCanonical->KeyArg, pCanonical->KeyArgLen);
  652. pBuffer += pCanonical->KeyArgLen;
  653. pMessage->VerifyPreludeLenMsb = MSBOF(pCanonical->VerifyPreludeLen);
  654. pMessage->VerifyPreludeLenLsb = LSBOF(pCanonical->VerifyPreludeLen);
  655. CopyMemory(pBuffer, pCanonical->VerifyPrelude,
  656. pCanonical->VerifyPreludeLen);
  657. pBuffer += pCanonical->VerifyPreludeLen;
  658. pMessage->ClientCertLenMsb = MSBOF(pCanonical->ClientCertLen);
  659. pMessage->ClientCertLenLsb = LSBOF(pCanonical->ClientCertLen);
  660. CopyMemory(pBuffer, pCanonical->pClientCert, pCanonical->ClientCertLen);
  661. pBuffer += pCanonical->ClientCertLen;
  662. pMessage->ResponseLenMsb = MSBOF(pCanonical->ResponseLen);
  663. pMessage->ResponseLenLsb = LSBOF(pCanonical->ResponseLen);
  664. CopyMemory(pBuffer, pCanonical->pbResponse, pCanonical->ResponseLen);
  665. SP_RETURN(PCT_ERR_OK);
  666. }
  667. SP_STATUS
  668. Pct1UnpackClientMasterKey(
  669. PSPBuffer pInput,
  670. PPct1_Client_Master_Key * ppClient)
  671. {
  672. PPct1_Client_Master_Key pCanonical;
  673. PUCHAR pBuffer;
  674. DWORD ReportedSize;
  675. PPCT1_CLIENT_MASTER_KEY pMessage;
  676. DWORD cbClearKey, cbEncryptedKey, cbKeyArg, cbVerifyPrelude, cbClientCert, cbResponse;
  677. SP_BEGIN("Pct1UnpackClientMasterKey");
  678. if(pInput == NULL ||
  679. ppClient == NULL ||
  680. pInput->pvBuffer == NULL)
  681. {
  682. SP_RETURN(PCT_INT_INTERNAL_ERROR);
  683. }
  684. pMessage = pInput->pvBuffer;
  685. if(pInput->cbData < 2)
  686. {
  687. pInput->cbData = 2;
  688. SP_RETURN(PCT_INT_INCOMPLETE_MSG);
  689. }
  690. ReportedSize = SIZEOF(pMessage);
  691. if(ReportedSize > PCT_MAX_SHAKE_LEN)
  692. {
  693. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  694. }
  695. if ((ReportedSize+2) > pInput->cbData)
  696. {
  697. pInput->cbData = ReportedSize+2;
  698. SP_RETURN(PCT_INT_INCOMPLETE_MSG);
  699. }
  700. if(ReportedSize < PCT_OFFSET_OF(PPCT1_CLIENT_MASTER_KEY, VariantData))
  701. {
  702. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  703. }
  704. /* Verify Header: */
  705. if (pMessage->MessageId != PCT1_MSG_CLIENT_MASTER_KEY )
  706. {
  707. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  708. }
  709. cbClearKey = COMBINEBYTES( pMessage->ClearKeyLenMsb,
  710. pMessage->ClearKeyLenLsb );
  711. cbEncryptedKey = COMBINEBYTES( pMessage->EncryptedKeyLenMsb,
  712. pMessage->EncryptedKeyLenLsb );
  713. cbKeyArg = COMBINEBYTES( pMessage->KeyArgLenMsb,
  714. pMessage->KeyArgLenLsb );
  715. cbVerifyPrelude = COMBINEBYTES( pMessage->VerifyPreludeLenMsb,
  716. pMessage->VerifyPreludeLenLsb );
  717. cbClientCert = COMBINEBYTES( pMessage->ClientCertLenMsb,
  718. pMessage->ClientCertLenLsb );
  719. cbResponse = COMBINEBYTES( pMessage->ResponseLenMsb,
  720. pMessage->ResponseLenLsb );
  721. /* defensive checks..... */
  722. if ((cbClearKey > SP_MAX_MASTER_KEY) ||
  723. (cbKeyArg > PCT1_MAX_KEY_ARGS) ||
  724. (cbVerifyPrelude > RESPONSE_SIZE))
  725. {
  726. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  727. }
  728. if ((PCT_OFFSET_OF(PPCT1_CLIENT_MASTER_KEY, VariantData) -
  729. sizeof(PCT1_MESSAGE_HEADER) +
  730. cbClearKey +
  731. cbEncryptedKey +
  732. cbKeyArg +
  733. cbVerifyPrelude +
  734. cbClientCert +
  735. cbResponse) !=
  736. ReportedSize)
  737. {
  738. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  739. }
  740. *ppClient = NULL;
  741. pCanonical = (PPct1_Client_Master_Key)SPExternalAlloc(
  742. sizeof(Pct1_Client_Master_Key) +
  743. cbClientCert +
  744. cbEncryptedKey +
  745. cbResponse);
  746. if (!pCanonical)
  747. {
  748. SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
  749. }
  750. pCanonical->ClearKeyLen = cbClearKey;
  751. pCanonical->EncryptedKeyLen = cbEncryptedKey;
  752. pCanonical->KeyArgLen = cbKeyArg;
  753. pCanonical->VerifyPreludeLen = cbVerifyPrelude;
  754. pCanonical->ClientCertLen = cbClientCert;
  755. pCanonical->ResponseLen = cbResponse;
  756. /* defensive checks..... */
  757. pCanonical->ClientCertSpec = MapCertFromExternal(pMessage->ClientCertSpecData);
  758. pCanonical->pClientCert = (PUCHAR)(pCanonical+1);
  759. pCanonical->ClientSigSpec = MapSigFromExternal(pMessage->ClientSigSpecData);
  760. /* ok, we're pretty sure we aren't going to fault. */
  761. pBuffer = pMessage->VariantData;
  762. CopyMemory(pCanonical->ClearKey, pBuffer, pCanonical->ClearKeyLen );
  763. pBuffer += pCanonical->ClearKeyLen;
  764. pCanonical->pbEncryptedKey = pCanonical->pClientCert + cbClientCert;
  765. CopyMemory(pCanonical->pbEncryptedKey, pBuffer, pCanonical->EncryptedKeyLen);
  766. pBuffer += pCanonical->EncryptedKeyLen;
  767. CopyMemory( pCanonical->KeyArg, pBuffer, pCanonical->KeyArgLen );
  768. pBuffer += pCanonical->KeyArgLen;
  769. CopyMemory( pCanonical->VerifyPrelude, pBuffer,
  770. pCanonical->VerifyPreludeLen );
  771. pBuffer += pCanonical->VerifyPreludeLen;
  772. CopyMemory( pCanonical->pClientCert, pBuffer, pCanonical->ClientCertLen );
  773. pBuffer += pCanonical->ClientCertLen;
  774. pCanonical->pbResponse = pCanonical->pbEncryptedKey + cbEncryptedKey;
  775. CopyMemory( pCanonical->pbResponse, pBuffer, pCanonical->ResponseLen );
  776. *ppClient = pCanonical;
  777. pInput->cbData = ReportedSize + sizeof(PCT1_MESSAGE_HEADER);
  778. SP_RETURN( PCT_ERR_OK );
  779. }
  780. SP_STATUS
  781. Pct1PackServerVerify(
  782. PPct1_Server_Verify pCanonical,
  783. PSPBuffer pCommOutput)
  784. {
  785. DWORD cbMessage;
  786. PPCT1_SERVER_VERIFY pMessage;
  787. PUCHAR pBuffer;
  788. SP_BEGIN("Pct1PackServerVerify");
  789. if(pCanonical == NULL || pCommOutput == NULL)
  790. {
  791. SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
  792. }
  793. pCommOutput->cbData = 0;
  794. cbMessage = pCanonical->ResponseLen +
  795. PCT_OFFSET_OF(PPCT1_SERVER_VERIFY, VariantData) -
  796. sizeof(PCT1_MESSAGE_HEADER);
  797. if (cbMessage > PCT_MAX_SHAKE_LEN)
  798. {
  799. SP_RETURN(PCT_INT_DATA_OVERFLOW);
  800. }
  801. pCommOutput->cbData = cbMessage + 2;
  802. /* are we allocating our own memory? */
  803. if(pCommOutput->pvBuffer == NULL)
  804. {
  805. pCommOutput->pvBuffer = SPExternalAlloc(pCommOutput->cbData);
  806. if (NULL == pCommOutput->pvBuffer)
  807. {
  808. SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
  809. }
  810. pCommOutput->cbBuffer = pCommOutput->cbData;
  811. }
  812. if(pCommOutput->cbData > pCommOutput->cbBuffer)
  813. {
  814. // Required size returned in pCommOutput->cbData.
  815. SP_RETURN(PCT_INT_BUFF_TOO_SMALL);
  816. }
  817. pMessage = pCommOutput->pvBuffer;
  818. pMessage->MessageId = PCT1_MSG_SERVER_VERIFY;
  819. pMessage->Header.Byte0 = MSBOF(cbMessage) | 0x80;
  820. pMessage->Header.Byte1 = LSBOF(cbMessage);
  821. CopyMemory(pMessage->SessionIdData, pCanonical->SessionIdData,
  822. PCT_SESSION_ID_SIZE);
  823. pBuffer = pMessage->VariantData;
  824. /* Pack certificate if present */
  825. pMessage->ResponseLenMsb = MSBOF(pCanonical->ResponseLen);
  826. pMessage->ResponseLenLsb = LSBOF(pCanonical->ResponseLen);
  827. if (pCanonical->ResponseLen)
  828. {
  829. CopyMemory( pBuffer,
  830. pCanonical->Response,
  831. pCanonical->ResponseLen);
  832. }
  833. SP_RETURN( PCT_ERR_OK );
  834. }
  835. SP_STATUS
  836. Pct1UnpackServerVerify(
  837. PSPBuffer pInput,
  838. PPct1_Server_Verify * ppServer)
  839. {
  840. PPct1_Server_Verify pCanonical;
  841. PPCT1_SERVER_VERIFY pMessage;
  842. PUCHAR pBuffer;
  843. DWORD cbResponse;
  844. DWORD ReportedSize;
  845. SP_BEGIN("Pct1UnpackServerVerify");
  846. if(pInput == NULL ||
  847. ppServer == NULL ||
  848. pInput->pvBuffer == NULL)
  849. {
  850. SP_RETURN(PCT_INT_INTERNAL_ERROR);
  851. }
  852. pMessage = pInput->pvBuffer;
  853. if(pInput->cbData < 2)
  854. {
  855. pInput->cbData = 2;
  856. SP_RETURN(PCT_INT_INCOMPLETE_MSG);
  857. }
  858. ReportedSize = SIZEOF(pMessage);
  859. if(ReportedSize > PCT_MAX_SHAKE_LEN)
  860. {
  861. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  862. }
  863. if ((ReportedSize+2) > pInput->cbData)
  864. {
  865. pInput->cbData = ReportedSize+2;
  866. SP_RETURN(PCT_INT_INCOMPLETE_MSG);
  867. }
  868. if(ReportedSize < PCT_OFFSET_OF(PPCT1_SERVER_VERIFY, VariantData))
  869. {
  870. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  871. }
  872. /* Verify Header: */
  873. if (pMessage->MessageId != PCT1_MSG_SERVER_VERIFY )
  874. {
  875. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  876. }
  877. *ppServer = NULL;
  878. /* Verify Header: */
  879. cbResponse = COMBINEBYTES(pMessage->ResponseLenMsb,
  880. pMessage->ResponseLenLsb);
  881. if (cbResponse > PCT_SESSION_ID_SIZE)
  882. {
  883. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  884. }
  885. if ((PCT_OFFSET_OF(PPCT1_SERVER_VERIFY, VariantData) -
  886. sizeof(PCT1_MESSAGE_HEADER) +
  887. cbResponse ) !=
  888. ReportedSize)
  889. {
  890. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  891. }
  892. pCanonical = (PPct1_Server_Verify)SPExternalAlloc( sizeof(Pct1_Server_Verify));
  893. if (!pCanonical)
  894. {
  895. SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
  896. }
  897. /* Expand out: */
  898. pCanonical->ResponseLen = cbResponse;
  899. CopyMemory((PUCHAR)pCanonical->SessionIdData, pMessage->SessionIdData,
  900. PCT_SESSION_ID_SIZE);
  901. pBuffer = pMessage->VariantData;
  902. CopyMemory(pCanonical->Response, pBuffer, cbResponse);
  903. *ppServer = pCanonical;
  904. pInput->cbData = ReportedSize + sizeof(PCT1_MESSAGE_HEADER);
  905. SP_RETURN(PCT_ERR_OK);
  906. }
  907. SP_STATUS
  908. Pct1PackError(
  909. PPct1_Error pCanonical,
  910. PSPBuffer pCommOutput)
  911. {
  912. DWORD cbMessage;
  913. PPCT1_ERROR pMessage;
  914. SP_BEGIN("Pct1PackError");
  915. if(pCanonical == NULL || pCommOutput == NULL)
  916. {
  917. SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
  918. }
  919. pCommOutput->cbData = 0;
  920. cbMessage = pCanonical->ErrInfoLen +
  921. PCT_OFFSET_OF(PPCT1_ERROR, VariantData) -
  922. sizeof(PCT1_MESSAGE_HEADER);
  923. if (cbMessage > PCT_MAX_SHAKE_LEN)
  924. {
  925. SP_RETURN(SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW));
  926. }
  927. pCommOutput->cbData = cbMessage+2;
  928. /* are we allocating our own memory? */
  929. if(pCommOutput->pvBuffer == NULL)
  930. {
  931. pCommOutput->pvBuffer = SPExternalAlloc(pCommOutput->cbData);
  932. if (NULL == pCommOutput->pvBuffer)
  933. {
  934. SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
  935. }
  936. pCommOutput->cbBuffer = pCommOutput->cbData;
  937. }
  938. if(pCommOutput->cbData > pCommOutput->cbBuffer)
  939. {
  940. // Required size returned in pCommOutput->cbData.
  941. SP_RETURN(PCT_INT_BUFF_TOO_SMALL);
  942. }
  943. pMessage = pCommOutput->pvBuffer;
  944. pMessage->Header.Byte0 = MSBOF(cbMessage) | 0x80;
  945. pMessage->Header.Byte1 = LSBOF(cbMessage);
  946. pMessage->MessageId = PCT1_MSG_ERROR;
  947. pMessage->ErrorMsb = MSBOF(pCanonical->Error);
  948. pMessage->ErrorLsb = LSBOF(pCanonical->Error);
  949. pMessage->ErrorInfoMsb = MSBOF(pCanonical->ErrInfoLen);
  950. pMessage->ErrorInfoLsb = LSBOF(pCanonical->ErrInfoLen);
  951. if(pCanonical->ErrInfoLen) {
  952. CopyMemory(pMessage->VariantData, pCanonical->ErrInfo, pCanonical->ErrInfoLen);
  953. }
  954. SP_RETURN( PCT_ERR_OK );
  955. }