Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-1.1
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-1.1
Commits
e5c071ab
Commit
e5c071ab
authored
Mar 10, 2007
by
Rémi Denis-Courmont
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
SRTCP support
parent
62e11e95
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
155 additions
and
40 deletions
+155
-40
libs/srtp/srtp.c
libs/srtp/srtp.c
+149
-37
libs/srtp/srtp.h
libs/srtp/srtp.h
+5
-2
libs/srtp/test-aes.c
libs/srtp/test-aes.c
+1
-1
No files found.
libs/srtp/srtp.c
View file @
e5c071ab
...
...
@@ -37,13 +37,9 @@
/* TODO:
* Useful stuff:
* - ROC profil thingy (multicast really needs this)
* - ROC profil
e
thingy (multicast really needs this)
* - replay protection
*
* Requirements for conformance:
* - suites with NULL cipher
* - SRTCP
*
* Useless stuff (because nothing depends on it):
* - non-nul key derivation rate
* - MKI payload
...
...
@@ -158,7 +154,10 @@ static int proto_create (srtp_proto_t *p, int gcipher, int gmd)
/**
* Allocates a Secure RTP session.
* Allocates a Secure RTP one-way session.
* The same session cannot be used both ways because this would confuse
* internal cryptographic counters; it is however of course feasible to open
* multiple simultaneous sessions with the same master key.
*
* @param name cipher-suite name
* @param kdr key derivation rate
...
...
@@ -257,7 +256,6 @@ derive (gcry_cipher_hd_t prf, const void *salt,
return
0
;
}
#include <stdio.h>
static
int
proto_derive
(
srtp_proto_t
*
p
,
gcry_cipher_hd_t
prf
,
...
...
@@ -267,21 +265,16 @@ proto_derive (srtp_proto_t *p, gcry_cipher_hd_t prf,
if
(
saltlen
!=
14
)
return
-
1
;
uint
32_t
cipherkey
[
4
],
authkey
[
5
];
uint
8_t
keybuf
[
20
];
uint8_t
label
=
rtcp
?
SRTCP_CRYPT
:
SRTP_CRYPT
;
if
(
derive
(
prf
,
salt
,
r
,
rlen
,
label
++
,
cipherkey
,
16
)
||
gcry_cipher_setkey
(
p
->
cipher
,
cipherkey
,
16
)
||
derive
(
prf
,
salt
,
r
,
rlen
,
label
++
,
authkey
,
20
)
||
gcry_md_setkey
(
p
->
mac
,
authkey
,
20
)
||
derive
(
prf
,
salt
,
r
,
rlen
,
label
++
,
p
->
salt
,
14
))
if
(
derive
(
prf
,
salt
,
r
,
rlen
,
label
++
,
keybuf
,
16
)
||
gcry_cipher_setkey
(
p
->
cipher
,
keybuf
,
16
)
||
derive
(
prf
,
salt
,
r
,
rlen
,
label
++
,
keybuf
,
20
)
||
gcry_md_setkey
(
p
->
mac
,
keybuf
,
20
)
||
derive
(
prf
,
salt
,
r
,
rlen
,
label
,
p
->
salt
,
14
))
return
-
1
;
debug
(
" cipher key: %08x%08x%08x%08x
\n
auth key: %08x%08x%08x%08x%08x
\n
"
,
ntohl
(
cipherkey
[
0
]),
ntohl
(
cipherkey
[
1
]),
ntohl
(
cipherkey
[
2
]),
ntohl
(
cipherkey
[
3
]),
ntohl
(
authkey
[
0
]),
ntohl
(
authkey
[
1
]),
ntohl
(
authkey
[
2
]),
ntohl
(
authkey
[
3
]),
ntohl
(
authkey
[
4
]));
return
0
;
}
...
...
@@ -329,7 +322,6 @@ srtp_derive (srtp_session_t *s, const void *key, size_t keylen,
}
/**
* Sets (or resets) the master key and master salt for a SRTP session.
* This must be done at least once before using rtp_send(), rtp_recv(),
...
...
@@ -350,7 +342,7 @@ srtp_setkey (srtp_session_t *s, const void *key, size_t keylen,
/** AES-CM encryption/decryption (ctr length = 16 bytes) */
static
int
en
crypt
(
gcry_cipher_hd_t
hd
,
uint32_t
*
ctr
,
uint8_t
*
data
,
size_t
len
)
ctr_
crypt
(
gcry_cipher_hd_t
hd
,
uint32_t
*
ctr
,
uint8_t
*
data
,
size_t
len
)
{
const
size_t
ctrlen
=
16
;
while
(
len
>=
ctrlen
)
...
...
@@ -382,9 +374,9 @@ encrypt (gcry_cipher_hd_t hd, uint32_t *ctr, uint8_t *data, size_t len)
/** AES-CM for RTP (salt = 14 bytes + 2 nul bytes) */
static
in
line
in
t
rtp_
en
crypt
(
gcry_cipher_hd_t
hd
,
uint32_t
ssrc
,
uint32_t
roc
,
uint16_t
seq
,
const
uint32_t
*
salt
,
uint8_t
*
data
,
size_t
len
)
static
int
rtp_crypt
(
gcry_cipher_hd_t
hd
,
uint32_t
ssrc
,
uint32_t
roc
,
uint16_t
seq
,
const
uint32_t
*
salt
,
uint8_t
*
data
,
size_t
len
)
{
/* Determines cryptographic counter (IV) */
uint32_t
counter
[
4
];
...
...
@@ -394,7 +386,7 @@ rtp_encrypt (gcry_cipher_hd_t hd, uint32_t ssrc, uint32_t roc, uint16_t seq,
counter
[
3
]
=
salt
[
3
]
^
htonl
(
seq
<<
16
);
/* Encryption */
return
en
crypt
(
hd
,
counter
,
data
,
len
);
return
ctr_
crypt
(
hd
,
counter
,
data
,
len
);
}
...
...
@@ -414,7 +406,7 @@ rtp_digest (gcry_md_hd_t md, const void *data, size_t len, uint32_t roc)
* (CTR block cypher mode of operation has identical encryption and
* decryption function).
*
* @param buf RTP packet to be en
crypted/diges
ted
* @param buf RTP packet to be en
-/decryp
ted
* @param len RTP packet length
*
* @return 0 on success, in case of error:
...
...
@@ -467,8 +459,8 @@ static int srtp_crypt (srtp_session_t *s, uint8_t *buf, size_t len)
if
(
s
->
flags
&
SRTP_UNENCRYPTED
)
return
0
;
if
(
rtp_
en
crypt
(
s
->
rtp
.
cipher
,
ssrc
,
s
->
rtp_roc
,
seq
,
s
->
rtp
.
salt
,
buf
+
offset
,
len
-
offset
))
if
(
rtp_crypt
(
s
->
rtp
.
cipher
,
ssrc
,
s
->
rtp_roc
,
seq
,
s
->
rtp
.
salt
,
buf
+
offset
,
len
-
offset
))
return
EINVAL
;
return
0
;
...
...
@@ -516,8 +508,8 @@ srtp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t bufsize)
* then decrypts it.
*
* @param buf RTP packet to be digested/decrypted
* @param lenp pointer to the RTP packet length on entry,
* set to the
S
RTP length on exit (undefined in case of error)
* @param lenp pointer to the
S
RTP packet length on entry,
* set to the RTP length on exit (undefined in case of error)
*
* @return 0 on success, in case of error:
* EINVAL malformatted SRTP packet
...
...
@@ -527,26 +519,146 @@ int
srtp_recv
(
srtp_session_t
*
s
,
uint8_t
*
buf
,
size_t
*
lenp
)
{
size_t
len
=
*
lenp
;
/* FIXME: anti-replay */
if
(
!
(
s
->
flags
&
SRTP_UNAUTHENTICATED
))
{
if
(
len
<
s
->
tag_len
)
return
EINVAL
;
len
-=
s
->
tag_len
;
*
lenp
=
len
;
const
uint8_t
*
tag
=
rtp_digest
(
s
->
rtp
.
mac
,
buf
,
len
,
s
->
rtp_roc
);
debug
(
" Auth tag: %08x%08x%04x (wanted)
\n
"
" Auth tag: %08x%08x%04x (recv'd)
\n
"
,
ntohl
(((
uint32_t
*
)
tag
)[
0
]),
ntohl
(((
uint32_t
*
)
tag
)[
1
]),
ntohs
(((
uint16_t
*
)
tag
)[
4
]),
ntohl
(((
uint32_t
*
)
w
)[
0
]),
ntohl
(((
uint32_t
*
)
w
)[
1
]),
ntohs
(((
uint16_t
*
)
w
)[
4
]));
if
(
memcmp
(
buf
+
len
,
tag
,
s
->
tag_len
))
return
EACCES
;
*
lenp
=
len
;
}
/* FIXME: anti-replay */
return
srtp_crypt
(
s
,
buf
,
len
);
}
/** AES-CM for RTCP (salt = 14 bytes + 2 nul bytes) */
static
int
rtcp_crypt
(
gcry_cipher_hd_t
hd
,
uint32_t
ssrc
,
uint32_t
index
,
const
uint32_t
*
salt
,
uint8_t
*
data
,
size_t
len
)
{
return
rtp_crypt
(
hd
,
ssrc
,
index
>>
16
,
index
&
0xffff
,
salt
,
data
,
len
);
}
/** Message Authentication and Integrity for RTCP */
static
const
uint8_t
*
rtcp_digest
(
gcry_md_hd_t
md
,
const
void
*
data
,
size_t
len
)
{
gcry_md_reset
(
md
);
gcry_md_write
(
md
,
data
,
len
);
return
gcry_md_read
(
md
,
0
);
}
/**
* Encrypts/decrypts a RTCP packet and updates SRTCP context
* (CTR block cypher mode of operation has identical encryption and
* decryption function).
*
* @param buf RTCP packet to be en-/decrypted
* @param len RTCP packet length
*
* @return 0 on success, in case of error:
* EINVAL malformatted RTCP packet
*/
static
int
srtcp_crypt
(
srtp_session_t
*
s
,
uint8_t
*
buf
,
size_t
len
)
{
assert
(
s
!=
NULL
);
/* 8-bytes unencrypted header, and 4-bytes unencrypted footer */
if
((
len
<
12
)
||
((
buf
[
0
]
>>
6
)
!=
2
))
return
EINVAL
;
uint32_t
index
=
s
->
rtcp_index
++
;
if
(
index
==
0x7fffffff
)
s
->
rtcp_index
=
0
;
/* 31-bit wrap */
if
(
s
->
flags
&
SRTCP_UNENCRYPTED
)
return
0
;
uint32_t
ssrc
;
memcpy
(
&
ssrc
,
buf
+
4
,
4
);
if
(
rtcp_crypt
(
s
->
rtcp
.
cipher
,
ssrc
,
index
,
s
->
rtp
.
salt
,
buf
+
8
,
len
-
8
))
return
EINVAL
;
return
0
;
}
/**
* Turns a RTCP packet into a SRTCP packet: encrypt it, then computes
* the authentication tag and appends it.
*
* @param buf RTCP packet to be encrypted/digested
* @param lenp pointer to the RTCP packet length on entry,
* set to the SRTCP length on exit (undefined in case of error)
* @param bufsize size (bytes) of the packet buffer
*
* @return 0 on success, in case of error:
* EINVAL malformatted RTCP packet or internal error
* ENOSPC bufsize is too small (to add index and authentication tag)
*/
int
srtcp_send
(
srtp_session_t
*
s
,
uint8_t
*
buf
,
size_t
*
lenp
,
size_t
bufsize
)
{
size_t
len
=
*
lenp
;
if
(
bufsize
<
(
len
+
4
+
s
->
tag_len
))
return
ENOSPC
;
uint32_t
index
=
s
->
rtcp_index
;
if
((
s
->
flags
&
SRTCP_UNENCRYPTED
)
==
0
)
index
|=
0x80000000
;
/* Set Encrypted bit */
memcpy
(
buf
+
len
,
&
(
uint32_t
){
htonl
(
index
)
},
4
);
int
val
=
srtcp_crypt
(
s
,
buf
,
len
);
if
(
val
)
return
val
;
len
+=
4
;
/* Digest SRTCP index too */
const
uint8_t
*
tag
=
rtcp_digest
(
s
->
rtp
.
mac
,
buf
,
len
);
memcpy
(
buf
+
len
,
tag
,
s
->
tag_len
);
*
lenp
=
len
+
s
->
tag_len
;
return
0
;
}
/**
* Turns a SRTCP packet into a RTCP packet: authenticates the packet,
* then decrypts it.
*
* @param buf RTCP packet to be digested/decrypted
* @param lenp pointer to the SRTCP packet length on entry,
* set to the RTCP length on exit (undefined in case of error)
*
* @return 0 on success, in case of error:
* EINVAL malformatted SRTCP packet
* EACCES authentication failed (spoofed packet or out-of-sync)
*/
int
srtcp_recv
(
srtp_session_t
*
s
,
uint8_t
*
buf
,
size_t
*
lenp
)
{
size_t
len
=
*
lenp
;
/* FIXME: anti-replay ?? */
if
(
len
<
(
4u
+
s
->
tag_len
))
return
EINVAL
;
len
-=
s
->
tag_len
;
const
uint8_t
*
tag
=
rtcp_digest
(
s
->
rtp
.
mac
,
buf
,
len
);
if
(
memcmp
(
buf
+
len
,
tag
,
s
->
tag_len
))
return
EACCES
;
len
-=
4
;
/* Remove SRTCP index befor decryption */
*
lenp
=
len
;
return
srtp_crypt
(
s
,
buf
,
len
);
}
...
...
libs/srtp/srtp.h
View file @
e5c071ab
...
...
@@ -39,11 +39,14 @@ extern "C" {
srtp_session_t
*
srtp_create
(
const
char
*
name
,
unsigned
flags
,
unsigned
kdr
,
uint16_t
winsize
);
void
srtp_destroy
(
srtp_session_t
*
s
);
int
srtp_setkey
(
srtp_session_t
*
s
,
const
void
*
key
,
size_t
keylen
,
const
void
*
salt
,
size_t
saltlen
);
int
srtp_send
(
srtp_session_t
*
s
,
uint8_t
*
buf
,
size_t
*
lenp
,
size_t
maxsize
);
int
srtp_recv
(
srtp_session_t
*
s
,
uint8_t
*
buf
,
size_t
*
lenp
);
int
srtcp_send
(
srtp_session_t
*
s
,
uint8_t
*
buf
,
size_t
*
lenp
,
size_t
maxsiz
);
int
srtcp_recv
(
srtp_session_t
*
s
,
uint8_t
*
buf
,
size_t
*
lenp
);
int
srtp_setkey
(
srtp_session_t
*
s
,
const
void
*
key
,
size_t
keylen
,
const
void
*
salt
,
size_t
saltlen
);
# ifdef __cplusplus
}
# endif
...
...
libs/srtp/test-aes.c
View file @
e5c071ab
...
...
@@ -117,7 +117,7 @@ static void test_keystream (void)
if
(
gcry_cipher_setkey
(
hd
,
key
,
sizeof
(
key
)))
fatal
(
"Cipher key error"
);
if
(
rtp_
en
crypt
(
hd
,
0
,
0
,
0
,
salt
,
buf
,
0xff020
))
if
(
rtp_crypt
(
hd
,
0
,
0
,
0
,
salt
,
buf
,
0xff020
))
fatal
(
"Encryption failure"
);
gcry_cipher_close
(
hd
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment