go-tpm-tools
go-tpm-tools copied to clipboard
CreateSigningKeyImportBlob for ECC keys
Is there any particular reason why CreateSigningKeyImportBlob
works only with RSA keys? createPublicPrivateSign allows the key to be only RSA. Probably support for exporting ECC parameters can be added there?
No particular reason. We would ideally support ECC, but it would require adding code in createPublicPrivateSign
and I just didn't get around to it in #70
I don't think it would be too hard to implement.
I've tried to do something along the lines of RSA example in the code, but it does not work unfortunately...
func createPublicPrivateSign(signingKey crypto.PrivateKey) (tpm2.Public, tpm2.Private, error) {
switch key := signingKey.(type) {
case *rsa.PrivateKey:
rsaPub := key.PublicKey
public := tpm2.Public{
Type: tpm2.AlgRSA,
NameAlg: client.DefaultEKTemplateRSA().NameAlg,
Attributes: tpm2.FlagSign,
RSAParameters: &tpm2.RSAParams{
KeyBits: uint16(rsaPub.N.BitLen()),
ExponentRaw: uint32(rsaPub.E),
ModulusRaw: rsaPub.N.Bytes(),
Sign: &tpm2.SigScheme{
Alg: tpm2.AlgRSASSA,
Hash: tpm2.AlgSHA256,
},
},
}
private := tpm2.Private{
Type: tpm2.AlgRSA,
AuthValue: nil,
SeedValue: nil, // Only Storage Keys need a seed value. See part 3 TPM2_CREATE b.3.
Sensitive: key.Primes[0].Bytes(),
}
return public, private, nil
case *ecdsa.PrivateKey:
eccPub := key.PublicKey
public := tpm2.Public{
Type: tpm2.AlgECC,
NameAlg: client.DefaultEKTemplateECC().NameAlg,
Attributes: tpm2.FlagSign,
ECCParameters: &tpm2.ECCParams{
CurveID: tpm2.CurveNISTP256,
Point: tpm2.ECPoint{
XRaw: make([]byte, 32),
YRaw: make([]byte, 32),
},
},
}
private := tpm2.Private{
Type: tpm2.AlgECC,
AuthValue: nil,
SeedValue: nil,
Sensitive: bytes.Join([][]byte{eccIntToBytes(eccPub, eccPub.X), eccIntToBytes(eccPub, eccPub.Y)}, []byte{}), // what to write here?
}
return public, private, nil
default:
return tpm2.Public{}, tpm2.Private{}, fmt.Errorf("unsupported signing key type: %T", signingKey)
}
}
It fails with Error: import failed: handle 0, error code 0x7 : key size is not supported
. Any pointers are greatly appreciated.
Okay, this version seems to be working. Can you take a look plese if it makes sense?
func createPublicPrivateSign(signingKey crypto.PrivateKey) (tpm2.Public, tpm2.Private, error) {
switch key := signingKey.(type) {
case *rsa.PrivateKey:
rsaPub := key.PublicKey
public := tpm2.Public{
Type: tpm2.AlgRSA,
NameAlg: client.DefaultEKTemplateRSA().NameAlg,
Attributes: tpm2.FlagSign,
RSAParameters: &tpm2.RSAParams{
KeyBits: uint16(rsaPub.N.BitLen()),
ExponentRaw: uint32(rsaPub.E),
ModulusRaw: rsaPub.N.Bytes(),
Sign: &tpm2.SigScheme{
Alg: tpm2.AlgRSASSA,
Hash: tpm2.AlgSHA256,
},
},
}
private := tpm2.Private{
Type: tpm2.AlgRSA,
AuthValue: nil,
SeedValue: nil, // Only Storage Keys need a seed value. See part 3 TPM2_CREATE b.3.
Sensitive: key.Primes[0].Bytes(),
}
return public, private, nil
case *ecdsa.PrivateKey:
eccPub := key.PublicKey
public := tpm2.Public{
Type: tpm2.AlgECC,
NameAlg: client.DefaultEKTemplateECC().NameAlg,
Attributes: tpm2.FlagSign,
ECCParameters: &tpm2.ECCParams{
CurveID: fromGoCurve[eccPub.Curve],
Point: tpm2.ECPoint{
XRaw: eccIntToBytes(eccPub, eccPub.X),
YRaw: eccIntToBytes(eccPub, eccPub.Y),
},
Sign: &tpm2.SigScheme{
Alg: tpm2.AlgECDSA,
Hash: tpm2.AlgSHA256,
},
},
}
private := tpm2.Private{
Type: tpm2.AlgECC,
AuthValue: nil,
SeedValue: nil,
Sensitive: key.D.Bytes(),
}
return public, private, nil
default:
return tpm2.Public{}, tpm2.Private{}, fmt.Errorf("unsupported signing key type: %T", signingKey)
}
}
@Lupus it seems roughly reasonable. I would need to double check the spec, but if it's working it's either exactly or almost exactly correct.
Care to open a PR so we can review, test, and add this functionality?
PR would require a CLA, I'm figuring out the details with my employer's legal department, and it can take ages 😞 So if you have some time to look at it and contribute on your own, that would likely be much faster.
Ahhhh, that makes sense. I can see if someone on our team has time to get a PR in soonish.