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 (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));
        }
Exemplo n.º 3
0
        public virtual byte[] processCommand(Apdu apdu)
        {
            CardContext context = handler.Context;

            if (apdu.P1 != 0)
            {
                return(Error.P1OrP2NotValid);
            }
            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)
            {
                return(Error.FileNotFound);
            }
            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);
            }
        }
Exemplo n.º 4
0
        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);
        }
Exemplo n.º 5
0
        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);
        }
Exemplo n.º 6
0
        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);
        }
Exemplo n.º 7
0
        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[] 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);
        }
Exemplo n.º 9
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 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);
        }
Exemplo n.º 11
0
        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));
        }
Exemplo n.º 12
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);
        }
        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);
        }