Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

Supporting development of ACME - Freshness code question

It seems like there are some "mixed messages" out there about what should be in OID 1.2.840.113635.100.8.11.1 in the attestation cert.

Is it just a SHA256 hash of the nonce issued by the ACME server?

The MDM profile yaml says:

"In the attestation certificate the value of the freshness code OID matches the nonce specified by the ACME server via the ACME protocol."

I'm hoping the difficulty we're seeing is down to the certificate being created once (and not again for 7 days). Otherwise, we're not decoding/understanding the OID's contents properly.

Thanks.

First some background: There are two different features that use Managed Device Attestation: ACME attestation and DeviceInformation attestation.

When you mention 7 days, that likely refers to the rate limit that applies to DeviceInformation attestation. ACME attestation only generates an attestation at the time the key is initially generated, so there's no 7 day rate limit.

The freshness code OID is also different between the two features. For DeviceInformation attestation the freshness code is the value from the DeviceInformation command's DeviceAttestationNonce key. For ACME attestation, it's a SHA256 hash of the nonce specified by the ACME server in its response containing the device-attest-01 challenge.

When the documentation uses the term "matches", it means that the ACME server should hash the nonce it previously sent and compare that to the value in the freshness code OID.

Thank you.

I think this is an issue that only occurs during the development stage, if you don't have the server side validation step in place when you start testing the previous steps.

So, I extracted the attestation certificate (to view with the UI) which had a timestamp of Mon May 5th at 21:18 GMT+1. My Mac is sending this same certificate for every request. I take it then that this won't change until there is a change to the information it contains, e.g. a software update, or it expires?

I can't match the OID to any of the nonces that the ACME server sent that day. I'm not sure why there is such a discrepancy between the certificate start timestamp and when the actual transactions took place. I see a nonce generated at 19:16 and then another at 23:24.

Is there something about the encoding of the OID that we're missing? The hex we see in the certificate, is it directly the SHA256 hash of the relevant nonce?

So, if the nonce sent was:

SS2sSl1PtspvFZ08kNtzKd

Then the hex I should see in the certificate would be:

BDE0169F46D9B2CF2D3ED100437AD41DA8B857B4A87FF3FE3F2DF836C91A696E

I updated the Mac to 24F74 yesterday. So, there is a new attestation certificate today. Again, the contents of the freshness code OID do not match any hash of the nonces sent by the server.

Does macOS store the nonce in a retrievable way or can we put something into debug mode and have it record what it's sending and receiving from the ACME server? It's like something is being lost in translation.

The developer figured it out. It doesn't match "the nonce" because Apple isn't using "the nonce" for ACME.

Apple is using the challenge token. The challenge token hashes to an exact match of the freshness code OID.

From device-attest-01:

{ "type": "device-attest-01", "url": "https://example.com/acme/chall/Rg5dV14Gh1Q", "status": "pending", "token": "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA" }

{ "protected": base64url({ "alg": "ES256", "kid": "https://example.com/acme/acct/evOfKhNU60wg", "nonce": "SS2sSl1PtspvFZ08kNtzKd", "url": "https://example.com/acme/chall/Rg5dV14Gh1Q" }), "payload": base64url({ "attObj": base64url(/* WebAuthn attestation object */), }), "signature": "Q1bURgJoEslbD1c5...3pYdSMLio57mQNN4" }

It may be the case that the term "nonce" is being used too loosely, which unfortunately is a dangerous thing when it has an actual definition in this protocol. We lost the best part of a week to this.

ACME YAML needs to be corrected.

I can't quite re-find the other instances I thought I saw claiming it's a hash of the nonce.

I would suggest this is made clearer in the published documentation. For example, this Apple Platform security guide should simply address the fact that it's a SHA256 hash of the token from the device-attest-01 challenge. I would have perceived the freshness code to be this final hash, whereas this document appears to describe the token as the freshness code that just happens to be hashed.

I don't know if the reason we got here was because you are using the relevant nonce for the DeviceInformation query that an MDM server can generate but it would appear to be vital that there is a clear distinction between the resultant 1.2.840.113635.100.8.11.1 for an ACME request with managed device attestation.

There is also the documentation on Webauthn which my developer colleague suggests is misleading now, although may have been accurate at one time. Is this now inaccurate too?

[There is also the documentation on Webauthn which my developer colleague suggests is misleading now, although may have been accurate at one time. Is this now inaccurate too?

https://www.w3.org/TR/webauthn-2/#sctn-apple-anonymous-attestation](https://www.w3.org/TR/webauthn-2/#sctn-apple-anonymous-attestation)

Supporting development of ACME - Freshness code question
 
 
Q