css.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,697 行 · 第 1/4 页
C
1,697 行
{ p_key[ i ] ^= dvdcss->css.p_bus_key[ 4 - (i % KEY_SIZE) ]; } /* If p_key is all zero then there really wasn't any key present * even though we got to read it without an error. */ if( !( p_key[0] | p_key[1] | p_key[2] | p_key[3] | p_key[4] ) ) { i_ret = 0; } else { PrintKey( dvdcss, "initial disc key ", dvdcss->css.p_disc_key ); DecryptTitleKey( dvdcss->css.p_disc_key, p_key ); PrintKey( dvdcss, "decrypted title key ", p_key ); i_ret = 1; } /* All went well either there wasn't a key or we have it now. */ memcpy( p_title_key, p_key, KEY_SIZE ); PrintKey( dvdcss, "title key is ", p_title_key ); return i_ret; } /* The title key request failed */ print_debug( dvdcss, "resetting drive and cracking title key" ); /* Read an unscrambled sector and reset the drive */ dvdcss->pf_seek( dvdcss, 0 ); dvdcss->pf_read( dvdcss, p_garbage, 1 ); dvdcss->pf_seek( dvdcss, 0 ); _dvdcss_disckey( dvdcss ); /* Fallback */ } /* METHOD is TITLE, we can't use the ioctls or requesting the title key * failed above. For these cases we try to crack the key instead. */ /* For now, the read limit is 9Gb / 2048 = 4718592 sectors. */ i_ret = CrackTitleKey( dvdcss, i_pos, 4718592, p_key ); memcpy( p_title_key, p_key, KEY_SIZE ); PrintKey( dvdcss, "title key is ", p_title_key ); return i_ret;}/***************************************************************************** * _dvdcss_unscramble: does the actual descrambling of data ***************************************************************************** * sec : sector to unscramble * key : title key for this sector *****************************************************************************/int _dvdcss_unscramble( dvd_key_t p_key, uint8_t *p_sec ){ unsigned int i_t1, i_t2, i_t3, i_t4, i_t5, i_t6; uint8_t *p_end = p_sec + DVDCSS_BLOCK_SIZE; /* PES_scrambling_control */ if( !(p_sec[0x14] & 0x30) ) { return 0; } i_t1 = (p_key[0] ^ p_sec[0x54]) | 0x100; i_t2 = p_key[1] ^ p_sec[0x55]; i_t3 = (p_key[2] | (p_key[3] << 8) | (p_key[4] << 16)) ^ (p_sec[0x56] | (p_sec[0x57] << 8) | (p_sec[0x58] << 16)); i_t4 = i_t3 & 7; i_t3 = i_t3 * 2 + 8 - i_t4; p_sec += 0x80; i_t5 = 0; while( p_sec != p_end ) { i_t4 = p_css_tab2[i_t2] ^ p_css_tab3[i_t1]; i_t2 = i_t1>>1; i_t1 = ( ( i_t1 & 1 ) << 8 ) ^ i_t4; i_t4 = p_css_tab5[i_t4]; i_t6 = ((((((( i_t3 >> 3 ) ^ i_t3 ) >> 1 ) ^ i_t3 ) >> 8 ) ^ i_t3 ) >> 5 ) & 0xff; i_t3 = (i_t3 << 8 ) | i_t6; i_t6 = p_css_tab4[i_t6]; i_t5 += i_t6 + i_t4; *p_sec = p_css_tab1[*p_sec] ^ ( i_t5 & 0xff ); p_sec++; i_t5 >>= 8; } return 0;}/* Following functions are local *//***************************************************************************** * GetBusKey : Go through the CSS Authentication process ***************************************************************************** * It simulates the mutual authentication between logical unit and host, * and stops when a session key (called bus key) has been established. * Always do the full auth sequence. Some drives seem to lie and always * respond with ASF=1. For instance the old DVD roms on Compaq Armada says * that ASF=1 from the start and then later fail with a 'read of scrambled * block without authentication' error. *****************************************************************************/static int GetBusKey( dvdcss_t dvdcss ){ uint8_t p_buffer[10]; uint8_t p_challenge[2*KEY_SIZE]; dvd_key_t p_key1; dvd_key_t p_key2; dvd_key_t p_key_check; uint8_t i_variant = 0; int i_ret = -1; int i; print_debug( dvdcss, "requesting AGID" ); i_ret = ioctl_ReportAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); /* We might have to reset hung authentication processes in the drive * by invalidating the corresponding AGID'. As long as we haven't got * an AGID, invalidate one (in sequence) and try again. */ for( i = 0; i_ret == -1 && i < 4 ; ++i ) { print_debug( dvdcss, "ioctl ReportAgid failed, " "invalidating AGID %d", i ); /* This is really _not good_, should be handled by the OS. * Invalidating an AGID could make another process fail somewhere * in its authentication process. */ dvdcss->css.i_agid = i; ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); print_debug( dvdcss, "requesting AGID" ); i_ret = ioctl_ReportAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); } /* Unable to authenticate without AGID */ if( i_ret == -1 ) { print_error( dvdcss, "ioctl ReportAgid failed, fatal" ); return -1; } /* Setup a challenge, any values should work */ for( i = 0 ; i < 10; ++i ) { p_challenge[i] = i; } /* Get challenge from host */ for( i = 0 ; i < 10 ; ++i ) { p_buffer[9-i] = p_challenge[i]; } /* Send challenge to LU */ if( ioctl_SendChallenge( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0 ) { print_error( dvdcss, "ioctl SendChallenge failed" ); ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); return -1; } /* Get key1 from LU */ if( ioctl_ReportKey1( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0) { print_error( dvdcss, "ioctl ReportKey1 failed" ); ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); return -1; } /* Send key1 to host */ for( i = 0 ; i < KEY_SIZE ; i++ ) { p_key1[i] = p_buffer[4-i]; } for( i = 0 ; i < 32 ; ++i ) { CryptKey( 0, i, p_challenge, p_key_check ); if( memcmp( p_key_check, p_key1, KEY_SIZE ) == 0 ) { print_debug( dvdcss, "drive authenticated, using variant %d", i ); i_variant = i; break; } } if( i == 32 ) { print_error( dvdcss, "drive would not authenticate" ); ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); return -1; } /* Get challenge from LU */ if( ioctl_ReportChallenge( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0 ) { print_error( dvdcss, "ioctl ReportKeyChallenge failed" ); ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); return -1; } /* Send challenge to host */ for( i = 0 ; i < 10 ; ++i ) { p_challenge[i] = p_buffer[9-i]; } CryptKey( 1, i_variant, p_challenge, p_key2 ); /* Get key2 from host */ for( i = 0 ; i < KEY_SIZE ; ++i ) { p_buffer[4-i] = p_key2[i]; } /* Send key2 to LU */ if( ioctl_SendKey2( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0 ) { print_error( dvdcss, "ioctl SendKey2 failed" ); ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); return -1; } /* The drive has accepted us as authentic. */ print_debug( dvdcss, "authentication established" ); memcpy( p_challenge, p_key1, KEY_SIZE ); memcpy( p_challenge + KEY_SIZE, p_key2, KEY_SIZE ); CryptKey( 2, i_variant, p_challenge, dvdcss->css.p_bus_key ); return 0;}/***************************************************************************** * PrintKey : debug function that dumps a key value *****************************************************************************/static void PrintKey( dvdcss_t dvdcss, char *prefix, uint8_t const *data ){ print_debug( dvdcss, "%s%02x:%02x:%02x:%02x:%02x", prefix, data[0], data[1], data[2], data[3], data[4] );}/***************************************************************************** * GetASF : Get Authentication success flag ***************************************************************************** * Returns : * -1 on ioctl error, * 0 if the device needs to be authenticated, * 1 either. *****************************************************************************/static int GetASF( dvdcss_t dvdcss ){ int i_asf = 0; if( ioctl_ReportASF( dvdcss->i_fd, NULL, &i_asf ) != 0 ) { /* The ioctl process has failed */ print_error( dvdcss, "GetASF fatal error" ); return -1; } if( i_asf ) { print_debug( dvdcss, "GetASF authenticated, ASF=1" ); } else { print_debug( dvdcss, "GetASF not authenticated, ASF=0" ); } return i_asf;}/***************************************************************************** * CryptKey : shuffles bits and unencrypt keys. ***************************************************************************** * Used during authentication and disc key negociation in GetBusKey. * i_key_type : 0->key1, 1->key2, 2->buskey. * i_variant : between 0 and 31. *****************************************************************************/static void CryptKey( int i_key_type, int i_variant, uint8_t const *p_challenge, uint8_t *p_key ){ /* Permutation table for challenge */ uint8_t pp_perm_challenge[3][10] = { { 1, 3, 0, 7, 5, 2, 9, 6, 4, 8 }, { 6, 1, 9, 3, 8, 5, 7, 4, 0, 2 }, { 4, 0, 3, 5, 7, 2, 8, 6, 1, 9 } }; /* Permutation table for variant table for key2 and buskey */ uint8_t pp_perm_variant[2][32] = { { 0x0a, 0x08, 0x0e, 0x0c, 0x0b, 0x09, 0x0f, 0x0d, 0x1a, 0x18, 0x1e, 0x1c, 0x1b, 0x19, 0x1f, 0x1d, 0x02, 0x00, 0x06, 0x04, 0x03, 0x01, 0x07, 0x05, 0x12, 0x10, 0x16, 0x14, 0x13, 0x11, 0x17, 0x15 }, { 0x12, 0x1a, 0x16, 0x1e, 0x02, 0x0a, 0x06, 0x0e, 0x10, 0x18, 0x14, 0x1c, 0x00, 0x08, 0x04, 0x0c, 0x13, 0x1b, 0x17, 0x1f, 0x03, 0x0b, 0x07, 0x0f, 0x11, 0x19, 0x15, 0x1d, 0x01, 0x09, 0x05, 0x0d } }; uint8_t p_variants[32] = { 0xB7, 0x74, 0x85, 0xD0, 0xCC, 0xDB, 0xCA, 0x73, 0x03, 0xFE, 0x31, 0x03, 0x52, 0xE0, 0xB7, 0x42, 0x63, 0x16, 0xF2, 0x2A, 0x79, 0x52, 0xFF, 0x1B, 0x7A, 0x11, 0xCA, 0x1A, 0x9B, 0x40, 0xAD, 0x01 }; /* The "secret" key */ uint8_t p_secret[5] = { 0x55, 0xD6, 0xC4, 0xC5, 0x28 }; uint8_t p_bits[30], p_scratch[10], p_tmp1[5], p_tmp2[5]; uint8_t i_lfsr0_o; /* 1 bit used */ uint8_t i_lfsr1_o; /* 1 bit used */ uint8_t i_css_variant, i_cse, i_index, i_combined, i_carry; uint8_t i_val = 0; uint32_t i_lfsr0, i_lfsr1; int i_term = 0; int i_bit; int i; for (i = 9; i >= 0; --i) p_scratch[i] = p_challenge[pp_perm_challenge[i_key_type][i]]; i_css_variant = ( i_key_type == 0 ) ? i_variant : pp_perm_variant[i_key_type-1][i_variant]; /* * This encryption engine implements one of 32 variations * one the same theme depending upon the choice in the * variant parameter (0 - 31). * * The algorithm itself manipulates a 40 bit input into * a 40 bit output. * The parameter 'input' is 80 bits. It consists of * the 40 bit input value that is to be encrypted followed * by a 40 bit seed value for the pseudo random number * generators. */ /* Feed the secret into the input values such that * we alter the seed to the LFSR's used above, then * generate the bits to play with. */ for( i = 5 ; --i >= 0 ; ) { p_tmp1[i] = p_scratch[5 + i] ^ p_secret[i] ^ p_crypt_tab2[i]; } /* * We use two LFSR's (seeded from some of the input data bytes) to * generate two streams of pseudo-random bits. These two bit streams * are then combined by simply adding with carry to generate a final * sequence of pseudo-random bits which is stored in the buffer that * 'output' points to the end of - len is the size of this buffer. * * The first LFSR is of degree 25, and has a polynomial of: * x^13 + x^5 + x^4 + x^1 + 1 * * The second LSFR is of degree 17, and has a (primitive) polynomial of: * x^15 + x^1 + 1 * * I don't know if these polynomials are primitive modulo 2, and thus * represent maximal-period LFSR's. * * * Note that we take the output of each LFSR from the new shifted in * bit, not the old shifted out bit. Thus for ease of use the LFSR's * are implemented in bit reversed order. * */ /* In order to ensure that the LFSR works we need to ensure that the * initial values are non-zero. Thus when we initialise them from * the seed, we ensure that a bit is set. */ i_lfsr0 = ( p_tmp1[0] << 17 ) | ( p_tmp1[1] << 9 ) | (( p_tmp1[2] & ~7 ) << 1 ) | 8 | ( p_tmp1[2] & 7 ); i_lfsr1 = ( p_tmp1[3] << 9 ) | 0x100 | p_tmp1[4]; i_index = sizeof(p_bits); i_carry = 0; do { for( i_bit = 0, i_val = 0 ; i_bit < 8 ; ++i_bit ) { i_lfsr0_o = ( ( i_lfsr0 >> 24 ) ^ ( i_lfsr0 >> 21 ) ^ ( i_lfsr0 >> 20 ) ^ ( i_lfsr0 >> 12 ) ) & 1; i_lfsr0 = ( i_lfsr0 << 1 ) | i_lfsr0_o; i_lfsr1_o = ( ( i_lfsr1 >> 16 ) ^ ( i_lfsr1 >> 2 ) ) & 1; i_lfsr1 = ( i_lfsr1 << 1 ) | i_lfsr1_o; i_combined = !i_lfsr1_o + i_carry + !i_lfsr0_o; /* taking bit 1 */ i_carry = ( i_combined >> 1 ) & 1; i_val |= ( i_combined & 1 ) << i_bit; } p_bits[--i_index] = i_val; } while( i_index > 0 ); /* This term is used throughout the following to * select one of 32 different variations on the * algorithm. */ i_cse = p_variants[i_css_variant] ^ p_crypt_tab2[i_css_variant]; /* Now the actual blocks doing the encryption. Each * of these works on 40 bits at a time and are quite * similar. */ i_index = 0; for( i = 5, i_term = 0 ; --i >= 0 ; i_term = p_scratch[i] ) { i_index = p_bits[25 + i] ^ p_scratch[i];
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?