fix #165, refine dh wrapper, ensure public key is 128bytes. 0.9.206.
正在显示
5 个修改的文件
包含
162 行增加
和
99 行删除
| @@ -208,6 +208,7 @@ Supported operating systems and hardware: | @@ -208,6 +208,7 @@ Supported operating systems and hardware: | ||
| 208 | * 2013-10-17, Created.<br/> | 208 | * 2013-10-17, Created.<br/> |
| 209 | 209 | ||
| 210 | ## History | 210 | ## History |
| 211 | +* v1.0, 2014-08-22, for [#165](https://github.com/winlinvip/simple-rtmp-server/issues/165), refine dh wrapper, ensure public key is 128bytes. 0.9.206. | ||
| 211 | * v1.0, 2014-08-19, for [#160](https://github.com/winlinvip/simple-rtmp-server/issues/160), support forward/edge to flussonic, disable debug_srs_upnode to make flussonic happy. 0.9.201. | 212 | * v1.0, 2014-08-19, for [#160](https://github.com/winlinvip/simple-rtmp-server/issues/160), support forward/edge to flussonic, disable debug_srs_upnode to make flussonic happy. 0.9.201. |
| 212 | * v1.0, 2014-08-17, for [#155](https://github.com/winlinvip/simple-rtmp-server/issues/155), refine for osx, with ssl/http, disable statistics. 0.9.198. | 213 | * v1.0, 2014-08-17, for [#155](https://github.com/winlinvip/simple-rtmp-server/issues/155), refine for osx, with ssl/http, disable statistics. 0.9.198. |
| 213 | * v1.0, 2014-08-06, fix [#148](https://github.com/winlinvip/simple-rtmp-server/issues/148), simplify the RTMP handshake key generation. 0.9.191. | 214 | * v1.0, 2014-08-06, fix [#148](https://github.com/winlinvip/simple-rtmp-server/issues/148), simplify the RTMP handshake key generation. 0.9.191. |
| @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 31 | // current release version | 31 | // current release version |
| 32 | #define VERSION_MAJOR "0" | 32 | #define VERSION_MAJOR "0" |
| 33 | #define VERSION_MINOR "9" | 33 | #define VERSION_MINOR "9" |
| 34 | -#define VERSION_REVISION "205" | 34 | +#define VERSION_REVISION "206" |
| 35 | #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION | 35 | #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION |
| 36 | // server info. | 36 | // server info. |
| 37 | #define RTMP_SIG_SRS_KEY "SRS" | 37 | #define RTMP_SIG_SRS_KEY "SRS" |
| @@ -145,88 +145,100 @@ namespace _srs_internal | @@ -145,88 +145,100 @@ namespace _srs_internal | ||
| 145 | "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ | 145 | "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ |
| 146 | "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \ | 146 | "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \ |
| 147 | "FFFFFFFFFFFFFFFF" | 147 | "FFFFFFFFFFFFFFFF" |
| 148 | - /** | ||
| 149 | - * initialize DH, create the public/private key. | ||
| 150 | - */ | ||
| 151 | - int __openssl_initialize_dh(DH* pdh, int32_t bits_count) | ||
| 152 | - { | ||
| 153 | - int ret = ERROR_SUCCESS; | ||
| 154 | 148 | ||
| 155 | - //2. Create his internal p and g | ||
| 156 | - if ((pdh->p = BN_new()) == NULL) { | ||
| 157 | - ret = ERROR_OpenSslCreateP; | ||
| 158 | - return ret; | ||
| 159 | - } | ||
| 160 | - if ((pdh->g = BN_new()) == NULL) { | ||
| 161 | - ret = ERROR_OpenSslCreateG; | ||
| 162 | - return ret; | ||
| 163 | - } | 149 | + SrsDH::SrsDH() |
| 150 | + { | ||
| 151 | + pdh = NULL; | ||
| 152 | + } | ||
| 164 | 153 | ||
| 165 | - //3. initialize p and g | ||
| 166 | - if (BN_hex2bn(&pdh->p, RFC2409_PRIME_1024) == 0) { | ||
| 167 | - ret = ERROR_OpenSslParseP1024; | ||
| 168 | - return ret; | ||
| 169 | - } | ||
| 170 | - if (BN_set_word(pdh->g, 2) != 1) { | ||
| 171 | - ret = ERROR_OpenSslSetG; | ||
| 172 | - return ret; | 154 | + SrsDH::~SrsDH() |
| 155 | + { | ||
| 156 | + if (pdh != NULL) { | ||
| 157 | + if (pdh->p != NULL) { | ||
| 158 | + BN_free(pdh->p); | ||
| 159 | + pdh->p = NULL; | ||
| 160 | + } | ||
| 161 | + if (pdh->g != NULL) { | ||
| 162 | + BN_free(pdh->g); | ||
| 163 | + pdh->g = NULL; | ||
| 164 | + } | ||
| 165 | + DH_free(pdh); | ||
| 166 | + pdh = NULL; | ||
| 173 | } | 167 | } |
| 168 | + } | ||
| 174 | 169 | ||
| 175 | - //4. Set the key length | ||
| 176 | - pdh->length = bits_count; | ||
| 177 | - | ||
| 178 | - //5. Generate private and public key | ||
| 179 | - if (DH_generate_key(pdh) != 1) { | ||
| 180 | - ret = ERROR_OpenSslGenerateDHKeys; | ||
| 181 | - return ret; | 170 | + int SrsDH::initialize(bool ensure_128bytes_public_key) |
| 171 | + { | ||
| 172 | + int ret = ERROR_SUCCESS; | ||
| 173 | + | ||
| 174 | + for (;;) { | ||
| 175 | + if ((ret = do_initialize()) != ERROR_SUCCESS) { | ||
| 176 | + return ret; | ||
| 177 | + } | ||
| 178 | + | ||
| 179 | + if (ensure_128bytes_public_key) { | ||
| 180 | + int32_t key_size = BN_num_bytes(pdh->pub_key); | ||
| 181 | + if (key_size != 128) { | ||
| 182 | + srs_warn("regenerate 128B key, current=%dB", key_size); | ||
| 183 | + continue; | ||
| 184 | + } | ||
| 185 | + } | ||
| 186 | + | ||
| 187 | + break; | ||
| 182 | } | 188 | } |
| 183 | 189 | ||
| 184 | return ret; | 190 | return ret; |
| 185 | } | 191 | } |
| 186 | - /** | ||
| 187 | - * create DH and copy the 128bytes public key. | ||
| 188 | - */ | ||
| 189 | - int __openssl_copy_key(DH* pdh, char* public_key, int32_t size) | 192 | + |
| 193 | + int SrsDH::copy_public_key(char* pkey, int32_t* ppkey_size) | ||
| 190 | { | 194 | { |
| 191 | int ret = ERROR_SUCCESS; | 195 | int ret = ERROR_SUCCESS; |
| 192 | 196 | ||
| 193 | - int32_t bits_count = 1024; | ||
| 194 | - | ||
| 195 | - // 2. generate the g, p, private/public key. | ||
| 196 | - if ((ret = __openssl_initialize_dh(pdh, bits_count)) != ERROR_SUCCESS) { | ||
| 197 | - return ret; | ||
| 198 | - } | ||
| 199 | - | ||
| 200 | // copy public key to bytes. | 197 | // copy public key to bytes. |
| 201 | // sometimes, the key_size is 127, seems ok. | 198 | // sometimes, the key_size is 127, seems ok. |
| 202 | int32_t key_size = BN_num_bytes(pdh->pub_key); | 199 | int32_t key_size = BN_num_bytes(pdh->pub_key); |
| 203 | srs_assert(key_size > 0); | 200 | srs_assert(key_size > 0); |
| 204 | 201 | ||
| 205 | - if (BN_bn2bin(pdh->pub_key, (unsigned char*)public_key) != size) { | ||
| 206 | - //("Unable to copy key"); return ret; | ||
| 207 | - ret = ERROR_OpenSslCopyKey; | ||
| 208 | - return ret; | 202 | + key_size = BN_bn2bin(pdh->pub_key, (unsigned char*)pkey); |
| 203 | + srs_assert(key_size > 0); | ||
| 204 | + | ||
| 205 | + if (ppkey_size != NULL) { | ||
| 206 | + // output the size of public key. | ||
| 207 | + // @see https://github.com/winlinvip/simple-rtmp-server/issues/165 | ||
| 208 | + srs_assert(key_size <= *ppkey_size); | ||
| 209 | + *ppkey_size = key_size; | ||
| 209 | } | 210 | } |
| 210 | 211 | ||
| 211 | return ret; | 212 | return ret; |
| 212 | } | 213 | } |
| 213 | - /** | ||
| 214 | - * use exists DH to create and copy the 128bytes shared key. | ||
| 215 | - * the peer public key used to generate the shared key. | ||
| 216 | - */ | ||
| 217 | - int __openssl_copy_shared_key(DH* pdh, const char* peer_pub_key, int ppk_size, char* shared_key) | 214 | + |
| 215 | + int SrsDH::copy_shared_key(const char* ppkey, int32_t ppkey_size, char* skey, int32_t* pskey_size) | ||
| 218 | { | 216 | { |
| 219 | int ret = ERROR_SUCCESS; | 217 | int ret = ERROR_SUCCESS; |
| 220 | 218 | ||
| 221 | BIGNUM* ppk = NULL; | 219 | BIGNUM* ppk = NULL; |
| 222 | - if ((ppk = BN_bin2bn((const unsigned char*)peer_pub_key, ppk_size, 0)) == NULL) { | 220 | + if ((ppk = BN_bin2bn((const unsigned char*)ppkey, ppkey_size, 0)) == NULL) { |
| 223 | ret = ERROR_OpenSslGetPeerPublicKey; | 221 | ret = ERROR_OpenSslGetPeerPublicKey; |
| 224 | return ret; | 222 | return ret; |
| 225 | } | 223 | } |
| 226 | 224 | ||
| 227 | - // if failed, donot return, do cleanup. | ||
| 228 | - if (DH_compute_key((unsigned char*)shared_key, ppk, pdh) < 0) { | 225 | + // if failed, donot return, do cleanup, @see ./test/dhtest.c:168 |
| 226 | + int32_t key_size = DH_compute_key((unsigned char*)skey, ppk, pdh); | ||
| 227 | + | ||
| 228 | + if (key_size < ppkey_size) { | ||
| 229 | + srs_warn("shared key size=%d, ppk_size=%d", key_size, ppkey_size); | ||
| 230 | + } | ||
| 231 | + | ||
| 232 | + if (key_size < 0) { | ||
| 229 | ret = ERROR_OpenSslComputeSharedKey; | 233 | ret = ERROR_OpenSslComputeSharedKey; |
| 234 | + } else { | ||
| 235 | + if (pskey_size != NULL) { | ||
| 236 | + if (key_size > *pskey_size) { | ||
| 237 | + ret = ERROR_OpenSslComputeSharedKey; | ||
| 238 | + } else { | ||
| 239 | + *pskey_size = key_size; | ||
| 240 | + } | ||
| 241 | + } | ||
| 230 | } | 242 | } |
| 231 | 243 | ||
| 232 | if (ppk) { | 244 | if (ppk) { |
| @@ -235,60 +247,50 @@ namespace _srs_internal | @@ -235,60 +247,50 @@ namespace _srs_internal | ||
| 235 | 247 | ||
| 236 | return ret; | 248 | return ret; |
| 237 | } | 249 | } |
| 238 | - /** | ||
| 239 | - * create DH and copy the 128bytes public key, | ||
| 240 | - * generate and copy the shared key. | ||
| 241 | - */ | ||
| 242 | - int __openssl_compute_key(DH* pdh, const char* peer_pub_key, int ppk_size, char* public_key, char* shared_key) | 250 | + |
| 251 | + int SrsDH::do_initialize() | ||
| 243 | { | 252 | { |
| 244 | int ret = ERROR_SUCCESS; | 253 | int ret = ERROR_SUCCESS; |
| 245 | 254 | ||
| 246 | - // create DH and copy the 128bytes public key | ||
| 247 | - if ((ret = __openssl_copy_key(pdh, public_key, ppk_size)) != ERROR_SUCCESS) { | 255 | + int32_t bits_count = 1024; |
| 256 | + | ||
| 257 | + //1. Create the DH | ||
| 258 | + if ((pdh = DH_new()) == NULL) { | ||
| 259 | + ret = ERROR_OpenSslCreateDH; | ||
| 248 | return ret; | 260 | return ret; |
| 249 | } | 261 | } |
| 250 | - | ||
| 251 | - // generate and copy the shared key | ||
| 252 | - if ((ret = __openssl_copy_shared_key(pdh, peer_pub_key, ppk_size, shared_key)) != ERROR_SUCCESS) { | 262 | + |
| 263 | + //2. Create his internal p and g | ||
| 264 | + if ((pdh->p = BN_new()) == NULL) { | ||
| 265 | + ret = ERROR_OpenSslCreateP; | ||
| 253 | return ret; | 266 | return ret; |
| 254 | } | 267 | } |
| 255 | - | ||
| 256 | - return ret; | ||
| 257 | - } | ||
| 258 | - void __openssl_free(DH* pdh) | ||
| 259 | - { | ||
| 260 | - if (pdh != NULL) { | ||
| 261 | - if (pdh->p != NULL) { | ||
| 262 | - BN_free(pdh->p); | ||
| 263 | - pdh->p = NULL; | ||
| 264 | - } | ||
| 265 | - if (pdh->g != NULL) { | ||
| 266 | - BN_free(pdh->g); | ||
| 267 | - pdh->g = NULL; | ||
| 268 | - } | ||
| 269 | - DH_free(pdh); | ||
| 270 | - pdh = NULL; | 268 | + if ((pdh->g = BN_new()) == NULL) { |
| 269 | + ret = ERROR_OpenSslCreateG; | ||
| 270 | + return ret; | ||
| 271 | + } | ||
| 272 | + | ||
| 273 | + //3. initialize p and g, @see ./test/ectest.c:260 | ||
| 274 | + if (!BN_hex2bn(&pdh->p, RFC2409_PRIME_1024)) { | ||
| 275 | + ret = ERROR_OpenSslParseP1024; | ||
| 276 | + return ret; | ||
| 277 | + } | ||
| 278 | + // @see ./test/bntest.c:1764 | ||
| 279 | + if (!BN_set_word(pdh->g, 2)) { | ||
| 280 | + ret = ERROR_OpenSslSetG; | ||
| 281 | + return ret; | ||
| 271 | } | 282 | } |
| 272 | - } | ||
| 273 | - int openssl_generate_key(char* public_key, int32_t size) | ||
| 274 | - { | ||
| 275 | - int ret = ERROR_SUCCESS; | ||
| 276 | 283 | ||
| 277 | - // Initialize | ||
| 278 | - DH* pdh = NULL; | 284 | + // 4. Set the key length |
| 285 | + pdh->length = bits_count; | ||
| 279 | 286 | ||
| 280 | - //1. Create the DH | ||
| 281 | - if ((pdh = DH_new()) == NULL) { | ||
| 282 | - ret = ERROR_OpenSslCreateDH; | 287 | + // 5. Generate private and public key |
| 288 | + // @see ./test/dhtest.c:152 | ||
| 289 | + if (!DH_generate_key(pdh)) { | ||
| 290 | + ret = ERROR_OpenSslGenerateDHKeys; | ||
| 283 | return ret; | 291 | return ret; |
| 284 | } | 292 | } |
| 285 | 293 | ||
| 286 | - // generate and copy key. | ||
| 287 | - ret = __openssl_copy_key(pdh, public_key, size); | ||
| 288 | - | ||
| 289 | - // cleanup | ||
| 290 | - __openssl_free(pdh); | ||
| 291 | - | ||
| 292 | return ret; | 294 | return ret; |
| 293 | } | 295 | } |
| 294 | 296 | ||
| @@ -933,13 +935,17 @@ namespace _srs_internal | @@ -933,13 +935,17 @@ namespace _srs_internal | ||
| 933 | time = ::time(NULL); | 935 | time = ::time(NULL); |
| 934 | version = 0x01000504; // server s1 version | 936 | version = 0x01000504; // server s1 version |
| 935 | 937 | ||
| 938 | + SrsDH dh; | ||
| 939 | + if ((ret = dh.initialize(true)) != ERROR_SUCCESS) { | ||
| 940 | + return ret; | ||
| 941 | + } | ||
| 936 | if (schema == srs_schema0) { | 942 | if (schema == srs_schema0) { |
| 937 | srs_key_block_init(&block0.key); | 943 | srs_key_block_init(&block0.key); |
| 938 | srs_digest_block_init(&block1.digest); | 944 | srs_digest_block_init(&block1.digest); |
| 939 | 945 | ||
| 940 | // directly generate the public key. | 946 | // directly generate the public key. |
| 941 | // @see: https://github.com/winlinvip/simple-rtmp-server/issues/148 | 947 | // @see: https://github.com/winlinvip/simple-rtmp-server/issues/148 |
| 942 | - if ((ret = openssl_generate_key(block0.key.key, 128)) != ERROR_SUCCESS) { | 948 | + if ((ret = dh.copy_public_key((char*)block0.key.key, NULL)) != ERROR_SUCCESS) { |
| 943 | srs_error("calc s1 key failed. ret=%d", ret); | 949 | srs_error("calc s1 key failed. ret=%d", ret); |
| 944 | return ret; | 950 | return ret; |
| 945 | } | 951 | } |
| @@ -949,7 +955,7 @@ namespace _srs_internal | @@ -949,7 +955,7 @@ namespace _srs_internal | ||
| 949 | 955 | ||
| 950 | // directly generate the public key. | 956 | // directly generate the public key. |
| 951 | // @see: https://github.com/winlinvip/simple-rtmp-server/issues/148 | 957 | // @see: https://github.com/winlinvip/simple-rtmp-server/issues/148 |
| 952 | - if ((ret = openssl_generate_key(block1.key.key, 128)) != ERROR_SUCCESS) { | 958 | + if ((ret = dh.copy_public_key((char*)block1.key.key, NULL)) != ERROR_SUCCESS) { |
| 953 | srs_error("calc s1 key failed. ret=%d", ret); | 959 | srs_error("calc s1 key failed. ret=%d", ret); |
| 954 | return ret; | 960 | return ret; |
| 955 | } | 961 | } |
| @@ -36,6 +36,9 @@ class SrsHandshakeBytes; | @@ -36,6 +36,9 @@ class SrsHandshakeBytes; | ||
| 36 | 36 | ||
| 37 | #ifdef SRS_AUTO_SSL | 37 | #ifdef SRS_AUTO_SSL |
| 38 | 38 | ||
| 39 | +// for openssl. | ||
| 40 | +#include <openssl/hmac.h> | ||
| 41 | + | ||
| 39 | namespace _srs_internal | 42 | namespace _srs_internal |
| 40 | { | 43 | { |
| 41 | /** | 44 | /** |
| @@ -117,6 +120,46 @@ namespace _srs_internal | @@ -117,6 +120,46 @@ namespace _srs_internal | ||
| 117 | int openssl_HMACsha256(const void* key, int key_size, const void* data, int data_size, void* digest); | 120 | int openssl_HMACsha256(const void* key, int key_size, const void* data, int data_size, void* digest); |
| 118 | int openssl_generate_key(char* public_key, int32_t size); | 121 | int openssl_generate_key(char* public_key, int32_t size); |
| 119 | 122 | ||
| 123 | + /** | ||
| 124 | + * the DH wrapper. | ||
| 125 | + */ | ||
| 126 | + class SrsDH | ||
| 127 | + { | ||
| 128 | + private: | ||
| 129 | + DH* pdh; | ||
| 130 | + public: | ||
| 131 | + SrsDH(); | ||
| 132 | + virtual ~SrsDH(); | ||
| 133 | + public: | ||
| 134 | + /** | ||
| 135 | + * initialize dh, generate the public and private key. | ||
| 136 | + * @param ensure_128bytes_public_key whether ensure public key is 128bytes, | ||
| 137 | + * sometimes openssl generate 127bytes public key. | ||
| 138 | + * default to false to donot ensure. | ||
| 139 | + */ | ||
| 140 | + virtual int initialize(bool ensure_128bytes_public_key = false); | ||
| 141 | + /** | ||
| 142 | + * copy the public key. | ||
| 143 | + * @param pkey the bytes to copy the public key. | ||
| 144 | + * @param ppkey_size the max public key size, output the actual public key size. | ||
| 145 | + * NULL to ignore. | ||
| 146 | + * @remark, when ensure_128bytes_public_key, the size always 128. | ||
| 147 | + */ | ||
| 148 | + virtual int copy_public_key(char* pkey, int32_t* ppkey_size); | ||
| 149 | + /** | ||
| 150 | + * generate and copy the shared key. | ||
| 151 | + * generate the shared key with peer public key. | ||
| 152 | + * @param ppkey peer public key. | ||
| 153 | + * @param ppkey_size the size of ppkey. | ||
| 154 | + * @param skey the computed shared key. | ||
| 155 | + * @param pskey_size the max shared key size, output the actual shared key size. | ||
| 156 | + * NULL to ignore. | ||
| 157 | + */ | ||
| 158 | + virtual int copy_shared_key(const char* ppkey, int32_t ppkey_size, char* skey, int32_t* pskey_size); | ||
| 159 | + private: | ||
| 160 | + virtual int do_initialize(); | ||
| 161 | + }; | ||
| 162 | + | ||
| 120 | // calc the offset of key, | 163 | // calc the offset of key, |
| 121 | // the key->offset cannot be used as the offset of key. | 164 | // the key->offset cannot be used as the offset of key. |
| 122 | int srs_key_block_get_offset(key_block* key); | 165 | int srs_key_block_get_offset(key_block* key); |
| @@ -238,11 +238,24 @@ VOID TEST(ProtocolHandshakeTest, OpensslSha256) | @@ -238,11 +238,24 @@ VOID TEST(ProtocolHandshakeTest, OpensslSha256) | ||
| 238 | // verify the dh key | 238 | // verify the dh key |
| 239 | VOID TEST(ProtocolHandshakeTest, DHKey) | 239 | VOID TEST(ProtocolHandshakeTest, DHKey) |
| 240 | { | 240 | { |
| 241 | + _srs_internal::SrsDH dh; | ||
| 242 | + | ||
| 243 | + ASSERT_TRUE(ERROR_SUCCESS == dh.initialize(true)); | ||
| 244 | + | ||
| 241 | char pub_key1[128]; | 245 | char pub_key1[128]; |
| 242 | - openssl_generate_key(pub_key1, 128); | 246 | + EXPECT_TRUE(ERROR_SUCCESS == dh.copy_public_key(pub_key1, NULL)); |
| 243 | 247 | ||
| 244 | char pub_key2[128]; | 248 | char pub_key2[128]; |
| 245 | - openssl_generate_key(pub_key2, 128); | 249 | + EXPECT_TRUE(ERROR_SUCCESS == dh.copy_public_key(pub_key2, NULL)); |
| 250 | + | ||
| 251 | + EXPECT_TRUE(srs_bytes_equals(pub_key1, pub_key2, 128)); | ||
| 252 | + | ||
| 253 | + // another dh | ||
| 254 | + _srs_internal::SrsDH dh0; | ||
| 255 | + | ||
| 256 | + ASSERT_TRUE(ERROR_SUCCESS == dh0.initialize(true)); | ||
| 257 | + | ||
| 258 | + EXPECT_TRUE(ERROR_SUCCESS == dh0.copy_public_key(pub_key2, NULL)); | ||
| 246 | 259 | ||
| 247 | EXPECT_FALSE(srs_bytes_equals(pub_key1, pub_key2, 128)); | 260 | EXPECT_FALSE(srs_bytes_equals(pub_key1, pub_key2, 128)); |
| 248 | } | 261 | } |
-
请 注册 或 登录 后发表评论