bluetooth door locking mechanism

121
University of Washington December 11 th , 2012 Safe Guard Lock System A secure locking system project Rob Greenewald, Mark Rathjen, David Chamberlain

Upload: dc46and2

Post on 17-Jul-2016

42 views

Category:

Documents


0 download

DESCRIPTION

Project report for an electrical engineering class project. Describes a system for locking and unlocking doors using a bluetooth enabled smartphone.

TRANSCRIPT

Page 1: Bluetooth Door Locking Mechanism

Safe Guard Lock SystemA secure locking system project

Rob Greenewald, Mark Rathjen, David Chamberlain

December 11th, 2012University of Washington

Page 2: Bluetooth Door Locking Mechanism

Table of ContentsAbstract.......................................................................................................................................................1

Introduction.................................................................................................................................................1

Discussion of the Project.............................................................................................................................2

Design Specification.................................................................................................................................2

Design Procedure....................................................................................................................................2

Use Cases.................................................................................................................................................3

System Description..................................................................................................................................5

System Block Diagram.........................................................................................................................5

Android Smartphone...........................................................................................................................5

Bluetooth Adapter...............................................................................................................................6

Bluetooth Module...............................................................................................................................6

Lock/Authentication Management......................................................................................................6

Lock Motor/Actuator...........................................................................................................................7

RFID Scanner........................................................................................................................................8

Command and Protocols.........................................................................................................................8

Generic Command...............................................................................................................................8

Begin Command..................................................................................................................................8

BEGINACK Command...........................................................................................................................8

Unlock Command................................................................................................................................9

Lock Command....................................................................................................................................9

Status Command.................................................................................................................................9

Add Member Command......................................................................................................................9

Remove Member Command..............................................................................................................10

Security..................................................................................................................................................10

Message Authentication Activity Diagram.............................................................................................11

Specification of External Environment...................................................................................................12

System Input and Output Specification.................................................................................................13

System Inputs........................................................................................................................................13

Smartphone/Bluetooth Adapter........................................................................................................13

i

Page 3: Bluetooth Door Locking Mechanism

Bluetooth Adapter/Bluetooth Module..............................................................................................13

Bluetooth Module/Lock Manager.....................................................................................................13

RFID/Lock Manager...........................................................................................................................13

System Outputs.....................................................................................................................................14

Lock Manager/Lock Servo..................................................................................................................14

Lock Manager/Bluetooth Module.....................................................................................................14

Bluetooth Module/Bluetooth Adapter..............................................................................................14

Smartphone/Bluetooth Adapter........................................................................................................14

Software Implementation......................................................................................................................14

Android Application...........................................................................................................................14

Generate/Construct Keys..................................................................................................................15

Construct Key Objects........................................................................................................................15

Read/Write Keys to Memory.............................................................................................................15

Authorize User...................................................................................................................................15

Read/Write Username to Memory....................................................................................................15

Get Username from User...................................................................................................................15

Compare Usernames.........................................................................................................................15

Lock/Unlock System...........................................................................................................................15

Discover/Connect to Lock..................................................................................................................15

Exchange Message.............................................................................................................................15

Construct and Sign/Encrypt Message................................................................................................16

Send Message....................................................................................................................................16

Exchange Public Key and Username..................................................................................................16

Discover/Connect to User Phone.......................................................................................................16

Exchange Message.............................................................................................................................16

Construct Message............................................................................................................................16

Send Message....................................................................................................................................16

Get Modulus and Exponent of Public Key..........................................................................................16

Add/Remove User from System........................................................................................................16

Get User’s Username and Public Key.................................................................................................16

Construct and Sign/Encrypt Message................................................................................................16

Send Message....................................................................................................................................16

ii

Page 4: Bluetooth Door Locking Mechanism

Activity Diagram................................................................................................................................17

Lock Control Software Implementation.............................................................................................20

Hardware Implementation....................................................................................................................25

Hardware Schematic..........................................................................................................................25

RFID Reader.......................................................................................................................................25

Bluetooth Module.............................................................................................................................25

Servo..................................................................................................................................................26

TI Stellaris Development Board.........................................................................................................26

Random Number Generator..............................................................................................................26

System Testing...........................................................................................................................................26

Test Plan................................................................................................................................................26

Test Specifications.................................................................................................................................27

Test Cases..............................................................................................................................................28

Results.......................................................................................................................................................29

Presentation of Results..........................................................................................................................29

Analysis of Errors...................................................................................................................................30

Bill of Materials..........................................................................................................................................31

Summary...................................................................................................................................................31

Conclusion.................................................................................................................................................32

Appendix...................................................................................................................................................33

Appendix A Android Application Code...................................................................................................33

Appendix A1 (DeviceListActivity.java)................................................................................................33

Appendix A2 (BluetoothChatService.java).........................................................................................36

Appendix A3 (BluetoothChat.java)....................................................................................................43

Appendix B Stellaris Board Code............................................................................................................55

Appendix B1 (main.c).........................................................................................................................55

Appendix B2 (parser.c)......................................................................................................................63

Appendix B3 (pwm.c).........................................................................................................................77

Appendix B4 (rfid_reader.c)...............................................................................................................79

Appendix B5 (userdb.c)......................................................................................................................80

Appendix B6 (utils.c)..........................................................................................................................84

Appendix B7 (sbrk.c)..........................................................................................................................89

iii

Page 5: Bluetooth Door Locking Mechanism

Appendix B8 (startup_gcc.c)..............................................................................................................89

Appendix B9 (global.h).......................................................................................................................92

Appendix B10 (parser.h)....................................................................................................................93

Appendix B11 (userdb.h)...................................................................................................................93

Appendix B12 (pwm.h)......................................................................................................................95

Appendix B13 (rfid_reader.h)............................................................................................................95

Appendix B14 (utils.h)........................................................................................................................95

iv

Page 6: Bluetooth Door Locking Mechanism

AbstractIn today’s technology driven world an opportunity to increase security and convenience for residents of an office or apartment building has become available for development. Our new Safe Guard Lock System will allow a resident to use their smartphone as a key to their apartment or office building. The client will need a system that can provide secure access to any deadbolt lock from the convenience of their smartphone. This need will be fulfilled by the use of a Stellaris microcontroller, servo motor, Android smartphone, and RFID Card reader. The system will had two inputs; the Android Smartphone and RFID reader. The system had one output to the servo motor to control the physical locking of the door. The system design used the Stellaris microcontroller as the brain of the system. The Android Smartphone talked to a Bluetooth module witch intern talked to the microcontroller via UART. The RFID talked to the microcontroller via a second UART channel. The Servo was controlled via a pulse width modulation from the microcontroller. Testing of the system included several test cases. These test cases included locking and unlocking of the door by the Android device and the RFID card. Also several bad RFID cards and Android devices were used to ensure that the door could only be operated by authorized users. The system produced mostly positive results, and a mostly fully functional product was created given the allotted time. Some errors did occur and were not able to be solved in time for the final demo.

IntroductionEveryone needs to a means to secure and control access to their homes, workplaces, cars, and information. Each of us deals with a wide variety of mechanisms for accomplishing this, which requires us to memorize many passwords and carry an awkward collection of mechanical and electronic keys. Although existing electronic lock systems are more convenient for the user and administrators than mechanical locks, each organization uses a different system, which prevents any simplification. The smart phone is becoming more ubiquitous in our society every day. This presents the opportunity to consolidate multiple access mechanisms into a single device, which most people already carry.

For our final project we propose to design and prototype a system that can wirelessly unlock a door with a smartphone. The smartphone will transmit the user’s identity and credentials to the lock control system (LCS) and request access. Modern cryptographic techniques will be used to secure communications between the LCS and smartphone, and a public-private key infrastructure will be used for authenticating users. If the LCS can authenticate the user and the he or she is on the list of authorized persons, then the door will be unlocked.

The project will begin by defining a standard for how the system will operate at the application level. This standard will include the application-layer communication protocol, the method of identifying and authenticating users, and the method of administering access-control devices (e.g. a lock). We believe our project may be the basis for a marketable product in the future, and creating such a standard will allow the system to be implemented with a wide variety of hardware and communication technologies—an important prerequisite to wide-spread adoption.

1

Page 7: Bluetooth Door Locking Mechanism

We will then implement the user and administrative aspects of the standard in a simple Android app. The LCS will be implemented in a custom microcontroller-based circuit. The LCS will be battery powered and will directly control and monitor the actuator which turns the lock. Communication between the smartphone and LCS will be via either the Bluetooth or the Near Field Communications protocol. An actuator will be designed and built to manipulate a common, mechanically-keyed deadbolt lock. This will allow the system to be temporarily installed and thoroughly tested on an apartment door without violating restrictions imposed by the lease and while still allowing access via the mechanical key.

Discussion of the Project

Design SpecificationAny prospective client looking to upgrade their security should consider the Safe Guard Lock System. The system provides a very convenient way to access any door that needs to be secure. The system also offers a high level of security for the amount of convenience offered to the client. By effectively making the clients smartphone their new key the Safe Guard Lock System will simplify their life by removing one more physical key that they must carry. This physical key could be in the form of the traditional metal key lock, or a security badge. The system uses the smartphone’s existing Bluetooth to connect to the lock. The security of this lock goes beyond the simple “pair key” of most Bluetooth devices. After pairing of the phone the system communicates with a high end security encryption and decryption algorithm.

As long as a client has a verified authentication key they will be able to access any door with the Safe Guard Lock System from the ease of their smartphone. There is also an Administrator to the system that will be able to add and remove users from the system. The system will come with a default admin, and can be changed to a custom admin in order for higher security. The system also has a backup physical RFID reader. Only a single RFID card will be allowed with each system. The RFID is meant for back up purposes only.

Design ProcedureThe design procedure began from the top down. The Safe Guard Lock System was imagined to be a convenient and secure way to lock and unlock any door with a deadbolt. The idea behind the system was to have a fully incorporated module that can be fitted over a deadbolt. From there the user’s smartphone would be able to lock and unlock the door through the use of an app on their device. The design of the system began with several choices. These choices included: Bluetooth as the communications medium between the smartphone and microcontroller, RSA with SHA-1 hashing as the security encryption/decryption protocol, and UART communication between the Bluetooth module/RFID module and the microcontroller.

In the Safe Guard Lock System the main brain was the Stellaris ARM M3 based microcontroller. This microcontroller was integrated onto an evaluation board that provided the UART communication

2

Page 8: Bluetooth Door Locking Mechanism

channels and pulse width modulation output that was required for this project. An Android Smartphone with firmware version 2.3.5 was used to build the locking application. The deadbolt lock was controlled using a pulse width modulation output to a servo motor. The RFID functionality was provided by an ID-12 RFID reader. The ID-12 reader was connected to a Sparkfun RFID USB Reader (SEN-09963). This board allowed the ID-12 reader to dump out its data via mini USB or UART. Finally the JY-MCU BT_BOARD was used for the Bluetooth communication module on the microcontroller side.

After the selection of all parts of the system they had to be integrated together. This was accomplished by connecting JY-MCU Bluetooth module to the microcontroller via UART, the RFID reader to the microcontroller via UART, and the servo was controlled with the pulse width modulation output from the microcontroller. The Android smartphone then communicated with the microcontroller through the JY-MCU Bluetooth module.

Use Cases

Lock/Unlock Door—An authorized individual opens the smartphone app and commands the door to be locked/unlocked. The LCON authenticates the user and locks/unlocks the door. A status message, indicating success or failure is shown to the user.

Check Status—An authorized individual opens the smartphone app and requests lock status. The LCON authenticates the user and reports the lock status.

3

Page 9: Bluetooth Door Locking Mechanism

Add AI—An Administrator opens the smartphone app and sends the identity and public key of a new authorized individual to the LCON. The LCON authenticates the administrator and adds the new AI to its internal database. A status message, indicating success or failure is shown to the administrator.

Delete AI—An Administrator opens the smartphone app and sends the identity of the authorized individual to be deleted to the LCON. The LCON authenticates the administrator and deletes the AI from its internal database. A status message, indicating success or failure is shown to the administrator.

List AI—An Administrator opens the smartphone app and requests the list of AIs from the LCON. The LCON authenticates the administrator and sends the list of AIs from its internal database back to the smartphone.

4

Page 10: Bluetooth Door Locking Mechanism

System Description

System Block Diagram

Android SmartPhone Bluetooth Adapter Bluetooth Module Lock/Authentication Management

Lock Motor/Actuator

Finger Print Scanner

Wireless Connection UART/RS-232

RS-232

Figure 1: Overall System Block Diagram

Android SmartphoneInputs:

User Interface Inputs (i.e. button press, text input)

File Reads to Internal File System of Phone for keys, username, and password

Outputs:

Lock Commands via Bluetooth (reference Commands and Protocols Section)

User Interface Updates (i.e. button states, text updates to user)

File Writes to Internal File System of Phone for keys, username, and password

The android smartphone will act as the user interface for this system. The user will be first authorized through the smartphone so that the owner’s keys will not be put in jeopardy. Once authentication has been established the smartphone communicates with the Bluetooth adapter and starts the discovery process looking for the advertisement of the lock. Once the lock’s advertisement is discovered the pairing and connection process is initiated. After connection has been established the smartphone creates a message requesting the lock be opened, which includes the lock command itself, username, random session token and signature generated from SHA-1 and RSA encryption. These command are

5

Page 11: Bluetooth Door Locking Mechanism

also specified in more detail in the commands and protocols section. Similar messages are constructed to unlock the door, add and remove users, as well as transfer public keys. The UI is updated to the user as the lock toggles between the lock and unlock states.

Security Algorithm:

Before sending a command to the lock management system via Bluetooth, a signature is included in the message using SHA-1 and RSA encryption, which is provided by the Android framework. A random number, used as the session token, which is randomly generated by the lock management system at connection is used in the signature to stop someone from receiving and replaying the message to the system.

Bluetooth AdapterInputs:

Status Updates from the lock manager received via BT

Outputs:

Commands from Android application to be sent via BT to lock management system

The Bluetooth adapter is the onboard smartphone adapter, which can be accessed through the Android framework. It will be used for the discovery, pairing, connection and transaction process between the smartphone and the lock manger.

Bluetooth ModuleInputs:

Commands from the Android application received via BT

Outputs:

Status updates from the lock management system sent to Android application via BT

The Bluetooth module is a serial port module that communicates to the lock manager over a UART/RS-232 communication protocol. This module manages the pairing and connection process between itself and the Bluetooth adapter on the Android smartphone.

Lock/Authentication ManagementInputs:

32-bit binary signal sent from the RFID scanner module via UART when card is scanned

Commands from the Android application sent via BT

6

Page 12: Bluetooth Door Locking Mechanism

Outputs:

Status updates sent to the Android application via BT

Pulse width modulator output driving servo

The Lock/Authentication manager manages all of the authentication process of the user and the control of the locking mechanism. Once a user discovers and connects to the module, the lock manager sends a randomly generated session token to the phone for use in the encryptions, and then waits until a message is received requesting what action to take. Once the message is received it should contain two parts the textual message and the encrypted message. The user’s name is obtained from the textual message and the public key corresponding to that user is obtained from the lookup table of authorized users. The encrypted signature is decrypted using the public key and the textual message is hashed, if both messages are equal after this process then the user is authorized for entrance and the lock is signaled to open. The message can also ask to add a new user to the lookup table, which requires that the authorized user’s signature goes through this authentication process and the new user’s public key is then added to the lookup table. Based on a timer the door will automatically relock after the door has be unlocked for a set amount of time.

Authentication can also be established through the RFID scanner where the user can put their card up against the door and upon verifying the 32-bit binary number will open the door for the authorized card. Once the user has been authorized the lock is signaled to unlock, and will automatically relock after a wait timer expires.

Security Algorithm:

Upon receiving a command from the Android application the lock management system parses the message for verification. First the signature is decrypted using the public key stored in the system for the user. The textual message signed by the user is then hashed by SHA-1 and compared to the decrypted signature. If the two results are equal then the authorized user sent the message and the command is processed and executed.

Lock Motor/ActuatorInputs:

Pulse width modulator output from lock management system

Outputs:

None

7

Page 13: Bluetooth Door Locking Mechanism

The lock motor/actuator will be a servo motor that can be controlled by a specified pulse width modulator output of the lock manager. Once the lock manager has authorized a user, the appropriate pulse width is supplied to the motor, which turns until a feedback signals that it’s reached to the full locked position. A similar sensor is used to signal that the lock has reached the full unlock position.

RFID ScannerInputs:

None

Outputs:

32-bit binary signal corresponding to the ID of the scanned RFID card

The RFID scanner is the back authentication system for users without a smartphone. The scanner itself is mounted on the door and when the user scans the card and the 32-bit binary signature is authorized with the lock management system, then the lock is opened if authentication is successful.

Command and ProtocolsAll of the primary communication is done over Bluetooth and interfaced through a UART interface. The commands and protocols are as follows:

Generic Command ‘<Cmd:Parameters(separated by :’s)>’

All commands will follow this generic interface where the entire command is surrounded by ‘<’ and ‘>’, and each element inside separated by ‘:’. The first element will be the type of command and each of the following elements will be the parameters passed in for that command.

Begin Command‘<BEGIN>’

Indicates that a smartphone wants to communicate with the LCON. This must proceed every other command sent to the LCON.

BEGINACK Command‘<BEGINACK:Status:RN>’

The LCON acknowledges the BEGIN command and is ready to receive a command other than <BEGIN>.

8

Page 14: Bluetooth Door Locking Mechanism

RN - Random number generated by the LCON, which should be included in the future commands.

Status - Current state of the lock system which will be either LOCKED or UNLOCKED.

Unlock Command‘<UNLOCK:TextUserName:RN:EncryptedHash>’

User requests that the system unlocks.

TextUserName – The user name of the person trying to gain access in ASCII format.

RN – The random number previously received from the Lock Control Device.

EncryptedHash – The SHA-1 hash of the previous command text (excluding the < and the trailing :, but including internal :’s) is computed, then encrypted using RSA and the user’s private key.

Lock Command‘<LOCK:TextUserName:RN:EncryptedHash >’

User requests that the system locks.

TextUserName, RN & EncrypetdHash – See Unlock Command.

Status Command‘<STATUS:TextMessage>’

TextMessage – Message carrying and ASCII format update of the state of the system. Either LOCKED or UNLOCKED.

Add Member Command‘<ADD:TextAdminName:TextUserName:NewKey:Perms:RN:EncryptedHash >’

Administrator requests an addition to the table of authorized users.

TextAdminName – The user name of the admin in control of managing key’s in the system in ASCII format.

NewUserName – The user name of the new authorized individual.

NewKey – Public key of the new member to add to the system of authorized people.

9

Page 15: Bluetooth Door Locking Mechanism

NewPerms – Permissions assigned to this user as an 8-bit field: bit 0 (LSB) = lock/unlock permission, bit 1 = admin rights.

RN & EncrypetdHash – See Unlock Command.

Remove Member Command‘<REMOVE:TextAdminName:OldUserName:OldKey:RN:EncryptedHash>’

Administrator requests a removal of a user from the table of authorized users.

TextAdminName – The user name of the admin in control of managing key’s in the system in ASCII format.

OldName – The user name to remove

OldKey – Public key of the old member to remove from the system of authorized people

RN & EncrypetdHash – See Unlock Command.

SecurityThe security of the system depends on being able to distinguish command messages sent by authorized users from those sent by an unauthorized person (an attacker). To provide a high degree of security, a public/private key infrastructure is established and digital signatures are used to ensure the integrity and authenticity of all command messages. The basic process of creating and verifying a digital signature is illustrated in Figure 2 below.

10

Page 16: Bluetooth Door Locking Mechanism

Figure 2: Digital signatures (photo by Microsoft)

After the command message is created by the Android app, a message digest is calculated with the one-way hash function SHA1. The user’s private key is then used to encrypt the message digest using the RSA encryption algorithm. This encrypted message digest is appended to the original message and the whole thing is transmitted to the lock control system. The lock control system parses the message to separate the signature and the original message. It then uses the same SHA1 hash function to calculate the message digest and uses the user’s public key to decrypt the digest contained in the signature. If the two digests match, then the signature is verified and the system knows that it really came from the claimed user and that it has not been altered en route.

One weakness of this system is it does not distinguish when a message was sent. A valid message and signature are always valid and could be captured by an attacker and replayed in the future. To eliminate this risk, a random session token is sent from the lock control system to the Android app. This session token must be included in the future command message and may be used only once. The phone must request a new random token before additional command messages are sent. With this system, an attacker cannot successfully replay an old message because the session token would no longer be valid. The attacker could not update the session token in the old message, because that would invalidate the signature. The attacker cannot successfully calculate a new signature, because they do not have access to the private key.

Message Authentication Activity DiagramThe following activity diagram describes the process of authenticating a message from a user.

11

Page 17: Bluetooth Door Locking Mechanism

Figure 3: Message Authentication Activity Diagram

Specification of External EnvironmentThe Smartphone Controlled Security Door System will be operating on the internal and external doors of office buildings, warehouses, and residential apartment buildings. The temperature range will be as

12

Page 18: Bluetooth Door Locking Mechanism

extreme as the environment where the building is located. For instance if the building is located in Dubai the temperatures will be hot and dry. If the building is located in Alaska then the environment will be cold and wet. Smartphone Controlled Security Door System’s external components must be weather proof. The Smartphone Controlled Security Door System will be running of the building power, so there is no need to worry about battery life.

System Input and Output SpecificationThe Smartphone Controlled Security Door System controls the locking and unlocking of any door it is installed in. The system has two inputs and one output that depends on the inputs. The inputs and outputs are described below.

System InputsThe Smartphone Controlled Security Door System shall support the following kinds of input signals:

Smartphone/Bluetooth AdapterThe smartphone application will support version 2.3 Android phones that have an onboard Bluetooth adaptor. Any inputs at this point will be the user pushing buttons on the phone, or buttons on the LCD display of the phone.

Bluetooth Adapter/Bluetooth ModuleAfter the user has configured the smartphone the next set of inputs will be the Bluetooth adapter on the phone providing an input to the Bluetooth module in the Smartphone Controlled Security Door System. The Bluetooth adapter must communicate with the following standards:

Operation in the range 2,400–2,483.5 MHz Max 100 mW power consumption Min data transfer rate of 1 Mbit/s In input mode the smartphone will act as master and the system will act as slave

Bluetooth Module/Lock ManagerThe Bluetooth module of the system will act as an input to the Lock Manager. The following are the specifications for this communication.

Communication will occur via UART 115,200 Baud Rate 0-5 Volt

RFID/Lock ManagerThe RFID reader will act as an input only to the Lock Manager. The following are the specifications for this communication:

Communication will occur via UART 9,600 Baud Rate 0-5 Volt

13

Page 19: Bluetooth Door Locking Mechanism

System OutputsThe Smartphone Controlled Security Door System shall support the following kinds of output signals:

Lock Manager/Lock ServoThe lock manager will control the operation of the physical servo on the lock.

5 volt operation Pulse Width Modulation controls position of servo Period between pulses is 20 ms Pulse width varies from 0.6 ms to 2.3 ms for 180 degree rotation

Lock Manager/Bluetooth ModuleThe Lock Manager will output to the Bluetooth module. The following are the specifications for this communication.

Communication will occur via UART 115,200 Baud Rate 0-5 Volt

Bluetooth Module/Bluetooth AdapterWhen the Bluetooth module needs to talk to the users smartphone it will output to the Bluetooth adapter. The Bluetooth Module must communicate with the following standards:

Operation in the range 2,400–2,483.5 MHz Max 100 mW power consumption Min data transfer rate of 1 Mbit/s In input mode the smartphone will act as master and the system will act as slave

Smartphone/Bluetooth AdapterAfter the Bluetooth adapter has received a communication from the Bluetooth module of the system the smartphone will display the correct output letting the user know what action has occurred.

Software Implementation

Android ApplicationThe android application is the interface into the lock system for the user where they are able to lock/unlock, add/remove user and exchange keys between phones. In the basic user interaction the process should be that the user opens the application, signs in with their username and presses the lock button, which should in turn open the lock of the lock system. In the case where the administrator is adding or deleting a user the user who wishes to be added to the system connects to the phone of the administrator. Once connected the user sends their username and public key to the admin. Then the phones would disconnect and the admin would connect to the lock management system. Then by pressing the add or remove user button the lock management system would add or remove the specified user from the table of authorized users. To allow this functionality the tasks were broken up as shown below:

14

Page 20: Bluetooth Door Locking Mechanism

Generate/Construct KeysIf it’s the first time the application is being used then a random public and private key must be generated for the user and stored in memory for later uses of the application. Otherwise there should already be a key stored on memory so read in the value and construct Key objects.

Construct Key ObjectsUse the modulus and exponent of the public and private keys to construct PublicKey and PrivateKey java objects for use in the Security Framework.

Read/Write Keys to MemoryIf not previously stored, write the modulus and exponent of the public and private keys to application file. Otherwise, read the previously stored public and private key modulus and exponent values and pass to construct key functions.

Authorize UserVerify that the user of the application is the owner of the phone by querying his username, which can be compared to a stored username in memory.

Read/Write Username to MemoryIf it’s the first time the application is being used then the specified username is written to memory for future authentication. Otherwise read the previously stored username from memory.

Get Username from UserQuery the user to provide their username by using a pop up dialog and wait for a submit action.

Compare UsernamesCompare the username stored in memory to the one provided by the user. Specify authentication success if the two are equal otherwise it’s a failure.

Lock/Unlock SystemThis process requires that the user discover and connect to the lock over Bluetooth using the menu navigation. Once connected a session is started given a randomly generated session token and status of current state of the lock so the UI can update the user. User sends the lock and unlock commands as result of pressing the toggle button, which causes a command to be constructed with user information, session token and user’s signature.

Discover/Connect to LockRequest the Bluetooth adapter to discover new devices and present results to user. When user specifies a device get the mac address and query the device for a connection.

Exchange MessageSend the specified command to the lock system including the user’s information and signature.

15

Page 21: Bluetooth Door Locking Mechanism

Construct and Sign/Encrypt MessageConstruct the textual message specified by the Command and Protocols section which includes the session token. Use SHA-1 hashing and RSA signature specifications and user’s private key to produce a user signature to send with the message.

Send MessageWrite the message to the Bluetooth adapter so that it can be pushed over the connection.

Exchange Public Key and UsernameUser discovers the Bluetooth advertisement of the Administrator’s phone, then connects and sends the user’s username and public key by command.

Discover/Connect to User PhoneRequest the Bluetooth adapter to discover new devices and present results to user. When user specifies the admin’s device get the mac address and query the device for a connection.

Exchange MessageSend the specified command to the administrator’s phone including the user’s information and public key.

Construct MessageConstruct a textual message following the specifications in the Commands and Protocols Section with the user’s username and public key.

Send MessageWrite the message to the Bluetooth adapter so that it can be pushed over the connection.

Get Modulus and Exponent of Public KeyObtain the modulus and exponent of the public key through manipulation of the java objects and their characteristics.

Add/Remove User from SystemSend a command to the lock management system with a username and public key, which the specified action to add or remove from the database of authorized user. Note: This is only sent from an administrative specified phone.

Get User’s Username and Public KeyCheck to see if a username and public key is cached in the phone from an exchange action.

Construct and Sign/Encrypt MessageConstruct a command based on the Command and Protocols Section for adding and removing users with the specified action, username and public key. Include a signature constructed using SHA-1 and RSA signature specifications and the private key of the user.

Send MessageWrite the message to the Bluetooth adapter so that it can be pushed over the connection.

16

Page 22: Bluetooth Door Locking Mechanism

Activity DiagramThe basic control flow of the Android application is straightforward as to allow for a simple interface for the user. The functionality of the application is partitioned so that each task is separate from one another. A representation of the control flow of the application can be viewed in the Activity Diagram in Figure 4 below:

17

Page 23: Bluetooth Door Locking Mechanism

Authorize User

Read Keys

Construct Keys

Generate Random Keys

Write Keys to Memory

/~KeysSaved

Discover/Connect to Lock

Discover/Connect to User Phone

Send Begin Command

Wait for Session Token and Status

Update UI

Construct Exchange Message

Add Username/Public Key

Send to Connected Device

Construct Lock/Unlock Message

Sign with Private Key

Send to Lock

Wait for Acknowledgement

/Unsuccessful

Get Username and Public Key

Construct Add/Remove Message

Sign with Private Key

Send to Lock

Wait for Acknowledgement

/Unsuccessful

Disconnect

/Disconnect

Disconnect

/ExitApplication

/Failure

18

Page 24: Bluetooth Door Locking Mechanism

Figure 4: System Activity Diagram

This activity diagram can be thought of separating the application into each of the main tasks that it executes. The first is above the first fork and join and is the initialization of the application, which has to authorize the user of the application and acquire public and private keys for that user. After initialization is finished the user either uses the phone for administrative or basic user purposes. On the far right path of the first fork, the user connects to administrative phone to pass them their username and public key so that its cached on the admin’s phone which can be used for add and remove user commands. The path to the left of the first fork is a process requiring a connection to the lock system. Once connected to the lock system, the second fork is to the left for opening and closing the lock for either basic or administrative user. The right path of the second fork allows an administrator to add or remove an authorized user from the lock management system. Once either path disconnects, it once again has the ability to start a new task by following any of the paths at the first fork until the application is close.

The code that corresponds to the implementation for the Android application can be found in the appendix. The over control flow of the user interface follows the general model of Android applications specified by the Google framework. The user interface that allows for each of the tasks shown in the activity diagram is shown in Figure 5 below:

Figure 5: Smartphone User Interface

19

Page 25: Bluetooth Door Locking Mechanism

If it’s the first time the user has used the application then they specify the username that will be used to access the application and sent with each command to the lock system. The submit button finalizes the chose and writes the username to memory. The next time the application is used, if the username is stored in memory the text box and submit button will be removed from the user interface. Once authentication of the user is finished they connect to either the lock system or the administrators phone by using the phones menu button, which shows a list of all available devices. If connection is made with another phone then the only enabled button is the “Send Public Key to Connected Device” which allows for a key exchange between a basic and admin user. If the connection is made with the lock system then the “Lock,” “Ad Key,” “Remove Key” buttons and “Admin?” checkbox are enabled allowing the user to lock/unlock the door, or add/remove users from the authorized users table if its an administrator. So the user interface adapters for the user depending on the state of the program, which allows the user to better assess the functionality of the application.

Lock Control Software ImplementationWe chose to create a bare-metal (sans operating system) software application for authenticating users and controlling the servo. We utilized the library of code distributed by Texas Instruments wherever it was practical to do so. We also utilized the open-source libraries libtomcrypt and libtommath to provide cryptographic and multiple precision math functionality. The implementation is largely interrupt driven and executes various tasks in a simple round-robin fashion. A timer produces interrupts at 1 ms intervals and is used for basic timekeeping. The system functionality can be decomposed into the blocks shown in Figure 6.

20

Page 26: Bluetooth Door Locking Mechanism

Lock Control

User Authentication

Command Parsing RFID Monitoring

MessageHashing

SignatureVerification

PWM Generation

User DatabaseManagement

User Lookup Add User Remove User

Random Number

Generator

Figure 6: Functional decomposition of the lock control system.

The top level functional block is responsible for initializing the system and required peripherals and providing the basic framework for the other functional blocks to operate. It integrates information provided by the command parser and RFID blocks, and subsequently controls the PWM generator (to actuate the lock servo). It is mostly implemented in the file main.c. After initialization, it enters an infinite loop, where each subsidiary functional block is either directly implemented or handled by a function call. At the conclusion of each pass through the loop, the processor is put into a low-power sleep mode until it is woken by an interrupt. The source of the interrupt may be UART activity, or the periodic timer.

The Command Parsing block comprises the largest body of code in the project. It is responsible for parsing commands received via Bluetooth, authenticating the sender, and taking the appropriate action in response to the command. Some parts of the implementation of this block reside in main.c, but most is in parser.c. Whenever data is received by the Bluetooth transceiver, it is sent to UART1, which causes an interrupt. The UART1 ISR moves the data to a ring buffer (RxBuff) and sets a flag to indicate new data has been received. Each time through the main loop, this flag is checked and if set, command parsing is initiated by calling the Parse() function.

The Parse() function returns different values which fall into 3 broad categories: values indicating a valid command has been received and some action should be taken, values indicating an invalid or unauthorized command has been received, or a value indicating the parser must wait for additional bytes to be received. The last possibility was necessary because of our chosen command protocol. Parsing the commands would have been much simpler if we could buffer an entire command and

21

Page 27: Bluetooth Door Locking Mechanism

process it all at once. However, the combination of variable command length, combined with the use of “binary” data transmission prevented us from knowing when the entire command had been received, without actually parsing at least part of it. (“Binary” data transmission means we were transmitting randomly distributed bytes, which could not be interpreted as ASCII characters. This precluded using particular characters to signal the end of the command, because any of the 256 possibilities could appear in these “binary” data sections.)

Whenever an invalid command is received, an error message indicating this fact is transmitted over the Bluetooth connection. However, because we parsed each byte as it was received, we might identify an invalid command before the sender was finished sending it. If the parser logic was immediately reset, it would regard the following bytes as a new command--also invalid--and would cause even more error messages. This is prevented by the use of a 1 s waiting period following the receipt of any invalid command, during which all command parsing is disabled and all received data is discarded. The waiting period begins after the last byte is received, and if a new byte is received during the waiting period, it is extended to 1 s from that point.

The User Authentication block is responsible for preventing unauthorized individuals from controlling the lock and is primarily implemented in parser.c. The authentication process starts with the receipt of an unauthenticated <BEGIN> command. The Lock Control system responds by supplying a random session token, which must be included in future authenticated commands. (This prevents valid, signed command messages from being replayed by an attacker in the future.) After commands are received the user must be authenticated by hashing the body of the command and verifying the signature with the user’s public key.

The Random Number Generator is a combination of software and special hardware. One GPIO pin, PC5, is configured as an output, and periodic timer interrupts are used to generate a square wave output on PC5. A second GPIO pin, PC7, is configured as an input and the two pins are bridged by the RC network shown in Figure 7. The PC7 pin is configured to generate an interrupt whenever it detects a changed state. The exact time required for the input (PC7) to register a changed state after the output (PC5) has changed varies randomly about a mean or expected value. A second periodic timer runs as fast as possible and its value is read whenever PC7 generates an interrupt. The lower 8 bits of the timer’s value, read at these somewhat random intervals, are random and uniformly distributed. This system produces 50 bytes of random data per second. 64 bytes of random data are required in order to respond to the <BEGIN> command, so random data is buffered in advance into a ring buffer (EntropyRB) so it is immediately available when needed.

The Message Hashing block is primarily implemented in libtomcrypt. The library functions sha1_init(), sha1_process(), and sha1_done() are called during the parsing process to facilitate the hash calculation. Likewise, the Signature Verification block is primarily implemented by the same library, as well as libtommath. The latter library is necessary for converting a byte array into the very large integer representing the public modulus, which is used by the RSA algorithm to verify the user’s digital signature. After the body and signature of a command have been parsed, the function rsa_verify_hash_ex() is called to actually verify the user’s digital signature.

22

Page 28: Bluetooth Door Locking Mechanism

The User Database Management block is responsible for adding and removing user records from the database and retrieving the stored information when needed. The major components of this block are implemented in userdb.c. The user information is stored in the non-volatile flash memory available on the Stellaris microcontroller. The linker script main.ld was modified to prevent executable code from being programmed into the last 64 kB of flash, so this could be used for database storage. The flash memory must be erased (which sets all bits to 1) before it can be programmed (which can only cause a bit to be set to 0). The flash can only be erased in 1024 byte blocks, so it was convenient to allocate one user record to each 1024 byte erase block. When a user record is stored, the target flash location is first erased with FlashErase(), then programmed with FlashProgram(), both functions from the LM3S8962 library.

Besides the actual user data, metadata must be also be stored to indicate which locations in flash hold valid user records, and where new records should be placed (to facilitate wear leveling). The application code (which is static) must always know where to find this metadata in flash after power-up. However, because the memory must be erased before it is programmed, if we were to simply write the metadata to the same area of the flash everytime, there would be a short window when there was no valid metadata anywhere in flash. If a reset, power failure, or system fault occurred during this window, all user data would be lost. The LM3S8962 includes the Flash Parameter Block module which is specifically intended to address this problem, and we chose to use the provided functions FlashPBInit(), FlashPBSave(), and FlashPBGet() for storing the metadata. This module uses a range of flash addresses and stores new data in a different location, before erasing the old data location. A system of sequence numbers and checksums is used so, after power-up, the system can determine where the most recent parameter block is stored within the aforementioned range of flash addresses.

The Add User block is responsible for storing user records in the database. The block is encapsulated in the StoreUserRec() function. The function first searches for an existing and identical user record in the database, and does nothing if it finds one. If no matching user records are found, the function checks the metadata to find the next available erase block in flash where it can store the new record. After programming the new record to flash, the metadata parameter block is updated to reflect the change. If it finds a record with matching username and public key, but different permissions, the new record is stored and the old record is marked as invalid in the metadata. This last case provides the mechanism for changing user permissions.

The Remove User block takes care of removing old user records, to prevent the user from continuing to use the lock. This block is encapsulated by the RemoverUserRec() function. It searches the database for a valid user record with identical username and public key. If it finds one, it updates the metadata parameter block to mark the record as invalid.

When a command is received, the user’s record must be retrieved, and this is the responsibility of the User Lookup block. The lookup is accomplished by performing an exhaustive search of all valid user records, to find all records matching the user name. Because there is no provision to prevent duplicate user names, users can only be uniquely identified by their public keys. (There are provisions to prevent user records with both identical usernames and identical public keys.) If two or more users are found

23

Page 29: Bluetooth Door Locking Mechanism

with the same name, the Message Hashing block will try each matching user record until it finds one whose public key can be used to validate the command’s signature.

When the system is powered on, we call the function CheckForAdmin() which scans the user database for valid administrator accounts. (Users with the admin permission bit set may add and remove other user records.) If no valid administrator accounts are found, then a hard-coded default user account with administrative priviledges is added to the user database. The credentials (user name and private key variables) necessary to use this account would be distributed with new lock control systems, to allow the new owner to initially control the system and to add users. After adding a new administrative user, the default account could them be removed to ensure system security. If at a later date, the administrator accidentally deleted himself and all other administrative accounts, the default user account would be re-added after the next system reset so the system would still be usable.

The RFID block is implemented as an interrupt service routine (ISR) (see UART0IntHandler() in main.c), a code section in the main loop, and the function is_rfid_valid(). The ISR is executed whenever information is available on the receive FIFO of UART0. It places the received bytes onto a software buffer (RFIDbuffer) and sets a global flag when this buffer is full. This global flag is checked every pass through the main loop; and, if it is set, the function is_rfid_valid() is called to determine if the RFID matches the one associated with this lock control device. If it is the correct the RFID tag, the state of the lock is toggled. Because the RFID tag is intended only to be a backup method for controlling the lock, the correct identification number is hard-coded into the application. Ideally, a dynamic database of RFID tag numbers would be implemented, but we were not able to accomplish this within our time constraints.

The pulse width modulated (PWM) output is used to control the position of the servo which manipulates the deadbolt handle. The PWM block is responsible for creating this output. It is implemented in pwm.c and consists of two functions: pwm_init() and PWM¬_Change(). The first function is called once after power-up and initializes the PWM peripheral module. The servo requires pulses at 50 Hz with the high time varying between about .6 and 2.6 ms, depending on the desired position. The latter function is called whenever it is necessary to lock or unlock the door. It accomplishes this by switching the high time between two preset values, which were determined by trial and error to be appropriate for locking and unlocking the door.

24

Page 30: Bluetooth Door Locking Mechanism

Hardware Implementation

Hardware Schematic

Figure 7: Overall System Hardware Schematic

Much of the hardware used in this project had to be supplemented with software support so some of the software implementation discussed in the Hardware Implementation section will supplement this discussion. Modules such as the RFID reader and Bluetooth modules had process chips, which allowed the Stellaris board to communicate to each device over a UART communication channel. So, each of the inputs and output of these mentioned about has a serial communication made by pressing bits over the connection.

RFID ReaderThe RFID reader module is the Innovations ID-12 module, which communicates over UART connection. The UART communication was established using the boards UART0 connection, configured to a baud rate of 9600, which is specified by the data sheet of the RFID reader. When the RFID card is placed above the reader the card is power just enough to send a 32-bit binary signal. That signal is read by the module on the RFID reader board and sent via UART to the UART0 Rx pin of the Stellaris board. Once the board receives a signal on this pin it triggers an interrupt, which processes the 32-bit number. The RFID reader did not require any configuration as the default settings are relevant to the configuration used in this project.

Bluetooth ModuleThe Bluetooth module consisted of the JY-MCU BC417, which had a UART module that allowed all interaction with the module to be a serial communication. The UART connection was made with the UART1 Tx and Rx pins of the Stellaris board. An additional pin on the Bluetooth module labeled KEY could be set to Vcc, and allowed for AT configuration commands to be sent and processed. So before integrating the module into the system the configuration setting were changed so that the baud rate was 115,200 and the advertised Bluetooth name was “LCON2.” At this baud rate the information coming over Bluetooth could be processed fast enough by the Stellaris board before there was any overflowing

25

Page 31: Bluetooth Door Locking Mechanism

buffer problems on the Bluetooth module. By using the UART interface to the Bluetooth module interaction was straight forward in the fact that it was like writing directly to the Android device.

ServoThe servo used for this project was the TowerPro SG-5010, which is a powerful servo that was calibrated to have high enough torque to turn the deadbolt lock. The servo works by having 3 connections, a ground, power and control connection. The control connection is used to send a pulse width modulated signal that tells the servo which position to be in. The Stellaris board had support for pulse width modulation and was configured on pin PW2 for this project. The datasheet for the servo specified that the period between pulses is 20ms and that the widths vary between 1 and 2 ms for the full 180-degree rotation. After experimentation of the servo this range was found to actually be between 0.6 and 2.3 ms to have the servo turn the 180 degrees. The Stellaris board PWM output was then configured to output these specified values. Once the servo was attached to the lock mechanism it was calibrated so that it could turn between the locked and unlocked positions. The lock and unlocked positions were at the 0.9ms and 2.2ms pulse width, which was used in the software manipulation of the Stellaris board to change between the two states.

TI Stellaris Development BoardThe Stellaris board was mainly using in the software implementation of the project as the hardware is configure to work with the board and software loaded onto it. To get the pulse width modulator pin to output the correct period and pulse width to the servo a pulse generator module on the board had to be started and configure for the correct frequency. The UART connection had to also be configured to use the correct baud rate of the connected modules. Interrupts were configured so that signals coming into the pins were intercepted and processed by the board.

Random Number GeneratorThe implementation of the random number generator uses a 100 Kohm resistor and 0.1 micro Farad capacitor as shown in the schematic about. The resistor is connected across pins PC5 and PC7 on the Stellaris board and the capacitor is connected between pins PC7 and ground. Reference the Software Implementation section for a detailed description for how it works.

System Testing

Test PlanThe testing for the Safe Guard Lock System was fairly straight forward. The operation of a door lock is the main result that needs to be tested along with two other features of the system. The first test was the ability to lock and unlock the door from the Smartphone. This simply meant pushing the lock button on the smartphone, waiting for the deadbolt to lock, then pushing the unlock button on the smartphone and waiting for the deadbolt to unlock. Next the same process was performed on the RFID card. The RFID card was swiped and the state of the lock would change. The card was swiped again and the state of the lock returned to its original position. An invalid card must also be swiped to ensure the lock doesn’t change position.

26

Page 32: Bluetooth Door Locking Mechanism

Next the add and remove user feature was tested. This meant connecting two phones via Bluetooth, having the Admin device receive the user key, then the Admin device connected to the Lock, finally the Admin adds the new user to the database maintained on the lock. Next the remove user was tested by using the same key that the Admin just added, connecting to the lock, and then selecting the remove user button. These actions should remove the user from the database kept on the lock. Finally the last test was for a newly added user to open the door. The new user was added to the database via the method described above. Then the new user selects the unlock and lock buttons. These button presses should unlock and lock the deadbolt.

Test SpecificationsThe following tests must be performed:

Deadbolt Unlocked from Admin Smartphoneo When the unlock button is pushed on the smartphone app the deadbolt moves to the

unlock position Deadbolt Locked from Admin Smartphone

o When the lock button is pushed on the smartphone app the deadbolt moves to the locked position

Deadbolt Unlocked from the RFID Cardo With the deadbolt starting in the locked state the RFID card is swiped, and then the

deadbolt moves to the unlocked state Deadbolt Locked from the RFID Card

o With the deadbolt starting in the unlocked state the RFID card is swiped, and then the deadbolt moves to the locked state

Deadbolt does not Operate with Invalid RFID Cardo With the deadbolt in any state an invalid RFID card is swiped, and the lock does not

change state Add New User Feature

o Connection from the Admin’s device to the new user’s device is made, and the new user’s key is passed to the Admin’s device

o The Admin connects with the lock, pushes the add button, and adds the new user to the database

New User can Unlock the Deadbolto After being added to the database the new user pushes the unlock button, and the

deadbolt moves to the unlocked state New User can Lock the Deadbolt

o After being added to the database the new user pushes the lock button, and the deadbolt moves to the locked state

Removing a User Feature

27

Page 33: Bluetooth Door Locking Mechanism

o Connection from the Admin’s device to the user’s device that is to be removed is made, and that user’s key is passed to the Admin’s device

o The Admin connects with the lock, pushes the remove button, and removes the user from the database

Test CasesBelow is a list of test cases and the test procedure explaining how to test each case.

Test Case Test ProcedureDeadbolt Unlocked from Admin Smartphone 1. Power on system and smartphone

2. If smartphone is not paired with lock due so now

3. Launch Safe Guard Lock App4. Connect to lock5. Press unlock button

Deadbolt Locked from Admin Smartphone 1. Power on system and smartphone2. If smartphone is not paired with lock due

so now3. Launch Safe Guard Lock App4. Connect to lock5. Press lock button

Deadbolt Unlocked from RFID Card 1. Power on system2. Set lock to locked state3. Hold Valid RFID Card to reader

Deadbolt Locked from RFID Card 1. Power on system2. Set lock to unlocked state3. Hold Valid RFID Card to reader

Deadbolt doesn’t Operate with Invalid RFID Card

1. Power on the system2. Hold Invalid RFID to reader

Add New User to Database 1. Connect new user and admin devices via Safe Guard Lock app

2. New user enters user name3. New user sends key to Admin4. Disconnect devices5. Admin connects to lock6. Admin pushes add user button

New User Unlock Deadbolt 1. Power on system2. New user connects to lock3. New user selects the unlock button

New User Lock Deadbolt 1. Power on system2. New user connects to lock3. New user selects the lock button

28

Page 34: Bluetooth Door Locking Mechanism

Remove User from Database 1. Connect user and admin devices via Safe Guard Lock app

2. User sends key to Admin3. Disconnect devices4. Admin connects to lock5. Admin pushes remove user button

Results

Presentation of ResultsWe built the prototype device shown in Figure 8 below to demonstrate and test our design. The servo was powered by a bench power supply, and the control signal was driven by the PWM output from the Stellaris board as described above. We had two RFID cards, only one of which had its ID number programmed into the Lock Control application. We tried waving both cards in front of the reader. Both cards were picked up by the reader (confirmed by a loud beep from the reader), but only the correct one would cause the door to be locked or unlocked. This worked very reliably, and confirms both that the RFID related code as well as the PWM/servo control code worked as designed.

Figure 8: Prototype lock actuating mechanism

29

Page 35: Bluetooth Door Locking Mechanism

We installed the android app on several phones and tested their performance. One of these phones was configured to use the default administrator account (see the Software Implementation section) and it was able to successfully lock and unlock the door. This confirms that our design was sound, and that all the authentication steps were working correctly (at least some of the time.) In order for the phone to exercise control over the lock in this way, many things must work simultaneously: the random session token is being stored by the phone and included in the subsequent commands, the command message is being hashed successfully on both devices, the phone is successfully encrypting the hash with the private key, the Lock Control system is successfully parsing the command and retrieving the user record from the database, and the Lock Control system is successfully decrypting the signature using the user’s public key.

We were also able to successfully generate private/public key pairs for new users using the android app, and to transfer the user name and public key to the phone with the admin user. In turn, we successfully used the android app to add and remove the new user record to the Lock Control system database. Using some debugging code, we were able to print the stored user records to a computer terminal and confirm that the user records were being storing correctly in the database. However, we could not get the phones with these new user accounts to actually control the lock. The Lock Control system would fail to verify the signature on messages received from these new users. This is detailed in the Error Analysis section, and unfortunately we didn’t have sufficient time to troubleshoot the problem further.

Analysis of ErrorsIn the result of this project there were two errors that persisted that was not fixed by the deadline of the project. The first was that about every 1 in 10 transactions of the randomly generated session token from the lock management system to the Android device was corrupted by noise, which caused the session token to become invalid and any command sent after that point was not authenticated by the lock management system. So the general process that created the error was a phone connected to the lock management system. Once the phone send the begin command the lock management system acknowledges by sending a begin acknowledge command with the status of the lock system and a random session token to be used with each command. When the phone receives this command it parses the information and stores the session token so that it can be used for future commands. In the transaction the session token gets corrupted so when it’s used for future commands both the session token and signature are invalid and that is expressed by the lock management system among parsing and sends a failure command to the phone. If the user then disconnects from the lock management system and reconnects, this process starts once again and a new session token is produced. And the commands sent from the phone then are verified as successful by the lock management system. This type of error could have been caused by other devices in the lab, as there are other Bluetooth devices being used by the other groups in the class. This could have also been caused by a difference in exchange rate as Bluetooth transfer rates are in the mega baud spectrum and the UART that pushes the Bluetooth information is at 115,200 baud, but the Bluetooth module’s buffer is very large to where successful transfer of 6 KB was done.

30

Page 36: Bluetooth Door Locking Mechanism

The second error that was still present in the project at the time of the deadline was that a new user’s public key and username could be added and removed from the database of authorized users, but the users added couldn’t gain the permissions to unlock and lock the system. To combat the problem it was verified that upon receiving the add user command that the lock management system was successful in writing the new user’s data into flash memory, as the data read after the write was confirmed to be correct. A similar procedure was done to make sure that the user could be removed from the system by making sure the valid bit in the table of authorized users was set to false. Also for comparison at the beginning of the lock management program, if there are no authorized users in the authorized table then a default key is added to the database. Commands that came from that user was processed through the database as any other user would be and was verified as an authorized user that could open or close the lock. So with this insight it was believed that the error might be in the signature of the message being produced on the Android application. Upon further investigation it was found that the lock system was not verifying the message being it was an invalid signature, but the problem could not be found on the Android side. The process of signing a message using the default admin key and an ordinary user was identical so it wasn’t clear what was causing the problem.

Other than these two problems the system had the functionality that was specified in the system description and produced what’s described in the Presentation, Discussion and Analysis of Results section.

Bill of MaterialsName Manufacturer Part Number Unit Price Quantity Net PriceStellaris Evaluation Board TI LM3S8962 89 1 89RFID Starter Kit Sparkfun RTL-09875 49.95 1 49.95Bluetooth Module Vetco jy-mcu bt_board V1.03 14.95 1 14.95Servo - Large Sparkfun ROB-09064 12.95 1 12.95Galaxy S Facinate Samsung/Google Android SCH-I500 189.99 1 189.990.1μF Ceramic Capacitor 0.2 1 0.21% Resistor 0.1 1 0.1

Total Price357.14

SummaryFor our final project, we designed and prototyped a system for controlling a deadbolt door lock with a Bluetooth equipped Android smartphone as well as a backup system utilizing a RFID card. The system consisted of an Android app installed on a smartphone, a LM3S8962 Stellaris development board, a RFID tag reader, a Bluetooth transceiver, and a servo motor. The system was secured with randomly generated session tokens and digital signatures utilizing the SHA1 one-way hash function coupled with RSA private-public key encryption.

31

Page 37: Bluetooth Door Locking Mechanism

The Android app was able to lock or unlock the door by communicating with the Lock Control system over a wireless Bluetooth connection. The app was able to generate private/public key pairs for new users and to transmit these to the administrator’s smartphone. The administrator was, it turn, able to add these new user credentials to the Lock Control system’s user database or delete them from the same. Although the design called for these newly added users to be able to lock or unlock the door just as the administrator could, the prototype device failed to function correctly in this way, nor could this be corrected during the time allotted for the project. The RFID card associated with the Lock Control system was able to lock or unlock the door as designed, while the other RFID card was disallowed from controlling the lock, also in accordance with our design.

ConclusionAlthough some aspects of our project did not come to fruition or work correctly, we found that our design was basically sound, and we are confident that the remaining bugs could be corrected if given sufficient time. The system was constructed of readily available components and utilized the popular and common Android smartphone platform. We expect that the app could be ported to other smartphone platforms without much difficulty. Most of the heavy-lifting in the software implementation was done by freely-available and open source software libraries. Libraries designed for use with modern operating systems on x86 hardware were reconfigured and built for a bare-metal ARM system with little difficulty (although there was a steep learning-curve for the tools involved.)

From this experience we conclude that it is easily within the reach of the average electronics hobbyist to build a similar system for controlling their locks without physical keys, and to be confident that such a system is equally secure as existing common locks (probably more secure). Further, we conclude that a commercial version could be easily produced and marketed without any new technology development. The widespread availability of such a system would relieve individuals of the necessity to carry many physical keys with them, and it would make keyed access much easier to manage for large organizations. The authentication mechanism we used is based on the OpenPGP standard, and could be used in many different situations to authenticate users. Essentially, any place a username and password is currently used, public/private key system could be used to provide even greater security, with much more convenient access. This means our system could be part of a revolution in access and authentication which would greatly improve the lives of many people.

32

Page 38: Bluetooth Door Locking Mechanism

Appendix

Appendix A Android Application Code

Appendix A1 (DeviceListActivity.java)/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */

package com.example.android.BluetoothChat;

import java.util.Set;

//import android.R;import android.app.Activity;import android.bluetooth.BluetoothAdapter;import android.bluetooth.BluetoothDevice;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.os.Bundle;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.view.Window;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.ArrayAdapter;import android.widget.Button;import android.widget.ListView;import android.widget.TextView;

/** * This Activity appears as a dialog. It lists any paired devices and * devices detected in the area after discovery. When a device is chosen * by the user, the MAC address of the device is sent back to the parent * Activity in the result Intent. */

public class DeviceListActivity extends Activity { // Debugging private static final String TAG = "DeviceListActivity"; private static final boolean D = true;

// Return Intent extra public static String EXTRA_DEVICE_ADDRESS = "device_address";

// Member fields private BluetoothAdapter mBtAdapter; private ArrayAdapter<String> mPairedDevicesArrayAdapter; private ArrayAdapter<String> mNewDevicesArrayAdapter;

@Override protected void onCreate(Bundle savedInstanceState) {

33

Page 39: Bluetooth Door Locking Mechanism

super.onCreate(savedInstanceState);

// Setup the window requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); setContentView(R.layout.device_list);

// Set result CANCELED incase the user backs out setResult(Activity.RESULT_CANCELED);

// Initialize the button to perform device discovery Button scanButton = (Button) findViewById(R.id.button_scan); scanButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { doDiscovery(); v.setVisibility(View.GONE); } });

// Initialize array adapters. One for already paired devices and // one for newly discovered devices mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name); mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);

// Find and set up the ListView for paired devices ListView pairedListView = (ListView) findViewById(R.id.paired_devices); pairedListView.setAdapter(mPairedDevicesArrayAdapter); pairedListView.setOnItemClickListener(mDeviceClickListener);

// Find and set up the ListView for newly discovered devices ListView newDevicesListView = (ListView) findViewById(R.id.new_devices); newDevicesListView.setAdapter(mNewDevicesArrayAdapter); newDevicesListView.setOnItemClickListener(mDeviceClickListener);

// Register for broadcasts when a device is discovered IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); this.registerReceiver(mReceiver, filter);

// Register for broadcasts when discovery has finished filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); this.registerReceiver(mReceiver, filter);

// Get the local Bluetooth adapter mBtAdapter = BluetoothAdapter.getDefaultAdapter();

// Get a set of currently paired devices Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();

// If there are paired devices, add each one to the ArrayAdapter if (pairedDevices.size() > 0) { findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE); for (BluetoothDevice device : pairedDevices) { mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress()); } } else { String noDevices = getResources().getText(R.string.none_paired).toString(); mPairedDevicesArrayAdapter.add(noDevices); } }

@Override protected void onDestroy() { super.onDestroy();

// Make sure we're not doing discovery anymore if (mBtAdapter != null) { mBtAdapter.cancelDiscovery(); }

// Unregister broadcast listeners

34

Page 40: Bluetooth Door Locking Mechanism

this.unregisterReceiver(mReceiver); }

/** * Start device discover with the BluetoothAdapter */ private void doDiscovery() { if (D) Log.d(TAG, "doDiscovery()");

// Indicate scanning in the title setProgressBarIndeterminateVisibility(true); setTitle(R.string.scanning);

// Turn on sub-title for new devices findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE);

// If we're already discovering, stop it if (mBtAdapter.isDiscovering()) { mBtAdapter.cancelDiscovery(); }

// Request discover from BluetoothAdapter mBtAdapter.startDiscovery(); }

// The on-click listener for all devices in the ListViews private OnItemClickListener mDeviceClickListener = new OnItemClickListener() { public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) { // Cancel discovery because it's costly and we're about to connect mBtAdapter.cancelDiscovery();

// Get the device MAC address, which is the last 17 chars in the View String info = ((TextView) v).getText().toString(); String address = info.substring(info.length() - 17);

// Create the result Intent and include the MAC address Intent intent = new Intent(); intent.putExtra(EXTRA_DEVICE_ADDRESS, address);

// Set result and finish this Activity setResult(Activity.RESULT_OK, intent); finish(); } };

// The BroadcastReceiver that listens for discovered devices and // changes the title when discovery is finished private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction();

// When discovery finds a device if (BluetoothDevice.ACTION_FOUND.equals(action)) { // Get the BluetoothDevice object from the Intent BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // If it's already paired, skip it, because it's been listed already if (device.getBondState() != BluetoothDevice.BOND_BONDED) { mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress()); } // When discovery is finished, change the Activity title } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { setProgressBarIndeterminateVisibility(false); setTitle(R.string.select_device); if (mNewDevicesArrayAdapter.getCount() == 0) { String noDevices = getResources().getText(R.string.none_found).toString(); mNewDevicesArrayAdapter.add(noDevices); } }

35

Page 41: Bluetooth Door Locking Mechanism

} };

}

Appendix A2 (BluetoothChatService.java)/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */

package com.example.android.BluetoothChat;

import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.util.UUID;

import android.bluetooth.BluetoothAdapter;import android.bluetooth.BluetoothDevice;import android.bluetooth.BluetoothServerSocket;import android.bluetooth.BluetoothSocket;import android.content.Context;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.util.Log;

/** * This class does all the work for setting up and managing Bluetooth * connections with other devices. It has a thread that listens for * incoming connections, a thread for connecting with a device, and a * thread for performing data transmissions when connected. */public class BluetoothChatService { // Debugging private static final String TAG = "BluetoothChatService"; private static final boolean D = true;

// Name for the SDP record when creating server socket private static final String NAME_SECURE = "BluetoothChatSecure"; private static final String NAME_INSECURE = "BluetoothChatInsecure";

// UUID's for serial port bluetooth connections private static final UUID MY_UUID_SECURE = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); private static final UUID MY_UUID_INSECURE = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

// Member fields private final BluetoothAdapter mAdapter; private final Handler mHandler; private AcceptThread mSecureAcceptThread; private AcceptThread mInsecureAcceptThread; private ConnectThread mConnectThread; private ConnectedThread mConnectedThread; private int mState;

36

Page 42: Bluetooth Door Locking Mechanism

// Constants that indicate the current connection state public static final int STATE_NONE = 0; // we're doing nothing public static final int STATE_LISTEN = 1; // now listening for incoming connections public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection public static final int STATE_CONNECTED = 3; // now connected to a remote device

/** * Constructor. Prepares a new BluetoothChat session. * @param context The UI Activity Context * @param handler A Handler to send messages back to the UI Activity */ public BluetoothChatService(Context context, Handler handler) { mAdapter = BluetoothAdapter.getDefaultAdapter(); mState = STATE_NONE; mHandler = handler; }

/** * Set the current state of the chat connection * @param state An integer defining the current connection state */ private synchronized void setState(int state) { if (D) Log.d(TAG, "setState() " + mState + " -> " + state); mState = state;

// Give the new state to the Handler so the UI Activity can update mHandler.obtainMessage(BluetoothChat.MESSAGE_STATE_CHANGE, state, -1).sendToTarget(); }

/** * Return the current connection state. */ public synchronized int getState() { return mState; }

/** * Start the chat service. Specifically start AcceptThread to begin a * session in listening (server) mode. Called by the Activity onResume() */ public synchronized void start() { if (D) Log.d(TAG, "start");

// Cancel any thread attempting to make a connection if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}

// Cancel any thread currently running a connection if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}

setState(STATE_LISTEN);

// Start the thread to listen on a BluetoothServerSocket if (mSecureAcceptThread == null) { mSecureAcceptThread = new AcceptThread(true); mSecureAcceptThread.start(); } if (mInsecureAcceptThread == null) { mInsecureAcceptThread = new AcceptThread(false); mInsecureAcceptThread.start(); } }

/** * Start the ConnectThread to initiate a connection to a remote device. * @param device The BluetoothDevice to connect * @param secure Socket Security type - Secure (true) , Insecure (false) */ public synchronized void connect(BluetoothDevice device, boolean secure) { if (D) Log.d(TAG, "connect to: " + device);

// Cancel any thread attempting to make a connection

37

Page 43: Bluetooth Door Locking Mechanism

if (mState == STATE_CONNECTING) { if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;} }

// Cancel any thread currently running a connection if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}

// Start the thread to connect with the given device mConnectThread = new ConnectThread(device, secure); mConnectThread.start(); setState(STATE_CONNECTING); }

/** * Start the ConnectedThread to begin managing a Bluetooth connection * @param socket The BluetoothSocket on which the connection was made * @param device The BluetoothDevice that has been connected */ public synchronized void connected(BluetoothSocket socket, BluetoothDevice device, final String socketType) { if (D) Log.d(TAG, "connected, Socket Type:" + socketType);

// Cancel the thread that completed the connection if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}

// Cancel any thread currently running a connection if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}

// Cancel the accept thread because we only want to connect to one device if (mSecureAcceptThread != null) { mSecureAcceptThread.cancel(); mSecureAcceptThread = null; } if (mInsecureAcceptThread != null) { mInsecureAcceptThread.cancel(); mInsecureAcceptThread = null; }

// Start the thread to manage the connection and perform transmissions mConnectedThread = new ConnectedThread(socket, socketType); mConnectedThread.start();

// Send the name of the connected device back to the UI Activity Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_DEVICE_NAME); Bundle bundle = new Bundle(); bundle.putString(BluetoothChat.DEVICE_NAME, device.getName()); msg.setData(bundle); mHandler.sendMessage(msg);

setState(STATE_CONNECTED); }

/** * Stop all threads */ public synchronized void stop() { if (D) Log.d(TAG, "stop");

if (mConnectThread != null) { mConnectThread.cancel(); mConnectThread = null; }

if (mConnectedThread != null) { mConnectedThread.cancel(); mConnectedThread = null; }

if (mSecureAcceptThread != null) {

38

Page 44: Bluetooth Door Locking Mechanism

mSecureAcceptThread.cancel(); mSecureAcceptThread = null; }

if (mInsecureAcceptThread != null) { mInsecureAcceptThread.cancel(); mInsecureAcceptThread = null; } setState(STATE_NONE); }

/** * Write to the ConnectedThread in an unsynchronized manner * @param out The bytes to write * @see ConnectedThread#write(byte[]) */ public void write(byte[] out) { // Create temporary object ConnectedThread r; // Synchronize a copy of the ConnectedThread synchronized (this) { if (mState != STATE_CONNECTED) return; r = mConnectedThread; } // Perform the write unsynchronized r.write(out); }

/** * Indicate that the connection attempt failed and notify the UI Activity. */ private void connectionFailed() { // Send a failure message back to the Activity Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST); Bundle bundle = new Bundle(); bundle.putString(BluetoothChat.TOAST, "Unable to connect device"); msg.setData(bundle); mHandler.sendMessage(msg);

// Start the service over to restart listening mode BluetoothChatService.this.start(); }

/** * Indicate that the connection was lost and notify the UI Activity. */ private void connectionLost() { // Send a failure message back to the Activity Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST); Bundle bundle = new Bundle(); bundle.putString(BluetoothChat.TOAST, "Device connection was lost"); msg.setData(bundle); mHandler.sendMessage(msg);

// Start the service over to restart listening mode BluetoothChatService.this.start(); }

/** * This thread runs while listening for incoming connections. It behaves * like a server-side client. It runs until a connection is accepted * (or until cancelled). */ private class AcceptThread extends Thread { // The local server socket private final BluetoothServerSocket mmServerSocket; private String mSocketType;

public AcceptThread(boolean secure) {

39

Page 45: Bluetooth Door Locking Mechanism

BluetoothServerSocket tmp = null; mSocketType = secure ? "Secure":"Insecure";

// Create a new listening server socket try { if (secure) { tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, MY_UUID_SECURE); } else { tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord( NAME_INSECURE, MY_UUID_INSECURE); } } catch (IOException e) { Log.e(TAG, "Socket Type: " + mSocketType + "listen() failed", e); } mmServerSocket = tmp; }

public void run() { if (D) Log.d(TAG, "Socket Type: " + mSocketType + "BEGIN mAcceptThread" + this); setName("AcceptThread" + mSocketType);

BluetoothSocket socket = null;

// Listen to the server socket if we're not connected while (mState != STATE_CONNECTED) { try { // This is a blocking call and will only return on a // successful connection or an exception socket = mmServerSocket.accept(); } catch (IOException e) { Log.e(TAG, "Socket Type: " + mSocketType + "accept() failed", e); break; }

// If a connection was accepted if (socket != null) { synchronized (BluetoothChatService.this) { switch (mState) { case STATE_LISTEN: case STATE_CONNECTING: // Situation normal. Start the connected thread. connected(socket, socket.getRemoteDevice(), mSocketType); break; case STATE_NONE: case STATE_CONNECTED: // Either not ready or already connected. Terminate new socket. try { socket.close(); } catch (IOException e) { Log.e(TAG, "Could not close unwanted socket", e); } break; } } } } if (D) Log.i(TAG, "END mAcceptThread, socket Type: " + mSocketType);

}

public void cancel() { if (D) Log.d(TAG, "Socket Type" + mSocketType + "cancel " + this); try { mmServerSocket.close(); } catch (IOException e) { Log.e(TAG, "Socket Type" + mSocketType + "close() of server failed", e);

40

Page 46: Bluetooth Door Locking Mechanism

} } }

/** * This thread runs while attempting to make an outgoing connection * with a device. It runs straight through; the connection either * succeeds or fails. */ private class ConnectThread extends Thread { private final BluetoothSocket mmSocket; private final BluetoothDevice mmDevice; private String mSocketType;

public ConnectThread(BluetoothDevice device, boolean secure) { mmDevice = device; BluetoothSocket tmp = null; mSocketType = secure ? "Secure" : "Insecure";

// Get a BluetoothSocket for a connection with the // given BluetoothDevice try { if (secure) { tmp = device.createRfcommSocketToServiceRecord( MY_UUID_SECURE); } else { tmp = device.createInsecureRfcommSocketToServiceRecord( MY_UUID_INSECURE); } } catch (IOException e) { Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e); } mmSocket = tmp; }

public void run() { Log.i(TAG, "BEGIN mConnectThread SocketType:" + mSocketType); setName("ConnectThread" + mSocketType);

// Always cancel discovery because it will slow down a connection mAdapter.cancelDiscovery();

// Make a connection to the BluetoothSocket try { // This is a blocking call and will only return on a // successful connection or an exception mmSocket.connect(); } catch (IOException e) { // Close the socket try { mmSocket.close(); } catch (IOException e2) { Log.e(TAG, "unable to close() " + mSocketType + " socket during connection failure", e2); } connectionFailed(); return; }

// Reset the ConnectThread because we're done synchronized (BluetoothChatService.this) { mConnectThread = null; }

// Start the connected thread connected(mmSocket, mmDevice, mSocketType); }

41

Page 47: Bluetooth Door Locking Mechanism

public void cancel() { try { mmSocket.close(); } catch (IOException e) { Log.e(TAG, "close() of connect " + mSocketType + " socket failed", e); } } }

/** * This thread runs during a connection with a remote device. * It handles all incoming and outgoing transmissions. */ private class ConnectedThread extends Thread { private final BluetoothSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream;

public ConnectedThread(BluetoothSocket socket, String socketType) { Log.d(TAG, "create ConnectedThread: " + socketType); mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null;

// Get the BluetoothSocket input and output streams try { tmpIn = socket.getInputStream(); tmpOut = socket.getOutputStream(); } catch (IOException e) { Log.e(TAG, "temp sockets not created", e); }

mmInStream = tmpIn; mmOutStream = tmpOut; }

public void run() { Log.i(TAG, "BEGIN mConnectedThread"); byte[] buffer = new byte[1024]; int bytes; // Right after establishing connection with the lock system send the begin // command so the system is aware of the connection. String startMsg = "<BEGIN>"; byte[] send = startMsg.getBytes(); write(send);

// Keep listening to the InputStream while connected while (true) { try { // Read from the InputStream bytes = mmInStream.read(buffer);

// Send the obtained bytes to the UI Activity mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer) .sendToTarget(); } catch (IOException e) { Log.e(TAG, "disconnected", e); connectionLost(); break; } } }

/** * Write to the connected OutStream. * @param buffer The bytes to write */ public void write(byte[] buffer) {

42

Page 48: Bluetooth Door Locking Mechanism

try { mmOutStream.write(buffer);

// Share the sent message back to the UI Activity mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer) .sendToTarget(); } catch (IOException e) { Log.e(TAG, "Exception during write", e); } }

public void cancel() { try { mmSocket.close(); } catch (IOException e) { Log.e(TAG, "close() of connect socket failed", e); } } }}

Appendix A3 (BluetoothChat.java)/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */

package com.example.android.BluetoothChat;

import java.io.BufferedInputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.math.BigInteger;import java.security.KeyFactory;import java.security.KeyPair;import java.security.KeyPairGenerator;import java.security.SecureRandom;import java.security.Signature;import java.security.interfaces.RSAPrivateKey;import java.security.interfaces.RSAPublicKey;import java.security.spec.RSAPrivateKeySpec;import java.security.spec.RSAPublicKeySpec;

import android.app.Activity;import android.bluetooth.BluetoothAdapter;import android.bluetooth.BluetoothDevice;import android.content.Context;import android.content.Intent;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.KeyEvent;import android.view.Menu;import android.view.MenuInflater;

43

Page 49: Bluetooth Door Locking Mechanism

import android.view.MenuItem;import android.view.View;import android.view.View.OnClickListener;import android.view.Window;import android.view.inputmethod.EditorInfo;import android.widget.Button;import android.widget.CheckBox;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import android.widget.ToggleButton;

/** * This is the main Activity that displays the current chat session. */public class BluetoothChat extends Activity {

private static byte[] mod = { (byte)0x00,(byte)0x87, (byte)0xE6, (byte)0x72, (byte)0xEA, (byte)0x38, (byte)0x82,

(byte)0x3D, (byte)0x8B, (byte)0xC0, (byte)0x2F, (byte)0x85, (byte)0xBD, (byte)0x1C, (byte)0xF2,

(byte)0x31, (byte)0x67, (byte)0x2E, (byte)0x39, (byte)0x1D, (byte)0x64, (byte)0xC4, (byte)0x53,

(byte)0x51, (byte)0x43, (byte)0x7E, (byte)0x2E, (byte)0xF0, (byte)0x42, (byte)0xA5, (byte)0xE8,

(byte)0x3C, (byte)0xAA, (byte)0x84, (byte)0xA9, (byte)0xC6, (byte)0x97, (byte)0xA6, (byte)0x90,

(byte)0xF9, (byte)0x7A, (byte)0x14, (byte)0x2E, (byte)0xCF, (byte)0xF0, (byte)0x42, (byte)0x49,

(byte)0x5A, (byte)0x5F, (byte)0x60, (byte)0x7E, (byte)0x6E, (byte)0xA2, (byte)0xB3, (byte)0x87,

(byte)0xBC, (byte)0x9E, (byte)0xBD, (byte)0x9D, (byte)0xBF, (byte)0x06, (byte)0x7F, (byte)0x9E,

(byte)0x2C, (byte)0x06, (byte)0x3B, (byte)0x84, (byte)0x4C, (byte)0xDF, (byte)0xEE, (byte)0x33,

(byte)0x76, (byte)0x3A, (byte)0xE2, (byte)0x5E, (byte)0xB3, (byte)0x58, (byte)0x3C, (byte)0x07,

(byte)0x4C, (byte)0x88, (byte)0x7B, (byte)0xA6, (byte)0xBB, (byte)0x2E, (byte)0xDF, (byte)0x25,

(byte)0x7B, (byte)0x77, (byte)0x2B, (byte)0x7D, (byte)0xF1, (byte)0xE0, (byte)0xC2, (byte)0x5D,

(byte)0xAD, (byte)0xDE, (byte)0x7F, (byte)0xD0, (byte)0x34, (byte)0xFD, (byte)0x4F, (byte)0xB0,

(byte)0x0D, (byte)0xCA, (byte)0x69, (byte)0x08, (byte)0xE9, (byte)0x03, (byte)0x0E, (byte)0x15,

(byte)0x5F, (byte)0x11, (byte)0xD2, (byte)0x66, (byte)0x36, (byte)0xD5, (byte)0xCE, (byte)0x70,

(byte)0x17, (byte)0x8E, (byte)0x01, (byte)0xF4, (byte)0x93, (byte)0x36, (byte)0x25, (byte)0xDB,

(byte)0xF3, (byte)0x43 };

private static byte[] privateExp = {(byte)0x0C, (byte)0x57, (byte)0x19, (byte)0xB2, (byte)0x39, (byte)0x05,

(byte)0x62, (byte)0x8F, (byte)0x51, (byte)0x19, (byte)0x3F, (byte)0x9C, (byte)0xA7, (byte)0x87,

(byte)0x3A, (byte)0x83, (byte)0x33, (byte)0x08, (byte)0x4E, (byte)0xA9, (byte)0xFA, (byte)0xC5,

(byte)0xD2, (byte)0x08, (byte)0x3D, (byte)0xEA, (byte)0x07, (byte)0x39, (byte)0x16, (byte)0x15,

(byte)0x9B, (byte)0x84, (byte)0xA4, (byte)0x5D, (byte)0x42, (byte)0x42, (byte)0x3D, (byte)0x06,

(byte)0xC7, (byte)0x10, (byte)0x95, (byte)0xCA, (byte)0x96, (byte)0x69, (byte)0x2B, (byte)0xAB,

(byte)0xBB, (byte)0x80, (byte)0x13, (byte)0xA4, (byte)0x07, (byte)0x69, (byte)0xD0, (byte)0xC1,

(byte)0x8F, (byte)0x98, (byte)0x1E, (byte)0x81, (byte)0xB7, (byte)0x79, (byte)0xE0, (byte)0x96,

(byte)0xBD, (byte)0x4A,

44

Page 50: Bluetooth Door Locking Mechanism

(byte)0x85, (byte)0x9C, (byte)0xE2, (byte)0x92, (byte)0x89, (byte)0x09, (byte)0xFB, (byte)0x54,

(byte)0x13, (byte)0x5B, (byte)0x5F, (byte)0x3B, (byte)0x3D, (byte)0x03, (byte)0xA7, (byte)0x12,

(byte)0x86, (byte)0xA9, (byte)0x67, (byte)0xDB, (byte)0x2A, (byte)0x0C, (byte)0x36, (byte)0x2C,

(byte)0x8D, (byte)0xBB, (byte)0xA0, (byte)0xCB, (byte)0xE9, (byte)0x18, (byte)0x4C, (byte)0xC3,

(byte)0xC0, (byte)0xAD, (byte)0x45, (byte)0xCC, (byte)0x88, (byte)0xC8, (byte)0x76, (byte)0x78,

(byte)0x1C, (byte)0x58, (byte)0xAD, (byte)0xD7, (byte)0xCA, (byte)0x17, (byte)0xFB, (byte)0x82,

(byte)0x9A, (byte)0xC9, (byte)0xB1, (byte)0x4E, (byte)0xF9, (byte)0xC8, (byte)0x9A, (byte)0x62,

(byte)0x2A, (byte)0x30, (byte)0xBB, (byte)0xAF, (byte)0xCB, (byte)0xB9, (byte)0xB9, (byte)0x01 };

private static byte[] publicExp = { (byte)0x01, (byte)0x00, (byte)0x01 };

boolean SECURE = true;boolean GENERATE_KEYS = true;boolean USE_ADMIN_NAME = false;

// Debugging private static final String TAG = "BluetoothChat"; private static final boolean D = true;

// Message types sent from the BluetoothChatService Handler public static final int MESSAGE_STATE_CHANGE = 1; public static final int MESSAGE_READ = 2; public static final int MESSAGE_WRITE = 3; public static final int MESSAGE_DEVICE_NAME = 4; public static final int MESSAGE_TOAST = 5;

// Key names received from the BluetoothChatService Handler public static final String DEVICE_NAME = "device_name"; public static final String TOAST = "toast"; private boolean UserNameProvided = false; // Name of the file with stored user data public static final String FILE_NAME = "user_data"; // User name public static String userName = "Dick Dangle"; // User password public static String userPW = "Titties"; private static KeyPair keys = null; // User public key public static RSAPublicKey publicKey = null; // User private key public static RSAPrivateKey privateKey = null;

// Intent request codes private static final int REQUEST_CONNECT_DEVICE_SECURE = 1; //private static final int REQUEST_CONNECT_DEVICE_INSECURE = 2; private static final int REQUEST_ENABLE_BT = 3;

// Layout Views private TextView mTitle; private TextView mStatus; private ToggleButton mLockToggle; private Button mAddUser; private Button mRemoveUser; private Button mSendButton; private CheckBox mAdminCheckBox; private TextView mAddRemoveUserText; private TextView mAddRemoveKeyText;

45

Page 51: Bluetooth Door Locking Mechanism

private Button mUserButton; private EditText mUsernameText; private TextView mUsernameView;

// Name of the connected device private String mConnectedDeviceName = null; // Local Bluetooth adapter private BluetoothAdapter mBluetoothAdapter = null; // Member object for the chat services private BluetoothChatService mChatService = null; public static final int KEY_LENGTH = 1032; // in bits public static final int PUB_EXP_LENGTH = 3; // in bytes public static final int PRIV_EXP_LENGTH = 1024; // in bits // Command Buffer for args from lock system byte[] cmdBuffer = new byte[2*KEY_LENGTH]; int cmdIndex = 0; // Store new user add/drop key byte[] extUserKey = new byte[KEY_LENGTH/8]; String extUserName = ""; boolean extUserObtained = false; private static final int RAND_NUM_LENGTH = 64; // bytes // Store the random number given at the start of the session byte[] randNum = new byte[RAND_NUM_LENGTH];

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if(D) Log.e(TAG, "+++ ON CREATE +++");

// Set up the window layout requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); setContentView(R.layout.main); getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title);

// Set up the custom title mTitle = (TextView) findViewById(R.id.title_left_text); mTitle.setText(R.string.app_name); mTitle = (TextView) findViewById(R.id.title_right_text);

// Get local Bluetooth adapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

// If the adapter is null, then Bluetooth is not supported if (mBluetoothAdapter == null) { Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show(); finish(); return; } }

@Override public void onStart() { super.onStart(); if(D) Log.e(TAG, "++ ON START ++");

// If BT is not on, request that it be enabled. // setupChat() will then be called during onActivityResult if (!mBluetoothAdapter.isEnabled()) { Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableIntent, REQUEST_ENABLE_BT); // Otherwise, setup the chat session } else { if (mChatService == null) setupChat(); } }

46

Page 52: Bluetooth Door Locking Mechanism

@Override public synchronized void onResume() { super.onResume(); if(D) Log.e(TAG, "+ ON RESUME +");

// Performing this check in onResume() covers the case in which BT was // not enabled during onStart(), so we were paused to enable it... // onResume() will be called when ACTION_REQUEST_ENABLE activity returns. if (mChatService != null) { // Only if the state is STATE_NONE, do we know that we haven't started already if (mChatService.getState() == BluetoothChatService.STATE_NONE) { // Start the Bluetooth chat services mChatService.start(); } } }

private void setupChat() { Log.d(TAG, "setupChat()"); // Initialize the submit user button form mUserButton = (Button) findViewById(R.id.submit_username); mUsernameText = (EditText) findViewById(R.id.enter_username); mUsernameView = (TextView) findViewById(R.id.enter_username); mUserButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { SetUsername(); } });

// Initialize the send button with a listener that for click events mSendButton = (Button) findViewById(R.id.button_send); mSendButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { String pre = "<KEY_EXCHANGE:" + userName + ":"; byte[] preBytes = pre.getBytes(); byte[] pubMod = publicKey.getModulus().toByteArray(); byte[] send = new byte[preBytes.length + KEY_LENGTH/8 + 1]; System.arraycopy(preBytes, 0, send, 0, preBytes.length); System.arraycopy(pubMod, 0, send, preBytes.length, pubMod.length); send[send.length - 1] = (byte)'>';

//byte[] test = new byte[]; sendByteArrayMessage(send); } }); // Initialize the status mStatus = (TextView) findViewById(R.id.status); //mStatus.setText("Status: Waiting For Connection..."); // Initialize the Lock toggle button and add listener for click events mLockToggle = (ToggleButton) findViewById(R.id.lock_toggle); mLockToggle.setEnabled(false); mLockToggle.setOnClickListener(new OnClickListener() { public void onClick(View v) { if (mLockToggle.isChecked()) { SendLockCommand("LOCK"); } else { SendLockCommand("UNLOCK"); } } });

47

Page 53: Bluetooth Door Locking Mechanism

mAdminCheckBox = (CheckBox) findViewById(R.id.permission_checkbox); // Initialize the AddUser and RemoveUser buttons with listeners mAddUser = (Button) findViewById(R.id.add_button); mRemoveUser = (Button) findViewById(R.id.remove_button); mAddUser.setOnClickListener(new OnClickListener() { public void onClick(View v) { SendAddRemoveCmd("ADD"); } }); mRemoveUser.setOnClickListener(new OnClickListener() { public void onClick(View v) { SendAddRemoveCmd("REMOVE"); } }); mAddRemoveUserText = (TextView) findViewById(R.id.username_add_drop); mAddRemoveKeyText = (TextView) findViewById(R.id.key_add_drop); if (GENERATE_KEYS) { // Check to see if we currently have a file to read from File modFile = new File("/data/data/com.example.android.BluetoothChat/files/modulous"); byte[] modBytes = new byte[KEY_LENGTH/8]; File pubExpFile = new File("/data/data/com.example.android.BluetoothChat/files/publicExp"); byte[] pubExpBytes = new byte[PUB_EXP_LENGTH]; File privExpFile = new File("/data/data/com.example.android.BluetoothChat/files/privateExp"); byte[] privExpBytes = new byte[PRIV_EXP_LENGTH/8]; try { // Get the parameters from the stored files BufferedInputStream modBuf = new BufferedInputStream(new FileInputStream(modFile)); modBuf.read(modBytes, 0, modBytes.length); modBuf.close(); BufferedInputStream pubBuf = new BufferedInputStream(new FileInputStream(pubExpFile)); pubBuf.read(pubExpBytes, 0, pubExpBytes.length); pubBuf.close(); BufferedInputStream privBuf = new BufferedInputStream(new FileInputStream(privExpFile)); privBuf.read(privExpBytes, 0, privExpBytes.length); privBuf.close();

// Construct keysKeyFactory keyMaker = KeyFactory.getInstance("RSA");

RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(modBytes), new BigInteger(pubExpBytes));

publicKey = (RSAPublicKey)keyMaker.generatePublic(pubKeySpec);RSAPrivateKeySpec privKeySpec = new RSAPrivateKeySpec(new

BigInteger(modBytes), new BigInteger(privExpBytes));privateKey = (RSAPrivateKey)keyMaker.generatePrivate(privKeySpec);

} catch (FileNotFoundException e) { // this means the keys haven't been generated yet, so generate and store them in files GenerateKeys();

48

Page 54: Bluetooth Door Locking Mechanism

try { FileOutputStream modOS = openFileOutput("modulous", Context.MODE_PRIVATE); modOS.write(privateKey.getModulus().toByteArray()); modOS.close(); FileOutputStream pubOS = openFileOutput("publicExp", Context.MODE_PRIVATE); pubOS.write(publicKey.getPublicExponent().toByteArray()); pubOS.close(); FileOutputStream privOS = openFileOutput("privateExp", Context.MODE_PRIVATE); privOS.write(privateKey.getPrivateExponent().toByteArray()); privOS.close(); } catch (Exception e1) { e1.printStackTrace(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); //mStatus.setText("Status: Bad Things"); } catch (Exception ex) { //mStatus.setText("Status: Bad Things"); } } else { ConstructHardKeys(); }

// Initialize the BluetoothChatService to perform bluetooth connections mChatService = new BluetoothChatService(this, mHandler);

// Initialize the buffer for outgoing messages //mOutStringBuffer = new StringBuffer(""); if (USE_ADMIN_NAME) { userName = "Default Admin"; mUsernameView.setText("Default Admin"); mUsernameView.setEnabled(false);

mUserButton.setEnabled(false); } else {

//GetUsername(); try {

File usernameFile = new File("/data/data/com.example.android.BluetoothChat/files/userName");

int length = (int)usernameFile.length(); byte[] userBytes = new byte[length];

// Get the parameters from the stored files BufferedInputStream userBuf = new BufferedInputStream(new

FileInputStream(usernameFile)); userBuf.read(userBytes, 0, userBytes.length); userBuf.close(); userName = new String(userBytes); UserNameProvided = true; mUsernameView.setText(userName); mUsernameView.setEnabled(false); mUserButton.setEnabled(false); } catch (FileNotFoundException e) { // Username has not been aquired //mStatus.setText("Status: Provide a Username!!"); } catch (Exception ex) {

49

Page 55: Bluetooth Door Locking Mechanism

}

} } private void SetUsername() { String newUsername = mUsernameView.getText().toString(); if (newUsername.length() > 0) {

try { FileOutputStream userOS = openFileOutput("userName",

Context.MODE_PRIVATE); userOS.write(newUsername.getBytes()); userOS.close(); userName = newUsername; UserNameProvided = true; mUsernameView.setEnabled(false); mUserButton.setEnabled(false);

} catch (Exception ex) { }

} } private void SendAddRemoveCmd(String cmd) {

if (extUserObtained) {int size = cmd.getBytes().length +1+ userName.getBytes().length +1+

extUserName.getBytes().length +1+ extUserKey.length +1+ randNum.length;if (cmd.equals("ADD")) size += 2;byte[] encrypt = new byte[size];byte perms = (mAdminCheckBox.isChecked()) ? ((byte)0x03) : ((byte)0x01);

String pre = cmd + ":" + userName + ":" + extUserName + ":";System.arraycopy(pre.getBytes(), 0, encrypt, 0, pre.getBytes().length);System.arraycopy(extUserKey, 0, encrypt, pre.getBytes().length,

extUserKey.length);encrypt[extUserKey.length + pre.getBytes().length] = (byte)':';

int current = extUserKey.length + pre.getBytes().length + 1;if (cmd.equals("ADD")) {

encrypt[current] = perms;encrypt[current+1] = (byte)':';current += 2;

}System.arraycopy(randNum, 0, encrypt, current, randNum.length);

byte[] sig = HashAndEncrypt(encrypt);byte[] send = new byte[1 + encrypt.length + 1 + sig.length + 1];send[0] = (byte)'<';System.arraycopy(encrypt, 0, send, 1, encrypt.length);send[encrypt.length + 1] = (byte)':';System.arraycopy(sig, 0, send, encrypt.length + 2, sig.length);send[send.length - 1] = (byte)'>';

sendByteArrayMessage(send);

//mAddRemoveUserText.setText("User Name: ");//mAddRemoveKeyText.setText("User's Key: ");//extUserObtained = false;

} } // Generate a new Public and Private Key for the user private void GenerateKeys() {

50

Page 56: Bluetooth Door Locking Mechanism

try { //generate the RSA keys KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA"); gen.initialize(KEY_LENGTH, new SecureRandom()); keys = gen.generateKeyPair(); publicKey = (RSAPublicKey)keys.getPublic(); privateKey = (RSAPrivateKey)keys.getPrivate(); } catch (Exception ex) { // No such algorithm exception } } private void ConstructHardKeys() { try {

// Construct keysKeyFactory keyMaker = KeyFactory.getInstance("RSA");

RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(mod), new BigInteger(publicExp));

publicKey = (RSAPublicKey)keyMaker.generatePublic(pubKeySpec);RSAPrivateKeySpec privKeySpec = new RSAPrivateKeySpec(new BigInteger(mod),

new BigInteger(privateExp));privateKey = (RSAPrivateKey)keyMaker.generatePrivate(privKeySpec);

} catch (Exception ex) { } } // Send the lock command to the locking system private void SendLockCommand(String cmd) { if (mChatService.getState() == BluetoothChatService.STATE_CONNECTED) { String info = cmd + ":" + userName + ":"; byte[] infoBytes = info.getBytes(); byte[] encryptInfo = new byte[infoBytes.length + RAND_NUM_LENGTH]; System.arraycopy(infoBytes, 0, encryptInfo, 0, infoBytes.length); System.arraycopy(randNum, 0, encryptInfo, infoBytes.length, RAND_NUM_LENGTH); byte[] encrypt = HashAndEncrypt(encryptInfo); byte[] send = new byte[1+encryptInfo.length+1+encrypt.length+1]; send[0] = (byte)'<'; System.arraycopy(encryptInfo, 0, send, 1, encryptInfo.length); send[1+encryptInfo.length] = (byte)':'; System.arraycopy(encrypt, 0, send, 1+encryptInfo.length+1, encrypt.length); send[send.length-1] = (byte)'>'; sendByteArrayMessage(send); } } // Hash and encrypt the string, returning the result private byte[] HashAndEncrypt(byte[] str) { try { // sign the message using SHA-1 hash and RSA Signature instance = Signature.getInstance("SHA1withRSA"); instance.initSign(privateKey); instance.update(str); return instance.sign(); } catch (Exception ex) { // No such algorithm exists } return new byte[10]; }

@Override public synchronized void onPause() { super.onPause();

51

Page 57: Bluetooth Door Locking Mechanism

if(D) Log.e(TAG, "- ON PAUSE -"); }

@Override public void onStop() { super.onStop(); if(D) Log.e(TAG, "-- ON STOP --"); }

@Override public void onDestroy() { super.onDestroy(); // Stop the Bluetooth chat services if (mChatService != null) mChatService.stop(); if(D) Log.e(TAG, "--- ON DESTROY ---"); }

private void ensureDiscoverable() { if(D) Log.d(TAG, "ensure discoverable"); if (mBluetoothAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) { Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); startActivity(discoverableIntent); } }

/** * Sends a message. * @param message A string of text to send. */ private void sendByteArrayMessage(byte[] message) { // Check that we're actually connected before trying anything if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) { Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show(); return; }

// Check that there's actually something to send if (message.length > 0) { // Get the message bytes and tell the BluetoothChatService to write mChatService.write(message); } }

// The action listener for the EditText widget, to listen for the return key private TextView.OnEditorActionListener mWriteListener = new TextView.OnEditorActionListener() { public boolean onEditorAction(TextView view, int actionId, KeyEvent event) { // If the action is a key-up event on the return key, send the message if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) { String message = view.getText().toString(); sendByteArrayMessage(message.getBytes()); } if(D) Log.i(TAG, "END onEditorAction"); return true; } };

// The Handler that gets information back from the BluetoothChatService private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MESSAGE_STATE_CHANGE: if(D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1); switch (msg.arg1) { case BluetoothChatService.STATE_CONNECTED: mTitle.setText(R.string.title_connected_to);

52

Page 58: Bluetooth Door Locking Mechanism

mTitle.append(mConnectedDeviceName); GoToConnectedState(); break; case BluetoothChatService.STATE_CONNECTING: mTitle.setText(R.string.title_connecting); mLockToggle.setEnabled(false); mStatus.setText("Status: Connecting to Lock"); break; case BluetoothChatService.STATE_LISTEN: case BluetoothChatService.STATE_NONE: mTitle.setText(R.string.title_not_connected); GoToDisconnectState(); break; } break; case MESSAGE_WRITE: //byte[] writeBuf = (byte[]) msg.obj; // construct a string from the buffer //String writeMessage = new String(writeBuf); //mConversationArrayAdapter.add("Me: " + writeMessage); break; case MESSAGE_READ: byte[] readBuf = (byte[]) msg.obj; synchronized (cmdBuffer){ System.arraycopy(readBuf, 0, cmdBuffer, cmdIndex, msg.arg1); cmdIndex += msg.arg1; if (cmdBuffer[cmdIndex - 1] == (byte)('>')) { //mStatus.setText("Parsing Command"); ParseCommand(); } } break; case MESSAGE_DEVICE_NAME: // save the connected device's name mConnectedDeviceName = msg.getData().getString(DEVICE_NAME); Toast.makeText(getApplicationContext(), "Connected to " + mConnectedDeviceName, Toast.LENGTH_SHORT).show(); break; case MESSAGE_TOAST: Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST), Toast.LENGTH_SHORT).show(); break; } } }; public void GoToConnectedState() { mLockToggle.setEnabled(true); mAddUser.setEnabled(true); mRemoveUser.setEnabled(true); mSendButton.setEnabled(true); mStatus.setText("Status: Connected to Lock"); } public void GoToDisconnectState() { mLockToggle.setEnabled(false); mStatus.setText("Status: Waiting For Connection..."); mAddUser.setEnabled(false); mRemoveUser.setEnabled(false); mSendButton.setEnabled(false); } public void ParseCommand() { String msg = new String(cmdBuffer, 1, cmdIndex-2);

53

Page 59: Bluetooth Door Locking Mechanism

String[] tokens = msg.split(":"); if (tokens[0].equals("BEGINACK")) { // Update the status to the user if (tokens[1].equals("LOCKED")) { mStatus.setText("Status: System is Locked"); mLockToggle.setChecked(true); } else if (tokens[1].equals("UNLOCKED")) { mStatus.setText("Status: System is Unlocked"); mLockToggle.setChecked(false); } // Save the random number for future use try { System.arraycopy(cmdBuffer, cmdIndex - 1 - RAND_NUM_LENGTH, randNum, 0, RAND_NUM_LENGTH); } catch (Exception ex) { } } else if (tokens[0].equals("BEGIN")) { mLockToggle.setEnabled(false); mAddUser.setEnabled(false); mRemoveUser.setEnabled(false); mSendButton.setEnabled(true); } else if (tokens[0].equals("STATUS")) { // Update the status to the user if (tokens[1].equals("LOCKED")) { mStatus.setText("Status: System is Locked"); mLockToggle.setChecked(true); } else if (tokens[1].equals("LOCKED")) { mStatus.setText("Status: System is Unlocked"); mLockToggle.setChecked(false); } else if (tokens[1].equals("ADD_SUCCESS")) { mStatus.setText("Status: Key Add was Successful"); } else if (tokens[1].equals("ADD_FAILED")) { mStatus.setText("Status: Key Add was Unsuccessful"); } } else if (tokens[0].equals("KEY_EXCHANGE")) { // Add the transferred user name and key to text boxes mAddRemoveUserText.setText("User Name: " + tokens[1]); mAddRemoveKeyText.setText("User's Key: Loaded"); extUserName = tokens[1]; System.arraycopy(cmdBuffer, cmdIndex-1-(KEY_LENGTH/8), extUserKey, 0, KEY_LENGTH/8); extUserObtained = true; } else { // Unknown cmd } // Reset the index of the command buffer cmdIndex = 0; }

public void onActivityResult(int requestCode, int resultCode, Intent data) { if(D) Log.d(TAG, "onActivityResult " + resultCode); switch (requestCode) { case REQUEST_CONNECT_DEVICE_SECURE: // When DeviceListActivity returns with a device to connect if (resultCode == Activity.RESULT_OK) { connectDevice(data, true);

54

Page 60: Bluetooth Door Locking Mechanism

} break; /* case REQUEST_CONNECT_DEVICE_INSECURE: // When DeviceListActivity returns with a device to connect if (resultCode == Activity.RESULT_OK) { connectDevice(data, false); } break; */ case REQUEST_ENABLE_BT: // When the request to enable Bluetooth returns if (resultCode == Activity.RESULT_OK) { // Bluetooth is now enabled, so set up a chat session setupChat(); } else { // User did not enable Bluetooth or an error occured Log.d(TAG, "BT not enabled"); Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show(); finish(); } } }

private void connectDevice(Intent data, boolean secure) { // Get the device MAC address String address = data.getExtras() .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS); // Get the BLuetoothDevice object BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); // Attempt to connect to the device mChatService.connect(device, secure); }

@Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.option_menu, menu); return true; }

@Override public boolean onOptionsItemSelected(MenuItem item) { Intent serverIntent = null; switch (item.getItemId()) { case R.id.secure_connect_scan: // Launch the DeviceListActivity to see devices and do scan serverIntent = new Intent(this, DeviceListActivity.class); startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_SECURE); return true; case R.id.disconnect_device: // Launch the DeviceListActivity to see devices and do scan //serverIntent = new Intent(this, DeviceListActivity.class); //startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_INSECURE); //disconnect from the current device // mChatService.stop(); mChatService.start(); return true; case R.id.discoverable: // Ensure this device is discoverable by others ensureDiscoverable(); return true; } return false; }

}

55

Page 61: Bluetooth Door Locking Mechanism

Appendix B Stellaris Board Code

Appendix B1 (main.c)//*****************************************************************************// main.c - This implements most of the functionality of the lock control// system// Authors: David Chamberlain, Rob Greenewald// Date: December 7, 2012//*****************************************************************************#include <stdbool.h>#include <stddef.h>#include <stdint.h>#include "inc/hw_ints.h"#include "inc/hw_memmap.h"#include "inc/hw_types.h"#include "inc/hw_gpio.h"#include "inc/lm3s8962.h"#include "driverlib/gpio.h"#include "driverlib/interrupt.h"#include "driverlib/sysctl.h"#include "driverlib/systick.h"#include "driverlib/uart.h"#include "driverlib/timer.h"#include "drivers/rit128x96x4.h"#include "utils/ustdlib.h"#include "utils.h"#include "parser.h"#include "global.h"#include "userdb.h"#include "driverlib/debug.h"//#include "../libtomcrypt-1.17/src/headers/tomcrypt.h"#include <tomcrypt.h>//#include "custcrypt.h"#include "rfid_reader.h"#include "pwm.h"

unsigned char rbuff[512];RingBuffer RxBuff = {rbuff, sizeof(rbuff), 0, 0};

#ifdef DEBUGunsigned char tbuff0[512];RingBuffer TxBuffU0 = {tbuff0, sizeof(tbuff0), 0, 0};char debug_msg[SCREEN_COLS + 1];#endif

volatile unsigned long g_ulTickCount = 0;unsigned long ClearCount = SCREENSAVER_TIMEOUT * TICK_RATE;unsigned long InvalidCount;unsigned long RNGcount = 0;unsigned char currentRN[RANDOM_NO_LENGTH] = "1234567812345678123456781234567812345678123456781234567812345678";volatile struct { bool but_press:1; bool screen_active:1; bool rx_new:1; bool reset_parser:1; bool invalid_wait:1; bool rfid_buf_full:1;

bool is_door_locked:1; //true if door is in locked state, false if door is in unlock state} Flags = {false, false, false, true, false, false, false};// RFID Global Variableschar RFIDbuffer[16];size_t rfid_pos = 0;

unsigned char ebuff[RANDOM_NO_LENGTH*4 + 1];RingBuffer EntropyRB = {ebuff, sizeof ebuff, 0, 0};

extern UserRecord newUR;

56

Page 62: Bluetooth Door Locking Mechanism

// The error routine that is called if ASSERT() fails.#ifdef DEBUGvoid __error__(char *pcFilename, unsigned long ulLine){ char msg[SCREEN_COLS + 1]; //WakeScreenSaver(); usnprintf(msg, sizeof msg, "ERR: %s ", pcFilename); ErrorPrint(msg); usnprintf(msg, sizeof msg, "line: %d ", ulLine); ErrorPrint(msg);}#endif

// The UART interrupt handlers. (Modified TI example code.)void UART0IntHandler(void){ unsigned long ulStatus;

// Get the interrrupt status. ulStatus = UARTIntStatus(UART0_BASE, true);

// Clear the asserted interrupts. UARTIntClear(UART0_BASE, ulStatus);

// Loop while there are characters in the receive FIFO. while(UARTCharsAvail(UART0_BASE)) { // Read the next character from the UART0 and write it to the RFID // array

if(16 >= rfid_pos){

RFIDbuffer[rfid_pos] = UARTCharGetNonBlocking(UART0_BASE);rfid_pos++;

} }

// Make sure the RFID flag is set after the buffer is fullif(16 == rfid_pos){

Flags.rfid_buf_full = 0x1; }

#ifdef DEBUG while (UARTSpaceAvail(UART0_BASE) && TxBuffU0.start != TxBuffU0.end) UARTCharPut(UART0_BASE, pullRB(&TxBuffU0));#endif}

void UART1IntHandler(void){ unsigned long ulStatus; char newbyte; // Get the interrrupt status. ulStatus = UARTIntStatus(UART1_BASE, true);

// Clear the asserted interrupts. UARTIntClear(UART1_BASE, ulStatus);

if (UARTCharsAvail(UART1_BASE)) { Flags.rx_new = 1; do // Loop while there are characters in the receive FIFO. { newbyte = UARTCharGetNonBlocking(UART1_BASE); pushRB(newbyte, &RxBuff); } while(UARTCharsAvail(UART1_BASE)); }

57

Page 63: Bluetooth Door Locking Mechanism

}

// Debounce the select button: set a flag when it is pressed.#define BUT_TICKS_PER_POLL ((TICK_RATE / BUT_POLL_RATE) == 0 ? 1 : (TICK_RATE / BUT_POLL_RATE) )#define BUT_HIST_LENGTH ((BUT_DEAD_TIME * TICK_RATE) / (BUT_TICKS_PER_POLL * 1000 ))#define BUT_HIST_MASK (0xffffffff << (BUT_HIST_LENGTH > 32 ? 32 : BUT_HIST_LENGTH + 1) )void DebounceSelect(void){ // 0 == button pressed // The most recent state of the switch is the LSB static uint32_t history = 0; if ((g_ulTickCount % BUT_TICKS_PER_POLL) == 0) { history = (history << 1) | HWREGBITB(GPIO_PORTF_BASE + ADDR_MASK, 1); // In order to trigger a button pressed flag, the current reading // should be 0 and all the previous readings should be 1. if ((history | BUT_HIST_MASK) == 0xfffffffe ) { Flags.but_press = 1; } }}

// Write status information to the screenvoid PrintStatus(void){ WakeScreenSaver();#ifdef DEBUG PrintLine(__FILE__); PrintLine( __TIME__ " " __DATE__); PrintLine("UART0: " STR(UART0_BAUD) " 8n1"); PrintLine("UART1: " STR(UART1_BAUD) " 8n1");#else PrintLine("----> SafeLock <----"); PrintLine("Firmware version:"); PrintLine( __TIME__ " " __DATE__);#endif}

// Inform the screen saver of activity which should prevent the screensaver // from activating;void WakeScreenSaver(void){ if (!Flags.screen_active) { Flags.screen_active = true; WriteScreen(); } ClearCount = g_ulTickCount + SCREENSAVER_TIMEOUT * TICK_RATE;}

// Turn the screen off if nothing has happened for a while.void ScreenSaverCheck(void){ if ( Flags.screen_active && g_ulTickCount >= ClearCount ) { // clear the screen RIT128x96x4Clear(); Flags.screen_active = false; }}

// The System Tick interrupt handler is called every 1/TICK_RATE seconds. The// interrupt is cleared automatically by hardware.void SysTickIntHandler(void){ g_ulTickCount++; DebounceSelect();

58

Page 64: Bluetooth Door Locking Mechanism

// create a 25 Hz square wave output on PC5 for the random number generator if (g_ulTickCount >= RNGcount) { //TimerLoadSet(TIMER0_BASE, TIMER_A, 1500000); HWREGBITB(GPIO_PORTC_BASE + ADDR_MASK, 5) ^= 1; RNGcount = g_ulTickCount + TICK_RATE/(25*2); }}

// When the cap on PC7 charges up/down (in response to the change on PC5) it // creates a interrupt. The exact time required for this to happen varies // randomly (around a mean value), so the lower bits of the timer can be used // to generate random numbers.void GPIOCIntHandler(void){ long status; status = GPIOPinIntStatus(GPIO_PORTC_BASE, true); GPIOPinIntClear(GPIO_PORTC_BASE, status); //usnprintf(debug_msg, sizeof debug_msg, "%d\r\n", 0xff & TimerValueGet(TIMER0_BASE, TIMER_A)); //UART0StringSend(debug_msg); if (spaceRB(&EntropyRB) > 0) pushRB(0xff & TimerValueGet(TIMER0_BASE, TIMER_A), &EntropyRB);}

void ChangeLockState(bool lock){ if (lock) { PWM_Change(true); Flags.is_door_locked = true; UART1StringSend("<STATUS:LOCKED>"); } else { PWM_Change(false); Flags.is_door_locked = false; UART1StringSend("<STATUS:UNLOCKED>"); }}

void TestUserDB(void);

int main(void){ volatile unsigned long i; unsigned char parse_result;

// Set the clock to run at 50 MHz //SysCtlClockSet(SYSCTL_OSC_MAIN | SYSCTL_XTAL_8MHZ | SYSCTL_USE_PLL | SYSCTL_SYSDIV_4); // Set the clock to run at 8 MHz SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_8MHZ);

// Initialize the OLED display RIT128x96x4Init(1000000); PrintStatus();

pwm_init(); ParamBlockInit(); CheckForAdmin();

// Enable the peripherals used SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

59

Page 65: Bluetooth Door Locking Mechanism

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

// Setup GPIO pin for select button GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_1); GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

// Enable the GPIO pin for the LEDs (PF0,2,3). Set the direction as // output, and enable the GPIO pin for digital function. GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3); GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

// Setup PC5 as an output for random number generation GPIOPinTypeGPIOOutput(GPIO_PORTC_BASE, GPIO_PIN_5); GPIOPadConfigSet(GPIO_PORTC_BASE, GPIO_PIN_5, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

// Setup PC7 as an input for random number generation GPIOPinTypeGPIOInput(GPIO_PORTC_BASE, GPIO_PIN_7); GPIOPadConfigSet(GPIO_PORTC_BASE, GPIO_PIN_7, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD); GPIOIntTypeSet(GPIO_PORTC_BASE, GPIO_PIN_7, GPIO_BOTH_EDGES); GPIOPinIntEnable(GPIO_PORTC_BASE,GPIO_PIN_7); IntEnable(INT_GPIOC);

// Set GPIO A0 and A1 as UART pins. GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); GPIOPinTypeUART(GPIO_PORTD_BASE, GPIO_PIN_2 | GPIO_PIN_3);

// Configure UART0 for x baud 8-N-1 operation. UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), UART0_BAUD, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));

// Configure UART1 for x baud 8-N-1 operation. UARTConfigSetExpClk(UART1_BASE, SysCtlClockGet(), UART1_BAUD, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));

// Enable the UART interrupt. IntEnable(INT_UART0); UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT | UART_INT_TX); IntEnable(INT_UART1); UARTIntEnable(UART1_BASE, UART_INT_RX | UART_INT_RT);

TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC); TimerEnable(TIMER0_BASE, TIMER_A); // Enable processor interrupts. IntMasterEnable(); // Configure SysTick to periodically interrupt. SysTickPeriodSet(SysCtlClockGet() / TICK_RATE); SysTickIntEnable(); SysTickEnable();

//pb.text = "Testin writing to flash: 1 2 3 ... :)\r\n"; //ustrncpy(pb.text, "Testin writing to flash: 1 2 3 ... :)\r\n", 100); //FlashPBInit(0x30000, 0x30800, 128); //FlashPBSave(&pb); //pbloc = FlashPBGet(); //memcpy(pbloc, &pb, sizeof pb);

//UART0StringSend("\r\nThe initialized value of pb.text:\r\n"); //UART0StringSend(pb.text);

60

Page 66: Bluetooth Door Locking Mechanism

//FlashPBInit(0x30000, 0x30800, 128); //pbloc = FlashPBGet(); //for (i = 0; i < sizeof pb; i++) // ((unsigned char*)&pb)[i] = pbloc[i];

//UART0StringSend("\r\nNow from flash:\r\n"); //UART0StringSend(pb.text);

#ifdef DEBUG // Explain the facts. UART0StringSend("This UART can be used for output, but the input is from the RFID.\r\n"); // turn on the amber ethernet LED (because we can!) HWREGBITB(GPIO_PORTF_BASE + ADDR_MASK, 3) = 0;

#endif

// Loop forever echoing data through the UART. while(true) { if (Flags.but_press) { Flags.but_press = 0; WakeScreenSaver();#ifdef DEBUG // Toggle the green ethernet LED (PF2). HWREGBITB(GPIO_PORTF_BASE + ADDR_MASK, 2) ^= 1; TestUserDB();#endif } else { ScreenSaverCheck(); }

if (Flags.rx_new) { Flags.rx_new = 0; if (RxBuff.start != RxBuff.end) { if (Flags.invalid_wait && g_ulTickCount < InvalidCount) { do { pullRB(&RxBuff); } while(RxBuff.start != RxBuff.end);

InvalidCount = g_ulTickCount + (INVALID_TIMEOUT * TICK_RATE)/1000; } else { Flags.invalid_wait = false; parse_result = Parse(Flags.reset_parser); Flags.reset_parser = false; switch(parse_result) { case PARSER_BUSY: break;

case PARSER_INVALID: //UART1StringSend("<INVALID>"); WakeScreenSaver(); PrintLine("Invalid command"); Flags.reset_parser = true; Flags.invalid_wait = true; InvalidCount = g_ulTickCount + (INVALID_TIMEOUT * TICK_RATE)/1000; break;

61

Page 67: Bluetooth Door Locking Mechanism

case PARSER_BAD_RN: UART1StringSend("<BAD_RN>"); WakeScreenSaver(); PrintLine("Bad session token"); Flags.reset_parser = true; Flags.invalid_wait = true; InvalidCount = g_ulTickCount + (INVALID_TIMEOUT * TICK_RATE)/1000; break;

case PARSER_BAD_AUTH: UART1StringSend("<BAD_AUTH>"); WakeScreenSaver(); PrintLine("Bad authentication"); Flags.reset_parser = true; Flags.invalid_wait = true; InvalidCount = g_ulTickCount + (INVALID_TIMEOUT * TICK_RATE)/1000; break;

case PARSER_BEGIN: for (i = 0; i < sizeof currentRN; i++) { // wait for it if necessary while (EntropyRB.start == EntropyRB.end);

currentRN[i] = pullRB(&EntropyRB); } UART1StringSend("<BEGINACK:"); if (Flags.is_door_locked) UART1StringSend("LOCKED:"); else UART1StringSend("UNLOCKED:");

UART1ArraySend(currentRN, sizeof currentRN); UART1StringSend(">");#ifdef DEBUG //UART0StringSend("Sent the RN:"); //UART0ArraySend(currentRN, sizeof currentRN); //UART0StringSend(":ENDRN");#endif Flags.reset_parser = true; break; case PARSER_UNLOCK: ChangeLockState(false); WakeScreenSaver(); PrintLine("Your will prevails."); Flags.reset_parser = true; break;

case PARSER_LOCK: ChangeLockState(true); WakeScreenSaver(); PrintLine("Barred, the way is."); Flags.reset_parser = true; break;

case PARSER_TOGGLE: // Toggle the ethernet LED (PF2). HWREGBITB(GPIO_PORTF_BASE + ADDR_MASK, 2) ^= 1; Flags.reset_parser = true; break;

case PARSER_ADD_USER: if (StoreUserRec(&newUR)) { UART1StringSend("<STATUS:ADD_SUCCESS>"); } else {

62

Page 68: Bluetooth Door Locking Mechanism

UART1StringSend("<STATUS:ADD_FAILED>"); } Flags.reset_parser = true; break;

case PARSER_RM_USER: if (RemoveUserRec(newUR.name, &newUR.pub_key)) { UART1StringSend("<STATUS:REMOVE_SUCCESS>"); } else { UART1StringSend("<STATUS:REMOVE_FAILED>"); } Flags.reset_parser = true; break;

default: ASSERT(false); // should never get here } } } }

// Check to see if a RFID has been read.if(Flags.rfid_buf_full)

{ // Clear the flag and i for the buffer

Flags.rfid_buf_full = 0;rfid_pos = 0x0;// Validate the Card IDif(is_rfid_valid(RFIDbuffer)){

// If RFID is validif(Flags.is_door_locked){

// Door is locked, so unlock the door ChangeLockState(false);

}else{

// Door is unlocked, so lock the door ChangeLockState(true);

} PrintLine("RFID: Valid");

}else{// If RFID is invalid

PrintLine("RFID: No Losers Allowed");}// Clear the rfid bufferclearRFIDBuff();

}

#ifdef DEBUG while (UARTSpaceAvail(UART0_BASE) && TxBuffU0.start != TxBuffU0.end) UARTCharPutNonBlocking(UART0_BASE, pullRB(&TxBuffU0));

ErrorFlush();#endif SysCtlSleep(); }}

Appendix B2 (parser.c)#define LTM_DESC#include <stdbool.h>#include "utils/ustdlib.h"#include "parser.h"#include "utils.h"#include "global.h"#include "driverlib/debug.h"

63

Page 69: Bluetooth Door Locking Mechanism

#include <tomcrypt.h>#include <tommath.h>#include "userdb.h"

extern RingBuffer RxBuff;#ifdef DEBUGextern RingBuffer TxBuffU0;extern char debug_msg[SCREEN_COLS + 1];#endifhash_state md;unsigned char hash[20];char username[MAX_USER_LENGTH + 1] = "default"; extern unsigned char currentRN[RANDOM_NO_LENGTH];unsigned char signature[SIGNATURE_SIZE];hash_state md;ltc_math_descriptor ltc_mp;UserRecord newUR = { {0}, 0, {{0}}};

// Parse a begin commandstatic bool pBegin(unsigned char* result, bool reset){ // we expect to read in "EGIN" static const unsigned char match[] = {'E', 'G', 'I', 'N'}; static size_t pos = 0;

if (reset) pos = 0;

do { if (match[pos++] != pullRB(&RxBuff)) { *result = PARSER_INVALID; return false; } } while (RxBuff.start != RxBuff.end && pos < sizeof match);

if (pos == sizeof match) { *result = PARSER_BEGIN; return true; } else { *result = PARSER_BUSY; return false; }}

// Parse a toggle commandstatic bool pToggle(unsigned char* result, bool reset){ // we expect to read in "OGGLE" static const unsigned char match[] = {'O', 'G', 'G', 'L', 'E'}; static size_t pos = 0;

if (reset) pos = 0;

do { if (match[pos++] != pullRB(&RxBuff)) { *result = PARSER_INVALID; return false; } }

64

Page 70: Bluetooth Door Locking Mechanism

while (RxBuff.start != RxBuff.end && pos < sizeof match);

if (pos == sizeof match) { *result = PARSER_TOGGLE; return true; } else { *result = PARSER_BUSY; return false; }}

// Parse the username field and store it in name.static bool pUsername(unsigned char* result, bool reset, char* name){ static size_t pos = 0; static struct { bool name_done:1; } pf = { false };

if (reset) { pos = 0; pf.name_done = false; }

do { if (pos < MAX_USER_LENGTH) { name[pos] = pullRB(&RxBuff); // check for the delimiter if (name[pos] == ':') { sha1_process(&md, (unsigned char*)&(name[pos]), 1); name[pos++] = '\0'; pf.name_done = true; break; } // make sure it is a normal printable ASCII character else if ( name[pos] >= 32 && name[pos] <= '~' ) { sha1_process(&md, (unsigned char*)&(name[pos++]), 1); } else { PrintLine("user bad"); *result = PARSER_INVALID; return false; } } // only one valid posibility at this point else if (pullRB(&RxBuff) == ':') { sha1_process(&md, (unsigned char*)":", 1); name[pos++] = '\0'; pf.name_done = true; break; } else { *result = PARSER_INVALID; return false; } } while (RxBuff.start != RxBuff.end);

65

Page 71: Bluetooth Door Locking Mechanism

if (pf.name_done) { *result = PARSER_NAME_DONE; return true; } else { *result = PARSER_BUSY; return false; }}

// Parse the random number field and verify is the correct numberstatic bool pRandomNumber(unsigned char* result, bool reset){ static size_t pos = 0;

if (reset) pos = 0;

if (pos < RANDOM_NO_LENGTH) { do { if (currentRN[pos] != pullRB(&RxBuff)) { *result = PARSER_BAD_RN; return false; } else { sha1_process(&md, &(currentRN[pos++]), 1); }

} while (RxBuff.start != RxBuff.end && pos < RANDOM_NO_LENGTH); }

if (RxBuff.start != RxBuff.end) { if (pullRB(&RxBuff) == ':') { *result = PARSER_RN_DONE; return true; } else { PrintLine("RN bad"); *result = PARSER_INVALID; return false; } }

*result = PARSER_BUSY; return false;}

// Parse the signature field and verify the signaturestatic bool pSignature(unsigned char* result, bool reset){ static size_t pos = 0; int verified, err; ltc_mp = ltm_desc; size_t matches, i, flash_idx; static rsa_key key; static mp_int e, N;

if (reset) pos = 0;

66

Page 72: Bluetooth Door Locking Mechanism

do { signature[pos++] = pullRB(&RxBuff); } while (RxBuff.start != RxBuff.end && pos < SIGNATURE_SIZE);

if ( pos == SIGNATURE_SIZE ) { // find user records matching the name

matches = FindMatchingUsers(username); usnprintf(debug_msg, sizeof debug_msg, "Found %d matches. ", matches); PrintLine(debug_msg);

// Create the key object key.type = PK_PUBLIC; key.e = &e; key.N = &N; mp_init_multi(key.e, key.N, NULL); mp_set_int(key.e, EXPONENT);

for (i = matches; i > 0; i--) { flash_idx = GetNextMatchIdx(); mp_read_unsigned_bin(key.N, FLASH_IDX_TO_URP(flash_idx)->pub_key.C, SIGNATURE_SIZE);

if (register_hash(&sha1_desc) != CRYPT_OK) { ASSERT(false); }

err = rsa_verify_hash_ex( signature, SIGNATURE_SIZE, hash, 20, LTC_LTC_PKCS_1_V1_5, find_hash("sha1"), SALT_SIZE, &verified, &key ); if (err != CRYPT_OK) PrintLine("verify returned error");

if (verified) { *result = PARSER_SIG_DONE; return true; }

PrintLine("not verified"); }

*result = PARSER_BAD_AUTH; return false; } else { *result = PARSER_BUSY; return false; }}

// Parse a lock commandstatic bool pLock(unsigned char* result, bool reset){ static const unsigned char match[] = {'O', 'C', 'K', ':'}; static struct { bool reset_name_parser:1; bool reset_RN_parser:1; bool reset_signature_parser:1; bool name_parsed:1;

67

Page 73: Bluetooth Door Locking Mechanism

bool RN_parsed:1; bool signature_parsed:1; bool success:1; } pf = { false, false, false, false, false, false, false }; static size_t pos = 0;

if (reset) { pf.reset_name_parser = true; pf.reset_RN_parser = true; pf.reset_signature_parser = true; pf.name_parsed = false; pf.RN_parsed = false; pf.signature_parsed = false; pos = 0; sha1_init(&md); sha1_process(&md, (unsigned char*)"L", 1); }

do { if (pos < sizeof match) { if (match[pos] != pullRB(&RxBuff)) { PrintLine("command bad"); *result = PARSER_INVALID; return false; } else { sha1_process(&md, &(match[pos++]), 1); } } else if (!pf.name_parsed) { pf.success = pUsername(result, pf.reset_name_parser, username); pf.reset_name_parser = false; if (pf.success) pf.name_parsed = true; else return false; } else if (!pf.RN_parsed) { pf.success = pRandomNumber(result, pf.reset_RN_parser); pf.reset_RN_parser = false; if (pf.success) { pf.RN_parsed = true; sha1_done(&md, hash); } else return false; } else if (!pf.signature_parsed) { pf.success = pSignature(result, pf.reset_signature_parser); pf.reset_signature_parser = false; if (pf.success) pf.signature_parsed = true; else return false; }

} while (RxBuff.start != RxBuff.end && !pf.signature_parsed);

if (pf.signature_parsed)

68

Page 74: Bluetooth Door Locking Mechanism

{ *result = PARSER_LOCK; return true; } else { *result = PARSER_BUSY; return false; }}

// Parse an unlock commandstatic bool pUnlock(unsigned char* result, bool reset){ static const unsigned char match[] = {'N', 'L', 'O', 'C', 'K', ':'}; static struct { bool reset_name_parser:1; bool reset_RN_parser:1; bool reset_signature_parser:1; bool name_parsed:1; bool RN_parsed:1; bool signature_parsed:1; bool success:1; } pf = { false, false, false, false, false, false, false }; static size_t pos = 0;

if (reset) { pf.reset_name_parser = true; pf.reset_RN_parser = true; pf.reset_signature_parser = true; pf.name_parsed = false; pf.RN_parsed = false; pf.signature_parsed = false; pos = 0; sha1_init(&md); sha1_process(&md, (unsigned char*)"U", 1); }

do { if (pos < sizeof match) { if (match[pos] != pullRB(&RxBuff)) { PrintLine("command bad"); *result = PARSER_INVALID; return false; } else { sha1_process(&md, &(match[pos++]), 1); } } else if (!pf.name_parsed) { pf.success = pUsername(result, pf.reset_name_parser, username); pf.reset_name_parser = false; if (pf.success) pf.name_parsed = true; else return false; } else if (!pf.RN_parsed) { pf.success = pRandomNumber(result, pf.reset_RN_parser); pf.reset_RN_parser = false; if (pf.success) {

69

Page 75: Bluetooth Door Locking Mechanism

pf.RN_parsed = true; sha1_done(&md, hash); } else return false; } else if (!pf.signature_parsed) { pf.success = pSignature(result, pf.reset_signature_parser); pf.reset_signature_parser = false; if (pf.success) pf.signature_parsed = true; else return false; }

} while (RxBuff.start != RxBuff.end && !pf.signature_parsed);

if (pf.signature_parsed) { //UART0StringSend("\r\nThe sha1 digest is:\r\n"); //for (i = 0; i < 20; i++) { //usnprintf(debug_msg, sizeof(debug_msg), "%02x", hash[i]); //UART0ArraySend((unsigned char*)debug_msg, 2); //} //UART0StringSend("\r\n"); //UART0ArraySend(hash, 20); //UART0StringSend("\r\n");

*result = PARSER_UNLOCK; return true; } else { *result = PARSER_BUSY; return false; }}

// Parse the new key fieldstatic bool pKey(unsigned char* result, bool reset, PublicKey* newkey){ static size_t pos = 0; static struct { bool gotkey:1; bool gotzero:1; } pf;

if (reset) { pos = 0; pf.gotkey = false; pf.gotzero = false; }

do { if (!pf.gotzero) { if (pullRB(&RxBuff) == 0) { pf.gotzero = true; sha1_process(&md, (unsigned char*)&pos, 1); } else { *result = PARSER_INVALID; return false;

70

Page 76: Bluetooth Door Locking Mechanism

} } else if (pos < SIGNATURE_SIZE) { newkey->C[pos] = pullRB(&RxBuff); sha1_process(&md, &(newkey->C[pos++]), 1); } else { pf.gotkey = true; if (pullRB(&RxBuff) == ':') { sha1_process(&md, (unsigned char*)":", 1); *result = PARSER_KEY_DONE; return true; } else { *result = PARSER_INVALID; return false; } } } while (RxBuff.start != RxBuff.end && !pf.gotkey);

*result = PARSER_BUSY; return false;}

// Parse the permission fieldstatic bool pPerms(unsigned char* result, bool reset, unsigned char* perm){ static struct { bool perm_done:1; } pf = { false };

if (reset) { pf.perm_done = false; }

do { if (!pf.perm_done) { *perm = pullRB(&RxBuff); sha1_process(&md, perm, 1); pf.perm_done = true; } else if (pullRB(&RxBuff) == ':') { sha1_process(&md, (unsigned char*)":", 1); *result = PARSER_PERMS_DONE; return true; } else { *result = PARSER_INVALID; return false; } } while (RxBuff.start != RxBuff.end);

*result = PARSER_BUSY; return false;}

// Parse an ADD commandstatic bool pAdd(unsigned char* result, bool reset)

71

Page 77: Bluetooth Door Locking Mechanism

{ static const unsigned char match[] = {'D', 'D', ':'}; static struct { bool reset_Aname_parser:1; bool reset_Uname_parser:1; bool reset_key_parser:1; bool reset_perms_parser:1; bool reset_RN_parser:1; bool reset_signature_parser:1; bool Aname_parsed:1; bool Uname_parsed:1; bool key_parsed:1; bool perms_parsed:1; bool RN_parsed:1; bool signature_parsed:1; bool success:1; } pf; static size_t pos = 0; //static char* newuser[MAX_USER_LENGTH + 1]; //static unsigned char newkey[SIGNATURE_SIZE];

if (reset) { pf.reset_Aname_parser = true; pf.reset_Uname_parser = true; pf.reset_key_parser = true; pf.reset_perms_parser = true; pf.reset_RN_parser = true; pf.reset_signature_parser = true; pf.Aname_parsed = false; pf.Uname_parsed = false; pf.key_parsed = false; pf.perms_parsed = false; pf.RN_parsed = false; pf.signature_parsed = false; pos = 0; sha1_init(&md); sha1_process(&md, (unsigned char*)"A", 1); }

do { if (pos < sizeof match) { if (match[pos] != pullRB(&RxBuff)) { PrintLine("command bad"); *result = PARSER_INVALID; return false; } else { sha1_process(&md, &(match[pos++]), 1); } } else if (!pf.Aname_parsed) { pf.success = pUsername(result, pf.reset_Aname_parser, username); pf.reset_Aname_parser = false; if (pf.success) { // TODO: check that username is a valid admin pf.Aname_parsed = true; } else return false; } else if (!pf.Uname_parsed) {

72

Page 78: Bluetooth Door Locking Mechanism

pf.success = pUsername(result, pf.reset_Uname_parser, newUR.name); pf.reset_Uname_parser = false; if (pf.success) { pf.Uname_parsed = true; } else return false; } else if (!pf.key_parsed) { pf.success = pKey(result, pf.reset_key_parser, &newUR.pub_key.C); pf.reset_key_parser = false; if (pf.success) { pf.key_parsed = true; } else return false; } else if (!pf.perms_parsed) { pf.success = pPerms(result, pf.reset_perms_parser, &newUR.perm); pf.reset_perms_parser = false; if (pf.success) { pf.perms_parsed = true; } else return false; } else if (!pf.RN_parsed) { pf.success = pRandomNumber(result, pf.reset_RN_parser); pf.reset_RN_parser = false; if (pf.success) { pf.RN_parsed = true; sha1_done(&md, hash); } else return false; } else if (!pf.signature_parsed) { pf.success = pSignature(result, pf.reset_signature_parser); pf.reset_signature_parser = false; if (pf.success) pf.signature_parsed = true; else return false; }

} while (RxBuff.start != RxBuff.end && !pf.signature_parsed);

if (pf.signature_parsed) { *result = PARSER_ADD_USER; return true; } else { *result = PARSER_BUSY; return false; }}

// Parse an REMOVE command

73

Page 79: Bluetooth Door Locking Mechanism

static bool pRemove(unsigned char* result, bool reset){ static const unsigned char match[] = {'E', 'M', 'O', 'V', 'E', ':'}; static struct { bool reset_Aname_parser:1; bool reset_Uname_parser:1; bool reset_key_parser:1; bool reset_RN_parser:1; bool reset_signature_parser:1; bool Aname_parsed:1; bool Uname_parsed:1; bool key_parsed:1; bool perms_parsed:1; bool RN_parsed:1; bool signature_parsed:1; bool success:1; } pf; static size_t pos = 0;

if (reset) { pf.reset_Aname_parser = true; pf.reset_Uname_parser = true; pf.reset_key_parser = true; pf.reset_RN_parser = true; pf.reset_signature_parser = true; pf.Aname_parsed = false; pf.Uname_parsed = false; pf.key_parsed = false; pf.RN_parsed = false; pf.signature_parsed = false; pos = 0; sha1_init(&md); sha1_process(&md, (unsigned char*)"R", 1); }

do { if (pos < sizeof match) { if (match[pos] != pullRB(&RxBuff)) { PrintLine("command bad"); *result = PARSER_INVALID; return false; } else { sha1_process(&md, &(match[pos++]), 1); } } else if (!pf.Aname_parsed) { pf.success = pUsername(result, pf.reset_Aname_parser, username); pf.reset_Aname_parser = false; if (pf.success) { // TODO: check that username is a valid admin pf.Aname_parsed = true; } else return false; } else if (!pf.Uname_parsed) { pf.success = pUsername(result, pf.reset_Uname_parser, newUR.name); pf.reset_Uname_parser = false; if (pf.success) {

74

Page 80: Bluetooth Door Locking Mechanism

pf.Uname_parsed = true; } else return false; } else if (!pf.key_parsed) { PrintLine("Made it here"); pf.success = pKey(result, pf.reset_key_parser, &newUR.pub_key.C); pf.reset_key_parser = false; if (pf.success) { pf.key_parsed = true; } else return false; } else if (!pf.RN_parsed) { pf.success = pRandomNumber(result, pf.reset_RN_parser); pf.reset_RN_parser = false; if (pf.success) { pf.RN_parsed = true; sha1_done(&md, hash); } else return false; } else if (!pf.signature_parsed) { pf.success = pSignature(result, pf.reset_signature_parser); pf.reset_signature_parser = false; if (pf.success) pf.signature_parsed = true; else return false; }

} while (RxBuff.start != RxBuff.end && !pf.signature_parsed);

if (pf.signature_parsed) { *result = PARSER_RM_USER; return true; } else { *result = PARSER_BUSY; return false; }}

// Parse the incoming bytes, possibly set some flags/globals, then return a // status indicator. Assumes there is at least one byte to be read in RxBuff.// If reset is true, all parser logic is reset.unsigned char Parse(bool reset){ static struct { bool command_started:1; // we got a '<' bool command_parsed:1; // we got everything but the '>' bool command_completed:1; // we got the final '>' bool reset_func:1; // reset subsidiary functions bool success:1; } pf = {false, false, false, false};

// A set of subsidiary functions will handle the inner parts of the // commands. They will store a result in the first parameter, and will

75

Page 81: Bluetooth Door Locking Mechanism

// return true if the parsing has completed successfully. If false is // returned the parsing has failed or is incomplete and the result should // be immediately returned by Parse() without further processing. If the // second command is true, the parser logic will be reset. static bool (*switched_func)(unsigned char*, bool) = NULL;

static unsigned char result;

if (reset) { pf.reset_func = true; pf.command_started = false; pf.command_parsed = false; pf.command_completed = false; switched_func = NULL; }

// Keep parsing as long as there's stuff in the buffer, but if the command // is invalid we will break or return. do { if (!pf.command_started) { if (pullRB(&RxBuff) == '<') { pf.command_started = true; } else { return PARSER_INVALID; } } else if (!pf.command_parsed) { if (switched_func == NULL) { // Determine command type switch(pullRB(&RxBuff)) { case 'B': // a BEGIN command switched_func = pBegin; break;

case 'T': // a TOGGLE command switched_func = pToggle; break;

case 'U': // a UNLOCK command switched_func = pUnlock; break; case 'L': // a LOCK command switched_func = pLock; break;

case 'A': // a ADD command switched_func = pAdd; break;

case 'R': // a REMOVE command switched_func = pRemove; break;

default: return PARSER_INVALID; } } else {

76

Page 82: Bluetooth Door Locking Mechanism

pf.success = switched_func(&result, pf.reset_func); pf.reset_func = false; if (pf.success) pf.command_parsed = true; else return result; } } else if (pullRB(&RxBuff) == '>') pf.command_completed = true; else return PARSER_INVALID; } while (RxBuff.start != RxBuff.end && !pf.command_completed);

if (pf.command_completed) return result; else return PARSER_BUSY;}

void TestUserDB(void){ size_t i, j; UserRecord ur = {"david", 0x11, {{ 0xf9, 0xe8, 0x73, 0x61, 0x13, 0x72, 0xfd, 0x56, 0xfa, 0xdb, 0x1b, 0xb1, 0x58, 0x1c, 0x33, 0x84, 0xca, 0x65, 0x80, 0x67, 0x3b, 0x55, 0x9c, 0x0f, 0x79, 0xd1, 0xbb, 0xaf, 0xc5, 0x18, 0x00, 0xe8, 0x1b, 0xd9, 0x83, 0x02, 0x10, 0x6b, 0xfc, 0x3c, 0x34, 0xc1, 0xd1, 0x02, 0x04, 0x43, 0xc5, 0xe1, 0xc0, 0xf9, 0xdf, 0xee, 0x80, 0xbe, 0x0b, 0x53, 0xbf, 0x58, 0xc9, 0x6e, 0x45, 0xcd, 0x4e, 0x69, 0x11, 0xf0, 0x8b, 0xd6, 0xc9, 0xd5, 0x34, 0x17, 0x6c, 0x86, 0x44, 0x8c, 0xb2, 0x56, 0x53, 0x67, 0xee, 0x86, 0x57, 0xb4, 0x9d, 0x74, 0xe7, 0xbc, 0xee, 0x2b, 0x91, 0xef, 0xc4, 0x4e, 0xc3, 0xfe, 0x18, 0x95, 0xf5, 0x09, 0xdd, 0x84, 0x66, 0xc8, 0x35, 0x97, 0xc4, 0xc2, 0x80, 0x3e, 0x58, 0xf6, 0xf2, 0xc7, 0xfe, 0x3b, 0x5a, 0x52, 0xe6, 0x4c, 0x36, 0x68, 0xcc, 0x0d, 0xc5, 0x9e, 0xb7, 0xf1 }}};

//UserRecord ur = {"sam", 0x11, {{ 0xe2, 0xa5, 0xf6, 0xd5, 0x14, 0xcd, 0x96, // 0xda, 0xfa, 0xe1, 0x9b, 0x6d, 0xb4, 0x2e, 0xce, 0xa4, 0x4f, 0xa2, 0x0c, // 0x77, 0xbf, 0xcf, 0x08, 0xe6, 0x3d, 0x1c, 0x22, 0xd5, 0xad, 0xba, 0xae, // 0x97, 0xab, 0x38, 0xb2, 0xa5, 0x47, 0xed, 0x75, 0x4d, 0xf4, 0x49, 0x00, // 0x68, 0xdd, 0x78, 0x47, 0x4f, 0x6c, 0xa5, 0x4c, 0xf2, 0x15, 0x66, 0xf3, // 0xdd, 0xd8, 0x52, 0x91, 0x30, 0x61, 0xf0, 0x8d, 0xd0, 0x41, 0x01, 0x57, // 0xcc, 0xb1, 0xa3, 0x15, 0x29, 0x25, 0x23, 0x5c, 0x71, 0xfc, 0x65, 0xc9, // 0xa3, 0xc8, 0xd9, 0x23, 0x0d, 0x29, 0x10, 0xd4, 0xc1, 0xe4, 0x2e, 0x95, // 0x57, 0xff, 0x30, 0x37, 0x62, 0x8e, 0xeb, 0x94, 0xde, 0x03, 0x61, 0x68, // 0x5c, 0x77, 0x13, 0x83, 0xa0, 0x31, 0x94, 0x41, 0x09, 0x59, 0x30, 0xa9, // 0x8b, 0x55, 0x6c, 0x0d, 0xb6, 0x14, 0xc7, 0xf1, 0x45, 0xd0, 0x2f, 0x1c, // 0xfd }}};

//if (!RemoveUserRec("sam", &ur.pub_key)) //UART0StringSend("remove failed! "); //else //UART0StringSend("remove succeeded ");

//if (!StoreUserRec(&ur)) //UART0StringSend("store failed! "); //else //UART0StringSend("store succeeded ");

const UserRecord* rec_flash_loc; size_t matches, flash_idx; long num;

matches = FindMatchingUsers("Syrip"); usnprintf(debug_msg, sizeof debug_msg, "Found %d matches. ", matches); UART0StringSend(debug_msg); for (i = matches; i > 0; i--)

77

Page 83: Bluetooth Door Locking Mechanism

{ flash_idx = GetNextMatchIdx(); usnprintf(debug_msg, sizeof debug_msg, "Match at %d: ", flash_idx); UART0StringSend(debug_msg); rec_flash_loc = FLASH_IDX_TO_URP(flash_idx); UART0StringSend(rec_flash_loc->name); //UART0ArraySend(&(rec_flash_loc->perm), 1); pushRB(rec_flash_loc->perm, &TxBuffU0); //UART0ArraySend((unsigned char*)&rec_flash_loc->pub_key.C, // sizeof(rec_flash_loc->pub_key.C)); for (j = 0; j < sizeof(rec_flash_loc->pub_key.C); j++) pushRB(rec_flash_loc->pub_key.C[j], &TxBuffU0); }

usnprintf(debug_msg, sizeof debug_msg, "PB size: %d. ", sizeof(ParameterBlock)); UART0StringSend(debug_msg);}

Appendix B3 (pwm.c)// Functions for setting up the PWM module and using it to lock or unlock the // door.// Author: Mark Rathjen// Modified by David Chamberlain December 6, 2012

#include <stdbool.h>#include "global.h"#include "inc/hw_types.h"#include "driverlib/pwm.h"#include "inc/hw_gpio.h"#include "driverlib/gpio.h"#include "inc/hw_memmap.h"#include "driverlib/sysctl.h"

unsigned long upper_period, lower_period, inc_period, current_period, ulPeriod;

// Initialize the pwmvoid pwm_init(void) { // Set up the clock to be used by the pwm SysCtlPWMClockSet(SYSCTL_PWMDIV_2);

// // Enable the peripherals used by this example. // SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // // Set GPIO F0 and G1 as PWM pins. They are used to output the PWM0 and // PWM1 signals. // GPIOPinTypePWM(GPIO_PORTB_BASE, GPIO_PIN_0); GPIOPinTypePWM(GPIO_PORTB_BASE, GPIO_PIN_1); // // Compute the PWM period based on the system clock. // // Unlocked State: SysCtlClockGet() / 2000; // Locked State: SysCtlClockGet() / 900; ulPeriod = SysCtlClockGet() / 100; upper_period = SysCtlClockGet() / 900; lower_period = SysCtlClockGet() / 2000; current_period = lower_period; // // Set the PWM period to 440 (A) Hz. // PWMGenConfigure(PWM0_BASE, PWM_GEN_1,

78

Page 84: Bluetooth Door Locking Mechanism

PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC); PWMGenPeriodSet(PWM0_BASE, PWM_GEN_1, ulPeriod); // // Set PWM0 to a duty cycle initializing lock to unlocked state // PWMPulseWidthSet(PWM0_BASE, PWM_OUT_2, lower_period); PWMPulseWidthSet(PWM0_BASE, PWM_OUT_3, lower_period); // // Enable the PWM0 and PWM1 output signals. // PWMOutputState(PWM0_BASE, PWM_OUT_2_BIT | PWM_OUT_3_BIT, true); // // Enable the PWM generator. // PWMGenEnable(PWM0_BASE, PWM_GEN_1);}

// Change the PWM to lock or unlock the door depending on the parametervoid PWM_Change(bool lock){ if (lock) { // Toggle the LED (PF0). HWREGBITB(GPIO_PORTF_BASE + ADDR_MASK, 0) ^= 1; // Increase the duty cycle if (current_period == lower_period) { current_period = upper_period; PWMPulseWidthSet(PWM0_BASE, PWM_OUT_2, current_period); } } else { // Toggle the LED (PF0). HWREGBITB(GPIO_PORTF_BASE + ADDR_MASK, 0) ^= 1; // // Decrease the duty cycle if (current_period == upper_period) { current_period = lower_period; PWMPulseWidthSet(PWM0_BASE, PWM_OUT_2, current_period); } }}

Appendix B4 (rfid_reader.c)//*****************************************************************************//// rfid_reader.c - This function communicates with the RFID Reader Module// via UART0. ////*****************************************************************************

#include "rfid_reader.h"#include "inc/hw_ints.h"#include "inc/hw_memmap.h"#include "inc/hw_types.h"#include "driverlib/debug.h"#include "driverlib/gpio.h"#include "driverlib/interrupt.h"#include "driverlib/sysctl.h"#include "driverlib/uart.h"

79

Page 85: Bluetooth Door Locking Mechanism

#include "drivers/rit128x96x4.h"#include "inc/lm3s8962.h"

extern char RFIDbuffer[16];char adminId[] = {0x02,'5','0','0','0','8','F','6','D','4','E','F','C',0x0D,0x0A,0x03};

short is_rfid_valid(char *id){ short good = 0; // Check the incoming buffer against the Admin ID for(short t = 0; t < 16; t++){ if(id[t] != adminId[t]) return good; }

// If the RFID matches return 1 good = 1; return good;}

//*****************************************************************************//// function hashit: Hashes a RFID for storage in the array////*****************************************************************************/*short hashit(char *toHash){ short sum = 0; // Sum the RFID for(short x = 0; x < 16; x++){ sum += *toHash; toHash++; } sum = sum * 17; return (sum % 53);}*/// Clears the buffer that the RFID Data is read into from UART0void clearRFIDBuff(void){ for(int x = 0; x<16; x++){ RFIDbuffer[x] = 0xFF; }}

Appendix B5 (userdb.c)#include <stdbool.h>#include "utils/ustdlib.h"#include "parser.h"#include "utils.h"#include "global.h"#include "driverlib/debug.h"#include "driverlib/flash.h"#include "utils/flash_pb.h"#include "userdb.h"

#ifdef DEBUGextern char debug_msg[SCREEN_COLS + 1];#endif//unsigned char public_modulus[SIGNATURE_SIZE] = { 0xe2, 0xa5, 0xf6, 0xd5, //0x14, 0xcd, 0x96, 0xda, 0xfa, 0xe1, 0x9b, 0x6d, 0xb4, 0x2e, 0xce, 0xa4, 0x4f, //0xa2, 0x0c, 0x77, 0xbf, 0xcf, 0x08, 0xe6, 0x3d, 0x1c, 0x22, 0xd5, 0xad, 0xba, //0xae, 0x97, 0xab, 0x38, 0xb2, 0xa5, 0x47, 0xed, 0x75, 0x4d, 0xf4, 0x49, 0x00, //0x68, 0xdd, 0x78, 0x47, 0x4f, 0x6c, 0xa5, 0x4c, 0xf2, 0x15, 0x66, 0xf3, 0xdd, //0xd8, 0x52, 0x91, 0x30, 0x61, 0xf0, 0x8d, 0xd0, 0x41, 0x01, 0x57, 0xcc, 0xb1, //0xa3, 0x15, 0x29, 0x25, 0x23, 0x5c, 0x71, 0xfc, 0x65, 0xc9, 0xa3, 0xc8, 0xd9, //0x23, 0x0d, 0x29, 0x10, 0xd4, 0xc1, 0xe4, 0x2e, 0x95, 0x57, 0xff, 0x30, 0x37, //0x62, 0x8e, 0xeb, 0x94, 0xde, 0x03, 0x61, 0x68, 0x5c, 0x77, 0x13, 0x83, 0xa0, //0x31, 0x94, 0x41, 0x09, 0x59, 0x30, 0xa9, 0x8b, 0x55, 0x6c, 0x0d, 0xb6, 0x14, //0xc7, 0xf1, 0x45, 0xd0, 0x2f, 0x1c, 0xfd };

unsigned char default_modulus[SIGNATURE_SIZE] = { 0x87, 0xE6, 0x72, 0xEA, 0x38,

80

Page 86: Bluetooth Door Locking Mechanism

0x82, 0x3D, 0x8B, 0xC0, 0x2F, 0x85, 0xBD, 0x1C, 0xF2, 0x31, 0x67, 0x2E, 0x39, 0x1D, 0x64, 0xC4, 0x53, 0x51, 0x43, 0x7E, 0x2E, 0xF0, 0x42, 0xA5, 0xE8, 0x3C, 0xAA, 0x84, 0xA9, 0xC6, 0x97, 0xA6, 0x90, 0xF9, 0x7A, 0x14, 0x2E, 0xCF, 0xF0, 0x42, 0x49, 0x5A, 0x5F, 0x60, 0x7E, 0x6E, 0xA2, 0xB3, 0x87, 0xBC, 0x9E, 0xBD, 0x9D, 0xBF, 0x06, 0x7F, 0x9E, 0x2C, 0x06, 0x3B, 0x84, 0x4C, 0xDF, 0xEE, 0x33, 0x76, 0x3A, 0xE2, 0x5E, 0xB3, 0x58, 0x3C, 0x07, 0x4C, 0x88, 0x7B, 0xA6, 0xBB, 0x2E, 0xDF, 0x25, 0x7B, 0x77, 0x2B, 0x7D, 0xF1, 0xE0, 0xC2, 0x5D, 0xAD, 0xDE, 0x7F, 0xD0, 0x34, 0xFD, 0x4F, 0xB0, 0x0D, 0xCA, 0x69, 0x08, 0xE9, 0x03, 0x0E, 0x15, 0x5F, 0x11, 0xD2, 0x66, 0x36, 0xD5, 0xCE, 0x70, 0x17, 0x8E, 0x01, 0xF4, 0x93, 0x36, 0x25, 0xDB, 0xF3, 0x43 };const char default_admin[] = "Default Admin";

ParameterBlock pb; // Temp copy of the parameter block in flashconst ParameterBlock* pb_flash_loc; // Pointer to the real parameter block in flashbool matches[MAX_NO_OF_USERS];size_t next_match_idx;extern UserRecord newUR;

// This should be called after power-up. It looks for a valid parameter block // in flash. If it doesn't find one, it creates one with the default values. // In any case, it saves a pointer to a valid parameter block in pb_flash_loc.void ParamBlockInit(void){ size_t i; size_t count=0;

FlashPBInit(PARAM_BLOCK_START, PARAM_BLOCK_END, PARAM_BLOCK_SIZE); pb_flash_loc = (ParameterBlock*) FlashPBGet();

// If there is no valid parameter block, FlashPBGet returns NULL if (pb_flash_loc == NULL) { for (i = 0; i < sizeof(pb.user_rec_stat); i++) pb.user_rec_stat[i] = 0;

pb.next_rec_loc = 2; FlashPBSave((unsigned char*)&pb); pb_flash_loc = (ParameterBlock*) FlashPBGet(); } else { pb.next_rec_loc = pb_flash_loc->next_rec_loc; for (i = 0; i < sizeof(pb.user_rec_stat); i++) pb.user_rec_stat[i] = pb_flash_loc->user_rec_stat[i];

}#ifdef DEBUG usnprintf(debug_msg, sizeof(debug_msg), "next_rec_loc = %d", pb_flash_loc->next_rec_loc); WakeScreenSaver(); PrintLine(debug_msg);

for (i=0; i<MAX_NO_OF_USERS;i++) { if (is_valid_rec(i)) count++; } usnprintf(debug_msg, sizeof(debug_msg), "user count: %d", count); PrintLine(debug_msg);#endif}

// Check if a valid admin is in the user DB. If not, add the default account.void CheckForAdmin(){ size_t i; for (i = 0; i < MAX_NO_OF_USERS; i++) { if (is_valid_rec(i) && (FLASH_IDX_TO_URP(i)->perm) & PERM_ADMIN)

81

Page 87: Bluetooth Door Locking Mechanism

return; }

// There are no admins, add the default for (i = 0; i < sizeof(default_admin); i++) { newUR.name[i] = default_admin[i]; }

for (i = 0; i < sizeof(default_modulus); i++) { newUR.pub_key.C[i] = default_modulus[i]; } newUR.perm = PERM_ADMIN; StoreUserRec(&newUR);}

// Returns true if flash_idx has a valid user recordbool is_valid_rec(size_t flash_idx){ return ((pb_flash_loc->user_rec_stat[flash_idx / 8] >> (flash_idx % 8)) & 1);}

// Finds the next free spot in the user DB and stores its index in free_idx. // Returns false if there is no free spot.bool get_free_DB_idx(size_t* free_idx, size_t start_idx){ bool success; size_t flash_idx, stop_idx; // Find next free spot stop_idx = flash_idx = start_idx; success = ! is_valid_rec(flash_idx); while (!success) { flash_idx = (flash_idx + 1) % MAX_NO_OF_USERS; if (flash_idx == stop_idx) break;

success = ! is_valid_rec(flash_idx); }

if (success) { *free_idx = flash_idx; return true; } else return false;}

// Finds all the valid user records with names matching name and returns the // number of matches. Retrieve pointers to these records by following this // function with calls to GetNextMatchIdx(). Name must be null-terminated.size_t FindMatchingUsers(const char* name){ size_t i; size_t count = 0;

for (i = 0; i < MAX_NO_OF_USERS; i++) { matches[i] = false; if (is_valid_rec(i)) { if (ustrcmp(FLASH_IDX_TO_URP(i)->name, name) == 0) { matches[i] = true;

82

Page 88: Bluetooth Door Locking Mechanism

if (count == 0) next_match_idx = i;

count++; } } }

return count;}

// Returns the index of the next matching user recordsize_t GetNextMatchIdx(void){ while ( next_match_idx < sizeof(matches) && ! matches[next_match_idx] ) next_match_idx++;

ASSERT(next_match_idx != sizeof(matches))

return next_match_idx++;}

// Returns true if two arrays are identicalbool ArrayEquals(const unsigned long* ray1, const unsigned long* ray2, size_t length){ size_t j;

for (j = 0; j < length; j++) { if (ray1[j] != ray2[j]) { return false; } } return true;}

// Stores a new user record into flash memory. Returns true if the operation // was successful. Might fail if we are out of flash, or the available flash // is bad. If an identical user rec exists, nothing will be changed and it // still returns true. If the user rec exists, but the permissions are // changing, the old record will be deleted and the new written.bool StoreUserRec(const UserRecord* rec){ size_t free_idx, start_idx, old_idx, i; bool write_failed = false; bool delete_old = false; const UserRecord* rec_flash_loc;

// Check if this user is already in the DB for (i = FindMatchingUsers(rec->name); i > 0; i--) { old_idx = GetNextMatchIdx(); rec_flash_loc = FLASH_IDX_TO_URP(old_idx); if (ArrayEquals(rec->pub_key.L, rec_flash_loc->pub_key.L, sizeof(PublicKey)/sizeof(long))) { if (rec_flash_loc->perm == rec->perm) { // This user is already in the DB and no changes are necessary return true; } else { delete_old = true; break; } } }

83

Page 89: Bluetooth Door Locking Mechanism

// Get the index where we should write to if (!get_free_DB_idx(&free_idx, pb.next_rec_loc)) return false;

start_idx = free_idx;

// Keep trying until the write succeeds or we have tried all free blocks while (true) { // Write the user record to flash pb.next_rec_loc = (free_idx + 1) % MAX_NO_OF_USERS; rec_flash_loc = FLASH_IDX_TO_URP(free_idx); FlashErase((unsigned long)rec_flash_loc); FlashProgram((unsigned long*)rec, (unsigned long)rec_flash_loc, sizeof(UserRecord));

write_failed = false; // Verify the data in flash for (i = 0; i < sizeof(UserRecord); i++) { if (((unsigned char*)rec_flash_loc)[i] != ((unsigned char*)rec)[i]) { write_failed = true; PrintLine("write failed"); break; } }

if (write_failed) { if (!get_free_DB_idx(&free_idx, pb.next_rec_loc)) { PrintLine("no more free"); return false; }

if (free_idx == start_idx) { PrintLine("free == start"); return false; } } else { break; }

}

// Update the parameter block HWREGBITB(pb.user_rec_stat + free_idx / 8, free_idx % 8) = 1; if (delete_old) HWREGBITB(pb.user_rec_stat + old_idx / 8, old_idx % 8) = 0; FlashPBSave((unsigned char*)&pb); pb_flash_loc = (ParameterBlock*)FlashPBGet(); return true;}

// Tries to find and delete from the user DB a record with the given name and // pub_key. Returns true if it succeeds.bool RemoveUserRec(const char* name, const PublicKey* pub_key){ size_t i, flash_idx; const UserRecord* rec_flash_loc;

// Assume there is only one record with matching name and pub_key for (i = FindMatchingUsers(name); i > 0; i--)

84

Page 90: Bluetooth Door Locking Mechanism

{ flash_idx = GetNextMatchIdx(); rec_flash_loc = FLASH_IDX_TO_URP(flash_idx); if (ArrayEquals(rec_flash_loc->pub_key.L, pub_key->L, sizeof(PublicKey) / sizeof(long))) { // Mark the record invalid in the parameter block HWREGBITB(pb.user_rec_stat + flash_idx / 8, flash_idx % 8) = 0; FlashPBSave((unsigned char*)&pb); pb_flash_loc = (ParameterBlock*)FlashPBGet(); return true; } }

return false;}

Appendix B6 (utils.c)#define DEBUG#include "utils.h"#include "driverlib/debug.h"#include <stdbool.h>

#define ADDR_MASK 0x3FC

ScreenBuffer sbuff = { {{0}}, 0, 0, 0 };

unsigned char errbuff[256];RingBuffer ErrorMsgBuff = {errbuff, sizeof errbuff, 0, 0};#ifdef DEBUGextern RingBuffer RxBuff;extern RingBuffer TxBuffU0;#endif

//struct {// char buff[64];// size_t start;// size_t end;//} ErrorMsgBuff = { {0}, 0, 0 };

extern void WakeScreenSaver(void);

// Send a string to the UART.void UART0StringSend(const char *pucBuffer){ // Loop while there are more characters to send. while(*pucBuffer != '\0') { // Write the next character to the UART. //UARTCharPut(UART0_BASE, *pucBuffer++); pushRB(*pucBuffer++, &TxBuffU0); }}

// Send a string to the UART.void UART1StringSend(const char *pucBuffer){ // Loop while there are more characters to send. while(*pucBuffer != '\0') {

#ifdef DEBUG pushRB(*pucBuffer, &TxBuffU0);#endif

// Write the next character to the UART. UARTCharPut(UART1_BASE, *pucBuffer++); }}

85

Page 91: Bluetooth Door Locking Mechanism

// Send an array of chars to UART1.void UART0ArraySend(const unsigned char* ray, size_t len){ size_t i = 0; while(i < len) UARTCharPut(UART0_BASE, ray[i++]);}

// Send an array of chars to UART1.void UART1ArraySend(const unsigned char* ray, size_t len){ size_t i = 0; while(i < len) {

#ifdef DEBUG pushRB(ray[i], &TxBuffU0);#endif

UARTCharPut(UART1_BASE, ray[i++]); }}

// Writes whatever is in the ScreenBuffer to the screen.void WriteScreen(){ unsigned char out_row = 0, in_row, Y = 0; for (out_row = 0; out_row < sbuff.validrows; out_row++) { in_row = (out_row + sbuff.firstrow) % SCREEN_ROWS; RIT128x96x4StringDraw(sbuff.buff[in_row], 0, Y, BRIGHTNESS); Y += ROW_HEIGHT; }}

// Prints a single char to the next available position on the screen. Will // automatically wrap at the end of the line and scroll to a new line if // necessary.void PrintChar(char c){ int buf_row; int X; int Y; bool update_whole_screen = false;

if (sbuff.column == 0) { // start a new row if (sbuff.validrows < SCREEN_ROWS) sbuff.validrows++; else { sbuff.firstrow = (sbuff.firstrow + 1) % SCREEN_ROWS; update_whole_screen = true; } }

buf_row = (sbuff.firstrow + sbuff.validrows - 1) % SCREEN_ROWS;

// Store c in the screen buffer sbuff.buff[buf_row][sbuff.column] = c;

// Write it to the screen if (update_whole_screen) { sbuff.column++; X = sbuff.column; while (X < SCREEN_COLS)

86

Page 92: Bluetooth Door Locking Mechanism

sbuff.buff[buf_row][X++] = ' ';

sbuff.buff[buf_row][X] = '\0'; WriteScreen(); } else { sbuff.buff[buf_row][sbuff.column + 1] = '\0'; X = sbuff.column * COL_WIDTH; Y = (sbuff.validrows - 1) * ROW_HEIGHT; RIT128x96x4StringDraw( &(sbuff.buff[ buf_row ][ sbuff.column ]), X, Y, BRIGHTNESS);

// update column sbuff.column++; if (sbuff.column == SCREEN_COLS) sbuff.column = 0; }}

//*****************************************************************************// Prints a string to the next line of screen. If the screen is full, the // previous contents will be shifted up a line. msg must be null terminated. // If msg is longer than the width of the screen, it will be truncated.//*****************************************************************************void PrintLine(char* msg){ int idx = 0; int row = (sbuff.firstrow + sbuff.validrows) % SCREEN_ROWS; int col = 0; do { sbuff.buff[row][col++] = msg[idx++]; } while (msg[idx] != '\0' && col < SCREEN_COLS);

while (col < SCREEN_COLS) sbuff.buff[row][col++] = ' '; // last char must be null in all cases sbuff.buff[row][col] = '\0';

if (sbuff.validrows < SCREEN_ROWS) sbuff.validrows++; else sbuff.firstrow = (sbuff.firstrow + 1) % SCREEN_ROWS;

sbuff.column = 0; WriteScreen();}

// Adds item to the end of rb. If rb is full, oldest data is overwritten.void pushRB(char item, RingBuffer* rb){ ASSERT(rb != NULL);

rb->buff[rb->end++] = item; if (rb->end == rb->size) rb->end = 0; if (rb->start == rb->end) {#ifdef DEBUG if (rb == &RxBuff) ErrorPrint(" RxBuff overflow "); else if (rb == &TxBuffU0) ErrorPrint(" TxBuffU0 overflow "); else if (rb == &ErrorMsgBuff)

87

Page 93: Bluetooth Door Locking Mechanism

ErrorPrint(" ErrorMsgBuff overflow ");#endif

rb->start++; if (rb->start == rb->size) rb->start = 0; }}

// Removes an item from the start of rb. You make sure the buffer isn't empty.char pullRB(RingBuffer* rb){ char result; ASSERT(rb != NULL);

if (rb->start != rb->end) { result = rb->buff[rb->start++]; if (rb->start == rb->size) rb->start = 0; } else { result = 0;

#ifdef DEBUG if (rb == &RxBuff) ErrorPrint(" RxBuff underflow "); else if (rb == &TxBuffU0) ErrorPrint(" TxBuffU0 underflow "); else if (rb == &ErrorMsgBuff) ErrorPrint(" ErrorMsgBuff underflow ");#endif

}

#ifdef DEBUG if (rb == &RxBuff) pushRB(result, &TxBuffU0);#endif

return result;}

// Returns the space available in the ring buffersize_t spaceRB(RingBuffer* rb){ if (rb->start == rb->end) return rb->size - 1; else if (rb->start < rb->end) return rb->size - rb->end + rb->start - 1;

else // rb->start > rb->end return rb->start - rb->end - 1;}

// Add a error message to a buffer, which will later be dumped to the screen by // calling ErrorFlush.void ErrorPrint(char* msg){ size_t space;

// Disable global interrupts __asm("cpsid i");

space = spaceRB(&ErrorMsgBuff);

// We need space for at least a character and a null

88

Page 94: Bluetooth Door Locking Mechanism

if (space < 2) { // Enable global interrupts __asm("cpsie i"); return; }

if (*msg != '\0') { pushRB(*(msg++), &ErrorMsgBuff); space--; }

while (*msg != '\0' && space > 1) { pushRB(*(msg++), &ErrorMsgBuff); space--; }

pushRB('\0', &ErrorMsgBuff);

// Enable global interrupts __asm("cpsie i");}

// Flush the error message buffer. Put this in the main loop. Do NOT have // code in an ISR that could write to the screen or call this funtion.void ErrorFlush(void){ char msg[SCREEN_COLS+1]; size_t i;

while (ErrorMsgBuff.start != ErrorMsgBuff.end) { // copy the next message in the buffer to msg i = 0; msg[i] = pullRB(&ErrorMsgBuff); while (msg[i] != '\0' && i < SCREEN_COLS) { msg[++i] = pullRB(&ErrorMsgBuff); }

if (msg[i] != '\0') { // We ran out of screen columns before finding the null. // Add the null to msg, and clear the rest of the message in the // buffer. msg[i] = '\0'; while (pullRB(&ErrorMsgBuff) != '\0'); }

//WakeScreenSaver(); //PrintLine(msg); UART0StringSend(msg); }}

Appendix B7 (sbrk.c)// posted by dereksoftstuff to TI E2E Community forums on July 25, 2008// http://e2e.ti.com/support/microcontrollers/stellaris_arm_cortex-m3_microcontroller/f/473/t/44452.aspx// // modified by David Chamberlain, December 5, 2012

#include <sys/types.h>//#include "utils.h"

// linker (main.ld) sets heap start and endextern unsigned int _HEAP_START;

89

Page 95: Bluetooth Door Locking Mechanism

extern unsigned int _HEAP_END;

static caddr_t heap = NULL;

// low level bulk memory allocator - used by malloccaddr_t _sbrk ( int increment ) {

caddr_t prevHeap; caddr_t nextHeap; if (heap == NULL) { // first allocation heap = (caddr_t)&_HEAP_START; }

prevHeap = heap; // Always return data aligned on a 8 byte boundary nextHeap = (caddr_t)(((unsigned int)(heap + increment) + 7) & ~7);

if (nextHeap > (caddr_t)&_HEAP_END) { return NULL; // error - no more memory } else { heap = nextHeap; return (caddr_t) prevHeap; } }

Appendix B8 (startup_gcc.c)// startup_gcc.c - Startup code for use with GNU tools.// Copyright (c) 2005-2012 Texas Instruments Incorporated. All rights reserved.// Software License Agreement// Texas Instruments (TI) is supplying this software for use solely and// exclusively on TI's microcontroller products. The software is owned by// TI and/or its suppliers, and is protected under applicable copyright// laws. You may not combine this software with "viral" open-source// software in order to form a larger program.// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL// DAMAGES, FOR ANY REASON WHATSOEVER.// This is part of revision 9453 of the EK-LM3S8962 Firmware Package.#include "utils.h"

#define ADDR_MASK 0x3FC

// Forward declaration of the default fault handlers.void ResetISR(void);static void NmiSR(void);static void FaultISR(void);static void IntDefaultHandler(void);

// External declaration for the interrupt handler used by the application.extern void SysTickIntHandler(void);extern void UART0IntHandler(void);extern void UART1IntHandler(void);extern void GPIOCIntHandler(void);

// The entry point for the application.extern int main(void);

// Reserve space for the system stack.

90

Page 96: Bluetooth Door Locking Mechanism

static unsigned long pulStack[4096];

// The vector table. Note that the proper constructs must be placed on this to// ensure that it ends up at physical address 0x0000.0000.__attribute__ ((section(".isr_vector")))void (* const g_pfnVectors[])(void) ={ (void (*)(void))((unsigned long)pulStack + sizeof(pulStack)), // The initial stack pointer ResetISR, // The reset handler NmiSR, // The NMI handler FaultISR, // The hard fault handler IntDefaultHandler, // The MPU fault handler IntDefaultHandler, // The bus fault handler IntDefaultHandler, // The usage fault handler 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved IntDefaultHandler, // SVCall handler IntDefaultHandler, // Debug monitor handler 0, // Reserved IntDefaultHandler, // The PendSV handler SysTickIntHandler, // The SysTick handler IntDefaultHandler, // GPIO Port A IntDefaultHandler, // GPIO Port B GPIOCIntHandler, // GPIO Port C IntDefaultHandler, // GPIO Port D IntDefaultHandler, // GPIO Port E UART0IntHandler, // UART0 Rx and Tx UART1IntHandler, // UART1 Rx and Tx IntDefaultHandler, // SSI0 Rx and Tx IntDefaultHandler, // I2C0 Master and Slave IntDefaultHandler, // PWM Fault IntDefaultHandler, // PWM Generator 0 IntDefaultHandler, // PWM Generator 1 IntDefaultHandler, // PWM Generator 2 IntDefaultHandler, // Quadrature Encoder 0 IntDefaultHandler, // ADC Sequence 0 IntDefaultHandler, // ADC Sequence 1 IntDefaultHandler, // ADC Sequence 2 IntDefaultHandler, // ADC Sequence 3 IntDefaultHandler, // Watchdog timer IntDefaultHandler, // Timer 0 subtimer A IntDefaultHandler, // Timer 0 subtimer B IntDefaultHandler, // Timer 1 subtimer A IntDefaultHandler, // Timer 1 subtimer B IntDefaultHandler, // Timer 2 subtimer A IntDefaultHandler, // Timer 2 subtimer B IntDefaultHandler, // Analog Comparator 0 IntDefaultHandler, // Analog Comparator 1 IntDefaultHandler, // Analog Comparator 2 IntDefaultHandler, // System Control (PLL, OSC, BO) IntDefaultHandler, // FLASH Control IntDefaultHandler, // GPIO Port F IntDefaultHandler, // GPIO Port G IntDefaultHandler, // GPIO Port H IntDefaultHandler, // UART2 Rx and Tx IntDefaultHandler, // SSI1 Rx and Tx IntDefaultHandler, // Timer 3 subtimer A IntDefaultHandler, // Timer 3 subtimer B IntDefaultHandler, // I2C1 Master and Slave IntDefaultHandler, // Quadrature Encoder 1 IntDefaultHandler, // CAN0 IntDefaultHandler, // CAN1 IntDefaultHandler, // CAN2 IntDefaultHandler, // Ethernet IntDefaultHandler // Hibernate};

91

Page 97: Bluetooth Door Locking Mechanism

// The following are constructs created by the linker, indicating where the// the "data" and "bss" segments reside in memory. The initializers for the// for the "data" segment resides immediately following the "text" segment.extern unsigned long _etext;extern unsigned long _data;extern unsigned long _edata;extern unsigned long _bss;extern unsigned long _ebss;

// This is the code that gets called when the processor first starts execution// following a reset event. Only the absolutely necessary set is performed,// after which the application supplied entry() routine is called. Any fancy// actions (such as making decisions based on the reset cause register, and// resetting the bits in that register) are left solely in the hands of the// application.voidResetISR(void){ unsigned long *pulSrc, *pulDest;

// Copy the data segment initializers from flash to SRAM. pulSrc = &_etext; for(pulDest = &_data; pulDest < &_edata; ) { *pulDest++ = *pulSrc++; }

// Zero fill the bss segment. __asm(" ldr r0, =_bss\n" " ldr r1, =_ebss\n" " mov r2, #0\n" " .thumb_func\n" "zero_loop:\n" " cmp r0, r1\n" " it lt\n" " strlt r2, [r0], #4\n" " blt zero_loop");

// Call the application's entry point. main();}

// This is the code that gets called when the processor receives a NMI. This// simply enters an infinite loop, preserving the system state for examination// by a debugger.static voidNmiSR(void){ //HWREGBITB(GPIO_PORTF_BASE + ADDR_MASK, 0) ^= 1; // Enter an infinite loop. while(1) { }}

// This is the code that gets called when the processor receives a fault// interrupt. This simply enters an infinite loop, preserving the system state// for examination by a debugger.static voidFaultISR(void){ HWREGBITB(GPIO_PORTF_BASE + ADDR_MASK, 0) ^= 1; // Enter an infinite loop. while(1) { }}

92

Page 98: Bluetooth Door Locking Mechanism

// This is the code that gets called when the processor receives an unexpected// interrupt. This simply enters an infinite loop, preserving the system state// for examination by a debugger.static voidIntDefaultHandler(void){ //HWREGBITB(GPIO_PORTF_BASE + ADDR_MASK, 0) ^= 1; ErrorPrint("ERR: unhandled interrupt"); // Go into an infinite loop. while(1) { }}

Appendix B9 (global.h)#ifndef GLOBAL_H_DEF#define GLOBAL_H_DEF

#ifndef NULL#define NULL ((void *)0)#endif

// The rate of system ticks in Hz#define TICK_RATE 1000#define UART0_BAUD 9600#define UART1_BAUD 115200#define BUT_POLL_RATE 500 // Hz#define BUT_DEAD_TIME 20 // ms#define SCREENSAVER_TIMEOUT 20 // seconds#define INVALID_TIMEOUT 1000 // ms#define RANDOM_NO_LENGTH 64 // bytes

// Add this to the base address of GPIO data registers to unmask the whole byte// see section 8.2.1.2 in the LM3S8962 datasheet.#define ADDR_MASK 0x3FC

#define STRX(x) #x#define STR(x) STRX(x) // convert integer macro x to string literal

// Inform the screen saver of activity which should prevent the screensaver // from activating;void WakeScreenSaver(void);

#endif

Appendix B10 (parser.h)#ifndef PARSER_H_DEF#define PARSER_H_DEF

// Theses are the status indicators returned by parser functions.#define PARSER_BUSY 0 // Waiting for more bytes to finish parsing#define PARSER_INVALID 1 // The incoming bytes are not a valid command#define PARSER_BAD_USER 2 // The user is not known#define PARSER_BAD_AUTH 3 // User authentication failed#define PARSER_BAD_PERM 4 // User doesn't have the correct permissions#define PARSER_UNLOCK 5 // The door should be unlocked#define PARSER_LOCK 6 // The door should be locked#define PARSER_STATUS 7 // The door's status should be returned#define PARSER_BEGIN 8 // Send the random number#define PARSER_ADD_USER 9 // A user is being added#define PARSER_TOGGLE 10 // Toggle the LED (for testing)#define PARSER_BAD_RN 11 // The random number was wrong#define PARSER_RM_USER 12 // A user is being deleted

// Internal status indicators#define PARSER_NAME_DONE 128 // A valid user name and trailing ':' has been received#define PARSER_RN_DONE 129 // A valid RN has been received#define PARSER_SIG_DONE 130 // A valid signature has been received

93

Page 99: Bluetooth Door Locking Mechanism

#define PARSER_KEY_DONE 131 // A key has been received#define PARSER_PERMS_DONE 132 // A key has been received

#define MAX_USER_LENGTH 20 // characters#define SIGNATURE_SIZE 128 // bytes#define EXPONENT 0x10001 // RSA public exponent#define SALT_SIZE 0 // bytes (This is irrelevant for PCKS V1.5 padding)

#define PERM_ADMIN 1 // And permission byte with this

// Parse the incoming bytes, possibly set some flags/globals, then return a // status indicator. Assumes there is at least one byte to be read in RxBuff.// If reset is true, all parser logic is reset.unsigned char Parse(bool reset);

#endif

Appendix B11 (userdb.h)#ifndef USERDB_H_DEF#define USERDB_H_DEF

// User Database:// Each record in the data base will be stored in single erase block of flash, // which is 1024 bytes. These records will be written directly to flash using // the FlashErase() and FlashProgram() functions (SW-DRL-UG-9453.pdf). The // user records can be read just like normal memory. The status of the user // database, that is which locations hold valid user records, will be stored in // a flash parameter block, provided by the FlashPB functions // (SW-EK-LM3S8962-UG-9453.pdf).#define PARAM_BLOCK_START 0x30000 // the start of the parameter block storage area, see main.ld#define FLASH_ERASE_BLOCK 1024 // bytes#define PARAM_BLOCK_END (PARAM_BLOCK_START + FLASH_ERASE_BLOCK*4) // use 4 erase blocks// The size of a single block. This must be: big enough to hold the // ParameterBlock struct below, a power of 2, and an integral divisor of 1024. // Also, ('START - 'END) / 'SIZE < 128.#define PARAM_BLOCK_SIZE 128 // (bytes) this seems like a good number#define END_OF_FLASH 0x40000// can't store more than this in the user DB#define MAX_NO_OF_USERS ((END_OF_FLASH - PARAM_BLOCK_END) / FLASH_ERASE_BLOCK)// convert an index to a UserRecord pointer#define FLASH_IDX_TO_URP(idx) ((const UserRecord*)(PARAM_BLOCK_END + idx * FLASH_ERASE_BLOCK))

typedef union { unsigned char C[SIGNATURE_SIZE / sizeof(char)]; unsigned long L[SIGNATURE_SIZE / sizeof(long)];} PublicKey;

typedef struct { char name[MAX_USER_LENGTH + 1]; unsigned char perm; PublicKey pub_key;} UserRecord;

typedef struct { unsigned char sequence; // these two bytes are reserved for the FlashPB functions unsigned char checksum; // don't write to them

// Each bit in this array will be set to 1 to indicate the corresponding // location in memory holds a valid user record. The least significant bit // of index 0 corresponds to the user record located at PARAM_BLOCK_END.#define USER_REC_STAT_SIZE ((MAX_NO_OF_USERS / sizeof(char)) + 1) unsigned char user_rec_stat[USER_REC_STAT_SIZE];

// For wear leveling, we will try to use the entire user db area of flash // before we reuse an old location. This number indicates which erase // block we should try to write the next user record to. (Don't assume it // is empty.) unsigned char next_rec_loc;

94

Page 100: Bluetooth Door Locking Mechanism

// Fill the rest of the PARAM_BLOCK_SIZE allocated to us. This should // prevent the FlashPBSave() function from trying to read an invalid // address, which would hard fault the system. It also should create a // compiler error if this struct is bigger than PARAM_BLOCK_SIZE. unsigned char padding[PARAM_BLOCK_SIZE - 3 - USER_REC_STAT_SIZE];} ParameterBlock;

// This should be called after power-up. It looks for a valid parameter block // in flash. If it doesn't find one, it creates one with the default values. // In any case, it saves a pointer to a valid parameter block in pb_flash_loc.void ParamBlockInit(void);

// Check if a valid admin is in the user DB. If not, add the default account.void CheckForAdmin();

// Returns true if flash_idx has a valid user recordbool is_valid_rec(size_t flash_idx);

// Finds the next free spot in the user DB and stores its index in free_idx. // Returns false if there is no free spot.bool get_free_DB_idx(size_t* free_idx, size_t start_idx);

// Finds all the valid user records with names matching name and returns the // number of matches. Retrieve pointers to these records by following this // function with calls to GetNextMatchIdx(). Name must be null-terminated.size_t FindMatchingUsers(const char* name);

// Returns the index of the next matching user recordsize_t GetNextMatchIdx(void);

// Returns true if two arrays are identicalbool ArrayEquals(const unsigned long* ray1, const unsigned long* ray2, size_t length);

// Stores a new user record into flash memory. Returns true if the operation // was successful. Might fail if we are out of flash, or the available flash // is bad. If an identical user rec exists, nothing will be changed and it // still returns true. If the user rec exists, but the permissions are // changing, the old record will be deleted and the new written.bool StoreUserRec(const UserRecord* rec);

// Tries to find and delete from the user DB a record with the given name and // pub_key. Returns true if it succeeds.bool RemoveUserRec(const char* name, const PublicKey* pub_key);#endif

Appendix B12 (pwm.h)// Initialize the pwmvoid pwm_init(void);

// Change the PWM to lock or unlock the door depending on the parametervoid PWM_Change(bool lock);

Appendix B13 (rfid_reader.h)//*****************************************************************************//// rfid_reader.h - Macros and defines used when a rfid reader is added to UART0////*****************************************************************************

//*****************************************************************************//// Function Prototypes////*****************************************************************************

short is_rfid_valid(char *id);void clearRFIDBuff(void);

95

Page 101: Bluetooth Door Locking Mechanism

Appendix B14 (utils.h)#ifndef UTILS_H_DEF#define UTILS_H_DEF

#include <stddef.h>#include "inc/hw_types.h"#include "inc/hw_memmap.h"#include "driverlib/uart.h"#include "drivers/rit128x96x4.h"

#define SCREEN_ROWS 12#define SCREEN_COLS 21#define BRIGHTNESS 15#define ROW_HEIGHT 8#define COL_WIDTH 6

typedef struct { char buff[SCREEN_ROWS][SCREEN_COLS + 1]; // +1 for null terminator unsigned char firstrow; unsigned char validrows; unsigned char column; // the column to write to next} ScreenBuffer;

// This ring buffer is empty when start == end. Read from the start index, // write to the end index.typedef struct { unsigned char* buff; unsigned short size; unsigned short start; unsigned short end;} RingBuffer;

// Adds item to the end of rb. If rb is full, oldest data is overwritten.void pushRB(char item, RingBuffer* rb);

// Removes an item from the start of rb. You make sure the buffer isn't empty.char pullRB(RingBuffer* rb);

// Returns the space available in the ring buffersize_t spaceRB(RingBuffer* rb);

// Send a string to UART0.void UART0StringSend(const char *pucBuffer);

// Send a string to UART1.void UART1StringSend(const char *pucBuffer);

// Send an array of chars to UART1.void UART0ArraySend(const unsigned char* ray, size_t len);

// Send an array of chars to UART1.void UART1ArraySend(const unsigned char* ray, size_t len);

// Writes whatever is in the ScreenBuff to the screen.void WriteScreen();

// Prints a string to the next line of screen. If the screen is full, the // previous contents will be shifted up a line. msg must be null terminated. // If msg is longer than the width of the screen, it will be truncated.void PrintLine(char* msg);

// Prints a single char to the next available position on the screen. Will // automatically wrap at the end of the line and scroll to a new line if // necessary.void PrintChar(char c);

// Route error messagesvoid ErrorPrint(char* msg);

96

Page 102: Bluetooth Door Locking Mechanism

// Flush the error message buffervoid ErrorFlush(void);#endif

97