func GetTPMv2Signer()

in aws_signing_helper/tpm_signer.go [331:444]


func GetTPMv2Signer(opts GetTPMv2SignerOpts) (signer Signer, signingAlgorithm string, err error) {
	var (
		certificate      *x509.Certificate
		certificateChain []*x509.Certificate
		keyPem           *pem.Block
		password         string
		emptyAuth        bool
		tpmData          tpm2_TPMKey
		handle           tpmutil.Handle
		public           tpm2.Public
		private          []byte
	)

	certificate = opts.certificate
	certificateChain = opts.certificateChain
	keyPem = opts.keyPem
	password = opts.password
	emptyAuth = opts.emptyAuth

	// If a handle is provided instead of a TPM key file
	if opts.handle != "" {
		handleParts := strings.Split(opts.handle, ":")
		if len(handleParts) != 2 {
			return nil, "", errors.New("invalid TPM handle format")
		}
		hexHandleStr := handleParts[1]
		if strings.HasPrefix(hexHandleStr, "0x") {
			hexHandleStr = hexHandleStr[2:]
		}
		handleValue, err := strconv.ParseUint(hexHandleStr, 16, 32)
		if err != nil {
			return nil, "", errors.New("invalid hex TPM handle value")
		}
		handle = tpmutil.Handle(handleValue)

		// Read the public key from the loaded key within the TPM
		rw, err := openTPM()
		if err != nil {
			return nil, "", err
		}
		defer rw.Close()

		public, _, _, err = tpm2.ReadPublic(rw, handle)
		if err != nil {
			return nil, "", err
		}
	} else {
		fixupEmptyAuth(&keyPem.Bytes)
		_, err = asn1.Unmarshal(keyPem.Bytes, &tpmData)
		if err != nil {
			return nil, "", err
		}

		emptyAuth = tpmData.EmptyAuth
		if emptyAuth && password != "" {
			return nil, "", errors.New("password is provided but TPM key file indicates that one isn't required")
		}

		if !tpmData.Oid.Equal(oidLoadableKey) {
			return nil, "", errors.New("invalid OID for TPMv2 key:" + tpmData.Oid.String())
		}

		if tpmData.Policy != nil || tpmData.AuthPolicy != nil {
			return nil, "", errors.New("TPMv2 policy not implemented yet")
		}
		if tpmData.Secret != nil {
			return nil, "", errors.New("TPMv2 key has 'secret' field which should not be set")
		}

		if !handleIsPersistent(tpmData.Parent) &&
			tpmData.Parent != int(tpm2.HandleOwner) &&
			tpmData.Parent != int(tpm2.HandleNull) &&
			tpmData.Parent != int(tpm2.HandleEndorsement) &&
			tpmData.Parent != int(tpm2.HandlePlatform) {
			return nil, "", errors.New("invalid parent for TPMv2 key")
		}
		if len(tpmData.Pubkey) < 2 ||
			len(tpmData.Pubkey)-2 != (int(tpmData.Pubkey[0])<<8)+int(tpmData.Pubkey[1]) {
			return nil, "", errors.New("invalid length for TPMv2 PUBLIC blob")
		}

		public, err = tpm2.DecodePublic(tpmData.Pubkey[2:])
		if err != nil {
			return nil, "", err
		}

		if len(tpmData.Privkey) < 2 ||
			len(tpmData.Privkey)-2 != (int(tpmData.Privkey[0])<<8)+int(tpmData.Privkey[1]) {
			return nil, "", errors.New("invalid length for TPMv2 PRIVATE blob")
		}
		private = tpmData.Privkey[2:]
	}

	switch public.Type {
	case tpm2.AlgRSA:
		signingAlgorithm = aws4_x509_rsa_sha256
	case tpm2.AlgECC:
		signingAlgorithm = aws4_x509_ecdsa_sha256
	default:
		return nil, "", errors.New("unsupported TPMv2 key type")
	}

	return &TPMv2Signer{
			certificate,
			certificateChain,
			tpmData,
			public,
			private,
			password,
			emptyAuth,
			handle,
		},
		signingAlgorithm, nil
}