draft-ietf-tsvwg-sctpcsum-02.txt   draft-ietf-tsvwg-sctpcsum-03.txt 
Network Working Group R. Stewart Network Working Group R. Stewart
Category: Internet Draft Cisco Systems Category: Internet Draft Cisco Systems
J. Stone J. Stone
Stanford Stanford
D. Otis D. Otis
SANlight SANlight
January 18, 2002 March 1, 2002
SCTP Checksum Change SCTP Checksum Change
draft-ietf-tsvwg-sctpcsum-02.txt draft-ietf-tsvwg-sctpcsum-03.txt
Status of this Memo Status of this Memo
This document is an internet-draft and is in full conformance with all This document is an internet-draft and is in full conformance with all
provisions of Section 10 of RFC2026. provisions of Section 10 of RFC2026.
Internet-Drafts are working documents of the Internet Engineering Task Internet-Drafts are working documents of the Internet Engineering Task
Force (IETF), its areas, and its working groups. Note that other groups Force (IETF), its areas, and its working groups. Note that other groups
may also distribute working documents as Internet-Drafts. Internet- may also distribute working documents as Internet-Drafts. Internet-
Drafts are draft documents valid for a maximum of six months and may be Drafts are draft documents valid for a maximum of six months and may be
skipping to change at page 1, line 42 skipping to change at page 1, line 42
Abstract Abstract
SCTP [RFC2960] currently uses an Adler-32 checksum. For small packets SCTP [RFC2960] currently uses an Adler-32 checksum. For small packets
Adler-32 provides weak detection of errors. This document changes that Adler-32 provides weak detection of errors. This document changes that
checksum and updates SCTP to use a 32 bit CRC checksum. checksum and updates SCTP to use a 32 bit CRC checksum.
Table of Contents Table of Contents
1 Introduction ................................................ 1 1 Introduction ................................................ 1
2 Checksum Procedures ......................................... 2 2 Checksum Procedures ......................................... 2
3 Security Considerations...................................... 4 3 Security Considerations...................................... 5
4 IANA Considerations.......................................... 4 4 IANA Considerations.......................................... 5
5 Acknowledgments ............................................. 4 5 Acknowledgments ............................................. 5
6 Authors' Addresses .......................................... 4 6 Authors' Addresses .......................................... 6
7 References .................................................. 5 7 References .................................................. 7
8 Appendix .................................................... 5 8 Appendix .................................................... 8
1 Introduction 1 Introduction
A fundamental weakness has been detected in SCTP's current Adler-32 A fundamental weakness has been detected in SCTP's current Adler-32
checksum algorithm [STONE]. One requirement of an effective checksum is checksum algorithm [STONE]. One requirement of an effective checksum is
that it evenly and smoothly spreads its input packets over the available that it evenly and smoothly spreads its input packets over the available
check bits. check bits.
From an email from Jonathan Stone, who analyzed the Adler-32 as part From an email from Jonathan Stone, who analyzed the Adler-32 as part
of his doctoral thesis: of his doctoral thesis:
skipping to change at page 3, line 45 skipping to change at page 3, line 45
CRC-32c value. If not, the receiver MUST treat the packet as an CRC-32c value. If not, the receiver MUST treat the packet as an
invalid SCTP packet. invalid SCTP packet.
The default procedure for handling invalid SCTP packets is to silently The default procedure for handling invalid SCTP packets is to silently
discard them. discard them.
We define a 'reflected value' as one that is the opposite of the We define a 'reflected value' as one that is the opposite of the
normal bit order of the machine. The 32 bit CRC is normal bit order of the machine. The 32 bit CRC is
calculated as described for CRC-32c and uses the polynomial code calculated as described for CRC-32c and uses the polynomial code
0x11EDC6F41 (Castagnoli93) or x^32+x^28+x^27+x^26+x^25 0x11EDC6F41 (Castagnoli93) or x^32+x^28+x^27+x^26+x^25
+x^23+x^22+x^20+x^19+x^18+x^14+x^13+x^11+x^10+x^9+x^8+x^6+x^0 with +x^23+x^22+x^20+x^19+x^18+x^14+x^13+x^11+x^10+x^9+x^8+x^6+x^0.
reflected placement. With most serial media, the bits within each The CRC is computed using a procedure similar to ETHERNET CRC [ITU32],
byte are shifted out least significant bit first. CRCs are modified to reflect transport level usage.
calculated from most significant to least. To accommodate the
serial bit order, a reflected table is used. This reflected technique
also reduces the number of instructions needed for each lookup.
Background information on reflected and non-reflected CRC tables
can be found in [Williams93]. A byte based lookup table would
use the same shifting algorithm (not the same table) as that
used by the ETHERNET CRC [ITU32] since the ethernet CRC is also
built with reflected placment.
To improve leading zero detection, the working accumulator holding CRC computation uses polynomial division. A message bit-string M
the CRC value is initialized to all one's prior to the packet is transformed to a polynomial, M(X), and the CRC is calculated
calculation but is not inverted before being placed in the SCTP from M(X) using polynomial arithmetic [Peterson 72].
Checksum field [McKee75]. Placement in the SCTP common header and jumbo When CRCs are used at the link layer, the polynomial is derived from
frames cause variances from the Ethernet CRC algorithm. The on-the-wire bit ordering: the first bit `on the wire' is
[Castagnoli93] polynomial offers error detection enhancements for the high-order coefficient. Since SCTP is a transport-level protocol,
jumbo frames at the expense of gates. The software table it cannot know the actual serial-media bit ordering. Moreover,
implementations for any 32 bit polynomial has the same overhead different links in the path between SCTP endpoints may use
however. different link-level bit orders)
A convention must therefore be established for mapping SCTP transport
messages to polynomials for purposes of CRC computation.
The bit-ordering for mapping SCTP messages to polynomials is
that bytes are taken most-significant first; but within each byte,
bits are taken least-significant first. The first byte of the
message provides the eight highest coefficients.
Within each byte, the least-significant SCTP bit gives the
most significant polynomial coefficient within that byte, and
the most-significant SCTP bit is the most significant polynomial
coefficient in that byte. (This bit ordering is sometimes
called `mirrored' or `reflected' [Williams93].) CRC polynomials
are to be transformed back into SCTP transport-level byte values
using a consistent mapping.
3 Security Considerations The SCTP transport-level CRC value should be calculated as follows:
- CRC input data are assumed to a byte stream numbered from 0
to N-1.
- the transport-level byte-stream is mapped to a polynomial value.
An N-byte PDU with bytes 0 to N-1, is considered as
coefficients of a polynomial M(x) of order 8N-1, with
bit 0 of byte j being coefficient x^(8j-1), bit 7 of byte
0 being coefficient x(8j^-8).
- the CRC remainder register is initialized with all
1s (equivalent to complementing the first 32 bits of the message)
- the polynomial is multiplied by x^32 and divided by G(x),
the generator polynomial, producing a remainder R(x) of degree
less than or equal to 31.
- the coefficients of R(x) are considered a 32 bit sequence.
- the bit sequence is complemented. The resulting is the CRC
polynomial.
- The CRC polynomial is mapped back into SCTP transport-level
bytes. Coefficient of x^31 gives the value of bit 0 of
SCTP byte 0, the coefficient of x^24 gives the value of
bit 7 of byte 0. the coefficient of x^7 gives bit 0 of
bit 0 and the coefficient of x^0 0 gives bit 7 of byte 3.
The resulting four-byte transport-level sequence is the
32-bit SCTP checksum value.
When an SCTP packet is transmitted, the sender MUST perform this
checksum procedure, using the preceding CRC computation:
1) Fill in the proper Verification Tag in the SCTP common header and
initialize the Checksum field to 0's.
2) Calculate the CRC-32c of the whole packet, including the SCTP common
header and all the chunks.
3) Put the resultant 32-bit SCTP checksum value into the Checksum field
in the common header, and leave the rest of the bits unchanged.
When an SCTP packet is received, the receiver MUST first perform the
following:
1) Store the received CRC-32c value,
2) Replace the 32 bits of the Checksum field in the received SCTP packet
with all '0's and calculate the SCTP CRC-32c checksum value of
the whole received packet. And,
3) Verify that the calculated CRC-32c value is the same as the received
CRC-32c value. If not, the receiver MUST treat the packet as an
invalid SCTP packet.
The default procedure for handling invalid SCTP packets is to silently
discard them.
If SCTP could follow link level CRC use, the CRC would be computed
over the link-level bit-stream. The first bit on the link
mapping to the highest-order coefficient, and so on down to the
last link-level bit as the lowest-order coefficient. The CRC value
would be transmitted immediately after the input message as a link-level
`trailer'. The resulting link-level bit-stream would be
(M(X)x) * x^32) + (M(X)*x^32))/ G(x), which is divisible by G(X).
There would thus be a constant CRC remainder for `good' packets.
However, given that implementations of RFC2960 have already
proliferated, the IETF discussions considered that the benefit of
a `trailer' CRC did not outweigh the cost of making a very large
change in the protocol processing. Further, packets accepted by
the SCTP `header' CRC are in one-to-one correspondence with
packets accepted by a modified procedure using a `trailer'
CRC value, and where the SCTP common checksum header is set to zero
on transmission and is received as zero.
There may be a computational advantage in validating the Association There may be a computational advantage in validating the Association
against the Verification Tag prior to performing a checksum as against the Verification Tag prior to performing a checksum as
invalid tags will result in the same action as a bad checksum in invalid tags will result in the same action as a bad checksum in
most cases. The exceptions for this technique would be INIT and some most cases. The exceptions for this technique would be INIT and some
SHUTDOWN-COMPLETE exchanges as well as a stale COOKIE-ECHO. These SHUTDOWN-COMPLETE exchanges as well as a stale COOKIE-ECHO. These
special case exchanges must represent small packets and will special case exchanges must represent small packets and will
minimize the effect of the checksum calculation. In general, minimize the effect of the checksum calculation.
the security considerations of RFC2960 apply to the protocol
with the new checksum as well. 3 Security Considerations
In general, the security considerations of RFC2960 apply to
the protocol with the new checksum as well.
4 IANA Considerations 4 IANA Considerations
There are no IANA considerations required in this document. There are no IANA considerations required in this document.
5 Acknowledgments 5 Acknowledgments
The authors would like to thank the following people that have The authors would like to thank the following people that have
provided comments and input on the checksum issue: provided comments and input on the checksum issue:
Mark Adler, Ran Atkinson, Stephen Bailey, David Black, Scott Mark Adler, Ran Atkinson, Stephen Bailey, David Black, Scott
Bradner, Mikael Degermark, Laurent Glaude, Klaus Gradischnig, Alf Bradner, Mikael Degermark, Laurent Glaude, Klaus Gradischnig, Alf
Heidermark, Jacob Heitz, Gareth Kiely, David Lehmann, Allision Heidermark, Jacob Heitz, Gareth Kiely, David Lehmann, Allision
Mankin, Lyndon Ong, Craig Partridge, Vern Paxson, Kacheong Poon, Mankin, Lyndon Ong, Craig Partridge, Vern Paxson, Kacheong Poon,
Michael Ramalho, David Reed, Ian Rytina, Hanns Juergen Schwarzbauer, Michael Ramalho, David Reed, Ian Rytina, Hanns Juergen Schwarzbauer,
Chip Sharp, Bill Sommerfeld, Michael Tuxen, Jim Williams, Jim Wendt, Chip Sharp, Bill Sommerfeld, Michael Tuexen, Jim Williams, Jim Wendt,
Michael Welzl, Jonathan Wood, Lloyd Wood, Qiaobing Xie, La Monte Michael Welzl, Jonathan Wood, Lloyd Wood, Qiaobing Xie, La Monte
Yarroll, Dafna Sheinwald, and Julian Satran, Pat Thaler, Vince Yarroll.
Cavanna, Matt Wakeley.
Special thanks to Mr. Ross William's and his informative document Special thanks to Dafna Scheinwald, Julian Satran Pat Thaler, Matt
[Williams93] which helped further the authors understanding of Wakeley, and Vince Cavanna, for selection criteria of polynomials and
both CRC's and bit reflection. examination of CRC polynomials, particularly CRC-32c [Castagnoli93].
Special thanks to Mr. Ross Williams and his document [Williams93].
This non-formal perspective on software aspects of CRCs furthered
understanding of authors previously unfamiliar with CRC computation.
More formal treatments of [Blahut 94] or [Peterson 72], was
also essential.
6 Authors' Addresses 6 Authors' Addresses
Randall R. Stewart Randall R. Stewart
24 Burning Bush Trail. 24 Burning Bush Trail.
Crystal Lake, IL 60012 Crystal Lake, IL 60012
USA USA
EMail: rrs@cisco.com EMail: rrs@cisco.com
Jonathan Stone Jonathan Stone
Room 446, Mail code 9040 Room 446, Mail code 9040
Gates building 4A Gates building 4A
Stanford, Ca 94305 Stanford, Ca 94305
EMail: jonathan@dsg.stanford.edu EMail: jonathan@dsg.stanford.edu
Douglas Otis Douglas Otis
800 E. Middlefield 800 E. Middlefield
Mountain View, CA 94043 Mountain View, CA 94043
skipping to change at page 5, line 53 skipping to change at page 7, line 27
7.1 Informative References 7.1 Informative References
[STONE] Stone, J., "Checksums in the Internet", Doctoral [STONE] Stone, J., "Checksums in the Internet", Doctoral
dissertation - August 2001 dissertation - August 2001
[Williams93] Williams, R., "A PAINLESS GUIDE TO CRC ERROR DETECTION [Williams93] Williams, R., "A PAINLESS GUIDE TO CRC ERROR DETECTION
ALGORITHMS" - Internet publication, August 1993, ALGORITHMS" - Internet publication, August 1993,
http://www.geocities.com/SiliconValley/Pines/8659/crc.htm. http://www.geocities.com/SiliconValley/Pines/8659/crc.htm.
8 Appendix [Blahut 1994], R.E. Blahut, Theory and Practice of Error Control
Codes, Addison-Wesley, 1994.
[Easics 2001]. http://www.easics.be/webtools/crctool. Online tools
for synthesis of CRC Verilog and VHDL.
[Feldmeier 95], David C. Feldmeier, Fast software implementation of
error detection codes, IEEE Transactions on Networking, vol 3 no 6,
pp 640-651, December, 1995.
[Glaise 1997] R. J. Glaise, A two-step computation of cyclic
redundancy code CRC-32 for ATM networks, IBM Journal of Research and
Development} vol 41 no 6, 1997. URL=
http://www.research.ibm.com/journal/rd/416/glaise.html.
[Prange 1957], E. Prange, Cyclic Error-Correcting codes in two
symbols, Technical report AFCRC-TN-57-103, Air Force Cambridge
Research Center, Cambridge, Mass. 1957.
[Peterson 1972], W. W. Peterson and E.J Weldon, Error Correcting
Codes, 2nd. edition, MIT Press, Cambridge, Massachusetts.
[Shie2001] Ming-Der Shieh et. al, A Systematic Approach for Parallel
CRC Computations. Journal of Information Science and Engineering,
Vol.17 No.3, pp.445-461
[Sprachman2001] Michael Sprachman, Automatic Generation of Parallel
CRC Circuits, IEEE Design & Test May-June 2001
8 Appendix
This appendix is for information only and is NOT part of the This appendix is for information only and is NOT part of the
standard. The following code is based on the Castagnoli's standard.
CRC-32c polynomial 0x11EDC6F41 as in [Castagnoli93] and is
not intended to represent an optimal implementation. The anticipated deployment of SCTP ranges over several orders of
magnitude of link speed: from cellular-power telephony devices at
tens of kilobits, to local links at tens of gigabits. Implementors
of SCTP should consider their link speed and choose, from the wide
range of CRC implementations, one which matches their own design
point for size, cost, and throughput. Many techniques for computing
CRCs are known. This Appendix surveys just a few, to give a feel for
the range of techniques available.
CRCs are derived from early work by Prange in the 1950s [Prange 57].
The theory underlying CRCs and choice of generator polynomial can be
introduced by either via the theory of Galois fields [Blahut 94]
or as ideals of an algebra over cyclic codes [cite Peterson 72].
One of the simplest techniques is direct bit-serial hardware
implementations, using the generator polynomial as the taps of a
linear feedback shift register (LSFR). LSFR computation follows
directly from the mathematics, and is generally attributed to Prange.
Tools exist which, a CRC generator polynomial, will produce
synthesizable Verilog code for CRC hardware [Easics 2001].
Since LSFRs do not scale well in speed, a variety of other
techniques have been explored. One technique exploits the fact that
the divisor of the polynomial long-division, G, is known in
advance. It is thus possible to pre-compute lookup tables giving the
polynomial remainder of multiple input bits --- typically 2, 4, or 8
bits of input at a time. This technique can be used either in
software or in hardware. Software to compute lookup tables yielding
2, 4, or 8 bits of result is freely available. [Williams93]
For multi-gigabit links, the above techniques may still not be fast
enough. One technique for computing CRCS at OC-48 rates is
`two-stage' CRC computation [Glaise 1997]. Here, some multiple
of G(x), G(x)H(x), is chosen so as to minimize the number of nonzero
coefficients, or weight, of the product G(x)H(x). The low weight of
the product polynomial makes it susceptible to efficient hardware
divide-by-constant implementations. This first stage gives M(x) /
(G(x)H(x)) as its result. The second stage then divides the result
of the first stage by H(x), yielding (M(x) / (G(x)H(x))) / H(x). If
H(x) is also relatively prime to G(x), this gives M(x)/G(x).
Further developments on this approach can be found in [Shie2001] and
[Sprachman2001].
The literature also includes a variety of software CRC
implementations. One approach is to use carefully-tuned assembly
code for direct polynomial division. [Feldmeier 95] reports that for
low-weight polynomials, tuned polynomial arithmetic gives higher
throughput than table-lookup algorithms. Even within table-lookup
algorithms, the size of the table can be tuned, either for total
cache footprint, or (for space-restricted environments) to minimize
total size.
Implementors should keep in mind the bit ordering described in
Section 2: the ordering of bits within bytes for computing CRCs in
SCTP is the least significant bit of each byte is the
most-significant polynomial coefficient(and vice-versa). This
`reflected' SCTP CRC bit ordering matches on-the-wire bit order for
Ethernet and other serial media, but is the reverse of traditional
Internet bit ordering.
One technique to accommodate this bit-reversal can be explained as
follows: sketch out a hardware implementation assuming the bits are
in CRC bit order; then perform a left-to-right inversion (mirror
image) on the entire algorithm. (We defer for a moment the issue of
byte order within words.) Then compute that "mirror image" in
software. The CRC from the ``mirror image'' algorithm will be the
bit-reversal of a correct hardware implementation. When the
link-level media sends each byte, the byte is sent in the reverse of
the host CPU bit-order. Serialization of each byte of the
``reflected'' CRC value re-reverses the bit order, so in the end,
each byte will be transmitted on-the-wire in the specified bit
order.
The following non-normative sample code is taken from an open-source
CRC generator [Williams93] using the ``mirroring'' technique
and yielding a lookup table for SCTP CRC32-c with 256 entries, each
32 bits wide. While neither especially slow nor especially fast, as
software table-lookup CRCs go, it has the advantage of working on
both big-endian and little-endian CPUs, using the same (host-order)
lookup tables, and using only the pre-defined ntohl() and htonl()
operations. The code is somewhat modified from [Williams93], to
ensure portability between big-endian and little-endian
architectures. (Note that if the byte endian-ness of the target
architecture is known to be little-endian the final bit-reversal and
byte-reversal steps can be folded into a single operation.)
/*************************************************************/ /*************************************************************/
/* Note Definition for Ross Williams table generatator would */ /* Note Definition for Ross Williams table generator would */
/* be: TB_WIDTH=4, TB_POLLY=0x1EDC6F41, TB_REVER=TRUE */ /* be: TB_WIDTH=4, TB_POLLY=0x1EDC6F41, TB_REVER=TRUE */
/* For Mr. Williams direct calculation code use the settings */ /* For Mr. Williams direct calculation code use the settings */
/* cm_width=32, cm_poly=0x1EDC6F41, cm_init=0xFFFFFFFF, */ /* cm_width=32, cm_poly=0x1EDC6F41, cm_init=0xFFFFFFFF, */
/* cm_refin=TRUE, cm_refot=TRUE, cm_xorort=0x00000000 */ /* cm_refin=TRUE, cm_refot=TRUE, cm_xorort=0x00000000 */
/*************************************************************/ /*************************************************************/
/* Example of the crc table file */ /* Example of the crc table file */
#ifndef __crc32cr_table_h__ #ifndef __crc32cr_table_h__
#define __crc32cr_table_h__ #define __crc32cr_table_h__
skipping to change at page 7, line 54 skipping to change at page 11, line 32
#define OUTPUT_FILE "crc32cr.h" #define OUTPUT_FILE "crc32cr.h"
#define CRC32C_POLY 0x1EDC6F41L #define CRC32C_POLY 0x1EDC6F41L
FILE *tf; FILE *tf;
unsigned long unsigned long
reflect_32 (unsigned long b) reflect_32 (unsigned long b)
{ {
int i; int i;
unsigned long rw = 0L; unsigned long rw = 0L;
for (i = 0; i < 32; i++) for (i = 0; i < 32; i++){
{
if (b & 1) if (b & 1)
rw |= 1 << (31 - i); rw |= 1 << (31 - i);
b >>= 1; b >>= 1;
} }
return (rw); return (rw);
} }
unsigned long unsigned long
build_crc_table (int index) build_crc_table (int index)
{ {
int i; int i;
unsigned long rb; unsigned long rb;
rb = reflect_32 (index); rb = reflect_32 (index);
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++){
{
if (rb & 0x80000000L) if (rb & 0x80000000L)
rb = (rb << 1) ^ CRC32C_POLY; rb = (rb << 1) ^ CRC32C_POLY;
else else
rb <<= 1; rb <<= 1;
} }
return (reflect_32 (rb)); return (reflect_32 (rb));
} }
main () main ()
{ {
int i; int i;
printf ("\nGenerating CRC-32c table file <%s>\n", OUTPUT_FILE); printf ("\nGenerating CRC-32c table file <%s>\n", OUTPUT_FILE);
if ((tf = fopen (OUTPUT_FILE, "w")) == NULL) if ((tf = fopen (OUTPUT_FILE, "w")) == NULL){
{
printf ("Unable to open %s\n", OUTPUT_FILE); printf ("Unable to open %s\n", OUTPUT_FILE);
exit (1); exit (1);
} }
fprintf (tf, "#ifndef __crc32cr_table_h__\n"); fprintf (tf, "#ifndef __crc32cr_table_h__\n");
fprintf (tf, "#define __crc32cr_table_h__\n\n"); fprintf (tf, "#define __crc32cr_table_h__\n\n");
fprintf (tf, "#define CRC32C_POLY 0x%08lX\n", CRC32C_POLY); fprintf (tf, "#define CRC32C_POLY 0x%08lX\n", CRC32C_POLY);
fprintf (tf, "#define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])\n"); fprintf (tf, "#define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])\n");
fprintf (tf, "\nunsigned long crc_c[256] =\n{\n"); fprintf (tf, "\nunsigned long crc_c[256] =\n{\n");
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++){
{
fprintf (tf, "0x%08lXL, ", build_crc_table (i)); fprintf (tf, "0x%08lXL, ", build_crc_table (i));
if ((i & 3) == 3) if ((i & 3) == 3)
fprintf (tf, "\n"); fprintf (tf, "\n");
} }
fprintf (tf, "};\n\n#endif\n"); fprintf (tf, "};\n\n#endif\n");
if (fclose (tf) != 0) if (fclose (tf) != 0)
printf ("Unable to close <%s>." OUTPUT_FILE); printf ("Unable to close <%s>." OUTPUT_FILE);
else else
printf ("\nThe CRC-32c table has been written to <%s>.\n", printf ("\nThe CRC-32c table has been written to <%s>.\n",
OUTPUT_FILE); OUTPUT_FILE);
} }
/* Example of crc insertion */ /* Example of crc insertion */
#include "crc32cr.h" #include "crc32cr.h"
int unsigned long
insert_crc32(unsigned char *buffer, unsigned int length) generate_crc32c(unsigned char *buffer, unsigned int length)
{ {
SCTP_message *message;
unsigned int i; unsigned int i;
unsigned long crc32 = ~0L; unsigned long crc32 = ~0L;
unsigned long result;
unsigned char byte0,byte1,byte2,byte3;
/* check packet length */ for (i = 0; i < length; i++){
if (length > NMAX || length < NMIN) CRC32C(crc32, buffer[i]);
return -1; }
result = ~crc32;
message = (SCTP_message *) buffer; /* result now holds the negated polynomial remainder;
message->common_header.checksum = 0L; * since the table and algorithm is "reflected" [williams95].
* That is, result has the same value as if we mapped the message
* to a polyomial, computed the host-bit-order polynomial
* remainder, performed final negation, then did an end-for-end
* bit-reversal.
* Note that a 32-bit bit-reversal is identical to four inplace
* 8-bit reversals followed by an end-for-end byteswap.
for (i = 0; i < length; i++) * In other words, the bytes of each bit are in the right order,
{ * but the bytes have been byteswapped. So we now do an explicit
CRC32C(crc32, buffer[i]); * byteswap. On a little-endian machine, this byteswap and
* the final ntohl cancel out and could be elided.
*/
byte0 = result & 0xff;
byte1 = (result>>8) & 0xff;
byte2 = (result>>16) & 0xff;
byte3 = (result>>24) & 0xff;
crc32 = ((byte0 << 24) |
(byte1 << 16) |
(byte2 << 8) |
byte3);
return ( crc32 );
} }
int
insert_crc32(unsigned char *buffer, unsigned int length)
{
SCTP_message *message;
unsigned long crc32;
message = (SCTP_message *) buffer;
message->common_header.checksum = 0L;
crc32 = generate_crc32c(buffer,length);
/* and insert it into the message */ /* and insert it into the message */
message->common_header.checksum = htonl(crc32); message->common_header.checksum = htonl(crc32);
return 1; return 1;
} }
/* Example of crc validation */ /* Example of crc validation */
/* Test of 32 zeros should yield 0x756EC955 placed in network order */ /* Test of 32 zeros should yield 0x756EC955 placed in network order */
/* 13 zeros followed by byte values of 1 - 0x1f should yield /* 13 zeros followed by byte values of 1 - 0x1f should yield
/* 0x5b988D47 */ /* 0x5b988D47 */
int int
validate_crc32(unsigned char *buffer, unsigned int length) validate_crc32(unsigned char *buffer, unsigned int length)
{ {
SCTP_message *message; SCTP_message *message;
unsigned int i; unsigned int i;
unsigned long original_crc32; unsigned long original_crc32;
unsigned long crc32 = ~0L; unsigned long crc32 = ~0L;
/* check packet length */
if (length > NMAX || length < NMIN)
return -1;
/* save and zero checksum */ /* save and zero checksum */
message = (SCTP_message *) buffer; message = (SCTP_message *) buffer;
original_crc32 = ntohl(message->common_header.checksum); original_crc32 = ntohl(message->common_header.checksum);
message->common_header.checksum = 0L; message->common_header.checksum = 0L;
crc32 = generate_crc32c(buffer,length);
for (i = 0; i < length; i++)
{
CRC32C(crc32, buffer[i]);
}
return ((original_crc32 == crc32)? 1 : -1); return ((original_crc32 == crc32)? 1 : -1);
} }
Full Copyright Statement Full Copyright Statement
Copyright (C) The Internet Society (2001). All Rights Reserved. Copyright (C) The Internet Society (2001). All Rights Reserved.
This document and translations of it may be copied and furnished to This document and translations of it may be copied and furnished to
others, and derivative works that comment on or otherwise explain it or others, and derivative works that comment on or otherwise explain it or
assist in its implementation may be prepared, copied, published and assist in its implementation may be prepared, copied, published and
 End of changes. 

This html diff was produced by rfcdiff 1.23, available from http://www.levkowetz.com/ietf/tools/rfcdiff/