func()

in aws_signing_helper/tpm_signer.go [117:245]


func (tpmv2Signer *TPMv2Signer) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) {
	var (
		keyHandle tpmutil.Handle
	)

	rw, err := openTPM()
	if err != nil {
		return nil, err
	}
	defer rw.Close()

	if tpmv2Signer.handle != 0 {
		keyHandle = tpmv2Signer.handle
	} else {
		parentHandle := tpmutil.Handle(tpmv2Signer.tpmData.Parent)
		if !handleIsPersistent(tpmv2Signer.tpmData.Parent) {
			// Parent and owner passwords aren't supported currently when creating a primary given a persistent handle for the parent
			parentHandle, _, err = tpm2.CreatePrimary(rw, tpmutil.Handle(tpmv2Signer.tpmData.Parent), tpm2.PCRSelection{}, "", "", primaryParams)
			if err != nil {
				return nil, err
			}
			defer tpm2.FlushContext(rw, parentHandle)
		}

		keyHandle, _, err = tpm2.Load(rw, parentHandle, "", tpmv2Signer.tpmData.Pubkey[2:], tpmv2Signer.tpmData.Privkey[2:])
		if err != nil {
			return nil, err
		}
		defer tpm2.FlushContext(rw, keyHandle)
	}

	var algo tpm2.Algorithm
	var shadigest []byte

	switch opts.HashFunc() {
	case crypto.SHA256:
		sha256digest := sha256.Sum256(digest)
		shadigest = sha256digest[:]
		algo = tpm2.AlgSHA256
	case crypto.SHA384:
		sha384digest := sha512.Sum384(digest)
		shadigest = sha384digest[:]
		algo = tpm2.AlgSHA384
	case crypto.SHA512:
		sha512digest := sha512.Sum512(digest)
		shadigest = sha512digest[:]
		algo = tpm2.AlgSHA512
	}

	if tpmv2Signer.public.Type == tpm2.AlgECC {
		// Check to see that ECDSA is supported for signing
		err = checkCapability(rw, tpm2.AlgECC)
		if err != nil {
			return nil, err
		}

		// For an EC key we lie to the TPM about what the hash is.
		// It doesn't actually matter what the original digest was;
		// the algo we feed to the TPM is *purely* based on the
		// size of the curve itself. We truncate the actual digest,
		// or pad with zeroes, to the byte size of the key.
		pubKey, err := tpmv2Signer.public.Key()
		if err != nil {
			return nil, err
		}
		ecPubKey, ok := pubKey.(*ecdsa.PublicKey)
		if !ok {
			return nil, errors.New("failed to obtain ecdsa.PublicKey")
		}
		bitSize := ecPubKey.Curve.Params().BitSize
		byteSize := (bitSize + 7) / 8
		if byteSize > sha512.Size {
			byteSize = sha512.Size
		}
		switch byteSize {
		case sha512.Size:
			algo = tpm2.AlgSHA512
		case sha512.Size384:
			algo = tpm2.AlgSHA384
		case sha512.Size256:
			algo = tpm2.AlgSHA256
		case sha1.Size:
			algo = tpm2.AlgSHA1
		default:
			return nil, errors.New("unsupported curve")
		}

		if len(shadigest) > byteSize {
			shadigest = shadigest[:byteSize]
		}

		for len(shadigest) < byteSize {
			shadigest = append([]byte{0}, shadigest...)
		}

		sig, err := tpmv2Signer.signHelper(rw, keyHandle, shadigest,
			&tpm2.SigScheme{Alg: tpm2.AlgECDSA, Hash: algo})
		if err != nil {
			return nil, err
		}
		signature, err = asn1.Marshal(struct {
			R *big.Int
			S *big.Int
		}{sig.ECC.R, sig.ECC.S})
		if err != nil {
			return nil, err
		}
	} else {
		// Check to see that the requested hash function is supported
		err = checkCapability(rw, algo)
		if err != nil {
			return nil, err
		}

		// Check to see that RSASSA is supported for signing
		err = checkCapability(rw, tpm2.AlgRSASSA)
		if err != nil {
			return nil, err
		}

		sig, err := tpmv2Signer.signHelper(rw, keyHandle, shadigest,
			&tpm2.SigScheme{Alg: tpm2.AlgRSASSA, Hash: algo})
		if err != nil {
			return nil, err
		}
		signature = sig.RSA.Signature
	}
	return signature, nil
}