Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

abstracting pkcs11 package and adding another vendor besides yubikey #1352

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

florianeichin
Copy link

@florianeichin florianeichin commented May 8, 2018

Issue Description

The only hardware that notary supports as trustmanager is Yubikey. We would like to extend notary to support other devices that work according to PKCS#11 -- and for our case add support for devices that are used through the opencryptoki library. Our suggestion is to split this up into two steps:

  1. Create an abstraction for pkcs11 (and move Yubikey in there).
  2. add opencryptoki support

So essentially this results in a file structure like the following:

├─trustmanager 
│     ├─pkcs11
│     │   ├─yubikey
│     │   └─ opencryptoki

Other PKCS#11 exploiters can hook in at the level below PKCS#11. To keep enablement of other PKCS#11 trustmanagers simple in general, we think it would make sense, to abstract some of the yubikey files and code pieces to reuse them.
The abstraction could go that far, that just the following yubikeystore functions have to stay hardware specific, everything else could be reused by opencryptoki and other pkcs11 implementations:

  • getECDSAKey(),
  • addECDSAKey(),
  • yubiRemoveKey(),
  • Sign(),
  • hardwareListKey(),
  • listObjects(),
  • SetupHSMEnv()

PR Description

This PR addresses #1289

  • First commit abstracts the yubikey package into a hardwareindependent pcks11 package and a hardwarespecific yubikey package.
  • Second commit adds opencryptoki as another hardware implementation.

@docker-jenkins
Copy link

Can one of the admins verify this patch?

@florianeichin florianeichin force-pushed the opencryptoki branch 6 times, most recently from cc73875 to e537e75 Compare May 9, 2018 09:40
hpk.libLoader = loader
}

// CryptoSigner returns a crypto.Signer tha wraps the HardwarePrivateKey. Needed for
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type "tha"

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed that and pushed the fix

@florianeichin florianeichin force-pushed the opencryptoki branch 3 times, most recently from 1d82cbf to 317691c Compare May 16, 2018 07:44
@justincormack
Copy link
Contributor

If you rebase this it should fix CI now...

@@ -69,7 +70,7 @@ func NewFileCachedRepository(baseDir string, gun data.GUN, baseURL string, rt ht
if err != nil {
return nil, err
}

pkcs11.Setup()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could/should this be done in an init() function in the pkcs11 package?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are absolutely right. A non_pkcs11 package should not contain any relation to a pkcs11 package it. I added an init() function in the pkcs11 package.
The init() just calls Setup(), because Docker for example uses another entrypoint into notary while building/pushing. It uses client/repo(_pkcs11).go as entry. If not calling Setup() there, the whole pkcs11 package would not be imported just pkcs11/common.
So init of pkcs11 would not be called.
Therefore in repo_pcks11.go the call for Setup() remains.

}

// hardwareSigner wraps a HardwarePrivateKey and implements the crypto.Signer interface
type hardwareSigner struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the need for the extra wrapper? crypto.Signer is only implemented by virtue of the embedded HardwarePrivateKey?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actualy don't know in that case. Took this from the original yubikey implementation. Seems to be implemented like this since the first yubikey enhanced release. So I don't know what was the intention to do it like that. Didn't want to touch things like this, to keep this restructuring as simple as possible.

)

const (
// SigAttempts defines maximum attempts to sign an image before aborting
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notary is not Docker/container specific, shouldn't reference "image"

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed "image" to "artifact"

SlotID: slot,
KeyID: keyID,
}
//err = hardwareKeyStore.AddECDSAKey(ctx, session, privKey, slot, s.PassRetriever, role)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove commented out line.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed the line

)

// SetKeyStore sets up the to be used keystore
func SetKeyStore(ks HardwareSpecificStore) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This appears to be restricting us to only being able to access a single hardware device at a time. Is that correct? If yes, how can we not incur that limitation.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes this is right, depending on which libs are found (opencryptoki and yubikey right now) a hardware device is chosen. Yet it would choose one of the libs and performing every crypto operation with it. What would be your suggestion for breaking down this limitation? And what do you mean with "at a time"? You would like to have a selection, which hardware should bes used? Didn't think about it (and it's design implications) too much yet, but with further development there could be a mechanism that chooses one if just one is present and asks which to use if more than one is found.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we would instantiate a key store for every recognized hardware device attached to the system. You might run into cases where say, 2 yubikeys were attached, one having the root or targets key, one having your delegation key.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really know, if and how this is supported by the yubikey library. As we never tell them which usb/device to use, I don't think that the yubicopkcs11 lib supports choosing a device. I think this is a bigger piece of work, that needs an own story and pr.

resolves notaryproject#1289
Signed-off-by: Florian Eichin <florian.eichin@gmail.com>
@florianeichin florianeichin force-pushed the opencryptoki branch 2 times, most recently from a7e8427 to 3f8397b Compare May 17, 2018 06:27
resolves notaryproject#1289
Signed-off-by: Florian Eichin <florian.eichin@gmail.com>
@florianeichin
Copy link
Author

As I'm leaving the team, developing the code leading to this PR, https://github.com/jschintag will continue development

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants