Toggle navigation
Toggle navigation
此项目
正在载入...
Sign in
胡斌
/
srs
转到一个项目
Toggle navigation
项目
群组
代码片段
帮助
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
winlin
2014-03-20 09:41:13 +0800
Browse Files
Options
Browse Files
Download
Plain Diff
Commit
c63ad488939f19a3aab48a9cfd0a356a97f82ae8
c63ad488
2 parents
822143b5
a2c50750
Merge branch 'master' of github.com:winlinvip/simple-rtmp-server
隐藏空白字符变更
内嵌
并排对比
正在显示
11 个修改的文件
包含
1103 行增加
和
953 行删除
README.md
trunk/conf/full.conf
trunk/conf/srs.conf
trunk/src/app/srs_app_encoder.cpp
trunk/src/core/srs_core.hpp
trunk/src/rtmp/srs_protocol_handshake.cpp
trunk/src/rtmp/srs_protocol_handshake.hpp
trunk/src/utest/srs_utest.cpp
trunk/src/utest/srs_utest.hpp
trunk/src/utest/srs_utest_handshake.cpp
trunk/src/utest/srs_utest_handshake.hpp
README.md
查看文件 @
c63ad48
...
...
@@ -167,6 +167,8 @@ See also: [Performance Test Guide](https://github.com/winlinvip/simple-rtmp-serv
*
nginx v1.5.0: 139524 lines
<br/>
### History
*
v1.0, 2014-03-19, add vn/an for FFMPEG to drop video/audio for radio stream.
*
v1.0, 2014-03-19, refine handshake, client support coplex handshake, add utest.
*
v1.0, 2014-03-16, support ARM(
[
debian armhf, v7cpu
](
https://github.com/winlinvip/simple-rtmp-server/wiki/SrsLinuxArm
)
) with rtmp/ssl/hls/librtmp.
*
v1.0, 2014-03-12, finish utest for amf0 codec.
*
v1.0, 2014-03-06, add gperftools for mem leak detect, mem/cpu profile.
...
...
trunk/conf/full.conf
100644 → 100755
查看文件 @
c63ad48
...
...
@@ -291,6 +291,25 @@ vhost audio.transcode.vhost.com {
}
}
}
# disable video, transcode/copy audio.
# for example, publish pure audio stream.
vhost
vn
.
transcode
.
vhost
.
com
{
transcode
{
enabled
on
;
ffmpeg
./
objs
/
ffmpeg
/
bin
/
ffmpeg
;
engine
vn
{
enabled
on
;
vcodec
vn
;
acodec
libaacplus
;
abitrate
45
;
asample_rate
44100
;
achannels
2
;
aparams
{
}
output
rtmp
://
127
.
0
.
0
.
1
:[
port
]/[
app
]?
vhost
=[
vhost
]/[
stream
]
_
[
engine
];
}
}
}
# ffmpeg-copy(forward implements by ffmpeg).
# copy the video and audio to a new stream.
vhost
copy
.
transcode
.
vhost
.
com
{
...
...
@@ -333,6 +352,7 @@ vhost all.transcode.vhost.com {
# video encoder name. can be:
# libx264: use h.264(libx264) video encoder.
# copy: donot encoder the video stream, copy it.
# vn: disable video output.
vcodec
libx264
;
# video bitrate, in kbps
vbitrate
1500
;
...
...
@@ -364,6 +384,7 @@ vhost all.transcode.vhost.com {
# audio encoder name. can be:
# libaacplus: use aac(libaacplus) audio encoder.
# copy: donot encoder the audio stream, copy it.
# an: disable audio output.
acodec
libaacplus
;
# audio bitrate, in kbps. [16, 72] for libaacplus.
abitrate
70
;
...
...
trunk/conf/srs.conf
100644 → 100755
查看文件 @
c63ad48
trunk/src/app/srs_app_encoder.cpp
查看文件 @
c63ad48
...
...
@@ -42,6 +42,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifdef SRS_FFMPEG
#define SRS_ENCODER_COPY "copy"
#define SRS_ENCODER_NO_VIDEO "vn"
#define SRS_ENCODER_NO_AUDIO "an"
#define SRS_ENCODER_VCODEC "libx264"
#define SRS_ENCODER_ACODEC "libaacplus"
...
...
@@ -138,7 +140,13 @@ int SrsFFMPEG::initialize(SrsRequest* req, SrsConfDirective* engine)
}
_transcoded_url
.
push_back
(
output
);
if
(
vcodec
!=
SRS_ENCODER_COPY
)
{
if
(
vcodec
==
SRS_ENCODER_NO_VIDEO
&&
acodec
==
SRS_ENCODER_NO_AUDIO
)
{
ret
=
ERROR_ENCODER_VCODEC
;
srs_warn
(
"video and audio disabled. ret=%d"
,
ret
);
return
ret
;
}
if
(
vcodec
!=
SRS_ENCODER_COPY
&&
vcodec
!=
SRS_ENCODER_NO_VIDEO
)
{
if
(
vcodec
!=
SRS_ENCODER_VCODEC
)
{
ret
=
ERROR_ENCODER_VCODEC
;
srs_error
(
"invalid vcodec, must be %s, actual %s, ret=%d"
,
...
...
@@ -182,7 +190,7 @@ int SrsFFMPEG::initialize(SrsRequest* req, SrsConfDirective* engine)
}
}
if
(
acodec
!=
SRS_ENCODER_COPY
)
{
if
(
acodec
!=
SRS_ENCODER_COPY
&&
acodec
!=
SRS_ENCODER_NO_AUDIO
)
{
if
(
acodec
!=
SRS_ENCODER_ACODEC
)
{
ret
=
ERROR_ENCODER_ACODEC
;
srs_error
(
"invalid acodec, must be %s, actual %s, ret=%d"
,
...
...
@@ -254,11 +262,15 @@ int SrsFFMPEG::start()
}
// video specified.
params
.
push_back
(
"-vcodec"
);
params
.
push_back
(
vcodec
);
if
(
vcodec
!=
SRS_ENCODER_NO_VIDEO
)
{
params
.
push_back
(
"-vcodec"
);
params
.
push_back
(
vcodec
);
}
else
{
params
.
push_back
(
"-vn"
);
}
// the codec params is disabled when copy
if
(
vcodec
!=
SRS_ENCODER_COPY
)
{
if
(
vcodec
!=
SRS_ENCODER_COPY
&&
vcodec
!=
SRS_ENCODER_NO_VIDEO
)
{
params
.
push_back
(
"-b:v"
);
snprintf
(
tmp
,
sizeof
(
tmp
),
"%d"
,
vbitrate
*
1000
);
params
.
push_back
(
tmp
);
...
...
@@ -299,11 +311,15 @@ int SrsFFMPEG::start()
}
// audio specified.
params
.
push_back
(
"-acodec"
);
params
.
push_back
(
acodec
);
if
(
acodec
!=
SRS_ENCODER_NO_AUDIO
)
{
params
.
push_back
(
"-acodec"
);
params
.
push_back
(
acodec
);
}
else
{
params
.
push_back
(
"-an"
);
}
// the codec params is disabled when copy
if
(
acodec
!=
SRS_ENCODER_COPY
)
{
if
(
acodec
!=
SRS_ENCODER_COPY
&&
acodec
!=
SRS_ENCODER_NO_AUDIO
)
{
params
.
push_back
(
"-b:a"
);
snprintf
(
tmp
,
sizeof
(
tmp
),
"%d"
,
abitrate
*
1000
);
params
.
push_back
(
tmp
);
...
...
trunk/src/core/srs_core.hpp
查看文件 @
c63ad48
...
...
@@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// current release version
#define VERSION_MAJOR "0"
#define VERSION_MINOR "9"
#define VERSION_REVISION "2
1
"
#define VERSION_REVISION "2
2
"
#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
// server info.
#define RTMP_SIG_SRS_KEY "srs"
...
...
trunk/src/rtmp/srs_protocol_handshake.cpp
查看文件 @
c63ad48
...
...
@@ -32,924 +32,944 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <srs_protocol_utility.hpp>
#include <srs_protocol_rtmp.hpp>
using
namespace
srs
;
#ifdef SRS_SSL
// 68bytes FMS key which is used to sign the sever packet.
u_int8_t
srs
::
SrsGenuineFMSKey
[]
=
{
0x47
,
0x65
,
0x6e
,
0x75
,
0x69
,
0x6e
,
0x65
,
0x20
,
0x41
,
0x64
,
0x6f
,
0x62
,
0x65
,
0x20
,
0x46
,
0x6c
,
0x61
,
0x73
,
0x68
,
0x20
,
0x4d
,
0x65
,
0x64
,
0x69
,
0x61
,
0x20
,
0x53
,
0x65
,
0x72
,
0x76
,
0x65
,
0x72
,
0x20
,
0x30
,
0x30
,
0x31
,
// Genuine Adobe Flash Media Server 001
0xf0
,
0xee
,
0xc2
,
0x4a
,
0x80
,
0x68
,
0xbe
,
0xe8
,
0x2e
,
0x00
,
0xd0
,
0xd1
,
0x02
,
0x9e
,
0x7e
,
0x57
,
0x6e
,
0xec
,
0x5d
,
0x2d
,
0x29
,
0x80
,
0x6f
,
0xab
,
0x93
,
0xb8
,
0xe6
,
0x36
,
0xcf
,
0xeb
,
0x31
,
0xae
};
// 68
// 62bytes FP key which is used to sign the client packet.
u_int8_t
srs
::
SrsGenuineFPKey
[]
=
{
0x47
,
0x65
,
0x6E
,
0x75
,
0x69
,
0x6E
,
0x65
,
0x20
,
0x41
,
0x64
,
0x6F
,
0x62
,
0x65
,
0x20
,
0x46
,
0x6C
,
0x61
,
0x73
,
0x68
,
0x20
,
0x50
,
0x6C
,
0x61
,
0x79
,
0x65
,
0x72
,
0x20
,
0x30
,
0x30
,
0x31
,
// Genuine Adobe Flash Player 001
0xF0
,
0xEE
,
0xC2
,
0x4A
,
0x80
,
0x68
,
0xBE
,
0xE8
,
0x2E
,
0x00
,
0xD0
,
0xD1
,
0x02
,
0x9E
,
0x7E
,
0x57
,
0x6E
,
0xEC
,
0x5D
,
0x2D
,
0x29
,
0x80
,
0x6F
,
0xAB
,
0x93
,
0xB8
,
0xE6
,
0x36
,
0xCF
,
0xEB
,
0x31
,
0xAE
};
// 62
using
namespace
srs
;
// for openssl_HMACsha256
#include <openssl/evp.h>
#include <openssl/hmac.h>
int
srs
::
openssl_HMACsha256
(
const
void
*
data
,
int
data_size
,
const
void
*
key
,
int
key_size
,
void
*
digest
)
{
HMAC_CTX
ctx
;
HMAC_CTX_init
(
&
ctx
);
HMAC_Init_ex
(
&
ctx
,
(
unsigned
char
*
)
key
,
key_size
,
EVP_sha256
(),
NULL
);
HMAC_Update
(
&
ctx
,
(
unsigned
char
*
)
data
,
data_size
);
unsigned
int
digest_size
;
HMAC_Final
(
&
ctx
,
(
unsigned
char
*
)
digest
,
&
digest_size
);
HMAC_CTX_cleanup
(
&
ctx
);
if
(
digest_size
!=
32
)
{
return
ERROR_OpenSslSha256DigestSize
;
}
return
ERROR_SUCCESS
;
}
// for __openssl_generate_key
#include <openssl/dh.h>
#define RFC2409_PRIME_1024 \
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \
"FFFFFFFFFFFFFFFF"
int
__openssl_generate_key
(
u_int8_t
*&
_private_key
,
u_int8_t
*&
_public_key
,
int32_t
&
size
,
DH
*&
pdh
,
int32_t
&
bits_count
,
u_int8_t
*&
shared_key
,
int32_t
&
shared_key_length
,
BIGNUM
*&
peer_public_key
){
int
ret
=
ERROR_SUCCESS
;
//1. Create the DH
if
((
pdh
=
DH_new
())
==
NULL
)
{
ret
=
ERROR_OpenSslCreateDH
;
return
ret
;
}
//2. Create his internal p and g
if
((
pdh
->
p
=
BN_new
())
==
NULL
)
{
ret
=
ERROR_OpenSslCreateP
;
return
ret
;
}
if
((
pdh
->
g
=
BN_new
())
==
NULL
)
{
ret
=
ERROR_OpenSslCreateG
;
return
ret
;
}
//3. initialize p, g and key length
if
(
BN_hex2bn
(
&
pdh
->
p
,
RFC2409_PRIME_1024
)
==
0
)
{
ret
=
ERROR_OpenSslParseP1024
;
return
ret
;
}
if
(
BN_set_word
(
pdh
->
g
,
2
)
!=
1
)
{
ret
=
ERROR_OpenSslSetG
;
return
ret
;
}
//4. Set the key length
pdh
->
length
=
bits_count
;
//5. Generate private and public key
if
(
DH_generate_key
(
pdh
)
!=
1
)
{
ret
=
ERROR_OpenSslGenerateDHKeys
;
return
ret
;
}
// CreateSharedKey
if
(
pdh
==
NULL
)
{
ret
=
ERROR_OpenSslGenerateDHKeys
;
return
ret
;
}
if
(
shared_key_length
!=
0
||
shared_key
!=
NULL
)
{
ret
=
ERROR_OpenSslShareKeyComputed
;
return
ret
;
}
shared_key_length
=
DH_size
(
pdh
);
if
(
shared_key_length
<=
0
||
shared_key_length
>
1024
)
{
ret
=
ERROR_OpenSslGetSharedKeySize
;
return
ret
;
}
shared_key
=
new
u_int8_t
[
shared_key_length
];
memset
(
shared_key
,
0
,
shared_key_length
);
peer_public_key
=
BN_bin2bn
(
_private_key
,
size
,
0
);
if
(
peer_public_key
==
NULL
)
{
ret
=
ERROR_OpenSslGetPeerPublicKey
;
return
ret
;
}
if
(
DH_compute_key
(
shared_key
,
peer_public_key
,
pdh
)
==
-
1
)
{
ret
=
ERROR_OpenSslComputeSharedKey
;
return
ret
;
}
// CopyPublicKey
if
(
pdh
==
NULL
)
{
ret
=
ERROR_OpenSslComputeSharedKey
;
return
ret
;
}
int32_t
keySize
=
BN_num_bytes
(
pdh
->
pub_key
);
if
((
keySize
<=
0
)
||
(
size
<=
0
)
||
(
keySize
>
size
))
{
//("CopyPublicKey failed due to either invalid DH state or invalid call"); return ret;
ret
=
ERROR_OpenSslInvalidDHState
;
return
ret
;
}
if
(
BN_bn2bin
(
pdh
->
pub_key
,
_public_key
)
!=
keySize
)
{
//("Unable to copy key"); return ret;
ret
=
ERROR_OpenSslCopyKey
;
return
ret
;
}
return
ret
;
}
int
openssl_generate_key
(
char
*
_private_key
,
char
*
_public_key
,
int32_t
size
)
{
int
ret
=
ERROR_SUCCESS
;
// Initialize
DH
*
pdh
=
NULL
;
int32_t
bits_count
=
1024
;
u_int8_t
*
shared_key
=
NULL
;
int32_t
shared_key_length
=
0
;
BIGNUM
*
peer_public_key
=
NULL
;
ret
=
__openssl_generate_key
(
(
u_int8_t
*&
)
_private_key
,
(
u_int8_t
*&
)
_public_key
,
size
,
pdh
,
bits_count
,
shared_key
,
shared_key_length
,
peer_public_key
);
if
(
pdh
!=
NULL
)
{
if
(
pdh
->
p
!=
NULL
)
{
BN_free
(
pdh
->
p
);
pdh
->
p
=
NULL
;
}
if
(
pdh
->
g
!=
NULL
)
{
BN_free
(
pdh
->
g
);
pdh
->
g
=
NULL
;
}
DH_free
(
pdh
);
pdh
=
NULL
;
}
if
(
shared_key
!=
NULL
)
{
delete
[]
shared_key
;
shared_key
=
NULL
;
}
if
(
peer_public_key
!=
NULL
)
{
BN_free
(
peer_public_key
);
peer_public_key
=
NULL
;
}
return
ret
;
}
// calc the offset of key,
// the key->offset cannot be used as the offset of key.
int
srs_key_block_get_offset
(
key_block
*
key
)
{
int
max_offset_size
=
764
-
128
-
4
;
int
offset
=
0
;
u_int8_t
*
pp
=
(
u_int8_t
*
)
&
key
->
offset
;
offset
+=
*
pp
++
;
offset
+=
*
pp
++
;
offset
+=
*
pp
++
;
offset
+=
*
pp
++
;
return
offset
%
max_offset_size
;
}
// create new key block data.
// if created, user must free it by srs_key_block_free
void
srs_key_block_init
(
key_block
*
key
)
namespace
srs
{
key
->
offset
=
(
int32_t
)
rand
();
key
->
random0
=
NULL
;
key
->
random1
=
NULL
;
int
offset
=
srs_key_block_get_offset
(
key
);
srs_assert
(
offset
>=
0
);
// 68bytes FMS key which is used to sign the sever packet.
u_int8_t
SrsGenuineFMSKey
[]
=
{
0x47
,
0x65
,
0x6e
,
0x75
,
0x69
,
0x6e
,
0x65
,
0x20
,
0x41
,
0x64
,
0x6f
,
0x62
,
0x65
,
0x20
,
0x46
,
0x6c
,
0x61
,
0x73
,
0x68
,
0x20
,
0x4d
,
0x65
,
0x64
,
0x69
,
0x61
,
0x20
,
0x53
,
0x65
,
0x72
,
0x76
,
0x65
,
0x72
,
0x20
,
0x30
,
0x30
,
0x31
,
// Genuine Adobe Flash Media Server 001
0xf0
,
0xee
,
0xc2
,
0x4a
,
0x80
,
0x68
,
0xbe
,
0xe8
,
0x2e
,
0x00
,
0xd0
,
0xd1
,
0x02
,
0x9e
,
0x7e
,
0x57
,
0x6e
,
0xec
,
0x5d
,
0x2d
,
0x29
,
0x80
,
0x6f
,
0xab
,
0x93
,
0xb8
,
0xe6
,
0x36
,
0xcf
,
0xeb
,
0x31
,
0xae
};
// 68
// 62bytes FP key which is used to sign the client packet.
u_int8_t
SrsGenuineFPKey
[]
=
{
0x47
,
0x65
,
0x6E
,
0x75
,
0x69
,
0x6E
,
0x65
,
0x20
,
0x41
,
0x64
,
0x6F
,
0x62
,
0x65
,
0x20
,
0x46
,
0x6C
,
0x61
,
0x73
,
0x68
,
0x20
,
0x50
,
0x6C
,
0x61
,
0x79
,
0x65
,
0x72
,
0x20
,
0x30
,
0x30
,
0x31
,
// Genuine Adobe Flash Player 001
0xF0
,
0xEE
,
0xC2
,
0x4A
,
0x80
,
0x68
,
0xBE
,
0xE8
,
0x2E
,
0x00
,
0xD0
,
0xD1
,
0x02
,
0x9E
,
0x7E
,
0x57
,
0x6E
,
0xEC
,
0x5D
,
0x2D
,
0x29
,
0x80
,
0x6F
,
0xAB
,
0x93
,
0xB8
,
0xE6
,
0x36
,
0xCF
,
0xEB
,
0x31
,
0xAE
};
// 62
int
openssl_HMACsha256
(
const
void
*
data
,
int
data_size
,
const
void
*
key
,
int
key_size
,
void
*
digest
)
{
HMAC_CTX
ctx
;
HMAC_CTX_init
(
&
ctx
);
HMAC_Init_ex
(
&
ctx
,
(
unsigned
char
*
)
key
,
key_size
,
EVP_sha256
(),
NULL
);
HMAC_Update
(
&
ctx
,
(
unsigned
char
*
)
data
,
data_size
);
key
->
random0_size
=
offset
;
if
(
key
->
random0_size
>
0
)
{
key
->
random0
=
new
char
[
key
->
random0_size
];
srs_random_generate
(
key
->
random0
,
key
->
random0_size
);
}
unsigned
int
digest_size
;
HMAC_Final
(
&
ctx
,
(
unsigned
char
*
)
digest
,
&
digest_size
);
HMAC_CTX_cleanup
(
&
ctx
);
if
(
digest_size
!=
32
)
{
return
ERROR_OpenSslSha256DigestSize
;
}
return
ERROR_SUCCESS
;
}
#define RFC2409_PRIME_1024 \
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \
"FFFFFFFFFFFFFFFF"
int
__openssl_generate_key
(
u_int8_t
*
_private_key
,
u_int8_t
*
_public_key
,
int32_t
&
size
,
DH
*&
pdh
,
int32_t
&
bits_count
,
u_int8_t
*&
shared_key
,
int32_t
&
shared_key_length
,
BIGNUM
*&
peer_public_key
){
int
ret
=
ERROR_SUCCESS
;
//1. Create the DH
if
((
pdh
=
DH_new
())
==
NULL
)
{
ret
=
ERROR_OpenSslCreateDH
;
return
ret
;
}
srs_random_generate
(
key
->
key
,
sizeof
(
key
->
key
));
//2. Create his internal p and g
if
((
pdh
->
p
=
BN_new
())
==
NULL
)
{
ret
=
ERROR_OpenSslCreateP
;
return
ret
;
}
if
((
pdh
->
g
=
BN_new
())
==
NULL
)
{
ret
=
ERROR_OpenSslCreateG
;
return
ret
;
}
key
->
random1_size
=
764
-
offset
-
128
-
4
;
if
(
key
->
random1_size
>
0
)
{
key
->
random1
=
new
char
[
key
->
random1_size
];
srs_random_generate
(
key
->
random1
,
key
->
random1_size
);
}
}
// parse key block from c1s1.
// if created, user must free it by srs_key_block_free
// @c1s1_key_bytes the key start bytes, maybe c1s1 or c1s1+764
int
srs_key_block_parse
(
key_block
*
key
,
char
*
c1s1_key_bytes
)
{
int
ret
=
ERROR_SUCCESS
;
char
*
pp
=
c1s1_key_bytes
+
764
;
//3. initialize p, g and key length
if
(
BN_hex2bn
(
&
pdh
->
p
,
RFC2409_PRIME_1024
)
==
0
)
{
ret
=
ERROR_OpenSslParseP1024
;
return
ret
;
}
if
(
BN_set_word
(
pdh
->
g
,
2
)
!=
1
)
{
ret
=
ERROR_OpenSslSetG
;
return
ret
;
}
pp
-=
sizeof
(
int32_t
);
key
->
offset
=
*
(
int32_t
*
)
pp
;
//4. Set the key length
pdh
->
length
=
bits_count
;
key
->
random0
=
NULL
;
key
->
random1
=
NULL
;
//5. Generate private and public key
if
(
DH_generate_key
(
pdh
)
!=
1
)
{
ret
=
ERROR_OpenSslGenerateDHKeys
;
return
ret
;
}
int
offset
=
srs_key_block_get_offset
(
key
);
srs_assert
(
offset
>=
0
);
// CreateSharedKey
if
(
pdh
==
NULL
)
{
ret
=
ERROR_OpenSslGenerateDHKeys
;
return
ret
;
}
pp
=
c1s1_key_bytes
;
key
->
random0_size
=
offset
;
if
(
key
->
random0_size
>
0
)
{
key
->
random0
=
new
char
[
key
->
random0_size
];
memcpy
(
key
->
random0
,
pp
,
key
->
random0_size
);
}
pp
+=
key
->
random0_size
;
if
(
shared_key_length
!=
0
||
shared_key
!=
NULL
)
{
ret
=
ERROR_OpenSslShareKeyComputed
;
return
ret
;
}
memcpy
(
key
->
key
,
pp
,
sizeof
(
key
->
key
));
pp
+=
sizeof
(
key
->
key
);
shared_key_length
=
DH_size
(
pdh
);
if
(
shared_key_length
<=
0
||
shared_key_length
>
1024
)
{
ret
=
ERROR_OpenSslGetSharedKeySize
;
return
ret
;
}
shared_key
=
new
u_int8_t
[
shared_key_length
];
memset
(
shared_key
,
0
,
shared_key_length
);
key
->
random1_size
=
764
-
offset
-
128
-
4
;
if
(
key
->
random1_size
>
0
)
{
key
->
random1
=
new
char
[
key
->
random1_size
];
memcpy
(
key
->
random1
,
pp
,
key
->
random1_size
);
}
peer_public_key
=
BN_bin2bn
(
_private_key
,
size
,
0
);
if
(
peer_public_key
==
NULL
)
{
ret
=
ERROR_OpenSslGetPeerPublicKey
;
return
ret
;
}
return
ret
;
}
// free the block data create by
// srs_key_block_init or srs_key_block_parse
void
srs_key_block_free
(
key_block
*
key
)
{
if
(
key
->
random0
)
{
srs_freepa
(
key
->
random0
);
}
if
(
key
->
random1
)
{
srs_freepa
(
key
->
random1
);
}
}
// calc the offset of digest,
// the key->offset cannot be used as the offset of digest.
int
srs_digest_block_get_offset
(
digest_block
*
digest
)
{
int
max_offset_size
=
764
-
32
-
4
;
int
offset
=
0
;
u_int8_t
*
pp
=
(
u_int8_t
*
)
&
digest
->
offset
;
offset
+=
*
pp
++
;
offset
+=
*
pp
++
;
offset
+=
*
pp
++
;
offset
+=
*
pp
++
;
return
offset
%
max_offset_size
;
}
// create new digest block data.
// if created, user must free it by srs_digest_block_free
void
srs_digest_block_init
(
digest_block
*
digest
)
{
digest
->
offset
=
(
int32_t
)
rand
();
digest
->
random0
=
NULL
;
digest
->
random1
=
NULL
;
if
(
DH_compute_key
(
shared_key
,
peer_public_key
,
pdh
)
==
-
1
)
{
ret
=
ERROR_OpenSslComputeSharedKey
;
return
ret
;
}
int
offset
=
srs_digest_block_get_offset
(
digest
);
srs_assert
(
offset
>=
0
);
// CopyPublicKey
if
(
pdh
==
NULL
)
{
ret
=
ERROR_OpenSslComputeSharedKey
;
return
ret
;
}
int32_t
keySize
=
BN_num_bytes
(
pdh
->
pub_key
);
if
((
keySize
<=
0
)
||
(
size
<=
0
)
||
(
keySize
>
size
))
{
//("CopyPublicKey failed due to either invalid DH state or invalid call"); return ret;
ret
=
ERROR_OpenSslInvalidDHState
;
return
ret
;
}
digest
->
random0_size
=
offset
;
if
(
digest
->
random0_size
>
0
)
{
digest
->
random0
=
new
char
[
digest
->
random0_size
];
srs_random_generate
(
digest
->
random0
,
digest
->
random0_size
);
if
(
BN_bn2bin
(
pdh
->
pub_key
,
_public_key
)
!=
keySize
)
{
//("Unable to copy key"); return ret;
ret
=
ERROR_OpenSslCopyKey
;
return
ret
;
}
return
ret
;
}
int
openssl_generate_key
(
char
*
_private_key
,
char
*
_public_key
,
int32_t
size
)
{
int
ret
=
ERROR_SUCCESS
;
srs_random_generate
(
digest
->
digest
,
sizeof
(
digest
->
digest
));
digest
->
random1_size
=
764
-
4
-
offset
-
32
;
if
(
digest
->
random1_size
>
0
)
{
digest
->
random1
=
new
char
[
digest
->
random1_size
];
srs_random_generate
(
digest
->
random1
,
digest
->
random1_size
);
}
}
// parse digest block from c1s1.
// if created, user must free it by srs_digest_block_free
// @c1s1_digest_bytes the digest start bytes, maybe c1s1 or c1s1+764
int
srs_digest_block_parse
(
digest_block
*
digest
,
char
*
c1s1_digest_bytes
)
{
int
ret
=
ERROR_SUCCESS
;
char
*
pp
=
c1s1_digest_bytes
;
// Initialize
DH
*
pdh
=
NULL
;
int32_t
bits_count
=
1024
;
u_int8_t
*
shared_key
=
NULL
;
int32_t
shared_key_length
=
0
;
BIGNUM
*
peer_public_key
=
NULL
;
ret
=
__openssl_generate_key
(
(
u_int8_t
*
)
_private_key
,
(
u_int8_t
*
)
_public_key
,
size
,
pdh
,
bits_count
,
shared_key
,
shared_key_length
,
peer_public_key
);
if
(
pdh
!=
NULL
)
{
if
(
pdh
->
p
!=
NULL
)
{
BN_free
(
pdh
->
p
);
pdh
->
p
=
NULL
;
}
if
(
pdh
->
g
!=
NULL
)
{
BN_free
(
pdh
->
g
);
pdh
->
g
=
NULL
;
}
DH_free
(
pdh
);
pdh
=
NULL
;
}
digest
->
offset
=
*
(
int32_t
*
)
pp
;
pp
+=
sizeof
(
int32_t
);
if
(
shared_key
!=
NULL
)
{
delete
[]
shared_key
;
shared_key
=
NULL
;
}
digest
->
random0
=
NULL
;
digest
->
random1
=
NULL
;
if
(
peer_public_key
!=
NULL
)
{
BN_free
(
peer_public_key
);
peer_public_key
=
NULL
;
}
int
offset
=
srs_digest_block_get_offset
(
digest
);
srs_assert
(
offset
>=
0
);
return
ret
;
}
digest
->
random0_size
=
offset
;
if
(
digest
->
random0_size
>
0
)
{
digest
->
random0
=
new
char
[
digest
->
random0_size
];
memcpy
(
digest
->
random0
,
pp
,
digest
->
random0_size
);
// calc the offset of key,
// the key->offset cannot be used as the offset of key.
int
srs_key_block_get_offset
(
key_block
*
key
)
{
int
max_offset_size
=
764
-
128
-
4
;
int
offset
=
0
;
u_int8_t
*
pp
=
(
u_int8_t
*
)
&
key
->
offset
;
offset
+=
*
pp
++
;
offset
+=
*
pp
++
;
offset
+=
*
pp
++
;
offset
+=
*
pp
++
;
return
offset
%
max_offset_size
;
}
// create new key block data.
// if created, user must free it by srs_key_block_free
void
srs_key_block_init
(
key_block
*
key
)
{
key
->
offset
=
(
int32_t
)
rand
();
key
->
random0
=
NULL
;
key
->
random1
=
NULL
;
int
offset
=
srs_key_block_get_offset
(
key
);
srs_assert
(
offset
>=
0
);
key
->
random0_size
=
offset
;
if
(
key
->
random0_size
>
0
)
{
key
->
random0
=
new
char
[
key
->
random0_size
];
srs_random_generate
(
key
->
random0
,
key
->
random0_size
);
}
srs_random_generate
(
key
->
key
,
sizeof
(
key
->
key
));
key
->
random1_size
=
764
-
offset
-
128
-
4
;
if
(
key
->
random1_size
>
0
)
{
key
->
random1
=
new
char
[
key
->
random1_size
];
srs_random_generate
(
key
->
random1
,
key
->
random1_size
);
}
}
pp
+=
digest
->
random0_size
;
memcpy
(
digest
->
digest
,
pp
,
sizeof
(
digest
->
digest
));
pp
+=
sizeof
(
digest
->
digest
);
// parse key block from c1s1.
// if created, user must free it by srs_key_block_free
// @c1s1_key_bytes the key start bytes, maybe c1s1 or c1s1+764
int
srs_key_block_parse
(
key_block
*
key
,
char
*
c1s1_key_bytes
)
{
int
ret
=
ERROR_SUCCESS
;
digest
->
random1_size
=
764
-
4
-
offset
-
32
;
if
(
digest
->
random1_size
>
0
)
{
digest
->
random1
=
new
char
[
digest
->
random1_size
];
memcpy
(
digest
->
random1
,
pp
,
digest
->
random1_size
);
char
*
pp
=
c1s1_key_bytes
+
764
;
pp
-=
sizeof
(
int32_t
);
key
->
offset
=
*
(
int32_t
*
)
pp
;
key
->
random0
=
NULL
;
key
->
random1
=
NULL
;
int
offset
=
srs_key_block_get_offset
(
key
);
srs_assert
(
offset
>=
0
);
pp
=
c1s1_key_bytes
;
key
->
random0_size
=
offset
;
if
(
key
->
random0_size
>
0
)
{
key
->
random0
=
new
char
[
key
->
random0_size
];
memcpy
(
key
->
random0
,
pp
,
key
->
random0_size
);
}
pp
+=
key
->
random0_size
;
memcpy
(
key
->
key
,
pp
,
sizeof
(
key
->
key
));
pp
+=
sizeof
(
key
->
key
);
key
->
random1_size
=
764
-
offset
-
128
-
4
;
if
(
key
->
random1_size
>
0
)
{
key
->
random1
=
new
char
[
key
->
random1_size
];
memcpy
(
key
->
random1
,
pp
,
key
->
random1_size
);
}
return
ret
;
}
return
ret
;
}
// free the block data create by
// srs_digest_block_init or srs_digest_block_parse
void
srs_digest_block_free
(
digest_block
*
digest
)
{
if
(
digest
->
random0
)
{
srs_freepa
(
digest
->
random0
);
}
if
(
digest
->
random1
)
{
srs_freepa
(
digest
->
random1
);
}
}
void
__srs_time_copy_to
(
char
*&
pp
,
int32_t
time
)
{
// 4bytes time
*
(
int32_t
*
)
pp
=
time
;
pp
+=
4
;
}
void
__srs_version_copy_to
(
char
*&
pp
,
int32_t
version
)
{
// 4bytes version
*
(
int32_t
*
)
pp
=
version
;
pp
+=
4
;
}
void
__srs_key_copy_to
(
char
*&
pp
,
key_block
*
key
)
{
// 764bytes key block
if
(
key
->
random0_size
>
0
)
{
memcpy
(
pp
,
key
->
random0
,
key
->
random0_size
);
// free the block data create by
// srs_key_block_init or srs_key_block_parse
void
srs_key_block_free
(
key_block
*
key
)
{
if
(
key
->
random0
)
{
srs_freepa
(
key
->
random0
);
}
if
(
key
->
random1
)
{
srs_freepa
(
key
->
random1
);
}
}
pp
+=
key
->
random0_size
;
memcpy
(
pp
,
key
->
key
,
sizeof
(
key
->
key
));
pp
+=
sizeof
(
key
->
key
);
if
(
key
->
random1_size
>
0
)
{
memcpy
(
pp
,
key
->
random1
,
key
->
random1_size
);
// calc the offset of digest,
// the key->offset cannot be used as the offset of digest.
int
srs_digest_block_get_offset
(
digest_block
*
digest
)
{
int
max_offset_size
=
764
-
32
-
4
;
int
offset
=
0
;
u_int8_t
*
pp
=
(
u_int8_t
*
)
&
digest
->
offset
;
offset
+=
*
pp
++
;
offset
+=
*
pp
++
;
offset
+=
*
pp
++
;
offset
+=
*
pp
++
;
return
offset
%
max_offset_size
;
}
// create new digest block data.
// if created, user must free it by srs_digest_block_free
void
srs_digest_block_init
(
digest_block
*
digest
)
{
digest
->
offset
=
(
int32_t
)
rand
();
digest
->
random0
=
NULL
;
digest
->
random1
=
NULL
;
int
offset
=
srs_digest_block_get_offset
(
digest
);
srs_assert
(
offset
>=
0
);
digest
->
random0_size
=
offset
;
if
(
digest
->
random0_size
>
0
)
{
digest
->
random0
=
new
char
[
digest
->
random0_size
];
srs_random_generate
(
digest
->
random0
,
digest
->
random0_size
);
}
srs_random_generate
(
digest
->
digest
,
sizeof
(
digest
->
digest
));
digest
->
random1_size
=
764
-
4
-
offset
-
32
;
if
(
digest
->
random1_size
>
0
)
{
digest
->
random1
=
new
char
[
digest
->
random1_size
];
srs_random_generate
(
digest
->
random1
,
digest
->
random1_size
);
}
}
pp
+=
key
->
random1_size
;
*
(
int32_t
*
)
pp
=
key
->
offset
;
pp
+=
4
;
}
void
__srs_digest_copy_to
(
char
*&
pp
,
digest_block
*
digest
,
bool
with_digest
)
{
// 732bytes digest block without the 32bytes digest-data
// nbytes digest block part1
*
(
int32_t
*
)
pp
=
digest
->
offset
;
pp
+=
4
;
// parse digest block from c1s1.
// if created, user must free it by srs_digest_block_free
// @c1s1_digest_bytes the digest start bytes, maybe c1s1 or c1s1+764
int
srs_digest_block_parse
(
digest_block
*
digest
,
char
*
c1s1_digest_bytes
)
{
int
ret
=
ERROR_SUCCESS
;
if
(
digest
->
random0_size
>
0
)
{
memcpy
(
pp
,
digest
->
random0
,
digest
->
random0_size
);
char
*
pp
=
c1s1_digest_bytes
;
digest
->
offset
=
*
(
int32_t
*
)
pp
;
pp
+=
sizeof
(
int32_t
);
digest
->
random0
=
NULL
;
digest
->
random1
=
NULL
;
int
offset
=
srs_digest_block_get_offset
(
digest
);
srs_assert
(
offset
>=
0
);
digest
->
random0_size
=
offset
;
if
(
digest
->
random0_size
>
0
)
{
digest
->
random0
=
new
char
[
digest
->
random0_size
];
memcpy
(
digest
->
random0
,
pp
,
digest
->
random0_size
);
}
pp
+=
digest
->
random0_size
;
memcpy
(
digest
->
digest
,
pp
,
sizeof
(
digest
->
digest
));
pp
+=
sizeof
(
digest
->
digest
);
digest
->
random1_size
=
764
-
4
-
offset
-
32
;
if
(
digest
->
random1_size
>
0
)
{
digest
->
random1
=
new
char
[
digest
->
random1_size
];
memcpy
(
digest
->
random1
,
pp
,
digest
->
random1_size
);
}
return
ret
;
}
pp
+=
digest
->
random0_size
;
// digest
if
(
with_digest
)
{
memcpy
(
pp
,
digest
->
digest
,
32
);
pp
+=
32
;
// free the block data create by
// srs_digest_block_init or srs_digest_block_parse
void
srs_digest_block_free
(
digest_block
*
digest
)
{
if
(
digest
->
random0
)
{
srs_freepa
(
digest
->
random0
);
}
if
(
digest
->
random1
)
{
srs_freepa
(
digest
->
random1
);
}
}
// nbytes digest block part2
if
(
digest
->
random1_size
>
0
)
{
memcpy
(
pp
,
digest
->
random1
,
digest
->
random1_size
);
void
__srs_time_copy_to
(
char
*&
pp
,
int32_t
time
)
{
// 4bytes time
*
(
int32_t
*
)
pp
=
time
;
pp
+=
4
;
}
pp
+=
digest
->
random1_size
;
}
/**
* copy whole c1s1 to bytes.
*/
void
srs_schema0_copy_to
(
char
*
bytes
,
bool
with_digest
,
int32_t
time
,
int32_t
version
,
key_block
*
key
,
digest_block
*
digest
)
{
char
*
pp
=
bytes
;
__srs_time_copy_to
(
pp
,
time
);
__srs_version_copy_to
(
pp
,
version
);
__srs_key_copy_to
(
pp
,
key
);
__srs_digest_copy_to
(
pp
,
digest
,
with_digest
);
if
(
with_digest
)
{
srs_assert
(
pp
-
bytes
==
1536
);
}
else
{
srs_assert
(
pp
-
bytes
==
1536
-
32
);
void
__srs_version_copy_to
(
char
*&
pp
,
int32_t
version
)
{
// 4bytes version
*
(
int32_t
*
)
pp
=
version
;
pp
+=
4
;
}
}
void
srs_schema1_copy_to
(
char
*
bytes
,
bool
with_digest
,
int32_t
time
,
int32_t
version
,
digest_block
*
digest
,
key_block
*
key
)
{
char
*
pp
=
bytes
;
__srs_time_copy_to
(
pp
,
time
);
__srs_version_copy_to
(
pp
,
version
);
__srs_digest_copy_to
(
pp
,
digest
,
with_digest
);
__srs_key_copy_to
(
pp
,
key
);
if
(
with_digest
)
{
srs_assert
(
pp
-
bytes
==
1536
);
}
else
{
srs_assert
(
pp
-
bytes
==
1536
-
32
);
void
__srs_key_copy_to
(
char
*&
pp
,
key_block
*
key
)
{
// 764bytes key block
if
(
key
->
random0_size
>
0
)
{
memcpy
(
pp
,
key
->
random0
,
key
->
random0_size
);
}
pp
+=
key
->
random0_size
;
memcpy
(
pp
,
key
->
key
,
sizeof
(
key
->
key
));
pp
+=
sizeof
(
key
->
key
);
if
(
key
->
random1_size
>
0
)
{
memcpy
(
pp
,
key
->
random1
,
key
->
random1_size
);
}
pp
+=
key
->
random1_size
;
*
(
int32_t
*
)
pp
=
key
->
offset
;
pp
+=
4
;
}
void
__srs_digest_copy_to
(
char
*&
pp
,
digest_block
*
digest
,
bool
with_digest
)
{
// 732bytes digest block without the 32bytes digest-data
// nbytes digest block part1
*
(
int32_t
*
)
pp
=
digest
->
offset
;
pp
+=
4
;
if
(
digest
->
random0_size
>
0
)
{
memcpy
(
pp
,
digest
->
random0
,
digest
->
random0_size
);
}
pp
+=
digest
->
random0_size
;
// digest
if
(
with_digest
)
{
memcpy
(
pp
,
digest
->
digest
,
32
);
pp
+=
32
;
}
// nbytes digest block part2
if
(
digest
->
random1_size
>
0
)
{
memcpy
(
pp
,
digest
->
random1
,
digest
->
random1_size
);
}
pp
+=
digest
->
random1_size
;
}
}
/**
* c1s1 is splited by digest:
* c1s1-part1: n bytes (time, version, key and digest-part1).
* digest-data: 32bytes
* c1s1-part2: (1536-n-32)bytes (digest-part2)
*/
char
*
srs
::
srs_bytes_join_schema0
(
int32_t
time
,
int32_t
version
,
key_block
*
key
,
digest_block
*
digest
)
{
char
*
bytes
=
new
char
[
1536
-
32
];
srs_schema0_copy_to
(
bytes
,
false
,
time
,
version
,
key
,
digest
);
return
bytes
;
}
/**
* c1s1 is splited by digest:
* c1s1-part1: n bytes (time, version and digest-part1).
* digest-data: 32bytes
* c1s1-part2: (1536-n-32)bytes (digest-part2 and key)
*/
char
*
srs
::
srs_bytes_join_schema1
(
int32_t
time
,
int32_t
version
,
digest_block
*
digest
,
key_block
*
key
)
{
char
*
bytes
=
new
char
[
1536
-
32
];
srs_schema1_copy_to
(
bytes
,
false
,
time
,
version
,
digest
,
key
);
return
bytes
;
}
/**
* compare the memory in bytes.
*/
bool
srs
::
srs_bytes_equals
(
void
*
pa
,
void
*
pb
,
int
size
)
{
u_int8_t
*
a
=
(
u_int8_t
*
)
pa
;
u_int8_t
*
b
=
(
u_int8_t
*
)
pb
;
/**
* copy whole c1s1 to bytes.
*/
void
srs_schema0_copy_to
(
char
*
bytes
,
bool
with_digest
,
int32_t
time
,
int32_t
version
,
key_block
*
key
,
digest_block
*
digest
)
{
char
*
pp
=
bytes
;
for
(
int
i
=
0
;
i
<
size
;
i
++
){
if
(
a
[
i
]
!=
b
[
i
]){
return
false
;
__srs_time_copy_to
(
pp
,
time
);
__srs_version_copy_to
(
pp
,
version
);
__srs_key_copy_to
(
pp
,
key
);
__srs_digest_copy_to
(
pp
,
digest
,
with_digest
);
if
(
with_digest
)
{
srs_assert
(
pp
-
bytes
==
1536
);
}
else
{
srs_assert
(
pp
-
bytes
==
1536
-
32
);
}
}
return
true
;
}
c2s2
::
c2s2
()
{
srs_random_generate
(
random
,
1504
);
srs_random_generate
(
digest
,
32
);
}
c2s2
::~
c2s2
()
{
}
void
c2s2
::
dump
(
char
*
_c2s2
)
{
memcpy
(
_c2s2
,
random
,
1504
);
memcpy
(
_c2s2
+
1504
,
digest
,
32
);
}
void
c2s2
::
parse
(
char
*
_c2s2
)
{
memcpy
(
random
,
_c2s2
,
1504
);
memcpy
(
digest
,
_c2s2
+
1504
,
32
);
}
int
c2s2
::
c2_create
(
c1s1
*
s1
)
{
int
ret
=
ERROR_SUCCESS
;
void
srs_schema1_copy_to
(
char
*
bytes
,
bool
with_digest
,
int32_t
time
,
int32_t
version
,
digest_block
*
digest
,
key_block
*
key
)
{
char
*
pp
=
bytes
;
char
temp_key
[
OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
s1
->
get_digest
(),
32
,
SrsGenuineFPKey
,
62
,
temp_key
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create c2 temp key failed. ret=%d"
,
ret
);
return
ret
;
__srs_time_copy_to
(
pp
,
time
);
__srs_version_copy_to
(
pp
,
version
);
__srs_digest_copy_to
(
pp
,
digest
,
with_digest
);
__srs_key_copy_to
(
pp
,
key
);
if
(
with_digest
)
{
srs_assert
(
pp
-
bytes
==
1536
);
}
else
{
srs_assert
(
pp
-
bytes
==
1536
-
32
);
}
}
srs_verbose
(
"generate c2 temp key success."
);
char
_digest
[
OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
random
,
1504
,
temp_key
,
32
,
_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create c2 digest failed. ret=%d"
,
ret
);
return
ret
;
/**
* c1s1 is splited by digest:
* c1s1-part1: n bytes (time, version, key and digest-part1).
* digest-data: 32bytes
* c1s1-part2: (1536-n-32)bytes (digest-part2)
*/
char
*
srs_bytes_join_schema0
(
int32_t
time
,
int32_t
version
,
key_block
*
key
,
digest_block
*
digest
)
{
char
*
bytes
=
new
char
[
1536
-
32
];
srs_schema0_copy_to
(
bytes
,
false
,
time
,
version
,
key
,
digest
);
return
bytes
;
}
/**
* c1s1 is splited by digest:
* c1s1-part1: n bytes (time, version and digest-part1).
* digest-data: 32bytes
* c1s1-part2: (1536-n-32)bytes (digest-part2 and key)
*/
char
*
srs_bytes_join_schema1
(
int32_t
time
,
int32_t
version
,
digest_block
*
digest
,
key_block
*
key
)
{
char
*
bytes
=
new
char
[
1536
-
32
];
srs_schema1_copy_to
(
bytes
,
false
,
time
,
version
,
digest
,
key
);
return
bytes
;
}
srs_verbose
(
"generate c2 digest success."
);
memcpy
(
digest
,
_digest
,
32
);
return
ret
;
}
int
c2s2
::
c2_validate
(
c1s1
*
s1
,
bool
&
is_valid
)
{
is_valid
=
false
;
int
ret
=
ERROR_SUCCESS
;
/**
* compare the memory in bytes.
*/
bool
srs_bytes_equals
(
void
*
pa
,
void
*
pb
,
int
size
)
{
u_int8_t
*
a
=
(
u_int8_t
*
)
pa
;
u_int8_t
*
b
=
(
u_int8_t
*
)
pb
;
if
(
!
a
&&
!
b
)
{
return
true
;
}
if
(
!
a
||
!
b
)
{
return
false
;
}
for
(
int
i
=
0
;
i
<
size
;
i
++
){
if
(
a
[
i
]
!=
b
[
i
]){
return
false
;
}
}
char
temp_key
[
OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
s1
->
get_digest
(),
32
,
SrsGenuineFPKey
,
62
,
temp_key
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create c2 temp key failed. ret=%d"
,
ret
);
return
ret
;
return
true
;
}
srs_verbose
(
"generate c2 temp key success."
);
char
_digest
[
OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
random
,
1504
,
temp_key
,
32
,
_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create c2 digest failed. ret=%d"
,
ret
);
return
ret
;
c2s2
::
c2s2
()
{
srs_random_generate
(
random
,
1504
);
srs_random_generate
(
digest
,
32
);
}
srs_verbose
(
"generate c2 digest success."
);
is_valid
=
srs_bytes_equals
(
digest
,
_digest
,
32
);
return
ret
;
}
int
c2s2
::
s2_create
(
c1s1
*
c1
)
{
int
ret
=
ERROR_SUCCESS
;
char
temp_key
[
OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
c1
->
get_digest
(),
32
,
SrsGenuineFMSKey
,
68
,
temp_key
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create s2 temp key failed. ret=%d"
,
ret
);
return
ret
;
c2s2
::~
c2s2
()
{
}
srs_verbose
(
"generate s2 temp key success."
);
char
_digest
[
OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
random
,
1504
,
temp_key
,
32
,
_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create s2 digest failed. ret=%d"
,
ret
);
return
ret
;
void
c2s2
::
dump
(
char
*
_c2s2
)
{
memcpy
(
_c2s2
,
random
,
1504
);
memcpy
(
_c2s2
+
1504
,
digest
,
32
);
}
srs_verbose
(
"generate s2 digest success."
);
memcpy
(
digest
,
_digest
,
32
);
return
ret
;
}
int
c2s2
::
s2_validate
(
c1s1
*
c1
,
bool
&
is_valid
)
{
is_valid
=
false
;
int
ret
=
ERROR_SUCCESS
;
char
temp_key
[
OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
c1
->
get_digest
(),
32
,
SrsGenuineFMSKey
,
68
,
temp_key
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create s2 temp key failed. ret=%d"
,
ret
);
return
ret
;
void
c2s2
::
parse
(
char
*
_c2s2
)
{
memcpy
(
random
,
_c2s2
,
1504
);
memcpy
(
digest
,
_c2s2
+
1504
,
32
);
}
srs_verbose
(
"generate s2 temp key success."
);
char
_digest
[
OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
random
,
1504
,
temp_key
,
32
,
_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create s2 digest failed. ret=%d"
,
ret
);
int
c2s2
::
c2_create
(
c1s1
*
s1
)
{
int
ret
=
ERROR_SUCCESS
;
char
temp_key
[
OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
s1
->
get_digest
(),
32
,
SrsGenuineFPKey
,
62
,
temp_key
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create c2 temp key failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"generate c2 temp key success."
);
char
_digest
[
OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
random
,
1504
,
temp_key
,
32
,
_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create c2 digest failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"generate c2 digest success."
);
memcpy
(
digest
,
_digest
,
32
);
return
ret
;
}
srs_verbose
(
"generate s2 digest success."
);
is_valid
=
srs_bytes_equals
(
digest
,
_digest
,
32
);
return
ret
;
}
// TODO: FIXME: move to the right position.
c1s1
::
c1s1
()
{
schema
=
srs_schema_invalid
;
}
c1s1
::~
c1s1
()
{
destroy_blocks
();
}
char
*
c1s1
::
get_digest
()
{
srs_assert
(
schema
!=
srs_schema_invalid
);
if
(
schema
==
srs_schema0
)
{
return
block1
.
digest
.
digest
;
}
else
{
return
block0
.
digest
.
digest
;
}
}
void
c1s1
::
dump
(
char
*
_c1s1
)
{
srs_assert
(
schema
!=
srs_schema_invalid
);
if
(
schema
==
srs_schema0
)
{
srs_schema0_copy_to
(
_c1s1
,
true
,
time
,
version
,
&
block0
.
key
,
&
block1
.
digest
);
}
else
{
srs_schema1_copy_to
(
_c1s1
,
true
,
time
,
version
,
&
block0
.
digest
,
&
block1
.
key
);
}
}
int
c1s1
::
parse
(
char
*
_c1s1
,
srs_schema_type
_schema
)
{
int
ret
=
ERROR_SUCCESS
;
if
(
_schema
==
srs_schema_invalid
)
{
ret
=
ERROR_RTMP_CH_SCHEMA
;
srs_error
(
"parse c1 failed. invalid schema=%d, ret=%d"
,
_schema
,
ret
);
int
c2s2
::
c2_validate
(
c1s1
*
s1
,
bool
&
is_valid
)
{
is_valid
=
false
;
int
ret
=
ERROR_SUCCESS
;
char
temp_key
[
OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
s1
->
get_digest
(),
32
,
SrsGenuineFPKey
,
62
,
temp_key
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create c2 temp key failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"generate c2 temp key success."
);
char
_digest
[
OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
random
,
1504
,
temp_key
,
32
,
_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create c2 digest failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"generate c2 digest success."
);
is_valid
=
srs_bytes_equals
(
digest
,
_digest
,
32
);
return
ret
;
}
destroy_blocks
();
time
=
*
(
int32_t
*
)
_c1s1
;
version
=
*
(
int32_t
*
)(
_c1s1
+
4
);
// client c1 version
if
(
_schema
==
srs_schema0
)
{
if
((
ret
=
srs_key_block_parse
(
&
block0
.
key
,
_c1s1
+
8
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"parse the c1 key failed. ret=%d"
,
ret
);
int
c2s2
::
s2_create
(
c1s1
*
c1
)
{
int
ret
=
ERROR_SUCCESS
;
char
temp_key
[
OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
c1
->
get_digest
(),
32
,
SrsGenuineFMSKey
,
68
,
temp_key
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create s2 temp key failed. ret=%d"
,
ret
);
return
ret
;
}
if
((
ret
=
srs_digest_block_parse
(
&
block1
.
digest
,
_c1s1
+
8
+
764
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"parse the c1 digest failed. ret=%d"
,
ret
);
srs_verbose
(
"generate s2 temp key success."
);
char
_digest
[
OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
random
,
1504
,
temp_key
,
32
,
_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create s2 digest failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"parse c1 key-digest success"
);
}
else
if
(
_schema
==
srs_schema1
)
{
if
((
ret
=
srs_digest_block_parse
(
&
block0
.
digest
,
_c1s1
+
8
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"parse the c1 key failed. ret=%d"
,
ret
);
srs_verbose
(
"generate s2 digest success."
);
memcpy
(
digest
,
_digest
,
32
);
return
ret
;
}
int
c2s2
::
s2_validate
(
c1s1
*
c1
,
bool
&
is_valid
)
{
is_valid
=
false
;
int
ret
=
ERROR_SUCCESS
;
char
temp_key
[
OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
c1
->
get_digest
(),
32
,
SrsGenuineFMSKey
,
68
,
temp_key
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create s2 temp key failed. ret=%d"
,
ret
);
return
ret
;
}
if
((
ret
=
srs_key_block_parse
(
&
block1
.
key
,
_c1s1
+
8
+
764
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"parse the c1 digest failed. ret=%d"
,
ret
);
srs_verbose
(
"generate s2 temp key success."
);
char
_digest
[
OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
random
,
1504
,
temp_key
,
32
,
_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create s2 digest failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"parse c1 digest-key success"
);
}
else
{
ret
=
ERROR_RTMP_CH_SCHEMA
;
srs_error
(
"parse c1 failed. invalid schema=%d, ret=%d"
,
_schema
,
ret
);
srs_verbose
(
"generate s2 digest success."
);
is_valid
=
srs_bytes_equals
(
digest
,
_digest
,
32
);
return
ret
;
}
schema
=
_schema
;
return
ret
;
}
int
c1s1
::
c1_create
(
srs_schema_type
_schema
)
{
int
ret
=
ERROR_SUCCESS
;
if
(
_schema
==
srs_schema_invalid
)
{
ret
=
ERROR_RTMP_CH_SCHEMA
;
srs_error
(
"create c1 failed. invalid schema=%d, ret=%d"
,
_schema
,
ret
);
return
ret
;
// TODO: FIXME: move to the right position.
c1s1
::
c1s1
()
{
schema
=
srs_schema_invalid
;
}
destroy_blocks
();
time
=
::
time
(
NULL
);
version
=
0x02070080
;
// client c1 version
if
(
_schema
==
srs_schema0
)
{
srs_key_block_init
(
&
block0
.
key
);
srs_digest_block_init
(
&
block1
.
digest
);
}
else
{
srs_digest_block_init
(
&
block0
.
digest
);
srs_key_block_init
(
&
block1
.
key
);
c1s1
::~
c1s1
()
{
destroy_blocks
();
}
schema
=
_schema
;
char
*
digest
=
NULL
;
if
((
ret
=
calc_c1_digest
(
digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"sign c1 error, failed to calc digest. ret=%d"
,
ret
);
return
ret
;
char
*
c1s1
::
get_digest
()
{
srs_assert
(
schema
!=
srs_schema_invalid
);
if
(
schema
==
srs_schema0
)
{
return
block1
.
digest
.
digest
;
}
else
{
return
block0
.
digest
.
digest
;
}
}
srs_assert
(
digest
!=
NULL
);
SrsAutoFree
(
char
,
digest
,
true
);
if
(
schema
==
srs_schema0
)
{
memcpy
(
block1
.
digest
.
digest
,
digest
,
32
);
}
else
{
memcpy
(
block0
.
digest
.
digest
,
digest
,
32
);
void
c1s1
::
dump
(
char
*
_c1s1
)
{
srs_assert
(
schema
!=
srs_schema_invalid
);
if
(
schema
==
srs_schema0
)
{
srs_schema0_copy_to
(
_c1s1
,
true
,
time
,
version
,
&
block0
.
key
,
&
block1
.
digest
);
}
else
{
srs_schema1_copy_to
(
_c1s1
,
true
,
time
,
version
,
&
block0
.
digest
,
&
block1
.
key
);
}
}
return
ret
;
}
int
c1s1
::
c1_validate_digest
(
bool
&
is_valid
)
{
is_valid
=
false
;
int
ret
=
ERROR_SUCCESS
;
char
*
c1_digest
=
NULL
;
if
((
ret
=
calc_c1_digest
(
c1_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"validate c1 error, failed to calc digest. ret=%d"
,
ret
);
int
c1s1
::
parse
(
char
*
_c1s1
,
srs_schema_type
_schema
)
{
int
ret
=
ERROR_SUCCESS
;
if
(
_schema
==
srs_schema_invalid
)
{
ret
=
ERROR_RTMP_CH_SCHEMA
;
srs_error
(
"parse c1 failed. invalid schema=%d, ret=%d"
,
_schema
,
ret
);
return
ret
;
}
destroy_blocks
();
time
=
*
(
int32_t
*
)
_c1s1
;
version
=
*
(
int32_t
*
)(
_c1s1
+
4
);
// client c1 version
if
(
_schema
==
srs_schema0
)
{
if
((
ret
=
srs_key_block_parse
(
&
block0
.
key
,
_c1s1
+
8
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"parse the c1 key failed. ret=%d"
,
ret
);
return
ret
;
}
if
((
ret
=
srs_digest_block_parse
(
&
block1
.
digest
,
_c1s1
+
8
+
764
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"parse the c1 digest failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"parse c1 key-digest success"
);
}
else
if
(
_schema
==
srs_schema1
)
{
if
((
ret
=
srs_digest_block_parse
(
&
block0
.
digest
,
_c1s1
+
8
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"parse the c1 key failed. ret=%d"
,
ret
);
return
ret
;
}
if
((
ret
=
srs_key_block_parse
(
&
block1
.
key
,
_c1s1
+
8
+
764
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"parse the c1 digest failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"parse c1 digest-key success"
);
}
else
{
ret
=
ERROR_RTMP_CH_SCHEMA
;
srs_error
(
"parse c1 failed. invalid schema=%d, ret=%d"
,
_schema
,
ret
);
return
ret
;
}
schema
=
_schema
;
return
ret
;
}
srs_assert
(
c1_digest
!=
NULL
);
SrsAutoFree
(
char
,
c1_digest
,
true
);
if
(
schema
==
srs_schema0
)
{
is_valid
=
srs_bytes_equals
(
block1
.
digest
.
digest
,
c1_digest
,
32
);
}
else
{
is_valid
=
srs_bytes_equals
(
block0
.
digest
.
digest
,
c1_digest
,
32
);
}
return
ret
;
}
int
c1s1
::
s1_validate_digest
(
bool
&
is_valid
)
{
is_valid
=
false
;
int
ret
=
ERROR_SUCCESS
;
char
*
s1_digest
=
NULL
;
if
((
ret
=
calc_s1_digest
(
s1_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"validate s1 error, failed to calc digest. ret=%d"
,
ret
);
int
c1s1
::
c1_create
(
srs_schema_type
_schema
)
{
int
ret
=
ERROR_SUCCESS
;
if
(
_schema
==
srs_schema_invalid
)
{
ret
=
ERROR_RTMP_CH_SCHEMA
;
srs_error
(
"create c1 failed. invalid schema=%d, ret=%d"
,
_schema
,
ret
);
return
ret
;
}
destroy_blocks
();
time
=
::
time
(
NULL
);
version
=
0x02070080
;
// client c1 version
if
(
_schema
==
srs_schema0
)
{
srs_key_block_init
(
&
block0
.
key
);
srs_digest_block_init
(
&
block1
.
digest
);
}
else
{
srs_digest_block_init
(
&
block0
.
digest
);
srs_key_block_init
(
&
block1
.
key
);
}
schema
=
_schema
;
char
*
digest
=
NULL
;
if
((
ret
=
calc_c1_digest
(
digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"sign c1 error, failed to calc digest. ret=%d"
,
ret
);
return
ret
;
}
srs_assert
(
digest
!=
NULL
);
SrsAutoFree
(
char
,
digest
,
true
);
if
(
schema
==
srs_schema0
)
{
memcpy
(
block1
.
digest
.
digest
,
digest
,
32
);
}
else
{
memcpy
(
block0
.
digest
.
digest
,
digest
,
32
);
}
return
ret
;
}
srs_assert
(
s1_digest
!=
NULL
);
SrsAutoFree
(
char
,
s1_digest
,
true
);
if
(
schema
==
srs_schema0
)
{
is_valid
=
srs_bytes_equals
(
block1
.
digest
.
digest
,
s1_digest
,
32
);
}
else
{
is_valid
=
srs_bytes_equals
(
block0
.
digest
.
digest
,
s1_digest
,
32
);
}
return
ret
;
}
int
c1s1
::
s1_create
(
c1s1
*
c1
)
{
int
ret
=
ERROR_SUCCESS
;
if
(
c1
->
schema
==
srs_schema_invalid
)
{
ret
=
ERROR_RTMP_CH_SCHEMA
;
srs_error
(
"create s1 failed. invalid schema=%d, ret=%d"
,
c1
->
schema
,
ret
);
int
c1s1
::
c1_validate_digest
(
bool
&
is_valid
)
{
is_valid
=
false
;
int
ret
=
ERROR_SUCCESS
;
char
*
c1_digest
=
NULL
;
if
((
ret
=
calc_c1_digest
(
c1_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"validate c1 error, failed to calc digest. ret=%d"
,
ret
);
return
ret
;
}
srs_assert
(
c1_digest
!=
NULL
);
SrsAutoFree
(
char
,
c1_digest
,
true
);
if
(
schema
==
srs_schema0
)
{
is_valid
=
srs_bytes_equals
(
block1
.
digest
.
digest
,
c1_digest
,
32
);
}
else
{
is_valid
=
srs_bytes_equals
(
block0
.
digest
.
digest
,
c1_digest
,
32
);
}
return
ret
;
}
destroy_blocks
();
schema
=
c1
->
schema
;
time
=
::
time
(
NULL
);
version
=
0x01000504
;
// server s1 version
if
(
schema
==
srs_schema0
)
{
srs_key_block_init
(
&
block0
.
key
);
srs_digest_block_init
(
&
block1
.
digest
);
}
else
{
srs_digest_block_init
(
&
block0
.
digest
);
srs_key_block_init
(
&
block1
.
key
);
int
c1s1
::
s1_validate_digest
(
bool
&
is_valid
)
{
is_valid
=
false
;
int
ret
=
ERROR_SUCCESS
;
char
*
s1_digest
=
NULL
;
if
((
ret
=
calc_s1_digest
(
s1_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"validate s1 error, failed to calc digest. ret=%d"
,
ret
);
return
ret
;
}
srs_assert
(
s1_digest
!=
NULL
);
SrsAutoFree
(
char
,
s1_digest
,
true
);
if
(
schema
==
srs_schema0
)
{
is_valid
=
srs_bytes_equals
(
block1
.
digest
.
digest
,
s1_digest
,
32
);
}
else
{
is_valid
=
srs_bytes_equals
(
block0
.
digest
.
digest
,
s1_digest
,
32
);
}
return
ret
;
}
if
(
schema
==
srs_schema0
)
{
if
((
ret
=
openssl_generate_key
(
c1
->
block0
.
key
.
key
,
block0
.
key
.
key
,
128
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"calc s1 key failed. ret=%d"
,
ret
);
int
c1s1
::
s1_create
(
c1s1
*
c1
)
{
int
ret
=
ERROR_SUCCESS
;
if
(
c1
->
schema
==
srs_schema_invalid
)
{
ret
=
ERROR_RTMP_CH_SCHEMA
;
srs_error
(
"create s1 failed. invalid schema=%d, ret=%d"
,
c1
->
schema
,
ret
);
return
ret
;
}
}
else
{
if
((
ret
=
openssl_generate_key
(
c1
->
block1
.
key
.
key
,
block1
.
key
.
key
,
128
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"calc s1 key failed. ret=%d"
,
ret
);
destroy_blocks
();
schema
=
c1
->
schema
;
time
=
::
time
(
NULL
);
version
=
0x01000504
;
// server s1 version
if
(
schema
==
srs_schema0
)
{
srs_key_block_init
(
&
block0
.
key
);
srs_digest_block_init
(
&
block1
.
digest
);
}
else
{
srs_digest_block_init
(
&
block0
.
digest
);
srs_key_block_init
(
&
block1
.
key
);
}
if
(
schema
==
srs_schema0
)
{
if
((
ret
=
openssl_generate_key
(
c1
->
block0
.
key
.
key
,
block0
.
key
.
key
,
128
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"calc s1 key failed. ret=%d"
,
ret
);
return
ret
;
}
}
else
{
if
((
ret
=
openssl_generate_key
(
c1
->
block1
.
key
.
key
,
block1
.
key
.
key
,
128
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"calc s1 key failed. ret=%d"
,
ret
);
return
ret
;
}
}
srs_verbose
(
"calc s1 key success."
);
char
*
s1_digest
=
NULL
;
if
((
ret
=
calc_s1_digest
(
s1_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"calc s1 digest failed. ret=%d"
,
ret
);
return
ret
;
}
}
srs_verbose
(
"calc s1 key success."
);
srs_verbose
(
"calc s1 digest success."
);
srs_assert
(
s1_digest
!=
NULL
);
SrsAutoFree
(
char
,
s1_digest
,
true
);
if
(
schema
==
srs_schema0
)
{
memcpy
(
block1
.
digest
.
digest
,
s1_digest
,
32
);
}
else
{
memcpy
(
block0
.
digest
.
digest
,
s1_digest
,
32
);
}
srs_verbose
(
"copy s1 key success."
);
char
*
s1_digest
=
NULL
;
if
((
ret
=
calc_s1_digest
(
s1_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"calc s1 digest failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"calc s1 digest success."
);
srs_assert
(
s1_digest
!=
NULL
);
SrsAutoFree
(
char
,
s1_digest
,
true
);
if
(
schema
==
srs_schema0
)
{
memcpy
(
block1
.
digest
.
digest
,
s1_digest
,
32
);
}
else
{
memcpy
(
block0
.
digest
.
digest
,
s1_digest
,
32
);
}
srs_verbose
(
"copy s1 key success."
);
return
ret
;
}
int
c1s1
::
calc_s1_digest
(
char
*&
digest
)
{
int
ret
=
ERROR_SUCCESS
;
srs_assert
(
schema
==
srs_schema0
||
schema
==
srs_schema1
);
char
*
c1s1_joined_bytes
=
NULL
;
if
(
schema
==
srs_schema0
)
{
c1s1_joined_bytes
=
srs_bytes_join_schema0
(
time
,
version
,
&
block0
.
key
,
&
block1
.
digest
);
}
else
{
c1s1_joined_bytes
=
srs_bytes_join_schema1
(
time
,
version
,
&
block0
.
digest
,
&
block1
.
key
);
}
srs_assert
(
c1s1_joined_bytes
!=
NULL
);
SrsAutoFree
(
char
,
c1s1_joined_bytes
,
true
);
int
c1s1
::
calc_s1_digest
(
char
*&
digest
)
{
int
ret
=
ERROR_SUCCESS
;
srs_assert
(
schema
==
srs_schema0
||
schema
==
srs_schema1
);
char
*
c1s1_joined_bytes
=
NULL
;
digest
=
new
char
[
OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
c1s1_joined_bytes
,
1536
-
32
,
SrsGenuineFMSKey
,
36
,
digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"calc digest for s1 failed. ret=%d"
,
ret
);
if
(
schema
==
srs_schema0
)
{
c1s1_joined_bytes
=
srs_bytes_join_schema0
(
time
,
version
,
&
block0
.
key
,
&
block1
.
digest
);
}
else
{
c1s1_joined_bytes
=
srs_bytes_join_schema1
(
time
,
version
,
&
block0
.
digest
,
&
block1
.
key
);
}
srs_assert
(
c1s1_joined_bytes
!=
NULL
);
SrsAutoFree
(
char
,
c1s1_joined_bytes
,
true
);
digest
=
new
char
[
OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
c1s1_joined_bytes
,
1536
-
32
,
SrsGenuineFMSKey
,
36
,
digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"calc digest for s1 failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"digest calculated for s1"
);
return
ret
;
}
srs_verbose
(
"digest calculated for s1"
);
return
ret
;
}
int
c1s1
::
calc_c1_digest
(
char
*&
digest
)
{
int
ret
=
ERROR_SUCCESS
;
srs_assert
(
schema
==
srs_schema0
||
schema
==
srs_schema1
);
char
*
c1s1_joined_bytes
=
NULL
;
if
(
schema
==
srs_schema0
)
{
c1s1_joined_bytes
=
srs_bytes_join_schema0
(
time
,
version
,
&
block0
.
key
,
&
block1
.
digest
);
}
else
{
c1s1_joined_bytes
=
srs_bytes_join_schema1
(
time
,
version
,
&
block0
.
digest
,
&
block1
.
key
);
}
srs_assert
(
c1s1_joined_bytes
!=
NULL
);
SrsAutoFree
(
char
,
c1s1_joined_bytes
,
true
);
int
c1s1
::
calc_c1_digest
(
char
*&
digest
)
{
int
ret
=
ERROR_SUCCESS
;
srs_assert
(
schema
==
srs_schema0
||
schema
==
srs_schema1
);
char
*
c1s1_joined_bytes
=
NULL
;
digest
=
new
char
[
OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
c1s1_joined_bytes
,
1536
-
32
,
SrsGenuineFPKey
,
30
,
digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"calc digest for c1 failed. ret=%d"
,
ret
);
if
(
schema
==
srs_schema0
)
{
c1s1_joined_bytes
=
srs_bytes_join_schema0
(
time
,
version
,
&
block0
.
key
,
&
block1
.
digest
);
}
else
{
c1s1_joined_bytes
=
srs_bytes_join_schema1
(
time
,
version
,
&
block0
.
digest
,
&
block1
.
key
);
}
srs_assert
(
c1s1_joined_bytes
!=
NULL
);
SrsAutoFree
(
char
,
c1s1_joined_bytes
,
true
);
digest
=
new
char
[
OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
c1s1_joined_bytes
,
1536
-
32
,
SrsGenuineFPKey
,
30
,
digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"calc digest for c1 failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"digest calculated for c1"
);
return
ret
;
}
srs_verbose
(
"digest calculated for c1"
);
return
ret
;
}
void
c1s1
::
destroy_blocks
()
{
if
(
schema
==
srs_schema_invalid
)
{
return
;
}
if
(
schema
==
srs_schema0
)
{
srs_key_block_free
(
&
block0
.
key
);
srs_digest_block_free
(
&
block1
.
digest
);
}
else
{
srs_digest_block_free
(
&
block0
.
digest
);
srs_key_block_free
(
&
block1
.
key
);
void
c1s1
::
destroy_blocks
()
{
if
(
schema
==
srs_schema_invalid
)
{
return
;
}
if
(
schema
==
srs_schema0
)
{
srs_key_block_free
(
&
block0
.
key
);
srs_digest_block_free
(
&
block1
.
digest
);
}
else
{
srs_digest_block_free
(
&
block0
.
digest
);
srs_key_block_free
(
&
block1
.
key
);
}
}
}
...
...
@@ -1144,13 +1164,10 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs
c2s2
c2
;
c2
.
parse
(
hs_bytes
->
c2
);
srs_verbose
(
"complex handshake read c2 success."
);
// verify c2
if
((
ret
=
c2
.
c2_validate
(
&
s1
,
is_valid
))
!=
ERROR_SUCCESS
||
!
is_valid
)
{
ret
=
ERROR_RTMP_HANDSHAKE
;
srs_trace
(
"verify c2 failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"verify c2 success."
);
// never verify c2, for ffmpeg will failed.
// it's ok for flash.
srs_trace
(
"comple handshake with client success"
);
...
...
trunk/src/rtmp/srs_protocol_handshake.hpp
查看文件 @
c63ad48
...
...
@@ -97,6 +97,78 @@ namespace srs
int
random1_size
;
};
// the digest key generate size.
#define OpensslHashSize 512
extern
u_int8_t
SrsGenuineFMSKey
[];
extern
u_int8_t
SrsGenuineFPKey
[];
int
openssl_HMACsha256
(
const
void
*
data
,
int
data_size
,
const
void
*
key
,
int
key_size
,
void
*
digest
);
int
openssl_generate_key
(
char
*
_private_key
,
char
*
_public_key
,
int32_t
size
);
// calc the offset of key,
// the key->offset cannot be used as the offset of key.
int
srs_key_block_get_offset
(
key_block
*
key
);
// create new key block data.
// if created, user must free it by srs_key_block_free
void
srs_key_block_init
(
key_block
*
key
);
// parse key block from c1s1.
// if created, user must free it by srs_key_block_free
// @c1s1_key_bytes the key start bytes, maybe c1s1 or c1s1+764
int
srs_key_block_parse
(
key_block
*
key
,
char
*
c1s1_key_bytes
);
// free the block data create by
// srs_key_block_init or srs_key_block_parse
void
srs_key_block_free
(
key_block
*
key
);
// calc the offset of digest,
// the key->offset cannot be used as the offset of digest.
int
srs_digest_block_get_offset
(
digest_block
*
digest
);
// create new digest block data.
// if created, user must free it by srs_digest_block_free
void
srs_digest_block_init
(
digest_block
*
digest
);
// parse digest block from c1s1.
// if created, user must free it by srs_digest_block_free
// @c1s1_digest_bytes the digest start bytes, maybe c1s1 or c1s1+764
int
srs_digest_block_parse
(
digest_block
*
digest
,
char
*
c1s1_digest_bytes
);
// free the block data create by
// srs_digest_block_init or srs_digest_block_parse
void
srs_digest_block_free
(
digest_block
*
digest
);
/**
* copy whole c1s1 to bytes.
*/
void
srs_schema0_copy_to
(
char
*
bytes
,
bool
with_digest
,
int32_t
time
,
int32_t
version
,
key_block
*
key
,
digest_block
*
digest
);
void
srs_schema1_copy_to
(
char
*
bytes
,
bool
with_digest
,
int32_t
time
,
int32_t
version
,
digest_block
*
digest
,
key_block
*
key
);
/**
* c1s1 is splited by digest:
* c1s1-part1: n bytes (time, version, key and digest-part1).
* digest-data: 32bytes
* c1s1-part2: (1536-n-32)bytes (digest-part2)
* @return a new allocated bytes, user must free it.
*/
char
*
srs_bytes_join_schema0
(
int32_t
time
,
int32_t
version
,
key_block
*
key
,
digest_block
*
digest
);
/**
* c1s1 is splited by digest:
* c1s1-part1: n bytes (time, version and digest-part1).
* digest-data: 32bytes
* c1s1-part2: (1536-n-32)bytes (digest-part2 and key)
* @return a new allocated bytes, user must free it.
*/
char
*
srs_bytes_join_schema1
(
int32_t
time
,
int32_t
version
,
digest_block
*
digest
,
key_block
*
key
);
/**
* compare the memory in bytes.
*/
bool
srs_bytes_equals
(
void
*
pa
,
void
*
pb
,
int
size
);
/**
* c1s1 schema0
* time: 4bytes
...
...
@@ -236,41 +308,14 @@ namespace srs
*/
virtual
int
s2_validate
(
c1s1
*
c1
,
bool
&
is_valid
);
};
/**
* compare the memory in bytes.
*/
bool
srs_bytes_equals
(
void
*
pa
,
void
*
pb
,
int
size
);
/**
* c1s1 is splited by digest:
* c1s1-part1: n bytes (time, version, key and digest-part1).
* digest-data: 32bytes
* c1s1-part2: (1536-n-32)bytes (digest-part2)
* @return a new allocated bytes, user must free it.
*/
char
*
srs_bytes_join_schema0
(
int32_t
time
,
int32_t
version
,
key_block
*
key
,
digest_block
*
digest
);
/**
* c1s1 is splited by digest:
* c1s1-part1: n bytes (time, version and digest-part1).
* digest-data: 32bytes
* c1s1-part2: (1536-n-32)bytes (digest-part2 and key)
* @return a new allocated bytes, user must free it.
*/
char
*
srs_bytes_join_schema1
(
int32_t
time
,
int32_t
version
,
digest_block
*
digest
,
key_block
*
key
);
// the digest key generate size.
#define OpensslHashSize 512
extern
u_int8_t
SrsGenuineFMSKey
[];
extern
u_int8_t
SrsGenuineFPKey
[];
int
openssl_HMACsha256
(
const
void
*
data
,
int
data_size
,
const
void
*
key
,
int
key_size
,
void
*
digest
);
}
#endif
/**
* try complex handshake, if failed, fallback to simple handshake.
* simple handshake.
* user can try complex handshake first,
* rollback to simple handshake if error ERROR_RTMP_TRY_SIMPLE_HS
*/
class
SrsSimpleHandshake
{
...
...
trunk/src/utest/srs_utest.cpp
查看文件 @
c63ad48
...
...
@@ -36,6 +36,77 @@ ISrsThreadContext* _srs_context = new ISrsThreadContext();
SrsConfig
*
_srs_config
=
NULL
;
SrsServer
*
_srs_server
=
NULL
;
MockEmptyIO
::
MockEmptyIO
()
{
}
MockEmptyIO
::~
MockEmptyIO
()
{
}
bool
MockEmptyIO
::
is_never_timeout
(
int64_t
/*timeout_us*/
)
{
return
true
;
}
int
MockEmptyIO
::
read_fully
(
const
void
*
/*buf*/
,
size_t
/*size*/
,
ssize_t
*
/*nread*/
)
{
return
ERROR_SUCCESS
;
}
int
MockEmptyIO
::
write
(
const
void
*
/*buf*/
,
size_t
/*size*/
,
ssize_t
*
/*nwrite*/
)
{
return
ERROR_SUCCESS
;
}
void
MockEmptyIO
::
set_recv_timeout
(
int64_t
/*timeout_us*/
)
{
}
int64_t
MockEmptyIO
::
get_recv_timeout
()
{
return
-
1
;
}
int64_t
MockEmptyIO
::
get_recv_bytes
()
{
return
-
1
;
}
int
MockEmptyIO
::
get_recv_kbps
()
{
return
0
;
}
void
MockEmptyIO
::
set_send_timeout
(
int64_t
/*timeout_us*/
)
{
}
int64_t
MockEmptyIO
::
get_send_timeout
()
{
return
0
;
}
int64_t
MockEmptyIO
::
get_send_bytes
()
{
return
0
;
}
int
MockEmptyIO
::
get_send_kbps
()
{
return
0
;
}
int
MockEmptyIO
::
writev
(
const
iovec
*/
*
iov
*/
,
int
/*iov_size*/
,
ssize_t
*
/*nwrite*/
)
{
return
ERROR_SUCCESS
;
}
int
MockEmptyIO
::
read
(
const
void
*
/*buf*/
,
size_t
/*size*/
,
ssize_t
*
/*nread*/
)
{
return
ERROR_SUCCESS
;
}
// basic test and samples.
VOID
TEST
(
SampleTest
,
FastSampleInt64Test
)
{
...
...
trunk/src/utest/srs_utest.hpp
查看文件 @
c63ad48
...
...
@@ -34,4 +34,36 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// we add an empty macro for upp to show the smart tips.
#define VOID
#include <srs_protocol_io.hpp>
class
MockEmptyIO
:
public
ISrsProtocolReaderWriter
{
public
:
MockEmptyIO
();
virtual
~
MockEmptyIO
();
// for protocol
public:
virtual
bool
is_never_timeout
(
int64_t
timeout_us
);
// for handshake.
public:
virtual
int
read_fully
(
const
void
*
buf
,
size_t
size
,
ssize_t
*
nread
);
virtual
int
write
(
const
void
*
buf
,
size_t
size
,
ssize_t
*
nwrite
);
// for protocol
public:
virtual
void
set_recv_timeout
(
int64_t
timeout_us
);
virtual
int64_t
get_recv_timeout
();
virtual
int64_t
get_recv_bytes
();
virtual
int
get_recv_kbps
();
// for protocol
public:
virtual
void
set_send_timeout
(
int64_t
timeout_us
);
virtual
int64_t
get_send_timeout
();
virtual
int64_t
get_send_bytes
();
virtual
int
get_send_kbps
();
virtual
int
writev
(
const
iovec
*
iov
,
int
iov_size
,
ssize_t
*
nwrite
);
// for protocol/amf0/msg-codec
public:
virtual
int
read
(
const
void
*
buf
,
size_t
size
,
ssize_t
*
nread
);
};
#endif
...
...
trunk/src/utest/srs_utest_handshake.cpp
查看文件 @
c63ad48
...
...
@@ -24,77 +24,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <srs_kernel_error.hpp>
#include <srs_core_autofree.hpp>
MockEmptyIO
::
MockEmptyIO
()
{
}
MockEmptyIO
::~
MockEmptyIO
()
{
}
bool
MockEmptyIO
::
is_never_timeout
(
int64_t
/*timeout_us*/
)
{
return
true
;
}
int
MockEmptyIO
::
read_fully
(
const
void
*
/*buf*/
,
size_t
/*size*/
,
ssize_t
*
/*nread*/
)
{
return
ERROR_SUCCESS
;
}
int
MockEmptyIO
::
write
(
const
void
*
/*buf*/
,
size_t
/*size*/
,
ssize_t
*
/*nwrite*/
)
{
return
ERROR_SUCCESS
;
}
void
MockEmptyIO
::
set_recv_timeout
(
int64_t
/*timeout_us*/
)
{
}
int64_t
MockEmptyIO
::
get_recv_timeout
()
{
return
-
1
;
}
int64_t
MockEmptyIO
::
get_recv_bytes
()
{
return
-
1
;
}
int
MockEmptyIO
::
get_recv_kbps
()
{
return
0
;
}
void
MockEmptyIO
::
set_send_timeout
(
int64_t
/*timeout_us*/
)
{
}
int64_t
MockEmptyIO
::
get_send_timeout
()
{
return
0
;
}
int64_t
MockEmptyIO
::
get_send_bytes
()
{
return
0
;
}
int
MockEmptyIO
::
get_send_kbps
()
{
return
0
;
}
int
MockEmptyIO
::
writev
(
const
iovec
*/
*
iov
*/
,
int
/*iov_size*/
,
ssize_t
*
/*nwrite*/
)
{
return
ERROR_SUCCESS
;
}
int
MockEmptyIO
::
read
(
const
void
*
/*buf*/
,
size_t
/*size*/
,
ssize_t
*
/*nread*/
)
{
return
ERROR_SUCCESS
;
}
#include <srs_protocol_utility.hpp>
// verify the sha256
VOID
TEST
(
HandshakeTest
,
OpensslSha256
)
...
...
@@ -124,6 +54,37 @@ VOID TEST(HandshakeTest, OpensslSha256)
EXPECT_TRUE
(
srs_bytes_equals
(
digest
,
expect_digest
,
32
));
}
// verify the dh key
VOID
TEST
(
HandshakeTest
,
DHKey
)
{
char
pri_key
[]
=
{
0x6e
,
0x65
,
0x69
,
0x2d
,
0x69
,
0x2d
,
0x69
,
0x73
,
0x6e
,
0x69
,
0x73
,
0x6c
,
0x65
,
0x72
,
0x69
,
0x72
,
0x76
,
0x65
,
0x72
,
0x69
,
0x77
,
0x74
,
0x2e
,
0x6e
,
0x72
,
0x76
,
0x72
,
0x65
,
0x72
,
0x70
,
0x72
,
0x69
,
0x69
,
0x70
,
0x72
,
0x73
,
0x6e
,
0x65
,
0x72
,
0x72
,
0x6e
,
0x2d
,
0x65
,
0x74
,
0x72
,
0x6c
,
0x69
,
0x74
,
0x69
,
0x65
,
0x40
,
0x69
,
0x69
,
0x76
,
0x77
,
0x2d
,
0x73
,
0x65
,
0x72
,
0x72
,
0x76
,
0x73
,
0x72
,
0x2e
,
0x2d
,
0x76
,
0x65
,
0x31
,
0x65
,
0x6d
,
0x6d
,
0x73
,
0x69
,
0x73
,
0x74
,
0x2e
,
0x74
,
0x72
,
0x65
,
0x65
,
0x72
,
0x65
,
0x2d
,
0x74
,
0x69
,
0x31
,
0x65
,
0x2d
,
0x6f
,
0x77
,
0x2e
,
0x76
,
0x77
,
0x2d
,
0x77
,
0x72
,
0x65
,
0x65
,
0x31
,
0x74
,
0x73
,
0x70
,
0x74
,
0x6e
,
0x72
,
0x6e
,
0x73
,
0x6d
,
0x2e
,
0x69
,
0x72
,
0x2d
,
0x65
,
0x69
,
0x77
,
0x69
,
0x76
,
0x72
,
0x77
,
0x72
,
0x32
,
0x6e
,
0x65
,
0x6c
,
0x2e
,
0x2d
,
0x6e
,
0x69
};
char
pub_key1
[
128
];
openssl_generate_key
(
pri_key
,
pub_key1
,
128
);
char
pub_key2
[
128
];
openssl_generate_key
(
pri_key
,
pub_key2
,
128
);
EXPECT_FALSE
(
srs_bytes_equals
(
pub_key1
,
pub_key2
,
128
));
}
// flash will sendout a c0c1 encrypt by ssl.
VOID
TEST
(
HandshakeTest
,
VerifyFPC0C1
)
{
...
...
@@ -172,7 +133,7 @@ VOID TEST(HandshakeTest, VerifyFPC0C1)
0xb1
,
0xb5
,
0xbc
,
0xa6
,
0xd6
,
0xd6
,
0x1d
,
0xce
,
0x93
,
0x78
,
0xb3
,
0xec
,
0xa8
,
0x64
,
0x19
,
0x13
};
EXPECT_TRUE
(
srs_bytes_equals
(
c1
.
block1
.
digest
.
digest
,
digest
,
32
));
}
}
VOID
TEST
(
HandshakeTest
,
SimpleHandshake
)
{
...
...
@@ -260,3 +221,19 @@ VOID TEST(HandshakeTest, ComplexHandshake)
ASSERT_TRUE
(
is_valid
);
}
}
VOID
TEST
(
HandshakeTest
,
BytesEqual
)
{
char
a1
[]
=
{
0x01
};
char
b1
[]
=
{
0x02
};
char
a2
[]
=
{
0x01
,
0x02
};
char
b2
[]
=
{
0x02
,
0x03
};
EXPECT_TRUE
(
srs_bytes_equals
(
NULL
,
NULL
,
0
));
EXPECT_FALSE
(
srs_bytes_equals
(
a1
,
NULL
,
1
));
EXPECT_FALSE
(
srs_bytes_equals
(
NULL
,
a1
,
1
));
EXPECT_FALSE
(
srs_bytes_equals
(
a1
,
b1
,
1
));
EXPECT_TRUE
(
srs_bytes_equals
(
a1
,
a1
,
1
));
EXPECT_TRUE
(
srs_bytes_equals
(
a1
,
a2
,
1
));
EXPECT_FALSE
(
srs_bytes_equals
(
a1
,
b2
,
1
));
}
...
...
trunk/src/utest/srs_utest_handshake.hpp
查看文件 @
c63ad48
...
...
@@ -29,39 +29,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <srs_utest.hpp>
#include <srs_protocol_io.hpp>
#include <srs_protocol_rtmp.hpp>
#include <srs_protocol_handshake.hpp>
using
namespace
srs
;
class
MockEmptyIO
:
public
ISrsProtocolReaderWriter
{
public
:
MockEmptyIO
();
virtual
~
MockEmptyIO
();
// for protocol
public:
virtual
bool
is_never_timeout
(
int64_t
timeout_us
);
// for handshake.
public:
virtual
int
read_fully
(
const
void
*
buf
,
size_t
size
,
ssize_t
*
nread
);
virtual
int
write
(
const
void
*
buf
,
size_t
size
,
ssize_t
*
nwrite
);
// for protocol
public:
virtual
void
set_recv_timeout
(
int64_t
timeout_us
);
virtual
int64_t
get_recv_timeout
();
virtual
int64_t
get_recv_bytes
();
virtual
int
get_recv_kbps
();
// for protocol
public:
virtual
void
set_send_timeout
(
int64_t
timeout_us
);
virtual
int64_t
get_send_timeout
();
virtual
int64_t
get_send_bytes
();
virtual
int
get_send_kbps
();
virtual
int
writev
(
const
iovec
*
iov
,
int
iov_size
,
ssize_t
*
nwrite
);
// for protocol/amf0/msg-codec
public:
virtual
int
read
(
const
void
*
buf
,
size_t
size
,
ssize_t
*
nread
);
};
#endif
...
...
请
注册
或
登录
后发表评论