private void SendDisconnect()
        {
            SessionControl commandKmmBody = new SessionControl();

            commandKmmBody.SessionControlOpcode = SessionControl.ScOpcode.Disconnect;
            commandKmmBody.SourceDeviceType     = SessionControl.ScSourceDeviceType.Kfd;

            KmmFrame commandKmmFrame = new KmmFrame(commandKmmBody);

            byte[] toRadio = commandKmmFrame.ToBytesWithPreamble(0x00);

            byte[] fromRadio = PerformKmmTransfer(toRadio);

            KmmFrame responseKmmFrame = new KmmFrame(true, fromRadio);

            KmmBody responseKmmBody = responseKmmFrame.KmmBody;

            if (responseKmmBody is SessionControl)
            {
                SessionControl kmm = responseKmmBody as SessionControl;

                if (kmm.SessionControlOpcode != SessionControl.ScOpcode.DisconnectAck)
                {
                    throw new Exception(string.Format("received unexpected session control opcode (0x{0:X2}) {1}", (byte)kmm.SessionControlOpcode, kmm.SessionControlOpcode.ToString()));
                }
            }
            else
            {
                throw new Exception("unexpected kmm");
            }
        }
        private void Mfid90SendDisconnect()
        {
            Mfid90SessionControlVer1 commandKmmBody = new Mfid90SessionControlVer1();

            commandKmmBody.SessionControlOpcode  = Mfid90SessionControlVer1.ScOpcode.Disconnect;
            commandKmmBody.SourceDeviceType      = Mfid90SessionControlVer1.ScSourceDeviceType.Kfd;
            commandKmmBody.IsSessionTypeIncluded = false;

            KmmFrame commandKmmFrame = new KmmFrame(commandKmmBody);

            byte[] toRadio = commandKmmFrame.ToBytesWithPreamble(0x90);

            byte[] fromRadio = PerformKmmTransfer(toRadio);

            KmmFrame responseKmmFrame = new KmmFrame(true, fromRadio);

            KmmBody responseKmmBody = responseKmmFrame.KmmBody;

            if (responseKmmBody is Mfid90SessionControlVer1)
            {
                Mfid90SessionControlVer1 kmm = responseKmmBody as Mfid90SessionControlVer1;

                if (kmm.SessionControlOpcode != Mfid90SessionControlVer1.ScOpcode.DisconnectAck)
                {
                    throw new Exception(string.Format("received unexpected session control opcode (0x{0:X2}) {1}", (byte)kmm.SessionControlOpcode, kmm.SessionControlOpcode.ToString()));
                }
            }
            else
            {
                throw new Exception("unexpected kmm");
            }
        }
        /* TIA 102.AACD-A 3.8.6 */
        public void EraseAllKeys()
        {
            Begin();

            ZeroizeCommand commandKmmBody = new ZeroizeCommand();

            KmmBody responseKmmBody = TxRxKmm(commandKmmBody);

            if (responseKmmBody is ZeroizeResponse)
            {
                Logger.Debug("zerozied");
            }
            else if (responseKmmBody is NegativeAcknowledgment)
            {
                NegativeAcknowledgment kmm = responseKmmBody as NegativeAcknowledgment;

                throw new Exception(string.Format("recieved negative acknowledgment, status {0} (0x{1:X2})", kmm.Status.ToString(), (byte)kmm.Status));
            }
            else
            {
                throw new Exception("unexpected kmm");
            }

            End();
        }
예제 #4
0
        /* TIA 102.AACD-A 3.7.2.9 */
        public List <RspKeysetInfo> ViewKeysetTaggingInfo()
        {
            //cg
            List <RspKeysetInfo> result = new List <RspKeysetInfo>();

            Begin();

            try
            {
                InventoryCommandListKeysetTaggingInfo commandKmmBody = new InventoryCommandListKeysetTaggingInfo();

                KmmBody responseKmmBody = TxRxKmm(commandKmmBody);

                if (responseKmmBody is InventoryResponseListKeysetTaggingInfo)
                {
                    Logger.Debug("KeysetTaggingInfo response");

                    InventoryResponseListKeysetTaggingInfo kmm = responseKmmBody as InventoryResponseListKeysetTaggingInfo;

                    for (int i = 0; i < kmm.KeysetItems.Count; i++)
                    {
                        KeysetItem item = kmm.KeysetItems[i];

                        RspKeysetInfo res = new RspKeysetInfo();

                        res.KeysetId           = item.KeysetId;
                        res.KeysetName         = item.KeysetName;
                        res.KeysetType         = item.KeysetType;
                        res.ActivationDateTime = item.ActivationDateTime;
                        res.ReservedField      = item.ReservedField;

                        result.Add(res);
                    }
                }
                else if (responseKmmBody is NegativeAcknowledgment)
                {
                    NegativeAcknowledgment kmm = responseKmmBody as NegativeAcknowledgment;

                    string statusDescr  = OperationStatusExtensions.ToStatusString(kmm.Status);
                    string statusReason = OperationStatusExtensions.ToReasonString(kmm.Status);
                    throw new Exception(string.Format("received negative acknowledgment{0}status: {1} (0x{2:X2}){0}{3}", Environment.NewLine, statusDescr, kmm.Status, statusReason));
                }
                else
                {
                    throw new Exception("unexpected kmm");
                }
            }
            catch
            {
                End();

                throw;
            }

            End();

            return(result);
        }
예제 #5
0
        private KmmBody TxRxKmm(KmmBody commandKmmBody)
        {
            KmmFrame commandKmmFrame = new KmmFrame(commandKmmBody);

            byte[] toRadio = WithPreamble ? commandKmmFrame.ToBytesWithPreamble(Mfid) : commandKmmFrame.ToBytes();

            byte[] fromRadio = DeviceProtocol.PerformKmmTransfer(toRadio);

            KmmFrame responseKmmFrame = new KmmFrame(WithPreamble, fromRadio);

            return(responseKmmFrame.KmmBody);
        }
예제 #6
0
        /* TIA 102.AACD-A 3.8.7 */
        public List <RspKeyInfo> ViewKeyInfo()
        {
            List <RspKeyInfo> result = new List <RspKeyInfo>();

            Begin();

            InventoryCommandListActiveKeys commandKmmBody = new InventoryCommandListActiveKeys();

            commandKmmBody.InventoryMarker  = 0;
            commandKmmBody.MaxKeysRequested = 78;

            KmmBody responseKmmBody = TxRxKmm(commandKmmBody);

            if (responseKmmBody is InventoryResponseListActiveKeys)
            {
                InventoryResponseListActiveKeys kmm = responseKmmBody as InventoryResponseListActiveKeys;

                Logger.Debug("number of active keys: {0}", kmm.Keys.Count);

                for (int i = 0; i < kmm.Keys.Count; i++)
                {
                    KeyInfo info = kmm.Keys[i];

                    Logger.Debug("* key index {0} *", i);
                    Logger.Debug("keyset id: {0} (dec), {0:X} (hex)", info.KeySetId);
                    Logger.Debug("sln: {0} (dec), {0:X} (hex)", info.SLN);
                    Logger.Debug("algorithm id: {0} (dec), {0:X} (hex)", info.AlgorithmId);
                    Logger.Debug("key id: {0} (dec), {0:X} (hex)", info.KeyId);

                    RspKeyInfo res = new RspKeyInfo();

                    res.KeysetId    = info.KeySetId;
                    res.Sln         = info.SLN;
                    res.AlgorithmId = info.AlgorithmId;
                    res.KeyId       = info.KeyId;

                    result.Add(res);
                }
            }
            else
            {
                throw new Exception("unexpected kmm");
            }

            End();

            return(result);
        }
예제 #7
0
        private KmmBody TxRxKmm(KmmBody commandKmmBody)
        {
            KmmFrame commandKmmFrame = new KmmFrame(commandKmmBody);

            byte[] toRadio = commandKmmFrame.ToBytes();

            Logger.Debug("KFD -> MR KMM FRAME: {0}", BitConverter.ToString(toRadio));

            byte[] fromRadio = ThreeWireProtocol.PerformKmmTransfer(toRadio);

            Logger.Debug("MR -> KFD KMM FRAME: {0}", BitConverter.ToString(fromRadio));

            KmmFrame responseKmmFrame = new KmmFrame(fromRadio);

            return(responseKmmFrame.KmmBody);
        }
예제 #8
0
        public RspRsiInfo ChangeRsi(int rsiOld, int rsiNew, int mnp)
        {
            RspRsiInfo result = new RspRsiInfo();

            Begin();

            try
            {
                ChangeRsiCommand cmdKmmBody = new ChangeRsiCommand();
                cmdKmmBody.RsiOld        = rsiOld;
                cmdKmmBody.RsiNew        = rsiNew;
                cmdKmmBody.MessageNumber = mnp;

                KmmBody rspKmmBody = TxRxKmm(cmdKmmBody);

                if (rspKmmBody is ChangeRsiResponse)
                {
                    ChangeRsiResponse kmm = rspKmmBody as ChangeRsiResponse;
                    result.RSI    = rsiNew;
                    result.MN     = mnp;
                    result.Status = kmm.Status;
                }
                else if (rspKmmBody is NegativeAcknowledgment)
                {
                    NegativeAcknowledgment kmm = rspKmmBody as NegativeAcknowledgment;

                    string statusDescr  = OperationStatusExtensions.ToStatusString(kmm.Status);
                    string statusReason = OperationStatusExtensions.ToReasonString(kmm.Status);
                    throw new Exception(string.Format("received negative acknowledgment{0}status: {1} (0x{2:X2}){0}{3}", Environment.NewLine, statusDescr, kmm.Status, statusReason));
                }
                else
                {
                    throw new Exception("unexpected kmm");
                }
            }
            catch
            {
                End();

                throw;
            }

            End();

            return(result);
        }
예제 #9
0
        /* TIA 102.AACD-A 3.7.2.13 */
        public int ViewMnp()
        {
            //cg
            int result = new int();

            Begin();

            try
            {
                InventoryCommandListMnp commandKmmBody = new InventoryCommandListMnp();

                KmmBody responseKmmBody = TxRxKmm(commandKmmBody);

                if (responseKmmBody is InventoryResponseListMnp)
                {
                    Logger.Debug("MNP response");

                    InventoryResponseListMnp kmm = responseKmmBody as InventoryResponseListMnp;

                    result = kmm.MessageNumberPeriod;
                }
                else if (responseKmmBody is NegativeAcknowledgment)
                {
                    NegativeAcknowledgment kmm = responseKmmBody as NegativeAcknowledgment;

                    string statusDescr  = OperationStatusExtensions.ToStatusString(kmm.Status);
                    string statusReason = OperationStatusExtensions.ToReasonString(kmm.Status);
                    throw new Exception(string.Format("received negative acknowledgment{0}status: {1} (0x{2:X2}){0}{3}", Environment.NewLine, statusDescr, kmm.Status, statusReason));
                }
                else
                {
                    throw new Exception("unexpected kmm");
                }
            }
            catch
            {
                End();

                throw;
            }

            End();

            return(result);
        }
예제 #10
0
        /* TIA 102.AACD-A 3.7.2.22 */
        public RspRsiInfo LoadConfig(int kmfRsi, int mnp)
        {
            //cg
            RspRsiInfo result = new RspRsiInfo();

            Begin();

            try
            {
                LoadConfigCommand cmdKmmBody = new LoadConfigCommand();
                cmdKmmBody.KmfRsi = kmfRsi;
                cmdKmmBody.MessageNumberPeriod = mnp;
                KmmBody rspKmmBody = TxRxKmm(cmdKmmBody);
                if (rspKmmBody is LoadConfigResponse)
                {
                    LoadConfigResponse kmm = rspKmmBody as LoadConfigResponse;
                    result.RSI    = kmm.RSI;
                    result.MN     = kmm.MN;
                    result.Status = kmm.Status;
                    //Console.WriteLine("response status: {0}", kmm.Status);
                }
                else if (rspKmmBody is NegativeAcknowledgment)
                {
                    NegativeAcknowledgment kmm = rspKmmBody as NegativeAcknowledgment;

                    string statusDescr  = OperationStatusExtensions.ToStatusString(kmm.Status);
                    string statusReason = OperationStatusExtensions.ToReasonString(kmm.Status);
                    throw new Exception(string.Format("received negative acknowledgment{0}status: {1} (0x{2:X2}){0}{3}", Environment.NewLine, statusDescr, kmm.Status, statusReason));
                }
                else
                {
                    throw new Exception("unexpected kmm");
                }
            }
            catch
            {
                End();

                throw;
            }

            End();

            return(result);
        }
예제 #11
0
        public RspChangeoverInfo ActivateKeyset(int keysetSuperseded, int keysetActivated)
        {
            RspChangeoverInfo result = new RspChangeoverInfo();

            Begin();

            try
            {
                ChangeoverCommand cmdKmmBody = new ChangeoverCommand();
                cmdKmmBody.KeysetIdSuperseded = keysetSuperseded;
                cmdKmmBody.KeysetIdActivated  = keysetActivated;
                KmmBody rspKmmBody = TxRxKmm(cmdKmmBody);

                if (rspKmmBody is ChangeoverResponse)
                {
                    ChangeoverResponse kmm = rspKmmBody as ChangeoverResponse;

                    result.KeysetIdSuperseded = kmm.KeysetIdSuperseded;
                    result.KeysetIdActivated  = kmm.KeysetIdActivated;
                }
                else if (rspKmmBody is NegativeAcknowledgment)
                {
                    NegativeAcknowledgment kmm = rspKmmBody as NegativeAcknowledgment;

                    string statusDescr  = OperationStatusExtensions.ToStatusString(kmm.Status);
                    string statusReason = OperationStatusExtensions.ToReasonString(kmm.Status);
                    throw new Exception(string.Format("received negative acknowledgment{0}status: {1} (0x{2:X2}){0}{3}", Environment.NewLine, statusDescr, kmm.Status, statusReason));
                }
                else
                {
                    throw new Exception("unexpected kmm");
                }
            }
            catch
            {
                End();

                throw;
            }

            End();

            return(result);
        }
예제 #12
0
        /* TIA 102.AACD-A 3.8.6 */
        public void EraseAllKeys()
        {
            Begin();

            ZeroizeCommand commandKmmBody = new ZeroizeCommand();

            KmmBody responseKmmBody = TxRxKmm(commandKmmBody);

            if (responseKmmBody is ZeroizeResponse)
            {
                Logger.Debug("zerozied");
            }
            else
            {
                throw new Exception("unexpected kmm");
            }

            End();
        }
예제 #13
0
        /* TIA 102.AACD-A 3.8.6 */
        public void EraseAllKeys()
        {
            Begin();

            try
            {
                ZeroizeCommand commandKmmBody = new ZeroizeCommand();

                KmmBody responseKmmBody = TxRxKmm(commandKmmBody);

                if (responseKmmBody is ZeroizeResponse)
                {
                    Logger.Debug("zerozied");
                }
                else if (responseKmmBody is NegativeAcknowledgment)
                {
                    NegativeAcknowledgment kmm = responseKmmBody as NegativeAcknowledgment;

                    string statusDescr  = OperationStatusExtensions.ToStatusString(kmm.Status);
                    string statusReason = OperationStatusExtensions.ToReasonString(kmm.Status);
                    throw new Exception(string.Format("received negative acknowledgment{0}status: {1} (0x{2:X2}){0}{3}", Environment.NewLine, statusDescr, kmm.Status, statusReason));
                }
                else
                {
                    throw new Exception("unexpected kmm");
                }
            }
            catch
            {
                End();

                throw;
            }

            End();
        }
예제 #14
0
        public void MrRunProducer()
        {
            try
            {
                while (true)
                {
                    byte rx;

                    /* RX: KEY SIGNATURE */

                    // currently there is no rx key signature function in the adapter
                    // however, the key signature will appear as a 0x00 byte

                    // the 5 second timeout should prevent most sync issues, however
                    // a rx key signature function should be added to the adapter
                    // to make this more robust and correct

                    Log.Debug("in: waiting for key signature");
                    rx = Protocol.GetByte(TIMEOUT_NONE);
                    Log.Trace("in: {0}", Utility.DataFormat(rx));

                    byte sig = 0x00; // key signature

                    if (rx == sig)
                    {
                        Log.Debug("in: got key signature");
                    }
                    else
                    {
                        string msg = string.Format("in: unexpected key signature opcode, expected ({0}) got ({1})", Utility.DataFormat(sig), Utility.DataFormat(rx));
                        Log.Warn(msg);
                        continue;
                    }

                    /* RX: READY REQUEST */

                    try
                    {
                        Log.Debug("in: waiting for ready request opcode");
                        rx = Protocol.GetByte(TIMEOUT_STD);
                        Log.Trace("in: {0}", Utility.DataFormat(rx));
                    }
                    catch (Exception)
                    {
                        string msg = string.Format("in: timed out waiting for ready request opcode");
                        Log.Warn(msg);
                        continue;
                    }

                    if (rx == OPCODE_READY_REQ)
                    {
                        Log.Debug("in: got ready request opcode");
                    }
                    else
                    {
                        string msg = string.Format("in: unexpected ready request opcode, expected ({0}) got ({1})", Utility.DataFormat(OPCODE_READY_REQ), Utility.DataFormat(rx));
                        Log.Warn(msg);
                        continue;
                    }

                    /* TX: READY GENERAL MODE */

                    Log.Debug("out: ready general mode opcode");
                    Log.Trace("out: {0}", Utility.DataFormat(OPCODE_READY_GENERAL_MODE));
                    Protocol.SendByte(OPCODE_READY_GENERAL_MODE);

                    while (true)
                    {
                        /* RX: FRAME TYPE */

                        try
                        {
                            Log.Debug("in: waiting for frame type opcode");
                            rx = Protocol.GetByte(TIMEOUT_STD);
                            Log.Trace("in: {0}", Utility.DataFormat(rx));
                        }
                        catch (Exception)
                        {
                            string msg = string.Format("in: timed out waiting for frame type opcode");
                            Log.Warn(msg);
                            break;
                        }

                        if (rx == OPCODE_KMM)
                        {
                            Log.Debug("in: got kmm opcode");

                            List <byte> rxFrame;

                            try
                            {
                                rxFrame = ParseKmmFrame();
                            }
                            catch (Exception ex)
                            {
                                Log.Warn(ex.Message);
                                break;
                            }

                            KmmFrame kfdKmmFrame = null;

                            try
                            {
                                kfdKmmFrame = new KmmFrame(rxFrame.ToArray());
                            }
                            catch (Exception ex)
                            {
                                Log.Warn(ex.Message);

                                byte[] message = rxFrame.ToArray();

                                if (message.Length != 0)
                                {
                                    Log.Warn("unexpected message id: {0} (dec), {0:X} (hex)", message[0]);

                                    NegativeAcknowledgment kmm = new NegativeAcknowledgment();

                                    kmm.AcknowledgedMessageId = (MessageId)message[0];
                                    kmm.Status = AckStatus.InvalidMessageId;

                                    KmmFrame frame = new KmmFrame(kmm);

                                    SendKmm(frame.ToBytes());
                                }

                                continue;
                            }

                            KmmBody kfdKmmBody = kfdKmmFrame.KmmBody;

                            if (kfdKmmBody is InventoryCommandListActiveKsetIds)
                            {
                                InventoryResponseListActiveKsetIds mrKmm = new InventoryResponseListActiveKsetIds();

                                // do not return any keysets, to match factory Motorola SU behavior

                                KmmFrame commandKmmFrame = new KmmFrame(mrKmm);

                                SendKmm(commandKmmFrame.ToBytes());
                            }
                            else if (kfdKmmBody is ModifyKeyCommand)
                            {
                                ModifyKeyCommand cmdKmm = kfdKmmBody as ModifyKeyCommand;

                                Log.Debug("keyset id: {0} (dec), {0:X} (hex)", cmdKmm.KeysetId);
                                Log.Debug("algorithm id: {0} (dec), {0:X} (hex)", cmdKmm.AlgorithmId);

                                RekeyAcknowledgment rspKmm = new RekeyAcknowledgment();

                                rspKmm.MessageIdAcknowledged = MessageId.ModifyKeyCommand;
                                rspKmm.NumberOfItems         = cmdKmm.KeyItems.Count;

                                for (int i = 0; i < cmdKmm.KeyItems.Count; i++)
                                {
                                    KeyItem item = cmdKmm.KeyItems[i];

                                    Log.Debug("* key item {0} *", i);
                                    Log.Debug("erase: {0}", item.Erase);
                                    Log.Debug("sln: {0} (dec), {0:X} (hex)", item.SLN);
                                    Log.Debug("key id: {0} (dec), {0:X} (hex)", item.KeyId);
                                    Log.Debug("key: {0}", BitConverter.ToString(item.Key));

                                    string algName = string.Empty;

                                    if (Enum.IsDefined(typeof(AlgorithmId), (byte)cmdKmm.AlgorithmId))
                                    {
                                        algName = ((AlgorithmId)cmdKmm.AlgorithmId).ToString();
                                    }
                                    else
                                    {
                                        algName = "UNKNOWN";
                                    }

                                    Status +=
                                        string.Format("Keyset ID: {0} (dec), {0:X} (hex)", cmdKmm.KeysetId) + Environment.NewLine +
                                        string.Format("SLN/CKR: {0} (dec), {0:X} (hex)", item.SLN) + Environment.NewLine +
                                        string.Format("Key ID: {0} (dec), {0:X} (hex)", item.KeyId) + Environment.NewLine +
                                        string.Format("Algorithm: {0} (dec), {0:X} (hex), {1}", cmdKmm.AlgorithmId, algName) + Environment.NewLine +
                                        string.Format("Key: {0}", BitConverter.ToString(item.Key).Replace("-", string.Empty)) + Environment.NewLine +
                                        "--" + Environment.NewLine;

                                    KeyStatus status = new KeyStatus();

                                    status.AlgorithmId = cmdKmm.AlgorithmId;
                                    status.KeyId       = item.KeyId;
                                    status.Status      = 0x00; // command was performed

                                    rspKmm.Keys.Add(status);
                                }

                                KmmFrame cmdKmmFrame = new KmmFrame(rspKmm);

                                SendKmm(cmdKmmFrame.ToBytes());
                            }
                        }
                        else if (rx == OPCODE_TRANSFER_DONE)
                        {
                            Log.Debug("in: got transfer done opcode");

                            /* TX: TRANSFER DONE */

                            Log.Debug("out: transfer done opcode");
                            Log.Trace("out: {0}", Utility.DataFormat(OPCODE_TRANSFER_DONE));
                            Protocol.SendByte(OPCODE_TRANSFER_DONE);

                            /* RX: DISCONNECT */

                            try
                            {
                                Log.Debug("in: waiting for disconnect opcode");
                                rx = Protocol.GetByte(TIMEOUT_STD);
                                Log.Trace("in: {0}", Utility.DataFormat(rx));
                            }
                            catch (Exception)
                            {
                                string msg = string.Format("in: timed out waiting for disconnect opcode");
                                Log.Warn(msg);
                                break;
                            }

                            if (rx == OPCODE_DISCONNECT)
                            {
                                Log.Debug("in: got disconnect opcode");
                            }
                            else
                            {
                                string msg = string.Format("in: unexpected disconnect opcode, expected ({0}) got ({1})", Utility.DataFormat(OPCODE_DISCONNECT), Utility.DataFormat(rx));
                                Log.Warn(msg);
                                break;
                            }

                            /* TX: DISCONNECT ACKNOWLEDGE */

                            Log.Debug("out: disconnect acknowledge opcode");
                            Log.Trace("out: {0}", Utility.DataFormat(OPCODE_DISCONNECT_ACK));
                            Protocol.SendByte(OPCODE_DISCONNECT_ACK);
                            break;
                        }
                        else
                        {
                            string msg = string.Format("in: unexpected frame type opcode ({0})", Utility.DataFormat(rx));
                            Log.Warn(msg);
                            break;
                        }
                    }
                }
            }
            catch (OperationCanceledException)
            {
                Log.Debug("operation cancelled");
                return;
            }
            catch (Exception ex)
            {
                Log.Warn("error in mr emulation: {0}", ex.Message);
                throw;
            }
        }
예제 #15
0
        public static int DeleteAuthenticationKey(bool targetSpecificSuId, bool deleteAllKeys, int wacnId, int systemId, int unitId)
        {
            Output.DebugLine("DeleteAuthenticationKey() :: targetSpecificSuId: {0}, deleteAllKeys: {1}, wacnId: 0x{2:X}, systemId: 0x{3:X}, unitId: 0x{4:X}", targetSpecificSuId, deleteAllKeys, wacnId, systemId, unitId);

            SuId commandSuId = new SuId(wacnId, systemId, unitId);

            Output.DebugLine("command suid - {0}", commandSuId.ToString());

            DeleteAuthenticationKeyCommand commandKmmBody = new DeleteAuthenticationKeyCommand(targetSpecificSuId, deleteAllKeys, commandSuId);

            Output.DebugLine("command kmm body - {0}", commandKmmBody.ToString());

            KmmFrame commandKmmFrame = new KmmFrame(commandKmmBody);

            Output.DebugLine("command kmm frame - {0}", commandKmmFrame.ToString());
            byte[] toRadio = commandKmmFrame.ToBytes();

            byte[] fromRadio;

            try
            {
                fromRadio = Network.QueryRadio(toRadio);
            }
            catch (Exception ex)
            {
                Output.ErrorLine("unable to connect to radio: {0}", ex.Message);
                return(-1);
            }

            KmmFrame responseKmmFrame = new KmmFrame(fromRadio);

            Output.DebugLine("response kmm frame - {0}", responseKmmFrame.ToString());

            KmmBody responseKmmBody = responseKmmFrame.KmmBody;

            if (responseKmmBody is DeleteAuthenticationKeyResponse)
            {
                Output.DebugLine("received DeleteAuthenticationKeyResponse kmm");
                DeleteAuthenticationKeyResponse deleteAuthenticationKeyResponse = responseKmmBody as DeleteAuthenticationKeyResponse;
                Output.DebugLine("response kmm body - {0}", deleteAuthenticationKeyResponse.ToString());
                Output.DebugLine("response suid - {0}", deleteAuthenticationKeyResponse.SuId.ToString());

                if (deleteAuthenticationKeyResponse.Status == Status.CommandWasPerformed)
                {
                    return(0);
                }
                else
                {
                    Output.ErrorLine("abnormal response - status: {0} (0x{1:X2})", deleteAuthenticationKeyResponse.Status.ToString(), (byte)deleteAuthenticationKeyResponse.Status);
                    return(-1);
                }
            }
            else if (responseKmmBody is NegativeAcknowledgement)
            {
                Output.ErrorLine("received NegativeAcknowledgement kmm");
                NegativeAcknowledgement negativeAcknowledgement = responseKmmBody as NegativeAcknowledgement;
                Output.DebugLine("response kmm body - {0}", negativeAcknowledgement.ToString());
                return(-1);
            }
            else
            {
                Output.ErrorLine("received unexpected kmm");
                return(-1);
            }
        }
예제 #16
0
        public static int ListSuIdItems()
        {
            Output.DebugLine("ListSuIdItems()");

            bool needsAnotherRun = true;
            int  inventoryMarker = 0;

            while (needsAnotherRun)
            {
                InventoryCommandListSuIdItems commandKmmBody = new InventoryCommandListSuIdItems(inventoryMarker, 59);
                Output.DebugLine("command kmm body - {0}", commandKmmBody.ToString());

                KmmFrame commandKmmFrame = new KmmFrame(commandKmmBody);
                Output.DebugLine("command kmm frame - {0}", commandKmmFrame.ToString());
                byte[] toRadio = commandKmmFrame.ToBytes();

                byte[] fromRadio;

                try
                {
                    fromRadio = Network.QueryRadio(toRadio);
                }
                catch (Exception ex)
                {
                    Output.ErrorLine("unable to connect to radio: {0}", ex.Message);
                    return(-1);
                }

                KmmFrame responseKmmFrame = new KmmFrame(fromRadio);
                Output.DebugLine("response kmm frame - {0}", responseKmmFrame.ToString());

                KmmBody responseKmmBody = responseKmmFrame.KmmBody;

                if (responseKmmBody is InventoryResponseListSuIdItems)
                {
                    Output.DebugLine("received InventoryResponseListSuIdItems kmm");
                    InventoryResponseListSuIdItems inventoryResponseListSuIdItems = responseKmmBody as InventoryResponseListSuIdItems;
                    Output.DebugLine("response kmm body - {0}", inventoryResponseListSuIdItems.ToString());

                    inventoryMarker = inventoryResponseListSuIdItems.InventoryMarker;
                    Output.DebugLine("inventory marker - {0}", inventoryMarker);

                    if (inventoryMarker > 0)
                    {
                        needsAnotherRun = true;
                    }
                    else
                    {
                        needsAnotherRun = false;
                    }

                    foreach (SuIdStatus responseSuIdStatus in inventoryResponseListSuIdItems.SuIdStatuses)
                    {
                        Output.InfoLine("WACN: 0x{0:X}, System: 0x{1:X}, Unit: 0x{2:X}, Key Assigned: {3}, Is Active: {4}", responseSuIdStatus.SuId.WacnId, responseSuIdStatus.SuId.SystemId, responseSuIdStatus.SuId.UnitId, responseSuIdStatus.KeyAssigned, responseSuIdStatus.ActiveSuId);
                    }
                }
                else if (responseKmmBody is NegativeAcknowledgement)
                {
                    Output.ErrorLine("received NegativeAcknowledgement kmm");
                    NegativeAcknowledgement negativeAcknowledgement = responseKmmBody as NegativeAcknowledgement;
                    Output.DebugLine("response kmm body - {0}", negativeAcknowledgement.ToString());
                    return(-1);
                }
                else
                {
                    Output.ErrorLine("received unexpected kmm");
                    return(-1);
                }
            }

            return(0);
        }
예제 #17
0
        public static int ListActiveSuId()
        {
            Output.DebugLine("ListActiveSuId()");

            InventoryCommandListActiveSuId commandKmmBody = new InventoryCommandListActiveSuId();

            Output.DebugLine("command kmm body - {0}", commandKmmBody.ToString());

            KmmFrame commandKmmFrame = new KmmFrame(commandKmmBody);

            Output.DebugLine("command kmm frame - {0}", commandKmmFrame.ToString());
            byte[] toRadio = commandKmmFrame.ToBytes();

            byte[] fromRadio;

            try
            {
                fromRadio = Network.QueryRadio(toRadio);
            }
            catch (Exception ex)
            {
                Output.ErrorLine("unable to connect to radio: {0}", ex.Message);
                return(-1);
            }

            KmmFrame responseKmmFrame = new KmmFrame(fromRadio);

            Output.DebugLine("response kmm frame - {0}", responseKmmFrame.ToString());

            KmmBody responseKmmBody = responseKmmFrame.KmmBody;

            if (responseKmmBody is InventoryResponseListActiveSuId)
            {
                Output.DebugLine("received InventoryResponseListActiveSuId kmm");
                InventoryResponseListActiveSuId inventoryResponseListActiveSuId = responseKmmBody as InventoryResponseListActiveSuId;
                Output.DebugLine("response kmm body - {0}", inventoryResponseListActiveSuId.ToString());
                Output.DebugLine("response suid - {0}", inventoryResponseListActiveSuId.SuId.ToString());

                if (inventoryResponseListActiveSuId.Status == Status.CommandWasPerformed)
                {
                    Output.InfoLine("WACN: 0x{0:X}, System: 0x{1:X}, Unit: 0x{2:X}, Key Assigned: {3}, Is Active: {4}", inventoryResponseListActiveSuId.SuId.WacnId, inventoryResponseListActiveSuId.SuId.SystemId, inventoryResponseListActiveSuId.SuId.UnitId, inventoryResponseListActiveSuId.KeyAssigned, inventoryResponseListActiveSuId.ActiveSuId);
                    return(0);
                }
                else
                {
                    Output.ErrorLine("abnormal response - status: {0} (0x{1:X2})", inventoryResponseListActiveSuId.Status.ToString(), (byte)inventoryResponseListActiveSuId.Status);
                    return(-1);
                }
            }
            else if (responseKmmBody is NegativeAcknowledgement)
            {
                Output.ErrorLine("received NegativeAcknowledgement kmm");
                NegativeAcknowledgement negativeAcknowledgement = responseKmmBody as NegativeAcknowledgement;
                Output.DebugLine("response kmm body - {0}", negativeAcknowledgement.ToString());
                return(-1);
            }
            else
            {
                Output.ErrorLine("received unexpected kmm");
                return(-1);
            }
        }
예제 #18
0
        public static int LoadAuthenticationKey(bool targetSpecificSuId, int wacnId, int systemId, int unitId, byte[] key)
        {
            Output.DebugLine("LoadAuthenticationKey() :: targetSpecificSuId: {0}, wacnId: 0x{1:X}, systemId: 0x{2:X}, unitId: 0x{3:X}, key (hex): {4}", targetSpecificSuId, wacnId, systemId, unitId, BitConverter.ToString(key));

            SuId commandSuId = new SuId(wacnId, systemId, unitId);

            Output.DebugLine("command suid - {0}", commandSuId.ToString());

            LoadAuthenticationKeyCommand commandKmmBody = new LoadAuthenticationKeyCommand(targetSpecificSuId, commandSuId, key);

            Output.DebugLine("command kmm body - {0}", commandKmmBody.ToString());

            KmmFrame commandKmmFrame = new KmmFrame(commandKmmBody);

            Output.DebugLine("command kmm frame - {0}", commandKmmFrame.ToString());
            byte[] toRadio = commandKmmFrame.ToBytes();

            byte[] fromRadio;

            try
            {
                fromRadio = Network.QueryRadio(toRadio);
            }
            catch (Exception ex)
            {
                Output.ErrorLine("unable to connect to radio: {0}", ex.Message);
                return(-1);
            }

            KmmFrame responseKmmFrame = new KmmFrame(fromRadio);

            Output.DebugLine("response kmm frame - {0}", responseKmmFrame.ToString());

            KmmBody responseKmmBody = responseKmmFrame.KmmBody;

            if (responseKmmBody is LoadAuthenticationKeyResponse)
            {
                Output.DebugLine("received LoadAuthenticationKeyResponse kmm");
                LoadAuthenticationKeyResponse loadAuthenticationKeyResponse = responseKmmBody as LoadAuthenticationKeyResponse;
                Output.DebugLine("response kmm body - {0}", loadAuthenticationKeyResponse.ToString());
                Output.DebugLine("response suid - {0}", loadAuthenticationKeyResponse.SuId.ToString());

                if (loadAuthenticationKeyResponse.AssignmentSuccess == true && loadAuthenticationKeyResponse.Status == Status.CommandWasPerformed)
                {
                    return(0);
                }
                else
                {
                    Output.ErrorLine("abnormal response - assignment success: {0}, status: {1} (0x{2:X2})", loadAuthenticationKeyResponse.AssignmentSuccess, loadAuthenticationKeyResponse.Status.ToString(), (byte)loadAuthenticationKeyResponse.Status);
                    return(-1);
                }
            }
            else if (responseKmmBody is NegativeAcknowledgement)
            {
                Output.ErrorLine("received NegativeAcknowledgement kmm");
                NegativeAcknowledgement negativeAcknowledgement = responseKmmBody as NegativeAcknowledgement;
                Output.DebugLine("response kmm body - {0}", negativeAcknowledgement.ToString());
                return(-1);
            }
            else
            {
                Output.ErrorLine("received unexpected kmm");
                return(-1);
            }
        }
예제 #19
0
        /* TIA 102.AACD-A 3.8.1 */
        public void Keyload(List <CmdKeyItem> keyItems)
        {
            List <List <CmdKeyItem> > keyGroups = KeyPartitioner.PartitionKeys(keyItems);

            Begin();

            try
            {
                InventoryCommandListActiveKsetIds cmdKmmBody1 = new InventoryCommandListActiveKsetIds();

                KmmBody rspKmmBody1 = TxRxKmm(cmdKmmBody1);

                int activeKeysetId = 0;

                if (rspKmmBody1 is InventoryResponseListActiveKsetIds)
                {
                    InventoryResponseListActiveKsetIds kmm = rspKmmBody1 as InventoryResponseListActiveKsetIds;

                    Logger.Debug("number of active keyset ids: {0}", kmm.KsetIds.Count);

                    for (int i = 0; i < kmm.KsetIds.Count; i++)
                    {
                        Logger.Debug("* keyset id index {0} *", i);
                        Logger.Debug("keyset id: {0} (dec), {0:X} (hex)", kmm.KsetIds[i]);
                    }

                    // TODO support more than one crypto group
                    if (kmm.KsetIds.Count > 0)
                    {
                        activeKeysetId = kmm.KsetIds[0];
                    }
                    else
                    {
                        activeKeysetId = 1; // to match KVL3000+ R3.53.03 behavior
                    }
                }
                else if (rspKmmBody1 is NegativeAcknowledgment)
                {
                    NegativeAcknowledgment kmm = rspKmmBody1 as NegativeAcknowledgment;

                    string statusDescr  = OperationStatusExtensions.ToStatusString(kmm.Status);
                    string statusReason = OperationStatusExtensions.ToReasonString(kmm.Status);
                    throw new Exception(string.Format("received negative acknowledgment{0}status: {1} (0x{2:X2}){0}{3}", Environment.NewLine, statusDescr, kmm.Status, statusReason));
                }
                else
                {
                    throw new Exception("unexpected kmm");
                }

                foreach (List <CmdKeyItem> keyGroup in keyGroups)
                {
                    ModifyKeyCommand modifyKeyCommand = new ModifyKeyCommand();

                    // TODO support more than one crypto group
                    if (keyGroup[0].UseActiveKeyset && !keyGroup[0].IsKek)
                    {
                        modifyKeyCommand.KeysetId = activeKeysetId;
                    }
                    else if (keyGroup[0].UseActiveKeyset && keyGroup[0].IsKek)
                    {
                        modifyKeyCommand.KeysetId = 0xFF; // to match KVL3000+ R3.53.03 behavior
                    }
                    else
                    {
                        modifyKeyCommand.KeysetId = keyGroup[0].KeysetId;
                    }

                    modifyKeyCommand.AlgorithmId = keyGroup[0].AlgorithmId;

                    foreach (CmdKeyItem key in keyGroup)
                    {
                        Logger.Debug(key.ToString());

                        KeyItem keyItem = new KeyItem();
                        keyItem.SLN   = key.Sln;
                        keyItem.KeyId = key.KeyId;
                        keyItem.Key   = key.Key.ToArray();
                        keyItem.KEK   = key.IsKek;
                        keyItem.Erase = false;

                        modifyKeyCommand.KeyItems.Add(keyItem);
                    }

                    KmmBody rspKmmBody2 = TxRxKmm(modifyKeyCommand);

                    if (rspKmmBody2 is RekeyAcknowledgment)
                    {
                        RekeyAcknowledgment kmm = rspKmmBody2 as RekeyAcknowledgment;

                        Logger.Debug("number of key status: {0}", kmm.Keys.Count);

                        for (int i = 0; i < kmm.Keys.Count; i++)
                        {
                            KeyStatus status = kmm.Keys[i];

                            Logger.Debug("* key status index {0} *", i);
                            Logger.Debug("algorithm id: {0} (dec), {0:X} (hex)", status.AlgorithmId);
                            Logger.Debug("key id: {0} (dec), {0:X} (hex)", status.KeyId);
                            Logger.Debug("status: {0} (dec), {0:X} (hex)", status.Status);

                            if (status.Status != 0)
                            {
                                string statusDescr  = OperationStatusExtensions.ToStatusString((OperationStatus)status.Status);
                                string statusReason = OperationStatusExtensions.ToReasonString((OperationStatus)status.Status);
                                throw new Exception(string.Format("received unexpected key status{0}status: {1} (0x{2:X2}){0}{3}", Environment.NewLine, statusDescr, status.Status, statusReason));
                            }
                        }
                    }
                    else if (rspKmmBody2 is NegativeAcknowledgment)
                    {
                        NegativeAcknowledgment kmm = rspKmmBody2 as NegativeAcknowledgment;

                        string statusDescr  = OperationStatusExtensions.ToStatusString(kmm.Status);
                        string statusReason = OperationStatusExtensions.ToReasonString(kmm.Status);
                        throw new Exception(string.Format("received negative acknowledgment{0}status: {1} (0x{2:X2}){0}{3}", Environment.NewLine, statusDescr, kmm.Status, statusReason));
                    }
                    else
                    {
                        throw new Exception("received unexpected kmm");
                    }
                }
            }
            catch
            {
                End();

                throw;
            }

            End();
        }
예제 #20
0
        /* TIA 102.AACD-A 3.8.7 */
        public List <RspKeyInfo> ViewKeyInfo()
        {
            List <RspKeyInfo> result = new List <RspKeyInfo>();

            Begin();

            try
            {
                bool more   = true;
                int  marker = 0;

                while (more)
                {
                    InventoryCommandListActiveKeys commandKmmBody = new InventoryCommandListActiveKeys();
                    commandKmmBody.InventoryMarker  = marker;
                    commandKmmBody.MaxKeysRequested = 78;

                    KmmBody responseKmmBody = TxRxKmm(commandKmmBody);

                    if (responseKmmBody is InventoryResponseListActiveKeys)
                    {
                        InventoryResponseListActiveKeys kmm = responseKmmBody as InventoryResponseListActiveKeys;

                        marker = kmm.InventoryMarker;

                        Logger.Debug("inventory marker: {0}", marker);

                        if (marker == 0)
                        {
                            more = false;
                        }

                        Logger.Debug("number of keys returned: {0}", kmm.Keys.Count);

                        for (int i = 0; i < kmm.Keys.Count; i++)
                        {
                            KeyInfo info = kmm.Keys[i];

                            Logger.Debug("* key index {0} *", i);
                            Logger.Debug("keyset id: {0} (dec), {0:X} (hex)", info.KeySetId);
                            Logger.Debug("sln: {0} (dec), {0:X} (hex)", info.SLN);
                            Logger.Debug("algorithm id: {0} (dec), {0:X} (hex)", info.AlgorithmId);
                            Logger.Debug("key id: {0} (dec), {0:X} (hex)", info.KeyId);

                            RspKeyInfo res = new RspKeyInfo();

                            res.KeysetId    = info.KeySetId;
                            res.Sln         = info.SLN;
                            res.AlgorithmId = info.AlgorithmId;
                            res.KeyId       = info.KeyId;

                            result.Add(res);
                        }
                    }
                    else if (responseKmmBody is NegativeAcknowledgment)
                    {
                        NegativeAcknowledgment kmm = responseKmmBody as NegativeAcknowledgment;

                        string statusDescr  = OperationStatusExtensions.ToStatusString(kmm.Status);
                        string statusReason = OperationStatusExtensions.ToReasonString(kmm.Status);
                        throw new Exception(string.Format("received negative acknowledgment{0}status: {1} (0x{2:X2}){0}{3}", Environment.NewLine, statusDescr, kmm.Status, statusReason));
                    }
                    else
                    {
                        throw new Exception("unexpected kmm");
                    }
                }
            }
            catch
            {
                End();

                throw;
            }

            End();

            return(result);
        }
예제 #21
0
        public List <RspRsiInfo> ViewRsiItems()
        {
            List <RspRsiInfo> result = new List <RspRsiInfo>();

            Begin();

            try
            {
                bool more   = true;
                int  marker = 0;

                while (more)
                {
                    InventoryCommandListRsiItems commandKmmBody = new InventoryCommandListRsiItems();

                    KmmBody responseKmmBody = TxRxKmm(commandKmmBody);

                    if (responseKmmBody is InventoryResponseListRsiItems)
                    {
                        InventoryResponseListRsiItems kmm = responseKmmBody as InventoryResponseListRsiItems;

                        Logger.Debug("inventory marker: {0}", marker);

                        if (marker == 0)
                        {
                            more = false;
                        }

                        Logger.Debug("number of RSIs returned: {0}", kmm.RsiItems.Count);

                        for (int i = 0; i < kmm.RsiItems.Count; i++)
                        {
                            RsiItem item = kmm.RsiItems[i];

                            Logger.Debug("* rsi index {0} *", i);
                            Logger.Debug("rsi id: {0} (dec), {0:X} (hex)", item.RSI);
                            Logger.Debug("mn: {0} (dec), {0:X} (hex)", item.MessageNumber);

                            RspRsiInfo res = new RspRsiInfo();

                            res.RSI = (int)item.RSI;
                            res.MN  = item.MessageNumber;

                            result.Add(res);
                        }
                    }
                    else if (responseKmmBody is NegativeAcknowledgment)
                    {
                        NegativeAcknowledgment kmm = responseKmmBody as NegativeAcknowledgment;

                        string statusDescr  = OperationStatusExtensions.ToStatusString(kmm.Status);
                        string statusReason = OperationStatusExtensions.ToReasonString(kmm.Status);
                        throw new Exception(string.Format("received negative acknowledgment{0}status: {1} (0x{2:X2}){0}{3}", Environment.NewLine, statusDescr, kmm.Status, statusReason));
                    }
                    else
                    {
                        throw new Exception("unexpected kmm");
                    }
                }
            }
            catch
            {
                End();

                throw;
            }

            End();

            return(result);
        }
예제 #22
0
        /* TIA 102.AACD-A 3.7.2.3 */
        public RspChangeoverInfo ActivateKeyset(int keysetSuperseded, int keysetActivated)
        {
            //cg
            RspChangeoverInfo result = new RspChangeoverInfo();

            Begin();

            try
            {
                ChangeoverCommand cmdKmmBody = new ChangeoverCommand();
                cmdKmmBody.KeysetIdSuperseded = keysetSuperseded;
                cmdKmmBody.KeysetIdActivated  = keysetActivated;
                KmmBody rspKmmBody = TxRxKmm(cmdKmmBody);
                if (rspKmmBody is ChangeoverResponse)
                {
                    ChangeoverResponse kmm = rspKmmBody as ChangeoverResponse;

                    /*
                     * for (int i = 0; i < kmm.KeysetItems.Count; i++)
                     * {
                     *  KeysetItem item = kmm.KeysetItems[i];
                     *
                     *  RspKeysetInfo res = new RspKeysetInfo();
                     *
                     *  res.KeysetId = item.KeysetId;
                     *  res.KeysetName = item.KeysetName;
                     *  res.KeysetType = item.KeysetType;
                     *  res.ActivationDateTime = item.ActivationDateTime;
                     *  res.ReservedField = item.ReservedField;
                     *
                     *  result.Add(res);
                     * }
                     */

                    result.KeysetIdSuperseded = kmm.KeysetIdSuperseded;
                    result.KeysetIdActivated  = kmm.KeysetIdActivated;
                    //Console.WriteLine("response status: {0}", kmm.Status);
                }
                else if (rspKmmBody is NegativeAcknowledgment)
                {
                    NegativeAcknowledgment kmm = rspKmmBody as NegativeAcknowledgment;

                    string statusDescr  = OperationStatusExtensions.ToStatusString(kmm.Status);
                    string statusReason = OperationStatusExtensions.ToReasonString(kmm.Status);
                    throw new Exception(string.Format("received negative acknowledgment{0}status: {1} (0x{2:X2}){0}{3}", Environment.NewLine, statusDescr, kmm.Status, statusReason));
                }
                else
                {
                    throw new Exception("unexpected kmm");
                }
            }
            catch
            {
                End();

                throw;
            }

            End();

            return(result);
        }
예제 #23
0
        /* TIA 102.AACD-A 3.8.1 */
        public void Keyload(bool useActiveKeyset, int keysetId, int sln, int keyId, int algId, List <byte> key)
        {
            Begin();

            InventoryCommandListActiveKsetIds cmdKmmBody1 = new InventoryCommandListActiveKsetIds();

            KmmBody rspKmmBody1 = TxRxKmm(cmdKmmBody1);

            int ksid = 0;

            if (rspKmmBody1 is InventoryResponseListActiveKsetIds)
            {
                InventoryResponseListActiveKsetIds kmm = rspKmmBody1 as InventoryResponseListActiveKsetIds;

                Logger.Debug("number of active keyset ids: {0}", kmm.KsetIds.Count);

                for (int i = 0; i < kmm.KsetIds.Count; i++)
                {
                    Logger.Debug("* keyset id index {0} *", i);
                    Logger.Debug("keyset id: {0} (dec), {0:X} (hex)", kmm.KsetIds[i]);
                }

                if (!useActiveKeyset)
                {
                    ksid = keysetId;
                }
                else if (useActiveKeyset && kmm.KsetIds.Count > 0)
                {
                    ksid = kmm.KsetIds[0];
                }
                else
                {
                    throw new Exception("no active keyset");
                }
            }
            else
            {
                throw new Exception("unexpected kmm");
            }

            // TODO support more than one key per keyload operation

            KeyItem keyItem = new KeyItem();

            keyItem.SLN   = sln;
            keyItem.KeyId = keyId;
            keyItem.Key   = key.ToArray();
            keyItem.Erase = false;

            ModifyKeyCommand modifyKeyCommand = new ModifyKeyCommand();

            modifyKeyCommand.KeysetId = ksid;

            modifyKeyCommand.AlgorithmId = algId;
            modifyKeyCommand.KeyItems.Add(keyItem);

            KmmBody rspKmmBody2 = TxRxKmm(modifyKeyCommand);

            if (rspKmmBody2 is RekeyAcknowledgment)
            {
                RekeyAcknowledgment kmm = rspKmmBody2 as RekeyAcknowledgment;

                Logger.Debug("number of key status: {0}", kmm.Keys.Count);

                for (int i = 0; i < kmm.Keys.Count; i++)
                {
                    KeyStatus status = kmm.Keys[i];

                    Logger.Debug("* key status index {0} *", i);
                    Logger.Debug("algorithm id: {0} (dec), {0:X} (hex)", status.AlgorithmId);
                    Logger.Debug("key id: {0} (dec), {0:X} (hex)", status.KeyId);
                    Logger.Debug("status: {0} (dec), {0:X} (hex)", status.Status);

                    if (status.Status != 0)
                    {
                        throw new Exception("unexpected status");
                    }
                }
            }
            else
            {
                throw new Exception("unexpected kmm");
            }

            End();
        }
        /* TIA 102.AACD-A 3.8.5 */
        public void EraseKeys(bool useActiveKeyset, int keysetId, int sln)
        {
            Begin();

            InventoryCommandListActiveKsetIds cmdKmmBody1 = new InventoryCommandListActiveKsetIds();

            KmmBody rspKmmBody1 = TxRxKmm(cmdKmmBody1);

            int ksid = 0;

            if (rspKmmBody1 is InventoryResponseListActiveKsetIds)
            {
                InventoryResponseListActiveKsetIds kmm = rspKmmBody1 as InventoryResponseListActiveKsetIds;

                Logger.Debug("number of active keyset ids: {0}", kmm.KsetIds.Count);

                for (int i = 0; i < kmm.KsetIds.Count; i++)
                {
                    Logger.Debug("* keyset id index {0} *", i);
                    Logger.Debug("keyset id: {0} (dec), {0:X} (hex)", kmm.KsetIds[i]);
                }

                if (!useActiveKeyset)
                {
                    ksid = keysetId;
                }
                else if (useActiveKeyset && kmm.KsetIds.Count > 0)
                {
                    ksid = kmm.KsetIds[0];
                }
                else
                {
                    ksid = 1; // to match KVL3000+ R3.53.03 behavior
                }
            }
            else if (rspKmmBody1 is NegativeAcknowledgment)
            {
                NegativeAcknowledgment kmm = rspKmmBody1 as NegativeAcknowledgment;

                throw new Exception(string.Format("recieved negative acknowledgment, status {0} (0x{1:X2})", kmm.Status.ToString(), (byte)kmm.Status));
            }
            else
            {
                throw new Exception("unexpected kmm");
            }

            // TODO support more than one key per erase operation

            KeyItem keyItem = new KeyItem();

            keyItem.SLN   = sln;
            keyItem.KeyId = 65535;                                                         // to match KVL3000+ R3.53.03 behavior
            keyItem.Key   = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; // to match KVL3000+ R3.53.03 behavior
            keyItem.Erase = true;

            ModifyKeyCommand modifyKeyCommand = new ModifyKeyCommand();

            modifyKeyCommand.KeysetId = ksid;

            modifyKeyCommand.AlgorithmId = 0x81; // to match KVL3000+ R3.53.03 behavior
            modifyKeyCommand.KeyItems.Add(keyItem);

            KmmBody rspKmmBody2 = TxRxKmm(modifyKeyCommand);

            if (rspKmmBody2 is RekeyAcknowledgment)
            {
                RekeyAcknowledgment kmm = rspKmmBody2 as RekeyAcknowledgment;

                Logger.Debug("number of key status: {0}", kmm.Keys.Count);

                for (int i = 0; i < kmm.Keys.Count; i++)
                {
                    KeyStatus status = kmm.Keys[i];

                    Logger.Debug("* key status index {0} *", i);
                    Logger.Debug("algorithm id: {0} (dec), {0:X} (hex)", status.AlgorithmId);
                    Logger.Debug("key id: {0} (dec), {0:X} (hex)", status.KeyId);
                    Logger.Debug("status: {0} (dec), {0:X} (hex)", status.Status);

                    if (status.Status != 0)
                    {
                        throw new Exception("unexpected status");
                    }
                }
            }
            else if (rspKmmBody2 is NegativeAcknowledgment)
            {
                NegativeAcknowledgment kmm = rspKmmBody2 as NegativeAcknowledgment;

                throw new Exception(string.Format("recieved negative acknowledgment, status {0} (0x{1:X2})", kmm.Status.ToString(), (byte)kmm.Status));
            }
            else
            {
                throw new Exception("unexpected kmm");
            }

            End();
        }