Verifying app's signature by code [duplicate] - objective-c

This question already has answers here:
How to obtain codesigned application certificate info
(2 answers)
Closed 8 years ago.
I have app signed. I created an identity and used codesign to sign my app as per Apple's Code Signing Guide.
Now, how do I check the signature from within my application?
I need to verify this on Cocoa apps (Objective-C) and apps written in C.

You could use NSTask and run "codesign --verify" and check the exit status. Of corse if the program was altered it could be altered to remove the check, so I'm not sure what that buys you.
If you are not worried about directed tampering (like the kind that might remove your check of the signature) you can use the codesign "kill" option, if you do merely executing means the signature is valid (at least for all pages that have been executed so far...but if a not-yet-resident page has been tampered with you will get killed when that one is read in anyway).
Maybe if you could explain a little more about why you want to verify the signature a better answer could be formed.

Note: Currently MacOS X does not verify signed code prior to execution. This may be different for sandboxed code, and it would seem sensible that it is otherwise anybody could edit the entitlements.
To check an applications signature from within the application itself you use the Code Signing Services. In particular look at SecCodeCheckValidity. The code to do the checking is not long, but there is quite a bit to understand so I won't give a code sample - you need to read and understand the documentation.
Checking the signature allows your application to detect changes to its code & resources and report it is "damaged" (it may well be, not all changes are malicious) and refuse to run. Adding such code does not of course guarantee your code is not damaged, but certainly it does raise the barrier higher against intentional damage (and if MacOS X starts doing the check itself then there will be a big win).

The way signiture verification is implemented on iOS is that when an application is being launched, the launchd daemon decrypts the binary using that device's specific private key (this is why you can't just decompile apps or copy-paste them from one device to another), if the decryption fails, the application fails to launch.
The native tools that do this are not available within applications due to the iOS sandboxing.
If you're simply attempting to track if someone has modified your binary, you can perform an MD5 or SHA1 hash of it, store it in NSUserDefaults and compare it at each app start. If the hash changes between executions you know it has been modified (possibly by a legitimate application update or possibly nefariously.)
Here's an example on how to get the hash of an NSData.
The binary file you're looking for is: AppName.app/AppName

Related

How to test whether credentials are valid?

I could not find in the docs the canonical way to check whether given credentials can be used to clone given repository. There is an issue that suggests that one way may be to check whether git_cred_acquire_cb() is called more than once. Can somebody confirm this or point out another way?
This is the suggested way. If your credential callback is called a second time, then the first credentials that you provided were not accepted. This pattern is primarily useful for UI applications (popping up a modal username/password dialog).
You can use the callback data to count the number of times you were called.
I realize that this may be imperfect, especially if you're binding libgit2 in another language. Setting up a data struct on the heap and managing its lifecycle is not always trivial.
You may also be able to just provide credentials and wait for a GIT_EAUTH return code. In theory, the various transport mechanisms should give up after several authentication failures no matter what. However, we found at least one bug in the 0.27 releases that would loop forever. Hence the suggestion.

Enable Transfer Acceleration for AWS SDK for macos

Disclaimer: I posted this originally on Code Review but as the code does not currently work I was suggested to post at SO instead.
I have converted the official AWS SDK iOS (v 2.5.0) framework (focusing on S3) to macOS and everything is working as expected with uploads and downloads. However, I wanted to also enable Transfer Acceleration for S3 using AWSTransferManager. I know that you can enable Transfer Acceleration (TA) using the AWSTransferUtility, but that utility uses pre-signed requests that are valid for only 50 minutes (useful for iOS but not macOS). I would like to be able to transfer files that are large and can take hours even when using Transfer Acceleration.
I have edited the original code from AWS to enable TA for AWSTransferManager, however, I still can not get this to work properly as the final signing of the upload/download request fails. The error message is:
Message=The request signature we calculated does not match the signature you provided. Check your key and signing method.}]
For the most part, I have edited the files AWSSignature, AWSS3TransferManager, and AWSService (AWSServiceConfiguration). I think that the signing error occurs because I am editing a path, or URL without correctly code signing the change (probably in AWSSignature.m). As I am uncertain as to where my code breaks, I have created a repository with all of the AWS SKD macOS files required to compile the framework including a unit test. If I run the test initializing the call to AWSServiceConfiguration with:
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc]initWithRegion:[region aws_regionTypeValue] credentialsProvider:credentialsProvider
accelerateModeEnabled:#(NO)
bucketName:self.testBucketName];
Then everything works as expected and the test file uploads and downloads correctly. However, if I try to turn transfer acceleration on (I have already made sure that my bucket has acceleration enabled), then it fails with the code signing error above.
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc]initWithRegion:[region aws_regionTypeValue] credentialsProvider:credentialsProvider
accelerateModeEnabled:#(YES)
bucketName:self.testBucketName];
In fact it seems like the test script is trying to upload a file much larger than what the testfile (3 Mb) really is. I assume my error is related to the signing of the URL body in some way as the size of the file seems wrong.
I know that finding this error requires a bigger effort than what is usually expected at SO and it is not something many will throw themselves at (but hopefully some) as it involves very complex code and it is time-consuming. However, I do believe that if we could make this work then many can find the framework for AWS SKD for macOS + Transfer Acceleration very useful.
I hope you will take a look at try to identify what may be my problem breaking the code signing.
All code for the framework+test example is available here: https://github.com/trondkr/aws-sdk-macos-TA. To run the unit test you need to provide the secret key and access id to your AWS S3 and the name of a bucket that has transfer acceleration enabled.
Thanks. Cheers, Trond

winVerifyTrust is crushed when the sys time is not accurate

I am developing a C# .net 3.5 application.
I am trying to verify a file signature by using WinVerifyTrust.
I also want a revocation check so I set the following parametrs of the WinTrustData.
FdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
DwProvFlags = WTD_REVOCATION_CHECK_CHAIN;
everyting works OK except when I move the system time forward, then the method is stuck and winVerifyTrust return an answer only after a very long while.
Do you have any idea why it is happening and how can I prevent it?
Thanks
This might be happening since revocation information, whether CRL or OCSP has a thisUpdate field which tells when the revocation information becomes valid. The OS might have downloaded the revocation information and has to block till the time it becomes valid for use.

Why is SFHFKeychainUtils failing with error errSecAuthFailed in a Cocoa app?

The debug build of some code utilizing SFHFKeychainUtils that is working without complaint on the mac which I'm developing on is triggering an error on another mac:
The code makes use of the following methods provided by SFHFKeychainUtils:
+[SFHFKeychainUtils getPasswordForUsername:andServiceName:accessGroup:error:]
+[SFHFKeychainUtils storeUsername:andPassword:forServiceName:accessGroup:updateExisting:updateExisting:error:]
A password is added for a username using +[SFHFKeychainUtils storeUsername:andPassword:forServiceName:accessGroup:updateExisting:updateExisting:error:]. Some time later, an attempt is made to retrieve the password using +[SFHFKeychainUtils getPasswordForUsername:andServiceName:accessGroup:error:]. However, this method is returning the error; its domain is SFHFKeychainUtilsErrorDomain and its code is -25293 (so it is errSecAuthFailed). This error is only returned when a password is in fact stored in the keychain (or at least when it is visible from Keychain Access).
Why is this taking place?
The problem is a lack of code signing. Code signing is required in order for the second machine to access the keychain. The fix was to enable code signing for the debug build.

Gaining Root Access w/ Elevated Helper & SMJobBless

I'm working on something that needs to install files periodically into a folder in /Library.
I understand that in the past I could have used one of the Authenticate methods but those have since been deprecated in 10.7.
What I've understood from my reading so far:
I should create a helper that somehow gets authenticated and have that helper do all of the moving tasks. I've taken a look at some of the sample code, including some involving XPC and one called Elevator but I'm a bit confused.
A lot of it seems to deal with setting up some sort of client / server model but I'm not sure how this would translate into me actually installing my files into the correct directories. Most of the examples are just passing strings.
My question simply: How can I create my folder in /Library programmatically and periodically write files to it while only prompting the user for a password ONCE and never again? I'm really not sure how to approach this and there doesn't seem to be much documentation.
You are correct that there isn't much documentation for this. You'll basically write another app, the helper app, which will get installed with SMJobBless(). Not surprisingly,
the tricky part here is the code signing. The least obvious part for me was that the SMAuthorizedClients and SMPrivilegedExecutables entries in the info plist files of each app are dependent on the identity/certificate that you used to sign the app with. There is also a trick with the compiler/linker to getting the info plist file compiled into the helper tool, which will be a single executable file, rather than a bundle.
Once you get the helper app up and running then you have to devise a way to communicate with it since these are two different processes. XPC is one option, perhaps the easiest. XPC is typically used with server processes, but what you are using here is the communication side of XPC only. Basically it passes dictionaries back and forth between the two apps. Create a standard format for the dictionary. I used #"action", #"source", and #"destination" with 3 different action values, #"filemove", #"filecopy", and #"makedirectory". Those are the 3 things that my helper app can do and I can easily add more if necessary.
The helper app will basically setup the XPC connection and event handler stuff and wait for a connection and commands. The commands will just be a dictionary so you check for the appropriate keys/values and do whatever.
I can provide more details and code if you need more help, but this question is 9 months old so I don't want to waste time giving you details you've already figured out.