From 437070dfa457d76e39ef708051e26fa40e1732dc Mon Sep 17 00:00:00 2001
From: renovate <renovate-bot@autistici.org>
Date: Tue, 18 Apr 2023 10:36:39 +0000
Subject: [PATCH] Update github.com/duo-labs/webauthn digest to ebaf9b7

---
 go.mod                                        |  2 +-
 go.sum                                        |  2 +
 .../webauthn/protocol/attestation_tpm.go      | 35 +++++++-----
 .../duo-labs/webauthn/protocol/credential.go  |  2 +-
 .../webauthn/protocol/webauthncose/ed25519.go |  2 +-
 .../protocol/webauthncose/ed25519_go112.go    |  2 +-
 .../protocol/webauthncose/webauthncose.go     | 40 +++++++++++++-
 .../duo-labs/webauthn/webauthn/login.go       | 53 +++++++++++++++----
 vendor/modules.txt                            |  2 +-
 9 files changed, 111 insertions(+), 29 deletions(-)

diff --git a/go.mod b/go.mod
index f5438c2c..416fdd63 100644
--- a/go.mod
+++ b/go.mod
@@ -9,7 +9,7 @@ require (
 	github.com/bradfitz/gomemcache v0.0.0-20230124162541-5f7a7d875746
 	github.com/cenkalti/backoff/v4 v4.1.3
 	github.com/coreos/go-systemd/v22 v22.5.0
-	github.com/duo-labs/webauthn v0.0.0-20220330035159-03696f3d4499
+	github.com/duo-labs/webauthn v0.0.0-20221205164246-ebaf9b74c6ec
 	github.com/form3tech-oss/jwt-go v3.2.5+incompatible // indirect
 	github.com/go-ldap/ldap/v3 v3.4.4
 	github.com/go-sql-driver/mysql v1.7.0
diff --git a/go.sum b/go.sum
index 50ea4681..83420bed 100644
--- a/go.sum
+++ b/go.sum
@@ -244,6 +244,8 @@ github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8
 github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
 github.com/duo-labs/webauthn v0.0.0-20220330035159-03696f3d4499 h1:jaQHuGKk9NVcfu9VbA7ygslr/7utxdYs47i4osBhZP8=
 github.com/duo-labs/webauthn v0.0.0-20220330035159-03696f3d4499/go.mod h1:UMk1JMDgQDcdI2vQz+WJOIUTSjIq07qSepAVgc93rUc=
+github.com/duo-labs/webauthn v0.0.0-20221205164246-ebaf9b74c6ec h1:darQ1FPPrwlzwmuN3fRMVCrsaCpuDqkKHADYzcMa73M=
+github.com/duo-labs/webauthn v0.0.0-20221205164246-ebaf9b74c6ec/go.mod h1:V3q8IgNpNqFio+56G0vy/QZIi7iho65UFrDwdF5OtZA=
 github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
 github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
diff --git a/vendor/github.com/duo-labs/webauthn/protocol/attestation_tpm.go b/vendor/github.com/duo-labs/webauthn/protocol/attestation_tpm.go
index 7cf578b3..5ee3ec5e 100644
--- a/vendor/github.com/duo-labs/webauthn/protocol/attestation_tpm.go
+++ b/vendor/github.com/duo-labs/webauthn/protocol/attestation_tpm.go
@@ -79,19 +79,20 @@ func verifyTPMFormat(att AttestationObject, clientDataHash []byte) (string, []in
 	}
 
 	key, err := webauthncose.ParsePublicKey(att.AuthData.AttData.CredentialPublicKey)
-	switch key.(type) {
+	if err != nil {
+		return tpmAttestationKey, nil, err
+	}
+	switch key := key.(type) {
 	case webauthncose.EC2PublicKeyData:
-		e := key.(webauthncose.EC2PublicKeyData)
-		if pubArea.ECCParameters.CurveID != googletpm.EllipticCurve(e.Curve) ||
-			0 != pubArea.ECCParameters.Point.X.Cmp(new(big.Int).SetBytes(e.XCoord)) ||
-			0 != pubArea.ECCParameters.Point.Y.Cmp(new(big.Int).SetBytes(e.YCoord)) {
+		if pubArea.ECCParameters.CurveID != key.TPMCurveID() ||
+			pubArea.ECCParameters.Point.X.Cmp(new(big.Int).SetBytes(key.XCoord)) != 0 ||
+			pubArea.ECCParameters.Point.Y.Cmp(new(big.Int).SetBytes(key.YCoord)) != 0 {
 			return tpmAttestationKey, nil, ErrAttestationFormat.WithDetails("Mismatch between ECCParameters in pubArea and credentialPublicKey")
 		}
 	case webauthncose.RSAPublicKeyData:
-		r := key.(webauthncose.RSAPublicKeyData)
-		mod := new(big.Int).SetBytes(r.Modulus)
-		exp := uint32(r.Exponent[0]) + uint32(r.Exponent[1])<<8 + uint32(r.Exponent[2])<<16
-		if 0 != pubArea.RSAParameters.Modulus.Cmp(mod) ||
+		mod := new(big.Int).SetBytes(key.Modulus)
+		exp := uint32(key.Exponent[0]) + uint32(key.Exponent[1])<<8 + uint32(key.Exponent[2])<<16
+		if pubArea.RSAParameters.Modulus.Cmp(mod) != 0 ||
 			pubArea.RSAParameters.Exponent != exp {
 			return tpmAttestationKey, nil, ErrAttestationFormat.WithDetails("Mismatch between RSAParameters in pubArea and credentialPublicKey")
 		}
@@ -104,6 +105,9 @@ func verifyTPMFormat(att AttestationObject, clientDataHash []byte) (string, []in
 
 	// Validate that certInfo is valid:
 	certInfo, err := googletpm.DecodeAttestationData(certInfoBytes)
+	if err != nil {
+		return tpmAttestationKey, nil, err
+	}
 	// 1/4 Verify that magic is set to TPM_GENERATED_VALUE.
 	if certInfo.Magic != 0xff544347 {
 		return tpmAttestationKey, nil, ErrAttestationFormat.WithDetails("Magic is not set to TPM_GENERATED_VALUE")
@@ -116,7 +120,7 @@ func verifyTPMFormat(att AttestationObject, clientDataHash []byte) (string, []in
 	f := webauthncose.HasherFromCOSEAlg(coseAlg)
 	h := f()
 	h.Write(attToBeSigned)
-	if 0 != bytes.Compare(certInfo.ExtraData, h.Sum(nil)) {
+	if !bytes.Equal(certInfo.ExtraData, h.Sum(nil)) {
 		return tpmAttestationKey, nil, ErrAttestationFormat.WithDetails("ExtraData is not set to hash of attToBeSigned")
 	}
 	// 4/4 Verify that attested contains a TPMS_CERTIFY_INFO structure as specified in
@@ -126,7 +130,7 @@ func verifyTPMFormat(att AttestationObject, clientDataHash []byte) (string, []in
 	f, err = certInfo.AttestedCertifyInfo.Name.Digest.Alg.HashConstructor()
 	h = f()
 	h.Write(pubAreaBytes)
-	if 0 != bytes.Compare(h.Sum(nil), certInfo.AttestedCertifyInfo.Name.Digest.Value) {
+	if !bytes.Equal(h.Sum(nil), certInfo.AttestedCertifyInfo.Name.Digest.Value) {
 		return tpmAttestationKey, nil, ErrAttestationFormat.WithDetails("Hash value mismatch attested and pubArea")
 	}
 
@@ -170,6 +174,9 @@ func verifyTPMFormat(att AttestationObject, clientDataHash []byte) (string, []in
 		for _, ext := range aikCert.Extensions {
 			if ext.Id.Equal([]int{2, 5, 29, 17}) {
 				manufacturer, model, version, err = parseSANExtension(ext.Value)
+				if err != nil {
+					return tpmAttestationKey, nil, err
+				}
 			}
 		}
 
@@ -177,7 +184,7 @@ func verifyTPMFormat(att AttestationObject, clientDataHash []byte) (string, []in
 			return tpmAttestationKey, nil, ErrAttestationFormat.WithDetails("Invalid SAN data in AIK certificate")
 		}
 
-		if false == isValidTPMManufacturer(manufacturer) {
+		if !isValidTPMManufacturer(manufacturer) {
 			return tpmAttestationKey, nil, ErrAttestationFormat.WithDetails("Invalid TPM manufacturer")
 		}
 
@@ -193,7 +200,7 @@ func verifyTPMFormat(att AttestationObject, clientDataHash []byte) (string, []in
 				ekuValid = true
 			}
 		}
-		if false == ekuValid {
+		if !ekuValid {
 			return tpmAttestationKey, nil, ErrAttestationFormat.WithDetails("AIK certificate missing EKU")
 		}
 
@@ -212,7 +219,7 @@ func verifyTPMFormat(att AttestationObject, clientDataHash []byte) (string, []in
 				}
 			}
 		}
-		if constraints.IsCA != false {
+		if constraints.IsCA {
 			return tpmAttestationKey, nil, ErrAttestationFormat.WithDetails("AIK certificate basic constraints missing or CA is true")
 		}
 		// 6/6 An Authority Information Access (AIA) extension with entry id-ad-ocsp and a CRL Distribution Point
diff --git a/vendor/github.com/duo-labs/webauthn/protocol/credential.go b/vendor/github.com/duo-labs/webauthn/protocol/credential.go
index a43369cb..f1426bfc 100644
--- a/vendor/github.com/duo-labs/webauthn/protocol/credential.go
+++ b/vendor/github.com/duo-labs/webauthn/protocol/credential.go
@@ -85,7 +85,7 @@ func ParseCredentialCreationResponseBody(body io.Reader) (*ParsedCredentialCreat
 	}
 
 	var pcc ParsedCredentialCreationData
-	pcc.ID, pcc.RawID, pcc.Type = ccr.ID, ccr.RawID, ccr.Type
+	pcc.ID, pcc.RawID, pcc.Type, pcc.ClientExtensionResults = ccr.ID, ccr.RawID, ccr.Type, ccr.ClientExtensionResults
 	pcc.Raw = ccr
 
 	parsedAttestationResponse, err := ccr.AttestationResponse.Parse()
diff --git a/vendor/github.com/duo-labs/webauthn/protocol/webauthncose/ed25519.go b/vendor/github.com/duo-labs/webauthn/protocol/webauthncose/ed25519.go
index 73ebc870..b3dc1f83 100644
--- a/vendor/github.com/duo-labs/webauthn/protocol/webauthncose/ed25519.go
+++ b/vendor/github.com/duo-labs/webauthn/protocol/webauthncose/ed25519.go
@@ -1,4 +1,4 @@
-// +build go1.13
+//go:build go1.13
 
 package webauthncose
 
diff --git a/vendor/github.com/duo-labs/webauthn/protocol/webauthncose/ed25519_go112.go b/vendor/github.com/duo-labs/webauthn/protocol/webauthncose/ed25519_go112.go
index f1ae39d7..7dc8c538 100644
--- a/vendor/github.com/duo-labs/webauthn/protocol/webauthncose/ed25519_go112.go
+++ b/vendor/github.com/duo-labs/webauthn/protocol/webauthncose/ed25519_go112.go
@@ -1,4 +1,4 @@
-// +build !go1.13
+//go:build !go1.13
 
 package webauthncose
 
diff --git a/vendor/github.com/duo-labs/webauthn/protocol/webauthncose/webauthncose.go b/vendor/github.com/duo-labs/webauthn/protocol/webauthncose/webauthncose.go
index 325f903c..8d568d50 100644
--- a/vendor/github.com/duo-labs/webauthn/protocol/webauthncose/webauthncose.go
+++ b/vendor/github.com/duo-labs/webauthn/protocol/webauthncose/webauthncose.go
@@ -14,6 +14,7 @@ import (
 
 	"golang.org/x/crypto/ed25519"
 
+	"github.com/duo-labs/webauthn/protocol/googletpm"
 	"github.com/duo-labs/webauthn/protocol/webauthncbor"
 )
 
@@ -198,7 +199,8 @@ func ParseFIDOPublicKey(keyBytes []byte) (EC2PublicKeyData, error) {
 // COSEAlgorithmIdentifier From §5.10.5. A number identifying a cryptographic algorithm. The algorithm
 // identifiers SHOULD be values registered in the IANA COSE Algorithms registry
 // [https://www.w3.org/TR/webauthn/#biblio-iana-cose-algs-reg], for instance, -7 for "ES256"
-//  and -257 for "RS256".
+//
+//	and -257 for "RS256".
 type COSEAlgorithmIdentifier int
 
 const (
@@ -238,6 +240,42 @@ const (
 	RSAKey COSEKeyType = 3
 )
 
+// The COSE Elliptic Curves
+// https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves
+type COSEEllipticCurve int
+
+const (
+	// EC2 NIST P-256 also known as secp256r1
+	P256 COSEEllipticCurve = 1
+	// EC2 NIST P-384 also known as secp384r1
+	P384 COSEEllipticCurve = 2
+	// EC2 NIST P-521 also known as secp521r1
+	P521 COSEEllipticCurve = 3
+	// OKP X25519 for use w/ ECDH only
+	X25519 COSEEllipticCurve = 4
+	// OKP X448 for use w/ ECDH only
+	X448 COSEEllipticCurve = 5
+	// OKP Ed25519 for use w/ EdDSA only
+	Ed25519 COSEEllipticCurve = 6
+	// OKP Ed448 for use w/ EdDSA only
+	Ed448 COSEEllipticCurve = 7
+	// EC2 SECG secp256k1 curve
+	secp256k1 COSEEllipticCurve = 8
+)
+
+func (k *EC2PublicKeyData) TPMCurveID() googletpm.EllipticCurve {
+	switch COSEEllipticCurve(k.Curve) {
+	case P256:
+		return googletpm.CurveNISTP256 // TPM_ECC_NIST_P256
+	case P384:
+		return googletpm.CurveNISTP384 // TPM_ECC_NIST_P384
+	case P521:
+		return googletpm.CurveNISTP521 // TPM_ECC_NIST_P521
+	default:
+		return googletpm.EllipticCurve(0) // TPM_ECC_NONE
+	}
+}
+
 func VerifySignature(key interface{}, data []byte, sig []byte) (bool, error) {
 
 	switch key.(type) {
diff --git a/vendor/github.com/duo-labs/webauthn/webauthn/login.go b/vendor/github.com/duo-labs/webauthn/webauthn/login.go
index 4ce3a88d..fdb923f3 100644
--- a/vendor/github.com/duo-labs/webauthn/webauthn/login.go
+++ b/vendor/github.com/duo-labs/webauthn/webauthn/login.go
@@ -15,6 +15,9 @@ import (
 // LoginOption is used to provide parameters that modify the default Credential Assertion Payload that is sent to the user.
 type LoginOption func(*protocol.PublicKeyCredentialRequestOptions)
 
+// DiscoverableUserHandler returns a *User given the provided userHandle.
+type DiscoverableUserHandler func(rawID, userHandle []byte) (user User, err error)
+
 // Creates the CredentialAssertion data payload that should be sent to the user agent for beginning the
 // login/assertion process. The format of this data can be seen in §5.5 of the WebAuthn specification
 // (https://www.w3.org/TR/webauthn/#assertion-options). These default values can be amended by providing
@@ -22,14 +25,9 @@ type LoginOption func(*protocol.PublicKeyCredentialRequestOptions)
 // RP in a secure manner and then provided to the FinishLogin function. This data helps us verify the
 // ownership of the credential being retreived.
 func (webauthn *WebAuthn) BeginLogin(user User, opts ...LoginOption) (*protocol.CredentialAssertion, *SessionData, error) {
-	challenge, err := protocol.CreateChallenge()
-	if err != nil {
-		return nil, nil, err
-	}
-
 	credentials := user.WebAuthnCredentials()
 
-	if len(credentials) == 0 { // If the user does not have any credentials, we cannot do login
+	if len(credentials) == 0 { // If the user does not have any credentials, we cannot perform an assertion.
 		return nil, nil, protocol.ErrBadRequest.WithDetails("Found no credentials for user")
 	}
 
@@ -42,6 +40,20 @@ func (webauthn *WebAuthn) BeginLogin(user User, opts ...LoginOption) (*protocol.
 		allowedCredentials[i] = credentialDescriptor
 	}
 
+	return webauthn.beginLogin(user.WebAuthnID(), allowedCredentials, opts...)
+}
+
+// BeginDiscoverableLogin begins a client-side discoverable login, previously known as Resident Key logins.
+func (webauthn *WebAuthn) BeginDiscoverableLogin(opts ...LoginOption) (*protocol.CredentialAssertion, *SessionData, error) {
+	return webauthn.beginLogin(nil, nil, opts...)
+}
+
+func (webauthn *WebAuthn) beginLogin(userID []byte, allowedCredentials []protocol.CredentialDescriptor, opts ...LoginOption) (*protocol.CredentialAssertion, *SessionData, error) {
+	challenge, err := protocol.CreateChallenge()
+	if err != nil {
+		return nil, nil, err
+	}
+
 	requestOptions := protocol.PublicKeyCredentialRequestOptions{
 		Challenge:          challenge,
 		Timeout:            webauthn.Config.Timeout,
@@ -56,13 +68,13 @@ func (webauthn *WebAuthn) BeginLogin(user User, opts ...LoginOption) (*protocol.
 
 	newSessionData := SessionData{
 		Challenge:            base64.RawURLEncoding.EncodeToString(challenge),
-		UserID:               user.WebAuthnID(),
+		UserID:               userID,
 		AllowedCredentialIDs: requestOptions.GetAllowedCredentialIDs(),
 		UserVerification:     requestOptions.UserVerification,
 		Extensions:           requestOptions.Extensions,
 	}
 
-	response := protocol.CredentialAssertion{requestOptions}
+	response := protocol.CredentialAssertion{Response: requestOptions}
 
 	return &response, &newSessionData, nil
 }
@@ -105,6 +117,29 @@ func (webauthn *WebAuthn) ValidateLogin(user User, session SessionData, parsedRe
 		return nil, protocol.ErrBadRequest.WithDetails("ID mismatch for User and Session")
 	}
 
+	return webauthn.validateLogin(user, session, parsedResponse)
+}
+
+// ValidateDiscoverableLogin is an overloaded version of ValidateLogin that allows for discoverable credentials.
+func (webauthn *WebAuthn) ValidateDiscoverableLogin(handler DiscoverableUserHandler, session SessionData, parsedResponse *protocol.ParsedCredentialAssertionData) (*Credential, error) {
+	if session.UserID != nil {
+		return nil, protocol.ErrBadRequest.WithDetails("Session was not initiated as a client-side discoverable login")
+	}
+
+	if parsedResponse.Response.UserHandle == nil {
+		return nil, protocol.ErrBadRequest.WithDetails("Client-side Discoverable Assertion was attempted with a blank User Handle")
+	}
+
+	user, err := handler(parsedResponse.RawID, parsedResponse.Response.UserHandle)
+	if err != nil {
+		return nil, protocol.ErrBadRequest.WithDetails("Failed to lookup Client-side Discoverable Credential")
+	}
+
+	return webauthn.validateLogin(user, session, parsedResponse)
+}
+
+// validateLogin takes a parsed response and validates it against the user credentials and session data
+func (webauthn *WebAuthn) validateLogin(user User, session SessionData, parsedResponse *protocol.ParsedCredentialAssertionData) (*Credential, error) {
 	// Step 1. If the allowCredentials option was given when this authentication ceremony was initiated,
 	// verify that credential.id identifies one of the public key credentials that were listed in
 	// allowCredentials.
@@ -143,7 +178,7 @@ func (webauthn *WebAuthn) ValidateLogin(user User, session SessionData, parsedRe
 	// This is in part handled by our Step 1
 
 	userHandle := parsedResponse.Response.UserHandle
-	if userHandle != nil && len(userHandle) > 0 {
+	if len(userHandle) > 0 {
 		if !bytes.Equal(userHandle, user.WebAuthnID()) {
 			return nil, protocol.ErrBadRequest.WithDetails("userHandle and User ID do not match")
 		}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 1dbf0e52..7e2ba46c 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -61,7 +61,7 @@ github.com/coreos/go-systemd/v22/daemon
 github.com/coreos/go-systemd/v22/journal
 # github.com/cpuguy83/go-md2man/v2 v2.0.0
 github.com/cpuguy83/go-md2man/v2/md2man
-# github.com/duo-labs/webauthn v0.0.0-20220330035159-03696f3d4499
+# github.com/duo-labs/webauthn v0.0.0-20221205164246-ebaf9b74c6ec
 ## explicit
 github.com/duo-labs/webauthn/metadata
 github.com/duo-labs/webauthn/protocol
-- 
GitLab