| 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 | */ |
| 22 | |
| 23 | #include "libavutil/bswap.h" |
| 24 | #include "libavutil/common.h" |
| 25 | #include "libavutil/des.h" |
| 26 | #include "libavutil/intreadwrite.h" |
| 27 | #include "libavutil/rc4.h" |
| 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 | { |
| 37 | // v ^ 3 gives the inverse (mod 16), could also be implemented |
| 38 | // as table etc. (only lowest 4 bits matter!) |
| 39 | uint32_t inverse = v * v * v; |
| 40 | // uses a fixpoint-iteration that doubles the number |
| 41 | // of correct lowest bits each time |
| 42 | inverse *= 2 - v * inverse; |
| 43 | inverse *= 2 - v * inverse; |
| 44 | inverse *= 2 - v * inverse; |
| 45 | return inverse; |
| 46 | } |
| 47 | |
| 48 | /** |
| 49 | * @brief read keys from keybuf into keys |
| 50 | * @param keybuf buffer containing the keys |
| 51 | * @param keys output key array containing the keys for encryption in |
| 52 | * native endianness |
| 53 | */ |
| 54 | static void multiswap_init(const uint8_t keybuf[48], uint32_t keys[12]) |
| 55 | { |
| 56 | int i; |
| 57 | for (i = 0; i < 12; i++) |
| 58 | keys[i] = AV_RL32(keybuf + (i << 2)) | 1; |
| 59 | } |
| 60 | |
| 61 | /** |
| 62 | * @brief invert the keys so that encryption become decryption keys and |
| 63 | * the other way round. |
| 64 | * @param keys key array of ints to invert |
| 65 | */ |
| 66 | static void multiswap_invert_keys(uint32_t keys[12]) |
| 67 | { |
| 68 | int i; |
| 69 | for (i = 0; i < 5; i++) |
| 70 | keys[i] = inverse(keys[i]); |
| 71 | for (i = 6; i < 11; i++) |
| 72 | keys[i] = inverse(keys[i]); |
| 73 | } |
| 74 | |
| 75 | static uint32_t multiswap_step(const uint32_t keys[12], uint32_t v) |
| 76 | { |
| 77 | int i; |
| 78 | v *= keys[0]; |
| 79 | for (i = 1; i < 5; i++) { |
| 80 | v = (v >> 16) | (v << 16); |
| 81 | v *= keys[i]; |
| 82 | } |
| 83 | v += keys[5]; |
| 84 | return v; |
| 85 | } |
| 86 | |
| 87 | static uint32_t multiswap_inv_step(const uint32_t keys[12], uint32_t v) |
| 88 | { |
| 89 | int i; |
| 90 | v -= keys[5]; |
| 91 | for (i = 4; i > 0; i--) { |
| 92 | v *= keys[i]; |
| 93 | v = (v >> 16) | (v << 16); |
| 94 | } |
| 95 | v *= keys[0]; |
| 96 | return v; |
| 97 | } |
| 98 | |
| 99 | /** |
| 100 | * @brief "MultiSwap" encryption |
| 101 | * @param keys 32 bit numbers in machine endianness, |
| 102 | * 0-4 and 6-10 must be inverted from decryption |
| 103 | * @param key another key, this one must be the same for the decryption |
| 104 | * @param data data to encrypt |
| 105 | * @return encrypted data |
| 106 | */ |
| 107 | static uint64_t multiswap_enc(const uint32_t keys[12], |
| 108 | uint64_t key, uint64_t data) |
| 109 | { |
| 110 | uint32_t a = data; |
| 111 | uint32_t b = data >> 32; |
| 112 | uint32_t c; |
| 113 | uint32_t tmp; |
| 114 | a += key; |
| 115 | tmp = multiswap_step(keys, a); |
| 116 | b += tmp; |
| 117 | c = (key >> 32) + tmp; |
| 118 | tmp = multiswap_step(keys + 6, b); |
| 119 | c += tmp; |
| 120 | return ((uint64_t)c << 32) | tmp; |
| 121 | } |
| 122 | |
| 123 | /** |
| 124 | * @brief "MultiSwap" decryption |
| 125 | * @param keys 32 bit numbers in machine endianness, |
| 126 | * 0-4 and 6-10 must be inverted from encryption |
| 127 | * @param key another key, this one must be the same as for the encryption |
| 128 | * @param data data to decrypt |
| 129 | * @return decrypted data |
| 130 | */ |
| 131 | static uint64_t multiswap_dec(const uint32_t keys[12], |
| 132 | uint64_t key, uint64_t data) |
| 133 | { |
| 134 | uint32_t a; |
| 135 | uint32_t b; |
| 136 | uint32_t c = data >> 32; |
| 137 | uint32_t tmp = data; |
| 138 | c -= tmp; |
| 139 | b = multiswap_inv_step(keys + 6, tmp); |
| 140 | tmp = c - (key >> 32); |
| 141 | b -= tmp; |
| 142 | a = multiswap_inv_step(keys, tmp); |
| 143 | a -= key; |
| 144 | return ((uint64_t)b << 32) | a; |
| 145 | } |
| 146 | |
| 147 | void ff_asfcrypt_dec(const uint8_t key[20], uint8_t *data, int len) |
| 148 | { |
| 149 | struct AVDES des; |
| 150 | struct AVRC4 rc4; |
| 151 | int num_qwords = len >> 3; |
| 152 | uint8_t *qwords = data; |
| 153 | uint64_t rc4buff[8] = { 0 }; |
| 154 | uint64_t packetkey; |
| 155 | uint32_t ms_keys[12]; |
| 156 | uint64_t ms_state; |
| 157 | int i; |
| 158 | if (len < 16) { |
| 159 | for (i = 0; i < len; i++) |
| 160 | data[i] ^= key[i]; |
| 161 | return; |
| 162 | } |
| 163 | |
| 164 | av_rc4_init(&rc4, key, 12 * 8, 1); |
| 165 | av_rc4_crypt(&rc4, (uint8_t *)rc4buff, NULL, sizeof(rc4buff), NULL, 1); |
| 166 | multiswap_init((uint8_t *)rc4buff, ms_keys); |
| 167 | |
| 168 | packetkey = AV_RN64(&qwords[num_qwords * 8 - 8]); |
| 169 | packetkey ^= rc4buff[7]; |
| 170 | av_des_init(&des, key + 12, 64, 1); |
| 171 | av_des_crypt(&des, (uint8_t *)&packetkey, (uint8_t *)&packetkey, 1, NULL, 1); |
| 172 | packetkey ^= rc4buff[6]; |
| 173 | |
| 174 | av_rc4_init(&rc4, (uint8_t *)&packetkey, 64, 1); |
| 175 | av_rc4_crypt(&rc4, data, data, len, NULL, 1); |
| 176 | |
| 177 | ms_state = 0; |
| 178 | for (i = 0; i < num_qwords - 1; i++, qwords += 8) |
| 179 | ms_state = multiswap_enc(ms_keys, ms_state, AV_RL64(qwords)); |
| 180 | multiswap_invert_keys(ms_keys); |
| 181 | packetkey = (packetkey << 32) | (packetkey >> 32); |
| 182 | packetkey = av_le2ne64(packetkey); |
| 183 | packetkey = multiswap_dec(ms_keys, ms_state, packetkey); |
| 184 | AV_WL64(qwords, packetkey); |
| 185 | } |