views:

340

answers:

2

Hi folks,

I am having a tough time finding an answer to my codesigning issues.

We have an application for Mac OS written under Cocoa. Finally - we did our codesigning, but i would like to add an extra security check - within the executable itself.

My idea is to validate the fingerprint of the certificate with which the current executable is signed when it is started. If it is missing or invalid (checked against a hardcoded hash within the application) - we shut it down.

So far, i haven't been able how to obtain the certificate used to codesign the executable programatically and check its data.

Does anyone have a clue on how to do this?

Thank you veery much! Martin K.

+3  A: 

If you're targeting 10.6+ you can use the code signing functions in the Security framework (documentation), in particular SecCodeCheckValidity. Otherwise, the source code to the code signing system is in libsecurity_codesigning.

Since you're using the code signature to authenticate your code you should also validate the designated requirement with SecCodeCopyDesignatedRequirement.

vt
+1  A: 

Thanks friend!

I managed to do it for 10.6 with the new functionality but the problem is i am targeting 10.5 and 10.6, at least until some time passes.

I have to throw some more time into libsecurity_codesigning soon so this can be completed for 10.5 also.

But, for people who are looking for ready solutions around here, here is what i ended up with:

SecStaticCodeRef ref = NULL;

NSURL * url = [NSURL URLWithString:[[NSBundle mainBundle] executablePath]];

OSStatus status;

// obtain the cert info from the executable status = SecStaticCodeCreateWithPath((CFURLRef)url, kSecCSDefaultFlags, &ref);

if (ref == NULL) exit(EXIT_STATUS_ON_BAD_CODE_SIGNATURE); if (status != noErr) exit(EXIT_STATUS_ON_BAD_CODE_SIGNATURE);

SecRequirementRef req = NULL;

// this is the public SHA1 fingerprint of the cert match string NSString * reqStr = [NSString stringWithFormat:@"%@ %@ = %@%@%@", @"certificate", @"leaf", @"H\"66875745923F01", @"F122B387B0F943", @"X7D981183151\"" ];

// create the requirement to check against status = SecRequirementCreateWithString((CFStringRef)reqStr, kSecCSDefaultFlags, &req);

if (status != noErr) exit(EXIT_STATUS_ON_BAD_CODE_SIGNATURE); if (req == NULL) exit(EXIT_STATUS_ON_BAD_CODE_SIGNATURE);

status = SecStaticCodeCheckValidity(ref, kSecCSCheckAllArchitectures, req);

if (status != noErr) exit(EXIT_STATUS_ON_BAD_CODE_SIGNATURE);

CFRelease(ref); CFRelease(req);

LogDebug(@"Code signature was checked and it seems OK");

Martin Kovachev
Thanks for sharing!BTW, I assume that NSURL * url = [[NSBundle mainBundle] bundleURL] in the second line can be used to check a validity of the whole bundle including Resources and Executables. Is it correct?
Stream