1 /* $Id$
2 * --------------------------------------------------------------------------
3 *
4 * //===== //===== ===//=== //===// // // //===//
5 * // // // // // // // // //
6 * //====// // // //===// // // //===<<
7 * // // // // // // // //
8 * ======// //===== // // //===== // //===//
9 *
10 * -------------- An SCTP implementation according to RFC 4960 --------------
11 *
12 * Copyright (C) 2000 by Siemens AG, Munich, Germany.
13 * Copyright (C) 2001-2004 Andreas Jungmaier
14 * Copyright (C) 2004-2019 Thomas Dreibholz
15 *
16 * Acknowledgements:
17 * Realized in co-operation between Siemens AG and the University of
18 * Duisburg-Essen, Institute for Experimental Mathematics, Computer
19 * Networking Technology group.
20 * This work was partially funded by the Bundesministerium fuer Bildung und
21 * Forschung (BMBF) of the Federal Republic of Germany
22 * (Förderkennzeichen 01AK045).
23 * The authors alone are responsible for the contents.
24 *
25 * This library is free software: you can redistribute it and/or modify it
26 * under the terms of the GNU Lesser General Public License as published by
27 * the Free Software Foundation, either version 2.1 of the License, or
28 * (at your option) any later version.
29 *
30 * This library is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
34 *
35 * You should have received a copy of the GNU Lesser General Public License
36 * along with this program. If not, see <http://www.gnu.org/licenses/>.
37 *
38 * Contact: sctp-discussion@sctp.de
39 * dreibh@iem.uni-due.de
40 * tuexen@fh-muenster.de
41 * andreas.jungmaier@web.de
42 */
43
44 #include "auxiliary.h"
45 #include "globals.h"
46 #include "sctp.h"
47 #include "adaptation.h"
48
49 #include <stdio.h>
50
51 #define BASE 65521L /* largest prime smaller than 65536 */
52 #define NMAX 5552
53 #define NMIN 16
54
55 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
56
57 #define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
58 #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
59 #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
60 #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
61 #define DO16(buf) DO8(buf,0); DO8(buf,8);
62
63 /* Example of the crc table file */
64
65 #define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
66
67 uint32_t crc_c[256] =
68 {
69 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
70 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
71 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
72 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
73 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
74 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
75 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
76 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
77 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
78 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
79 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
80 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
81 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
82 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
83 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
84 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
85 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
86 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
87 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
88 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
89 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
90 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
91 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
92 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
93 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
94 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
95 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
96 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
97 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
98 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
99 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
100 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
101 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
102 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
103 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
104 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
105 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
106 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
107 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
108 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
109 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
110 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
111 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
112 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
113 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
114 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
115 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
116 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
117 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
118 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
119 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
120 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
121 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
122 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
123 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
124 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
125 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
126 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
127 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
128 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
129 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
130 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
131 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
132 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351,
133 };
134
135 static int insert_adler32(unsigned char *buffer, int length);
136 static int insert_crc32(unsigned char *buffer, int length);
137 static int validate_adler32(unsigned char *header_start, int length);
138 static int validate_crc32(unsigned char *buffer, int length);
139
140
141 static int (*insert_checksum) (unsigned char* buffer, int length) = insert_crc32;
142 static int (*validate_checksum) (unsigned char* buffer, int length) = validate_crc32;
143
144
145 static uint32_t sctp_adler32(uint32_t adler, const unsigned char *buf, unsigned int len);
146
147
set_checksum_algorithm(int algorithm)148 int set_checksum_algorithm(int algorithm){
149 if (algorithm == SCTP_CHECKSUM_ALGORITHM_CRC32C) {
150 insert_checksum = &insert_crc32;
151 validate_checksum = &validate_crc32;
152 return SCTP_SUCCESS;
153 } else if (algorithm == SCTP_CHECKSUM_ALGORITHM_ADLER32) {
154 insert_checksum = &insert_adler32;
155 validate_checksum = &validate_adler32;
156 return SCTP_SUCCESS;
157 } else
158 return -1;
159 }
160
161
key_operation(int operation_code)162 unsigned char* key_operation(int operation_code)
163 {
164 static unsigned char *secret_key = NULL;
165 uint32_t count = 0, tmp;
166
167 if (operation_code == KEY_READ) return secret_key;
168 else if (operation_code == KEY_INIT) {
169 if (secret_key != NULL) {
170 error_log(ERROR_MAJOR, "tried to init secret key, but key already created !");
171 return secret_key;
172 }
173 secret_key = (unsigned char*)malloc(SECRET_KEYSIZE);
174 while (count < SECRET_KEYSIZE){
175 /* if you care for security, you need to use a cryptographically secure PRNG */
176 tmp = adl_random();
177 memcpy(&secret_key[count], &tmp, sizeof(uint32_t));
178 count += sizeof(uint32_t);
179 }
180 } else {
181 error_log(ERROR_MAJOR, "unknown key operation code !");
182 return NULL;
183 }
184 return secret_key;
185 }
186
aux_insert_checksum(unsigned char * buffer,int length)187 int aux_insert_checksum(unsigned char *buffer, int length)
188 {
189 return ((*insert_checksum)(buffer,length));
190 }
191
192
insert_adler32(unsigned char * buffer,int length)193 static int insert_adler32(unsigned char *buffer, int length)
194 {
195 SCTP_message *message;
196 uint32_t a32;
197 /* save crc value from PDU */
198 if (length > NMAX || length < NMIN)
199 return -1;
200 message = (SCTP_message *) buffer;
201 message->common_header.checksum = htonl(0L);
202
203 /* now compute the thingie */
204 /* FIXME : sanity checks for size etc. */
205 a32 = sctp_adler32(1, buffer, length);
206
207 /* and insert it into the message */
208 message->common_header.checksum = htonl(a32);
209
210 event_logi(VERBOSE, "DEBUG Validation : Inserting adler32 == %x", a32);
211
212 return 1;
213 }
214
generate_crc32c(unsigned char * buffer,int length)215 static uint32_t generate_crc32c(unsigned char *buffer, int length)
216 {
217 unsigned char byte0, byte1, byte2, byte3, swap;
218 uint32_t crc32 = ~0L;
219 int i;
220
221 for (i = 0; i < length; i++)
222 {
223 CRC32C(crc32, buffer[i]);
224 }
225 crc32 =~ crc32;
226 /* do the swap */
227 byte0 = (unsigned char) crc32 & 0xff;
228 byte1 = (unsigned char) (crc32>>8) & 0xff;
229 byte2 = (unsigned char) (crc32>>16) & 0xff;
230 byte3 = (unsigned char) (crc32>>24) & 0xff;
231 swap = byte0; byte0 = byte3; byte3 = swap;
232 swap = byte1; byte1 = byte2; byte2 = swap;
233 crc32 = ((byte3 << 24)|(byte2 << 16)|(byte1 << 8)| byte0);
234
235 return crc32;
236
237 }
238
insert_crc32(unsigned char * buffer,int length)239 static int insert_crc32(unsigned char *buffer, int length)
240 {
241 SCTP_message *message;
242 uint32_t crc32c;
243
244 /* check packet length */
245 if (length > NMAX || length < NMIN)
246 return -1;
247
248 message = (SCTP_message *) buffer;
249 message->common_header.checksum = 0L;
250 crc32c = generate_crc32c(buffer, length);
251 /* and insert it into the message */
252 message->common_header.checksum = htonl(crc32c);
253
254 return 1;
255 }
256
257
validate_size(unsigned char * header_start,int length)258 int validate_size(unsigned char *header_start, int length)
259 {
260 if ((length % 4) != 0L)
261 return 0;
262 if (length > NMAX || length < NMIN)
263 return 0;
264 return 1;
265 }
266
267
268
validate_adler32(unsigned char * header_start,int length)269 static int validate_adler32(unsigned char *header_start, int length)
270 {
271 SCTP_message *message;
272 uint32_t old_crc32;
273 uint32_t a32;
274
275 /* save crc value from PDU */
276 message = (SCTP_message *) header_start;
277 old_crc32 = ntohl(message->common_header.checksum);
278
279 event_logi(VVERBOSE, "DEBUG Validation : old adler == %x", old_crc32);
280
281 message->common_header.checksum = htonl(0L);
282
283 /* now compute the thingie */
284 a32 = sctp_adler32(1, header_start, length);
285
286 event_logi(VVERBOSE, "DEBUG Validation : my adler32 == %x", a32);
287 if (a32 == old_crc32) return 1;
288 return 0;
289 }
290
validate_crc32(unsigned char * buffer,int length)291 static int validate_crc32(unsigned char *buffer, int length)
292 {
293 SCTP_message *message;
294 uint32_t original_crc32;
295 uint32_t crc32 = ~0;
296
297 /* check packet length */
298
299 /* save and zero checksum */
300 message = (SCTP_message *) buffer;
301 original_crc32 = ntohl(message->common_header.checksum);
302 event_logi(VVERBOSE, "DEBUG Validation : old crc32c == %x", original_crc32);
303 message->common_header.checksum = 0;
304 crc32 = generate_crc32c(buffer, length);
305 event_logi(VVERBOSE, "DEBUG Validation : my crc32c == %x", crc32);
306
307 return ((original_crc32 == crc32)? 1 : 0);
308 }
309
310
311
validate_datagram(unsigned char * buffer,int length)312 int validate_datagram(unsigned char *buffer, int length)
313 {
314 /* sanity check for size (min,max, multiple of 32 bits) */
315 if (!validate_size(buffer, length))
316 return 0;
317 if (!(*validate_checksum)(buffer, length))
318 return 0;
319 /* FIXME : validation is not yet complete */
320 return 1;
321 }
322
323 /**
324 * adler32.c -- compute the Adler-32 checksum of a data stream
325 * Copyright (C) 1995-1996 Mark Adler
326 * For conditions of distribution and use, see copyright notice in zlib.h
327 * available, e.g. from http://www.cdrom.com/pub/infozip/zlib/
328 */
sctp_adler32(uint32_t adler,const unsigned char * buf,unsigned int len)329 static uint32_t sctp_adler32(uint32_t adler, const unsigned char *buf, unsigned int len)
330 {
331 uint32_t s1 = adler & 0xffff;
332 uint32_t s2 = (adler >> 16) & 0xffff;
333 int k;
334
335 if (buf == NULL)
336 return 1L;
337
338 while (len > 0) {
339 k = len < NMAX ? len : NMAX;
340 len -= k;
341 while (k >= 16) {
342 DO16(buf);
343 buf += 16;
344 k -= 16;
345 }
346 if (k != 0)
347 do {
348 s1 += *buf++;
349 s2 += s1;
350 }
351 while (--k);
352 s1 %= BASE;
353 s2 %= BASE;
354 }
355 return (s2 << 16) | s1;
356 }
357