annotate asfcrypt.c @ 6247:a64b9fa63635 libavformat

bswap: change ME to NE in macro names Other parts of FFmpeg use NE (native endian) rather than ME (machine). This makes it consistent.
author mru
date Sat, 10 Jul 2010 22:09:01 +0000
parents 8b49322b8735
children e630da0f5861
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2652
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
1 /*
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
2 * ASF decryption
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
3 * Copyright (c) 2007 Reimar Doeffinger
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
4 * This is a rewrite of code contained in freeme/freeme2
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
5 *
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
6 * This file is part of FFmpeg.
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
7 *
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
8 * FFmpeg is free software; you can redistribute it and/or
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
9 * modify it under the terms of the GNU Lesser General Public
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
10 * License as published by the Free Software Foundation; either
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
11 * version 2.1 of the License, or (at your option) any later version.
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
12 *
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
13 * FFmpeg is distributed in the hope that it will be useful,
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
16 * Lesser General Public License for more details.
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
17 *
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
18 * You should have received a copy of the GNU Lesser General Public
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
19 * License along with FFmpeg; if not, write to the Free Software
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
21 */
3286
6f61c3b36632 Use full path for #includes from another directory.
diego
parents: 2652
diff changeset
22
6f61c3b36632 Use full path for #includes from another directory.
diego
parents: 2652
diff changeset
23 #include "libavutil/common.h"
6f61c3b36632 Use full path for #includes from another directory.
diego
parents: 2652
diff changeset
24 #include "libavutil/intreadwrite.h"
6f61c3b36632 Use full path for #includes from another directory.
diego
parents: 2652
diff changeset
25 #include "libavutil/bswap.h"
6f61c3b36632 Use full path for #includes from another directory.
diego
parents: 2652
diff changeset
26 #include "libavutil/des.h"
6f61c3b36632 Use full path for #includes from another directory.
diego
parents: 2652
diff changeset
27 #include "libavutil/rc4.h"
2652
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
28 #include "asfcrypt.h"
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
29
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
30 /**
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
31 * \brief find multiplicative inverse modulo 2 ^ 32
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
32 * \param v number to invert, must be odd!
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
33 * \return number so that result * v = 1 (mod 2^32)
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
34 */
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
35 static uint32_t inverse(uint32_t v) {
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
36 // v ^ 3 gives the inverse (mod 16), could also be implemented
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
37 // as table etc. (only lowest 4 bits matter!)
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
38 uint32_t inverse = v * v * v;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
39 // uses a fixpoint-iteration that doubles the number
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
40 // of correct lowest bits each time
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
41 inverse *= 2 - v * inverse;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
42 inverse *= 2 - v * inverse;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
43 inverse *= 2 - v * inverse;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
44 return inverse;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
45 }
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
46
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
47 /**
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
48 * \brief read keys from keybuf into keys
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
49 * \param keybuf buffer containing the keys
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
50 * \param keys output key array containing the keys for encryption in
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
51 * native endianness
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
52 */
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
53 static void multiswap_init(const uint8_t keybuf[48], uint32_t keys[12]) {
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
54 int i;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
55 for (i = 0; i < 12; i++)
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
56 keys[i] = AV_RL32(keybuf + (i << 2)) | 1;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
57 }
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
58
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
59 /**
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
60 * \brief invert the keys so that encryption become decryption keys and
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
61 * the other way round.
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
62 * \param keys key array of ints to invert
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
63 */
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
64 static void multiswap_invert_keys(uint32_t keys[12]) {
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
65 int i;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
66 for (i = 0; i < 5; i++)
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
67 keys[i] = inverse(keys[i]);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
68 for (i = 6; i < 11; i++)
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
69 keys[i] = inverse(keys[i]);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
70 }
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
71
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
72 static uint32_t multiswap_step(const uint32_t keys[12], uint32_t v) {
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
73 int i;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
74 v *= keys[0];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
75 for (i = 1; i < 5; i++) {
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
76 v = (v >> 16) | (v << 16);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
77 v *= keys[i];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
78 }
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
79 v += keys[5];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
80 return v;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
81 }
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
82
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
83 static uint32_t multiswap_inv_step(const uint32_t keys[12], uint32_t v) {
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
84 int i;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
85 v -= keys[5];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
86 for (i = 4; i > 0; i--) {
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
87 v *= keys[i];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
88 v = (v >> 16) | (v << 16);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
89 }
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
90 v *= keys[0];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
91 return v;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
92 }
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
93
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
94 /**
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
95 * \brief "MultiSwap" encryption
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
96 * \param keys 32 bit numbers in machine endianness,
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
97 * 0-4 and 6-10 must be inverted from decryption
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
98 * \param key another key, this one must be the same for the decryption
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
99 * \param data data to encrypt
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
100 * \return encrypted data
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
101 */
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
102 static uint64_t multiswap_enc(const uint32_t keys[12], uint64_t key, uint64_t data) {
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
103 uint32_t a = data;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
104 uint32_t b = data >> 32;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
105 uint32_t c;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
106 uint32_t tmp;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
107 a += key;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
108 tmp = multiswap_step(keys , a);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
109 b += tmp;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
110 c = (key >> 32) + tmp;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
111 tmp = multiswap_step(keys + 6, b);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
112 c += tmp;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
113 return ((uint64_t)c << 32) | tmp;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
114 }
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
115
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
116 /**
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
117 * \brief "MultiSwap" decryption
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
118 * \param keys 32 bit numbers in machine endianness,
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
119 * 0-4 and 6-10 must be inverted from encryption
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
120 * \param key another key, this one must be the same as for the encryption
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
121 * \param data data to decrypt
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
122 * \return decrypted data
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
123 */
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
124 static uint64_t multiswap_dec(const uint32_t keys[12], uint64_t key, uint64_t data) {
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
125 uint32_t a;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
126 uint32_t b;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
127 uint32_t c = data >> 32;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
128 uint32_t tmp = data;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
129 c -= tmp;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
130 b = multiswap_inv_step(keys + 6, tmp);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
131 tmp = c - (key >> 32);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
132 b -= tmp;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
133 a = multiswap_inv_step(keys , tmp);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
134 a -= key;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
135 return ((uint64_t)b << 32) | a;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
136 }
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
137
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
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
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
141 int num_qwords = len >> 3;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
142 uint64_t *qwords = (uint64_t *)data;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
143 uint64_t rc4buff[8];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
144 uint64_t packetkey;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
145 uint32_t ms_keys[12];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
146 uint64_t ms_state;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
147 int i;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
148 if (len < 16) {
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
149 for (i = 0; i < len; i++)
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
150 data[i] ^= key[i];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
151 return;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
152 }
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
153
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
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
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
157 multiswap_init((uint8_t *)rc4buff, ms_keys);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
158
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
159 packetkey = qwords[num_qwords - 1];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
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
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
163 packetkey ^= rc4buff[6];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
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
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
167
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
168 ms_state = 0;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
169 for (i = 0; i < num_qwords - 1; i++, qwords++)
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
170 ms_state = multiswap_enc(ms_keys, ms_state, AV_RL64(qwords));
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
171 multiswap_invert_keys(ms_keys);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
172 packetkey = (packetkey << 32) | (packetkey >> 32);
6247
a64b9fa63635 bswap: change ME to NE in macro names
mru
parents: 4367
diff changeset
173 packetkey = le2ne_64(packetkey);
2652
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
174 packetkey = multiswap_dec(ms_keys, ms_state, packetkey);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
175 AV_WL64(qwords, packetkey);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
176 }