mirror of
				https://github.com/ossrs/srs.git
				synced 2025-03-09 15:49:59 +00:00 
			
		
		
		
	for bug #235, use strategy to implements the schema0 and schema1.
This commit is contained in:
		
							parent
							
								
									5d883e2e29
								
							
						
					
					
						commit
						4b9875e279
					
				
					 2 changed files with 584 additions and 261 deletions
				
			
		| 
						 | 
					@ -638,6 +638,385 @@ namespace _srs_internal
 | 
				
			||||||
        return bytes;
 | 
					        return bytes;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    c1s1_strategy::c1s1_strategy()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    c1s1_strategy::~c1s1_strategy()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    c1s1_strategy_schema0::c1s1_strategy_schema0()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        key.init();
 | 
				
			||||||
 | 
					        digest.init();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    c1s1_strategy_schema0::~c1s1_strategy_schema0()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        key.free();
 | 
				
			||||||
 | 
					        digest.free();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    srs_schema_type c1s1_strategy_schema0::schema()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return srs_schema0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    char* c1s1_strategy_schema0::get_digest()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return digest.digest;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    void c1s1_strategy_schema0::dump(c1s1* owner, char* _c1s1)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        srs_schema0_copy_to(_c1s1, true, owner->time, owner->version, &key, &digest);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    int c1s1_strategy_schema0::parse(char* _c1s1)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int ret = ERROR_SUCCESS;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if ((ret = key.parse(_c1s1 + 8)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					            srs_error("parse the c1 key failed. ret=%d", ret);
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if ((ret = digest.parse(_c1s1 + 8 + 764)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					            srs_error("parse the c1 digest failed. ret=%d", ret);
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        srs_verbose("parse c1 key-digest success");
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    int c1s1_strategy_schema0::c1_create(c1s1* owner)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int ret = ERROR_SUCCESS;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // generate digest
 | 
				
			||||||
 | 
					        char* c1_digest = NULL;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if ((ret = calc_c1_digest(owner, c1_digest)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					            srs_error("sign c1 error, failed to calc digest. ret=%d", ret);
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        srs_assert(c1_digest != NULL);
 | 
				
			||||||
 | 
					        SrsAutoFree(char, c1_digest);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        memcpy(digest.digest, c1_digest, 32);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    int c1s1_strategy_schema0::c1_validate_digest(c1s1* owner, bool& is_valid)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int ret = ERROR_SUCCESS;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        char* c1_digest = NULL;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if ((ret = calc_c1_digest(owner, 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);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        is_valid = srs_bytes_equals(digest.digest, c1_digest, 32);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    int c1s1_strategy_schema0::s1_create(c1s1* owner)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int ret = ERROR_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SrsDH dh;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // ensure generate 128bytes public key.
 | 
				
			||||||
 | 
					        if ((ret = dh.initialize(true)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // directly generate the public key.
 | 
				
			||||||
 | 
					        // @see: https://github.com/winlinvip/simple-rtmp-server/issues/148
 | 
				
			||||||
 | 
					        int pkey_size = 128;
 | 
				
			||||||
 | 
					        // TODO: FIXME: use c1 public key to calc the shared key.
 | 
				
			||||||
 | 
					        if ((ret = dh.copy_public_key(key.key, pkey_size)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					            srs_error("calc s1 key failed. ret=%d", ret);
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        srs_assert(pkey_size == 128);
 | 
				
			||||||
 | 
					        srs_verbose("calc s1 key success.");
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        char* s1_digest = NULL;
 | 
				
			||||||
 | 
					        if ((ret = calc_s1_digest(owner, 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);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        memcpy(digest.digest, s1_digest, 32);
 | 
				
			||||||
 | 
					        srs_verbose("copy s1 key success.");
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    int c1s1_strategy_schema0::s1_validate_digest(c1s1* owner, bool& is_valid)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int ret = ERROR_SUCCESS;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        char* s1_digest = NULL;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if ((ret = calc_s1_digest(owner, 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);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        is_valid = srs_bytes_equals(digest.digest, s1_digest, 32);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    int c1s1_strategy_schema0::calc_c1_digest(c1s1* owner, char*& c1_digest)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int ret = ERROR_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        char* c1s1_joined_bytes = NULL;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        c1s1_joined_bytes = srs_bytes_join_schema0(owner->time, owner->version, &key, &digest);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        srs_assert(c1s1_joined_bytes != NULL);
 | 
				
			||||||
 | 
					        SrsAutoFree(char, c1s1_joined_bytes);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        c1_digest = new char[__SRS_OpensslHashSize];
 | 
				
			||||||
 | 
					        if ((ret = openssl_HMACsha256(SrsGenuineFPKey, 30, c1s1_joined_bytes, 1536 - 32, c1_digest)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					            srs_freep(c1_digest);
 | 
				
			||||||
 | 
					            srs_error("calc digest for c1 failed. ret=%d", ret);
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        srs_verbose("digest calculated for c1");
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    int c1s1_strategy_schema0::calc_s1_digest(c1s1* owner, char*& s1_digest)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int ret = ERROR_SUCCESS;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        char* c1s1_joined_bytes = NULL;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        c1s1_joined_bytes = srs_bytes_join_schema0(owner->time, owner->version, &key, &digest);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        srs_assert(c1s1_joined_bytes != NULL);
 | 
				
			||||||
 | 
					        SrsAutoFree(char, c1s1_joined_bytes);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        s1_digest = new char[__SRS_OpensslHashSize];
 | 
				
			||||||
 | 
					        if ((ret = openssl_HMACsha256(SrsGenuineFMSKey, 36, c1s1_joined_bytes, 1536 - 32, s1_digest)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					            srs_freep(s1_digest);
 | 
				
			||||||
 | 
					            srs_error("calc digest for s1 failed. ret=%d", ret);
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        srs_verbose("digest calculated for s1");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    c1s1_strategy_schema1::c1s1_strategy_schema1()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        key.init();
 | 
				
			||||||
 | 
					        digest.init();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    c1s1_strategy_schema1::~c1s1_strategy_schema1()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        key.free();
 | 
				
			||||||
 | 
					        digest.free();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    srs_schema_type c1s1_strategy_schema1::schema()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return srs_schema1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    char* c1s1_strategy_schema1::get_digest()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return digest.digest;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    void c1s1_strategy_schema1::dump(c1s1* owner, char* _c1s1)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        srs_schema0_copy_to(_c1s1, true, owner->time, owner->version, &key, &digest);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    int c1s1_strategy_schema1::parse(char* _c1s1)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int ret = ERROR_SUCCESS;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if ((ret = digest.parse(_c1s1 + 8)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					            srs_error("parse the c1 digest failed. ret=%d", ret);
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if ((ret = key.parse(_c1s1 + 8 + 764)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					            srs_error("parse the c1 key failed. ret=%d", ret);
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        srs_verbose("parse c1 digest-key success");
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    int c1s1_strategy_schema1::c1_create(c1s1* owner)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int ret = ERROR_SUCCESS;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // generate digest
 | 
				
			||||||
 | 
					        char* c1_digest = NULL;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if ((ret = calc_c1_digest(owner, c1_digest)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					            srs_error("sign c1 error, failed to calc digest. ret=%d", ret);
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        srs_assert(c1_digest != NULL);
 | 
				
			||||||
 | 
					        SrsAutoFree(char, c1_digest);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        memcpy(digest.digest, c1_digest, 32);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    int c1s1_strategy_schema1::c1_validate_digest(c1s1* owner, bool& is_valid)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int ret = ERROR_SUCCESS;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        char* c1_digest = NULL;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if ((ret = calc_c1_digest(owner, 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);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        is_valid = srs_bytes_equals(digest.digest, c1_digest, 32);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    int c1s1_strategy_schema1::s1_create(c1s1* owner)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int ret = ERROR_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SrsDH dh;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // ensure generate 128bytes public key.
 | 
				
			||||||
 | 
					        if ((ret = dh.initialize(true)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // directly generate the public key.
 | 
				
			||||||
 | 
					        // @see: https://github.com/winlinvip/simple-rtmp-server/issues/148
 | 
				
			||||||
 | 
					        int pkey_size = 128;
 | 
				
			||||||
 | 
					        if ((ret = dh.copy_public_key(key.key, pkey_size)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					            srs_error("calc s1 key failed. ret=%d", ret);
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        srs_assert(pkey_size == 128);
 | 
				
			||||||
 | 
					        srs_verbose("calc s1 key success.");
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        char* s1_digest = NULL;
 | 
				
			||||||
 | 
					        if ((ret = calc_s1_digest(owner, 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);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        memcpy(digest.digest, s1_digest, 32);
 | 
				
			||||||
 | 
					        srs_verbose("copy s1 key success.");
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    int c1s1_strategy_schema1::s1_validate_digest(c1s1* owner, bool& is_valid)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int ret = ERROR_SUCCESS;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        char* s1_digest = NULL;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if ((ret = calc_s1_digest(owner, 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);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        is_valid = srs_bytes_equals(digest.digest, s1_digest, 32);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    int c1s1_strategy_schema1::calc_c1_digest(c1s1* owner, char*& c1_digest)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int ret = ERROR_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        char* c1s1_joined_bytes = NULL;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        c1s1_joined_bytes = srs_bytes_join_schema1(owner->time, owner->version, &digest, &key);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        srs_assert(c1s1_joined_bytes != NULL);
 | 
				
			||||||
 | 
					        SrsAutoFree(char, c1s1_joined_bytes);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        c1_digest = new char[__SRS_OpensslHashSize];
 | 
				
			||||||
 | 
					        if ((ret = openssl_HMACsha256(SrsGenuineFPKey, 30, c1s1_joined_bytes, 1536 - 32, c1_digest)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					            srs_freep(c1_digest);
 | 
				
			||||||
 | 
					            srs_error("calc digest for c1 failed. ret=%d", ret);
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        srs_verbose("digest calculated for c1");
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    int c1s1_strategy_schema1::calc_s1_digest(c1s1* owner, char*& s1_digest)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int ret = ERROR_SUCCESS;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        char* c1s1_joined_bytes = NULL;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        c1s1_joined_bytes = srs_bytes_join_schema1(owner->time, owner->version, &digest, &key);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        srs_assert(c1s1_joined_bytes != NULL);
 | 
				
			||||||
 | 
					        SrsAutoFree(char, c1s1_joined_bytes);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        s1_digest = new char[__SRS_OpensslHashSize];
 | 
				
			||||||
 | 
					        if ((ret = openssl_HMACsha256(SrsGenuineFMSKey, 36, c1s1_joined_bytes, 1536 - 32, s1_digest)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					            srs_freep(s1_digest);
 | 
				
			||||||
 | 
					            srs_error("calc digest for s1 failed. ret=%d", ret);
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        srs_verbose("digest calculated for s1");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    c2s2::c2s2()
 | 
					    c2s2::c2s2()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        srs_random_generate(random, 1504);
 | 
					        srs_random_generate(random, 1504);
 | 
				
			||||||
| 
						 | 
					@ -762,314 +1141,129 @@ namespace _srs_internal
 | 
				
			||||||
    // TODO: FIXME: move to the right position.
 | 
					    // TODO: FIXME: move to the right position.
 | 
				
			||||||
    c1s1::c1s1()
 | 
					    c1s1::c1s1()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        schema = srs_schema_invalid;
 | 
					        payload = NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    c1s1::~c1s1()
 | 
					    c1s1::~c1s1()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        destroy_blocks();
 | 
					        srs_freep(payload);
 | 
				
			||||||
 | 
					        /*
 | 
				
			||||||
 | 
					        void c1s1::destroy_blocks()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (schema == srs_schema_invalid) {
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            if (schema == srs_schema0) {
 | 
				
			||||||
 | 
					                block0.key.free();
 | 
				
			||||||
 | 
					                block1.digest.free();
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                block0.digest.free();
 | 
				
			||||||
 | 
					                block1.key.free();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }*/
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    srs_schema_type c1s1::schema()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        srs_assert(payload != NULL);
 | 
				
			||||||
 | 
					        return payload->schema();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    char* c1s1::get_digest()
 | 
					    char* c1s1::get_digest()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        srs_assert(schema != srs_schema_invalid);
 | 
					        srs_assert(payload != NULL);
 | 
				
			||||||
        
 | 
					        return payload->get_digest();
 | 
				
			||||||
        if (schema == srs_schema0) {
 | 
					 | 
				
			||||||
            return block1.digest.digest;
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            return block0.digest.digest;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    void c1s1::dump(char* _c1s1)
 | 
					    void c1s1::dump(char* _c1s1)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        srs_assert(schema != srs_schema_invalid);
 | 
					        srs_assert(payload != NULL);
 | 
				
			||||||
        
 | 
					        return payload->dump(this, _c1s1);
 | 
				
			||||||
        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 c1s1::parse(char* _c1s1, srs_schema_type schema)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        int ret = ERROR_SUCCESS;
 | 
					        int ret = ERROR_SUCCESS;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        if (_schema == srs_schema_invalid) {
 | 
					        if (schema != srs_schema0 && schema != srs_schema1) {
 | 
				
			||||||
            ret = ERROR_RTMP_CH_SCHEMA;
 | 
					            ret = ERROR_RTMP_CH_SCHEMA;
 | 
				
			||||||
            srs_error("parse c1 failed. invalid schema=%d, ret=%d", _schema, ret);
 | 
					            srs_error("parse c1 failed. invalid schema=%d, ret=%d", schema, ret);
 | 
				
			||||||
            return ret;
 | 
					            return ret;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        destroy_blocks();
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        time = __srs_stream_read_4bytes(_c1s1);
 | 
					        time = __srs_stream_read_4bytes(_c1s1);
 | 
				
			||||||
        version = __srs_stream_read_4bytes(_c1s1 + 4); // client c1 version
 | 
					        version = __srs_stream_read_4bytes(_c1s1 + 4); // client c1 version
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        if (_schema == srs_schema0) {
 | 
					        srs_freep(payload);
 | 
				
			||||||
            if ((ret = block0.key.parse(_c1s1 + 8)) != ERROR_SUCCESS) {
 | 
					        if (schema == srs_schema0) {
 | 
				
			||||||
                srs_error("parse the c1 key failed. ret=%d", ret);
 | 
					            payload = new c1s1_strategy_schema0();
 | 
				
			||||||
                return ret;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if ((ret = block1.digest.parse(_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 = block0.digest.parse(_c1s1 + 8)) != ERROR_SUCCESS) {
 | 
					 | 
				
			||||||
                srs_error("parse the c1 key failed. ret=%d", ret);
 | 
					 | 
				
			||||||
                return ret;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if ((ret = block1.key.parse(_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 {
 | 
					        } else {
 | 
				
			||||||
            ret = ERROR_RTMP_CH_SCHEMA;
 | 
					            payload = new c1s1_strategy_schema1();
 | 
				
			||||||
            srs_error("parse c1 failed. invalid schema=%d, ret=%d", _schema, ret);
 | 
					 | 
				
			||||||
            return ret;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        schema = _schema;
 | 
					        return payload->parse(_c1s1);
 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        return ret;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    int c1s1::c1_create(srs_schema_type _schema)
 | 
					    int c1s1::c1_create(srs_schema_type schema)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        int ret = ERROR_SUCCESS;
 | 
					        int ret = ERROR_SUCCESS;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        if (_schema == srs_schema_invalid) {
 | 
					        if (schema != srs_schema0 && schema != srs_schema1) {
 | 
				
			||||||
            ret = ERROR_RTMP_CH_SCHEMA;
 | 
					            ret = ERROR_RTMP_CH_SCHEMA;
 | 
				
			||||||
            srs_error("create c1 failed. invalid schema=%d, ret=%d", _schema, ret);
 | 
					            srs_error("create c1 failed. invalid schema=%d, ret=%d", schema, ret);
 | 
				
			||||||
            return ret;
 | 
					            return ret;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        destroy_blocks();
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // client c1 time and version
 | 
					        // client c1 time and version
 | 
				
			||||||
        time = ::time(NULL);
 | 
					        time = ::time(NULL);
 | 
				
			||||||
        version = 0x80000702; // client c1 version
 | 
					        version = 0x80000702; // client c1 version
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        // generate signature by schema
 | 
					        // generate signature by schema
 | 
				
			||||||
        if (_schema == srs_schema0) {
 | 
					        srs_freep(payload);
 | 
				
			||||||
            block0.key.init();
 | 
					 | 
				
			||||||
            block1.digest.init();
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            block0.digest.init();
 | 
					 | 
				
			||||||
            block1.key.init();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        schema = _schema;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // generate digest
 | 
					 | 
				
			||||||
        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);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if (schema == srs_schema0) {
 | 
					        if (schema == srs_schema0) {
 | 
				
			||||||
            memcpy(block1.digest.digest, digest, 32);
 | 
					            payload = new c1s1_strategy_schema0();
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            memcpy(block0.digest.digest, digest, 32);
 | 
					            payload = new c1s1_strategy_schema1();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        return ret;
 | 
					        return payload->c1_create(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    int c1s1::c1_validate_digest(bool& is_valid)
 | 
					    int c1s1::c1_validate_digest(bool& is_valid)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        is_valid = false;
 | 
					        is_valid = false;
 | 
				
			||||||
        int ret = ERROR_SUCCESS;
 | 
					        srs_assert(payload);
 | 
				
			||||||
        
 | 
					        return payload->c1_validate_digest(this, is_valid);
 | 
				
			||||||
        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);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        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)
 | 
					    int c1s1::s1_validate_digest(bool& is_valid)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        is_valid = false;
 | 
					        is_valid = false;
 | 
				
			||||||
        int ret = ERROR_SUCCESS;
 | 
					        srs_assert(payload);
 | 
				
			||||||
        
 | 
					        return payload->s1_validate_digest(this, is_valid);
 | 
				
			||||||
        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);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        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 c1s1::s1_create(c1s1* c1)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        int ret = ERROR_SUCCESS;
 | 
					        int ret = ERROR_SUCCESS;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        if (c1->schema == srs_schema_invalid) {
 | 
					        if (c1->schema() != srs_schema0 && c1->schema() != srs_schema1) {
 | 
				
			||||||
            ret = ERROR_RTMP_CH_SCHEMA;
 | 
					            ret = ERROR_RTMP_CH_SCHEMA;
 | 
				
			||||||
            srs_error("create s1 failed. invalid schema=%d, ret=%d", c1->schema, ret);
 | 
					            srs_error("create s1 failed. invalid schema=%d, ret=%d", c1->schema(), ret);
 | 
				
			||||||
            return ret;
 | 
					            return ret;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        destroy_blocks();
 | 
					 | 
				
			||||||
        schema = c1->schema;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        time = ::time(NULL);
 | 
					        time = ::time(NULL);
 | 
				
			||||||
        version = 0x01000504; // server s1 version
 | 
					        version = 0x01000504; // server s1 version
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        SrsDH dh;
 | 
					        srs_freep(payload);
 | 
				
			||||||
        
 | 
					        if (c1->schema() == srs_schema0) {
 | 
				
			||||||
        // ensure generate 128bytes public key.
 | 
					            payload = new c1s1_strategy_schema0();
 | 
				
			||||||
        if ((ret = dh.initialize(true)) != ERROR_SUCCESS) {
 | 
					 | 
				
			||||||
            return ret;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if (schema == srs_schema0) {
 | 
					 | 
				
			||||||
            block0.key.init();
 | 
					 | 
				
			||||||
            block1.digest.init();
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            // directly generate the public key.
 | 
					 | 
				
			||||||
            // @see: https://github.com/winlinvip/simple-rtmp-server/issues/148
 | 
					 | 
				
			||||||
            int pkey_size = 128;
 | 
					 | 
				
			||||||
            if ((ret = dh.copy_public_key(block0.key.key, pkey_size)) != ERROR_SUCCESS) {
 | 
					 | 
				
			||||||
                srs_error("calc s1 key failed. ret=%d", ret);
 | 
					 | 
				
			||||||
                return ret;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            srs_assert(pkey_size == 128);
 | 
					 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            block0.digest.init();
 | 
					            payload = new c1s1_strategy_schema1();
 | 
				
			||||||
            block1.key.init();
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            // directly generate the public key.
 | 
					 | 
				
			||||||
            // @see: https://github.com/winlinvip/simple-rtmp-server/issues/148
 | 
					 | 
				
			||||||
            int pkey_size = 128;
 | 
					 | 
				
			||||||
            if ((ret = dh.copy_public_key(block1.key.key, pkey_size)) != ERROR_SUCCESS) {
 | 
					 | 
				
			||||||
                srs_error("calc s1 key failed. ret=%d", ret);
 | 
					 | 
				
			||||||
                return ret;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            srs_assert(pkey_size == 128);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        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);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        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);
 | 
					        return payload->s1_create(this);
 | 
				
			||||||
        SrsAutoFree(char, c1s1_joined_bytes);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        digest = new char[__SRS_OpensslHashSize];
 | 
					 | 
				
			||||||
        if ((ret = openssl_HMACsha256(SrsGenuineFMSKey, 36, c1s1_joined_bytes, 1536 - 32, digest)) != ERROR_SUCCESS) {
 | 
					 | 
				
			||||||
            srs_error("calc digest for s1 failed. ret=%d", ret);
 | 
					 | 
				
			||||||
            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);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        digest = new char[__SRS_OpensslHashSize];
 | 
					 | 
				
			||||||
        if ((ret = openssl_HMACsha256(SrsGenuineFPKey, 30, c1s1_joined_bytes, 1536 - 32, digest)) != ERROR_SUCCESS) {
 | 
					 | 
				
			||||||
            srs_error("calc digest for c1 failed. ret=%d", ret);
 | 
					 | 
				
			||||||
            return ret;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        srs_verbose("digest calculated for c1");
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        return ret;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    void c1s1::destroy_blocks()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (schema == srs_schema_invalid) {
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if (schema == srs_schema0) {
 | 
					 | 
				
			||||||
            block0.key.free();
 | 
					 | 
				
			||||||
            block1.digest.free();
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            block0.digest.free();
 | 
					 | 
				
			||||||
            block1.key.free();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1190,6 +1384,7 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs
 | 
				
			||||||
    // decode c1
 | 
					    // decode c1
 | 
				
			||||||
    c1s1 c1;
 | 
					    c1s1 c1;
 | 
				
			||||||
    // try schema0.
 | 
					    // try schema0.
 | 
				
			||||||
 | 
					    // @remark, use schema0 to make flash player happy.
 | 
				
			||||||
    if ((ret = c1.parse(hs_bytes->c0c1 + 1, srs_schema0)) != ERROR_SUCCESS) {
 | 
					    if ((ret = c1.parse(hs_bytes->c0c1 + 1, srs_schema0)) != ERROR_SUCCESS) {
 | 
				
			||||||
        srs_error("parse c1 schema%d error. ret=%d", srs_schema0, ret);
 | 
					        srs_error("parse c1 schema%d error. ret=%d", srs_schema0, ret);
 | 
				
			||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
| 
						 | 
					@ -1197,6 +1392,7 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs
 | 
				
			||||||
    // try schema1
 | 
					    // try schema1
 | 
				
			||||||
    bool is_valid = false;
 | 
					    bool is_valid = false;
 | 
				
			||||||
    if ((ret = c1.c1_validate_digest(is_valid)) != ERROR_SUCCESS || !is_valid) {
 | 
					    if ((ret = c1.c1_validate_digest(is_valid)) != ERROR_SUCCESS || !is_valid) {
 | 
				
			||||||
 | 
					        srs_info("schema0 failed, try schema1.");
 | 
				
			||||||
        if ((ret = c1.parse(hs_bytes->c0c1 + 1, srs_schema1)) != ERROR_SUCCESS) {
 | 
					        if ((ret = c1.parse(hs_bytes->c0c1 + 1, srs_schema1)) != ERROR_SUCCESS) {
 | 
				
			||||||
            srs_error("parse c1 schema%d error. ret=%d", srs_schema1, ret);
 | 
					            srs_error("parse c1 schema%d error. ret=%d", srs_schema1, ret);
 | 
				
			||||||
            return ret;
 | 
					            return ret;
 | 
				
			||||||
| 
						 | 
					@ -1207,6 +1403,8 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs
 | 
				
			||||||
            srs_info("all schema valid failed, try simple handshake. ret=%d", ret);
 | 
					            srs_info("all schema valid failed, try simple handshake. ret=%d", ret);
 | 
				
			||||||
            return ret;
 | 
					            return ret;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        srs_info("schema0 is ok.");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    srs_verbose("decode c1 success.");
 | 
					    srs_verbose("decode c1 success.");
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
| 
						 | 
					@ -1321,7 +1519,7 @@ int SrsComplexHandshake::handshake_with_server(SrsHandshakeBytes* hs_bytes, ISrs
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // verify s1s2
 | 
					    // verify s1s2
 | 
				
			||||||
    c1s1 s1;
 | 
					    c1s1 s1;
 | 
				
			||||||
    if ((ret = s1.parse(hs_bytes->s0s1s2 + 1, c1.schema)) != ERROR_SUCCESS) {
 | 
					    if ((ret = s1.parse(hs_bytes->s0s1s2 + 1, c1.schema())) != ERROR_SUCCESS) {
 | 
				
			||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -219,6 +219,121 @@ namespace _srs_internal
 | 
				
			||||||
    */
 | 
					    */
 | 
				
			||||||
    char* srs_bytes_join_schema1(int32_t time, int32_t version, digest_block* digest, key_block* key);
 | 
					    char* srs_bytes_join_schema1(int32_t time, int32_t version, digest_block* digest, key_block* key);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    class c1s1;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * the c1s1 strategy, use schema0 or schema1.
 | 
				
			||||||
 | 
					    * the template method class to defines common behaviors,
 | 
				
			||||||
 | 
					    * while the concrete class to implements in schema0 or schema1.
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    class c1s1_strategy
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        c1s1_strategy();
 | 
				
			||||||
 | 
					        virtual ~c1s1_strategy();
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					        * get the scema.
 | 
				
			||||||
 | 
					        */
 | 
				
			||||||
 | 
					        virtual srs_schema_type schema() = 0;
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					        * get the digest key.
 | 
				
			||||||
 | 
					        */
 | 
				
			||||||
 | 
					        virtual char* get_digest() = 0;
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					        * copy to bytes.
 | 
				
			||||||
 | 
					        */
 | 
				
			||||||
 | 
					        virtual void dump(c1s1* owner, char* _c1s1) = 0;
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					        * server: parse the c1s1, discovery the key and digest by schema.
 | 
				
			||||||
 | 
					        * use the c1_validate_digest() to valid the digest of c1.
 | 
				
			||||||
 | 
					        */
 | 
				
			||||||
 | 
					        virtual int parse(char* _c1s1) = 0;
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					        * client: create and sign c1 by schema.
 | 
				
			||||||
 | 
					        * sign the c1, generate the digest.
 | 
				
			||||||
 | 
					        *         calc_c1_digest(c1, schema) {
 | 
				
			||||||
 | 
					        *            get c1s1-joined from c1 by specified schema
 | 
				
			||||||
 | 
					        *            digest-data = HMACsha256(c1s1-joined, FPKey, 30)
 | 
				
			||||||
 | 
					        *            return digest-data;
 | 
				
			||||||
 | 
					        *        }
 | 
				
			||||||
 | 
					        *        random fill 1536bytes c1 // also fill the c1-128bytes-key
 | 
				
			||||||
 | 
					        *        time = time() // c1[0-3]
 | 
				
			||||||
 | 
					        *        version = [0x80, 0x00, 0x07, 0x02] // c1[4-7]
 | 
				
			||||||
 | 
					        *        schema = choose schema0 or schema1
 | 
				
			||||||
 | 
					        *        digest-data = calc_c1_digest(c1, schema)
 | 
				
			||||||
 | 
					        *        copy digest-data to c1
 | 
				
			||||||
 | 
					        */
 | 
				
			||||||
 | 
					        virtual int c1_create(c1s1* owner) = 0;
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					        * server: validate the parsed c1 schema
 | 
				
			||||||
 | 
					        */
 | 
				
			||||||
 | 
					        virtual int c1_validate_digest(c1s1* owner, bool& is_valid) = 0;
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					        * server: create and sign the s1 from c1.
 | 
				
			||||||
 | 
					        */
 | 
				
			||||||
 | 
					        virtual int s1_create(c1s1* owner) = 0;
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					        * server: validate the parsed s1 schema
 | 
				
			||||||
 | 
					        */
 | 
				
			||||||
 | 
					        virtual int s1_validate_digest(c1s1* owner, bool& is_valid) = 0;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * c1s1 schema0
 | 
				
			||||||
 | 
					    *     key: 764bytes
 | 
				
			||||||
 | 
					    *     digest: 764bytes
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    class c1s1_strategy_schema0 : public c1s1_strategy
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
					        key_block key;
 | 
				
			||||||
 | 
					        digest_block digest;
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        c1s1_strategy_schema0();
 | 
				
			||||||
 | 
					        virtual ~c1s1_strategy_schema0();
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        virtual srs_schema_type schema();
 | 
				
			||||||
 | 
					        virtual char* get_digest();
 | 
				
			||||||
 | 
					        virtual void dump(c1s1* owner, char* _c1s1);
 | 
				
			||||||
 | 
					        virtual int parse(char* _c1s1);
 | 
				
			||||||
 | 
					        virtual int c1_create(c1s1* owner);
 | 
				
			||||||
 | 
					        virtual int c1_validate_digest(c1s1* owner, bool& is_valid);
 | 
				
			||||||
 | 
					        virtual int s1_create(c1s1* owner);
 | 
				
			||||||
 | 
					        virtual int s1_validate_digest(c1s1* owner, bool& is_valid);
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
					        virtual int calc_c1_digest(c1s1* owner, char*& c1_digest);
 | 
				
			||||||
 | 
					        virtual int calc_s1_digest(c1s1* owner, char*& s1_digest);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * c1s1 schema1
 | 
				
			||||||
 | 
					    *     digest: 764bytes
 | 
				
			||||||
 | 
					    *     key: 764bytes
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    class c1s1_strategy_schema1 : public c1s1_strategy
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
					        digest_block digest;
 | 
				
			||||||
 | 
					        key_block key;
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        c1s1_strategy_schema1();
 | 
				
			||||||
 | 
					        virtual ~c1s1_strategy_schema1();
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        virtual srs_schema_type schema();
 | 
				
			||||||
 | 
					        virtual char* get_digest();
 | 
				
			||||||
 | 
					        virtual void dump(c1s1* owner, char* _c1s1);
 | 
				
			||||||
 | 
					        virtual int parse(char* _c1s1);
 | 
				
			||||||
 | 
					        virtual int c1_create(c1s1* owner);
 | 
				
			||||||
 | 
					        virtual int c1_validate_digest(c1s1* owner, bool& is_valid);
 | 
				
			||||||
 | 
					        virtual int s1_create(c1s1* owner);
 | 
				
			||||||
 | 
					        virtual int s1_validate_digest(c1s1* owner, bool& is_valid);
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
					        virtual int calc_c1_digest(c1s1* owner, char*& c1_digest);
 | 
				
			||||||
 | 
					        virtual int calc_s1_digest(c1s1* owner, char*& s1_digest);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    * c1s1 schema0
 | 
					    * c1s1 schema0
 | 
				
			||||||
    *     time: 4bytes
 | 
					    *     time: 4bytes
 | 
				
			||||||
| 
						 | 
					@ -235,30 +350,20 @@ namespace _srs_internal
 | 
				
			||||||
    class c1s1
 | 
					    class c1s1
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        union block {
 | 
					 | 
				
			||||||
            key_block key; 
 | 
					 | 
				
			||||||
            digest_block digest; 
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // 4bytes
 | 
					        // 4bytes
 | 
				
			||||||
        int32_t time;
 | 
					        int32_t time;
 | 
				
			||||||
        // 4bytes
 | 
					        // 4bytes
 | 
				
			||||||
        int32_t version;
 | 
					        int32_t version;
 | 
				
			||||||
        // 764bytes
 | 
					        // 764bytes+764bytes
 | 
				
			||||||
        // if schema0, use key
 | 
					        c1s1_strategy* payload;
 | 
				
			||||||
        // if schema1, use digest
 | 
					 | 
				
			||||||
        block block0;
 | 
					 | 
				
			||||||
        // 764bytes
 | 
					 | 
				
			||||||
        // if schema0, use digest
 | 
					 | 
				
			||||||
        // if schema1, use key
 | 
					 | 
				
			||||||
        block block1;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // the logic schema
 | 
					 | 
				
			||||||
        srs_schema_type schema;
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        c1s1();
 | 
					        c1s1();
 | 
				
			||||||
        virtual ~c1s1();
 | 
					        virtual ~c1s1();
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
 | 
					        * get the scema.
 | 
				
			||||||
 | 
					        */
 | 
				
			||||||
 | 
					        virtual srs_schema_type schema();
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
        * get the digest key.
 | 
					        * get the digest key.
 | 
				
			||||||
        */
 | 
					        */
 | 
				
			||||||
        virtual char* get_digest();
 | 
					        virtual char* get_digest();
 | 
				
			||||||
| 
						 | 
					@ -269,6 +374,7 @@ namespace _srs_internal
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
        * server: parse the c1s1, discovery the key and digest by schema.
 | 
					        * server: parse the c1s1, discovery the key and digest by schema.
 | 
				
			||||||
        * use the c1_validate_digest() to valid the digest of c1.
 | 
					        * use the c1_validate_digest() to valid the digest of c1.
 | 
				
			||||||
 | 
					        * use the s1_validate_digest() to valid the digest of s1.
 | 
				
			||||||
        */
 | 
					        */
 | 
				
			||||||
        virtual int parse(char* _c1s1, srs_schema_type _schema);
 | 
					        virtual int parse(char* _c1s1, srs_schema_type _schema);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
| 
						 | 
					@ -294,16 +400,35 @@ namespace _srs_internal
 | 
				
			||||||
        virtual int c1_validate_digest(bool& is_valid);
 | 
					        virtual int c1_validate_digest(bool& is_valid);
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
        * server: create and sign the s1 from c1.
 | 
					        * server: create and sign the s1 from c1.
 | 
				
			||||||
 | 
					        *       // decode c1 try schema0 then schema1
 | 
				
			||||||
 | 
					        *       c1-digest-data = get-c1-digest-data(schema0)
 | 
				
			||||||
 | 
					        *       if c1-digest-data equals to calc_c1_digest(c1, schema0) {  
 | 
				
			||||||
 | 
					        *           c1-key-data = get-c1-key-data(schema0)  
 | 
				
			||||||
 | 
					        *           schema = schema0
 | 
				
			||||||
 | 
					        *       } else {  
 | 
				
			||||||
 | 
					        *           c1-digest-data = get-c1-digest-data(schema1)  
 | 
				
			||||||
 | 
					        *           if c1-digest-data not equals to calc_c1_digest(c1, schema1) {
 | 
				
			||||||
 | 
					        *               switch to simple handshake.  
 | 
				
			||||||
 | 
					        *               return  
 | 
				
			||||||
 | 
					        *           }
 | 
				
			||||||
 | 
					        *           c1-key-data = get-c1-key-data(schema1)  
 | 
				
			||||||
 | 
					        *           schema = schema1
 | 
				
			||||||
 | 
					        *       }
 | 
				
			||||||
 | 
					        * 
 | 
				
			||||||
 | 
					        *       // generate s1
 | 
				
			||||||
 | 
					        *       random fill 1536bytes s1
 | 
				
			||||||
 | 
					        *       time = time() // c1[0-3]
 | 
				
			||||||
 | 
					        *       version = [0x04, 0x05, 0x00, 0x01] // s1[4-7]
 | 
				
			||||||
 | 
					        *       s1-key-data=shared_key=DH_compute_key(peer_pub_key=c1-key-data)
 | 
				
			||||||
 | 
					        *       get c1s1-joined by specified schema
 | 
				
			||||||
 | 
					        *       s1-digest-data = HMACsha256(c1s1-joined, FMSKey, 36)
 | 
				
			||||||
 | 
					        *       copy s1-digest-data and s1-key-data to s1.
 | 
				
			||||||
        */
 | 
					        */
 | 
				
			||||||
        virtual int s1_create(c1s1* c1);
 | 
					        virtual int s1_create(c1s1* c1);
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
        * server: validate the parsed s1 schema
 | 
					        * server: validate the parsed s1 schema
 | 
				
			||||||
        */
 | 
					        */
 | 
				
			||||||
        virtual int s1_validate_digest(bool& is_valid);
 | 
					        virtual int s1_validate_digest(bool& is_valid);
 | 
				
			||||||
    private:
 | 
					 | 
				
			||||||
        virtual int calc_s1_digest(char*& digest);
 | 
					 | 
				
			||||||
        virtual int calc_c1_digest(char*& digest);
 | 
					 | 
				
			||||||
        virtual void destroy_blocks();
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue