Update dependencies
This commit is contained in:
87
vendor/github.com/tailscale/certstore/.appveyor.yml
generated
vendored
Normal file
87
vendor/github.com/tailscale/certstore/.appveyor.yml
generated
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
skip_branch_with_pr: true
|
||||
os: "Visual Studio 2015"
|
||||
|
||||
build: off
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- # Default Go, x64
|
||||
ARCH: x64
|
||||
MSYS2_ARCH: x86_64
|
||||
MSYS2_DIR: msys64
|
||||
MSYSTEM: MINGW64
|
||||
GOPATH: c:\gopath
|
||||
GOROOT: c:\go
|
||||
GOARCH: amd64
|
||||
EXTLD: x86_64-w64-mingw32-gcc
|
||||
- # Default Go, x86
|
||||
ARCH: x86
|
||||
MSYS2_ARCH: i686
|
||||
MSYS2_DIR: msys64
|
||||
MSYSTEM: MINGW32
|
||||
GOPATH: c:\gopath
|
||||
GOROOT: c:\go-x86
|
||||
GOARCH: 386
|
||||
EXTLD: i686-w64-mingw32-gcc
|
||||
- # Go 1.12, x64
|
||||
ARCH: x64
|
||||
MSYS2_ARCH: x86_64
|
||||
MSYS2_DIR: msys64
|
||||
MSYSTEM: MINGW64
|
||||
GOPATH: c:\gopath
|
||||
GOROOT: c:\go112
|
||||
GOARCH: amd64
|
||||
EXTLD: x86_64-w64-mingw32-gcc
|
||||
- # Go 1.11, x64
|
||||
ARCH: x64
|
||||
MSYS2_ARCH: x86_64
|
||||
MSYS2_DIR: msys64
|
||||
MSYSTEM: MINGW64
|
||||
GOPATH: c:\gopath
|
||||
GOROOT: c:\go111
|
||||
GOARCH: amd64
|
||||
EXTLD: x86_64-w64-mingw32-gcc
|
||||
- # Go 1.10, x64
|
||||
ARCH: x64
|
||||
MSYS2_ARCH: x86_64
|
||||
MSYS2_DIR: msys64
|
||||
MSYSTEM: MINGW64
|
||||
GOPATH: c:\gopath
|
||||
GOROOT: c:\go110
|
||||
GOARCH: amd64
|
||||
EXTLD: x86_64-w64-mingw32-gcc
|
||||
- # Go 1.9, x64
|
||||
ARCH: x64
|
||||
MSYS2_ARCH: x86_64
|
||||
MSYS2_DIR: msys64
|
||||
MSYSTEM: MINGW64
|
||||
GOPATH: c:\gopath
|
||||
GOROOT: c:\go19
|
||||
GOARCH: amd64
|
||||
EXTLD: x86_64-w64-mingw32-gcc
|
||||
- # Go 1.9, x64
|
||||
ARCH: x64
|
||||
MSYS2_ARCH: x86_64
|
||||
MSYS2_DIR: msys64
|
||||
MSYSTEM: MINGW64
|
||||
GOPATH: c:\gopath
|
||||
GOROOT: c:\go18
|
||||
GOARCH: amd64
|
||||
EXTLD: x86_64-w64-mingw32-gcc
|
||||
|
||||
clone_folder: C:\gopath\src\github.com\github\certstore
|
||||
|
||||
before_test:
|
||||
# Ensure CGO is enabled
|
||||
- set CGO_ENABLED=1
|
||||
# Go paths
|
||||
- set PATH=%GOROOT%\bin;C:\%GOPATH%\bin;%PATH%
|
||||
# MSYS paths
|
||||
- set PATH=C:\%MSYS2_DIR%\%MSYSTEM%\bin;C:\%MSYS2_DIR%\usr\bin;%PATH%
|
||||
# Install build deps
|
||||
- bash -lc "for n in `seq 1 3`; do pacman --noconfirm -S mingw-w64-%MSYS2_ARCH%-libtool && break || sleep 15; done"
|
||||
# Install Go deps
|
||||
- go get -t -v ./...
|
||||
|
||||
test_script:
|
||||
- go test -v ./...
|
||||
21
vendor/github.com/tailscale/certstore/LICENSE.md
generated
vendored
Normal file
21
vendor/github.com/tailscale/certstore/LICENSE.md
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Ben Toews.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
98
vendor/github.com/tailscale/certstore/README.md
generated
vendored
Normal file
98
vendor/github.com/tailscale/certstore/README.md
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
# certstore
|
||||
|
||||
Certstore is a Go library for accessing user identities stored in platform certificate stores. On Windows and macOS, certstore can enumerate user identities and sign messages with their private keys.
|
||||
|
||||
## Fork from original module
|
||||
|
||||
This is a fork from the [cyolosecurity fork](https://github.com/cyolosecurity/certstore/)
|
||||
of the the original [certstore module](https://github.com/github/certstore/). The cyolosecurity
|
||||
fork adds some functionality that we require (RSA-PSS support and ability to use the machine
|
||||
certificate store instead of the current user certificate store). However, the cyolosecurity
|
||||
fork did not update the module name, so we are unable to import it directly, thus leading to
|
||||
the Tailscale fork.
|
||||
|
||||
As of this writing, the [RSA-PSS PR](https://github.com/github/certstore/pull/18) has been
|
||||
under review for several months and the machine certificate store change has not yet been sent
|
||||
to the github maintainer for review. Ideally these changes will make their way back into the
|
||||
original module and we can
|
||||
[discontinue this fork](https://github.com/tailscale/tailscale/issues/2005) at some point in
|
||||
the future.
|
||||
|
||||
## Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
|
||||
"github.com/github/certstore"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sig, err := signWithMyIdentity("Ben Toews", "hello, world!")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(hex.EncodeToString(sig))
|
||||
}
|
||||
|
||||
func signWithMyIdentity(cn, msg string) ([]byte, error) {
|
||||
// Open the certificate store for use. This must be Close()'ed once you're
|
||||
// finished with the store and any identities it contains.
|
||||
store, err := certstore.Open()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer store.Close()
|
||||
|
||||
// Get an Identity slice, containing every identity in the store. Each of
|
||||
// these must be Close()'ed when you're done with them.
|
||||
idents, err := store.Identities()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Iterate through the identities, looking for the one we want.
|
||||
var me certstore.Identity
|
||||
for _, ident := range idents {
|
||||
defer ident.Close()
|
||||
|
||||
crt, errr := ident.Certificate()
|
||||
if errr != nil {
|
||||
return nil, errr
|
||||
}
|
||||
|
||||
if crt.Subject.CommonName == "Ben Toews" {
|
||||
me = ident
|
||||
}
|
||||
}
|
||||
|
||||
if me == nil {
|
||||
return nil, errors.New("Couldn't find my identity")
|
||||
}
|
||||
|
||||
// Get a crypto.Signer for the identity.
|
||||
signer, err := me.Signer()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Digest and sign our message.
|
||||
digest := sha256.Sum256([]byte(msg))
|
||||
signature, err := signer.Sign(rand.Reader, digest[:], crypto.SHA256)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return signature, nil
|
||||
}
|
||||
|
||||
```
|
||||
71
vendor/github.com/tailscale/certstore/certstore.go
generated
vendored
Normal file
71
vendor/github.com/tailscale/certstore/certstore.go
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
package certstore
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrUnsupportedHash is returned by Signer.Sign() when the provided hash
|
||||
// algorithm isn't supported.
|
||||
ErrUnsupportedHash = errors.New("unsupported hash algorithm")
|
||||
)
|
||||
|
||||
// StoreLocation defines the store location to look certificates in.
|
||||
type StoreLocation int
|
||||
|
||||
const (
|
||||
// User is the user scoped certificate store. "CURRENT_USER" on Windows or
|
||||
// "login" on MacOS
|
||||
User StoreLocation = iota
|
||||
// System is the system scoped certificate store. "LOCAL_MACHINE" on Windows
|
||||
// or "System" on MacOS
|
||||
System
|
||||
)
|
||||
|
||||
// StorePermission defines the store permission to open the store with
|
||||
type StorePermission int
|
||||
|
||||
const (
|
||||
// ReadOnly is the store permission allows reading and using certificates
|
||||
ReadOnly StorePermission = iota
|
||||
// ReadWrite is the store permission that allows importing certificates
|
||||
ReadWrite
|
||||
)
|
||||
|
||||
// Open opens the system's certificate store.
|
||||
func Open(location StoreLocation, permissions ...StorePermission) (Store, error) {
|
||||
return openStore(location, permissions...)
|
||||
}
|
||||
|
||||
// Store represents the system's certificate store.
|
||||
type Store interface {
|
||||
// Identities gets a list of identities from the store.
|
||||
Identities() ([]Identity, error)
|
||||
|
||||
// Import imports a PKCS#12 (PFX) blob containing a certificate and private
|
||||
// key.
|
||||
Import(data []byte, password string) error
|
||||
|
||||
// Close closes the store.
|
||||
Close()
|
||||
}
|
||||
|
||||
// Identity is a X.509 certificate and its corresponding private key.
|
||||
type Identity interface {
|
||||
// Certificate gets the identity's certificate.
|
||||
Certificate() (*x509.Certificate, error)
|
||||
|
||||
// CertificateChain attempts to get the identity's full certificate chain.
|
||||
CertificateChain() ([]*x509.Certificate, error)
|
||||
|
||||
// Signer gets a crypto.Signer that uses the identity's private key.
|
||||
Signer() (crypto.Signer, error)
|
||||
|
||||
// Delete deletes this identity from the system.
|
||||
Delete() error
|
||||
|
||||
// Close any manually managed memory held by the Identity.
|
||||
Close()
|
||||
}
|
||||
497
vendor/github.com/tailscale/certstore/certstore_darwin.go
generated
vendored
Normal file
497
vendor/github.com/tailscale/certstore/certstore_darwin.go
generated
vendored
Normal file
@@ -0,0 +1,497 @@
|
||||
package certstore
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -x objective-c
|
||||
#cgo LDFLAGS: -framework CoreFoundation -framework Security
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <Security/Security.h>
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// work around https://golang.org/doc/go1.10#cgo
|
||||
// in go>=1.10 CFTypeRefs are translated to uintptrs instead of pointers.
|
||||
var (
|
||||
nilCFDictionaryRef C.CFDictionaryRef
|
||||
nilSecCertificateRef C.SecCertificateRef
|
||||
nilCFArrayRef C.CFArrayRef
|
||||
nilCFDataRef C.CFDataRef
|
||||
nilCFErrorRef C.CFErrorRef
|
||||
nilCFStringRef C.CFStringRef
|
||||
nilSecIdentityRef C.SecIdentityRef
|
||||
nilSecKeyRef C.SecKeyRef
|
||||
nilCFAllocatorRef C.CFAllocatorRef
|
||||
)
|
||||
|
||||
// macStore is a bogus type. We have to explicitly open/close the store on
|
||||
// windows, so we provide those methods here too.
|
||||
type macStore int
|
||||
|
||||
// openStore is a function for opening a macStore.
|
||||
func openStore(_ StoreLocation, _ ...StorePermission) (macStore, error) {
|
||||
return macStore(0), nil
|
||||
}
|
||||
|
||||
// Identities implements the Store interface.
|
||||
func (s macStore) Identities() ([]Identity, error) {
|
||||
query := mapToCFDictionary(map[C.CFTypeRef]C.CFTypeRef{
|
||||
C.CFTypeRef(C.kSecClass): C.CFTypeRef(C.kSecClassIdentity),
|
||||
C.CFTypeRef(C.kSecReturnRef): C.CFTypeRef(C.kCFBooleanTrue),
|
||||
C.CFTypeRef(C.kSecMatchLimit): C.CFTypeRef(C.kSecMatchLimitAll),
|
||||
})
|
||||
if query == nilCFDictionaryRef {
|
||||
return nil, errors.New("error creating CFDictionary")
|
||||
}
|
||||
defer C.CFRelease(C.CFTypeRef(query))
|
||||
|
||||
var absResult C.CFTypeRef
|
||||
if err := osStatusError(C.SecItemCopyMatching(query, &absResult)); err != nil {
|
||||
if err == errSecItemNotFound {
|
||||
return []Identity{}, nil
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
defer C.CFRelease(C.CFTypeRef(absResult))
|
||||
|
||||
// don't need to release aryResult since the abstract result is released above.
|
||||
aryResult := C.CFArrayRef(absResult)
|
||||
|
||||
// identRefs aren't owned by us initially. newMacIdentity retains them.
|
||||
n := C.CFArrayGetCount(aryResult)
|
||||
identRefs := make([]C.CFTypeRef, n)
|
||||
C.CFArrayGetValues(aryResult, C.CFRange{0, n}, (*unsafe.Pointer)(unsafe.Pointer(&identRefs[0])))
|
||||
|
||||
idents := make([]Identity, 0, n)
|
||||
for _, identRef := range identRefs {
|
||||
idents = append(idents, newMacIdentity(C.SecIdentityRef(identRef)))
|
||||
}
|
||||
|
||||
return idents, nil
|
||||
}
|
||||
|
||||
// Import implements the Store interface.
|
||||
func (s macStore) Import(data []byte, password string) error {
|
||||
cdata, err := bytesToCFData(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer C.CFRelease(C.CFTypeRef(cdata))
|
||||
|
||||
cpass := stringToCFString(password)
|
||||
defer C.CFRelease(C.CFTypeRef(cpass))
|
||||
|
||||
cops := mapToCFDictionary(map[C.CFTypeRef]C.CFTypeRef{
|
||||
C.CFTypeRef(C.kSecImportExportPassphrase): C.CFTypeRef(cpass),
|
||||
})
|
||||
if cops == nilCFDictionaryRef {
|
||||
return errors.New("error creating CFDictionary")
|
||||
}
|
||||
defer C.CFRelease(C.CFTypeRef(cops))
|
||||
|
||||
var cret C.CFArrayRef
|
||||
if err := osStatusError(C.SecPKCS12Import(cdata, cops, &cret)); err != nil {
|
||||
return err
|
||||
}
|
||||
defer C.CFRelease(C.CFTypeRef(cret))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close implements the Store interface.
|
||||
func (s macStore) Close() {}
|
||||
|
||||
// macIdentity implements the Identity interface.
|
||||
type macIdentity struct {
|
||||
ref C.SecIdentityRef
|
||||
kref C.SecKeyRef
|
||||
cref C.SecCertificateRef
|
||||
crt *x509.Certificate
|
||||
chain []*x509.Certificate
|
||||
}
|
||||
|
||||
func newMacIdentity(ref C.SecIdentityRef) *macIdentity {
|
||||
C.CFRetain(C.CFTypeRef(ref))
|
||||
return &macIdentity{ref: ref}
|
||||
}
|
||||
|
||||
// Certificate implements the Identity interface.
|
||||
func (i *macIdentity) Certificate() (*x509.Certificate, error) {
|
||||
certRef, err := i.getCertRef()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
crt, err := exportCertRef(certRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
i.crt = crt
|
||||
|
||||
return i.crt, nil
|
||||
}
|
||||
|
||||
// CertificateChain implements the Identity interface.
|
||||
func (i *macIdentity) CertificateChain() ([]*x509.Certificate, error) {
|
||||
if i.chain != nil {
|
||||
return i.chain, nil
|
||||
}
|
||||
|
||||
certRef, err := i.getCertRef()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
policy := C.SecPolicyCreateSSL(0, nilCFStringRef)
|
||||
|
||||
var trustRef C.SecTrustRef
|
||||
if err := osStatusError(C.SecTrustCreateWithCertificates(C.CFTypeRef(certRef), C.CFTypeRef(policy), &trustRef)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer C.CFRelease(C.CFTypeRef(trustRef))
|
||||
|
||||
var status C.SecTrustResultType
|
||||
if err := osStatusError(C.SecTrustEvaluate(trustRef, &status)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var (
|
||||
nchain = C.SecTrustGetCertificateCount(trustRef)
|
||||
chain = make([]*x509.Certificate, 0, int(nchain))
|
||||
)
|
||||
|
||||
for i := C.CFIndex(0); i < nchain; i++ {
|
||||
// TODO: do we need to release these?
|
||||
chainCertref := C.SecTrustGetCertificateAtIndex(trustRef, i)
|
||||
if chainCertref == nilSecCertificateRef {
|
||||
return nil, errors.New("nil certificate in chain")
|
||||
}
|
||||
|
||||
chainCert, err := exportCertRef(chainCertref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
chain = append(chain, chainCert)
|
||||
}
|
||||
|
||||
i.chain = chain
|
||||
|
||||
return chain, nil
|
||||
}
|
||||
|
||||
// Signer implements the Identity interface.
|
||||
func (i *macIdentity) Signer() (crypto.Signer, error) {
|
||||
// pre-load the certificate so Public() is less likely to return nil
|
||||
// unexpectedly.
|
||||
if _, err := i.Certificate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return i, nil
|
||||
}
|
||||
|
||||
// Delete implements the Identity interface.
|
||||
func (i *macIdentity) Delete() error {
|
||||
itemList := []C.SecIdentityRef{i.ref}
|
||||
itemListPtr := (*unsafe.Pointer)(unsafe.Pointer(&itemList[0]))
|
||||
citemList := C.CFArrayCreate(nilCFAllocatorRef, itemListPtr, 1, nil)
|
||||
if citemList == nilCFArrayRef {
|
||||
return errors.New("error creating CFArray")
|
||||
}
|
||||
defer C.CFRelease(C.CFTypeRef(citemList))
|
||||
|
||||
query := mapToCFDictionary(map[C.CFTypeRef]C.CFTypeRef{
|
||||
C.CFTypeRef(C.kSecClass): C.CFTypeRef(C.kSecClassIdentity),
|
||||
C.CFTypeRef(C.kSecMatchItemList): C.CFTypeRef(citemList),
|
||||
})
|
||||
if query == nilCFDictionaryRef {
|
||||
return errors.New("error creating CFDictionary")
|
||||
}
|
||||
defer C.CFRelease(C.CFTypeRef(query))
|
||||
|
||||
if err := osStatusError(C.SecItemDelete(query)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close implements the Identity interface.
|
||||
func (i *macIdentity) Close() {
|
||||
if i.ref != nilSecIdentityRef {
|
||||
C.CFRelease(C.CFTypeRef(i.ref))
|
||||
i.ref = nilSecIdentityRef
|
||||
}
|
||||
|
||||
if i.kref != nilSecKeyRef {
|
||||
C.CFRelease(C.CFTypeRef(i.kref))
|
||||
i.kref = nilSecKeyRef
|
||||
}
|
||||
|
||||
if i.cref != nilSecCertificateRef {
|
||||
C.CFRelease(C.CFTypeRef(i.cref))
|
||||
i.cref = nilSecCertificateRef
|
||||
}
|
||||
}
|
||||
|
||||
// Public implements the crypto.Signer interface.
|
||||
func (i *macIdentity) Public() crypto.PublicKey {
|
||||
cert, err := i.Certificate()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return cert.PublicKey
|
||||
}
|
||||
|
||||
// Sign implements the crypto.Signer interface.
|
||||
func (i *macIdentity) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) {
|
||||
hash := opts.HashFunc()
|
||||
|
||||
if len(digest) != hash.Size() {
|
||||
return nil, errors.New("bad digest for hash")
|
||||
}
|
||||
|
||||
kref, err := i.getKeyRef()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cdigest, err := bytesToCFData(digest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer C.CFRelease(C.CFTypeRef(cdigest))
|
||||
|
||||
algo, err := i.getAlgo(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// sign the digest
|
||||
var cerr C.CFErrorRef
|
||||
csig := C.SecKeyCreateSignature(kref, algo, cdigest, &cerr)
|
||||
|
||||
if err := cfErrorError(cerr); err != nil {
|
||||
defer C.CFRelease(C.CFTypeRef(cerr))
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if csig == nilCFDataRef {
|
||||
return nil, errors.New("nil signature from SecKeyCreateSignature")
|
||||
}
|
||||
|
||||
defer C.CFRelease(C.CFTypeRef(csig))
|
||||
|
||||
sig := cfDataToBytes(csig)
|
||||
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
// getAlgo decides which algorithm to use with this key type for the given hash.
|
||||
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
|
||||
}
|
||||
|
||||
switch crt.PublicKey.(type) {
|
||||
case *ecdsa.PublicKey:
|
||||
switch hash {
|
||||
case crypto.SHA256:
|
||||
algo = C.kSecKeyAlgorithmECDSASignatureDigestX962SHA256
|
||||
case crypto.SHA384:
|
||||
algo = C.kSecKeyAlgorithmECDSASignatureDigestX962SHA384
|
||||
case crypto.SHA512:
|
||||
algo = C.kSecKeyAlgorithmECDSASignatureDigestX962SHA512
|
||||
default:
|
||||
err = ErrUnsupportedHash
|
||||
}
|
||||
case *rsa.PublicKey:
|
||||
if _, ok := opts.(*rsa.PSSOptions); ok {
|
||||
switch hash {
|
||||
case crypto.SHA256:
|
||||
algo = C.kSecKeyAlgorithmRSASignatureDigestPSSSHA256
|
||||
case crypto.SHA384:
|
||||
algo = C.kSecKeyAlgorithmRSASignatureDigestPSSSHA384
|
||||
case crypto.SHA512:
|
||||
algo = C.kSecKeyAlgorithmRSASignatureDigestPSSSHA512
|
||||
default:
|
||||
err = ErrUnsupportedHash
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
switch hash {
|
||||
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")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// getKeyRef gets the SecKeyRef for this identity's pricate key.
|
||||
func (i *macIdentity) getKeyRef() (C.SecKeyRef, error) {
|
||||
if i.kref != nilSecKeyRef {
|
||||
return i.kref, nil
|
||||
}
|
||||
|
||||
var keyRef C.SecKeyRef
|
||||
if err := osStatusError(C.SecIdentityCopyPrivateKey(i.ref, &keyRef)); err != nil {
|
||||
return nilSecKeyRef, err
|
||||
}
|
||||
|
||||
i.kref = keyRef
|
||||
|
||||
return i.kref, nil
|
||||
}
|
||||
|
||||
// getCertRef gets the SecCertificateRef for this identity's certificate.
|
||||
func (i *macIdentity) getCertRef() (C.SecCertificateRef, error) {
|
||||
if i.cref != nilSecCertificateRef {
|
||||
return i.cref, nil
|
||||
}
|
||||
|
||||
var certRef C.SecCertificateRef
|
||||
if err := osStatusError(C.SecIdentityCopyCertificate(i.ref, &certRef)); err != nil {
|
||||
return nilSecCertificateRef, err
|
||||
}
|
||||
|
||||
i.cref = certRef
|
||||
|
||||
return i.cref, nil
|
||||
}
|
||||
|
||||
// exportCertRef gets a *x509.Certificate for the given SecCertificateRef.
|
||||
func exportCertRef(certRef C.SecCertificateRef) (*x509.Certificate, error) {
|
||||
derRef := C.SecCertificateCopyData(certRef)
|
||||
if derRef == nilCFDataRef {
|
||||
return nil, errors.New("error getting certificate from identity")
|
||||
}
|
||||
defer C.CFRelease(C.CFTypeRef(derRef))
|
||||
|
||||
der := cfDataToBytes(derRef)
|
||||
crt, err := x509.ParseCertificate(der)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return crt, nil
|
||||
}
|
||||
|
||||
// stringToCFString converts a Go string to a CFStringRef.
|
||||
func stringToCFString(gostr string) C.CFStringRef {
|
||||
cstr := C.CString(gostr)
|
||||
defer C.free(unsafe.Pointer(cstr))
|
||||
|
||||
return C.CFStringCreateWithCString(nilCFAllocatorRef, cstr, C.kCFStringEncodingUTF8)
|
||||
}
|
||||
|
||||
// mapToCFDictionary converts a Go map[C.CFTypeRef]C.CFTypeRef to a
|
||||
// CFDictionaryRef.
|
||||
func mapToCFDictionary(gomap map[C.CFTypeRef]C.CFTypeRef) C.CFDictionaryRef {
|
||||
var (
|
||||
n = len(gomap)
|
||||
keys = make([]unsafe.Pointer, 0, n)
|
||||
values = make([]unsafe.Pointer, 0, n)
|
||||
)
|
||||
|
||||
for k, v := range gomap {
|
||||
keys = append(keys, unsafe.Pointer(k))
|
||||
values = append(values, unsafe.Pointer(v))
|
||||
}
|
||||
|
||||
return C.CFDictionaryCreate(nilCFAllocatorRef, &keys[0], &values[0], C.CFIndex(n), nil, nil)
|
||||
}
|
||||
|
||||
// cfDataToBytes converts a CFDataRef to a Go byte slice.
|
||||
func cfDataToBytes(cfdata C.CFDataRef) []byte {
|
||||
nBytes := C.CFDataGetLength(cfdata)
|
||||
bytesPtr := C.CFDataGetBytePtr(cfdata)
|
||||
return C.GoBytes(unsafe.Pointer(bytesPtr), C.int(nBytes))
|
||||
}
|
||||
|
||||
// bytesToCFData converts a Go byte slice to a CFDataRef.
|
||||
func bytesToCFData(gobytes []byte) (C.CFDataRef, error) {
|
||||
var (
|
||||
cptr = (*C.UInt8)(nil)
|
||||
clen = C.CFIndex(len(gobytes))
|
||||
)
|
||||
|
||||
if len(gobytes) > 0 {
|
||||
cptr = (*C.UInt8)(&gobytes[0])
|
||||
}
|
||||
|
||||
cdata := C.CFDataCreate(nilCFAllocatorRef, cptr, clen)
|
||||
if cdata == nilCFDataRef {
|
||||
return nilCFDataRef, errors.New("error creatin cfdata")
|
||||
}
|
||||
|
||||
return cdata, nil
|
||||
}
|
||||
|
||||
// osStatus wraps a C.OSStatus
|
||||
type osStatus C.OSStatus
|
||||
|
||||
const (
|
||||
errSecItemNotFound = osStatus(C.errSecItemNotFound)
|
||||
)
|
||||
|
||||
// osStatusError returns an error for an OSStatus unless it is errSecSuccess.
|
||||
func osStatusError(s C.OSStatus) error {
|
||||
if s == C.errSecSuccess {
|
||||
return nil
|
||||
}
|
||||
|
||||
return osStatus(s)
|
||||
}
|
||||
|
||||
// Error implements the error interface.
|
||||
func (s osStatus) Error() string {
|
||||
return fmt.Sprintf("OSStatus %d", s)
|
||||
}
|
||||
|
||||
// cfErrorError returns an error for a CFErrorRef unless it is nil.
|
||||
func cfErrorError(cerr C.CFErrorRef) error {
|
||||
if cerr == nilCFErrorRef {
|
||||
return nil
|
||||
}
|
||||
|
||||
code := int(C.CFErrorGetCode(cerr))
|
||||
|
||||
if cdescription := C.CFErrorCopyDescription(cerr); cdescription != nilCFStringRef {
|
||||
defer C.CFRelease(C.CFTypeRef(cdescription))
|
||||
|
||||
if cstr := C.CFStringGetCStringPtr(cdescription, C.kCFStringEncodingUTF8); cstr != nil {
|
||||
str := C.GoString(cstr)
|
||||
|
||||
return fmt.Errorf("CFError %d (%s)", code, str)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return fmt.Errorf("CFError %d", code)
|
||||
}
|
||||
14
vendor/github.com/tailscale/certstore/certstore_linux.go
generated
vendored
Normal file
14
vendor/github.com/tailscale/certstore/certstore_linux.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
package certstore
|
||||
|
||||
import "errors"
|
||||
|
||||
// This will hopefully give a compiler error that will hint at the fact that
|
||||
// this package isn't designed to work on Linux.
|
||||
func init() {
|
||||
CERTSTORE_DOESNT_WORK_ON_LINIX
|
||||
}
|
||||
|
||||
// Implement this function, just to silence other compiler errors.
|
||||
func openStore(location StoreLocation, permissions ...StorePermission) (Store, error) {
|
||||
return nil, errors.New("certstore only works on macOS and Windows")
|
||||
}
|
||||
639
vendor/github.com/tailscale/certstore/certstore_windows.go
generated
vendored
Normal file
639
vendor/github.com/tailscale/certstore/certstore_windows.go
generated
vendored
Normal file
@@ -0,0 +1,639 @@
|
||||
package certstore
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/asn1"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/cpu"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
const myStoreName = "MY"
|
||||
|
||||
var (
|
||||
// winAPIFlag specifies the flags that should be passed to
|
||||
// CryptAcquireCertificatePrivateKey. This impacts whether the CryptoAPI or CNG
|
||||
// API will be used.
|
||||
//
|
||||
// Possible values are:
|
||||
//
|
||||
// 0 — Only use CryptoAPI.
|
||||
// windows.CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG — Prefer CryptoAPI.
|
||||
// windows.CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG — Prefer CNG.
|
||||
// windows.CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG — Only use CNG.
|
||||
winAPIFlag uint32 = windows.CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG
|
||||
)
|
||||
|
||||
// winStore is a wrapper around a certStoreHandle.
|
||||
type winStore struct {
|
||||
store certStoreHandle
|
||||
}
|
||||
|
||||
// openStore opens the current user's personal cert store.
|
||||
func openStore(location StoreLocation, permissions ...StorePermission) (*winStore, error) {
|
||||
storeName, err := windows.UTF16PtrFromString(myStoreName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var flags uint32
|
||||
switch location {
|
||||
case User:
|
||||
flags |= windows.CERT_SYSTEM_STORE_CURRENT_USER
|
||||
case System:
|
||||
flags |= windows.CERT_SYSTEM_STORE_LOCAL_MACHINE
|
||||
}
|
||||
|
||||
for _, p := range permissions {
|
||||
switch p {
|
||||
case ReadOnly:
|
||||
flags |= windows.CERT_STORE_READONLY_FLAG
|
||||
}
|
||||
}
|
||||
|
||||
store, err := windows.CertOpenStore(windows.CERT_STORE_PROV_SYSTEM_W, 0, 0, flags, uintptr(unsafe.Pointer(storeName)))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open system cert store: %w", err)
|
||||
}
|
||||
|
||||
return &winStore{certStoreHandle(store)}, nil
|
||||
}
|
||||
|
||||
// Identities implements the Store interface.
|
||||
func (s *winStore) Identities() ([]Identity, error) {
|
||||
var (
|
||||
err error
|
||||
idents []Identity
|
||||
|
||||
// CertFindChainInStore parameters
|
||||
encoding = uint32(windows.X509_ASN_ENCODING)
|
||||
flags = uint32(windows.CERT_CHAIN_FIND_BY_ISSUER_CACHE_ONLY_FLAG | windows.CERT_CHAIN_FIND_BY_ISSUER_CACHE_ONLY_URL_FLAG)
|
||||
findType = uint32(windows.CERT_CHAIN_FIND_BY_ISSUER)
|
||||
params = &windows.CertChainFindByIssuerPara{Size: uint32(unsafe.Sizeof(windows.CertChainFindByIssuerPara{}))}
|
||||
chainCtx *windows.CertChainContext
|
||||
)
|
||||
|
||||
for {
|
||||
chainCtx, err = windows.CertFindChainInStore(windows.Handle(s.store), encoding, flags, findType, unsafe.Pointer(params), chainCtx)
|
||||
if errors.Is(err, syscall.Errno(windows.CRYPT_E_NOT_FOUND)) {
|
||||
return idents, nil
|
||||
}
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to iterate certs in store: %w", err)
|
||||
break
|
||||
}
|
||||
if chainCtx.ChainCount < 1 {
|
||||
err = errors.New("bad chain")
|
||||
break
|
||||
}
|
||||
|
||||
// not sure why this isn't 1 << 29
|
||||
const maxPointerArray = 1 << 28
|
||||
|
||||
// rgpChain is actually an array, but we only care about the first one.
|
||||
simpleChain := *chainCtx.Chains
|
||||
if simpleChain.NumElements < 1 || simpleChain.NumElements > maxPointerArray {
|
||||
err = errors.New("bad chain")
|
||||
break
|
||||
}
|
||||
|
||||
chainElts := unsafe.Slice(simpleChain.Elements, simpleChain.NumElements)
|
||||
|
||||
// Build chain of certificates from each elt's certificate context.
|
||||
chain := make([]*windows.CertContext, len(chainElts))
|
||||
for j := range chainElts {
|
||||
chain[j] = chainElts[j].CertContext
|
||||
}
|
||||
|
||||
idents = append(idents, newWinIdentity(chain))
|
||||
}
|
||||
|
||||
for _, ident := range idents {
|
||||
ident.Close()
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Import implements the Store interface.
|
||||
func (s *winStore) Import(data []byte, password string) error {
|
||||
cpw, err := windows.UTF16PtrFromString(password)
|
||||
if err != nil {
|
||||
return fmt.Errorf("converting password: %w", err)
|
||||
}
|
||||
|
||||
pfx := &windows.CryptDataBlob{
|
||||
Size: uint32(len(data)),
|
||||
Data: unsafe.SliceData(data),
|
||||
}
|
||||
|
||||
var flags uint32
|
||||
flags = windows.CRYPT_USER_KEYSET
|
||||
|
||||
// import into preferred KSP
|
||||
if winAPIFlag&windows.CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG > 0 {
|
||||
flags |= windows.PKCS12_PREFER_CNG_KSP
|
||||
} else if winAPIFlag&windows.CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG > 0 {
|
||||
flags |= windows.PKCS12_ALWAYS_CNG_KSP
|
||||
}
|
||||
|
||||
store, err := windows.PFXImportCertStore(pfx, cpw, flags)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to import PFX cert store: %w", err)
|
||||
}
|
||||
defer windows.CertCloseStore(store, windows.CERT_CLOSE_STORE_FORCE_FLAG)
|
||||
|
||||
var (
|
||||
ctx *windows.CertContext
|
||||
encoding = uint32(windows.X509_ASN_ENCODING | windows.PKCS_7_ASN_ENCODING)
|
||||
)
|
||||
|
||||
for {
|
||||
// iterate through certs in temporary store
|
||||
ctx, err = windows.CertFindCertificateInStore(store, encoding, 0, windows.CERT_FIND_ANY, nil, ctx)
|
||||
if errors.Is(err, syscall.Errno(windows.CRYPT_E_NOT_FOUND)) {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to iterate certs in store: %w", err)
|
||||
}
|
||||
|
||||
// Copy the cert to the system store.
|
||||
if err := windows.CertAddCertificateContextToStore(windows.Handle(s.store), ctx, windows.CERT_STORE_ADD_REPLACE_EXISTING, nil); err != nil {
|
||||
return fmt.Errorf("failed to add imported certificate to %s store: %w", myStoreName, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close implements the Store interface.
|
||||
func (s *winStore) Close() {
|
||||
windows.CertCloseStore(windows.Handle(s.store), 0)
|
||||
s.store = 0
|
||||
}
|
||||
|
||||
// winIdentity implements the Identity interface.
|
||||
type winIdentity struct {
|
||||
chain []*windows.CertContext
|
||||
signer *winPrivateKey
|
||||
}
|
||||
|
||||
func newWinIdentity(chain []*windows.CertContext) *winIdentity {
|
||||
for _, ctx := range chain {
|
||||
windows.CertDuplicateCertificateContext(ctx)
|
||||
}
|
||||
|
||||
return &winIdentity{chain: chain}
|
||||
}
|
||||
|
||||
// Certificate implements the Identity interface.
|
||||
func (i *winIdentity) Certificate() (*x509.Certificate, error) {
|
||||
return exportCertCtx(i.chain[0])
|
||||
}
|
||||
|
||||
// CertificateChain implements the Identity interface.
|
||||
func (i *winIdentity) CertificateChain() ([]*x509.Certificate, error) {
|
||||
var (
|
||||
certs = make([]*x509.Certificate, len(i.chain))
|
||||
err error
|
||||
)
|
||||
|
||||
for j := range i.chain {
|
||||
if certs[j], err = exportCertCtx(i.chain[j]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return certs, nil
|
||||
}
|
||||
|
||||
// Signer implements the Identity interface.
|
||||
func (i *winIdentity) Signer() (crypto.Signer, error) {
|
||||
return i.getPrivateKey()
|
||||
}
|
||||
|
||||
// getPrivateKey gets this identity's private *winPrivateKey.
|
||||
func (i *winIdentity) getPrivateKey() (*winPrivateKey, error) {
|
||||
if i.signer != nil {
|
||||
return i.signer, nil
|
||||
}
|
||||
|
||||
cert, err := i.Certificate()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get identity certificate: %w", err)
|
||||
}
|
||||
|
||||
signer, err := newWinPrivateKey(i.chain[0], cert.PublicKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load identity private key: %w", err)
|
||||
}
|
||||
|
||||
i.signer = signer
|
||||
|
||||
return i.signer, nil
|
||||
}
|
||||
|
||||
// Delete implements the Identity interface.
|
||||
func (i *winIdentity) Delete() error {
|
||||
// duplicate cert context, since CertDeleteCertificateFromStore will free it.
|
||||
deleteCtx := windows.CertDuplicateCertificateContext(i.chain[0])
|
||||
|
||||
// try deleting cert
|
||||
if err := windows.CertDeleteCertificateFromStore(deleteCtx); err != nil {
|
||||
return fmt.Errorf("failed to delete certificate from store: %w", err)
|
||||
}
|
||||
|
||||
// try deleting private key
|
||||
wpk, err := i.getPrivateKey()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get identity private key: %w", err)
|
||||
}
|
||||
|
||||
if err := wpk.Delete(); err != nil {
|
||||
return fmt.Errorf("failed to delete identity private key: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close implements the Identity interface.
|
||||
func (i *winIdentity) Close() {
|
||||
if i.signer != nil {
|
||||
i.signer.Close()
|
||||
i.signer = nil
|
||||
}
|
||||
|
||||
for _, ctx := range i.chain {
|
||||
_ = windows.CertFreeCertificateContext(ctx)
|
||||
i.chain = nil
|
||||
}
|
||||
}
|
||||
|
||||
// winPrivateKey is a wrapper around a HCRYPTPROV_OR_NCRYPT_KEY_HANDLE.
|
||||
type winPrivateKey struct {
|
||||
publicKey crypto.PublicKey
|
||||
|
||||
// CryptoAPI fields
|
||||
capiProv cryptProviderHandle
|
||||
|
||||
// CNG fields
|
||||
cngHandle nCryptKeyHandle
|
||||
keySpec uint32
|
||||
}
|
||||
|
||||
// newWinPrivateKey gets a *winPrivateKey for the given certificate.
|
||||
func newWinPrivateKey(certCtx *windows.CertContext, publicKey crypto.PublicKey) (*winPrivateKey, error) {
|
||||
var (
|
||||
provOrKey windows.Handle // HCRYPTPROV_OR_NCRYPT_KEY_HANDLE
|
||||
keySpec uint32
|
||||
mustFree bool
|
||||
)
|
||||
|
||||
if publicKey == nil {
|
||||
return nil, errors.New("nil public key")
|
||||
}
|
||||
|
||||
// Get a handle for the found private key.
|
||||
if err := windows.CryptAcquireCertificatePrivateKey(certCtx, winAPIFlag, nil, &provOrKey, &keySpec, &mustFree); err != nil {
|
||||
return nil, fmt.Errorf("failed to get private key for certificate: %w", err)
|
||||
}
|
||||
|
||||
if !mustFree {
|
||||
// This shouldn't happen since we're not asking for cached keys.
|
||||
return nil, errors.New("CryptAcquireCertificatePrivateKey set mustFree")
|
||||
}
|
||||
|
||||
if keySpec == windows.CERT_NCRYPT_KEY_SPEC {
|
||||
return &winPrivateKey{
|
||||
publicKey: publicKey,
|
||||
cngHandle: nCryptKeyHandle(provOrKey),
|
||||
}, nil
|
||||
} else {
|
||||
return &winPrivateKey{
|
||||
publicKey: publicKey,
|
||||
capiProv: cryptProviderHandle(provOrKey),
|
||||
keySpec: keySpec,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Public implements the crypto.Signer interface.
|
||||
func (wpk *winPrivateKey) Public() crypto.PublicKey {
|
||||
return wpk.publicKey
|
||||
}
|
||||
|
||||
// Sign implements the crypto.Signer interface.
|
||||
func (wpk *winPrivateKey) Sign(_ io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) {
|
||||
if wpk.capiProv != 0 {
|
||||
return wpk.capiSignHash(opts, digest)
|
||||
} else if wpk.cngHandle != 0 {
|
||||
return wpk.cngSignHash(opts, digest)
|
||||
} else {
|
||||
return nil, errors.New("bad private key")
|
||||
}
|
||||
}
|
||||
|
||||
type bCryptPKCS1PaddingInfo struct {
|
||||
// Algorithm is the name of the hashing algorithm to use, in UTF16. Use one
|
||||
// of the BCRYPT_*_ALGORITHM constants.
|
||||
Algorithm *uint16
|
||||
}
|
||||
|
||||
type bCryptPSSPaddingInfo struct {
|
||||
// Algorithm is the name of the hashing algorithm to use, in UTF16. Use one
|
||||
// of the BCRYPT_*_ALGORITHM constants.
|
||||
Algorithm *uint16
|
||||
// SaltLength is the size, in bytes, of the random salt to use for the
|
||||
// padding.
|
||||
SaltLength uint32
|
||||
}
|
||||
|
||||
// cngSignHash signs a digest using the CNG APIs.
|
||||
func (wpk *winPrivateKey) cngSignHash(opts crypto.SignerOpts, digest []byte) ([]byte, error) {
|
||||
hash := opts.HashFunc()
|
||||
if len(digest) != hash.Size() {
|
||||
return nil, errors.New("cngSignHash: bad digest for hash")
|
||||
}
|
||||
|
||||
var (
|
||||
// input
|
||||
padPtr unsafe.Pointer
|
||||
digestPtr = unsafe.SliceData(digest)
|
||||
digestLen = uint32(len(digest))
|
||||
flags uint32
|
||||
|
||||
// output
|
||||
sigLen uint32
|
||||
)
|
||||
|
||||
// setup pkcs1v1.5 padding for RSA
|
||||
if _, isRSA := wpk.publicKey.(*rsa.PublicKey); isRSA {
|
||||
var alg string
|
||||
switch hash {
|
||||
case crypto.SHA256:
|
||||
alg = BCRYPT_SHA256_ALGORITHM
|
||||
case crypto.SHA384:
|
||||
alg = BCRYPT_SHA384_ALGORITHM
|
||||
case crypto.SHA512:
|
||||
alg = BCRYPT_SHA512_ALGORITHM
|
||||
default:
|
||||
return nil, fmt.Errorf("cngSignHash: converting from Go algorithm: %w", ErrUnsupportedHash)
|
||||
}
|
||||
|
||||
algName, err := windows.UTF16PtrFromString(alg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if pssOpts, ok := opts.(*rsa.PSSOptions); ok {
|
||||
saltLen := pssOpts.SaltLength
|
||||
if saltLen == rsa.PSSSaltLengthEqualsHash {
|
||||
saltLen = len(digest)
|
||||
} else if saltLen == rsa.PSSSaltLengthAuto {
|
||||
saltLen = hash.Size()
|
||||
}
|
||||
padPtr = unsafe.Pointer(&bCryptPSSPaddingInfo{
|
||||
Algorithm: algName,
|
||||
SaltLength: uint32(saltLen),
|
||||
})
|
||||
flags |= BCRYPT_PAD_PSS
|
||||
} else {
|
||||
padPtr = unsafe.Pointer(&bCryptPKCS1PaddingInfo{
|
||||
Algorithm: algName,
|
||||
})
|
||||
flags |= BCRYPT_PAD_PKCS1
|
||||
}
|
||||
}
|
||||
|
||||
// get signature length
|
||||
if err := nCryptSignHash(wpk.cngHandle, padPtr, digestPtr, digestLen, nil, 0, &sigLen, flags); err != nil {
|
||||
return nil, fmt.Errorf("cngSignHash: failed to get signature length: %w", err)
|
||||
}
|
||||
|
||||
// get signature
|
||||
sig := make([]byte, sigLen)
|
||||
if err := nCryptSignHash(wpk.cngHandle, padPtr, digestPtr, digestLen, unsafe.SliceData(sig), sigLen, &sigLen, flags); err != nil {
|
||||
return nil, fmt.Errorf("cngSignHash: failed to sign digest: %w", err)
|
||||
}
|
||||
|
||||
// CNG returns a raw ECDSA signature, but we wan't ASN.1 DER encoding.
|
||||
if _, isEC := wpk.publicKey.(*ecdsa.PublicKey); isEC {
|
||||
if len(sig)%2 != 0 {
|
||||
return nil, errors.New("cngSignHash: bad ecdsa signature from CNG")
|
||||
}
|
||||
|
||||
type ecdsaSignature struct {
|
||||
R, S *big.Int
|
||||
}
|
||||
|
||||
r := new(big.Int).SetBytes(sig[:len(sig)/2])
|
||||
s := new(big.Int).SetBytes(sig[len(sig)/2:])
|
||||
|
||||
encoded, err := asn1.Marshal(ecdsaSignature{r, s})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cngSignHash: failed to ASN.1 encode EC signature: %w", err)
|
||||
}
|
||||
|
||||
return encoded, nil
|
||||
}
|
||||
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
// capiSignHash signs a digest using the CryptoAPI APIs.
|
||||
func (wpk *winPrivateKey) capiSignHash(opts crypto.SignerOpts, digest []byte) ([]byte, error) {
|
||||
if _, ok := opts.(*rsa.PSSOptions); ok {
|
||||
return nil, fmt.Errorf("capiSignHash: CAPI does not support PSS padding, %w", ErrUnsupportedHash)
|
||||
}
|
||||
|
||||
hash := opts.HashFunc()
|
||||
if len(digest) != hash.Size() {
|
||||
return nil, errors.New("capiSignHash: bad digest for hash")
|
||||
}
|
||||
|
||||
// Figure out which CryptoAPI hash algorithm we're using.
|
||||
var hash_alg cryptAlgorithm
|
||||
|
||||
switch hash {
|
||||
case crypto.SHA256:
|
||||
hash_alg = CALG_SHA_256
|
||||
case crypto.SHA384:
|
||||
hash_alg = CALG_SHA_384
|
||||
case crypto.SHA512:
|
||||
hash_alg = CALG_SHA_512
|
||||
default:
|
||||
return nil, fmt.Errorf("capiSignHash: converting from Go algorithm: %w", ErrUnsupportedHash)
|
||||
}
|
||||
|
||||
// Instantiate a CryptoAPI hash object.
|
||||
var chash cryptHashHandle
|
||||
|
||||
if err := cryptCreateHash(wpk.capiProv, hash_alg, 0, 0, &chash); err != nil {
|
||||
if errors.Is(err, syscall.Errno(windows.NTE_BAD_ALGID)) {
|
||||
err = ErrUnsupportedHash
|
||||
}
|
||||
return nil, fmt.Errorf("capiSignHash: cryptCreateHash: %w", err)
|
||||
}
|
||||
defer cryptDestroyHash(chash)
|
||||
|
||||
// Make sure the hash size matches.
|
||||
var (
|
||||
hashSize uint32
|
||||
hashSizeLen = uint32(unsafe.Sizeof(hashSize))
|
||||
)
|
||||
|
||||
if err := cryptGetHashParam(chash, HP_HASHSIZE, unsafe.Pointer(&hashSize), &hashSizeLen, 0); err != nil {
|
||||
return nil, fmt.Errorf("capiSignHash: failed to get hash size: %w", err)
|
||||
}
|
||||
|
||||
if hash.Size() != int(hashSize) {
|
||||
return nil, errors.New("capiSignHash: invalid CryptoAPI hash")
|
||||
}
|
||||
|
||||
// Put our digest into the hash object.
|
||||
if err := cryptSetHashParam(chash, HP_HASHVAL, unsafe.Pointer(unsafe.SliceData(digest)), 0); err != nil {
|
||||
return nil, fmt.Errorf("capiSignHash: failed to set hash digest: %w", err)
|
||||
}
|
||||
|
||||
// Get signature length.
|
||||
var sigLen uint32
|
||||
|
||||
if err := cryptSignHash(chash, wpk.keySpec, nil, 0, nil, &sigLen); err != nil {
|
||||
return nil, fmt.Errorf("capiSignHash: failed to get signature length: %w", err)
|
||||
}
|
||||
|
||||
// Get signature
|
||||
sig := make([]byte, int(sigLen))
|
||||
|
||||
if err := cryptSignHash(chash, wpk.keySpec, nil, 0, unsafe.SliceData(sig), &sigLen); err != nil {
|
||||
return nil, fmt.Errorf("capiSignHash: failed to sign digest: %w", err)
|
||||
}
|
||||
|
||||
// Signature is little endian, but we want big endian. Reverse it.
|
||||
for i := len(sig)/2 - 1; i >= 0; i-- {
|
||||
opp := len(sig) - 1 - i
|
||||
sig[i], sig[opp] = sig[opp], sig[i]
|
||||
}
|
||||
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
func (wpk *winPrivateKey) Delete() error {
|
||||
if wpk.cngHandle != 0 {
|
||||
// Delete CNG key
|
||||
if err := nCryptDeleteKey(wpk.cngHandle, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if wpk.capiProv != 0 {
|
||||
// Delete CryptoAPI key
|
||||
var (
|
||||
containerName string
|
||||
providerName string
|
||||
providerType uint32
|
||||
err error
|
||||
)
|
||||
|
||||
containerName, err = wpk.getProviderStringParam(PP_CONTAINER)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get PP_CONTAINER: %w", err)
|
||||
}
|
||||
|
||||
providerName, err = wpk.getProviderStringParam(PP_NAME)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get PP_NAME: %w", err)
|
||||
}
|
||||
|
||||
providerType, err = wpk.getProviderUint32Param(PP_PROVTYPE)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get PP_PROVTYPE: %w", err)
|
||||
}
|
||||
|
||||
// use CRYPT_SILENT too?
|
||||
var prov windows.Handle
|
||||
if err := windows.CryptAcquireContext(&prov, windows.StringToUTF16Ptr(containerName), windows.StringToUTF16Ptr(providerName),
|
||||
providerType, windows.CRYPT_DELETEKEYSET); err != nil {
|
||||
return fmt.Errorf("failed to delete key set (container=%q, name=%q, provtype=%d): %w",
|
||||
containerName, providerName, providerType, err)
|
||||
}
|
||||
wpk.capiProv = 0
|
||||
} else {
|
||||
return errors.New("bad private key")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getProviderParam gets a parameter about a provider.
|
||||
func (wpk *winPrivateKey) getProviderParam(param uint32) ([]byte, error) {
|
||||
var dataLen uint32
|
||||
if err := cryptGetProvParam(wpk.capiProv, param, nil, &dataLen, 0); err != nil {
|
||||
return nil, fmt.Errorf("failed to get provider parameter size: %w", err)
|
||||
}
|
||||
|
||||
data := make([]byte, dataLen)
|
||||
if err := cryptGetProvParam(wpk.capiProv, param, unsafe.SliceData(data), &dataLen, 0); err != nil {
|
||||
return nil, fmt.Errorf("failed to get provider parameter: %w", err)
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// getProviderStringParam gets a parameter about a provider. The parameter is a zero-terminated char string.
|
||||
func (wpk *winPrivateKey) getProviderStringParam(param uint32) (string, error) {
|
||||
val, err := wpk.getProviderParam(param)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return windows.ByteSliceToString(val), nil
|
||||
}
|
||||
|
||||
// getProviderUint32Param gets a parameter about a provider. The parameter is a uint32.
|
||||
func (wpk *winPrivateKey) getProviderUint32Param(param uint32) (uint32, error) {
|
||||
val, err := wpk.getProviderParam(param)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(val) != 4 {
|
||||
return 0, errors.New("uint32 data length is not 32 bits")
|
||||
}
|
||||
if cpu.IsBigEndian {
|
||||
return binary.BigEndian.Uint32(val), nil
|
||||
}
|
||||
return binary.LittleEndian.Uint32(val), nil
|
||||
}
|
||||
|
||||
// Close closes this winPrivateKey.
|
||||
func (wpk *winPrivateKey) Close() {
|
||||
if wpk.cngHandle != 0 {
|
||||
_ = nCryptFreeObject(windows.Handle(wpk.cngHandle))
|
||||
wpk.cngHandle = 0
|
||||
}
|
||||
|
||||
if wpk.capiProv != 0 {
|
||||
_ = windows.CryptReleaseContext(windows.Handle(wpk.capiProv), 0)
|
||||
wpk.capiProv = 0
|
||||
}
|
||||
}
|
||||
|
||||
// exportCertCtx exports a *windows.CertContext as an *x509.Certificate.
|
||||
func exportCertCtx(ctx *windows.CertContext) (*x509.Certificate, error) {
|
||||
der := unsafe.Slice(ctx.EncodedCert, ctx.Length)
|
||||
|
||||
cert, err := x509.ParseCertificate(der)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("certificate parsing failed: %w", err)
|
||||
}
|
||||
|
||||
return cert, nil
|
||||
}
|
||||
79
vendor/github.com/tailscale/certstore/crypt_strings_windows.go
generated
vendored
Normal file
79
vendor/github.com/tailscale/certstore/crypt_strings_windows.go
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
package certstore
|
||||
|
||||
const (
|
||||
// NCRYPT Object Property Names
|
||||
NCRYPT_ALGORITHM_GROUP_PROPERTY = "Algorithm Group"
|
||||
NCRYPT_ALGORITHM_PROPERTY = "Algorithm Name"
|
||||
NCRYPT_BLOCK_LENGTH_PROPERTY = "Block Length"
|
||||
NCRYPT_CERTIFICATE_PROPERTY = "SmartCardKeyCertificate"
|
||||
NCRYPT_DH_PARAMETERS_PROPERTY = BCRYPT_DH_PARAMETERS
|
||||
BCRYPT_DH_PARAMETERS = "DHParameters"
|
||||
NCRYPT_EXPORT_POLICY_PROPERTY = "Export Policy"
|
||||
NCRYPT_IMPL_TYPE_PROPERTY = "Impl Type"
|
||||
NCRYPT_KEY_TYPE_PROPERTY = "Key Type"
|
||||
NCRYPT_KEY_USAGE_PROPERTY = "Key Usage"
|
||||
NCRYPT_LAST_MODIFIED_PROPERTY = "Modified"
|
||||
NCRYPT_LENGTH_PROPERTY = "Length"
|
||||
NCRYPT_LENGTHS_PROPERTY = "Lengths"
|
||||
NCRYPT_MAX_NAME_LENGTH_PROPERTY = "Max Name Length"
|
||||
NCRYPT_NAME_PROPERTY = "Name"
|
||||
NCRYPT_PIN_PROMPT_PROPERTY = "SmartCardPinPrompt"
|
||||
NCRYPT_PIN_PROPERTY = "SmartCardPin"
|
||||
NCRYPT_PROVIDER_HANDLE_PROPERTY = "Provider Handle"
|
||||
NCRYPT_READER_PROPERTY = "SmartCardReader"
|
||||
NCRYPT_ROOT_CERTSTORE_PROPERTY = "SmartcardRootCertStore"
|
||||
NCRYPT_SECURE_PIN_PROPERTY = "SmartCardSecurePin"
|
||||
NCRYPT_SECURITY_DESCR_PROPERTY = "Security Descr"
|
||||
NCRYPT_SECURITY_DESCR_SUPPORT_PROPERTY = "Security Descr Support"
|
||||
NCRYPT_SMARTCARD_GUID_PROPERTY = "SmartCardGuid"
|
||||
NCRYPT_UI_POLICY_PROPERTY = "UI Policy"
|
||||
NCRYPT_UNIQUE_NAME_PROPERTY = "Unique Name"
|
||||
NCRYPT_USE_CONTEXT_PROPERTY = "Use Context"
|
||||
NCRYPT_USE_COUNT_ENABLED_PROPERTY = "Enabled Use Count"
|
||||
NCRYPT_USE_COUNT_PROPERTY = "Use Count"
|
||||
NCRYPT_USER_CERTSTORE_PROPERTY = "SmartCardUserCertStore"
|
||||
NCRYPT_VERSION_PROPERTY = "Version"
|
||||
NCRYPT_WINDOW_HANDLE_PROPERTY = "HWND Handle"
|
||||
|
||||
// BCRYPT BLOB Types
|
||||
BCRYPT_DH_PRIVATE_BLOB = "DHPRIVATEBLOB"
|
||||
BCRYPT_DH_PUBLIC_BLOB = "DHPUBLICBLOB"
|
||||
BCRYPT_DSA_PRIVATE_BLOB = "DSAPRIVATEBLOB"
|
||||
BCRYPT_DSA_PUBLIC_BLOB = "DSAPUBLICBLOB"
|
||||
BCRYPT_ECCPRIVATE_BLOB = "ECCPRIVATEBLOB"
|
||||
BCRYPT_ECCPUBLIC_BLOB = "ECCPUBLICBLOB"
|
||||
BCRYPT_PRIVATE_KEY_BLOB = "PRIVATEBLOB"
|
||||
BCRYPT_PUBLIC_KEY_BLOB = "PUBLICBLOB"
|
||||
BCRYPT_RSAFULLPRIVATE_BLOB = "RSAFULLPRIVATEBLOB"
|
||||
BCRYPT_RSAPRIVATE_BLOB = "RSAPRIVATEBLOB"
|
||||
BCRYPT_RSAPUBLIC_BLOB = "RSAPUBLICBLOB"
|
||||
|
||||
// BCRYPT Algorithm Names
|
||||
BCRYPT_3DES_ALGORITHM = "3DES"
|
||||
BCRYPT_AES_ALGORITHM = "AES"
|
||||
BCRYPT_DES_ALGORITHM = "DES"
|
||||
BCRYPT_DSA_ALGORITHM = "DSA"
|
||||
BCRYPT_ECDH_P256_ALGORITHM = "ECDH_P256"
|
||||
BCRYPT_ECDH_P384_ALGORITHM = "ECDH_P384"
|
||||
BCRYPT_ECDSA_P256_ALGORITHM = "ECDSA_P256"
|
||||
BCRYPT_ECDSA_P384_ALGORITHM = "ECDSA_P384"
|
||||
BCRYPT_ECDSA_P521_ALGORITHM = "ECDSA_P521"
|
||||
BCRYPT_MD2_ALGORITHM = "MD2"
|
||||
BCRYPT_MD4_ALGORITHM = "MD4"
|
||||
BCRYPT_MD5_ALGORITHM = "MD5"
|
||||
BCRYPT_RC2_ALGORITHM = "RC2"
|
||||
BCRYPT_RC4_ALGORITHM = "RC4"
|
||||
BCRYPT_RNG_ALGORITHM = "RNG"
|
||||
BCRYPT_RSA_ALGORITHM = "RSA"
|
||||
BCRYPT_RSA_SIGN_ALGORITHM = "RSA_SIGN"
|
||||
BCRYPT_SHA1_ALGORITHM = "SHA1"
|
||||
BCRYPT_SHA256_ALGORITHM = "SHA256"
|
||||
BCRYPT_SHA384_ALGORITHM = "SHA384"
|
||||
BCRYPT_SHA512_ALGORITHM = "SHA512"
|
||||
BCRYPT_SP800108_CTR_HMAC_ALGORITHM = "SP800_108_CTR_HMAC"
|
||||
BCRYPT_SP80056A_CONCAT_ALGORITHM = "SP800_56A_CONCAT"
|
||||
BCRYPT_PBKDF2_ALGORITHM = "PBKDF2"
|
||||
BCRYPT_ECDSA_ALGORITHM = "ECDSA"
|
||||
BCRYPT_ECDH_ALGORITHM = "ECDH"
|
||||
BCRYPT_XTS_AES_ALGORITHM = "XTS-AES"
|
||||
)
|
||||
67
vendor/github.com/tailscale/certstore/syscall_windows.go
generated
vendored
Normal file
67
vendor/github.com/tailscale/certstore/syscall_windows.go
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
package certstore
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go syscall_windows.go
|
||||
|
||||
type certStoreHandle windows.Handle
|
||||
|
||||
// CryptoAPI APIs from wincrypt.h
|
||||
|
||||
type cryptProviderHandle windows.Handle // HCRYPTPROV
|
||||
type cryptHashHandle windows.Handle // HCRYPTHASH
|
||||
type cryptKeyHandle windows.Handle // HCRYPTKEY
|
||||
type cryptAlgorithm uint32 // ALG_ID
|
||||
|
||||
const (
|
||||
// Values for ALG_ID
|
||||
CALG_SHA_256 cryptAlgorithm = 0x0000800c
|
||||
CALG_SHA_384 cryptAlgorithm = 0x0000800d
|
||||
CALG_SHA_512 cryptAlgorithm = 0x0000800e
|
||||
|
||||
// Values of the dwParam for CryptGetHashParam and/or CryptSetHashParam
|
||||
HP_ALGID = 0x1
|
||||
HP_HASHVAL = 0x2
|
||||
HP_HASHSIZE = 0x4
|
||||
HP_HMAC_INFO = 0x5
|
||||
|
||||
// Values of the dwParam for CryptGetProvParam and/or CryptSetProvParam
|
||||
PP_NAME = 4
|
||||
PP_CONTAINER = 6
|
||||
PP_PROVTYPE = 16
|
||||
)
|
||||
|
||||
// https://learn.microsoft.com/en-ca/windows/win32/api/wincrypt/nf-wincrypt-cryptcreatehash
|
||||
//sys cryptCreateHash(hProv cryptProviderHandle, Algid cryptAlgorithm, hKey cryptKeyHandle, dwFlags uint32, phHash *cryptHashHandle) (err error) = advapi32.CryptCreateHash
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptdestroyhash
|
||||
//sys cryptDestroyHash(hHash cryptHashHandle) (err error) = advapi32.CryptDestroyHash
|
||||
// https://learn.microsoft.com/en-ca/windows/win32/api/wincrypt/nf-wincrypt-cryptgethashparam
|
||||
//sys cryptGetHashParam(hHash cryptHashHandle, dwParam uint32, pbData unsafe.Pointer, pdwDataLen *uint32, dwFlags uint32) (err error) = advapi32.CryptGetHashParam
|
||||
// https://learn.microsoft.com/en-ca/windows/win32/api/wincrypt/nf-wincrypt-cryptsethashparam
|
||||
//sys cryptSetHashParam(hHash cryptHashHandle, dwParam uint32, pbData unsafe.Pointer, dwFlags uint32) (err error) = advapi32.CryptSetHashParam
|
||||
// https://learn.microsoft.com/en-ca/windows/win32/api/wincrypt/nf-wincrypt-cryptsignhashw
|
||||
//sys cryptSignHash(hHash cryptHashHandle, dwKeySpec uint32, szDescription *uint16, dwFlags uint32, pbSignature *byte, pdwSigLen *uint32) (err error) = advapi32.CryptSignHashW
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptgetprovparam
|
||||
//sys cryptGetProvParam(hProv cryptProviderHandle, dwParam uint32, pbData *byte, pdwDataLen *uint32, dwFlags uint32) (err error) = advapi32.CryptGetProvParam
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptsetprovparam
|
||||
//sys cryptSetProvParam(hProv cryptProviderHandle, dwParam uint32, pbData *byte, dwFlags uint32) (err error) = advapi32.CryptSetProvParam
|
||||
|
||||
// CNG APIs from bcrypt.h and ncrypt.h.
|
||||
const (
|
||||
// Flags for NCryptSignHash and others
|
||||
BCRYPT_PAD_NONE = 0x00000001
|
||||
BCRYPT_PAD_PKCS1 = 0x00000002
|
||||
BCRYPT_PAD_OAEP = 0x00000004
|
||||
BCRYPT_PAD_PSS = 0x00000008
|
||||
)
|
||||
|
||||
type nCryptKeyHandle windows.Handle
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/ncrypt/nf-ncrypt-ncryptsignhash
|
||||
//sys nCryptSignHash(hKey nCryptKeyHandle, pPaddingInfo unsafe.Pointer, pbHashValue *byte, cbHashValue uint32, pbSignature *byte, cbSignature uint32, pcbResult *uint32, dwFlags uint32) (ret error) = ncrypt.NCryptSignHash
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/ncrypt/nf-ncrypt-ncryptdeletekey
|
||||
//sys nCryptDeleteKey(hKey nCryptKeyHandle, dwFlags uint32) (ret error) = ncrypt.NCryptDeleteKey
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/ncrypt/nf-ncrypt-ncryptfreeobject
|
||||
//sys nCryptFreeObject(hObject windows.Handle) (ret error) = ncrypt.NCryptFreeObject
|
||||
134
vendor/github.com/tailscale/certstore/zsyscall_windows.go
generated
vendored
Normal file
134
vendor/github.com/tailscale/certstore/zsyscall_windows.go
generated
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
// Code generated by 'go generate'; DO NOT EDIT.
|
||||
|
||||
package certstore
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var _ unsafe.Pointer
|
||||
|
||||
// Do the interface allocations only once for common
|
||||
// Errno values.
|
||||
const (
|
||||
errnoERROR_IO_PENDING = 997
|
||||
)
|
||||
|
||||
var (
|
||||
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
|
||||
errERROR_EINVAL error = syscall.EINVAL
|
||||
)
|
||||
|
||||
// errnoErr returns common boxed Errno values, to prevent
|
||||
// allocations at runtime.
|
||||
func errnoErr(e syscall.Errno) error {
|
||||
switch e {
|
||||
case 0:
|
||||
return errERROR_EINVAL
|
||||
case errnoERROR_IO_PENDING:
|
||||
return errERROR_IO_PENDING
|
||||
}
|
||||
// TODO: add more here, after collecting data on the common
|
||||
// error values see on Windows. (perhaps when running
|
||||
// all.bat?)
|
||||
return e
|
||||
}
|
||||
|
||||
var (
|
||||
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
|
||||
modncrypt = windows.NewLazySystemDLL("ncrypt.dll")
|
||||
|
||||
procCryptCreateHash = modadvapi32.NewProc("CryptCreateHash")
|
||||
procCryptDestroyHash = modadvapi32.NewProc("CryptDestroyHash")
|
||||
procCryptGetHashParam = modadvapi32.NewProc("CryptGetHashParam")
|
||||
procCryptGetProvParam = modadvapi32.NewProc("CryptGetProvParam")
|
||||
procCryptSetHashParam = modadvapi32.NewProc("CryptSetHashParam")
|
||||
procCryptSetProvParam = modadvapi32.NewProc("CryptSetProvParam")
|
||||
procCryptSignHashW = modadvapi32.NewProc("CryptSignHashW")
|
||||
procNCryptDeleteKey = modncrypt.NewProc("NCryptDeleteKey")
|
||||
procNCryptFreeObject = modncrypt.NewProc("NCryptFreeObject")
|
||||
procNCryptSignHash = modncrypt.NewProc("NCryptSignHash")
|
||||
)
|
||||
|
||||
func cryptCreateHash(hProv cryptProviderHandle, Algid cryptAlgorithm, hKey cryptKeyHandle, dwFlags uint32, phHash *cryptHashHandle) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procCryptCreateHash.Addr(), 5, uintptr(hProv), uintptr(Algid), uintptr(hKey), uintptr(dwFlags), uintptr(unsafe.Pointer(phHash)), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func cryptDestroyHash(hHash cryptHashHandle) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procCryptDestroyHash.Addr(), 1, uintptr(hHash), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func cryptGetHashParam(hHash cryptHashHandle, dwParam uint32, pbData unsafe.Pointer, pdwDataLen *uint32, dwFlags uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procCryptGetHashParam.Addr(), 5, uintptr(hHash), uintptr(dwParam), uintptr(pbData), uintptr(unsafe.Pointer(pdwDataLen)), uintptr(dwFlags), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func cryptGetProvParam(hProv cryptProviderHandle, dwParam uint32, pbData *byte, pdwDataLen *uint32, dwFlags uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procCryptGetProvParam.Addr(), 5, uintptr(hProv), uintptr(dwParam), uintptr(unsafe.Pointer(pbData)), uintptr(unsafe.Pointer(pdwDataLen)), uintptr(dwFlags), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func cryptSetHashParam(hHash cryptHashHandle, dwParam uint32, pbData unsafe.Pointer, dwFlags uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procCryptSetHashParam.Addr(), 4, uintptr(hHash), uintptr(dwParam), uintptr(pbData), uintptr(dwFlags), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func cryptSetProvParam(hProv cryptProviderHandle, dwParam uint32, pbData *byte, dwFlags uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procCryptSetProvParam.Addr(), 4, uintptr(hProv), uintptr(dwParam), uintptr(unsafe.Pointer(pbData)), uintptr(dwFlags), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func cryptSignHash(hHash cryptHashHandle, dwKeySpec uint32, szDescription *uint16, dwFlags uint32, pbSignature *byte, pdwSigLen *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procCryptSignHashW.Addr(), 6, uintptr(hHash), uintptr(dwKeySpec), uintptr(unsafe.Pointer(szDescription)), uintptr(dwFlags), uintptr(unsafe.Pointer(pbSignature)), uintptr(unsafe.Pointer(pdwSigLen)))
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func nCryptDeleteKey(hKey nCryptKeyHandle, dwFlags uint32) (ret error) {
|
||||
r0, _, _ := syscall.Syscall(procNCryptDeleteKey.Addr(), 2, uintptr(hKey), uintptr(dwFlags), 0)
|
||||
if r0 != 0 {
|
||||
ret = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func nCryptFreeObject(hObject windows.Handle) (ret error) {
|
||||
r0, _, _ := syscall.Syscall(procNCryptFreeObject.Addr(), 1, uintptr(hObject), 0, 0)
|
||||
if r0 != 0 {
|
||||
ret = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func nCryptSignHash(hKey nCryptKeyHandle, pPaddingInfo unsafe.Pointer, pbHashValue *byte, cbHashValue uint32, pbSignature *byte, cbSignature uint32, pcbResult *uint32, dwFlags uint32) (ret error) {
|
||||
r0, _, _ := syscall.Syscall9(procNCryptSignHash.Addr(), 8, uintptr(hKey), uintptr(pPaddingInfo), uintptr(unsafe.Pointer(pbHashValue)), uintptr(cbHashValue), uintptr(unsafe.Pointer(pbSignature)), uintptr(cbSignature), uintptr(unsafe.Pointer(pcbResult)), uintptr(dwFlags), 0)
|
||||
if r0 != 0 {
|
||||
ret = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user