-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This is the initial implementation of the fido-hid pieces with a an inmemory impl of the key management.
- Loading branch information
0 parents
commit c63c9c5
Showing
8 changed files
with
1,196 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package attestation | ||
|
||
import ( | ||
"crypto/ecdsa" | ||
"crypto/x509" | ||
"encoding/pem" | ||
) | ||
|
||
// this is the same cert used by github/SoftU2F | ||
// https://github.com/github/SoftU2F/blob/master/SelfSignedCertificate/SelfSignedCertificate.m | ||
// We resuse that cert to help reduce the ability to track | ||
// an individual using this cert | ||
|
||
var attestationPrivateKeyPem = `-----BEGIN PRIVATE KEY----- | ||
MHcCAQEEIAOEKsf0zeNn3qBWxk9/OxXqfUvEg8rGl58qMZOtVzEJoAoGCCqGSM49 | ||
AwEHoUQDQgAE9pyrJBRLtO+H9w8jHFzU9XgErPjgxrKz41IYPYA5H2vSedJqTINk | ||
dObC2iOT/6wdUDRsXCOQZVeTPsuT/27e0Q== | ||
-----END PRIVATE KEY-----` | ||
|
||
var attestationCertPem = `-----BEGIN CERTIFICATE----- | ||
MIIBcTCCARagAwIBAgIJAIqK93XCOr/GMAoGCCqGSM49BAMCMBMxETAPBgNVBAMM | ||
CFNvZnQgVTJGMB4XDTE3MTAyMDIxNTEzM1oXDTI3MTAyMDIxNTEzM1owEzERMA8G | ||
A1UEAwwIU29mdCBVMkYwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ5gjPmSDFB | ||
Jap5rwDMdyqO4lCcWqQXxXtHBN+S+zt6ytC3amquoctXGuOOKZikTkT/gX8LFXVq | ||
mMZIcvC4EziGo1MwUTAdBgNVHQ4EFgQU8bJw2i1BjqI2uvqQWqNempxTxD4wHwYD | ||
VR0jBBgwFoAU8bJw2i1BjqI2uvqQWqNempxTxD4wDwYDVR0TAQH/BAUwAwEB/zAK | ||
BggqhkjOPQQDAgNJADBGAiEApFdcnvfziaAunldkAvHDwNViRH461fZv/6tFlbYP | ||
GEwCIQCS1PM8fMOKTgdr3hpqeQq/ysQK8NJZtPbFADEk8effHQ== | ||
-----END CERTIFICATE----- | ||
` | ||
|
||
var ( | ||
CertDer []byte | ||
PrivateKey *ecdsa.PrivateKey | ||
) | ||
|
||
func init() { | ||
certDer, _ := pem.Decode([]byte(attestationCertPem)) | ||
CertDer = certDer.Bytes | ||
|
||
privKeyDer, _ := pem.Decode([]byte(attestationPrivateKeyPem)) | ||
|
||
var err error | ||
PrivateKey, err = x509.ParseECPrivateKey(privKeyDer.Bytes) | ||
if err != nil { | ||
panic(err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
// fidoauth implements the fido1 authentication API | ||
package fidoauth | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
) | ||
|
||
const ( | ||
CmdRegister = 0x01 | ||
CmdAuthenticate = 0x02 | ||
CmdVersion = 0x03 | ||
|
||
CtrlCheckOnly AuthCtrl = 0x07 // Check if the provided key is valid | ||
CtrlEnforeUserPresenceAndSign AuthCtrl = 0x03 // confirm with user then sign | ||
CtrlDontEnforeUserPresenceAndSign AuthCtrl = 0x08 // just sign without confirming | ||
) | ||
|
||
type AuthenticatorRequest struct { | ||
Command uint8 | ||
Param1 uint8 | ||
Param2 uint8 | ||
Size int | ||
Data []byte | ||
|
||
Register *AuthenticatorRegisterReq | ||
Authenticate *AuthenticatorAuthReq | ||
} | ||
|
||
type AuthenticatorRegisterReq struct { | ||
ChallengeParam [32]byte | ||
ApplicationParam [32]byte | ||
} | ||
|
||
type AuthenticatorResponse struct { | ||
Data []byte | ||
Status uint16 | ||
} | ||
|
||
type AuthCtrl uint8 | ||
|
||
type AuthenticatorAuthReq struct { | ||
Ctrl AuthCtrl | ||
ChallengeParam [32]byte | ||
ApplicationParam [32]byte | ||
KeyHandle []byte | ||
} | ||
|
||
func DecodeAuthenticatorRequest(raw []byte) (*AuthenticatorRequest, error) { | ||
if len(raw) < 7 { | ||
return nil, fmt.Errorf("authenticator request too short") | ||
} | ||
|
||
req := AuthenticatorRequest{ | ||
Command: raw[1], | ||
Param1: raw[2], | ||
Param2: raw[3], | ||
Size: (int(raw[4]) << 16) | (int(raw[5]) << 8) | int(raw[6]), | ||
Data: raw[7:], | ||
} | ||
|
||
log.Printf("got authenticatorrequest data: %+v", req.Data) | ||
|
||
if req.Command == CmdRegister { | ||
var reg AuthenticatorRegisterReq | ||
if len(req.Data) < len(reg.ChallengeParam)+len(reg.ApplicationParam) { | ||
return nil, fmt.Errorf("register request incorrect size: %d", len(req.Data)) | ||
} | ||
|
||
copy(reg.ChallengeParam[:], req.Data[:32]) | ||
copy(reg.ApplicationParam[:], req.Data[32:]) | ||
req.Register = ® | ||
} else if req.Command == CmdAuthenticate { | ||
var auth AuthenticatorAuthReq | ||
|
||
if len(req.Data) < len(auth.ChallengeParam)+len(auth.ApplicationParam)+2 { | ||
return nil, fmt.Errorf("authenticate request too small: %d", len(req.Data)) | ||
} | ||
|
||
auth.Ctrl = AuthCtrl(req.Param1) | ||
|
||
switch auth.Ctrl { | ||
case CtrlCheckOnly, CtrlEnforeUserPresenceAndSign, CtrlDontEnforeUserPresenceAndSign: | ||
default: | ||
return nil, fmt.Errorf("unknown ctrl type: %02x", auth.Ctrl) | ||
} | ||
|
||
data := req.Data | ||
copy(auth.ChallengeParam[:], data[:32]) | ||
data = data[32:] | ||
|
||
copy(auth.ApplicationParam[:], data[:32]) | ||
data = data[32:] | ||
|
||
khLen := data[0] | ||
data = data[1:] | ||
|
||
if len(data) < int(khLen) { | ||
return nil, fmt.Errorf("key handle len too short %d vs %d", len(data), int(khLen)) | ||
} | ||
|
||
auth.KeyHandle = data[:khLen] | ||
req.Authenticate = &auth | ||
} | ||
|
||
return &req, nil | ||
} |
Oops, something went wrong.