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 + -
显示快捷键?