Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Evidence Source: NFC Reader #380

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions ControlPlane.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
6D6857041A2046FD00803A34 /* NFCMirrorEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D6857031A2046FD00803A34 /* NFCMirrorEvidenceSource.m */; };
732A58DF1484300A0011019C /* ShellScriptEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 732A58DE1484300A0011019C /* ShellScriptEvidenceSource.m */; };
739492E2146B8018003C94DE /* DisplaySleepTimeAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 739492E1146B8018003C94DE /* DisplaySleepTimeAction.m */; };
73A5092F14849405007D22B5 /* ShellScriptRule.xib in Resources */ = {isa = PBXBuildFile; fileRef = 73A5092714849405007D22B5 /* ShellScriptRule.xib */; };
Expand Down Expand Up @@ -307,6 +308,8 @@
29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
32CA4F630368D1EE00C91783 /* ControlPlane_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ControlPlane_Prefix.pch; path = Source/ControlPlane_Prefix.pch; sourceTree = "<group>"; };
6D6857021A2046FD00803A34 /* NFCMirrorEvidenceSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NFCMirrorEvidenceSource.h; path = Source/NFCMirrorEvidenceSource.h; sourceTree = "<group>"; };
6D6857031A2046FD00803A34 /* NFCMirrorEvidenceSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NFCMirrorEvidenceSource.m; path = Source/NFCMirrorEvidenceSource.m; sourceTree = "<group>"; };
732A58DD1484300A0011019C /* ShellScriptEvidenceSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ShellScriptEvidenceSource.h; path = Source/ShellScriptEvidenceSource.h; sourceTree = "<group>"; };
732A58DE1484300A0011019C /* ShellScriptEvidenceSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ShellScriptEvidenceSource.m; path = Source/ShellScriptEvidenceSource.m; sourceTree = "<group>"; };
732A58E91484311C0011019C /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "pt-PT"; path = "pt-PT.lproj/CoreLocationRule.xib"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1011,6 +1014,8 @@
8DE428FA0C5084D00073499A /* TimeOfDayEvidenceSource.m */,
8D35A34C0BBBA0CB006ACBB0 /* USBEvidenceSource.h */,
8D35A34D0BBBA0CB006ACBB0 /* USBEvidenceSource.m */,
6D6857021A2046FD00803A34 /* NFCMirrorEvidenceSource.h */,
6D6857031A2046FD00803A34 /* NFCMirrorEvidenceSource.m */,
);
name = "Concrete Evidence Sources";
sourceTree = "<group>";
Expand Down Expand Up @@ -1493,6 +1498,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6D6857041A2046FD00803A34 /* NFCMirrorEvidenceSource.m in Sources */,
DAF2257E15ABD8CD003A8030 /* DisplayBrightnessAction.m in Sources */,
DAE893EE1454FFFB005FA13C /* ToggleFirewallAction.m in Sources */,
DAF36ECA143E7C5700350991 /* CoreLocationSource.m in Sources */,
Expand Down
1 change: 1 addition & 0 deletions Source/CPController.m
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ + (void)initialize {
[appDefaults setValue:@"" forKey:@"DefaultContext"];
[appDefaults setValue:[NSNumber numberWithBool:YES] forKey:@"EnablePersistentContext"];
[appDefaults setValue:@"" forKey:@"PersistentContext"];
[appDefaults setValue:[NSNumber numberWithBool:NO] forKey:@"EnableNFCMirrorEvidenceSource"];

// Advanced
[appDefaults setValue:[NSNumber numberWithBool:NO] forKey:@"ShowAdvancedPreferences"];
Expand Down
3 changes: 3 additions & 0 deletions Source/EvidenceSource.m
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ - (NSArray *)getEvidenceSourcePlugins;
#import "RunningApplicationEvidenceSource.h"
#import "TimeOfDayEvidenceSource.h"
#import "USBEvidenceSource.h"
#import "NFCMirrorEvidenceSource.h"
#import "CoreWLANEvidenceSource.h"
#import "ShellScriptEvidenceSource.h"
#import "SleepEvidenceSource.h"
Expand Down Expand Up @@ -445,6 +446,7 @@ - (id)init {
[FireWireEvidenceSource class],
[MonitorEvidenceSource class],
[USBEvidenceSource class],
[NFCMirrorEvidenceSource class],
[AudioOutputEvidenceSource class],
//[HostAvailabilityEvidenceSource class],
[BluetoothEvidenceSource class],
Expand Down Expand Up @@ -496,6 +498,7 @@ - (id)init {
NSLocalizedString(@"Sleep/Wake", @"Evidence source");
NSLocalizedString(@"TimeOfDay", @"Evidence source");
NSLocalizedString(@"USB", @"Evidence source");
NSLocalizedString(@"NFC Mirror", @"Evidence source");
NSLocalizedString(@"WiFi using CoreWLAN", @"Evidence source");
}

Expand Down
46 changes: 46 additions & 0 deletions Source/NFCMirrorEvidenceSource.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// NFCMirrorEvidenceSource.h
// ControlPlane
//
// Created by Eric Betts on 11/21/14.
//
//

#import "GenericEvidenceSource.h"
#import <IOKit/hid/IOHIDLib.h>
#import <IOKit/hid/IOHIDKeys.h>
#import <IOKit/hid/IOHIDManager.h>

#define UPSIDE_DOWN 5
#define RIGHTSIDE_UP 4
#define TAG_EVENT 2
#define MIRROR_REPORT_LENGTH 64
#define TAG_ON 1
#define TAG_OFF 2

@interface NFCMirrorEvidenceSource : GenericEvidenceSource {
NSLock *lock;

NSMutableArray *tags;
}

@property IOHIDDeviceRef mirror;

- (id)init;
- (void)dealloc;

- (void)start;
- (void)stop;

- (void)doUpdate;
- (void)clearCollectedData;

- (NSString *)name;
- (BOOL)doesRuleMatch:(NSDictionary *)rule;
- (NSString *)getSuggestionLeadText:(NSString *)type;
- (NSArray *)getSuggestions;

- (NSArray *)getTags;


@end
261 changes: 261 additions & 0 deletions Source/NFCMirrorEvidenceSource.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
//
// NFCMirrorEvidenceSource.m
// ControlPlane
//
// Created by Eric Betts on 11/21/14.
//
//

#import "NFCMirrorEvidenceSource.h"

@implementation NFCMirrorEvidenceSource

- (id)init {
if (!(self = [super init]))
return nil;

lock = [[NSLock alloc] init];
tags = [[NSMutableArray alloc] init];

return self;
}

- (void)dealloc {
[lock release];
[tags release];

[super dealloc];
}

#pragma mark C callbacks

void MyInputCallback(void *inContext, IOReturn result, void *sender,
IOHIDReportType type, uint32_t reportID, uint8_t *report,
CFIndex reportLength) {
// process device response buffer (report) here
NFCMirrorEvidenceSource *self = (__bridge NFCMirrorEvidenceSource *)inContext;
NSString *tagID = @"";
int interface = report[0];
int method = report[1];
// int correlationID = report[2] * 255 + report[3];
int dataLength = report[4];
uint8_t *data = report + 5;
if (reportLength == 0 || report[1] == 0) {
return;
} else if (reportLength == MIRROR_REPORT_LENGTH) {
if (interface == TAG_EVENT) {
tagID = [self bytesToString:data andLength:dataLength];
[self handleTag:tagID forState:method];
}
}
}

static void Handle_DeviceMatchingCallback(void *inContext, IOReturn inResult,
void *inSender,
IOHIDDeviceRef inIOHIDDeviceRef) {
@autoreleasepool {
NFCMirrorEvidenceSource *self =
(__bridge NFCMirrorEvidenceSource *)inContext;
self.mirror = inIOHIDDeviceRef;
long reportSize = 0;
uint8_t *report;
(void)IOHIDDevice_GetLongProperty(
inIOHIDDeviceRef, CFSTR(kIOHIDMaxInputReportSizeKey), &reportSize);
if (reportSize) {
report = calloc(1, reportSize);
if (report) {
IOHIDDeviceRegisterInputReportCallback(
inIOHIDDeviceRef, report, reportSize, MyInputCallback, inContext);
NSLog(@"%s", __PRETTY_FUNCTION__);
//Default to choreo off so I can use at work
//[self setChoreography:NO];
}
}
}
}

static void Handle_DeviceRemovalCallback(void *inContext, IOReturn inResult,
void *inSender,
IOHIDDeviceRef inIOHIDDeviceRef) {
@autoreleasepool {
NFCMirrorEvidenceSource *self =
(__bridge NFCMirrorEvidenceSource *)inContext;
self.mirror = nil;
NSLog(@"%s", __PRETTY_FUNCTION__);
}
}

- (NSString *)description {
return NSLocalizedString(@"Create rules based on presence of NFC tag.", @"");
}

- (NSString *)name {
return @"NFCMirror";
}

- (NSString *)getSuggestionLeadText:(NSString *)type {
return NSLocalizedString(@"The presence of", @"In rule-adding dialog");
}


- (NSArray *)getSuggestions
{
NSMutableArray *arr = [NSMutableArray array];

[lock lock];
NSEnumerator *en = [tags objectEnumerator];
NSString *aTag;
while ((aTag = [en nextObject])) {
[arr addObject:@{@"type": @"NFCMirror", @"parameter": aTag, @"description": aTag}];
}
[lock unlock];

return arr;
}

- (NSString *)friendlyName {
return NSLocalizedString(@"NFC Tag", @"");
}

- (BOOL)doesRuleMatch:(NSDictionary *)rule
{
BOOL match = NO;
NSString *inputTag = rule[@"parameter"];
[lock lock];
match = [tags containsObject:inputTag];
[lock unlock];
return match;
}

- (void)start {
if (running) {
return;
}

const long vendorId = 0x1da8;
const long productId = 0x1301;
NSDictionary *dict = @{
@kIOHIDProductIDKey: @(productId),
@kIOHIDVendorIDKey: @(vendorId)
};
IOHIDManagerRef managerRef =
IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
IOHIDManagerScheduleWithRunLoop(managerRef, CFRunLoopGetCurrent(),
kCFRunLoopDefaultMode);
IOHIDManagerOpen(managerRef, 0L);
IOHIDManagerSetDeviceMatching(managerRef, (__bridge CFDictionaryRef)dict);
IOHIDManagerRegisterDeviceMatchingCallback(
managerRef, Handle_DeviceMatchingCallback, (__bridge void *)(self));
IOHIDManagerRegisterDeviceRemovalCallback(
managerRef, Handle_DeviceRemovalCallback, (__bridge void *)(self));

running = YES;
}

- (void)stop {
if (!running) {
return;
}
[self setDataCollected:NO];
// remove callbacks?

running = NO;
}

- (NSArray *)getTags {
NSArray *arr;

[lock lock];
arr = [NSArray arrayWithArray:tags];
[lock unlock];

return arr;
}

- (void)doUpdate
{
#ifdef DEBUG_MODE
NSLog(@"%@ >> found %ld tags", [self class], (long) [tags count]);
#endif
}

- (void)clearCollectedData
{
[lock lock];
[tags removeAllObjects];
[self setDataCollected:NO];
[lock unlock];
}

+ (BOOL)isEvidenceSourceApplicableToSystem {
return YES; //Figure out how to check currently connected USB devices
}

- (void)handleTag:(NSString *)tagID forState:(int)state {
NSLog(@"\t\t\t\t%s %@ %i", __PRETTY_FUNCTION__, tagID, state);
[self setDataCollected:YES];
if (state == TAG_ON) {
[lock lock];
[tags addObject:tagID];
[lock unlock];
} else if (state == TAG_OFF) {
[lock lock];
[tags removeObject:tagID];
[lock unlock];
}
}

- (NSString *)bytesToString:(uint8_t *)bytes andLength:(CFIndex)length {
NSMutableString *result =
[NSMutableString stringWithCapacity:2 * length + length - 1];
for (int i = 0; i < length; i++) {
[result appendFormat:@"%02X", bytes[i]];
}
return [result lowercaseString]; // Result is auto-released
}

- (void)setChoreography:(NSNotification *)notification {
NSDictionary *userInfo = notification.userInfo;
NSNumber *state = userInfo[@"state"];
size_t bufferSize = 64;
long reportSize = 0;
uint8_t *outputBuffer = malloc(bufferSize);
memset(outputBuffer, 0, bufferSize);
// Interface
outputBuffer[0] = 0x03;
// CID
outputBuffer[2] = 0;
outputBuffer[3] = 0;
// length
outputBuffer[4] = 0;

if ([state boolValue]) {
NSLog(@"Choreography on");
// Method
outputBuffer[1] = 0x03;
} else {
NSLog(@"Choreography off");
// Method
outputBuffer[1] = 0x01;
}
IOHIDDeviceSetReport(self.mirror, kIOHIDReportTypeOutput, reportSize,
outputBuffer, bufferSize);
free(outputBuffer);
}

static Boolean IOHIDDevice_GetLongProperty(IOHIDDeviceRef inDeviceRef,
CFStringRef inKey, long *outValue) {
Boolean result = FALSE;
CFTypeRef tCFTypeRef = IOHIDDeviceGetProperty(inDeviceRef, inKey);
if (tCFTypeRef) {
// if this is a number
if (CFNumberGetTypeID() == CFGetTypeID(tCFTypeRef)) {
// get its value
result = CFNumberGetValue((CFNumberRef)tCFTypeRef, kCFNumberSInt32Type,
outValue);
}
}
return result;
}

@end