How to lock the Impinj Monza tags?

Locking the memory on EPC GEN 2 compliant tags is an often misunderstood process. Many think that it is simply a matter of changing the access password to a non-zero value (the default for Gen 2 tags) and then the tag is ‘locked’ but this is not the case. This posting will review how tag locking works for EPC RFID tags and show you how to lock the Impinj Monza tags using the Octane Software Development Kit (SDK) for C# .Net.

For instructions on locking memory specifically with Monza-R6 please see Monza R6 Permalock memory. This article only applies to Monza R6 and not R6-A or R6-P.

GEN 2 TAG PASSWORDS

An EPC GEN 2 tag has two separate passwords, an access password and a kill password, each are 32 bits and are stored in the reserved bank (bank 00) of the tag memory.

STATES

When a tag is singulated, it enters one of two states:
Secured (if access password is all zeros, which is the factory default)
Open (if non-zero access password has been programmed to the tag)

A tag in the open state can be moved to secured by providing the previously programmed non-zero access password.

The key thing to remember is that assigning a non-zero access password does not, in itself, prevent anyone with a GEN 2 reader from reading or changing data on the tag. It only requires that any future users must provide the access password in order to change the lock state and is simply one step in effectively locking tag memory.

Each memory bank can be in one of four lock states:
  • 1. Unlocked (None)
    2. Perma-unlocked (can never be locked)
    3. Locked
    4. Perma-locked (can never be unlocked)

This is illustrated below using intellisense options when programming the lock state of the tag.

LOCK PROCEDURE

The steps would be (for a factory default tag):
1. Write a 32 bit (8 hex character) non-zero access password.
2. Lock the selected memory bank
3. Lock the access password – this will prevent the password from being read or over-written. Not doing this step would allow any user to simply read the access password, then use it to unlock and over-write memory on the tag (unless it has been perma-locked).

Only reserved memory bank (access and kill passwords) can be both write and READ locked – all others (EPC, TID, and User) can be write-locked only. Typically the Tag Identification (TID) memory bank is perma-locked at the factory.

Each tag memory bank can be individually write locked as shown below.

tag lock
OTHER USEFUL NOTES

 

In addition to the increased memory size, the Impinj Monza 4QT tag chips offer the ability to independently lock four fixed, 128-bit sections of user memory (block permalock). This feature is particularly useful for situations such as in a supply chain, where various participants along the chain may want to record data, but not necessarily have it be openly available to all parties.
Lock status cannot be read, it can only be inferred. So there is no direct way to query a tag and have it reply if it is locked or not. However, in some cases when attempting to access a tag memory bank, it will return a pretty specific error “tag memory locked”.
SAMPLE CODE
Here is an example of locking EPC memory bank in C# using the Octane SDK.
using System;
using Impinj.OctaneSdk;
namespace OctaneSdkExamples
{
class Program
{
// Create an instance of the ImpinjReader class.
static ImpinjReader reader = new ImpinjReader();
static void Main(string[] args)
{
try
{
// Connect to the reader.
// Change the ReaderHostname constant  to the IP address or hostname of your reader.
reader.Connect(ReaderHostname);
// Assign the TagOpComplete event handler.
// This specifies which method to call
// when tag operations are complete.
reader.TagOpComplete += OnTagOpComplete;
// Configure the reader with the default settings.
reader.ApplyDefaultSettings();
// Create a tag operation sequence.
// You can add multiple read, write, lock, kill and QT
// operations to this sequence.
TagOpSequence seq = new TagOpSequence();
// Define a tag write operation that sets the access password.
TagWriteOp writeOp = new TagWriteOp();
// Assumes that current access password is not set
// (zero is the default)
writeOp.AccessPassword = null;
// The access password is in the Reserved memory bank.
writeOp.MemoryBank = MemoryBank.Reserved;
// A pointer to the start of the access password.
writeOp.WordPointer = WordPointers.AccessPassword;
// The new access password to write.
writeOp.Data = TagData.FromHexString(“11112222”);
// Add this tag write op to the tag operation sequence.
seq.Ops.Add(writeOp);
// Create a tag lock operation to lock the access password.
TagLockOp lockAccessPwOp = new TagLockOp();
// Lock the access password.
lockAccessPwOp.MemoryBank = LockMemoryBank.AccessPassword;
// Set the lock type.
lockAccessPwOp.LockType = TagLockState.Lock;
// Add this tag lock op to the tag operation sequence.
seq.Ops.Add(lockAccessPwOp);
// Create a tag lock operation to lock EPC memory bank.
TagLockOp lockUserOp = new TagLockOp();
// Lock EPC.
lockUserOp.MemoryBank = LockMemoryBank.EPC;
// Set the lock type.
lockUserOp.LockType = TagLockState.Lock;
// Add this tag lock op to the tag operation sequence.
seq.Ops.Add(lockUserOp);
// Add the tag operation sequence to the reader.
// The reader supports multiple sequences.
reader.AddOpSequence(seq);
// Start the reader
reader.Start();
}
catch (OctaneSdkException e)
{
// Handle Octane SDK errors.
Console.WriteLine(“Octane SDK exception: {0}”, e.Message);
}
catch (Exception e)
{
// Handle other .NET errors.
Console.WriteLine(“Exception : {0}”, e.Message);
}
// Wait for the user to press enter.
Console.WriteLine(“Press enter to exit.”);
Console.ReadLine();
// Stop reading.
reader.Stop();
// Disconnect from the reader.
reader.Disconnect();
}
// This event handler will be called when tag
// operations have been executed by the reader.
static void OnTagOpComplete(ImpinjReader reader, TagOpReport report)
{
// Loop through all the completed tag operations
foreach (TagOpResult result in report)
{
if (result is TagWriteOpResult)
{
// These are the results of settings the access password.
// Cast it to the correct type.
TagWriteOpResult writeResult = result as TagWriteOpResult;
// Print out the results.
Console.WriteLine(“Set access password complete.”);
Console.WriteLine(“EPC : {0}”, writeResult.Tag.Epc);
Console.WriteLine(“Status : {0}”, writeResult.Result);
Console.WriteLine(“Number of words written : {0}”, writeResult.NumWordsWritten);
}
else if (result is TagLockOpResult)
{
// Cast it to the correct type.
// These are the results of locking the access password or user memory.
TagLockOpResult lockResult = result as TagLockOpResult;
// Print out the results.
Console.WriteLine(“Lock operation complete.”);
Console.WriteLine(“EPC : {0}”, lockResult.Tag.Epc);
Console.WriteLine(“Status : {0}”, lockResult.Result);
}
}
}
}
}

Leave a Reply