go-tpm-tools icon indicating copy to clipboard operation
go-tpm-tools copied to clipboard

CreateSigningKeyImportBlob for ECC keys

Open Lupus opened this issue 2 years ago • 6 comments

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?

Lupus avatar Jun 30 '22 09:06 Lupus

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.

josephlr avatar Jun 30 '22 09:06 josephlr

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.

Lupus avatar Jun 30 '22 15:06 Lupus

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 avatar Jul 01 '22 07:07 Lupus

@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?

josephlr avatar Jul 01 '22 09:07 josephlr

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.

Lupus avatar Jul 01 '22 09:07 Lupus

Ahhhh, that makes sense. I can see if someone on our team has time to get a PR in soonish.

josephlr avatar Jul 01 '22 21:07 josephlr