How to programmatically determine if a disk is encrypted on OS X? - macos

Given a volume, how do I determine whether it is encrypted or not? I've found stuff like DADiskCopyDescription() and NSURL's getResourceValue:forKey:error: which give a wealth of information, but not whether the volume is encrypted.
Even if there isn't a public API for this then scraping output from a command line tool which ships with the OS would be acceptable. The closest I found was 'diskutil info /dev/disk0', but again no encryption information. Annoyingly the GUI Disk Utility app does provide this information when you click on the blue info button.

You can (ab)use IOKit for this. Note that the CoreStorage Encrypted property is not officially defined anywhere, so this is decidedly not public API. Also, you'll need to inspect the whole disk object that Core Storage offers to the OS (e.g. disk1), not the partition that the Core Storage LV lives on (e.g. disk0s2).
const char *bsdDisk = "disk1";
DASessionRef session = DASessionCreate(kCFAllocatorDefault);
DADiskRef disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, "disk1");
io_service_t diskService = DADiskCopyIOMedia(disk);
CFBooleanRef isEncrypted = IORegistryEntryCreateCFProperty(diskService,
CFSTR("CoreStorage Encrypted"),
kCFAllocatorDefault,
0);
fprintf(stdout,
"%s %s encrypted\n",
bsdDisk,
(CFBooleanGetValue(isEncrypted)) ? "is" : "is not");
CFRelease(isEncrypted);
IOObjectRelease(diskService);
CFRelease(disk);
CFRelease(session);

It looks like this information is available using system_profiler -detailLevel basic.

Related

Is there a way to find out which USB interface Mac OS has a driver attached to?

I'm trying to debug a libusb function called libusb_kernel_driver_active(). It tells if a USB device has an operating system driver attached to it. It takes an interface number as one of its arguments. I want to be able to find out which interface the operating system's driver is currently attached to. Is there a way to do this using a terminal command or IOKit?
I have tried IORegistryExplorer but it doesn't list this information.
ioreg does not appear to list USB interface information.
Maybe someone out there knows of an IOKit function that can tell us the information we want.
To find this information out, open the IORegistryExplorer program (spotlight can find it). Then select IOService from the drop down menu in the upper left corner of the window. In the search bar type the name of your device. If it is found select in on the tree below. Then delete all text from the search field to see all the available fields.
The IORegistryExplorer answer is correct, but as the question hints at, there are other ways to obtain the information, both on the Terminal and programmatically.
Terminal (ioreg)
The command
ioreg -irc IOUSBDevice
Will list all USB devices detected by the system, as well as any client objects in the I/O Registry. This means either the driver client directly (kext, dext, or user space) or the IOUSBInterface objects representing the different interfaces on a composite device, and the driver clients attached to each of those.
You can search by name instead of class type by using the -n option instead of -c but often the USB-level name doesn't match the retail name of the device, or is somehow abbreviated. It's usually easier to inspect all USB devices manually.
Programmatically
In your program, you can search for all USB devices in the system using something like this:
io_iterator_t device_iter = IO_OBJECT_NULL;
IOReturn ret = IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching(kIOUSBDeviceClassName), &device_iter);
if (ret == kIOReturnSuccess && device_iter != IO_OBJECT_NULL)
{
while (io_service_t device = IOIteratorNext(device_iter))
{
io_name_t device_name = "";
IORegistryEntryGetName(device, device_name);
// do something with device_nameā€¦
}
}
Once you have selected your device, you can then use IORegistryEntryCreateIterator() to iterate over its child objects (possibly recursively), which should allow you to identify the driver being used or obtain any other information you require.

Access hardware from user process

I have a driver that runs in the kernel of a Windows Embedded Compact 2013. The driver is loaded with the "Drivers\BuiltIn" registry key. It accesses a set of HW-registers that are mapped with MmMapIoSpace.
The access to the hardware has some problems. That's why I would like to develop the hardware access in a user mode program and debug the problems. I created a program with VS2013 for that purpose. That's the way we used to go with Windows CE 5.0.
The driver maps the physical address with MmMapIoSpace to the process address space. My program should do the same or something similar. Unfortunately this doesn't work in my program. MmMapIoSpace returns NULL, LastError=87 (invalid parameters). Even CreateStaticMapping returns NULL.
How can I access memory mapped register in WEC2013 without building a new platform for each iteration?
MmMapIoSpace doesn't work in applications anymore since WinCE6.
You maybe could create a driver which maps your hw-register to your user process. Your user process would then obtain this pointer by an ioctl call to this driver.
We mapped some external memory to an application with this method.
VirtualAllocCopyEx() can create a mapping to a specified process.
Hope, this helps. Greetings.
Corresponding to timmfs answer I implemented this code in the driver's XXX_IOControl function:
PHYSICAL_ADDRESS PhysAddress = { 0 };
PhysAddress.LowPart = phys_address;
PVOID pRegister = MmMapIoSpace(PhysAddress, phys_size, FALSE);
HANDLE hCallerProcess = (HANDLE)GetCallerVMProcessId();
HANDLE hCurrentProcess = (HANDLE)GetCurrentProcessId();
PVOID UserSpaceAddress = VirtualAllocCopyEx(hCurrentProcess, hCallerProcess, pRegister, shys_size, PAGE_NOCACHE);
This excerpt shows some solutions for pitfalls I met. So I show how I get all the parameters.

Getting the BSD name of a USB device using IOKit to write to the device?

I am trying to determine the BSD name of virtual serial port using IOKit under MacOS.
I have a USB CDC device that looks like a virtual serial port, and I want to get the BSD device path so that I can just do a fopen("/dev/tty.usbmodem123"). I have a program that takes the VID and PID and waits for the device to be plugged in, and then I want to use the BSD name write to the device. The device mounts differently on every system and I am trying to use this as a teaching tool, so I need to search for the device before I write to it without manually inspecting /dev/tty.* for where the device mounted.
I have 3 questions.
Firstly, can one get the BSD name of a virtual serial port using CFSTR(kIOBSDNameKey)?
IORegistryEntrySearchCFProperty() and FindProp() always return "null". Does anyone know if the BSD name can be returned by a non-block device?
I am currently doing this:
bsdName = IORegistryEntrySearchCFProperty(p_usb_ref, kIOServicePlane, CFSTR(kIOBSDNameKey), kCFAllocatorDefault, kIORegistryIterateRecursively );
Secondly, I have been able to get service plane name:
IOService:/AppleACPIPlatformExpert/PCI0#0/AppleACPIPCI/OHC1#4/AppleUSBOHCI/Intro to Electronics#4100000
and this corresponds to a mount point of: /dev/tty.usbmodem411
Does anyone know how to translate the service plane name to the dev tree name?
Thirdly, am I making this too complicated? I already know the device io handle, is there a way to use that to write data to the device? I just need to send a few ASCII bytes to flash some LEDs.
Any advice would be greatly appreciated.
EDIT:
After spending some more time looking at this, I found that my issue was that I was querying for the BSD name before the CDC driver was being loaded. I am currently getting the BSD name, and then sorting out for the VID and PID.
The code that solved my issue above is:
matchingDictionary = IOServiceMatching(kIOSerialBSDServiceValue);
CFDictionarySetValue(matchingDictionary, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDModemType));
kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &iter);
And then you iterate through iter to find the device with the correct ID.
This is what I use with a IONotification when adding a USB serial device:
Under 10.11 it came up empty. After trying a lot of things, this was my solution:
while ((usbDevice = IOIteratorNext(iterator)))
{
//when hotplugging under OSX 10.11:
sleep(1);//otherwise the property will be empty.
CFStringRef deviceBSDName_cf = (CFStringRef) IORegistryEntrySearchCFProperty (usbDevice,
kIOServicePlane,
CFSTR (kIOCalloutDeviceKey),
kCFAllocatorDefault,
kIORegistryIterateRecursively );
NSLog(#"device path: %#", deviceBSDName_cf);
}
It should find something like: /dev/cu.xxxxx
Hope it helps someone.
Perhaps things have changed in OS X 10.10? Your last code snippet doesn't seem to find the /dev/tty.usbmodem00054741 device on my system:
io_iterator_t devlisthndl = 0;
CFMutableDictionaryRef matchingDictionary = IOServiceMatching(kIOSerialBSDServiceValue);
CFIndex dict_count = CFDictionaryGetCount(matchingDictionary);
CFDictionarySetValue(matchingDictionary, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDModemType));
kern_return_t kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &devlisthndl);
(lldb) p matchingDictionary
(CFMutableDictionaryRef) $3 = 0x0000610000267780 #"0 entries"
How did you end up obtaining the mount point string?

Determining a DVD drive's region code in OS X in C WITHOUT requiring that a DVD be in the drive

Basically I run a network of computers and need to know what region code the drives of the various computers are set to. I don't need to change the region, but I have no idea how to determine the region without going to each computer individually and sticking in a disc. I tried using Apple's cocoa DVD playback framework, but that requires that a disk be inserted into the drive, which sort of defeats the purpose.
So are there any APIs that I can use to determine the region code on a Mac Pro's DVD drive without requiring that a disc be inserted? I am willing to code in pretty much any language.
Thanks
I found some utilities that are capable of dealing with DVD region settings on OS X: DVD Info X, and Region X. DVD Info X will display the region code of your drive without requiring to have a DVD inserted.
Region X is more interesting because although it doesn't directly serve your purpose, its source is available. Looking at it I found that the ScanAll method in Region X.m is what you need. More specifically, the interesting case is the one where the disk name isn't found (because there's no disk mounted) and a SCSI command is used to find out the DVD drive's properties (the printf calls are my addition):
task = (*scsitaskinterface)->CreateSCSITask(scsitaskinterface);
if (task)
{
cdb[0] = 0xa4;
cdb[1] = 0x00;
cdb[2] = 0x00;
cdb[3] = 0x00;
cdb[4] = 0x00;
cdb[5] = 0x00;
cdb[6] = 0x00;
cdb[7] = 0x00;
cdb[8] = (sizeof(DVDInfo) >> 8) & 0xff;
cdb[9] = sizeof(DVDInfo) & 0xff;
cdb[10] = 0x08;
cdb[11] = 0x00;
memset(&DVDInfo, 0, sizeof(DVDInfo));
ProcessCDB(task, cdb, 12, DirIn, &DVDInfo, sizeof(DVDInfo), 30000);
printf("drive region %#hhx\n", DVDInfo.driveRegion);
printf("number of region changes left: %hhu\n", DVDInfo.numberUserResets);
if (DVDInfo.rpcScheme == 0) RPC1++;
if (DVDInfo.rpcScheme != 0) RPC2++;
(*task)->Release(task);
}
I ran this on my Macbook Pro and the result was as expected.
Obviously you'll need to massage it in order to isolate that part into something you can use, but I think that this code will be a useful starting point.
I don't have an answer as such, but I have 2 links for you:
Code (for windows, not for Mac) that explains how to read the region:
http://www.codeproject.com/KB/system/mydvdregion.aspx
Since these are pure SCSI commands - it is probably possible to adapt it for Mac.
ftp://ftp.san.ru/unix/soft.cvs/wine.git/wine-git/dlls/ntdll/cdrom.c
There is Mac support there - and they read DVD region there too.

Detecting appearance/disappearance of volumes on osx

I want to update a list of storage devices as the user inserts USB keys, adds external disks and mounts disk images. IOKit's IOServiceAddInterestNotification looks like the way to go, but the obvious use of registering general interest in kIOMediaClass only gives you notifications for unmounting of volumes and then only sometimes.
What's the right way to do this?
The following calls in DiskArbitration.h do exactly what I want:
DARegisterDiskAppearedCallback
DARegisterDiskDisappearedCallback
DARegisterDiskDescriptionChangedCallback
These cover insertion, removal (even of unmountable volumes)
metadata change events.
P.S. Don't forget to add your DASession to a runloop
or you won't get any callbacks.
I want to update a list of storage devices as the user inserts USB keys, adds external disks and mounts disk images.
I can get you two out of three with this piece of code, which I imagine wouldn't require a lot more work to give you the third.
File: USBNotificationExample.c
Description: This sample demonstrates how to use IOKitLib and IOUSBLib to set up asynchronous
callbacks when a USB device is attached to or removed from the system.
It also shows how to associate arbitrary data with each device instance.
http://opensource.apple.com/source/IOUSBFamily/IOUSBFamily-385.4.1/Examples/Another%20USB%20Notification%20Example/USBNotificationExample.c
I've personally used (a slightly modified copy of this code) for a long time, to monitor the connection of USB HDDs.
As you can see from this small sample, it may easily prove adaptable to monitor mounted drives. Or it may not. YMMV.
matchingDict = IOServiceMatching(kIOUSBDeviceClassName); // Interested in instances of class
// IOUSBDevice and its subclasses
and when it matches
void DeviceAdded(void *refCon, io_iterator_t iterator)
{
kern_return_t kr;
io_service_t usbDevice;
IOCFPlugInInterface **plugInInterface=NULL;
SInt32 score;
HRESULT res;
while ( (usbDevice = IOIteratorNext(iterator)) )
{
io_name_t deviceName;
CFStringRef deviceNameAsCFString;
MyPrivateData *privateDataRef = NULL;
UInt32 locationID;
printf("Device 0x%08x added.\n", usbDevice);
and so forth, and so on.
Would watching /Volumes for changes do what you need?
If you happen to be working at the Cocoa level, you can also register to receive the following notifications from NSWorkspace:
NSWorkspaceDidMountNotification
NSWorkspaceDidRenameVolumeNotification
NSWorkspaceWillUnmountNotification
NSWorkspaceDidUnmountNotification

Resources