Ignore:
Timestamp:
Oct 6, 2013, 10:26:28 AM (6 years ago)
Author:
Gorgone Impertinence
Message:

revert 8951 & 8952
sorry for this !

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/reader-videoguard2.c

    r8951 r8960  
    88static void dimeno_PostProcess_Decrypt(struct s_reader *reader, unsigned char *rxbuff, unsigned char *cw)
    99{
    10     struct videoguard_data *csystem_data = reader->csystem_data;
    11     unsigned char tag, len, len2;
    12     bool valid_0x55 = 0;
    13     unsigned char *body;
    14     unsigned char buffer[0x10];
    15     int32_t a = 0x13;
    16     len2 = rxbuff[4];
    17     while (a < len2 + 5 - 9) //  +5 for 5 ins bytes, -9 (body=8 len=1) to prevent memcpy(buffer+8,body,8) from reading past rxbuff
    18     {
    19         tag = rxbuff[a];
    20         len = rxbuff[a + 1];
    21         body = rxbuff + a + 2;
    22         switch (tag)
    23         {
    24         case 0x55:
    25         {
    26             if (body[0] == 0x84)    //Tag 0x56 has valid data...
    27             {
    28                 valid_0x55 = 1;
    29             }
    30         } break;
    31         case 0x56:
    32         {
    33             memcpy(buffer + 8, body, 8);
    34         } break;
    35         }
    36         a += len + 2;
    37     }
    38     if (valid_0x55)
    39     {
    40         memcpy(buffer, rxbuff + 5, 8);
    41         AES_decrypt(buffer, buffer, &(csystem_data->astrokey));
    42         memcpy(cw + 0, buffer, 8);  // copy calculated CW in right place
    43     }
     10    struct videoguard_data *csystem_data = reader->csystem_data;
     11    unsigned char tag, len, len2;
     12    bool valid_0x55 = 0;
     13    unsigned char *body;
     14    unsigned char buffer[0x10];
     15    int32_t a = 0x13;
     16    len2 = rxbuff[4];
     17    while(a < len2 + 5 - 9)  //  +5 for 5 ins bytes, -9 (body=8 len=1) to prevent memcpy(buffer+8,body,8) from reading past rxbuff
     18    {
     19        tag = rxbuff[a];
     20        len = rxbuff[a + 1];
     21        body = rxbuff + a + 2;
     22        switch(tag)
     23        {
     24        case 0x55:
     25        {
     26            if(body[0] == 0x84)     //Tag 0x56 has valid data...
     27            {
     28                valid_0x55 = 1;
     29            }
     30        }
     31        break;
     32        case 0x56:
     33        {
     34            memcpy(buffer + 8, body, 8);
     35        }
     36        break;
     37        }
     38        a += len + 2;
     39    }
     40    if(valid_0x55)
     41    {
     42        memcpy(buffer, rxbuff + 5, 8);
     43        AES_decrypt(buffer, buffer, &(csystem_data->astrokey));
     44        memcpy(cw + 0, buffer, 8);  // copy calculated CW in right place
     45    }
    4446}
    4547
    4648static void do_post_dw_hash(struct s_reader *reader, unsigned char *cw, const unsigned char *ecm_header_data)
    4749{
    48     int32_t i, ecmi, ecm_header_count;
    49     unsigned char buffer[0x85]; //original 0x80 but with 0x7D mask applied +8 bytes cw it was still to small
    50     unsigned char md5tmp[MD5_DIGEST_LENGTH];
    51     static const uint16_t Hash3[] = {0x0123, 0x4567, 0x89AB, 0xCDEF, 0xF861, 0xCB52};
    52     static const unsigned char Hash4[] = {0x0B, 0x04, 0x07, 0x08, 0x05, 0x09, 0x0B, 0x0A, 0x07, 0x02, 0x0A, 0x05, 0x04, 0x08, 0x0D, 0x0F};
    53     static const uint16_t NdTabB001[0x15][0x20] =
    54     {
    55         {
    56             0xEAF1, 0x0237, 0x29D0, 0xBAD2, 0xE9D3, 0x8BAE, 0x2D6D, 0xCD1B,
    57             0x538D, 0xDE6B, 0xA634, 0xF81A, 0x18B5, 0x5087, 0x14EA, 0x672E,
    58             0xF0FC, 0x055E, 0x62E5, 0xB78F, 0x5D09, 0x0003, 0xE4E8, 0x2DCE,
    59             0x6BE0, 0xAC4E, 0xF485, 0x6967, 0xF28C, 0x97A0, 0x01EF, 0x0100
    60         },
    61         {
    62             0xC539, 0xF5B9, 0x9099, 0x013A, 0xD4B9, 0x6AB5, 0xEA67, 0x7EB4,
    63             0x6C30, 0x4BF0, 0xB810, 0xB0B5, 0xB76D, 0xA751, 0x1AE7, 0x14CA,
    64             0x4F4F, 0x1586, 0x2608, 0x10B1, 0xE7E1, 0x48BE, 0x7DDD, 0x5ECB,
    65             0xCFBF, 0x323B, 0x8B31, 0xB131, 0x0F1A, 0x664B, 0x0140, 0x0100
    66         },
    67         {
    68             0x3C7D, 0xBDC4, 0xFEC7, 0x26A6, 0xB0A0, 0x6E55, 0xF710, 0xF9BF,
    69             0x0023, 0xE81F, 0x41CA, 0xBE32, 0xB461, 0xE92D, 0xF1AF, 0x409F,
    70             0xFC85, 0xFE5B, 0x7FCE, 0x17F5, 0x01AB, 0x4A46, 0xEB05, 0xA251,
    71             0xDC6F, 0xF0C0, 0x10F0, 0x1D51, 0xEFAA, 0xE9BF, 0x0100, 0x0100
    72         },
    73         {
    74             0x1819, 0x0CAA, 0x9067, 0x607A, 0x7576, 0x1CBC, 0xE51D, 0xBF77,
    75             0x7EC6, 0x839E, 0xB695, 0xF096, 0xDC10, 0xCB69, 0x4654, 0x8E68,
    76             0xD62D, 0x4F1A, 0x4227, 0x92AC, 0x9064, 0x6BD1, 0x1E75, 0x2747,
    77             0x00DA, 0xA6A6, 0x6CF1, 0xD151, 0xBE56, 0x3E33, 0x0128, 0x0100
    78         },
    79         {
    80             0x4091, 0x09ED, 0xD494, 0x6054, 0x1869, 0x71D5, 0xB572, 0x7BF1,
    81             0xE925, 0xEE2D, 0xEEDE, 0xA13C, 0x6613, 0x9BAB, 0x122D, 0x7AE4,
    82             0x5268, 0xE6C9, 0x50CB, 0x79A1, 0xF212, 0xA062, 0x6B48, 0x70B3,
    83             0xF6B0, 0x06D5, 0xF8AB, 0xECF5, 0x6255, 0xEDD8, 0x79D2, 0x290A
    84         },
    85         {
    86             0xD3CF, 0x014E, 0xACB3, 0x8F6B, 0x0F2C, 0xA5D8, 0xE8E0, 0x863D,
    87             0x80D5, 0x5705, 0x658A, 0x8BC2, 0xEE46, 0xD3AE, 0x0199, 0x0100,
    88             0x4A35, 0xABE4, 0xF976, 0x935A, 0xA8A5, 0xBAE9, 0x24D0, 0x71AA,
    89             0xB3FE, 0x095E, 0xAB06, 0x4CD5, 0x2F0D, 0x1ACB, 0x59F3, 0x4C50
    90         },
    91         {
    92             0xFD27, 0x0F8E, 0x191A, 0xEEE7, 0x2F49, 0x3A05, 0x3267, 0x4F88,
    93             0x38AE, 0xFCE9, 0x9476, 0x18C6, 0xF961, 0x4EF0, 0x39D0, 0x42E6,
    94             0xB747, 0xE625, 0xB68E, 0x5100, 0xF92A, 0x86FE, 0xE79B, 0xEE91,
    95             0x21D5, 0x4C3C, 0x683D, 0x5AD1, 0x1B49, 0xF407, 0x0194, 0x0100
    96         },
    97         {
    98             0x4BF9, 0xDC0D, 0x9478, 0x5174, 0xCB4A, 0x8A89, 0x4D6A, 0xFED8,
    99             0xF123, 0xA8CD, 0xEEE7, 0xA6D1, 0xB763, 0xF5E2, 0xE085, 0x01EF,
    100             0xE466, 0x9FA3, 0x2F68, 0x2190, 0x423F, 0x287F, 0x7F3F, 0x09F6,
    101             0x2111, 0xA963, 0xD0BB, 0x674A, 0xBA72, 0x45F9, 0xF186, 0xB8F5
    102         },
    103         {
    104             0x0010, 0xD1B9, 0xB164, 0x9E87, 0x1F49, 0x6950, 0x2DBF, 0x38D3,
    105             0x2EB0, 0x3E8E, 0x91E6, 0xF688, 0x7E41, 0x566E, 0x01B0, 0x0100,
    106             0x24A1, 0x73D8, 0xA0C3, 0xF71B, 0xA0A5, 0x2A06, 0xBA46, 0xFEC3,
    107             0xDD4C, 0x52CC, 0xF9BC, 0x3B7E, 0x3812, 0x0666, 0xB74B, 0x40F8
    108         },
    109         {
    110             0x28F2, 0x7C81, 0xFC92, 0x6FBD, 0x53D6, 0x72A3, 0xBBDF, 0xB6FC,
    111             0x9CE5, 0x2331, 0xD4F6, 0xC5BB, 0xE8BB, 0x6676, 0x02D9, 0x2F0E,
    112             0xD009, 0xD136, 0xCD09, 0x7551, 0x1826, 0x9D9B, 0x63EA, 0xFC63,
    113             0x68CD, 0x3672, 0xCB95, 0xD28E, 0xF1CD, 0x20CA, 0x014C, 0x0100
    114         },
    115         {
    116             0xE539, 0x55B7, 0x989D, 0x21C4, 0x463A, 0xE68F, 0xF8B5, 0xE5C5,
    117             0x662B, 0x35BF, 0x3C50, 0x0131, 0xF4BF, 0x38B2, 0x41BC, 0xB829,
    118             0x02B7, 0x6B8F, 0xA25C, 0xAFD2, 0xD84A, 0x2243, 0x53EB, 0xC6C9,
    119             0x2E14, 0x181F, 0x8F96, 0xDF0E, 0x0D4C, 0x30F6, 0xFFE1, 0x9DDA
    120         },
    121         {
    122             0x30B6, 0x777E, 0xDA3D, 0xAF77, 0x205E, 0xC90B, 0x856B, 0xB451,
    123             0x3BCC, 0x76C2, 0x8ACF, 0xDCB1, 0xA5E5, 0xDD64, 0x0197, 0x0100,
    124             0xE751, 0xB661, 0x0404, 0xDB4A, 0xE9DD, 0xA400, 0xAF26, 0x3F5E,
    125             0x904B, 0xA924, 0x09E0, 0xE72B, 0x825B, 0x2C50, 0x6FD0, 0x0D52
    126         },
    127         {
    128             0x2730, 0xC2BA, 0x9E44, 0x5815, 0xFC47, 0xB21D, 0x67B8, 0xF8B9,
    129             0x047D, 0xB0AF, 0x9F14, 0x741B, 0x4668, 0xBE54, 0xDE16, 0xDB14,
    130             0x7CB7, 0xF2B8, 0x0683, 0x762C, 0x09A0, 0x9507, 0x7F92, 0x022C,
    131             0xBA6A, 0x7D52, 0x0AF4, 0x1BC3, 0xB46A, 0xC4FD, 0x01C2, 0x0100
    132         },
    133         {
    134             0x7611, 0x66F3, 0xEE87, 0xEDD3, 0xC559, 0xEFD4, 0xDC59, 0xF86B,
    135             0x6D1C, 0x1C85, 0x9BB1, 0x3373, 0x763F, 0x4EBE, 0x1BF3, 0x99B5,
    136             0xD721, 0x978F, 0xCF5C, 0xAC51, 0x0984, 0x7462, 0x8F0C, 0x2817,
    137             0x4AD9, 0xFD41, 0x6678, 0x7C85, 0xD330, 0xC9F8, 0x1D9A, 0xC622
    138         },
    139         {
    140             0x5AE4, 0xE16A, 0x60F6, 0xFD45, 0x668C, 0x29D6, 0x0285, 0x6B92,
    141             0x92C2, 0x21DE, 0x45E0, 0xEF3D, 0x8B0D, 0x02CD, 0x0198, 0x0100,
    142             0x9E6D, 0x4D38, 0xDEF9, 0xE6F2, 0xF72E, 0xB313, 0x14F2, 0x390A,
    143             0x2D67, 0xC71E, 0xCB69, 0x7F66, 0xD3CF, 0x7F8A, 0x81D9, 0x9DDE
    144         },
    145         {
    146             0x85E3, 0x8F29, 0x36EB, 0xC968, 0x3696, 0x59F6, 0x7832, 0xA78B,
    147             0xA1D8, 0xF5CF, 0xAB64, 0x646D, 0x7A2A, 0xBAF8, 0xAA87, 0x41C7,
    148             0x5120, 0xDE78, 0x738D, 0xDC1A, 0x268D, 0x5DF8, 0xED69, 0x1C8A,
    149             0xBC85, 0x3DCD, 0xAE30, 0x0F8D, 0xEC89, 0x3ABD, 0x0166, 0x0100
    150         },
    151         {
    152             0xB8BD, 0x643B, 0x748E, 0xBD63, 0xEC6F, 0xE23A, 0x9493, 0xDD76,
    153             0x0A62, 0x774F, 0xCD68, 0xA67A, 0x9A23, 0xC8A8, 0xBDE5, 0x9D1B,
    154             0x2B86, 0x8B36, 0x5428, 0x1DFB, 0xCD1D, 0x0713, 0x29C2, 0x8E8E,
    155             0x5207, 0xA13F, 0x6005, 0x4F5E, 0x52E0, 0xE7C8, 0x6D1C, 0x3E34
    156         },
    157         {
    158             0x581D, 0x2BFA, 0x5E1D, 0xA891, 0x1069, 0x1DA4, 0x39A0, 0xBE45,
    159             0x5B9A, 0x7333, 0x6F3E, 0x8637, 0xA550, 0xC9E9, 0x5C6C, 0x42BA,
    160             0xA712, 0xC3EA, 0x3808, 0x0910, 0xAA4D, 0x5B25, 0xABCD, 0xE680,
    161             0x96AD, 0x2CEC, 0x8EBB, 0xA47D, 0x1690, 0xE8FB, 0x01C8, 0x0100
    162         },
    163         {
    164             0x73B9, 0x82BC, 0x9EBC, 0xB130, 0x0DA5, 0x8617, 0x9F7B, 0x9766,
    165             0x205D, 0x752D, 0xB05C, 0x2A17, 0xA75C, 0x18EF, 0x8339, 0xFD34,
    166             0x8DA2, 0x7970, 0xD0B4, 0x70F1, 0x3765, 0x7380, 0x7CAF, 0x570E,
    167             0x6440, 0xBC44, 0x0743, 0x2D02, 0x0419, 0xA240, 0x2113, 0x1AD4
    168         },
    169         {
    170             0x1EB5, 0xBBFF, 0x39B1, 0x3209, 0x705F, 0x15F4, 0xD7AD, 0x340B,
    171             0xC2A6, 0x25CA, 0xF412, 0x9570, 0x0F4F, 0xE4D5, 0x1614, 0xE464,
    172             0x911A, 0x0F0E, 0x07DA, 0xA929, 0x2379, 0xD988, 0x0AA6, 0x3B57,
    173             0xBF63, 0x71FB, 0x72D5, 0x26CE, 0xB0AF, 0xCF45, 0x011B, 0x0100
    174         },
    175         {
    176             0x9999, 0x98FE, 0xA108, 0x6588, 0xF90B, 0x4554, 0xFF38, 0x4642,
    177             0x8F5F, 0x6CC3, 0x4E8E, 0xFF7E, 0x64C2, 0x50CA, 0x0E7F, 0xAD7D,
    178             0x6AAB, 0x33C1, 0xE1F4, 0x6165, 0x7894, 0x83B9, 0x0A0C, 0x38AF,
    179             0x5803, 0x18C0, 0xFA36, 0x592C, 0x4548, 0xABB8, 0x1527, 0xAEE9
    180         }
    181     };
    182 
    183 
    184     //ecm_header_data = 01 03 b0 01 01
    185     if (!cw_is_valid(cw))         //if cw is all zero, keep it that way
    186     {
    187         return;
    188     }
    189     ecm_header_count = ecm_header_data[0];
    190     for (i = 0, ecmi = 1; i < ecm_header_count; i++)
    191     {
    192         if (ecm_header_data[ecmi + 1] != 0xb0)
    193         {
    194             ecmi += ecm_header_data[ecmi] + 1;
    195         }
    196         else
    197         {
    198             switch (ecm_header_data[ecmi + 2])
    199             {
    200             //b0 01
    201             case 1:
    202             {
    203                 uint16_t hk[8], r, j, m = 0;
    204                 for (r = 0; r < 6; r++)
    205                     hk[2 + r] = Hash3[r];
    206                 for (r = 0; r < 2; r++)
    207                 {
    208                     for (j = 0; j < 0x48; j += 2)
    209                     {
    210                         if (r)
    211                         {
    212                             hk[0] = ((hk[3] & hk[5]) | ((~hk[5]) & hk[4]));
    213                         }
    214                         else
    215                         {
    216                             hk[0] = ((hk[3] & hk[4]) | ((~hk[3]) & hk[5]));
    217                         }
    218                         if (j < 8)
    219                         {
    220                             hk[0] = (hk[0] + ((cw[j + 1] << 8) | cw[j]));
    221                         }
    222                         if (j == 8)
    223                         {
    224                             hk[0] = (hk[0] + 0x80);
    225                         }
    226                         hk[0] = (hk[0] + hk[2] + (0xFF & NdTabB001[ecm_header_data[ecmi + 3]][m >> 1] >> ((m & 1) << 3)));
    227                         hk[1] = hk[2];
    228                         hk[2] = hk[3];
    229                         hk[3] = hk[4];
    230                         hk[4] = hk[5];
    231                         hk[5] = hk[6];
    232                         hk[6] = hk[7];
    233                         hk[7] = hk[2] + (((hk[0] << Hash4[m & 0xF]) | (hk[0] >> (0x10 - Hash4[m & 0xF]))));
    234                         m = (m + 1) & 0x3F;
    235                     }
    236                 }
    237                 for (r = 0; r < 6; r++)
    238                 {
    239                     hk[2 + r] += Hash3[r];
    240                 }
    241                 for (r = 0; r < 7; r++)
    242                 {
    243                     cw[r] = hk[2 + (r >> 1)] >> ((r & 1) << 3);
    244                 }
    245                 cw[3] = (cw[0] + cw[1] + cw[2]) & 0xFF;
    246                 cw[7] = (cw[4] + cw[5] + cw[6]) & 0xFF;
    247                 rdr_ddump_mask(reader, D_READER, cw, 8, "Postprocessed Case 1 DW:");
    248                 break;
    249             }
    250             case 3:
    251             {
    252                 memset(buffer, 0, sizeof(buffer));
    253                 memcpy(buffer, cw, 8);
    254                 memcpy(buffer + 8, &ecm_header_data[ecmi + 3], ecm_header_data[ecmi] & 0x7D);
    255                 MD5(buffer, 8 + (ecm_header_data[ecmi] & 0x7D), md5tmp);
    256                 memcpy(cw, md5tmp, 8);
    257                 rdr_ddump_mask(reader, D_READER, cw, 8, "Postprocessed Case 3 DW:");
    258                 break;
    259             }
    260             case 2:
    261             {
    262                 /* Method 2 left out */
    263                 //memcpy(DW_OUTPUT, DW_INPUT, 8);
    264                 break;
    265             }
    266             }
    267         }
    268     }
     50    int32_t i, ecmi, ecm_header_count;
     51    unsigned char buffer[0x85]; //original 0x80 but with 0x7D mask applied +8 bytes cw it was still to small
     52    unsigned char md5tmp[MD5_DIGEST_LENGTH];
     53    static const uint16_t Hash3[] = {0x0123, 0x4567, 0x89AB, 0xCDEF, 0xF861, 0xCB52};
     54    static const unsigned char Hash4[] = {0x0B, 0x04, 0x07, 0x08, 0x05, 0x09, 0x0B, 0x0A, 0x07, 0x02, 0x0A, 0x05, 0x04, 0x08, 0x0D, 0x0F};
     55    static const uint16_t NdTabB001[0x15][0x20] =
     56    {
     57        {
     58            0xEAF1, 0x0237, 0x29D0, 0xBAD2, 0xE9D3, 0x8BAE, 0x2D6D, 0xCD1B,
     59            0x538D, 0xDE6B, 0xA634, 0xF81A, 0x18B5, 0x5087, 0x14EA, 0x672E,
     60            0xF0FC, 0x055E, 0x62E5, 0xB78F, 0x5D09, 0x0003, 0xE4E8, 0x2DCE,
     61            0x6BE0, 0xAC4E, 0xF485, 0x6967, 0xF28C, 0x97A0, 0x01EF, 0x0100
     62        },
     63        {
     64            0xC539, 0xF5B9, 0x9099, 0x013A, 0xD4B9, 0x6AB5, 0xEA67, 0x7EB4,
     65            0x6C30, 0x4BF0, 0xB810, 0xB0B5, 0xB76D, 0xA751, 0x1AE7, 0x14CA,
     66            0x4F4F, 0x1586, 0x2608, 0x10B1, 0xE7E1, 0x48BE, 0x7DDD, 0x5ECB,
     67            0xCFBF, 0x323B, 0x8B31, 0xB131, 0x0F1A, 0x664B, 0x0140, 0x0100
     68        },
     69        {
     70            0x3C7D, 0xBDC4, 0xFEC7, 0x26A6, 0xB0A0, 0x6E55, 0xF710, 0xF9BF,
     71            0x0023, 0xE81F, 0x41CA, 0xBE32, 0xB461, 0xE92D, 0xF1AF, 0x409F,
     72            0xFC85, 0xFE5B, 0x7FCE, 0x17F5, 0x01AB, 0x4A46, 0xEB05, 0xA251,
     73            0xDC6F, 0xF0C0, 0x10F0, 0x1D51, 0xEFAA, 0xE9BF, 0x0100, 0x0100
     74        },
     75        {
     76            0x1819, 0x0CAA, 0x9067, 0x607A, 0x7576, 0x1CBC, 0xE51D, 0xBF77,
     77            0x7EC6, 0x839E, 0xB695, 0xF096, 0xDC10, 0xCB69, 0x4654, 0x8E68,
     78            0xD62D, 0x4F1A, 0x4227, 0x92AC, 0x9064, 0x6BD1, 0x1E75, 0x2747,
     79            0x00DA, 0xA6A6, 0x6CF1, 0xD151, 0xBE56, 0x3E33, 0x0128, 0x0100
     80        },
     81        {
     82            0x4091, 0x09ED, 0xD494, 0x6054, 0x1869, 0x71D5, 0xB572, 0x7BF1,
     83            0xE925, 0xEE2D, 0xEEDE, 0xA13C, 0x6613, 0x9BAB, 0x122D, 0x7AE4,
     84            0x5268, 0xE6C9, 0x50CB, 0x79A1, 0xF212, 0xA062, 0x6B48, 0x70B3,
     85            0xF6B0, 0x06D5, 0xF8AB, 0xECF5, 0x6255, 0xEDD8, 0x79D2, 0x290A
     86        },
     87        {
     88            0xD3CF, 0x014E, 0xACB3, 0x8F6B, 0x0F2C, 0xA5D8, 0xE8E0, 0x863D,
     89            0x80D5, 0x5705, 0x658A, 0x8BC2, 0xEE46, 0xD3AE, 0x0199, 0x0100,
     90            0x4A35, 0xABE4, 0xF976, 0x935A, 0xA8A5, 0xBAE9, 0x24D0, 0x71AA,
     91            0xB3FE, 0x095E, 0xAB06, 0x4CD5, 0x2F0D, 0x1ACB, 0x59F3, 0x4C50
     92        },
     93        {
     94            0xFD27, 0x0F8E, 0x191A, 0xEEE7, 0x2F49, 0x3A05, 0x3267, 0x4F88,
     95            0x38AE, 0xFCE9, 0x9476, 0x18C6, 0xF961, 0x4EF0, 0x39D0, 0x42E6,
     96            0xB747, 0xE625, 0xB68E, 0x5100, 0xF92A, 0x86FE, 0xE79B, 0xEE91,
     97            0x21D5, 0x4C3C, 0x683D, 0x5AD1, 0x1B49, 0xF407, 0x0194, 0x0100
     98        },
     99        {
     100            0x4BF9, 0xDC0D, 0x9478, 0x5174, 0xCB4A, 0x8A89, 0x4D6A, 0xFED8,
     101            0xF123, 0xA8CD, 0xEEE7, 0xA6D1, 0xB763, 0xF5E2, 0xE085, 0x01EF,
     102            0xE466, 0x9FA3, 0x2F68, 0x2190, 0x423F, 0x287F, 0x7F3F, 0x09F6,
     103            0x2111, 0xA963, 0xD0BB, 0x674A, 0xBA72, 0x45F9, 0xF186, 0xB8F5
     104        },
     105        {
     106            0x0010, 0xD1B9, 0xB164, 0x9E87, 0x1F49, 0x6950, 0x2DBF, 0x38D3,
     107            0x2EB0, 0x3E8E, 0x91E6, 0xF688, 0x7E41, 0x566E, 0x01B0, 0x0100,
     108            0x24A1, 0x73D8, 0xA0C3, 0xF71B, 0xA0A5, 0x2A06, 0xBA46, 0xFEC3,
     109            0xDD4C, 0x52CC, 0xF9BC, 0x3B7E, 0x3812, 0x0666, 0xB74B, 0x40F8
     110        },
     111        {
     112            0x28F2, 0x7C81, 0xFC92, 0x6FBD, 0x53D6, 0x72A3, 0xBBDF, 0xB6FC,
     113            0x9CE5, 0x2331, 0xD4F6, 0xC5BB, 0xE8BB, 0x6676, 0x02D9, 0x2F0E,
     114            0xD009, 0xD136, 0xCD09, 0x7551, 0x1826, 0x9D9B, 0x63EA, 0xFC63,
     115            0x68CD, 0x3672, 0xCB95, 0xD28E, 0xF1CD, 0x20CA, 0x014C, 0x0100
     116        },
     117        {
     118            0xE539, 0x55B7, 0x989D, 0x21C4, 0x463A, 0xE68F, 0xF8B5, 0xE5C5,
     119            0x662B, 0x35BF, 0x3C50, 0x0131, 0xF4BF, 0x38B2, 0x41BC, 0xB829,
     120            0x02B7, 0x6B8F, 0xA25C, 0xAFD2, 0xD84A, 0x2243, 0x53EB, 0xC6C9,
     121            0x2E14, 0x181F, 0x8F96, 0xDF0E, 0x0D4C, 0x30F6, 0xFFE1, 0x9DDA
     122        },
     123        {
     124            0x30B6, 0x777E, 0xDA3D, 0xAF77, 0x205E, 0xC90B, 0x856B, 0xB451,
     125            0x3BCC, 0x76C2, 0x8ACF, 0xDCB1, 0xA5E5, 0xDD64, 0x0197, 0x0100,
     126            0xE751, 0xB661, 0x0404, 0xDB4A, 0xE9DD, 0xA400, 0xAF26, 0x3F5E,
     127            0x904B, 0xA924, 0x09E0, 0xE72B, 0x825B, 0x2C50, 0x6FD0, 0x0D52
     128        },
     129        {
     130            0x2730, 0xC2BA, 0x9E44, 0x5815, 0xFC47, 0xB21D, 0x67B8, 0xF8B9,
     131            0x047D, 0xB0AF, 0x9F14, 0x741B, 0x4668, 0xBE54, 0xDE16, 0xDB14,
     132            0x7CB7, 0xF2B8, 0x0683, 0x762C, 0x09A0, 0x9507, 0x7F92, 0x022C,
     133            0xBA6A, 0x7D52, 0x0AF4, 0x1BC3, 0xB46A, 0xC4FD, 0x01C2, 0x0100
     134        },
     135        {
     136            0x7611, 0x66F3, 0xEE87, 0xEDD3, 0xC559, 0xEFD4, 0xDC59, 0xF86B,
     137            0x6D1C, 0x1C85, 0x9BB1, 0x3373, 0x763F, 0x4EBE, 0x1BF3, 0x99B5,
     138            0xD721, 0x978F, 0xCF5C, 0xAC51, 0x0984, 0x7462, 0x8F0C, 0x2817,
     139            0x4AD9, 0xFD41, 0x6678, 0x7C85, 0xD330, 0xC9F8, 0x1D9A, 0xC622
     140        },
     141        {
     142            0x5AE4, 0xE16A, 0x60F6, 0xFD45, 0x668C, 0x29D6, 0x0285, 0x6B92,
     143            0x92C2, 0x21DE, 0x45E0, 0xEF3D, 0x8B0D, 0x02CD, 0x0198, 0x0100,
     144            0x9E6D, 0x4D38, 0xDEF9, 0xE6F2, 0xF72E, 0xB313, 0x14F2, 0x390A,
     145            0x2D67, 0xC71E, 0xCB69, 0x7F66, 0xD3CF, 0x7F8A, 0x81D9, 0x9DDE
     146        },
     147        {
     148            0x85E3, 0x8F29, 0x36EB, 0xC968, 0x3696, 0x59F6, 0x7832, 0xA78B,
     149            0xA1D8, 0xF5CF, 0xAB64, 0x646D, 0x7A2A, 0xBAF8, 0xAA87, 0x41C7,
     150            0x5120, 0xDE78, 0x738D, 0xDC1A, 0x268D, 0x5DF8, 0xED69, 0x1C8A,
     151            0xBC85, 0x3DCD, 0xAE30, 0x0F8D, 0xEC89, 0x3ABD, 0x0166, 0x0100
     152        },
     153        {
     154            0xB8BD, 0x643B, 0x748E, 0xBD63, 0xEC6F, 0xE23A, 0x9493, 0xDD76,
     155            0x0A62, 0x774F, 0xCD68, 0xA67A, 0x9A23, 0xC8A8, 0xBDE5, 0x9D1B,
     156            0x2B86, 0x8B36, 0x5428, 0x1DFB, 0xCD1D, 0x0713, 0x29C2, 0x8E8E,
     157            0x5207, 0xA13F, 0x6005, 0x4F5E, 0x52E0, 0xE7C8, 0x6D1C, 0x3E34
     158        },
     159        {
     160            0x581D, 0x2BFA, 0x5E1D, 0xA891, 0x1069, 0x1DA4, 0x39A0, 0xBE45,
     161            0x5B9A, 0x7333, 0x6F3E, 0x8637, 0xA550, 0xC9E9, 0x5C6C, 0x42BA,
     162            0xA712, 0xC3EA, 0x3808, 0x0910, 0xAA4D, 0x5B25, 0xABCD, 0xE680,
     163            0x96AD, 0x2CEC, 0x8EBB, 0xA47D, 0x1690, 0xE8FB, 0x01C8, 0x0100
     164        },
     165        {
     166            0x73B9, 0x82BC, 0x9EBC, 0xB130, 0x0DA5, 0x8617, 0x9F7B, 0x9766,
     167            0x205D, 0x752D, 0xB05C, 0x2A17, 0xA75C, 0x18EF, 0x8339, 0xFD34,
     168            0x8DA2, 0x7970, 0xD0B4, 0x70F1, 0x3765, 0x7380, 0x7CAF, 0x570E,
     169            0x6440, 0xBC44, 0x0743, 0x2D02, 0x0419, 0xA240, 0x2113, 0x1AD4
     170        },
     171        {
     172            0x1EB5, 0xBBFF, 0x39B1, 0x3209, 0x705F, 0x15F4, 0xD7AD, 0x340B,
     173            0xC2A6, 0x25CA, 0xF412, 0x9570, 0x0F4F, 0xE4D5, 0x1614, 0xE464,
     174            0x911A, 0x0F0E, 0x07DA, 0xA929, 0x2379, 0xD988, 0x0AA6, 0x3B57,
     175            0xBF63, 0x71FB, 0x72D5, 0x26CE, 0xB0AF, 0xCF45, 0x011B, 0x0100
     176        },
     177        {
     178            0x9999, 0x98FE, 0xA108, 0x6588, 0xF90B, 0x4554, 0xFF38, 0x4642,
     179            0x8F5F, 0x6CC3, 0x4E8E, 0xFF7E, 0x64C2, 0x50CA, 0x0E7F, 0xAD7D,
     180            0x6AAB, 0x33C1, 0xE1F4, 0x6165, 0x7894, 0x83B9, 0x0A0C, 0x38AF,
     181            0x5803, 0x18C0, 0xFA36, 0x592C, 0x4548, 0xABB8, 0x1527, 0xAEE9
     182        }
     183    };
     184
     185
     186    //ecm_header_data = 01 03 b0 01 01
     187    if(!cw_is_valid(cw))          //if cw is all zero, keep it that way
     188    {
     189        return;
     190    }
     191    ecm_header_count = ecm_header_data[0];
     192    for(i = 0, ecmi = 1; i < ecm_header_count; i++)
     193    {
     194        if(ecm_header_data[ecmi + 1] != 0xb0)
     195        {
     196            ecmi += ecm_header_data[ecmi] + 1;
     197        }
     198        else
     199        {
     200            switch(ecm_header_data[ecmi + 2])
     201            {
     202                //b0 01
     203            case 1:
     204            {
     205                uint16_t hk[8], r, j, m = 0;
     206                for(r = 0; r < 6; r++)
     207                    { hk[2 + r] = Hash3[r]; }
     208                for(r = 0; r < 2; r++)
     209                {
     210                    for(j = 0; j < 0x48; j += 2)
     211                    {
     212                        if(r)
     213                        {
     214                            hk[0] = ((hk[3] & hk[5]) | ((~hk[5]) & hk[4]));
     215                        }
     216                        else
     217                        {
     218                            hk[0] = ((hk[3] & hk[4]) | ((~hk[3]) & hk[5]));
     219                        }
     220                        if(j < 8)
     221                        {
     222                            hk[0] = (hk[0] + ((cw[j + 1] << 8) | cw[j]));
     223                        }
     224                        if(j == 8)
     225                        {
     226                            hk[0] = (hk[0] + 0x80);
     227                        }
     228                        hk[0] = (hk[0] + hk[2] + (0xFF & NdTabB001[ecm_header_data[ecmi + 3]][m >> 1] >> ((m & 1) << 3)));
     229                        hk[1] = hk[2];
     230                        hk[2] = hk[3];
     231                        hk[3] = hk[4];
     232                        hk[4] = hk[5];
     233                        hk[5] = hk[6];
     234                        hk[6] = hk[7];
     235                        hk[7] = hk[2] + (((hk[0] << Hash4[m & 0xF]) | (hk[0] >> (0x10 - Hash4[m & 0xF]))));
     236                        m = (m + 1) & 0x3F;
     237                    }
     238                }
     239                for(r = 0; r < 6; r++)
     240                {
     241                    hk[2 + r] += Hash3[r];
     242                }
     243                for(r = 0; r < 7; r++)
     244                {
     245                    cw[r] = hk[2 + (r >> 1)] >> ((r & 1) << 3);
     246                }
     247                cw[3] = (cw[0] + cw[1] + cw[2]) & 0xFF;
     248                cw[7] = (cw[4] + cw[5] + cw[6]) & 0xFF;
     249                rdr_ddump_mask(reader, D_READER, cw, 8, "Postprocessed Case 1 DW:");
     250                break;
     251            }
     252            case 3:
     253            {
     254                memset(buffer, 0, sizeof(buffer));
     255                memcpy(buffer, cw, 8);
     256                memcpy(buffer + 8, &ecm_header_data[ecmi + 3], ecm_header_data[ecmi] & 0x7D);
     257                MD5(buffer, 8 + (ecm_header_data[ecmi] & 0x7D), md5tmp);
     258                memcpy(cw, md5tmp, 8);
     259                rdr_ddump_mask(reader, D_READER, cw, 8, "Postprocessed Case 3 DW:");
     260                break;
     261            }
     262            case 2:
     263            {
     264                /* Method 2 left out */
     265                //memcpy(DW_OUTPUT, DW_INPUT, 8);
     266                break;
     267            }
     268            }
     269        }
     270    }
    269271}
    270272
     
    272274static void vg2_read_tiers(struct s_reader *reader)
    273275{
    274     def_resp;
    275     int32_t l;
    276 
    277     /* ins2a is not needed and causes an error on some cards eg Sky Italy 09CD
    278        check if ins2a is in command table before running it
    279     */
    280     static const unsigned char ins2a[5] = { 0xD0, 0x2a, 0x00, 0x00, 0x00 };
    281     if (cmd_exists(reader, ins2a))
    282     {
    283         l = do_cmd(reader, ins2a, NULL, NULL, cta_res);
    284         if (l < 0 || !status_ok(cta_res + l))
    285         {
    286             rdr_log(reader, "classD0 ins2a: failed");
    287             return;
    288         }
    289     }
    290 
    291     static const unsigned char ins76007f[5] = { 0xD0, 0x76, 0x00, 0x7f, 0x02 };
    292     if (!write_cmd_vg(ins76007f, NULL) || !status_ok(cta_res + 2))
    293     {
    294         rdr_log(reader, "classD0 ins76007f: failed");
    295         return;
    296     }
    297     int32_t num = cta_res[1];
    298 
    299     int32_t i;
    300     unsigned char ins76[5] = { 0xD0, 0x76, 0x00, 0x00, 0x00 };
    301     struct videoguard_data *csystem_data = reader->csystem_data;
    302 
    303     // some cards start real tiers info in middle of tier info
    304     // and have blank tiers between old tiers and real tiers eg 09AC
    305     int32_t starttier = csystem_data->card_tierstart;
    306     bool stopemptytier = 1;
    307     if (!starttier)
    308         stopemptytier = 0;
    309 
    310     // check to see if specified start tier is blank and if blank, start at 0 and ignore blank tiers
    311     ins76[2] = starttier;
    312     l = do_cmd(reader, ins76, NULL, NULL, cta_res);
    313     if (l < 0 || !status_ok(cta_res + l)) return;
    314     if (cta_res[2] == 0 && cta_res[3] == 0 )
    315     {
    316         stopemptytier = 0;
    317         starttier = 0;
    318     }
    319 
    320     cs_clear_entitlement(reader); // reset the entitlements
    321 
    322     for (i = starttier; i < num; i++)
    323     {
    324         ins76[2] = i;
    325         l = do_cmd(reader, ins76, NULL, NULL, cta_res);
    326         if (l < 0 || !status_ok(cta_res + l)) return;
    327         if (cta_res[2] == 0 && cta_res[3] == 0 && stopemptytier) return;
    328         if (cta_res[2] != 0 || cta_res[3] != 0)
    329         {
    330             char tiername[83];
    331             uint16_t tier_id = (cta_res[2] << 8) | cta_res[3];
    332             // add entitlements to list
    333             struct tm timeinfo;
    334             memset(&timeinfo, 0, sizeof(struct tm));
    335             rev_date_calc_tm(&cta_res[4], &timeinfo, csystem_data->card_baseyear);
    336             cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), tier_id, 0, 0, mktime(&timeinfo), 4);
    337 
    338             if (!stopemptytier)
    339             {
    340                 rdr_debug_mask(reader, D_READER, "tier: %04x, tier-number: 0x%02x", tier_id, i);
    341             }
    342             rdr_log(reader, "tier: %04x, expiry date: %04d/%02d/%02d-%02d:%02d:%02d %s", tier_id, timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec, get_tiername(tier_id, reader->caid, tiername));
    343         }
    344     }
     276    def_resp;
     277    int32_t l;
     278
     279    /* ins2a is not needed and causes an error on some cards eg Sky Italy 09CD
     280       check if ins2a is in command table before running it
     281    */
     282    static const unsigned char ins2a[5] = { 0xD0, 0x2a, 0x00, 0x00, 0x00 };
     283    if(cmd_exists(reader, ins2a))
     284    {
     285        l = do_cmd(reader, ins2a, NULL, NULL, cta_res);
     286        if(l < 0 || !status_ok(cta_res + l))
     287        {
     288            rdr_log(reader, "classD0 ins2a: failed");
     289            return;
     290        }
     291    }
     292
     293    static const unsigned char ins76007f[5] = { 0xD0, 0x76, 0x00, 0x7f, 0x02 };
     294    if(!write_cmd_vg(ins76007f, NULL) || !status_ok(cta_res + 2))
     295    {
     296        rdr_log(reader, "classD0 ins76007f: failed");
     297        return;
     298    }
     299    int32_t num = cta_res[1];
     300
     301    int32_t i;
     302    unsigned char ins76[5] = { 0xD0, 0x76, 0x00, 0x00, 0x00 };
     303    struct videoguard_data *csystem_data = reader->csystem_data;
     304
     305    // some cards start real tiers info in middle of tier info
     306    // and have blank tiers between old tiers and real tiers eg 09AC
     307    int32_t starttier = csystem_data->card_tierstart;
     308    bool stopemptytier = 1;
     309    if(!starttier)
     310        { stopemptytier = 0; }
     311
     312    // check to see if specified start tier is blank and if blank, start at 0 and ignore blank tiers
     313    ins76[2] = starttier;
     314    l = do_cmd(reader, ins76, NULL, NULL, cta_res);
     315    if(l < 0 || !status_ok(cta_res + l)) { return; }
     316    if(cta_res[2] == 0 && cta_res[3] == 0)
     317    {
     318        stopemptytier = 0;
     319        starttier = 0;
     320    }
     321
     322    cs_clear_entitlement(reader); // reset the entitlements
     323
     324    for(i = starttier; i < num; i++)
     325    {
     326        ins76[2] = i;
     327        l = do_cmd(reader, ins76, NULL, NULL, cta_res);
     328        if(l < 0 || !status_ok(cta_res + l)) { return; }
     329        if(cta_res[2] == 0 && cta_res[3] == 0 && stopemptytier) { return; }
     330        if(cta_res[2] != 0 || cta_res[3] != 0)
     331        {
     332            char tiername[83];
     333            uint16_t tier_id = (cta_res[2] << 8) | cta_res[3];
     334            // add entitlements to list
     335            struct tm timeinfo;
     336            memset(&timeinfo, 0, sizeof(struct tm));
     337            rev_date_calc_tm(&cta_res[4], &timeinfo, csystem_data->card_baseyear);
     338            cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), tier_id, 0, 0, mktime(&timeinfo), 4);
     339
     340            if(!stopemptytier)
     341            {
     342                rdr_debug_mask(reader, D_READER, "tier: %04x, tier-number: 0x%02x", tier_id, i);
     343            }
     344            rdr_log(reader, "tier: %04x, expiry date: %04d/%02d/%02d-%02d:%02d:%02d %s", tier_id, timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec, get_tiername(tier_id, reader->caid, tiername));
     345        }
     346    }
    345347}
    346348
    347349static int32_t videoguard2_card_init(struct s_reader *reader, ATR *newatr)
    348350{
    349     get_hist;
    350     if ((hist_size < 7) || (hist[1] != 0xB0) || (hist[4] != 0xFF) || (hist[5] != 0x4A) || (hist[6] != 0x50))
    351     {
    352         rdr_debug_mask(reader, D_READER, "failed history check");
    353         return ERROR;
    354     }
    355     rdr_debug_mask(reader, D_READER, "passed history check");
    356 
    357     get_atr;
    358     def_resp;
    359 
    360     if (!cs_malloc(&reader->csystem_data, sizeof(struct videoguard_data)))
    361         return ERROR;
    362     struct videoguard_data *csystem_data = reader->csystem_data;
    363 
    364     /* set information on the card stored in reader-videoguard-common.c */
    365     set_known_card_info(reader, atr, &atr_size);
    366 
    367     if ((reader->ndsversion != NDS2) &&
    368             (((csystem_data->card_system_version != NDS2) && (csystem_data->card_system_version != NDSUNKNOWN)) ||
    369             (reader->ndsversion != NDSAUTO)))
    370     {
    371         /* known ATR and not NDS2
    372            or known NDS2 ATR and forced to another NDS version */
    373         return ERROR;
    374     }
    375 
    376     rdr_debug_mask(reader, D_READER, "type: %s, baseyear: %i", csystem_data->card_desc, csystem_data->card_baseyear);
    377     if (reader->ndsversion == NDS2)
    378     {
    379         rdr_debug_mask(reader, D_READER, "forced to NDS2");
    380     }
    381 
    382     //a non videoguard2/NDS2 card will fail on read_cmd_len(ins7401)
    383     //this way unknown videoguard2/NDS2 cards will also pass this check
    384 
    385     unsigned char ins7401[5] = { 0xD0, 0x74, 0x01, 0x00, 0x00 };
    386     int32_t l;
    387     if ((l = read_cmd_len(reader, ins7401)) < 0) //not a videoguard2/NDS card or communication error
    388     {
    389         return ERROR;
    390     }
    391     ins7401[4] = l;
    392     if (!write_cmd_vg(ins7401, NULL) || !status_ok(cta_res + l))
    393     {
    394         rdr_log(reader, "classD0 ins7401: failed - cmd list not read");
    395         return ERROR;
    396     }
    397 
    398     memorize_cmd_table (reader, cta_res, l);
    399 
    400     unsigned char buff[256];
    401 
    402     static const unsigned char ins7416[5] = { 0xD0, 0x74, 0x16, 0x00, 0x00 };
    403     if (do_cmd(reader, ins7416, NULL, NULL, cta_res) < 0)
    404     {
    405         rdr_log(reader, "classD0 ins7416: failed");
    406         return ERROR;
    407     }
    408 
    409     static const unsigned char ins02[5] = { 0xD0, 0x02, 0x00, 0x00, 0x08 };
    410     // D0 02 command is not always present in command table but should be supported
    411     // on most cards so do not use do_cmd()
    412     if (!write_cmd_vg(ins02, NULL) || !status_ok(cta_res + 8))
    413     {
    414         rdr_log(reader, "Unable to get NDS ROM version.");
    415     }
    416     else
    417     {
    418         int i;
    419         for (i = 0; i < 8; i++)
    420         {
    421             if (cta_res[i] <= 0x09)
    422             {
    423                 cta_res[i] = cta_res[i] + 0x30;
    424             }
    425             else if (!isalnum(cta_res[i]))
    426             {
    427                 cta_res[i] = '*';
    428             }
    429         }
    430         memset(reader->rom, 0, sizeof(reader->rom));
    431         memcpy(reader->rom, cta_res, 4);
    432         reader->rom[4] = '-';
    433         memcpy(reader->rom + 5, cta_res + 4, 4);
    434 
    435         rdr_log(reader, "Card type:   %c%c%c%c", reader->rom[0], reader->rom[1], reader->rom[2], reader->rom[3]);
    436         rdr_log(reader, "Rom version: %c%c%c%c", reader->rom[5], reader->rom[6], reader->rom[7], reader->rom[8]);
    437     }
    438 
    439 
    440     unsigned char boxID [4];
    441 
    442     if (reader->boxid > 0)
    443     {
    444         /* the boxid is specified in the config */
    445         int32_t i;
    446         for (i = 0; i < 4; i++)
    447         {
    448             boxID[i] = (reader->boxid >> (8 * (3 - i))) % 0x100;
    449         }
    450     }
    451     else
    452     {
    453         unsigned char ins36[5] = { 0xD0, 0x36, 0x00, 0x00, 0x00 };
    454         static const unsigned char ins5e[5] = { 0xD0, 0x5E, 0x00, 0x0C, 0x02 };
    455 
    456         /* we can try to get the boxid from the card */
    457         int32_t boxidOK = 0;
    458         l = read_cmd_len(reader, ins36);
    459         if (l > 0)
    460         {
    461             ins36[4] = l;
    462         }
    463         else if (cmd_exists(reader, ins5e))
    464         {
    465             if (!write_cmd_vg(ins5e, NULL) || !status_ok(cta_res + 2))
    466             {
    467                 rdr_log(reader, "classD0 ins5e: failed");
    468             }
    469             else
    470             {
    471                 ins36[3] = cta_res[0];
    472                 ins36[4] = cta_res[1];
    473             }
    474         }
    475         l = ins36[4];
    476         if (!write_cmd_vg(ins36, NULL) || !status_ok(cta_res + l))
    477         {
    478             rdr_log(reader, "classD0 ins36: failed");
    479             return ERROR;
    480         }
    481         memcpy(buff, ins36, 5);
    482         memcpy(buff + 5, cta_res, l);
    483         memcpy(buff + 5 + l, cta_res + l, 2);
    484         if (l < 13)
    485             rdr_log(reader, "classD0 ins36: answer too int16");
    486         else if (buff[7] > 0x0F)
    487             rdr_log(reader, "classD0 ins36: encrypted - can't parse");
    488         else
    489         {
    490             /* skipping the initial fixed fields: cmdecho (4) + length (1) + encr/rev++ (4) */
    491             int32_t i = 9;
    492             int32_t gotUA = 0;
    493             while (i < l)
    494             {
    495                 if (!gotUA && buff[i] < 0xF0) /* then we guess that the next 4 bytes is the UA */
    496                 {
    497                     gotUA = 1;
    498                     i += 4;
    499                 }
    500                 else switch (buff[i])     /* object length vary depending on type */
    501                     {
    502                     case 0x00: /* padding */
    503                         i += 1;
    504                         break;
    505                     case 0xEF: /* card status */
    506                         i += 3;
    507                         break;
    508                     case 0xD1:
    509                         i += 4;
    510                         break;
    511                     case 0xDF: /* next server contact */
    512                         i += 5;
    513                         break;
    514                     case 0xF3: /* boxID */
    515                         memcpy(boxID, buff + i + 1, sizeof(boxID));
    516                         boxidOK = 1;
    517                         i += 5;
    518                         break;
    519                     case 0xF6:
    520                         i += 6;
    521                         break;
    522                     case 0x01: /* date & time */
    523                         i += 7;
    524                         break;
    525                     case 0xFA:
    526                         i += 9;
    527                         break;
    528                     case 0x5E:
    529                     case 0x67: /* signature */
    530                     case 0xDE:
    531                     case 0xE2:
    532                     case 0xE9: /* tier dates */
    533                     case 0xF8: /* Old PPV Event Record */
    534                     case 0xFD:
    535                         i += buff[i + 1] + 2; /* skip length + 2 bytes (type and length) */
    536                         break;
    537                     default: /* default to assume a length byte */
    538                         rdr_log(reader, "classD0 ins36: returned unknown type=0x%02X - parsing may fail", buff[i]);
    539                         i += buff[i + 1] + 2;
    540                     }
    541             }
    542         }
    543 
    544         if (!boxidOK)
    545         {
    546             rdr_log(reader, "no boxID available");
    547             return ERROR;
    548         }
    549     }
    550 
    551     static const unsigned char ins4C[5] = { 0xD0, 0x4C, 0x00, 0x00, 0x09 };
    552     unsigned char payload4C[9] = { 0, 0, 0, 0, 3, 0, 0, 0, 4 };
    553     memcpy(payload4C, boxID, 4);
    554     if (!write_cmd_vg(ins4C, payload4C) || !status_ok(cta_res + l))
    555     {
    556         rdr_log(reader, "classD0 ins4C: failed - sending boxid failed");
    557         return ERROR;
    558     }
    559 
    560     //int16_t int32_t SWIRDstatus = cta_res[1];
    561     static const unsigned char ins58[5] = { 0xD0, 0x58, 0x00, 0x00, 0x00 };
    562     l = do_cmd(reader, ins58, NULL, NULL, cta_res);
    563     if (l < 0)
    564     {
    565         rdr_log(reader, "classD0 ins58: failed");
    566         return ERROR;
    567     }
    568     memset(reader->hexserial, 0, 8);
    569     memcpy(reader->hexserial + 2, cta_res + 3, 4);
    570     memcpy(reader->sa, cta_res + 3, 3);
    571     reader->caid = cta_res[24] * 0x100 + cta_res[25];
    572 
    573     /* we have one provider, 0x0000 */
    574     reader->nprov = 1;
    575     memset(reader->prid, 0x00, sizeof(reader->prid));
    576 
    577     /*
    578     rdr_log(reader, "INS58 : Fuse byte=0x%02X, IRDStatus=0x%02X", cta_res[2],SWIRDstatus);
    579     if (SWIRDstatus==4)  {
    580     // If swMarriage=4, not married then exchange for BC Key
    581     rdr_log(reader, "Card not married, exchange for BC Keys");
    582     */
    583 
    584     cCamCryptVG_SetSeed(reader);
    585 
    586     static const unsigned char insB4[5] = { 0xD0, 0xB4, 0x00, 0x00, 0x40 };
    587     unsigned char tbuff[64];
    588     cCamCryptVG_GetCamKey(reader, tbuff);
    589     l = do_cmd(reader, insB4, tbuff, NULL, cta_res);
    590     if (l < 0 || !status_ok(cta_res))
    591     {
    592         rdr_log(reader, "classD0 insB4: failed");
    593         return ERROR;
    594     }
    595 
    596     static const unsigned char insBC[5] = { 0xD0, 0xBC, 0x00, 0x00, 0x00 };
    597     l = do_cmd(reader, insBC, NULL, NULL, cta_res);
    598     if (l < 0)
    599     {
    600         rdr_log(reader, "classD0 insBC: failed");
    601         return ERROR;
    602     }
    603 
    604     // Class D1/D3 instructions only work after this point
    605 
    606     static const unsigned char insBE[5] = { 0xD3, 0xBE, 0x00, 0x00, 0x00 };
    607     l = do_cmd(reader, insBE, NULL, NULL, cta_res);
    608     if (l < 0)
    609     {
    610         rdr_log(reader, "classD3 insBE: failed");
    611         return ERROR;
    612     }
    613 
    614     static const unsigned char ins58a[5] = { 0xD1, 0x58, 0x00, 0x00, 0x00 };
    615     l = do_cmd(reader, ins58a, NULL, NULL, cta_res);
    616     if (l < 0)
    617     {
    618         rdr_log(reader, "classD1 ins58: failed");
    619         return ERROR;
    620     }
    621 
    622     static const unsigned char ins4Ca[5] = { 0xD1, 0x4C, 0x00, 0x00, 0x00 };
    623     l = do_cmd(reader, ins4Ca, payload4C, NULL, cta_res);
    624     if (l < 0 || !status_ok(cta_res))
    625     {
    626         rdr_log(reader, "classD1 ins4Ca: failed");
    627         return ERROR;
    628     }
    629 
    630     if (reader->ins7E[0x1A])
    631     {
    632         static const uint8_t ins7E[5] = { 0xD1, 0x7E, 0x10, 0x00, 0x1A };
    633         l = do_cmd(reader, ins7E, reader->ins7E, NULL, cta_res);
    634         if (l < 0 || !status_ok(cta_res))
    635         {
    636             rdr_log(reader, "classD1 ins7E: failed");
    637             return ERROR;
    638         }
    639     }
    640 
    641     if (reader->ins7E11[0x01])
    642     {
    643         unsigned char ins742b[5] = { 0xD0, 0x74, 0x2b, 0x00, 0x00 };
    644 
    645         l = read_cmd_len(reader, ins742b);  //get command len for ins742b
    646 
    647         if (l < 2)
    648         {
    649             rdr_log(reader, "No TA1 change for this card is possible by ins7E11");
    650         }
    651         else
    652         {
    653             ins742b[4] = l;
    654             bool ta1ok = 0;
    655 
    656             if (!write_cmd_vg(ins742b, NULL) || !status_ok(cta_res + ins742b[4])) //get supported TA1 bytes
    657             {
    658                 rdr_log(reader, "classD0 ins742b: failed");
    659                 return ERROR;
    660             }
    661             else
    662             {
    663                 int32_t i;
    664 
    665                 for (i = 2; i < l; i++)
    666                 {
    667                     if (cta_res[i] == reader->ins7E11[0x00])
    668                     {
    669                         ta1ok = 1;
    670                         break;
    671                     }
    672                 }
    673             }
    674             if (ta1ok == 0)
    675             {
    676                 rdr_log(reader, "The value %02X of ins7E11 is not supported,try one between %02X and %02X", reader->ins7E11[0x00], cta_res[2], cta_res[ins742b[4] - 1]);
    677             }
    678             else
    679             {
    680                 static const uint8_t ins7E11[5] = { 0xD0, 0x7E, 0x11, 0x00, 0x01 };
    681 
    682                 reader->ins7e11_fast_reset = 0;
    683 
    684                 l = do_cmd(reader, ins7E11, reader->ins7E11, NULL, cta_res);
    685 
    686                 if (l < 0 || !status_ok(cta_res))
    687                 {
    688                     rdr_log(reader, "classD0 ins7E11: failed");
    689                     return ERROR;
    690                 }
    691                 else
    692                 {
    693                     unsigned char TA1;
    694 
    695                     if (ATR_GetInterfaceByte (newatr, 1, ATR_INTERFACE_BYTE_TA, &TA1) == ATR_OK)
    696                     {
    697                         if (TA1 != reader->ins7E11[0x00])
    698                         {
    699                             rdr_log(reader, "classD0 ins7E11: Scheduling card reset for TA1 change from %02X to %02X", TA1, reader->ins7E11[0x00]);
    700                             reader->ins7e11_fast_reset = 1;
     351    get_hist;
     352    if((hist_size < 7) || (hist[1] != 0xB0) || (hist[4] != 0xFF) || (hist[5] != 0x4A) || (hist[6] != 0x50))
     353    {
     354        rdr_debug_mask(reader, D_READER, "failed history check");
     355        return ERROR;
     356    }
     357    rdr_debug_mask(reader, D_READER, "passed history check");
     358
     359    get_atr;
     360    def_resp;
     361
     362    if(!cs_malloc(&reader->csystem_data, sizeof(struct videoguard_data)))
     363        { return ERROR; }
     364    struct videoguard_data *csystem_data = reader->csystem_data;
     365
     366    /* set information on the card stored in reader-videoguard-common.c */
     367    set_known_card_info(reader, atr, &atr_size);
     368
     369    if((reader->ndsversion != NDS2) &&
     370            (((csystem_data->card_system_version != NDS2) && (csystem_data->card_system_version != NDSUNKNOWN)) ||
     371            (reader->ndsversion != NDSAUTO)))
     372    {
     373        /* known ATR and not NDS2
     374           or known NDS2 ATR and forced to another NDS version */
     375        return ERROR;
     376    }
     377
     378    rdr_debug_mask(reader, D_READER, "type: %s, baseyear: %i", csystem_data->card_desc, csystem_data->card_baseyear);
     379    if(reader->ndsversion == NDS2)
     380    {
     381        rdr_debug_mask(reader, D_READER, "forced to NDS2");
     382    }
     383
     384    //a non videoguard2/NDS2 card will fail on read_cmd_len(ins7401)
     385    //this way unknown videoguard2/NDS2 cards will also pass this check
     386
     387    unsigned char ins7401[5] = { 0xD0, 0x74, 0x01, 0x00, 0x00 };
     388    int32_t l;
     389    if((l = read_cmd_len(reader, ins7401)) < 0) //not a videoguard2/NDS card or communication error
     390    {
     391        return ERROR;
     392    }
     393    ins7401[4] = l;
     394    if(!write_cmd_vg(ins7401, NULL) || !status_ok(cta_res + l))
     395    {
     396        rdr_log(reader, "classD0 ins7401: failed - cmd list not read");
     397        return ERROR;
     398    }
     399
     400    memorize_cmd_table(reader, cta_res, l);
     401
     402    unsigned char buff[256];
     403
     404    static const unsigned char ins7416[5] = { 0xD0, 0x74, 0x16, 0x00, 0x00 };
     405    if(do_cmd(reader, ins7416, NULL, NULL, cta_res) < 0)
     406    {
     407        rdr_log(reader, "classD0 ins7416: failed");
     408        return ERROR;
     409    }
     410
     411    static const unsigned char ins02[5] = { 0xD0, 0x02, 0x00, 0x00, 0x08 };
     412    // D0 02 command is not always present in command table but should be supported
     413    // on most cards so do not use do_cmd()
     414    if(!write_cmd_vg(ins02, NULL) || !status_ok(cta_res + 8))
     415    {
     416        rdr_log(reader, "Unable to get NDS ROM version.");
     417    }
     418    else
     419    {
     420        int i;
     421        for(i = 0; i < 8; i++)
     422        {
     423            if(cta_res[i] <= 0x09)
     424            {
     425                cta_res[i] = cta_res[i] + 0x30;
     426            }
     427            else if(!isalnum(cta_res[i]))
     428            {
     429                cta_res[i] = '*';
     430            }
     431        }
     432        memset(reader->rom, 0, sizeof(reader->rom));
     433        memcpy(reader->rom, cta_res, 4);
     434        reader->rom[4] = '-';
     435        memcpy(reader->rom + 5, cta_res + 4, 4);
     436
     437        rdr_log(reader, "Card type:   %c%c%c%c", reader->rom[0], reader->rom[1], reader->rom[2], reader->rom[3]);
     438        rdr_log(reader, "Rom version: %c%c%c%c", reader->rom[5], reader->rom[6], reader->rom[7], reader->rom[8]);
     439    }
     440
     441
     442    unsigned char boxID [4];
     443
     444    if(reader->boxid > 0)
     445    {
     446        /* the boxid is specified in the config */
     447        int32_t i;
     448        for(i = 0; i < 4; i++)
     449        {
     450            boxID[i] = (reader->boxid >> (8 * (3 - i))) % 0x100;
     451        }
     452    }
     453    else
     454    {
     455        unsigned char ins36[5] = { 0xD0, 0x36, 0x00, 0x00, 0x00 };
     456        static const unsigned char ins5e[5] = { 0xD0, 0x5E, 0x00, 0x0C, 0x02 };
     457
     458        /* we can try to get the boxid from the card */
     459        int32_t boxidOK = 0;
     460        l = read_cmd_len(reader, ins36);
     461        if(l > 0)
     462        {
     463            ins36[4] = l;
     464        }
     465        else if(cmd_exists(reader, ins5e))
     466        {
     467            if(!write_cmd_vg(ins5e, NULL) || !status_ok(cta_res + 2))
     468            {
     469                rdr_log(reader, "classD0 ins5e: failed");
     470            }
     471            else
     472            {
     473                ins36[3] = cta_res[0];
     474                ins36[4] = cta_res[1];
     475            }
     476        }
     477        l = ins36[4];
     478        if(!write_cmd_vg(ins36, NULL) || !status_ok(cta_res + l))
     479        {
     480            rdr_log(reader, "classD0 ins36: failed");
     481            return ERROR;
     482        }
     483        memcpy(buff, ins36, 5);
     484        memcpy(buff + 5, cta_res, l);
     485        memcpy(buff + 5 + l, cta_res + l, 2);
     486        if(l < 13)
     487            { rdr_log(reader, "classD0 ins36: answer too int16"); }
     488        else if(buff[7] > 0x0F)
     489            { rdr_log(reader, "classD0 ins36: encrypted - can't parse"); }
     490        else
     491        {
     492            /* skipping the initial fixed fields: cmdecho (4) + length (1) + encr/rev++ (4) */
     493            int32_t i = 9;
     494            int32_t gotUA = 0;
     495            while(i < l)
     496            {
     497                if(!gotUA && buff[i] < 0xF0) /* then we guess that the next 4 bytes is the UA */
     498                {
     499                    gotUA = 1;
     500                    i += 4;
     501                }
     502                else switch(buff[i])      /* object length vary depending on type */
     503                    {
     504                    case 0x00: /* padding */
     505                        i += 1;
     506                        break;
     507                    case 0xEF: /* card status */
     508                        i += 3;
     509                        break;
     510                    case 0xD1:
     511                        i += 4;
     512                        break;
     513                    case 0xDF: /* next server contact */
     514                        i += 5;
     515                        break;
     516                    case 0xF3: /* boxID */
     517                        memcpy(boxID, buff + i + 1, sizeof(boxID));
     518                        boxidOK = 1;
     519                        i += 5;
     520                        break;
     521                    case 0xF6:
     522                        i += 6;
     523                        break;
     524                    case 0x01: /* date & time */
     525                        i += 7;
     526                        break;
     527                    case 0xFA:
     528                        i += 9;
     529                        break;
     530                    case 0x5E:
     531                    case 0x67: /* signature */
     532                    case 0xDE:
     533                    case 0xE2:
     534                    case 0xE9: /* tier dates */
     535                    case 0xF8: /* Old PPV Event Record */
     536                    case 0xFD:
     537                        i += buff[i + 1] + 2; /* skip length + 2 bytes (type and length) */
     538                        break;
     539                    default: /* default to assume a length byte */
     540                        rdr_log(reader, "classD0 ins36: returned unknown type=0x%02X - parsing may fail", buff[i]);
     541                        i += buff[i + 1] + 2;
     542                    }
     543            }
     544        }
     545
     546        if(!boxidOK)
     547        {
     548            rdr_log(reader, "no boxID available");
     549            return ERROR;
     550        }
     551    }
     552
     553    static const unsigned char ins4C[5] = { 0xD0, 0x4C, 0x00, 0x00, 0x09 };
     554    unsigned char payload4C[9] = { 0, 0, 0, 0, 3, 0, 0, 0, 4 };
     555    memcpy(payload4C, boxID, 4);
     556    if(!write_cmd_vg(ins4C, payload4C) || !status_ok(cta_res + l))
     557    {
     558        rdr_log(reader, "classD0 ins4C: failed - sending boxid failed");
     559        return ERROR;
     560    }
     561
     562    //int16_t int32_t SWIRDstatus = cta_res[1];
     563    static const unsigned char ins58[5] = { 0xD0, 0x58, 0x00, 0x00, 0x00 };
     564    l = do_cmd(reader, ins58, NULL, NULL, cta_res);
     565    if(l < 0)
     566    {
     567        rdr_log(reader, "classD0 ins58: failed");
     568        return ERROR;
     569    }
     570    memset(reader->hexserial, 0, 8);
     571    memcpy(reader->hexserial + 2, cta_res + 3, 4);
     572    memcpy(reader->sa, cta_res + 3, 3);
     573    reader->caid = cta_res[24] * 0x100 + cta_res[25];
     574
     575    /* we have one provider, 0x0000 */
     576    reader->nprov = 1;
     577    memset(reader->prid, 0x00, sizeof(reader->prid));
     578
     579    /*
     580    rdr_log(reader, "INS58 : Fuse byte=0x%02X, IRDStatus=0x%02X", cta_res[2],SWIRDstatus);
     581    if (SWIRDstatus==4)  {
     582    // If swMarriage=4, not married then exchange for BC Key
     583    rdr_log(reader, "Card not married, exchange for BC Keys");
     584    */
     585
     586    cCamCryptVG_SetSeed(reader);
     587
     588    static const unsigned char insB4[5] = { 0xD0, 0xB4, 0x00, 0x00, 0x40 };
     589    unsigned char tbuff[64];
     590    cCamCryptVG_GetCamKey(reader, tbuff);
     591    l = do_cmd(reader, insB4, tbuff, NULL, cta_res);
     592    if(l < 0 || !status_ok(cta_res))
     593    {
     594        rdr_log(reader, "classD0 insB4: failed");
     595        return ERROR;
     596    }
     597
     598    static const unsigned char insBC[5] = { 0xD0, 0xBC, 0x00, 0x00, 0x00 };
     599    l = do_cmd(reader, insBC, NULL, NULL, cta_res);
     600    if(l < 0)
     601    {
     602        rdr_log(reader, "classD0 insBC: failed");
     603        return ERROR;
     604    }
     605
     606    // Class D1/D3 instructions only work after this point
     607
     608    static const unsigned char insBE[5] = { 0xD3, 0xBE, 0x00, 0x00, 0x00 };
     609    l = do_cmd(reader, insBE, NULL, NULL, cta_res);
     610    if(l < 0)
     611    {
     612        rdr_log(reader, "classD3 insBE: failed");
     613        return ERROR;
     614    }
     615
     616    static const unsigned char ins58a[5] = { 0xD1, 0x58, 0x00, 0x00, 0x00 };
     617    l = do_cmd(reader, ins58a, NULL, NULL, cta_res);
     618    if(l < 0)
     619    {
     620        rdr_log(reader, "classD1 ins58: failed");
     621        return ERROR;
     622    }
     623
     624    static const unsigned char ins4Ca[5] = { 0xD1, 0x4C, 0x00, 0x00, 0x00 };
     625    l = do_cmd(reader, ins4Ca, payload4C, NULL, cta_res);
     626    if(l < 0 || !status_ok(cta_res))
     627    {
     628        rdr_log(reader, "classD1 ins4Ca: failed");
     629        return ERROR;
     630    }
     631
     632    if(reader->ins7E[0x1A])
     633    {
     634        static const uint8_t ins7E[5] = { 0xD1, 0x7E, 0x10, 0x00, 0x1A };
     635        l = do_cmd(reader, ins7E, reader->ins7E, NULL, cta_res);
     636        if(l < 0 || !status_ok(cta_res))
     637        {
     638            rdr_log(reader, "classD1 ins7E: failed");
     639            return ERROR;
     640        }
     641    }
     642
     643    if(reader->ins7E11[0x01])
     644    {
     645        unsigned char ins742b[5] = { 0xD0, 0x74, 0x2b, 0x00, 0x00 };
     646
     647        l = read_cmd_len(reader, ins742b);  //get command len for ins742b
     648
     649        if(l < 2)
     650        {
     651            rdr_log(reader, "No TA1 change for this card is possible by ins7E11");
     652        }
     653        else
     654        {
     655            ins742b[4] = l;
     656            bool ta1ok = 0;
     657
     658            if(!write_cmd_vg(ins742b, NULL) || !status_ok(cta_res + ins742b[4])) //get supported TA1 bytes
     659            {
     660                rdr_log(reader, "classD0 ins742b: failed");
     661                return ERROR;
     662            }
     663            else
     664            {
     665                int32_t i;
     666
     667                for(i = 2; i < l; i++)
     668                {
     669                    if(cta_res[i] == reader->ins7E11[0x00])
     670                    {
     671                        ta1ok = 1;
     672                        break;
     673                    }
     674                }
     675            }
     676            if(ta1ok == 0)
     677            {
     678                rdr_log(reader, "The value %02X of ins7E11 is not supported,try one between %02X and %02X", reader->ins7E11[0x00], cta_res[2], cta_res[ins742b[4] - 1]);
     679            }
     680            else
     681            {
     682                static const uint8_t ins7E11[5] = { 0xD0, 0x7E, 0x11, 0x00, 0x01 };
     683
     684                reader->ins7e11_fast_reset = 0;
     685
     686                l = do_cmd(reader, ins7E11, reader->ins7E11, NULL, cta_res);
     687
     688                if(l < 0 || !status_ok(cta_res))
     689                {
     690                    rdr_log(reader, "classD0 ins7E11: failed");
     691                    return ERROR;
     692                }
     693                else
     694                {
     695                    unsigned char TA1;
     696
     697                    if(ATR_GetInterfaceByte(newatr, 1, ATR_INTERFACE_BYTE_TA, &TA1) == ATR_OK)
     698                    {
     699                        if(TA1 != reader->ins7E11[0x00])
     700                        {
     701                            rdr_log(reader, "classD0 ins7E11: Scheduling card reset for TA1 change from %02X to %02X", TA1, reader->ins7E11[0x00]);
     702                            reader->ins7e11_fast_reset = 1;
    701703#ifdef WITH_COOLAPI
    702                             if (reader->typ == R_MOUSE || reader->typ == R_SC8in1 || reader->typ == R_SMART || reader->typ == R_INTERNAL)
    703                             {
     704                            if(reader->typ == R_MOUSE || reader->typ == R_SC8in1 || reader->typ == R_SMART || reader->typ == R_INTERNAL)
     705                            {
    704706#else
    705                             if (reader->typ == R_MOUSE || reader->typ == R_SC8in1 || reader->typ == R_SMART)
    706                             {
     707                            if(reader->typ == R_MOUSE || reader->typ == R_SC8in1 || reader->typ == R_SMART)
     708                            {
    707709#endif
    708                                 add_job(reader->client, ACTION_READER_RESET_FAST, NULL, 0);
    709                             }
    710                             else
    711                             {
    712                                 add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
    713                             }
    714                             return OK; // Skip the rest of the init since the card will be reset anyway
    715                         }
    716                     }
    717                 }
    718             }
    719         }
    720     }
    721 
    722     /* get parental lock settings */
    723     static const unsigned char ins74e[5] = {0xD0, 0x74, 0x0E, 0x00, 0x00};
    724     if (cmd_exists(reader, ins74e))
    725     {
    726         l = do_cmd(reader, ins74e, NULL, NULL, cta_res);
    727         if (l < 0 || !status_ok(cta_res + l))
    728         {
    729             rdr_log(reader, "classD0 ins74e: failed to get parental lock settings");
    730         }
    731         else
    732         {
    733             char tmp[l > 0 ? l * 3 : 1];
    734             rdr_log(reader, "parental lock setting: %s", cs_hexdump(1, cta_res + 2, l - 2, tmp, sizeof(tmp)));
    735         }
    736     }
    737 
    738     /* disable parental lock */
    739     static const uchar ins2e[5] = {0xD0, 0x2E, 0x00, 0x00, 0x04};
    740     static const uchar payload2e[4] = {0xFF, 0xFF, 0xFF, 0xFF};
    741     if (cfg.ulparent)
    742     {
    743         if (cmd_exists(reader, ins74e) && write_cmd_vg(ins2e, payload2e) && status_ok(cta_res + l))
    744         {
    745             rdr_log(reader, "parental lock disabled");
    746         }
    747         else
    748         {
    749             rdr_log(reader, "cannot disable parental lock");
    750         }
    751         if (cmd_exists(reader, ins74e))
    752         {
    753             l = do_cmd(reader, ins74e, NULL, NULL, cta_res);
    754             if (l < 0 || !status_ok(cta_res + l))
    755             {
    756                 rdr_log(reader, "classD0 ins74e: failed to get parental lock settings");
    757             }
    758             else
    759             {
    760                 char tmp[l > 0 ? l * 3 : 1];
    761                 rdr_log(reader, "parental lock setting after disabling: %s", cs_hexdump(1, cta_res + 2, l - 2, tmp, sizeof(tmp)));
    762             }
    763         }
    764     }
    765 
    766     // fix for 09ac cards
    767     unsigned char dimeno_magic[0x10] = {0xF9, 0xFB, 0xCD, 0x5A, 0x76, 0xB5, 0xC4, 0x5C, 0xC8, 0x2E, 0x1D, 0xE1, 0xCC, 0x5B, 0x6B, 0x02};
    768     int32_t a;
    769     for (a = 0; a < 4; a++)
    770         dimeno_magic[a] = dimeno_magic[a] ^ boxID[a];
    771     AES_set_decrypt_key(dimeno_magic, 128, &(csystem_data->astrokey));
    772 
    773     rdr_log(reader, "type: %s, caid: %04X",
    774             csystem_data->card_desc,
    775             reader->caid);
    776     rdr_log_sensitive(reader, "serial: {%02X%02X%02X%02X}, BoxID: {%02X%02X%02X%02X}, baseyear: %i",
    777                       reader->hexserial[2], reader->hexserial[3], reader->hexserial[4], reader->hexserial[5],
    778                       boxID[0], boxID[1], boxID[2], boxID[3],
    779                       csystem_data->card_baseyear);
    780     rdr_log(reader, "ready for requests");
    781 
    782     return OK;
     710                                add_job(reader->client, ACTION_READER_RESET_FAST, NULL, 0);
     711                            }
     712                            else
     713                            {
     714                                add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
     715                            }
     716                            return OK; // Skip the rest of the init since the card will be reset anyway
     717                        }
     718                    }
     719                }
     720            }
     721        }
     722    }
     723
     724    /* get parental lock settings */
     725    static const unsigned char ins74e[5] = {0xD0, 0x74, 0x0E, 0x00, 0x00};
     726    if(cmd_exists(reader, ins74e))
     727    {
     728        l = do_cmd(reader, ins74e, NULL, NULL, cta_res);
     729        if(l < 0 || !status_ok(cta_res + l))
     730        {
     731            rdr_log(reader, "classD0 ins74e: failed to get parental lock settings");
     732        }
     733        else
     734        {
     735            char tmp[l > 0 ? l * 3 : 1];
     736            rdr_log(reader, "parental lock setting: %s", cs_hexdump(1, cta_res + 2, l - 2, tmp, sizeof(tmp)));
     737        }
     738    }
     739
     740    /* disable parental lock */
     741    static const uchar ins2e[5] = {0xD0, 0x2E, 0x00, 0x00, 0x04};
     742    static const uchar payload2e[4] = {0xFF, 0xFF, 0xFF, 0xFF};
     743    if(cfg.ulparent)
     744    {
     745        if(cmd_exists(reader, ins74e) && write_cmd_vg(ins2e, payload2e) && status_ok(cta_res + l))
     746        {
     747            rdr_log(reader, "parental lock disabled");
     748        }
     749        else
     750        {
     751            rdr_log(reader, "cannot disable parental lock");
     752        }
     753        if(cmd_exists(reader, ins74e))
     754        {
     755            l = do_cmd(reader, ins74e, NULL, NULL, cta_res);
     756            if(l < 0 || !status_ok(cta_res + l))
     757            {
     758                rdr_log(reader, "classD0 ins74e: failed to get parental lock settings");
     759            }
     760            else
     761            {
     762                char tmp[l > 0 ? l * 3 : 1];
     763                rdr_log(reader, "parental lock setting after disabling: %s", cs_hexdump(1, cta_res + 2, l - 2, tmp, sizeof(tmp)));
     764            }
     765        }
     766    }
     767
     768    // fix for 09ac cards
     769    unsigned char dimeno_magic[0x10] = {0xF9, 0xFB, 0xCD, 0x5A, 0x76, 0xB5, 0xC4, 0x5C, 0xC8, 0x2E, 0x1D, 0xE1, 0xCC, 0x5B, 0x6B, 0x02};
     770    int32_t a;
     771    for(a = 0; a < 4; a++)
     772        { dimeno_magic[a] = dimeno_magic[a] ^ boxID[a]; }
     773    AES_set_decrypt_key(dimeno_magic, 128, &(csystem_data->astrokey));
     774
     775    rdr_log(reader, "type: %s, caid: %04X",
     776            csystem_data->card_desc,
     777            reader->caid);
     778    rdr_log_sensitive(reader, "serial: {%02X%02X%02X%02X}, BoxID: {%02X%02X%02X%02X}, baseyear: %i",
     779                      reader->hexserial[2], reader->hexserial[3], reader->hexserial[4], reader->hexserial[5],
     780                      boxID[0], boxID[1], boxID[2], boxID[3],
     781                      csystem_data->card_baseyear);
     782    rdr_log(reader, "ready for requests");
     783
     784    return OK;
    783785}
    784786
    785787static int32_t videoguard2_do_ecm(struct s_reader *reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
    786788{
    787     unsigned char cta_res[CTA_RES_LEN];
    788     static const char valid_ecm[] = { 0x00, 0x00, 0x01 };
    789     unsigned char ins40[5] = { 0xD1, 0x40, 0x00, 0x80, 0xFF };
    790     static const unsigned char ins54[5] = { 0xD3, 0x54, 0x00, 0x00, 0x00};
    791     int32_t posECMpart2 = er->ecm[6] + 7;
    792     int32_t lenECMpart2 = er->ecm[posECMpart2] + 1;
    793     unsigned char tbuff[264], rbuff[264];
    794     tbuff[0] = 0;
    795 
    796     memset(ea->cw + 0, 0, 16); //set cw to 0 so client will know it is invalid unless it is overwritten with a valid cw
    797 
    798     if (memcmp(&(er->ecm[3]), valid_ecm, sizeof(valid_ecm) != 0))
    799     {
    800         rdr_log(reader, "Not a valid ecm");
    801         return ERROR;
    802     }
    803 
    804     memcpy(tbuff + 1, er->ecm + posECMpart2 + 1, lenECMpart2 - 1);
    805 
    806     /*
    807       //log parental lock byte
    808       int32_t j;
    809       for (j = posECMpart2+1; j < lenECMpart2+posECMpart2+1-4; j++){
    810         if (er->ecm[j] == 0x02 && er->ecm[j+3] == 0x02) {
    811           rdr_log(reader, "channel parental lock mask: %02X%02X, channel parental lock byte: %02X",er->ecm[j+1],er->ecm[j+2],er->ecm[j+4]);
    812           break;
    813         }
    814       }
    815 
    816       //log tiers
    817       int32_t k;
    818       char tiername[83];
    819       for (k = posECMpart2+1; k < lenECMpart2+posECMpart2+1-4; k++){
    820         if (er->ecm[k] == 0x03 && er->ecm[k+3] == 0x80) {
    821           uint16_t vtier_id = (er->ecm[k+1] << 8) | er->ecm[k+2];
    822           get_tiername(vtier_id, reader->caid, tiername);
    823           rdr_log(reader, "valid tier: %04x %s",vtier_id, tiername);
    824         }
    825       }
    826     */
    827 
    828     int32_t new_len = lenECMpart2;
    829     if (reader->fix_9993 && reader->caid == 0x919 && tbuff[1] == 0x7F)
    830     {
    831         tbuff[1] = 0x47; tbuff[2] = 0x08;
    832         memmove(tbuff + 11, tbuff + 13, new_len - 11);
    833         new_len -= 2;
    834     }
    835     ins40[4] = new_len;
    836     int32_t l;
    837 
    838     l = do_cmd(reader, ins40, tbuff, NULL, cta_res);
    839     if (l < 0 || !status_ok(cta_res))
    840     {
    841         rdr_log(reader, "classD0 ins40: (%d) status not ok %02x %02x", l, cta_res[0], cta_res[1]);
    842         rdr_log(reader, "The card is not answering correctly! Restarting reader for safety");
    843         add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
    844         return ERROR;
    845     }
    846     else
    847     {
    848         l = do_cmd(reader, ins54, NULL, rbuff, cta_res);
    849         if (l < 0 || !status_ok(cta_res + l))
    850         {
    851             rdr_log(reader, "classD3 ins54: (%d) status not ok %02x %02x", l, cta_res[0], cta_res[1]);
    852             rdr_log(reader, "The card is not answering correctly! Restarting reader for safety");
    853             add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
    854             return ERROR;
    855         }
    856         else
    857         {
    858 
    859             // Log decrypted INS54
    860             rdr_ddump_mask(reader, D_READER, rbuff, 5, "INS54:");
    861             rdr_ddump_mask(reader, D_READER, rbuff + 5, rbuff[4], "Decrypted payload");
    862 
    863             if (!cw_is_valid(rbuff + 5)) //sky cards report 90 00 = ok but send cw = 00 when channel not subscribed
    864             {
    865                 rdr_log(reader, "classD3 ins54: status 90 00 = ok but cw=00 -> channel not subscribed " );
    866                 return ERROR;
    867             }
    868 
    869             // copy cw1 in place
    870             memcpy(ea->cw + 0, rbuff + 5, 8);
    871 
    872             // process cw2
    873             unsigned char *payload = rbuff + 5;
    874             int32_t payloadLen = rbuff[4];
    875             int32_t ind = 8 + 6; // +8 for CW1, +6 for counter(?)
    876 
    877             while (ind < payloadLen)
    878             {
    879                 switch (payload[ind])
    880                 {
    881                 case 0x25:  // CW2
    882                     //cs_dump (payload + ind, payload[ind+1]+2, "INS54 - CW2");
    883                     memcpy(ea->cw + 8, &payload[ind + 3], 8);
    884                     ind += payload[ind + 1] + 2;
    885                     break;
    886 
    887                 default:
    888                     //cs_dump (payload + ind, payload[ind+1]+2, "INS54");
    889                     ind += payload[ind + 1] + 2;
    890                     break;
    891                 }
    892             }
    893 
    894             if (new_len != lenECMpart2)
    895             {
    896                 memcpy(ea->cw, ea->cw + 8, 8);
    897                 memset(ea->cw + 8, 0, 8);
    898             }
    899             // fix for 09ac cards
    900             dimeno_PostProcess_Decrypt(reader, rbuff, ea->cw);
    901 
    902             //test for postprocessing marker
    903             int32_t posB0 = -1;
    904             int32_t i;
    905             for (i = 6; i < posECMpart2; i++)
    906             {
    907                 if (er->ecm[i - 3] == 0x80 && er->ecm[i] == 0xB0 && ((er->ecm[i + 1] == 0x01) || (er->ecm[i + 1] == 0x02) || (er->ecm[i + 1] == 0x03) ) )
    908                 {
    909                     posB0 = i;
    910                     break;
    911                 }
    912             }
    913             if (posB0 != -1)
    914             {
    915                 do_post_dw_hash(reader, ea->cw + 0, &er->ecm[posB0 - 2]);
    916                 do_post_dw_hash(reader, ea->cw + 8, &er->ecm[posB0 - 2]);
    917             }
    918 
    919             if (reader->caid == 0x0907)   //quickfix: cw2 is not a valid cw, something went wrong before
    920             {
    921                 memset(ea->cw + 8, 0, 8);
    922                 if (er->ecm[0] & 1)
    923                 {
    924                     memcpy(ea->cw + 8, ea->cw, 8);
    925                     memset(ea->cw, 0, 8);
    926                 }
    927             }
    928             else
    929             {
    930                 if (er->ecm[0] & 1)
    931                 {
    932                     unsigned char tmpcw[8];
    933                     memcpy(tmpcw, ea->cw + 8, 8);
    934                     memcpy(ea->cw + 8, ea->cw + 0, 8);
    935                     memcpy(ea->cw + 0, tmpcw, 8);
    936                 }
    937             }
    938 
    939             return OK;
    940         }
    941     }
     789    unsigned char cta_res[CTA_RES_LEN];
     790    static const char valid_ecm[] = { 0x00, 0x00, 0x01 };
     791    unsigned char ins40[5] = { 0xD1, 0x40, 0x00, 0x80, 0xFF };
     792    static const unsigned char ins54[5] = { 0xD3, 0x54, 0x00, 0x00, 0x00};
     793    int32_t posECMpart2 = er->ecm[6] + 7;
     794    int32_t lenECMpart2 = er->ecm[posECMpart2] + 1;
     795    unsigned char tbuff[264], rbuff[264];
     796    tbuff[0] = 0;
     797
     798    memset(ea->cw + 0, 0, 16); //set cw to 0 so client will know it is invalid unless it is overwritten with a valid cw
     799
     800    if(memcmp(&(er->ecm[3]), valid_ecm, sizeof(valid_ecm) != 0))
     801    {
     802        rdr_log(reader, "Not a valid ecm");
     803        return ERROR;
     804    }
     805
     806    memcpy(tbuff + 1, er->ecm + posECMpart2 + 1, lenECMpart2 - 1);
     807
     808    /*
     809      //log parental lock byte
     810      int32_t j;
     811      for (j = posECMpart2+1; j < lenECMpart2+posECMpart2+1-4; j++){
     812        if (er->ecm[j] == 0x02 && er->ecm[j+3] == 0x02) {
     813          rdr_log(reader, "channel parental lock mask: %02X%02X, channel parental lock byte: %02X",er->ecm[j+1],er->ecm[j+2],er->ecm[j+4]);
     814          break;
     815        }
     816      }
     817
     818      //log tiers
     819      int32_t k;
     820      char tiername[83];
     821      for (k = posECMpart2+1; k < lenECMpart2+posECMpart2+1-4; k++){
     822        if (er->ecm[k] == 0x03 && er->ecm[k+3] == 0x80) {
     823          uint16_t vtier_id = (er->ecm[k+1] << 8) | er->ecm[k+2];
     824          get_tiername(vtier_id, reader->caid, tiername);
     825          rdr_log(reader, "valid tier: %04x %s",vtier_id, tiername);
     826        }
     827      }
     828    */
     829
     830    int32_t new_len = lenECMpart2;
     831    if(reader->fix_9993 && reader->caid == 0x919 && tbuff[1] == 0x7F)
     832    {
     833        tbuff[1] = 0x47;
     834        tbuff[2] = 0x08;
     835        memmove(tbuff + 11, tbuff + 13, new_len - 11);
     836        new_len -= 2;
     837    }
     838    ins40[4] = new_len;
     839    int32_t l;
     840
     841    l = do_cmd(reader, ins40, tbuff, NULL, cta_res);
     842    if(l < 0 || !status_ok(cta_res))
     843    {
     844        rdr_log(reader, "classD0 ins40: (%d) status not ok %02x %02x", l, cta_res[0], cta_res[1]);
     845        rdr_log(reader, "The card is not answering correctly! Restarting reader for safety");
     846        add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
     847        return ERROR;
     848    }
     849    else
     850    {
     851        l = do_cmd(reader, ins54, NULL, rbuff, cta_res);
     852        if(l < 0 || !status_ok(cta_res + l))
     853        {
     854            rdr_log(reader, "classD3 ins54: (%d) status not ok %02x %02x", l, cta_res[0], cta_res[1]);
     855            rdr_log(reader, "The card is not answering correctly! Restarting reader for safety");
     856            add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
     857            return ERROR;
     858        }
     859        else
     860        {
     861
     862            // Log decrypted INS54
     863            rdr_ddump_mask(reader, D_READER, rbuff, 5, "INS54:");
     864            rdr_ddump_mask(reader, D_READER, rbuff + 5, rbuff[4], "Decrypted payload");
     865
     866            if(!cw_is_valid(rbuff + 5))  //sky cards report 90 00 = ok but send cw = 00 when channel not subscribed
     867            {
     868                rdr_log(reader, "classD3 ins54: status 90 00 = ok but cw=00 -> channel not subscribed ");
     869                return ERROR;
     870            }
     871
     872            // copy cw1 in place
     873            memcpy(ea->cw + 0, rbuff + 5, 8);
     874
     875            // process cw2
     876            unsigned char *payload = rbuff + 5;
     877            int32_t payloadLen = rbuff[4];
     878            int32_t ind = 8 + 6; // +8 for CW1, +6 for counter(?)
     879
     880            while(ind < payloadLen)
     881            {
     882                switch(payload[ind])
     883                {
     884                case 0x25:  // CW2
     885                    //cs_dump (payload + ind, payload[ind+1]+2, "INS54 - CW2");
     886                    memcpy(ea->cw + 8, &payload[ind + 3], 8);
     887                    ind += payload[ind + 1] + 2;
     888                    break;
     889
     890                default:
     891                    //cs_dump (payload + ind, payload[ind+1]+2, "INS54");
     892                    ind += payload[ind + 1] + 2;
     893                    break;
     894                }
     895            }
     896
     897            if(new_len != lenECMpart2)
     898            {
     899                memcpy(ea->cw, ea->cw + 8, 8);
     900                memset(ea->cw + 8, 0, 8);
     901            }
     902            // fix for 09ac cards
     903            dimeno_PostProcess_Decrypt(reader, rbuff, ea->cw);
     904
     905            //test for postprocessing marker
     906            int32_t posB0 = -1;
     907            int32_t i;
     908            for(i = 6; i < posECMpart2; i++)
     909            {
     910                if(er->ecm[i - 3] == 0x80 && er->ecm[i] == 0xB0 && ((er->ecm[i + 1] == 0x01) || (er->ecm[i + 1] == 0x02) || (er->ecm[i + 1] == 0x03)))
     911                {
     912                    posB0 = i;
     913                    break;
     914                }
     915            }
     916            if(posB0 != -1)
     917            {
     918                do_post_dw_hash(reader, ea->cw + 0, &er->ecm[posB0 - 2]);
     919                do_post_dw_hash(reader, ea->cw + 8, &er->ecm[posB0 - 2]);
     920            }
     921
     922            if(reader->caid == 0x0907)    //quickfix: cw2 is not a valid cw, something went wrong before
     923            {
     924                memset(ea->cw + 8, 0, 8);
     925                if(er->ecm[0] & 1)
     926                {
     927                    memcpy(ea->cw + 8, ea->cw, 8);
     928                    memset(ea->cw, 0, 8);
     929                }
     930            }
     931            else
     932            {
     933                if(er->ecm[0] & 1)
     934                {
     935                    unsigned char tmpcw[8];
     936                    memcpy(tmpcw, ea->cw + 8, 8);
     937                    memcpy(ea->cw + 8, ea->cw + 0, 8);
     938                    memcpy(ea->cw + 0, tmpcw, 8);
     939                }
     940            }
     941
     942            return OK;
     943        }
     944    }
    942945}
    943946
    944947static int32_t videoguard2_do_emm(struct s_reader *reader, EMM_PACKET *ep)
    945948{
    946     return videoguard_do_emm(reader, ep, 0xD1, vg2_read_tiers, do_cmd);
     949    return videoguard_do_emm(reader, ep, 0xD1, vg2_read_tiers, do_cmd);
    947950}
    948951
    949952static int32_t videoguard2_card_info(struct s_reader *reader)
    950953{
    951     /* info is displayed in init, or when processing info */
    952     struct videoguard_data *csystem_data = reader->csystem_data;
    953     rdr_log(reader, "card detected");
    954     rdr_log(reader, "type: %s", csystem_data->card_desc);
    955     if (reader->ins7e11_fast_reset != 1)
    956     {
    957         vg2_read_tiers(reader);
    958     }
    959     return OK;
     954    /* info is displayed in init, or when processing info */
     955    struct videoguard_data *csystem_data = reader->csystem_data;
     956    rdr_log(reader, "card detected");
     957    rdr_log(reader, "type: %s", csystem_data->card_desc);
     958    if(reader->ins7e11_fast_reset != 1)
     959    {
     960        vg2_read_tiers(reader);
     961    }
     962    return OK;
    960963}
    961964
    962965void reader_videoguard2(struct s_cardsystem *ph)
    963966{
    964     ph->do_emm = videoguard2_do_emm;
    965     ph->do_ecm = videoguard2_do_ecm;
    966     ph->card_info = videoguard2_card_info;
    967     ph->card_init = videoguard2_card_init;
    968     ph->get_emm_type = videoguard_get_emm_type;
    969     ph->get_emm_filter = videoguard_get_emm_filter;
    970     ph->caids[0] = 0x09;
    971     ph->desc = "videoguard2";
     967    ph->do_emm = videoguard2_do_emm;
     968    ph->do_ecm = videoguard2_do_ecm;
     969    ph->card_info = videoguard2_card_info;
     970    ph->card_init = videoguard2_card_init;
     971    ph->get_emm_type = videoguard_get_emm_type;
     972    ph->get_emm_filter = videoguard_get_emm_filter;
     973    ph->caids[0] = 0x09;
     974    ph->desc = "videoguard2";
    972975}
    973976#endif
Note: See TracChangeset for help on using the changeset viewer.