The SafetyProvider calculates the CRC signature (ResponseSPDU.CRC) and sends it to the SafetyConsumer as part of SPDU. This enables the SafetyConsumer to check the correctness of the SPDU including the SafetyData, Flags, MNR, SafetyConsumerID and SPDU_ID by recalculating the CRC signature (CRC_calc).
[RQ8.19] The generator polynomial 0x F4ACFB13 shall be used for the 32-Bit CRC signature.
[RQ8.20] If SafetyData is longer than one byte (e.g., if it is of data type UInt16, Int16 or Float32), it shall be decoded and encoded using little endian order in which the least significant byte appears first in the incremental memory address stream.
[RQ8.21] The calculation sequence shall begin with the highest memory address (n) of the STrailer counting back to the lowest memory address (0) and then include also the SafetyData beginning with the highest memory address.
Figure 23 and shows the calculation sequence of a CRC_SPDU on a little-endian machine, using an example SafetyData with the following fields:
The STrailer and SafetyData have a total length of 34 bytes. The calculation of ResponseSPDU.CRC (SafetyProvider) or CRC_calc (SafetyConsumer) is done in reverse order, from bottom to top. In the example shown in Figure 23, CRC calculation starts at byte index 33 (most significant byte of the MNR) and ends at byte index 0.
NOTE: the reverse order ensures that the effectiveness of the CRC mechanism remains independent of any CRCs used within the underlying OPC UA channel, even if it would coincidentally use the same CRC polynomial.
Figure 23 – Calculation of the CRC (on little-endian machines, CRC32_Backward)
An alternative way to calculate the CRC (particularly useful on big-endian machines) is shown in Figure 24. Here, the individual elements of the ResponseSPDU are already arranged in memory in reversed order, and CRC calculation is executed from byte 0 to byte 33.
Figure 24 – Calculation of the CRC (on big-endian machines, CRC32_Forward)
[RQ8.22] On the SafetyConsumer, CRC_calc shall be calculated using data received in the ResponseSPDU, and not from expected values.