From: hyc Date: Sat, 27 Feb 2010 21:48:51 +0000 (+0000) Subject: More FP10 handshake support. X-Git-Tag: v2.4~253 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a459d3b25d626a21799ece38647c94dad54d3f18;p=rtmpdump More FP10 handshake support. git-svn-id: svn://svn.mplayerhq.hu/rtmpdump/trunk@276 400ebc74-4327-4243-bc38-086b20814532 --- diff --git a/README b/README index 6bc9324..d819224 100644 --- a/README +++ b/README @@ -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/ diff --git a/handshake.h b/handshake.h index 75317e6..f58891b 100644 --- a/handshake.h +++ b/handshake.h @@ -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 #include +#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, char *handshakeMessage, const char *key, /* 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, char *handshakeMessage, const char *key, * */ +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