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

Support environment contraints (launch constraints and library contraints) #83

Closed
indygreg opened this issue Jun 20, 2023 · 7 comments
Closed
Labels
apple-codesign apple-codesign crate and rcodesign CLI tool enhancement New feature or request

Comments

@indygreg
Copy link
Owner

There's a new blob (0xfade8181 magic) defining launch constraints. There's also a new Lightweight Code Requirements primitive related to it.

I haven't looked into it much and don't know how critical it is. Figured I'd file an issue to track implementing the missing feature.

@indygreg indygreg added enhancement New feature or request apple-codesign apple-codesign crate and rcodesign CLI tool labels Jun 20, 2023
@roblabla
Copy link
Collaborator

@indygreg indygreg changed the title Support launch requirements Support environment contraints (launch constraints and library contraints) Nov 12, 2023
@indygreg
Copy link
Owner Author

I think basic feature implementation will be pretty straightforward.

All 4 flavors of environment constraints appear to be DER encoded plists stored as separate blobs in the embedded signature. Like entitlements. So I think for an initial pass we essentially need to allow user-defined plists to define constraints and then turn them into blobs if present.

Open questions:

  • Do we need to massage the plists in any way? Video mentioned something about requiring a trust chain to Apple. Not sure if that is implicit or needs to be captured in the encoded plist DER.
  • Do we need to implement an environment constraints plist reader? Or can we treat as an opaque plist?
  • Can launch constraints get defined in Info.plist or any other magic source? I saw a reference to a SpawnConstraint in an Info.plist looking file in the video.
  • Minimum targeting constraints. Video says need minimum deployment target of macOS 13.3. But I need to test what happens if you attempt to run a Mach-O binary with embedded constraints from an older macOS machine. (I can't recall if signature validation barfs on unknown blobs or silently ignores them.)
  • Do we need to provide pre-canned ways to define convenient constraints? e.g. should we provide an easy mechanism to automatically define a constraint on or ?

@indygreg
Copy link
Owner Author

704f020101b04a30090c046363617402010030090c04636f6d7002010130270c0472657173b01f301d0c0f7465616d2d6964656e7469666965720c0a38584355553232534e3230090c0476657273020101 is an example DER encoded blob payload from the input of:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>team-identifier</key>
  <string>8XCUU22SN2</string>
</dict>
</plist>

On first glance this appears to encode identically to entitlements plist DER.

@indygreg
Copy link
Owner Author

indygreg commented Nov 12, 2023

Actually, the DER decoded plist has some extra data in there:

Application 16 (2 elem)
  INTEGER 1
  [16] (4 elem)
    SEQUENCE (2 elem)
      UTF8String ccat
      INTEGER 0
    SEQUENCE (2 elem)
      UTF8String comp
      INTEGER 1
    SEQUENCE (2 elem)
      UTF8String reqs
      [16] (1 elem)
        SEQUENCE (2 elem)
          UTF8String team-identifier
          UTF8String 8XCUU22SN2
    SEQUENCE (2 elem)
      UTF8String vers
      INTEGER 1

Looks like the encoded plist is roughly equivalent to:

<dict>
  <key>ccat</key>
  <integer>0</integer>
  <key>comp</key>
  <integer>1</integer>
  <key>reqs</key>
  <dict>
  <!-- user provided plist here -->
  </dict>
  <key>vers</key>
  <integer>1</integer>
<dict>

So we'll have to figure out what ccat, comp, and vers are.

Fortunately, codesign can be an oracle for us, just like it was for reversing the entitlements plist DER encoding.

@indygreg
Copy link
Owner Author

https://theevilbit.github.io/posts/launch_constraints_deep_dive/ has a great write-up of launch constraints internals.

@theevilbit Thanks for writing up your insights on launch constraints! I was wondering if you have any knowledge to share on the DER/plist encoding of environment constraints inside Mach-O code signatures.

From the previous comment, we see the user-provided constraints plist is joined by 3 additional keys: vers, ccat, and comp.

I'm guessing vers is a version number.

But I'm unsure what the others could be.

Perhaps ccat is constraint category? (But it seems odd to me for the binary to self-advertise its constraint category instead of the reader deducing it from the encoded requirements expression since you can't trust it is accurate. And if I define a launch constraint matching the expressions provided on https://gist.github.com/theevilbit/a6fef1e0397425a334d064f7b6e1be53 it doesn't result in ccat=1. So maybe they aren't constraint categories?)

I'm not yet sure what comp is. Compatibility version perhaps? Maybe vers and comp advertise the producing version and target version of the constraints subsystem?

So far every Mach-O with launch constraints I've come across has vers=1, ccat=0, comp=1.

@theevilbit
Copy link

Hi,

Sorry, no experience with these, but it certainly looks interesting.

Csaba

@indygreg
Copy link
Owner Author

I have this feature mostly implemented locally. I'm going to hardcode vers=1, ccat=0, comp=1 for the time being. Once we see different versions in the wild we can figure out what these fields mean and implement proper support for them.

If constraints take off in popularity, we can look into making it easier to generate pre-canned constraints policies during signing operations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
apple-codesign apple-codesign crate and rcodesign CLI tool enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants