Exemplo n.º 1
0
    def mutual_authenticate(self, p1, p2, mutual_challenge):   
        """
        Takes an encrypted challenge in the form 
        'Terminal Challenge | Card Challenge | Card number'
        and checks it for validity. If the challenge is successful
        the card encrypts 'Card Challenge | Terminal challenge' and
        returns this value
        """
        
        key = self._get_referenced_key(p1, p2)
        card_number = self.get_card_number()

        if (key == None):
            raise SwError(SW["ERR_INCORRECTP1P2"])
        if p1 == 0x00: #No information given
            cipher = get_referenced_cipher(self.cipher)   
        else:
            cipher = get_referenced_cipher(p1)
        
        if (cipher == None):
            raise SwError(SW["ERR_INCORRECTP1P2"])

        plain = vsCrypto.decrypt(cipher, key, mutual_challenge)
        last_challenge_len = len(self.last_challenge)
        terminal_challenge = plain[:last_challenge_len-1]
        card_challenge = plain[last_challenge_len:-len(card_number)-1]
        serial_number = plain[-len(card_number):]
        
        if terminal_challenge != self.last_challenge:
            raise SwError(SW["WARN_NOINFO63"])
        elif serial_number != card_number:
            raise SwError(SW["WARN_NOINFO63"])
        
        result = card_challenge + terminal_challenge
        return SW["NORMAL"], vsCrypto.encrypt(cipher, key, result)
Exemplo n.º 2
0
    def mutual_authenticate(self, p1, p2, mutual_challenge):
        """
        Takes an encrypted challenge in the form 
        'Terminal Challenge | Card Challenge | Card number'
        and checks it for validity. If the challenge is successful
        the card encrypts 'Card Challenge | Terminal challenge' and
        returns this value
        """

        key = self._get_referenced_key(p1, p2)
        card_number = self.get_card_number()

        if (key == None):
            raise SwError(SW["ERR_INCORRECTP1P2"])
        if p1 == 0x00:  #No information given
            cipher = get_referenced_cipher(self.cipher)
        else:
            cipher = get_referenced_cipher(p1)

        if (cipher == None):
            raise SwError(SW["ERR_INCORRECTP1P2"])

        plain = vsCrypto.decrypt(cipher, key, mutual_challenge)
        last_challenge_len = len(self.last_challenge)
        terminal_challenge = plain[:last_challenge_len - 1]
        card_challenge = plain[last_challenge_len:-len(card_number) - 1]
        serial_number = plain[-len(card_number):]

        if terminal_challenge != self.last_challenge:
            raise SwError(SW["WARN_NOINFO63"])
        elif serial_number != card_number:
            raise SwError(SW["WARN_NOINFO63"])

        result = card_challenge + terminal_challenge
        return SW["NORMAL"], vsCrypto.encrypt(cipher, key, result)
Exemplo n.º 3
0
    def external_authenticate(self, p1, p2, resp_data):
        """Performs the basic access control protocol as defined in
        the ICAO MRTD standard"""
        rnd_icc = self.last_challenge

        # Receive Mutual Authenticate APDU from terminal
        # Decrypt data and check MAC
        Eifd = resp_data[:-8]
        padded_Eifd = vsCrypto.append_padding(self.current_SE.cct.blocklength,
                                              Eifd)
        Mifd = vsCrypto.crypto_checksum("CC", self.KMac, padded_Eifd)
        # Check the MAC
        if not Mifd == resp_data[-8:]:
            raise SwError(SW["ERR_SECMESSOBJECTSINCORRECT"])
        # Decrypt the data
        plain = vsCrypto.decrypt("DES3-CBC", self.KEnc, resp_data[:-8])
        if plain[8:16] != rnd_icc:
            raise SwError(SW["WARN_NOINFO63"])
        # Extract keying material from IFD, generate ICC keying material
        Kifd = plain[16:]
        rnd_ifd = plain[:8]
        Kicc = urandom(16)
        # Generate Answer
        data = plain[8:16] + plain[:8] + Kicc
        Eicc = vsCrypto.encrypt("DES3-CBC", self.KEnc, data)
        padded_Eicc = vsCrypto.append_padding(self.current_SE.cct.blocklength,
                                              Eicc)
        Micc = vsCrypto.crypto_checksum("CC", self.KMac, padded_Eicc)
        # Derive the final keys and set the current SE
        KSseed = vsCrypto.operation_on_string(Kicc, Kifd, lambda a, b: a ^ b)
        self.current_SE.ct.key = self.derive_key(KSseed, 1)
        self.current_SE.cct.key = self.derive_key(KSseed, 2)
        self.current_SE.ssc = stringtoint(rnd_icc[-4:] + rnd_ifd[-4:])
        return SW["NORMAL"], Eicc + Micc
Exemplo n.º 4
0
 def encipher(self, p1, p2, data):
     """
     Encipher data using key, algorithm, IV and Padding specified
     by the current Security environment.
     
     :returns: raw data (no TLV coding).
     """
     algo = self.ct.algorithm
     key = self.ct.key
     if key == None or algo == None:
         raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
     else:
         padded = vsCrypto.append_padding(vsCrypto.get_cipher_blocklen(algo), data)
         crypted = vsCrypto.encrypt(algo, key, padded, self.ct.iv)
         return crypted
Exemplo n.º 5
0
 def encipher(self, p1, p2, data):
     """
     Encipher data using key, algorithm, IV and Padding specified
     by the current Security environment.
     
     :returns: raw data (no TLV coding).
     """
     algo = self.ct.algorithm
     key = self.ct.key
     if key == None or algo == None:
         raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
     else:
         padded = vsCrypto.append_padding(vsCrypto.get_cipher_blocklen(algo), data)
         crypted = vsCrypto.encrypt(algo, key, padded, self.ct.iv)
         return crypted
Exemplo n.º 6
0
    def internal_authenticate(self, p1, p2, data):
        """
        Authenticate card to terminal. Encrypt the challenge of the terminal
        to prove key posession
        """

        if p1 == 0x00:  #No information given
            cipher = get_referenced_cipher(self.cipher)
        else:
            cipher = get_referenced_cipher(p1)

        if cipher == "RSA" or cipher == "DSA":
            crypted_challenge = self.asym_key.sign(data, "")
            crypted_challenge = crypted_challenge[0]
            crypted_challenge = inttostring(crypted_challenge)
        else:
            key = self._get_referenced_key(p1, p2)
            crypted_challenge = vsCrypto.encrypt(cipher, key, data)

        return SW["NORMAL"], crypted_challenge
Exemplo n.º 7
0
    def internal_authenticate(self, p1, p2, data):
        """
        Authenticate card to terminal. Encrypt the challenge of the terminal
        to prove key posession
        """
        
        if p1 == 0x00: #No information given
            cipher = get_referenced_cipher(self.cipher)   
        else:
            cipher = get_referenced_cipher(p1)

        if cipher == "RSA" or cipher == "DSA":
            crypted_challenge = self.asym_key.sign(data,"")
            crypted_challenge = crypted_challenge[0]
            crypted_challenge = inttostring(crypted_challenge)
        else:
            key = self._get_referenced_key(p1, p2)
            crypted_challenge = vsCrypto.encrypt(cipher, key, data)
        
        return SW["NORMAL"], crypted_challenge
Exemplo n.º 8
0
 def external_authenticate(self, p1, p2, data):
     """
     Authenticate the terminal to the card. Check whether Terminal correctly
     encrypted the given challenge or not
     """
     if self.last_challenge is None:
         raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
     
     key = self._get_referenced_key(p1, p2) 
     if p1 == 0x00: #No information given
         cipher = get_referenced_cipher(self.cipher)   
     else:
         cipher = get_referenced_cipher(p1)     
     
     reference = vsCrypto.append_padding(cipher, self.last_challenge)
     reference = vsCrypto.encrypt(cipher, key, reference)
     if(reference == data):
         #Invalidate last challenge
         self.last_challenge = None
         return SW["NORMAL"], ""
     else:
         raise SwError(SW["WARN_NOINFO63"])
Exemplo n.º 9
0
 def external_authenticate(self, p1, p2, data):
     """
     Authenticate the terminal to the card. Check whether Terminal correctly
     encrypted the given challenge or not
     """
     if self.last_challenge is None:
         raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
     
     key = self._get_referenced_key(p1, p2) 
     if p1 == 0x00: #No information given
         cipher = get_referenced_cipher(self.cipher)   
     else:
         cipher = get_referenced_cipher(p1)     
     
     reference = vsCrypto.append_padding(cipher, self.last_challenge)
     reference = vsCrypto.encrypt(cipher, key, reference)
     if(reference == data):
         #Invalidate last challenge
         self.last_challenge = None
         return SW["NORMAL"], ""
     else:
         raise SwError(SW["WARN_NOINFO63"])