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
}