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

CreateSigningKeyImportBlob for ECC keys #215

Open
Lupus opened this issue Jun 30, 2022 · 6 comments
Open

CreateSigningKeyImportBlob for ECC keys #215

Lupus opened this issue Jun 30, 2022 · 6 comments
Labels
good first issue Good for newcomers

Comments

@Lupus
Copy link

Lupus commented Jun 30, 2022

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?

@josephlr
Copy link
Member

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 josephlr added the good first issue Good for newcomers label Jun 30, 2022
@Lupus
Copy link
Author

Lupus commented Jun 30, 2022

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
Copy link
Author

Lupus commented Jul 1, 2022

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)
	}
}

@josephlr
Copy link
Member

josephlr commented Jul 1, 2022

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

@Lupus
Copy link
Author

Lupus commented Jul 1, 2022

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.

@josephlr
Copy link
Member

josephlr commented Jul 1, 2022

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

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

No branches or pull requests

2 participants