Summary

  • RFC 3385 treated “32-bit checksum” as an incomplete description. Undetected-error behavior also depended on the generator polynomial, protected block length, error distribution and the structure of real data.
  • The authors judged CRC32C a good basic error detector for iSCSI under declared accidental-corruption assumptions. They did not make it a cryptographic integrity mechanism or a universal probability guarantee.

Place two four-byte fields beside an iSCSI data block. They consume the same wire space. They can even carry values that look equally random in a trace. Yet one may reliably expose a clustered corruption pattern that the other lets pass. The visible width is identical; the protection is not.

RFC 3385 was published in September 2002 to estimate probabilities of undetected error and support the choice of an error-detection code for iSCSI. Its category was Informational. It did not specify the complete iSCSI protocol, certify an implementation or report field adoption. Its job was analytical: make the integrity trade-off legible before a reassuring label hardened into a protocol choice.

iSCSI was moving SCSI commands and storage data across IP networks. Storage applications brought a severe consequence model. A transport error that escaped detection could reach a device or filesystem as apparently valid content. The quantity of data mattered too. The memo pointed toward petabyte-scale movement and required very good behavior at least through blocks of 8 KiB.

The prior iSCSI requirements document, RFC 3347, explained why the ordinary TCP checksum was not enough as the sole story. Research had shown that some bit errors could pass it. A proxy or gateway could terminate the TCP stream, remove and rebuild iSCSI headers, then recompute the TCP checksum. Protection of SCSI data, commands and status therefore needed a digest boundary belonging to iSCSI rather than a blind assumption that every lower layer preserved the original evidence.

RFC 3385 began by refusing to treat errors as one uniform phenomenon. It considered burst errors on noisy channels and independent single-bit errors on low-noise channels. A memory fault or software defect could also create a clustered pattern. What mattered was not only how often bits changed, but how changed bits were distributed and how long a block was when the code examined it.

A cyclic redundancy check forms a codeword by appending parity bits computed with a generator polynomial. At the receiver, an erroneous word can be accepted only when the error pattern itself has the mathematical structure of a valid codeword. Minimum distance and weight distribution therefore shape what patterns remain invisible. “Thirty-two bits” states the amount of redundancy. It does not state the geometry of the code.

That distinction became sharper for shortened codes. Different generator polynomials of the same degree could behave differently once codewords were shortened to practical block lengths. The memo cited work finding orders-of-magnitude differences between 32-bit polynomials for a particular burst condition. A width comparison would classify those codes as equivalent precisely where the analysis showed them diverging.

The familiar IEEE 802 polynomial and CRC32C were both 32-bit CRCs. CRC32C used generator 0x11EDC6F41. The different polynomial was not a cosmetic implementation detail. It changed minimum-distance behavior over relevant ranges and therefore changed which error patterns were guaranteed or likely to be detected.

The paper's estimates were explicitly conditional. It assumed a burst-error rate, an independent bit-error rate and a distribution for burst duration. It translated a fixed-duration burst into more corrupted bits as transmission speed rose. It also reasoned about an 8 KiB protection unit. The resulting probabilities do not float free of those inputs. Replacing the channel, workload, block or distribution changes the claim that can be made.

This is especially important because one number can look cosmic. Under its declared assumptions, the memo derived extremely low estimates for undetected burst error with CRC32C. Those are not measurements from every network, nor a warranty that a deployment will experience that rate. They are outputs of a model. Their proper evidentiary form is “given these assumptions, this code produced this bound,” not “CRC32C fails only once in an unimaginable number of events.”

The comparison with Fletcher and Adler checksums supplied a second lesson. Under the analyzed independent-error conditions, the memo estimated that CRC performance was roughly 12,000 times better than Fletcher and 22,000 times better than Adler. It also highlighted simple multi-byte error patterns that additive checksums could miss. Real data could be biased rather than uniformly random, and cited experiments found checksums suffered substantially from such hot spots while CRCs spread their sensitivity differently.

The summary table made the same-width comparison concrete. Fletcher32, Adler32, IEEE-802 CRC and CRC32C all carried 32 bits, yet the table assigned them different minimum-distance ranges and model-dependent undetected-error estimates. The authors concluded that CRC32C was a good basic mechanism for iSCSI because it combined protection level, relative insensitivity to biased data and the ability to protect large blocks.

Cost remained part of the decision. The cited synthesis exercise counted XOR gates and optimized cells for candidate polynomials. CRC32C cost more hardware than CCITT-CRC32 in that setup. But the CRC circuit represented less than one percent of a representative one-million-cell chip. The document did not erase the cost; it placed it next to the integrity gain so the choice could be judged on the right scale.

Software and hardware paths also mattered. The memo included serial and 32-bit parallel implementations, while noting that software commonly used tables indexed by incoming data and current state. A standard polynomial was not sufficient for interoperability by name alone. Bit order, initialization, complementation, padding and mapping of the final remainder also needed an exact contract.

CRC linearity created an incremental-update option. If an intermediate node changed a covered header, it could adjust the CRC using the known delta rather than reread and recompute the whole data block. The final target could still verify the combined header, data and CRC, including unwanted changes introduced along the path. This was a performance and coverage property, not permission to treat all middlebox changes as trusted.

The consolidated iSCSI specification, RFC 7143, later made the operational contract explicit. HeaderDigest and DataDigest default to None, while every initiator and target must implement CRC32C and None. When peers negotiate a digest, it applies through the Full Feature Phase. The specification calls these digests non-cryptographic and says they extend error checking across the communication path, including elements that can modify network-level PDUs.

That later contract creates several facts that must not be collapsed. An implementation may support CRC32C. A session may offer it. The peer may select it. A particular PDU may verify successfully. None of those facts alone proves that CRC32C was active for every connection, that the covered bytes matched an operator's mental model or that stored content remained correct after the protected path ended.

The security boundary was unambiguous. An attacker able to modify the data can also modify the error-detection value so the new pair verifies. CRCs in this memo detect unintentional change. They do not authenticate a sender, bind authorization or prevent malicious tampering. A passing CRC is evidence against some accidental-error patterns, not evidence against an active adversary.

The same CRC32C polynomial appeared in the SCTP change documented by RFC 3309 and in later SCTP specifications such as RFC 4960 and RFC 9260. That chronology shows reuse of a well-studied code, but it does not make every use case equivalent. Different packet lengths, covered fields, lower layers, failure distributions and recovery rules create different evidence surfaces.

Earlier Internet checksum work provides another useful boundary. RFC 1071 documented efficient computation of the Internet checksum. RFC 1141 and RFC 1624 addressed incremental updates, including an error in the earlier formula. RFC 2151 described a Fletcher checksum for an alternate UDP checksum, while RFC 1950 used Adler-32 in the zlib format. These documents show that “checksum” names a family of purposes and arithmetic structures, not one interchangeable assurance level.

The memo ended with a systems warning. A burst characterized by fixed time occupies more bits as channel speed increases. A higher-layer CRC can improve detection for its protected unit, but it cannot by itself hold long-term risk constant as physical and lower-layer conditions evolve. Better coding and lower bit-error rates at lower layers remain part of the control surface.

Lu Heng's minimum-initial-specification lens explains why the polynomial and digest procedure needed to be fixed even while implementations retained hardware and software freedom. The specification had to localize the shared decision: exact generator, bit mapping and negotiated coverage. It could leave optimization to implementers only after every implementation meant the same thing by a passing digest.

His reality-layers lens exposes the danger of the width label. Field present, algorithm supported, digest negotiated, PDU covered, value verified, accidental corruption excluded under a model, and adversarial integrity established are distinct facts. “It has a 32-bit checksum” compresses all seven into a symbol that proves almost none of them.

RFC 3385's historical contribution was therefore not merely recommending CRC32C. It demonstrated how to turn an integrity slogan into a bounded evidence claim. The number of bits was the visible shell. The polynomial, block, workload, path and threat model decided what the shell could honestly mean.

Sources