#!/usr/bin/perl

use warnings;
use strict;
use Chipcard::PCSC;
use Chipcard::PCSC::Card;

my $hcontext = new Chipcard::PCSC();
my @readers_list = $hcontext->ListReaders();
my $hcard = new Chipcard::PCSC::Card ($hcontext, $readers_list[0]);
my $result;

sub pin_to_array {
        my $pin = shift;
        my @array;

        confess ("PIN code must not exceed 8 bytes.") unless (length $pin <= 8);

        $pin =~ s/(.)/$1 /g;
        @array = split / /, $pin;
        @array = map (ord, @array);

        # Pad the array with 0xFF up to 8 bytes
        while ($#array < 7) { push @array, 0xFF; }

        return @array;
}

if (!$hcard) {
   print "[*] no sim card inserted\n";
   exit(-1);
}

if (@ARGV != 1) {
   printf "[*] sim_get_kc.pl [pin]\n";
   exit(-1);
}

# unlock sim
$result = $hcard->Transmit([0xA0, 0x20, 0x00, 0x01, 0x08, pin_to_array($ARGV[0])]);
if ($$result[0] != 0x9f && $$result[0] != 0x90) {
   printf "[*] wrong pin\n";
   exit(-1);
}

# select MF
$result = $hcard->Transmit([0xA0, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00]);
if ($$result[0] != 0x9f) {
   printf "[*] can't select MF\n";
   exit(-1);
}

# select DF GSM
$hcard->Transmit([0xA0, 0xA4, 0x00, 0x00, 0x02, 0x7F, 0x20]);
if ($$result[0] != 0x9f) {
   printf "[*] can't select DF GSM\n";
   exit(-1);
}

# select EF KC
$hcard->Transmit([0xA0, 0xA4, 0x00, 0x00, 0x02, 0x6F, 0x20]);
if ($$result[0] != 0x9f) {
   printf "[*] can't select EF KC\n";
   exit(-1);
}

# read binary - 9 bytes
my $kc = $hcard->Transmit([0xA0, 0xB0, 0x00, 0x00, 0x09]);

my $kc_ascii = "";
for (my $i = 0; $i < 8; $i++) {
   $kc_ascii .= sprintf "%02x", $$kc[$i];
}
print "[*] kc: [" . $kc_ascii . "]\n";

# disconnect
$hcard->Disconnect($Chipcard::PCSC::SCARD_RESET);
