1 /*
2  *  Copyright (C) 2008-2009 Andrej Stepanchuk
3  *  Copyright (C) 2009-2010 Howard Chu
4  *  Copyright (C) 2010 2a665470ced7adb7156fcef47f8199a6371c117b8a79e399a2771e0b36384090
5  *
6  *  This file is part of librtmp.
7  *
8  *  librtmp is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU Lesser General Public License as
10  *  published by the Free Software Foundation; either version 2.1,
11  *  or (at your option) any later version.
12  *
13  *  librtmp is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU Lesser General Public License
19  *  along with librtmp see the file COPYING.  If not, write to
20  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  *  Boston, MA  02110-1301, USA.
22  *  http://www.gnu.org/copyleft/lgpl.html
23  */
24 
25 /* This file is #included in rtmp.c, it is not meant to be compiled alone */
26 
27 #ifdef USE_POLARSSL
28 #include <polarssl/sha2.h>
29 #include <polarssl/arc4.h>
30 #ifndef SHA256_DIGEST_LENGTH
31 #define SHA256_DIGEST_LENGTH	32
32 #endif
33 #define HMAC_CTX	sha2_context
34 #define HMAC_setup(ctx, key, len)	sha2_hmac_starts(&ctx, (unsigned char *)key, len, 0)
35 #define HMAC_crunch(ctx, buf, len)	sha2_hmac_update(&ctx, buf, len)
36 #define HMAC_finish(ctx, dig, dlen)	dlen = SHA256_DIGEST_LENGTH; sha2_hmac_finish(&ctx, dig)
37 
38 typedef arc4_context *	RC4_handle;
39 #define RC4_alloc(h)	*h = malloc(sizeof(arc4_context))
40 #define RC4_setkey(h,l,k)	arc4_setup(h,k,l)
41 #define RC4_encrypt(h,l,d)	arc4_crypt(h,l,(unsigned char *)d,(unsigned char *)d)
42 #define RC4_encrypt2(h,l,s,d)	arc4_crypt(h,l,(unsigned char *)s,(unsigned char *)d)
43 #define RC4_free(h)	free(h)
44 
45 #elif defined(USE_GNUTLS)
46 #include <nettle/hmac.h>
47 #include <nettle/arcfour.h>
48 #ifndef SHA256_DIGEST_LENGTH
49 #define SHA256_DIGEST_LENGTH	32
50 #endif
51 #undef HMAC_CTX
52 #define HMAC_CTX	struct hmac_sha256_ctx
53 #define HMAC_setup(ctx, key, len)	hmac_sha256_set_key(&ctx, len, key)
54 #define HMAC_crunch(ctx, buf, len)	hmac_sha256_update(&ctx, len, buf)
55 #define HMAC_finish(ctx, dig, dlen)	dlen = SHA256_DIGEST_LENGTH; hmac_sha256_digest(&ctx, SHA256_DIGEST_LENGTH, dig)
56 #define HMAC_close(ctx)
57 
58 typedef struct arcfour_ctx*	RC4_handle;
59 #define RC4_alloc(h)	*h = malloc(sizeof(struct arcfour_ctx))
60 #define RC4_setkey(h,l,k)	arcfour_set_key(h, l, k)
61 #define RC4_encrypt(h,l,d)	arcfour_crypt(h,l,(uint8_t *)d,(uint8_t *)d)
62 #define RC4_encrypt2(h,l,s,d)	arcfour_crypt(h,l,(uint8_t *)d,(uint8_t *)s)
63 #define RC4_free(h)	free(h)
64 
65 #else	/* USE_OPENSSL */
66 #include <openssl/sha.h>
67 #include <openssl/hmac.h>
68 #include <openssl/rc4.h>
69 #if OPENSSL_VERSION_NUMBER < 0x0090800 || !defined(SHA256_DIGEST_LENGTH)
70 #error Your OpenSSL is too old, need 0.9.8 or newer with SHA256
71 #endif
72 #define HMAC_setup(ctx, key, len)	HMAC_CTX_init(&ctx); HMAC_Init_ex(&ctx, key, len, EVP_sha256(), 0)
73 #define HMAC_crunch(ctx, buf, len)	HMAC_Update(&ctx, buf, len)
74 #define HMAC_finish(ctx, dig, dlen)	HMAC_Final(&ctx, dig, &dlen); HMAC_CTX_cleanup(&ctx)
75 
76 typedef RC4_KEY *	RC4_handle;
77 #define RC4_alloc(h)	*h = malloc(sizeof(RC4_KEY))
78 #define RC4_setkey(h,l,k)	RC4_set_key(h,l,k)
79 #define RC4_encrypt(h,l,d)	RC4(h,l,(uint8_t *)d,(uint8_t *)d)
80 #define RC4_encrypt2(h,l,s,d)	RC4(h,l,(uint8_t *)s,(uint8_t *)d)
81 #define RC4_free(h)	free(h)
82 #endif
83 
84 #define FP10
85 
86 #include "dh.h"
87 
88 static const uint8_t GenuineFMSKey[] = {
89   0x47, 0x65, 0x6e, 0x75, 0x69, 0x6e, 0x65, 0x20, 0x41, 0x64, 0x6f, 0x62,
90     0x65, 0x20, 0x46, 0x6c,
91   0x61, 0x73, 0x68, 0x20, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x20, 0x53, 0x65,
92     0x72, 0x76, 0x65, 0x72,
93   0x20, 0x30, 0x30, 0x31,	/* Genuine Adobe Flash Media Server 001 */
94 
95   0xf0, 0xee, 0xc2, 0x4a, 0x80, 0x68, 0xbe, 0xe8, 0x2e, 0x00, 0xd0, 0xd1,
96   0x02, 0x9e, 0x7e, 0x57, 0x6e, 0xec, 0x5d, 0x2d, 0x29, 0x80, 0x6f, 0xab,
97     0x93, 0xb8, 0xe6, 0x36,
98   0xcf, 0xeb, 0x31, 0xae
99 };				/* 68 */
100 
101 static const uint8_t GenuineFPKey[] = {
102   0x47, 0x65, 0x6E, 0x75, 0x69, 0x6E, 0x65, 0x20, 0x41, 0x64, 0x6F, 0x62,
103     0x65, 0x20, 0x46, 0x6C,
104   0x61, 0x73, 0x68, 0x20, 0x50, 0x6C, 0x61, 0x79, 0x65, 0x72, 0x20, 0x30,
105     0x30, 0x31,			/* Genuine Adobe Flash Player 001 */
106   0xF0, 0xEE,
107   0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02, 0x9E,
108     0x7E, 0x57, 0x6E, 0xEC,
109   0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8, 0xE6, 0x36, 0xCF, 0xEB,
110     0x31, 0xAE
111 };				/* 62 */
112 
InitRC4Encryption(uint8_t * secretKey,uint8_t * pubKeyIn,uint8_t * pubKeyOut,RC4_handle * rc4keyIn,RC4_handle * rc4keyOut)113 static void InitRC4Encryption
114   (uint8_t * secretKey,
115    uint8_t * pubKeyIn,
116    uint8_t * pubKeyOut, RC4_handle *rc4keyIn, RC4_handle *rc4keyOut)
117 {
118   uint8_t digest[SHA256_DIGEST_LENGTH];
119   unsigned int digestLen = 0;
120   HMAC_CTX ctx;
121 
122   RC4_alloc(rc4keyIn);
123   RC4_alloc(rc4keyOut);
124 
125   HMAC_setup(ctx, secretKey, 128);
126   HMAC_crunch(ctx, pubKeyIn, 128);
127   HMAC_finish(ctx, digest, digestLen);
128 
129   RTMP_Log(RTMP_LOGDEBUG, "RC4 Out Key: ");
130   RTMP_LogHex(RTMP_LOGDEBUG, digest, 16);
131 
132   RC4_setkey(*rc4keyOut, 16, digest);
133 
134   HMAC_setup(ctx, secretKey, 128);
135   HMAC_crunch(ctx, pubKeyOut, 128);
136   HMAC_finish(ctx, digest, digestLen);
137 
138   RTMP_Log(RTMP_LOGDEBUG, "RC4 In Key: ");
139   RTMP_LogHex(RTMP_LOGDEBUG, digest, 16);
140 
141   RC4_setkey(*rc4keyIn, 16, digest);
142 }
143 
144 typedef unsigned int (getoff)(uint8_t *buf, unsigned int len);
145 
146 static unsigned int
GetDHOffset2(uint8_t * handshake,unsigned int len)147 GetDHOffset2(uint8_t *handshake, unsigned int len)
148 {
149   unsigned int offset = 0;
150   uint8_t *ptr = handshake + 768;
151   unsigned int res;
152 
153   assert(RTMP_SIG_SIZE <= len);
154 
155   offset += (*ptr);
156   ptr++;
157   offset += (*ptr);
158   ptr++;
159   offset += (*ptr);
160   ptr++;
161   offset += (*ptr);
162 
163   res = (offset % 632) + 8;
164 
165   if (res + 128 > 767)
166     {
167       RTMP_Log(RTMP_LOGERROR,
168 	  "%s: Couldn't calculate correct DH offset (got %d), exiting!",
169 	  __FUNCTION__, res);
170       exit(1);
171     }
172   return res;
173 }
174 
175 static unsigned int
GetDigestOffset2(uint8_t * handshake,unsigned int len)176 GetDigestOffset2(uint8_t *handshake, unsigned int len)
177 {
178   unsigned int offset = 0;
179   uint8_t *ptr = handshake + 772;
180   unsigned int res;
181 
182   offset += (*ptr);
183   ptr++;
184   offset += (*ptr);
185   ptr++;
186   offset += (*ptr);
187   ptr++;
188   offset += (*ptr);
189 
190   res = (offset % 728) + 776;
191 
192   if (res + 32 > 1535)
193     {
194       RTMP_Log(RTMP_LOGERROR,
195 	  "%s: Couldn't calculate correct digest offset (got %d), exiting",
196 	  __FUNCTION__, res);
197       exit(1);
198     }
199   return res;
200 }
201 
202 static unsigned int
GetDHOffset1(uint8_t * handshake,unsigned int len)203 GetDHOffset1(uint8_t *handshake, unsigned int len)
204 {
205   unsigned int offset = 0;
206   uint8_t *ptr = handshake + 1532;
207   unsigned int res;
208 
209   assert(RTMP_SIG_SIZE <= len);
210 
211   offset += (*ptr);
212   ptr++;
213   offset += (*ptr);
214   ptr++;
215   offset += (*ptr);
216   ptr++;
217   offset += (*ptr);
218 
219   res = (offset % 632) + 772;
220 
221   if (res + 128 > 1531)
222     {
223       RTMP_Log(RTMP_LOGERROR, "%s: Couldn't calculate DH offset (got %d), exiting!",
224 	  __FUNCTION__, res);
225       exit(1);
226     }
227 
228   return res;
229 }
230 
231 static unsigned int
GetDigestOffset1(uint8_t * handshake,unsigned int len)232 GetDigestOffset1(uint8_t *handshake, unsigned int len)
233 {
234   unsigned int offset = 0;
235   uint8_t *ptr = handshake + 8;
236   unsigned int res;
237 
238   assert(12 <= len);
239 
240   offset += (*ptr);
241   ptr++;
242   offset += (*ptr);
243   ptr++;
244   offset += (*ptr);
245   ptr++;
246   offset += (*ptr);
247 
248   res = (offset % 728) + 12;
249 
250   if (res + 32 > 771)
251     {
252       RTMP_Log(RTMP_LOGERROR,
253 	  "%s: Couldn't calculate digest offset (got %d), exiting!",
254 	  __FUNCTION__, res);
255       exit(1);
256     }
257 
258   return res;
259 }
260 
261 static getoff *digoff[] = {GetDigestOffset1, GetDigestOffset2};
262 static getoff *dhoff[] = {GetDHOffset1, GetDHOffset2};
263 
264 static void
HMACsha256(const uint8_t * message,size_t messageLen,const uint8_t * key,size_t keylen,uint8_t * digest)265 HMACsha256(const uint8_t *message, size_t messageLen, const uint8_t *key,
266 	   size_t keylen, uint8_t *digest)
267 {
268   unsigned int digestLen;
269   HMAC_CTX ctx;
270 
271   HMAC_setup(ctx, key, keylen);
272   HMAC_crunch(ctx, message, messageLen);
273   HMAC_finish(ctx, digest, digestLen);
274 
275   assert(digestLen == 32);
276 }
277 
278 static void
CalculateDigest(unsigned int digestPos,uint8_t * handshakeMessage,const uint8_t * key,size_t keyLen,uint8_t * digest)279 CalculateDigest(unsigned int digestPos, uint8_t *handshakeMessage,
280 		const uint8_t *key, size_t keyLen, uint8_t *digest)
281 {
282   const int messageLen = RTMP_SIG_SIZE - SHA256_DIGEST_LENGTH;
283   uint8_t message[RTMP_SIG_SIZE - SHA256_DIGEST_LENGTH];
284 
285   memcpy(message, handshakeMessage, digestPos);
286   memcpy(message + digestPos,
287 	 &handshakeMessage[digestPos + SHA256_DIGEST_LENGTH],
288 	 messageLen - digestPos);
289 
290   HMACsha256(message, messageLen, key, keyLen, digest);
291 }
292 
293 static int
VerifyDigest(unsigned int digestPos,uint8_t * handshakeMessage,const uint8_t * key,size_t keyLen)294 VerifyDigest(unsigned int digestPos, uint8_t *handshakeMessage, const uint8_t *key,
295 	     size_t keyLen)
296 {
297   uint8_t calcDigest[SHA256_DIGEST_LENGTH];
298 
299   CalculateDigest(digestPos, handshakeMessage, key, keyLen, calcDigest);
300 
301   return memcmp(&handshakeMessage[digestPos], calcDigest,
302 		SHA256_DIGEST_LENGTH) == 0;
303 }
304 
305 /* handshake
306  *
307  * Type		= [1 bytes] plain: 0x03, encrypted: 0x06, 0x08, 0x09
308  * -------------------------------------------------------------------- [1536 bytes]
309  * Uptime	= [4 bytes] big endian unsigned number, uptime
310  * Version 	= [4 bytes] each byte represents a version number, e.g. 9.0.124.0
311  * ...
312  *
313  */
314 
315 static const uint32_t rtmpe8_keys[16][4] = {
316 	{0xbff034b2, 0x11d9081f, 0xccdfb795, 0x748de732},
317 	{0x086a5eb6, 0x1743090e, 0x6ef05ab8, 0xfe5a39e2},
318 	{0x7b10956f, 0x76ce0521, 0x2388a73a, 0x440149a1},
319 	{0xa943f317, 0xebf11bb2, 0xa691a5ee, 0x17f36339},
320 	{0x7a30e00a, 0xb529e22c, 0xa087aea5, 0xc0cb79ac},
321 	{0xbdce0c23, 0x2febdeff, 0x1cfaae16, 0x1123239d},
322 	{0x55dd3f7b, 0x77e7e62e, 0x9bb8c499, 0xc9481ee4},
323 	{0x407bb6b4, 0x71e89136, 0xa7aebf55, 0xca33b839},
324 	{0xfcf6bdc3, 0xb63c3697, 0x7ce4f825, 0x04d959b2},
325 	{0x28e091fd, 0x41954c4c, 0x7fb7db00, 0xe3a066f8},
326 	{0x57845b76, 0x4f251b03, 0x46d45bcd, 0xa2c30d29},
327 	{0x0acceef8, 0xda55b546, 0x03473452, 0x5863713b},
328 	{0xb82075dc, 0xa75f1fee, 0xd84268e8, 0xa72a44cc},
329 	{0x07cf6e9e, 0xa16d7b25, 0x9fa7ae6c, 0xd92f5629},
330 	{0xfeb1eae4, 0x8c8c3ce1, 0x4e0064a7, 0x6a387c2a},
331 	{0x893a9427, 0xcc3013a2, 0xf106385b, 0xa829f927}
332 };
333 
334 /* RTMPE type 8 uses XTEA on the regular signature
335  * http://en.wikipedia.org/wiki/XTEA
336  */
rtmpe8_sig(uint8_t * in,uint8_t * out,int keyid)337 static void rtmpe8_sig(uint8_t *in, uint8_t *out, int keyid)
338 {
339   unsigned int i, num_rounds = 32;
340   uint32_t v0, v1, sum=0, delta=0x9E3779B9;
341   uint32_t const *k;
342 
343   v0 = in[0] | (in[1] << 8) | (in[2] << 16) | (in[3] << 24);
344   v1 = in[4] | (in[5] << 8) | (in[6] << 16) | (in[7] << 24);
345   k = rtmpe8_keys[keyid];
346 
347   for (i=0; i < num_rounds; i++) {
348     v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
349     sum += delta;
350     v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
351   }
352 
353   out[0] = v0; v0 >>= 8;
354   out[1] = v0; v0 >>= 8;
355   out[2] = v0; v0 >>= 8;
356   out[3] = v0;
357 
358   out[4] = v1; v1 >>= 8;
359   out[5] = v1; v1 >>= 8;
360   out[6] = v1; v1 >>= 8;
361   out[7] = v1;
362 }
363 
364 /* RTMPE type 9 uses Blowfish on the regular signature
365  * http://en.wikipedia.org/wiki/Blowfish_(cipher)
366  */
367 #define	BF_ROUNDS	16
368 typedef struct bf_key {
369 	uint32_t s[4][256];
370 	uint32_t p[BF_ROUNDS+2];
371 } bf_key;
372 
373 static const uint32_t bf_sinit[][256] = {
374 
375   /* S-Box 0 */
376   { 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
377     0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
378     0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
379     0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
380     0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
381     0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
382     0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
383     0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
384     0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
385     0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
386     0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
387     0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
388     0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
389     0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
390     0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
391     0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
392     0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
393     0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
394     0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
395     0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
396     0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
397     0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
398     0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
399     0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
400     0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
401     0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
402     0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
403     0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
404     0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
405     0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
406     0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
407     0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
408     0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
409     0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
410     0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
411     0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
412     0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
413     0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
414     0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
415     0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
416     0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
417     0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
418     0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, },
419 
420   /* S-Box 1 */
421   { 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
422     0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
423     0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
424     0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
425     0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
426     0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
427     0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
428     0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
429     0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
430     0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
431     0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
432     0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
433     0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
434     0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
435     0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
436     0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
437     0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
438     0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
439     0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
440     0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
441     0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
442     0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
443     0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
444     0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
445     0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
446     0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
447     0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
448     0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
449     0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
450     0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
451     0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
452     0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
453     0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
454     0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
455     0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
456     0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
457     0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
458     0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
459     0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
460     0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
461     0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
462     0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
463     0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, },
464 
465   /* S-Box 2 */
466   { 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
467     0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
468     0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
469     0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
470     0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
471     0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
472     0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
473     0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
474     0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
475     0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
476     0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
477     0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
478     0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
479     0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
480     0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
481     0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
482     0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
483     0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
484     0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
485     0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
486     0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
487     0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
488     0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
489     0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
490     0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
491     0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
492     0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
493     0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
494     0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
495     0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
496     0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
497     0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
498     0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
499     0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
500     0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
501     0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
502     0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
503     0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
504     0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
505     0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
506     0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
507     0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
508     0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0, },
509 
510   /* S-Box 3 */
511   { 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
512     0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
513     0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
514     0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
515     0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
516     0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
517     0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
518     0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
519     0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
520     0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
521     0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
522     0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
523     0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
524     0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
525     0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
526     0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
527     0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
528     0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
529     0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
530     0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
531     0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
532     0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
533     0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
534     0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
535     0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
536     0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
537     0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
538     0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
539     0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
540     0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
541     0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
542     0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
543     0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
544     0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
545     0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
546     0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
547     0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
548     0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
549     0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
550     0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
551     0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
552     0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
553     0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6, },
554 };
555 
556 static const uint32_t bf_pinit[] = {
557   /* P-Box */
558   0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
559   0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
560   0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b,
561 };
562 
563 #define KEYBYTES	24
564 
565 static const unsigned char rtmpe9_keys[16][KEYBYTES] = {
566  { 0x79, 0x34, 0x77, 0x4c, 0x67, 0xd1, 0x38, 0x3a, 0xdf, 0xb3, 0x56, 0xbe,
567    0x8b, 0x7b, 0xd0, 0x24, 0x38, 0xe0, 0x73, 0x58, 0x41, 0x5d, 0x69, 0x67, },
568  { 0x46, 0xf6, 0xb4, 0xcc, 0x01, 0x93, 0xe3, 0xa1, 0x9e, 0x7d, 0x3c, 0x65,
569    0x55, 0x86, 0xfd, 0x09, 0x8f, 0xf7, 0xb3, 0xc4, 0x6f, 0x41, 0xca, 0x5c, },
570  { 0x1a, 0xe7, 0xe2, 0xf3, 0xf9, 0x14, 0x79, 0x94, 0xc0, 0xd3, 0x97, 0x43,
571    0x08, 0x7b, 0xb3, 0x84, 0x43, 0x2f, 0x9d, 0x84, 0x3f, 0x21, 0x01, 0x9b, },
572  { 0xd3, 0xe3, 0x54, 0xb0, 0xf7, 0x1d, 0xf6, 0x2b, 0x5a, 0x43, 0x4d, 0x04,
573    0x83, 0x64, 0x3e, 0x0d, 0x59, 0x2f, 0x61, 0xcb, 0xb1, 0x6a, 0x59, 0x0d, },
574  { 0xc8, 0xc1, 0xe9, 0xb8, 0x16, 0x56, 0x99, 0x21, 0x7b, 0x5b, 0x36, 0xb7,
575    0xb5, 0x9b, 0xdf, 0x06, 0x49, 0x2c, 0x97, 0xf5, 0x95, 0x48, 0x85, 0x7e, },
576  { 0xeb, 0xe5, 0xe6, 0x2e, 0xa4, 0xba, 0xd4, 0x2c, 0xf2, 0x16, 0xe0, 0x8f,
577    0x66, 0x23, 0xa9, 0x43, 0x41, 0xce, 0x38, 0x14, 0x84, 0x95, 0x00, 0x53, },
578  { 0x66, 0xdb, 0x90, 0xf0, 0x3b, 0x4f, 0xf5, 0x6f, 0xe4, 0x9c, 0x20, 0x89,
579    0x35, 0x5e, 0xd2, 0xb2, 0xc3, 0x9e, 0x9f, 0x7f, 0x63, 0xb2, 0x28, 0x81, },
580  { 0xbb, 0x20, 0xac, 0xed, 0x2a, 0x04, 0x6a, 0x19, 0x94, 0x98, 0x9b, 0xc8,
581    0xff, 0xcd, 0x93, 0xef, 0xc6, 0x0d, 0x56, 0xa7, 0xeb, 0x13, 0xd9, 0x30, },
582  { 0xbc, 0xf2, 0x43, 0x82, 0x09, 0x40, 0x8a, 0x87, 0x25, 0x43, 0x6d, 0xe6,
583    0xbb, 0xa4, 0xb9, 0x44, 0x58, 0x3f, 0x21, 0x7c, 0x99, 0xbb, 0x3f, 0x24, },
584  { 0xec, 0x1a, 0xaa, 0xcd, 0xce, 0xbd, 0x53, 0x11, 0xd2, 0xfb, 0x83, 0xb6,
585    0xc3, 0xba, 0xab, 0x4f, 0x62, 0x79, 0xe8, 0x65, 0xa9, 0x92, 0x28, 0x76, },
586  { 0xc6, 0x0c, 0x30, 0x03, 0x91, 0x18, 0x2d, 0x7b, 0x79, 0xda, 0xe1, 0xd5,
587    0x64, 0x77, 0x9a, 0x12, 0xc5, 0xb1, 0xd7, 0x91, 0x4f, 0x96, 0x4c, 0xa3, },
588  { 0xd7, 0x7c, 0x2a, 0xbf, 0xa6, 0xe7, 0x85, 0x7c, 0x45, 0xad, 0xff, 0x12,
589    0x94, 0xd8, 0xde, 0xa4, 0x5c, 0x3d, 0x79, 0xa4, 0x44, 0x02, 0x5d, 0x22, },
590  { 0x16, 0x19, 0x0d, 0x81, 0x6a, 0x4c, 0xc7, 0xf8, 0xb8, 0xf9, 0x4e, 0xcd,
591    0x2c, 0x9e, 0x90, 0x84, 0xb2, 0x08, 0x25, 0x60, 0xe1, 0x1e, 0xae, 0x18, },
592  { 0xe9, 0x7c, 0x58, 0x26, 0x1b, 0x51, 0x9e, 0x49, 0x82, 0x60, 0x61, 0xfc,
593    0xa0, 0xa0, 0x1b, 0xcd, 0xf5, 0x05, 0xd6, 0xa6, 0x6d, 0x07, 0x88, 0xa3, },
594  { 0x2b, 0x97, 0x11, 0x8b, 0xd9, 0x4e, 0xd9, 0xdf, 0x20, 0xe3, 0x9c, 0x10,
595    0xe6, 0xa1, 0x35, 0x21, 0x11, 0xf9, 0x13, 0x0d, 0x0b, 0x24, 0x65, 0xb2, },
596  { 0x53, 0x6a, 0x4c, 0x54, 0xac, 0x8b, 0x9b, 0xb8, 0x97, 0x29, 0xfc, 0x60,
597    0x2c, 0x5b, 0x3a, 0x85, 0x68, 0xb5, 0xaa, 0x6a, 0x44, 0xcd, 0x3f, 0xa7, },
598 };
599 
600 #define	BF_ENC(X,S) \
601 	(((S[0][X>>24] + S[1][X>>16 & 0xff]) ^ S[2][(X>>8) & 0xff]) + S[3][X & 0xff])
602 
bf_enc(uint32_t * x,bf_key * key)603 static void bf_enc(uint32_t *x, bf_key *key)
604 {
605   uint32_t  Xl;
606   uint32_t  Xr;
607   uint32_t  temp;
608   int	i;
609 
610   Xl = x[0];
611   Xr = x[1];
612 
613   for (i = 0; i < BF_ROUNDS; ++i) {
614     Xl ^= key->p[i];
615     Xr ^= BF_ENC(Xl,key->s);
616 
617     temp = Xl;
618     Xl = Xr;
619     Xr = temp;
620   }
621 
622   Xl ^= key->p[BF_ROUNDS];
623   Xr ^= key->p[BF_ROUNDS + 1];
624 
625   x[0] = Xr;
626   x[1] = Xl;
627 }
628 
bf_setkey(const unsigned char * kp,int keybytes,bf_key * key)629 static void bf_setkey(const unsigned char *kp, int keybytes, bf_key *key)
630 {
631   int          i;
632   int          j;
633   int          k;
634   uint32_t  data;
635   uint32_t  d[2];
636 
637   memcpy(key->p, bf_pinit, sizeof(key->p));
638   memcpy(key->s, bf_sinit, sizeof(key->s));
639 
640   j = 0;
641   for (i = 0; i < BF_ROUNDS + 2; ++i) {
642     data = 0x00000000;
643 	for (k = 0; k < 4; ++k) {
644 	  data = (data << 8) | kp[j];
645 	  j = j + 1;
646 	  if (j >= keybytes) {
647 	    j = 0;
648 	  }
649 	}
650 	key->p[i] ^= data;
651   }
652 
653   d[0] = 0x00000000;
654   d[1] = 0x00000000;
655 
656   for (i = 0; i < BF_ROUNDS + 2; i += 2) {
657     bf_enc(d, key);
658 
659 	key->p[i] = d[0];
660 	key->p[i + 1] = d[1];
661   }
662 
663   for (i = 0; i < 4; ++i) {
664 	for (j = 0; j < 256; j += 2) {
665 
666 	  bf_enc(d, key);
667 
668 	  key->s[i][j] = d[0];
669 	  key->s[i][j + 1] = d[1];
670 	}
671   }
672 }
673 
rtmpe9_sig(uint8_t * in,uint8_t * out,int keyid)674 static void rtmpe9_sig(uint8_t *in, uint8_t *out, int keyid)
675 {
676   uint32_t d[2];
677   bf_key key;
678 
679   bf_setkey(rtmpe9_keys[keyid], KEYBYTES, &key);
680 
681   /* input is little-endian */
682   d[0] = in[0] | (in[1] << 8) | (in[2] << 16) | (in[3] << 24);
683   d[1] = in[4] | (in[5] << 8) | (in[6] << 16) | (in[7] << 24);
684   bf_enc(d, &key);
685   out[0] = d[0] & 0xff;
686   out[1] = (d[0] >> 8) & 0xff;
687   out[2] = (d[0] >> 16) & 0xff;
688   out[3] = (d[0] >> 24) & 0xff;
689   out[4] = d[1] & 0xff;
690   out[5] = (d[1] >> 8) & 0xff;
691   out[6] = (d[1] >> 16) & 0xff;
692   out[7] = (d[1] >> 24) & 0xff;
693 }
694 
695 static int
HandShake(RTMP * r,int FP9HandShake)696 HandShake(RTMP * r, int FP9HandShake)
697 {
698   int i, offalg = 0;
699   int dhposClient = 0;
700   int digestPosClient = 0;
701   int encrypted = r->Link.protocol & RTMP_FEATURE_ENC;
702 
703   RC4_handle keyIn = 0;
704   RC4_handle keyOut = 0;
705 
706   int32_t *ip;
707   uint32_t uptime;
708 
709   uint8_t clientbuf[RTMP_SIG_SIZE + 4], *clientsig=clientbuf+4;
710   uint8_t serversig[RTMP_SIG_SIZE], client2[RTMP_SIG_SIZE], *reply;
711   uint8_t type;
712   getoff *getdh = NULL, *getdig = NULL;
713 
714   if (encrypted || r->Link.SWFSize)
715     FP9HandShake = TRUE;
716   else
717     FP9HandShake = FALSE;
718 
719   r->Link.rc4keyIn = r->Link.rc4keyOut = 0;
720 
721   if (encrypted)
722     {
723       clientsig[-1] = 0x06;	/* 0x08 is RTMPE as well */
724       offalg = 1;
725     }
726   else
727     clientsig[-1] = 0x03;
728 
729   uptime = htonl(RTMP_GetTime());
730   memcpy(clientsig, &uptime, 4);
731 
732   if (FP9HandShake)
733     {
734       /* set version to at least 9.0.115.0 */
735       if (encrypted)
736 	{
737 	  clientsig[4] = 128;
738 	  clientsig[6] = 3;
739 	}
740       else
741         {
742 	  clientsig[4] = 10;
743 	  clientsig[6] = 45;
744 	}
745       clientsig[5] = 0;
746       clientsig[7] = 2;
747 
748       RTMP_Log(RTMP_LOGDEBUG, "%s: Client type: %02X", __FUNCTION__, clientsig[-1]);
749       getdig = digoff[offalg];
750       getdh  = dhoff[offalg];
751     }
752   else
753     {
754       memset(&clientsig[4], 0, 4);
755     }
756 
757   /* generate random data */
758 #ifdef _DEBUG
759   memset(clientsig+8, 0, RTMP_SIG_SIZE-8);
760 #else
761   ip = (int32_t *)(clientsig+8);
762   for (i = 2; i < RTMP_SIG_SIZE/4; i++)
763     *ip++ = rand();
764 #endif
765 
766   /* set handshake digest */
767   if (FP9HandShake)
768     {
769       if (encrypted)
770 	{
771 	  /* generate Diffie-Hellmann parameters */
772 	  r->Link.dh = DHInit(1024);
773 	  if (!r->Link.dh)
774 	    {
775 	      RTMP_Log(RTMP_LOGERROR, "%s: Couldn't initialize Diffie-Hellmann!",
776 		  __FUNCTION__);
777 	      return FALSE;
778 	    }
779 
780 	  dhposClient = getdh(clientsig, RTMP_SIG_SIZE);
781 	  RTMP_Log(RTMP_LOGDEBUG, "%s: DH pubkey position: %d", __FUNCTION__, dhposClient);
782 
783 	  if (!DHGenerateKey(r->Link.dh))
784 	    {
785 	      RTMP_Log(RTMP_LOGERROR, "%s: Couldn't generate Diffie-Hellmann public key!",
786 		  __FUNCTION__);
787 	      return FALSE;
788 	    }
789 
790 	  if (!DHGetPublicKey(r->Link.dh, &clientsig[dhposClient], 128))
791 	    {
792 	      RTMP_Log(RTMP_LOGERROR, "%s: Couldn't write public key!", __FUNCTION__);
793 	      return FALSE;
794 	    }
795 	}
796 
797       digestPosClient = getdig(clientsig, RTMP_SIG_SIZE);	/* reuse this value in verification */
798       RTMP_Log(RTMP_LOGDEBUG, "%s: Client digest offset: %d", __FUNCTION__,
799 	  digestPosClient);
800 
801       CalculateDigest(digestPosClient, clientsig, GenuineFPKey, 30,
802 		      &clientsig[digestPosClient]);
803 
804       RTMP_Log(RTMP_LOGDEBUG, "%s: Initial client digest: ", __FUNCTION__);
805       RTMP_LogHex(RTMP_LOGDEBUG, clientsig + digestPosClient,
806 	     SHA256_DIGEST_LENGTH);
807     }
808 
809 #ifdef _DEBUG
810   RTMP_Log(RTMP_LOGDEBUG, "Clientsig: ");
811   RTMP_LogHex(RTMP_LOGDEBUG, clientsig, RTMP_SIG_SIZE);
812 #endif
813 
814   if (!WriteN(r, (char *)clientsig-1, RTMP_SIG_SIZE + 1))
815     return FALSE;
816 
817   if (ReadN(r, (char *)&type, 1) != 1)	/* 0x03 or 0x06 */
818     return FALSE;
819 
820   RTMP_Log(RTMP_LOGDEBUG, "%s: Type Answer   : %02X", __FUNCTION__, type);
821 
822   if (type != clientsig[-1])
823     RTMP_Log(RTMP_LOGWARNING, "%s: Type mismatch: client sent %d, server answered %d",
824 	__FUNCTION__, clientsig[-1], type);
825 
826   if (ReadN(r, (char *)serversig, RTMP_SIG_SIZE) != RTMP_SIG_SIZE)
827     return FALSE;
828 
829   /* decode server response */
830   memcpy(&uptime, serversig, 4);
831   uptime = ntohl(uptime);
832 
833   RTMP_Log(RTMP_LOGDEBUG, "%s: Server Uptime : %d", __FUNCTION__, uptime);
834   RTMP_Log(RTMP_LOGDEBUG, "%s: FMS Version   : %d.%d.%d.%d", __FUNCTION__, serversig[4],
835       serversig[5], serversig[6], serversig[7]);
836 
837   if (FP9HandShake && type == 3 && !serversig[4])
838     FP9HandShake = FALSE;
839 
840 #ifdef _DEBUG
841   RTMP_Log(RTMP_LOGDEBUG, "Server signature:");
842   RTMP_LogHex(RTMP_LOGDEBUG, serversig, RTMP_SIG_SIZE);
843 #endif
844 
845   if (FP9HandShake)
846     {
847       uint8_t digestResp[SHA256_DIGEST_LENGTH];
848       uint8_t *signatureResp = NULL;
849 
850       /* we have to use this signature now to find the correct algorithms for getting the digest and DH positions */
851       int digestPosServer = getdig(serversig, RTMP_SIG_SIZE);
852 
853       if (!VerifyDigest(digestPosServer, serversig, GenuineFMSKey, 36))
854 	{
855 	  RTMP_Log(RTMP_LOGWARNING, "Trying different position for server digest!");
856 	  offalg ^= 1;
857 	  getdig = digoff[offalg];
858 	  getdh  = dhoff[offalg];
859 	  digestPosServer = getdig(serversig, RTMP_SIG_SIZE);
860 
861 	  if (!VerifyDigest(digestPosServer, serversig, GenuineFMSKey, 36))
862 	    {
863 	      RTMP_Log(RTMP_LOGERROR, "Couldn't verify the server digest");	/* continuing anyway will probably fail */
864 	      return FALSE;
865 	    }
866 	}
867 
868       /* generate SWFVerification token (SHA256 HMAC hash of decompressed SWF, key are the last 32 bytes of the server handshake) */
869       if (r->Link.SWFSize)
870 	{
871 	  const char swfVerify[] = { 0x01, 0x01 };
872 	  char *vend = r->Link.SWFVerificationResponse+sizeof(r->Link.SWFVerificationResponse);
873 
874 	  memcpy(r->Link.SWFVerificationResponse, swfVerify, 2);
875 	  AMF_EncodeInt32(&r->Link.SWFVerificationResponse[2], vend, r->Link.SWFSize);
876 	  AMF_EncodeInt32(&r->Link.SWFVerificationResponse[6], vend, r->Link.SWFSize);
877 	  HMACsha256(r->Link.SWFHash, SHA256_DIGEST_LENGTH,
878 		     &serversig[RTMP_SIG_SIZE - SHA256_DIGEST_LENGTH],
879 		     SHA256_DIGEST_LENGTH,
880 		     (uint8_t *)&r->Link.SWFVerificationResponse[10]);
881 	}
882 
883       /* do Diffie-Hellmann Key exchange for encrypted RTMP */
884       if (encrypted)
885 	{
886 	  /* compute secret key */
887 	  uint8_t secretKey[128] = { 0 };
888 	  int len, dhposServer;
889 
890 	  dhposServer = getdh(serversig, RTMP_SIG_SIZE);
891 	  RTMP_Log(RTMP_LOGDEBUG, "%s: Server DH public key offset: %d", __FUNCTION__,
892 	    dhposServer);
893 	  len = DHComputeSharedSecretKey(r->Link.dh, &serversig[dhposServer],
894 	  				128, secretKey);
895 	  if (len < 0)
896 	    {
897 	      RTMP_Log(RTMP_LOGDEBUG, "%s: Wrong secret key position!", __FUNCTION__);
898 	      return FALSE;
899 	    }
900 
901 	  RTMP_Log(RTMP_LOGDEBUG, "%s: Secret key: ", __FUNCTION__);
902 	  RTMP_LogHex(RTMP_LOGDEBUG, secretKey, 128);
903 
904 	  InitRC4Encryption(secretKey,
905 			    (uint8_t *) & serversig[dhposServer],
906 			    (uint8_t *) & clientsig[dhposClient],
907 			    &keyIn, &keyOut);
908 	}
909 
910 
911       reply = client2;
912 #ifdef _DEBUG
913       memset(reply, 0xff, RTMP_SIG_SIZE);
914 #else
915       ip = (int32_t *)reply;
916       for (i = 0; i < RTMP_SIG_SIZE/4; i++)
917         *ip++ = rand();
918 #endif
919       /* calculate response now */
920       signatureResp = reply+RTMP_SIG_SIZE-SHA256_DIGEST_LENGTH;
921 
922       HMACsha256(&serversig[digestPosServer], SHA256_DIGEST_LENGTH,
923 		 GenuineFPKey, sizeof(GenuineFPKey), digestResp);
924       HMACsha256(reply, RTMP_SIG_SIZE - SHA256_DIGEST_LENGTH, digestResp,
925 		 SHA256_DIGEST_LENGTH, signatureResp);
926 
927       /* some info output */
928       RTMP_Log(RTMP_LOGDEBUG,
929 	  "%s: Calculated digest key from secure key and server digest: ",
930 	  __FUNCTION__);
931       RTMP_LogHex(RTMP_LOGDEBUG, digestResp, SHA256_DIGEST_LENGTH);
932 
933 #ifdef FP10
934       if (type == 8 )
935         {
936 	  uint8_t *dptr = digestResp;
937 	  uint8_t *sig = signatureResp;
938 	  /* encrypt signatureResp */
939           for (i=0; i<SHA256_DIGEST_LENGTH; i+=8)
940 	    rtmpe8_sig(sig+i, sig+i, dptr[i] % 15);
941         }
942       else if (type == 9)
943         {
944 	  uint8_t *dptr = digestResp;
945 	  uint8_t *sig = signatureResp;
946 	  /* encrypt signatureResp */
947           for (i=0; i<SHA256_DIGEST_LENGTH; i+=8)
948             rtmpe9_sig(sig+i, sig+i, dptr[i] % 15);
949         }
950 #endif
951       RTMP_Log(RTMP_LOGDEBUG, "%s: Client signature calculated:", __FUNCTION__);
952       RTMP_LogHex(RTMP_LOGDEBUG, signatureResp, SHA256_DIGEST_LENGTH);
953     }
954   else
955     {
956       reply = serversig;
957 #if 0
958       uptime = htonl(RTMP_GetTime());
959       memcpy(reply+4, &uptime, 4);
960 #endif
961     }
962 
963 #ifdef _DEBUG
964   RTMP_Log(RTMP_LOGDEBUG, "%s: Sending handshake response: ",
965     __FUNCTION__);
966   RTMP_LogHex(RTMP_LOGDEBUG, reply, RTMP_SIG_SIZE);
967 #endif
968   if (!WriteN(r, (char *)reply, RTMP_SIG_SIZE))
969     return FALSE;
970 
971   /* 2nd part of handshake */
972   if (ReadN(r, (char *)serversig, RTMP_SIG_SIZE) != RTMP_SIG_SIZE)
973     return FALSE;
974 
975 #ifdef _DEBUG
976   RTMP_Log(RTMP_LOGDEBUG, "%s: 2nd handshake: ", __FUNCTION__);
977   RTMP_LogHex(RTMP_LOGDEBUG, serversig, RTMP_SIG_SIZE);
978 #endif
979 
980   if (FP9HandShake)
981     {
982       uint8_t signature[SHA256_DIGEST_LENGTH];
983       uint8_t digest[SHA256_DIGEST_LENGTH];
984 
985       if (serversig[4] == 0 && serversig[5] == 0 && serversig[6] == 0
986 	  && serversig[7] == 0)
987 	{
988 	  RTMP_Log(RTMP_LOGDEBUG,
989 	      "%s: Wait, did the server just refuse signed authentication?",
990 	      __FUNCTION__);
991 	}
992       RTMP_Log(RTMP_LOGDEBUG, "%s: Server sent signature:", __FUNCTION__);
993       RTMP_LogHex(RTMP_LOGDEBUG, &serversig[RTMP_SIG_SIZE - SHA256_DIGEST_LENGTH],
994 	     SHA256_DIGEST_LENGTH);
995 
996       /* verify server response */
997       HMACsha256(&clientsig[digestPosClient], SHA256_DIGEST_LENGTH,
998 		 GenuineFMSKey, sizeof(GenuineFMSKey), digest);
999       HMACsha256(serversig, RTMP_SIG_SIZE - SHA256_DIGEST_LENGTH, digest,
1000 		 SHA256_DIGEST_LENGTH, signature);
1001 
1002       /* show some information */
1003       RTMP_Log(RTMP_LOGDEBUG, "%s: Digest key: ", __FUNCTION__);
1004       RTMP_LogHex(RTMP_LOGDEBUG, digest, SHA256_DIGEST_LENGTH);
1005 
1006 #ifdef FP10
1007       if (type == 8 )
1008         {
1009 	  uint8_t *dptr = digest;
1010 	  uint8_t *sig = signature;
1011 	  /* encrypt signature */
1012           for (i=0; i<SHA256_DIGEST_LENGTH; i+=8)
1013 	    rtmpe8_sig(sig+i, sig+i, dptr[i] % 15);
1014         }
1015       else if (type == 9)
1016         {
1017 	  uint8_t *dptr = digest;
1018 	  uint8_t *sig = signature;
1019 	  /* encrypt signatureResp */
1020           for (i=0; i<SHA256_DIGEST_LENGTH; i+=8)
1021             rtmpe9_sig(sig+i, sig+i, dptr[i] % 15);
1022         }
1023 #endif
1024       RTMP_Log(RTMP_LOGDEBUG, "%s: Signature calculated:", __FUNCTION__);
1025       RTMP_LogHex(RTMP_LOGDEBUG, signature, SHA256_DIGEST_LENGTH);
1026       if (memcmp
1027 	  (signature, &serversig[RTMP_SIG_SIZE - SHA256_DIGEST_LENGTH],
1028 	   SHA256_DIGEST_LENGTH) != 0)
1029 	{
1030 	  RTMP_Log(RTMP_LOGWARNING, "%s: Server not genuine Adobe!", __FUNCTION__);
1031 	  return FALSE;
1032 	}
1033       else
1034 	{
1035 	  RTMP_Log(RTMP_LOGDEBUG, "%s: Genuine Adobe Flash Media Server", __FUNCTION__);
1036 	}
1037 
1038       if (encrypted)
1039 	{
1040 	  char buff[RTMP_SIG_SIZE];
1041 	  /* set keys for encryption from now on */
1042 	  r->Link.rc4keyIn = keyIn;
1043 	  r->Link.rc4keyOut = keyOut;
1044 
1045 
1046 	  /* update the keystreams */
1047 	  if (r->Link.rc4keyIn)
1048 	    {
1049 	      RC4_encrypt(r->Link.rc4keyIn, RTMP_SIG_SIZE, (uint8_t *) buff);
1050 	    }
1051 
1052 	  if (r->Link.rc4keyOut)
1053 	    {
1054 	      RC4_encrypt(r->Link.rc4keyOut, RTMP_SIG_SIZE, (uint8_t *) buff);
1055 	    }
1056 	}
1057     }
1058   else
1059     {
1060       if (memcmp(serversig, clientsig, RTMP_SIG_SIZE) != 0)
1061 	{
1062 	  RTMP_Log(RTMP_LOGWARNING, "%s: client signature does not match!",
1063 	      __FUNCTION__);
1064 	}
1065     }
1066 
1067   RTMP_Log(RTMP_LOGDEBUG, "%s: Handshaking finished....", __FUNCTION__);
1068   return TRUE;
1069 }
1070 
1071 static int
SHandShake(RTMP * r)1072 SHandShake(RTMP * r)
1073 {
1074   int i, offalg = 0;
1075   int dhposServer = 0;
1076   int digestPosServer = 0;
1077   RC4_handle keyIn = 0;
1078   RC4_handle keyOut = 0;
1079   int FP9HandShake = FALSE;
1080   int encrypted;
1081   int32_t *ip;
1082 
1083   uint8_t clientsig[RTMP_SIG_SIZE];
1084   uint8_t serverbuf[RTMP_SIG_SIZE + 4], *serversig = serverbuf+4;
1085   uint8_t type;
1086   uint32_t uptime;
1087   getoff *getdh = NULL, *getdig = NULL;
1088 
1089   if (ReadN(r, (char *)&type, 1) != 1)	/* 0x03 or 0x06 */
1090     return FALSE;
1091 
1092   if (ReadN(r, (char *)clientsig, RTMP_SIG_SIZE) != RTMP_SIG_SIZE)
1093     return FALSE;
1094 
1095   RTMP_Log(RTMP_LOGDEBUG, "%s: Type Requested : %02X", __FUNCTION__, type);
1096   RTMP_LogHex(RTMP_LOGDEBUG2, clientsig, RTMP_SIG_SIZE);
1097 
1098   if (type == 3)
1099     {
1100       encrypted = FALSE;
1101     }
1102   else if (type == 6 || type == 8)
1103     {
1104       offalg = 1;
1105       encrypted = TRUE;
1106       FP9HandShake = TRUE;
1107       r->Link.protocol |= RTMP_FEATURE_ENC;
1108       /* use FP10 if client is capable */
1109       if (clientsig[4] == 128)
1110 	type = 8;
1111     }
1112   else
1113     {
1114       RTMP_Log(RTMP_LOGERROR, "%s: Unknown version %02x",
1115 	  __FUNCTION__, type);
1116       return FALSE;
1117     }
1118 
1119   if (!FP9HandShake && clientsig[4])
1120     FP9HandShake = TRUE;
1121 
1122   serversig[-1] = type;
1123 
1124   r->Link.rc4keyIn = r->Link.rc4keyOut = 0;
1125 
1126   uptime = htonl(RTMP_GetTime());
1127   memcpy(serversig, &uptime, 4);
1128 
1129   if (FP9HandShake)
1130     {
1131       /* Server version */
1132       serversig[4] = 3;
1133       serversig[5] = 5;
1134       serversig[6] = 1;
1135       serversig[7] = 1;
1136 
1137       getdig = digoff[offalg];
1138       getdh  = dhoff[offalg];
1139     }
1140   else
1141     {
1142       memset(&serversig[4], 0, 4);
1143     }
1144 
1145   /* generate random data */
1146 #ifdef _DEBUG
1147   memset(serversig+8, 0, RTMP_SIG_SIZE-8);
1148 #else
1149   ip = (int32_t *)(serversig+8);
1150   for (i = 2; i < RTMP_SIG_SIZE/4; i++)
1151     *ip++ = rand();
1152 #endif
1153 
1154   /* set handshake digest */
1155   if (FP9HandShake)
1156     {
1157       if (encrypted)
1158 	{
1159 	  /* generate Diffie-Hellmann parameters */
1160 	  r->Link.dh = DHInit(1024);
1161 	  if (!r->Link.dh)
1162 	    {
1163 	      RTMP_Log(RTMP_LOGERROR, "%s: Couldn't initialize Diffie-Hellmann!",
1164 		  __FUNCTION__);
1165 	      return FALSE;
1166 	    }
1167 
1168 	  dhposServer = getdh(serversig, RTMP_SIG_SIZE);
1169 	  RTMP_Log(RTMP_LOGDEBUG, "%s: DH pubkey position: %d", __FUNCTION__, dhposServer);
1170 
1171 	  if (!DHGenerateKey(r->Link.dh))
1172 	    {
1173 	      RTMP_Log(RTMP_LOGERROR, "%s: Couldn't generate Diffie-Hellmann public key!",
1174 		  __FUNCTION__);
1175 	      return FALSE;
1176 	    }
1177 
1178 	  if (!DHGetPublicKey
1179 	      (r->Link.dh, (uint8_t *) &serversig[dhposServer], 128))
1180 	    {
1181 	      RTMP_Log(RTMP_LOGERROR, "%s: Couldn't write public key!", __FUNCTION__);
1182 	      return FALSE;
1183 	    }
1184 	}
1185 
1186       digestPosServer = getdig(serversig, RTMP_SIG_SIZE);	/* reuse this value in verification */
1187       RTMP_Log(RTMP_LOGDEBUG, "%s: Server digest offset: %d", __FUNCTION__,
1188 	  digestPosServer);
1189 
1190       CalculateDigest(digestPosServer, serversig, GenuineFMSKey, 36,
1191 		      &serversig[digestPosServer]);
1192 
1193       RTMP_Log(RTMP_LOGDEBUG, "%s: Initial server digest: ", __FUNCTION__);
1194       RTMP_LogHex(RTMP_LOGDEBUG, serversig + digestPosServer,
1195 	     SHA256_DIGEST_LENGTH);
1196     }
1197 
1198   RTMP_Log(RTMP_LOGDEBUG2, "Serversig: ");
1199   RTMP_LogHex(RTMP_LOGDEBUG2, serversig, RTMP_SIG_SIZE);
1200 
1201   if (!WriteN(r, (char *)serversig-1, RTMP_SIG_SIZE + 1))
1202     return FALSE;
1203 
1204   /* decode client response */
1205   memcpy(&uptime, clientsig, 4);
1206   uptime = ntohl(uptime);
1207 
1208   RTMP_Log(RTMP_LOGDEBUG, "%s: Client Uptime : %d", __FUNCTION__, uptime);
1209   RTMP_Log(RTMP_LOGDEBUG, "%s: Player Version: %d.%d.%d.%d", __FUNCTION__, clientsig[4],
1210       clientsig[5], clientsig[6], clientsig[7]);
1211 
1212   if (FP9HandShake)
1213     {
1214       uint8_t digestResp[SHA256_DIGEST_LENGTH];
1215       uint8_t *signatureResp = NULL;
1216 
1217       /* we have to use this signature now to find the correct algorithms for getting the digest and DH positions */
1218       int digestPosClient = getdig(clientsig, RTMP_SIG_SIZE);
1219 
1220       if (!VerifyDigest(digestPosClient, clientsig, GenuineFPKey, 30))
1221 	{
1222 	  RTMP_Log(RTMP_LOGWARNING, "Trying different position for client digest!");
1223 	  offalg ^= 1;
1224 	  getdig = digoff[offalg];
1225 	  getdh  = dhoff[offalg];
1226 
1227 	  digestPosClient = getdig(clientsig, RTMP_SIG_SIZE);
1228 
1229 	  if (!VerifyDigest(digestPosClient, clientsig, GenuineFPKey, 30))
1230 	    {
1231 	      RTMP_Log(RTMP_LOGERROR, "Couldn't verify the client digest");	/* continuing anyway will probably fail */
1232 	      return FALSE;
1233 	    }
1234 	}
1235 
1236       /* generate SWFVerification token (SHA256 HMAC hash of decompressed SWF, key are the last 32 bytes of the server handshake) */
1237       if (r->Link.SWFSize)
1238 	{
1239 	  const char swfVerify[] = { 0x01, 0x01 };
1240           char *vend = r->Link.SWFVerificationResponse+sizeof(r->Link.SWFVerificationResponse);
1241 
1242 	  memcpy(r->Link.SWFVerificationResponse, swfVerify, 2);
1243 	  AMF_EncodeInt32(&r->Link.SWFVerificationResponse[2], vend, r->Link.SWFSize);
1244 	  AMF_EncodeInt32(&r->Link.SWFVerificationResponse[6], vend, r->Link.SWFSize);
1245 	  HMACsha256(r->Link.SWFHash, SHA256_DIGEST_LENGTH,
1246 		     &serversig[RTMP_SIG_SIZE - SHA256_DIGEST_LENGTH],
1247 		     SHA256_DIGEST_LENGTH,
1248 		     (uint8_t *)&r->Link.SWFVerificationResponse[10]);
1249 	}
1250 
1251       /* do Diffie-Hellmann Key exchange for encrypted RTMP */
1252       if (encrypted)
1253 	{
1254 	  int dhposClient, len;
1255 	  /* compute secret key */
1256 	  uint8_t secretKey[128] = { 0 };
1257 
1258 	  dhposClient = getdh(clientsig, RTMP_SIG_SIZE);
1259 	  RTMP_Log(RTMP_LOGDEBUG, "%s: Client DH public key offset: %d", __FUNCTION__,
1260 	    dhposClient);
1261 	  len =
1262 	    DHComputeSharedSecretKey(r->Link.dh,
1263 				     (uint8_t *) &clientsig[dhposClient], 128,
1264 				     secretKey);
1265 	  if (len < 0)
1266 	    {
1267 	      RTMP_Log(RTMP_LOGDEBUG, "%s: Wrong secret key position!", __FUNCTION__);
1268 	      return FALSE;
1269 	    }
1270 
1271 	  RTMP_Log(RTMP_LOGDEBUG, "%s: Secret key: ", __FUNCTION__);
1272 	  RTMP_LogHex(RTMP_LOGDEBUG, secretKey, 128);
1273 
1274 	  InitRC4Encryption(secretKey,
1275 			    (uint8_t *) &clientsig[dhposClient],
1276 			    (uint8_t *) &serversig[dhposServer],
1277 			    &keyIn, &keyOut);
1278 	}
1279 
1280 
1281       /* calculate response now */
1282       signatureResp = clientsig+RTMP_SIG_SIZE-SHA256_DIGEST_LENGTH;
1283 
1284       HMACsha256(&clientsig[digestPosClient], SHA256_DIGEST_LENGTH,
1285 		 GenuineFMSKey, sizeof(GenuineFMSKey), digestResp);
1286       HMACsha256(clientsig, RTMP_SIG_SIZE - SHA256_DIGEST_LENGTH, digestResp,
1287 		 SHA256_DIGEST_LENGTH, signatureResp);
1288 #ifdef FP10
1289       if (type == 8 )
1290         {
1291 	  uint8_t *dptr = digestResp;
1292 	  uint8_t *sig = signatureResp;
1293 	  /* encrypt signatureResp */
1294           for (i=0; i<SHA256_DIGEST_LENGTH; i+=8)
1295 	    rtmpe8_sig(sig+i, sig+i, dptr[i] % 15);
1296         }
1297       else if (type == 9)
1298         {
1299 	  uint8_t *dptr = digestResp;
1300 	  uint8_t *sig = signatureResp;
1301 	  /* encrypt signatureResp */
1302           for (i=0; i<SHA256_DIGEST_LENGTH; i+=8)
1303             rtmpe9_sig(sig+i, sig+i, dptr[i] % 15);
1304         }
1305 #endif
1306 
1307       /* some info output */
1308       RTMP_Log(RTMP_LOGDEBUG,
1309 	  "%s: Calculated digest key from secure key and server digest: ",
1310 	  __FUNCTION__);
1311       RTMP_LogHex(RTMP_LOGDEBUG, digestResp, SHA256_DIGEST_LENGTH);
1312 
1313       RTMP_Log(RTMP_LOGDEBUG, "%s: Server signature calculated:", __FUNCTION__);
1314       RTMP_LogHex(RTMP_LOGDEBUG, signatureResp, SHA256_DIGEST_LENGTH);
1315     }
1316 #if 0
1317   else
1318     {
1319       uptime = htonl(RTMP_GetTime());
1320       memcpy(clientsig+4, &uptime, 4);
1321     }
1322 #endif
1323 
1324   RTMP_Log(RTMP_LOGDEBUG2, "%s: Sending handshake response: ",
1325     __FUNCTION__);
1326   RTMP_LogHex(RTMP_LOGDEBUG2, clientsig, RTMP_SIG_SIZE);
1327 
1328   if (!WriteN(r, (char *)clientsig, RTMP_SIG_SIZE))
1329     return FALSE;
1330 
1331   /* 2nd part of handshake */
1332   if (ReadN(r, (char *)clientsig, RTMP_SIG_SIZE) != RTMP_SIG_SIZE)
1333     return FALSE;
1334 
1335   RTMP_Log(RTMP_LOGDEBUG2, "%s: 2nd handshake: ", __FUNCTION__);
1336   RTMP_LogHex(RTMP_LOGDEBUG2, clientsig, RTMP_SIG_SIZE);
1337 
1338   if (FP9HandShake)
1339     {
1340       uint8_t signature[SHA256_DIGEST_LENGTH];
1341       uint8_t digest[SHA256_DIGEST_LENGTH];
1342 
1343       RTMP_Log(RTMP_LOGDEBUG, "%s: Client sent signature:", __FUNCTION__);
1344       RTMP_LogHex(RTMP_LOGDEBUG, &clientsig[RTMP_SIG_SIZE - SHA256_DIGEST_LENGTH],
1345 	     SHA256_DIGEST_LENGTH);
1346 
1347       /* verify client response */
1348       HMACsha256(&serversig[digestPosServer], SHA256_DIGEST_LENGTH,
1349 		 GenuineFPKey, sizeof(GenuineFPKey), digest);
1350       HMACsha256(clientsig, RTMP_SIG_SIZE - SHA256_DIGEST_LENGTH, digest,
1351 		 SHA256_DIGEST_LENGTH, signature);
1352 #ifdef FP10
1353       if (type == 8 )
1354         {
1355 	  uint8_t *dptr = digest;
1356 	  uint8_t *sig = signature;
1357 	  /* encrypt signatureResp */
1358           for (i=0; i<SHA256_DIGEST_LENGTH; i+=8)
1359 	    rtmpe8_sig(sig+i, sig+i, dptr[i] % 15);
1360         }
1361       else if (type == 9)
1362         {
1363 	  uint8_t *dptr = digest;
1364 	  uint8_t *sig = signature;
1365 	  /* encrypt signatureResp */
1366           for (i=0; i<SHA256_DIGEST_LENGTH; i+=8)
1367             rtmpe9_sig(sig+i, sig+i, dptr[i] % 15);
1368         }
1369 #endif
1370 
1371       /* show some information */
1372       RTMP_Log(RTMP_LOGDEBUG, "%s: Digest key: ", __FUNCTION__);
1373       RTMP_LogHex(RTMP_LOGDEBUG, digest, SHA256_DIGEST_LENGTH);
1374 
1375       RTMP_Log(RTMP_LOGDEBUG, "%s: Signature calculated:", __FUNCTION__);
1376       RTMP_LogHex(RTMP_LOGDEBUG, signature, SHA256_DIGEST_LENGTH);
1377       if (memcmp
1378 	  (signature, &clientsig[RTMP_SIG_SIZE - SHA256_DIGEST_LENGTH],
1379 	   SHA256_DIGEST_LENGTH) != 0)
1380 	{
1381 	  RTMP_Log(RTMP_LOGWARNING, "%s: Client not genuine Adobe!", __FUNCTION__);
1382 	  return FALSE;
1383 	}
1384       else
1385 	{
1386 	  RTMP_Log(RTMP_LOGDEBUG, "%s: Genuine Adobe Flash Player", __FUNCTION__);
1387 	}
1388 
1389       if (encrypted)
1390 	{
1391 	  char buff[RTMP_SIG_SIZE];
1392 	  /* set keys for encryption from now on */
1393 	  r->Link.rc4keyIn = keyIn;
1394 	  r->Link.rc4keyOut = keyOut;
1395 
1396 	  /* update the keystreams */
1397 	  if (r->Link.rc4keyIn)
1398 	    {
1399 	      RC4_encrypt(r->Link.rc4keyIn, RTMP_SIG_SIZE, (uint8_t *) buff);
1400 	    }
1401 
1402 	  if (r->Link.rc4keyOut)
1403 	    {
1404 	      RC4_encrypt(r->Link.rc4keyOut, RTMP_SIG_SIZE, (uint8_t *) buff);
1405 	    }
1406 	}
1407     }
1408   else
1409     {
1410       if (memcmp(serversig, clientsig, RTMP_SIG_SIZE) != 0)
1411 	{
1412 	  RTMP_Log(RTMP_LOGWARNING, "%s: client signature does not match!",
1413 	      __FUNCTION__);
1414 	}
1415     }
1416 
1417   RTMP_Log(RTMP_LOGDEBUG, "%s: Handshaking finished....", __FUNCTION__);
1418   return TRUE;
1419 }
1420