annotate asfcrypt.c @ 3068:9cc9ff5aff9c libavformat

set bps to uncompressed original sound data for compressed audio according to aiff specs, qt set it to 16 for mace and ima4, fail if block align is not set.
author bcoudurier
date Mon, 25 Feb 2008 12:00:31 +0000
parents 2d28b2a5b2e4
children 6f61c3b36632
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 */
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
22 #include "common.h"
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
23 #include "intreadwrite.h"
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
24 #include "bswap.h"
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
25 #include "des.h"
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
26 #include "rc4.h"
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
27 #include "asfcrypt.h"
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
28
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
29 /**
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
30 * \brief find multiplicative inverse modulo 2 ^ 32
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
31 * \param v number to invert, must be odd!
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
32 * \return number so that result * v = 1 (mod 2^32)
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
33 */
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
34 static uint32_t inverse(uint32_t v) {
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
35 // v ^ 3 gives the inverse (mod 16), could also be implemented
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
36 // as table etc. (only lowest 4 bits matter!)
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
37 uint32_t inverse = v * v * v;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
38 // uses a fixpoint-iteration that doubles the number
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
39 // of correct lowest bits each time
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
40 inverse *= 2 - v * inverse;
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 return inverse;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
44 }
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 * \brief read keys from keybuf into keys
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
48 * \param keybuf buffer containing the keys
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
49 * \param keys output key array containing the keys for encryption in
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
50 * native endianness
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
51 */
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
52 static void multiswap_init(const uint8_t keybuf[48], uint32_t keys[12]) {
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
53 int i;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
54 for (i = 0; i < 12; i++)
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
55 keys[i] = AV_RL32(keybuf + (i << 2)) | 1;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
56 }
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 * \brief invert the keys so that encryption become decryption keys and
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
60 * the other way round.
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
61 * \param keys key array of ints to invert
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
62 */
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
63 static void multiswap_invert_keys(uint32_t keys[12]) {
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
64 int i;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
65 for (i = 0; i < 5; i++)
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
66 keys[i] = inverse(keys[i]);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
67 for (i = 6; i < 11; i++)
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
68 keys[i] = inverse(keys[i]);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
69 }
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
70
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
71 static uint32_t multiswap_step(const uint32_t keys[12], uint32_t v) {
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
72 int i;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
73 v *= keys[0];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
74 for (i = 1; i < 5; i++) {
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
75 v = (v >> 16) | (v << 16);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
76 v *= keys[i];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
77 }
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
78 v += keys[5];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
79 return v;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
80 }
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
81
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
82 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
83 int i;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
84 v -= keys[5];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
85 for (i = 4; i > 0; i--) {
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
86 v *= keys[i];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
87 v = (v >> 16) | (v << 16);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
88 }
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
89 v *= keys[0];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
90 return v;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
91 }
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 * \brief "MultiSwap" encryption
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
95 * \param keys 32 bit numbers in machine endianness,
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
96 * 0-4 and 6-10 must be inverted from decryption
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
97 * \param key another key, this one must be the same for the decryption
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
98 * \param data data to encrypt
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
99 * \return encrypted data
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
100 */
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
101 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
102 uint32_t a = data;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
103 uint32_t b = data >> 32;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
104 uint32_t c;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
105 uint32_t tmp;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
106 a += key;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
107 tmp = multiswap_step(keys , a);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
108 b += tmp;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
109 c = (key >> 32) + tmp;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
110 tmp = multiswap_step(keys + 6, b);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
111 c += tmp;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
112 return ((uint64_t)c << 32) | tmp;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
113 }
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 * \brief "MultiSwap" decryption
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
117 * \param keys 32 bit numbers in machine endianness,
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
118 * 0-4 and 6-10 must be inverted from encryption
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
119 * \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
120 * \param data data to decrypt
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
121 * \return decrypted data
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
122 */
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
123 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
124 uint32_t a;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
125 uint32_t b;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
126 uint32_t c = data >> 32;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
127 uint32_t tmp = data;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
128 c -= tmp;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
129 b = multiswap_inv_step(keys + 6, tmp);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
130 tmp = c - (key >> 32);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
131 b -= tmp;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
132 a = multiswap_inv_step(keys , tmp);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
133 a -= key;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
134 return ((uint64_t)b << 32) | a;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
135 }
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
136
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
137 void ff_asfcrypt_dec(const uint8_t key[20], uint8_t *data, int len) {
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
138 int num_qwords = len >> 3;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
139 uint64_t *qwords = (uint64_t *)data;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
140 uint64_t rc4buff[8];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
141 uint64_t packetkey;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
142 uint32_t ms_keys[12];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
143 uint64_t ms_state;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
144 int i;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
145 if (len < 16) {
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
146 for (i = 0; i < len; i++)
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
147 data[i] ^= key[i];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
148 return;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
149 }
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
150
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
151 memset(rc4buff, 0, sizeof(rc4buff));
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
152 ff_rc4_enc(key, 12, (uint8_t *)rc4buff, sizeof(rc4buff));
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
153 multiswap_init((uint8_t *)rc4buff, ms_keys);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
154
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
155 packetkey = qwords[num_qwords - 1];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
156 packetkey ^= rc4buff[7];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
157 packetkey = be2me_64(packetkey);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
158 packetkey = ff_des_encdec(packetkey, AV_RB64(key + 12), 1);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
159 packetkey = be2me_64(packetkey);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
160 packetkey ^= rc4buff[6];
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
161
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
162 ff_rc4_enc((uint8_t *)&packetkey, 8, data, len);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
163
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
164 ms_state = 0;
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
165 for (i = 0; i < num_qwords - 1; i++, qwords++)
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
166 ms_state = multiswap_enc(ms_keys, ms_state, AV_RL64(qwords));
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
167 multiswap_invert_keys(ms_keys);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
168 packetkey = (packetkey << 32) | (packetkey >> 32);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
169 packetkey = le2me_64(packetkey);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
170 packetkey = multiswap_dec(ms_keys, ms_state, packetkey);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
171 AV_WL64(qwords, packetkey);
2d28b2a5b2e4 Add support for decrypting asf files
reimar
parents:
diff changeset
172 }