1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-02-15 04:42:04 +00:00
srs/trunk/src/rtmp/srs_protocol_handshake.cpp

1160 lines
32 KiB
C++
Raw Normal View History

2013-11-23 03:36:07 +00:00
/*
The MIT License (MIT)
Copyright (c) 2013-2014 winlin
2013-11-23 03:36:07 +00:00
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <srs_protocol_handshake.hpp>
2013-11-23 03:36:07 +00:00
#include <time.h>
#include <stdlib.h>
#include <srs_core_autofree.hpp>
#include <srs_kernel_error.hpp>
#include <srs_kernel_log.hpp>
#include <srs_protocol_io.hpp>
2013-11-23 03:36:07 +00:00
using namespace srs;
2013-11-23 03:36:07 +00:00
void srs_random_generate(char* bytes, int size)
{
2014-03-18 03:32:58 +00:00
static char cdata[] = {
0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2d, 0x72, 0x74, 0x6d, 0x70, 0x2d, 0x73, 0x65,
0x72, 0x76, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x2d, 0x77, 0x69,
0x6e, 0x74, 0x65, 0x72, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x40, 0x31, 0x32, 0x36,
0x2e, 0x63, 0x6f, 0x6d
};
for (int i = 0; i < size; i++) {
bytes[i] = cdata[rand() % (sizeof(cdata) - 1)];
}
2013-11-23 03:36:07 +00:00
}
2013-11-27 14:41:58 +00:00
#ifdef SRS_SSL
2013-11-23 03:36:07 +00:00
// 68bytes FMS key which is used to sign the sever packet.
u_int8_t srs::SrsGenuineFMSKey[] = {
2013-11-23 03:36:07 +00:00
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[] = {
2013-11-23 03:36:07 +00:00
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
#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)
{
2013-11-23 03:36:07 +00:00
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;
}
#include <openssl/dh.h>
#define RFC2409_PRIME_1024 \
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \
"FFFFFFFFFFFFFFFF"
int __openssl_generate_key(
2014-03-18 03:32:58 +00:00
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
2013-11-23 03:36:07 +00:00
){
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
2013-11-23 03:36:07 +00:00
//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;
2014-03-18 03:32:58 +00:00
return ret;
2013-11-23 03:36:07 +00:00
}
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(
2014-03-18 03:32:58 +00:00
(u_int8_t*&)_private_key, (u_int8_t*&)_public_key, size,
pdh, bits_count, shared_key, shared_key_length, peer_public_key
2013-11-23 03:36:07 +00:00
);
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)
{
2014-03-18 03:32:58 +00:00
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;
2013-11-23 03:36:07 +00:00
}
// create new key block data.
// if created, user must free it by srs_key_block_free
void srs_key_block_init(key_block* key)
{
2014-03-18 03:32:58 +00:00
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);
}
2013-11-23 03:36:07 +00:00
}
// 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)
{
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
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;
2013-11-23 03:36:07 +00:00
}
// free the block data create by
// srs_key_block_init or srs_key_block_parse
void srs_key_block_free(key_block* key)
{
2014-03-18 03:32:58 +00:00
if (key->random0) {
srs_freepa(key->random0);
}
if (key->random1) {
srs_freepa(key->random1);
}
2013-11-23 03:36:07 +00:00
}
// 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)
{
2014-03-18 03:32:58 +00:00
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;
2013-11-23 03:36:07 +00:00
}
// create new digest block data.
// if created, user must free it by srs_digest_block_free
void srs_digest_block_init(digest_block* digest)
{
2014-03-18 03:32:58 +00:00
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);
}
2013-11-23 03:36:07 +00:00
}
// 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)
{
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
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;
2013-11-23 03:36:07 +00:00
}
// free the block data create by
// srs_digest_block_init or srs_digest_block_parse
void srs_digest_block_free(digest_block* digest)
{
2014-03-18 03:32:58 +00:00
if (digest->random0) {
srs_freepa(digest->random0);
}
if (digest->random1) {
srs_freepa(digest->random1);
}
2013-11-23 03:36:07 +00:00
}
void __srs_time_copy_to(char*& pp, int32_t time)
{
2014-03-18 03:32:58 +00:00
// 4bytes time
*(int32_t*)pp = time;
pp += 4;
2013-11-23 03:36:07 +00:00
}
void __srs_version_copy_to(char*& pp, int32_t version)
{
2014-03-18 03:32:58 +00:00
// 4bytes version
*(int32_t*)pp = version;
pp += 4;
2013-11-23 03:36:07 +00:00
}
void __srs_key_copy_to(char*& pp, key_block* key)
{
2014-03-18 03:32:58 +00:00
// 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;
2013-11-23 03:36:07 +00:00
}
void __srs_digest_copy_to(char*& pp, digest_block* digest, bool with_digest)
{
2014-03-18 03:32:58 +00:00
// 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;
2013-11-23 03:36:07 +00:00
}
/**
* copy whole c1s1 to bytes.
*/
void srs_schema0_copy_to(char* bytes, bool with_digest,
2014-03-18 03:32:58 +00:00
int32_t time, int32_t version, key_block* key, digest_block* digest)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
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);
}
2013-11-23 03:36:07 +00:00
}
void srs_schema1_copy_to(char* bytes, bool with_digest,
2014-03-18 03:32:58 +00:00
int32_t time, int32_t version, digest_block* digest, key_block* key)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
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);
}
2013-11-23 03:36:07 +00:00
}
2013-11-23 03:36:07 +00:00
/**
* c1s1 is splited by digest:
2014-03-18 03:32:58 +00:00
* c1s1-part1: n bytes (time, version, key and digest-part1).
* digest-data: 32bytes
* c1s1-part2: (1536-n-32)bytes (digest-part2)
2013-11-23 03:36:07 +00:00
*/
char* srs::srs_bytes_join_schema0(int32_t time, int32_t version, key_block* key, digest_block* digest)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
char* bytes = new char[1536 -32];
srs_schema0_copy_to(bytes, false, time, version, key, digest);
return bytes;
2013-11-23 03:36:07 +00:00
}
2013-11-23 03:36:07 +00:00
/**
* c1s1 is splited by digest:
2014-03-18 03:32:58 +00:00
* c1s1-part1: n bytes (time, version and digest-part1).
* digest-data: 32bytes
* c1s1-part2: (1536-n-32)bytes (digest-part2 and key)
2013-11-23 03:36:07 +00:00
*/
char* srs::srs_bytes_join_schema1(int32_t time, int32_t version, digest_block* digest, key_block* key)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
char* bytes = new char[1536 -32];
srs_schema1_copy_to(bytes, false, time, version, digest, key);
return bytes;
2013-11-23 03:36:07 +00:00
}
/**
* compare the memory in bytes.
*/
bool srs::srs_bytes_equals(void* pa, void* pb, int size)
{
2014-03-18 03:32:58 +00:00
u_int8_t* a = (u_int8_t*)pa;
u_int8_t* b = (u_int8_t*)pb;
2013-11-23 03:36:07 +00:00
for(int i = 0; i < size; i++){
if(a[i] != b[i]){
return false;
}
}
return true;
}
c2s2::c2s2()
{
2014-03-18 03:32:58 +00:00
srs_random_generate(random, 1504);
srs_random_generate(digest, 32);
2013-11-23 03:36:07 +00:00
}
c2s2::~c2s2()
{
}
void c2s2::dump(char* _c2s2)
{
2014-03-18 03:32:58 +00:00
memcpy(_c2s2, random, 1504);
memcpy(_c2s2 + 1504, digest, 32);
2013-11-23 03:36:07 +00:00
}
int c2s2::c2_create(c1s1* s1)
{
2014-03-18 03:32:58 +00:00
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;
2013-11-23 03:36:07 +00:00
}
int c2s2::s2_create(c1s1* c1)
{
2014-03-18 03:32:58 +00:00
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;
}
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("generate s2 digest success.");
memcpy(digest, _digest, 32);
return ret;
2013-11-23 03:36:07 +00:00
}
c1s1::c1s1()
{
2014-03-18 03:32:58 +00:00
schema = srs_schema_invalid;
2013-11-23 03:36:07 +00:00
}
c1s1::~c1s1()
{
2014-03-18 03:32:58 +00:00
destroy_blocks();
2013-11-23 03:36:07 +00:00
}
char* c1s1::get_digest()
{
2014-03-18 03:32:58 +00:00
srs_assert(schema != srs_schema_invalid);
if (schema == srs_schema0) {
return block1.digest.digest;
} else {
return block0.digest.digest;
}
2013-11-23 03:36:07 +00:00
}
void c1s1::dump(char* _c1s1)
{
2014-03-18 03:32:58 +00:00
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);
}
2013-11-23 03:36:07 +00:00
}
int c1s1::c1_create(srs_schema_type _schema)
{
2014-03-18 03:32:58 +00:00
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;
2013-11-23 03:36:07 +00:00
}
int c1s1::c1_parse(char* _c1s1, srs_schema_type _schema)
{
2014-03-18 03:32:58 +00:00
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;
2013-11-23 03:36:07 +00:00
}
int c1s1::c1_validate_digest(bool& is_valid)
{
2014-03-18 03:32:58 +00:00
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;
2013-11-23 03:36:07 +00:00
}
2014-03-19 05:10:25 +00:00
int c1s1::s1_validate_digest(bool& is_valid)
{
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;
}
2013-11-23 03:36:07 +00:00
int c1s1::s1_create(c1s1* c1)
{
2014-03-18 03:32:58 +00:00
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;
}
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 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;
2013-11-23 03:36:07 +00:00
}
int c1s1::calc_s1_digest(char*& digest)
{
2014-03-18 03:32:58 +00:00
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);
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;
2013-11-23 03:36:07 +00:00
}
int c1s1::calc_c1_digest(char*& digest)
{
2014-03-18 03:32:58 +00:00
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);
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;
2013-11-23 03:36:07 +00:00
}
void c1s1::destroy_blocks()
{
2014-03-18 03:32:58 +00:00
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);
}
2013-11-23 03:36:07 +00:00
}
2013-11-27 14:41:58 +00:00
#endif
2013-11-23 03:36:07 +00:00
SrsSimpleHandshake::SrsSimpleHandshake()
{
}
SrsSimpleHandshake::~SrsSimpleHandshake()
{
}
2014-03-02 04:35:15 +00:00
int SrsSimpleHandshake::handshake_with_client(ISrsProtocolReaderWriter* skt, SrsComplexHandshake* complex_hs)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
2013-11-23 03:36:07 +00:00
ssize_t nsize;
char* c0c1 = new char[1537];
SrsAutoFree(char, c0c1, true);
if ((ret = skt->read_fully(c0c1, 1537, &nsize)) != ERROR_SUCCESS) {
2013-11-23 03:36:07 +00:00
srs_warn("read c0c1 failed. ret=%d", ret);
return ret;
}
srs_verbose("read c0c1 success.");
2014-03-18 03:32:58 +00:00
// plain text required.
if (c0c1[0] != 0x03) {
ret = ERROR_RTMP_PLAIN_REQUIRED;
srs_warn("only support rtmp plain text. ret=%d", ret);
return ret;
}
2013-11-23 03:36:07 +00:00
srs_verbose("check c0 success, required plain text.");
// try complex handshake
2014-03-02 04:35:15 +00:00
if (complex_hs) {
2014-03-18 03:32:58 +00:00
ret = complex_hs->handshake_with_client(skt, c0c1 + 1);
if (ret == ERROR_SUCCESS) {
srs_trace("complex handshake success.");
return ret;
}
if (ret != ERROR_RTMP_TRY_SIMPLE_HS) {
srs_error("complex handshake failed. ret=%d", ret);
return ret;
}
srs_info("rollback complex to simple handshake. ret=%d", ret);
}
char* s0s1s2 = new char[3073];
srs_random_generate(s0s1s2, 3073);
2013-11-23 03:36:07 +00:00
SrsAutoFree(char, s0s1s2, true);
2014-03-18 03:32:58 +00:00
// plain text required.
2013-11-23 03:36:07 +00:00
s0s1s2[0] = 0x03;
if ((ret = skt->write(s0s1s2, 3073, &nsize)) != ERROR_SUCCESS) {
2013-11-23 03:36:07 +00:00
srs_warn("simple handshake send s0s1s2 failed. ret=%d", ret);
return ret;
}
srs_verbose("simple handshake send s0s1s2 success.");
char* c2 = new char[1536];
SrsAutoFree(char, c2, true);
if ((ret = skt->read_fully(c2, 1536, &nsize)) != ERROR_SUCCESS) {
2013-11-23 03:36:07 +00:00
srs_warn("simple handshake read c2 failed. ret=%d", ret);
return ret;
}
srs_verbose("simple handshake read c2 success.");
srs_trace("simple handshake success.");
2014-03-18 03:32:58 +00:00
return ret;
2013-11-23 03:36:07 +00:00
}
2014-03-02 04:35:15 +00:00
int SrsSimpleHandshake::handshake_with_server(ISrsProtocolReaderWriter* skt, SrsComplexHandshake* complex_hs)
2013-11-29 07:07:05 +00:00
{
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
2013-11-29 07:07:05 +00:00
// try complex handshake
2014-03-02 04:35:15 +00:00
if (complex_hs) {
2014-03-18 03:32:58 +00:00
ret = complex_hs->handshake_with_server(skt);
if (ret == ERROR_SUCCESS) {
srs_trace("complex handshake success.");
return ret;
}
if (ret != ERROR_RTMP_TRY_SIMPLE_HS) {
srs_error("complex handshake failed. ret=%d", ret);
return ret;
}
srs_info("rollback complex to simple handshake. ret=%d", ret);
}
// simple handshake
2013-11-29 07:07:05 +00:00
ssize_t nsize;
char* c0c1 = new char[1537];
SrsAutoFree(char, c0c1, true);
2014-03-18 03:32:58 +00:00
srs_random_generate(c0c1, 1537);
// plain text required.
c0c1[0] = 0x03;
if ((ret = skt->write(c0c1, 1537, &nsize)) != ERROR_SUCCESS) {
2013-11-29 07:07:05 +00:00
srs_warn("write c0c1 failed. ret=%d", ret);
return ret;
}
srs_verbose("write c0c1 success.");
2014-03-18 03:32:58 +00:00
char* s0s1s2 = new char[3073];
2013-11-29 07:07:05 +00:00
SrsAutoFree(char, s0s1s2, true);
if ((ret = skt->read_fully(s0s1s2, 3073, &nsize)) != ERROR_SUCCESS) {
2013-11-29 07:07:05 +00:00
srs_warn("simple handshake recv s0s1s2 failed. ret=%d", ret);
return ret;
}
srs_verbose("simple handshake recv s0s1s2 success.");
2014-03-18 03:32:58 +00:00
// plain text required.
2013-11-29 07:07:05 +00:00
if (s0s1s2[0] != 0x03) {
ret = ERROR_RTMP_HANDSHAKE;
srs_warn("handshake failed, plain text required. ret=%d", ret);
return ret;
}
char* c2 = new char[1536];
SrsAutoFree(char, c2, true);
2014-03-18 03:32:58 +00:00
srs_random_generate(c2, 1536);
if ((ret = skt->write(c2, 1536, &nsize)) != ERROR_SUCCESS) {
2013-11-29 07:07:05 +00:00
srs_warn("simple handshake write c2 failed. ret=%d", ret);
return ret;
}
srs_verbose("simple handshake write c2 success.");
srs_trace("simple handshake success.");
2014-03-18 03:32:58 +00:00
return ret;
2013-11-29 07:07:05 +00:00
}
2013-11-23 03:36:07 +00:00
SrsComplexHandshake::SrsComplexHandshake()
{
}
SrsComplexHandshake::~SrsComplexHandshake()
{
}
2013-11-27 14:41:58 +00:00
#ifndef SRS_SSL
int SrsComplexHandshake::handshake_with_client(ISrsProtocolReaderWriter* /*skt*/, char* /*_c1*/)
2013-11-27 14:41:58 +00:00
{
2014-03-18 09:44:43 +00:00
srs_trace("directly use simple handshake for ssl disabled.");
2014-03-18 03:32:58 +00:00
return ERROR_RTMP_TRY_SIMPLE_HS;
2013-11-27 14:41:58 +00:00
}
#else
int SrsComplexHandshake::handshake_with_client(ISrsProtocolReaderWriter* skt, char* _c1)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
2013-11-27 14:41:58 +00:00
2013-11-23 03:36:07 +00:00
ssize_t nsize;
2014-03-18 03:32:58 +00:00
static bool _random_initialized = false;
if (!_random_initialized) {
srand(0);
_random_initialized = true;
srs_trace("srand initialized the random.");
}
// decode c1
c1s1 c1;
// try schema0.
if ((ret = c1.c1_parse(_c1, srs_schema0)) != ERROR_SUCCESS) {
srs_error("parse c1 schema%d error. ret=%d", srs_schema0, ret);
return ret;
}
// try schema1
bool is_valid = false;
if ((ret = c1.c1_validate_digest(is_valid)) != ERROR_SUCCESS || !is_valid) {
if ((ret = c1.c1_parse(_c1, srs_schema1)) != ERROR_SUCCESS) {
srs_error("parse c1 schema%d error. ret=%d", srs_schema1, ret);
return ret;
}
if ((ret = c1.c1_validate_digest(is_valid)) != ERROR_SUCCESS || !is_valid) {
ret = ERROR_RTMP_TRY_SIMPLE_HS;
srs_info("all schema valid failed, try simple handshake. ret=%d", ret);
return ret;
}
}
srs_verbose("decode c1 success.");
// encode s1
c1s1 s1;
if ((ret = s1.s1_create(&c1)) != ERROR_SUCCESS) {
srs_error("create s1 from c1 failed. ret=%d", ret);
return ret;
}
srs_verbose("create s1 from c1 success.");
2014-03-19 05:10:25 +00:00
// verify s1
if ((ret = s1.s1_validate_digest(is_valid)) != ERROR_SUCCESS || !is_valid) {
ret = ERROR_RTMP_TRY_SIMPLE_HS;
srs_info("valid s1 failed, try simple handshake. ret=%d", ret);
return ret;
}
srs_verbose("verify s1 from c1 success.");
2014-03-18 03:32:58 +00:00
c2s2 s2;
if ((ret = s2.s2_create(&c1)) != ERROR_SUCCESS) {
srs_error("create s2 from c1 failed. ret=%d", ret);
return ret;
}
srs_verbose("create s2 from c1 success.");
// sendout s0s1s2
char* s0s1s2 = new char[3073];
2013-11-23 03:36:07 +00:00
SrsAutoFree(char, s0s1s2, true);
2014-03-18 03:32:58 +00:00
// plain text required.
s0s1s2[0] = 0x03;
s1.dump(s0s1s2 + 1);
s2.dump(s0s1s2 + 1537);
if ((ret = skt->write(s0s1s2, 3073, &nsize)) != ERROR_SUCCESS) {
2013-11-23 03:36:07 +00:00
srs_warn("complex handshake send s0s1s2 failed. ret=%d", ret);
return ret;
}
srs_verbose("complex handshake send s0s1s2 success.");
// recv c2
char* c2 = new char[1536];
SrsAutoFree(char, c2, true);
if ((ret = skt->read_fully(c2, 1536, &nsize)) != ERROR_SUCCESS) {
2013-11-23 03:36:07 +00:00
srs_warn("complex handshake read c2 failed. ret=%d", ret);
return ret;
}
srs_verbose("complex handshake read c2 success.");
2014-03-18 03:32:58 +00:00
return ret;
2013-11-23 03:36:07 +00:00
}
2013-11-27 14:41:58 +00:00
#endif
2013-11-23 03:36:07 +00:00
2013-11-29 07:07:05 +00:00
#ifndef SRS_SSL
int SrsComplexHandshake::handshake_with_server(ISrsProtocolReaderWriter* /*skt*/)
2013-11-29 07:07:05 +00:00
{
2014-03-18 03:32:58 +00:00
return ERROR_RTMP_TRY_SIMPLE_HS;
2013-11-29 07:07:05 +00:00
}
#else
int SrsComplexHandshake::handshake_with_server(ISrsProtocolReaderWriter* /*skt*/)
2013-11-29 07:07:05 +00:00
{
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
// TODO: implements complex handshake.
ret = ERROR_RTMP_TRY_SIMPLE_HS;
return ret;
2013-11-29 07:07:05 +00:00
}
#endif