public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;

            if (apdu.P1 != 0 || apdu.P2 != 0)
                return Error.P1OrP2NotValid;

            if (apdu.Data == null || apdu.Data.Length == 0)
                return Error.DataFieldNotValid;

            if (context.CurEF == null)
                return Error.NoCurrentEFSelected;

            if (!(context.CurEF is EFRecord))
                return Error.CommandIncompatibleWithFileStructure;

            var efRec = context.CurEF as EFRecord;

            if (!handler.IsVerifiedAC(efRec,EF_AC.AC_APPEND))
                return Error.SecurityStatusNotSatisfied;

            int recNum=efRec.Append(apdu.Data);
            context.CurRecord = recNum;

            return Error.Ok;
        }
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;
            
            if (context.CurEF == null)
                return Error.NoCurrentEFSelected;

            if (!(context.CurEF is EFBinary))
                return Error.CommandIncompatibleWithFileStructure;

            var efBin=context.CurEF as EFBinary;

            if (!handler.IsVerifiedAC(efBin,EF_AC.AC_UPDATE))
                return Error.SecurityStatusNotSatisfied;

            var offset = (apdu.P1 << 8) | apdu.P2;
            if (efBin.Data.Length<offset+apdu.Data.Length)
                return Error.WrongLength;

            if (apdu.Data==null || apdu.Data.Length==0)
                return Error.DataFieldNotValid;

            Array.Copy(apdu.Data, 0, efBin.Data, offset, apdu.Data.Length);

            return Error.Ok;
        }
        public void getSMKeys(Apdu apdu, out BSO sigIn, out BSO encIn, out BSO sigOut, out BSO encOut)
        {
            CardContext context = handler.Context;

            sigIn = null;
            encIn = null;
            sigOut = null;
            encOut = null;

            ushort pinId = (ushort)(apdu.P2 & 0x7f);
            BSO pin = null;
            if (pinId != 0)
            {
                bool backTrack = (apdu.P2 & 0x80) != 0;
                if (backTrack)
                    pin = context.CurDF.GetChildBSO(pinId, backTrack);
                else
                    pin = context.CurDF.Owner.MasterFile.GetChildBSO(pinId, false);
            }
            else
                pin = handler.GetEnvironmentKey(SecurityEnvironmentComponent.TEST);

            if (pin == null)
                throw new ISO7816Exception(Error.ObjectNotFound);

            encIn = handler.getSMKey(pin, BSO_SM.SM_ENC_USE);
            sigIn = handler.getSMKey(pin, BSO_SM.SM_SIG_USE);

        }
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;
            
            if (context.CurEF == null)
                return Error.NoCurrentEFSelected;

            if (apdu.Data != null && apdu.Data.Length > 0)
                return Error.DataFieldNotValid;

            if (!(context.CurEF is EFBinary))
                return Error.CommandIncompatibleWithFileStructure;

            var efBin=context.CurEF as EFBinary;

            if (!handler.IsVerifiedAC(efBin, EF_AC.AC_READ))
                return Error.SecurityStatusNotSatisfied;

            var offset = (apdu.P1 << 8) | apdu.P2;
            int len = 0;
            if (apdu.UseLE) {
                if (apdu.LE == 0) len = 256;
                else len = apdu.LE;
            }
            if (efBin.Data.Length < offset)
                return Error.P1OrP2NotValid;

            if (efBin.Data.Length < offset + len)
                len = efBin.Data.Length - offset;

            return Util.Response(efBin.Data, offset, len, Error.Ok);
        }
 public void getSMKeys(Apdu apdu, out BSO sigIn, out BSO encIn, out BSO sigOut, out BSO encOut)
 {
     sigIn = null;
     encIn = null;
     sigOut = null;
     encOut = null;
 }
        public void getSMKeys(Apdu apdu, out BSO sigIn, out BSO encIn, out BSO sigOut, out BSO encOut)
        {
            CardContext context = handler.Context;

            sigIn = null;
            encIn = null;
            sigOut = null;
            encOut = null;


            ushort bsoId = (ushort)(apdu.P2 & 0x7f);
            bool backTrack = (apdu.P2 & 0x80) != 0;
            BSO bso = null;
            if (backTrack)
                bso = context.CurDF.GetChildBSO(bsoId, backTrack);
            else
                bso = context.CurDF.Owner.MasterFile.GetChildBSO(bsoId, false);

            if (bso == null) 
                throw new ISO7816Exception(Error.ObjectNotFound);

            encIn = handler.getSMKey(bso, BSO_SM.SM_ENC_UNBLOCK);
            sigIn = handler.getSMKey(bso, BSO_SM.SM_SIG_UNBLOCK);

        }
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;
            if (apdu.P1 != 0 && 
                apdu.P1 != 1 && 
                apdu.P1 != 3) return Error.P1OrP2NotValid;
            bool setNewPin = apdu.P1 == 0;
            bool verifyPin = apdu.P1 != 3;

            if (apdu.P1 == 3 && (apdu.Data != null && apdu.Data.Length > 0))
                return Error.DataFieldNotValid;

            ushort bsoId = (ushort)(apdu.P2 & 0x7f);
            bool backTrack = (apdu.P2 & 0x80) != 0;
            BSO bso = null;
            if (backTrack)
                bso = context.CurDF.GetChildBSO(bsoId, backTrack);
            else
                bso = context.CurDF.Owner.MasterFile.GetChildBSO(bsoId, false);
            if (bso == null) return Error.FileNotFound;
            if (bso.Class != BSOClass.Test)
                return Error.InsNotValid;

            // deve essere un test object di tipo PIN
            if (setNewPin && bso.Algo != BSOAlgo.PIN)
                return Error.InsNotValid;

            int startPin = 0;
            if (verifyPin)
            {
                // cerco il BSO referenziato dall' AC_CHANGE del PIN
                byte condition = bso.AC[BSO_AC.AC_UNBLOCK];
                if (condition == AC.Always || condition == AC.Never)
                    return Error.ObjectNotFound;
                BSO changePin = bso.Parent.GetChildBSO(condition, true);
                if (changePin == null) return Error.FileNotFound;

                if (changePin.Class != BSOClass.Test || changePin.Algo != BSOAlgo.PIN)
                    return Error.InsNotValid;
                int pinLen=0;
                if (!setNewPin)
                    pinLen = apdu.Data != null ? apdu.Data.Length : 0;
                else
                    pinLen = changePin.Data.Length;
                if (!handler.VerifyBSO(changePin, new ByteArray(apdu.Data).Left(pinLen)))
                    return Error.VerificationFailed;
                startPin = changePin.Data.Length;
            }
            if (!handler.IsVerifiedAC(bso, BSO_AC.AC_UNBLOCK))
                throw new ISO7816Exception(Error.SecurityStatusNotSatisfied);

            handler.UnblockBSO(bso);

            if (setNewPin)
                bso.Data = new ByteArray(apdu.Data).Sub(startPin);
            return Error.Ok;
        }
        public void getSMKeys(Apdu apdu, out BSO sigIn, out BSO encIn, out BSO sigOut, out BSO encOut)
        {
            var context = handler.Context;

            sigOut = null;
            encOut = null;

            encIn = handler.getSMKey(context.CurDF, DF_SM.SM_ENC_CREATE);
            sigIn = handler.getSMKey(context.CurDF, DF_SM.SM_SIG_CREATE);
        }
        public void PutDataSEKeys(Apdu apdu, out BSO sigIn, out BSO encIn, out BSO sigOut, out BSO encOut) {
            sigOut = null;
            encOut = null;

            if (context.CurDF == null)
                throw new ISO7816Exception(Error.ClaNotValid);

            encIn = handler.getSMKey(context.CurDF, DF_SM.SM_ENC_UPDATE_APPEND);
            sigIn = handler.getSMKey(context.CurDF, DF_SM.SM_SIG_UPDATE_APPEND);
        }
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;
            if (apdu.P1 != 0 || apdu.P2 != 0) 
                return Error.P1OrP2NotValid;
            if (!apdu.UseLE)
                return Error.DataFieldNotValid;

            return Util.Response(handler.GetChallenge(apdu.LE), Error.Ok);
        }
        public virtual byte[] processCommand(Apdu apdu)
        {
            context = handler.Context;
            if (apdu.P1 == 0x01 && apdu.P2 == 0x6E)
                return PutDataOCI(apdu);
            if (apdu.P1 == 0x01 && apdu.P2 == 0x6F)
                return PutDataFCI(apdu);
            if (apdu.P1 == 0x01 && apdu.P2 == 0x6D)
                return PutDataSE(apdu);

            return Error.P1OrP2NotValid;
        }
        public void getSMKeys(Apdu apdu, out BSO sigIn, out BSO encIn, out BSO sigOut, out BSO encOut)
        {
            context = handler.Context;

            if (apdu.P1 == 0x01 && apdu.P2 == 0x6E)
                PutDataOCIKeys(apdu, out sigIn, out encIn, out sigOut, out encOut);
            else if (apdu.P1 == 0x01 && apdu.P2 == 0x6F)
                PutDataFCIKeys(apdu, out sigIn, out encIn, out sigOut, out encOut);
            else if (apdu.P1 == 0x01 && apdu.P2 == 0x6D)
                PutDataSEKeys(apdu, out sigIn, out encIn, out sigOut, out encOut);
            else throw new ISO7816Exception(Error.P1OrP2NotValid);
        }
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;
            if (apdu.P1 != 0 || apdu.P2 != 0) 
                return Error.P1OrP2NotValid;
            if (apdu.Data == null || apdu.Data.Length != 8)
                return Error.DataFieldNotValid;

            ByteArray data = apdu.Data;
            if (data[4]!=0 || data[5]!=0)
                return Error.DataFieldNotValid;

            ushort pubExpLen=Util.ToUShort(data,6);
            if (pubExpLen == 0) pubExpLen = 24;
            if (pubExpLen<16 || pubExpLen>64)
                return Error.DataFieldNotValid;

            var Module = context.CurDF.GetChildBSO(Util.ToUShort(data[0],data[1]), false);
            if (Module == null)
                return Error.ObjectNotFound;
            if (Module.Algo != BSOAlgo.RSA_DS_Test &&
                Module.Algo != BSOAlgo.RSA_Enc)
                return Error.InsNotValid;

            if (!handler.IsVerifiedAC(Module, BSO_AC.AC_GENKEYPAIR))
                return Error.SecurityStatusNotSatisfied;

            var privExp = context.CurDF.GetChildBSO(Util.ToUShort((byte)(data[0] | 1), data[1]), false);
            if (privExp == null)
                return Error.ObjectNotFound;
            if (privExp.Algo != BSOAlgo.RSA_DS_Test &&
                privExp.Algo != BSOAlgo.RSA_Enc)
                return Error.InsNotValid;

            var pubKey = context.CurDF.GetChildEF(Util.ToUShort(data.Sub(2, 2)));
            if (pubKey == null)
                return Error.FileNotFound;

            if (!(pubKey is EFLinearTLV))
                return Error.CommandIncompatibleWithFileStructure;

            if (!handler.IsVerifiedAC(pubKey, EF_AC.AC_APPEND))
                return Error.SecurityStatusNotSatisfied;
            
            handler.GenerateKey(privExp, Module, pubKey as EFLinearTLV, pubExpLen);

            return Error.Ok;
        }
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;
            if (apdu.P1 != 0 && apdu.P1 != 1) return Error.P1OrP2NotValid;
            bool verify = apdu.P1 == 0;

            ushort pinId = (ushort)(apdu.P2 & 0x7f);
            bool backTrack = (apdu.P2 & 0x80) != 0;
            BSO pin = null;
            if (backTrack)
                pin = context.CurDF.GetChildBSO(pinId, backTrack);
            else
                pin = context.CurDF.Owner.MasterFile.GetChildBSO(pinId, false);
            if (pin == null) return Error.FileNotFound;
            // deve essere un test object di tipo PIN
            if (pin.Class != BSOClass.Test || pin.Algo != BSOAlgo.PIN)
                return Error.InsNotValid;

            int startPin = 0;
            if (verify)
            {
                // cerco il BSO referenziato dall' AC_CHANGE del PIN
                byte condition = pin.AC[BSO_AC.AC_CHANGE];
                if (condition == AC.Never)
                    return Error.ObjectNotFound;
                if (condition != AC.Always)
                {
                    BSO changePin = pin.Parent.GetChildBSO(condition, true);
                    if (changePin == null) return Error.FileNotFound;

                    if (changePin.Class != BSOClass.Test || changePin.Algo != BSOAlgo.PIN)
                        return Error.InsNotValid;

                    if (!handler.VerifyBSO(changePin, new ByteArray(apdu.Data).Left(changePin.Data.Length)))
                        return Error.VerificationFailed;
                    startPin = changePin.Data.Length;
                }
            }
            if (startPin == apdu.Data.Length)
                return Error.WrongLength;
            if (handler.IsVerifiedAC(pin, BSO_AC.AC_CHANGE))
                pin.Data = new ByteArray(apdu.Data).Sub(startPin);
            else
                return Error.SecurityStatusNotSatisfied;

            handler.UnblockBSO(pin);
            return Error.Ok;
        }
        public void getSMKeys(Apdu apdu, out BSO sigIn, out BSO encIn, out BSO sigOut, out BSO encOut)
        {
            CardContext context = handler.Context;

            sigIn = null;
            encIn = null;
            sigOut = null;
            encOut = null;

            var efBin = context.CurEF as EFBinary;
            if (efBin == null)
                return;

            encIn = handler.getSMKey(efBin, EF_SM.SM_ENC_UPDATE);
            sigIn = handler.getSMKey(efBin, EF_SM.SM_SIG_UPDATE);
        }
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;
            if (apdu.P1 != 0 || apdu.P2 != 0) 
                return Error.P1OrP2NotValid;
            if (apdu.Data != null && apdu.Data.Length != 0)
                return Error.DataFieldNotValid;

            var ef = context.CurFile;
            if (ef == null)
                return Error.NoCurrentEFSelected;

            if (ef.Active)
                return Error.InsNotValid;
            ef.Active = true;

            return Error.Ok;
        }
 public virtual byte[] processCommand(Apdu apdu)
 {
     CardContext context = handler.Context;
     if (apdu.P1 != 0xf3 &&
         apdu.P1 != 0xf1)
         return Error.P1OrP2NotValid;
     if (apdu.P1 == 0xf3) {
         var se = context.CurDF.GetChildSE(apdu.P2, true);
         if (se == null)
             return Error.RecordNotFound;
         if (!handler.IsVerifiedAC(se, SE_AC.AC_RESTORE))
             return Error.SecurityStatusNotSatisfied;
         handler.RestoreSE(se);
     }
     else if (apdu.P1 == 0xf1)
     {
         TLV se=new TLV(apdu.Data);
         byte[] id=se[0x83];
         if (id==null)
             id=se[0x84];
         if (id==null)
             return Error.DataFieldNotValid;
         if (id.Length!=1)
             return Error.DataFieldNotValid;
         SecurityEnvironmentComponent comp = 0;
         switch (apdu.P2) { 
             case 0xb8:
                 comp = SecurityEnvironmentComponent.CON;
                 break;
             case 0xa4:
                 comp = SecurityEnvironmentComponent.TEST;
                 break;
             case 0xb6:
                 comp = SecurityEnvironmentComponent.CDS;
                 break;
             default:
                 return Error.P1OrP2NotValid;
         }
         if (comp == 0)
             return Error.P1OrP2NotValid;
         handler.RestoreSE(comp,id[0]);
     }
     return Error.Ok;
 }
        public void getSMKeys(Apdu apdu, out BSO sigIn, out BSO encIn, out BSO sigOut, out BSO encOut)
        {
            sigOut = null;
            encOut = null;

            BSO key =null;
            if (apdu.P1 == 0x80 && apdu.P2 == 0x86)
                key = handler.GetEnvironmentKey(SecurityEnvironmentComponent.CON);
            else if (apdu.P1 == 0x86 && apdu.P2 == 0x80)
                key = handler.GetEnvironmentKey(SecurityEnvironmentComponent.CON);
            else if (apdu.P1 == 0x9E && apdu.P2 == 0x9A)
                key = handler.GetEnvironmentKey(SecurityEnvironmentComponent.CDS);


            encIn = handler.getSMKey(key, BSO_SM.SM_ENC_USE);
            sigIn = handler.getSMKey(key, BSO_SM.SM_SIG_USE);
            encOut = handler.getSMKey(key, BSO_SM.SM_ENC_USE_OUT);
            sigOut = handler.getSMKey(key, BSO_SM.SM_SIG_USE_OUT);
        }
        public void getSMKeys(Apdu apdu, out BSO sigIn, out BSO encIn, out BSO sigOut, out BSO encOut)
        {
            CardContext context = handler.Context;

            sigIn = null;
            encIn = null;
            sigOut = null;
            encOut = null;

            var efBin = context.CurEF as EFRecord;
            if (efBin == null)
                return;

            encIn = handler.getSMKey(efBin, EF_SM.SM_ENC_READ_IN);
            sigIn = handler.getSMKey(efBin, EF_SM.SM_SIG_READ_IN);

            encOut = handler.getSMKey(efBin, EF_SM.SM_ENC_READ_OUT);
            sigOut = handler.getSMKey(efBin, EF_SM.SM_SIG_READ_OUT);
        }
        public void PutDataFCIKeys(Apdu apdu, out BSO sigIn, out BSO encIn, out BSO sigOut, out BSO encOut)
        {
            if (context.CurFile == null)
                throw new ISO7816Exception(Error.NoCurrentEFSelected);

            sigOut = null;
            encOut = null;

            if (context.CurFile is DF)
            {
                encIn = handler.getSMKey(context.CurFile, DF_SM.SM_ENC_ADMIN);
                sigIn = handler.getSMKey(context.CurFile, DF_SM.SM_SIG_ADMIN);
            }
            else if (context.CurFile is EF)
            {
                encIn = handler.getSMKey(context.CurFile, EF_SM.SM_ENC_ADMIN);
                sigIn = handler.getSMKey(context.CurFile, EF_SM.SM_SIG_ADMIN);
            }
            else
                throw new ISO7816Exception(Error.NoCurrentEFSelected);
        }
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;

            ushort bsoId = Util.ToUShort(apdu.P1, (byte)(apdu.P2 & 0x7f));
            bool backTrack = (apdu.P2 & 0x80) != 0;
            BSO bso = null;
            if (backTrack)
                bso = context.CurDF.GetChildBSO(bsoId, backTrack);
            else
                bso = context.CurDF.Owner.MasterFile.GetChildBSO(bsoId, false);
            if (bso == null) return Error.FileNotFound;

            if (!handler.IsVerifiedAC(bso, BSO_AC.AC_CHANGE))
                return Error.SecurityStatusNotSatisfied;

            if (bso.Data.Length != apdu.Data.Length)
                return Error.DataFieldNotValid;
            bso.Data = apdu.Data;

            handler.UnblockBSO(bso);
            return Error.Ok;
        }
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;
            if (apdu.P1 != 0) return Error.P1OrP2NotValid;
            ushort pinId = (ushort)(apdu.P2 & 0x7f);
            bool backTrack = (apdu.P2 & 0x80) != 0;
            BSO pin=null;
            if (backTrack)
                pin = context.CurDF.GetChildBSO(pinId, backTrack);
            else
                pin = context.CurDF.Owner.MasterFile.GetChildBSO(pinId, false);
            if (pin == null)
                return Error.ObjectNotFound;
            if (pin.Class!=BSOClass.Test || pin.Algo!=BSOAlgo.PIN)
                return Error.InsNotValid;

            if (!handler.IsVerifiedAC(pin,BSO_AC.AC_USE))
                return Error.SecurityStatusNotSatisfied;

            if (handler.VerifyBSO(pin,apdu.Data))
                return Error.Ok;
            else
                return Error.VerificationFailed;
        }
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;
            
            if (context.CurDF == null)
                return Error.ClaNotValid;

            TLV fciExt = new TLV(apdu.Data);
            if (fciExt[0x62] == null) return Error.DataFieldNotValid;
            TLV fci = new TLV(fciExt[0x62]);
            var Size1 = fci[0x80];
            var Size2 = fci[0x81];
            var Options = fci[0x82];
            var Id = fci[0x83];
            var Fixed = fci[0x85];
            var AC = fci[0x86];
            var SM = card.GetSMTLV(fci);
            if (Size1 != null && Size2 != null) return Error.DataFieldNotValid;
            if (Options==null) return Error.DataFieldNotValid;
            if (Id == null) return Error.DataFieldNotValid;
            if (Fixed == null) return Error.DataFieldNotValid;
            if (AC == null) return Error.DataFieldNotValid;

            if (Options.Length != 3) return Error.DataFieldNotValid;
            if (Id.Length != 2) return Error.DataFieldNotValid;
            if (Fixed.Length != 1) return Error.DataFieldNotValid;

            if (Fixed[0] != 1) return Error.DataFieldNotValid;
            if (Options[0] == 0x38 && Size2 == null) return Error.DataFieldNotValid;

            if (!handler.IsVerifiedAC(context.CurDF, DF_AC.AC_CREATE))
                return Error.SecurityStatusNotSatisfied;
            ushort newId=Util.ToUShort(Id);

            if (newId == 0x3F00 || newId == 0x3FFF || newId == 0xFFFF)
                return Error.DataFieldNotValid;

            if (context.CurDF.GetChildEForDF(newId) != null)
                return Error.FileAlreadyExists;

            CardSelectable obj = null;
            if (Options[0] == 0x38)
                obj = card.CreateDF(newId, context.CurDF);
            else if (Options[0] == 0x01)
                obj = card.CreateEF(newId, context.CurDF,Util.ToUInt(Size1));
            else if (Options[0] == 0x02)
                obj = new EFLinearFixed(newId, card, context.CurDF, Util.ToUInt(Size1), Options[2]);
            else if (Options[0] == 0x05)
                obj = card.CreateEFLinearTLV(newId, context.CurDF, Util.ToUInt(Size1));
            else if (Options[0] == 0x06)
                obj = new EFCyclic(newId, card, context.CurDF, Util.ToUInt(Size1), Options[2]);
            else
                return Error.DataFieldNotValid;

            if (AC != null)
                obj.AC.Set(AC);
            if (SM != null)
                obj.SM.Set(SM);

            if (obj != null)
                context.CurFile = obj;

            return Error.Ok;
        }
        public virtual byte[] PutDataFCI(Apdu apdu)
        {
            TLV fci = new TLV(apdu.Data);
            var Aid = fci[0x84];
            var AC = fci[0x86];
            var SM = card.GetSMTLV(fci);

            if (Aid!=null && Aid.Length > 16) 
                return Error.DataFieldNotValid;

            if (context.CurFile is EF)
            {
                if (!handler.IsVerifiedAC(context.CurFile, EF_AC.AC_ADMIN))
                    return Error.SecurityStatusNotSatisfied;
            }
            else if (context.CurFile is DF)
            {
                if (!handler.IsVerifiedAC(context.CurFile, DF_AC.AC_ADMIN))
                    return Error.SecurityStatusNotSatisfied;
            }

            if (context.CurEF != null && Aid != null) 
                return Error.CommandIncompatibleWithFileStructure;
            if (AC != null) context.CurFile.AC.Set(AC);
            if (SM != null) context.CurFile.SM.Set(SM);
            
            if (context.CurDF != null)
                if (Aid != null) context.CurDF.AID = Aid;

            return Error.Ok;
        }
Exemple #25
0
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;

            if (apdu.P1 != 0xf3 &&
                apdu.P1 != 0xf1)
            {
                return(Error.P1OrP2NotValid);
            }
            if (apdu.P1 == 0xf3)
            {
                var se = context.CurDF.GetChildSE(apdu.P2, true);
                if (se == null)
                {
                    return(Error.RecordNotFound);
                }
                if (!handler.IsVerifiedAC(se, SE_AC.AC_RESTORE))
                {
                    return(Error.SecurityStatusNotSatisfied);
                }
                handler.RestoreSE(se);
            }
            else if (apdu.P1 == 0xf1)
            {
                TLV    se = new TLV(apdu.Data);
                byte[] id = se[0x83];
                if (id == null)
                {
                    id = se[0x84];
                }
                if (id == null)
                {
                    return(Error.DataFieldNotValid);
                }
                if (id.Length != 1)
                {
                    return(Error.DataFieldNotValid);
                }
                SecurityEnvironmentComponent comp = 0;
                switch (apdu.P2)
                {
                case 0xb8:
                    comp = SecurityEnvironmentComponent.CON;
                    break;

                case 0xa4:
                    comp = SecurityEnvironmentComponent.TEST;
                    break;

                case 0xb6:
                    comp = SecurityEnvironmentComponent.CDS;
                    break;

                default:
                    return(Error.P1OrP2NotValid);
                }
                if (comp == 0)
                {
                    return(Error.P1OrP2NotValid);
                }
                handler.RestoreSE(comp, id[0]);
            }
            return(Error.Ok);
        }
 public byte[] ProcessApdu(byte[] apdu)
 {
     try
     {
         Apdu Apdu = new Apdu(apdu);
         card.Log(Apdu);
         Apdu   initialApdu = Apdu;
         ushort key         = Util.ToUShort((byte)(Apdu.CLA & 0xf0), Apdu.INS);
         if (commandMap.ContainsKey(key))
         {
             BSO sigIn, encIn, sigOut, encOut;
             commandMap[key].getSMKeys(Apdu, out sigIn, out encIn, out sigOut, out encOut);
             var challenge = context.Challenge;
             if (sigIn != null || encIn != null || sigOut != null || encOut != null)
             {
                 if (!Apdu.IsSM)
                 {
                     return(Error.SMObjectMissing);
                 }
                 if (sigIn != null)
                 {
                     context.Challenge = null;
                 }
                 Apdu = Apdu.GetClearApdu(Apdu, encIn, sigIn, encOut, sigOut, challenge);
             }
             else
             {
                 if (Apdu.IsSM)
                 {
                     return(Error.ConditionsOfUseNotSatisfied);
                 }
             }
             var resp = commandMap[key].processCommand(Apdu);
             card.Log(resp);
             var random = context.Random;
             if (encOut != null || sigOut != null || sigIn != null || encIn != null)
             {
                 if (sigOut != null)
                 {
                     context.Challenge = null;
                 }
                 context.Random = null;
                 return(Apdu.GetSMResponse(initialApdu, resp, encOut, sigOut, random));
             }
             else
             {
                 return(resp);
             }
         }
         card.Log("Comando non riconosciuto");
         card.Log(Error.InsNotValid);
         return(Error.InsNotValid);
     }
     catch (ISO7816Exception cex)
     {
         card.Log((byte[])cex.CardError);
         return(cex.CardError);
     }
     catch (Exception ex)
     {
         card.Log(ex.ToString());
         return(Error.InternalError);
     }
 }
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;

            if (apdu.P1 != 0 &&
                apdu.P1 != 1 &&
                apdu.P1 != 3)
            {
                return(Error.P1OrP2NotValid);
            }
            bool setNewPin = apdu.P1 == 0;
            bool verifyPin = apdu.P1 != 3;

            if (apdu.P1 == 3 && (apdu.Data != null && apdu.Data.Length > 0))
            {
                return(Error.DataFieldNotValid);
            }

            ushort bsoId     = (ushort)(apdu.P2 & 0x7f);
            bool   backTrack = (apdu.P2 & 0x80) != 0;
            BSO    bso       = null;

            if (backTrack)
            {
                bso = context.CurDF.GetChildBSO(bsoId, backTrack);
            }
            else
            {
                bso = context.CurDF.Owner.MasterFile.GetChildBSO(bsoId, false);
            }
            if (bso == null)
            {
                return(Error.FileNotFound);
            }
            if (bso.Class != BSOClass.Test)
            {
                return(Error.InsNotValid);
            }

            // deve essere un test object di tipo PIN
            if (setNewPin && bso.Algo != BSOAlgo.PIN)
            {
                return(Error.InsNotValid);
            }

            int startPin = 0;

            if (verifyPin)
            {
                // cerco il BSO referenziato dall' AC_CHANGE del PIN
                byte condition = bso.AC[BSO_AC.AC_UNBLOCK];
                if (condition == AC.Always || condition == AC.Never)
                {
                    return(Error.ObjectNotFound);
                }
                BSO changePin = bso.Parent.GetChildBSO(condition, true);
                if (changePin == null)
                {
                    return(Error.FileNotFound);
                }

                if (changePin.Class != BSOClass.Test || changePin.Algo != BSOAlgo.PIN)
                {
                    return(Error.InsNotValid);
                }
                int pinLen = 0;
                if (!setNewPin)
                {
                    pinLen = apdu.Data != null ? apdu.Data.Length : 0;
                }
                else
                {
                    pinLen = changePin.Data.Length;
                }
                if (!handler.VerifyBSO(changePin, new ByteArray(apdu.Data).Left(pinLen)))
                {
                    return(Error.VerificationFailed);
                }
                startPin = changePin.Data.Length;
            }
            if (!handler.IsVerifiedAC(bso, BSO_AC.AC_UNBLOCK))
            {
                throw new ISO7816Exception(Error.SecurityStatusNotSatisfied);
            }

            handler.UnblockBSO(bso);

            if (setNewPin)
            {
                bso.Data = new ByteArray(apdu.Data).Sub(startPin);
            }
            return(Error.Ok);
        }
Exemple #28
0
 public byte[] Should_the_result_match_the_expected_result(Apdu apdu)
 {
     return(apdu.ToArray());
 }
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;

            if (context.CurEF == null)
            {
                return(Error.NoCurrentEFSelected);
            }

            if (!(context.CurEF is EFRecord))
            {
                return(Error.CommandIncompatibleWithFileStructure);
            }

            if (apdu.Data == null || apdu.Data.Length == 0)
            {
                return(Error.DataFieldNotValid);
            }

            var efRec = context.CurEF as EFRecord;

            if (!handler.IsVerifiedAC(efRec, EF_AC.AC_UPDATE))
            {
                return(Error.SecurityStatusNotSatisfied);
            }

            int?recNum = 0;

            if (apdu.P1 == 0)
            {
                if (apdu.P2 == 0)
                {
                    recNum = 0;
                }
                else if (apdu.P2 == 1)
                {
                    recNum = efRec.Data.Count - 1;
                }
                else if (apdu.P2 == 2)
                {
                    if (!context.CurRecord.HasValue)
                    {
                        recNum = 0;
                    }
                    else
                    {
                        recNum = context.CurRecord.Value + 1;
                    }
                }
                else if (apdu.P2 == 3)
                {
                    if (!context.CurRecord.HasValue)
                    {
                        recNum = efRec.Data.Count - 1;
                    }
                    else
                    {
                        recNum = context.CurRecord.Value - 1;
                    }
                }
                else if (apdu.P2 == 4)
                {
                    if (!context.CurRecord.HasValue)
                    {
                        recNum = 0;
                    }
                    else
                    {
                        recNum = context.CurRecord.Value;
                    }
                }
            }
            else if (apdu.P2 == 4)
            {
                if (apdu.P1 <= efRec.Data.Count && apdu.P1 > 0)
                {
                    recNum = apdu.P1 - 1;
                }
                else
                {
                    return(Error.RecordNotFound);
                }
            }
            else if (efRec is EFLinearTLV)
            {
                var efl = efRec as EFLinearTLV;
                if (apdu.P2 == 0)
                {
                    recNum = efl.SearchRecord(apdu.P1);
                }
                else if (apdu.P2 == 1)
                {
                    recNum = efl.SearchRecordRev(apdu.P1);
                }
                else if (apdu.P2 == 2)
                {
                    if (context.CurRecord.HasValue)
                    {
                        recNum = efl.SearchRecord(context.CurRecord.Value, apdu.P1);
                    }
                    else
                    {
                        recNum = efl.SearchRecord(apdu.P1);
                    }
                }
                else if (apdu.P2 == 3)
                {
                    if (context.CurRecord.HasValue)
                    {
                        recNum = efl.SearchRecordRev(context.CurRecord.Value, apdu.P1);
                    }
                    else
                    {
                        recNum = efl.SearchRecordRev(apdu.P1);
                    }
                }
            }
            if (!recNum.HasValue)
            {
                return(Error.RecordNotFound);
            }

            if (apdu.P2 != 4)
            {
                if (!(efRec is EFCyclic))
                {
                    context.CurRecord = recNum;
                }
                else
                {
                    context.CurRecord = 0;
                }
            }

            if (recNum.Value >= efRec.Data.Count)
            {
                return(Error.RecordNotFound);
            }

            efRec.Update(recNum.Value, apdu.Data);
            return(Error.Ok);
        }
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;
            if (apdu.P1 == 0x80 && apdu.P2 == 0x86) { 
                // DEC
                BSO key = handler.GetEnvironmentKey(SecurityEnvironmentComponent.CON);
                if (key.Class != BSOClass.PSO)
                    return Error.P1OrP2NotValid;

                if (key.Algo!=BSOAlgo.RSA_Enc && 
                    key.Algo!=BSOAlgo.DES3_Enc_SMEnc)
                    return Error.P1OrP2NotValid;

                if (!handler.IsVerifiedAC(key, BSO_AC.AC_USE))
                    return Error.SecurityStatusNotSatisfied;

                byte[] data=handler.Decrypt(key, new ByteArray(apdu.Data).Sub(1));
                // devo paddare per arrivare alla lunghezza del modulo
                if (key.Algo == BSOAlgo.RSA_Enc)
                {
                    if (data.Length < (key.data.Length - 2))
                    {
                        var dataPad = new byte[key.data.Length - 2];
                        data.CopyTo(dataPad, dataPad.Length - data.Length);
                        data = dataPad;
                    }
                }
                return Util.Response(data, Error.Ok);
            }
            else if (apdu.P1 == 0x86 && apdu.P2 == 0x80)
            {
                // ENC
                BSO key = handler.GetEnvironmentKey(SecurityEnvironmentComponent.CON);
                if (key.Class != BSOClass.PSO)
                    return Error.P1OrP2NotValid;

                if (key.Algo != BSOAlgo.RSA_Enc &&
                    key.Algo != BSOAlgo.DES3_Enc_SMEnc)
                    return Error.P1OrP2NotValid;

                if (!handler.IsVerifiedAC(key, BSO_AC.AC_USE))
                    return Error.SecurityStatusNotSatisfied;

                byte[] data = handler.Encrypt(key, apdu.Data);
                if (key.Algo == BSOAlgo.RSA_Enc && data.Length < (key.data.Length - 2))
                {
                    var dataPad = new byte[key.data.Length - 2];
                    data.CopyTo(dataPad, dataPad.Length - data.Length);
                    data = dataPad;
                }
                return Util.Response(new ByteArray(0).Append(data), Error.Ok);
            }
            else if (apdu.P1 == 0x9E && apdu.P2 == 0x9A)
            {
                // CDS
                BSO key = handler.GetEnvironmentKey(SecurityEnvironmentComponent.CDS);
                if (key.Class != BSOClass.PSO)
                    return Error.P1OrP2NotValid;

                if (key.Algo != BSOAlgo.RSA_DS_Test)
                    return Error.P1OrP2NotValid;

                if (!handler.IsVerifiedAC(key, BSO_AC.AC_USE))
                    return Error.SecurityStatusNotSatisfied;

                byte[] data = handler.DigitalSignature(key, apdu.Data);
                if (data.Length < (key.data.Length - 2))
                {
                    var dataPad = new byte[key.data.Length - 2];
                    data.CopyTo(dataPad, dataPad.Length - data.Length);
                    data = dataPad;
                }
                return Util.Response(data, Error.Ok);
            }
            return Error.P1OrP2NotValid;
        }
Exemple #31
0
        /// <summary>
        ///     Read Property.
        /// </summary>
        /// <param name="recipient">The recipient.</param>
        /// <param name="arrayidx">The arrayidx.</param>
        /// <param name="objtype">The objtype.</param>
        /// <param name="objprop">The objprop.</param>
        /// <param name="property">The property.</param>
        /// <returns></returns>
        public bool SendReadProperty(
            Device recipient,
            int arrayidx,
            BacnetEnums.BacnetObjectType objtype,
            BacnetEnums.BacnetPropertyId objprop,
            Property property)
        {
            // Create and send an Confirmed Request

            //value = "(none)";
            if (recipient == null)
            {
                return(false);
            }

            if (property == null)
            {
                return(false);
            }

            //uint instance = BACnetData.Devices[deviceidx].Instance;

            var sendBytes = new byte[50];

            // BVLL
            sendBytes[0] = Bvlc.BacnetBvlcTypeBip;
            sendBytes[1] = Bvlc.BacnetBvlcFuncUnicastNpdu;
            sendBytes[2] = 0x00;
            sendBytes[3] = 0x00; // BVLL Length, fix later (24?)

            // NPDU
            sendBytes[4] = BacnetEnums.BacnetProtocolVersion;
            if (recipient.SourceLength == 0)
            {
                sendBytes[5] = 0x04; // Control flags, no destination address
            }
            else
            {
                sendBytes[5] = 0x24; // Control flags, with broadcast or destination address
            }
            uint len = 6;

            if (recipient.SourceLength > 0)
            {
                // Get the (MSTP) Network number (2001)
                var temp2 = BitConverter.GetBytes(recipient.Network);
                sendBytes[len++] = temp2[1];
                sendBytes[len++] = temp2[0];

                // Get the MAC address (0x0D)
                var temp4 = BitConverter.GetBytes(recipient.MacAddress);

                sendBytes[len++] = 0x01; // MAC address length - adjust for other lengths ...
                sendBytes[len++] = temp4[0];
                sendBytes[len++] = 0xFF; // Hop count = 255
            }

            // APDU
            sendBytes[len++] = 0x00; // Control flags
            sendBytes[len++] = 0x05; // Max APDU length (1476)

            // Create invoke counter
            sendBytes[len++] = (byte)(invokeCounter);
            invokeCounter    = ((invokeCounter + 1) & 0xFF);

            sendBytes[len++] = 0x0C; // Service Choice: Read Property request

            // Service Request (var part of APDU):
            // Set up Object ID (Context Tag)
            len = Apdu.SetObjectId(ref sendBytes, len, objtype, recipient.Instance);

            // Set up Property ID (Context Tag)
            len = Apdu.SetPropertyId(ref sendBytes, len, objprop);

            // Optional array index goes here
            if (arrayidx >= 0)
            {
                len = Apdu.SetArrayIdx(ref sendBytes, len, arrayidx);
            }

            // Fix the BVLL length
            sendBytes[3] = (byte)len;

            var getResponse = false;
            var count       = 0;

            while (count < BacnetUnicastRequestRepeatCount && !getResponse)
            {
                sendUdp.EnableBroadcast = false;
                sendUdp.Send(sendBytes, (int)len, recipient.ServerEp);

                while (!getResponse)
                {
                    if (sendUdp.Client.Available <= 0)
                    {
                        continue;
                    }
                    //recvBytes = SendUDP.Receive(ref RemoteEP);
                    var sendTo    = recipient.ServerEp;
                    var recvBytes = sendUdp.Receive(ref sendTo);

                    var apduOffset = Npdu.Parse(recvBytes, Bvlc.BacnetBvlcHeaderLen); // BVLL is always 4 bytes

                    // Check for APDU response
                    // 0x - Confirmed Request
                    // 1x - Un-Confirmed Request
                    // 2x - Simple ACK
                    // 3x - Complex ACK
                    // 4x - Segment ACK
                    // 5x - Error
                    // 6x - Reject
                    // 7x - Abort
                    if (recvBytes[apduOffset] != 0x30)
                    {
                        continue;
                    }
                    // Verify the Invoke ID is the same
                    var ic = (byte)(invokeCounter == 0 ? 255 : invokeCounter - 1);
                    if (ic != recvBytes[apduOffset + 1])
                    {
                        continue;
                    }
                    Apdu.ParseProperty(ref recvBytes, apduOffset, property);
                    getResponse = true; // This will still execute the finally
                }

                count++;
            }
            return(getResponse);
        }
Exemple #32
0
        /// <summary>
        ///     Write Property.
        /// </summary>
        /// <param name="recipient">The receipient.</param>
        /// <param name="arrayidx">The arrayidx.</param>
        /// <param name="objtype">The objtype.</param>
        /// <param name="objprop">The objprop.</param>
        /// <param name="property">The property.</param>
        /// <param name="priority">The priority.</param>
        /// <returns></returns>
        public bool SendWriteProperty(
            Device recipient,
            int arrayidx,
            BacnetEnums.BacnetObjectType objtype,
            BacnetEnums.BacnetPropertyId objprop,
            Property property,
            int priority)
        {
            // Create and send an Confirmed Request
            if (recipient == null)
            {
                return(false);
            }

            if (property == null)
            {
                return(false);
            }

            var sendBytes = new byte[50];

            // BVLL
            var len = Bvlc.Fill(ref sendBytes, Bvlc.BacnetBvlcFuncUnicastNpdu, 0);

            // NPDU
            sendBytes[len++] = BacnetEnums.BacnetProtocolVersion;
            if (recipient.SourceLength == 0)
            {
                sendBytes[len++] = 0x04; // Control flags, no destination address
            }
            else
            {
                sendBytes[len++] = 0x24; // Control flags, with broadcast or destination
            }
            if (recipient.SourceLength > 0)
            {
                // Get the (MSTP) Network number (2001)
                //sendBytes[6] = 0x07;  // Destination network address (2001)
                //sendBytes[7] = 0xD1;
                var temp2 = BitConverter.GetBytes(recipient.Network);
                sendBytes[len++] = temp2[1];
                sendBytes[len++] = temp2[0];

                // Get the MAC address (0x0D)
                //sendBytes[8] = 0x01;  // MAC address length
                //sendBytes[9] = 0x0D;  // Destination MAC layer address
                var temp4 = BitConverter.GetBytes(recipient.MacAddress);
                sendBytes[len++] = 0x01; // MAC address length - adjust for other lengths ...
                sendBytes[len++] = temp4[0];

                sendBytes[len++] = 0xFF; // Hop count = 255
            }

            // APDU
            sendBytes[len++] = 0x00; // Control flags
            sendBytes[len++] = 0x05; // Max APDU length (1476)

            // Create invoke counter
            //sendBytes[len++] = InvokeCounter++;  // Invoke ID
            sendBytes[len++] = (byte)(invokeCounter);
            invokeCounter    = ((invokeCounter + 1) & 0xFF);

            sendBytes[len++] = 0x0F; // Service Choice: Write Property request

            // Service Request (var part of APDU):
            // Set up Object ID (Context Tag)
            len = Apdu.SetObjectId(ref sendBytes, len, objtype, recipient.Instance);

            // Set up Property ID (Context Tag)
            len = Apdu.SetPropertyId(ref sendBytes, len, objprop);

            // Optional array index goes here
            if (arrayidx >= 0)
            {
                len = Apdu.SetArrayIdx(ref sendBytes, len, arrayidx);
            }

            // Set the value to send
            len = Apdu.SetProperty(ref sendBytes, len, property);

            //PEP Optional array index goes here

            // Set priority
            if (priority > 0)
            {
                len = Apdu.SetPriority(ref sendBytes, len, priority);
            }

            // Fix the BVLL length
            sendBytes[3] = (byte)len;

            var count       = 0;
            var getResponse = false;

            while (count < BacnetUnicastRequestRepeatCount && !getResponse)
            {
                sendUdp.EnableBroadcast = false;
                sendUdp.Send(sendBytes, (int)len, recipient.ServerEp);

                while (!getResponse)
                {
                    if (sendUdp.Client.Available <= 0)
                    {
                        continue;
                    }
                    //recvBytes = SendUDP.Receive(ref RemoteEP);
                    var sendTo    = recipient.ServerEp;
                    var recvBytes = sendUdp.Receive(ref sendTo);

                    var apduOffset = Npdu.Parse(recvBytes, 4); // BVLL is always 4 bytes
                    // Check for APDU response, and decide what to do
                    // 0x - Confirmed Request
                    // 1x - Un-Confirmed Request
                    // 2x - Simple ACK
                    // 3x - Complex ACK
                    // 4x - Segment ACK
                    // 5x - Error
                    // 6x - Reject
                    // 7x - Abort
                    if (recvBytes[apduOffset] != 0x20)
                    {
                        continue;
                    }
                    // Verify the Invoke ID is the same
                    var ic = (byte)(invokeCounter == 0 ? 255 : invokeCounter - 1);
                    if (ic == recvBytes[apduOffset + 1])
                    {
                        getResponse = true; // This will still execute the finally
                    }
                }
                count++;
            }
            return(getResponse); // This will still execute the finally
        }
Exemple #33
0
        /// <summary>
        ///     Collect Who-Is information from a single IP address.
        ///     @todo: Use exceptions for timeout.
        /// </summary>
        /// <param name="bIpAddress">IP host address of suspected BACnet device.</param>
        /// <param name="milliseconds">I-Am receive timeout in milliseconds.</param>
        /// <returns>A BACnet Device object representation MAYBE with filled properties.</returns>
        public Device UnicastWhoIsOnSingleIp(IPEndPoint bIpAddress, int milliseconds)
        {
            var sendBytes = new byte[12];
            var device    = new Device();

            try
            {
                //PEP Use NPDU.Create and APDU.Create (when written)
                sendBytes[0] = Bvlc.BacnetBvlcTypeBip;
                sendBytes[1] = Bvlc.BacnetBvlcFuncUnicastNpdu;
                sendBytes[2] = 0;
                sendBytes[3] = 12;
                sendBytes[4] = BacnetEnums.BacnetProtocolVersion;
                sendBytes[5] = 0x20; // Control flags
                sendBytes[6] = 0xFF; // Destination network address (65535)
                sendBytes[7] = 0xFF;
                sendBytes[8] = 0;    // Destination MAC layer address length, 0 = Broadcast
                sendBytes[9] = 0xFF; // Hop count = 255

                sendBytes[10] = (byte)BacnetEnums.BacnetPduType.PduTypeUnconfirmedServiceRequest;
                sendBytes[11] = (byte)BacnetEnums.BacnetUnconfirmedService.ServiceUnconfirmedWhoIs;

                sendUdp.EnableBroadcast = false;
                sendUdp.Send(sendBytes, 12, bIpAddress);

                var watch = new Stopwatch();
                watch.Start();

                while (true)
                {
                    if (watch.Elapsed.TotalMilliseconds >= milliseconds)
                    {
                        break;
                    }
                    // Process the response packets
                    //if (WinSockRecvReady() > 0)
                    //{
                    //  if (WinSockRecvFrom(recvBytes, ref count, ref ipaddr) > 0)
                    // Process the response packets
                    if (sendUdp.Client.Available > 0)
                    {
                        var recvBytes = sendUdp.Receive(ref bIpAddress);
                        {
                            // Parse and save the BACnet data
                            var npduOffset = Bvlc.Parse(recvBytes, 0);
                            var apduOffset = Npdu.Parse(recvBytes, npduOffset);
                            if (Apdu.ParseIAm(recvBytes, apduOffset) <= 0)
                            {
                                continue;
                            }
                            device.Name         = "Device";
                            device.SourceLength = Npdu.Slen;
                            device.ServerEp     = bIpAddress;
                            device.Network      = Npdu.Snet;
                            device.MacAddress   = Npdu.SAddress;
                            device.Instance     = Apdu.ObjectId;

                            // We should now have enough info to read/write properties for this device
                        }
                    }
                }

                watch.Stop();
            }
            catch (Exception e)
            {
                Log.ErrorFormat("Error on UnicastWhoIsOnSingleIp {0}", e.Message);
            }

            return(device);
        }
Exemple #34
0
        /// <summary>
        ///     Who-Is, and collect the device about who answers
        /// </summary>
        /// <param name="milliseconds"></param>
        /// <returns></returns>
        public List <Device> GetDevices(int milliseconds)
        {
            // Get the host data, send a Who-Is, accept responses and save in the DeviceList
            var sendBytes = new byte[12];

            devices.Clear();

            // Send the request
            try
            {
                //PEP Use NPDU.Create and APDU.Create (when written)
                sendBytes[0] = Bvlc.BacnetBvlcTypeBip;
                sendBytes[1] = Bvlc.BacnetBvlcFuncUnicastNpdu;
                sendBytes[2] = 0;
                sendBytes[3] = 12;
                sendBytes[4] = BacnetEnums.BacnetProtocolVersion;
                sendBytes[5] = 0x20; // Control flags
                sendBytes[6] = 0xFF; // Destination network address (65535)
                sendBytes[7] = 0xFF;
                sendBytes[8] = 0;    // Destination MAC layer address length, 0 = Broadcast
                sendBytes[9] = 0xFF; // Hop count = 255

                sendBytes[10] = (byte)BacnetEnums.BacnetPduType.PduTypeUnconfirmedServiceRequest;
                sendBytes[11] = (byte)BacnetEnums.BacnetUnconfirmedService.ServiceUnconfirmedWhoIs;

                sendUdp.EnableBroadcast = false;
                sendUdp.Send(sendBytes, 12, broadcastEp);

                var watch = new Stopwatch();
                watch.Start();

                while (true)
                {
                    if (watch.Elapsed.TotalMilliseconds >= milliseconds)
                    {
                        break;
                    }
                    var remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);

                    if (sendUdp.Client.Available > 0)
                    {
                        var recvBytes = sendUdp.Receive(ref remoteIpEndPoint);
                        // Parse and save the BACnet data
                        var npduOffset = Bvlc.Parse(recvBytes, 0);
                        var apduOffset = Npdu.Parse(recvBytes, npduOffset);

                        if (Apdu.ParseIAm(recvBytes, apduOffset) <= 0)
                        {
                            continue;
                        }
                        var device = new Device
                        {
                            Name         = "Device",
                            SourceLength = Npdu.Slen,
                            ServerEp     = remoteIpEndPoint,
                            Network      = Npdu.Snet,
                            MacAddress   = Npdu.SAddress,
                            Instance     = Apdu.ObjectId
                        };
                        if (!devices.Contains(device))
                        {
                            devices.Add(device);
                        }
                    }
                }

                watch.Stop();
            }
            catch (Exception ex)
            {
                Log.ErrorFormat("Error GetDevices {0}", ex.Message);
            }
            return(devices);
        }
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;

            if (context.CurEF == null)
            {
                return(Error.NoCurrentEFSelected);
            }

            if (!(context.CurEF is EFRecord))
            {
                return(Error.CommandIncompatibleWithFileStructure);
            }

            var efRec = context.CurEF as EFRecord;

            if (!handler.IsVerifiedAC(efRec, EF_AC.AC_READ))
            {
                return(Error.SecurityStatusNotSatisfied);
            }

            int?recNum = 0;

            if (apdu.P1 == 0)
            {
                if (apdu.P2 == 0)
                {
                    recNum = 0;
                }
                else if (apdu.P2 == 1)
                {
                    recNum = efRec.Data.Count - 1;
                }
                else if (apdu.P2 == 2)
                {
                    if (!context.CurRecord.HasValue)
                    {
                        recNum = 0;
                    }
                    else
                    {
                        recNum = context.CurRecord.Value + 1;
                    }
                }
                else if (apdu.P2 == 3)
                {
                    if (!context.CurRecord.HasValue)
                    {
                        recNum = efRec.Data.Count - 1;
                    }
                    else
                    {
                        recNum = context.CurRecord.Value - 1;
                    }
                }
                else if (apdu.P2 == 4)
                {
                    if (!context.CurRecord.HasValue)
                    {
                        recNum = 0;
                    }
                    else
                    {
                        recNum = context.CurRecord.Value;
                    }
                }
            }
            else if (apdu.P2 == 4)
            {
                if (apdu.P1 <= efRec.Data.Count && apdu.P1 > 0)
                {
                    recNum = apdu.P1 - 1;
                }
                else
                {
                    return(Error.RecordNotFound);
                }
            }
            else if (efRec is EFLinearTLV)
            {
                var efl = efRec as EFLinearTLV;
                if (apdu.P2 == 0)
                {
                    recNum = efl.SearchRecord(apdu.P1);
                }
                else if (apdu.P2 == 1)
                {
                    recNum = efl.SearchRecordRev(apdu.P1);
                }
                else if (apdu.P2 == 2)
                {
                    if (context.CurRecord.HasValue)
                    {
                        recNum = efl.SearchRecord(context.CurRecord.Value, apdu.P1);
                    }
                    else
                    {
                        recNum = efl.SearchRecord(apdu.P1);
                    }
                }
                else if (apdu.P2 == 3)
                {
                    if (context.CurRecord.HasValue)
                    {
                        recNum = efl.SearchRecordRev(context.CurRecord.Value, apdu.P1);
                    }
                    else
                    {
                        recNum = efl.SearchRecordRev(apdu.P1);
                    }
                }
            }
            if (!recNum.HasValue)
            {
                return(Error.RecordNotFound);
            }

            if (apdu.P2 != 4)
            {
                context.CurRecord = recNum;
            }

            if (recNum.Value >= efRec.Data.Count)
            {
                return(Error.RecordNotFound);
            }
            var recVal = efRec.Read(recNum.Value);

            if (apdu.UseLE && apdu.LE != 0)
            {
                recVal = new ByteArray(recVal).Left(apdu.LE);
            }

            return(Util.Response(recVal, Error.Ok));
        }
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;
            if (apdu.P2 != 0)
                return Error.P1OrP2NotValid;
            CardSelectable obj = null;
            switch (apdu.P1)
            {
                case 0:
                    if (apdu.Data == null || apdu.Data.Length == 0)
                        obj = card.MasterFile;
                    else
                    {
                        if (apdu.Data.Length != 2)
                            return Error.DataFieldNotValid;
                        ushort id = Util.ToUShort(apdu.Data);
                        if (id == 0x3f00)
                            obj = card.MasterFile;
                        else
                        {
                            obj = context.CurDF.GetChildEForDF(id);
                            if (obj == null && context.CurDF.Parent != null)
                                obj = context.CurDF.Parent.GetChildEForDF(id);
                            if (obj == null && context.CurDF.Parent != null && id == context.CurDF.ID)
                                obj = context.CurDF.Parent;
                        }
                    }
                    if (obj == null)
                        return Error.FileNotFound;

                    context.CurFile = obj;
                    break;
                case 1:
                    if (apdu.Data == null || apdu.Data.Length != 2)
                        return Error.DataFieldNotValid;
                    ushort id2 = Util.ToUShort(apdu.Data);
                    obj = context.CurDF.GetChildDF(id2);
                    if (obj == null)
                        return Error.FileNotFound;
                    context.CurFile = obj;
                    break;
                case 2:
                    if (apdu.Data == null || apdu.Data.Length != 2)
                        return Error.DataFieldNotValid;
                    ushort id3 = Util.ToUShort(apdu.Data);
                    obj = context.CurDF.GetChildDF(id3);
                    if (obj == null)
                        return Error.FileNotFound;
                    context.CurFile = obj;
                    break;
                case 3:
                    if (apdu.Data != null && apdu.Data.Length != 0)
                        return Error.DataFieldNotValid;

                    if (context.CurDF.Parent == null)
                        return Error.FileNotFound;

                    context.CurFile = context.CurDF.Parent;
                    break;
                case 4:
                    if (apdu.Data == null || apdu.Data.Length == 0)
                        return Error.DataFieldNotValid;

                    DF namedDF = handler.GetNamedDF(card.MasterFile, apdu.Data);
                    if (namedDF == null)
                        return Error.FileNotFound;

                    context.CurFile = namedDF;
                    break;
                case 8:
                    if (apdu.Data == null || apdu.Data.Length == 0)
                        obj = card.MasterFile;
                    else
                        if (apdu.Data != null && apdu.Data.Length == 2 && Util.ToUShort(apdu.Data) == 0x3f00)
                            obj = card.MasterFile;
                        else
                        {
                            if ((apdu.Data.Length % 2) != 0)
                                return Error.DataFieldNotValid;
                            obj = handler.GetSelectablePath(card.MasterFile, apdu.Data, 0);
                            if (obj == null)
                                return Error.FileNotFound;
                        }
                    context.CurFile = obj;
                    break;
                case 9:
                    if (apdu.Data == null || apdu.Data.Length == 0)
                        return Error.DataFieldNotValid;
                    else
                    {
                        if ((apdu.Data.Length % 2) != 0)
                            return Error.DataFieldNotValid;
                        if (context.CurDF == null)
                            return Error.ClaNotValid;
                        obj = handler.GetSelectablePath(context.CurDF, apdu.Data, 0);
                        if (obj == null)
                            return Error.FileNotFound;
                    }
                    context.CurFile = obj;
                    break;
                default:
                    return Error.P1OrP2NotValid;
            }
            if (context.CurFile == null)
                return Error.FileNotFound;
            var outData = (context.CurFile as IObjectWithFCI).FCI;
            TLV tlv = new TLV();
            TLV tlv2 = new TLV();
            tlv2.elems.AddRange(outData);
            tlv.addTag(0x6f, tlv2.GetBytes());
            return Util.Response(tlv.GetBytes(), Error.Ok);
        }
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;

            if (context.CurEF == null)
                return Error.NoCurrentEFSelected;

            if (!(context.CurEF is EFRecord))
                return Error.CommandIncompatibleWithFileStructure;

            var efRec = context.CurEF as EFRecord;

            if (!handler.IsVerifiedAC(efRec, EF_AC.AC_READ))
                return Error.SecurityStatusNotSatisfied;

            int? recNum=0;
            if (apdu.P1 == 0) {
                if (apdu.P2 == 0)
                    recNum = 0;
                else if (apdu.P2 == 1)
                    recNum = efRec.Data.Count - 1;
                else if (apdu.P2 == 2)
                {
                    if (!context.CurRecord.HasValue)
                        recNum = 0;
                    else
                        recNum = context.CurRecord.Value+1;
                }
                else if (apdu.P2 == 3)
                {
                    if (!context.CurRecord.HasValue)
                        recNum = efRec.Data.Count - 1;
                    else
                        recNum = context.CurRecord.Value - 1;
                }
                else if (apdu.P2 == 4)
                {
                    if (!context.CurRecord.HasValue)
                        recNum = 0;
                    else
                        recNum = context.CurRecord.Value;
                }
            }
            else if (apdu.P2 == 4) {
                if (apdu.P1 <= efRec.Data.Count && apdu.P1 > 0)
                    recNum = apdu.P1 - 1;
                else
                    return Error.RecordNotFound;
            }
            else if (efRec is EFLinearTLV) {
                var efl = efRec as EFLinearTLV;
                if (apdu.P2 == 0) {
                    recNum = efl.SearchRecord(apdu.P1);
                }
                else if (apdu.P2 == 1) {
                    recNum = efl.SearchRecordRev(apdu.P1);
                }
                else if (apdu.P2 == 2) {
                    if (context.CurRecord.HasValue)
                        recNum = efl.SearchRecord(context.CurRecord.Value, apdu.P1);
                    else
                        recNum = efl.SearchRecord(apdu.P1);
                }
                else if (apdu.P2 == 3) {
                    if (context.CurRecord.HasValue)
                        recNum = efl.SearchRecordRev(context.CurRecord.Value, apdu.P1);
                    else
                        recNum = efl.SearchRecordRev(apdu.P1);
                }
            }
            if (!recNum.HasValue)
                return Error.RecordNotFound;

            if (apdu.P2 != 4)
                context.CurRecord = recNum;

            if (recNum.Value >= efRec.Data.Count)
                return Error.RecordNotFound;
            var recVal=efRec.Read(recNum.Value);

            if (apdu.UseLE && apdu.LE!=0)
                recVal=new ByteArray(recVal).Left(apdu.LE);

            return Util.Response(recVal, Error.Ok);
        }
 public virtual byte[] PutDataOCI(Apdu apdu)
 {
     TLV oci = new TLV(apdu.Data);
     ushort id = Util.ToUShort(oci[0x83]);
     if (context.CurDF == null)
         return Error.ClaNotValid;
     var obj = context.CurDF.GetChildBSO(id);
     if (obj == null)
         return CreateBSO(oci);
     else
     {
         if (!(obj is BSO))
             return Error.DataFieldNotValid;
         return UpdateBSO(obj as BSO, oci);
     }
 }
Exemple #39
0
 public void sendCommand(ref Apdu apdu)
 {
     apduCommand = apdu;
     sendCommand();
     apdu = apduCommand;
 }
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;

            if (apdu.P1 == 0x80 && apdu.P2 == 0x86)
            {
                // DEC
                BSO key = handler.GetEnvironmentKey(SecurityEnvironmentComponent.CON);
                if (key.Class != BSOClass.PSO)
                {
                    return(Error.P1OrP2NotValid);
                }

                if (key.Algo != BSOAlgo.RSA_Enc &&
                    key.Algo != BSOAlgo.DES3_Enc_SMEnc)
                {
                    return(Error.P1OrP2NotValid);
                }

                if (!handler.IsVerifiedAC(key, BSO_AC.AC_USE))
                {
                    return(Error.SecurityStatusNotSatisfied);
                }

                byte[] data = handler.Decrypt(key, new ByteArray(apdu.Data).Sub(1));
                // devo paddare per arrivare alla lunghezza del modulo
                if (key.Algo == BSOAlgo.RSA_Enc)
                {
                    if (data.Length < (key.data.Length - 2))
                    {
                        var dataPad = new byte[key.data.Length - 2];
                        data.CopyTo(dataPad, dataPad.Length - data.Length);
                        data = dataPad;
                    }
                }
                return(Util.Response(data, Error.Ok));
            }
            else if (apdu.P1 == 0x86 && apdu.P2 == 0x80)
            {
                // ENC
                BSO key = handler.GetEnvironmentKey(SecurityEnvironmentComponent.CON);
                if (key.Class != BSOClass.PSO)
                {
                    return(Error.P1OrP2NotValid);
                }

                if (key.Algo != BSOAlgo.RSA_Enc &&
                    key.Algo != BSOAlgo.DES3_Enc_SMEnc)
                {
                    return(Error.P1OrP2NotValid);
                }

                if (!handler.IsVerifiedAC(key, BSO_AC.AC_USE))
                {
                    return(Error.SecurityStatusNotSatisfied);
                }

                byte[] data = handler.Encrypt(key, apdu.Data);
                if (key.Algo == BSOAlgo.RSA_Enc && data.Length < (key.data.Length - 2))
                {
                    var dataPad = new byte[key.data.Length - 2];
                    data.CopyTo(dataPad, dataPad.Length - data.Length);
                    data = dataPad;
                }
                return(Util.Response(new ByteArray(0).Append(data), Error.Ok));
            }
            else if (apdu.P1 == 0x9E && apdu.P2 == 0x9A)
            {
                // CDS
                BSO key = handler.GetEnvironmentKey(SecurityEnvironmentComponent.CDS);
                if (key.Class != BSOClass.PSO)
                {
                    return(Error.P1OrP2NotValid);
                }

                if (key.Algo != BSOAlgo.RSA_DS_Test)
                {
                    return(Error.P1OrP2NotValid);
                }

                if (!handler.IsVerifiedAC(key, BSO_AC.AC_USE))
                {
                    return(Error.SecurityStatusNotSatisfied);
                }

                byte[] data = handler.DigitalSignature(key, apdu.Data);
                if (data.Length < (key.data.Length - 2))
                {
                    var dataPad = new byte[key.data.Length - 2];
                    data.CopyTo(dataPad, dataPad.Length - data.Length);
                    data = dataPad;
                }
                return(Util.Response(data, Error.Ok));
            }
            return(Error.P1OrP2NotValid);
        }
 public byte[] ProcessApdu(byte[] apdu)
 {
     try
     {
         Apdu Apdu = new Apdu(apdu);
         card.Log(Apdu);
         Apdu initialApdu = Apdu;
         ushort key = Util.ToUShort((byte)(Apdu.CLA & 0xf0),Apdu.INS);
         if (commandMap.ContainsKey(key))
         {
             BSO sigIn, encIn, sigOut, encOut;
             commandMap[key].getSMKeys(Apdu, out sigIn, out encIn, out sigOut, out encOut);
             var challenge = context.Challenge;
             if (sigIn != null || encIn != null || sigOut != null || encOut != null)
             {
                 if (!Apdu.IsSM)
                     return Error.SMObjectMissing;
                 if (sigIn != null)
                     context.Challenge = null;
                 Apdu = Apdu.GetClearApdu(Apdu, encIn, sigIn, encOut, sigOut, challenge);
             }
             else
             {
                 if (Apdu.IsSM)
                     return Error.ConditionsOfUseNotSatisfied;
             }
             var resp=commandMap[key].processCommand(Apdu);
             card.Log(resp);
             var random = context.Random;
             if (encOut != null || sigOut != null || sigIn != null || encIn != null)
             {
                 if (sigOut != null)
                     context.Challenge = null;
                 context.Random = null;
                 return Apdu.GetSMResponse(initialApdu, resp, encOut, sigOut, random);
             }
             else
             {
                 return resp;
             }
         }
         card.Log("Comando non riconosciuto");
         card.Log(Error.InsNotValid);
         return Error.InsNotValid;
     }
     catch (ISO7816Exception cex)
     {
         card.Log((byte[])cex.CardError);
         return cex.CardError;
     }
     catch (Exception ex)
     {
         card.Log(ex.ToString());
         return Error.InternalError;
     }
 }
Exemple #42
0
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;

            if (apdu.P2 != 0)
            {
                return(Error.P1OrP2NotValid);
            }
            CardSelectable obj = null;

            switch (apdu.P1)
            {
            case 0:
                if (apdu.Data == null || apdu.Data.Length == 0)
                {
                    obj = card.MasterFile;
                }
                else
                {
                    if (apdu.Data.Length != 2)
                    {
                        return(Error.DataFieldNotValid);
                    }
                    ushort id = Util.ToUShort(apdu.Data);
                    if (id == 0x3f00)
                    {
                        obj = card.MasterFile;
                    }
                    else
                    {
                        obj = context.CurDF.GetChildEForDF(id);
                        if (obj == null && context.CurDF.Parent != null)
                        {
                            obj = context.CurDF.Parent.GetChildEForDF(id);
                        }
                        if (obj == null && context.CurDF.Parent != null && id == context.CurDF.ID)
                        {
                            obj = context.CurDF.Parent;
                        }
                    }
                }
                if (obj == null)
                {
                    return(Error.FileNotFound);
                }

                context.CurFile = obj;
                break;

            case 1:
                if (apdu.Data == null || apdu.Data.Length != 2)
                {
                    return(Error.DataFieldNotValid);
                }
                ushort id2 = Util.ToUShort(apdu.Data);
                obj = context.CurDF.GetChildDF(id2);
                if (obj == null)
                {
                    return(Error.FileNotFound);
                }
                context.CurFile = obj;
                break;

            case 2:
                if (apdu.Data == null || apdu.Data.Length != 2)
                {
                    return(Error.DataFieldNotValid);
                }
                ushort id3 = Util.ToUShort(apdu.Data);
                obj = context.CurDF.GetChildDF(id3);
                if (obj == null)
                {
                    return(Error.FileNotFound);
                }
                context.CurFile = obj;
                break;

            case 3:
                if (apdu.Data != null && apdu.Data.Length != 0)
                {
                    return(Error.DataFieldNotValid);
                }

                if (context.CurDF.Parent == null)
                {
                    return(Error.FileNotFound);
                }

                context.CurFile = context.CurDF.Parent;
                break;

            case 4:
                if (apdu.Data == null || apdu.Data.Length == 0)
                {
                    return(Error.DataFieldNotValid);
                }

                DF namedDF = handler.GetNamedDF(card.MasterFile, apdu.Data);
                if (namedDF == null)
                {
                    return(Error.FileNotFound);
                }

                context.CurFile = namedDF;
                break;

            case 8:
                if (apdu.Data == null || apdu.Data.Length == 0)
                {
                    obj = card.MasterFile;
                }
                else
                if (apdu.Data != null && apdu.Data.Length == 2 && Util.ToUShort(apdu.Data) == 0x3f00)
                {
                    obj = card.MasterFile;
                }
                else
                {
                    if ((apdu.Data.Length % 2) != 0)
                    {
                        return(Error.DataFieldNotValid);
                    }
                    obj = handler.GetSelectablePath(card.MasterFile, apdu.Data, 0);
                    if (obj == null)
                    {
                        return(Error.FileNotFound);
                    }
                }
                context.CurFile = obj;
                break;

            case 9:
                if (apdu.Data == null || apdu.Data.Length == 0)
                {
                    return(Error.DataFieldNotValid);
                }
                else
                {
                    if ((apdu.Data.Length % 2) != 0)
                    {
                        return(Error.DataFieldNotValid);
                    }
                    if (context.CurDF == null)
                    {
                        return(Error.ClaNotValid);
                    }
                    obj = handler.GetSelectablePath(context.CurDF, apdu.Data, 0);
                    if (obj == null)
                    {
                        return(Error.FileNotFound);
                    }
                }
                context.CurFile = obj;
                break;

            default:
                return(Error.P1OrP2NotValid);
            }
            if (context.CurFile == null)
            {
                return(Error.FileNotFound);
            }
            var outData = (context.CurFile as IObjectWithFCI).FCI;
            TLV tlv     = new TLV();
            TLV tlv2    = new TLV();

            tlv2.elems.AddRange(outData);
            tlv.addTag(0x6f, tlv2.GetBytes());
            return(Util.Response(tlv.GetBytes(), Error.Ok));
        }
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;

            if (context.CurEF == null)
                return Error.NoCurrentEFSelected;

            if (!(context.CurEF is EFRecord))
                return Error.CommandIncompatibleWithFileStructure;

            if (apdu.Data == null || apdu.Data.Length == 0)
                return Error.DataFieldNotValid;

            var efRec = context.CurEF as EFRecord;

            if (!handler.IsVerifiedAC(efRec, EF_AC.AC_UPDATE))
                return Error.SecurityStatusNotSatisfied;

            int? recNum=0;
            if (apdu.P1 == 0) {
                if (apdu.P2 == 0)
                    recNum = 0;
                else if (apdu.P2 == 1)
                    recNum = efRec.Data.Count - 1;
                else if (apdu.P2 == 2)
                {
                    if (!context.CurRecord.HasValue)
                        recNum = 0;
                    else
                        recNum = context.CurRecord.Value+1;
                }
                else if (apdu.P2 == 3)
                {
                    if (!context.CurRecord.HasValue)
                        recNum = efRec.Data.Count - 1;
                    else
                        recNum = context.CurRecord.Value - 1;
                }
                else if (apdu.P2 == 4)
                {
                    if (!context.CurRecord.HasValue)
                        recNum = 0;
                    else
                        recNum = context.CurRecord.Value;
                }
            }
            else if (apdu.P2 == 4) {
                if (apdu.P1 <= efRec.Data.Count && apdu.P1 > 0)
                    recNum = apdu.P1 - 1;
                else
                    return Error.RecordNotFound;
            }
            else if (efRec is EFLinearTLV) {
                var efl = efRec as EFLinearTLV;
                if (apdu.P2 == 0) {
                    recNum = efl.SearchRecord(apdu.P1);
                }
                else if (apdu.P2 == 1) {
                    recNum = efl.SearchRecordRev(apdu.P1);
                }
                else if (apdu.P2 == 2) {
                    if (context.CurRecord.HasValue)
                        recNum = efl.SearchRecord(context.CurRecord.Value, apdu.P1);
                    else
                        recNum = efl.SearchRecord(apdu.P1);
                }
                else if (apdu.P2 == 3) {
                    if (context.CurRecord.HasValue)
                        recNum = efl.SearchRecordRev(context.CurRecord.Value, apdu.P1);
                    else
                        recNum = efl.SearchRecordRev(apdu.P1);
                }
            }
            if (!recNum.HasValue)
                return Error.RecordNotFound;

            if (apdu.P2 != 4)
                if (!(efRec is EFCyclic))
                    context.CurRecord = recNum;
                else
                    context.CurRecord = 0;

            if (recNum.Value >= efRec.Data.Count)
                return Error.RecordNotFound;

            efRec.Update(recNum.Value, apdu.Data);
            return Error.Ok;
        }
Exemple #44
0
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;

            if (apdu.P1 != 0 && apdu.P1 != 1)
            {
                return(Error.P1OrP2NotValid);
            }
            bool verify = apdu.P1 == 0;

            ushort pinId     = (ushort)(apdu.P2 & 0x7f);
            bool   backTrack = (apdu.P2 & 0x80) != 0;
            BSO    pin       = null;

            if (backTrack)
            {
                pin = context.CurDF.GetChildBSO(pinId, backTrack);
            }
            else
            {
                pin = context.CurDF.Owner.MasterFile.GetChildBSO(pinId, false);
            }
            if (pin == null)
            {
                return(Error.FileNotFound);
            }
            // deve essere un test object di tipo PIN
            if (pin.Class != BSOClass.Test || pin.Algo != BSOAlgo.PIN)
            {
                return(Error.InsNotValid);
            }

            int startPin = 0;

            if (verify)
            {
                // cerco il BSO referenziato dall' AC_CHANGE del PIN
                byte condition = pin.AC[BSO_AC.AC_CHANGE];
                if (condition == AC.Never)
                {
                    return(Error.ObjectNotFound);
                }
                if (condition != AC.Always)
                {
                    BSO changePin = pin.Parent.GetChildBSO(condition, true);
                    if (changePin == null)
                    {
                        return(Error.FileNotFound);
                    }

                    if (changePin.Class != BSOClass.Test || changePin.Algo != BSOAlgo.PIN)
                    {
                        return(Error.InsNotValid);
                    }

                    if (!handler.VerifyBSO(changePin, new ByteArray(apdu.Data).Left(changePin.Data.Length)))
                    {
                        return(Error.VerificationFailed);
                    }
                    startPin = changePin.Data.Length;
                }
            }
            if (startPin == apdu.Data.Length)
            {
                return(Error.WrongLength);
            }
            if (handler.IsVerifiedAC(pin, BSO_AC.AC_CHANGE))
            {
                pin.Data = new ByteArray(apdu.Data).Sub(startPin);
            }
            else
            {
                return(Error.SecurityStatusNotSatisfied);
            }

            handler.UnblockBSO(pin);
            return(Error.Ok);
        }
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;

            if (apdu.P1 != 0 || apdu.P2 != 0)
            {
                return(Error.P1OrP2NotValid);
            }
            if (apdu.Data == null || apdu.Data.Length != 8)
            {
                return(Error.DataFieldNotValid);
            }

            ByteArray data = apdu.Data;

            if (data[4] != 0 || data[5] != 0)
            {
                return(Error.DataFieldNotValid);
            }

            ushort pubExpLen = Util.ToUShort(data, 6);

            if (pubExpLen == 0)
            {
                pubExpLen = 24;
            }
            if (pubExpLen < 16 || pubExpLen > 64)
            {
                return(Error.DataFieldNotValid);
            }

            var Module = context.CurDF.GetChildBSO(Util.ToUShort(data[0], data[1]), false);

            if (Module == null)
            {
                return(Error.ObjectNotFound);
            }
            if (Module.Algo != BSOAlgo.RSA_DS_Test &&
                Module.Algo != BSOAlgo.RSA_Enc)
            {
                return(Error.InsNotValid);
            }

            if (!handler.IsVerifiedAC(Module, BSO_AC.AC_GENKEYPAIR))
            {
                return(Error.SecurityStatusNotSatisfied);
            }

            var privExp = context.CurDF.GetChildBSO(Util.ToUShort((byte)(data[0] | 1), data[1]), false);

            if (privExp == null)
            {
                return(Error.ObjectNotFound);
            }
            if (privExp.Algo != BSOAlgo.RSA_DS_Test &&
                privExp.Algo != BSOAlgo.RSA_Enc)
            {
                return(Error.InsNotValid);
            }

            var pubKey = context.CurDF.GetChildEF(Util.ToUShort(data.Sub(2, 2)));

            if (pubKey == null)
            {
                return(Error.FileNotFound);
            }

            if (!(pubKey is EFLinearTLV))
            {
                return(Error.CommandIncompatibleWithFileStructure);
            }

            if (!handler.IsVerifiedAC(pubKey, EF_AC.AC_APPEND))
            {
                return(Error.SecurityStatusNotSatisfied);
            }

            handler.GenerateKey(privExp, Module, pubKey as EFLinearTLV, pubExpLen);

            return(Error.Ok);
        }