support h264/avc codec by rtmp complex handshake(SrsComplexHandshake)
正在显示
8 个修改的文件
包含
1030 行增加
和
28 行删除
| @@ -105,7 +105,7 @@ MAIN_ENTRANCES=("srs_main_server") | @@ -105,7 +105,7 @@ MAIN_ENTRANCES=("srs_main_server") | ||
| 105 | # srs(simple rtmp server) over st(state-threads) | 105 | # srs(simple rtmp server) over st(state-threads) |
| 106 | ModuleLibFiles=(${LibSTfile}) | 106 | ModuleLibFiles=(${LibSTfile}) |
| 107 | MODULE_OBJS="${CORE_OBJS[@]} ${CONFIG_OBJS[@]} ${PROTOCOL_OBJS[@]} ${MAIN_OBJS[@]}" | 107 | MODULE_OBJS="${CORE_OBJS[@]} ${CONFIG_OBJS[@]} ${PROTOCOL_OBJS[@]} ${MAIN_OBJS[@]}" |
| 108 | -BUILD_KEY="simple_rtmp_server" APP_MAIN="srs_main_server" APP_NAME="simple_rtmp_server" LINK_OPTIONS="-ldl" SO_PATH="" . auto/apps.sh | 108 | +BUILD_KEY="simple_rtmp_server" APP_MAIN="srs_main_server" APP_NAME="simple_rtmp_server" LINK_OPTIONS="-ldl -lssl" SO_PATH="" . auto/apps.sh |
| 109 | 109 | ||
| 110 | echo 'configure ok! ' | 110 | echo 'configure ok! ' |
| 111 | 111 |
| @@ -32,6 +32,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -32,6 +32,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 32 | 32 | ||
| 33 | /** | 33 | /** |
| 34 | * Annex E. The FLV File Format | 34 | * Annex E. The FLV File Format |
| 35 | +* @doc update the README.cmd | ||
| 35 | */ | 36 | */ |
| 36 | class SrsCodec | 37 | class SrsCodec |
| 37 | { | 38 | { |
| @@ -28,15 +28,200 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -28,15 +28,200 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 28 | 28 | ||
| 29 | #include <srs_core_error.hpp> | 29 | #include <srs_core_error.hpp> |
| 30 | #include <srs_core_log.hpp> | 30 | #include <srs_core_log.hpp> |
| 31 | +#include <srs_core_auto_free.hpp> | ||
| 32 | +#include <srs_core_socket.hpp> | ||
| 31 | 33 | ||
| 32 | -SrsComplexHandshake::SrsComplexHandshake() | ||
| 33 | -{ | 34 | +// 68bytes FMS key which is used to sign the sever packet. |
| 35 | +u_int8_t SrsGenuineFMSKey[] = { | ||
| 36 | + 0x47, 0x65, 0x6e, 0x75, 0x69, 0x6e, 0x65, 0x20, | ||
| 37 | + 0x41, 0x64, 0x6f, 0x62, 0x65, 0x20, 0x46, 0x6c, | ||
| 38 | + 0x61, 0x73, 0x68, 0x20, 0x4d, 0x65, 0x64, 0x69, | ||
| 39 | + 0x61, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, | ||
| 40 | + 0x20, 0x30, 0x30, 0x31, // Genuine Adobe Flash Media Server 001 | ||
| 41 | + 0xf0, 0xee, 0xc2, 0x4a, 0x80, 0x68, 0xbe, 0xe8, | ||
| 42 | + 0x2e, 0x00, 0xd0, 0xd1, 0x02, 0x9e, 0x7e, 0x57, | ||
| 43 | + 0x6e, 0xec, 0x5d, 0x2d, 0x29, 0x80, 0x6f, 0xab, | ||
| 44 | + 0x93, 0xb8, 0xe6, 0x36, 0xcf, 0xeb, 0x31, 0xae | ||
| 45 | +}; // 68 | ||
| 46 | + | ||
| 47 | +// 62bytes FP key which is used to sign the client packet. | ||
| 48 | +u_int8_t SrsGenuineFPKey[] = { | ||
| 49 | + 0x47, 0x65, 0x6E, 0x75, 0x69, 0x6E, 0x65, 0x20, | ||
| 50 | + 0x41, 0x64, 0x6F, 0x62, 0x65, 0x20, 0x46, 0x6C, | ||
| 51 | + 0x61, 0x73, 0x68, 0x20, 0x50, 0x6C, 0x61, 0x79, | ||
| 52 | + 0x65, 0x72, 0x20, 0x30, 0x30, 0x31, // Genuine Adobe Flash Player 001 | ||
| 53 | + 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, | ||
| 54 | + 0x2E, 0x00, 0xD0, 0xD1, 0x02, 0x9E, 0x7E, 0x57, | ||
| 55 | + 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, | ||
| 56 | + 0x93, 0xB8, 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE | ||
| 57 | +}; // 62 | ||
| 58 | + | ||
| 59 | +#include <openssl/evp.h> | ||
| 60 | +#include <openssl/hmac.h> | ||
| 61 | +int openssl_HMACsha256(const void* data, int data_size, const void* key, int key_size, void* digest) { | ||
| 62 | + HMAC_CTX ctx; | ||
| 63 | + | ||
| 64 | + HMAC_CTX_init(&ctx); | ||
| 65 | + HMAC_Init_ex(&ctx, (unsigned char*) key, key_size, EVP_sha256(), NULL); | ||
| 66 | + HMAC_Update(&ctx, (unsigned char *) data, data_size); | ||
| 67 | + | ||
| 68 | + unsigned int digest_size; | ||
| 69 | + HMAC_Final(&ctx, (unsigned char *) digest, &digest_size); | ||
| 70 | + | ||
| 71 | + HMAC_CTX_cleanup(&ctx); | ||
| 72 | + | ||
| 73 | + if (digest_size != 32) { | ||
| 74 | + return ERROR_OpenSslSha256DigestSize; | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + return ERROR_SUCCESS; | ||
| 34 | } | 78 | } |
| 35 | 79 | ||
| 36 | -SrsComplexHandshake::~SrsComplexHandshake() | 80 | +#include <openssl/dh.h> |
| 81 | +#define RFC2409_PRIME_1024 \ | ||
| 82 | + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ | ||
| 83 | + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ | ||
| 84 | + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ | ||
| 85 | + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ | ||
| 86 | + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \ | ||
| 87 | + "FFFFFFFFFFFFFFFF" | ||
| 88 | +int __openssl_generate_key( | ||
| 89 | + u_int8_t*& _private_key, u_int8_t*& _public_key, int32_t& size, | ||
| 90 | + DH*& pdh, int32_t& bits_count, u_int8_t*& shared_key, int32_t& shared_key_length, BIGNUM*& peer_public_key | ||
| 91 | +){ | ||
| 92 | + int ret = ERROR_SUCCESS; | ||
| 93 | + | ||
| 94 | + //1. Create the DH | ||
| 95 | + if ((pdh = DH_new()) == NULL) { | ||
| 96 | + ret = ERROR_OpenSslCreateDH; | ||
| 97 | + return ret; | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + //2. Create his internal p and g | ||
| 101 | + if ((pdh->p = BN_new()) == NULL) { | ||
| 102 | + ret = ERROR_OpenSslCreateP; | ||
| 103 | + return ret; | ||
| 104 | + } | ||
| 105 | + if ((pdh->g = BN_new()) == NULL) { | ||
| 106 | + ret = ERROR_OpenSslCreateG; | ||
| 107 | + return ret; | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + //3. initialize p, g and key length | ||
| 111 | + if (BN_hex2bn(&pdh->p, RFC2409_PRIME_1024) == 0) { | ||
| 112 | + ret = ERROR_OpenSslParseP1024; | ||
| 113 | + return ret; | ||
| 114 | + } | ||
| 115 | + if (BN_set_word(pdh->g, 2) != 1) { | ||
| 116 | + ret = ERROR_OpenSslSetG; | ||
| 117 | + return ret; | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + //4. Set the key length | ||
| 121 | + pdh->length = bits_count; | ||
| 122 | + | ||
| 123 | + //5. Generate private and public key | ||
| 124 | + if (DH_generate_key(pdh) != 1) { | ||
| 125 | + ret = ERROR_OpenSslGenerateDHKeys; | ||
| 126 | + return ret; | ||
| 127 | + } | ||
| 128 | + | ||
| 129 | + // CreateSharedKey | ||
| 130 | + if (pdh == NULL) { | ||
| 131 | + ret = ERROR_OpenSslGenerateDHKeys; | ||
| 132 | + return ret; | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | + if (shared_key_length != 0 || shared_key != NULL) { | ||
| 136 | + ret = ERROR_OpenSslShareKeyComputed; | ||
| 137 | + return ret; | ||
| 138 | + } | ||
| 139 | + | ||
| 140 | + shared_key_length = DH_size(pdh); | ||
| 141 | + if (shared_key_length <= 0 || shared_key_length > 1024) { | ||
| 142 | + ret = ERROR_OpenSslGetSharedKeySize; | ||
| 143 | + return ret; | ||
| 144 | + } | ||
| 145 | + shared_key = new u_int8_t[shared_key_length]; | ||
| 146 | + memset(shared_key, 0, shared_key_length); | ||
| 147 | + | ||
| 148 | + peer_public_key = BN_bin2bn(_private_key, size, 0); | ||
| 149 | + if (peer_public_key == NULL) { | ||
| 150 | + ret = ERROR_OpenSslGetPeerPublicKey; | ||
| 151 | + return ret; | ||
| 152 | + } | ||
| 153 | + | ||
| 154 | + if (DH_compute_key(shared_key, peer_public_key, pdh) == -1) { | ||
| 155 | + ret = ERROR_OpenSslComputeSharedKey; | ||
| 156 | + return ret; | ||
| 157 | + } | ||
| 158 | + | ||
| 159 | + // CopyPublicKey | ||
| 160 | + if (pdh == NULL) { | ||
| 161 | + ret = ERROR_OpenSslComputeSharedKey; | ||
| 162 | + return ret; | ||
| 163 | + } | ||
| 164 | + | ||
| 165 | + int32_t keySize = BN_num_bytes(pdh->pub_key); | ||
| 166 | + if ((keySize <= 0) || (size <= 0) || (keySize > size)) { | ||
| 167 | + //("CopyPublicKey failed due to either invalid DH state or invalid call"); return ret; | ||
| 168 | + ret = ERROR_OpenSslInvalidDHState; | ||
| 169 | + return ret; | ||
| 170 | + } | ||
| 171 | + | ||
| 172 | + if (BN_bn2bin(pdh->pub_key, _public_key) != keySize) { | ||
| 173 | + //("Unable to copy key"); return ret; | ||
| 174 | + ret = ERROR_OpenSslCopyKey; | ||
| 175 | + return ret; | ||
| 176 | + } | ||
| 177 | + | ||
| 178 | + return ret; | ||
| 179 | +} | ||
| 180 | +int openssl_generate_key(char* _private_key, char* _public_key, int32_t size) | ||
| 37 | { | 181 | { |
| 182 | + int ret = ERROR_SUCCESS; | ||
| 183 | + | ||
| 184 | + // Initialize | ||
| 185 | + DH* pdh = NULL; | ||
| 186 | + int32_t bits_count = 1024; | ||
| 187 | + u_int8_t* shared_key = NULL; | ||
| 188 | + int32_t shared_key_length = 0; | ||
| 189 | + BIGNUM* peer_public_key = NULL; | ||
| 190 | + | ||
| 191 | + ret = __openssl_generate_key( | ||
| 192 | + (u_int8_t*&)_private_key, (u_int8_t*&)_public_key, size, | ||
| 193 | + pdh, bits_count, shared_key, shared_key_length, peer_public_key | ||
| 194 | + ); | ||
| 195 | + | ||
| 196 | + if (pdh != NULL) { | ||
| 197 | + if (pdh->p != NULL) { | ||
| 198 | + BN_free(pdh->p); | ||
| 199 | + pdh->p = NULL; | ||
| 200 | + } | ||
| 201 | + if (pdh->g != NULL) { | ||
| 202 | + BN_free(pdh->g); | ||
| 203 | + pdh->g = NULL; | ||
| 204 | + } | ||
| 205 | + DH_free(pdh); | ||
| 206 | + pdh = NULL; | ||
| 207 | + } | ||
| 208 | + | ||
| 209 | + if (shared_key != NULL) { | ||
| 210 | + delete[] shared_key; | ||
| 211 | + shared_key = NULL; | ||
| 212 | + } | ||
| 213 | + | ||
| 214 | + if (peer_public_key != NULL) { | ||
| 215 | + BN_free(peer_public_key); | ||
| 216 | + peer_public_key = NULL; | ||
| 217 | + } | ||
| 218 | + | ||
| 219 | + return ret; | ||
| 38 | } | 220 | } |
| 39 | 221 | ||
| 222 | +// the digest key generate size. | ||
| 223 | +#define OpensslHashSize 512 | ||
| 224 | + | ||
| 40 | /** | 225 | /** |
| 41 | * 764bytes key结构 | 226 | * 764bytes key结构 |
| 42 | * random-data: (offset)bytes | 227 | * random-data: (offset)bytes |
| @@ -60,11 +245,99 @@ struct key_block | @@ -60,11 +245,99 @@ struct key_block | ||
| 60 | // 4bytes | 245 | // 4bytes |
| 61 | int32_t offset; | 246 | int32_t offset; |
| 62 | }; | 247 | }; |
| 248 | +// calc the offset of key, | ||
| 249 | +// the key->offset cannot be used as the offset of key. | ||
| 250 | +int srs_key_block_get_offset(key_block* key) | ||
| 251 | +{ | ||
| 252 | + int max_offset_size = 764 - 128 - 4; | ||
| 253 | + | ||
| 254 | + int offset = 0; | ||
| 255 | + u_int8_t* pp = (u_int8_t*)&key->offset; | ||
| 256 | + offset += *pp++; | ||
| 257 | + offset += *pp++; | ||
| 258 | + offset += *pp++; | ||
| 259 | + offset += *pp++; | ||
| 260 | + | ||
| 261 | + return offset % max_offset_size; | ||
| 262 | +} | ||
| 263 | +// create new key block data. | ||
| 264 | +// if created, user must free it by srs_key_block_free | ||
| 63 | void srs_key_block_init(key_block* key) | 265 | void srs_key_block_init(key_block* key) |
| 64 | { | 266 | { |
| 267 | + key->offset = (int32_t)rand(); | ||
| 268 | + key->random0 = NULL; | ||
| 269 | + key->random1 = NULL; | ||
| 270 | + | ||
| 271 | + int offset = srs_key_block_get_offset(key); | ||
| 272 | + srs_assert(offset >= 0); | ||
| 273 | + | ||
| 274 | + key->random0_size = offset; | ||
| 275 | + if (key->random0_size > 0) { | ||
| 276 | + key->random0 = new char[key->random0_size]; | ||
| 277 | + for (int i = 0; i < key->random0_size; i++) { | ||
| 278 | + *(key->random0 + i) = rand() % 256; | ||
| 279 | + } | ||
| 280 | + } | ||
| 281 | + | ||
| 282 | + for (int i = 0; i < (int)sizeof(key->key); i++) { | ||
| 283 | + *(key->key + i) = rand() % 256; | ||
| 284 | + } | ||
| 285 | + | ||
| 286 | + key->random1_size = 764 - offset - 128 - 4; | ||
| 287 | + if (key->random1_size > 0) { | ||
| 288 | + key->random1 = new char[key->random1_size]; | ||
| 289 | + for (int i = 0; i < key->random1_size; i++) { | ||
| 290 | + *(key->random1 + i) = rand() % 256; | ||
| 291 | + } | ||
| 292 | + } | ||
| 65 | } | 293 | } |
| 294 | +// parse key block from c1s1. | ||
| 295 | +// if created, user must free it by srs_key_block_free | ||
| 296 | +// @c1s1_key_bytes the key start bytes, maybe c1s1 or c1s1+764 | ||
| 297 | +int srs_key_block_parse(key_block* key, char* c1s1_key_bytes) | ||
| 298 | +{ | ||
| 299 | + int ret = ERROR_SUCCESS; | ||
| 300 | + | ||
| 301 | + char* pp = c1s1_key_bytes + 764; | ||
| 302 | + | ||
| 303 | + pp -= sizeof(int32_t); | ||
| 304 | + key->offset = *(int32_t*)pp; | ||
| 305 | + | ||
| 306 | + key->random0 = NULL; | ||
| 307 | + key->random1 = NULL; | ||
| 308 | + | ||
| 309 | + int offset = srs_key_block_get_offset(key); | ||
| 310 | + srs_assert(offset >= 0); | ||
| 311 | + | ||
| 312 | + pp = c1s1_key_bytes; | ||
| 313 | + key->random0_size = offset; | ||
| 314 | + if (key->random0_size > 0) { | ||
| 315 | + key->random0 = new char[key->random0_size]; | ||
| 316 | + memcpy(key->random0, pp, key->random0_size); | ||
| 317 | + } | ||
| 318 | + pp += key->random0_size; | ||
| 319 | + | ||
| 320 | + memcpy(key->key, pp, sizeof(key->key)); | ||
| 321 | + pp += sizeof(key->key); | ||
| 322 | + | ||
| 323 | + key->random1_size = 764 - offset - 128 - 4; | ||
| 324 | + if (key->random1_size > 0) { | ||
| 325 | + key->random1 = new char[key->random1_size]; | ||
| 326 | + memcpy(key->random1, pp, key->random1_size); | ||
| 327 | + } | ||
| 328 | + | ||
| 329 | + return ret; | ||
| 330 | +} | ||
| 331 | +// free the block data create by | ||
| 332 | +// srs_key_block_init or srs_key_block_parse | ||
| 66 | void srs_key_block_free(key_block* key) | 333 | void srs_key_block_free(key_block* key) |
| 67 | { | 334 | { |
| 335 | + if (key->random0) { | ||
| 336 | + srs_freepa(key->random0); | ||
| 337 | + } | ||
| 338 | + if (key->random1) { | ||
| 339 | + srs_freepa(key->random1); | ||
| 340 | + } | ||
| 68 | } | 341 | } |
| 69 | 342 | ||
| 70 | /** | 343 | /** |
| @@ -90,11 +363,243 @@ struct digest_block | @@ -90,11 +363,243 @@ struct digest_block | ||
| 90 | char* random1; | 363 | char* random1; |
| 91 | int random1_size; | 364 | int random1_size; |
| 92 | }; | 365 | }; |
| 366 | +// calc the offset of digest, | ||
| 367 | +// the key->offset cannot be used as the offset of digest. | ||
| 368 | +int srs_digest_block_get_offset(digest_block* digest) | ||
| 369 | +{ | ||
| 370 | + int max_offset_size = 764 - 32 - 4; | ||
| 371 | + | ||
| 372 | + int offset = 0; | ||
| 373 | + u_int8_t* pp = (u_int8_t*)&digest->offset; | ||
| 374 | + offset += *pp++; | ||
| 375 | + offset += *pp++; | ||
| 376 | + offset += *pp++; | ||
| 377 | + offset += *pp++; | ||
| 378 | + | ||
| 379 | + return offset % max_offset_size; | ||
| 380 | +} | ||
| 381 | +// create new digest block data. | ||
| 382 | +// if created, user must free it by srs_digest_block_free | ||
| 93 | void srs_digest_block_init(digest_block* digest) | 383 | void srs_digest_block_init(digest_block* digest) |
| 94 | { | 384 | { |
| 385 | + digest->offset = (int32_t)rand(); | ||
| 386 | + digest->random0 = NULL; | ||
| 387 | + digest->random1 = NULL; | ||
| 388 | + | ||
| 389 | + int offset = srs_digest_block_get_offset(digest); | ||
| 390 | + srs_assert(offset >= 0); | ||
| 391 | + | ||
| 392 | + digest->random0_size = offset; | ||
| 393 | + if (digest->random0_size > 0) { | ||
| 394 | + digest->random0 = new char[digest->random0_size]; | ||
| 395 | + for (int i = 0; i < digest->random0_size; i++) { | ||
| 396 | + *(digest->random0 + i) = rand() % 256; | ||
| 397 | + } | ||
| 398 | + } | ||
| 399 | + | ||
| 400 | + for (int i = 0; i < (int)sizeof(digest->digest); i++) { | ||
| 401 | + *(digest->digest + i) = rand() % 256; | ||
| 402 | + } | ||
| 403 | + | ||
| 404 | + digest->random1_size = 764 - 4 - offset - 32; | ||
| 405 | + if (digest->random1_size > 0) { | ||
| 406 | + digest->random1 = new char[digest->random1_size]; | ||
| 407 | + for (int i = 0; i < digest->random1_size; i++) { | ||
| 408 | + *(digest->random1 + i) = rand() % 256; | ||
| 409 | + } | ||
| 410 | + } | ||
| 411 | +} | ||
| 412 | +// parse digest block from c1s1. | ||
| 413 | +// if created, user must free it by srs_digest_block_free | ||
| 414 | +// @c1s1_digest_bytes the digest start bytes, maybe c1s1 or c1s1+764 | ||
| 415 | +int srs_digest_block_parse(digest_block* digest, char* c1s1_digest_bytes) | ||
| 416 | +{ | ||
| 417 | + int ret = ERROR_SUCCESS; | ||
| 418 | + | ||
| 419 | + char* pp = c1s1_digest_bytes; | ||
| 420 | + | ||
| 421 | + digest->offset = *(int32_t*)pp; | ||
| 422 | + pp += sizeof(int32_t); | ||
| 423 | + | ||
| 424 | + digest->random0 = NULL; | ||
| 425 | + digest->random1 = NULL; | ||
| 426 | + | ||
| 427 | + int offset = srs_digest_block_get_offset(digest); | ||
| 428 | + srs_assert(offset >= 0); | ||
| 429 | + | ||
| 430 | + digest->random0_size = offset; | ||
| 431 | + if (digest->random0_size > 0) { | ||
| 432 | + digest->random0 = new char[digest->random0_size]; | ||
| 433 | + memcpy(digest->random0, pp, digest->random0_size); | ||
| 434 | + } | ||
| 435 | + pp += digest->random0_size; | ||
| 436 | + | ||
| 437 | + memcpy(digest->digest, pp, sizeof(digest->digest)); | ||
| 438 | + pp += sizeof(digest->digest); | ||
| 439 | + | ||
| 440 | + digest->random1_size = 764 - 4 - offset - 32; | ||
| 441 | + if (digest->random1_size > 0) { | ||
| 442 | + digest->random1 = new char[digest->random1_size]; | ||
| 443 | + memcpy(digest->random1, pp, digest->random1_size); | ||
| 444 | + } | ||
| 445 | + | ||
| 446 | + return ret; | ||
| 95 | } | 447 | } |
| 448 | +// free the block data create by | ||
| 449 | +// srs_digest_block_init or srs_digest_block_parse | ||
| 96 | void srs_digest_block_free(digest_block* digest) | 450 | void srs_digest_block_free(digest_block* digest) |
| 97 | { | 451 | { |
| 452 | + if (digest->random0) { | ||
| 453 | + srs_freepa(digest->random0); | ||
| 454 | + } | ||
| 455 | + if (digest->random1) { | ||
| 456 | + srs_freepa(digest->random1); | ||
| 457 | + } | ||
| 458 | +} | ||
| 459 | + | ||
| 460 | +/** | ||
| 461 | +* the schema type. | ||
| 462 | +*/ | ||
| 463 | +enum srs_schema_type { | ||
| 464 | + srs_schema0 = 0, // key-digest sequence | ||
| 465 | + srs_schema1 = 1, // digest-key sequence | ||
| 466 | + srs_schema_invalid = 2, | ||
| 467 | +}; | ||
| 468 | + | ||
| 469 | +void __time_copy_to(char*& pp, int32_t time) | ||
| 470 | +{ | ||
| 471 | + // 4bytes time | ||
| 472 | + *(int32_t*)pp = time; | ||
| 473 | + pp += 4; | ||
| 474 | +} | ||
| 475 | +void __version_copy_to(char*& pp, int32_t version) | ||
| 476 | +{ | ||
| 477 | + // 4bytes version | ||
| 478 | + *(int32_t*)pp = version; | ||
| 479 | + pp += 4; | ||
| 480 | +} | ||
| 481 | +void __key_copy_to(char*& pp, key_block* key) | ||
| 482 | +{ | ||
| 483 | + // 764bytes key block | ||
| 484 | + if (key->random0_size > 0) { | ||
| 485 | + memcpy(pp, key->random0, key->random0_size); | ||
| 486 | + } | ||
| 487 | + pp += key->random0_size; | ||
| 488 | + | ||
| 489 | + memcpy(pp, key->key, sizeof(key->key)); | ||
| 490 | + pp += sizeof(key->key); | ||
| 491 | + | ||
| 492 | + if (key->random1_size > 0) { | ||
| 493 | + memcpy(pp, key->random1, key->random1_size); | ||
| 494 | + } | ||
| 495 | + pp += key->random1_size; | ||
| 496 | + | ||
| 497 | + *(int32_t*)pp = key->offset; | ||
| 498 | + pp += 4; | ||
| 499 | +} | ||
| 500 | +void __digest_copy_to(char*& pp, digest_block* digest, bool with_digest) | ||
| 501 | +{ | ||
| 502 | + // 732bytes digest block without the 32bytes digest-data | ||
| 503 | + // nbytes digest block part1 | ||
| 504 | + *(int32_t*)pp = digest->offset; | ||
| 505 | + pp += 4; | ||
| 506 | + | ||
| 507 | + if (digest->random0_size > 0) { | ||
| 508 | + memcpy(pp, digest->random0, digest->random0_size); | ||
| 509 | + } | ||
| 510 | + pp += digest->random0_size; | ||
| 511 | + | ||
| 512 | + // digest | ||
| 513 | + if (with_digest) { | ||
| 514 | + memcpy(pp, digest->digest, 32); | ||
| 515 | + pp += 32; | ||
| 516 | + } | ||
| 517 | + | ||
| 518 | + // nbytes digest block part2 | ||
| 519 | + if (digest->random1_size > 0) { | ||
| 520 | + memcpy(pp, digest->random1, digest->random1_size); | ||
| 521 | + } | ||
| 522 | + pp += digest->random1_size; | ||
| 523 | +} | ||
| 524 | + | ||
| 525 | +/** | ||
| 526 | +* copy whole c1s1 to bytes. | ||
| 527 | +*/ | ||
| 528 | +void schema0_copy_to(char* bytes, bool with_digest, | ||
| 529 | + int32_t time, int32_t version, key_block* key, digest_block* digest) | ||
| 530 | +{ | ||
| 531 | + char* pp = bytes; | ||
| 532 | + | ||
| 533 | + __time_copy_to(pp, time); | ||
| 534 | + __version_copy_to(pp, version); | ||
| 535 | + __key_copy_to(pp, key); | ||
| 536 | + __digest_copy_to(pp, digest, with_digest); | ||
| 537 | + | ||
| 538 | + if (with_digest) { | ||
| 539 | + srs_assert(pp - bytes == 1536); | ||
| 540 | + } else { | ||
| 541 | + srs_assert(pp - bytes == 1536 - 32); | ||
| 542 | + } | ||
| 543 | +} | ||
| 544 | +void schema1_copy_to(char* bytes, bool with_digest, | ||
| 545 | + int32_t time, int32_t version, digest_block* digest, key_block* key) | ||
| 546 | +{ | ||
| 547 | + char* pp = bytes; | ||
| 548 | + | ||
| 549 | + __time_copy_to(pp, time); | ||
| 550 | + __version_copy_to(pp, version); | ||
| 551 | + __digest_copy_to(pp, digest, with_digest); | ||
| 552 | + __key_copy_to(pp, key); | ||
| 553 | + | ||
| 554 | + if (with_digest) { | ||
| 555 | + srs_assert(pp - bytes == 1536); | ||
| 556 | + } else { | ||
| 557 | + srs_assert(pp - bytes == 1536 - 32); | ||
| 558 | + } | ||
| 559 | +} | ||
| 560 | +/** | ||
| 561 | +* c1s1 is splited by digest: | ||
| 562 | +* c1s1-part1: n bytes (time, version, key and digest-part1). | ||
| 563 | +* digest-data: 32bytes | ||
| 564 | +* c1s1-part2: (1536-n-32)bytes (digest-part2) | ||
| 565 | +*/ | ||
| 566 | +char* bytes_join_schema0(int32_t time, int32_t version, key_block* key, digest_block* digest) | ||
| 567 | +{ | ||
| 568 | + char* bytes = new char[1536 -32]; | ||
| 569 | + | ||
| 570 | + schema0_copy_to(bytes, false, time, version, key, digest); | ||
| 571 | + | ||
| 572 | + return bytes; | ||
| 573 | +} | ||
| 574 | +/** | ||
| 575 | +* c1s1 is splited by digest: | ||
| 576 | +* c1s1-part1: n bytes (time, version and digest-part1). | ||
| 577 | +* digest-data: 32bytes | ||
| 578 | +* c1s1-part2: (1536-n-32)bytes (digest-part2 and key) | ||
| 579 | +*/ | ||
| 580 | +char* bytes_join_schema1(int32_t time, int32_t version, digest_block* digest, key_block* key) | ||
| 581 | +{ | ||
| 582 | + char* bytes = new char[1536 -32]; | ||
| 583 | + | ||
| 584 | + schema1_copy_to(bytes, false, time, version, digest, key); | ||
| 585 | + | ||
| 586 | + return bytes; | ||
| 587 | +} | ||
| 588 | + | ||
| 589 | +/** | ||
| 590 | +* compare the memory in bytes. | ||
| 591 | +*/ | ||
| 592 | +bool srs_bytes_equals(void* pa, void* pb, int size){ | ||
| 593 | + u_int8_t* a = (u_int8_t*)pa; | ||
| 594 | + u_int8_t* b = (u_int8_t*)pb; | ||
| 595 | + | ||
| 596 | + for(int i = 0; i < size; i++){ | ||
| 597 | + if(a[i] != b[i]){ | ||
| 598 | + return false; | ||
| 599 | + } | ||
| 600 | + } | ||
| 601 | + | ||
| 602 | + return true; | ||
| 98 | } | 603 | } |
| 99 | 604 | ||
| 100 | /** | 605 | /** |
| @@ -111,10 +616,6 @@ void srs_digest_block_free(digest_block* digest) | @@ -111,10 +616,6 @@ void srs_digest_block_free(digest_block* digest) | ||
| 111 | */ | 616 | */ |
| 112 | struct c1s1 | 617 | struct c1s1 |
| 113 | { | 618 | { |
| 114 | - enum schema_type { | ||
| 115 | - schema0 = 0, | ||
| 116 | - schema1 = 1 | ||
| 117 | - }; | ||
| 118 | union block { | 619 | union block { |
| 119 | key_block key; | 620 | key_block key; |
| 120 | digest_block digest; | 621 | digest_block digest; |
| @@ -134,33 +635,443 @@ struct c1s1 | @@ -134,33 +635,443 @@ struct c1s1 | ||
| 134 | block block1; | 635 | block block1; |
| 135 | 636 | ||
| 136 | // the logic schema | 637 | // the logic schema |
| 137 | - schema_type schema; | 638 | + srs_schema_type schema; |
| 138 | 639 | ||
| 139 | - c1s1() | ||
| 140 | - { | ||
| 141 | - time = ::time(NULL); | ||
| 142 | - version = 0x00; | ||
| 143 | - | ||
| 144 | - schema = c1s1::schema0; | 640 | + c1s1(); |
| 641 | + virtual ~c1s1(); | ||
| 642 | + /** | ||
| 643 | + * get the digest key. | ||
| 644 | + */ | ||
| 645 | + virtual char* get_digest(); | ||
| 646 | + /** | ||
| 647 | + * copy to bytes. | ||
| 648 | + */ | ||
| 649 | + virtual void dump(char* _c1s1); | ||
| 650 | + | ||
| 651 | + /** | ||
| 652 | + * client: create and sign c1 by schema. | ||
| 653 | + * sign the c1, generate the digest. | ||
| 654 | + * calc_c1_digest(c1, schema) { | ||
| 655 | + * get c1s1-joined from c1 by specified schema | ||
| 656 | + * digest-data = HMACsha256(c1s1-joined, FPKey, 30) | ||
| 657 | + * return digest-data; | ||
| 658 | + * } | ||
| 659 | + * random fill 1536bytes c1 // also fill the c1-128bytes-key | ||
| 660 | + * time = time() // c1[0-3] | ||
| 661 | + * version = [0x80, 0x00, 0x07, 0x02] // c1[4-7] | ||
| 662 | + * schema = choose schema0 or schema1 | ||
| 663 | + * digest-data = calc_c1_digest(c1, schema) | ||
| 664 | + * copy digest-data to c1 | ||
| 665 | + */ | ||
| 666 | + virtual int c1_create(srs_schema_type _schema); | ||
| 667 | + /** | ||
| 668 | + * server: parse the c1s1, discovery the key and digest by schema. | ||
| 669 | + * use the c1_validate_digest() to valid the digest of c1. | ||
| 670 | + */ | ||
| 671 | + virtual int c1_parse(char* _c1s1, srs_schema_type _schema); | ||
| 672 | + /** | ||
| 673 | + * server: validate the parsed schema and c1s1 | ||
| 674 | + */ | ||
| 675 | + virtual int c1_validate_digest(bool& is_valid); | ||
| 676 | + /** | ||
| 677 | + * server: create and sign the s1 from c1. | ||
| 678 | + */ | ||
| 679 | + virtual int s1_create(c1s1* c1); | ||
| 680 | +private: | ||
| 681 | + virtual int calc_s1_digest(char*& digest); | ||
| 682 | + virtual int calc_c1_digest(char*& digest); | ||
| 683 | + virtual void destroy_blocks(); | ||
| 684 | +}; | ||
| 685 | + | ||
| 686 | +/** | ||
| 687 | +* the c2s2 complex handshake structure. | ||
| 688 | +* random-data: 1504bytes | ||
| 689 | +* digest-data: 32bytes | ||
| 690 | +*/ | ||
| 691 | +struct c2s2 | ||
| 692 | +{ | ||
| 693 | + char random[1504]; | ||
| 694 | + char digest[32]; | ||
| 695 | + | ||
| 696 | + c2s2(); | ||
| 697 | + virtual ~c2s2(); | ||
| 698 | + | ||
| 699 | + /** | ||
| 700 | + * copy to bytes. | ||
| 701 | + */ | ||
| 702 | + virtual void dump(char* _c2s2); | ||
| 703 | + | ||
| 704 | + /** | ||
| 705 | + * create c2. | ||
| 706 | + * random fill c2s2 1536 bytes | ||
| 707 | + * | ||
| 708 | + * // client generate C2, or server valid C2 | ||
| 709 | + * temp-key = HMACsha256(s1-digest, FPKey, 62) | ||
| 710 | + * c2-digest-data = HMACsha256(c2-random-data, temp-key, 32) | ||
| 711 | + */ | ||
| 712 | + virtual int c2_create(c1s1* s1); | ||
| 713 | + | ||
| 714 | + /** | ||
| 715 | + * create s2. | ||
| 716 | + * random fill c2s2 1536 bytes | ||
| 717 | + * | ||
| 718 | + * // server generate S2, or client valid S2 | ||
| 719 | + * temp-key = HMACsha256(c1-digest, FMSKey, 68) | ||
| 720 | + * s2-digest-data = HMACsha256(s2-random-data, temp-key, 32) | ||
| 721 | + */ | ||
| 722 | + virtual int s2_create(c1s1* c1); | ||
| 723 | +}; | ||
| 724 | + | ||
| 725 | +c2s2::c2s2() | ||
| 726 | +{ | ||
| 727 | + for (int i = 0; i < 1504; i++) { | ||
| 728 | + *(random + i) = rand(); | ||
| 729 | + } | ||
| 730 | + for (int i = 0; i < 32; i++) { | ||
| 731 | + *(digest + i) = rand(); | ||
| 732 | + } | ||
| 733 | +} | ||
| 734 | + | ||
| 735 | +c2s2::~c2s2() | ||
| 736 | +{ | ||
| 737 | +} | ||
| 738 | + | ||
| 739 | +void c2s2::dump(char* _c2s2) | ||
| 740 | +{ | ||
| 741 | + memcpy(_c2s2, random, 1504); | ||
| 742 | + memcpy(_c2s2 + 1504, digest, 32); | ||
| 743 | +} | ||
| 744 | + | ||
| 745 | +int c2s2::c2_create(c1s1* s1) | ||
| 746 | +{ | ||
| 747 | + int ret = ERROR_SUCCESS; | ||
| 748 | + | ||
| 749 | + char temp_key[OpensslHashSize]; | ||
| 750 | + if ((ret = openssl_HMACsha256(s1->get_digest(), 32, SrsGenuineFPKey, 62, temp_key)) != ERROR_SUCCESS) { | ||
| 751 | + srs_error("create c2 temp key failed. ret=%d", ret); | ||
| 752 | + return ret; | ||
| 753 | + } | ||
| 754 | + srs_verbose("generate c2 temp key success."); | ||
| 755 | + | ||
| 756 | + char _digest[OpensslHashSize]; | ||
| 757 | + if ((ret = openssl_HMACsha256(random, 1504, temp_key, 32, _digest)) != ERROR_SUCCESS) { | ||
| 758 | + srs_error("create c2 digest failed. ret=%d", ret); | ||
| 759 | + return ret; | ||
| 760 | + } | ||
| 761 | + srs_verbose("generate c2 digest success."); | ||
| 762 | + | ||
| 763 | + memcpy(digest, _digest, 32); | ||
| 764 | + | ||
| 765 | + return ret; | ||
| 766 | +} | ||
| 767 | + | ||
| 768 | +int c2s2::s2_create(c1s1* c1) | ||
| 769 | +{ | ||
| 770 | + int ret = ERROR_SUCCESS; | ||
| 771 | + | ||
| 772 | + char temp_key[OpensslHashSize]; | ||
| 773 | + if ((ret = openssl_HMACsha256(c1->get_digest(), 32, SrsGenuineFMSKey, 68, temp_key)) != ERROR_SUCCESS) { | ||
| 774 | + srs_error("create s2 temp key failed. ret=%d", ret); | ||
| 775 | + return ret; | ||
| 776 | + } | ||
| 777 | + srs_verbose("generate s2 temp key success."); | ||
| 778 | + | ||
| 779 | + char _digest[OpensslHashSize]; | ||
| 780 | + if ((ret = openssl_HMACsha256(random, 1504, temp_key, 32, _digest)) != ERROR_SUCCESS) { | ||
| 781 | + srs_error("create s2 digest failed. ret=%d", ret); | ||
| 782 | + return ret; | ||
| 783 | + } | ||
| 784 | + srs_verbose("generate s2 digest success."); | ||
| 785 | + | ||
| 786 | + memcpy(digest, _digest, 32); | ||
| 787 | + | ||
| 788 | + return ret; | ||
| 789 | +} | ||
| 790 | + | ||
| 791 | +c1s1::c1s1() | ||
| 792 | +{ | ||
| 793 | + schema = srs_schema_invalid; | ||
| 794 | +} | ||
| 795 | +c1s1::~c1s1() | ||
| 796 | +{ | ||
| 797 | + destroy_blocks(); | ||
| 798 | +} | ||
| 799 | + | ||
| 800 | +char* c1s1::get_digest() | ||
| 801 | +{ | ||
| 802 | + srs_assert(schema != srs_schema_invalid); | ||
| 803 | + | ||
| 804 | + if (schema == srs_schema0) { | ||
| 805 | + return block1.digest.digest; | ||
| 806 | + } else { | ||
| 807 | + return block0.digest.digest; | ||
| 808 | + } | ||
| 809 | +} | ||
| 810 | + | ||
| 811 | +void c1s1::dump(char* _c1s1) | ||
| 812 | +{ | ||
| 813 | + srs_assert(schema != srs_schema_invalid); | ||
| 814 | + | ||
| 815 | + if (schema == srs_schema0) { | ||
| 816 | + schema0_copy_to(_c1s1, true, time, version, &block0.key, &block1.digest); | ||
| 817 | + } else { | ||
| 818 | + schema1_copy_to(_c1s1, true, time, version, &block0.digest, &block1.key); | ||
| 819 | + } | ||
| 820 | +} | ||
| 821 | + | ||
| 822 | +int c1s1::c1_create(srs_schema_type _schema) | ||
| 823 | +{ | ||
| 824 | + int ret = ERROR_SUCCESS; | ||
| 825 | + | ||
| 826 | + if (_schema == srs_schema_invalid) { | ||
| 827 | + ret = ERROR_RTMP_CH_SCHEMA; | ||
| 828 | + srs_error("create c1 failed. invalid schema=%d, ret=%d", _schema, ret); | ||
| 829 | + return ret; | ||
| 830 | + } | ||
| 831 | + | ||
| 832 | + destroy_blocks(); | ||
| 833 | + | ||
| 834 | + time = ::time(NULL); | ||
| 835 | + version = 0x02070080; // client c1 version | ||
| 836 | + | ||
| 837 | + if (_schema == srs_schema0) { | ||
| 145 | srs_key_block_init(&block0.key); | 838 | srs_key_block_init(&block0.key); |
| 146 | srs_digest_block_init(&block1.digest); | 839 | srs_digest_block_init(&block1.digest); |
| 840 | + } else { | ||
| 841 | + srs_digest_block_init(&block0.digest); | ||
| 842 | + srs_key_block_init(&block1.key); | ||
| 843 | + } | ||
| 844 | + | ||
| 845 | + schema = _schema; | ||
| 846 | + | ||
| 847 | + char* digest = NULL; | ||
| 848 | + | ||
| 849 | + if ((ret = calc_c1_digest(digest)) != ERROR_SUCCESS) { | ||
| 850 | + srs_error("sign c1 error, failed to calc digest. ret=%d", ret); | ||
| 851 | + return ret; | ||
| 852 | + } | ||
| 853 | + | ||
| 854 | + srs_assert(digest != NULL); | ||
| 855 | + SrsAutoFree(char, digest, true); | ||
| 856 | + | ||
| 857 | + if (schema == srs_schema0) { | ||
| 858 | + memcpy(block1.digest.digest, digest, 32); | ||
| 859 | + } else { | ||
| 860 | + memcpy(block0.digest.digest, digest, 32); | ||
| 861 | + } | ||
| 862 | + | ||
| 863 | + return ret; | ||
| 864 | +} | ||
| 865 | + | ||
| 866 | +int c1s1::c1_parse(char* _c1s1, srs_schema_type _schema) | ||
| 867 | +{ | ||
| 868 | + int ret = ERROR_SUCCESS; | ||
| 869 | + | ||
| 870 | + if (_schema == srs_schema_invalid) { | ||
| 871 | + ret = ERROR_RTMP_CH_SCHEMA; | ||
| 872 | + srs_error("parse c1 failed. invalid schema=%d, ret=%d", _schema, ret); | ||
| 873 | + return ret; | ||
| 147 | } | 874 | } |
| 148 | - virtual ~c1s1() | ||
| 149 | - { | ||
| 150 | - if (schema == c1s1::schema0) { | ||
| 151 | - srs_key_block_free(&block0.key); | ||
| 152 | - srs_digest_block_free(&block1.digest); | ||
| 153 | - } else { | ||
| 154 | - srs_digest_block_free(&block0.digest); | ||
| 155 | - srs_key_block_free(&block1.key); | 875 | + |
| 876 | + destroy_blocks(); | ||
| 877 | + | ||
| 878 | + time = *(int32_t*)_c1s1; | ||
| 879 | + version = *(int32_t*)(_c1s1 + 4); // client c1 version | ||
| 880 | + | ||
| 881 | + if (_schema == srs_schema0) { | ||
| 882 | + if ((ret = srs_key_block_parse(&block0.key, _c1s1 + 8)) != ERROR_SUCCESS) { | ||
| 883 | + srs_error("parse the c1 key failed. ret=%d", ret); | ||
| 884 | + return ret; | ||
| 885 | + } | ||
| 886 | + if ((ret = srs_digest_block_parse(&block1.digest, _c1s1 + 8 + 764)) != ERROR_SUCCESS) { | ||
| 887 | + srs_error("parse the c1 digest failed. ret=%d", ret); | ||
| 888 | + return ret; | ||
| 889 | + } | ||
| 890 | + srs_verbose("parse c1 key-digest success"); | ||
| 891 | + } else if (_schema == srs_schema1) { | ||
| 892 | + if ((ret = srs_digest_block_parse(&block0.digest, _c1s1 + 8)) != ERROR_SUCCESS) { | ||
| 893 | + srs_error("parse the c1 key failed. ret=%d", ret); | ||
| 894 | + return ret; | ||
| 156 | } | 895 | } |
| 896 | + if ((ret = srs_key_block_parse(&block1.key, _c1s1 + 8 + 764)) != ERROR_SUCCESS) { | ||
| 897 | + srs_error("parse the c1 digest failed. ret=%d", ret); | ||
| 898 | + return ret; | ||
| 899 | + } | ||
| 900 | + srs_verbose("parse c1 digest-key success"); | ||
| 901 | + } else { | ||
| 902 | + ret = ERROR_RTMP_CH_SCHEMA; | ||
| 903 | + srs_error("parse c1 failed. invalid schema=%d, ret=%d", _schema, ret); | ||
| 904 | + return ret; | ||
| 157 | } | 905 | } |
| 158 | -}; | 906 | + |
| 907 | + schema = _schema; | ||
| 908 | + | ||
| 909 | + return ret; | ||
| 910 | +} | ||
| 911 | + | ||
| 912 | +int c1s1::c1_validate_digest(bool& is_valid) | ||
| 913 | +{ | ||
| 914 | + int ret = ERROR_SUCCESS; | ||
| 915 | + | ||
| 916 | + char* c1_digest = NULL; | ||
| 917 | + | ||
| 918 | + if ((ret = calc_c1_digest(c1_digest)) != ERROR_SUCCESS) { | ||
| 919 | + srs_error("validate c1 error, failed to calc digest. ret=%d", ret); | ||
| 920 | + return ret; | ||
| 921 | + } | ||
| 922 | + | ||
| 923 | + srs_assert(c1_digest != NULL); | ||
| 924 | + SrsAutoFree(char, c1_digest, true); | ||
| 925 | + | ||
| 926 | + if (schema == srs_schema0) { | ||
| 927 | + is_valid = srs_bytes_equals(block1.digest.digest, c1_digest, 32); | ||
| 928 | + } else { | ||
| 929 | + is_valid = srs_bytes_equals(block0.digest.digest, c1_digest, 32); | ||
| 930 | + } | ||
| 931 | + | ||
| 932 | + return ret; | ||
| 933 | +} | ||
| 934 | + | ||
| 935 | +int c1s1::s1_create(c1s1* c1) | ||
| 936 | +{ | ||
| 937 | + int ret = ERROR_SUCCESS; | ||
| 938 | + | ||
| 939 | + if (c1->schema == srs_schema_invalid) { | ||
| 940 | + ret = ERROR_RTMP_CH_SCHEMA; | ||
| 941 | + srs_error("create s1 failed. invalid schema=%d, ret=%d", c1->schema, ret); | ||
| 942 | + return ret; | ||
| 943 | + } | ||
| 944 | + | ||
| 945 | + destroy_blocks(); | ||
| 946 | + schema = c1->schema; | ||
| 947 | + | ||
| 948 | + time = ::time(NULL); | ||
| 949 | + version = 0x01000504; // server s1 version | ||
| 950 | + | ||
| 951 | + if (schema == srs_schema0) { | ||
| 952 | + srs_key_block_init(&block0.key); | ||
| 953 | + srs_digest_block_init(&block1.digest); | ||
| 954 | + } else { | ||
| 955 | + srs_digest_block_init(&block0.digest); | ||
| 956 | + srs_key_block_init(&block1.key); | ||
| 957 | + } | ||
| 958 | + | ||
| 959 | + if (schema == srs_schema0) { | ||
| 960 | + if ((ret = openssl_generate_key(c1->block0.key.key, block0.key.key, 128)) != ERROR_SUCCESS) { | ||
| 961 | + srs_error("calc s1 key failed. ret=%d", ret); | ||
| 962 | + return ret; | ||
| 963 | + } | ||
| 964 | + } else { | ||
| 965 | + if ((ret = openssl_generate_key(c1->block1.key.key, block1.key.key, 128)) != ERROR_SUCCESS) { | ||
| 966 | + srs_error("calc s1 key failed. ret=%d", ret); | ||
| 967 | + return ret; | ||
| 968 | + } | ||
| 969 | + } | ||
| 970 | + srs_verbose("calc s1 key success."); | ||
| 971 | + | ||
| 972 | + char* s1_digest = NULL; | ||
| 973 | + if ((ret = calc_s1_digest(s1_digest)) != ERROR_SUCCESS) { | ||
| 974 | + srs_error("calc s1 digest failed. ret=%d", ret); | ||
| 975 | + return ret; | ||
| 976 | + } | ||
| 977 | + srs_verbose("calc s1 digest success."); | ||
| 978 | + | ||
| 979 | + srs_assert(s1_digest != NULL); | ||
| 980 | + SrsAutoFree(char, s1_digest, true); | ||
| 981 | + | ||
| 982 | + if (schema == srs_schema0) { | ||
| 983 | + memcpy(block1.digest.digest, s1_digest, 32); | ||
| 984 | + } else { | ||
| 985 | + memcpy(block0.digest.digest, s1_digest, 32); | ||
| 986 | + } | ||
| 987 | + srs_verbose("copy s1 key success."); | ||
| 988 | + | ||
| 989 | + return ret; | ||
| 990 | +} | ||
| 991 | + | ||
| 992 | +int c1s1::calc_s1_digest(char*& digest) | ||
| 993 | +{ | ||
| 994 | + int ret = ERROR_SUCCESS; | ||
| 995 | + | ||
| 996 | + srs_assert(schema == srs_schema0 || schema == srs_schema1); | ||
| 997 | + | ||
| 998 | + char* c1s1_joined_bytes = NULL; | ||
| 999 | + | ||
| 1000 | + if (schema == srs_schema0) { | ||
| 1001 | + c1s1_joined_bytes = bytes_join_schema0(time, version, &block0.key, &block1.digest); | ||
| 1002 | + } else { | ||
| 1003 | + c1s1_joined_bytes = bytes_join_schema1(time, version, &block0.digest, &block1.key); | ||
| 1004 | + } | ||
| 1005 | + | ||
| 1006 | + srs_assert(c1s1_joined_bytes != NULL); | ||
| 1007 | + SrsAutoFree(char, c1s1_joined_bytes, true); | ||
| 1008 | + | ||
| 1009 | + digest = new char[OpensslHashSize]; | ||
| 1010 | + if ((ret = openssl_HMACsha256(c1s1_joined_bytes, 1536 - 32, SrsGenuineFMSKey, 36, digest)) != ERROR_SUCCESS) { | ||
| 1011 | + srs_error("calc digest for s1 failed. ret=%d", ret); | ||
| 1012 | + return ret; | ||
| 1013 | + } | ||
| 1014 | + srs_verbose("digest calculated for s1"); | ||
| 1015 | + | ||
| 1016 | + return ret; | ||
| 1017 | +} | ||
| 1018 | + | ||
| 1019 | +int c1s1::calc_c1_digest(char*& digest) | ||
| 1020 | +{ | ||
| 1021 | + int ret = ERROR_SUCCESS; | ||
| 1022 | + | ||
| 1023 | + srs_assert(schema == srs_schema0 || schema == srs_schema1); | ||
| 1024 | + | ||
| 1025 | + char* c1s1_joined_bytes = NULL; | ||
| 1026 | + | ||
| 1027 | + if (schema == srs_schema0) { | ||
| 1028 | + c1s1_joined_bytes = bytes_join_schema0(time, version, &block0.key, &block1.digest); | ||
| 1029 | + } else { | ||
| 1030 | + c1s1_joined_bytes = bytes_join_schema1(time, version, &block0.digest, &block1.key); | ||
| 1031 | + } | ||
| 1032 | + | ||
| 1033 | + srs_assert(c1s1_joined_bytes != NULL); | ||
| 1034 | + SrsAutoFree(char, c1s1_joined_bytes, true); | ||
| 1035 | + | ||
| 1036 | + digest = new char[OpensslHashSize]; | ||
| 1037 | + if ((ret = openssl_HMACsha256(c1s1_joined_bytes, 1536 - 32, SrsGenuineFPKey, 30, digest)) != ERROR_SUCCESS) { | ||
| 1038 | + srs_error("calc digest for c1 failed. ret=%d", ret); | ||
| 1039 | + return ret; | ||
| 1040 | + } | ||
| 1041 | + srs_verbose("digest calculated for c1"); | ||
| 1042 | + | ||
| 1043 | + return ret; | ||
| 1044 | +} | ||
| 1045 | + | ||
| 1046 | +void c1s1::destroy_blocks() | ||
| 1047 | +{ | ||
| 1048 | + if (schema == srs_schema_invalid) { | ||
| 1049 | + return; | ||
| 1050 | + } | ||
| 1051 | + | ||
| 1052 | + if (schema == srs_schema0) { | ||
| 1053 | + srs_key_block_free(&block0.key); | ||
| 1054 | + srs_digest_block_free(&block1.digest); | ||
| 1055 | + } else { | ||
| 1056 | + srs_digest_block_free(&block0.digest); | ||
| 1057 | + srs_key_block_free(&block1.key); | ||
| 1058 | + } | ||
| 1059 | +} | ||
| 1060 | + | ||
| 1061 | +SrsComplexHandshake::SrsComplexHandshake() | ||
| 1062 | +{ | ||
| 1063 | +} | ||
| 1064 | + | ||
| 1065 | +SrsComplexHandshake::~SrsComplexHandshake() | ||
| 1066 | +{ | ||
| 1067 | +} | ||
| 159 | 1068 | ||
| 160 | int SrsComplexHandshake::handshake(SrsSocket& skt, char* _c1) | 1069 | int SrsComplexHandshake::handshake(SrsSocket& skt, char* _c1) |
| 161 | { | 1070 | { |
| 162 | int ret = ERROR_SUCCESS; | 1071 | int ret = ERROR_SUCCESS; |
| 163 | 1072 | ||
| 1073 | + ssize_t nsize; | ||
| 1074 | + | ||
| 164 | static bool _random_initialized = false; | 1075 | static bool _random_initialized = false; |
| 165 | if (!_random_initialized) { | 1076 | if (!_random_initialized) { |
| 166 | srand(0); | 1077 | srand(0); |
| @@ -168,7 +1079,65 @@ int SrsComplexHandshake::handshake(SrsSocket& skt, char* _c1) | @@ -168,7 +1079,65 @@ int SrsComplexHandshake::handshake(SrsSocket& skt, char* _c1) | ||
| 168 | srs_trace("srand initialized the random."); | 1079 | srs_trace("srand initialized the random."); |
| 169 | } | 1080 | } |
| 170 | 1081 | ||
| 1082 | + // decode c1 | ||
| 171 | c1s1 c1; | 1083 | c1s1 c1; |
| 1084 | + // try schema0. | ||
| 1085 | + if ((ret = c1.c1_parse(_c1, srs_schema0)) != ERROR_SUCCESS) { | ||
| 1086 | + srs_error("parse c1 schema%d error. ret=%d", srs_schema0, ret); | ||
| 1087 | + return ret; | ||
| 1088 | + } | ||
| 1089 | + // try schema1 | ||
| 1090 | + bool is_valid = false; | ||
| 1091 | + if ((ret = c1.c1_validate_digest(is_valid)) != ERROR_SUCCESS || !is_valid) { | ||
| 1092 | + if ((ret = c1.c1_parse(_c1, srs_schema1)) != ERROR_SUCCESS) { | ||
| 1093 | + srs_error("parse c1 schema%d error. ret=%d", srs_schema1, ret); | ||
| 1094 | + return ret; | ||
| 1095 | + } | ||
| 1096 | + | ||
| 1097 | + if ((ret = c1.c1_validate_digest(is_valid)) != ERROR_SUCCESS || !is_valid) { | ||
| 1098 | + ret = ERROR_RTMP_TRY_SIMPLE_HS; | ||
| 1099 | + srs_info("all schema valid failed, try simple handshake. ret=%d", ret); | ||
| 1100 | + return ret; | ||
| 1101 | + } | ||
| 1102 | + } | ||
| 1103 | + srs_verbose("decode c1 success."); | ||
| 1104 | + | ||
| 1105 | + // encode s1 | ||
| 1106 | + c1s1 s1; | ||
| 1107 | + if ((ret = s1.s1_create(&c1)) != ERROR_SUCCESS) { | ||
| 1108 | + srs_error("create s1 from c1 failed. ret=%d", ret); | ||
| 1109 | + return ret; | ||
| 1110 | + } | ||
| 1111 | + srs_verbose("create s1 from c1 success."); | ||
| 1112 | + | ||
| 1113 | + c2s2 s2; | ||
| 1114 | + if ((ret = s2.s2_create(&c1)) != ERROR_SUCCESS) { | ||
| 1115 | + srs_error("create s2 from c1 failed. ret=%d", ret); | ||
| 1116 | + return ret; | ||
| 1117 | + } | ||
| 1118 | + srs_verbose("create s2 from c1 success."); | ||
| 1119 | + | ||
| 1120 | + // sendout s0s1s2 | ||
| 1121 | + char* s0s1s2 = new char[3073]; | ||
| 1122 | + SrsAutoFree(char, s0s1s2, true); | ||
| 1123 | + // plain text required. | ||
| 1124 | + s0s1s2[0] = 0x03; | ||
| 1125 | + s1.dump(s0s1s2 + 1); | ||
| 1126 | + s2.dump(s0s1s2 + 1537); | ||
| 1127 | + if ((ret = skt.write(s0s1s2, 3073, &nsize)) != ERROR_SUCCESS) { | ||
| 1128 | + srs_warn("complex handshake send s0s1s2 failed. ret=%d", ret); | ||
| 1129 | + return ret; | ||
| 1130 | + } | ||
| 1131 | + srs_verbose("complex handshake send s0s1s2 success."); | ||
| 1132 | + | ||
| 1133 | + // recv c2 | ||
| 1134 | + char* c2 = new char[1536]; | ||
| 1135 | + SrsAutoFree(char, c2, true); | ||
| 1136 | + if ((ret = skt.read_fully(c2, 1536, &nsize)) != ERROR_SUCCESS) { | ||
| 1137 | + srs_warn("complex handshake read c2 failed. ret=%d", ret); | ||
| 1138 | + return ret; | ||
| 1139 | + } | ||
| 1140 | + srs_verbose("complex handshake read c2 success."); | ||
| 172 | 1141 | ||
| 173 | return ret; | 1142 | return ret; |
| 174 | } | 1143 | } |
| @@ -36,6 +36,7 @@ class SrsSocket; | @@ -36,6 +36,7 @@ class SrsSocket; | ||
| 36 | * rtmp complex handshake, | 36 | * rtmp complex handshake, |
| 37 | * @see also crtmp(crtmpserver) or librtmp, | 37 | * @see also crtmp(crtmpserver) or librtmp, |
| 38 | * @see also: http://blog.csdn.net/win_lin/article/details/13006803 | 38 | * @see also: http://blog.csdn.net/win_lin/article/details/13006803 |
| 39 | +* @doc update the README.cmd | ||
| 39 | */ | 40 | */ |
| 40 | class SrsComplexHandshake | 41 | class SrsComplexHandshake |
| 41 | { | 42 | { |
| @@ -63,10 +63,39 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -63,10 +63,39 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 63 | #define ERROR_RTMP_AMF0_ENCODE 309 | 63 | #define ERROR_RTMP_AMF0_ENCODE 309 |
| 64 | #define ERROR_RTMP_CHUNK_SIZE 310 | 64 | #define ERROR_RTMP_CHUNK_SIZE 310 |
| 65 | #define ERROR_RTMP_TRY_SIMPLE_HS 311 | 65 | #define ERROR_RTMP_TRY_SIMPLE_HS 311 |
| 66 | +#define ERROR_RTMP_CH_SCHEMA 312 | ||
| 66 | 67 | ||
| 67 | #define ERROR_SYSTEM_STREAM_INIT 400 | 68 | #define ERROR_SYSTEM_STREAM_INIT 400 |
| 68 | #define ERROR_SYSTEM_PACKET_INVALID 401 | 69 | #define ERROR_SYSTEM_PACKET_INVALID 401 |
| 69 | #define ERROR_SYSTEM_CLIENT_INVALID 402 | 70 | #define ERROR_SYSTEM_CLIENT_INVALID 402 |
| 70 | #define ERROR_SYSTEM_ASSERT_FAILED 403 | 71 | #define ERROR_SYSTEM_ASSERT_FAILED 403 |
| 71 | 72 | ||
| 73 | +// see librtmp. | ||
| 74 | +// failed when open ssl create the dh | ||
| 75 | +#define ERROR_OpenSslCreateDH 500 | ||
| 76 | +// failed when open ssl create the Private key. | ||
| 77 | +#define ERROR_OpenSslCreateP 501 | ||
| 78 | +// when open ssl create G. | ||
| 79 | +#define ERROR_OpenSslCreateG 502 | ||
| 80 | +// when open ssl parse P1024 | ||
| 81 | +#define ERROR_OpenSslParseP1024 503 | ||
| 82 | +// when open ssl set G | ||
| 83 | +#define ERROR_OpenSslSetG 504 | ||
| 84 | +// when open ssl generate DHKeys | ||
| 85 | +#define ERROR_OpenSslGenerateDHKeys 505 | ||
| 86 | +// when open ssl share key already computed. | ||
| 87 | +#define ERROR_OpenSslShareKeyComputed 506 | ||
| 88 | +// when open ssl get shared key size. | ||
| 89 | +#define ERROR_OpenSslGetSharedKeySize 507 | ||
| 90 | +// when open ssl get peer public key. | ||
| 91 | +#define ERROR_OpenSslGetPeerPublicKey 508 | ||
| 92 | +// when open ssl compute shared key. | ||
| 93 | +#define ERROR_OpenSslComputeSharedKey 509 | ||
| 94 | +// when open ssl is invalid DH state. | ||
| 95 | +#define ERROR_OpenSslInvalidDHState 510 | ||
| 96 | +// when open ssl copy key | ||
| 97 | +#define ERROR_OpenSslCopyKey 511 | ||
| 98 | +// when open ssl sha256 digest key invalid size. | ||
| 99 | +#define ERROR_OpenSslSha256DigestSize 512 | ||
| 100 | + | ||
| 72 | #endif | 101 | #endif |
| @@ -345,6 +345,7 @@ public: | @@ -345,6 +345,7 @@ public: | ||
| 345 | * shared ptr message. | 345 | * shared ptr message. |
| 346 | * for audio/video/data message that need less memory copy. | 346 | * for audio/video/data message that need less memory copy. |
| 347 | * and only for output. | 347 | * and only for output. |
| 348 | +* @doc update the README.cmd | ||
| 348 | */ | 349 | */ |
| 349 | class SrsSharedPtrMessage : public ISrsMessage | 350 | class SrsSharedPtrMessage : public ISrsMessage |
| 350 | { | 351 | { |
| @@ -210,18 +210,18 @@ int SrsRtmp::handshake() | @@ -210,18 +210,18 @@ int SrsRtmp::handshake() | ||
| 210 | // plain text required. | 210 | // plain text required. |
| 211 | s0s1s2[0] = 0x03; | 211 | s0s1s2[0] = 0x03; |
| 212 | if ((ret = skt.write(s0s1s2, 3073, &nsize)) != ERROR_SUCCESS) { | 212 | if ((ret = skt.write(s0s1s2, 3073, &nsize)) != ERROR_SUCCESS) { |
| 213 | - srs_warn("send s0s1s2 failed. ret=%d", ret); | 213 | + srs_warn("simple handshake send s0s1s2 failed. ret=%d", ret); |
| 214 | return ret; | 214 | return ret; |
| 215 | } | 215 | } |
| 216 | - srs_verbose("send s0s1s2 success."); | 216 | + srs_verbose("simple handshake send s0s1s2 success."); |
| 217 | 217 | ||
| 218 | char* c2 = new char[1536]; | 218 | char* c2 = new char[1536]; |
| 219 | SrsAutoFree(char, c2, true); | 219 | SrsAutoFree(char, c2, true); |
| 220 | if ((ret = skt.read_fully(c2, 1536, &nsize)) != ERROR_SUCCESS) { | 220 | if ((ret = skt.read_fully(c2, 1536, &nsize)) != ERROR_SUCCESS) { |
| 221 | - srs_warn("read c2 failed. ret=%d", ret); | 221 | + srs_warn("simple handshake read c2 failed. ret=%d", ret); |
| 222 | return ret; | 222 | return ret; |
| 223 | } | 223 | } |
| 224 | - srs_verbose("read c2 success."); | 224 | + srs_verbose("simple handshake read c2 success."); |
| 225 | 225 | ||
| 226 | srs_trace("simple handshake success."); | 226 | srs_trace("simple handshake success."); |
| 227 | 227 |
| @@ -68,6 +68,7 @@ public: | @@ -68,6 +68,7 @@ public: | ||
| 68 | private: | 68 | private: |
| 69 | /** | 69 | /** |
| 70 | * detect the time jitter and correct it. | 70 | * detect the time jitter and correct it. |
| 71 | + * @doc update the README.cmd | ||
| 71 | */ | 72 | */ |
| 72 | virtual int jitter_correct(SrsSharedPtrMessage* msg); | 73 | virtual int jitter_correct(SrsSharedPtrMessage* msg); |
| 73 | }; | 74 | }; |
-
请 注册 或 登录 后发表评论