예제 #1
0
 def _mac(key, data, ssc=None, dopad=True):
     if ssc:
         data = ssc + data
     if dopad:
         topad = 8 - len(data) % 8
         data = data + "\x80" + ("\x00" * (topad - 1))
     a = crypto_utils.cipher(True, "des-cbc", key[:8], data, "\x00" * 8)
     b = crypto_utils.cipher(False, "des-ecb", key[8:16], a[-8:])
     c = crypto_utils.cipher(True, "des-ecb", key[:8], b)
     return c
 def _mac(key, data, ssc = None, dopad=True):
     if ssc:
         data = ssc + data
     if dopad:
         topad = 8 - len(data) % 8
         data = data + "\x80" + ("\x00" * (topad-1))
     a = crypto_utils.cipher(True, "des-cbc", key[:8], data)
     b = crypto_utils.cipher(False, "des-ecb", key[8:16], a[-8:])
     c = crypto_utils.cipher(True, "des-ecb", key[:8], b)
     return c
예제 #3
0
 def encrypt_command(self, tlv_data):
     config = self.get_config(SE_APDU, TEMPLATE_CT)
     
     if config.algorithm is None: ## FIXME: Find out the correct way to determine this
         return tlv_data
     
     result = []
     for data in tlv_data:
         tag, length, value, marks = data
         if self.MARK_ENCRYPT in marks and tag not in (0xff, 0x00):
             t = tag & ~(0x01)
             if t == 0x84:
                 value_ = self.pad(value)
                 if generic_card.DEBUG:
                     print "| Tag 0x%02x, length 0x%02x, encrypting (with ISO padding): " % (tag, length)
                     print "|| " + "\n|| ".join( utils.hexdump( value_ ).splitlines() )
                 
                 value = crypto_utils.cipher( True, 
                     self.get_cipherspec(config),
                     self.get_key(config),
                     value_,
                     self.get_iv(config) )
                 
                 if generic_card.DEBUG:
                     print "| Encrypted result of length 0x%02x:" % len(value)
                     print "|| " + "\n|| ".join( utils.hexdump(value).splitlines() )
                     print
             elif t == 0x86:
                 pi = value[0]
                 value_ = self.pad(value[1:], ord(pi))
                 if generic_card.DEBUG:
                     print "| Tag 0x%02x, length 0x%02x, encrypting (with padding type %x): " % (tag, length, ord(pi))
                     print "|| " + "\n|| ".join( utils.hexdump( value_ ).splitlines() )
                 
                 value = pi + crypto_utils.cipher( True,
                     self.get_cipherspec(config),
                     self.get_key(config),
                     value_,
                     self.get_iv(config) )
                 
                 if generic_card.DEBUG:
                     print "| Encrypted result of length 0x%02x:" % len(value)
                     print "|| " + "\n|| ".join( utils.hexdump(value).splitlines() )
                     print
             
             result.append( (tag, length, value) )
         else: # Ignore
             result.append(data[:3])
     
     return result
예제 #4
0
 def cmd_enc(self, *args):
     "Encrypt or decrypt with openssl-like interface"
     
     args = list(args)
     
     MODE_DECRYPT = "-d"
     MODE_ENCRYPT = "-e"
     mode = MODE_ENCRYPT
     if "-d" in args:
         mode = MODE_DECRYPT
     
     input = None
     if "-in" in args:
         i = args.index("-in")
         input = args[i+1]
     
     if "-K" not in args:
         raise ValueError, "Must specify key with -K"
     i = args.index("-K")
     key = args[i+1]
     key = binascii.a2b_hex("".join(key.split()))
     
     iv = None
     if "-iv" in args:
         i = args.index("-iv")
         iv = args[i+1]
         iv = binascii.a2b_hex("".join(iv.split()))
     
     cipher = "des"
     if args[0][0] != "-":
         cipher = args[0]
     
     text = None
     if "-text" in args:
         if input is not None:
             raise ValueError, "Can't give -in and -text"
         i = args.index("-text")
         text = binascii.a2b_hex("".join(args[i+1].split()))
     
     if text is None:
         if input is None:
             text = self.card.last_result.data
         else:
             fp = file(input)
             text = fp.read()
             fp.close()
     
     result = crypto_utils.cipher(mode == MODE_ENCRYPT, cipher, key, text, iv)
     
     self.card.last_result = utils.R_APDU(result+"\x00\x00")
     print utils.hexdump(result)
 def cmd_perform_bac(self, mrz2, verbose=1):
     "Perform the Basic Acess Control authentication and establishment of session keys"
     mrz2 = mrz2.upper()
     Kseed = self.derive_seed(mrz2, verbose)
     Kenc = self.derive_key(Kseed, 1)
     Kmac = self.derive_key(Kseed, 2)
     if verbose:
         print "Kenc    = %s" % hexdump(Kenc)
         print "Kmac    = %s" % hexdump(Kmac)
         
         print
     result = self.send_apdu(self.APDU_GET_RANDOM)
     if not self.check_sw(result.sw):
         raise BACError, "SW after GET RANDOM was %02x%02x. Card refused to send rcd_icc. Should NEVER happen." % (result.sw1, result.sw2)
     
     rnd_icc = result.data
     if verbose:
         print "RND.icc = %s" % hexdump(rnd_icc)
     
     rndtmp = self._make_random(8 + 16)
     rnd_ifd = rndtmp[:8]
     Kifd = rndtmp[8:]
     if verbose:
         print "RND.ifd = %s" % hexdump(rnd_ifd)
         print "Kifd    = %s" % hexdump(Kifd, indent=10)
     
     S = rnd_ifd + rnd_icc + Kifd
     Eifd = crypto_utils.cipher(True, "des3-cbc", Kenc, S)
     Mifd = self._mac(Kmac, Eifd)
     if verbose:
         print "Eifd    = %s" % hexdump(Eifd, indent=10)
         print "Mifd    = %s" % hexdump(Mifd)
         
         print
     auth_apdu = C_APDU(self.APDU_MUTUAL_AUTHENTICATE, data = Eifd + Mifd)
     result = self.send_apdu(auth_apdu)
     if not self.check_sw(result.sw):
         raise BACError, "SW after MUTUAL AUTHENTICATE was %02x%02x. Card did not accept our BAC attempt" % (result.sw1, result.sw2)
     
     resp_data = result.data
     Eicc = resp_data[:-8]
     Micc = self._mac(Kmac, Eicc)
     if not Micc == resp_data[-8:]:
         raise ValueError, "Passport authentication failed: Wrong MAC on incoming data during Mutual Authenticate"
     
     if verbose:
         print "Eicc    = %s" % hexdump(Eicc, indent=10)
         print "Micc    = %s" % hexdump(Micc)
         print "Micc verified OK"
     
     R = crypto_utils.cipher(False, "des3-cbc", Kenc, Eicc)
     if verbose:
         print "R       = %s" % hexdump(R, indent=10)
     if not R[:8] == rnd_icc:
         raise BACError, "Passport authentication failed: Wrong RND.icc on incoming data during Mutual Authenticate"
     if not R[8:16] == rnd_ifd:
         raise BACError, "Passport authentication failed: Wrong RND.ifd on incoming data during Mutual Authenticate"
     Kicc = R[16:]
     
     if verbose:
         print "Kicc    = %s" % hexdump(Kicc)
         print
     
     KSseed = crypto_utils.operation_on_string(Kicc, Kifd, lambda a,b: a^b)
     self.KSenc = self.derive_key(KSseed, 1)
     self.KSmac = self.derive_key(KSseed, 2)
     self.ssc = rnd_icc[-4:] + rnd_ifd[-4:]
     
     if False:
         self.KSenc = binascii.a2b_hex("979EC13B1CBFE9DCD01AB0FED307EAE5")
         self.KSmac = binascii.a2b_hex("F1CB1F1FB5ADF208806B89DC579DC1F8")
         self.ssc =   binascii.a2b_hex("887022120C06C226")
     
     if verbose:
         print "KSseed  = %s" % hexdump(KSseed)
         print "KSenc   = %s" % hexdump(self.KSenc)
         print "KSmac   = %s" % hexdump(self.KSmac)
         print "ssc     = %s" % hexdump(self.ssc)
     
     self.se = Passport_Security_Environment(self)
예제 #6
0
 def _mac(self, config, data):
     return crypto_utils.cipher( True, 
         self.get_cipherspec(config),
         self.get_key(config),
         data,
         self.get_iv(config) )[-8:]
예제 #7
0
 def decrypt_response(self, tlv_data):
     config = self.get_config(SE_RAPDU, TEMPLATE_CT)
     
     if config.algorithm is None: ## FIXME: Find out the correct way to determine this
         return tlv_data
     
     result = []
     
     for data in tlv_data:
         tag, length, value = data[:3]
         marks = len(data) > 3 and data[3] or ()
         t = tag & ~(0x01)
         if t == 0x84:
             if generic_card.DEBUG:
                 print
                 print "| Tag 0x%02x, length 0x%02x, encrypted (with ISO padding): " % (tag, length)
                 print "|| " + "\n|| ".join( utils.hexdump( value ).splitlines() )
             
             value_ = crypto_utils.cipher( False, 
                 self.get_cipherspec(config),
                 self.get_key(config),
                 value,
                 self.get_iv(config) )
             
             if generic_card.DEBUG:
                 print "| Decrypted result of length 0x%02x:" % len(value_)
                 print "|| " + "\n|| ".join( utils.hexdump(value_).splitlines() )
             
             value = self.unpad(value_)
             
             if False:
                 print "| Depadded result of length 0x%02x:" % len(value)
                 print "|| " + "\n|| ".join( utils.hexdump(value).splitlines() )
             marks = marks + (self.MARK_ENCRYPT,)
         elif t == 0x86:
             pi = value[0]
             if generic_card.DEBUG:
                 print
                 print "| Tag 0x%02x, length 0x%02x, decrypting (with padding type %x): " % (tag, length, ord(pi))
                 print "|| " + "\n|| ".join( utils.hexdump( value[1:] ).splitlines() )
             
             value_ = crypto_utils.cipher( False,
                 self.get_cipherspec(config),
                 self.get_key(config),
                 value[1:],
                 self.get_iv(config) )
             
             if generic_card.DEBUG:
                 print "| Decrypted result of length 0x%02x:" % len(value_)
                 print "|| " + "\n|| ".join( utils.hexdump(value_).splitlines() )
             
             value = self.unpad(value_, ord(pi))
             
             if False:
                 print "| Depadded result of length 0x%02x:" % len(value)
                 print "|| " + "\n|| ".join( utils.hexdump(value).splitlines() )
             
             value = pi + value
             marks = marks + (self.MARK_ENCRYPT,)
         
         result.append( (tag, length, value, marks) )
     
     return result
예제 #8
0
    def cmd_perform_bac(self, mrz2, verbose=1):
        "Perform the Basic Acess Control authentication and establishment of session keys"
        mrz2 = mrz2.upper()
        Kseed = self.derive_seed(mrz2, verbose)
        Kenc = self.derive_key(Kseed, 1)
        Kmac = self.derive_key(Kseed, 2)
        if verbose:
            print "Kenc    = %s" % hexdump(Kenc)
            print "Kmac    = %s" % hexdump(Kmac)

            print
        result = self.send_apdu(self.APDU_GET_RANDOM)
        if not self.check_sw(result.sw):
            raise BACError, "SW after GET RANDOM was %02x%02x. Card refused to send rcd_icc. Should NEVER happen." % (
                result.sw1, result.sw2)

        rnd_icc = result.data
        if verbose:
            print "RND.icc = %s" % hexdump(rnd_icc)

        rndtmp = self._make_random(8 + 16)
        rnd_ifd = rndtmp[:8]
        Kifd = rndtmp[8:]
        if verbose:
            print "RND.ifd = %s" % hexdump(rnd_ifd)
            print "Kifd    = %s" % hexdump(Kifd, indent=10)

        S = rnd_ifd + rnd_icc + Kifd
        Eifd = crypto_utils.cipher(True, "des3-cbc", Kenc, S, "\x00" * 8)
        Mifd = self._mac(Kmac, Eifd)
        if verbose:
            print "Eifd    = %s" % hexdump(Eifd, indent=10)
            print "Mifd    = %s" % hexdump(Mifd)

            print
        auth_apdu = C_APDU(self.APDU_MUTUAL_AUTHENTICATE, data=Eifd + Mifd)
        result = self.send_apdu(auth_apdu)
        if not self.check_sw(result.sw):
            raise BACError, "SW after MUTUAL AUTHENTICATE was %02x%02x. Card did not accept our BAC attempt" % (
                result.sw1, result.sw2)

        resp_data = result.data
        Eicc = resp_data[:-8]
        Micc = self._mac(Kmac, Eicc)
        if not Micc == resp_data[-8:]:
            raise ValueError, "Passport authentication failed: Wrong MAC on incoming data during Mutual Authenticate"

        if verbose:
            print "Eicc    = %s" % hexdump(Eicc, indent=10)
            print "Micc    = %s" % hexdump(Micc)
            print "Micc verified OK"

        R = crypto_utils.cipher(False, "des3-cbc", Kenc, Eicc, "\x00" * 8)
        if verbose:
            print "R       = %s" % hexdump(R, indent=10)
        if not R[:8] == rnd_icc:
            raise BACError, "Passport authentication failed: Wrong RND.icc on incoming data during Mutual Authenticate"
        if not R[8:16] == rnd_ifd:
            raise BACError, "Passport authentication failed: Wrong RND.ifd on incoming data during Mutual Authenticate"
        Kicc = R[16:]

        if verbose:
            print "Kicc    = %s" % hexdump(Kicc)
            print

        KSseed = crypto_utils.operation_on_string(Kicc, Kifd,
                                                  lambda a, b: a ^ b)
        self.KSenc = self.derive_key(KSseed, 1)
        self.KSmac = self.derive_key(KSseed, 2)
        self.ssc = rnd_icc[-4:] + rnd_ifd[-4:]

        if False:
            self.KSenc = binascii.a2b_hex("979EC13B1CBFE9DCD01AB0FED307EAE5")
            self.KSmac = binascii.a2b_hex("F1CB1F1FB5ADF208806B89DC579DC1F8")
            self.ssc = binascii.a2b_hex("887022120C06C226")

        if verbose:
            print "KSseed  = %s" % hexdump(KSseed)
            print "KSenc   = %s" % hexdump(self.KSenc)
            print "KSmac   = %s" % hexdump(self.KSmac)
            print "ssc     = %s" % hexdump(self.ssc)

        self.se = Passport_Security_Environment(self)