Locking Memory on EPC RFID Tags

This article covers the locking features of the Impinj Monza 4D, 4E, 4QT, 5, R6-A, R6-B, R6-P, and Impinj M700 series chips. For instructions on locking memory specifically with Monza R6 please see Monza R6 Permalock memory.

Locking the memory on EPC Gen2 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 Gen2 tags) and then the tag is 'locked' but this is not the case. This article 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. 


An EPC Gen2 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.


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" state 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 Gen2 compliant 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.


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.


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".


Here is an example of locking Access Password and 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)
                // Connect to the reader.
                // Supply your reader's hostname or IP address as the command line argument.
                if (args.Length != 1)
Console.WriteLine("Error: No hostname specified. Pass in the reader hostname as a command line argument when running the Sdk Example.");
string hostname = args[0];
// 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
// and EPC memory bank. TagLockOp lockOp = new TagLockOp(); lockOp.AccessPasswordLockType = TagLockState.Lock; lockOp.EpcLockType = TagLockState.Lock; // Add this tag lock op to the tag operation sequence. seq.Ops.Add(lockOp); // 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); } } } } }
Was this article helpful?
0 out of 0 found this helpful



Article is closed for comments.