Skip to content

Commit

Permalink
Certstore: Add ability to cert_match_by with thumbprint
Browse files Browse the repository at this point in the history
Input value should be hex-encoded string of the SHA1 thumbprint.

See: #6024

Signed-off-by: Neil Twigg <neil@nats.io>
  • Loading branch information
neilalexander committed Oct 29, 2024
1 parent 7fb9e43 commit f1e915b
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 4 deletions.
6 changes: 4 additions & 2 deletions server/certstore/certstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,13 @@ type MatchByType int
const (
matchByIssuer MatchByType = iota + 1
matchBySubject
matchByThumbprint
)

var MatchByMap = map[string]MatchByType{
"issuer": matchByIssuer,
"subject": matchBySubject,
"issuer": matchByIssuer,
"subject": matchBySubject,
"thumbprint": matchByThumbprint,
}

var Usage = `
Expand Down
23 changes: 21 additions & 2 deletions server/certstore/certstore_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rsa"
"crypto/sha1"
"crypto/tls"
"crypto/x509"
"encoding/binary"
"encoding/hex"
"fmt"
"io"
"math/big"
Expand Down Expand Up @@ -228,6 +230,8 @@ func TLSConfig(certStore StoreType, certMatchBy MatchByType, certMatch string, c
leaf, leafCtx, err = cs.certBySubject(certMatch, scope)
} else if certMatchBy == matchByIssuer {
leaf, leafCtx, err = cs.certByIssuer(certMatch, scope)
} else if certMatchBy == matchByThumbprint {
leaf, leafCtx, err = cs.certByThumbprint(certMatch, scope)
} else {
return ErrBadMatchByType
}
Expand Down Expand Up @@ -326,7 +330,7 @@ func winFindCert(store windows.Handle, enc, findFlags, findType uint32, para *ui
)
if h == 0 {
// Actual error, or simply not found?
if errno, ok := err.(syscall.Errno); ok && errno == winCryptENotFound {
if errno, ok := err.(syscall.Errno); ok && errno == syscall.Errno(winCryptENotFound) {
return nil, ErrFailedCertSearch
}
return nil, ErrFailedCertSearch
Expand Down Expand Up @@ -386,7 +390,22 @@ func (w *winCertStore) certBySubject(subject string, storeType uint32) (*x509.Ce
return w.certSearch(winFindSubjectStr, subject, winMyStore, storeType)
}

// caCertBySubject matches and returns all matching certificates of the subject field.
// certByThumbprint matches and returns the first certificate found by passed SHA1 thumbprint.
// CertContext pointer returned allows subsequent key operations like Sign. Caller specifies
// current user's personal certs or local machine's personal certs using storeType.
// See CERT_FIND_SUBJECT_STR description at https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certfindcertificateinstore
func (w *winCertStore) certByThumbprint(hash string, storeType uint32) (*x509.Certificate, *windows.CertContext, error) {
hb, err := hex.DecodeString(hash)
if err != nil {
return nil, nil, err
}
if len(hb) != sha1.Size {
return nil, nil, fmt.Errorf("incorrect thumbprint length %d", len(hb))
}
return w.certSearch(winFindHashStr, string(hb), winMyStore, storeType)
}

// caCertsBySubjectMatch matches and returns all matching certificates of the subject field.
//
// The following locations are searched:
// 1) Root (Trusted Root Certification Authorities)
Expand Down

0 comments on commit f1e915b

Please sign in to comment.