Android MIFARE读写器协议详解1


M1 主要指标 
1:容量为8K位EEPROM 
2:分为16个扇区,每个扇区为4块,每块16个字节,以块为存取单位 
3:每个扇区有独立的一组密码及访问控制 
4:每张卡有唯一序列号,为32位 
5:具有防冲突机制,支持多卡操作 
6:无电源,自带天线,内含加密控制逻辑和通讯逻辑电路 
7: 数据保存期为10年,可改写10万次,读无限次 
8:工作温度:-20℃~50℃(温度为90%), PET材料封装得M1卡,温度可达100℃。
9:工作频率:13.56MHZ 
10:通信速率:106KBPS 
11: 读写距离:10mm以内(与读写器有关) 

M1 存储结构
Mifare1S50非接触式智能卡片有着16个Sector(扇区);每个Sector包含4个Block(块);每个Block具有16个byte的存储容量。
Sector被定义为Sector0至Sector15;Block被分为Block0至Block3;整个Mifare1S50非接触式智能卡共有64个Block。

Android MIFARE读写器协议详解1_第1张图片



Sector0中的Block0记录了该张智能卡的序列号以及生产厂商的标志信息等,这些信息已在卡片出厂时固化,不能更改,因此该Block不能再复用为应用数据块。
每个Sector中的Block3被特别用来存放对该Sector中应用块Block0,1,2及其本身Block3进行数据存取的密码及存取权限。
整个Mifare1S50非接触式智能卡共有16个Block3。根据绝对地址编址,他们可被编为Block3(在Sector0中),Block7(在Sector1中),Block11(在Sector2中),以及Block63(在Sector15中)等。
 对于某一Sector中的Block3的绝对地址编址可以由下列公式计算得到:
 Block X=(N+1)*4-1  其中:X:绝对地址编址的Block块号
 N:Sector扇号,0至15


通常每个扇区的Block0,1,2都存放着非常保密的数据,例如坐公交车/出租车前在公交公司指定地点已购买的车资钱款,智能大厦/智能小区进出时所需的控制信息,
股票交易时持有股票交易智能卡片者必须对已存放在智能卡中的交易密码数据(例如帐户、存款信息、已买进股票数量/品种等等)进行确认,才能得以股票交易等。
数据块可作两种应用:
用作一般的数据保存,可以进行读、写操作。
用作数据值,可以进行初始化值、加值、减值、读值操作。

由于每一个Block3中包含了该扇区的密码字节以及对该扇区中其余Block0,1,2进行数据处理的存取控制权限字节,因此如何操作处理Block3将是很重要的内容。以下将展开对每个扇区的Block3进行研究。
Block3有16个byte组成。前6个字节是密码A(KEYA),KEYA的缺省值可能为“A0A1A2A3A4A5”;
最后6个字节是密码B(KEYB),KEYB的缺省值可能为“B0B1B2B3B4B5”;
中间4个字节是控制字节,缺省值可能为“FFH07H80H69H”;
利用KEYA或KEYB并遵守早已定义在4个控制字节中的存取条件,我们便能对该密码(KEYA或KEYB)所对应的Sector内的应用块Block0,1,2进行数据读/写/更新等操作。

Android MIFARE读写器协议详解1_第2张图片



每个扇区的密码和存取控制都是独立的,可以根据实际需要设定各自的密码及存取控制。
存取控制为4个字节,共32位,扇区中的每个块(包括数据块和控制块)的存取条件是由密码和存取控制共同决定的,
在存取控制中每个块都有相应的三个控制位,定义如下:
块0:   C10   C20   C30           
块1:   C11   C21   C31          
块2:   C12   C22   C32          
块3:   C13   C23   C33 


三个控制位以正和反两种形式存在于存取控制字节中,决定了该块的访问权限(如     进行减值操作必须验证KEY A,进行加值操作必须验证KEY B,等等)。三个控制   位在存取控制字节中的位置,以块0为例:

Android MIFARE读写器协议详解1_第3张图片

Android MIFARE读写器协议详解1_第4张图片



数据块(块0、块1、块2)的存取控制如下:


Android MIFARE读写器协议详解1_第5张图片



例如:当块0的存取控制位C10 C20 C30=1 0 0时,验证密码A或密码B正确后可读;验证密码B正确后可写;不能进行加值、减值操作。
控制块块3的存取控制与数据块(块0、1、2)不同,它的存取控制如下:


Android MIFARE读写器协议详解1_第6张图片



例如:当块3的存取控制位C13 C23 C33=1 0 0时,
表示:  密码A:不可读,验证KEYA或KEYB正确后,可写(更改)。          
存取控制:验证KEYA或KEYB正确后,可读、可写。           
 密码B:验证KEYA或KEYB正确后,可读、可写。


工作原理
卡片的电气部分只由一个天线和ASIC组成。 
天线:卡片的天线是只有几组绕线的线圈,很适于封装到IS0卡片中。 
ASIC:卡片的ASIC由一个高速(106KB波特率)的RF接口,一个控制单元和一个 8K位EEPROM组成。 
工作原理:读写器向M1卡发一组固定频率的电磁波,卡片内有一个LC串联谐振电路,其频率与讯写器发射的频率相同,
在电磁波的激励下,LC谐振电路产生共振,从而使电容内有了电荷,在这个电容的另一端,接有一个单向导通的电子泵,
将电容内的电荷送到另一个电容内储存,当所积累的电荷达到2V时,此电容可做为电源为其它电路提供工作电压,将卡内数据发射出去或接取读写器的数据。


M1射频卡与读写器的通讯

Android MIFARE读写器协议详解1_第7张图片



复位应答(Answer to request)
M1射频卡的通讯协议和通讯波特率是定义好的,当有卡片进入读写器的操作范围时,读写器以特定的协议与它通讯,从而确定该卡是否为M1射频卡,即验证卡片的卡型。


防冲突机制 (Anticollision Loop) 
当有多张卡进入读写器操作范围时,防冲突机制会从其中选择一张进行操作,未选中的则处于空闲模式等待下一次选卡,该过程会返回被选卡的序列号。


选择卡片(Select Tag)
选择被选中的卡的序列号,并同时返回卡的容量代码。


三次互相确认
选定要处理的卡片之后,读写器就确定要访问的扇区号,并对该扇区密码进行密码校验,
在三次相互认证之后就可以通过加密流进行通讯。(在选择另一扇区时,则必须进行另一扇区密码校验。) 


对数据块的操作
读 (Read):读一个块; 
写 (Write):写一个块; 
加(Increment):对数值块进行加值; 
减(Decrement):对数值块进行减值; 
存储(Restore):将块中的内容存到数据寄存器中; 
传输(Transfer):将数据寄存器中的内容写入块中; 
中止(Halt):将卡置于暂停工作状态;


数据完整性
在非接触通讯中,以下措施保证了读写器和卡片之间数据传递完整、可靠:
防冲突 
每块有16位CRC纠错 
每字节有奇偶校验位 
检查位数 
用编码方式来区分“1”、“0”或无信息
信道监测(通过协议顺序和位流分析)


保密性
S50射频卡的保密性能很好是由于:读写前的三次确认、独一无二的卡片序列号、传递数 据加密、传输密码和访问密码的保护。 
卡片中的密码是受保护、不可读的,只有知道密码的用户才能修改它。卡中的EEPROM 存储区分为16个扇区,每个扇区都有自己的访问密码,
用户可根据扇区的不同应用设定不同的密码(一卡多用)。扇区的访问密码分为KEY A和KEY B两组不同密码,根据访问条件,

在校验KEY A和KEY B之后才可以对存储器进行访问。例如:KEY A用于保护减操作,KEY B用于保护加操作。 三次相互确认 确认过程如图示所示:


Android MIFARE读写器协议详解1_第8张图片


图中的所示的符号 
Token AB=ekAB(RA RB B Text2)                        
 Token BA=ekAB(RB RA Text4) 
(A)  B发出一个随机数RB (B)  A返回Token AB给B (C)   收到Token AB后,B译码并验证符号AB中所含的随机数RB是否与在(A)中所 发出的一致。 
(D)  B发给A一个值BA 
(E)  收到BA之后,A译码并验证RB的正确性,同时还验证BA中所含的随机数 RA是否和(B)发出的一致。


由于非接触式智能卡的操作,包括数据流的传递等都是以“非接触”方式来完成的,因此在MCU与非接触式智能卡之间必须有一个传递密码(或数据流)的中间媒体,即ASIC模块。
RC150/170就是这样一种ASIC模块。它担负着非接触式智能卡与MCU(微处理机)之间所有的密码/数据相互传递的重要任务。对非接触式智能卡进行密码操作,变成对RC150/170ASIC模块进行密码操作。
RC150/170ASIC模块与非接触式智能卡之间的信息传递(包括密码等)对用户来说是透明的,会自动传递并完成。因此如何对非接触式智能卡进行“密码操作”(对Block3的操作)变成如何对RC150/170ASIC模块进行密码操作。


在研究ASIC模块RC150/170的时候,我们必须关注所有与“密码操作”有关的寄存器/存储器的情况。
密码数据寄存器KeyDataRegister(寄存器地址:0x0A);  
密码地址寄存器KeyAddressRegister(寄存器地址:0x0C);
密码状态/控制寄存器KeyStatus&ControlRegister(KEYSTACON)(寄存器地址:0x0B);
其他相关寄存器。所有这些与“密码操作”相关的寄存器都是“只可写不可读”的,即WOM(Write-Only-Memory)。因此不要试图去读取这些寄存器的内容。


“密码操作”的研究及其应用程序开发
通常,对非接触式智能卡的“密码操作”有两个主要步骤。每一个主要步骤又有若干个小的步骤有序并且必须是连续地完成。  
“密码操作”的两个主要步骤是:  
“LOAD_KEY”密码存取  
“AUTHENTICATION”密码认证


LOAD_KEY”密码存取必须由以下步骤有序并连续地完成:
1:设置新的密码值
2:设置密码状态/控制寄存器KeyStatus&ControlRegister(KEYSTACON)
3:设置密码地址寄存器KeyAddressRegister(寄存器地址:0x0C)  
4:设置密码数据寄存器KeyDataRegister(寄存器地址:0x0A)
5:校验STACON寄存器,以确定这次的“LOAD_KEY”密码存取是否有效
以下将按照上述的次序进行具体的程序设计,所有的程序都使用标准的Intel-51MCU指令,以利于读者在LOW-LEVEL级上移植到其相应的应用项目中。


1:设置新的密码值
新的密码值为6个bytes,在如下的程序设计中被依次存放在MCU内部RAM的72H~77H的6个单元中;
程序员亦可自定义其他的存储单元作为新的密码值存放的缓冲区;R1寄存器为新密码缓存首地址指针。如下所设置新的密码值为:“AAAAAAAAAAAA”
SETUP_NEW_KEY_VALUE:     
MOV R7,#06H;密码长度为6bytes      
MOV R1,#72H;R1为新密码缓存首地址指针      
MOV @R1,#0AAH;设置新密码值
MOV 73H,#0AAH      
MOV 74H,#0AAH      
MOV 75H,#0AAH      
MOV 76H,#0AAH      
MOV 77H,#0AAH  
良好的经验告诉我们,为了确保整个智能卡系统的高度安全保密,我们有必要在程序设计中,在完成了“密码操作”之后,立即清除存放新的密码值的缓冲区,简单的方法如下:
CLEAR_NEW_KEY_BUFFER:     
MOV R7,#06H;密码长度为6bytes
MOV R1,#72H;R1为新密码缓存首地址指针
CLEAR_LOOP:      
MOV @R1,#00H;清除新密码值所在缓冲区
INC R1
DJNZ R7,CLEAR_LOOP


2:设置密码状态/控制寄存器KeyStatus&ControlRegister(KEYSTACON)
KEYSTACON寄存器是一个只可读不可写的寄存器(存储器),它指示出“密码操作”时所处的状态和要控制的ASIC内部“密码存储器RAM”的选择。
这里所指的“状态”是指本次“密码操作”两个主要步骤中的一个。
KEYSTACON寄存器是一个8-bit的存储器,其中有用的位(bit)只有3位。
MSB(“A/L”位)若被设置为“0”,则意味着当前“密码操作”的“状态”是“LOAD_KEY(密码存取)”;
若被设置为“1”,则当前“密码操作”的“状态”是“AUTHENTICATION(密码认证)”。
最后2个bit:KS0KS1是密码集keyset的选择。在ASIC中共有3套密码集(keyset)和一个传输密码(TransportKey)可被选择。
设置KS0、KS1的值实际上是在选择(寻址)ASIC模块内部存放密码的不同的存储器单元(密码箱)。
如果“LOAD_KEY”(密码存取)时使用了keyset0,则“AUTHENTICATION”(密码认证)时只能使用keyset0,而不能使用keyset1或文keyset2或其他,
因为在ASIC模块内,keyset0指定的密码存储器地址单元与keyset1或keyset2所指定的密码存储器地址单元是不同的单元。
这就好比去超级市场购物,入超市前您把您的包裹寄存在超市门前包裹箱A中,并得到打印有开起包裹箱A的(开箱)密码纸条;
当您欲取回包裹时,拿着包裹箱A的(开箱)密码纸条而去开包裹箱B或C的箱门,当然不能打开,因为您的地址(箱号)不对,当然您的包裹也不能拿到。
这是密码的认证出错。在ASIC中有相同之处。如果“LOAD_KEY”(密码存取)时使用了keyset0,并存放上密码,
而在“AUTHENTICATION”(密码认证)时却使用keyset1或keyset2或其他而来验证刚才存放的密码,当然会得到ASIC模块返回的认证出错(“AE=1”)。
当KS1KS0=“00”时,选择使用keyset0;
当KS1KS0=“01”时,选择使用keyset1;
当KS1KS0=“10”时,选择使用keyset2;
当KS1KS0=“11”时,选择使用传输密码(TransportKey)。


以下是设置密码状态/控制寄存器KeyStatus&ControlRegister(KEYSTACON)的程序:
SETUP_KEYSTACON:
MOV 7EH,#00000000B; 选择使用keyset0,并指明是“LOAD_KEY”
MOV A,7EH ; 7EH单元存放了设置KEYSTACON的值
MOV R0,#0BH ; KEYSTACON寄存器地址为0Bh
MOVX @R0,A ; 设置KEYSTACON寄存器
如果我们要选择使用keyset2,则相应可以设置7EH单元为#00000010b(0x02),即:
MOV 7EH,#00000010B


3:设置密码地址寄存器KeyAddressRegister(寄存器地址:0x0C)
在成功地完成了对密码状态/控制寄存器(KEYSTACON)的设置之后,必须立即对密码地址寄存器KeyAddressRegister进行设置,
而不能对密码数据寄存器KeyDataRegister进行设置或做其他设置,否则将出错。
因为ASIC内部接收MCU指令/数据的存储单元是按照FIFO(“FirstInFirstOut”即“先进先出”)方式工作的。
由于一张非接触式智能卡有16个Sector(扇区),并且每个Sector都可能有着各自不同的密码,
因此在ASIC模块中就会有不同的密码存储器与之相对应。当对16个Sector中的一个Sector进行密码操作时,
就必须对ASIC模块中与该Sector对应的密码存储器进行寻址,找到这一密码存储器确切位置。
不过MCU送出的寻址地址只是ASIC在其内部做第二次寻址(地址变化)的“一部分”地址。
这里所指的“一部分”是出于高度安全保密的原因。以下是8位(bit)密码地址寄存器的说明:


MSB(“A/L”bit)与KEYSTACON寄存器中的MSB有着相同的意义;
“A/B”bit位指出MCU要使用的密码的类型。当“A/B”=“0”时,MCU使用KEYA;当“A/B”=“1”时,MCU使用KEYB;
 “A5~A0”指出要求密码操作的某一Sector的地址。
当要对Sector0进行密码操作时,“A5~A0”应该被设置为“00000b”(0x00);
如果是Sector1,“A5~A0”应该被设置为“00001b”(0x01);
如果是Sector5,“A5~A0”应该被设置为“00101b(0x05),等等。
以下是设置密码地址寄存器KeyAddressRegister的程序:


SETUP_Key_Address_Reg:
MOV 7DH,#00000001B ;使用KEYA,对Sector1进行“LOAD_KEY”
MOV A,7DH      ;7DH单元存储了密码地址寄存器值
MOV R0,#0CH     ;密码地址寄存器地址为“0Ch”
MOV X@R0,A      ;设置密码地址寄存器


如果要对Sector1使用KEYB,则7DH单元必须设置为“#01000001b”(0x41),即:
MOV 7DH,#01000001B


更进一步,如果要对Sector5使用KEYB,则7DH单元必须设置为“#01000101b”
(0x45),即: V 7DH,#01000101B


这样,Sector5中Block0,1,2(相应于绝对块地址为:Block20,21,22)中原有数据将可以被操作。
Sector5中Block3也可以按照预先定义的存取控制条件而被改写密码,或被读出密码或控制字节。


4:设置密码数据寄存器KeyDataRegister(寄存器地址:0x0A)
如果成功地完成了以上几个方面的设置,ASIC模块现在可以接收MCU送出的新的密码值了,
即现在应该设置密码数据寄存器KeyDataRegister。
密码数据寄存器KeyDataRegister也是WOM类型的存储器。只可写入数据,不可读出数据,或读到的数据是无效的。
由于密码的长度为6bytes,因此密码数据寄存器KeyDataRegister也将由6个bytes的FIFO存储器组成。
以下是设置密码数据寄存器KeyDataRegister的程序:
SETUP_Key_Data_Reg:
MOV R1,#72H   ;R1为新密码缓存(72H~77H)首地址指针
MOV R7,#06H   ;密码长度=6bytes
MOV R0,#0AH   ;密码数据寄存器地址为:“0Ah”


WRITE_Key_Data_Reg_LOOP:
MOV A,@R1    ;取出一个byte的新密码值
MOV X@R0,A    ;将一个byte的新密码值送入密码数据寄;存器中(ASIC模块中)
INC R1
DJNZ R7,WRITE_Key_Data_Reg_LOOP
这里有一个非常重要的问题,即传送6bytes长度的密码时,这6bytes的顺序必须引起高度重视。
由于每一个Block3都有着如下的存储格式存放着密码KEYA,KEYB及4个字节的存取控制条件:
因此,密码数据寄存器接收MCU发送的第一个密码字节(byte)必须是KEYA中的第一个字节,
即表中的“A0”字节。否则送入非接触式智能卡中的密码将是反向的6个字节。密码KEYB具有相同之处。


5:校验STACON寄存器,以确定这次的“LOAD_KEY”(密码存取)是否有效
在完成上述操作后,接着应该对以上的结果进行校验,以确定这次的“LOAD_KEY”(密码文存取)是否有效。
这可以通过校验STACON寄存器中的“AE”bit位来完成。STACON寄存器是ASIC模块中极为重要的状态寄存器和控制寄存器。
当对ASIC模块进行任何读/写操作时,它是一个状态寄存器,指出当时读/写操作的状态是如何的。


此时的STACON寄存器有着如下的8个bit的状态格式:
当对ASIC模块进行任何控制操作时,它是一个控制寄存器,此时的STACON寄存器又有着如下的8个bit的控制格式:
我们进行密码操作,读写ASIC模块时,只是会涉及STACON寄存器中的“AuthenticationError”bit(即“AE”位)。
A当“AE”=“1”时,指明刚才的密码操作(“LOAD_KEY”或“AUTHENTICATION”)没有成功;
B当“AE”=“0”时,指明刚才的密码操作(“LOAD_KEY”或“AUTHENTICATION”)成功;
以下是校验STACON寄存器,以确定这次“LOAD_KEY”密码存取操作是否有效的校验程序:
VERIFY_LOAD_KEY_Operationroutine:
VERIFY_LOAD_KEY_OP:
MOV R0,#01H   ;STACON寄存器地址为“01H”
MOV XA,@R0   ;读ASIC内的STACON寄存器;如果“AE”=“1”,转出错处理
JB ACC.2, LOAD_KEY_Operation_ERR   ;否则“AE”=“00”,此次“LOAD_KEY”成功
MOV B,#00H;送OK标志“00”
AJMP LOAD_KEY_Operation_OK
LOAD_KEY_Operation_ERR:
MOV B,#99H;送出错标志“99”,此次“LOAD_KEY”失败
......
(出错处理)
......
AJMP VERIFY_EXIT
LOAD_KEY_Operation_OK:
MOV A,B
ACALL DISPLAY
......
(“OK”处理)
......
VERIFY_EXIT:
RET


6:“AUTHENTICATION”(密码认证)
“AUTHENTICATION”(密码认证)操作必须按照如下的几个步骤进行:
  设置ASIC模块中的TOC/BCNTS寄存器等
  设置密码状态/控制寄存器KeyStatus&ControlRegister(KEYSTACON)
  设置密码地址寄存器KeyAddressRegister(寄存器地址:0x0C)
  设置AUTHENTICATION指令码
  密码地址变换
  校验STACON寄存器,以确定这次的“AUTHENTICATION”密码认证是否有效
  关闭TOC及一些其它操作等
  由于“AUTHENTICATION”(密码认证)操作同“LOAD_KEY”(密码存取)操作相互类似,在此不再重复。
  只有在完全完成了上述的两个主要的密码操作步骤,并且得当了ASIC模块“OK”的响应,
非接触式智能卡上相对应与刚才进行过密码操作的某一扇区Sectorm内的Block0,1,2才能被MCU
进行访问,包括进行读/写等数据操作。一旦要求对另一扇区Sectorn内的Block进行数据读写
时,则必须重新开始对扇区Sectorn进行密码操作,包括“LOAD_KEY”(密码存取)操作和密码认证等。




读  卡: 
PC机发送:OB  S  M1  M2  M3  M4  M5  M6  K  X 其  中:
OB为命令头,十六进制表示; 
S为扇区编号,范围0~15; 
M1  M2  M3  M4  M5  M6为扇区密码; 
K为扇区块号:范围:0~2; 
X为异或校验: 
X=0B XOR  S XOR  M1 XOR  XOR M3  XOR M4  XOR M5  XOR M6  XOR K 
 
写  卡: 
PC机发送:09  S  M1  M2  M3  M4  M5  M6  D1  D2  D3  D4  D5  D6  D7  D8  D9  D10  D11  D12  D13  D14  D15  D16  K  X 
09为命令头; 
S同上;
M1~M5:同上; 
D1~D16:16个字节的数据,范围0~255;         K同上;X=异或校验; 
X=从09(包含09)异或到K(包含K)的值。  


修改密码: 
PC机发送:0A  S  M1  M2  M3  M4  M5  M6  K1  K2  K3  K4  K5  K6  X 


0A为命令头;
S同上; 
M1~M6:为旧密码,范围0~255;         
K1~K6:为新密码,范围0~255; 
X=从0A(包含0A)异或到K6(包含K6)的异或值。


读序列号: 
PC机发送:0x0C:十六进制。


下位机回应: 
1、若收到一个字节: 
如果为:
1)0xAA—发送命令成功;         
2)0Xbb—写数据成功:         
3)0xCC—修改密码成功;        
4)0xFF—发送命令失败; 
5)0xDD—密码错误或认证没通过。 


2、若收到16个字节: 
则这16个字节为读取的某扇区16个字节的数据。 
若收到4个字节: 则这4个字节为读取的序列号。


参考文档
http://wenku.baidu.com/link?url=5bCa39ae-RxX2z8iagVWompUZGxB99zqDj9Ubq0BRVd1jV2skWFdLuWJhkGflRpi1Ew_MMXA1YOkuo6adtm9Loo1c3tpR-hxKC8txh1XTdO
http://wenku.baidu.com/view/422a6f3a580216fc700afda9.html
http://wenku.baidu.com/view/37b82a8371fe910ef12df8d7.html?re=view


时间
起草于 2015-10-15


你可能感兴趣的:(Android,NFC模块)