Ejemplo n.º 1
0
        private ByteArray GenerateExAuthMAC(ByteArray command, ByteArray terminalCryptogram)
        {
            ByteArray input  = command.Extract(0, 5) + terminalCryptogram + new ByteArray("80 00 00");
            ByteArray result = input.EncodeAsData(_sessionKeys.SignKey, new ByteArray(8), PaddingMode.None, CipherMode.CBC);

            return(result.LSB(8));
        }
Ejemplo n.º 2
0
        private ByteArray GenerateExAuthMAC2(ByteArray command, ByteArray terminalCryptogram)
        {
            ByteArray input = command.Extract(0, 5) + terminalCryptogram + new ByteArray("80 00 00");

            ByteArray mac_key_left  = _sessionKeys.SignKey.MSB(8); //MSB mac key
            ByteArray mac_key_right = _sessionKeys.SignKey.LSB(8);
            ByteArray iv            = new ByteArray(8, 0x00);

            //ByteArray result = input.EncodeAsData(SessionKeys.SignKey, new ByteArray(8), PaddingMode.None, CipherMode.CBC);
            //ByteArray result = input.EncodeAsData(mac_key_left + mac_key_right, iv, PaddingMode.None, CipherMode.CBC);
            //ByteArray result_comp = result.LSB(8);

            ByteArray apdu_left  = input.MSB(8);
            ByteArray apdu_right = input.LSB(8);

            ByteArray result1 = apdu_left.SimpleEncodeAsData(mac_key_left, iv, PaddingMode.None, CipherMode.CBC);
            ByteArray result2 = result1.XOR(apdu_right);
            ByteArray result3 = result2.SimpleEncodeAsData(mac_key_left, iv, PaddingMode.None, CipherMode.CBC);
            ByteArray result4 = result3.SimpleDecodeAsData(mac_key_right, iv, PaddingMode.None, CipherMode.CBC);
            ByteArray result5 = result4.SimpleEncodeAsData(mac_key_left, iv, PaddingMode.None, CipherMode.CBC);

            Logger.Log("[JavaCard] Wyliczanie MAC dla APDU {0} (kolejne wyniki algorytmu DES)\n{1}\n{2}\n{3}\n{4}\n{5}", input, result1, result2, result3, result4, result5);

            return(result5);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Dywersyfikuje klucze CM metodą GPIC_Serial
        /// </summary>
        /// <param name="motherKey">Klucz matka do dywersyfikacji</param>
        /// <param name="initUpdateResponse"> </param>
        /// <returns>Klucze Auth, Sign, KEK</returns>
        public JavaCardKeys GPICSerialDiversificate(ByteArray motherKey, ByteArray initUpdateResponse)
        {
            ByteArray diversificationData = initUpdateResponse.Extract(0, 2) + initUpdateResponse.Extract(4, 4);

            ByteArray[] keys           = new ByteArray[3];
            ByteArray   authEncDivData = diversificationData + new ByteArray("f0 01") + diversificationData + new ByteArray("0f 01");

            keys[0] = authEncDivData.EncodeAsData(motherKey, new ByteArray(8), PaddingMode.None, CipherMode.ECB);
            ByteArray sigDivData = diversificationData + new ByteArray("f0 02") + diversificationData + new ByteArray("0f 02");

            keys[1] = sigDivData.EncodeAsData(motherKey, new ByteArray(8), PaddingMode.None, CipherMode.ECB);
            ByteArray kekDivData = diversificationData + new ByteArray("f0 03") + diversificationData + new ByteArray("0f 03");

            keys[2] = kekDivData.EncodeAsData(motherKey, new ByteArray(8), PaddingMode.None, CipherMode.ECB);
            return(new JavaCardKeys(keys));
        }
Ejemplo n.º 4
0
 public static ByteArray Encrypt(ByteArray data, ByteArray key, ref ByteArray iv)
 {
     using (var memoryStream = new MemoryStream())
     {
         using (var aes = new AesManaged {
             Key = key.ByteData, IV = iv.ByteData, Padding = PaddingMode.None, Mode = CipherMode.CBC
         })
         {
             using (var cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write))
             {
                 cryptoStream.Write(data.ByteData, 0, data.Length);
             }
         }
         ByteArray result = new ByteArray(memoryStream.ToArray());
         iv = new ByteArray(result.Extract(result.Length - 16, 16).ByteData);
         return(result);
     }
 }
Ejemplo n.º 5
0
 public static ByteArray Decrypt(ByteArray encrypted, ByteArray key, ref ByteArray iv)
 {
     using (var memoryStream = new MemoryStream(encrypted.ByteData))
     {
         using (var aes = new AesManaged {
             Key = key.ByteData, IV = iv.ByteData, Padding = PaddingMode.None, Mode = CipherMode.CBC
         })
         {
             using (var cryptoStream = new CryptoStream(memoryStream, aes.CreateDecryptor(), CryptoStreamMode.Read))
             {
                 byte[] decrypt = new byte[encrypted.Length];
                 cryptoStream.Read(decrypt, 0, decrypt.Length);
                 ByteArray result = new ByteArray(decrypt);
                 iv = new ByteArray(encrypted.Extract(encrypted.Length - 16, 16).ByteData);
                 return(result);
             }
         }
     }
 }
Ejemplo n.º 6
0
        public ByteArray ListApplications()
        {
            // p1 = 80, 40, 20, 10
            // p2 = xxxxxxx0 - first or all, xxxxxxx1 - next, xxxxxx0x - less info, xxxxxx1x - more info
            try
            {
                ByteArray apdu     = new ByteArray("80 F2 80 00 02 4F 00 00");
                ByteArray response = SendSecuredCommand(apdu);
                //return response;


                apdu     = new ByteArray("80 F2 40 00 02 4F 00 00");
                response = SendSecuredCommand(apdu);
                //return response;



                apdu      = new ByteArray("80 F2 20 00 02 4F 00 00");
                response  = SendSecuredCommand(apdu);
                apdu      = new ByteArray("80 F2 20 01 02 4F 00 00");
                response  = response.Extract(0, response.Length - 2);
                response += SendSecuredCommand(apdu);

                return(response);



                apdu     = new ByteArray("80 F2 10 00 02 4F 00 00");
                response = SendSecuredCommand(apdu);
                return(response);
            }
            catch (APDUException exception)
            {
                return(null);
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Uwierzytelnia do CM podanym kluczem
        /// </summary>
        public JavaCardKeys StartSecuredChannel(ByteArray motherKey, KeyDiversificationMethod diversification = KeyDiversificationMethod.None, SecurityControlMode securityMode = SecurityControlMode.NoSecurity, byte keyVersion = 0x00, byte referenceControlParameter2 = 0x00)
        {
            try
            {
                //losowanie danych terminala
                ByteArray terminalRandom = new ByteArray(8);
                terminalRandom.Randomize(random);

                //Initialize Update
                ByteArray response = InitializeUpdate(keyVersion, 00, terminalRandom);

                //z odpowiedzi wyciągamy dane
                byte scpId = response[11];
                if (scpId == 0x01)
                {
                    scp = SecureChannelProtocol.SCP01;
                }
                else if (scpId == 0x02)
                {
                    scp = SecureChannelProtocol.SCP02;
                }
                ByteArray sn             = response.Extract(4, 4);
                ByteArray aid            = response.Extract(0, 2);
                ByteArray cardRandom     = response.Extract(12, 8);
                ByteArray cardCryptogram = response.Extract(20, 8);

                Logger.Log("[JavaCard] \n{0}:\t{1}\n{2}:\t{3}\n{4}:\t{5}\n{6}:\t{7}\n{8}:\t{9}", "TerminalRandom", terminalRandom, "SN", sn, "AID", aid, "CardRandom", cardRandom, "CardCryptogram", cardCryptogram);

                //wyliczanie kluczy z matki
                switch (diversification)
                {
                case KeyDiversificationMethod.None:
                    Keys = new JavaCardKeys(motherKey);
                    break;

                case KeyDiversificationMethod.GPICSN:
                    Keys = GPICSerialDiversificate(motherKey, response);
                    break;

                case KeyDiversificationMethod.MPCOS3DES:
                    throw new Exception("Wybrany algorytm dywersyfikacji nie jest na razie wspierany");
                    break;

                case KeyDiversificationMethod.TagCF:
                    Keys = TagCFDiversificate(motherKey, response);
                    break;
                }

                //wyliczamy klucze sesyjne AUTH/ENC i MAC
                if (scp == SecureChannelProtocol.SCP01)
                {
                    ComputeSessionKeys(Keys, terminalRandom, cardRandom);
                }
                else if (scp == SecureChannelProtocol.SCP02)
                {
                    ComputeSessionKeys2(Keys, terminalRandom, cardRandom);
                }
                else
                {
                    throw new Exception("Nieobsługiwany protokół bezpiecznego kanału");
                }

                //weryfikujemy kryptogram zwrócony przez InitializeUpdate
                if (!CheckCardCryptogram(cardCryptogram, terminalRandom, cardRandom))
                {
                    throw new JavaCardAuthenticationException("Kryptogram zwrócony przez komendę InitializeUpdate nie zgadza się.");
                }

                //ExternalAuthenticate
                ByteArray externalAuthenticateCommand = new ByteArray("84 82") + (byte)securityMode + new ByteArray("00 10");
                ByteArray terminalCryptogram          = GenerateTerminalCryptogram(terminalRandom, cardRandom);
                ByteArray MAC = new ByteArray();
                if (scp == SecureChannelProtocol.SCP01)
                {
                    MAC = GenerateExAuthMAC(externalAuthenticateCommand, terminalCryptogram);
                }
                else if (scp == SecureChannelProtocol.SCP02)
                {
                    MAC = GenerateExAuthMAC2(externalAuthenticateCommand, terminalCryptogram);
                }
                ByteArray fullExternalAuthenticateCommand = externalAuthenticateCommand + terminalCryptogram + MAC;
                Encoder.SendCommand(fullExternalAuthenticateCommand);

                _securityMode = securityMode;
                _lastMAC      = MAC;
                _authenticatedKeySetVersion = response[10];
            }
            catch (APDUException exception)
            {
                _sessionKeys  = null;
                _securityMode = SecurityControlMode.NoSecurity;
                throw new JavaCardAuthenticationException("Błąd ustanowienia bezpiecznego kanału.", exception);
            }
            catch (Exception exception)
            {
                _sessionKeys  = null;
                _securityMode = SecurityControlMode.NoSecurity;
                throw new JavaCardAuthenticationException("Błąd ustanowienia bezpiecznego kanału.", exception);
            }

            return(_sessionKeys);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Wysyła polecenie apdu bezpiecznym kanałem
        /// </summary>
        /// <param name="command">apdu</param>
        /// <returns></returns>
        public ByteArray SendSecuredCommand(ByteArray command)
        {
            byte      CLA, INS, P1, P2, Lc, Le;
            Boolean   hasLe = false;
            ByteArray data  = new ByteArray();

            Logger.Log("[JavaCard] +> " + command);

            //rozbijamy APDU na części składowe
            CLA = command[0];
            INS = command[1];
            P1  = command[2];
            P2  = command[3];
            Lc  = 0x00;
            Le  = 0x00;
            if (command.Length == 5)
            {
                Le    = command[4];
                hasLe = true;
            }
            else if (command.Length > 5)
            {
                Lc   = command[4];
                data = command.Extract(5, Lc);
                if (command.Length > Lc + 5)
                {
                    Le    = command[command.Length - 1];
                    hasLe = true;
                }
            }

            ByteArray commandToSend = new ByteArray(command.ByteData);

            if (_securityMode == SecurityControlMode.MAC)
            {
                ByteArray toMac = new ByteArray(new byte[] { (byte)(CLA | 0x04), INS, P1, P2, (byte)(Lc + 8) }) + data; //Lc zwiększamy o 8 - długość MACa
                commandToSend = new ByteArray(toMac.StringData);

                //macujemy
                ByteArray macData = MacData(toMac);
                _lastMAC       = macData.LSB(8);
                commandToSend += _lastMAC;

                if (hasLe)
                {
                    commandToSend += Le;
                }
            }
            else if (_securityMode == SecurityControlMode.MACAndEncryption)
            {
                //szyfrujemy
                ByteArray toEncrypt     = data;
                ByteArray encryptedData = EncryptData(toEncrypt);

                //macujemy
                ByteArray toMac   = new ByteArray(new byte[] { (byte)(CLA | 0x04), INS, P1, P2, (byte)(Lc + 8) }) + data;
                ByteArray macData = MacData(toMac);
                _lastMAC = macData.LSB(8);

                commandToSend = new ByteArray(new byte[] { (byte)(CLA | 0x04), INS, P1, P2, (byte)(encryptedData.Length + _lastMAC.Length) }) + encryptedData + _lastMAC;
                if (hasLe)
                {
                    commandToSend += Le;
                }
            }

            return(Encoder.SendCommand(commandToSend));
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Uwierzytelnia do CM podanymi kluczami
        /// </summary>
        /// <param name="keys">Klucze</param>
        /// <param name="keySet"></param>
        /// <param name="keyIndex"></param>
        /// <param name="securityMode"></param>
        public JavaCardKeys StartSecuredChannel(JavaCardKeys keys, SecurityControlMode securityMode, Byte keySet = 0, Byte keyIndex = 0)
        {
            try
            {
                //losowanie danych terminala
                ByteArray terminalRandom = new ByteArray(8);
                terminalRandom.Randomize(random);
                //terminalRandom = new ByteArray("00 00 00 00 00 00 00 00");

                //Initialize Update
                ByteArray initializeUpdateCommand = new ByteArray("80 50 00 00 08") + terminalRandom + new ByteArray("00");
                initializeUpdateCommand[2] = keySet;
                initializeUpdateCommand[3] = keyIndex;

                ByteArray response = Encoder.SendCommand(initializeUpdateCommand);

                //z odpowiedzi wyciągamy losowe dane karty i kryptogram
                ByteArray cardRandom     = response.Extract(12, 8);
                ByteArray cardCryptogram = response.Extract(20, 8);

                byte scpId = response[11];
                if (scpId == 0x01)
                {
                    scp = SecureChannelProtocol.SCP01;
                }
                else if (scpId == 0x02)
                {
                    scp = SecureChannelProtocol.SCP02;
                }

                //wyliczamy klucze sesyjne AUTH/ENC i MAC
                if (scp == SecureChannelProtocol.SCP01)
                {
                    ComputeSessionKeys(Keys, terminalRandom, cardRandom);
                }
                else if (scp == SecureChannelProtocol.SCP02)
                {
                    ComputeSessionKeys2(Keys, terminalRandom, cardRandom);
                }
                else
                {
                    throw new Exception("Nieobsługiwany protokół bezpiecznego kanału");
                }

                //weryfikujemy kryptogram zwrócony przez InitializeUpdate
                if (!CheckCardCryptogram(cardCryptogram, terminalRandom, cardRandom))
                {
                    throw new JavaCardAuthenticationException("Kryptogram zwrócony przez komendę InitializeUpdate nie zgadza się.");
                }

                //ExternalAuthenticate
                ByteArray externalAuthenticateCommand = new ByteArray("84 82") + (byte)securityMode + new ByteArray("00 10");
                ByteArray terminalCryptogram          = GenerateTerminalCryptogram(terminalRandom, cardRandom);
                ByteArray MAC = GenerateExAuthMAC(externalAuthenticateCommand, terminalCryptogram);

                ByteArray fullExternalAuthenticateCommand = externalAuthenticateCommand + terminalCryptogram + MAC;
                Encoder.SendCommand(fullExternalAuthenticateCommand);
                _securityMode = securityMode;
                _lastMAC      = MAC;
                _authenticatedKeySetVersion = response[10];
            }
            catch (APDUException exception)
            {
                _sessionKeys  = null;
                _securityMode = SecurityControlMode.NoSecurity;
                throw new JavaCardAuthenticationException("Błąd ustanowienia bezpiecznego kanału.", exception);
            }
            catch (Exception exception)
            {
                _sessionKeys  = null;
                _securityMode = SecurityControlMode.NoSecurity;
                throw new JavaCardAuthenticationException("Błąd ustanowienia bezpiecznego kanału.", exception);
            }
            return(_sessionKeys);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Wysyła do karty polecenie APDU
        /// </summary>
        /// <param name="command">Polecenie APDU</param>
        /// <param name="checkSuccessful">Ma sprawdzać, czy odpowiedź jest poprawna (90 00)</param>
        /// <exception cref="APDUException"></exception>
        /// <returns>Odpowiedź na polecenie APDU</returns>
        public ByteArray SendCommand(ByteArray command, bool checkSuccessful = true)
        {
            ConnectCard(false);

            CardCommandAPDU apdu = null;

            if (command.Length == 4)
            {
                apdu = new CardCommandAPDU(command[0], command[1], command[2], command[3]);
            }
            else if (command.Length == 5)
            {
                apdu = new CardCommandAPDU(command[0], command[1], command[2], command[3], command[4]);
            }
            else if (command.Length > 5)
            {
                ByteArray data   = command.Extract(5, command[4]);
                int       length = 5 + command[4];
                if (length == command.Length)
                {
                    apdu = new CardCommandAPDU(command[0], command[1], command[2], command[3], data.ByteData);
                }
                else
                {
                    apdu = new CardCommandAPDU(command[0], command[1], command[2], command[3], data.ByteData, command[command.Length - 1]);
                }
            }

            if (apdu == null)
            {
                throw new Exception("Nieprawidłowa komenda APDU: " + command);
            }

            int tryCounter            = 5;
            CardResponseAPDU response = null;

            do
            {
                try
                {
                    Logger.Log("[Encoder] -> " + command);
                    response = CardHandle.SendCommand(apdu);
                    break;
                }
                catch (System.Runtime.InteropServices.COMException comException)
                {
                    tryCounter--;
                    if (tryCounter == 0)
                    {
                        throw new Exception("Sprzętowy błąd wykonywania komendy APDU (Message: " + comException.Message + ", HResult: " + comException.ErrorCode + ")");
                    }
                }
                catch (SCardException scException)
                {
                    tryCounter--;
                    if (tryCounter == 0)
                    {
                        throw new Exception("Sprzętowy błąd wykonywania komendy APDU (Kod: " + scException.ResponseCode + ").", scException);
                    }
                }
                catch (Exception terminalException)
                {
                    tryCounter--;
                    if (tryCounter == 0)
                    {
                        throw new Exception("Sprzętowy błąd wykonywania komendy APDU.", terminalException);
                    }
                }
            } while (true);

            ByteArray result = new ByteArray(response.GenerateBytes());

            Logger.Log("[Encoder] <- " + result);

            if (checkSuccessful && !response.IsSuccessful && !response.IsWarning)
            {
                throw new APDUException("Błąd wykonywania komendy APDU", command, new ByteArray(response.GenerateBytes()), response.SW1, response.SW2);
            }

            return(result);
        }