2017-04-17 18:08:24 -04:00
|
|
|
// +build pkcs11
|
|
|
|
|
|
|
|
package yubikey
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/pem"
|
|
|
|
"errors"
|
|
|
|
"github.com/docker/notary"
|
|
|
|
"github.com/docker/notary/trustmanager"
|
2017-08-24 18:40:24 -04:00
|
|
|
"github.com/docker/notary/tuf/data"
|
2017-04-17 18:08:24 -04:00
|
|
|
"github.com/docker/notary/tuf/utils"
|
|
|
|
)
|
|
|
|
|
|
|
|
// YubiImport is a wrapper around the YubiStore that allows us to import private
|
|
|
|
// keys to the yubikey
|
|
|
|
type YubiImport struct {
|
|
|
|
dest *YubiStore
|
|
|
|
passRetriever notary.PassRetriever
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewImporter returns a wrapper for the YubiStore provided that enables importing
|
|
|
|
// keys via the simple Set(string, []byte) interface
|
|
|
|
func NewImporter(ys *YubiStore, ret notary.PassRetriever) *YubiImport {
|
|
|
|
return &YubiImport{
|
|
|
|
dest: ys,
|
|
|
|
passRetriever: ret,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set determines if we are allowed to set the given key on the Yubikey and
|
|
|
|
// calls through to YubiStore.AddKey if it's valid
|
|
|
|
func (s *YubiImport) Set(name string, bytes []byte) error {
|
|
|
|
block, _ := pem.Decode(bytes)
|
|
|
|
if block == nil {
|
|
|
|
return errors.New("invalid PEM data, could not parse")
|
|
|
|
}
|
|
|
|
role, ok := block.Headers["role"]
|
|
|
|
if !ok {
|
|
|
|
return errors.New("no role found for key")
|
|
|
|
}
|
|
|
|
ki := trustmanager.KeyInfo{
|
|
|
|
// GUN is ignored by YubiStore
|
2017-08-24 18:40:24 -04:00
|
|
|
Role: data.RoleName(role),
|
2017-04-17 18:08:24 -04:00
|
|
|
}
|
|
|
|
privKey, err := utils.ParsePEMPrivateKey(bytes, "")
|
|
|
|
if err != nil {
|
|
|
|
privKey, _, err = trustmanager.GetPasswdDecryptBytes(
|
|
|
|
s.passRetriever,
|
|
|
|
bytes,
|
|
|
|
name,
|
2017-08-24 18:40:24 -04:00
|
|
|
ki.Role.String(),
|
2017-04-17 18:08:24 -04:00
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return s.dest.AddKey(ki, privKey)
|
|
|
|
}
|