Pad the ECDSA key that gets put into the Yubikey so it has 32 bytes.

Apparently that is required by the template, and will error if it
does not. Sometimes, ECDSA keys are generated which when encoded
seems to only have 31 bytes.

Signed-off-by: Ying Li <ying.li@docker.com>
Signed-off-by: David Lawrence <david.lawrence@docker.com>

Signed-off-by: Ying Li <ying.li@docker.com> (github: endophage)
This commit is contained in:
Ying Li 2015-11-09 13:05:52 -08:00 committed by David Lawrence
parent 91b7d87a7b
commit 397adb4291
2 changed files with 43 additions and 1 deletions

View File

@ -30,6 +30,9 @@ const (
KeymodeTouch = 1 // touch enabled KeymodeTouch = 1 // touch enabled
KeymodePinOnce = 2 // require pin entry once KeymodePinOnce = 2 // require pin entry once
KeymodePinAlways = 4 // require pin entry all the time KeymodePinAlways = 4 // require pin entry all the time
// the key size, when importing a key into yubikey, MUST be 32 bytes
ecdsaPrivateKeySize = 32
) )
// what key mode to use when generating keys // what key mode to use when generating keys
@ -136,6 +139,18 @@ func (y *YubiPrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts
return sig, nil return sig, nil
} }
// If a byte array is less than the number of bytes specified by
// ecdsaPrivateKeySize, left-zero-pad the byte array until
// it is the required size.
func ensurePrivateKeySize(payload []byte) []byte {
final := payload
if len(payload) < ecdsaPrivateKeySize {
final = make([]byte, ecdsaPrivateKeySize)
copy(final[ecdsaPrivateKeySize-len(payload):], payload)
}
return final
}
// addECDSAKey adds a key to the yubikey // addECDSAKey adds a key to the yubikey
func addECDSAKey( func addECDSAKey(
ctx *pkcs11.Ctx, ctx *pkcs11.Ctx,
@ -161,7 +176,7 @@ func addECDSAKey(
return err return err
} }
ecdsaPrivKeyD := ecdsaPrivKey.D.Bytes() ecdsaPrivKeyD := ensurePrivateKeySize(ecdsaPrivKey.D.Bytes())
logrus.Debugf("Getting D bytes: %v\n", ecdsaPrivKeyD) logrus.Debugf("Getting D bytes: %v\n", ecdsaPrivKeyD)
template, err := NewCertificate(role) template, err := NewCertificate(role)

View File

@ -4,6 +4,7 @@ package trustmanager
import ( import (
"crypto/rand" "crypto/rand"
"reflect"
"testing" "testing"
"github.com/docker/notary/passphrase" "github.com/docker/notary/passphrase"
@ -25,6 +26,32 @@ func clearAllKeys(t *testing.T) {
} }
} }
func TestEnsurePrivateKeySizePassesThroughRightSizeArrays(t *testing.T) {
fullByteArray := make([]byte, ecdsaPrivateKeySize)
for i := range fullByteArray {
fullByteArray[i] = byte(1)
}
result := ensurePrivateKeySize(fullByteArray)
assert.True(t, reflect.DeepEqual(fullByteArray, result))
}
// The pad32Byte helper function left zero-pads byte arrays that are less than
// ecdsaPrivateKeySize bytes
func TestEnsurePrivateKeySizePadsLessThanRequiredSizeArrays(t *testing.T) {
shortByteArray := make([]byte, ecdsaPrivateKeySize/2)
for i := range shortByteArray {
shortByteArray[i] = byte(1)
}
expected := append(
make([]byte, ecdsaPrivateKeySize-ecdsaPrivateKeySize/2),
shortByteArray...)
result := ensurePrivateKeySize(shortByteArray)
assert.True(t, reflect.DeepEqual(expected, result))
}
func testAddKey(t *testing.T, store *YubiKeyStore) (data.PrivateKey, error) { func testAddKey(t *testing.T, store *YubiKeyStore) (data.PrivateKey, error) {
privKey, err := GenerateECDSAKey(rand.Reader) privKey, err := GenerateECDSAKey(rand.Reader)
assert.NoError(t, err) assert.NoError(t, err)