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" | ||||
| ) | ||||
| 
 | ||||
| const maxSize = 5 << 20 | ||||
| const ( | ||||
| 	maxSize = 5 << 20 | ||||
| ) | ||||
| 
 | ||||
| func init() { | ||||
| 	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 | ||||
| } | ||||
| 
 | ||||
| // 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
 | ||||
| // TUF repository.
 | ||||
| func (r *NotaryRepository) Initialize(rootKeyID string) error { | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ import ( | |||
| 	"fmt" | ||||
| 	"math" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/docker/notary/keystoremanager" | ||||
|  | @ -55,7 +56,12 @@ func certRemove(cmd *cobra.Command, args []string) { | |||
| 
 | ||||
| 	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 { | ||||
| 		fatalf("failed to create a new truststore manager with directory: %s", trustDir) | ||||
| 	} | ||||
|  | @ -119,7 +125,12 @@ func certList(cmd *cobra.Command, args []string) { | |||
| 
 | ||||
| 	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 { | ||||
| 		fatalf("failed to create a new truststore manager with directory: %s", trustDir) | ||||
| 	} | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ import ( | |||
| 	notaryclient "github.com/docker/notary/client" | ||||
| 	"github.com/docker/notary/keystoremanager" | ||||
| 	"github.com/docker/notary/pkg/passphrase" | ||||
| 	"github.com/docker/notary/trustmanager" | ||||
| 
 | ||||
| 	"github.com/spf13/cobra" | ||||
| ) | ||||
|  | @ -111,7 +112,12 @@ func keysRemoveKey(cmd *cobra.Command, args []string) { | |||
| 
 | ||||
| 	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 { | ||||
| 		fatalf("failed to create a new truststore manager with directory: %s", trustDir) | ||||
| 	} | ||||
|  | @ -167,7 +173,12 @@ func keysList(cmd *cobra.Command, args []string) { | |||
| 
 | ||||
| 	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 { | ||||
| 		fatalf("failed to create a new truststore manager with directory: %s", trustDir) | ||||
| 	} | ||||
|  | @ -220,7 +231,12 @@ func keysGenerateRootKey(cmd *cobra.Command, args []string) { | |||
| 
 | ||||
| 	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 { | ||||
| 		fatalf("failed to create a new truststore manager with directory: %s", trustDir) | ||||
| 	} | ||||
|  | @ -244,7 +260,12 @@ func keysExport(cmd *cobra.Command, args []string) { | |||
| 
 | ||||
| 	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 { | ||||
| 		fatalf("failed to create a new truststore manager with directory: %s", trustDir) | ||||
| 	} | ||||
|  | @ -287,7 +308,12 @@ func keysExportRoot(cmd *cobra.Command, args []string) { | |||
| 
 | ||||
| 	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 { | ||||
| 		fatalf("failed to create a new truststore manager with directory: %s", trustDir) | ||||
| 	} | ||||
|  | @ -322,7 +348,12 @@ func keysImport(cmd *cobra.Command, args []string) { | |||
| 
 | ||||
| 	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 { | ||||
| 		fatalf("failed to create a new truststore manager with directory: %s", trustDir) | ||||
| 	} | ||||
|  | @ -351,7 +382,12 @@ func keysImportRoot(cmd *cobra.Command, args []string) { | |||
| 
 | ||||
| 	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 { | ||||
| 		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-") | ||||
| 	defer os.RemoveAll(tempBaseDir) | ||||
| 
 | ||||
| 	tempKeysPath := filepath.Join(tempBaseDir, privDir) | ||||
| 	tempKeysPath := filepath.Join(tempBaseDir, PrivDir) | ||||
| 	tempKeyStore, err := trustmanager.NewKeyFileStore(tempKeysPath, newPassphraseRetriever) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
|  | @ -178,7 +178,7 @@ func (km *KeyStoreManager) ExportAllKeys(dest io.Writer, newPassphraseRetriever | |||
| 	defer os.RemoveAll(tempBaseDir) | ||||
| 
 | ||||
| 	// 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) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
|  | @ -190,7 +190,7 @@ func (km *KeyStoreManager) ExportAllKeys(dest io.Writer, newPassphraseRetriever | |||
| 
 | ||||
| 	zipWriter := zip.NewWriter(dest) | ||||
| 
 | ||||
| 	if err := addKeysToArchive(zipWriter, tempKeyStore, privDir); err != nil { | ||||
| 	if err := addKeysToArchive(zipWriter, tempKeyStore, PrivDir); err != nil { | ||||
| 		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
 | ||||
| 		// package guarantees that the separator will be /
 | ||||
| 		if strings.HasPrefix(fNameTrimmed, privDir) { | ||||
| 		if strings.HasPrefix(fNameTrimmed, PrivDir) { | ||||
| 			if fNameTrimmed[len(fNameTrimmed)-5:] == "_root" { | ||||
| 				if err = checkRootKeyIsEncrypted(fileBytes); err != nil { | ||||
| 					rc.Close() | ||||
| 					return err | ||||
| 				} | ||||
| 			} | ||||
| 			keyName := strings.TrimPrefix(fNameTrimmed, privDir) | ||||
| 			keyName := strings.TrimPrefix(fNameTrimmed, PrivDir) | ||||
| 			newKeys[keyName] = fileBytes | ||||
| 		} else { | ||||
| 			// 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) | ||||
| 
 | ||||
| 	// 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) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
|  | @ -299,7 +299,7 @@ func (km *KeyStoreManager) ExportKeysByGUN(dest io.Writer, gun string, passphras | |||
| 		return ErrNoKeysFoundForGUN | ||||
| 	} | ||||
| 
 | ||||
| 	if err := addKeysToArchive(zipWriter, tempKeyStore, privDir); err != nil { | ||||
| 	if err := addKeysToArchive(zipWriter, tempKeyStore, PrivDir); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,7 +10,6 @@ import ( | |||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/Sirupsen/logrus" | ||||
| 	"github.com/docker/notary/pkg/passphrase" | ||||
| 	"github.com/docker/notary/trustmanager" | ||||
| 	"github.com/docker/notary/tuf/data" | ||||
| 	"github.com/docker/notary/tuf/signed" | ||||
|  | @ -26,7 +25,7 @@ type KeyStoreManager struct { | |||
| 
 | ||||
| const ( | ||||
| 	trustDir       = "trusted_certificates" | ||||
| 	privDir        = "private" | ||||
| 	PrivDir        = "private" | ||||
| 	rsaRootKeySize = 4096 // Used for new root keys
 | ||||
| ) | ||||
| 
 | ||||
|  | @ -56,13 +55,7 @@ func (err ErrRootRotationFail) Error() string { | |||
| 
 | ||||
| // NewKeyStoreManager returns an initialized KeyStoreManager, or an error
 | ||||
| // if it fails to create the KeyFileStores or load certificates
 | ||||
| func NewKeyStoreManager(baseDir string, passphraseRetriever passphrase.Retriever) (*KeyStoreManager, error) { | ||||
| 	keysPath := filepath.Join(baseDir, privDir) | ||||
| 	keyStore, err := trustmanager.NewKeyFileStore(keysPath, passphraseRetriever) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| func NewKeyStoreManager(baseDir string, keyStore *trustmanager.KeyFileStore) (*KeyStoreManager, error) { | ||||
| 	trustPath := filepath.Join(baseDir, trustDir) | ||||
| 
 | ||||
| 	// Load all CAs that aren't expired and don't use SHA1
 | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ import ( | |||
| 	"encoding/json" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"testing" | ||||
| 	"text/template" | ||||
| 
 | ||||
|  | @ -121,8 +122,12 @@ func TestValidateRoot(t *testing.T) { | |||
| 	defer os.RemoveAll(tempBaseDir) | ||||
| 	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
 | ||||
| 	keyStoreManager, err := NewKeyStoreManager(tempBaseDir, passphraseRetriever) | ||||
| 	keyStoreManager, err := NewKeyStoreManager(tempBaseDir, fileKeyStore) | ||||
| 	assert.NoError(t, err) | ||||
| 
 | ||||
| 	// Execute our template
 | ||||
|  | @ -229,8 +234,12 @@ func filestoreWithTwoCerts(t *testing.T, gun, keyAlg string) ( | |||
| 	tempBaseDir, err := ioutil.TempDir("", "notary-test-") | ||||
| 	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
 | ||||
| 	keyStoreManager, err := NewKeyStoreManager(tempBaseDir, passphraseRetriever) | ||||
| 	keyStoreManager, err := NewKeyStoreManager(tempBaseDir, fileKeyStore) | ||||
| 	assert.NoError(t, err) | ||||
| 
 | ||||
| 	certs := make([]*x509.Certificate, 2) | ||||
|  |  | |||
|  | @ -15,13 +15,17 @@ import ( | |||
| 	"math/big" | ||||
| 
 | ||||
| 	"github.com/Sirupsen/logrus" | ||||
| 	"github.com/docker/notary/pkg/passphrase" | ||||
| 	"github.com/docker/notary/trustmanager" | ||||
| 	"github.com/docker/notary/tuf/data" | ||||
| 	"github.com/miekg/pkcs11" | ||||
| ) | ||||
| 
 | ||||
| const pkcs11Lib = "/usr/local/lib/libykcs11.so" | ||||
| const USER_PIN = "123456" | ||||
| const ( | ||||
| 	pkcs11Lib   = "/usr/local/lib/libykcs11.so" | ||||
| 	USER_PIN    = "123456" | ||||
| 	SO_USER_PIN = "010203040506070801020304050607080102030405060708" | ||||
| ) | ||||
| 
 | ||||
| // Hardcoded yubikey PKCS11 ID
 | ||||
| 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
 | ||||
| type YubiPrivateKey struct { | ||||
| 	data.ECDSAPublicKey | ||||
| 	passRetriever passphrase.Retriever | ||||
| } | ||||
| 
 | ||||
| type YubikeySigner struct { | ||||
| 	YubiPrivateKey | ||||
| } | ||||
| 
 | ||||
| func NewYubiPrivateKey(pubKey data.ECDSAPublicKey) *YubiPrivateKey { | ||||
| 	return &YubiPrivateKey{ECDSAPublicKey: pubKey} | ||||
| func NewYubiPrivateKey(pubKey data.ECDSAPublicKey, passRetriever passphrase.Retriever) *YubiPrivateKey { | ||||
| 	return &YubiPrivateKey{ | ||||
| 		ECDSAPublicKey: pubKey, | ||||
| 		passRetriever:  passRetriever, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| 
 | ||||
| 	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 { | ||||
| 		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
 | ||||
| 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()) | ||||
| 
 | ||||
| 	// 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 { | ||||
| 		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
 | ||||
| func sign(ctx *pkcs11.Ctx, session pkcs11.SessionHandle, pkcs11KeyID, payload []byte) ([]byte, error) { | ||||
| 	err := ctx.Login(session, pkcs11.CKU_USER, USER_PIN) | ||||
| func sign(ctx *pkcs11.Ctx, session pkcs11.SessionHandle, pkcs11KeyID []byte, passRetriever passphrase.Retriever, payload []byte) ([]byte, error) { | ||||
| 	err := login(ctx, session, passRetriever, pkcs11.CKU_USER, USER_PIN) | ||||
| 	if err != nil { | ||||
| 		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 | ||||
| } | ||||
| 
 | ||||
| type YubiKeyStore struct{} | ||||
| type YubiKeyStore struct { | ||||
| 	passRetriever passphrase.Retriever | ||||
| } | ||||
| 
 | ||||
| func NewYubiKeyStore() *YubiKeyStore { | ||||
| 	return &YubiKeyStore{} | ||||
| func NewYubiKeyStore(passphraseRetriever passphrase.Retriever) *YubiKeyStore { | ||||
| 	return &YubiKeyStore{passRetriever: passphraseRetriever} | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| 
 | ||||
| 	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) { | ||||
|  | @ -303,7 +313,7 @@ func (s *YubiKeyStore) GetKey(keyID string) (data.PrivateKey, string, error) { | |||
| 	if pubKey.ID() != keyID { | ||||
| 		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 { | ||||
| 		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 | ||||
| } | ||||
| 
 | ||||
| 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