forked from TrueCloudLab/certificates
Reneame attestation statement error
This commit is contained in:
parent
3cd72ac72a
commit
08815c5e90
2 changed files with 27 additions and 27 deletions
|
@ -359,7 +359,7 @@ func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose
|
||||||
if len(data.Nonce) != 0 {
|
if len(data.Nonce) != 0 {
|
||||||
sum := sha256.Sum256([]byte(ch.Token))
|
sum := sha256.Sum256([]byte(ch.Token))
|
||||||
if subtle.ConstantTimeCompare(data.Nonce, sum[:]) != 1 {
|
if subtle.ConstantTimeCompare(data.Nonce, sum[:]) != 1 {
|
||||||
return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatement, "challenge token does not match"))
|
return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatementType, "challenge token does not match"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,7 +368,7 @@ func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose
|
||||||
//
|
//
|
||||||
// Note: We might want to use an external service for this.
|
// Note: We might want to use an external service for this.
|
||||||
if data.UDID != ch.Value && data.SerialNumber != ch.Value {
|
if data.UDID != ch.Value && data.SerialNumber != ch.Value {
|
||||||
return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatement, "permanent identifier does not match"))
|
return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatementType, "permanent identifier does not match"))
|
||||||
}
|
}
|
||||||
case "step":
|
case "step":
|
||||||
data, err := doStepAttestationFormat(ctx, ch, jwk, &att)
|
data, err := doStepAttestationFormat(ctx, ch, jwk, &att)
|
||||||
|
@ -388,10 +388,10 @@ func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose
|
||||||
//
|
//
|
||||||
// Note: We might want to use an external service for this.
|
// Note: We might want to use an external service for this.
|
||||||
if data.SerialNumber != ch.Value {
|
if data.SerialNumber != ch.Value {
|
||||||
return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatement, "permanent identifier does not match"))
|
return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatementType, "permanent identifier does not match"))
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatement, "unexpected attestation object format"))
|
return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatementType, "unexpected attestation object format"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update and store the challenge.
|
// Update and store the challenge.
|
||||||
|
@ -447,7 +447,7 @@ func doAppleAttestationFormat(ctx context.Context, ch *Challenge, db DB, att *At
|
||||||
|
|
||||||
x5c, ok := att.AttStatement["x5c"].([]interface{})
|
x5c, ok := att.AttStatement["x5c"].([]interface{})
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, NewError(ErrorBadAttestationStatement, "x5c not present")
|
return nil, NewError(ErrorBadAttestationStatementType, "x5c not present")
|
||||||
}
|
}
|
||||||
if len(x5c) == 0 {
|
if len(x5c) == 0 {
|
||||||
return nil, NewError(ErrorRejectedIdentifierType, "x5c is empty")
|
return nil, NewError(ErrorRejectedIdentifierType, "x5c is empty")
|
||||||
|
@ -455,22 +455,22 @@ func doAppleAttestationFormat(ctx context.Context, ch *Challenge, db DB, att *At
|
||||||
|
|
||||||
der, ok := x5c[0].([]byte)
|
der, ok := x5c[0].([]byte)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, NewError(ErrorBadAttestationStatement, "x5c is malformed")
|
return nil, NewError(ErrorBadAttestationStatementType, "x5c is malformed")
|
||||||
}
|
}
|
||||||
leaf, err := x509.ParseCertificate(der)
|
leaf, err := x509.ParseCertificate(der)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, WrapError(ErrorBadAttestationStatement, err, "x5c is malformed")
|
return nil, WrapError(ErrorBadAttestationStatementType, err, "x5c is malformed")
|
||||||
}
|
}
|
||||||
|
|
||||||
intermediates := x509.NewCertPool()
|
intermediates := x509.NewCertPool()
|
||||||
for _, v := range x5c[1:] {
|
for _, v := range x5c[1:] {
|
||||||
der, ok = v.([]byte)
|
der, ok = v.([]byte)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, NewError(ErrorBadAttestationStatement, "x5c is malformed")
|
return nil, NewError(ErrorBadAttestationStatementType, "x5c is malformed")
|
||||||
}
|
}
|
||||||
cert, err := x509.ParseCertificate(der)
|
cert, err := x509.ParseCertificate(der)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, WrapError(ErrorBadAttestationStatement, err, "x5c is malformed")
|
return nil, WrapError(ErrorBadAttestationStatementType, err, "x5c is malformed")
|
||||||
}
|
}
|
||||||
intermediates.AddCert(cert)
|
intermediates.AddCert(cert)
|
||||||
}
|
}
|
||||||
|
@ -481,7 +481,7 @@ func doAppleAttestationFormat(ctx context.Context, ch *Challenge, db DB, att *At
|
||||||
CurrentTime: time.Now().Truncate(time.Second),
|
CurrentTime: time.Now().Truncate(time.Second),
|
||||||
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
|
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return nil, WrapError(ErrorBadAttestationStatement, err, "x5c is not valid")
|
return nil, WrapError(ErrorBadAttestationStatementType, err, "x5c is not valid")
|
||||||
}
|
}
|
||||||
|
|
||||||
data := &appleAttestationData{
|
data := &appleAttestationData{
|
||||||
|
@ -545,28 +545,28 @@ func doStepAttestationFormat(ctx context.Context, ch *Challenge, jwk *jose.JSONW
|
||||||
// Extract x5c and verify certificate
|
// Extract x5c and verify certificate
|
||||||
x5c, ok := att.AttStatement["x5c"].([]interface{})
|
x5c, ok := att.AttStatement["x5c"].([]interface{})
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, NewError(ErrorBadAttestationStatement, "x5c not present")
|
return nil, NewError(ErrorBadAttestationStatementType, "x5c not present")
|
||||||
}
|
}
|
||||||
if len(x5c) == 0 {
|
if len(x5c) == 0 {
|
||||||
return nil, NewError(ErrorRejectedIdentifierType, "x5c is empty")
|
return nil, NewError(ErrorRejectedIdentifierType, "x5c is empty")
|
||||||
}
|
}
|
||||||
der, ok := x5c[0].([]byte)
|
der, ok := x5c[0].([]byte)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, NewError(ErrorBadAttestationStatement, "x5c is malformed")
|
return nil, NewError(ErrorBadAttestationStatementType, "x5c is malformed")
|
||||||
}
|
}
|
||||||
leaf, err := x509.ParseCertificate(der)
|
leaf, err := x509.ParseCertificate(der)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, WrapError(ErrorBadAttestationStatement, err, "x5c is malformed")
|
return nil, WrapError(ErrorBadAttestationStatementType, err, "x5c is malformed")
|
||||||
}
|
}
|
||||||
intermediates := x509.NewCertPool()
|
intermediates := x509.NewCertPool()
|
||||||
for _, v := range x5c[1:] {
|
for _, v := range x5c[1:] {
|
||||||
der, ok = v.([]byte)
|
der, ok = v.([]byte)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, NewError(ErrorBadAttestationStatement, "x5c is malformed")
|
return nil, NewError(ErrorBadAttestationStatementType, "x5c is malformed")
|
||||||
}
|
}
|
||||||
cert, err := x509.ParseCertificate(der)
|
cert, err := x509.ParseCertificate(der)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, WrapError(ErrorBadAttestationStatement, err, "x5c is malformed")
|
return nil, WrapError(ErrorBadAttestationStatementType, err, "x5c is malformed")
|
||||||
}
|
}
|
||||||
intermediates.AddCert(cert)
|
intermediates.AddCert(cert)
|
||||||
}
|
}
|
||||||
|
@ -576,7 +576,7 @@ func doStepAttestationFormat(ctx context.Context, ch *Challenge, jwk *jose.JSONW
|
||||||
CurrentTime: time.Now().Truncate(time.Second),
|
CurrentTime: time.Now().Truncate(time.Second),
|
||||||
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
|
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return nil, WrapError(ErrorBadAttestationStatement, err, "x5c is not valid")
|
return nil, WrapError(ErrorBadAttestationStatementType, err, "x5c is not valid")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify proof of possession of private key validating the key
|
// Verify proof of possession of private key validating the key
|
||||||
|
@ -586,10 +586,10 @@ func doStepAttestationFormat(ctx context.Context, ch *Challenge, jwk *jose.JSONW
|
||||||
var sig []byte
|
var sig []byte
|
||||||
csig, ok := att.AttStatement["sig"].([]byte)
|
csig, ok := att.AttStatement["sig"].([]byte)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, NewError(ErrorBadAttestationStatement, "sig not present")
|
return nil, NewError(ErrorBadAttestationStatementType, "sig not present")
|
||||||
}
|
}
|
||||||
if err := cbor.Unmarshal(csig, &sig); err != nil {
|
if err := cbor.Unmarshal(csig, &sig); err != nil {
|
||||||
return nil, NewError(ErrorBadAttestationStatement, "sig is malformed")
|
return nil, NewError(ErrorBadAttestationStatementType, "sig is malformed")
|
||||||
}
|
}
|
||||||
keyAuth, err := KeyAuthorization(ch.Token, jwk)
|
keyAuth, err := KeyAuthorization(ch.Token, jwk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -599,23 +599,23 @@ func doStepAttestationFormat(ctx context.Context, ch *Challenge, jwk *jose.JSONW
|
||||||
switch pub := leaf.PublicKey.(type) {
|
switch pub := leaf.PublicKey.(type) {
|
||||||
case *ecdsa.PublicKey:
|
case *ecdsa.PublicKey:
|
||||||
if pub.Curve != elliptic.P256() {
|
if pub.Curve != elliptic.P256() {
|
||||||
return nil, WrapError(ErrorBadAttestationStatement, err, "unsupported elliptic curve %s", pub.Curve)
|
return nil, WrapError(ErrorBadAttestationStatementType, err, "unsupported elliptic curve %s", pub.Curve)
|
||||||
}
|
}
|
||||||
sum := sha256.Sum256([]byte(keyAuth))
|
sum := sha256.Sum256([]byte(keyAuth))
|
||||||
if !ecdsa.VerifyASN1(pub, sum[:], sig) {
|
if !ecdsa.VerifyASN1(pub, sum[:], sig) {
|
||||||
return nil, NewError(ErrorBadAttestationStatement, "failed to validate signature")
|
return nil, NewError(ErrorBadAttestationStatementType, "failed to validate signature")
|
||||||
}
|
}
|
||||||
case *rsa.PublicKey:
|
case *rsa.PublicKey:
|
||||||
sum := sha256.Sum256([]byte(keyAuth))
|
sum := sha256.Sum256([]byte(keyAuth))
|
||||||
if err := rsa.VerifyPKCS1v15(pub, crypto.SHA256, sum[:], sig); err != nil {
|
if err := rsa.VerifyPKCS1v15(pub, crypto.SHA256, sum[:], sig); err != nil {
|
||||||
return nil, NewError(ErrorBadAttestationStatement, "failed to validate signature")
|
return nil, NewError(ErrorBadAttestationStatementType, "failed to validate signature")
|
||||||
}
|
}
|
||||||
case ed25519.PublicKey:
|
case ed25519.PublicKey:
|
||||||
if !ed25519.Verify(pub, []byte(keyAuth), sig) {
|
if !ed25519.Verify(pub, []byte(keyAuth), sig) {
|
||||||
return nil, NewError(ErrorBadAttestationStatement, "failed to validate signature")
|
return nil, NewError(ErrorBadAttestationStatementType, "failed to validate signature")
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return nil, NewError(ErrorBadAttestationStatement, "unsupported public key type %T", pub)
|
return nil, NewError(ErrorBadAttestationStatementType, "unsupported public key type %T", pub)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse attestation data:
|
// Parse attestation data:
|
||||||
|
@ -630,7 +630,7 @@ func doStepAttestationFormat(ctx context.Context, ch *Challenge, jwk *jose.JSONW
|
||||||
var serialNumber int
|
var serialNumber int
|
||||||
rest, err := asn1.Unmarshal(ext.Value, &serialNumber)
|
rest, err := asn1.Unmarshal(ext.Value, &serialNumber)
|
||||||
if err != nil || len(rest) > 0 {
|
if err != nil || len(rest) > 0 {
|
||||||
return nil, WrapError(ErrorBadAttestationStatement, err, "error parsing serial number")
|
return nil, WrapError(ErrorBadAttestationStatementType, err, "error parsing serial number")
|
||||||
}
|
}
|
||||||
data.SerialNumber = strconv.Itoa(serialNumber)
|
data.SerialNumber = strconv.Itoa(serialNumber)
|
||||||
break
|
break
|
||||||
|
|
|
@ -17,8 +17,8 @@ const (
|
||||||
ErrorAccountDoesNotExistType ProblemType = iota
|
ErrorAccountDoesNotExistType ProblemType = iota
|
||||||
// ErrorAlreadyRevokedType request specified a certificate to be revoked that has already been revoked
|
// ErrorAlreadyRevokedType request specified a certificate to be revoked that has already been revoked
|
||||||
ErrorAlreadyRevokedType
|
ErrorAlreadyRevokedType
|
||||||
// ErrorBadAttestation WebAuthn attestation statement could not be verified
|
// ErrorBadAttestationStatementType WebAuthn attestation statement could not be verified
|
||||||
ErrorBadAttestationStatement
|
ErrorBadAttestationStatementType
|
||||||
// ErrorBadCSRType CSR is unacceptable (e.g., due to a short key)
|
// ErrorBadCSRType CSR is unacceptable (e.g., due to a short key)
|
||||||
ErrorBadCSRType
|
ErrorBadCSRType
|
||||||
// ErrorBadNonceType client sent an unacceptable anti-replay nonce
|
// ErrorBadNonceType client sent an unacceptable anti-replay nonce
|
||||||
|
@ -174,7 +174,7 @@ var (
|
||||||
details: "The JWS was signed with an algorithm the server does not support",
|
details: "The JWS was signed with an algorithm the server does not support",
|
||||||
status: 400,
|
status: 400,
|
||||||
},
|
},
|
||||||
ErrorBadAttestationStatement: {
|
ErrorBadAttestationStatementType: {
|
||||||
typ: officialACMEPrefix + ErrorBadNonceType.String(),
|
typ: officialACMEPrefix + ErrorBadNonceType.String(),
|
||||||
details: "Attestation statement cannot be verified",
|
details: "Attestation statement cannot be verified",
|
||||||
status: 400,
|
status: 400,
|
||||||
|
|
Loading…
Reference in a new issue