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.

1329 lines
42 KiB

  1. /*++
  2. Copyright (c) 1997-2001 Microsoft Corporation
  3. Module Name:
  4. hughes.c
  5. Abstract:
  6. This module contains the code to create/verify the Hughes transform.
  7. Author:
  8. Sanjay Anand (SanjayAn) 13-March-1997
  9. ChunYe
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. NTSTATUS
  16. IPSecHashMdlChain(
  17. IN PSA_TABLE_ENTRY pSA,
  18. IN PVOID pBuffer,
  19. IN PUCHAR pHash,
  20. IN BOOLEAN fIncoming,
  21. IN AH_ALGO eAlgo,
  22. OUT PULONG pLen,
  23. IN ULONG Index
  24. )
  25. /*++
  26. Routine Description:
  27. Hash the entire chain using the algo passed in
  28. Arguments:
  29. pSA - the security association
  30. pBuffer - chain of MDLs (if fIncoming is FALSE) or RcvBufs (if fIncoming is TRUE)
  31. pHash - where to put the hash
  32. fIncoming - TRUE if on recv path
  33. eAlgo - the algorithm index
  34. pLen - returns length hashed
  35. Return Value:
  36. STATUS_SUCCESS
  37. Others:
  38. STATUS_INSUFFICIENT_RESOURCES
  39. STATUS_UNSUCCESSFUL (error in algo.)
  40. --*/
  41. {
  42. ALGO_STATE State = {0};
  43. NTSTATUS status;
  44. PAUTH_ALGO pAlgo=&(auth_algorithms[eAlgo]);
  45. PUCHAR pPyld;
  46. ULONG Len;
  47. State.as_sa = pSA;
  48. status = pAlgo->init(&State, Index);
  49. if (fIncoming) {
  50. IPRcvBuf *pBuf = (IPRcvBuf *)pBuffer;
  51. while (pBuf) {
  52. IPSecQueryRcvBuf(pBuf, &pPyld, &Len);
  53. pAlgo->update(&State, pPyld, Len);
  54. *pLen += Len;
  55. pBuf = IPSEC_BUFFER_LINKAGE(pBuf);
  56. }
  57. } else {
  58. PNDIS_BUFFER pBuf = (PNDIS_BUFFER)pBuffer;
  59. while (pBuf) {
  60. IPSecQueryNdisBuf(pBuf, &pPyld, &Len);
  61. pAlgo->update(&State, pPyld, Len);
  62. *pLen += Len;
  63. pBuf = NDIS_BUFFER_LINKAGE(pBuf);
  64. }
  65. }
  66. pAlgo->finish(&State, pHash, Index);
  67. return STATUS_SUCCESS;
  68. }
  69. NTSTATUS
  70. IPSecCreateHughes(
  71. IN PUCHAR pIPHeader,
  72. IN PVOID pData,
  73. IN PSA_TABLE_ENTRY pSA,
  74. IN ULONG Index,
  75. OUT PVOID *ppNewData,
  76. OUT PVOID *ppSCContext,
  77. OUT PULONG pExtraBytes,
  78. IN ULONG HdrSpace,
  79. IN PNDIS_PACKET pNdisPacket,
  80. IN BOOLEAN fCryptoOnly
  81. )
  82. /*++
  83. Routine Description:
  84. Create the combined esp-des-* transform, as outlined in
  85. draft-ietf-ipsec-esp-v2-00, on the send side.
  86. 0 1 2 3
  87. 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  88. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ----
  89. | Security Parameters Index (SPI) | ^
  90. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Auth.
  91. | Sequence Number | |Coverage
  92. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | -----
  93. | Payload Data* (variable) | | ^
  94. ~ ~ | |
  95. | | | |
  96. + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Confid.
  97. | | Padding (0-255 bytes) | |Coverage*
  98. +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
  99. | | Pad Length | Next Header | v v
  100. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -------
  101. | Authentication Data (variable) |
  102. ~ ~
  103. | |
  104. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  105. * If included in the Payload field, cryptographic synchronization
  106. data, e.g., an IV, usually is not encrypted per se, although it
  107. often is referred to as being part of the ciphertext.
  108. The payload field, as defined in [ESP], is broken down according to
  109. the following diagram:
  110. +---------------+---------------+---------------+---------------+
  111. | |
  112. + Initialization Vector (IV) +
  113. | |
  114. +---------------+---------------+---------------+---------------+
  115. | |
  116. ~ Encrypted Payload (variable length) ~
  117. | |
  118. +---------------------------------------------------------------+
  119. 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
  120. Arguments:
  121. pIPHeader - points to start of IP header.
  122. pData - points to the data after the IP header. PNDIS_BUFFER
  123. pSA - Sec. Assoc. entry
  124. ppNewData - the new MDL chain to be used by TCPIP
  125. ppSCContext - send complete context used to clean up IPSEC headers
  126. pExtraBytes - the header expansion caused by this IPSEC header
  127. Return Value:
  128. STATUS_SUCCESS
  129. Others:
  130. STATUS_INSUFFICIENT_RESOURCES
  131. STATUS_UNSUCCESSFUL (error in algo.)
  132. --*/
  133. {
  134. ESP UNALIGNED *pESP;
  135. NTSTATUS status = STATUS_SUCCESS;
  136. PNDIS_BUFFER pESPBuffer = NULL;
  137. PNDIS_BUFFER pPadBuf = NULL;
  138. PNDIS_BUFFER pOptBuf = NULL;
  139. ULONG espLen;
  140. ULONG padLen;
  141. ULONG totalLen = 0;
  142. IPHeader UNALIGNED * pIPH;
  143. PIPSEC_SEND_COMPLETE_CONTEXT pContext;
  144. PNDIS_BUFFER pNewMdl = NULL;
  145. PNDIS_BUFFER pSaveMdl;
  146. PAUTH_ALGO pAlgo = &(auth_algorithms[pSA->INT_ALGO(Index)]);
  147. ULONG PayloadType;
  148. ULONG hdrLen;
  149. PUCHAR pPad;
  150. ULONG TruncatedLen = (pSA->INT_ALGO(Index) != IPSEC_AH_NONE)? pSA->sa_TruncatedLen: 0;
  151. BOOLEAN fTunnel = ( (pSA->sa_Flags & FLAGS_SA_TUNNEL) &&
  152. ((Index == 0) ||
  153. ((Index == 1) && (pSA->sa_Operation[0] == Compress))));
  154. ULONG tag = (!fTunnel) ?
  155. IPSEC_TAG_HUGHES :
  156. IPSEC_TAG_HUGHES_TU;
  157. IPHeader UNALIGNED * pIPH2;
  158. PNDIS_BUFFER pHdrBuf=NULL;
  159. ULONG bytesLeft;
  160. ULONG hashBytes=0;
  161. ULONG saveFlags=0;
  162. ULONG Seq;
  163. USHORT IPLength;
  164. PNDIS_BUFFER pSaveDataLinkage = NDIS_BUFFER_LINKAGE((PNDIS_BUFFER)pData);
  165. PNDIS_BUFFER pSaveOptLinkage = NULL;
  166. PNDIS_BUFFER pSaveBeforePad = NULL;
  167. IPSEC_DEBUG(HUGHES, ("Entering IPSecCreateHughes\n"));
  168. #if DBG
  169. IPSEC_DEBUG(MDL, ("Entering IPSecCreateHughes\n"));
  170. IPSEC_PRINT_CONTEXT(*ppSCContext);
  171. IPSEC_PRINT_MDL(pData);
  172. #endif
  173. ASSERT(pSA->sa_Operation[Index] == Encrypt);
  174. if (*ppSCContext == NULL) {
  175. pContext = IPSecAllocateSendCompleteCtx(tag);
  176. if (!pContext) {
  177. IPSEC_DEBUG(HUGHES, ("Failed to alloc. SendCtx\n"));
  178. return STATUS_INSUFFICIENT_RESOURCES;
  179. }
  180. IPSEC_INCREMENT(g_ipsec.NumSends);
  181. IPSecZeroMemory(pContext, sizeof(IPSEC_SEND_COMPLETE_CONTEXT));
  182. #if DBG
  183. RtlCopyMemory(pContext->Signature, "ISC4", 4);
  184. #endif
  185. //
  186. // Send complete context
  187. //
  188. *ppSCContext = pContext;
  189. } else {
  190. pContext = *ppSCContext;
  191. saveFlags = pContext->Flags;
  192. }
  193. //
  194. // get the pad len -> total length + replay prevention field len + padlen + payloadtype needs to be padded to
  195. // 8 byte boundary.
  196. //
  197. pIPH = (IPHeader UNALIGNED *)pIPHeader;
  198. hdrLen = (pIPH->iph_verlen & (UCHAR)~IP_VER_FLAG) << 2;
  199. //
  200. // Transport mode: payload is after IP header => payloadlen is total len - hdr len
  201. // Tunnel modes: payload starts at IP header => payloadlen is total len
  202. //
  203. totalLen = (!fTunnel) ?
  204. NET_SHORT(pIPH->iph_length) - hdrLen :
  205. NET_SHORT(pIPH->iph_length);
  206. if ((pSA->CONF_ALGO(Index) == IPSEC_ESP_NONE) || fCryptoOnly) {
  207. if (fTunnel) {
  208. pContext->Flags |= SCF_NOE_TU;
  209. } else {
  210. pContext->Flags |= SCF_NOE_TPT;
  211. }
  212. }
  213. {
  214. PCONFID_ALGO pConfAlgo;
  215. ULONG blockLen;
  216. pConfAlgo = &(conf_algorithms[pSA->CONF_ALGO(Index)]);
  217. blockLen = pConfAlgo->blocklen;
  218. bytesLeft = (totalLen) % blockLen;
  219. if (bytesLeft <= blockLen - NUM_EXTRA) {
  220. //
  221. // we can now fit the leftover + Pad length + Payload Type in a single
  222. // chunk
  223. //
  224. padLen = blockLen - bytesLeft;
  225. } else {
  226. //
  227. // we pad the bytesleft to next octet boundary, then attach the length/type
  228. //
  229. padLen = (blockLen << 1) - bytesLeft;
  230. }
  231. }
  232. //
  233. // Get buffer for trailing PAD and signature (MD5 signature len)
  234. //
  235. IPSecAllocateBuffer(&status,
  236. &pPadBuf,
  237. &pPad,
  238. padLen + pAlgo->OutputLen,
  239. tag);
  240. if (!NT_SUCCESS(status)) {
  241. NTSTATUS ntstatus;
  242. IPSEC_DEBUG(HUGHES, ("Failed to alloc. PAD MDL\n"));
  243. pContext->Flags = saveFlags;
  244. return status;
  245. }
  246. //
  247. // the padding should contain 1, 2, 3, 4.... (latest ESP draft - draft-ietf-ipsec-esp-v2-02.txt)
  248. // for any algo that doesn't specify its own padding - right now all implemented algos go with
  249. // the default.
  250. //
  251. RtlCopyMemory(pPad, DefaultPad, padLen);
  252. IPSEC_DEBUG(HUGHES, ("IP Len: %lx, pPad: %lx, PadLen: %lx\n", NET_SHORT(pIPH->iph_length), pPad, padLen));
  253. //
  254. // Link in the pad buffer at end of the data chain
  255. //
  256. {
  257. PNDIS_BUFFER temp = pData;
  258. while (NDIS_BUFFER_LINKAGE(temp)) {
  259. temp = NDIS_BUFFER_LINKAGE(temp);
  260. }
  261. NDIS_BUFFER_LINKAGE(temp) = pPadBuf;
  262. pSaveBeforePad = temp;
  263. if (fTunnel) {
  264. pContext->BeforePadTuMdl = temp;
  265. pContext->PadTuMdl = pPadBuf;
  266. } else {
  267. pContext->BeforePadMdl = temp;
  268. pContext->PadMdl = pPadBuf;
  269. }
  270. }
  271. NDIS_BUFFER_LINKAGE(pPadBuf) = NULL;
  272. espLen = sizeof(ESP) + pSA->sa_ivlen + pSA->sa_ReplayLen;
  273. //
  274. // Get buffer for Hughes header
  275. //
  276. IPSecAllocateBuffer(&status,
  277. &pESPBuffer,
  278. (PUCHAR *)&pESP,
  279. sizeof(ESP) + pSA->sa_ivlen + pSA->sa_ReplayLen,
  280. tag);
  281. if (!NT_SUCCESS(status)) {
  282. NTSTATUS ntstatus;
  283. IPSEC_DEBUG(HUGHES, ("Failed to alloc. ESP MDL\n"));
  284. NDIS_BUFFER_LINKAGE(pSaveBeforePad) = NULL;
  285. IPSecFreeBuffer(&ntstatus, pPadBuf);
  286. pContext->Flags = saveFlags;
  287. return status;
  288. }
  289. if (fTunnel) {
  290. PNDIS_BUFFER pSrcOptBuf;
  291. PUCHAR pOpt;
  292. PUCHAR pSrcOpt;
  293. ULONG optLen = 0;
  294. IPSEC_DEBUG(HUGHES, ("Hughes Tunnel mode...\n"));
  295. //
  296. // Allocate an MDL for the new cleartext IP header
  297. //
  298. IPSecAllocateBuffer(&status,
  299. &pHdrBuf,
  300. (PUCHAR *)&pIPH2,
  301. sizeof(IPHeader),
  302. IPSEC_TAG_AH);
  303. if (!NT_SUCCESS(status)) {
  304. NTSTATUS ntstatus;
  305. IPSEC_DEBUG(HUGHES, ("Failed to alloc. PAD MDL\n"));
  306. NDIS_BUFFER_LINKAGE(pSaveBeforePad) = NULL;
  307. IPSecFreeBuffer(&ntstatus, pPadBuf);
  308. IPSecFreeBuffer(&ntstatus, pESPBuffer);
  309. pContext->Flags = saveFlags;
  310. return status;
  311. }
  312. *pExtraBytes += espLen + padLen + TruncatedLen + sizeof(IPHeader);
  313. //
  314. // Now hookup the MDLs
  315. //
  316. pContext->Flags |= SCF_HU_TU;
  317. pContext->HUTuMdl = pESPBuffer;
  318. pContext->PrevTuMdl = (PNDIS_BUFFER)pData;
  319. pContext->HUHdrMdl = pHdrBuf;
  320. pContext->OriTuMdl = NDIS_BUFFER_LINKAGE((PNDIS_BUFFER)pData);
  321. NDIS_BUFFER_LINKAGE(pESPBuffer) = pHdrBuf;
  322. if (hdrLen > sizeof(IPHeader)) {
  323. if (HdrSpace < *pExtraBytes) {
  324. IPSEC_DEBUG(AH, ("Going to frag.\n"));
  325. pSrcOptBuf = NDIS_BUFFER_LINKAGE((PNDIS_BUFFER)pData);
  326. pSaveOptLinkage = NDIS_BUFFER_LINKAGE(pSrcOptBuf);
  327. IPSecQueryNdisBuf(pSrcOptBuf, &pSrcOpt, &optLen);
  328. IPSecAllocateBuffer(&status,
  329. &pOptBuf,
  330. (PUCHAR *)&pOpt,
  331. hdrLen - sizeof(IPHeader),
  332. IPSEC_TAG_AH);
  333. if (!NT_SUCCESS(status)) {
  334. NTSTATUS ntstatus;
  335. IPSEC_DEBUG(AH, ("Failed to alloc. PAD MDL\n"));
  336. NDIS_BUFFER_LINKAGE((PNDIS_BUFFER)pData) = pSaveDataLinkage;
  337. NDIS_BUFFER_LINKAGE(pSaveBeforePad) = NULL;
  338. IPSecFreeBuffer(&ntstatus, pESPBuffer);
  339. if (pHdrBuf) {
  340. IPSecFreeBuffer(&ntstatus, pHdrBuf);
  341. }
  342. IPSecFreeBuffer(&ntstatus, pPadBuf);
  343. pContext->Flags = saveFlags;
  344. return status;
  345. }
  346. RtlCopyMemory(pOpt, pSrcOpt, hdrLen-sizeof(IPHeader));
  347. pContext->OptMdl = pOptBuf;
  348. IPSEC_DEBUG(HUGHES, ("Copying options. S: %lx, D: %lx\n", pSrcOptBuf, pOptBuf));
  349. //
  350. // replace the original Opt Mdl with ours.
  351. //
  352. NDIS_BUFFER_LINKAGE(pOptBuf) = NDIS_BUFFER_LINKAGE(pSrcOptBuf);
  353. NDIS_BUFFER_LINKAGE(pHdrBuf) = pOptBuf;
  354. IPSEC_DEBUG(HUGHES, ("Options; pointed Hdrbuf: %lx to pOptBuf: %lx\n", pHdrBuf, pOptBuf));
  355. *pExtraBytes += hdrLen-sizeof(IPHeader);
  356. } else {
  357. NDIS_BUFFER_LINKAGE(pHdrBuf) = NDIS_BUFFER_LINKAGE((PNDIS_BUFFER)pData);
  358. }
  359. } else {
  360. NDIS_BUFFER_LINKAGE(pHdrBuf) = NDIS_BUFFER_LINKAGE((PNDIS_BUFFER)pData);
  361. }
  362. NDIS_BUFFER_LINKAGE((PNDIS_BUFFER)pData) = pESPBuffer;
  363. //
  364. // xsum the new IP header since we expect that to be the case
  365. // at this stage in tpt mode.
  366. //
  367. RtlCopyMemory(pIPH2, pIPH, sizeof(IPHeader));
  368. //
  369. // no options in the outer header; reset the len.
  370. //
  371. pIPH->iph_verlen = IP_VERSION + (sizeof(IPHeader) >> 2);
  372. //
  373. // also reset the frag. params.
  374. //
  375. pIPH->iph_offset &= ~(IP_MF_FLAG | IP_OFFSET_MASK);
  376. ASSERT(pSA->sa_TunnelAddr);
  377. //
  378. // Tunnel starts here; replace dest addr to point to Tunnel end if specified
  379. // else tunnel ends at final dest
  380. //
  381. pIPH->iph_dest = pSA->sa_TunnelAddr;
  382. //
  383. // The first pended packet on a gateway (proxy negotiating for two subnets)
  384. // would come via the transmit path. Hence the source address would not be
  385. // kosher. We need to replace the src address in that case also.
  386. // We get this from the corresponding inbound SA's tunnel addr.
  387. //
  388. pIPH->iph_src = pSA->sa_SrcTunnelAddr;
  389. pIPH->iph_id = (ushort) TCPIP_GEN_IPID();
  390. pIPH->iph_xsum = 0;
  391. pIPH->iph_xsum = ~xsum(pIPH, sizeof(IPHeader));
  392. //
  393. // Set up headers so CreateHash works as in Tpt mode.
  394. //
  395. pIPHeader = (PUCHAR)pIPH;
  396. *ppNewData = pData;
  397. PayloadType = IP_IN_IP;
  398. } else {
  399. *pExtraBytes += espLen + padLen + TruncatedLen;
  400. if (hdrLen > sizeof(IPHeader)) {
  401. //
  402. // Options present - chain ESP after options
  403. //
  404. pSaveMdl = pContext->OriHUMdl = NDIS_BUFFER_LINKAGE(NDIS_BUFFER_LINKAGE((PNDIS_BUFFER)pData));
  405. pContext->PrevMdl = NDIS_BUFFER_LINKAGE((PNDIS_BUFFER)pData);
  406. NDIS_BUFFER_LINKAGE(pESPBuffer) = pContext->OriHUMdl;
  407. NDIS_BUFFER_LINKAGE(NDIS_BUFFER_LINKAGE((PNDIS_BUFFER)pData)) = pESPBuffer;
  408. pContext->Flags |= SCF_HU_TPT;
  409. } else {
  410. //
  411. // Chain the ESP buffer after IP header
  412. //
  413. pSaveMdl = pContext->OriHUMdl = NDIS_BUFFER_LINKAGE((PNDIS_BUFFER)pData);
  414. pContext->PrevMdl = (PNDIS_BUFFER)pData;
  415. NDIS_BUFFER_LINKAGE(pESPBuffer) = pContext->OriHUMdl;
  416. NDIS_BUFFER_LINKAGE((PNDIS_BUFFER)pData) = pESPBuffer;
  417. pContext->Flags |= SCF_HU_TPT;
  418. }
  419. //
  420. // Save the MDL pointer so we can hook it in place on SendComplete
  421. //
  422. pContext->HUMdl = pESPBuffer;
  423. PayloadType = ((UNALIGNED IPHeader *)pIPH)->iph_protocol;
  424. }
  425. //
  426. // Fill in the padlen at start of pad + padlen - NUM_EXTRA
  427. //
  428. *(pPad + padLen - NUM_EXTRA) = (UCHAR)padLen - NUM_EXTRA;
  429. //
  430. // Set the Payload Type
  431. //
  432. *(pPad + padLen + sizeof(UCHAR) - NUM_EXTRA) = (UCHAR)PayloadType;
  433. //
  434. // Initialize the other fields of the ESP header
  435. //
  436. pESP->esp_spi = HOST_TO_NET_LONG(pSA->sa_OtherSPIs[Index]);
  437. //
  438. // Copy the Replay field into the Hughes header
  439. //
  440. Seq = IPSEC_INCREMENT(pSA->sa_ReplaySendSeq[Index]);
  441. *(UNALIGNED ULONG *)(pESP + 1) = HOST_TO_NET_LONG(Seq);
  442. if ((pSA->CONF_ALGO(Index) != IPSEC_ESP_NONE) && !fCryptoOnly) {
  443. UCHAR feedback[MAX_BLOCKLEN];
  444. KIRQL kIrql;
  445. //
  446. // Pad is included in the chain, so prevent double free by NULL'ing
  447. // the ref.
  448. //
  449. if (fTunnel) {
  450. pContext->PadTuMdl = NULL;
  451. } else {
  452. pContext->PadMdl = NULL;
  453. }
  454. //
  455. // NOTE: The way the IV is supposed to work is that initially, the IV
  456. // is a random value. The IV is then updated with the residue of the
  457. // last encryption block of a packet. This is used as the starting IV
  458. // for the next block. This assures a fairly random IV sample and
  459. // introduces some notion of IV chaining.
  460. //
  461. // The only way for this to work is to make the entire encryption atomic,
  462. // which would be a performance drag. So, we take a less strict approach here.
  463. //
  464. // We just ensure that each packet starts at a random value, and also do the
  465. // chaining.
  466. //
  467. //
  468. // Copy the IV into the Hughes header
  469. //
  470. ACQUIRE_LOCK(&pSA->sa_Lock, &kIrql);
  471. RtlCopyMemory( ((PUCHAR)(pESP + 1) + pSA->sa_ReplayLen),
  472. pSA->sa_iv[Index],
  473. pSA->sa_ivlen);
  474. //
  475. // Init the CBC feedback
  476. //
  477. RtlCopyMemory( feedback,
  478. pSA->sa_iv[Index],
  479. DES_BLOCKLEN);
  480. IPSecGenerateRandom((PUCHAR)&pSA->sa_iv[Index][0], DES_BLOCKLEN);
  481. RELEASE_LOCK(&pSA->sa_Lock, kIrql);
  482. //
  483. // Encrypt the entire block, starting after the IV (if it exists)
  484. //
  485. //
  486. // Make it appear that pESPMdl points to after Replay field
  487. //
  488. NdisBufferLength((PNDIS_BUFFER)pESPBuffer) -= (sizeof(ESP) + pSA->sa_ivlen + pSA->sa_ReplayLen);
  489. (PUCHAR)((PNDIS_BUFFER)pESPBuffer)->MappedSystemVa += (sizeof(ESP) + pSA->sa_ivlen + pSA->sa_ReplayLen);
  490. //
  491. // Remove the Hash bytes since we dont want to encrypt them
  492. //
  493. NdisBufferLength((PNDIS_BUFFER)pPadBuf) -= pAlgo->OutputLen;
  494. ASSERT(NdisBufferLength((PNDIS_BUFFER)pESPBuffer) == 0);
  495. status = IPSecEncryptBuffer((PVOID)pESPBuffer,
  496. &pNewMdl,
  497. pSA,
  498. pPadBuf,
  499. &padLen,
  500. 0,
  501. Index,
  502. feedback);
  503. if (!NT_SUCCESS(status)) {
  504. NTSTATUS ntstatus;
  505. IPSEC_DEBUG(HUGHES, ("Failed to encrypt, pESP: %lx\n", pESP));
  506. //
  507. // Don't forget we need to restore ESP MDL since SystemVa has been
  508. // changed. If not, we have trouble later if the same buffer is
  509. // used during reinject since we use the buffer as a real MDL
  510. // there.
  511. //
  512. NdisBufferLength((PNDIS_BUFFER)pESPBuffer) += (sizeof(ESP) + pSA->sa_ivlen + pSA->sa_ReplayLen);
  513. (PUCHAR)((PNDIS_BUFFER)pESPBuffer)->MappedSystemVa -= (sizeof(ESP) + pSA->sa_ivlen + pSA->sa_ReplayLen);
  514. NDIS_BUFFER_LINKAGE((PNDIS_BUFFER)pData) = pSaveDataLinkage;
  515. NDIS_BUFFER_LINKAGE(pSaveBeforePad) = NULL;
  516. if (pSaveOptLinkage) {
  517. NDIS_BUFFER_LINKAGE(NDIS_BUFFER_LINKAGE((PNDIS_BUFFER)pData)) = pSaveOptLinkage;
  518. }
  519. IPSecFreeBuffer(&ntstatus, pESPBuffer);
  520. if (pHdrBuf) {
  521. IPSecFreeBuffer(&ntstatus, pHdrBuf);
  522. }
  523. if (pOptBuf) {
  524. IPSecFreeBuffer(&ntstatus, pOptBuf);
  525. }
  526. IPSecFreeBuffer(&ntstatus, pPadBuf);
  527. pContext->Flags = saveFlags;
  528. return status;
  529. }
  530. NdisBufferLength((PNDIS_BUFFER)pPadBuf) += pAlgo->OutputLen;
  531. //
  532. // Restore ESP MDL
  533. //
  534. NdisBufferLength((PNDIS_BUFFER)pESPBuffer) += (sizeof(ESP) + pSA->sa_ivlen + pSA->sa_ReplayLen);
  535. (PUCHAR)((PNDIS_BUFFER)pESPBuffer)->MappedSystemVa -= (sizeof(ESP) + pSA->sa_ivlen + pSA->sa_ReplayLen);
  536. NDIS_BUFFER_LINKAGE(pESPBuffer) = pNewMdl;
  537. //
  538. // HMAC the entire block - starting at the SPI field => start of pESPBuffer
  539. //
  540. status = IPSecHashMdlChain( pSA,
  541. (PVOID)pESPBuffer, // source
  542. pPad, // dest
  543. FALSE, // fIncoming
  544. pSA->INT_ALGO(Index), // algo
  545. &hashBytes,
  546. Index);
  547. if (!NT_SUCCESS(status)) {
  548. NTSTATUS ntstatus;
  549. IPSEC_DEBUG(HUGHES, ("Failed to hash, pAH: %lx\n", pESP));
  550. NDIS_BUFFER_LINKAGE((PNDIS_BUFFER)pData) = pSaveDataLinkage;
  551. NDIS_BUFFER_LINKAGE(pSaveBeforePad) = NULL;
  552. if (pSaveOptLinkage) {
  553. NDIS_BUFFER_LINKAGE(NDIS_BUFFER_LINKAGE((PNDIS_BUFFER)pData)) = pSaveOptLinkage;
  554. }
  555. IPSecFreeBuffer(&ntstatus, pESPBuffer);
  556. if (pHdrBuf) {
  557. IPSecFreeBuffer(&ntstatus, pHdrBuf);
  558. }
  559. if (pOptBuf) {
  560. IPSecFreeBuffer(&ntstatus, pOptBuf);
  561. }
  562. IPSecFreeBuffer(&ntstatus, pPadBuf);
  563. IPSecFreeBuffer(&ntstatus, pNewMdl);
  564. pContext->Flags = saveFlags;
  565. return status;
  566. }
  567. //
  568. // hook up the pad mdl which contains the final hash (the pad mdl was copied into
  569. // newMdl returned by EncryptDESCBC). Also, set the length of the Pad mdl to hash len.
  570. //
  571. // Remember we need to truncate this to 96 bits, so make it appear
  572. // as if we have only 96 bits.
  573. //
  574. NdisBufferLength(pPadBuf) = TruncatedLen;
  575. NDIS_BUFFER_LINKAGE(pNewMdl) = pPadBuf;
  576. pNdisPacket->Private.Tail = pPadBuf;
  577. } else {
  578. //
  579. // HMAC the entire block - starting at the SPI field => start of pESPBuffer
  580. //
  581. //
  582. // Remove the Hash bytes since we dont want to hash them
  583. //
  584. if (!fCryptoOnly) {
  585. NdisBufferLength((PNDIS_BUFFER)pPadBuf) -= pAlgo->OutputLen;
  586. status = IPSecHashMdlChain( pSA,
  587. (PVOID)pESPBuffer, // source
  588. (PUCHAR)(pPad + padLen), // dest
  589. FALSE, // fIncoming
  590. pSA->INT_ALGO(Index), // algo
  591. &hashBytes,
  592. Index);
  593. NdisBufferLength((PNDIS_BUFFER)pPadBuf) += pAlgo->OutputLen;
  594. if (!NT_SUCCESS(status)) {
  595. NTSTATUS ntstatus;
  596. IPSEC_DEBUG(HUGHES, ("Failed to hash, pAH: %lx\n", pESP));
  597. NDIS_BUFFER_LINKAGE((PNDIS_BUFFER)pData) = pSaveDataLinkage;
  598. NDIS_BUFFER_LINKAGE(pSaveBeforePad) = NULL;
  599. if (pSaveOptLinkage) {
  600. NDIS_BUFFER_LINKAGE(NDIS_BUFFER_LINKAGE((PNDIS_BUFFER)pData)) = pSaveOptLinkage;
  601. }
  602. IPSecFreeBuffer(&ntstatus, pESPBuffer);
  603. if (pHdrBuf) {
  604. IPSecFreeBuffer(&ntstatus, pHdrBuf);
  605. }
  606. if (pOptBuf) {
  607. IPSecFreeBuffer(&ntstatus, pOptBuf);
  608. }
  609. IPSecFreeBuffer(&ntstatus, pPadBuf);
  610. IPSecFreeBuffer(&ntstatus, pNewMdl);
  611. pContext->Flags = saveFlags;
  612. return status;
  613. }
  614. } else {
  615. IPSEC_GET_TOTAL_LEN(pESPBuffer, &hashBytes);
  616. }
  617. if (fCryptoOnly) {
  618. //
  619. // Zero out the hash.
  620. //
  621. IPSecZeroMemory(pPad + padLen, TruncatedLen);
  622. IPSecZeroMemory((PUCHAR)(pESP + 1) + pSA->sa_ReplayLen, pSA->sa_ivlen);
  623. }
  624. NdisBufferLength(pPadBuf) = padLen + TruncatedLen;
  625. pNdisPacket->Private.Tail = pPadBuf;
  626. }
  627. if (pSA->CONF_ALGO(Index) != IPSEC_ESP_NONE) {
  628. ADD_TO_LARGE_INTEGER(
  629. &pSA->sa_Stats.ConfidentialBytesSent,
  630. totalLen);
  631. ADD_TO_LARGE_INTEGER(
  632. &g_ipsec.Statistics.uConfidentialBytesSent,
  633. totalLen);
  634. }
  635. if (pSA->INT_ALGO(Index) != IPSEC_AH_NONE) {
  636. ADD_TO_LARGE_INTEGER(
  637. &pSA->sa_Stats.AuthenticatedBytesSent,
  638. hashBytes);
  639. ADD_TO_LARGE_INTEGER(
  640. &g_ipsec.Statistics.uAuthenticatedBytesSent,
  641. hashBytes);
  642. }
  643. //
  644. // Bump up the bytes transformed count.
  645. //
  646. ADD_TO_LARGE_INTEGER(
  647. &pSA->sa_TotalBytesTransformed,
  648. totalLen);
  649. //
  650. // Update the IP header length to reflect the Hughes header
  651. //
  652. IPLength = NET_SHORT(pIPH->iph_length) + (USHORT)(espLen + padLen + TruncatedLen);
  653. if (fTunnel) {
  654. IPLength += sizeof(IPHeader);
  655. }
  656. UpdateIPLength(pIPH, NET_SHORT(IPLength));
  657. UpdateIPProtocol(pIPH, PROTOCOL_ESP);
  658. //
  659. // Return modified packet.
  660. //
  661. IPSEC_DEBUG(HUGHES, ("Exiting IPSecCreateHughes, espLen: %lx, padLen: %lx, status: %lx\n", espLen, padLen, status));
  662. #if DBG
  663. IPSEC_DEBUG(MDL, ("Exiting IPSecCreateHughes\n"));
  664. IPSEC_PRINT_CONTEXT(*ppSCContext);
  665. if (*ppNewData) {
  666. IPSEC_PRINT_MDL(*ppNewData);
  667. }
  668. else {
  669. IPSEC_PRINT_MDL(pData);
  670. }
  671. #endif
  672. return STATUS_SUCCESS;
  673. }
  674. NTSTATUS
  675. IPSecVerifyHughes(
  676. IN PUCHAR *pIPHeader,
  677. IN PVOID pData,
  678. IN PSA_TABLE_ENTRY pSA,
  679. IN ULONG Index,
  680. OUT PULONG pExtraBytes,
  681. IN BOOLEAN fCryptoDone,
  682. IN BOOLEAN fFastRcv
  683. )
  684. /*++
  685. Routine Description:
  686. Verify the combined esp-des-md5 transform, as outlined in
  687. draft-ietf-ipsec-esp-des-md5, on the send side.
  688. Arguments:
  689. pIPHeader - points to start of IP header.
  690. pData - points to the data after the IP header. IPRcvBuf*
  691. pSA - Sec. Assoc. entry
  692. pExtraBytes - out param to inform IP on recv path how many bytes IPSEC took off.
  693. Return Value:
  694. STATUS_SUCCESS
  695. Others:
  696. STATUS_INSUFFICIENT_RESOURCES
  697. STATUS_UNSUCCESSFUL (error in algo.)
  698. --*/
  699. {
  700. PESP pESP;
  701. NTSTATUS status = STATUS_SUCCESS;
  702. PNDIS_BUFFER pESPBuffer;
  703. PNDIS_BUFFER pPadBuffer;
  704. LONG espLen;
  705. UCHAR padLen;
  706. UCHAR payloadType;
  707. ULONG uTotalLen = 0;
  708. ULONG totalLen;
  709. ULONG safetyLen;
  710. ULONG hdrLen;
  711. PUCHAR pHash;
  712. UCHAR tempHash[SAFETY_LEN+1];
  713. ULONG Len;
  714. UCHAR Buf[MAX_AH_OUTPUT_LEN];
  715. PUCHAR pAHData = Buf;
  716. PAUTH_ALGO pAlgo = &(auth_algorithms[pSA->INT_ALGO(Index)]);
  717. ULONG hashBytes = 0;
  718. IPRcvBuf *temp = (IPRcvBuf *)pData;
  719. IPHeader UNALIGNED *pIPH = (IPHeader UNALIGNED *)*pIPHeader;
  720. ULONG extraBytes = 0;
  721. USHORT FilterFlags;
  722. BOOLEAN fTunnel = ((pSA->sa_Flags & FLAGS_SA_TUNNEL) &&
  723. ((Index == 0) ||
  724. ((Index == 1) && (pSA->sa_Operation[0] == Compress))));
  725. ULONG TruncatedLen = (pSA->INT_ALGO(Index) != IPSEC_AH_NONE)? pSA->sa_TruncatedLen: 0;
  726. ULONG uPadLen = 0;
  727. IPRcvBuf * temp_pre = NULL;
  728. PUCHAR data;
  729. IPSEC_DEBUG(HUGHES, ("Entering IPSecVerifyHughes\n"));
  730. ASSERT(pSA->sa_Operation[Index] == Encrypt);
  731. hdrLen = (pIPH->iph_verlen & (UCHAR)~IP_VER_FLAG) << 2;
  732. //
  733. // Transport mode: payload is after IP header => payloadlen is total len - hdr len
  734. // Tunnel mode: payload starts at IP header => payloadlen is total len
  735. //
  736. IPSEC_GET_TOTAL_LEN_RCV_BUF(pData, &totalLen);
  737. //
  738. // Do we have enough in the buffer?
  739. //
  740. Len = sizeof(ESP) + pSA->sa_ivlen + pSA->sa_ReplayLen + TruncatedLen;
  741. IPSEC_DEBUG(HUGHES, ("VerifyHughes: iph_len %d & hdrLen %d\n", NET_SHORT(pIPH->iph_length), hdrLen));
  742. IPSEC_DEBUG(HUGHES, ("VerifyHughes: DataLen %d & IPSecLen %d\n", totalLen, Len));
  743. if (totalLen < Len || totalLen != (NET_SHORT(pIPH->iph_length) - hdrLen)) {
  744. ASSERT(FALSE);
  745. return STATUS_INVALID_PARAMETER;
  746. }
  747. //
  748. // Check for replay first
  749. // See if the signature matches the hash
  750. // First get the *&*&* hash - its at the end of the packet...
  751. //
  752. //
  753. // Check the replay window
  754. //
  755. IPSecQueryRcvBuf((IPRcvBuf *)pData, &pESP, &espLen);
  756. IPSEC_DEBUG(HUGHES, ("VerifyHughes: First buffer %lx\n", temp));
  757. //
  758. // Travel to the end of the packet and then backup TruncatedLen bytes
  759. //
  760. while (IPSEC_BUFFER_LINKAGE(temp)) {
  761. temp = IPSEC_BUFFER_LINKAGE(temp);
  762. }
  763. IPSEC_DEBUG(HUGHES, ("VerifyHughes: Last buffer %lx\n", temp));
  764. //
  765. // See if we have at least the full hash and padding in this one. Else go thru'
  766. // the slow path.
  767. //
  768. IPSecQueryRcvBuf(temp, &pHash, &Len);
  769. IPSEC_DEBUG(HUGHES, ("VerifyHughes: Last buffer length %d\n", Len));
  770. safetyLen = MAX_PAD_LEN + TruncatedLen + 1;
  771. IPSEC_DEBUG(HUGHES, ("VerifyHughes: Safety length %d\n", safetyLen));
  772. if (Len >= safetyLen) {
  773. //
  774. // now read the hash out of the buffer
  775. //
  776. pHash = pHash + Len - TruncatedLen;
  777. //
  778. // also remove the hash from the buffer
  779. //
  780. IPSEC_ADJUST_BUFFER_LEN (temp, Len - TruncatedLen);
  781. extraBytes += TruncatedLen;
  782. Len -= TruncatedLen;
  783. IPSEC_DEBUG(HUGHES, ("VerifyHughes: Modified Last buffer length %d\n", Len));
  784. IPSEC_DEBUG(HUGHES, ("pHash: %lx\n", pHash));
  785. } else {
  786. //
  787. // out of luck; need to grovel the lists for the TRUNC_LEN + MAX_PAD_LEN (SAFETY_LEN) bytes of data.
  788. // we copy out the last SAFETY_LEN bytes into another buffer and plug that into the list at the end
  789. // by re-allocing the last RcvBuf. We also zap the lengths of the remaining RcvBufs that contain these
  790. // special bytes.
  791. // NOTE: We also remove the hash from the buffer chain.
  792. //
  793. ULONG length;
  794. ULONG offset=0; // offset within the current buffer
  795. ULONG off=0; // offset in the dest buffer (tempHash)
  796. ULONG bytesLeft = safetyLen;
  797. IPRcvBuf tmpRcvBuf={0};
  798. LONG len = NET_SHORT(pIPH->iph_length) - safetyLen - hdrLen;
  799. temp = (IPRcvBuf *)pData;
  800. IPSEC_DEBUG(HUGHES, ("VerifyHughes: pData %lx & Len %lx\n", pData, len));
  801. //
  802. // first travel to the buffer that points to a chain containing the
  803. // last SAFETY_LEN bytes by skipping (Total - SAFETY_LEN) bytes.
  804. //
  805. while (temp) {
  806. IPSecQueryRcvBuf(temp, &data, &length);
  807. len -= length;
  808. if (len < 0) {
  809. break;
  810. }
  811. temp = IPSEC_BUFFER_LINKAGE(temp);
  812. }
  813. if (!temp) {
  814. return STATUS_UNSUCCESSFUL;
  815. }
  816. //
  817. // pTemp now points to the last SAFETY_LEN bytes. Note that the last SAFETY_LEN bytes
  818. // might be in as many buffers and that there might be an offset in the current temp
  819. // where the last set of bytes starts.
  820. //
  821. len = -len;
  822. offset = length - len;
  823. IPSEC_DEBUG(HUGHES, ("After skip temp: %lx, Len: %d, offset: %d\n", temp, len, offset));
  824. do {
  825. RtlCopyMemory( tempHash+off,
  826. data+offset,
  827. len);
  828. off += len;
  829. bytesLeft -= len;
  830. //
  831. // Also remove the hash bytes from the chain as we traverse it.
  832. //
  833. IPSEC_ADJUST_BUFFER_LEN (temp, length - len);
  834. if (bytesLeft == 0) {
  835. ASSERT(off == safetyLen);
  836. break;
  837. }
  838. temp = IPSEC_BUFFER_LINKAGE(temp);
  839. if (!temp) {
  840. return STATUS_UNSUCCESSFUL;
  841. }
  842. IPSecQueryRcvBuf(temp, &data, &length);
  843. offset = 0;
  844. len = length;
  845. } while (TRUE);
  846. IPSEC_DEBUG(HUGHES, ("After copy tempHash: %lx\n", tempHash));
  847. //
  848. // Now we have an IPRcvBuf chain which has had SAFETY_LEN bytes removed.
  849. // We reallocate these SAFETY_LEN bytes in the last buffer with help from IP.
  850. //
  851. tmpRcvBuf = *temp;
  852. if (!TCPIP_ALLOC_BUFF(temp, safetyLen)) {
  853. IPSEC_DEBUG(HUGHES, ("Failed to realloc last 22 bytes\n"));
  854. return STATUS_INSUFFICIENT_RESOURCES;
  855. }
  856. IPSEC_DEBUG(HUGHES, ("Alloc'ed new temp: %lx\n", temp));
  857. //
  858. // Now temp points to the new buffer with SAFETY_LEN number of bytes.
  859. // Free the Original buffer.
  860. //
  861. TCPIP_FREE_BUFF(&tmpRcvBuf);
  862. //
  863. // Copy over the bytes into the buffer just allocated.
  864. //
  865. IPSEC_ADJUST_BUFFER_LEN (temp, safetyLen);
  866. IPSecQueryRcvBuf(temp, &data, &Len);
  867. ASSERT(Len == safetyLen);
  868. RtlCopyMemory( data,
  869. tempHash,
  870. safetyLen);
  871. //
  872. // now read the hash out of the buffer
  873. //
  874. pHash = data + Len - TruncatedLen;
  875. //
  876. // also remove the hash from the buffer
  877. //
  878. IPSEC_ADJUST_BUFFER_LEN (temp, Len - TruncatedLen);
  879. IPSEC_DEBUG(HUGHES, ("Len in temp: %d\n", temp->ipr_size));
  880. extraBytes += TruncatedLen;
  881. Len -= TruncatedLen;
  882. IPSEC_DEBUG(HUGHES, ("pHash: %lx, Len: %d\n", pHash, Len));
  883. }
  884. //
  885. // Hash is generated starting after the IPHeader, ie at start of pData
  886. //
  887. if (!fCryptoDone) {
  888. status = IPSecHashMdlChain( pSA,
  889. (PVOID)pData, // source
  890. pAHData, // dest
  891. TRUE, // fIncoming
  892. pSA->INT_ALGO(Index), // algo
  893. &hashBytes,
  894. Index);
  895. if (!NT_SUCCESS(status)) {
  896. IPSEC_DEBUG(HUGHES, ("Failed to hash, pData: %lx\n", pData));
  897. return status;
  898. }
  899. if (!IPSecEqualMemory( pAHData,
  900. pHash,
  901. TruncatedLen * sizeof(UCHAR))) {
  902. IPSecBufferEvent( pIPH->iph_src,
  903. EVENT_IPSEC_AUTH_FAILURE,
  904. 2,
  905. TRUE);
  906. IPSEC_DEBUG(HUGHES, ("Failed to compare, pPyld: %lx, pAHData: %lx\n", pHash, pAHData));
  907. IPSEC_INC_STATISTIC(dwNumPacketsNotAuthenticated);
  908. return IPSEC_INVALID_ESP;
  909. }
  910. } else {
  911. hashBytes = totalLen - TruncatedLen;
  912. }
  913. status=IPSecChkReplayWindow(
  914. NET_TO_HOST_LONG(*(ULONG UNALIGNED *)(pESP + 1)),
  915. pSA,
  916. Index);
  917. if (!NT_SUCCESS(status)) {
  918. IPSEC_DEBUG(HUGHES, ("Replay check failed, pSA: %lx\n", pSA));
  919. IPSEC_INC_STATISTIC(dwNumPacketsWithReplayDetection);
  920. return status;
  921. }
  922. if (pSA->INT_ALGO(Index) != IPSEC_AH_NONE) {
  923. ADD_TO_LARGE_INTEGER(
  924. &pSA->sa_Stats.AuthenticatedBytesReceived,
  925. hashBytes);
  926. ADD_TO_LARGE_INTEGER(
  927. &g_ipsec.Statistics.uAuthenticatedBytesReceived,
  928. hashBytes);
  929. }
  930. espLen = sizeof(ESP) + pSA->sa_ivlen + pSA->sa_ReplayLen;
  931. if ((pSA->CONF_ALGO(Index) != IPSEC_ESP_NONE) && !fCryptoDone) {
  932. PCONFID_ALGO pConfAlgo;
  933. ULONG blockLen;
  934. pConfAlgo = &(conf_algorithms[pSA->CONF_ALGO(Index)]);
  935. blockLen = pConfAlgo->blocklen;
  936. //
  937. // Make sure the data is aligned to 8 byte boundary.
  938. //
  939. if ((hashBytes - espLen) % blockLen) {
  940. IPSEC_DEBUG(ESP, ("ESP data not aligned: hashBytes %d, totalLen %d, espLen %d, blockLen %d\n", hashBytes, totalLen, espLen, blockLen));
  941. return STATUS_UNSUCCESSFUL;
  942. }
  943. //
  944. // Decrypt the entire block
  945. //
  946. status = IPSecDecryptBuffer(pData,
  947. pSA,
  948. &padLen,
  949. &payloadType,
  950. Index);
  951. if (!NT_SUCCESS(status)) {
  952. IPSEC_DEBUG(HUGHES, ("Failed the decrypt\n"));
  953. return status;
  954. }
  955. }
  956. //
  957. // Now remove the Pad too since it was not removed in Decrypt
  958. //
  959. padLen = *(pHash - (sizeof(UCHAR) << 1));
  960. payloadType = *(pHash - sizeof(UCHAR));
  961. IPSEC_DEBUG(HUGHES, ("ESP: PadLen: %d, PayloadType: %lx, pHash: %lx, Len: %d\n", padLen, payloadType, pHash, Len));
  962. //
  963. // Entire pad may not be in this buffer.
  964. //
  965. uPadLen = padLen + NUM_EXTRA;
  966. IPSEC_DEBUG(HUGHES, ("Total pad length = %d\n", uPadLen));
  967. while (Len < uPadLen) {
  968. IPSEC_ADJUST_BUFFER_LEN (temp, 0);
  969. IPSEC_DEBUG(HUGHES, ("Buffer: %lx has a length %d - setting it to 0\n", temp, Len));
  970. uPadLen -= Len;
  971. IPSEC_DEBUG(HUGHES, ("Net pad length = %d\n", uPadLen));
  972. temp_pre = (IPRcvBuf *) pData;
  973. while (temp_pre->ipr_next != temp) {
  974. temp_pre = IPSEC_BUFFER_LINKAGE(temp_pre);
  975. if (!temp_pre) {
  976. IPSEC_DEBUG(HUGHES, ("Total size of all the buffers is smaller than the esp pad length\n"));
  977. ASSERT(temp_pre);
  978. return STATUS_UNSUCCESSFUL;
  979. }
  980. }
  981. IPSecQueryRcvBuf(temp_pre, &data, &Len);
  982. temp = temp_pre;
  983. }
  984. IPSEC_ADJUST_BUFFER_LEN (temp, Len - uPadLen);
  985. IPSEC_DEBUG(HUGHES, ("Buffer: %lx has a length %d - setting it to %d\n", temp, Len, Len - uPadLen));
  986. extraBytes += (padLen + NUM_EXTRA);
  987. if (pSA->CONF_ALGO(Index) != IPSEC_ESP_NONE) {
  988. ADD_TO_LARGE_INTEGER(
  989. &pSA->sa_Stats.ConfidentialBytesReceived,
  990. totalLen - (extraBytes + espLen));
  991. ADD_TO_LARGE_INTEGER(
  992. &g_ipsec.Statistics.uConfidentialBytesReceived,
  993. totalLen - (extraBytes + espLen));
  994. }
  995. //
  996. // Bump up the bytes transformed count.
  997. //
  998. ADD_TO_LARGE_INTEGER(
  999. &pSA->sa_TotalBytesTransformed,
  1000. totalLen);
  1001. if (!fTunnel) {
  1002. //
  1003. // Update the IP header length to reflect removal of the ESP header
  1004. //
  1005. IPSEC_DEBUG(HUGHES, ("VerifyHughes: iph_len %d, padLen %d, truncLen %d & espLen %d\n", NET_SHORT(pIPH->iph_length), uPadLen, TruncatedLen, espLen));
  1006. pIPH->iph_length =
  1007. NET_SHORT(
  1008. NET_SHORT(pIPH->iph_length) -
  1009. (USHORT)(espLen + uPadLen + TruncatedLen));
  1010. IPSEC_DEBUG(HUGHES, ("VerifyHughes: iph_len %d\n", NET_SHORT(pIPH->iph_length)));
  1011. //
  1012. // set the payload type in the IP header
  1013. //
  1014. pIPH->iph_protocol = payloadType;
  1015. //
  1016. // Remove the ESP header from the packet; pad was removed in Decrypt
  1017. //
  1018. IPSEC_SET_OFFSET_IN_BUFFER(pData, espLen);
  1019. //
  1020. // Move the IP header forward for filter/firewall hook, fast path only.
  1021. //
  1022. if (fFastRcv) {
  1023. IPSEC_DEBUG(HUGHES, ("VerifyHughes: fast receive true - "));
  1024. IPSEC_DEBUG(HUGHES, ("Moving the IP header forward from %lx by espLen %d\n", pIPH, espLen));
  1025. IPSecMoveMemory(((PUCHAR)pIPH) + espLen, (PUCHAR)pIPH, hdrLen);
  1026. *pIPHeader=(PUCHAR)pIPH+espLen;
  1027. pIPH = (IPHeader UNALIGNED *)*pIPHeader;
  1028. }
  1029. extraBytes += espLen;
  1030. //
  1031. // Return modified packet.
  1032. //
  1033. IPSEC_DEBUG(HUGHES, ("Exiting VerifyHughes: extra bytes %d & status: %lx\n", extraBytes, status));
  1034. *pExtraBytes += extraBytes;
  1035. #if DBG
  1036. IPSEC_GET_TOTAL_LEN_RCV_BUF(pData, &uTotalLen);
  1037. IPSEC_DEBUG(HUGHES, ("VerifyHughes: iph_length %d & buflen %d\n", NET_SHORT(pIPH->iph_length), uTotalLen));
  1038. #endif
  1039. return STATUS_SUCCESS;
  1040. } else {
  1041. //
  1042. // set the payload type in the IP header
  1043. //
  1044. pIPH->iph_protocol = payloadType;
  1045. //
  1046. // Remove the ESP header from the packet
  1047. //
  1048. IPSEC_SET_OFFSET_IN_BUFFER(pData, espLen);
  1049. //
  1050. // Move the IP header forward for filter/firewall hook, fast path only.
  1051. //
  1052. if (fFastRcv) {
  1053. IPSecMoveMemory(((PUCHAR)pIPH) + espLen, (PUCHAR)pIPH, hdrLen);
  1054. *pIPHeader=(PUCHAR)pIPH+espLen;
  1055. pIPH = (IPHeader UNALIGNED *)*pIPHeader;
  1056. }
  1057. extraBytes += espLen;
  1058. //
  1059. // Return modified packet.
  1060. //
  1061. IPSEC_DEBUG(ESP, ("Exiting IPSecVerifyHughes, espLen: %lx, status: %lx\n", espLen, status));
  1062. if (payloadType != IP_IN_IP) {
  1063. IPSEC_INC_STATISTIC(dwNumPacketsNotDecrypted);
  1064. IPSEC_DEBUG(ESP, ("Bad payloadtype: %c\n", payloadType));
  1065. status = STATUS_INVALID_PARAMETER;
  1066. }
  1067. *pExtraBytes += extraBytes;
  1068. //
  1069. // Drop the original packet
  1070. //
  1071. return status;
  1072. }
  1073. }