Skip to content

Commit

Permalink
Merge pull request #5 from smallstep/herman/windows-ecdsa-signature-a…
Browse files Browse the repository at this point in the history
…lgorithm

Explicitly set ECDSA signature scheme on Windows
  • Loading branch information
hslatman authored Oct 10, 2024
2 parents 413678f + 82220f4 commit 3b625a2
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 4 deletions.
2 changes: 1 addition & 1 deletion attest/key_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ func (k *windowsAK20) sign(tb tpmBase, digest []byte, pub crypto.PublicKey, opts

switch p := pub.(type) {
case *ecdsa.PublicKey:
return signECDSA(rw, hnd, digest, p.Curve)
return signECDSA(rw, hnd, digest, p.Curve, opts)
case *rsa.PublicKey:
return signRSA(rw, hnd, digest, opts)
}
Expand Down
40 changes: 37 additions & 3 deletions attest/wrapped_tpm20.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"fmt"
"io"
"math/big"
"runtime"

"github.com/google/go-tpm/legacy/tpm2"
"github.com/google/go-tpm/tpmutil"
Expand Down Expand Up @@ -560,14 +561,47 @@ func (k *wrappedKey20) sign(tb tpmBase, digest []byte, pub crypto.PublicKey, opt
}
switch p := pub.(type) {
case *ecdsa.PublicKey:
return signECDSA(t.rwc, k.hnd, digest, p.Curve)
return signECDSA(t.rwc, k.hnd, digest, p.Curve, opts)
case *rsa.PublicKey:
return signRSA(t.rwc, k.hnd, digest, opts)
}
return nil, fmt.Errorf("unsupported signing key type: %T", pub)
}

func signECDSA(rw io.ReadWriter, key tpmutil.Handle, digest []byte, curve elliptic.Curve) ([]byte, error) {
func signECDSA(rw io.ReadWriter, key tpmutil.Handle, digest []byte, curve elliptic.Curve, opts crypto.SignerOpts) ([]byte, error) {
var scheme *tpm2.SigScheme
if runtime.GOOS == "windows" {
// On Windows, if no scheme is specified, error code 0x12
// "unsupported or incompatible scheme" will be returned.
// By selecting an appropriate signature scheme this is prevented.
// TODO(hs): specify algorithm explicitly on Linux too?
// TODO(hs): determine if basing this off of the curve is OK; it's
// possible the TPM in fact doesn't support the hash algorithm.
h := tpm2.AlgSHA256
switch curve {
case elliptic.P384():
h = tpm2.AlgSHA384
case elliptic.P521():
h = tpm2.AlgSHA512
}
scheme = &tpm2.SigScheme{
Alg: tpm2.AlgECDSA,
Hash: h,
}
}

// if opts is provided, it can override the hash function to use.
if opts != nil {
h, err := tpm2.HashToAlgorithm(opts.HashFunc())
if err != nil {
return nil, fmt.Errorf("incorrect hash algorithm: %v", err)
}
scheme = &tpm2.SigScheme{
Alg: tpm2.AlgECDSA,
Hash: h,
}
}

// https://cs.opensource.google/go/go/+/refs/tags/go1.19.2:src/crypto/ecdsa/ecdsa.go;l=181
orderBits := curve.Params().N.BitLen()
orderBytes := (orderBits + 7) / 8
Expand All @@ -581,7 +615,7 @@ func signECDSA(rw io.ReadWriter, key tpmutil.Handle, digest []byte, curve ellipt
}
digest = ret.Bytes()

sig, err := tpm2.Sign(rw, key, "", digest, nil, nil)
sig, err := tpm2.Sign(rw, key, "", digest, nil, scheme)
if err != nil {
return nil, fmt.Errorf("cannot sign: %v", err)
}
Expand Down

0 comments on commit 3b625a2

Please sign in to comment.