1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <webrtc/SCTPHandler.h>
18
19 #include "Utils.h"
20
21 #include <https/SafeCallbackable.h>
22 #include <https/Support.h>
23
24 #include <android-base/logging.h>
25
SCTPHandler(std::shared_ptr<RunLoop> runLoop,std::shared_ptr<DTLS> dtls)26 SCTPHandler::SCTPHandler(
27 std::shared_ptr<RunLoop> runLoop,
28 std::shared_ptr<DTLS> dtls)
29 : mRunLoop(runLoop),
30 mDTLS(dtls),
31 mInitiateTag(0),
32 mSendingTSN(0),
33 mSentGreeting(false) {
34 }
35
run()36 void SCTPHandler::run() {
37 }
38
inject(uint8_t * data,size_t size)39 int SCTPHandler::inject(uint8_t *data, size_t size) {
40 LOG(INFO)
41 << "Received SCTP datagram of size " << size << ":";
42
43 hexdump(data, size);
44
45 if (size < 12) {
46 // Need at least the common header.
47 return -EINVAL;
48 }
49
50 auto srcPort = U16_AT(&data[0]);
51 auto dstPort = U16_AT(&data[2]);
52
53 if (dstPort != 5000) {
54 return -EINVAL;
55 }
56
57 auto checkSumIn = U32_AT(&data[8]);
58 SET_U32(&data[8], 0x00000000);
59 auto checkSum = crc32c(data, size);
60
61 if (checkSumIn != checkSum) {
62 LOG(WARNING)
63 << "SCTPHandler::inject checksum invalid."
64 << " (in: " << StringPrintf("0x%08x", checkSumIn) << ", "
65 << "computed: " << StringPrintf("0x%08x", checkSum) << ")";
66
67 return -EINVAL;
68 }
69
70 bool firstChunk = true;
71 size_t offset = 12;
72 while (offset < size) {
73 if (offset + 4 > size) {
74 return -EINVAL;
75 }
76
77 size_t chunkLength = U16_AT(&data[offset + 2]);
78
79 if (offset + chunkLength > size) {
80 return -EINVAL;
81 }
82
83 size_t paddedChunkLength = chunkLength;
84 size_t pad = chunkLength % 4;
85 if (pad) {
86 pad = 4 - pad;
87 paddedChunkLength += pad;
88 }
89
90 bool lastChunk =
91 (offset + chunkLength == size)
92 || (offset + paddedChunkLength == size);
93
94 auto err = processChunk(
95 srcPort,
96 &data[offset],
97 chunkLength,
98 firstChunk,
99 lastChunk);
100
101 if (err) {
102 return err;
103 }
104
105 firstChunk = false;
106
107 offset += chunkLength;
108
109 if (offset == size) {
110 break;
111 }
112
113 if (offset + pad > size) {
114 return -EINVAL;
115 }
116
117 offset += pad;
118 }
119
120 return 0;
121 }
122
processChunk(uint16_t srcPort,const uint8_t * data,size_t size,bool firstChunk,bool lastChunk)123 int SCTPHandler::processChunk(
124 uint16_t srcPort,
125 const uint8_t *data,
126 size_t size,
127 bool firstChunk,
128 bool lastChunk) {
129 static constexpr uint8_t DATA = 0;
130 static constexpr uint8_t INIT = 1;
131 static constexpr uint8_t INIT_ACK = 2;
132 static constexpr uint8_t SACK = 3;
133 static constexpr uint8_t HEARTBEAT = 4;
134 static constexpr uint8_t HEARTBEAT_ACK = 5;
135 static constexpr uint8_t COOKIE_ECHO = 10;
136 static constexpr uint8_t COOKIE_ACK = 11;
137 static constexpr uint8_t SHUTDOWN_COMPLETE = 14;
138
139 static constexpr uint64_t kCookie = 0xDABBAD00DEADBAADull;
140
141 auto chunkType = data[0];
142 if ((!firstChunk || !lastChunk)
143 && (chunkType == INIT
144 || chunkType == INIT_ACK
145 || chunkType == SHUTDOWN_COMPLETE)) {
146 // These chunks must be by themselves, no other chunks must be part
147 // of the same datagram.
148
149 return -EINVAL;
150 }
151
152 switch (chunkType) {
153 case INIT:
154 {
155 if (size < 20) {
156 return -EINVAL;
157 }
158
159 mInitiateTag = U32_AT(&data[4]);
160
161 uint8_t out[12 + 24 + sizeof(kCookie)];
162 SET_U16(&out[0], 5000);
163 SET_U16(&out[2], srcPort);
164 SET_U32(&out[4], mInitiateTag);
165 SET_U32(&out[8], 0x00000000); // Checksum: to be filled in below.
166
167 size_t offset = 12;
168 out[offset++] = INIT_ACK;
169 out[offset++] = 0x00;
170
171 SET_U16(&out[offset], sizeof(out) - 12);
172 offset += 2;
173
174 SET_U32(&out[offset], 0xb0b0cafe); // initiate tag
175 offset += 4;
176
177 SET_U32(&out[offset], 0x00020000); // a_rwnd
178 offset += 4;
179
180 SET_U16(&out[offset], 1); // Number of Outbound Streams
181 offset += 2;
182
183 SET_U16(&out[offset], 1); // Number of Inbound Streams
184 offset += 2;
185
186 mSendingTSN = 0x12345678;
187
188 SET_U32(&out[offset], mSendingTSN); // Initial TSN
189 offset += 4;
190
191 SET_U16(&out[offset], 0x0007); // STATE_COOKIE
192 offset += 2;
193
194 static_assert((sizeof(kCookie) % 4) == 0);
195
196 SET_U16(&out[offset], 4 + sizeof(kCookie));
197 offset += 2;
198
199 memcpy(&out[offset], &kCookie, sizeof(kCookie));
200 offset += sizeof(kCookie);
201
202 CHECK_EQ(offset, sizeof(out));
203
204 SET_U32(&out[8], crc32c(out, sizeof(out)));
205
206 LOG(INFO) << "Sending SCTP INIT_ACK:";
207 hexdump(out, sizeof(out));
208
209 mDTLS->writeApplicationData(out, sizeof(out));
210 break;
211 }
212
213 case COOKIE_ECHO:
214 {
215 if (size != (4 + sizeof(kCookie))) {
216 return -EINVAL;
217 }
218
219 if (memcmp(&data[4], &kCookie, sizeof(kCookie))) {
220 return -EINVAL;
221 }
222
223 uint8_t out[12 + 4];
224 SET_U16(&out[0], 5000);
225 SET_U16(&out[2], srcPort);
226 SET_U32(&out[4], mInitiateTag);
227 SET_U32(&out[8], 0x00000000); // Checksum: to be filled in below.
228
229 size_t offset = 12;
230 out[offset++] = COOKIE_ACK;
231 out[offset++] = 0x00;
232 SET_U16(&out[offset], sizeof(out) - 12);
233 offset += 2;
234
235 CHECK_EQ(offset, sizeof(out));
236
237 SET_U32(&out[8], crc32c(out, sizeof(out)));
238
239 LOG(INFO) << "Sending SCTP COOKIE_ACK:";
240 hexdump(out, sizeof(out));
241
242 mDTLS->writeApplicationData(out, sizeof(out));
243 break;
244 }
245
246 case DATA:
247 {
248 if (size < 17) {
249 // Minimal size (16 bytes header + 1 byte payload), empty
250 // payloads are prohibited.
251 return -EINVAL;
252 }
253
254 auto TSN = U32_AT(&data[4]);
255
256 uint8_t out[12 + 16];
257 SET_U16(&out[0], 5000);
258 SET_U16(&out[2], srcPort);
259 SET_U32(&out[4], mInitiateTag);
260 SET_U32(&out[8], 0x00000000); // Checksum: to be filled in below.
261
262 size_t offset = 12;
263 out[offset++] = SACK;
264 out[offset++] = 0x00;
265
266 SET_U16(&out[offset], sizeof(out) - 12);
267 offset += 2;
268
269 SET_U32(&out[offset], TSN);
270 offset += 4;
271
272 SET_U32(&out[offset], 0x00020000); // a_rwnd
273 offset += 4;
274
275 SET_U16(&out[offset], 0); // Number of Gap Ack Blocks
276 offset += 2;
277
278 SET_U16(&out[offset], 0); // Number of Duplicate TSNs
279 offset += 2;
280
281 CHECK_EQ(offset, sizeof(out));
282
283 SET_U32(&out[8], crc32c(out, sizeof(out)));
284
285 LOG(INFO) << "Sending SCTP SACK:";
286 hexdump(out, sizeof(out));
287
288 mDTLS->writeApplicationData(out, sizeof(out));
289
290 if (!mSentGreeting) {
291 mRunLoop->postWithDelay(
292 std::chrono::seconds(1),
293 makeSafeCallback(
294 this,
295 &SCTPHandler::onSendGreeting,
296 srcPort,
297 (size_t)0 /* index */));
298
299 mSentGreeting = true;
300 }
301 break;
302 }
303
304 case HEARTBEAT:
305 {
306 if (size < 8) {
307 return -EINVAL;
308 }
309
310 if (U16_AT(&data[4]) != 1 /* Heartbeat Info Type */
311 || size != (U16_AT(&data[6]) + 4)) {
312 return -EINVAL;
313 }
314
315 size_t pad = size % 4;
316 if (pad) {
317 pad = 4 - pad;
318 }
319
320 std::vector<uint8_t> outVec(12 + size + pad);
321
322 uint8_t *out = outVec.data();
323 SET_U16(&out[0], 5000);
324 SET_U16(&out[2], srcPort);
325 SET_U32(&out[4], mInitiateTag);
326 SET_U32(&out[8], 0x00000000); // Checksum: to be filled in below.
327
328 size_t offset = 12;
329 out[offset++] = HEARTBEAT_ACK;
330 out[offset++] = 0x00;
331
332 SET_U16(&out[offset], outVec.size() - 12 - pad);
333 offset += 2;
334
335 memcpy(&out[offset], &data[4], size - 4);
336 offset += size - 4;
337
338 memset(&out[offset], 0x00, pad);
339 offset += pad;
340
341 CHECK_EQ(offset, outVec.size());
342
343 SET_U32(&out[8], crc32c(out, outVec.size()));
344
345 LOG(INFO) << "Sending SCTP HEARTBEAT_ACK:";
346 hexdump(out, outVec.size());
347
348 mDTLS->writeApplicationData(out, outVec.size());
349 break;
350 }
351
352 default:
353 break;
354 }
355
356 return 0;
357 }
358
onSendGreeting(uint16_t srcPort,size_t index)359 void SCTPHandler::onSendGreeting(uint16_t srcPort, size_t index) {
360 static constexpr uint8_t DATA = 0;
361 // static constexpr uint8_t PPID_WEBRTC_CONTROL = 0x32;
362 static constexpr uint8_t PPID_WEBRTC_STRING = 0x33;
363
364 std::string message;
365 if (index == 0) {
366 message = "Howdy! How's y'all doin?";
367 } else {
368 message = "But wait... There's more!";
369 }
370
371 size_t pad = message.size() % 4;
372 if (pad) {
373 pad = 4 - pad;
374 }
375
376 std::vector<uint8_t> outVec(12 + 16 + message.size() + pad);
377
378 uint8_t *out = outVec.data();
379 SET_U16(&out[0], 5000);
380 SET_U16(&out[2], srcPort);
381 SET_U32(&out[4], mInitiateTag);
382 SET_U32(&out[8], 0x00000000); // Checksum: to be filled in below.
383
384 size_t offset = 12;
385 out[offset++] = DATA;
386 out[offset++] = 0x03; // both Beginning and End of user message.
387
388 SET_U16(&out[offset], outVec.size() - 12 - pad);
389 offset += 2;
390
391 SET_U32(&out[offset], mSendingTSN); // TSN
392 offset += 4;
393
394 ++mSendingTSN;
395
396 SET_U16(&out[offset], 0); // Stream Identifier
397 offset += 2;
398
399 SET_U16(&out[offset], index); // Stream Sequence Number
400 offset += 2;
401
402 SET_U32(&out[offset], PPID_WEBRTC_STRING); // Payload Protocol Identifier
403 offset += 4;
404
405 // https://tools.ietf.org/html/draft-ietf-rtcweb-data-protocol-08#section-5.1
406 // https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-11#section-6.5
407
408 // DATA(payload protocol=0x32 (50, WebRTC Control), sequence 0)
409 // 03 00 00 00 00 00 00 00 ........
410 // 00 0c 00 00 64 61 74 61 ....data
411 // 2d 63 68 61 6e 6e 65 6c -channel
412
413 // DATA(payload protocol=0x33 (51, WebRTC String), sequence 1)
414 // "Hello, world!"
415
416 memcpy(&out[offset], message.data(), message.size());
417 offset += message.size();
418
419 memset(&out[offset], 0x00, pad);
420 offset += pad;
421
422 CHECK_EQ(offset, outVec.size());
423
424 SET_U32(&out[8], crc32c(out, outVec.size()));
425
426 LOG(INFO) << "Sending SCTP DATA:";
427 hexdump(out, outVec.size());
428
429 mDTLS->writeApplicationData(out, outVec.size());
430
431 if (index == 0) {
432 mRunLoop->postWithDelay(
433 std::chrono::seconds(3),
434 makeSafeCallback(
435 this,
436 &SCTPHandler::onSendGreeting,
437 srcPort,
438 (size_t)1 /* index */));
439 }
440 }
441
442 static const uint32_t crc_c[256] = {
443 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
444 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
445 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
446 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
447 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
448 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
449 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
450 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
451 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
452 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
453 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
454 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
455 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
456 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
457 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
458 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
459 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
460 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
461 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
462 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
463 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
464 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
465 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
466 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
467 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
468 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
469 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
470 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
471 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
472 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
473 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
474 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
475 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
476 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
477 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
478 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
479 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
480 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
481 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
482 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
483 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
484 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
485 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
486 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
487 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
488 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
489 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
490 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
491 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
492 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
493 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
494 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
495 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
496 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
497 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
498 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
499 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
500 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
501 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
502 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
503 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
504 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
505 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
506 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351,
507 };
508
509 #define CRC32C_POLY 0x1EDC6F41
510 #define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
511
swap32(uint32_t x)512 static uint32_t swap32(uint32_t x) {
513 return (x >> 24)
514 | (((x >> 16) & 0xff) << 8)
515 | (((x >> 8) & 0xff) << 16)
516 | ((x & 0xff) << 24);
517 }
518
519 // static
crc32c(const uint8_t * data,size_t size)520 uint32_t SCTPHandler::crc32c(const uint8_t *data, size_t size) {
521 uint32_t crc32 = ~(uint32_t)0;
522
523 for (size_t i = 0; i < size; ++i) {
524 CRC32C(crc32, data[i]);
525 }
526
527 return ~swap32(crc32);
528 }
529
530