func GetMatchingCertsAndIdentity()

in aws_signing_helper/cert_store_signer_darwin.go [47:116]


func GetMatchingCertsAndIdentity(certIdentifier CertIdentifier) ([]C.SecIdentityRef, []C.SecCertificateRef, []CertificateContainer, error) {
	queryMap := 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),
	}

	query := mapToCFDictionary(queryMap)
	if query == 0 {
		return nil, nil, 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 nil, nil, nil, errors.New("unable to find matching identity in cert store")
		}
		return nil, nil, nil, err
	}
	defer C.CFRelease(C.CFTypeRef(absResult))
	aryResult := C.CFArrayRef(absResult)

	// identRefs aren't owned by us initially
	numIdentRefs := C.CFArrayGetCount(aryResult)
	identRefs := make([]C.CFTypeRef, numIdentRefs)
	C.CFArrayGetValues(aryResult, C.CFRange{0, numIdentRefs}, (*unsafe.Pointer)(unsafe.Pointer(&identRefs[0])))
	var certContainers []CertificateContainer
	var certRefs []C.SecCertificateRef
	var outputIdentRefs []C.SecIdentityRef
	var isMatch bool
	certContainerIndex := 0
	for _, curIdentRef := range identRefs {
		curCertRef, err := getCertRef(C.SecIdentityRef(curIdentRef))
		if err != nil {
			return nil, nil, nil, errors.New("unable to get cert ref")
		}
		curCert, err := exportCertRef(curCertRef)
		if err != nil {
			if Debug {
				log.Printf("unable to parse certificate with error (%s) - skipping\n", err)
			}
			goto nextIteration
		}

		// Find whether there is a matching certificate
		isMatch = certMatches(certIdentifier, *curCert)
		if isMatch {
			certContainers = append(certContainers, CertificateContainer{certContainerIndex, curCert, ""})
			certContainerIndex += 1
			// Assign to certRef and identRef at most once in the loop
			// Both values are only useful if there is exactly one match in the certificate store
			// When creating a signer, there has to be exactly one matching certificate

			certRefs = append(certRefs, curCertRef)
			// Note that only the SecIdentityRef needs to be retained since it was neither created nor copied
			C.CFRetain(C.CFTypeRef(curIdentRef))
			outputIdentRefs = append(outputIdentRefs, C.SecIdentityRef(curIdentRef))
		}

	nextIteration:
	}

	if Debug {
		log.Printf("found %d matching identities\n", len(certContainers))
	}

	// It's the caller's responsibility to release each SecIdentityRef after use.
	return outputIdentRefs, certRefs, certContainers, nil
}