func DecryptProtectedSettings()

in pkg/decrypt/decypt_windows.go [26:91]


func DecryptProtectedSettings(configFolder string, thumbprint string, decoded []byte) (string, error) {
	// Open My/Local
	handle, err := syscall.CertOpenStore(windows.CERT_STORE_PROV_SYSTEM, 0, 0, windows.CERT_SYSTEM_STORE_LOCAL_MACHINE, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("MY"))))
	if err != nil {
		return "", fmt.Errorf("VMextension: Cannot open certificate store due to '%v'", err)
	}
	if handle == 0 {
		return "", extensionerrors.ErrMustRunAsAdmin
	}
	defer syscall.CertCloseStore(handle, 0)

	// Convert the thumbprint to bytes. We do byte comparison vs string comparison because otherwise we'd need to normalize the strings
	decodedThumbprint, err := thumbprintStringToHex(thumbprint)
	if err != nil {
		return "", fmt.Errorf("VmExtension: Invalid thumbprint")
	}

	// Find the certificate by thumbprint
	const crypteENotFound = 0x80092004
	var cert *syscall.CertContext
	var prevContext *syscall.CertContext
	found := false
	for {
		// Keep retrieving the next certificate
		cert, err := syscall.CertEnumCertificatesInStore(handle, prevContext)
		if err != nil {
			if errno, ok := err.(syscall.Errno); ok {
				if errno == crypteENotFound {
					// We've reached the last certificate
					break
				}
			}
			return "", fmt.Errorf("VmExtension: Could not enumerate certificates due to '%v'", err)
		}

		if cert == nil {
			break
		}

		// Determine the cert thumbprint
		foundthumbprint, err := crypto.GetCertificateThumbprint(cert)
		if err == nil && foundthumbprint != nil {
			// TODO: consider logging if we have an error. For now, we just ignore the cert
			if bytes.Compare(decodedThumbprint, foundthumbprint) == 0 {
				found = true
				break
			}
		}

		prevContext = cert
	}

	if !found {
		return "", extensionerrors.ErrCertWithThumbprintNotFound
	}

	// Decrypt the protected settings
	decryptedBytes, err := decryptDataWithCert(decoded, cert, uintptr(handle))
	if err != nil {
		return "", err
	}

	// Now deserialize the data
	v := string(decryptedBytes[:])
	return v, err
}