Skip to content

Commit

Permalink
Merge pull request #84 from smlx/minor-fixes
Browse files Browse the repository at this point in the history
Improve error handling
  • Loading branch information
smlx authored Nov 20, 2021
2 parents 6ca6c21 + 9a2b738 commit c08053b
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 42 deletions.
2 changes: 1 addition & 1 deletion cmd/piv-agent/setupslots.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type SetupSlotsCmd struct {
Card string `kong:"help='Specify a smart card device'"`
ResetSlots bool `kong:"help='Overwrite existing keys in the targeted slots'"`
PIN uint64 `kong:"help='The PIN/PUK of the device (6-8 digits). Will be prompted interactively if not provided.'"`
SigningKeys []string `kong:"default='',enum='cached,always,never',help='Set up slots for signing keys with various touch policies (default none, possible values cached,always,never)'"`
SigningKeys []string `kong:"required,enum='cached,always,never',help='Set up slots for signing keys with various touch policies (possible values cached,always,never)'"`
DecryptingKey bool `kong:"default='false',help='Set up slot for a decrypting key (default false)'"`
}

Expand Down
93 changes: 56 additions & 37 deletions internal/assuan/assuan.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ type KeyService interface {
// New initialises a new gpg-agent server assuan FSM.
// It returns a *fsm.Machine configured in the ready state.
func New(rw io.ReadWriter, log *zap.Logger, ks ...KeyService) *Assuan {
var keyFound bool
var signature []byte
var keygrips, hash [][]byte
assuan := Assuan{
Expand All @@ -49,10 +48,7 @@ func New(rw io.ReadWriter, log *zap.Logger, ks ...KeyService) *Assuan {
_, err = io.WriteString(rw,
"OK Pleased to meet you, process 123456789\n")
case reset:
assuan.signer = nil
assuan.decrypter = nil
assuan.hashAlgo = 0
assuan.hash = []byte{}
assuan.reset()
_, err = io.WriteString(rw, "OK\n")
case option:
// ignore option values - piv-agent doesn't use them
Expand All @@ -65,38 +61,7 @@ func New(rw io.ReadWriter, log *zap.Logger, ks ...KeyService) *Assuan {
err = fmt.Errorf("unknown getinfo command: %q", assuan.data[0])
}
case havekey:
// HAVEKEY arguments are either:
// * a list of keygrips; or
// * --list=1000
// if _any_ key is available, we return OK, otherwise No_Secret_Key.
// handle --list
if bytes.HasPrefix(assuan.data[0], []byte("--list")) {
var grips []byte
grips, err = allKeygrips(ks)
if err != nil {
_, _ = io.WriteString(rw, "ERR 1 couldn't list keygrips\n")
return err
}
// apply buggy libgcrypt encoding
_, err = io.WriteString(rw, fmt.Sprintf("D %s\nOK\n",
PercentEncodeSExp(grips)))
return err
}
// handle list of keygrips
keygrips, err = hexDecode(assuan.data...)
if err != nil {
return fmt.Errorf("couldn't decode keygrips: %v", err)
}
keyFound, _, err = haveKey(ks, keygrips)
if err != nil {
_, _ = io.WriteString(rw, "ERR 1 couldn't check for keygrip\n")
return err
}
if keyFound {
_, err = io.WriteString(rw, "OK\n")
} else {
_, err = io.WriteString(rw, "No_Secret_Key\n")
}
err = assuan.havekey(rw, ks)
case keyinfo:
err = doKeyinfo(rw, assuan.data, ks)
case scd:
Expand Down Expand Up @@ -291,6 +256,14 @@ func New(rw io.ReadWriter, log *zap.Logger, ks ...KeyService) *Assuan {
// ignore this event since we don't currently use the client's
// description in the prompt
_, err = io.WriteString(rw, "OK\n")
case havekey:
// gpg skips the RESET command occasionally so we have to emulate it.
assuan.reset()
// now jump straight to havekey
if err = assuan.havekey(rw, ks); err != nil {
return err
}
_, err = io.WriteString(rw, "OK\n")
default:
return fmt.Errorf("unknown event: %v", Event(e))
}
Expand All @@ -301,6 +274,52 @@ func New(rw io.ReadWriter, log *zap.Logger, ks ...KeyService) *Assuan {
return &assuan
}

func (assuan *Assuan) reset() {
assuan.signer = nil
assuan.decrypter = nil
assuan.hashAlgo = 0
assuan.hash = []byte{}
}

func (assuan *Assuan) havekey(rw io.ReadWriter, ks []KeyService) error {
var err error
var keyFound bool
var keygrips [][]byte
// HAVEKEY arguments are either:
// * a list of keygrips; or
// * --list=1000
// if _any_ key is available, we return OK, otherwise No_Secret_Key.
// handle --list
if bytes.HasPrefix(assuan.data[0], []byte("--list")) {
var grips []byte
grips, err = allKeygrips(ks)
if err != nil {
_, _ = io.WriteString(rw, "ERR 1 couldn't list keygrips\n")
return err
}
// apply buggy libgcrypt encoding
_, err = io.WriteString(rw, fmt.Sprintf("D %s\nOK\n",
PercentEncodeSExp(grips)))
return err
}
// handle list of keygrips
keygrips, err = hexDecode(assuan.data...)
if err != nil {
return fmt.Errorf("couldn't decode keygrips: %v", err)
}
keyFound, _, err = haveKey(ks, keygrips)
if err != nil {
_, _ = io.WriteString(rw, "ERR 1 couldn't check for keygrip\n")
return err
}
if keyFound {
_, err = io.WriteString(rw, "OK\n")
} else {
_, err = io.WriteString(rw, "No_Secret_Key\n")
}
return err
}

// doKeyinfo checks for key availability by keygrip, writing the result to rw.
func doKeyinfo(rw io.ReadWriter, data [][]byte, ks []KeyService) error {
// KEYINFO arguments are a list of keygrips
Expand Down
4 changes: 2 additions & 2 deletions internal/assuan/event_enumer.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions internal/assuan/fsm.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,5 +156,9 @@ var assuanTransitions = []fsm.Transition{
Src: fsm.State(decryptingKeyIsSet),
Event: fsm.Event(pkdecrypt),
Dst: fsm.State(waitingForCiphertext),
}, {
Src: fsm.State(waitingForCiphertext),
Event: fsm.Event(havekey),
Dst: fsm.State(connected),
},
}
4 changes: 2 additions & 2 deletions internal/assuan/state_enumer.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit c08053b

Please sign in to comment.