⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 css.c

📁 python的多媒体包,可以实现很多漂亮的功能哦
💻 C
📖 第 1 页 / 共 4 页
字号:

    if( GetBusKey( dvdcss ) < 0 )
    {
        return -1;
    }

    /* Get encrypted disc key */
    if( ioctl_ReadDiscKey( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0 )
    {
        _dvdcss_error( dvdcss, "ioctl ReadDiscKey failed" );
        return -1;
    }

    /* This should have invaidated the AGID and got us ASF=1. */
    if( GetASF( dvdcss ) != 1 )
    {
        /* Region mismatch (or region not set) is the most likely source. */
        _dvdcss_error( dvdcss,
                       "ASF not 1 after reading disc key (region mismatch?)" );
        ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid );
        return -1;
    }

    /* Decrypt disc key using bus key */
    for( i = 0 ; i < DVD_DISCKEY_SIZE ; i++ )
    {
        p_buffer[ i ] ^= dvdcss->css.p_bus_key[ 4 - (i % KEY_SIZE) ];
    }

    switch( dvdcss->i_method )
    {
        case DVDCSS_METHOD_KEY:

            /* Decrypt disc key with player key. */
            _dvdcss_debug( dvdcss, "decrypting disc key with player keys" );
            if( ! DecryptDiscKey( p_buffer, p_disc_key ) )
            {
                PrintKey( dvdcss, "decrypted disc key is ", p_disc_key );
                break;
            }
            _dvdcss_debug( dvdcss, "failed to decrypt the disc key, "
                                   "faulty drive/kernel? "
                                   "cracking title keys instead" );

            /* Fallback, but not to DISC as the disc key might be faulty */
            dvdcss->i_method = DVDCSS_METHOD_TITLE;
            break;

        case DVDCSS_METHOD_DISC:

            /* Crack Disc key to be able to use it */
            _dvdcss_debug( dvdcss, "cracking disc key from key hash ..."
                                   " this will take some time" );
            memcpy( p_disc_key, p_buffer, KEY_SIZE );
            if( ! CrackDiscKey( dvdcss, p_disc_key ) )
            {
                PrintKey( dvdcss, "cracked disc key is ", p_disc_key );
                break;
            }
            _dvdcss_debug( dvdcss, "failed to crack the disc key" );
            memset( p_disc_key, 0, KEY_SIZE );
            dvdcss->i_method = DVDCSS_METHOD_TITLE;
            break;

        default:

            _dvdcss_debug( dvdcss, "disc key needs not be decrypted" );
            memset( p_disc_key, 0, KEY_SIZE );
            break;
    }

    memcpy( dvdcss->css.p_disc_key, p_disc_key, KEY_SIZE );

    return 0;
}


/*****************************************************************************
 * _dvdcss_titlekey: get title key.
 *****************************************************************************/
int _dvdcss_titlekey( dvdcss_t dvdcss, int i_pos, dvd_key_t p_title_key )
{
    static uint8_t p_garbage[ DVDCSS_BLOCK_SIZE ];  /* we never read it back */
    uint8_t p_key[ KEY_SIZE ];
    int i, i_ret = 0;

    if( dvdcss->b_ioctls && ( dvdcss->i_method == DVDCSS_METHOD_KEY ||
                              dvdcss->i_method == DVDCSS_METHOD_DISC ) )
    {
        /* We have a decrypted Disc key and the ioctls are available,
         * read the title key and decrypt it.
         */

        _dvdcss_debug( dvdcss, "getting title key the classic way" );

        /* We need to authenticate again every time to get a new session key */
        if( GetBusKey( dvdcss ) < 0 )
        {
            return -1;
        }

        /* Get encrypted title key */
        if( ioctl_ReadTitleKey( dvdcss->i_fd, &dvdcss->css.i_agid,
                                i_pos, p_key ) < 0 )
        {
            _dvdcss_debug( dvdcss,
                           "ioctl ReadTitleKey failed (region mismatch?)" );
            i_ret = -1;
        }

        /* Test ASF, it will be reset to 0 if we got a Region error */
        switch( GetASF( dvdcss ) )
        {
            case -1:
                /* An error getting the ASF status, something must be wrong. */
                _dvdcss_debug( dvdcss, "lost ASF requesting title key" );
                ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid );
                i_ret = -1;
                break;

            case 0:
                /* This might either be a title that has no key,
                 * or we encountered a region error. */
                _dvdcss_debug( dvdcss, "lost ASF requesting title key" );
                break;

            case 1:
                /* Drive status is ok. */
                /* If the title key request failed, but we did not loose ASF,
                 * we might stil have the AGID.  Other code assume that we
                 * will not after this so invalidate it(?). */
                if( i_ret < 0 )
                {
                    ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid );
                }
                break;
        }

        if( !( i_ret < 0 ) )
        {
            /* Decrypt title key using the bus key */
            for( i = 0 ; i < KEY_SIZE ; i++ )
            {
                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
            {
                DecryptTitleKey( dvdcss->css.p_disc_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 */
        _dvdcss_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)
    {
        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 */

/*****************************************************************************
 * 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 */
        _dvdcss_error( dvdcss, "GetASF fatal error" );
        return -1;
    }

    if( i_asf )
    {
        _dvdcss_debug( dvdcss, "GetASF authenticated, ASF=1" );
    }
    else
    {
        _dvdcss_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];
        i_index = p_crypt_tab1[i_index] ^ ~p_crypt_tab2[i_index] ^ i_cse;

        p_tmp1[i] = p_crypt_tab2[i_index] ^ p_crypt_tab3[i_index] ^ i_term;
    }
    p_tmp1[4] ^= p_tmp1[0];

    for( i = 5, i_term = 0 ; --i >= 0 ; i_term = p_tmp1[i] )
    {
        i_index = p_bits[20 + i] ^ p_tmp1[i];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -