in aws_signing_helper/cert_store_signer_windows.go [149:251]
func GetMatchingCertsAndChain(certIdentifier CertIdentifier) (store windows.Handle, certCtxs []*windows.CertContext, certChains [][]*x509.Certificate, certContainers []CertificateContainer, err error) {
storeName, err := windows.UTF16PtrFromString(certIdentifier.SystemStoreName)
if err != nil {
return 0, nil, nil, nil, errors.New("unable to UTF-16 encode personal certificate store name")
}
store, err = windows.CertOpenStore(windows.CERT_STORE_PROV_SYSTEM_W, 0, 0, windows.CERT_SYSTEM_STORE_CURRENT_USER, uintptr(unsafe.Pointer(storeName)))
if err != nil {
return 0, nil, nil, nil, errors.New("failed to open system cert store")
}
var (
// 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
paramsPtr unsafe.Pointer
chainCtx *windows.CertChainContext = nil
certCtx *windows.CertContext
)
params.Size = uint32(unsafe.Sizeof(params))
paramsPtr = unsafe.Pointer(¶ms)
var curCertCtx *windows.CertContext
var curCert *x509.Certificate
certContainerIndex := 0
for {
// Previous chainCtx should be freed here if it isn't nil
chainCtx, err = windows.CertFindChainInStore(store, encoding, flags, findType, paramsPtr, chainCtx)
if err != nil {
if strings.Contains(err.Error(), "Cannot find object or property.") {
break
}
err = errors.New("unable to find certificate chain in store")
goto fail
}
if chainCtx.ChainCount < 1 {
err = errors.New("bad chain")
goto fail
}
// When multiple valid certification paths that are found for a given
// certificate, only the first one is considered
simpleChain := *chainCtx.Chains
if simpleChain.NumElements < 1 {
err = errors.New("bad chain")
goto fail
}
// Convert the array into a pointer
chainElts := unsafe.Slice(simpleChain.Elements, simpleChain.NumElements)
// Build chain of certificates from each element's certificate context.
x509CertChain := make([]*x509.Certificate, len(chainElts))
for j := range chainElts {
curCertCtx = chainElts[j].CertContext
x509CertChain[j], err = exportCertContext(curCertCtx)
if err != nil {
if Debug {
log.Printf("unable to parse certificate with error (%s) - skipping\n", err)
}
goto nextIteration
}
}
curCert = x509CertChain[0]
if certMatches(certIdentifier, *curCert) {
certContainers = append(certContainers, CertificateContainer{certContainerIndex, curCert, ""})
certContainerIndex += 1
certChains = append(certChains, x509CertChain[:])
certCtx = chainElts[0].CertContext
// It's the responsibility of the caller to free the below once they are done using it.
windows.CertDuplicateCertificateContext(certCtx)
certCtxs = append(certCtxs, certCtx)
}
nextIteration:
}
if Debug {
log.Printf("found %d matching identities\n", len(certContainers))
}
return store, certCtxs, certChains, certContainers, nil
fail:
if chainCtx != nil {
windows.CertFreeCertificateChain(chainCtx)
chainCtx = nil
}
for i, curCertCtx := range certCtxs {
if curCertCtx != nil {
windows.CertFreeCertificateContext(curCertCtx)
certCtxs[i] = nil
}
}
windows.CertCloseStore(store, 0)
return 0, nil, nil, nil, err
}