Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 30 additions & 14 deletions certstore/certstore_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ func (i *macIdentity) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts
}
defer C.CFRelease(C.CFTypeRef(cdigest))

algo, err := i.getAlgo(hash)
algo, err := i.getAlgo(opts)
if err != nil {
return nil, err
}
Expand All @@ -305,8 +305,10 @@ func (i *macIdentity) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts
return sig, nil
}

// getAlgo decides which algorithm to use with this key type for the given hash.
func (i *macIdentity) getAlgo(hash crypto.Hash) (algo C.SecKeyAlgorithm, err error) {
// getAlgo decides which algorithm to use with this key type for the given opts.
func (i *macIdentity) getAlgo(opts crypto.SignerOpts) (algo C.SecKeyAlgorithm, err error) {
hash := opts.HashFunc()

var crt *x509.Certificate
if crt, err = i.Certificate(); err != nil {
return
Expand All @@ -327,17 +329,31 @@ func (i *macIdentity) getAlgo(hash crypto.Hash) (algo C.SecKeyAlgorithm, err err
err = ErrUnsupportedHash
}
case *rsa.PublicKey:
switch hash {
case crypto.SHA1:
algo = C.kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1
case crypto.SHA256:
algo = C.kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256
case crypto.SHA384:
algo = C.kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384
case crypto.SHA512:
algo = C.kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512
default:
err = ErrUnsupportedHash
_, isPSS := opts.(*rsa.PSSOptions)
if isPSS {
switch hash {
case crypto.SHA256:
algo = C.kSecKeyAlgorithmRSASignatureDigestPSSSHA256
case crypto.SHA384:
algo = C.kSecKeyAlgorithmRSASignatureDigestPSSSHA384
case crypto.SHA512:
algo = C.kSecKeyAlgorithmRSASignatureDigestPSSSHA512
default:
err = ErrUnsupportedHash
}
} else {
switch hash {
case crypto.SHA1:
algo = C.kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1
case crypto.SHA256:
algo = C.kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256
case crypto.SHA384:
algo = C.kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384
case crypto.SHA512:
algo = C.kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512
default:
err = ErrUnsupportedHash
}
}
default:
err = errors.New("unsupported key type")
Expand Down
55 changes: 55 additions & 0 deletions certstore/certstore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,61 @@ func ImportDeleteHelper(t *testing.T, i *fakeca.Identity) {
})
}

func TestSignerRSAPSS(t *testing.T) {
withIdentity(t, leafRSA, func(ident Identity) {
signer, err := ident.Signer()
if err != nil {
t.Fatal(err)
}

// RSA-PSS with SHA-256 (used by TLS 1.3 CertificateVerify)
sha256Digest := sha256.Sum256([]byte("hello"))
pssOpts := &rsa.PSSOptions{
SaltLength: rsa.PSSSaltLengthEqualsHash,
Hash: crypto.SHA256,
}
sig, err := signer.Sign(rand.Reader, sha256Digest[:], pssOpts)
if err != nil {
t.Fatal(err)
}

pub := signer.Public().(*rsa.PublicKey)
if err := rsa.VerifyPSS(pub, crypto.SHA256, sha256Digest[:], sig, pssOpts); err != nil {
t.Fatalf("PSS SHA-256 signature verification failed: %v", err)
}

// RSA-PSS with SHA-384
sha384Digest := sha512.Sum384([]byte("hello"))
pssOpts384 := &rsa.PSSOptions{
SaltLength: rsa.PSSSaltLengthEqualsHash,
Hash: crypto.SHA384,
}
sig, err = signer.Sign(rand.Reader, sha384Digest[:], pssOpts384)
if err != nil {
t.Fatal(err)
}

if err := rsa.VerifyPSS(pub, crypto.SHA384, sha384Digest[:], sig, pssOpts384); err != nil {
t.Fatalf("PSS SHA-384 signature verification failed: %v", err)
}

// RSA-PSS with SHA-512
sha512Digest := sha512.Sum512([]byte("hello"))
pssOpts512 := &rsa.PSSOptions{
SaltLength: rsa.PSSSaltLengthEqualsHash,
Hash: crypto.SHA512,
}
sig, err = signer.Sign(rand.Reader, sha512Digest[:], pssOpts512)
if err != nil {
t.Fatal(err)
}

if err := rsa.VerifyPSS(pub, crypto.SHA512, sha512Digest[:], sig, pssOpts512); err != nil {
t.Fatalf("PSS SHA-512 signature verification failed: %v", err)
}
})
}

func TestSignerRSA(t *testing.T) {
rsaPriv, ok := leafRSA.PrivateKey.(*rsa.PrivateKey)
if !ok {
Expand Down
58 changes: 40 additions & 18 deletions certstore/certstore_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -361,14 +361,16 @@ func (wpk *winPrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.Signer
if wpk.capiProv != 0 {
return wpk.capiSignHash(opts.HashFunc(), digest)
} else if wpk.cngHandle != 0 {
return wpk.cngSignHash(opts.HashFunc(), digest)
return wpk.cngSignHash(opts, digest)
} else {
return nil, errors.New("bad private key")
}
}

// cngSignHash signs a digest using the CNG APIs.
func (wpk *winPrivateKey) cngSignHash(hash crypto.Hash, digest []byte) ([]byte, error) {
func (wpk *winPrivateKey) cngSignHash(opts crypto.SignerOpts, digest []byte) ([]byte, error) {
hash := opts.HashFunc()

if len(digest) != hash.Size() {
return nil, errors.New("bad digest for hash")
}
Expand All @@ -384,23 +386,43 @@ func (wpk *winPrivateKey) cngSignHash(hash crypto.Hash, digest []byte) ([]byte,
sigLen = C.DWORD(0)
)

// setup pkcs1v1.5 padding for RSA
// setup padding for RSA
if _, isRSA := wpk.publicKey.(*rsa.PublicKey); isRSA {
flags |= C.BCRYPT_PAD_PKCS1
padInfo := C.BCRYPT_PKCS1_PADDING_INFO{}
padPtr = unsafe.Pointer(&padInfo)

switch hash {
case crypto.SHA1:
padInfo.pszAlgId = BCRYPT_SHA1_ALGORITHM
case crypto.SHA256:
padInfo.pszAlgId = BCRYPT_SHA256_ALGORITHM
case crypto.SHA384:
padInfo.pszAlgId = BCRYPT_SHA384_ALGORITHM
case crypto.SHA512:
padInfo.pszAlgId = BCRYPT_SHA512_ALGORITHM
default:
return nil, ErrUnsupportedHash
_, isPSS := opts.(*rsa.PSSOptions)
if isPSS {
flags |= C.BCRYPT_PAD_PSS
padInfo := C.BCRYPT_PSS_PADDING_INFO{
cbSalt: C.ULONG(hash.Size()),
}
padPtr = unsafe.Pointer(&padInfo)

switch hash {
case crypto.SHA256:
padInfo.pszAlgId = BCRYPT_SHA256_ALGORITHM
case crypto.SHA384:
padInfo.pszAlgId = BCRYPT_SHA384_ALGORITHM
case crypto.SHA512:
padInfo.pszAlgId = BCRYPT_SHA512_ALGORITHM
default:
return nil, ErrUnsupportedHash
}
} else {
flags |= C.BCRYPT_PAD_PKCS1
padInfo := C.BCRYPT_PKCS1_PADDING_INFO{}
padPtr = unsafe.Pointer(&padInfo)

switch hash {
case crypto.SHA1:
padInfo.pszAlgId = BCRYPT_SHA1_ALGORITHM
case crypto.SHA256:
padInfo.pszAlgId = BCRYPT_SHA256_ALGORITHM
case crypto.SHA384:
padInfo.pszAlgId = BCRYPT_SHA384_ALGORITHM
case crypto.SHA512:
padInfo.pszAlgId = BCRYPT_SHA512_ALGORITHM
default:
return nil, ErrUnsupportedHash
}
}
}

Expand Down