1. 程式人生 > >Android程式執行分析——中等複雜程度的NTAG I2C Demo為例(三)

Android程式執行分析——中等複雜程度的NTAG I2C Demo為例(三)

本節接上一篇,主要討論不同認證狀態下的認證方式的具體實現

討論的內容是接這篇文章的後半部分

protectPlus

首先看第一個

這個函式的實現如下

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.nxp.nfc_demo.reader.I2C_Enabled_Commands#protectPlus()
	 * 
	 */
	//See P23
	@Override
	public void protectPlus(byte[] pwd, byte startAddr) throws IOException,
			FormatException, NotPlusTagException {
		byte[] data = new byte[4];
		
		if(getProduct() != Prod.NTAG_I2C_1k_Plus && getProduct() != Prod.NTAG_I2C_2k_Plus) {
			throw new NotPlusTagException(
					"Auth Operations are not supported by non NTAG I2C PLUS products");
		}
		reader.SectorSelect((byte) 0);
		
		// Set the password indicated by the user
		reader.write(pwd, Register.PWD.getValue());

		//See P24
		//Access Conditions----------------------------------------------------------
		byte access = (byte) 0x00;
		byte authLimit = 0x00; 				// Don't limit the number of auth attempts


		access ^= 1 << Access_Offset.NFC_PROT.getValue();			// NFC_Prot
		access ^= 0 << Access_Offset.NFC_DIS_SEC1.getValue();		// NFC_DIS_SEC1
		access |= authLimit << Access_Offset.AUTH_LIM.getValue();	// AUTHLIM
		
		// Write the ACCESS configuration
		data[0] = access;
		data[1] = 0x00;
		data[2] = 0x00;
		data[3] = 0x00;
		reader.write(data, Register.ACCESS.getValue());
		//Access Conditions End-------------------------------------------------------

		//See P24
		//Protection bits (PT_I2C)------------------------------------------------------
		byte ptI2C = 0x00;
		byte i2CProt = 0x00;

		ptI2C ^= 0 << PT_I2C_Offset.K2_PROT.getValue();			// 2K Prot
		ptI2C ^= 1 << PT_I2C_Offset.SRAM_PROT.getValue();			// SRAM Prot
		ptI2C |= i2CProt << PT_I2C_Offset.I2C_PROT.getValue();	// I2C Prot

		// Write the PT_I2C configuration-----------------------------------------------
		data[0] = ptI2C;
		data[1] = 0x00;
		data[2] = 0x00;
		data[3] = 0x00;
		reader.write(data, Register.PT_I2C.getValue());
		//Protection bits (PT_I2C) End--------------------------------------------------

		// See P12
		// AUTH0-------------------------------------------------------------------
		// Write the AUTH0 lock starting page
		data[0] = 0x00;
		data[1] = 0x00;
		data[2] = 0x00;
		data[3] = startAddr;
		reader.write(data, Register.AUTH0.getValue());
		// AUTH0 End----------------------------------------------------------------
	}

可以看到這個函式的實現是很複雜的,用到了一些位操作,分析如下:

首先new一個4byte的陣列

顯然這個就是拿來放pwd的,因為pwd就是4個byte的

緊接著我呼叫getProduct()函式,並且判斷其返回值,這個函式的具體實現以後有機會再細說,可以簡單地理解為,NXP NFC晶片的某些暫存器裡存放了這款晶片的產品型號資訊,通過這個函式可以讀取這些暫存器,從而獲得當前這款晶片的產品資訊

緊接著選擇sector0,這裡用到的SectorSelect函式具體實現以後有機會再說,可以簡單地理解為,選擇接下來要操作sector

然後,進行使用write函式,這個函式有2個引數,一個是你選擇的pwd(或者說你輸入的pwd),另外一個是NXP NFC晶片中pwd儲存的offset,其實就是常數0xE5

需要注意的一點是,在這種狀態下,上一個圖片中的這句話實際上是在做一個輸入密碼的操作,而不能說是一個認證操作(說是認證容易引起歧義)

下面是對access暫存器的一些操作,操作的方法很簡單,你新建一個byte,名為access,初始化為0x00,然後對這個access進行修改,之後再把這個access寫入到NXP NFC晶片中

我們看一下實現的程式碼,先初始化兩個byte

下面3句程式碼,前2句是模2加(異或),最後一句是按位或

因為每次傳輸都是傳4個byte,因此接下來的傳輸操作如圖所示

類似地,接下來進行對PT_I2C暫存器的配置,配置的方法很簡單,和上面都是一樣的

類似地,接下來對AUTH0暫存器進行配置

至此,protectPlus完成

unprotectPlus

/*
	 * (non-Javadoc)
	 * 
	 * @see com.nxp.nfc_demo.reader.I2C_Enabled_Commands#unprotectPlus()
	 * 
	 */
	@Override
	public void unprotectPlus() throws IOException, FormatException, NotPlusTagException {
		byte[] data = new byte[4];
		
		if(getProduct() != Prod.NTAG_I2C_1k_Plus && getProduct() != Prod.NTAG_I2C_2k_Plus) {
			throw new NotPlusTagException(
					"Auth Operations are not supported by non NTAG I2C PLUS products");
		}
		reader.SectorSelect((byte) 0);

		// See P24
		// AUTH0-------------------------------------------------------------------
		// Write the AUTH0 lock starting page
		data[0] = 0x00;
		data[1] = 0x00;
		data[2] = 0x00;
		data[3] = (byte) 0xFF;
		reader.write(data, Register.AUTH0.getValue());
		// AUTH0 End----------------------------------------------------------------

		// P24
		// PWD---------------------------------------------------------------------
		// Set the password to FFs
		data[0] = (byte) 0xFF;
		data[1] = (byte) 0xFF;
		data[2] = (byte) 0xFF;
		data[3] = (byte) 0xFF;
		reader.write(data, Register.PWD.getValue());
		// PWD End------------------------------------------------------------------

		// SeeP24
		// ACCESS-------------------------------------------------------------------
		// Write the ACCESS configuration
		data[0] = 0x00;
		data[1] = 0x00;
		data[2] = 0x00;
		data[3] = 0x00;
		reader.write(data, Register.ACCESS.getValue());
		// ACCESS End---------------------------------------------------------------

		// Write the PT_I2C configuration------------------------------------------------
		// Write the PT I2C configuration
		data[0] = 0x00;
		data[1] = 0x00;
		data[2] = 0x00;
		data[3] = 0x00;
		reader.write(data, Register.PT_I2C.getValue());
		// Write the PT_I2C configuration End--------------------------------------------
	}

稍微看一下這個函式的實現,你會發現,和上一個函式非常相似,但是少去了你設定初始密碼的環節

一樣的套路

配置Auth0暫存器

配置Access暫存器

配置PT_I2C暫存器

至此這個函式也結束了

authenticatePlus

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.nxp.nfc_demo.reader.I2C_Enabled_Commands#authenticatePlus()
	 * 
	 */
	@Override
	public byte[] authenticatePlus(byte[] pwd) throws IOException, NotPlusTagException {
		if(getProduct() != Prod.NTAG_I2C_1k_Plus && getProduct() != Prod.NTAG_I2C_2k_Plus) {
			throw new NotPlusTagException(
					"Auth Operations are not supported by non NTAG I2C PLUS products");
		}
		return reader.pwdAuth(pwd);
	}

可以看到,前面的套路是一樣的,但是後面呼叫了pwdAuth函式

這個函式的實現是這樣的,說白了就是把你的密碼傳到NXP NFC晶片裡去