windows: add CertFindCertificateInStore, CertFindChainInStore and CryptAcquireCertificatePrivateKey

add cert loading related syscall
CertFindCertificateInStore [1]
CertFindChainInStore [2]
CryptAcquireCertificatePrivateKey [3]

[1] https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certfindcertificateinstore
[2] https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certfindchaininstore
[3] https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptacquirecertificateprivatekey

Change-Id: I179bffd06d714d729f3afd83687336edecae6b37
GitHub-Last-Rev: 58a8c666c8
GitHub-Pull-Request: golang/sys#94
Reviewed-on: https://go-review.googlesource.com/c/sys/+/281012
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Jason A. Donenfeld <Jason@zx2c4.com>
Trust: Jason A. Donenfeld <Jason@zx2c4.com>
Trust: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Boshi LIAN
2021-02-12 18:49:36 +00:00
committed by Jason A. Donenfeld
parent 8ebf48af03
commit 3351caf150
3 changed files with 161 additions and 0 deletions

View File

@@ -283,6 +283,9 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys CertVerifyCertificateChainPolicy(policyOID uintptr, chain *CertChainContext, para *CertChainPolicyPara, status *CertChainPolicyStatus) (err error) = crypt32.CertVerifyCertificateChainPolicy
//sys CertGetNameString(certContext *CertContext, nameType uint32, flags uint32, typePara unsafe.Pointer, name *uint16, size uint32) (chars uint32) = crypt32.CertGetNameStringW
//sys CertFindExtension(objId *byte, countExtensions uint32, extensions *CertExtension) (ret *CertExtension) = crypt32.CertFindExtension
//sys CertFindCertificateInStore(store Handle, certEncodingType uint32, findFlags uint32, findType uint32, findPara unsafe.Pointer, prevCertContext *CertContext) (cert *CertContext, err error) [failretval==nil] = crypt32.CertFindCertificateInStore
//sys CertFindChainInStore(store Handle, certEncodingType uint32, findFlags uint32, findType uint32, findPara unsafe.Pointer, prevChainContext *CertChainContext) (certchain *CertChainContext, err error) [failretval==nil] = crypt32.CertFindChainInStore
//sys CryptAcquireCertificatePrivateKey(cert *CertContext, flags uint32, parameters unsafe.Pointer, cryptProvOrNCryptKey *Handle, keySpec *uint32, callerFreeProvOrNCryptKey *bool) (err error) = crypt32.CryptAcquireCertificatePrivateKey
//sys CryptQueryObject(objectType uint32, object unsafe.Pointer, expectedContentTypeFlags uint32, expectedFormatTypeFlags uint32, flags uint32, msgAndCertEncodingType *uint32, contentType *uint32, formatType *uint32, certStore *Handle, msg *Handle, context *unsafe.Pointer) (err error) = crypt32.CryptQueryObject
//sys CryptDecodeObject(encodingType uint32, structType *byte, encodedBytes *byte, lenEncodedBytes uint32, flags uint32, decoded unsafe.Pointer, decodedLen *uint32) (err error) = crypt32.CryptDecodeObject
//sys CryptProtectData(dataIn *DataBlob, name *uint16, optionalEntropy *DataBlob, reserved uintptr, promptStruct *CryptProtectPromptStruct, flags uint32, dataOut *DataBlob) (err error) = crypt32.CryptProtectData

View File

@@ -287,6 +287,23 @@ const (
PKCS12_NO_PERSIST_KEY = 0x00008000
PKCS12_INCLUDE_EXTENDED_PROPERTIES = 0x00000010
/* Flags for CryptAcquireCertificatePrivateKey */
CRYPT_ACQUIRE_CACHE_FLAG = 0x00000001
CRYPT_ACQUIRE_USE_PROV_INFO_FLAG = 0x00000002
CRYPT_ACQUIRE_COMPARE_KEY_FLAG = 0x00000004
CRYPT_ACQUIRE_NO_HEALING = 0x00000008
CRYPT_ACQUIRE_SILENT_FLAG = 0x00000040
CRYPT_ACQUIRE_WINDOW_HANDLE_FLAG = 0x00000080
CRYPT_ACQUIRE_NCRYPT_KEY_FLAGS_MASK = 0x00070000
CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG = 0x00010000
CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG = 0x00020000
CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG = 0x00040000
/* pdwKeySpec for CryptAcquireCertificatePrivateKey */
AT_KEYEXCHANGE = 1
AT_SIGNATURE = 2
CERT_NCRYPT_KEY_SPEC = 0xFFFFFFFF
/* Default usage match type is AND with value zero */
USAGE_MATCH_TYPE_AND = 0
USAGE_MATCH_TYPE_OR = 1
@@ -412,6 +429,89 @@ const (
CERT_TRUST_IS_CA_TRUSTED = 0x00004000
CERT_TRUST_IS_COMPLEX_CHAIN = 0x00010000
/* Certificate Information Flags */
CERT_INFO_VERSION_FLAG = 1
CERT_INFO_SERIAL_NUMBER_FLAG = 2
CERT_INFO_SIGNATURE_ALGORITHM_FLAG = 3
CERT_INFO_ISSUER_FLAG = 4
CERT_INFO_NOT_BEFORE_FLAG = 5
CERT_INFO_NOT_AFTER_FLAG = 6
CERT_INFO_SUBJECT_FLAG = 7
CERT_INFO_SUBJECT_PUBLIC_KEY_INFO_FLAG = 8
CERT_INFO_ISSUER_UNIQUE_ID_FLAG = 9
CERT_INFO_SUBJECT_UNIQUE_ID_FLAG = 10
CERT_INFO_EXTENSION_FLAG = 11
/* dwFindType for CertFindCertificateInStore */
CERT_COMPARE_MASK = 0xFFFF
CERT_COMPARE_SHIFT = 16
CERT_COMPARE_ANY = 0
CERT_COMPARE_SHA1_HASH = 1
CERT_COMPARE_NAME = 2
CERT_COMPARE_ATTR = 3
CERT_COMPARE_MD5_HASH = 4
CERT_COMPARE_PROPERTY = 5
CERT_COMPARE_PUBLIC_KEY = 6
CERT_COMPARE_HASH = CERT_COMPARE_SHA1_HASH
CERT_COMPARE_NAME_STR_A = 7
CERT_COMPARE_NAME_STR_W = 8
CERT_COMPARE_KEY_SPEC = 9
CERT_COMPARE_ENHKEY_USAGE = 10
CERT_COMPARE_CTL_USAGE = CERT_COMPARE_ENHKEY_USAGE
CERT_COMPARE_SUBJECT_CERT = 11
CERT_COMPARE_ISSUER_OF = 12
CERT_COMPARE_EXISTING = 13
CERT_COMPARE_SIGNATURE_HASH = 14
CERT_COMPARE_KEY_IDENTIFIER = 15
CERT_COMPARE_CERT_ID = 16
CERT_COMPARE_CROSS_CERT_DIST_POINTS = 17
CERT_COMPARE_PUBKEY_MD5_HASH = 18
CERT_COMPARE_SUBJECT_INFO_ACCESS = 19
CERT_COMPARE_HASH_STR = 20
CERT_COMPARE_HAS_PRIVATE_KEY = 21
CERT_FIND_ANY = (CERT_COMPARE_ANY << CERT_COMPARE_SHIFT)
CERT_FIND_SHA1_HASH = (CERT_COMPARE_SHA1_HASH << CERT_COMPARE_SHIFT)
CERT_FIND_MD5_HASH = (CERT_COMPARE_MD5_HASH << CERT_COMPARE_SHIFT)
CERT_FIND_SIGNATURE_HASH = (CERT_COMPARE_SIGNATURE_HASH << CERT_COMPARE_SHIFT)
CERT_FIND_KEY_IDENTIFIER = (CERT_COMPARE_KEY_IDENTIFIER << CERT_COMPARE_SHIFT)
CERT_FIND_HASH = CERT_FIND_SHA1_HASH
CERT_FIND_PROPERTY = (CERT_COMPARE_PROPERTY << CERT_COMPARE_SHIFT)
CERT_FIND_PUBLIC_KEY = (CERT_COMPARE_PUBLIC_KEY << CERT_COMPARE_SHIFT)
CERT_FIND_SUBJECT_NAME = (CERT_COMPARE_NAME<<CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG)
CERT_FIND_SUBJECT_ATTR = (CERT_COMPARE_ATTR<<CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG)
CERT_FIND_ISSUER_NAME = (CERT_COMPARE_NAME<<CERT_COMPARE_SHIFT | CERT_INFO_ISSUER_FLAG)
CERT_FIND_ISSUER_ATTR = (CERT_COMPARE_ATTR<<CERT_COMPARE_SHIFT | CERT_INFO_ISSUER_FLAG)
CERT_FIND_SUBJECT_STR_A = (CERT_COMPARE_NAME_STR_A<<CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG)
CERT_FIND_SUBJECT_STR_W = (CERT_COMPARE_NAME_STR_W<<CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG)
CERT_FIND_SUBJECT_STR = CERT_FIND_SUBJECT_STR_W
CERT_FIND_ISSUER_STR_A = (CERT_COMPARE_NAME_STR_A<<CERT_COMPARE_SHIFT | CERT_INFO_ISSUER_FLAG)
CERT_FIND_ISSUER_STR_W = (CERT_COMPARE_NAME_STR_W<<CERT_COMPARE_SHIFT | CERT_INFO_ISSUER_FLAG)
CERT_FIND_ISSUER_STR = CERT_FIND_ISSUER_STR_W
CERT_FIND_KEY_SPEC = (CERT_COMPARE_KEY_SPEC << CERT_COMPARE_SHIFT)
CERT_FIND_ENHKEY_USAGE = (CERT_COMPARE_ENHKEY_USAGE << CERT_COMPARE_SHIFT)
CERT_FIND_CTL_USAGE = CERT_FIND_ENHKEY_USAGE
CERT_FIND_SUBJECT_CERT = (CERT_COMPARE_SUBJECT_CERT << CERT_COMPARE_SHIFT)
CERT_FIND_ISSUER_OF = (CERT_COMPARE_ISSUER_OF << CERT_COMPARE_SHIFT)
CERT_FIND_EXISTING = (CERT_COMPARE_EXISTING << CERT_COMPARE_SHIFT)
CERT_FIND_CERT_ID = (CERT_COMPARE_CERT_ID << CERT_COMPARE_SHIFT)
CERT_FIND_CROSS_CERT_DIST_POINTS = (CERT_COMPARE_CROSS_CERT_DIST_POINTS << CERT_COMPARE_SHIFT)
CERT_FIND_PUBKEY_MD5_HASH = (CERT_COMPARE_PUBKEY_MD5_HASH << CERT_COMPARE_SHIFT)
CERT_FIND_SUBJECT_INFO_ACCESS = (CERT_COMPARE_SUBJECT_INFO_ACCESS << CERT_COMPARE_SHIFT)
CERT_FIND_HASH_STR = (CERT_COMPARE_HASH_STR << CERT_COMPARE_SHIFT)
CERT_FIND_HAS_PRIVATE_KEY = (CERT_COMPARE_HAS_PRIVATE_KEY << CERT_COMPARE_SHIFT)
CERT_FIND_OPTIONAL_ENHKEY_USAGE_FLAG = 0x1
CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG = 0x2
CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG = 0x4
CERT_FIND_NO_ENHKEY_USAGE_FLAG = 0x8
CERT_FIND_OR_ENHKEY_USAGE_FLAG = 0x10
CERT_FIND_VALID_ENHKEY_USAGE_FLAG = 0x20
CERT_FIND_OPTIONAL_CTL_USAGE_FLAG = CERT_FIND_OPTIONAL_ENHKEY_USAGE_FLAG
CERT_FIND_EXT_ONLY_CTL_USAGE_FLAG = CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
CERT_FIND_PROP_ONLY_CTL_USAGE_FLAG = CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
CERT_FIND_NO_CTL_USAGE_FLAG = CERT_FIND_NO_ENHKEY_USAGE_FLAG
CERT_FIND_OR_CTL_USAGE_FLAG = CERT_FIND_OR_ENHKEY_USAGE_FLAG
CERT_FIND_VALID_CTL_USAGE_FLAG = CERT_FIND_VALID_ENHKEY_USAGE_FLAG
/* policyOID values for CertVerifyCertificateChainPolicy function */
CERT_CHAIN_POLICY_BASE = 1
CERT_CHAIN_POLICY_AUTHENTICODE = 2
@@ -423,6 +523,17 @@ const (
CERT_CHAIN_POLICY_EV = 8
CERT_CHAIN_POLICY_SSL_F12 = 9
/* flag for dwFindType CertFindChainInStore */
CERT_CHAIN_FIND_BY_ISSUER = 1
/* dwFindFlags for CertFindChainInStore when dwFindType == CERT_CHAIN_FIND_BY_ISSUER */
CERT_CHAIN_FIND_BY_ISSUER_COMPARE_KEY_FLAG = 0x0001
CERT_CHAIN_FIND_BY_ISSUER_COMPLEX_CHAIN_FLAG = 0x0002
CERT_CHAIN_FIND_BY_ISSUER_CACHE_ONLY_URL_FLAG = 0x0004
CERT_CHAIN_FIND_BY_ISSUER_LOCAL_MACHINE_FLAG = 0x0008
CERT_CHAIN_FIND_BY_ISSUER_NO_KEY_FLAG = 0x4000
CERT_CHAIN_FIND_BY_ISSUER_CACHE_ONLY_FLAG = 0x8000
/* Certificate Store close flags */
CERT_CLOSE_STORE_FORCE_FLAG = 0x00000001
CERT_CLOSE_STORE_CHECK_FLAG = 0x00000002
@@ -1360,6 +1471,19 @@ type CryptProtectPromptStruct struct {
Prompt *uint16
}
type CertChainFindByIssuerPara struct {
Size uint32
UsageIdentifier *byte
KeySpec uint32
AcquirePrivateKeyFlags uint32
IssuerCount uint32
Issuer Pointer
FindCallback Pointer
FindArg Pointer
IssuerChainIndex *uint32
IssuerElementIndex *uint32
}
type WinTrustData struct {
Size uint32
PolicyCallbackData uintptr

View File

@@ -146,6 +146,8 @@ var (
procCertDeleteCertificateFromStore = modcrypt32.NewProc("CertDeleteCertificateFromStore")
procCertDuplicateCertificateContext = modcrypt32.NewProc("CertDuplicateCertificateContext")
procCertEnumCertificatesInStore = modcrypt32.NewProc("CertEnumCertificatesInStore")
procCertFindCertificateInStore = modcrypt32.NewProc("CertFindCertificateInStore")
procCertFindChainInStore = modcrypt32.NewProc("CertFindChainInStore")
procCertFindExtension = modcrypt32.NewProc("CertFindExtension")
procCertFreeCertificateChain = modcrypt32.NewProc("CertFreeCertificateChain")
procCertFreeCertificateContext = modcrypt32.NewProc("CertFreeCertificateContext")
@@ -154,6 +156,7 @@ var (
procCertOpenStore = modcrypt32.NewProc("CertOpenStore")
procCertOpenSystemStoreW = modcrypt32.NewProc("CertOpenSystemStoreW")
procCertVerifyCertificateChainPolicy = modcrypt32.NewProc("CertVerifyCertificateChainPolicy")
procCryptAcquireCertificatePrivateKey = modcrypt32.NewProc("CryptAcquireCertificatePrivateKey")
procCryptDecodeObject = modcrypt32.NewProc("CryptDecodeObject")
procCryptProtectData = modcrypt32.NewProc("CryptProtectData")
procCryptQueryObject = modcrypt32.NewProc("CryptQueryObject")
@@ -1210,6 +1213,24 @@ func CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (contex
return
}
func CertFindCertificateInStore(store Handle, certEncodingType uint32, findFlags uint32, findType uint32, findPara unsafe.Pointer, prevCertContext *CertContext) (cert *CertContext, err error) {
r0, _, e1 := syscall.Syscall6(procCertFindCertificateInStore.Addr(), 6, uintptr(store), uintptr(certEncodingType), uintptr(findFlags), uintptr(findType), uintptr(findPara), uintptr(unsafe.Pointer(prevCertContext)))
cert = (*CertContext)(unsafe.Pointer(r0))
if cert == nil {
err = errnoErr(e1)
}
return
}
func CertFindChainInStore(store Handle, certEncodingType uint32, findFlags uint32, findType uint32, findPara unsafe.Pointer, prevChainContext *CertChainContext) (certchain *CertChainContext, err error) {
r0, _, e1 := syscall.Syscall6(procCertFindChainInStore.Addr(), 6, uintptr(store), uintptr(certEncodingType), uintptr(findFlags), uintptr(findType), uintptr(findPara), uintptr(unsafe.Pointer(prevChainContext)))
certchain = (*CertChainContext)(unsafe.Pointer(r0))
if certchain == nil {
err = errnoErr(e1)
}
return
}
func CertFindExtension(objId *byte, countExtensions uint32, extensions *CertExtension) (ret *CertExtension) {
r0, _, _ := syscall.Syscall(procCertFindExtension.Addr(), 3, uintptr(unsafe.Pointer(objId)), uintptr(countExtensions), uintptr(unsafe.Pointer(extensions)))
ret = (*CertExtension)(unsafe.Pointer(r0))
@@ -1269,6 +1290,19 @@ func CertVerifyCertificateChainPolicy(policyOID uintptr, chain *CertChainContext
return
}
func CryptAcquireCertificatePrivateKey(cert *CertContext, flags uint32, parameters unsafe.Pointer, cryptProvOrNCryptKey *Handle, keySpec *uint32, callerFreeProvOrNCryptKey *bool) (err error) {
var _p0 uint32
if *callerFreeProvOrNCryptKey {
_p0 = 1
}
r1, _, e1 := syscall.Syscall6(procCryptAcquireCertificatePrivateKey.Addr(), 6, uintptr(unsafe.Pointer(cert)), uintptr(flags), uintptr(parameters), uintptr(unsafe.Pointer(cryptProvOrNCryptKey)), uintptr(unsafe.Pointer(keySpec)), uintptr(unsafe.Pointer(&_p0)))
*callerFreeProvOrNCryptKey = _p0 != 0
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func CryptDecodeObject(encodingType uint32, structType *byte, encodedBytes *byte, lenEncodedBytes uint32, flags uint32, decoded unsafe.Pointer, decodedLen *uint32) (err error) {
r1, _, e1 := syscall.Syscall9(procCryptDecodeObject.Addr(), 7, uintptr(encodingType), uintptr(unsafe.Pointer(structType)), uintptr(unsafe.Pointer(encodedBytes)), uintptr(lenEncodedBytes), uintptr(flags), uintptr(decoded), uintptr(unsafe.Pointer(decodedLen)), 0, 0)
if r1 == 0 {