Mercurial > libavformat.hg
annotate asfcrypt.c @ 4874:5370b0c1653c libavformat
Increase the SDP buffer size (again!) and also increase the temporary
buffer size of the fmtp parameter buffer. For Vorbis RT(S)P, these
contain full Vorbis headers, which can be up to 12kb each, formatted
in base64, so 16kb total. Patch required for proper Vorbis/RTP playback,
submitted as GSoC qualification task in the thread "RTP/Vorbis payload
implementation (GSoC qual task)" by Colin McQuillan m.niloc googlemail
com.
author | rbultje |
---|---|
date | Tue, 14 Apr 2009 13:22:40 +0000 |
parents | 8b49322b8735 |
children | a64b9fa63635 |
rev | line source |
---|---|
2652 | 1 /* |
2 * ASF decryption | |
3 * Copyright (c) 2007 Reimar Doeffinger | |
4 * This is a rewrite of code contained in freeme/freeme2 | |
5 * | |
6 * This file is part of FFmpeg. | |
7 * | |
8 * FFmpeg is free software; you can redistribute it and/or | |
9 * modify it under the terms of the GNU Lesser General Public | |
10 * License as published by the Free Software Foundation; either | |
11 * version 2.1 of the License, or (at your option) any later version. | |
12 * | |
13 * FFmpeg 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 GNU | |
16 * Lesser General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU Lesser General Public | |
19 * License along with FFmpeg; if not, write to the Free Software | |
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
21 */ | |
3286 | 22 |
23 #include "libavutil/common.h" | |
24 #include "libavutil/intreadwrite.h" | |
25 #include "libavutil/bswap.h" | |
26 #include "libavutil/des.h" | |
27 #include "libavutil/rc4.h" | |
2652 | 28 #include "asfcrypt.h" |
29 | |
30 /** | |
31 * \brief find multiplicative inverse modulo 2 ^ 32 | |
32 * \param v number to invert, must be odd! | |
33 * \return number so that result * v = 1 (mod 2^32) | |
34 */ | |
35 static uint32_t inverse(uint32_t v) { | |
36 // v ^ 3 gives the inverse (mod 16), could also be implemented | |
37 // as table etc. (only lowest 4 bits matter!) | |
38 uint32_t inverse = v * v * v; | |
39 // uses a fixpoint-iteration that doubles the number | |
40 // of correct lowest bits each time | |
41 inverse *= 2 - v * inverse; | |
42 inverse *= 2 - v * inverse; | |
43 inverse *= 2 - v * inverse; | |
44 return inverse; | |
45 } | |
46 | |
47 /** | |
48 * \brief read keys from keybuf into keys | |
49 * \param keybuf buffer containing the keys | |
50 * \param keys output key array containing the keys for encryption in | |
51 * native endianness | |
52 */ | |
53 static void multiswap_init(const uint8_t keybuf[48], uint32_t keys[12]) { | |
54 int i; | |
55 for (i = 0; i < 12; i++) | |
56 keys[i] = AV_RL32(keybuf + (i << 2)) | 1; | |
57 } | |
58 | |
59 /** | |
60 * \brief invert the keys so that encryption become decryption keys and | |
61 * the other way round. | |
62 * \param keys key array of ints to invert | |
63 */ | |
64 static void multiswap_invert_keys(uint32_t keys[12]) { | |
65 int i; | |
66 for (i = 0; i < 5; i++) | |
67 keys[i] = inverse(keys[i]); | |
68 for (i = 6; i < 11; i++) | |
69 keys[i] = inverse(keys[i]); | |
70 } | |
71 | |
72 static uint32_t multiswap_step(const uint32_t keys[12], uint32_t v) { | |
73 int i; | |
74 v *= keys[0]; | |
75 for (i = 1; i < 5; i++) { | |
76 v = (v >> 16) | (v << 16); | |
77 v *= keys[i]; | |
78 } | |
79 v += keys[5]; | |
80 return v; | |
81 } | |
82 | |
83 static uint32_t multiswap_inv_step(const uint32_t keys[12], uint32_t v) { | |
84 int i; | |
85 v -= keys[5]; | |
86 for (i = 4; i > 0; i--) { | |
87 v *= keys[i]; | |
88 v = (v >> 16) | (v << 16); | |
89 } | |
90 v *= keys[0]; | |
91 return v; | |
92 } | |
93 | |
94 /** | |
95 * \brief "MultiSwap" encryption | |
96 * \param keys 32 bit numbers in machine endianness, | |
97 * 0-4 and 6-10 must be inverted from decryption | |
98 * \param key another key, this one must be the same for the decryption | |
99 * \param data data to encrypt | |
100 * \return encrypted data | |
101 */ | |
102 static uint64_t multiswap_enc(const uint32_t keys[12], uint64_t key, uint64_t data) { | |
103 uint32_t a = data; | |
104 uint32_t b = data >> 32; | |
105 uint32_t c; | |
106 uint32_t tmp; | |
107 a += key; | |
108 tmp = multiswap_step(keys , a); | |
109 b += tmp; | |
110 c = (key >> 32) + tmp; | |
111 tmp = multiswap_step(keys + 6, b); | |
112 c += tmp; | |
113 return ((uint64_t)c << 32) | tmp; | |
114 } | |
115 | |
116 /** | |
117 * \brief "MultiSwap" decryption | |
118 * \param keys 32 bit numbers in machine endianness, | |
119 * 0-4 and 6-10 must be inverted from encryption | |
120 * \param key another key, this one must be the same as for the encryption | |
121 * \param data data to decrypt | |
122 * \return decrypted data | |
123 */ | |
124 static uint64_t multiswap_dec(const uint32_t keys[12], uint64_t key, uint64_t data) { | |
125 uint32_t a; | |
126 uint32_t b; | |
127 uint32_t c = data >> 32; | |
128 uint32_t tmp = data; | |
129 c -= tmp; | |
130 b = multiswap_inv_step(keys + 6, tmp); | |
131 tmp = c - (key >> 32); | |
132 b -= tmp; | |
133 a = multiswap_inv_step(keys , tmp); | |
134 a -= key; | |
135 return ((uint64_t)b << 32) | a; | |
136 } | |
137 | |
138 void ff_asfcrypt_dec(const uint8_t key[20], uint8_t *data, int len) { | |
4367
8b49322b8735
Add and use a public API for RC4 and DES, analogous to the AES API.
reimar
parents:
3286
diff
changeset
|
139 struct AVDES des; |
8b49322b8735
Add and use a public API for RC4 and DES, analogous to the AES API.
reimar
parents:
3286
diff
changeset
|
140 struct AVRC4 rc4; |
2652 | 141 int num_qwords = len >> 3; |
142 uint64_t *qwords = (uint64_t *)data; | |
143 uint64_t rc4buff[8]; | |
144 uint64_t packetkey; | |
145 uint32_t ms_keys[12]; | |
146 uint64_t ms_state; | |
147 int i; | |
148 if (len < 16) { | |
149 for (i = 0; i < len; i++) | |
150 data[i] ^= key[i]; | |
151 return; | |
152 } | |
153 | |
154 memset(rc4buff, 0, sizeof(rc4buff)); | |
4367
8b49322b8735
Add and use a public API for RC4 and DES, analogous to the AES API.
reimar
parents:
3286
diff
changeset
|
155 av_rc4_init(&rc4, key, 12 * 8, 1); |
8b49322b8735
Add and use a public API for RC4 and DES, analogous to the AES API.
reimar
parents:
3286
diff
changeset
|
156 av_rc4_crypt(&rc4, (uint8_t *)rc4buff, NULL, sizeof(rc4buff), NULL, 1); |
2652 | 157 multiswap_init((uint8_t *)rc4buff, ms_keys); |
158 | |
159 packetkey = qwords[num_qwords - 1]; | |
160 packetkey ^= rc4buff[7]; | |
4367
8b49322b8735
Add and use a public API for RC4 and DES, analogous to the AES API.
reimar
parents:
3286
diff
changeset
|
161 av_des_init(&des, key + 12, 64, 1); |
8b49322b8735
Add and use a public API for RC4 and DES, analogous to the AES API.
reimar
parents:
3286
diff
changeset
|
162 av_des_crypt(&des, (uint8_t *)&packetkey, (uint8_t *)&packetkey, 1, NULL, 1); |
2652 | 163 packetkey ^= rc4buff[6]; |
164 | |
4367
8b49322b8735
Add and use a public API for RC4 and DES, analogous to the AES API.
reimar
parents:
3286
diff
changeset
|
165 av_rc4_init(&rc4, (uint8_t *)&packetkey, 64, 1); |
8b49322b8735
Add and use a public API for RC4 and DES, analogous to the AES API.
reimar
parents:
3286
diff
changeset
|
166 av_rc4_crypt(&rc4, data, data, len, NULL, 1); |
2652 | 167 |
168 ms_state = 0; | |
169 for (i = 0; i < num_qwords - 1; i++, qwords++) | |
170 ms_state = multiswap_enc(ms_keys, ms_state, AV_RL64(qwords)); | |
171 multiswap_invert_keys(ms_keys); | |
172 packetkey = (packetkey << 32) | (packetkey >> 32); | |
173 packetkey = le2me_64(packetkey); | |
174 packetkey = multiswap_dec(ms_keys, ms_state, packetkey); | |
175 AV_WL64(qwords, packetkey); | |
176 } |