[rtmpdump] r276 - in trunk: README handshake.h
hyc
subversion at mplayerhq.hu
Sat Feb 27 22:48:52 CET 2010
Author: hyc
Date: Sat Feb 27 22:48:51 2010
New Revision: 276
Log:
More FP10 handshake support.
Modified:
trunk/README
trunk/handshake.h
Modified: trunk/README
==============================================================================
--- trunk/README Fri Feb 26 05:32:55 2010 (r275)
+++ trunk/README Sat Feb 27 22:48:51 2010 (r276)
@@ -1,6 +1,7 @@
RTMP Dump v2.1d
(C) 2009 Andrej Stepanchuk
(C) 2009-2010 Howard Chu
+(C) 2010 2a665470ced7adb7156fcef47f8199a6371c117b8a79e399a2771e0b36384090
License: GPLv2
http://rtmpdump.mplayerhq.hu/
Modified: trunk/handshake.h
==============================================================================
--- trunk/handshake.h Fri Feb 26 05:32:55 2010 (r275)
+++ trunk/handshake.h Sat Feb 27 22:48:51 2010 (r276)
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2008-2009 Andrej Stepanchuk
- * Copyright (C) 2009 Howard Chu
+ * Copyright (C) 2009-2010 Howard Chu
+ * Copyright (C) 2010 2a665470ced7adb7156fcef47f8199a6371c117b8a79e399a2771e0b36384090
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,6 +26,8 @@
#include <openssl/hmac.h>
#include <openssl/rc4.h>
+#define FP10
+
#include "dh.h"
static const char GenuineFMSKey[] = {
@@ -87,6 +90,8 @@ static void InitRC4Encryption
RC4_set_key(*rc4keyIn, 16, digest);
}
+typedef unsigned int (getoff)(char *buf, unsigned int len);
+
static unsigned int
GetDHOffset2(char *handshake, unsigned int len)
{
@@ -243,7 +248,7 @@ VerifyDigest(unsigned int digestPos, cha
/* handshake
*
- * Type = [1 bytes] 0x06, 0x08 encrypted, 0x03 plain
+ * Type = [1 bytes] plain: 0x03, encrypted: 0x06, 0x08, 0x09
* -------------------------------------------------------------------- [1536 bytes]
* Uptime = [4 bytes] big endian unsigned number, uptime
* Version = [4 bytes] each byte represents a version number, e.g. 9.0.124.0
@@ -251,6 +256,55 @@ VerifyDigest(unsigned int digestPos, cha
*
*/
+static const uint32_t rtmpe8_keys[16][4] = {
+ {0xbff034b2, 0x11d9081f, 0xccdfb795, 0x748de732},
+ {0x086a5eb6, 0x1743090e, 0x6ef05ab8, 0xfe5a39e2},
+ {0x7b10956f, 0x76ce0521, 0x2388a73a, 0x440149a1},
+ {0xa943f317, 0xebf11bb2, 0xa691a5ee, 0x17f36339},
+ {0x7a30e00a, 0xb529e22c, 0xa087aea5, 0xc0cb79ac},
+ {0xbdce0c23, 0x2febdeff, 0x1cfaae16, 0x1123239d},
+ {0x55dd3f7b, 0x77e7e62e, 0x9bb8c499, 0xc9481ee4},
+ {0x407bb6b4, 0x71e89136, 0xa7aebf55, 0xca33b839},
+ {0xfcf6bdc3, 0xb63c3697, 0x7ce4f825, 0x04d959b2},
+ {0x28e091fd, 0x41954c4c, 0x7fb7db00, 0xe3a066f8},
+ {0x57845b76, 0x4f251b03, 0x46d45bcd, 0xa2c30d29},
+ {0x0acceef8, 0xda55b546, 0x03473452, 0x5863713b},
+ {0xb82075dc, 0xa75f1fee, 0xd84268e8, 0xa72a44cc},
+ {0x07cf6e9e, 0xa16d7b25, 0x9fa7ae6c, 0xd92f5629},
+ {0xfeb1eae4, 0x8c8c3ce1, 0x4e0064a7, 0x6a387c2a},
+ {0x893a9427, 0xcc3013a2, 0xf106385b, 0xa829f927}
+};
+
+/* RTMPE type 8 uses XTEA on the regular signature
+ * http://en.wikipedia.org/wiki/XTEA
+ */
+static void rtmpe8_sig(unsigned char *in, unsigned char *out, int keyid)
+{
+ unsigned int i, num_rounds = 32;
+ uint32_t v0, v1, sum=0, delta=0x9E3779B9;
+ uint32_t const *k;
+
+ v0 = in[0] | (in[1] << 8) | (in[2] << 16) | (in[3] << 24);
+ v1 = in[4] | (in[5] << 8) | (in[6] << 16) | (in[7] << 24);
+ k = rtmpe8_keys[keyid];
+
+ for (i=0; i < num_rounds; i++) {
+ v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
+ sum += delta;
+ v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
+ }
+
+ out[0] = v0; v0 >>= 8;
+ out[1] = v0; v0 >>= 8;
+ out[2] = v0; v0 >>= 8;
+ out[3] = v0;
+
+ out[4] = v1; v1 >>= 8;
+ out[5] = v1; v1 >>= 8;
+ out[6] = v1; v1 >>= 8;
+ out[7] = v1;
+}
+
static bool
HandShake(RTMP * r, bool FP9HandShake)
{
@@ -267,8 +321,9 @@ HandShake(RTMP * r, bool FP9HandShake)
uint32_t uptime;
char clientbuf[RTMP_SIG_SIZE + 4], *clientsig=clientbuf+4;
- char serversig[RTMP_SIG_SIZE];
+ char serversig[RTMP_SIG_SIZE], client2[RTMP_SIG_SIZE], *reply;
char type;
+ getoff *getdh, *getdig;
if (encrypted || r->Link.SWFHash.av_len)
FP9HandShake = true;
@@ -289,9 +344,15 @@ HandShake(RTMP * r, bool FP9HandShake)
{
/* set version to at least 9.0.115.0 */
#ifdef FP10
+ getdig = GetDigestOffset2;
+ getdh = GetDHOffset2;
+
clientsig[4] = 128;
clientsig[6] = 3;
#else
+ getdig = GetDigestOffset1;
+ getdh = GetDHOffset1;
+
clientsig[4] = 9;
clientsig[6] = 124;
#endif
@@ -328,11 +389,7 @@ HandShake(RTMP * r, bool FP9HandShake)
return false;
}
-#ifdef FP10
- dhposClient = GetDHOffset2(clientsig, RTMP_SIG_SIZE);
-#else
- dhposClient = GetDHOffset1(clientsig, RTMP_SIG_SIZE);
-#endif
+ dhposClient = getdh(clientsig, RTMP_SIG_SIZE);
Log(LOGDEBUG, "%s: DH pubkey position: %d", __FUNCTION__, dhposClient);
if (!DHGenerateKey(r->Link.dh))
@@ -350,11 +407,7 @@ HandShake(RTMP * r, bool FP9HandShake)
}
}
-#ifdef FP10
- digestPosClient = GetDigestOffset2(clientsig, RTMP_SIG_SIZE);
-#else
- digestPosClient = GetDigestOffset1(clientsig, RTMP_SIG_SIZE); /* reuse this value in verification */
-#endif
+ digestPosClient = getdig(clientsig, RTMP_SIG_SIZE); /* reuse this value in verification */
Log(LOGDEBUG, "%s: Client digest offset: %d", __FUNCTION__,
digestPosClient);
@@ -466,13 +519,21 @@ HandShake(RTMP * r, bool FP9HandShake)
}
+ reply = client2;
+#ifdef _DEBUG
+ memset(reply, 0xff, RTMP_SIG_SIZE);
+#else
+ ip = (int32_t *)reply;
+ for (i = 0; i < RTMP_SIG_SIZE/4; i++)
+ *ip++ = rand();
+#endif
/* calculate response now */
char digestResp[SHA256_DIGEST_LENGTH];
- char *signatureResp = serversig+RTMP_SIG_SIZE-SHA256_DIGEST_LENGTH;
+ char *signatureResp = reply+RTMP_SIG_SIZE-SHA256_DIGEST_LENGTH;
HMACsha256(&serversig[digestPosServer], SHA256_DIGEST_LENGTH,
GenuineFPKey, sizeof(GenuineFPKey), digestResp);
- HMACsha256(serversig, RTMP_SIG_SIZE - SHA256_DIGEST_LENGTH, digestResp,
+ HMACsha256(reply, RTMP_SIG_SIZE - SHA256_DIGEST_LENGTH, digestResp,
SHA256_DIGEST_LENGTH, signatureResp);
/* some info output */
@@ -482,26 +543,41 @@ HandShake(RTMP * r, bool FP9HandShake)
LogHex(LOGDEBUG, digestResp, SHA256_DIGEST_LENGTH);
#ifdef FP10
- if (type == 8 || type == 9)
+ if (type == 8 )
{
+ unsigned char *dptr = (unsigned char *)digestResp;
+ unsigned char *sig = (unsigned char *)signatureResp;
/* encrypt signatureResp */
+ for (i=0; i<SHA256_DIGEST_LENGTH; i+=8)
+ rtmpe8_sig(sig+i, sig+i, dptr[i] % 15);
+ }
+#if 0
+ else if (type == 9))
+ {
+ unsigned char *dptr = (unsigned char *)digestResp;
+ unsigned char *sig = (unsigned char *)signatureResp;
+ /* encrypt signatureResp */
+ for (i=0; i<SHA256_DIGEST_LENGTH; i+=8)
+ rtmpe9_sig(sig+i, sig+i, dptr[i] % 15);
}
#endif
+#endif
Log(LOGDEBUG, "%s: Client signature calculated:", __FUNCTION__);
LogHex(LOGDEBUG, signatureResp, SHA256_DIGEST_LENGTH);
}
else
{
+ reply = serversig;
uptime = htonl(RTMP_GetTime());
- memcpy(serversig+4, &uptime, 4);
+ memcpy(reply+4, &uptime, 4);
}
#ifdef _DEBUG
Log(LOGDEBUG, "%s: Sending handshake response: ",
__FUNCTION__);
- LogHex(LOGDEBUG, serversig, RTMP_SIG_SIZE);
+ LogHex(LOGDEBUG, reply, RTMP_SIG_SIZE);
#endif
- if (!WriteN(r, serversig, RTMP_SIG_SIZE))
+ if (!WriteN(r, reply, RTMP_SIG_SIZE))
return false;
/* 2nd part of handshake */
@@ -539,6 +615,26 @@ HandShake(RTMP * r, bool FP9HandShake)
Log(LOGDEBUG, "%s: Digest key: ", __FUNCTION__);
LogHex(LOGDEBUG, digest, SHA256_DIGEST_LENGTH);
+#ifdef FP10
+ if (type == 8 )
+ {
+ unsigned char *dptr = (unsigned char *)digest;
+ unsigned char *sig = (unsigned char *)signature;
+ /* encrypt signature */
+ for (i=0; i<SHA256_DIGEST_LENGTH; i+=8)
+ rtmpe8_sig(sig+i, sig+i, dptr[i] % 15);
+ }
+#if 0
+ else if (type == 9)
+ {
+ unsigned char *dptr = (unsigned char *)digest;
+ unsigned char *sig = (unsigned char *)signature;
+ /* encrypt signatureResp */
+ for (i=0; i<SHA256_DIGEST_LENGTH; i+=8)
+ rtmpe9_sig(sig+i, sig+i, dptr[i] % 15);
+ }
+#endif
+#endif
Log(LOGDEBUG, "%s: Signature calculated:", __FUNCTION__);
LogHex(LOGDEBUG, signature, SHA256_DIGEST_LENGTH);
if (memcmp
More information about the rtmpdump
mailing list