Changeset 7bdd4ba5b1c58233b656c75e4abd9017f7ef02ee
- Timestamp:
- 03/11/07 19:53:53
(1 year ago)
- Author:
- Rémi Denis-Courmont <rem@videolan.org>
- git-committer:
- Rémi Denis-Courmont <rem@videolan.org> 1173639233 +0000
- git-parent:
[a65a62289c22ad0c988d833eb25e3a616b524aba]
- git-author:
- Rémi Denis-Courmont <rem@videolan.org> 1173639233 +0000
- Message:
Untested support for RFC4771:
Integrity Transform Carrying Roll-Over Counter for SRTP
Once debugged, it should provide a simple way to synchronize live
(multicast...) secure streams.
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| r9c7f833 |
r7bdd4ba |
|
| 18 | 18 | */ |
|---|
| 19 | 19 | |
|---|
| | 20 | /* TODO: |
|---|
| | 21 | * Useless stuff (because nothing depends on it): |
|---|
| | 22 | * - non-nul key derivation rate |
|---|
| | 23 | * - MKI payload |
|---|
| | 24 | */ |
|---|
| | 25 | |
|---|
| 20 | 26 | #ifdef HAVE_CONFIG_H |
|---|
| 21 | 27 | # include <config.h> |
|---|
| … | … | |
| 34 | 40 | #include <gcrypt.h> |
|---|
| 35 | 41 | |
|---|
| | 42 | #ifdef WIN32 |
|---|
| | 43 | # include <winsock2.h> |
|---|
| | 44 | #else |
|---|
| | 45 | # include <netinet/in.h> |
|---|
| | 46 | # include <pthread.h> |
|---|
| | 47 | GCRY_THREAD_OPTION_PTHREAD_IMPL; |
|---|
| | 48 | #endif |
|---|
| | 49 | |
|---|
| 36 | 50 | #define debug( ... ) (void)0 |
|---|
| 37 | | |
|---|
| 38 | | /* TODO: |
|---|
| 39 | | * Useful stuff: |
|---|
| 40 | | * - ROC profile thingy (multicast really needs this) |
|---|
| 41 | | * |
|---|
| 42 | | * Useless stuff (because nothing depends on it): |
|---|
| 43 | | * - non-nul key derivation rate |
|---|
| 44 | | * - MKI payload |
|---|
| 45 | | */ |
|---|
| 46 | 51 | |
|---|
| 47 | 52 | typedef struct srtp_proto_t |
|---|
| … | … | |
| 77 | 82 | |
|---|
| 78 | 83 | |
|---|
| 79 | | #ifdef WIN32 |
|---|
| 80 | | # include <winsock2.h> |
|---|
| 81 | | #else |
|---|
| 82 | | # include <netinet/in.h> |
|---|
| 83 | | # include <pthread.h> |
|---|
| 84 | | GCRY_THREAD_OPTION_PTHREAD_IMPL; |
|---|
| 85 | | #endif |
|---|
| | 84 | static inline unsigned rcc_mode (const srtp_session_t *s) |
|---|
| | 85 | { |
|---|
| | 86 | return (s->flags >> 4) & 3; |
|---|
| | 87 | } |
|---|
| 86 | 88 | |
|---|
| 87 | 89 | static bool libgcrypt_usable = false; |
|---|
| … | … | |
| 217 | 219 | s->flags = flags; |
|---|
| 218 | 220 | s->tag_len = tag_len; |
|---|
| | 221 | s->rtp_rcc = 1; /* Default RCC rate */ |
|---|
| | 222 | if (rcc_mode (s)) |
|---|
| | 223 | { |
|---|
| | 224 | if (tag_len < 4) |
|---|
| | 225 | goto error; |
|---|
| | 226 | } |
|---|
| 219 | 227 | |
|---|
| 220 | 228 | if (proto_create (&s->rtp, cipher, md) == 0) |
|---|
| … | … | |
| 225 | 233 | } |
|---|
| 226 | 234 | |
|---|
| | 235 | error: |
|---|
| 227 | 236 | free (s); |
|---|
| 228 | 237 | return NULL; |
|---|
| … | … | |
| 441 | 450 | /** Message Authentication and Integrity for RTP */ |
|---|
| 442 | 451 | static const uint8_t * |
|---|
| 443 | | rtp_digest (srtp_session_t *s, const uint8_t *data, size_t len) |
|---|
| | 452 | rtp_digest (srtp_session_t *s, const uint8_t *data, size_t len, |
|---|
| | 453 | uint32_t roc) |
|---|
| 444 | 454 | { |
|---|
| 445 | 455 | const gcry_md_hd_t md = s->rtp.mac; |
|---|
| 446 | | uint32_t roc = htonl (srtp_compute_roc (s, rtp_seq (data))); |
|---|
| 447 | 456 | |
|---|
| 448 | 457 | gcry_md_reset (md); |
|---|
| 449 | 458 | gcry_md_write (md, data, len); |
|---|
| 450 | | gcry_md_write (md, &roc, 4); |
|---|
| | 459 | gcry_md_write (md, &(uint32_t){ htonl (roc) }, 4); |
|---|
| 451 | 460 | return gcry_md_read (md, 0); |
|---|
| 452 | 461 | } |
|---|
| … | … | |
| 533 | 542 | * @param buf RTP packet to be encrypted/digested |
|---|
| 534 | 543 | * @param lenp pointer to the RTP packet length on entry, |
|---|
| 535 | | * set to the SRTP length on exit (undefined in case of error) |
|---|
| | 544 | * set to the SRTP length on exit (undefined on non-ENOSPC error) |
|---|
| 536 | 545 | * @param bufsize size (bytes) of the packet buffer |
|---|
| 537 | 546 | * |
|---|
| 538 | 547 | * @return 0 on success, in case of error: |
|---|
| 539 | 548 | * EINVAL malformatted RTP packet or internal error |
|---|
| 540 | | * ENOSPC bufsize is too small (to add authentication tag) |
|---|
| | 549 | * ENOSPC bufsize is too small to add authentication tag |
|---|
| | 550 | * (<lenp> will hold the required byte size) |
|---|
| 541 | 551 | * EACCES packet would trigger a replay error on receiver |
|---|
| 542 | 552 | */ |
|---|
| … | … | |
| 551 | 561 | if (!(s->flags & SRTP_UNAUTHENTICATED)) |
|---|
| 552 | 562 | { |
|---|
| 553 | | if (bufsize < (len + s->tag_len)) |
|---|
| | 563 | size_t tag_len = s->tag_len; |
|---|
| | 564 | *lenp = len + tag_len; |
|---|
| | 565 | if (bufsize < (len + tag_len)) |
|---|
| 554 | 566 | return ENOSPC; |
|---|
| 555 | 567 | |
|---|
| 556 | | const uint8_t *tag = rtp_digest (s, buf, len); |
|---|
| 557 | | memcpy (buf + len, tag, s->tag_len); |
|---|
| 558 | | *lenp = len + s->tag_len; |
|---|
| | 568 | uint32_t roc = srtp_compute_roc (s, rtp_seq (buf)); |
|---|
| | 569 | const uint8_t *tag = rtp_digest (s, buf, len, roc); |
|---|
| | 570 | if (rcc_mode (s)) |
|---|
| | 571 | { |
|---|
| | 572 | assert (s->rtp_rcc); |
|---|
| | 573 | if ((rtp_seq (buf) % s->rtp_rcc) == 0) |
|---|
| | 574 | { |
|---|
| | 575 | memcpy (buf + len, &(uint32_t){ htonl (s->rtp_roc) }, 4); |
|---|
| | 576 | len += 4; |
|---|
| | 577 | if (rcc_mode (s) == 3) |
|---|
| | 578 | tag_len = 0; |
|---|
| | 579 | else |
|---|
| | 580 | tag_len -= 4; |
|---|
| | 581 | } |
|---|
| | 582 | else |
|---|
| | 583 | { |
|---|
| | 584 | if (rcc_mode (s) & 1) |
|---|
| | 585 | tag_len = 0; |
|---|
| | 586 | } |
|---|
| | 587 | } |
|---|
| | 588 | memcpy (buf + len, tag, tag_len); |
|---|
| 559 | 589 | } |
|---|
| 560 | 590 | |
|---|
| … | … | |
| 579 | 609 | { |
|---|
| 580 | 610 | size_t len = *lenp; |
|---|
| | 611 | if (len < 12u) |
|---|
| | 612 | return EINVAL; |
|---|
| 581 | 613 | |
|---|
| 582 | 614 | if (!(s->flags & SRTP_UNAUTHENTICATED)) |
|---|
| 583 | 615 | { |
|---|
| 584 | | if (len < (12u + s->tag_len)) |
|---|
| | 616 | size_t tag_len = s->tag_len, roc_len = 0; |
|---|
| | 617 | if (rcc_mode (s)) |
|---|
| | 618 | { |
|---|
| | 619 | if ((rtp_seq (buf) % s->rtp_rcc) == 0) |
|---|
| | 620 | { |
|---|
| | 621 | roc_len = 4; |
|---|
| | 622 | if (rcc_mode (s) == 3) |
|---|
| | 623 | tag_len = 0; |
|---|
| | 624 | else |
|---|
| | 625 | tag_len -= 4; |
|---|
| | 626 | } |
|---|
| | 627 | else |
|---|
| | 628 | { |
|---|
| | 629 | if (rcc_mode (s) & 1) |
|---|
| | 630 | tag_len = 0; // RCC mode 1 or 3: no auth |
|---|
| | 631 | } |
|---|
| | 632 | } |
|---|
| | 633 | |
|---|
| | 634 | if (len < (12u + roc_len + tag_len)) |
|---|
| 585 | 635 | return EINVAL; |
|---|
| 586 | | len -= s->tag_len; |
|---|
| 587 | | |
|---|
| 588 | | const uint8_t *tag = rtp_digest (s, buf, len); |
|---|
| 589 | | if (memcmp (buf + len, tag, s->tag_len)) |
|---|
| | 636 | len -= roc_len + tag_len; |
|---|
| | 637 | |
|---|
| | 638 | uint32_t roc = srtp_compute_roc (s, rtp_seq (buf)), rcc; |
|---|
| | 639 | if (roc_len) |
|---|
| | 640 | { |
|---|
| | 641 | assert (roc_len == 4); |
|---|
| | 642 | memcpy (&rcc, buf + len, 4); |
|---|
| | 643 | rcc = ntohl (rcc); |
|---|
| | 644 | } |
|---|
| | 645 | else |
|---|
| | 646 | rcc = roc; |
|---|
| | 647 | |
|---|
| | 648 | const uint8_t *tag = rtp_digest (s, buf, len, rcc); |
|---|
| | 649 | if (memcmp (buf + len + roc_len, tag, s->tag_len)) |
|---|
| 590 | 650 | return EACCES; |
|---|
| 591 | 651 | |
|---|
| | 652 | if (roc_len) |
|---|
| | 653 | { |
|---|
| | 654 | /* Authenticated packet carried a Roll-Over-Counter */ |
|---|
| | 655 | s->rtp_roc += rcc - roc; |
|---|
| | 656 | assert (srtp_compute_roc (s, rtp_seq (buf)) == rcc); |
|---|
| | 657 | } |
|---|
| 592 | 658 | *lenp = len; |
|---|
| 593 | 659 | } |
|---|