Changeset eb7428c1d38b3b70af04184f4f0562a50db12931
- Timestamp:
- 10/03/07 17:28:20
(2 years ago)
- Author:
- Rémi Denis-Courmont <rem@videolan.org>
- git-committer:
- Rémi Denis-Courmont <rem@videolan.org> 1173544100 +0000
- git-parent:
[fb8aac670cd81dded1ec61986934d04eb2f3bb5d]
- git-author:
- Rémi Denis-Courmont <rem@videolan.org> 1173544100 +0000
- Message:
RTP HMAC-SHA1 authentication
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| r22c5fe4 |
reb7428c |
|
| 34 | 34 | #include <gcrypt.h> |
|---|
| 35 | 35 | |
|---|
| | 36 | #define debug( ... ) (void)0 |
|---|
| | 37 | |
|---|
| 36 | 38 | /* TODO: |
|---|
| 37 | 39 | * Useful stuff: |
|---|
| … | … | |
| 53 | 55 | gcry_md_hd_t mac; |
|---|
| 54 | 56 | uint32_t salt[4]; |
|---|
| 55 | | uint8_t mac_len; |
|---|
| 56 | 57 | } srtp_proto_t; |
|---|
| 57 | 58 | |
|---|
| … | … | |
| 65 | 66 | uint32_t rtp_roc; |
|---|
| 66 | 67 | uint16_t rtp_seq; |
|---|
| | 68 | uint8_t tag_len; |
|---|
| 67 | 69 | }; |
|---|
| 68 | 70 | |
|---|
| … | … | |
| 177 | 179 | return NULL; // FIXME: replay protection not implemented yet |
|---|
| 178 | 180 | |
|---|
| 179 | | uint8_t mac_len; |
|---|
| | 181 | uint8_t tag_len; |
|---|
| 180 | 182 | int cipher = GCRY_CIPHER_AES, md = GCRY_MD_SHA1; |
|---|
| 181 | 183 | |
|---|
| 182 | 184 | if (strcmp (name, "AES_CM_128_HMAC_SHA1_80") == 0) |
|---|
| 183 | | mac_len = 80; |
|---|
| | 185 | tag_len = 10; |
|---|
| 184 | 186 | else |
|---|
| 185 | 187 | if (strcmp (name, "AES_CM_128_HMAC_SHA1_32") == 0) |
|---|
| 186 | | mac_len = 32; |
|---|
| | 188 | tag_len = 4; |
|---|
| 187 | 189 | else |
|---|
| 188 | 190 | // F8_128_HMAC_SHA1_80 is not implemented |
|---|
| … | … | |
| 199 | 201 | s->flags = flags; |
|---|
| 200 | 202 | s->kdr = kdr; |
|---|
| | 203 | s->tag_len = tag_len; |
|---|
| 201 | 204 | |
|---|
| 202 | 205 | if (proto_create (&s->rtp, cipher, md) == 0) |
|---|
| … | … | |
| 255 | 258 | } |
|---|
| 256 | 259 | |
|---|
| | 260 | #include <stdio.h> |
|---|
| 257 | 261 | |
|---|
| 258 | 262 | static int |
|---|
| … | … | |
| 264 | 268 | return -1; |
|---|
| 265 | 269 | |
|---|
| 266 | | uint8_t cipherkey[16]; |
|---|
| | 270 | uint32_t cipherkey[4], authkey[5]; |
|---|
| 267 | 271 | uint8_t label = rtcp ? SRTCP_CRYPT : SRTP_CRYPT; |
|---|
| 268 | 272 | |
|---|
| 269 | 273 | if (derive (prf, salt, r, rlen, label++, cipherkey, 16) |
|---|
| 270 | 274 | || gcry_cipher_setkey (p->cipher, cipherkey, 16) |
|---|
| 271 | | || derive (prf, salt, r, rlen, label++, NULL, 0) /* FIXME HMAC */ |
|---|
| | 275 | || derive (prf, salt, r, rlen, label++, authkey, 20) |
|---|
| | 276 | || gcry_md_setkey (p->mac, authkey, 20) |
|---|
| 272 | 277 | || derive (prf, salt, r, rlen, label++, p->salt, 14)) |
|---|
| 273 | 278 | return -1; |
|---|
| | 279 | |
|---|
| | 280 | debug (" cipher key: %08x%08x%08x%08x\n auth key: %08x%08x%08x%08x%08x\n", |
|---|
| | 281 | ntohl (cipherkey[0]), ntohl (cipherkey[1]), ntohl (cipherkey[2]), |
|---|
| | 282 | ntohl (cipherkey[3]), ntohl (authkey[0]), ntohl (authkey[1]), |
|---|
| | 283 | ntohl (authkey[2]), ntohl (authkey[3]), ntohl (authkey[4])); |
|---|
| 274 | 284 | |
|---|
| 275 | 285 | return 0; |
|---|
| … | … | |
| 389 | 399 | |
|---|
| 390 | 400 | |
|---|
| | 401 | /** Message Authentication and Integrity for RTP */ |
|---|
| | 402 | static const uint8_t * |
|---|
| | 403 | rtp_digest (gcry_md_hd_t md, const void *data, size_t len, uint32_t roc) |
|---|
| | 404 | { |
|---|
| | 405 | gcry_md_reset (md); |
|---|
| | 406 | gcry_md_write (md, data, len); |
|---|
| | 407 | gcry_md_write (md, &(uint32_t){ htonl (roc) }, 4); |
|---|
| | 408 | return gcry_md_read (md, 0); |
|---|
| | 409 | } |
|---|
| | 410 | |
|---|
| | 411 | |
|---|
| 391 | 412 | /** |
|---|
| 392 | 413 | * Encrypts/decrypts a RTP packet and updates SRTP context |
|---|
| … | … | |
| 400 | 421 | * EINVAL malformatted RTP packet |
|---|
| 401 | 422 | */ |
|---|
| 402 | | static int srtp_encrypt (srtp_session_t *s, uint8_t *buf, size_t len) |
|---|
| | 423 | static int srtp_crypt (srtp_session_t *s, uint8_t *buf, size_t len) |
|---|
| 403 | 424 | { |
|---|
| 404 | 425 | assert (s != NULL); |
|---|
| … | … | |
| 420 | 441 | |
|---|
| 421 | 442 | memcpy (&extlen, buf + offset - 2, 2); |
|---|
| 422 | | offset += htons (extlen); |
|---|
| | 443 | offset += htons (extlen); // skips RTP extension header |
|---|
| 423 | 444 | } |
|---|
| 424 | 445 | |
|---|
| … | … | |
| 466 | 487 | * |
|---|
| 467 | 488 | * @return 0 on success, in case of error: |
|---|
| 468 | | * EINVAL malformatted RTP packet |
|---|
| | 489 | * EINVAL malformatted RTP packet or internal error |
|---|
| 469 | 490 | * ENOSPC bufsize is too small (to add authentication tag) |
|---|
| 470 | 491 | */ |
|---|
| … | … | |
| 473 | 494 | { |
|---|
| 474 | 495 | size_t len = *lenp; |
|---|
| 475 | | int val = srtp_encrypt (s, buf, len); |
|---|
| | 496 | int val = srtp_crypt (s, buf, len); |
|---|
| 476 | 497 | if (val) |
|---|
| 477 | 498 | return val; |
|---|
| 478 | 499 | |
|---|
| 479 | | if (bufsize < (len + s->rtp.mac_len)) |
|---|
| | 500 | if (s->flags & SRTP_UNAUTHENTICATED) |
|---|
| | 501 | return 0; |
|---|
| | 502 | |
|---|
| | 503 | if (bufsize < (len + s->tag_len)) |
|---|
| 480 | 504 | return ENOSPC; |
|---|
| 481 | 505 | |
|---|
| 482 | | /* FIXME: HMAC and anti-replay */ |
|---|
| | 506 | const uint8_t *tag = rtp_digest (s->rtp.mac, buf, len, s->rtp_roc); |
|---|
| | 507 | memcpy (buf + len, tag, s->tag_len); |
|---|
| | 508 | *lenp = len + s->tag_len; |
|---|
| | 509 | |
|---|
| 483 | 510 | return 0; |
|---|
| 484 | 511 | } |
|---|
| … | … | |
| 486 | 513 | |
|---|
| 487 | 514 | /** |
|---|
| 488 | | * Turns a RTP packet into a SRTP packet: encrypt it, then computes |
|---|
| 489 | | * the authentication tag and appends it. |
|---|
| 490 | | * Note that you can encrypt packet in disorder. |
|---|
| 491 | | * |
|---|
| 492 | | * @param buf RTP packet to be decrypted/digested |
|---|
| | 515 | * Turns a SRTP packet into a RTP packet: authenticates the packet, |
|---|
| | 516 | * then decrypts it. |
|---|
| | 517 | * |
|---|
| | 518 | * @param buf RTP packet to be digested/decrypted |
|---|
| 493 | 519 | * @param lenp pointer to the RTP packet length on entry, |
|---|
| 494 | 520 | * set to the SRTP length on exit (undefined in case of error) |
|---|
| 495 | 521 | * |
|---|
| 496 | 522 | * @return 0 on success, in case of error: |
|---|
| 497 | | * EINVAL malformatted RTP packet |
|---|
| | 523 | * EINVAL malformatted SRTP packet |
|---|
| 498 | 524 | * EACCES authentication failed (spoofed packet or out-of-sync) |
|---|
| 499 | 525 | */ |
|---|
| … | … | |
| 502 | 528 | { |
|---|
| 503 | 529 | size_t len = *lenp; |
|---|
| 504 | | int val = srtp_encrypt (s, buf, len); |
|---|
| 505 | | if (val) |
|---|
| 506 | | return val; |
|---|
| 507 | | |
|---|
| 508 | | /* FIXME: HMAC and anti-replay */ |
|---|
| 509 | | return 0; |
|---|
| 510 | | } |
|---|
| 511 | | |
|---|
| | 530 | |
|---|
| | 531 | if (!(s->flags & SRTP_UNAUTHENTICATED)) |
|---|
| | 532 | { |
|---|
| | 533 | if (len < s->tag_len) |
|---|
| | 534 | return EINVAL; |
|---|
| | 535 | len -= s->tag_len; |
|---|
| | 536 | *lenp = len; |
|---|
| | 537 | |
|---|
| | 538 | const uint8_t *tag = rtp_digest (s->rtp.mac, buf, len, s->rtp_roc); |
|---|
| | 539 | debug (" Auth tag: %08x%08x%04x (wanted)\n" |
|---|
| | 540 | " Auth tag: %08x%08x%04x (recv'd)\n", |
|---|
| | 541 | ntohl (((uint32_t *)tag)[0]), ntohl (((uint32_t *)tag)[1]), |
|---|
| | 542 | ntohs (((uint16_t *)tag)[4]), |
|---|
| | 543 | ntohl (((uint32_t *)w)[0]), ntohl (((uint32_t *)w)[1]), |
|---|
| | 544 | ntohs (((uint16_t *)w)[4])); |
|---|
| | 545 | if (memcmp (buf + len, tag, s->tag_len)) |
|---|
| | 546 | return EACCES; |
|---|
| | 547 | } |
|---|
| | 548 | |
|---|
| | 549 | /* FIXME: anti-replay */ |
|---|
| | 550 | |
|---|
| | 551 | return srtp_crypt (s, buf, len); |
|---|
| | 552 | } |
|---|
| | 553 | |
|---|