mirror of https://github.com/docker/docs.git
ask for pin when signing
Signed-off-by: David Lawrence <david.lawrence@docker.com> (github: endophage)
This commit is contained in:
parent
53ed60ed89
commit
07f0065152
|
|
@ -24,7 +24,9 @@ import (
|
||||||
"github.com/docker/notary/tuf/store"
|
"github.com/docker/notary/tuf/store"
|
||||||
)
|
)
|
||||||
|
|
||||||
const maxSize = 5 << 20
|
const (
|
||||||
|
maxSize = 5 << 20
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
data.SetDefaultExpiryTimes(
|
data.SetDefaultExpiryTimes(
|
||||||
|
|
@ -96,6 +98,50 @@ func NewTarget(targetName string, targetPath string) (*Target, error) {
|
||||||
return &Target{Name: targetName, Hashes: meta.Hashes, Length: meta.Length}, nil
|
return &Target{Name: targetName, Hashes: meta.Hashes, Length: meta.Length}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewNotaryRepository is a helper method that returns a new notary repository.
|
||||||
|
// It takes the base directory under where all the trust files will be stored
|
||||||
|
// (usually ~/.docker/trust/).
|
||||||
|
func NewNotaryRepository(baseDir, gun, baseURL string, rt http.RoundTripper,
|
||||||
|
passphraseRetriever passphrase.Retriever) (*NotaryRepository, error) {
|
||||||
|
|
||||||
|
keysPath := filepath.Join(baseDir, keystoremanager.PrivDir)
|
||||||
|
fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, passphraseRetriever)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
keyStoreManager, err := keystoremanager.NewKeyStoreManager(baseDir, fileKeyStore)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
yubiKeyStore := api.NewYubiKeyStore(passphraseRetriever)
|
||||||
|
cryptoService := cryptoservice.NewCryptoService(gun, yubiKeyStore, fileKeyStore)
|
||||||
|
|
||||||
|
nRepo := &NotaryRepository{
|
||||||
|
gun: gun,
|
||||||
|
baseDir: baseDir,
|
||||||
|
baseURL: baseURL,
|
||||||
|
tufRepoPath: filepath.Join(baseDir, tufDir, filepath.FromSlash(gun)),
|
||||||
|
CryptoService: cryptoService,
|
||||||
|
roundTrip: rt,
|
||||||
|
KeyStoreManager: keyStoreManager,
|
||||||
|
}
|
||||||
|
|
||||||
|
fileStore, err := store.NewFilesystemStore(
|
||||||
|
nRepo.tufRepoPath,
|
||||||
|
"metadata",
|
||||||
|
"json",
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
nRepo.fileStore = fileStore
|
||||||
|
|
||||||
|
return nRepo, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize creates a new repository by using rootKey as the root Key for the
|
// Initialize creates a new repository by using rootKey as the root Key for the
|
||||||
// TUF repository.
|
// TUF repository.
|
||||||
func (r *NotaryRepository) Initialize(rootKeyID string) error {
|
func (r *NotaryRepository) Initialize(rootKeyID string) error {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/notary/keystoremanager"
|
"github.com/docker/notary/keystoremanager"
|
||||||
|
|
@ -55,7 +56,12 @@ func certRemove(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
parseConfig()
|
parseConfig()
|
||||||
|
|
||||||
keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir, retriever)
|
keysPath := filepath.Join(trustDir, keystoremanager.PrivDir)
|
||||||
|
fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, retriever)
|
||||||
|
if err != nil {
|
||||||
|
fatalf("failed to create private key store in directory: %s", keysPath)
|
||||||
|
}
|
||||||
|
keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir, fileKeyStore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("failed to create a new truststore manager with directory: %s", trustDir)
|
fatalf("failed to create a new truststore manager with directory: %s", trustDir)
|
||||||
}
|
}
|
||||||
|
|
@ -119,7 +125,12 @@ func certList(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
parseConfig()
|
parseConfig()
|
||||||
|
|
||||||
keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir, retriever)
|
keysPath := filepath.Join(trustDir, keystoremanager.PrivDir)
|
||||||
|
fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, retriever)
|
||||||
|
if err != nil {
|
||||||
|
fatalf("failed to create private key store in directory: %s", keysPath)
|
||||||
|
}
|
||||||
|
keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir, fileKeyStore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("failed to create a new truststore manager with directory: %s", trustDir)
|
fatalf("failed to create a new truststore manager with directory: %s", trustDir)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import (
|
||||||
notaryclient "github.com/docker/notary/client"
|
notaryclient "github.com/docker/notary/client"
|
||||||
"github.com/docker/notary/keystoremanager"
|
"github.com/docker/notary/keystoremanager"
|
||||||
"github.com/docker/notary/pkg/passphrase"
|
"github.com/docker/notary/pkg/passphrase"
|
||||||
|
"github.com/docker/notary/trustmanager"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
@ -111,7 +112,12 @@ func keysRemoveKey(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
parseConfig()
|
parseConfig()
|
||||||
|
|
||||||
keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir, retriever)
|
keysPath := filepath.Join(trustDir, keystoremanager.PrivDir)
|
||||||
|
fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, retriever)
|
||||||
|
if err != nil {
|
||||||
|
fatalf("failed to create private key store in directory: %s", keysPath)
|
||||||
|
}
|
||||||
|
keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir, fileKeyStore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("failed to create a new truststore manager with directory: %s", trustDir)
|
fatalf("failed to create a new truststore manager with directory: %s", trustDir)
|
||||||
}
|
}
|
||||||
|
|
@ -167,7 +173,12 @@ func keysList(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
parseConfig()
|
parseConfig()
|
||||||
|
|
||||||
keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir, retriever)
|
keysPath := filepath.Join(trustDir, keystoremanager.PrivDir)
|
||||||
|
fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, retriever)
|
||||||
|
if err != nil {
|
||||||
|
fatalf("failed to create private key store in directory: %s", keysPath)
|
||||||
|
}
|
||||||
|
keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir, fileKeyStore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("failed to create a new truststore manager with directory: %s", trustDir)
|
fatalf("failed to create a new truststore manager with directory: %s", trustDir)
|
||||||
}
|
}
|
||||||
|
|
@ -220,7 +231,12 @@ func keysGenerateRootKey(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
parseConfig()
|
parseConfig()
|
||||||
|
|
||||||
keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir, retriever)
|
keysPath := filepath.Join(trustDir, keystoremanager.PrivDir)
|
||||||
|
fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, retriever)
|
||||||
|
if err != nil {
|
||||||
|
fatalf("failed to create private key store in directory: %s", keysPath)
|
||||||
|
}
|
||||||
|
keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir, fileKeyStore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("failed to create a new truststore manager with directory: %s", trustDir)
|
fatalf("failed to create a new truststore manager with directory: %s", trustDir)
|
||||||
}
|
}
|
||||||
|
|
@ -244,7 +260,12 @@ func keysExport(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
parseConfig()
|
parseConfig()
|
||||||
|
|
||||||
keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir, retriever)
|
keysPath := filepath.Join(trustDir, keystoremanager.PrivDir)
|
||||||
|
fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, retriever)
|
||||||
|
if err != nil {
|
||||||
|
fatalf("failed to create private key store in directory: %s", keysPath)
|
||||||
|
}
|
||||||
|
keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir, fileKeyStore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("failed to create a new truststore manager with directory: %s", trustDir)
|
fatalf("failed to create a new truststore manager with directory: %s", trustDir)
|
||||||
}
|
}
|
||||||
|
|
@ -287,7 +308,12 @@ func keysExportRoot(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
parseConfig()
|
parseConfig()
|
||||||
|
|
||||||
keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir, retriever)
|
keysPath := filepath.Join(trustDir, keystoremanager.PrivDir)
|
||||||
|
fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, retriever)
|
||||||
|
if err != nil {
|
||||||
|
fatalf("failed to create private key store in directory: %s", keysPath)
|
||||||
|
}
|
||||||
|
keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir, fileKeyStore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("failed to create a new truststore manager with directory: %s", trustDir)
|
fatalf("failed to create a new truststore manager with directory: %s", trustDir)
|
||||||
}
|
}
|
||||||
|
|
@ -322,7 +348,12 @@ func keysImport(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
parseConfig()
|
parseConfig()
|
||||||
|
|
||||||
keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir, retriever)
|
keysPath := filepath.Join(trustDir, keystoremanager.PrivDir)
|
||||||
|
fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, retriever)
|
||||||
|
if err != nil {
|
||||||
|
fatalf("failed to create private key store in directory: %s", keysPath)
|
||||||
|
}
|
||||||
|
keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir, fileKeyStore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("failed to create a new truststore manager with directory: %s", trustDir)
|
fatalf("failed to create a new truststore manager with directory: %s", trustDir)
|
||||||
}
|
}
|
||||||
|
|
@ -351,7 +382,12 @@ func keysImportRoot(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
parseConfig()
|
parseConfig()
|
||||||
|
|
||||||
keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir, retriever)
|
keysPath := filepath.Join(trustDir, keystoremanager.PrivDir)
|
||||||
|
fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, retriever)
|
||||||
|
if err != nil {
|
||||||
|
fatalf("failed to create private key store in directory: %s", keysPath)
|
||||||
|
}
|
||||||
|
keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir, fileKeyStore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("failed to create a new truststore manager with directory: %s", trustDir)
|
fatalf("failed to create a new truststore manager with directory: %s", trustDir)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ func (km *KeyStoreManager) ExportRootKeyReencrypt(dest io.Writer, keyID string,
|
||||||
tempBaseDir, err := ioutil.TempDir("", "notary-key-export-")
|
tempBaseDir, err := ioutil.TempDir("", "notary-key-export-")
|
||||||
defer os.RemoveAll(tempBaseDir)
|
defer os.RemoveAll(tempBaseDir)
|
||||||
|
|
||||||
tempKeysPath := filepath.Join(tempBaseDir, privDir)
|
tempKeysPath := filepath.Join(tempBaseDir, PrivDir)
|
||||||
tempKeyStore, err := trustmanager.NewKeyFileStore(tempKeysPath, newPassphraseRetriever)
|
tempKeyStore, err := trustmanager.NewKeyFileStore(tempKeysPath, newPassphraseRetriever)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -178,7 +178,7 @@ func (km *KeyStoreManager) ExportAllKeys(dest io.Writer, newPassphraseRetriever
|
||||||
defer os.RemoveAll(tempBaseDir)
|
defer os.RemoveAll(tempBaseDir)
|
||||||
|
|
||||||
// Create temporary keystore to use as a staging area
|
// Create temporary keystore to use as a staging area
|
||||||
tempKeysPath := filepath.Join(tempBaseDir, privDir)
|
tempKeysPath := filepath.Join(tempBaseDir, PrivDir)
|
||||||
tempKeyStore, err := trustmanager.NewKeyFileStore(tempKeysPath, newPassphraseRetriever)
|
tempKeyStore, err := trustmanager.NewKeyFileStore(tempKeysPath, newPassphraseRetriever)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -190,7 +190,7 @@ func (km *KeyStoreManager) ExportAllKeys(dest io.Writer, newPassphraseRetriever
|
||||||
|
|
||||||
zipWriter := zip.NewWriter(dest)
|
zipWriter := zip.NewWriter(dest)
|
||||||
|
|
||||||
if err := addKeysToArchive(zipWriter, tempKeyStore, privDir); err != nil {
|
if err := addKeysToArchive(zipWriter, tempKeyStore, PrivDir); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -224,14 +224,14 @@ func (km *KeyStoreManager) ImportKeysZip(zipReader zip.Reader) error {
|
||||||
|
|
||||||
// Note that using / as a separator is okay here - the zip
|
// Note that using / as a separator is okay here - the zip
|
||||||
// package guarantees that the separator will be /
|
// package guarantees that the separator will be /
|
||||||
if strings.HasPrefix(fNameTrimmed, privDir) {
|
if strings.HasPrefix(fNameTrimmed, PrivDir) {
|
||||||
if fNameTrimmed[len(fNameTrimmed)-5:] == "_root" {
|
if fNameTrimmed[len(fNameTrimmed)-5:] == "_root" {
|
||||||
if err = checkRootKeyIsEncrypted(fileBytes); err != nil {
|
if err = checkRootKeyIsEncrypted(fileBytes); err != nil {
|
||||||
rc.Close()
|
rc.Close()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
keyName := strings.TrimPrefix(fNameTrimmed, privDir)
|
keyName := strings.TrimPrefix(fNameTrimmed, PrivDir)
|
||||||
newKeys[keyName] = fileBytes
|
newKeys[keyName] = fileBytes
|
||||||
} else {
|
} else {
|
||||||
// This path inside the zip archive doesn't look like a
|
// This path inside the zip archive doesn't look like a
|
||||||
|
|
@ -283,7 +283,7 @@ func (km *KeyStoreManager) ExportKeysByGUN(dest io.Writer, gun string, passphras
|
||||||
defer os.RemoveAll(tempBaseDir)
|
defer os.RemoveAll(tempBaseDir)
|
||||||
|
|
||||||
// Create temporary keystore to use as a staging area
|
// Create temporary keystore to use as a staging area
|
||||||
tempKeysPath := filepath.Join(tempBaseDir, privDir)
|
tempKeysPath := filepath.Join(tempBaseDir, PrivDir)
|
||||||
tempKeyStore, err := trustmanager.NewKeyFileStore(tempKeysPath, passphraseRetriever)
|
tempKeyStore, err := trustmanager.NewKeyFileStore(tempKeysPath, passphraseRetriever)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -299,7 +299,7 @@ func (km *KeyStoreManager) ExportKeysByGUN(dest io.Writer, gun string, passphras
|
||||||
return ErrNoKeysFoundForGUN
|
return ErrNoKeysFoundForGUN
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := addKeysToArchive(zipWriter, tempKeyStore, privDir); err != nil {
|
if err := addKeysToArchive(zipWriter, tempKeyStore, PrivDir); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/docker/notary/pkg/passphrase"
|
|
||||||
"github.com/docker/notary/trustmanager"
|
"github.com/docker/notary/trustmanager"
|
||||||
"github.com/docker/notary/tuf/data"
|
"github.com/docker/notary/tuf/data"
|
||||||
"github.com/docker/notary/tuf/signed"
|
"github.com/docker/notary/tuf/signed"
|
||||||
|
|
@ -26,7 +25,7 @@ type KeyStoreManager struct {
|
||||||
|
|
||||||
const (
|
const (
|
||||||
trustDir = "trusted_certificates"
|
trustDir = "trusted_certificates"
|
||||||
privDir = "private"
|
PrivDir = "private"
|
||||||
rsaRootKeySize = 4096 // Used for new root keys
|
rsaRootKeySize = 4096 // Used for new root keys
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -56,13 +55,7 @@ func (err ErrRootRotationFail) Error() string {
|
||||||
|
|
||||||
// NewKeyStoreManager returns an initialized KeyStoreManager, or an error
|
// NewKeyStoreManager returns an initialized KeyStoreManager, or an error
|
||||||
// if it fails to create the KeyFileStores or load certificates
|
// if it fails to create the KeyFileStores or load certificates
|
||||||
func NewKeyStoreManager(baseDir string, passphraseRetriever passphrase.Retriever) (*KeyStoreManager, error) {
|
func NewKeyStoreManager(baseDir string, keyStore *trustmanager.KeyFileStore) (*KeyStoreManager, error) {
|
||||||
keysPath := filepath.Join(baseDir, privDir)
|
|
||||||
keyStore, err := trustmanager.NewKeyFileStore(keysPath, passphraseRetriever)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
trustPath := filepath.Join(baseDir, trustDir)
|
trustPath := filepath.Join(baseDir, trustDir)
|
||||||
|
|
||||||
// Load all CAs that aren't expired and don't use SHA1
|
// Load all CAs that aren't expired and don't use SHA1
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
|
@ -121,8 +122,12 @@ func TestValidateRoot(t *testing.T) {
|
||||||
defer os.RemoveAll(tempBaseDir)
|
defer os.RemoveAll(tempBaseDir)
|
||||||
assert.NoError(t, err, "failed to create a temporary directory: %s", err)
|
assert.NoError(t, err, "failed to create a temporary directory: %s", err)
|
||||||
|
|
||||||
|
keysPath := filepath.Join(tempBaseDir, PrivDir)
|
||||||
|
fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, passphraseRetriever)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// Create a FileStoreManager
|
// Create a FileStoreManager
|
||||||
keyStoreManager, err := NewKeyStoreManager(tempBaseDir, passphraseRetriever)
|
keyStoreManager, err := NewKeyStoreManager(tempBaseDir, fileKeyStore)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// Execute our template
|
// Execute our template
|
||||||
|
|
@ -229,8 +234,12 @@ func filestoreWithTwoCerts(t *testing.T, gun, keyAlg string) (
|
||||||
tempBaseDir, err := ioutil.TempDir("", "notary-test-")
|
tempBaseDir, err := ioutil.TempDir("", "notary-test-")
|
||||||
assert.NoError(t, err, "failed to create a temporary directory: %s", err)
|
assert.NoError(t, err, "failed to create a temporary directory: %s", err)
|
||||||
|
|
||||||
|
keysPath := filepath.Join(tempBaseDir, PrivDir)
|
||||||
|
fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, passphraseRetriever)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// Create a FileStoreManager
|
// Create a FileStoreManager
|
||||||
keyStoreManager, err := NewKeyStoreManager(tempBaseDir, passphraseRetriever)
|
keyStoreManager, err := NewKeyStoreManager(tempBaseDir, fileKeyStore)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
certs := make([]*x509.Certificate, 2)
|
certs := make([]*x509.Certificate, 2)
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,17 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
|
"github.com/docker/notary/pkg/passphrase"
|
||||||
"github.com/docker/notary/trustmanager"
|
"github.com/docker/notary/trustmanager"
|
||||||
"github.com/docker/notary/tuf/data"
|
"github.com/docker/notary/tuf/data"
|
||||||
"github.com/miekg/pkcs11"
|
"github.com/miekg/pkcs11"
|
||||||
)
|
)
|
||||||
|
|
||||||
const pkcs11Lib = "/usr/local/lib/libykcs11.so"
|
const (
|
||||||
const USER_PIN = "123456"
|
pkcs11Lib = "/usr/local/lib/libykcs11.so"
|
||||||
|
USER_PIN = "123456"
|
||||||
|
SO_USER_PIN = "010203040506070801020304050607080102030405060708"
|
||||||
|
)
|
||||||
|
|
||||||
// Hardcoded yubikey PKCS11 ID
|
// Hardcoded yubikey PKCS11 ID
|
||||||
var YUBIKEY_ROOT_KEY_ID = []byte{2}
|
var YUBIKEY_ROOT_KEY_ID = []byte{2}
|
||||||
|
|
@ -29,14 +33,18 @@ var YUBIKEY_ROOT_KEY_ID = []byte{2}
|
||||||
// YubiPrivateKey represents a private key inside of a yubikey
|
// YubiPrivateKey represents a private key inside of a yubikey
|
||||||
type YubiPrivateKey struct {
|
type YubiPrivateKey struct {
|
||||||
data.ECDSAPublicKey
|
data.ECDSAPublicKey
|
||||||
|
passRetriever passphrase.Retriever
|
||||||
}
|
}
|
||||||
|
|
||||||
type YubikeySigner struct {
|
type YubikeySigner struct {
|
||||||
YubiPrivateKey
|
YubiPrivateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewYubiPrivateKey(pubKey data.ECDSAPublicKey) *YubiPrivateKey {
|
func NewYubiPrivateKey(pubKey data.ECDSAPublicKey, passRetriever passphrase.Retriever) *YubiPrivateKey {
|
||||||
return &YubiPrivateKey{ECDSAPublicKey: pubKey}
|
return &YubiPrivateKey{
|
||||||
|
ECDSAPublicKey: pubKey,
|
||||||
|
passRetriever: passRetriever,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ys *YubikeySigner) Public() crypto.PublicKey {
|
func (ys *YubikeySigner) Public() crypto.PublicKey {
|
||||||
|
|
@ -72,7 +80,7 @@ func (y *YubiPrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts
|
||||||
}
|
}
|
||||||
defer cleanup(ctx, session)
|
defer cleanup(ctx, session)
|
||||||
|
|
||||||
sig, err := sign(ctx, session, YUBIKEY_ROOT_KEY_ID, msg)
|
sig, err := sign(ctx, session, YUBIKEY_ROOT_KEY_ID, y.passRetriever, msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to sign using Yubikey: %v", err)
|
return nil, fmt.Errorf("failed to sign using Yubikey: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -81,11 +89,11 @@ func (y *YubiPrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts
|
||||||
}
|
}
|
||||||
|
|
||||||
// addECDSAKey adds a key to the yubikey
|
// addECDSAKey adds a key to the yubikey
|
||||||
func addECDSAKey(ctx *pkcs11.Ctx, session pkcs11.SessionHandle, privKey data.PrivateKey, pkcs11KeyID []byte) error {
|
func addECDSAKey(ctx *pkcs11.Ctx, session pkcs11.SessionHandle, privKey data.PrivateKey, pkcs11KeyID []byte, passRetriever passphrase.Retriever) error {
|
||||||
logrus.Debugf("Got into add key with key: %s\n", privKey.ID())
|
logrus.Debugf("Got into add key with key: %s\n", privKey.ID())
|
||||||
|
|
||||||
// TODO(diogo): Figure out CKU_SO with yubikey
|
// TODO(diogo): Figure out CKU_SO with yubikey
|
||||||
err := ctx.Login(session, pkcs11.CKU_SO, "010203040506070801020304050607080102030405060708")
|
err := login(ctx, session, passRetriever, pkcs11.CKU_SO, SO_USER_PIN)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -206,8 +214,8 @@ func getECDSAKey(ctx *pkcs11.Ctx, session pkcs11.SessionHandle, pkcs11KeyID []by
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sign returns a signature for a given signature request
|
// Sign returns a signature for a given signature request
|
||||||
func sign(ctx *pkcs11.Ctx, session pkcs11.SessionHandle, pkcs11KeyID, payload []byte) ([]byte, error) {
|
func sign(ctx *pkcs11.Ctx, session pkcs11.SessionHandle, pkcs11KeyID []byte, passRetriever passphrase.Retriever, payload []byte) ([]byte, error) {
|
||||||
err := ctx.Login(session, pkcs11.CKU_USER, USER_PIN)
|
err := login(ctx, session, passRetriever, pkcs11.CKU_USER, USER_PIN)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error logging in: %v", err)
|
return nil, fmt.Errorf("error logging in: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -253,10 +261,12 @@ func sign(ctx *pkcs11.Ctx, session pkcs11.SessionHandle, pkcs11KeyID, payload []
|
||||||
return sig[:], nil
|
return sig[:], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type YubiKeyStore struct{}
|
type YubiKeyStore struct {
|
||||||
|
passRetriever passphrase.Retriever
|
||||||
|
}
|
||||||
|
|
||||||
func NewYubiKeyStore() *YubiKeyStore {
|
func NewYubiKeyStore(passphraseRetriever passphrase.Retriever) *YubiKeyStore {
|
||||||
return &YubiKeyStore{}
|
return &YubiKeyStore{passRetriever: passphraseRetriever}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *YubiKeyStore) ListKeys() map[string]string {
|
func (s *YubiKeyStore) ListKeys() map[string]string {
|
||||||
|
|
@ -285,7 +295,7 @@ func (s *YubiKeyStore) AddKey(keyID, alias string, privKey data.PrivateKey) erro
|
||||||
}
|
}
|
||||||
defer cleanup(ctx, session)
|
defer cleanup(ctx, session)
|
||||||
|
|
||||||
return addECDSAKey(ctx, session, privKey, YUBIKEY_ROOT_KEY_ID)
|
return addECDSAKey(ctx, session, privKey, YUBIKEY_ROOT_KEY_ID, s.passRetriever)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *YubiKeyStore) GetKey(keyID string) (data.PrivateKey, string, error) {
|
func (s *YubiKeyStore) GetKey(keyID string) (data.PrivateKey, string, error) {
|
||||||
|
|
@ -303,7 +313,7 @@ func (s *YubiKeyStore) GetKey(keyID string) (data.PrivateKey, string, error) {
|
||||||
if pubKey.ID() != keyID {
|
if pubKey.ID() != keyID {
|
||||||
return nil, "", fmt.Errorf("expected root key: %s, but found: %s\n", keyID, pubKey.ID())
|
return nil, "", fmt.Errorf("expected root key: %s, but found: %s\n", keyID, pubKey.ID())
|
||||||
}
|
}
|
||||||
privKey := NewYubiPrivateKey(*pubKey)
|
privKey := NewYubiPrivateKey(*pubKey, s.passRetriever)
|
||||||
if privKey == nil {
|
if privKey == nil {
|
||||||
return nil, "", errors.New("could not initialize new YubiPrivateKey")
|
return nil, "", errors.New("could not initialize new YubiPrivateKey")
|
||||||
}
|
}
|
||||||
|
|
@ -367,3 +377,40 @@ func SetupHSMEnv(libraryPath string) (*pkcs11.Ctx, pkcs11.SessionHandle, error)
|
||||||
|
|
||||||
return p, session, nil
|
return p, session, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func login(ctx *pkcs11.Ctx, session pkcs11.SessionHandle, passRetriever passphrase.Retriever, userFlag uint, defaultPassw string) error {
|
||||||
|
// try default password
|
||||||
|
err := ctx.Login(session, userFlag, defaultPassw)
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// default failed, ask user for password
|
||||||
|
for attempts := 0; ; attempts++ {
|
||||||
|
var (
|
||||||
|
giveup bool
|
||||||
|
err error
|
||||||
|
user string
|
||||||
|
)
|
||||||
|
if userFlag == pkcs11.CKU_SO {
|
||||||
|
user = "SO Pin"
|
||||||
|
} else {
|
||||||
|
user = "Pin"
|
||||||
|
}
|
||||||
|
passwd, giveup, err := passRetriever(user, "yubikey", false, attempts)
|
||||||
|
// Check if the passphrase retriever got an error or if it is telling us to give up
|
||||||
|
if giveup || err != nil {
|
||||||
|
return trustmanager.ErrPasswordInvalid{}
|
||||||
|
}
|
||||||
|
if attempts > 2 {
|
||||||
|
return trustmanager.ErrAttemptsExceeded{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to convert PEM encoded bytes back to a PrivateKey using the passphrase
|
||||||
|
err = ctx.Login(session, userFlag, passwd)
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue