I just went to use libcrypto on Lion and it looks like the entire api has been deprecated. The man pages haven't been updated since 10.6.6.
Does anybody know what the replacement for libcrypto is on Lion?
libcrypto is part of OpenSSL, which hasn't changed much. It's not going away, but Apple recommends that developers use their CDSA (Common Data Security Architecture) library rather than using OpenSSL directly.
In case you know what you're doing and you just want to get rid of these warnings, one way is to add
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
to the relevant headers – in my case /usr/include/openssl/crypto.h and /usr/include/openssl/md5.h.
Ok, answering my own question here.
10.7 introduced Transforms into Security.framework, which is tied closely to SecKey. Transforms let you do lots of things, including encoding (eg. base64), digests, signing/verifying, and encryption.
Here's an example of how to sign some data. All of the transforms follow the same basic pattern; if you look in the Headers for Security.framework you'll see a header for each type of transform. These are from SecTransformReadTransform.h and SecSignVerifyTransform.h. I'm omitting any error checking or cleanup code here for simplicity.
NSData *dataToBeSigned = ;// Get this from somewhere. We set sha1 attributes down below, so this should be a sha1 digest
SecKeyRef *key = ;// Get this from somewhere; keychain or SecItemImport
SecGroupTransformRef group = SecTransformCreateGroupTransform();
CFReadStreamRef readStream = NULL;
SecTransformRef readTransform = NULL;
SecTransformRef signingTransform = NULL;
// Setup our input stream as well as an input transform
readStream = CFReadStreamCreateWithBytesNoCopy(kCFAllocatorDefault,
[dataToBeSigned bytes],
[dataToBeSigned length],
kCFAllocatorNull); // Pass Null allocator so it doesn't free NSData's bytes
readTransform = SecTransformCreateReadTransformWithReadStream(readStream);
// Setup a signing transform
signingTransform = SecSignTransformCreate(key, NULL);
SecTransformSetAttribute(signingTransform, kSecInputIsDigest, kCFBooleanTrue, NULL);
SecTransformSetAttribute(signingTransform, kSecDigestTypeAttribute, kSecDigestSHA1, NULL);
// Connect read and signing transform; Have read pass its data to the signer
SecTransformConnectTransforms(readTransform, kSecTransformOutputAttributeName,
self.signingTransformRef, kSecTransformInputAttributeName,
group, NULL);
// Execute the sequence of transforms (group)
// The last one in the connected sequence is the return value
NSData *signature = SecTransformExecute(group, NULL);
Related
I'm looking at Karabiner, the OSX keyboard remapper for Parallels development. According to this issue this is best fixed by filing a bug with Apple.
What is the alternative (if any) supported API to create such a functionality?
As noted by pkamb on the github issue that OP linked to (added since he posted), Apple technote TN2450 documents the proper API:
The IOKit HID APIs can be used for key remapping. The user will
provide a dictionary of key remapping that the HID event system will
apply to the keyboard. Listing 3 : Key Remapping using IOKit HID
APIs. // compiled with Xcode 8.2.1
#import <Foundation/Foundation.h>
#import <IOKit/hidsystem/IOHIDEventSystemClient.h>
#import <IOKit/hidsystem/IOHIDServiceClient.h>
#import <IOKit/hid/IOHIDUsageTables.h>
int main(int argc, char *argv[])
{
IOHIDEventSystemClientRef system;
CFArrayRef services;
uint64_t aKey = 0x700000004;
uint64_t bKey = 0x700000005;
NSArray *map = #[
#{#kIOHIDKeyboardModifierMappingSrcKey:#(aKey),
#kIOHIDKeyboardModifierMappingDstKey:#(bKey)},
#{#kIOHIDKeyboardModifierMappingSrcKey:#(bKey),
#kIOHIDKeyboardModifierMappingDstKey:#(aKey)},
];
system = IOHIDEventSystemClientCreateSimpleClient(kCFAllocatorDefault);
services = IOHIDEventSystemClientCopyServices(system);
for(CFIndex i = 0; i < CFArrayGetCount(services); i++) {
IOHIDServiceClientRef service = (IOHIDServiceClientRef)CFArrayGetValueAtIndex(services, i);
if(IOHIDServiceClientConformsTo(service, kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard)) {
IOHIDServiceClientSetProperty(service, CFSTR(kIOHIDUserKeyUsageMapKey), (CFArrayRef)map);
}
}
CFRelease(services);
CFRelease(system);
return 0;
}
Example:
If you are trying to re-map the command / option / control keys on an external USB keyboard, take a look at the enum's defined in IOHIDUsageTables.h. For example, a Z-88 keyboard can be remapped to match the key layout on a MacBookPro using this mapping:
NSArray *remap = #[
#{#kIOHIDKeyboardModifierMappingSrcKey:#(0x7000000E3),
#kIOHIDKeyboardModifierMappingDstKey:#(0x7000000E2)},
#{#kIOHIDKeyboardModifierMappingSrcKey:#(0x7000000E2),
#kIOHIDKeyboardModifierMappingDstKey:#(0x7000000E3)},
#{#kIOHIDKeyboardModifierMappingSrcKey:#(0x7000000E6),
#kIOHIDKeyboardModifierMappingDstKey:#(0x7000000E7)},
#{#kIOHIDKeyboardModifierMappingSrcKey:#(0x700000065),
#kIOHIDKeyboardModifierMappingDstKey:#(0x7000000E6)}
];
LeftGUI (E3) → LeftAlt (E2)
LeftAlt (E2) → LeftGUI (E3)
RightAlt (E6) → RightGUI (E7)
Application (65) → RightAlt (E6)
To undo a mapping, map the same keys back to their original values. Using the above example:
NSArray *unmap = #[
#{#kIOHIDKeyboardModifierMappingSrcKey:#(0x7000000E3),
#kIOHIDKeyboardModifierMappingDstKey:#(0x7000000E3)},
#{#kIOHIDKeyboardModifierMappingSrcKey:#(0x7000000E2),
#kIOHIDKeyboardModifierMappingDstKey:#(0x7000000E2)},
#{#kIOHIDKeyboardModifierMappingSrcKey:#(0x7000000E6),
#kIOHIDKeyboardModifierMappingDstKey:#(0x7000000E6)},
#{#kIOHIDKeyboardModifierMappingSrcKey:#(0x700000065),
#kIOHIDKeyboardModifierMappingDstKey:#(0x700000065)}
];
Karabiner-Elements is solid and versatile despite the sketchy documentation and user interface, excusable for a work in progress. There are many useful examples, e.g., this one which required dedicated tools and the Karabiner error log to generate the tricky JSON rules. Any key can be both a modifier and regular key, run a program, etc., all at once. Public domain on GitHub.
I have built some code to process video files on OSX, frame by frame. The following is an extract from the code which builds OK, opens the file, locates the video track (only track) and starts reading CMSampleBuffers without problem. However each CMSampleBufferRef I obtain returns NULL when I try to extract the pixel buffer frame. There's no indication in iOS documentation as to why I could expect a NULL return value or how I could expect to fix the issue. It happens with all the videos on which I've tested it, regardless of capture source or CODEC.
Any help greatly appreciated.
NSString *assetInPath = #"/Users/Dave/Movies/movie.mp4";
NSURL *assetInUrl = [NSURL fileURLWithPath:assetInPath];
AVAsset *assetIn = [AVAsset assetWithURL:assetInUrl];
NSError *error;
AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:assetIn error:&error];
AVAssetTrack *track = [assetIn.tracks objectAtIndex:0];
AVAssetReaderOutput *assetReaderOutput = [[AVAssetReaderTrackOutput alloc]
initWithTrack:track
outputSettings:nil];
[assetReader addOutput:assetReaderOutput];
// Start reading
[assetReader startReading];
CMSampleBufferRef sampleBuffer;
do {
sampleBuffer = [assetReaderOutput copyNextSampleBuffer];
/**
** At this point, sampleBuffer is non-null, has all appropriate attributes to indicate that
** it's a video frame, 320x240 or whatever and looks perfectly fine. But the next
** line always returns NULL without logging any obvious error message
**/
CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
if( pixelBuffer != NULL ) {
size_t width = CVPixelBufferGetWidth(pixelBuffer);
size_t height = CVPixelBufferGetHeight(pixelBuffer);
CVPixelBufferLockBaseAddress(pixelBuffer, 0);
...
other processing removed here for clarity
}
} while( ... );
To be clear, I've stripped all error checking code but no problems were being indicated in that code. i.e. The AVAssetReader is reading, CMSampleBufferRef looks fine etc.
You haven't specified any outputSettings when creating your AVAssetReaderTrackOutput. I've run into your issue when specifying "nil" in order to receive the video track's original pixel format when calling copyNextSampleBuffer. In my app I wanted to ensure no conversion was happening when calling copyNextSampleBuffer for the sake of performance, if this isn't a big concern for you, specify a pixel format in the output settings.
The following are Apple's recommend pixel formats based on the hardware capabilities:
kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
Because you haven't supplied any outputSettings you're forced to use the raw data contained within in the frame.
You have to get the block buffer from the sample buffer using CMSampleBufferGetDataBuffer(sampleBuffer), after you have that you need to get the actual location of the block buffer using
size_t blockBufferLength;
char *blockBufferPointer;
CMBlockBufferGetDataPointer(blockBuffer, 0, NULL, &blockBufferLength, &blockBufferPointer);
Look at *blockBufferPointer and decode the bytes using the frame header information for your required codec.
FWIW: Here is what official docs say for the return value of CMSampleBufferGetImageBuffer:
"Result is a CVImageBuffer of media data. The result will be NULL if the CMSampleBuffer does not contain a CVImageBuffer, or if the CMSampleBuffer contains a CMBlockBuffer, or if there is some other error."
Also note that the caller does not own the returned dataBuffer from CMSampleBufferGetImageBuffer, and must retain it explicitly if the caller needs to maintain a reference to it.
Hopefully this info helps.
I've run into a problem using the AudioFilePlayer audio unit with app sandboxing enabled on OS X 10.8. I have an AUGraph with only two nodes, consisting of an AudioFilePlayer unit connected to a DefaultOutput unit. The goal (right now) is to simply play a single audio file. If sandboxing is not enabled, everything works fine. If I enable sandboxing, AUGraphOpen() returns error -3000 (invalidComponentID). If I remove the file player node from the AUGraph, the error goes away, which at least implies that the audio file player is causing the problem.
Here's the code I use to set the file player node up:
OSStatus AddFileToGraph(AUGraph graph, NSURL *fileURL, AudioFileInfo *outFileInfo, AUNode *outFilePlayerNode)
{
OSStatus error = noErr;
if ((error = AudioFileOpenURL((__bridge CFURLRef)fileURL, kAudioFileReadPermission, 0, &outFileInfo->inputFile))) {
NSLog(#"Could not open audio file at %# (%ld)", fileURL, (long)error);
return error;
}
// Get the audio data format from the file
UInt32 propSize = sizeof(outFileInfo->inputFormat);
if ((error = AudioFileGetProperty(outFileInfo->inputFile, kAudioFilePropertyDataFormat, &propSize, &outFileInfo->inputFormat))) {
NSLog(#"Couldn't get format of input file %#", fileURL);
return error;
}
// Add AUAudioFilePlayer node
AudioComponentDescription fileplayercd = {0};
fileplayercd.componentType = kAudioUnitType_Generator;
fileplayercd.componentSubType = kAudioUnitSubType_AudioFilePlayer;
fileplayercd.componentManufacturer = kAudioUnitManufacturer_Apple;
fileplayercd.componentFlags = kAudioComponentFlag_SandboxSafe;
if ((error = AUGraphAddNode(graph, &fileplayercd, outFilePlayerNode))) {
NSLog(#"AUAudioFilePlayer node not found (%ld)", (long)error);
return error;
}
return error;
}
Note that fileURL in the AudioFileOpenURL() call is a URL obtained from security scoped bookmark data, and is the URL to a file that has been dragged into the application by the user.
If I set the com.apple.security.temporary-exception.audio-unit-host sandboxing entitlement, when AUGraphOpen() is called, the user is prompted to lower security settings, and assuming they accept, playback again works fine (the sandbox is disabled).
So, this points to the AudioFilePlayer unit not being sandbox-safe/compatible. Is this true? It's difficult to believe that Apple wouldn't have fixed such an important part of the CoreAudio API to be sandbox compatible. Also note that I specify the kAudioComponentFlag_SandboxSafe flag in the description passed to AUGraphAddNode, and that call does not fail. Also, I can only find one reference to AudioFilePlayer not being sandbox-safe online, in the form of this post to the CoreAudio mailing list, and it didn't receive any replies. Perhaps I'm making some other subtle mistake that happens to cause a problem with sandboxing enabled, but not when it's off (I'm new to Core Audio)?
When writing a new Core Image filter, you need to write the kernel in the Core Image Kernel Language which is a mildly mutate OpenGL Shader Language. You compile these at runtime with something like this…
NSString *myCode = ...
NSArray *kernels = [CIKernel kernelsWithString:myCode];
The problem is any syntax error and you just get back a nil instead of an array. The documented API does not suggest a mechanism to get diagnostic information.
If you work on your filter in Quartz Composer, as recommended in the Apple docs, you will notice that it can give you syntax error information. (This only works for simple filters.)
So, how do you get diagnostic information back for an bad kernel source file?
Update: Depending on circumstances, you may get formatted lines on your console. If you are so lucky then you needn't worry about this, just look for lines like:
8: error: in function kernel vec4 clipDetection (uniform in sampler, uniform in float)
8: error: unknown variable name: gratuitous
Of course if you still need to get hold of the information…
If you use introspection on the CIKernel class, you will find a kernelsWithString:messageLog: method. There is no public interface to it, but don't let that stop you…
NSString *myCode = ...
NSMutableArray *messageLog = [NSMutableArray array];
NSArray *kernels = [[CIKernel class] performSelector:#selector(kernelsWithString:messageLog:) withObject:myCode withObject:messageLog];
if ( messageLog.count > 0) NSLog(#"Error: %#", messageLog.description);
The messageLog argument wants to be a mutable array. In the event of errors, it will have some dictionaries put into it. The contents of these are documented nowhere visible on the internet, but they look something like this (in a case where I added "gratuitous error" to a kernel's source)…
2012-12-06 17:56:53.077 MyProgram[14334:303] Error: (
{
CIKernelMessageDescription = "kernel vec4 clipDetection (uniform in sampler, uniform in float)";
CIKernelMessageLineNumber = 8;
CIKernelMessageType = CIKernelMessageTypeFunctionName;
},
{
CIKernelMessageDescription = "unknown variable name: gratuitous";
CIKernelMessageLineNumber = 8;
CIKernelMessageType = CIKernelMessageTypeError;
}
)
As always, think twice or more about leaving this in shipping code. It is undocumented and Apple could do anything to it at any time. They might even, you know, document it.
I am using Lion and Xcode 4.1.
SecKeyRawSign is not documented for OSX still it can be called and successfully signed for RSA certificate but failed with EC Cert.
SecKeyRawSign method returns -50 i.e. invalid parameters for ec cert-384.
Can SecKeyRawSign be used for OSX and EC Cert? If yes what would be the padding parameter?
Thanks in advance.
SecKeyRawSign is a private function in Mac OS 10.6 and 10.7, so you shouldn't use it. Its problem with ECC certificates may just be one of the reasons it has not (yet?) been made public.
The official high-level API for data signing in 10.7 is SecSignTransformCreate in Security Transforms. It should automatically use a suitable digest algorithm; if not, you just set kSecDigestTypeAttribute and kSecDigestLengthAttribute to whatever you need. AFAIK the padding algorithm is not configurable.
On 10.6 or below, you have to use CDSA. First, you create a context with CSSM_CSP_CreateSignatureContext. The signature algorithm is CSSM_ALGID_SHA512WithECDSA (or similar); you can get the other arguments from SecKeyGetCSPHandle, SecKeyGetCSSMKey, and SecKeyGetCredentials. Once you have the signing context, you sign your data with CSSM_SignData. The digest algorithm should be CSSM_ALGID_NONE.
The padding is best explained by Thomas Pornin's answer to another question.
#Fnord
Thanks for response. I wrote following code:
CFDataRef
CreateSignature (SecKeyRef privateKeyRef, CFDataRef plaintext, CFErrorRef &error)
{
SecTransformRef signingTransform = SecSignTransformCreate(privateKeyRef, error);
if (signingTransform == NULL)
return NULL;
Boolean success = SecTransformSetAttribute(signingTransform,
kSecTransformInputAttributeName,
plaintext,
error);
if (!success) {
CFRelease(signingTransform);
return NULL;
}
CFDataRef signature = SecTransformExecute(signingTransform, error);
CFRetain(signature);
CFRelease(signingTransform);
return signature;
}