diff --git a/certstore/certstore_windows.go b/certstore/certstore_windows.go index 86c0b1c..885b3df 100644 --- a/certstore/certstore_windows.go +++ b/certstore/certstore_windows.go @@ -1,34 +1,6 @@ -package certstore +// +build windows -/* -#cgo windows LDFLAGS: -lcrypt32 -lncrypt - -#include -#include -#include - -char* errMsg(DWORD code) { - char* lpMsgBuf; - DWORD ret = 0; - - ret = FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - code, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, - 0, NULL); - - if (ret == 0) { - return NULL; - } else { - return lpMsgBuf; - } -} -*/ -import "C" +package certstore import ( "crypto" @@ -39,53 +11,62 @@ import ( "fmt" "io" "math/big" - "unicode/utf16" + "reflect" + "syscall" "unsafe" + "golang.org/x/sys/windows" + "github.com/pkg/errors" ) -const ( - winTrue C.WINBOOL = 1 - winFalse C.WINBOOL = 0 - - // ERROR_SUCCESS - ERROR_SUCCESS = 0x00000000 - - // CRYPT_E_NOT_FOUND — Cannot find object or property. - CRYPT_E_NOT_FOUND = 0x80092004 - - // NTE_BAD_ALGID — Invalid algorithm specified. - NTE_BAD_ALGID = 0x80090008 +var ( + ncrypt = windows.MustLoadDLL("ncrypt.dll") + nCryptSignHash = ncrypt.MustFindProc("NCryptSignHash") + nCryptFreeObject = ncrypt.MustFindProc("NCryptFreeObject") + nCryptDeleteKey = ncrypt.MustFindProc("NCryptDeleteKey") ) -// winAPIFlag specifies the flags that should be passed to -// CryptAcquireCertificatePrivateKey. This impacts whether the CryptoAPI or CNG -// API will be used. -// -// Possible values are: -// 0x00000000 — — Only use CryptoAPI. -// 0x00010000 — CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG — Prefer CryptoAPI. -// 0x00020000 — CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG — Prefer CNG. -// 0x00040000 — CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG — Only uyse CNG. -var winAPIFlag C.DWORD = C.CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG +const ( + bcryptPadPkcs1 = 0x00000002 // BCRYPT_PAD_PKCS1 + bcryptPadPss = 0x00000008 // BCRYPT_PAD_PSS +) // winStore is a wrapper around a C.HCERTSTORE. type winStore struct { - store C.HCERTSTORE + store windows.Handle } // openStore opens the current user's personal cert store. -func openStore() (*winStore, error) { - storeName := unsafe.Pointer(stringToUTF16("MY")) - defer C.free(storeName) +func openStore() (Store, error) { + return OpenStoreWindows("MY", StoreLocationCurrentUser) +} + +type StoreLocation int + +const ( + StoreLocationCurrentUser = iota + StoreLocationLocalMachine +) + +func OpenStoreWindows(store string, location StoreLocation) (Store, error) { + storeName, err := windows.UTF16PtrFromString(store) + if err != nil { + return nil, err + } + + var loc uint32 = windows.CERT_SYSTEM_STORE_CURRENT_USER - store := C.CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, 0, C.CERT_SYSTEM_STORE_CURRENT_USER, storeName) - if store == nil { - return nil, lastError("failed to open system cert store") + if location == StoreLocationLocalMachine { + loc = windows.CERT_SYSTEM_STORE_LOCAL_MACHINE } - return &winStore{store}, nil + h, err := windows.CertOpenStore(windows.CERT_STORE_PROV_SYSTEM_W, 0, 0, loc, uintptr(unsafe.Pointer(storeName))) + if err != nil { + return nil, err + } + + return &winStore{h}, nil } // Identities implements the Store interface. @@ -94,47 +75,50 @@ func (s *winStore) Identities() ([]Identity, error) { err error idents = []Identity{} - // CertFindChainInStore parameters - encoding = C.DWORD(C.X509_ASN_ENCODING) - flags = C.DWORD(C.CERT_CHAIN_FIND_BY_ISSUER_CACHE_ONLY_FLAG | C.CERT_CHAIN_FIND_BY_ISSUER_CACHE_ONLY_URL_FLAG) - findType = C.DWORD(C.CERT_CHAIN_FIND_BY_ISSUER) - params = &C.CERT_CHAIN_FIND_BY_ISSUER_PARA{cbSize: C.DWORD(unsafe.Sizeof(C.CERT_CHAIN_FIND_BY_ISSUER_PARA{}))} - paramsPtr = unsafe.Pointer(params) - chainCtx = C.PCCERT_CHAIN_CONTEXT(nil) + 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) ) + var params windows.CertChainFindByIssuerPara + params.Size = uint32(unsafe.Sizeof(params)) + var paramsPtr = unsafe.Pointer(¶ms) + + var chainCtx *windows.CertChainContext for { - if chainCtx = C.CertFindChainInStore(s.store, encoding, flags, findType, paramsPtr, chainCtx); chainCtx == nil { + chainCtx, _ = windows.CertFindChainInStore(s.store, encoding, flags, findType, paramsPtr, chainCtx) + if chainCtx == nil { break } - if chainCtx.cChain < 1 { + + if chainCtx.ChainCount < 1 { err = errors.New("bad chain") goto fail } - // 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.rgpChain - if simpleChain.cElement < 1 || simpleChain.cElement > maxPointerArray { + simpleChain := *chainCtx.Chains + if simpleChain.NumElements < 1 { err = errors.New("bad chain") goto fail } - // Hacky way to get chain elements (c array) as a slice. - chainElts := (*[maxPointerArray]C.PCERT_CHAIN_ELEMENT)(unsafe.Pointer(simpleChain.rgpElement))[:simpleChain.cElement:simpleChain.cElement] + var chainElts []*windows.CertChainElement + slice := (*reflect.SliceHeader)(unsafe.Pointer(&chainElts)) + slice.Data = uintptr(unsafe.Pointer(simpleChain.Elements)) + slice.Len = int(simpleChain.NumElements) + slice.Cap = int(simpleChain.NumElements) + + chain := make([]*windows.CertContext, simpleChain.NumElements) - // Build chain of certificates from each elt's certificate context. - chain := make([]C.PCCERT_CONTEXT, len(chainElts)) for j := range chainElts { - chain[j] = chainElts[j].pCertContext + chain[j] = chainElts[j].CertContext } idents = append(idents, newWinIdentity(chain)) } - if err = checkError("failed to iterate certs in store"); err != nil && errors.Cause(err) != errCode(CRYPT_E_NOT_FOUND) { + if errno, ok := err.(syscall.Errno); ok && errno == syscall.Errno(windows.CRYPT_E_NOT_FOUND) { goto fail } @@ -150,51 +134,46 @@ fail: // Import implements the Store interface. func (s *winStore) Import(data []byte, password string) error { - cdata := C.CBytes(data) - defer C.free(cdata) - - cpw := stringToUTF16(password) - defer C.free(unsafe.Pointer(cpw)) - - pfx := &C.CRYPT_DATA_BLOB{ - cbData: C.DWORD(len(data)), - pbData: (*C.BYTE)(cdata), + cpw, err := windows.UTF16PtrFromString(password) + if err != nil { + return err } - flags := C.CRYPT_USER_KEYSET - - // import into preferred KSP - if winAPIFlag&C.CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG > 0 { - flags |= C.PKCS12_PREFER_CNG_KSP - } else if winAPIFlag&C.CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG > 0 { - flags |= C.PKCS12_ALWAYS_CNG_KSP + pfx := &windows.CryptDataBlob{ + Size: uint32(len(data)), + Data: &data[0], } - store := C.PFXImportCertStore(pfx, cpw, C.DWORD(flags)) - if store == nil { - return lastError("failed to import PFX cert store") + flags := uint32(windows.CRYPT_USER_KEYSET | windows.PKCS12_ALWAYS_CNG_KSP) + + store, err := windows.PFXImportCertStore(pfx, cpw, flags) + if err != nil { + return err } - defer C.CertCloseStore(store, C.CERT_CLOSE_STORE_FORCE_FLAG) + defer windows.CertCloseStore(store, windows.CERT_CLOSE_STORE_FORCE_FLAG) var ( - ctx = C.PCCERT_CONTEXT(nil) - encoding = C.DWORD(C.X509_ASN_ENCODING | C.PKCS_7_ASN_ENCODING) + ctx *windows.CertContext + encoding = uint32(windows.X509_ASN_ENCODING | windows.PKCS_7_ASN_ENCODING) ) for { // iterate through certs in temporary store - if ctx = C.CertFindCertificateInStore(store, encoding, 0, C.CERT_FIND_ANY, nil, ctx); ctx == nil { - if err := checkError("failed to iterate certs in store"); err != nil && errors.Cause(err) != errCode(CRYPT_E_NOT_FOUND) { - return err + ctx, err = windows.CertFindCertificateInStore(store, encoding, 0, windows.CERT_FIND_ANY, nil, ctx) + + if ctx == nil { + if errno, ok := err.(syscall.Errno); ok && errno == syscall.Errno(windows.CRYPT_E_NOT_FOUND) { + break } - break + return err } - // Copy the cert to the system store. - if ok := C.CertAddCertificateContextToStore(s.store, ctx, C.CERT_STORE_ADD_REPLACE_EXISTING, nil); ok == winFalse { - return lastError("failed to add importerd certificate to MY store") + err = windows.CertAddCertificateContextToStore(s.store, ctx, windows.CERT_STORE_ADD_REPLACE_EXISTING, nil) + if err != nil { + return err } + } return nil @@ -202,19 +181,18 @@ func (s *winStore) Import(data []byte, password string) error { // Close implements the Store interface. func (s *winStore) Close() { - C.CertCloseStore(s.store, 0) - s.store = nil + windows.CertCloseStore(s.store, 0) } // winIdentity implements the Identity interface. type winIdentity struct { - chain []C.PCCERT_CONTEXT + chain []*windows.CertContext signer *winPrivateKey } -func newWinIdentity(chain []C.PCCERT_CONTEXT) *winIdentity { +func newWinIdentity(chain []*windows.CertContext) *winIdentity { for _, ctx := range chain { - C.CertDuplicateCertificateContext(ctx) + windows.CertDuplicateCertificateContext(ctx) } return &winIdentity{chain: chain} @@ -270,11 +248,15 @@ func (i *winIdentity) getPrivateKey() (*winPrivateKey, error) { // Delete implements the Identity interface. func (i *winIdentity) Delete() error { // duplicate cert context, since CertDeleteCertificateFromStore will free it. - deleteCtx := C.CertDuplicateCertificateContext(i.chain[0]) - // try deleting cert - if ok := C.CertDeleteCertificateFromStore(deleteCtx); ok == winFalse { - return lastError("failed to delete certificate from store") + deleteCtx := windows.CertDuplicateCertificateContext(i.chain[0]) + if deleteCtx == nil { + return errors.Errorf("cannot duplicate cert") + } + + err := windows.CertDeleteCertificateFromStore(deleteCtx) + if err != nil { + return err } // try deleting private key @@ -298,7 +280,7 @@ func (i *winIdentity) Close() { } for _, ctx := range i.chain { - C.CertFreeCertificateContext(ctx) + windows.CertFreeCertificateContext(ctx) i.chain = nil } } @@ -307,48 +289,49 @@ func (i *winIdentity) Close() { type winPrivateKey struct { publicKey crypto.PublicKey - // CryptoAPI fields - capiProv C.HCRYPTPROV - // CNG fields - cngHandle C.NCRYPT_KEY_HANDLE - keySpec C.DWORD + cngHandle uintptr + keySpec uint32 } // newWinPrivateKey gets a *winPrivateKey for the given certificate. -func newWinPrivateKey(certCtx C.PCCERT_CONTEXT, publicKey crypto.PublicKey) (*winPrivateKey, error) { - var ( - provOrKey C.HCRYPTPROV_OR_NCRYPT_KEY_HANDLE - keySpec C.DWORD - mustFree C.WINBOOL - ) - +func newWinPrivateKey(certCtx *windows.CertContext, publicKey crypto.PublicKey) (*winPrivateKey, error) { if publicKey == nil { return nil, errors.New("nil public key") } - // Get a handle for the found private key. - if ok := C.CryptAcquireCertificatePrivateKey(certCtx, winAPIFlag, nil, &provOrKey, &keySpec, &mustFree); ok == winFalse { - return nil, lastError("failed to get private key for certificate") + var ( + h windows.Handle + keySpec uint32 + mustFree bool + ) + + err := windows.CryptAcquireCertificatePrivateKey( + certCtx, + windows.CRYPT_ACQUIRE_CACHE_FLAG|windows.CRYPT_ACQUIRE_SILENT_FLAG|windows.CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG, + nil, + &h, + &keySpec, + &mustFree, + ) + + if err != nil { + return nil, err } - if mustFree != winTrue { + if mustFree { // This shouldn't happen since we're not asking for cached keys. return nil, errors.New("CryptAcquireCertificatePrivateKey set mustFree") } - if keySpec == C.CERT_NCRYPT_KEY_SPEC { - return &winPrivateKey{ - publicKey: publicKey, - cngHandle: C.NCRYPT_KEY_HANDLE(provOrKey), - }, nil - } else { - return &winPrivateKey{ - publicKey: publicKey, - capiProv: C.HCRYPTPROV(provOrKey), - keySpec: keySpec, - }, nil + if keySpec != windows.CERT_NCRYPT_KEY_SPEC { + return nil, errors.New("cryptAcquireOnlyNcryptKeyFlag returned non cng key spec") } + + return &winPrivateKey{ + publicKey: publicKey, + cngHandle: uintptr(h), + }, nil } // Public implements the crypto.Signer interface. @@ -358,62 +341,112 @@ func (wpk *winPrivateKey) Public() crypto.PublicKey { // Sign implements the crypto.Signer interface. func (wpk *winPrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) { - if wpk.capiProv != 0 { - return wpk.capiSignHash(opts.HashFunc(), digest) - } else if wpk.cngHandle != 0 { - return wpk.cngSignHash(opts.HashFunc(), digest) + if wpk.cngHandle != 0 { + return wpk.cngSignHash(opts, digest) } else { return nil, errors.New("bad private key") } } +type bcryptPkcs1PaddingInfo struct { + pszAlgID *uint16 +} + +type bcryptPssPaddingInfo struct { + pszAlgID *uint16 + cbSalt uint32 +} + // 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") } var ( // input - padPtr = unsafe.Pointer(nil) - digestPtr = (*C.BYTE)(&digest[0]) - digestLen = C.DWORD(len(digest)) - flags = C.DWORD(0) + padPtr = uintptr(unsafe.Pointer(nil)) + digestPtr = uintptr(unsafe.Pointer((&digest[0]))) + digestLen = uintptr(len(digest)) + flags = uintptr(0) // output - sigLen = C.DWORD(0) + sigLen = uint32(0) ) // setup pkcs1v1.5 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) + var pszAlgId *uint16 switch hash { case crypto.SHA1: - padInfo.pszAlgId = BCRYPT_SHA1_ALGORITHM + pszAlgId = windows.StringToUTF16Ptr("SHA1") case crypto.SHA256: - padInfo.pszAlgId = BCRYPT_SHA256_ALGORITHM + pszAlgId = windows.StringToUTF16Ptr("SHA256") case crypto.SHA384: - padInfo.pszAlgId = BCRYPT_SHA384_ALGORITHM + pszAlgId = windows.StringToUTF16Ptr("SHA384") case crypto.SHA512: - padInfo.pszAlgId = BCRYPT_SHA512_ALGORITHM + pszAlgId = windows.StringToUTF16Ptr("SHA512") default: return nil, ErrUnsupportedHash } + + if pssOpts, ok := opts.(*rsa.PSSOptions); ok { + saltLength := pssOpts.SaltLength + switch saltLength { + case rsa.PSSSaltLengthAuto: + // TODO priv property + // saltLength = priv.Size() - 2 - hash.Size() + return nil, ErrUnsupportedHash + case rsa.PSSSaltLengthEqualsHash: + saltLength = hash.Size() + } + + flags = bcryptPadPss + padPtr = uintptr(unsafe.Pointer(&bcryptPssPaddingInfo{ + pszAlgID: pszAlgId, + cbSalt: uint32(saltLength), + })) + + } else { + flags = bcryptPadPkcs1 + padPtr = uintptr(unsafe.Pointer(&bcryptPkcs1PaddingInfo{ + pszAlgID: pszAlgId, + })) + } } - // get signature length - if err := checkStatus(C.NCryptSignHash(wpk.cngHandle, padPtr, digestPtr, digestLen, nil, 0, &sigLen, flags)); err != nil { + r, _, err := nCryptSignHash.Call( + wpk.cngHandle, + padPtr, + digestPtr, + digestLen, + 0, + 0, + uintptr(unsafe.Pointer(&sigLen)), + flags) + + if r != 0 { return nil, errors.Wrap(err, "failed to get signature length") } // get signature sig := make([]byte, sigLen) - sigPtr := (*C.BYTE)(&sig[0]) - if err := checkStatus(C.NCryptSignHash(wpk.cngHandle, padPtr, digestPtr, digestLen, sigPtr, sigLen, &sigLen, flags)); err != nil { - return nil, errors.Wrap(err, "failed to sign digest") + sigPtr := uintptr(unsafe.Pointer(&sig[0])) + + r, _, err = nCryptSignHash.Call( + wpk.cngHandle, + padPtr, + digestPtr, + digestLen, + sigPtr, + uintptr(sigLen), + uintptr(unsafe.Pointer(&sigLen)), + flags) + + if r != 0 { + return nil, fmt.Errorf("NCryptSignHash returned %X during signing: %v", r, err) } // CNG returns a raw ECDSA signature, but we wan't ASN.1 DER encoding. @@ -437,130 +470,16 @@ func (wpk *winPrivateKey) cngSignHash(hash crypto.Hash, digest []byte) ([]byte, return encoded, nil } - return sig, nil -} - -// capiSignHash signs a digest using the CryptoAPI APIs. -func (wpk *winPrivateKey) capiSignHash(hash crypto.Hash, digest []byte) ([]byte, error) { - if len(digest) != hash.Size() { - return nil, errors.New("bad digest for hash") - } - - // Figure out which CryptoAPI hash algorithm we're using. - var hash_alg C.ALG_ID - - switch hash { - case crypto.SHA1: - hash_alg = C.CALG_SHA1 - case crypto.SHA256: - hash_alg = C.CALG_SHA_256 - case crypto.SHA384: - hash_alg = C.CALG_SHA_384 - case crypto.SHA512: - hash_alg = C.CALG_SHA_512 - default: - return nil, ErrUnsupportedHash - } - - // Instantiate a CryptoAPI hash object. - var chash C.HCRYPTHASH - - if ok := C.CryptCreateHash(C.HCRYPTPROV(wpk.capiProv), hash_alg, 0, 0, &chash); ok == winFalse { - if err := lastError("failed to create hash"); errors.Cause(err) == errCode(NTE_BAD_ALGID) { - return nil, ErrUnsupportedHash - } else { - return nil, err - } - } - defer C.CryptDestroyHash(chash) - - // Make sure the hash size matches. - var ( - hashSize C.DWORD - hashSizePtr = (*C.BYTE)(unsafe.Pointer(&hashSize)) - hashSizeLen = C.DWORD(unsafe.Sizeof(hashSize)) - ) - - if ok := C.CryptGetHashParam(chash, C.HP_HASHSIZE, hashSizePtr, &hashSizeLen, 0); ok == winFalse { - return nil, lastError("failed to get hash size") - } - - if hash.Size() != int(hashSize) { - return nil, errors.New("invalid CryptoAPI hash") - } - - // Put our digest into the hash object. - digestPtr := (*C.BYTE)(unsafe.Pointer(&digest[0])) - if ok := C.CryptSetHashParam(chash, C.HP_HASHVAL, digestPtr, 0); ok == winFalse { - return nil, lastError("failed to set hash digest") - } - - // Get signature length. - var sigLen C.DWORD - - if ok := C.CryptSignHash(chash, wpk.keySpec, nil, 0, nil, &sigLen); ok == winFalse { - return nil, lastError("failed to get signature length") - } - - // Get signature - var ( - sig = make([]byte, int(sigLen)) - sigPtr = (*C.BYTE)(unsafe.Pointer(&sig[0])) - ) - - if ok := C.CryptSignHash(chash, wpk.keySpec, nil, 0, sigPtr, &sigLen); ok == winFalse { - return nil, lastError("failed to sign digest") - } - - // 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 + return sig[:sigLen], nil } func (wpk *winPrivateKey) Delete() error { if wpk.cngHandle != 0 { // Delete CNG key - if err := checkStatus(C.NCryptDeleteKey(wpk.cngHandle, 0)); err != nil { + r, _, err := nCryptDeleteKey.Call(wpk.cngHandle, 0) + if r != 0 { return err } - } else if wpk.capiProv != 0 { - // Delete CryptoAPI key - var ( - param unsafe.Pointer - err error - - containerName C.LPCTSTR - providerName C.LPCTSTR - providerType *C.DWORD - ) - - if param, err = wpk.getProviderParam(C.PP_CONTAINER); err != nil { - return errors.Wrap(err, "failed to get PP_CONTAINER") - } else { - containerName = C.LPCTSTR(param) - } - - if param, err = wpk.getProviderParam(C.PP_NAME); err != nil { - return errors.Wrap(err, "failed to get PP_NAME") - } else { - providerName = C.LPCTSTR(param) - } - - if param, err = wpk.getProviderParam(C.PP_PROVTYPE); err != nil { - return errors.Wrap(err, "failed to get PP_PROVTYPE") - } else { - providerType = (*C.DWORD)(param) - } - - // use CRYPT_SILENT too? - var prov C.HCRYPTPROV - if ok := C.CryptAcquireContext(&prov, containerName, providerName, *providerType, C.CRYPT_DELETEKEYSET); ok == winFalse { - return lastError("failed to delete key set") - } } else { return errors.New("bad private key") } @@ -568,115 +487,20 @@ func (wpk *winPrivateKey) Delete() error { return nil } -// getProviderParam gets a parameter about a provider. -func (wpk *winPrivateKey) getProviderParam(param C.DWORD) (unsafe.Pointer, error) { - var dataLen C.DWORD - if ok := C.CryptGetProvParam(wpk.capiProv, param, nil, &dataLen, 0); ok == winFalse { - return nil, lastError("failed to get provider parameter size") - } - - data := make([]byte, dataLen) - dataPtr := (*C.BYTE)(unsafe.Pointer(&data[0])) - if ok := C.CryptGetProvParam(wpk.capiProv, param, dataPtr, &dataLen, 0); ok == winFalse { - return nil, lastError("failed to get provider parameter") - } - - // TODO leaking memory here - return C.CBytes(data), nil -} - // Close closes this winPrivateKey. func (wpk *winPrivateKey) Close() { if wpk.cngHandle != 0 { - C.NCryptFreeObject(C.NCRYPT_HANDLE(wpk.cngHandle)) + nCryptFreeObject.Call(wpk.cngHandle) wpk.cngHandle = 0 } - - if wpk.capiProv != 0 { - C.CryptReleaseContext(wpk.capiProv, 0) - wpk.capiProv = 0 - } -} - -// exportCertCtx exports a PCCERT_CONTEXT as an *x509.Certificate. -func exportCertCtx(ctx C.PCCERT_CONTEXT) (*x509.Certificate, error) { - der := C.GoBytes(unsafe.Pointer(ctx.pbCertEncoded), C.int(ctx.cbCertEncoded)) - - cert, err := x509.ParseCertificate(der) - if err != nil { - return nil, errors.Wrap(err, "certificate parsing failed") - } - - return cert, nil -} - -type errCode uint64 - -// lastError gets the last error from the current thread. If there isn't one, it -// returns a new error. -func lastError(msg string) error { - if err := checkError(msg); err != nil { - return err - } - - return errors.New(msg) -} - -// checkError tries to get the last error from the current thread. If there -// isn't one, it returns nil. -func checkError(msg string) error { - if code := errCode(C.GetLastError()); code != 0 { - return errors.Wrap(code, msg) - } - - return nil -} - -func (c errCode) Error() string { - cmsg := C.errMsg(C.DWORD(c)) - if cmsg == nil { - return fmt.Sprintf("Error %X", int(c)) - } - defer C.LocalFree(C.HLOCAL(cmsg)) - - gomsg := C.GoString(cmsg) - - return fmt.Sprintf("Error: %X %s", int(c), gomsg) -} - -type securityStatus uint64 - -func checkStatus(s C.SECURITY_STATUS) error { - ss := securityStatus(s) - - if ss == ERROR_SUCCESS { - return nil - } - - if ss == NTE_BAD_ALGID { - return ErrUnsupportedHash - } - - return ss -} - -func (ss securityStatus) Error() string { - return fmt.Sprintf("SECURITY_STATUS %d", int(ss)) } -func stringToUTF16(s string) C.LPCWSTR { - // Not sure why this isn't 1 << 30... - const maxUint16Array = 1 << 29 - - if len(s) > maxUint16Array { - panic("string too long") - } - - wstr := utf16.Encode([]rune(s)) - - p := C.calloc(C.size_t(len(wstr)+1), C.size_t(unsafe.Sizeof(uint16(0)))) - pp := (*[maxUint16Array]uint16)(p) - copy(pp[:], wstr) - - return (C.LPCWSTR)(p) +// exportCertCtx exports a windows.CertContext as an *x509.Certificate. +func exportCertCtx(ctx *windows.CertContext) (*x509.Certificate, error) { + var der []byte + slice := (*reflect.SliceHeader)(unsafe.Pointer(&der)) + slice.Data = uintptr(unsafe.Pointer(ctx.EncodedCert)) + slice.Len = int(ctx.Length) + slice.Cap = int(ctx.Length) + return x509.ParseCertificate(der) } diff --git a/certstore/crypt_strings_windows.go b/certstore/crypt_strings_windows.go deleted file mode 100644 index 1e8216f..0000000 --- a/certstore/crypt_strings_windows.go +++ /dev/null @@ -1,207 +0,0 @@ -package certstore - -/* -#include -#include -#include - -// -// Go complains about LPCWSTR constants not being defined, so we define getter -// methods for a bunch of constants we might want. -// - -// Store name -LPCSTR GET_CERT_STORE_PROV_SYSTEM_W() { return CERT_STORE_PROV_SYSTEM_W; } - -// NCRYPT Object Property Names -LPCWSTR GET_NCRYPT_ALGORITHM_GROUP_PROPERTY() { return NCRYPT_ALGORITHM_GROUP_PROPERTY; } -LPCWSTR GET_NCRYPT_ALGORITHM_PROPERTY() { return NCRYPT_ALGORITHM_PROPERTY; } -LPCWSTR GET_NCRYPT_BLOCK_LENGTH_PROPERTY() { return NCRYPT_BLOCK_LENGTH_PROPERTY; } -LPCWSTR GET_NCRYPT_CERTIFICATE_PROPERTY() { return NCRYPT_CERTIFICATE_PROPERTY; } -LPCWSTR GET_NCRYPT_DH_PARAMETERS_PROPERTY() { return NCRYPT_DH_PARAMETERS_PROPERTY; } -LPCWSTR GET_NCRYPT_EXPORT_POLICY_PROPERTY() { return NCRYPT_EXPORT_POLICY_PROPERTY; } -LPCWSTR GET_NCRYPT_IMPL_TYPE_PROPERTY() { return NCRYPT_IMPL_TYPE_PROPERTY; } -LPCWSTR GET_NCRYPT_KEY_TYPE_PROPERTY() { return NCRYPT_KEY_TYPE_PROPERTY; } -LPCWSTR GET_NCRYPT_KEY_USAGE_PROPERTY() { return NCRYPT_KEY_USAGE_PROPERTY; } -LPCWSTR GET_NCRYPT_LAST_MODIFIED_PROPERTY() { return NCRYPT_LAST_MODIFIED_PROPERTY; } -LPCWSTR GET_NCRYPT_LENGTH_PROPERTY() { return NCRYPT_LENGTH_PROPERTY; } -LPCWSTR GET_NCRYPT_LENGTHS_PROPERTY() { return NCRYPT_LENGTHS_PROPERTY; } -LPCWSTR GET_NCRYPT_MAX_NAME_LENGTH_PROPERTY() { return NCRYPT_MAX_NAME_LENGTH_PROPERTY; } -LPCWSTR GET_NCRYPT_NAME_PROPERTY() { return NCRYPT_NAME_PROPERTY; } -LPCWSTR GET_NCRYPT_PIN_PROMPT_PROPERTY() { return NCRYPT_PIN_PROMPT_PROPERTY; } -LPCWSTR GET_NCRYPT_PIN_PROPERTY() { return NCRYPT_PIN_PROPERTY; } -LPCWSTR GET_NCRYPT_PROVIDER_HANDLE_PROPERTY() { return NCRYPT_PROVIDER_HANDLE_PROPERTY; } -LPCWSTR GET_NCRYPT_READER_PROPERTY() { return NCRYPT_READER_PROPERTY; } -LPCWSTR GET_NCRYPT_ROOT_CERTSTORE_PROPERTY() { return NCRYPT_ROOT_CERTSTORE_PROPERTY; } -LPCWSTR GET_NCRYPT_SECURE_PIN_PROPERTY() { return NCRYPT_SECURE_PIN_PROPERTY; } -LPCWSTR GET_NCRYPT_SECURITY_DESCR_PROPERTY() { return NCRYPT_SECURITY_DESCR_PROPERTY; } -LPCWSTR GET_NCRYPT_SECURITY_DESCR_SUPPORT_PROPERTY() { return NCRYPT_SECURITY_DESCR_SUPPORT_PROPERTY; } -LPCWSTR GET_NCRYPT_SMARTCARD_GUID_PROPERTY() { return NCRYPT_SMARTCARD_GUID_PROPERTY; } -LPCWSTR GET_NCRYPT_UI_POLICY_PROPERTY() { return NCRYPT_UI_POLICY_PROPERTY; } -LPCWSTR GET_NCRYPT_UNIQUE_NAME_PROPERTY() { return NCRYPT_UNIQUE_NAME_PROPERTY; } -LPCWSTR GET_NCRYPT_USE_CONTEXT_PROPERTY() { return NCRYPT_USE_CONTEXT_PROPERTY; } -LPCWSTR GET_NCRYPT_USE_COUNT_ENABLED_PROPERTY() { return NCRYPT_USE_COUNT_ENABLED_PROPERTY; } -LPCWSTR GET_NCRYPT_USE_COUNT_PROPERTY() { return NCRYPT_USE_COUNT_PROPERTY; } -LPCWSTR GET_NCRYPT_USER_CERTSTORE_PROPERTY() { return NCRYPT_USER_CERTSTORE_PROPERTY; } -LPCWSTR GET_NCRYPT_VERSION_PROPERTY() { return NCRYPT_VERSION_PROPERTY; } -LPCWSTR GET_NCRYPT_WINDOW_HANDLE_PROPERTY() { return NCRYPT_WINDOW_HANDLE_PROPERTY; } - -// BCRYPT BLOB Types -LPCWSTR GET_BCRYPT_DH_PRIVATE_BLOB() { return BCRYPT_DH_PRIVATE_BLOB; } -LPCWSTR GET_BCRYPT_DH_PUBLIC_BLOB() { return BCRYPT_DH_PUBLIC_BLOB; } -LPCWSTR GET_BCRYPT_DSA_PRIVATE_BLOB() { return BCRYPT_DSA_PRIVATE_BLOB; } -LPCWSTR GET_BCRYPT_DSA_PUBLIC_BLOB() { return BCRYPT_DSA_PUBLIC_BLOB; } -LPCWSTR GET_BCRYPT_ECCPRIVATE_BLOB() { return BCRYPT_ECCPRIVATE_BLOB; } -LPCWSTR GET_BCRYPT_ECCPUBLIC_BLOB() { return BCRYPT_ECCPUBLIC_BLOB; } -LPCWSTR GET_BCRYPT_PUBLIC_KEY_BLOB() { return BCRYPT_PUBLIC_KEY_BLOB; } -LPCWSTR GET_BCRYPT_PRIVATE_KEY_BLOB() { return BCRYPT_PRIVATE_KEY_BLOB; } -LPCWSTR GET_BCRYPT_RSAFULLPRIVATE_BLOB() { return BCRYPT_RSAFULLPRIVATE_BLOB; } -LPCWSTR GET_BCRYPT_RSAPRIVATE_BLOB() { return BCRYPT_RSAPRIVATE_BLOB; } -LPCWSTR GET_BCRYPT_RSAPUBLIC_BLOB() { return BCRYPT_RSAPUBLIC_BLOB; } - -// BCRYPT Algorithm Names -LPCWSTR GET_BCRYPT_3DES_ALGORITHM() { return BCRYPT_3DES_ALGORITHM; } -LPCWSTR GET_BCRYPT_3DES_112_ALGORITHM() { return BCRYPT_3DES_112_ALGORITHM; } -LPCWSTR GET_BCRYPT_AES_ALGORITHM() { return BCRYPT_AES_ALGORITHM; } -LPCWSTR GET_BCRYPT_AES_CMAC_ALGORITHM() { return BCRYPT_AES_CMAC_ALGORITHM; } -LPCWSTR GET_BCRYPT_AES_GMAC_ALGORITHM() { return BCRYPT_AES_GMAC_ALGORITHM; } -LPCWSTR GET_BCRYPT_CAPI_KDF_ALGORITHM() { return BCRYPT_CAPI_KDF_ALGORITHM; } -LPCWSTR GET_BCRYPT_DES_ALGORITHM() { return BCRYPT_DES_ALGORITHM; } -LPCWSTR GET_BCRYPT_DESX_ALGORITHM() { return BCRYPT_DESX_ALGORITHM; } -LPCWSTR GET_BCRYPT_DH_ALGORITHM() { return BCRYPT_DH_ALGORITHM; } -LPCWSTR GET_BCRYPT_DSA_ALGORITHM() { return BCRYPT_DSA_ALGORITHM; } -LPCWSTR GET_BCRYPT_ECDH_P256_ALGORITHM() { return BCRYPT_ECDH_P256_ALGORITHM; } -LPCWSTR GET_BCRYPT_ECDH_P384_ALGORITHM() { return BCRYPT_ECDH_P384_ALGORITHM; } -LPCWSTR GET_BCRYPT_ECDH_P521_ALGORITHM() { return BCRYPT_ECDH_P521_ALGORITHM; } -LPCWSTR GET_BCRYPT_ECDSA_P256_ALGORITHM() { return BCRYPT_ECDSA_P256_ALGORITHM; } -LPCWSTR GET_BCRYPT_ECDSA_P384_ALGORITHM() { return BCRYPT_ECDSA_P384_ALGORITHM; } -LPCWSTR GET_BCRYPT_ECDSA_P521_ALGORITHM() { return BCRYPT_ECDSA_P521_ALGORITHM; } -LPCWSTR GET_BCRYPT_MD2_ALGORITHM() { return BCRYPT_MD2_ALGORITHM; } -LPCWSTR GET_BCRYPT_MD4_ALGORITHM() { return BCRYPT_MD4_ALGORITHM; } -LPCWSTR GET_BCRYPT_MD5_ALGORITHM() { return BCRYPT_MD5_ALGORITHM; } -LPCWSTR GET_BCRYPT_RC2_ALGORITHM() { return BCRYPT_RC2_ALGORITHM; } -LPCWSTR GET_BCRYPT_RC4_ALGORITHM() { return BCRYPT_RC4_ALGORITHM; } -LPCWSTR GET_BCRYPT_RNG_ALGORITHM() { return BCRYPT_RNG_ALGORITHM; } -LPCWSTR GET_BCRYPT_RNG_DUAL_EC_ALGORITHM() { return BCRYPT_RNG_DUAL_EC_ALGORITHM; } -LPCWSTR GET_BCRYPT_RNG_FIPS186_DSA_ALGORITHM() { return BCRYPT_RNG_FIPS186_DSA_ALGORITHM; } -LPCWSTR GET_BCRYPT_RSA_ALGORITHM() { return BCRYPT_RSA_ALGORITHM; } -LPCWSTR GET_BCRYPT_RSA_SIGN_ALGORITHM() { return BCRYPT_RSA_SIGN_ALGORITHM; } -LPCWSTR GET_BCRYPT_SHA1_ALGORITHM() { return BCRYPT_SHA1_ALGORITHM; } -LPCWSTR GET_BCRYPT_SHA256_ALGORITHM() { return BCRYPT_SHA256_ALGORITHM; } -LPCWSTR GET_BCRYPT_SHA384_ALGORITHM() { return BCRYPT_SHA384_ALGORITHM; } -LPCWSTR GET_BCRYPT_SHA512_ALGORITHM() { return BCRYPT_SHA512_ALGORITHM; } -LPCWSTR GET_BCRYPT_SP800108_CTR_HMAC_ALGORITHM() { return BCRYPT_SP800108_CTR_HMAC_ALGORITHM; } -LPCWSTR GET_BCRYPT_SP80056A_CONCAT_ALGORITHM() { return BCRYPT_SP80056A_CONCAT_ALGORITHM; } -LPCWSTR GET_BCRYPT_PBKDF2_ALGORITHM() { return BCRYPT_PBKDF2_ALGORITHM; } - -// -// These may be missing from bcrypt.h if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) -// Not sure what that really means... -// - -#ifndef BCRYPT_ECDSA_ALGORITHM -#define BCRYPT_ECDSA_ALGORITHM L"ECDSA" -#endif - -#ifndef BCRYPT_ECDH_ALGORITHM -#define BCRYPT_ECDH_ALGORITHM L"ECDH" -#endif - -#ifndef BCRYPT_XTS_AES_ALGORITHM -#define BCRYPT_XTS_AES_ALGORITHM L"XTS-AES" -#endif - -LPCWSTR GET_BCRYPT_ECDSA_ALGORITHM() { return BCRYPT_ECDSA_ALGORITHM; } -LPCWSTR GET_BCRYPT_ECDH_ALGORITHM() { return BCRYPT_ECDH_ALGORITHM; } -LPCWSTR GET_BCRYPT_XTS_AES_ALGORITHM() { return BCRYPT_XTS_AES_ALGORITHM; } -*/ -import "C" - -var ( - // Store name - CERT_STORE_PROV_SYSTEM_W = C.GET_CERT_STORE_PROV_SYSTEM_W() - - // NCRYPT Object Property Names - NCRYPT_ALGORITHM_GROUP_PROPERTY = C.GET_NCRYPT_ALGORITHM_GROUP_PROPERTY() - NCRYPT_ALGORITHM_PROPERTY = C.GET_NCRYPT_ALGORITHM_PROPERTY() - NCRYPT_BLOCK_LENGTH_PROPERTY = C.GET_NCRYPT_BLOCK_LENGTH_PROPERTY() - NCRYPT_CERTIFICATE_PROPERTY = C.GET_NCRYPT_CERTIFICATE_PROPERTY() - NCRYPT_DH_PARAMETERS_PROPERTY = C.GET_NCRYPT_DH_PARAMETERS_PROPERTY() - NCRYPT_EXPORT_POLICY_PROPERTY = C.GET_NCRYPT_EXPORT_POLICY_PROPERTY() - NCRYPT_IMPL_TYPE_PROPERTY = C.GET_NCRYPT_IMPL_TYPE_PROPERTY() - NCRYPT_KEY_TYPE_PROPERTY = C.GET_NCRYPT_KEY_TYPE_PROPERTY() - NCRYPT_KEY_USAGE_PROPERTY = C.GET_NCRYPT_KEY_USAGE_PROPERTY() - NCRYPT_LAST_MODIFIED_PROPERTY = C.GET_NCRYPT_LAST_MODIFIED_PROPERTY() - NCRYPT_LENGTH_PROPERTY = C.GET_NCRYPT_LENGTH_PROPERTY() - NCRYPT_LENGTHS_PROPERTY = C.GET_NCRYPT_LENGTHS_PROPERTY() - NCRYPT_MAX_NAME_LENGTH_PROPERTY = C.GET_NCRYPT_MAX_NAME_LENGTH_PROPERTY() - NCRYPT_NAME_PROPERTY = C.GET_NCRYPT_NAME_PROPERTY() - NCRYPT_PIN_PROMPT_PROPERTY = C.GET_NCRYPT_PIN_PROMPT_PROPERTY() - NCRYPT_PIN_PROPERTY = C.GET_NCRYPT_PIN_PROPERTY() - NCRYPT_PROVIDER_HANDLE_PROPERTY = C.GET_NCRYPT_PROVIDER_HANDLE_PROPERTY() - NCRYPT_READER_PROPERTY = C.GET_NCRYPT_READER_PROPERTY() - NCRYPT_ROOT_CERTSTORE_PROPERTY = C.GET_NCRYPT_ROOT_CERTSTORE_PROPERTY() - NCRYPT_SECURE_PIN_PROPERTY = C.GET_NCRYPT_SECURE_PIN_PROPERTY() - NCRYPT_SECURITY_DESCR_PROPERTY = C.GET_NCRYPT_SECURITY_DESCR_PROPERTY() - NCRYPT_SECURITY_DESCR_SUPPORT_PROPERTY = C.GET_NCRYPT_SECURITY_DESCR_SUPPORT_PROPERTY() - NCRYPT_SMARTCARD_GUID_PROPERTY = C.GET_NCRYPT_SMARTCARD_GUID_PROPERTY() - NCRYPT_UI_POLICY_PROPERTY = C.GET_NCRYPT_UI_POLICY_PROPERTY() - NCRYPT_UNIQUE_NAME_PROPERTY = C.GET_NCRYPT_UNIQUE_NAME_PROPERTY() - NCRYPT_USE_CONTEXT_PROPERTY = C.GET_NCRYPT_USE_CONTEXT_PROPERTY() - NCRYPT_USE_COUNT_ENABLED_PROPERTY = C.GET_NCRYPT_USE_COUNT_ENABLED_PROPERTY() - NCRYPT_USE_COUNT_PROPERTY = C.GET_NCRYPT_USE_COUNT_PROPERTY() - NCRYPT_USER_CERTSTORE_PROPERTY = C.GET_NCRYPT_USER_CERTSTORE_PROPERTY() - NCRYPT_VERSION_PROPERTY = C.GET_NCRYPT_VERSION_PROPERTY() - NCRYPT_WINDOW_HANDLE_PROPERTY = C.GET_NCRYPT_WINDOW_HANDLE_PROPERTY() - - // BCRYPT BLOB Types - BCRYPT_DH_PRIVATE_BLOB = C.GET_BCRYPT_DH_PRIVATE_BLOB() - BCRYPT_DH_PUBLIC_BLOB = C.GET_BCRYPT_DH_PUBLIC_BLOB() - BCRYPT_DSA_PRIVATE_BLOB = C.GET_BCRYPT_DSA_PRIVATE_BLOB() - BCRYPT_DSA_PUBLIC_BLOB = C.GET_BCRYPT_DSA_PUBLIC_BLOB() - BCRYPT_ECCPRIVATE_BLOB = C.GET_BCRYPT_ECCPRIVATE_BLOB() - BCRYPT_ECCPUBLIC_BLOB = C.GET_BCRYPT_ECCPUBLIC_BLOB() - BCRYPT_PUBLIC_KEY_BLOB = C.GET_BCRYPT_PUBLIC_KEY_BLOB() - BCRYPT_PRIVATE_KEY_BLOB = C.GET_BCRYPT_PRIVATE_KEY_BLOB() - BCRYPT_RSAFULLPRIVATE_BLOB = C.GET_BCRYPT_RSAFULLPRIVATE_BLOB() - BCRYPT_RSAPRIVATE_BLOB = C.GET_BCRYPT_RSAPRIVATE_BLOB() - BCRYPT_RSAPUBLIC_BLOB = C.GET_BCRYPT_RSAPUBLIC_BLOB() - - // BCRYPT Algorithm Names - BCRYPT_3DES_ALGORITHM = C.GET_BCRYPT_3DES_ALGORITHM() - BCRYPT_3DES_112_ALGORITHM = C.GET_BCRYPT_3DES_112_ALGORITHM() - BCRYPT_AES_ALGORITHM = C.GET_BCRYPT_AES_ALGORITHM() - BCRYPT_AES_CMAC_ALGORITHM = C.GET_BCRYPT_AES_CMAC_ALGORITHM() - BCRYPT_AES_GMAC_ALGORITHM = C.GET_BCRYPT_AES_GMAC_ALGORITHM() - BCRYPT_CAPI_KDF_ALGORITHM = C.GET_BCRYPT_CAPI_KDF_ALGORITHM() - BCRYPT_DES_ALGORITHM = C.GET_BCRYPT_DES_ALGORITHM() - BCRYPT_DESX_ALGORITHM = C.GET_BCRYPT_DESX_ALGORITHM() - BCRYPT_DH_ALGORITHM = C.GET_BCRYPT_DH_ALGORITHM() - BCRYPT_DSA_ALGORITHM = C.GET_BCRYPT_DSA_ALGORITHM() - BCRYPT_ECDH_P256_ALGORITHM = C.GET_BCRYPT_ECDH_P256_ALGORITHM() - BCRYPT_ECDH_P384_ALGORITHM = C.GET_BCRYPT_ECDH_P384_ALGORITHM() - BCRYPT_ECDH_P521_ALGORITHM = C.GET_BCRYPT_ECDH_P521_ALGORITHM() - BCRYPT_ECDSA_P256_ALGORITHM = C.GET_BCRYPT_ECDSA_P256_ALGORITHM() - BCRYPT_ECDSA_P384_ALGORITHM = C.GET_BCRYPT_ECDSA_P384_ALGORITHM() - BCRYPT_ECDSA_P521_ALGORITHM = C.GET_BCRYPT_ECDSA_P521_ALGORITHM() - BCRYPT_MD2_ALGORITHM = C.GET_BCRYPT_MD2_ALGORITHM() - BCRYPT_MD4_ALGORITHM = C.GET_BCRYPT_MD4_ALGORITHM() - BCRYPT_MD5_ALGORITHM = C.GET_BCRYPT_MD5_ALGORITHM() - BCRYPT_RC2_ALGORITHM = C.GET_BCRYPT_RC2_ALGORITHM() - BCRYPT_RC4_ALGORITHM = C.GET_BCRYPT_RC4_ALGORITHM() - BCRYPT_RNG_ALGORITHM = C.GET_BCRYPT_RNG_ALGORITHM() - BCRYPT_RNG_DUAL_EC_ALGORITHM = C.GET_BCRYPT_RNG_DUAL_EC_ALGORITHM() - BCRYPT_RNG_FIPS186_DSA_ALGORITHM = C.GET_BCRYPT_RNG_FIPS186_DSA_ALGORITHM() - BCRYPT_RSA_ALGORITHM = C.GET_BCRYPT_RSA_ALGORITHM() - BCRYPT_RSA_SIGN_ALGORITHM = C.GET_BCRYPT_RSA_SIGN_ALGORITHM() - BCRYPT_SHA1_ALGORITHM = C.GET_BCRYPT_SHA1_ALGORITHM() - BCRYPT_SHA256_ALGORITHM = C.GET_BCRYPT_SHA256_ALGORITHM() - BCRYPT_SHA384_ALGORITHM = C.GET_BCRYPT_SHA384_ALGORITHM() - BCRYPT_SHA512_ALGORITHM = C.GET_BCRYPT_SHA512_ALGORITHM() - BCRYPT_SP800108_CTR_HMAC_ALGORITHM = C.GET_BCRYPT_SP800108_CTR_HMAC_ALGORITHM() - BCRYPT_SP80056A_CONCAT_ALGORITHM = C.GET_BCRYPT_SP80056A_CONCAT_ALGORITHM() - BCRYPT_PBKDF2_ALGORITHM = C.GET_BCRYPT_PBKDF2_ALGORITHM() - BCRYPT_ECDSA_ALGORITHM = C.GET_BCRYPT_ECDSA_ALGORITHM() - BCRYPT_ECDH_ALGORITHM = C.GET_BCRYPT_ECDH_ALGORITHM() - BCRYPT_XTS_AES_ALGORITHM = C.GET_BCRYPT_XTS_AES_ALGORITHM() -) diff --git a/certstore/main_windows_test.go b/certstore/main_windows_test.go deleted file mode 100644 index 94a2cd7..0000000 --- a/certstore/main_windows_test.go +++ /dev/null @@ -1,25 +0,0 @@ -package certstore - -import ( - "fmt" - "os" - "testing" -) - -func TestMain(m *testing.M) { - // Prefer CryptoAPI - fmt.Println("CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG") - winAPIFlag = 0x00010000 - if status := m.Run(); status != 0 { - os.Exit(status) - } - - // Prefer CNG - fmt.Println("CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG") - winAPIFlag = 0x00020000 - if status := m.Run(); status != 0 { - os.Exit(status) - } - - os.Exit(0) -} diff --git a/go.mod b/go.mod index ba48589..738e146 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/github/smimesign -go 1.12 +go 1.17 require ( github.com/certifi/gocertifi v0.0.0-20180118203423-deb3ae2ef261 @@ -9,5 +9,8 @@ require ( github.com/pkg/errors v0.8.1 github.com/stretchr/testify v1.3.0 golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734 + golang.org/x/sys v0.0.0-20210219172841-57ea560cfca1 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 ) + +require github.com/pmezard/go-difflib v1.0.0 // indirect diff --git a/go.sum b/go.sum index 0ce1304..4a22fb8 100644 --- a/go.sum +++ b/go.sum @@ -18,6 +18,8 @@ golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8U golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210219172841-57ea560cfca1 h1:mDSj8NPponP6fRpRDblAGl5bpSHjPulHtk5lGl0gLSY= +golang.org/x/sys v0.0.0-20210219172841-57ea560cfca1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=