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