Signed-off-by: James Almer <[email protected]>
---
libavformat/rtmpcrypt.c | 66 +++++++++++++++++++++++++++++++------------------
libavformat/rtmpcrypt.h | 5 ++--
libavformat/rtmpproto.c | 15 ++++++-----
3 files changed, 54 insertions(+), 32 deletions(-)
diff --git a/libavformat/rtmpcrypt.c b/libavformat/rtmpcrypt.c
index 887427d..9144938 100644
--- a/libavformat/rtmpcrypt.c
+++ b/libavformat/rtmpcrypt.c
@@ -28,6 +28,7 @@
#include "libavutil/blowfish.h"
#include "libavutil/intreadwrite.h"
+#include "libavutil/mem.h"
#include "libavutil/opt.h"
#include "libavutil/rc4.h"
#include "libavutil/xtea.h"
@@ -43,8 +44,8 @@ typedef struct RTMPEContext {
const AVClass *class;
URLContext *stream; ///< TCP stream
FF_DH *dh; ///< Diffie-Hellman context
- struct AVRC4 key_in; ///< RC4 key used for decrypt data
- struct AVRC4 key_out; ///< RC4 key used for encrypt data
+ struct AVRC4 *key_in; ///< RC4 key used for decrypt data
+ struct AVRC4 *key_out; ///< RC4 key used for encrypt data
int handshaked; ///< flag indicating when the handshake
is performed
int tunneling; ///< use a HTTP connection (RTMPTE)
} RTMPEContext;
@@ -170,54 +171,69 @@ int ff_rtmpe_compute_secret_key(URLContext *h, const
uint8_t *serverdata,
if ((ret = ff_rtmp_calc_digest(serverdata + server_pos, 128, 0, secret_key,
128, digest)) < 0)
return ret;
- av_rc4_init(&rt->key_out, digest, 16 * 8, 1);
+
+ if (!(rt->key_out = av_rc4_alloc()))
+ return AVERROR(ENOMEM);
+ av_rc4_init(rt->key_out, digest, 16 * 8, 1);
/* set input key */
if ((ret = ff_rtmp_calc_digest(clientdata + client_pos, 128, 0, secret_key,
128, digest)) < 0)
return ret;
- av_rc4_init(&rt->key_in, digest, 16 * 8, 1);
+
+ if (!(rt->key_in = av_rc4_alloc()))
+ return AVERROR(ENOMEM);
+ av_rc4_init(rt->key_in, digest, 16 * 8, 1);
return 0;
}
-static void rtmpe8_sig(const uint8_t *in, uint8_t *out, int key_id)
+static void rtmpe8_sig(struct AVXTEA *ctx, const uint8_t *in, uint8_t *out,
int key_id)
{
- struct AVXTEA ctx;
-
- av_xtea_init(&ctx, rtmpe8_keys[key_id]);
- av_xtea_crypt(&ctx, out, in, 1, NULL, 0);
+ av_xtea_init(ctx, rtmpe8_keys[key_id]);
+ av_xtea_crypt(ctx, out, in, 1, NULL, 0);
}
-static void rtmpe9_sig(const uint8_t *in, uint8_t *out, int key_id)
+static void rtmpe9_sig(struct AVBlowfish *ctx, const uint8_t *in, uint8_t
*out, int key_id)
{
- struct AVBlowfish ctx;
uint32_t xl, xr;
xl = AV_RL32(in);
xr = AV_RL32(in + 4);
- av_blowfish_init(&ctx, rtmpe9_keys[key_id], 24);
- av_blowfish_crypt_ecb(&ctx, &xl, &xr, 0);
+ av_blowfish_init(ctx, rtmpe9_keys[key_id], 24);
+ av_blowfish_crypt_ecb(ctx, &xl, &xr, 0);
AV_WL32(out, xl);
AV_WL32(out + 4, xr);
}
-void ff_rtmpe_encrypt_sig(URLContext *h, uint8_t *sig, const uint8_t *digest,
+int ff_rtmpe_encrypt_sig(URLContext *h, uint8_t *sig, const uint8_t *digest,
int type)
{
int i;
- for (i = 0; i < 32; i += 8) {
- if (type == 8) {
+ if (type == 8) {
+ struct AVXTEA *ctx = av_xtea_alloc();
+
+ if (!ctx)
+ return AVERROR(ENOMEM);
+ for (i = 0; i < 32; i += 8)
/* RTMPE type 8 uses XTEA on the signature */
- rtmpe8_sig(sig + i, sig + i, digest[i] % 15);
- } else if (type == 9) {
+ rtmpe8_sig(ctx, sig + i, sig + i, digest[i] % 15);
+ av_free(ctx);
+ } else if (type == 9) {
+ struct AVBlowfish *ctx = av_blowfish_alloc();
+
+ if (!ctx)
+ return AVERROR(ENOMEM);
+ for (i = 0; i < 32; i += 8)
/* RTMPE type 9 uses Blowfish on the signature */
- rtmpe9_sig(sig + i, sig + i, digest[i] % 15);
- }
+ rtmpe9_sig(ctx, sig + i, sig + i, digest[i] % 15);
+ av_free(ctx);
}
+
+ return 0;
}
int ff_rtmpe_update_keystream(URLContext *h)
@@ -226,8 +242,8 @@ int ff_rtmpe_update_keystream(URLContext *h)
char buf[RTMP_HANDSHAKE_PACKET_SIZE];
/* skip past 1536 bytes of the RC4 bytestream */
- av_rc4_crypt(&rt->key_in, buf, NULL, sizeof(buf), NULL, 1);
- av_rc4_crypt(&rt->key_out, buf, NULL, sizeof(buf), NULL, 1);
+ av_rc4_crypt(rt->key_in, buf, NULL, sizeof(buf), NULL, 1);
+ av_rc4_crypt(rt->key_out, buf, NULL, sizeof(buf), NULL, 1);
/* the next requests will be encrypted using RC4 keys */
rt->handshaked = 1;
@@ -239,6 +255,8 @@ static int rtmpe_close(URLContext *h)
{
RTMPEContext *rt = h->priv_data;
+ av_free(rt->key_in);
+ av_free(rt->key_out);
ff_dh_free(rt->dh);
ffurl_close(rt->stream);
@@ -287,7 +305,7 @@ static int rtmpe_read(URLContext *h, uint8_t *buf, int size)
if (rt->handshaked && ret > 0) {
/* decrypt data received by the server */
- av_rc4_crypt(&rt->key_in, buf, buf, ret, NULL, 1);
+ av_rc4_crypt(rt->key_in, buf, buf, ret, NULL, 1);
}
return ret;
@@ -300,7 +318,7 @@ static int rtmpe_write(URLContext *h, const uint8_t *buf,
int size)
if (rt->handshaked) {
/* encrypt data to send to the server */
- av_rc4_crypt(&rt->key_out, buf, buf, size, NULL, 1);
+ av_rc4_crypt(rt->key_out, buf, buf, size, NULL, 1);
}
if ((ret = ffurl_write(rt->stream, buf, size)) < 0)
diff --git a/libavformat/rtmpcrypt.h b/libavformat/rtmpcrypt.h
index 2799433..7f8f09e 100644
--- a/libavformat/rtmpcrypt.h
+++ b/libavformat/rtmpcrypt.h
@@ -54,9 +54,10 @@ int ff_rtmpe_compute_secret_key(URLContext *h, const uint8_t
*serverdata,
* @param signature the signature to encrypt
* @param digest the digest used for finding the encryption key
* @param type type of encryption (8 for XTEA, 9 for Blowfish)
+ * @return zero on success, negative value otherwise
*/
-void ff_rtmpe_encrypt_sig(URLContext *h, uint8_t *signature,
- const uint8_t *digest, int type);
+int ff_rtmpe_encrypt_sig(URLContext *h, uint8_t *signature,
+ const uint8_t *digest, int type);
/**
* Update the keystream and set RC4 keys for encryption.
diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c
index e75a519..78b353c 100644
--- a/libavformat/rtmpproto.c
+++ b/libavformat/rtmpproto.c
@@ -1322,7 +1322,8 @@ static int rtmp_handshake(URLContext *s, RTMPContext *rt)
return ret;
/* Encrypt the signature received by the server. */
- ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
+ if ((ret = ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
serverdata[0])) < 0)
+ return ret;
}
if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32,
32)) {
@@ -1346,9 +1347,10 @@ static int rtmp_handshake(URLContext *s, RTMPContext *rt)
if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
/* Encrypt the signature to be send to the server. */
- ff_rtmpe_encrypt_sig(rt->stream, tosend +
- RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
- serverdata[0]);
+ if ((ret = ff_rtmpe_encrypt_sig(rt->stream, tosend +
+ RTMP_HANDSHAKE_PACKET_SIZE - 32,
digest,
+ serverdata[0])) < 0)
+ return ret;
}
// write reply back to the server
@@ -1371,8 +1373,9 @@ static int rtmp_handshake(URLContext *s, RTMPContext *rt)
if (serverdata[0] == 9) {
/* Encrypt the signature received by the server. */
- ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
- serverdata[0]);
+ if ((ret = ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
+ serverdata[0])) < 0)
+ return ret;
}
}
--
2.4.5
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel