From d715faf2a04c3bca2ee135d24903237a0aca1f91 Mon Sep 17 00:00:00 2001 From: Maksim An Date: Wed, 2 Sep 2026 23:11:39 -0700 Subject: [PATCH] winapi: add CIM verification and block info bindings Add CimGetVerificationInformation2 and CimQueryBlockInfo syscall bindings for cimfs.dll and cimwriter.dll. Expose the APIs through the winapi facade and model their shared CIMFS types. Signed-off-by: Maksim An --- internal/winapi/cimfs.go | 14 +++ internal/winapi/cimfs/cimfs.go | 6 ++ internal/winapi/cimfs/zsyscall_windows.go | 92 ++++++++++++++----- internal/winapi/cimwriter/cimwriter.go | 6 ++ internal/winapi/cimwriter/zsyscall_windows.go | 82 +++++++++++++---- internal/winapi/types/cimfs.go | 27 ++++++ 6 files changed, 190 insertions(+), 37 deletions(-) diff --git a/internal/winapi/cimfs.go b/internal/winapi/cimfs.go index 3e3c15412f..e7222a1c8e 100644 --- a/internal/winapi/cimfs.go +++ b/internal/winapi/cimfs.go @@ -154,6 +154,20 @@ func CimGetVerificationInformation(blockCimPath string, isSealed *uint32, hashSi )(blockCimPath, isSealed, hashSize, signatureSize, fixedHeaderSize, hash, signature) } +func CimGetVerificationInformation2(blockCimPath string, flags types.CimGetVerificationInfoFlags, isSealed *uint32, hashSize *uint64, signatureOffset *uint64, signatureSize *uint64, fixedHeaderSize *uint64, hash *byte, signature *byte, signatureType *types.CimSignatureType, hashAlgorithm *types.CimHashAlgorithm) (hr error) { + return pickSupported( + cimwriter.CimGetVerificationInformation2, + cimfs.CimGetVerificationInformation2, + )(blockCimPath, flags, isSealed, hashSize, signatureOffset, signatureSize, fixedHeaderSize, hash, signature, signatureType, hashAlgorithm) +} + +func CimQueryBlockInfo(blockCimPath string, cimInfoBufferSize uint32, cimInfoBuffer *types.CimFsCimInfo, requiredBufferSize *uint32, cimCount *uint32) (hr error) { + return pickSupported( + cimwriter.CimQueryBlockInfo, + cimfs.CimQueryBlockInfo, + )(blockCimPath, cimInfoBufferSize, cimInfoBuffer, requiredBufferSize, cimCount) +} + func CimMountVerifiedImage(imagePath string, fsName string, flags uint32, volumeID *guid.GUID, hashSize uint16, hash *byte) error { return cimfs.CimMountVerifiedImage(imagePath, fsName, flags, volumeID, hashSize, hash) } diff --git a/internal/winapi/cimfs/cimfs.go b/internal/winapi/cimfs/cimfs.go index 0317c73a78..48c04924b7 100644 --- a/internal/winapi/cimfs/cimfs.go +++ b/internal/winapi/cimfs/cimfs.go @@ -19,6 +19,10 @@ type FsHandle = types.FsHandle type StreamHandle = types.StreamHandle type FileMetadata = types.CimFsFileMetadata type ImagePath = types.CimFsImagePath +type CimInfo = types.CimFsCimInfo +type VerificationInfoFlags = types.CimGetVerificationInfoFlags +type SignatureType = types.CimSignatureType +type HashAlgorithm = types.CimHashAlgorithm //sys CimMountImage(imagePath string, fsName string, flags uint32, volumeID *GUID) (hr error) = cimfs.CimMountImage? //sys CimDismountImage(volumeID *GUID) (hr error) = cimfs.CimDismountImage? @@ -41,6 +45,8 @@ type ImagePath = types.CimFsImagePath //sys CimCreateMergeLink(cimFSHandle FsHandle, newPath string, oldPath string) (hr error) = cimfs.CimCreateMergeLink? //sys CimSealImage(blockCimPath string, hashSize *uint64, fixedHeaderSize *uint64, hash *byte) (hr error) = cimfs.CimSealImage? //sys CimGetVerificationInformation(blockCimPath string, isSealed *uint32, hashSize *uint64, signatureSize *uint64, fixedHeaderSize *uint64, hash *byte, signature *byte) (hr error) = cimfs.CimGetVerificationInformation? +//sys CimGetVerificationInformation2(blockCimPath string, flags VerificationInfoFlags, isSealed *uint32, hashSize *uint64, signatureOffset *uint64, signatureSize *uint64, fixedHeaderSize *uint64, hash *byte, signature *byte, signatureType *SignatureType, hashAlgorithm *HashAlgorithm) (hr error) = cimfs.CimGetVerificationInformation2? +//sys CimQueryBlockInfo(blockCimPath string, cimInfoBufferSize uint32, cimInfoBuffer *CimInfo, requiredBufferSize *uint32, cimCount *uint32) (hr error) = cimfs.CimQueryBlockInfo? //sys CimMountVerifiedImage(imagePath string, fsName string, flags uint32, volumeID *GUID, hashSize uint16, hash *byte) (hr error) = cimfs.CimMountVerifiedImage? //sys CimMergeMountVerifiedImage(numCimPaths uint32, backingImagePaths *ImagePath, flags uint32, volumeID *GUID, hashSize uint16, hash *byte) (hr error) = cimfs.CimMergeMountVerifiedImage? diff --git a/internal/winapi/cimfs/zsyscall_windows.go b/internal/winapi/cimfs/zsyscall_windows.go index d1c36868bf..3256ba5331 100644 --- a/internal/winapi/cimfs/zsyscall_windows.go +++ b/internal/winapi/cimfs/zsyscall_windows.go @@ -39,27 +39,29 @@ func errnoErr(e syscall.Errno) error { var ( modcimfs = windows.NewLazySystemDLL("cimfs.dll") - procCimAddFsToMergedImage = modcimfs.NewProc("CimAddFsToMergedImage") - procCimAddFsToMergedImage2 = modcimfs.NewProc("CimAddFsToMergedImage2") - procCimCloseImage = modcimfs.NewProc("CimCloseImage") - procCimCloseStream = modcimfs.NewProc("CimCloseStream") - procCimCommitImage = modcimfs.NewProc("CimCommitImage") - procCimCreateAlternateStream = modcimfs.NewProc("CimCreateAlternateStream") - procCimCreateFile = modcimfs.NewProc("CimCreateFile") - procCimCreateHardLink = modcimfs.NewProc("CimCreateHardLink") - procCimCreateImage = modcimfs.NewProc("CimCreateImage") - procCimCreateImage2 = modcimfs.NewProc("CimCreateImage2") - procCimCreateMergeLink = modcimfs.NewProc("CimCreateMergeLink") - procCimDeletePath = modcimfs.NewProc("CimDeletePath") - procCimDismountImage = modcimfs.NewProc("CimDismountImage") - procCimGetVerificationInformation = modcimfs.NewProc("CimGetVerificationInformation") - procCimMergeMountImage = modcimfs.NewProc("CimMergeMountImage") - procCimMergeMountVerifiedImage = modcimfs.NewProc("CimMergeMountVerifiedImage") - procCimMountImage = modcimfs.NewProc("CimMountImage") - procCimMountVerifiedImage = modcimfs.NewProc("CimMountVerifiedImage") - procCimSealImage = modcimfs.NewProc("CimSealImage") - procCimTombstoneFile = modcimfs.NewProc("CimTombstoneFile") - procCimWriteStream = modcimfs.NewProc("CimWriteStream") + procCimAddFsToMergedImage = modcimfs.NewProc("CimAddFsToMergedImage") + procCimAddFsToMergedImage2 = modcimfs.NewProc("CimAddFsToMergedImage2") + procCimCloseImage = modcimfs.NewProc("CimCloseImage") + procCimCloseStream = modcimfs.NewProc("CimCloseStream") + procCimCommitImage = modcimfs.NewProc("CimCommitImage") + procCimCreateAlternateStream = modcimfs.NewProc("CimCreateAlternateStream") + procCimCreateFile = modcimfs.NewProc("CimCreateFile") + procCimCreateHardLink = modcimfs.NewProc("CimCreateHardLink") + procCimCreateImage = modcimfs.NewProc("CimCreateImage") + procCimCreateImage2 = modcimfs.NewProc("CimCreateImage2") + procCimCreateMergeLink = modcimfs.NewProc("CimCreateMergeLink") + procCimDeletePath = modcimfs.NewProc("CimDeletePath") + procCimDismountImage = modcimfs.NewProc("CimDismountImage") + procCimGetVerificationInformation = modcimfs.NewProc("CimGetVerificationInformation") + procCimGetVerificationInformation2 = modcimfs.NewProc("CimGetVerificationInformation2") + procCimMergeMountImage = modcimfs.NewProc("CimMergeMountImage") + procCimMergeMountVerifiedImage = modcimfs.NewProc("CimMergeMountVerifiedImage") + procCimMountImage = modcimfs.NewProc("CimMountImage") + procCimMountVerifiedImage = modcimfs.NewProc("CimMountVerifiedImage") + procCimQueryBlockInfo = modcimfs.NewProc("CimQueryBlockInfo") + procCimSealImage = modcimfs.NewProc("CimSealImage") + procCimTombstoneFile = modcimfs.NewProc("CimTombstoneFile") + procCimWriteStream = modcimfs.NewProc("CimWriteStream") ) func CimAddFsToMergedImage(cimFSHandle FsHandle, path string) (hr error) { @@ -366,6 +368,30 @@ func _CimGetVerificationInformation(blockCimPath *uint16, isSealed *uint32, hash return } +func CimGetVerificationInformation2(blockCimPath string, flags VerificationInfoFlags, isSealed *uint32, hashSize *uint64, signatureOffset *uint64, signatureSize *uint64, fixedHeaderSize *uint64, hash *byte, signature *byte, signatureType *SignatureType, hashAlgorithm *HashAlgorithm) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(blockCimPath) + if hr != nil { + return + } + return _CimGetVerificationInformation2(_p0, flags, isSealed, hashSize, signatureOffset, signatureSize, fixedHeaderSize, hash, signature, signatureType, hashAlgorithm) +} + +func _CimGetVerificationInformation2(blockCimPath *uint16, flags VerificationInfoFlags, isSealed *uint32, hashSize *uint64, signatureOffset *uint64, signatureSize *uint64, fixedHeaderSize *uint64, hash *byte, signature *byte, signatureType *SignatureType, hashAlgorithm *HashAlgorithm) (hr error) { + hr = procCimGetVerificationInformation2.Find() + if hr != nil { + return + } + r0, _, _ := syscall.SyscallN(procCimGetVerificationInformation2.Addr(), uintptr(unsafe.Pointer(blockCimPath)), uintptr(flags), uintptr(unsafe.Pointer(isSealed)), uintptr(unsafe.Pointer(hashSize)), uintptr(unsafe.Pointer(signatureOffset)), uintptr(unsafe.Pointer(signatureSize)), uintptr(unsafe.Pointer(fixedHeaderSize)), uintptr(unsafe.Pointer(hash)), uintptr(unsafe.Pointer(signature)), uintptr(unsafe.Pointer(signatureType)), uintptr(unsafe.Pointer(hashAlgorithm))) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + func CimMergeMountImage(numCimPaths uint32, backingImagePaths *ImagePath, flags uint32, volumeID *GUID) (hr error) { hr = procCimMergeMountImage.Find() if hr != nil { @@ -454,6 +480,30 @@ func _CimMountVerifiedImage(imagePath *uint16, fsName *uint16, flags uint32, vol return } +func CimQueryBlockInfo(blockCimPath string, cimInfoBufferSize uint32, cimInfoBuffer *CimInfo, requiredBufferSize *uint32, cimCount *uint32) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(blockCimPath) + if hr != nil { + return + } + return _CimQueryBlockInfo(_p0, cimInfoBufferSize, cimInfoBuffer, requiredBufferSize, cimCount) +} + +func _CimQueryBlockInfo(blockCimPath *uint16, cimInfoBufferSize uint32, cimInfoBuffer *CimInfo, requiredBufferSize *uint32, cimCount *uint32) (hr error) { + hr = procCimQueryBlockInfo.Find() + if hr != nil { + return + } + r0, _, _ := syscall.SyscallN(procCimQueryBlockInfo.Addr(), uintptr(unsafe.Pointer(blockCimPath)), uintptr(cimInfoBufferSize), uintptr(unsafe.Pointer(cimInfoBuffer)), uintptr(unsafe.Pointer(requiredBufferSize)), uintptr(unsafe.Pointer(cimCount))) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + func CimSealImage(blockCimPath string, hashSize *uint64, fixedHeaderSize *uint64, hash *byte) (hr error) { var _p0 *uint16 _p0, hr = syscall.UTF16PtrFromString(blockCimPath) diff --git a/internal/winapi/cimwriter/cimwriter.go b/internal/winapi/cimwriter/cimwriter.go index d8f4d4dc12..55fcc56beb 100644 --- a/internal/winapi/cimwriter/cimwriter.go +++ b/internal/winapi/cimwriter/cimwriter.go @@ -17,6 +17,10 @@ type FsHandle = types.FsHandle type StreamHandle = types.StreamHandle type FileMetadata = types.CimFsFileMetadata type ImagePath = types.CimFsImagePath +type CimInfo = types.CimFsCimInfo +type VerificationInfoFlags = types.CimGetVerificationInfoFlags +type SignatureType = types.CimSignatureType +type HashAlgorithm = types.CimHashAlgorithm //sys CimCreateImage(imagePath string, oldFSName *uint16, newFSName *uint16, cimFSHandle *FsHandle) (hr error) = cimwriter.CimCreateImage? //sys CimCreateImage2(imagePath string, flags uint32, oldFSName *uint16, newFSName *uint16, cimFSHandle *FsHandle) (hr error) = cimwriter.CimCreateImage2? @@ -37,6 +41,8 @@ type ImagePath = types.CimFsImagePath //sys CimSealImage(blockCimPath string, hashSize *uint64, fixedHeaderSize *uint64, hash *byte) (hr error) = cimwriter.CimSealImage? //sys CimGetVerificationInformation(blockCimPath string, isSealed *uint32, hashSize *uint64, signatureSize *uint64, fixedHeaderSize *uint64, hash *byte, signature *byte) (hr error) = cimwriter.CimGetVerificationInformation? +//sys CimGetVerificationInformation2(blockCimPath string, flags VerificationInfoFlags, isSealed *uint32, hashSize *uint64, signatureOffset *uint64, signatureSize *uint64, fixedHeaderSize *uint64, hash *byte, signature *byte, signatureType *SignatureType, hashAlgorithm *HashAlgorithm) (hr error) = cimwriter.CimGetVerificationInformation2? +//sys CimQueryBlockInfo(blockCimPath string, cimInfoBufferSize uint32, cimInfoBuffer *CimInfo, requiredBufferSize *uint32, cimCount *uint32) (hr error) = cimwriter.CimQueryBlockInfo? var load = sync.OnceValue(func() error { // Pre-load the DLL with a restricted search path (System32 + application directory only) diff --git a/internal/winapi/cimwriter/zsyscall_windows.go b/internal/winapi/cimwriter/zsyscall_windows.go index 3dbafa1a29..a64c370378 100644 --- a/internal/winapi/cimwriter/zsyscall_windows.go +++ b/internal/winapi/cimwriter/zsyscall_windows.go @@ -37,22 +37,24 @@ func errnoErr(e syscall.Errno) error { var ( modcimwriter = syscall.NewLazyDLL("cimwriter.dll") - procCimAddFsToMergedImage = modcimwriter.NewProc("CimAddFsToMergedImage") - procCimAddFsToMergedImage2 = modcimwriter.NewProc("CimAddFsToMergedImage2") - procCimCloseImage = modcimwriter.NewProc("CimCloseImage") - procCimCloseStream = modcimwriter.NewProc("CimCloseStream") - procCimCommitImage = modcimwriter.NewProc("CimCommitImage") - procCimCreateAlternateStream = modcimwriter.NewProc("CimCreateAlternateStream") - procCimCreateFile = modcimwriter.NewProc("CimCreateFile") - procCimCreateHardLink = modcimwriter.NewProc("CimCreateHardLink") - procCimCreateImage = modcimwriter.NewProc("CimCreateImage") - procCimCreateImage2 = modcimwriter.NewProc("CimCreateImage2") - procCimCreateMergeLink = modcimwriter.NewProc("CimCreateMergeLink") - procCimDeletePath = modcimwriter.NewProc("CimDeletePath") - procCimGetVerificationInformation = modcimwriter.NewProc("CimGetVerificationInformation") - procCimSealImage = modcimwriter.NewProc("CimSealImage") - procCimTombstoneFile = modcimwriter.NewProc("CimTombstoneFile") - procCimWriteStream = modcimwriter.NewProc("CimWriteStream") + procCimAddFsToMergedImage = modcimwriter.NewProc("CimAddFsToMergedImage") + procCimAddFsToMergedImage2 = modcimwriter.NewProc("CimAddFsToMergedImage2") + procCimCloseImage = modcimwriter.NewProc("CimCloseImage") + procCimCloseStream = modcimwriter.NewProc("CimCloseStream") + procCimCommitImage = modcimwriter.NewProc("CimCommitImage") + procCimCreateAlternateStream = modcimwriter.NewProc("CimCreateAlternateStream") + procCimCreateFile = modcimwriter.NewProc("CimCreateFile") + procCimCreateHardLink = modcimwriter.NewProc("CimCreateHardLink") + procCimCreateImage = modcimwriter.NewProc("CimCreateImage") + procCimCreateImage2 = modcimwriter.NewProc("CimCreateImage2") + procCimCreateMergeLink = modcimwriter.NewProc("CimCreateMergeLink") + procCimDeletePath = modcimwriter.NewProc("CimDeletePath") + procCimGetVerificationInformation = modcimwriter.NewProc("CimGetVerificationInformation") + procCimGetVerificationInformation2 = modcimwriter.NewProc("CimGetVerificationInformation2") + procCimQueryBlockInfo = modcimwriter.NewProc("CimQueryBlockInfo") + procCimSealImage = modcimwriter.NewProc("CimSealImage") + procCimTombstoneFile = modcimwriter.NewProc("CimTombstoneFile") + procCimWriteStream = modcimwriter.NewProc("CimWriteStream") ) func CimAddFsToMergedImage(cimFSHandle FsHandle, path string) (hr error) { @@ -344,6 +346,54 @@ func _CimGetVerificationInformation(blockCimPath *uint16, isSealed *uint32, hash return } +func CimGetVerificationInformation2(blockCimPath string, flags VerificationInfoFlags, isSealed *uint32, hashSize *uint64, signatureOffset *uint64, signatureSize *uint64, fixedHeaderSize *uint64, hash *byte, signature *byte, signatureType *SignatureType, hashAlgorithm *HashAlgorithm) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(blockCimPath) + if hr != nil { + return + } + return _CimGetVerificationInformation2(_p0, flags, isSealed, hashSize, signatureOffset, signatureSize, fixedHeaderSize, hash, signature, signatureType, hashAlgorithm) +} + +func _CimGetVerificationInformation2(blockCimPath *uint16, flags VerificationInfoFlags, isSealed *uint32, hashSize *uint64, signatureOffset *uint64, signatureSize *uint64, fixedHeaderSize *uint64, hash *byte, signature *byte, signatureType *SignatureType, hashAlgorithm *HashAlgorithm) (hr error) { + hr = procCimGetVerificationInformation2.Find() + if hr != nil { + return + } + r0, _, _ := syscall.SyscallN(procCimGetVerificationInformation2.Addr(), uintptr(unsafe.Pointer(blockCimPath)), uintptr(flags), uintptr(unsafe.Pointer(isSealed)), uintptr(unsafe.Pointer(hashSize)), uintptr(unsafe.Pointer(signatureOffset)), uintptr(unsafe.Pointer(signatureSize)), uintptr(unsafe.Pointer(fixedHeaderSize)), uintptr(unsafe.Pointer(hash)), uintptr(unsafe.Pointer(signature)), uintptr(unsafe.Pointer(signatureType)), uintptr(unsafe.Pointer(hashAlgorithm))) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func CimQueryBlockInfo(blockCimPath string, cimInfoBufferSize uint32, cimInfoBuffer *CimInfo, requiredBufferSize *uint32, cimCount *uint32) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(blockCimPath) + if hr != nil { + return + } + return _CimQueryBlockInfo(_p0, cimInfoBufferSize, cimInfoBuffer, requiredBufferSize, cimCount) +} + +func _CimQueryBlockInfo(blockCimPath *uint16, cimInfoBufferSize uint32, cimInfoBuffer *CimInfo, requiredBufferSize *uint32, cimCount *uint32) (hr error) { + hr = procCimQueryBlockInfo.Find() + if hr != nil { + return + } + r0, _, _ := syscall.SyscallN(procCimQueryBlockInfo.Addr(), uintptr(unsafe.Pointer(blockCimPath)), uintptr(cimInfoBufferSize), uintptr(unsafe.Pointer(cimInfoBuffer)), uintptr(unsafe.Pointer(requiredBufferSize)), uintptr(unsafe.Pointer(cimCount))) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + func CimSealImage(blockCimPath string, hashSize *uint64, fixedHeaderSize *uint64, hash *byte) (hr error) { var _p0 *uint16 _p0, hr = syscall.UTF16PtrFromString(blockCimPath) diff --git a/internal/winapi/types/cimfs.go b/internal/winapi/types/cimfs.go index 2fa8cfc71d..b8f77bd00b 100644 --- a/internal/winapi/types/cimfs.go +++ b/internal/winapi/types/cimfs.go @@ -11,6 +11,27 @@ import ( type FsHandle uintptr type StreamHandle uintptr +type CimGetVerificationInfoFlags uint32 + +const ( + CimGetVerificationInfoNone CimGetVerificationInfoFlags = 0 + CimGetVerificationInfoFromSkeletonCim CimGetVerificationInfoFlags = 1 +) + +type CimSignatureType uint32 + +const ( + CimSignatureNone CimSignatureType = 0 + CimSignaturePKCS7 CimSignatureType = 1 +) + +type CimHashAlgorithm uint32 + +const ( + CimHashAlgorithmSHA256 CimHashAlgorithm = 0 + CimHashAlgorithmSHA512 CimHashAlgorithm = 1 +) + type CimFsFileMetadata struct { Attributes uint32 FileSize int64 @@ -34,3 +55,9 @@ type CimFsImagePath struct { ImageDir *uint16 ImageName *uint16 } + +type CimFsCimInfo struct { + NextEntryOffset uint32 + CimNameLength uint16 + CimName [1]uint16 +}