Skip to content

Commit

Permalink
feat: callenge offset
Browse files Browse the repository at this point in the history
  • Loading branch information
tarrencev committed Oct 14, 2022
1 parent 0c2f80d commit 04d9a66
Show file tree
Hide file tree
Showing 9 changed files with 13 additions and 13 deletions.
4 changes: 2 additions & 2 deletions protocol/assertion.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,15 @@ func ParseCredentialRequestResponseBody(body io.Reader) (*ParsedCredentialAssert
// Follow the remaining steps outlined in §7.2 Verifying an authentication assertion
// (https://www.w3.org/TR/webauthn/#verifying-assertion) and return an error if there
// is a failure during each step.
func (p *ParsedCredentialAssertionData) Verify(storedChallenge string, relyingPartyID, relyingPartyOrigin, appID string, verifyUser bool, credentialBytes []byte) error {
func (p *ParsedCredentialAssertionData) Verify(storedChallenge string, relyingPartyID, relyingPartyOrigin, appID string, verifyUser bool, credentialBytes []byte, challengeOffset uint) error {

// Steps 4 through 6 in verifying the assertion data (https://www.w3.org/TR/webauthn/#verifying-assertion) are
// "assertive" steps, i.e "Let JSONtext be the result of running UTF-8 decode on the value of cData."
// We handle these steps in part as we verify but also beforehand

// Handle steps 7 through 10 of assertion by verifying stored data against the Collected Client Data
// returned by the authenticator
validError := p.Response.CollectedClientData.Verify(storedChallenge, AssertCeremony, relyingPartyOrigin)
validError := p.Response.CollectedClientData.Verify(storedChallenge, AssertCeremony, relyingPartyOrigin, challengeOffset)
if validError != nil {
return validError
}
Expand Down
2 changes: 1 addition & 1 deletion protocol/assertion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ func TestParsedCredentialAssertionData_Verify(t *testing.T) {
Raw: tt.fields.Raw,
}

if err := p.Verify(tt.args.storedChallenge.String(), tt.args.relyingPartyID, tt.args.relyingPartyOrigin, "", tt.args.verifyUser, tt.args.credentialBytes); (err != nil) != tt.wantErr {
if err := p.Verify(tt.args.storedChallenge.String(), tt.args.relyingPartyID, tt.args.relyingPartyOrigin, "", tt.args.verifyUser, tt.args.credentialBytes, 0); (err != nil) != tt.wantErr {
t.Errorf("ParsedCredentialAssertionData.Verify() error = %v, wantErr %v", err, tt.wantErr)
}
})
Expand Down
2 changes: 1 addition & 1 deletion protocol/attestation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func TestAttestationVerify(t *testing.T) {
pcc.Response = *parsedAttestationResponse

// Test Base Verification
err = pcc.Verify(options.Response.Challenge.String(), false, options.Response.RelyingParty.ID, options.Response.RelyingParty.Name)
err = pcc.Verify(options.Response.Challenge.String(), false, options.Response.RelyingParty.ID, options.Response.RelyingParty.Name, 0)
if err != nil {
t.Fatalf("Not valid: %+v (%s)", err, err.(*Error).DevInfo)
}
Expand Down
4 changes: 2 additions & 2 deletions protocol/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func FullyQualifiedOrigin(u *url.URL) string {
// new credential and steps 7 through 10 of verifying an authentication assertion
// See https://www.w3.org/TR/webauthn/#registering-a-new-credential
// and https://www.w3.org/TR/webauthn/#verifying-assertion
func (c *CollectedClientData) Verify(storedChallenge string, ceremony CeremonyType, relyingPartyOrigin string) error {
func (c *CollectedClientData) Verify(storedChallenge string, ceremony CeremonyType, relyingPartyOrigin string, challengeOffset uint) error {

// Registration Step 3. Verify that the value of C.type is webauthn.create.

Expand All @@ -76,7 +76,7 @@ func (c *CollectedClientData) Verify(storedChallenge string, ceremony CeremonyTy
// passed to the get() call.

challenge := c.Challenge
if subtle.ConstantTimeCompare([]byte(storedChallenge), []byte(challenge)) != 1 {
if subtle.ConstantTimeCompare([]byte(storedChallenge)[challengeOffset:], []byte(challenge)[challengeOffset:]) != 1 {
err := ErrVerification.WithDetails("Error validating challenge")
return err.WithInfo(fmt.Sprintf("Expected b Value: %#v\nReceived b: %#v\n", storedChallenge, challenge))
}
Expand Down
4 changes: 2 additions & 2 deletions protocol/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func TestVerifyCollectedClientData(t *testing.T) {
var storedChallenge = newChallenge

originURL, _ := url.Parse(ccd.Origin)
err = ccd.Verify(storedChallenge.String(), ccd.Type, FullyQualifiedOrigin(originURL))
err = ccd.Verify(storedChallenge.String(), ccd.Type, FullyQualifiedOrigin(originURL), 0)
if err != nil {
t.Fatalf("error verifying challenge: expected %#v got %#v", Challenge(ccd.Challenge), storedChallenge)
}
Expand All @@ -43,7 +43,7 @@ func TestVerifyCollectedClientDataIncorrectChallenge(t *testing.T) {
t.Fatalf("error creating challenge: %s", err)
}
storedChallenge := Challenge(bogusChallenge)
err = ccd.Verify(storedChallenge.String(), ccd.Type, ccd.Origin)
err = ccd.Verify(storedChallenge.String(), ccd.Type, ccd.Origin, 0)
if err == nil {
t.Fatalf("error expected but not received. expected %#v got %#v", Challenge(ccd.Challenge), storedChallenge)
}
Expand Down
4 changes: 2 additions & 2 deletions protocol/credential.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,10 @@ func ParseCredentialCreationResponseBody(body io.Reader) (*ParsedCredentialCreat

// Verifies the Client and Attestation data as laid out by §7.1. Registering a new credential
// https://www.w3.org/TR/webauthn/#registering-a-new-credential
func (pcc *ParsedCredentialCreationData) Verify(storedChallenge string, verifyUser bool, relyingPartyID, relyingPartyOrigin string) error {
func (pcc *ParsedCredentialCreationData) Verify(storedChallenge string, verifyUser bool, relyingPartyID, relyingPartyOrigin string, challengeOffset uint) error {

// Handles steps 3 through 6 - Verifying the Client Data against the Relying Party's stored data
verifyError := pcc.Response.CollectedClientData.Verify(storedChallenge, CreateCeremony, relyingPartyOrigin)
verifyError := pcc.Response.CollectedClientData.Verify(storedChallenge, CreateCeremony, relyingPartyOrigin, challengeOffset)
if verifyError != nil {
return verifyError
}
Expand Down
2 changes: 1 addition & 1 deletion protocol/credential_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ func TestParsedCredentialCreationData_Verify(t *testing.T) {
Response: tt.fields.Response,
Raw: tt.fields.Raw,
}
if err := pcc.Verify(tt.args.storedChallenge.String(), tt.args.verifyUser, tt.args.relyingPartyID, tt.args.relyingPartyOrigin); (err != nil) != tt.wantErr {
if err := pcc.Verify(tt.args.storedChallenge.String(), tt.args.verifyUser, tt.args.relyingPartyID, tt.args.relyingPartyOrigin, 0); (err != nil) != tt.wantErr {
t.Errorf("ParsedCredentialCreationData.Verify() error = %+v, wantErr %v", err, tt.wantErr)
}
})
Expand Down
2 changes: 1 addition & 1 deletion webauthn/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ func (webauthn *WebAuthn) validateLogin(user User, session SessionData, parsedRe
}

// Handle steps 4 through 16
validError := parsedResponse.Verify(session.Challenge[challengeOffset:], rpID, rpOrigin, appID, shouldVerifyUser, loginCredential.PublicKey)
validError := parsedResponse.Verify(session.Challenge, rpID, rpOrigin, appID, shouldVerifyUser, loginCredential.PublicKey, challengeOffset)
if validError != nil {
return nil, validError
}
Expand Down
2 changes: 1 addition & 1 deletion webauthn/registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ func (webauthn *WebAuthn) CreateCredential(user User, session SessionData, parse

shouldVerifyUser := session.UserVerification == protocol.VerificationRequired

invalidErr := parsedResponse.Verify(session.Challenge, shouldVerifyUser, webauthn.Config.RPID, webauthn.Config.RPOrigin)
invalidErr := parsedResponse.Verify(session.Challenge, shouldVerifyUser, webauthn.Config.RPID, webauthn.Config.RPOrigin, 0)
if invalidErr != nil {
return nil, invalidErr
}
Expand Down

0 comments on commit 04d9a66

Please sign in to comment.