; decss.ss, v1.0 ; Implementation of CSS descrambling in Scheme. ; Copyleft 2000 by John R. Hall ; Based on the ubiquitous css_descramble.c by Derek Fawcus. ; First, some bit pushing routines. These rely on MzScheme-specific functions, ; but it's likely that other implementations of Scheme provide similar facilities. (define uint8-and (lambda (a b) (bitwise-and a b #xFF))) (define uint8-or (lambda (a b) (bitwise-and (bitwise-ior a b) #xFF))) (define uint8-xor (lambda (a b) (bitwise-and (bitwise-xor a b) #xFF))) (define uint8-not (lambda (a) (bitwise-and (bitwise-not a) #xFF))) (define uint8-shl (lambda (a c) (bitwise-and (arithmetic-shift a c) #xFF))) (define uint8-shr (lambda (a c) (bitwise-and (arithmetic-shift a (- 0 c)) #xFF))) (define uint8-chop (lambda (a) (bitwise-and a #xFF))) (define uint32-and (lambda (a b) (bitwise-and a b #xFFFFFFFF))) (define uint32-or (lambda (a b) (bitwise-and (bitwise-ior a b) #xFFFFFFFF))) (define uint32-xor (lambda (a b) (bitwise-and (bitwise-xor a b) #xFFFFFFFF))) (define uint32-not (lambda (a) (bitwise-and (bitwise-not a) #xFFFFFFFF))) (define uint32-shl (lambda (a c) (bitwise-and (arithmetic-shift a c) #xFFFFFFFF))) (define uint32-shr (lambda (a c) (bitwise-and (arithmetic-shift a (- 0 c)) #xFFFFFFFF))) ; Now the tables. This data was converted from the existing C CSS decoders. (define css-table-1 #(#x33 #x73 #x3B #x26 #x63 #x23 #x6B #x76 #x3E #x7E #x36 #x2B #x6E #x2E #x66 #x7B #xD3 #x93 #xDB #x06 #x43 #x03 #x4B #x96 #xDE #x9E #xD6 #x0B #x4E #x0E #x46 #x9B #x57 #x17 #x5F #x82 #xC7 #x87 #xCF #x12 #x5A #x1A #x52 #x8F #xCA #x8A #xC2 #x1F #xD9 #x99 #xD1 #x00 #x49 #x09 #x41 #x90 #xD8 #x98 #xD0 #x01 #x48 #x08 #x40 #x91 #x3D #x7D #x35 #x24 #x6D #x2D #x65 #x74 #x3C #x7C #x34 #x25 #x6C #x2C #x64 #x75 #xDD #x9D #xD5 #x04 #x4D #x0D #x45 #x94 #xDC #x9C #xD4 #x05 #x4C #x0C #x44 #x95 #x59 #x19 #x51 #x80 #xC9 #x89 #xC1 #x10 #x58 #x18 #x50 #x81 #xC8 #x88 #xC0 #x11 #xD7 #x97 #xDF #x02 #x47 #x07 #x4F #x92 #xDA #x9A #xD2 #x0F #x4A #x0A #x42 #x9F #x53 #x13 #x5B #x86 #xC3 #x83 #xCB #x16 #x5E #x1E #x56 #x8B #xCE #x8E #xC6 #x1B #xB3 #xF3 #xBB #xA6 #xE3 #xA3 #xEB #xF6 #xBE #xFE #xB6 #xAB #xEE #xAE #xE6 #xFB #x37 #x77 #x3F #x22 #x67 #x27 #x6F #x72 #x3A #x7A #x32 #x2F #x6A #x2A #x62 #x7F #xB9 #xF9 #xB1 #xA0 #xE9 #xA9 #xE1 #xF0 #xB8 #xF8 #xB0 #xA1 #xE8 #xA8 #xE0 #xF1 #x5D #x1D #x55 #x84 #xCD #x8D #xC5 #x14 #x5C #x1C #x54 #x85 #xCC #x8C #xC4 #x15 #xBD #xFD #xB5 #xA4 #xED #xAD #xE5 #xF4 #xBC #xFC #xB4 #xA5 #xEC #xAC #xE4 #xF5 #x39 #x79 #x31 #x20 #x69 #x29 #x61 #x70 #x38 #x78 #x30 #x21 #x68 #x28 #x60 #x71 #xB7 #xF7 #xBF #xA2 #xE7 #xA7 #xEF #xF2 #xBA #xFA #xB2 #xAF #xEA #xAA #xE2 #xFF)) (define css-lfsr1-bits-0 #(#x00 #x01 #x02 #x03 #x04 #x05 #x06 #x07 #x09 #x08 #x0B #x0A #x0D #x0C #x0F #x0E #x12 #x13 #x10 #x11 #x16 #x17 #x14 #x15 #x1B #x1A #x19 #x18 #x1F #x1E #x1D #x1C #x24 #x25 #x26 #x27 #x20 #x21 #x22 #x23 #x2D #x2C #x2F #x2E #x29 #x28 #x2B #x2A #x36 #x37 #x34 #x35 #x32 #x33 #x30 #x31 #x3F #x3E #x3D #x3C #x3B #x3A #x39 #x38 #x49 #x48 #x4B #x4A #x4D #x4C #x4F #x4E #x40 #x41 #x42 #x43 #x44 #x45 #x46 #x47 #x5B #x5A #x59 #x58 #x5F #x5E #x5D #x5C #x52 #x53 #x50 #x51 #x56 #x57 #x54 #x55 #x6D #x6C #x6F #x6E #x69 #x68 #x6B #x6A #x64 #x65 #x66 #x67 #x60 #x61 #x62 #x63 #x7F #x7E #x7D #x7C #x7B #x7A #x79 #x78 #x76 #x77 #x74 #x75 #x72 #x73 #x70 #x71 #x92 #x93 #x90 #x91 #x96 #x97 #x94 #x95 #x9B #x9A #x99 #x98 #x9F #x9E #x9D #x9C #x80 #x81 #x82 #x83 #x84 #x85 #x86 #x87 #x89 #x88 #x8B #x8A #x8D #x8C #x8F #x8E #xB6 #xB7 #xB4 #xB5 #xB2 #xB3 #xB0 #xB1 #xBF #xBE #xBD #xBC #xBB #xBA #xB9 #xB8 #xA4 #xA5 #xA6 #xA7 #xA0 #xA1 #xA2 #xA3 #xAD #xAC #xAF #xAE #xA9 #xA8 #xAB #xAA #xDB #xDA #xD9 #xD8 #xDF #xDE #xDD #xDC #xD2 #xD3 #xD0 #xD1 #xD6 #xD7 #xD4 #xD5 #xC9 #xC8 #xCB #xCA #xCD #xCC #xCF #xCE #xC0 #xC1 #xC2 #xC3 #xC4 #xC5 #xC6 #xC7 #xFF #xFE #xFD #xFC #xFB #xFA #xF9 #xF8 #xF6 #xF7 #xF4 #xF5 #xF2 #xF3 #xF0 #xF1 #xED #xEC #xEF #xEE #xE9 #xE8 #xEB #xEA #xE4 #xE5 #xE6 #xE7 #xE0 #xE1 #xE2 #xE3)) (define css-lfsr1-bits-1 #(#x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF #x00 #x24 #x49 #x6D #x92 #xB6 #xDB #xFF)) (define css-bit-reverse #(#x00 #x80 #x40 #xC0 #x20 #xA0 #x60 #xE0 #x10 #x90 #x50 #xD0 #x30 #xB0 #x70 #xF0 #x08 #x88 #x48 #xC8 #x28 #xA8 #x68 #xE8 #x18 #x98 #x58 #xD8 #x38 #xB8 #x78 #xF8 #x04 #x84 #x44 #xC4 #x24 #xA4 #x64 #xE4 #x14 #x94 #x54 #xD4 #x34 #xB4 #x74 #xF4 #x0C #x8C #x4C #xCC #x2C #xAC #x6C #xEC #x1C #x9C #x5C #xDC #x3C #xBC #x7C #xFC #x02 #x82 #x42 #xC2 #x22 #xA2 #x62 #xE2 #x12 #x92 #x52 #xD2 #x32 #xB2 #x72 #xF2 #x0A #x8A #x4A #xCA #x2A #xAA #x6A #xEA #x1A #x9A #x5A #xDA #x3A #xBA #x7A #xFA #x06 #x86 #x46 #xC6 #x26 #xA6 #x66 #xE6 #x16 #x96 #x56 #xD6 #x36 #xB6 #x76 #xF6 #x0E #x8E #x4E #xCE #x2E #xAE #x6E #xEE #x1E #x9E #x5E #xDE #x3E #xBE #x7E #xFE #x01 #x81 #x41 #xC1 #x21 #xA1 #x61 #xE1 #x11 #x91 #x51 #xD1 #x31 #xB1 #x71 #xF1 #x09 #x89 #x49 #xC9 #x29 #xA9 #x69 #xE9 #x19 #x99 #x59 #xD9 #x39 #xB9 #x79 #xF9 #x05 #x85 #x45 #xC5 #x25 #xA5 #x65 #xE5 #x15 #x95 #x55 #xD5 #x35 #xB5 #x75 #xF5 #x0D #x8D #x4D #xCD #x2D #xAD #x6D #xED #x1D #x9D #x5D #xDD #x3D #xBD #x7D #xFD #x03 #x83 #x43 #xC3 #x23 #xA3 #x63 #xE3 #x13 #x93 #x53 #xD3 #x33 #xB3 #x73 #xF3 #x0B #x8B #x4B #xCB #x2B #xAB #x6B #xEB #x1B #x9B #x5B #xDB #x3B #xBB #x7B #xFB #x07 #x87 #x47 #xC7 #x27 #xA7 #x67 #xE7 #x17 #x97 #x57 #xD7 #x37 #xB7 #x77 #xF7 #x0F #x8F #x4F #xCF #x2F #xAF #x6F #xEF #x1F #x9F #x5F #xDF #x3F #xBF #x7F #xFF)) ; And now, what we've all been waiting for... (define css-salt (lambda (data key value) (uint8-xor (vector-ref key value) (vector-ref data (+ value #x54))))) (define css-descramble (lambda (data key) (let decoder ((lfsr1-low (bitwise-ior (css-salt data key 0) #x100)) (lfsr1-high (css-salt data key 1)) (lfsr0 (let ((tmp (- (+ (bitwise-ior (uint32-shl (css-salt data key 4) 17) (uint32-shl (css-salt data key 3) 9) (uint32-shl (css-salt data key 2) 1)) 8) (bitwise-and (css-salt data key 2) 7)))) (bitwise-ior (uint32-shl (vector-ref css-bit-reverse (uint8-chop tmp)) 24) (uint32-shl (vector-ref css-bit-reverse (uint8-chop (uint32-shr tmp 8))) 16) (uint32-shl (vector-ref css-bit-reverse (uint8-chop (uint32-shr tmp 16))) 8) (vector-ref css-bit-reverse (uint8-chop (uint32-shr tmp 24)))))) (position #x80) (combined 0) (decoded (make-vector 2048))) (if (< position #x800) (let* ((o-lfsr1 (uint8-xor (vector-ref css-lfsr1-bits-0 lfsr1-high) (vector-ref css-lfsr1-bits-1 lfsr1-low))) (o-lfsr1-r (vector-ref css-bit-reverse o-lfsr1)) (o-lfsr0 (uint32-shr (uint32-xor (uint32-shr (uint32-xor (uint32-shr (uint32-xor (uint32-shr lfsr0 8) lfsr0) 1) lfsr0) 3) lfsr0) 7)) (new-lfsr1-high (uint32-shr lfsr1-low 1)) (new-lfsr1-low (uint32-xor (uint32-shl (bitwise-and lfsr1-low 1) 8) o-lfsr1)) (new-lfsr0 (uint32-or (uint32-shr lfsr0 8) (uint32-shl o-lfsr0 24))) (new-combined (+ combined o-lfsr0 (uint8-not o-lfsr1)))) (vector-set! decoded position (uint8-xor (vector-ref css-table-1 (vector-ref data position)) (uint8-chop new-combined))) (decoder new-lfsr1-low new-lfsr1-high new-lfsr0 (+ position 1) (uint32-shr new-combined 8) decoded)) decoded))))