📄 ipsec_esp_message.c
字号:
pOutgoingIV = pPacket + LENGTH_OF_SPI_AND_SEQ_FIELDS; /* Generate transmitted IV and store in ESP packet now, as it is updated during encryption */ if (AESCTRMode) { /* Generate Counter Block */ CTRModeCounterBlockBuild (cipher, pOutgoingIV);#if (defined IPSEC_VERBOSE_PACKET_DEBUGGING || IPSEC_VERBOSE_AES_CTR_DEBUGGING) ike_debug_printf_bytes (IKE_ERROR_PRINTF, "<AES-CTR Counter Block pre-encryption>:", (unsigned char *)cipher->_pIV, cipher->IVSizeGet (cipher));#endif } else { CBCModeIVGenerate (cipher, pOutgoingIV); } } /* endif (IVLength > 0) */#ifdef IPSEC_VERBOSE_PACKET_DEBUGGING ike_debug_printf_bytes (IKE_ERROR_PRINTF, "== packet with inserted IV:", pPacket, packetBufDataSizeGet(pPacketBuf));#endif /* point to start of plaintext */ pPlaintext = pPacket + LENGTH_OF_SPI_AND_SEQ_FIELDS + IVLength; /* Trailer includes: * (max. # of padding bytes) + [PAD_LENGTH],[NEXT_MESSAGE] bytes */#ifdef IPSEC_USE_RANDOM_PADSIZE maxTrailerLength = MAXIMUM_ESP_PAD_LENGTH + LENGTH_OF_PADLEN_AND_NEXTHDR_FIELDS;#else maxTrailerLength = cipher->blockSizeGet (cipher) + LENGTH_OF_PADLEN_AND_NEXTHDR_FIELDS;#endif /* To our plaintext packet, add room for: * - trailer (padding+[PAD_LENGTH],[NEXT_FIELD]); and * - ESP Auth's digest, if any. */ /* NOTE: packetBufWritableTrailerGet() checks if there is enough slack * in the rw_packet struct to give us the space we want; if so, it * returns a pointer to the new trailer space. In reality * no wrSecAlloc() is done. This just gives us a pointer within the buffer. */ pTrailerFields = packetBufWritableTrailerGet(pPacketBuf, (maxTrailerLength + cipherESP->hmacDigestSizeGet(cipherESP))); if (pTrailerFields == NULL) { ipsec_printf (IPSEC_ERROR_PRINTF, "IPsec: Failed Encryption (insufficient room for trailer).\n"); return (FALSE); } /* pad packet according to RFC2406 algorithm: 0x01,0x02,0x03,... */ padLength = cipher->padding->pad (cipher->padding, pPlaintext, plaintextLength); /* Padding has been added to plaintext, record the increased length */ plaintextLength = plaintextLength + padLength; pTrailerFields = pPlaintext + plaintextLength; wrSecSerializeUChar (padLength, &pTrailerFields); /* pTrailerFields++ */ wrSecSerializeUChar (pESPMessage->next_header, &pTrailerFields); /* pTrailerFields++ */ plaintextLength = plaintextLength + LENGTH_OF_PADLEN_AND_NEXTHDR_FIELDS; /* NOTE: packetBufExtendBack() records that we're using some of the * slack space at the end of the rw_packet buffer. No wrSecAlloc() is done, * this just verifies the additional storage is available and adjusts * the meta-info associated with the rw_packet. */ if (packetBufExtendBack(pPacketBuf, (padLength + LENGTH_OF_PADLEN_AND_NEXTHDR_FIELDS + cipherESP->hmacDigestSizeGet(cipherESP))) == FALSE) { return (FALSE); }#ifdef IPSEC_VERBOSE_PACKET_DEBUGGING ike_debug_printf_bytes (IKE_ERROR_PRINTF, "== packet after padding:", pPacket, packetBufDataSizeGet(pPacketBuf)); { char printBuf[512]; ((C_OBJ *)cipher)->toString ((C_OBJ *)cipher, (unsigned char *)printBuf, 512); printf ("%s\n", printBuf); }#endif /* encrypt packet */ /* NOTE: cipher object updates 4th parameter with actual encrypted packet length, which includes padding. */ /* NOTE: CCI considers pCiphertext and ciphertextLength as * IN-OUT parameters so we must set them here. */ pCiphertext = pPlaintext; ciphertextLength = plaintextLength; /* New single-pass interface to encryption/HMAC generation is set up here. * The single-pass algorithm requires: * 1) location and size of ciphertext * 2) location and size of un-encrypted headers * 3) location and size of destination buffer for (truncated 96-bit) digest. */ /* ESP Authorization covers ESP Hdr: [SPI | SEQ], [IV], [ESP-PAYLOAD]. * The single-pass algorithm needs a separate pointer to the un-encrypted * portion; in our case, the header. */ cipherESP->hmacInBufSet(cipherESP, pPacket, LENGTH_OF_SPI_AND_SEQ_FIELDS + IVLength); /* pTrailerFields points to just beyond what it last wrote -- the PAD_LENGTH * and NEXT_HEADER fields; thus it points to where we want the Auth data to go. */ cipherESP->hmacDigestBufSet(cipherESP, pTrailerFields); #ifdef IPSEC_VERBOSE_PACKET_DEBUGGING { char printBuf[512]; ((C_OBJ *)cipher)->toString ((C_OBJ *)cipher, (unsigned char *)printBuf, 512); printf ("%s\n", printBuf); } #endif cciStatus = cipher->encrypt (cipher, pPlaintext, plaintextLength, pCiphertext, &ciphertextLength); if (cciStatus != CCI_SUCCESS) { ipsec_printf (IPSEC_ERROR_PRINTF, "IPsec: Failed Encryption.\n"); return (FALSE); } /* We should now have [ESP HDR][ESP PAYLOAD][ESP TRAILER][HMAC Digest]. * However, IPsec uses truncated HMAC digests (96 bits for all algorithms * as of this writing), so as a final step we chop off the least-significant * portion. */ if( packetBufReduceBack(pPacketBuf, (cipherESP->hmacDigestSizeGet(cipherESP) - cipherESP->hmacDigestTruncSizeGet(cipherESP))) == FALSE ) { return(FALSE); }#ifdef IPSEC_VERBOSE_PACKET_DEBUGGING ike_debug_printf_bytes (IKE_ERROR_PRINTF, "== packet after encryption:", pPacket, packetBufDataSizeGet(pPacketBuf)); if (AESCTRMode == TRUE) { ike_debug_printf_bytes (IKE_ERROR_PRINTF, "<AES-CTR Counter Block post-encryption>:", (unsigned char *)cipher->_pIV, cipher->IVSizeGet (cipher)); }#endif return (TRUE); }/******************************************************************************/UINT ipsec_esp_message_peek_at_security_parameters_index ( IP_VI_MESSAGE *p_ip_message ) { PACKETBUF* pPacketBuf; UCHAR* bptr_packet; UINT spi; pPacketBuf = p_ip_message->pPayload; bptr_packet = packetBufDataGet(pPacketBuf); if (bptr_packet == NULL) { return (FALSE); } spi = wrSecDeserializeULong (&bptr_packet); return (spi); }/******************************************************************************/void ipsec_esp_message_get_spi_and_sequence_number ( IPSEC_ESP_MESSAGE *sptr_ipsec_esp_message, IP_VI_MESSAGE *p_ip_message ) { PACKETBUF* pPacketBuf; UCHAR* bptr_packet; pPacketBuf = p_ip_message->pPayload; bptr_packet = packetBufDataGet(pPacketBuf); if (bptr_packet != NULL) { sptr_ipsec_esp_message->spi = wrSecDeserializeULong (&bptr_packet); sptr_ipsec_esp_message->esp_sequence_number = wrSecDeserializeULong (&bptr_packet); } }/******************************************************************************/void ipsec_esp_message_set_authentication_algorithm ( IPSEC_ESP_MESSAGE *sptr_ipsec_esp_message, IPSEC_AUTH_ALGORITHM_ID authentication_type ) { sptr_ipsec_esp_message->authentication_type = authentication_type; }/******************************************************************************/void ipsec_esp_message_set_crypto_algorithm ( IPSEC_ESP_MESSAGE *sptr_ipsec_esp_message, IPSEC_ESP_TRANSFORM_ID crypto_algorithm ) { sptr_ipsec_esp_message->crypto_algorithm = crypto_algorithm; }/******************************************************************************* ipsec_decrypt_esp_message - Decrypts the part of the esp packet.** DESCRIPTION : This decrypts the part of the esp packet from a given point * (third argument) of a given length.* (specified in the fourth argument)** RETURNS : TRUE or FALSE.*/BOOL ipsec_decrypt_esp_message ( SA_BUNDLE *sptr_ib_sa_bundle, UCHAR *bptr_packet, UINT packet_length, UCHAR ** bptr_decrypted_data, USHORT *decrypted_packet_length, UINT *padLength, UCHAR *next_header ) { UCHAR *pTrailerFields; UINT IVLength; UINT encrypted_packet_length; UCHAR *bptr_encrypted_packet; BOOL AESCTRMode; cci_st cciStatus; int pad; INBOUND_ESP_SA_SPEC *sptr_ib_esp_sa_spec; SA_SPEC *sptr_sa_spec; CIPHER *cipher; CIPHER_ESP *cipherESP; UINT cciHMACAlg; void *iterator = (void *)NULL; AESCTRMode = FALSE; wrSecListScanLock( sptr_ib_sa_bundle->sa_specs ); while ((sptr_sa_spec = wrSecListScan( sptr_ib_sa_bundle->sa_specs, &iterator )) != NULL) { if (sptr_sa_spec->type == IPSEC_ESP_PROTOCOL_SPEC) { break; } } wrSecListScanUnlock( sptr_ib_sa_bundle->sa_specs ); if (sptr_sa_spec == NULL) { return (FALSE); } sptr_ib_esp_sa_spec = (INBOUND_ESP_SA_SPEC *)sptr_sa_spec; cipher = (CIPHER *)(&sptr_ib_esp_sa_spec->localCipher); cipherESP = (CIPHER_ESP *)cipher; if ((cipher->cipherGet (cipher) == CCI_CIPHER_AES) && (cipher->modeGet (cipher) == CCI_MODE_CTR)) { AESCTRMode = TRUE; } /* Temporarily disable HMAC calculation since we just want decryption here */ cciHMACAlg = cipherESP->hmacGet(cipherESP); if( cipherESP->hmacSet(cipherESP, CCI_HMAC_NONE) != OK ) { ipsec_printf(IPSEC_ERROR_PRINTF, "== %s: Error setting HMAC algorithm to HMAC_NONE.\n", __FUNCTION__); return (FALSE); } IVLength = cipher->IVSizeGet (cipher); if (AESCTRMode) { IVLength = IVLength - sizeof (UINT) - sizeof (UINT); /* Extract IV from incoming packet, put into AES cipher counter block */ CTRModeCounterBlockIVExtractAndSet (cipher, bptr_packet + LENGTH_OF_SPI_AND_SEQ_FIELDS); } else { /* extract iv */ cipher->IVSet (cipher, (bptr_packet + LENGTH_OF_SPI_AND_SEQ_FIELDS)); } encrypted_packet_length = packet_length - (LENGTH_OF_SPI_AND_SEQ_FIELDS + IVLength); /* check for alignment */ if ((pad = (packet_length % cipher->blockSizeGet (cipher))) != 0) { encrypted_packet_length -= pad; } if (encrypted_packet_length <= cipher->blockSizeGet (cipher)) { return (FALSE); } bptr_encrypted_packet = bptr_packet + LENGTH_OF_SPI_AND_SEQ_FIELDS + IVLength; /* decrypt packet */ cciStatus = cipher->decrypt (cipher, bptr_encrypted_packet, encrypted_packet_length, bptr_encrypted_packet, &encrypted_packet_length); /* Restore HMAC algorithm used by this SA */ if( cipherESP->hmacSet(cipherESP, cciHMACAlg) != OK ) { ipsec_printf(IPSEC_ERROR_PRINTF, "== %s: Error restoring HMAC algorithm.\n", __FUNCTION__); return (FALSE); } if (cciStatus != CCI_SUCCESS) { return (FALSE); } /* deserialize trailer */ pTrailerFields = (bptr_packet + packet_length) - LENGTH_OF_PADLEN_AND_NEXTHDR_FIELDS; *bptr_decrypted_data = bptr_encrypted_packet; *padLength = wrSecDeserializeUChar (&pTrailerFields); /* pTrailerFields++ */ *decrypted_packet_length = encrypted_packet_length; *next_header = (IP_TRANSPORT_PROTOCOL)wrSecDeserializeUChar (&pTrailerFields); /* pTrailerFields++ */ return (TRUE); }/*****************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -