RTMP complex handshake,變更的握手,支持h264/aac

當服務器和客戶端的握手是按照rtmp協議進行,是不支持h264/aac的,有數據,就是沒有視頻和聲音。

原因是adobe變更了握手的數據結構,標準rtmp協議的握手的包是隨機的1536字節(S1S2C1C2),變更後的是需要進行摘要和加密。

rtmp協議定義的爲simple handshake,變更後加密握手可稱爲complex handshake。

本文詳細分析了rtmpd(ccrtmpserver)中的處理邏輯,以及rtmpdump的處理邏輯,從一個全是魔法數字的世界找到他們的數據結構和算法。

complex handshake C1S1結構

complex handshake將C1S1分爲4個部分,它們的順序(schema)一種可能是:

[plain]  view plain  copy
  1. // c1s1 schema0  
  2. time: 4bytes  
  3. version: 4bytes  
  4. key: 764bytes  
  5. digest: 764bytes  
其中,key和digest可能會交換位置,即schema可能是:

[plain]  view plain  copy
  1. // c1s1 schema1  
  2. time: 4bytes  
  3. version: 4bytes  
  4. digest: 764bytes  
  5. key: 764bytes  

客戶端來決定使用哪種schema,服務器端則需要先嚐試按照schema0解析,失敗則用schema1解析。如下圖所示:


無論key和digest位置如何,它們的結構是不變的:

[plain]  view plain  copy
  1. // 764bytes key結構  
  2. random-data: (offset)bytes  
  3. key-data: 128bytes  
  4. random-data: (764-offset-128-4)bytes  
  5. offset: 4bytes  
  6.   
  7. // 764bytes digest結構  
  8. offset: 4bytes  
  9. random-data: (offset)bytes  
  10. digest-data: 32bytes  
  11. random-data: (764-4-offset-32)bytes  

備註:發現FMS只認識digest-key結構。

如下圖所示:



crtmp中這些全是魔法數字。

complex handshake C2S2結構

C2S2主要是提供對C1S1的驗證。結構如下:

[plain]  view plain  copy
  1. // 1536bytes C2S2結構  
  2. random-data: 1504bytes  
  3. digest-data: 32bytes  

C2S2的結構相對比較簡單。如下圖所示:


下面介紹C1S1C2S2的生成以及驗證算法。

complex handshake C1S1算法

C1S1中都是包含32字節的digest,而且digest將C1S1分成兩部分:

[plain]  view plain  copy
  1. // C1S1被digest分成兩部分  
  2. c1s1-part1: n bytes  
  3. digest-data: 32bytes  
  4. c1s1-part2: (1536-n-32)bytes  

如下圖所示:


在生成C1時,需要用到c1s1-part1和c1s1-part2這兩個部分的字節拼接起來的字節,定義爲:

[plain]  view plain  copy
  1. c1s1-joined = bytes_join(c1s1-part1, c1s1-part2)  

也就是說,把1536字節的c1s1中的32字節的digest拿剪刀剪掉,剩下的頭和尾加在一起就是c1s1-joined。

用到的兩個常量FPKey和FMSKey:

[plain]  view plain  copy
  1. u_int8_t FMSKey[] = {  
  2.     0x47, 0x65, 0x6e, 0x75, 0x69, 0x6e, 0x65, 0x20,  
  3.     0x41, 0x64, 0x6f, 0x62, 0x65, 0x20, 0x46, 0x6c,  
  4.     0x61, 0x73, 0x68, 0x20, 0x4d, 0x65, 0x64, 0x69,  
  5.     0x61, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,  
  6.     0x20, 0x30, 0x30, 0x31, // Genuine Adobe Flash Media Server 001  
  7.     0xf0, 0xee, 0xc2, 0x4a, 0x80, 0x68, 0xbe, 0xe8,  
  8.     0x2e, 0x00, 0xd0, 0xd1, 0x02, 0x9e, 0x7e, 0x57,  
  9.     0x6e, 0xec, 0x5d, 0x2d, 0x29, 0x80, 0x6f, 0xab,  
  10.     0x93, 0xb8, 0xe6, 0x36, 0xcf, 0xeb, 0x31, 0xae  
  11. }; // 68  
  12.   
  13. u_int8_t FPKey[] = {  
  14.     0x47, 0x65, 0x6E, 0x75, 0x69, 0x6E, 0x65, 0x20,  
  15.     0x41, 0x64, 0x6F, 0x62, 0x65, 0x20, 0x46, 0x6C,  
  16.     0x61, 0x73, 0x68, 0x20, 0x50, 0x6C, 0x61, 0x79,  
  17.     0x65, 0x72, 0x20, 0x30, 0x30, 0x31, // Genuine Adobe Flash Player 001  
  18.     0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8,  
  19.     0x2E, 0x00, 0xD0, 0xD1, 0x02, 0x9E, 0x7E, 0x57,  
  20.     0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB,  
  21.     0x93, 0xB8, 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE  
  22. }; // 62  
生成C1的算法如下:

[plain]  view plain  copy
  1. calc_c1_digest(c1, schema) {  
  2.     get c1s1-joined from c1 by specified schema  
  3.     digest-data = HMACsha256(c1s1-joined, FPKey, 30)  
  4.     return digest-data;  
  5. }  
  6. random fill 1536bytes c1 // also fill the c1-128bytes-key  
  7. time = time() // c1[0-3]  
  8. version = [0x80, 0x00, 0x07, 0x02] // c1[4-7]  
  9. schema = choose schema0 or schema1  
  10. digest-data = calc_c1_digest(c1, schema)  
  11. copy digest-data to c1  
生成S1的算法如下:

[plain]  view plain  copy
  1. /*decode c1 try schema0 then schema1*/  
  2. c1-digest-data = get-c1-digest-data(schema0)  
  3. if c1-digest-data equals to calc_c1_digest(c1, schema0) {  
  4.     c1-key-data = get-c1-key-data(schema0)  
  5.     schema = schema0  
  6. } else {  
  7.     c1-digest-data = get-c1-digest-data(schema1)  
  8.     if c1-digest-data not equals to calc_c1_digest(c1, schema1) {  
  9.         switch to simple handshake.  
  10.         return  
  11.     }  
  12.     c1-key-data = get-c1-key-data(schema1)  
  13.     schema = schema1  
  14. }  
  15.   
  16. /*generate s1*/  
  17. random fill 1536bytes s1  
  18. time = time() // c1[0-3]  
  19. version = [0x04, 0x05, 0x00, 0x01] // s1[4-7]  
  20. s1-key-data=shared_key=DH_compute_key(peer_pub_key=c1-key-data)  
  21. get c1s1-joined by specified schema  
  22. s1-digest-data = HMACsha256(c1s1-joined, FMSKey, 36)  
  23. copy s1-digest-data and s1-key-data to s1.  

C1S1的算法完畢。

complex handshake C2S2

C2S2的生成算法如下:

[plain]  view plain  copy
  1. random fill c2s2 1536 bytes  
  2.   
  3. // client generate C2, or server valid C2  
  4. temp-key = HMACsha256(s1-digest, FPKey, 62)  
  5. c2-digest-data = HMACsha256(c2-random-data, temp-key, 32)  
  6.   
  7. // server generate S2, or client valid S2  
  8. temp-key = HMACsha256(c1-digest, FMSKey, 68)  
  9. s2-digest-data = HMACsha256(s2-random-data, temp-key, 32)  
驗證的算法是一樣的。

代碼實現

[cpp]  view plain  copy
  1. /* 
  2. The MIT License (MIT) 
  3.  
  4. Copyright (c) 2013-2014 winlin 
  5.  
  6. Permission is hereby granted, free of charge, to any person obtaining a copy of 
  7. this software and associated documentation files (the "Software"), to deal in 
  8. the Software without restriction, including without limitation the rights to 
  9. use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 
  10. the Software, and to permit persons to whom the Software is furnished to do so, 
  11. subject to the following conditions: 
  12.  
  13. The above copyright notice and this permission notice shall be included in all 
  14. copies or substantial portions of the Software. 
  15.  
  16. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
  17. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 
  18. FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
  19. COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 
  20. IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
  21. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
  22. */  
  23.   
  24. #ifndef SRS_RTMP_PROTOCOL_HANDSHKAE_HPP  
  25. #define SRS_RTMP_PROTOCOL_HANDSHKAE_HPP  
  26.   
  27. /* 
  28. #include  
  29. */  
  30.   
  31. #include   
  32.   
  33. class ISrsProtocolReaderWriter;  
  34. class SrsComplexHandshake;  
  35. class SrsHandshakeBytes;  
  36. class SrsStream;  
  37.   
  38. #ifdef SRS_AUTO_SSL  
  39.   
  40. // for openssl.  
  41. #include   
  42.   
  43. namespace _srs_internal  
  44. {  
  45.     // the digest key generate size.  
  46.     #define __SRS_OpensslHashSize 512  
  47.     extern u_int8_t SrsGenuineFMSKey[];  
  48.     extern u_int8_t SrsGenuineFPKey[];  
  49.     int openssl_HMACsha256(const void* key, int key_size, const void* data, int data_size, void* digest);  
  50.     int openssl_generate_key(char* public_key, int32_t size);  
  51.       
  52.     /** 
  53.     * the DH wrapper. 
  54.     */  
  55.     class SrsDH  
  56.     {  
  57.     private:  
  58.         DH* pdh;  
  59.     public:  
  60.         SrsDH();  
  61.         virtual ~SrsDH();  
  62.     public:  
  63.         /** 
  64.         * initialize dh, generate the public and private key. 
  65.         * @param ensure_128bytes_public_key whether ensure public key is 128bytes, 
  66.         *       sometimes openssl generate 127bytes public key. 
  67.         *       default to false to donot ensure. 
  68.         */  
  69.         virtual int initialize(bool ensure_128bytes_public_key = false);  
  70.         /** 
  71.         * copy the public key. 
  72.         * @param pkey the bytes to copy the public key. 
  73.         * @param pkey_size the max public key size, output the actual public key size. 
  74.         *       user should never ignore this size. 
  75.         * @remark, when ensure_128bytes_public_key, the size always 128. 
  76.         */  
  77.         virtual int copy_public_key(char* pkey, int32_t& pkey_size);  
  78.         /** 
  79.         * generate and copy the shared key. 
  80.         * generate the shared key with peer public key. 
  81.         * @param ppkey peer public key. 
  82.         * @param ppkey_size the size of ppkey. 
  83.         * @param skey the computed shared key. 
  84.         * @param skey_size the max shared key size, output the actual shared key size. 
  85.         *       user should never ignore this size. 
  86.         */  
  87.         virtual int copy_shared_key(const char* ppkey, int32_t ppkey_size, char* skey, int32_t& skey_size);  
  88.     private:  
  89.         virtual int do_initialize();  
  90.     };  
  91.     /** 
  92.     * the schema type. 
  93.     */  
  94.     enum srs_schema_type   
  95.     {  
  96.         srs_schema_invalid = 2,  
  97.           
  98.         /** 
  99.         * key-digest sequence 
  100.         */  
  101.         srs_schema0 = 0,  
  102.           
  103.         /** 
  104.         * digest-key sequence 
  105.         * @remark, FMS requires the schema1(digest-key), or connect failed. 
  106.         */  
  107.         //   
  108.         srs_schema1 = 1,  
  109.     };  
  110.       
  111.     /** 
  112.     * 764bytes key structure 
  113.     *     random-data: (offset)bytes 
  114.     *     key-data: 128bytes 
  115.     *     random-data: (764-offset-128-4)bytes 
  116.     *     offset: 4bytes 
  117.     * @see also: http://blog.csdn.net/win_lin/article/details/13006803 
  118.     */  
  119.     class key_block  
  120.     {  
  121.     public:  
  122.         // (offset)bytes  
  123.         char* random0;  
  124.         int random0_size;  
  125.           
  126.         // 128bytes  
  127.         char key[128];  
  128.           
  129.         // (764-offset-128-4)bytes  
  130.         char* random1;  
  131.         int random1_size;  
  132.           
  133.         // 4bytes  
  134.         int32_t offset;  
  135.     public:  
  136.         key_block();  
  137.         virtual ~key_block();  
  138.     public:  
  139.         // parse key block from c1s1.  
  140.         // if created, user must free it by srs_key_block_free  
  141.         // @stream contains c1s1_key_bytes the key start bytes  
  142.         int parse(SrsStream* stream);  
  143.     private:  
  144.         // calc the offset of key,  
  145.         // the key->offset cannot be used as the offset of key.  
  146.         int calc_valid_offset();  
  147.     };  
  148.       
  149.     /** 
  150.     * 764bytes digest structure 
  151.     *     offset: 4bytes 
  152.     *     random-data: (offset)bytes 
  153.     *     digest-data: 32bytes 
  154.     *     random-data: (764-4-offset-32)bytes 
  155.     * @see also: http://blog.csdn.net/win_lin/article/details/13006803 
  156.     */  
  157.     class digest_block  
  158.     {  
  159.     public:  
  160.         // 4bytes  
  161.         int32_t offset;  
  162.           
  163.         // (offset)bytes  
  164.         char* random0;  
  165.         int random0_size;  
  166.           
  167.         // 32bytes  
  168.         char digest[32];  
  169.           
  170.         // (764-4-offset-32)bytes  
  171.         char* random1;  
  172.         int random1_size;  
  173.     public:  
  174.         digest_block();  
  175.         virtual ~digest_block();  
  176.     public:  
  177.         // parse digest block from c1s1.  
  178.         // if created, user must free it by srs_digest_block_free  
  179.         // @stream contains c1s1_digest_bytes the digest start bytes  
  180.         int parse(SrsStream* stream);  
  181.     private:  
  182.         // calc the offset of digest,  
  183.         // the key->offset cannot be used as the offset of digest.  
  184.         int calc_valid_offset();  
  185.     };  
  186.       
  187.     class c1s1;  
  188.       
  189.     /** 
  190.     * the c1s1 strategy, use schema0 or schema1. 
  191.     * the template method class to defines common behaviors, 
  192.     * while the concrete class to implements in schema0 or schema1. 
  193.     */  
  194.     class c1s1_strategy  
  195.     {  
  196.     protected:  
  197.         key_block key;  
  198.         digest_block digest;  
  199.     public:  
  200.         c1s1_strategy();  
  201.         virtual ~c1s1_strategy();  
  202.     public:  
  203.         /** 
  204.         * get the scema. 
  205.         */  
  206.         virtual srs_schema_type schema() = 0;  
  207.         /** 
  208.         * get the digest. 
  209.         */  
  210.         virtual char* get_digest();  
  211.         /** 
  212.         * get the key. 
  213.         */  
  214.         virtual char* get_key();  
  215.         /** 
  216.         * copy to bytes. 
  217.         * @param size must be 1536. 
  218.         */  
  219.         virtual int dump(c1s1* owner, char* _c1s1, int size);  
  220.         /** 
  221.         * server: parse the c1s1, discovery the key and digest by schema. 
  222.         * use the c1_validate_digest() to valid the digest of c1. 
  223.         */  
  224.         virtual int parse(char* _c1s1, int size) = 0;  
  225.     public:  
  226.         /** 
  227.         * client: create and sign c1 by schema. 
  228.         * sign the c1, generate the digest. 
  229.         *         calc_c1_digest(c1, schema) { 
  230.         *            get c1s1-joined from c1 by specified schema 
  231.         *            digest-data = HMACsha256(c1s1-joined, FPKey, 30) 
  232.         *            return digest-data; 
  233.         *        } 
  234.         *        random fill 1536bytes c1 // also fill the c1-128bytes-key 
  235.         *        time = time() // c1[0-3] 
  236.         *        version = [0x80, 0x00, 0x07, 0x02] // c1[4-7] 
  237.         *        schema = choose schema0 or schema1 
  238.         *        digest-data = calc_c1_digest(c1, schema) 
  239.         *        copy digest-data to c1 
  240.         */  
  241.         virtual int c1_create(c1s1* owner);  
  242.         /** 
  243.         * server: validate the parsed c1 schema 
  244.         */  
  245.         virtual int c1_validate_digest(c1s1* owner, bool& is_valid);  
  246.         /** 
  247.         * server: create and sign the s1 from c1. 
  248.         *       // decode c1 try schema0 then schema1 
  249.         *       c1-digest-data = get-c1-digest-data(schema0) 
  250.         *       if c1-digest-data equals to calc_c1_digest(c1, schema0) {   
  251.         *           c1-key-data = get-c1-key-data(schema0)   
  252.         *           schema = schema0 
  253.         *       } else {   
  254.         *           c1-digest-data = get-c1-digest-data(schema1)   
  255.         *           if c1-digest-data not equals to calc_c1_digest(c1, schema1) { 
  256.         *               switch to simple handshake.   
  257.         *               return   
  258.         *           } 
  259.         *           c1-key-data = get-c1-key-data(schema1)   
  260.         *           schema = schema1 
  261.         *       } 
  262.         *  
  263.         *       // generate s1 
  264.         *       random fill 1536bytes s1 
  265.         *       time = time() // c1[0-3] 
  266.         *       version = [0x04, 0x05, 0x00, 0x01] // s1[4-7] 
  267.         *       s1-key-data=shared_key=DH_compute_key(peer_pub_key=c1-key-data) 
  268.         *       get c1s1-joined by specified schema 
  269.         *       s1-digest-data = HMACsha256(c1s1-joined, FMSKey, 36) 
  270.         *       copy s1-digest-data and s1-key-data to s1. 
  271.         * @param c1, to get the peer_pub_key of client. 
  272.         */  
  273.         virtual int s1_create(c1s1* owner, c1s1* c1);  
  274.         /** 
  275.         * server: validate the parsed s1 schema 
  276.         */  
  277.         virtual int s1_validate_digest(c1s1* owner, bool& is_valid);  
  278.     public:  
  279.         /** 
  280.         * calc the digest for c1 
  281.         */  
  282.         virtual int calc_c1_digest(c1s1* owner, char*& c1_digest);  
  283.         /** 
  284.         * calc the digest for s1 
  285.         */  
  286.         virtual int calc_s1_digest(c1s1* owner, char*& s1_digest);  
  287.         /** 
  288.         * copy whole c1s1 to bytes. 
  289.         * @param size must always be 1536 with digest, and 1504 without digest. 
  290.         */  
  291.         virtual int copy_to(c1s1* owner, char* bytes, int size, bool with_digest) = 0;  
  292.         /** 
  293.         * copy time and version to stream. 
  294.         */  
  295.         virtual void copy_time_version(SrsStream* stream, c1s1* owner);  
  296.         /** 
  297.         * copy key to stream. 
  298.         */  
  299.         virtual void copy_key(SrsStream* stream);  
  300.         /** 
  301.         * copy digest to stream. 
  302.         */  
  303.         virtual void copy_digest(SrsStream* stream, bool with_digest);  
  304.     };  
  305.       
  306.     /** 
  307.     * c1s1 schema0 
  308.     *     key: 764bytes 
  309.     *     digest: 764bytes 
  310.     */  
  311.     class c1s1_strategy_schema0 : public c1s1_strategy  
  312.     {  
  313.     public:  
  314.         c1s1_strategy_schema0();  
  315.         virtual ~c1s1_strategy_schema0();  
  316.     public:  
  317.         virtual srs_schema_type schema();  
  318.         virtual int parse(char* _c1s1, int size);  
  319.     public:  
  320.         virtual int copy_to(c1s1* owner, char* bytes, int size, bool with_digest);  
  321.     };  
  322.       
  323.     /** 
  324.     * c1s1 schema1 
  325.     *     digest: 764bytes 
  326.     *     key: 764bytes 
  327.     */  
  328.     class c1s1_strategy_schema1 : public c1s1_strategy  
  329.     {  
  330.     public:  
  331.         c1s1_strategy_schema1();  
  332.         virtual ~c1s1_strategy_schema1();  
  333.     public:  
  334.         virtual srs_schema_type schema();  
  335.         virtual int parse(char* _c1s1, int size);  
  336.     public:  
  337.         virtual int copy_to(c1s1* owner, char* bytes, int size, bool with_digest);  
  338.     };  
  339.   
  340.     /** 
  341.     * c1s1 schema0 
  342.     *     time: 4bytes 
  343.     *     version: 4bytes 
  344.     *     key: 764bytes 
  345.     *     digest: 764bytes 
  346.     * c1s1 schema1 
  347.     *     time: 4bytes 
  348.     *     version: 4bytes 
  349.     *     digest: 764bytes 
  350.     *     key: 764bytes 
  351.     * @see also: http://blog.csdn.net/win_lin/article/details/13006803 
  352.     */  
  353.     class c1s1  
  354.     {  
  355.     public:  
  356.         // 4bytes  
  357.         int32_t time;  
  358.         // 4bytes  
  359.         int32_t version;  
  360.         // 764bytes+764bytes  
  361.         c1s1_strategy* payload;  
  362.     public:  
  363.         c1s1();  
  364.         virtual ~c1s1();  
  365.     public:  
  366.         /** 
  367.         * get the scema. 
  368.         */  
  369.         virtual srs_schema_type schema();  
  370.         /** 
  371.         * get the digest key. 
  372.         */  
  373.         virtual char* get_digest();  
  374.         /** 
  375.         * get the key. 
  376.         */  
  377.         virtual char* get_key();  
  378.     public:  
  379.         /** 
  380.         * copy to bytes. 
  381.         * @param size, must always be 1536. 
  382.         */  
  383.         virtual int dump(char* _c1s1, int size);  
  384.         /** 
  385.         * server: parse the c1s1, discovery the key and digest by schema. 
  386.         * @param size, must always be 1536. 
  387.         * use the c1_validate_digest() to valid the digest of c1. 
  388.         * use the s1_validate_digest() to valid the digest of s1. 
  389.         */  
  390.         virtual int parse(char* _c1s1, int size, srs_schema_type _schema);  
  391.     public:  
  392.         /** 
  393.         * client: create and sign c1 by schema. 
  394.         * sign the c1, generate the digest. 
  395.         *         calc_c1_digest(c1, schema) { 
  396.         *            get c1s1-joined from c1 by specified schema 
  397.         *            digest-data = HMACsha256(c1s1-joined, FPKey, 30) 
  398.         *            return digest-data; 
  399.         *        } 
  400.         *        random fill 1536bytes c1 // also fill the c1-128bytes-key 
  401.         *        time = time() // c1[0-3] 
  402.         *        version = [0x80, 0x00, 0x07, 0x02] // c1[4-7] 
  403.         *        schema = choose schema0 or schema1 
  404.         *        digest-data = calc_c1_digest(c1, schema) 
  405.         *        copy digest-data to c1 
  406.         */  
  407.         virtual int c1_create(srs_schema_type _schema);  
  408.         /** 
  409.         * server: validate the parsed c1 schema 
  410.         */  
  411.         virtual int c1_validate_digest(bool& is_valid);  
  412.     public:  
  413.         /** 
  414.         * server: create and sign the s1 from c1. 
  415.         *       // decode c1 try schema0 then schema1 
  416.         *       c1-digest-data = get-c1-digest-data(schema0) 
  417.         *       if c1-digest-data equals to calc_c1_digest(c1, schema0) {   
  418.         *           c1-key-data = get-c1-key-data(schema0)   
  419.         *           schema = schema0 
  420.         *       } else {   
  421.         *           c1-digest-data = get-c1-digest-data(schema1)   
  422.         *           if c1-digest-data not equals to calc_c1_digest(c1, schema1) { 
  423.         *               switch to simple handshake.   
  424.         *               return   
  425.         *           } 
  426.         *           c1-key-data = get-c1-key-data(schema1)   
  427.         *           schema = schema1 
  428.         *       } 
  429.         *  
  430.         *       // generate s1 
  431.         *       random fill 1536bytes s1 
  432.         *       time = time() // c1[0-3] 
  433.         *       version = [0x04, 0x05, 0x00, 0x01] // s1[4-7] 
  434.         *       s1-key-data=shared_key=DH_compute_key(peer_pub_key=c1-key-data) 
  435.         *       get c1s1-joined by specified schema 
  436.         *       s1-digest-data = HMACsha256(c1s1-joined, FMSKey, 36) 
  437.         *       copy s1-digest-data and s1-key-data to s1. 
  438.         */  
  439.         virtual int s1_create(c1s1* c1);  
  440.         /** 
  441.         * server: validate the parsed s1 schema 
  442.         */  
  443.         virtual int s1_validate_digest(bool& is_valid);  
  444.     };  
  445.       
  446.     /** 
  447.     * the c2s2 complex handshake structure. 
  448.     * random-data: 1504bytes 
  449.     * digest-data: 32bytes 
  450.     * @see also: http://blog.csdn.net/win_lin/article/details/13006803 
  451.     */  
  452.     class c2s2  
  453.     {  
  454.     public:  
  455.         char random[1504];  
  456.         char digest[32];  
  457.     public:  
  458.         c2s2();  
  459.         virtual ~c2s2();  
  460.     public:  
  461.         /** 
  462.         * copy to bytes. 
  463.         * @param size, must always be 1536. 
  464.         */  
  465.         virtual int dump(char* _c2s2, int size);  
  466.         /** 
  467.         * parse the c2s2 
  468.         * @param size, must always be 1536. 
  469.         */  
  470.         virtual int parse(char* _c2s2, int size);  
  471.     public:  
  472.         /** 
  473.         * create c2. 
  474.         * random fill c2s2 1536 bytes 
  475.         *  
  476.         * // client generate C2, or server valid C2 
  477.         * temp-key = HMACsha256(s1-digest, FPKey, 62) 
  478.         * c2-digest-data = HMACsha256(c2-random-data, temp-key, 32) 
  479.         */  
  480.         virtual int c2_create(c1s1* s1);  
  481.           
  482.         /** 
  483.         * validate the c2 from client. 
  484.         */  
  485.         virtual int c2_validate(c1s1* s1, bool& is_valid);  
  486.     public:  
  487.         /** 
  488.         * create s2. 
  489.         * random fill c2s2 1536 bytes 
  490.         *  
  491.         * // server generate S2, or client valid S2 
  492.         * temp-key = HMACsha256(c1-digest, FMSKey, 68) 
  493.         * s2-digest-data = HMACsha256(s2-random-data, temp-key, 32) 
  494.         */  
  495.         virtual int s2_create(c1s1* c1);  
  496.           
  497.         /** 
  498.         * validate the s2 from server. 
  499.         */  
  500.         virtual int s2_validate(c1s1* c1, bool& is_valid);  
  501.     };  
  502. }  
  503.   
  504. #endif  
  505.   
  506. /** 
  507. * simple handshake. 
  508. * user can try complex handshake first,  
  509. * rollback to simple handshake if error ERROR_RTMP_TRY_SIMPLE_HS 
  510. */  
  511. class SrsSimpleHandshake  
  512. {  
  513. public:  
  514.     SrsSimpleHandshake();  
  515.     virtual ~SrsSimpleHandshake();  
  516. public:  
  517.     /** 
  518.     * simple handshake. 
  519.     */  
  520.     virtual int handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io);  
  521.     virtual int handshake_with_server(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io);  
  522. };  
  523.   
  524. /** 
  525. * rtmp complex handshake, 
  526. * @see also crtmp(crtmpserver) or librtmp, 
  527. * @see also: http://blog.csdn.net/win_lin/article/details/13006803 
  528. */  
  529. class SrsComplexHandshake  
  530. {  
  531. public:  
  532.     SrsComplexHandshake();  
  533.     virtual ~SrsComplexHandshake();  
  534. public:  
  535.     /** 
  536.     * complex hanshake. 
  537.     * @return user must: 
  538.     *     continue connect app if success, 
  539.     *     try simple handshake if error is ERROR_RTMP_TRY_SIMPLE_HS, 
  540.     *     otherwise, disconnect 
  541.     */  
  542.     virtual int handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io);  
  543.     virtual int handshake_with_server(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io);  
  544. };  
  545.   
  546. #endif  
  547. /* 
  548. The MIT License (MIT) 
  549.  
  550. Copyright (c) 2013-2014 winlin 
  551.  
  552. Permission is hereby granted, free of charge, to any person obtaining a copy of 
  553. this software and associated documentation files (the "Software"), to deal in 
  554. the Software without restriction, including without limitation the rights to 
  555. use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 
  556. the Software, and to permit persons to whom the Software is furnished to do so, 
  557. subject to the following conditions: 
  558.  
  559. The above copyright notice and this permission notice shall be included in all 
  560. copies or substantial portions of the Software. 
  561.  
  562. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
  563. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 
  564. FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
  565. COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 
  566. IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
  567. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
  568. */  
  569.   
  570. #include   
  571.   
  572. #include   
  573.   
  574. #include   
  575. #include   
  576. #include   
  577. #include   
  578. #include   
  579. #include   
  580. #include   
  581.   
  582. #ifdef SRS_AUTO_SSL  
  583.   
  584. using namespace _srs_internal;  
  585.   
  586. // for openssl_HMACsha256  
  587. #include   
  588. #include   
  589. // for __openssl_generate_key  
  590. #include   
  591.   
  592. namespace _srs_internal  
  593. {  
  594.     // 68bytes FMS key which is used to sign the sever packet.  
  595.     u_int8_t SrsGenuineFMSKey[] = {  
  596.         0x47, 0x65, 0x6e, 0x75, 0x69, 0x6e, 0x65, 0x20,  
  597.         0x41, 0x64, 0x6f, 0x62, 0x65, 0x20, 0x46, 0x6c,  
  598.         0x61, 0x73, 0x68, 0x20, 0x4d, 0x65, 0x64, 0x69,  
  599.         0x61, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,  
  600.         0x20, 0x30, 0x30, 0x31, // Genuine Adobe Flash Media Server 001  
  601.         0xf0, 0xee, 0xc2, 0x4a, 0x80, 0x68, 0xbe, 0xe8,  
  602.         0x2e, 0x00, 0xd0, 0xd1, 0x02, 0x9e, 0x7e, 0x57,  
  603.         0x6e, 0xec, 0x5d, 0x2d, 0x29, 0x80, 0x6f, 0xab,  
  604.         0x93, 0xb8, 0xe6, 0x36, 0xcf, 0xeb, 0x31, 0xae  
  605.     }; // 68  
  606.       
  607.     // 62bytes FP key which is used to sign the client packet.  
  608.     u_int8_t SrsGenuineFPKey[] = {  
  609.         0x47, 0x65, 0x6E, 0x75, 0x69, 0x6E, 0x65, 0x20,  
  610.         0x41, 0x64, 0x6F, 0x62, 0x65, 0x20, 0x46, 0x6C,  
  611.         0x61, 0x73, 0x68, 0x20, 0x50, 0x6C, 0x61, 0x79,  
  612.         0x65, 0x72, 0x20, 0x30, 0x30, 0x31, // Genuine Adobe Flash Player 001  
  613.         0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8,  
  614.         0x2E, 0x00, 0xD0, 0xD1, 0x02, 0x9E, 0x7E, 0x57,  
  615.         0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB,  
  616.         0x93, 0xB8, 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE  
  617.     }; // 62  
  618.       
  619.     int __openssl_HMACsha256(HMAC_CTX* ctx, const void* data, int data_size, void* digest, unsigned int* digest_size)   
  620.     {  
  621.         int ret = ERROR_SUCCESS;  
  622.           
  623.         if (HMAC_Update(ctx, (unsigned char *) data, data_size) < 0) {  
  624.             ret = ERROR_OpenSslSha256Update;  
  625.             return ret;  
  626.         }  
  627.       
  628.         if (HMAC_Final(ctx, (unsigned char *) digest, digest_size) < 0) {  
  629.             ret = ERROR_OpenSslSha256Final;  
  630.             return ret;  
  631.         }  
  632.           
  633.         return ret;  
  634.     }  
  635.     /** 
  636.     * sha256 digest algorithm. 
  637.     * @param key the sha256 key, NULL to use EVP_Digest, for instance, 
  638.     *       hashlib.sha256(data).digest(). 
  639.     */  
  640.     int openssl_HMACsha256(const void* key, int key_size, const void* data, int data_size, void* digest)   
  641.     {  
  642.         int ret = ERROR_SUCCESS;  
  643.           
  644.         unsigned int digest_size = 0;  
  645.           
  646.         unsigned char* __key = (unsigned char*)key;  
  647.         unsigned char* __digest = (unsigned char*)digest;  
  648.           
  649.         if (key == NULL) {  
  650.             // use data to digest.  
  651.             // @see ./crypto/sha/sha256t.c  
  652.             // @see ./crypto/evp/digest.c  
  653.             if (EVP_Digest(data, data_size, __digest, &digest_size, EVP_sha256(), NULL) < 0)  
  654.             {  
  655.                 ret = ERROR_OpenSslSha256EvpDigest;  
  656.                 return ret;  
  657.             }  
  658.         } else {  
  659.             // use key-data to digest.  
  660.             HMAC_CTX ctx;  
  661.               
  662.             // @remark, if no key, use EVP_Digest to digest,  
  663.             // for instance, in python, hashlib.sha256(data).digest().  
  664.             HMAC_CTX_init(&ctx);  
  665.               
  666.             if (HMAC_Init_ex(&ctx, __key, key_size, EVP_sha256(), NULL) < 0) {  
  667.                 ret = ERROR_OpenSslSha256Init;  
  668.                 return ret;  
  669.             }  
  670.               
  671.             ret = __openssl_HMACsha256(&ctx, data, data_size, __digest, &digest_size);  
  672.             HMAC_CTX_cleanup(&ctx);  
  673.               
  674.             if (ret != ERROR_SUCCESS) {  
  675.                 return ret;  
  676.             }  
  677.         }  
  678.           
  679.         if (digest_size != 32) {  
  680.             ret = ERROR_OpenSslSha256DigestSize;  
  681.             return ret;  
  682.         }  
  683.           
  684.         return ret;  
  685.     }  
  686.       
  687.     #define RFC2409_PRIME_1024 \  
  688.             "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \  
  689.             "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \  
  690.             "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \  
  691.             "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \  
  692.             "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \  
  693.             "FFFFFFFFFFFFFFFF"  
  694.       
  695.     SrsDH::SrsDH()  
  696.     {  
  697.         pdh = NULL;  
  698.     }  
  699.       
  700.     SrsDH::~SrsDH()  
  701.     {  
  702.         if (pdh != NULL) {  
  703.             if (pdh->p != NULL) {  
  704.                 BN_free(pdh->p);  
  705.                 pdh->p = NULL;  
  706.             }  
  707.             if (pdh->g != NULL) {  
  708.                 BN_free(pdh->g);  
  709.                 pdh->g = NULL;  
  710.             }  
  711.             DH_free(pdh);  
  712.             pdh = NULL;  
  713.         }  
  714.     }  
  715.       
  716.     int SrsDH::initialize(bool ensure_128bytes_public_key)  
  717.     {  
  718.         int ret = ERROR_SUCCESS;  
  719.           
  720.         for (;;) {  
  721.             if ((ret = do_initialize()) != ERROR_SUCCESS) {  
  722.                 return ret;  
  723.             }  
  724.               
  725.             if (ensure_128bytes_public_key) {  
  726.                 int32_t key_size = BN_num_bytes(pdh->pub_key);  
  727.                 if (key_size != 128) {  
  728.                     srs_warn("regenerate 128B key, current=%dB", key_size);  
  729.                     continue;  
  730.                 }  
  731.             }  
  732.               
  733.             break;  
  734.         }  
  735.           
  736.         return ret;  
  737.     }  
  738.       
  739.     int SrsDH::copy_public_key(char* pkey, int32_t& pkey_size)  
  740.     {  
  741.         int ret = ERROR_SUCCESS;  
  742.           
  743.         // copy public key to bytes.  
  744.         // sometimes, the key_size is 127, seems ok.  
  745.         int32_t key_size = BN_num_bytes(pdh->pub_key);  
  746.         srs_assert(key_size > 0);  
  747.           
  748.         // maybe the key_size is 127, but dh will write all 128bytes pkey,  
  749.         // so, donot need to set/initialize the pkey.  
  750.         // @see https://github.com/winlinvip/simple-rtmp-server/issues/165  
  751.         key_size = BN_bn2bin(pdh->pub_key, (unsigned char*)pkey);  
  752.         srs_assert(key_size > 0);  
  753.           
  754.         // output the size of public key.  
  755.         // @see https://github.com/winlinvip/simple-rtmp-server/issues/165  
  756.         srs_assert(key_size <= pkey_size);  
  757.         pkey_size = key_size;  
  758.           
  759.         return ret;  
  760.     }  
  761.       
  762.     int SrsDH::copy_shared_key(const char* ppkey, int32_t ppkey_size, char* skey, int32_t& skey_size)  
  763.     {  
  764.         int ret = ERROR_SUCCESS;  
  765.           
  766.         BIGNUM* ppk = NULL;  
  767.         if ((ppk = BN_bin2bn((const unsigned char*)ppkey, ppkey_size, 0)) == NULL) {  
  768.             ret = ERROR_OpenSslGetPeerPublicKey;  
  769.             return ret;  
  770.         }  
  771.           
  772.         // if failed, donot return, do cleanup, @see ./test/dhtest.c:168  
  773.         // maybe the key_size is 127, but dh will write all 128bytes skey,  
  774.         // so, donot need to set/initialize the skey.  
  775.         // @see https://github.com/winlinvip/simple-rtmp-server/issues/165  
  776.         int32_t key_size = DH_compute_key((unsigned char*)skey, ppk, pdh);  
  777.           
  778.         if (key_size < ppkey_size) {  
  779.             srs_warn("shared key size=%d, ppk_size=%d", key_size, ppkey_size);  
  780.         }  
  781.           
  782.         if (key_size < 0 || key_size > skey_size) {  
  783.             ret = ERROR_OpenSslComputeSharedKey;  
  784.         } else {  
  785.             skey_size = key_size;  
  786.         }  
  787.           
  788.         if (ppk) {  
  789.             BN_free(ppk);  
  790.         }  
  791.           
  792.         return ret;  
  793.     }  
  794.       
  795.     int SrsDH::do_initialize()  
  796.     {  
  797.         int ret = ERROR_SUCCESS;  
  798.           
  799.         int32_t bits_count = 1024;   
  800.           
  801.         //1. Create the DH  
  802.         if ((pdh = DH_new()) == NULL) {  
  803.             ret = ERROR_OpenSslCreateDH;   
  804.             return ret;  
  805.         }  
  806.       
  807.         //2. Create his internal p and g  
  808.         if ((pdh->p = BN_new()) == NULL) {  
  809.             ret = ERROR_OpenSslCreateP;   
  810.             return ret;  
  811.         }  
  812.         if ((pdh->g = BN_new()) == NULL) {  
  813.             ret = ERROR_OpenSslCreateG;   
  814.             return ret;  
  815.         }  
  816.       
  817.         //3. initialize p and g, @see ./test/ectest.c:260  
  818.         if (!BN_hex2bn(&pdh->p, RFC2409_PRIME_1024)) {  
  819.             ret = ERROR_OpenSslParseP1024;   
  820.             return ret;  
  821.         }  
  822.         // @see ./test/bntest.c:1764  
  823.         if (!BN_set_word(pdh->g, 2)) {  
  824.             ret = ERROR_OpenSslSetG;  
  825.             return ret;  
  826.         }  
  827.       
  828.         // 4. Set the key length  
  829.         pdh->length = bits_count;  
  830.       
  831.         // 5. Generate private and public key  
  832.         // @see ./test/dhtest.c:152  
  833.         if (!DH_generate_key(pdh)) {  
  834.             ret = ERROR_OpenSslGenerateDHKeys;  
  835.             return ret;  
  836.         }  
  837.           
  838.         return ret;  
  839.     }  
  840.       
  841.     key_block::key_block()  
  842.     {  
  843.         offset = (int32_t)rand();  
  844.         random0 = NULL;  
  845.         random1 = NULL;  
  846.           
  847.         int valid_offset = calc_valid_offset();  
  848.         srs_assert(valid_offset >= 0);  
  849.           
  850.         random0_size = valid_offset;  
  851.         if (random0_size > 0) {  
  852.             random0 = new char[random0_size];  
  853.             srs_random_generate(random0, random0_size);  
  854.             snprintf(random0, random0_size, "%s", RTMP_SIG_SRS_HANDSHAKE);  
  855.         }  
  856.           
  857.         srs_random_generate(key, sizeof(key));  
  858.           
  859.         random1_size = 764 - valid_offset - 128 - 4;  
  860.         if (random1_size > 0) {  
  861.             random1 = new char[random1_size];  
  862.             srs_random_generate(random1, random1_size);  
  863.             snprintf(random1, random1_size, "%s", RTMP_SIG_SRS_HANDSHAKE);  
  864.         }  
  865.     }  
  866.       
  867.     key_block::~key_block()  
  868.     {  
  869.         srs_freep(random0);  
  870.         srs_freep(random1);  
  871.     }  
  872.       
  873.     int key_block::parse(SrsStream* stream)  
  874.     {  
  875.         int ret = ERROR_SUCCESS;  
  876.           
  877.         // the key must be 764 bytes.  
  878.         srs_assert(stream->require(764));  
  879.       
  880.         // read the last offset first, 760-763  
  881.         stream->skip(764 - sizeof(int32_t));  
  882.         offset = stream->read_4bytes();  
  883.           
  884.         // reset stream to read others.  
  885.         stream->skip(-764);  
  886.           
  887.         int valid_offset = calc_valid_offset();  
  888.         srs_assert(valid_offset >= 0);  
  889.           
  890.         random0_size = valid_offset;  
  891.         if (random0_size > 0) {  
  892.             srs_freep(random0);  
  893.             random0 = new char[random0_size];  
  894.             stream->read_bytes(random0, random0_size);  
  895.         }  
  896.           
  897.         stream->read_bytes(key, 128);  
  898.           
  899.         random1_size = 764 - valid_offset - 128 - 4;  
  900.         if (random1_size > 0) {  
  901.             srs_freep(random1);  
  902.             random1 = new char[random1_size];  
  903.             stream->read_bytes(random1, random1_size);  
  904.         }  
  905.           
  906.         return ret;  
  907.     }  
  908.       
  909.     int key_block::calc_valid_offset()  
  910.     {  
  911.         int max_offset_size = 764 - 128 - 4;  
  912.           
  913.         int valid_offset = 0;  
  914.         u_int8_t* pp = (u_int8_t*)&offset;  
  915.         valid_offset += *pp++;  
  916.         valid_offset += *pp++;  
  917.         valid_offset += *pp++;  
  918.         valid_offset += *pp++;  
  919.       
  920.         return valid_offset % max_offset_size;  
  921.     }  
  922.       
  923.     digest_block::digest_block()  
  924.     {  
  925.         offset = (int32_t)rand();  
  926.         random0 = NULL;  
  927.         random1 = NULL;  
  928.           
  929.         int valid_offset = calc_valid_offset();  
  930.         srs_assert(valid_offset >= 0);  
  931.           
  932.         random0_size = valid_offset;  
  933.         if (random0_size > 0) {  
  934.             random0 = new char[random0_size];  
  935.             srs_random_generate(random0, random0_size);  
  936.             snprintf(random0, random0_size, "%s", RTMP_SIG_SRS_HANDSHAKE);  
  937.         }  
  938.           
  939.         srs_random_generate(digest, sizeof(digest));  
  940.           
  941.         random1_size = 764 - 4 - valid_offset - 32;  
  942.         if (random1_size > 0) {  
  943.             random1 = new char[random1_size];  
  944.             srs_random_generate(random1, random1_size);  
  945.             snprintf(random1, random1_size, "%s", RTMP_SIG_SRS_HANDSHAKE);  
  946.         }  
  947.     }  
  948.       
  949.     digest_block::~digest_block()  
  950.     {  
  951.         srs_freep(random0);  
  952.         srs_freep(random1);  
  953.     }  
  954.   
  955.     int digest_block::parse(SrsStream* stream)  
  956.     {  
  957.         int ret = ERROR_SUCCESS;  
  958.           
  959.         // the digest must be 764 bytes.  
  960.         srs_assert(stream->require(764));  
  961.           
  962.         offset = stream->read_4bytes();  
  963.           
  964.         int valid_offset = calc_valid_offset();  
  965.         srs_assert(valid_offset >= 0);  
  966.           
  967.         random0_size = valid_offset;  
  968.         if (random0_size > 0) {  
  969.             srs_freep(random0);  
  970.             random0 = new char[random0_size];  
  971.             stream->read_bytes(random0, random0_size);  
  972.         }  
  973.           
  974.         stream->read_bytes(digest, 32);  
  975.           
  976.         random1_size = 764 - 4 - valid_offset - 32;  
  977.         if (random1_size > 0) {  
  978.             srs_freep(random1);  
  979.             random1 = new char[random1_size];  
  980.             stream->read_bytes(random1, random1_size);  
  981.         }  
  982.           
  983.         return ret;  
  984.     }  
  985.       
  986.     int digest_block::calc_valid_offset()  
  987.     {  
  988.         int max_offset_size = 764 - 32 - 4;  
  989.           
  990.         int valid_offset = 0;  
  991.         u_int8_t* pp = (u_int8_t*)&offset;  
  992.         valid_offset += *pp++;  
  993.         valid_offset += *pp++;  
  994.         valid_offset += *pp++;  
  995.         valid_offset += *pp++;  
  996.       
  997.         return valid_offset % max_offset_size;  
  998.     }  
  999.       
  1000.     c1s1_strategy::c1s1_strategy()  
  1001.     {  
  1002.     }  
  1003.       
  1004.     c1s1_strategy::~c1s1_strategy()  
  1005.     {  
  1006.     }  
  1007.       
  1008.     char* c1s1_strategy::get_digest()  
  1009.     {  
  1010.         return digest.digest;  
  1011.     }  
  1012.       
  1013.     char* c1s1_strategy::get_key()  
  1014.     {  
  1015.         return key.key;  
  1016.     }  
  1017.       
  1018.     int c1s1_strategy::dump(c1s1* owner, char* _c1s1, int size)  
  1019.     {  
  1020.         srs_assert(size == 1536);  
  1021.         return copy_to(owner, _c1s1, size, true);  
  1022.     }  
  1023.       
  1024.     int c1s1_strategy::c1_create(c1s1* owner)  
  1025.     {  
  1026.         int ret = ERROR_SUCCESS;  
  1027.           
  1028.         // generate digest  
  1029.         char* c1_digest = NULL;  
  1030.           
  1031.         if ((ret = calc_c1_digest(owner, c1_digest)) != ERROR_SUCCESS) {  
  1032.             srs_error("sign c1 error, failed to calc digest. ret=%d", ret);  
  1033.             return ret;  
  1034.         }  
  1035.           
  1036.         srs_assert(c1_digest != NULL);  
  1037.         SrsAutoFree(char, c1_digest);  
  1038.           
  1039.         memcpy(digest.digest, c1_digest, 32);  
  1040.           
  1041.         return ret;  
  1042.     }  
  1043.       
  1044.     int c1s1_strategy::c1_validate_digest(c1s1* owner, bool& is_valid)  
  1045.     {  
  1046.         int ret = ERROR_SUCCESS;  
  1047.           
  1048.         char* c1_digest = NULL;  
  1049.           
  1050.         if ((ret = calc_c1_digest(owner, c1_digest)) != ERROR_SUCCESS) {  
  1051.             srs_error("validate c1 error, failed to calc digest. ret=%d", ret);  
  1052.             return ret;  
  1053.         }  
  1054.           
  1055.         srs_assert(c1_digest != NULL);  
  1056.         SrsAutoFree(char, c1_digest);  
  1057.           
  1058.         is_valid = srs_bytes_equals(digest.digest, c1_digest, 32);  
  1059.           
  1060.         return ret;  
  1061.     }  
  1062.       
  1063.     int c1s1_strategy::s1_create(c1s1* owner, c1s1* c1)  
  1064.     {  
  1065.         int ret = ERROR_SUCCESS;  
  1066.   
  1067.         SrsDH dh;  
  1068.           
  1069.         // ensure generate 128bytes public key.  
  1070.         if ((ret = dh.initialize(true)) != ERROR_SUCCESS) {  
  1071.             return ret;  
  1072.         }  
  1073.           
  1074.         // directly generate the public key.  
  1075.         // @see: https://github.com/winlinvip/simple-rtmp-server/issues/148  
  1076.         int pkey_size = 128;  
  1077.         if ((ret = dh.copy_shared_key(c1->get_key(), 128, key.key, pkey_size)) != ERROR_SUCCESS) {  
  1078.             srs_error("calc s1 key failed. ret=%d", ret);  
  1079.             return ret;  
  1080.         }  
  1081.         srs_assert(pkey_size == 128);  
  1082.         srs_verbose("calc s1 key success.");  
  1083.               
  1084.         char* s1_digest = NULL;  
  1085.         if ((ret = calc_s1_digest(owner, s1_digest))  != ERROR_SUCCESS) {  
  1086.             srs_error("calc s1 digest failed. ret=%d", ret);  
  1087.             return ret;  
  1088.         }  
  1089.         srs_verbose("calc s1 digest success.");  
  1090.           
  1091.         srs_assert(s1_digest != NULL);  
  1092.         SrsAutoFree(char, s1_digest);  
  1093.           
  1094.         memcpy(digest.digest, s1_digest, 32);  
  1095.         srs_verbose("copy s1 key success.");  
  1096.           
  1097.         return ret;  
  1098.     }  
  1099.       
  1100.     int c1s1_strategy::s1_validate_digest(c1s1* owner, bool& is_valid)  
  1101.     {  
  1102.         int ret = ERROR_SUCCESS;  
  1103.           
  1104.         char* s1_digest = NULL;  
  1105.           
  1106.         if ((ret = calc_s1_digest(owner, s1_digest)) != ERROR_SUCCESS) {  
  1107.             srs_error("validate s1 error, failed to calc digest. ret=%d", ret);  
  1108.             return ret;  
  1109.         }  
  1110.           
  1111.         srs_assert(s1_digest != NULL);  
  1112.         SrsAutoFree(char, s1_digest);  
  1113.           
  1114.         is_valid = srs_bytes_equals(digest.digest, s1_digest, 32);  
  1115.           
  1116.         return ret;  
  1117.     }  
  1118.       
  1119.     int c1s1_strategy::calc_c1_digest(c1s1* owner, char*& c1_digest)  
  1120.     {  
  1121.         int ret = ERROR_SUCCESS;  
  1122.   
  1123.         /** 
  1124.         * c1s1 is splited by digest: 
  1125.         *     c1s1-part1: n bytes (time, version, key and digest-part1). 
  1126.         *     digest-data: 32bytes 
  1127.         *     c1s1-part2: (1536-n-32)bytes (digest-part2) 
  1128.         * @return a new allocated bytes, user must free it. 
  1129.         */  
  1130.         char* c1s1_joined_bytes = new char[1536 -32];  
  1131.         SrsAutoFree(char, c1s1_joined_bytes);  
  1132.         if ((ret = copy_to(owner, c1s1_joined_bytes, 1536 - 32, false)) != ERROR_SUCCESS) {  
  1133.             return ret;  
  1134.         }  
  1135.           
  1136.         c1_digest = new char[__SRS_OpensslHashSize];  
  1137.         if ((ret = openssl_HMACsha256(SrsGenuineFPKey, 30, c1s1_joined_bytes, 1536 - 32, c1_digest)) != ERROR_SUCCESS) {  
  1138.             srs_freep(c1_digest);  
  1139.             srs_error("calc digest for c1 failed. ret=%d", ret);  
  1140.             return ret;  
  1141.         }  
  1142.         srs_verbose("digest calculated for c1");  
  1143.           
  1144.         return ret;  
  1145.     }  
  1146.       
  1147.     int c1s1_strategy::calc_s1_digest(c1s1* owner, char*& s1_digest)  
  1148.     {  
  1149.         int ret = ERROR_SUCCESS;  
  1150.   
  1151.         /** 
  1152.         * c1s1 is splited by digest: 
  1153.         *     c1s1-part1: n bytes (time, version, key and digest-part1). 
  1154.         *     digest-data: 32bytes 
  1155.         *     c1s1-part2: (1536-n-32)bytes (digest-part2) 
  1156.         * @return a new allocated bytes, user must free it. 
  1157.         */  
  1158.         char* c1s1_joined_bytes = new char[1536 -32];  
  1159.         SrsAutoFree(char, c1s1_joined_bytes);  
  1160.         if ((ret = copy_to(owner, c1s1_joined_bytes, 1536 - 32, false)) != ERROR_SUCCESS) {  
  1161.             return ret;  
  1162.         }  
  1163.           
  1164.         s1_digest = new char[__SRS_OpensslHashSize];  
  1165.         if ((ret = openssl_HMACsha256(SrsGenuineFMSKey, 36, c1s1_joined_bytes, 1536 - 32, s1_digest)) != ERROR_SUCCESS) {  
  1166.             srs_freep(s1_digest);  
  1167.             srs_error("calc digest for s1 failed. ret=%d", ret);  
  1168.             return ret;  
  1169.         }  
  1170.         srs_verbose("digest calculated for s1");  
  1171.   
  1172.         return ret;  
  1173.     }  
  1174.       
  1175.     void c1s1_strategy::copy_time_version(SrsStream* stream, c1s1* owner)  
  1176.     {  
  1177.         srs_assert(stream->require(8));  
  1178.           
  1179.         // 4bytes time  
  1180.         stream->write_4bytes(owner->time);  
  1181.   
  1182.         // 4bytes version  
  1183.         stream->write_4bytes(owner->version);  
  1184.     }  
  1185.     void c1s1_strategy::copy_key(SrsStream* stream)  
  1186.     {  
  1187.         srs_assert(key.random0_size >= 0);  
  1188.         srs_assert(key.random1_size >= 0);  
  1189.           
  1190.         int total = key.random0_size + 128 + key.random1_size + 4;  
  1191.         srs_assert(stream->require(total));  
  1192.           
  1193.         // 764bytes key block  
  1194.         if (key.random0_size > 0) {  
  1195.             stream->write_bytes(key.random0, key.random0_size);  
  1196.         }  
  1197.           
  1198.         stream->write_bytes(key.key, 128);  
  1199.           
  1200.         if (key.random1_size > 0) {  
  1201.             stream->write_bytes(key.random1, key.random1_size);  
  1202.         }  
  1203.           
  1204.         stream->write_4bytes(key.offset);  
  1205.     }  
  1206.     void c1s1_strategy::copy_digest(SrsStream* stream, bool with_digest)  
  1207.     {  
  1208.         srs_assert(key.random0_size >= 0);  
  1209.         srs_assert(key.random1_size >= 0);  
  1210.           
  1211.         int total = 4 + digest.random0_size + digest.random1_size;  
  1212.         if (with_digest) {  
  1213.             total += 32;  
  1214.         }  
  1215.         srs_assert(stream->require(total));  
  1216.           
  1217.         // 732bytes digest block without the 32bytes digest-data  
  1218.         // nbytes digest block part1  
  1219.         stream->write_4bytes(digest.offset);  
  1220.           
  1221.         // digest random padding.  
  1222.         if (digest.random0_size > 0) {  
  1223.             stream->write_bytes(digest.random0, digest.random0_size);  
  1224.         }  
  1225.           
  1226.         // digest  
  1227.         if (with_digest) {  
  1228.             stream->write_bytes(digest.digest, 32);  
  1229.         }  
  1230.           
  1231.         // nbytes digest block part2  
  1232.         if (digest.random1_size > 0) {  
  1233.             stream->write_bytes(digest.random1, digest.random1_size);  
  1234.         }  
  1235.     }  
  1236.       
  1237.     c1s1_strategy_schema0::c1s1_strategy_schema0()  
  1238.     {  
  1239.     }  
  1240.       
  1241.     c1s1_strategy_schema0::~c1s1_strategy_schema0()  
  1242.     {  
  1243.     }  
  1244.       
  1245.     srs_schema_type c1s1_strategy_schema0::schema()  
  1246.     {  
  1247.         return srs_schema0;  
  1248.     }  
  1249.       
  1250.     int c1s1_strategy_schema0::parse(char* _c1s1, int size)  
  1251.     {  
  1252.         int ret = ERROR_SUCCESS;  
  1253.           
  1254.         srs_assert(size == 1536);  
  1255.           
  1256.         SrsStream stream;  
  1257.           
  1258.         if ((ret = stream.initialize(_c1s1 + 8, 764)) != ERROR_SUCCESS) {  
  1259.             return ret;  
  1260.         }  
  1261.           
  1262.         if ((ret = key.parse(&stream)) != ERROR_SUCCESS) {  
  1263.             srs_error("parse the c1 key failed. ret=%d", ret);  
  1264.             return ret;  
  1265.         }  
  1266.           
  1267.         if ((ret = stream.initialize(_c1s1 + 8 + 764, 764)) != ERROR_SUCCESS) {  
  1268.             return ret;  
  1269.         }  
  1270.   
  1271.         if ((ret = digest.parse(&stream)) != ERROR_SUCCESS) {  
  1272.             srs_error("parse the c1 digest failed. ret=%d", ret);  
  1273.             return ret;  
  1274.         }  
  1275.           
  1276.         srs_verbose("parse c1 key-digest success");  
  1277.           
  1278.         return ret;  
  1279.     }  
  1280.       
  1281.     int c1s1_strategy_schema0::copy_to(c1s1* owner, char* bytes, int size, bool with_digest)  
  1282.     {  
  1283.         int ret = ERROR_SUCCESS;  
  1284.           
  1285.         if (with_digest) {  
  1286.             srs_assert(size == 1536);  
  1287.         } else {  
  1288.             srs_assert(size == 1504);  
  1289.         }  
  1290.           
  1291.         SrsStream stream;  
  1292.           
  1293.         if ((ret = stream.initialize(bytes, size)) != ERROR_SUCCESS) {  
  1294.             return ret;  
  1295.         }  
  1296.           
  1297.         copy_time_version(&stream, owner);  
  1298.         copy_key(&stream);  
  1299.         copy_digest(&stream, with_digest);  
  1300.           
  1301.         srs_assert(stream.empty());  
  1302.           
  1303.         return ret;  
  1304.     }  
  1305.       
  1306.     c1s1_strategy_schema1::c1s1_strategy_schema1()  
  1307.     {  
  1308.     }  
  1309.       
  1310.     c1s1_strategy_schema1::~c1s1_strategy_schema1()  
  1311.     {  
  1312.     }  
  1313.       
  1314.     srs_schema_type c1s1_strategy_schema1::schema()  
  1315.     {  
  1316.         return srs_schema1;  
  1317.     }  
  1318.       
  1319.     int c1s1_strategy_schema1::parse(char* _c1s1, int size)  
  1320.     {  
  1321.         int ret = ERROR_SUCCESS;  
  1322.           
  1323.         srs_assert(size == 1536);  
  1324.           
  1325.         SrsStream stream;  
  1326.           
  1327.         if ((ret = stream.initialize(_c1s1 + 8, 764)) != ERROR_SUCCESS) {  
  1328.             return ret;  
  1329.         }  
  1330.   
  1331.         if ((ret = digest.parse(&stream)) != ERROR_SUCCESS) {  
  1332.             srs_error("parse the c1 digest failed. ret=%d", ret);  
  1333.             return ret;  
  1334.         }  
  1335.           
  1336.         if ((ret = stream.initialize(_c1s1 + 8 + 764, 764)) != ERROR_SUCCESS) {  
  1337.             return ret;  
  1338.         }  
  1339.           
  1340.         if ((ret = key.parse(&stream)) != ERROR_SUCCESS) {  
  1341.             srs_error("parse the c1 key failed. ret=%d", ret);  
  1342.             return ret;  
  1343.         }  
  1344.           
  1345.         srs_verbose("parse c1 digest-key success");  
  1346.           
  1347.         return ret;  
  1348.     }  
  1349.       
  1350.     int c1s1_strategy_schema1::copy_to(c1s1* owner, char* bytes, int size, bool with_digest)  
  1351.     {  
  1352.         int ret = ERROR_SUCCESS;  
  1353.           
  1354.         if (with_digest) {  
  1355.             srs_assert(size == 1536);  
  1356.         } else {  
  1357.             srs_assert(size == 1504);  
  1358.         }  
  1359.           
  1360.         SrsStream stream;  
  1361.           
  1362.         if ((ret = stream.initialize(bytes, size)) != ERROR_SUCCESS) {  
  1363.             return ret;  
  1364.         }  
  1365.           
  1366.         copy_time_version(&stream, owner);  
  1367.         copy_digest(&stream, with_digest);  
  1368.         copy_key(&stream);  
  1369.           
  1370.         srs_assert(stream.empty());  
  1371.           
  1372.         return ret;  
  1373.     }  
  1374.       
  1375.     c1s1::c1s1()  
  1376.     {  
  1377.         payload = NULL;  
  1378.     }  
  1379.     c1s1::~c1s1()  
  1380.     {  
  1381.         srs_freep(payload);  
  1382.     }  
  1383.       
  1384.     srs_schema_type c1s1::schema()  
  1385.     {  
  1386.         srs_assert(payload != NULL);  
  1387.         return payload->schema();  
  1388.     }  
  1389.       
  1390.     char* c1s1::get_digest()  
  1391.     {  
  1392.         srs_assert(payload != NULL);  
  1393.         return payload->get_digest();  
  1394.     }  
  1395.       
  1396.     char* c1s1::get_key()  
  1397.     {  
  1398.         srs_assert(payload != NULL);  
  1399.         return payload->get_key();  
  1400.     }  
  1401.       
  1402.     int c1s1::dump(char* _c1s1, int size)  
  1403.     {  
  1404.         srs_assert(size == 1536);  
  1405.         srs_assert(payload != NULL);  
  1406.         return payload->dump(this, _c1s1, size);  
  1407.     }  
  1408.       
  1409.     int c1s1::parse(char* _c1s1, int size, srs_schema_type schema)  
  1410.     {  
  1411.         int ret = ERROR_SUCCESS;  
  1412.           
  1413.         srs_assert(size == 1536);  
  1414.           
  1415.         if (schema != srs_schema0 && schema != srs_schema1) {  
  1416.             ret = ERROR_RTMP_CH_SCHEMA;  
  1417.             srs_error("parse c1 failed. invalid schema=%d, ret=%d", schema, ret);  
  1418.             return ret;  
  1419.         }  
  1420.           
  1421.         SrsStream stream;  
  1422.           
  1423.         if ((ret = stream.initialize(_c1s1, size)) != ERROR_SUCCESS) {  
  1424.             return ret;  
  1425.         }  
  1426.           
  1427.         time = stream.read_4bytes();  
  1428.         version = stream.read_4bytes(); // client c1 version  
  1429.           
  1430.         srs_freep(payload);  
  1431.         if (schema == srs_schema0) {  
  1432.             payload = new c1s1_strategy_schema0();  
  1433.         } else {  
  1434.             payload = new c1s1_strategy_schema1();  
  1435.         }  
  1436.   
  1437.         return payload->parse(_c1s1, size);  
  1438.     }  
  1439.       
  1440.     int c1s1::c1_create(srs_schema_type schema)  
  1441.     {  
相關文章
相關標籤/搜索