Is there an easy way to compare signing identifiers?

I have several executables, and I want them to be able to trust each other, since they grew up together and have had many bonding adventures together.

When getting an XPC (or AppleEvents, thank you Quinn 😄) from another process, is there an easy way to find out if the other process is signed the same way the receiving process is? The code signing identity is easy to check, but of course it's also pretty easy to forge. (So this would be a variant, I think, of a question I asked a few months ago, how to see if a process is "properly" signed [which, as I said then, means it's got a valid code signature, and that is anchored "properly," which is to say something that would pass gatekeeper]. Only easier, because I really just want to say "here is my SecCode, here is this other process', are they both comparable?)

Although I guess another thing would be to see if they're both in the same app group?

is there an easy way to find out if the other process is signed the same way the receiving process is?

Yes. The special sauce here is a code signing requirement. You set up a requirement that identifies the code you care about, and then use the code signing API to check that requirement at runtime. For more details, see this post.

IMPORTANT If you’re using the XPC C API, there’s a new routine that can radically simplify this. See this post for details.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Being lazy, I was hoping for pre-canned code. 😄 I've got notes to digest about it all, at least.

Ok, @eskimo, I am too dumb to figure this out. In particular, "a requirement that identifies the code you care about" (and note that I'm not getting messages via just XPC). I've gone over the code signing documents, and there's just so much "use a requirement that specifies what you want" without showing me enough about how to get what I want...

There are multiple ways to express what I would like to do. I think I can easily break them down into two types. For these, I'm going to use B as some random process, and A as the process trying to do the checking. (A might be a network extension, an endpoint security process, or just sampling random pids so it can kill them off and see how things respond.)

  1. A wants to see if B is "legitimately signed." I believe "anchor apple or anchor apple generic" is a good starting place. But I also want to ensure that the Identifier belongs to whoever signed it. E.g., if it's signed "com.apple.sh" but was signed that way by me, that's not legitimate. Is there a way to tell that?
  2. A wants to see if B is part of its own organization. This would mean that they're signed the same way (e.g., same signing identity). (I was thinking about checking the identifier, but if A can see that B has the same signing identity as it, as long as it's not adhock 😄, that's correct.) If I use SecCodeCopySigningInformation(), with kSecCSSigningInformation, and then look for kSecCodeInfoCertificates in the dictionary... can I just check to see if they're all the same? Just a simple comparison of each element in each array?

Maybe (2) is in fact so easy I just described it. But what about (1)?

Ok, so I have verified that (2) works! I can tell that an apple event came from my own buddies by comparing the certificates, which involved some work getting the audit token and doing stuff. Most of which I'd done before. So, again, thanks Quinn :).

However, I still have no idea how to do (1).

A wants to see if B is "legitimately signed."

The problem here is one of definition. What does “legitimately signed” actually mean? There’s N categories of code on macOS:

  • Unsigned (Intel only)

  • Ad hoc signed

  • Apple code, signed by Apple

  • Development-signed third-party code

  • Mac App Store products

  • Developer ID products

Which of those do you consider legitimate?

A wants to see if B is part of its own organization.

Comparing certificates is not a good plan because it’s possible for two code items from the same organisation to be signed with different certificates. The obvious example of this is certificate expiration. If your Developer ID certificate expires and you renew it, it’ll be a different certificate.

The canonical way to test for this is:

  • Check that the code is valid Developer ID code.

  • Check that the Team ID in the leaf certificate matches your Team ID.

This can definitely be expressed in the requirements language. As to the specifics, that’s not something I’m willing to go into here on DevForums. This stuff is both complex and security critical, so I need to do proper research before I craft specific advice, and then get that advice reviewed by the relevant folks. I can only do that level of work in the context of a DTS tech support incident.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Comparing certificates is not a good plan because it’s possible for two code items from the same organisation to be signed with different certificates. The obvious example of this is certificate expiration. If your Developer ID certificate expires and you renew it, it’ll be a different certificate.

I thought about that; however, in this case, all of our executables are currently in the same bundle. They may be pulled out at some point, but I still have hopes of being able to do a drag&drop install ;). As a result, they will all be signed during the same build, and therefore with the same certificate.

I keep thinking about "legitimate" and kinda keep leaning towards maybe it's not a problem. The big thing I think I want to know is if we decide to treat processes by tld.domain.company differently, then the process that says it is that, actually is that.

As usual, you've given me more to think about which I always appreciate! If, for no other reason, it lets me refine what I'm trying to ask, and often to do.

Oh, also I was trying to figure out how to find my team id programmatically, I think.

Is there an easy way to compare signing identifiers?
 
 
Q