iOS 16 beta 1 support

This commit is contained in:
Brandon Weeks 2022-06-06 21:09:31 -07:00
parent 77c6d10fd6
commit 7e1b0bebd9
4 changed files with 82 additions and 1 deletions

View file

@ -33,7 +33,7 @@ func (n *NewOrderRequest) Validate() error {
return acme.NewError(acme.ErrorMalformedType, "identifiers list cannot be empty")
}
for _, id := range n.Identifiers {
if !(id.Type == acme.DNS || id.Type == acme.IP || id.Type == acme.PermanentIdentifier) {
if !(id.Type == acme.DNS || id.Type == acme.IP || id.Type == acme.PermanentIdentifier || id.Type == acme.CA) {
return acme.NewError(acme.ErrorMalformedType, "identifier type unsupported: %s", id.Type)
}
if id.Type == acme.IP && net.ParseIP(id.Value) == nil {
@ -375,6 +375,8 @@ func challengeTypes(az *acme.Authorization) []acme.ChallengeType {
}
case acme.PermanentIdentifier:
chTypes = []acme.ChallengeType{acme.DEVICEATTEST01}
case acme.CA:
chTypes = []acme.ChallengeType{acme.APPLEATTEST01}
default:
chTypes = []acme.ChallengeType{}
}

View file

@ -13,11 +13,13 @@ import (
"encoding/base64"
"encoding/hex"
"encoding/json"
"encoding/pem"
"errors"
"fmt"
"io"
"net"
"net/url"
"os"
"reflect"
"strings"
"time"
@ -41,6 +43,7 @@ const (
TLSALPN01 ChallengeType = "tls-alpn-01"
// DEVICEATTEST01 is the device-attest-01 ACME challenge type
DEVICEATTEST01 ChallengeType = "device-attest-01"
APPLEATTEST01 ChallengeType = "client-01"
)
// Challenge represents an ACME response Challenge type.
@ -84,6 +87,8 @@ func (ch *Challenge) Validate(ctx context.Context, db DB, jwk *jose.JSONWebKey,
return tlsalpn01Validate(ctx, ch, db, jwk)
case DEVICEATTEST01:
return deviceAttest01Validate(ctx, ch, db, jwk, payload)
case APPLEATTEST01:
return appleAttest01Validate(ctx, ch, db, jwk, payload)
default:
return NewErrorISE("unexpected challenge type '%s'", ch.Type)
}
@ -416,6 +421,68 @@ func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose
return nil
}
type ApplePayload struct {
AttObj string `json:"attObj"`
Error string `json:"error"`
}
func appleAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWebKey, payload []byte) error {
var p ApplePayload
if err := json.Unmarshal(payload, &p); err != nil {
return WrapErrorISE(err, "error unmarshalling JSON")
}
fmt.Fprintf(os.Stderr, "p.AttObj: %v\n", p.AttObj)
attObj, err := base64.RawURLEncoding.DecodeString(p.AttObj)
if err != nil {
return WrapErrorISE(err, "error base64 decoding attObj")
}
att := AttestationObject{}
if err := cbor.Unmarshal(attObj, &att); err != nil {
return WrapErrorISE(err, "error unmarshalling CBOR")
}
if att.Format != "apple" {
return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatement,
"unexpected attestation object format"))
}
x5c, x509present := att.AttStatement["x5c"].([]interface{})
if !x509present {
return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatement,
"x5c not present"))
}
attCertBytes, valid := x5c[0].([]byte)
if !valid {
return storeError(ctx, db, ch, true, NewError(ErrorRejectedIdentifierType,
"error getting certificate from x5c cert chain"))
}
attCert, err := x509.ParseCertificate(attCertBytes)
if err != nil {
return WrapErrorISE(err, "error parsing AK certificate")
}
b := &pem.Block{
Type: "CERTIFICATE",
Bytes: attCert.Raw,
}
pem.Encode(os.Stderr, b)
// Update and store the challenge.
ch.Status = StatusValid
ch.Error = nil
ch.ValidatedAt = clock.Now().Format(time.RFC3339)
if err := db.UpdateChallenge(ctx, ch); err != nil {
return WrapErrorISE(err, "error updating challenge")
}
return nil
}
// serverName determines the SNI HostName to set based on an acme.Challenge
// for TLS-ALPN-01 challenges RFC8738 states that, if HostName is an IP, it
// should be the ARPA address https://datatracker.ietf.org/doc/html/rfc8738#section-6.

View file

@ -19,6 +19,8 @@ const (
ErrorAccountDoesNotExistType ProblemType = iota
// ErrorAlreadyRevokedType request specified a certificate to be revoked that has already been revoked
ErrorAlreadyRevokedType
// ErrorBadAttestation WebAuthn attestation statement could not be verified
ErrorBadAttestationStatement
// ErrorBadCSRType CSR is unacceptable (e.g., due to a short key)
ErrorBadCSRType
// ErrorBadNonceType client sent an unacceptable anti-replay nonce

View file

@ -5,7 +5,9 @@ import (
"context"
"crypto/x509"
"encoding/json"
"encoding/pem"
"net"
"os"
"sort"
"strings"
"time"
@ -25,6 +27,7 @@ const (
DNS IdentifierType = "dns"
// DNS is the ACME dns identifier type
PermanentIdentifier IdentifierType = "permanent-identifier"
CA IdentifierType = "ca"
)
// Identifier encodes the type that an order pertains to.
@ -146,6 +149,12 @@ func (o *Order) Finalize(ctx context.Context, db DB, csr *x509.CertificateReques
return NewErrorISE("unexpected status %s for order %s", o.Status, o.ID)
}
b := &pem.Block{
Type: "CERTIFICATE REQUEST",
Bytes: csr.Raw,
}
pem.Encode(os.Stderr, b)
// canonicalize the CSR to allow for comparison
csr = canonicalize(csr)
@ -229,6 +238,7 @@ func (o *Order) sans(csr *x509.CertificateRequest) ([]x509util.SubjectAlternativ
case PermanentIdentifier:
orderPIDs[indexPID] = n.Value
indexPID++
case CA:
default:
return sans, NewErrorISE("unsupported identifier type in order: %s", n.Type)
}