Touch ID

From The iPhone Wiki
Revision as of 16:30, 18 October 2014 by IAdam1n (talk | contribs) (New devices.)
Jump to: navigation, search

The iPhone 5s and newer, iPad Air 2 and newer, and iPad mini 3 and newer comes equipped with Touch ID, a fingerprint scanner. Currently, there is no official developer API for it, because it is intended for unlocking the device and purchasing items on iTunes Store only. According to this article the sensor is bound to each device uniquely. This means that Touch ID sensors seem to be tied to specific devices somehow similar to HDMI protected media path.

However there is a private API for it; its dylib file is in Xcode 5 in the path

Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/PrivateFrameworks/BiometricKit.framework/BiometricKit

Since it contains a 64-bit ARM slice only, the common disassembly tools cannot process the file (beyond basic header and data segment analysis).

Process

Fingerprint Registration Process

Touch ID process

Apple has applied for belows process to be patented for TouchID in Apple Patent Application 20130308838.

  • The fingerprint sensor detects an object to scan (activated via the 'metal ring' around the home button).
  • The fingerprint sensor starts the scan - basically it takes a picture of the finger (UIImage).
  • The picture is transferred to the Secure Enclave Processor (SEP) over an an encrypted dataline (similar to HDMI protected media path).
  • The SEP stores this picture as a so-called template. Then it constructs a lower resolution version: a histogram of the most common ridge angles storing it together with the higer resolution template in the Secure Enclave.
  • The SEP sends the lower resolution version to the main CPU.
  • The main CPU stores the lower resultion version in a database (for a later authentication).

Fingerprint Authentication Process

  • The fingerprint sensor detects an object to scan (activated via the 'metal ring' around the home button).
  • The fingerprint sensor starts the scan - basically it takes a picture of the finger (UIImage).
  • The picture is transferred to the Secure Enclave Processor (SEP) over an an encrypted dataline (similar to HDMI protected media path).
  • The SEP constructs a lower resolution version: a histogram of the most common ridge angles.
  • The SEP sends the lower resolution version to the main CPU.
  • The main compares the the lower resolution version for possible matches in its database.
  • The main sends possible matches back to SEP or the authentication is rejected if no matches are found.
  • The SEP takes the matches received by the main CPU and compares the initial image to high resolution versions of the received matches from main CPU.
  • Access is granted in case of positive comparison or rejected in case of negative comparison.

Inferred Information

Based on a string dump, here is what is implied.

  • It's codename is "mesa"
  • It communicates over XPC to a binary that handles access to it
  • There are kernel extensions to interface with it
  • The kernel extension communicates to the secure keystore to set and verify fingerprints
  • The fingerprint scanner calibrates itself and has upgradable firmware
  • The fingerprint scanner uses normal image formats (i.e. UIImage) before setting and verifying fingerprints
  • There's biometric lockout as well as passcode lockout
  • The A7 chip contains a secure element marketed as the Secure Enclave. The string dump refers to SEP, the Secure Element Protocol. This chip is most likely one sourced from NXP. It contains physical security to ensure that the only operations of the chip involve setting new fingerprints and verifying fingerprints against the ones stored in it (i.e. challenge-response). This way, the fingerprint data cannot be extracted from it.

String Dump

Below there is a full string dump of the framework, which can hint at its functionalities.

initWithMachServiceName:options:
connectWithReplyBlock:
registerDelegate:withReplyBlock:
suspendWork:withReplyBlock:
enroll:withAuthToken:withReplyBlock:
match:withReplyBlock:
match:withOptions:withReplyBlock:
matchIdentities:withReplyBlock:
cancelWithReplyBlock:
updateIdentity:withReplyBlock:
removeIdentity:withReplyBlock:
getIdentityFromUUID:withReplyBlock:
identities:withReplyBlock:
resetEngineWithReplyBlock:
registerDSID:withAuthToken:withReplyBlock:
registerStoreToken:withReplyBlock:
getCountersignedStoreTokenWithReplyBlock:
getMaxIdentityCount:withReplyBlock:
enrollContinueWithReplyBlock:
pullAlignmentDataWithReplyBlock:
pullMatchTopologyDataWithReplyBlock:
getNodeTopologyForIdentity:withReplyBlock:
preventAutonomousMatchingMode:withReplyBlock:
getProvisioningStateWithReplyBlock:
getCalBlobVersionWithReplyBlock:
getSensorCalibrationStatusWithReplyBlock:
getCalibrationDataStateWithReplyBlock:
setDebugImages:withReplyBlock:
pullCaptureBufferWithReplyBlock:
pullDebugImageData:withReplyBlock:
provisionSensorWithReplyBlock:
unpairSensorWithReplyBlock:
lockSensorWithReplyBlock:
getSerialisedTemplateForIdentity:withReplyBlock:
interfaceWithProtocol:
setRemoteObjectInterface:
remoteObjectInterface
setWithObject:
setClasses:forSelector:argumentIndex:ofReply:
setWithObjects:
enrollResult:
matchResult:
statusMessage:
homeButtonPressed
setExportedInterface:
setExportedObject:
setInterruptionHandler:
resume
invalidate
remoteObjectProxyWithErrorHandler:
code
respondsToSelector:
connect
registerDelegate:
suspendWork:
enroll:withAuthToken:
match:
match:withOptions:
matchIdentities:
cancel
updateIdentity:
removeIdentity:
getIdentityFromUUID:
identities:
getMaxIdentityCount:
resetEngine
enrollContinue
pullAlignmentData
pullMatchTopologyData
getNodeTopologyForIdentity:
preventAutonomousMatchingMode:
getProvisioningState
registerDSID:withAuthToken:
registerStoreToken:
getCountersignedStoreToken:
getCalBlobVersion
getSensorCalibrationStatus
getCalibrationDataState
pullCaptureBuffer
pullDebugImageData:imageWidth:imageHeight:
provisionSensor
unpairSensor
lockSensor
setDebugImages:
getSerialisedTemplateForIdentity:
delegate
setDelegate:
interruptionHandler
_connection
_delegate
_interruptionHandler
setTopology:
setDetails:
topology
details
_topology
_details
initEnrollmentValues
message
messageDetails
objectForKeyedSubscript:
currentPrimaryComponentID
integerValue
doubleValue
statistics
enroll:
enrollResult:componentSet:
enrollProgress:
_fingerOn
_enrolling
_badImagePerFingerDown
_enrollmentStarTime
_touchesPerEnroll
_badImagesPerEnroll
_rejectedImagesPerEnroll
_primaryClusterAdditions
_primaryClusterFailedAdditions
_otherClustersAdditions
_joinEvents
_area
_primaryClusterArea
numberWithBool:
preferencesGetStringValue:
preferencesGetBOOLValue:
enableLogger:toPath:
manager
defaultCenter
appDidEnterBackground:
addObserver:selector:name:object:
appWillEnterForeground:
bundleForClass:
imageNamed:inBundle:
updateEnableLogger
dataWithBytes:length:
startEnrollLog
data
logRemoveIdentity:
bytes
imageFromRawImageData:
imageFromBitmapData:inRect:
pullDebugImageData:target:
getRadarAtachmentsForLastEnrollment
getRadarAtachmentsForLastMatch
length
stringWithString:
getModulationRatio
stringForProvisioningState:
getSensorPatchVersion
stringWithFormat:
getLogsForProcess:
sharedConnection
isFingerprintUnlockAllowed
setGracePeriod:passcode:completionBlock:
finishEnrollLogWithStatus:withIdentity:withTemplate:
matchResult:withDetails:
createMatchInfo:withTopology:withMatchImage:
logMatchResult:withTopology:withImage:withCaptureBuffer:withTemplate:
getBytes:length:
logEnrollMessage:withTopology:withImage:withCaptureBuffer:
logStatus:
enrollProgressMessage:
logRejectedImage:
size
drawInRect:
drawInRect:blendMode:alpha:
CGImage
scale
imageOrientation
imageWithCGImage:scale:orientation:
imageWithImage:inRect:
identityImage:
imageWithImage:withNode:withRect:alpha:
compositeTopologyImage:
imageTopology:forGroup:
imageFauxprint:withTheta:withLamda:
greenColor
imageWithImage:withTintColor:
dataWithData:
imageWithCGImage:
preferencesSetBOOLValue:forKey:
pullDebugImage:
getLoggerAttachmentsForRadar:
stringFromSensorConfiguration
matchIdentity:
topologyImage:
imageWithImage:withMaskImage:
inUse
setInUse:
enrollProgressConfigRenderMode
setEnrollProgressConfigRenderMode:
enrollProgressConfigRenderViewSize
setEnrollProgressConfigRenderViewSize:
renderMode
setRenderMode:
opacity
setOpacity:
_xpcClient
_enrollingMode
_matchingMode
_statistics
_scanbedImage
_fauxprintImage
_nodeRect
_images
_compSet
_rejectTouchCount
_rejectTouch
_showDebugImages
_enableLogger
_enrollImageSet
_isInternalInstall
_inUse
_enrollProgressConfigRenderMode
_renderMode
_opacity
_enrollProgressConfigRenderViewSize
setUuid:
decodeBytesForKey:returnedLength:
initWithUUIDBytes:
decodeIntForKey:
decodeObjectOfClass:forKey:
copy
getUUIDBytes:
encodeBytes:length:forKey:
encodeInt:forKey:
encodeObject:forKey:
biometricKitIdentity
supportsSecureCoding
encodeWithCoder:
initWithCoder:
uuid
type
setType:
attribute
setAttribute:
entity
setEntity:
name
setName:
stringByReplacingOccurrencesOfString:withString:
initWithCapacity:
setLength:
mutableBytes
defaultManager
createDirectoryAtPath:withIntermediateDirectories:attributes:error:
removeItemAtPath:error:
UUIDString
setMessageDetails:
setCaptureImage:
setRenderedImage:
progress
setProgress:
setCurrentPrimaryComponentID:
captureImage
renderedImage
setMessage:
_message
_progress
_currentPrimaryComponentID
_captureImage
_renderedImage
_messageDetails
setX:
setY:
angle
setAngle:
_angle
setTransformationCoordinates:
componentID
setComponentID:
transformationCoordinates
_componentID
_transformationCoordinates
pathComponents
com.apple.biometrickitd
T@"<BiometricKitDelegate>",N,V_delegate
interruptionHandler
T@?,C,N,V_interruptionHandler
topology
T@"NSDictionary",&,N,V_details
com.apple.fingerprint.enroll.attempts
com.apple.fingerprint.enroll.passes
com.apple.fingerprint.enroll.touchesPerEnroll
com.apple.fingerprint.enroll.badImagesPerEnroll
com.apple.fingerprint.enroll.rejectedImagesPerEnroll
com.apple.fingerprint.enroll.primaryClusterAdditions
com.apple.fingerprint.enroll.primaryClusterFailedAdditions
com.apple.fingerprint.enroll.otherClustersAdditions
com.apple.fingerprint.enroll.joinEvents
com.apple.fingerprint.enroll.clusterCount
com.apple.fingerprint.enroll.nodeCount
com.apple.fingerprint.enroll.primaryClusterNodeCount
com.apple.fingerprint.enroll.area
com.apple.fingerprint.enroll.primaryClusterArea
com.apple.fingerprint.enroll.passTime
com.apple.fingerprint.enroll.fails
com.apple.fingerprint.enroll.failTime
com.apple.ManagedConfiguration.profileListChanged
com.apple.biometrickitd.debugLogEnabled
com.apple.biometrickitd.debugLogPath
debugLogEnabled
debugLogPath
BKOptionSuppressHapticFeedback
BKOptionFilterOutHomeButtonEvents
BKOptionMatchForUnlock
InternalBuild
scanbed
synthetic
Uninitialized
Not Provisioned
Unprovisioned
Provisioned
Provisioned Locked
Unpaired
Unknown
biosensor,mesa
modulation-ratio
AppleBiometricSensor
patch-version
Mesa configuration:
Provisioning Status: %@
Calibrated: 
- Version: 
- Signed: 
Modulation ratio: 
Kernel: 
Thick kernel
Thin kernel
Sensor Patch Version: 
Steps to Reproduce:
inUse
TB,V_inUse
enrollProgressConfigRenderMode
Ti,N,V_enrollProgressConfigRenderMode
enrollProgressConfigRenderViewSize
T{CGSize=dd},N,V_enrollProgressConfigRenderViewSize
renderMode
Ti,N,V_renderMode
opacity
Tf,N,V_opacity
Notification callback.
BiometricKitErrorDomain
BKIdentityUUID
BKIdentityType
BKIdentityAttribute
BKIdentityEntityNumber
BKIdentityName
/var/mobile/BiometricKit/biometrickitd
BKEPDReason
BKEPDNewNodeID
BKEPDNewComponentID
BKEPDNewNodeCoordinates
BKEPDRemovedNodeID
BKEPDRemovedComponentID
BKEPDExtendedComponentID
BKEPDResultComponentID
BKEPDMergedInComponents
BKEPDRedundantNode
BKTDLargestCompArea
BKTDLargestCompNodes
BKTDTotalArea
BKTDTotalNodes
BKTemplateUpdated
Td,N,V_x
Td,N,V_y
angle
Td,N,V_angle
componentID
Tq,N,V_componentID
transformationCoordinates
T@"BiometricKitEnrollProgressCoordinates",&,N,V_transformationCoordinates
Remove identity: %@
Log package:%@
biometrickitd
%@.tar.gz
cd %@ && tar -cjf %@ %@
Time: % 8.3f
PASS
FAIL
Closing log with result %@
Template identity:
UUID  : %@
Type  : %i
Attrib: %i
Entity: %i
Error: Unable to get identity
Serialised template: %@
%@_%04d.bin
Status message: %@
Progress %i
Count of enrollments: %i
BiometricKitErrorTaskCancelled
BiometricKitErrorIdentityInvalid
BiometricKitErrorIdentityNotAllowed
BiometricKitErrorIdentityErrorInvalidData
BiometricKitErrorIdentityErrorUnknown
BiometricKitStatusFingerOn
BiometricKitStatusFingerOff
BiometricKitStatusEnrollmentComplete
BiometricKitStatusEnrollmentCancelled
BiometricKitStatusEnrollmentFailed
BiometricKitStatusEnrollmentTimeout
BiometricKitStatusUnknownError
BiometricKitStatusImageRejected
BiometricKitStatusNoCalibration
BiometricKitImageForProcessing
BiometricKitStatusTemplateListUpdated
BiometricKitStatusRequestFingerOff
BiometricKitStatusAutoMatchingStarted
BiometricKitStatusAutoMatchingStopped
BiometricKitStatusCaptureRestart
BiometricKitStatusScanTooShort
BiometricKitStatusAutoMatchingStartByHomeButton
BiometricKitStatusMatchingCancelled
BiometricKitStatusFingerOnBeforeFirstPasscodeUnlock
BiometricKitStatusFingerOnInPasscodeLockout
BiometricKitStatusFingerOnInBioLockout
BiometricKitStatusFingerOnTokenExpired
BiometricKitStatusESDRecovery
BiometricKitStatusImageRejectedUnknown
BiometricKitStatusImageRejectedBadBlocks
BiometricKitStatusImageRejectedChFPN
BiometricKitStatusImageRejectedCaFPN
BiometricKitStatusSensorOperationModeIdle
BiometricKitStatusSensorOperationModeCapture
BiometricKitStatusSensorOperationModePause
Other unknown status %i
Image #%i was rejected
Sensor patch version: %ld
Sensor patch version: unknown
Calibration Data: %@
Capture buffer: %@
Matcher: image refused
Matcher: image %s node %u
added as
replaced
Coordinates: %s[%i, %i, %i]
inverse of 
Parent: %i
Processed image: %@
Enroll debug log, version 7
static const node_placement_t table_%02i = 
%@{%i,%i,%i,%i,%i,%i,{
%@{%i,%i,%i,%i,%i}
%@},%i,%i,%i,%i,%i,0x%04x};
bin8
bin16
binXX
calibdata.bin
calibration-blob
Image #%i%s
 was sent to matcher
Match result
Match details:
Matching score: %i
Match S2S count: %i
Matching node: %i
Updated node: %i
Not available
No match (artificial)
No match
Image #%i
Warning: the log is not complete, previous part of the log was deleted.
Starting enrollment
Starting matching
No known identities with enroll log are available.
Known identities with enroll log available:
%@ : %@
Match debug log, version 7
messages.log
OS version: %@ (%@)
Mesa: %@
Process name:%@
PrimaryUsagePage
PrimaryUsage
com.apple.iokit.hid.displayStatus
com.apple.mobile.keybagd.lock_status
AppleMesaSEPDriver
IOGeneralInterest
ScanningState
ScanningStateIdle
ScanningStateShortScanning
ScanningStateLongScanning
Unknown scanning state %i
Event: %@
HomeButtonPress
ExtendedDeviceLockState
MobileKeyBagDeviceIsUnlocked
MobileKeyBagDeviceIsLocked
MobileKeyBagDeviceIsLocking
MobileKeyBagDisabled
MobileKeyBagDeviceUnlockInProgress
MobileKeyBagDeviceInGracePeriod
MobileKeyBagDeviceInAssertDelay
MobileKeyBagDeviceInBioUnlock
Unknown lock state %i
DisplayOn
DisplayOff
/SourceCache/Mesa/Mesa-152/AppleBiometricServices/BiometricKit/BiometricKitDebugLog.m
/var/mobile/Library/Logs/CrashReporter/BiometricKit
v24@0:8@"BiometricKitIdentity"16
@"NSXPCConnection"
@"<BiometricKitDelegate>"
@"BiometricKitXPCClient"
@"BiometricKitStatistics"
@"UIImage"
[25{CGRect="origin"{CGPoint="x"d"y"d}"size"{CGSize="width"d"height"d}}]
[25@"UIImage"]
{?="count"i"capa"i"items"^^{?}"unusedImageCount"i"componentCount"i"componentCapa"i"bestComponentIndex"i"bestMapiComponentIndex"i"components"^^{?}"mapiNodeAddedIndex"s"mapiNodeRemovedIndex"s"updateCount"i"structureIsInconsistent"B}
{?="nodes"[25{?="imageData"@"NSData""width"I"height"I}]}
BiometricKitXpcProtocol
BiometricKitDelegateXpcProtocol
BiometricKitXPCClient
BiometricKitTemplateInfo
BiometricKitStatistics
BiometricKit
BiometricKitDelegate
BiometricKitIdentity
NSSecureCoding
NSCoding
BiometricKitMatchInfo
BiometricKitEnrollProgressInfo
BiometricKitEnrollProgressCoordinates
BiometricKitEnrollProgressMergedComponent
BiometricKitDebugLog
Hacking.png This hardware article is a "stub", an incomplete page. Please add more content to this article and remove this tag.