CMSDecoderFinalizeMessage crashing with self-generated CMS message

Hi,

I face a strange issue with CMSDecoder.

When I encrypt + sign a message with CMSEncodeContent and then try to decode the same CFData using CMSDecoderUpdateMessage/CMSDecoderFinalizeMessage the library crashes.

If I only encrypt the data the exception disappear but I cannot get back the content (nil). If I only sign the data I can get the original message using CMSDecoderCopyContent.

Does anybody already faced this issue ? Could it be related to my identities / certificates ?

Reproduced with macOS 12.5.1. Sample code bellow.

NSString*   message = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.";

NSData* rawData = [message dataUsingEncoding:NSASCIIStringEncoding];  

id  signIdentity = nil;
id  encryptCertificate = nil;

// Load signing identity
NSDictionary*    signQuery = @{
        (id)kSecClass:(id)kSecClassIdentity,
        (id)kSecMatchTrustedOnly:@YES,
        (id)kSecMatchIssuers:mySigningCAIssuer,
        (id)kSecReturnRef:@YES
};

CFTypeRef   item = nil;
OSStatus    status = SecItemCopyMatching((CFDictionaryRef)signQuery, &item);
if (status == errSecSuccess) {
        signIdentity = CFBridgingRelease(item);
}

// Load encryption certificate
NSDictionary*    encryptQuery = @{
        (id)kSecClass:(id)kSecClassCertificate,
        (id)kSecMatchTrustedOnly:@YES,
        (id)kSecMatchIssuers:myEncryptCAIssuer,
        (id)kSecReturnRef:@YES
};

status = SecItemCopyMatching((CFDictionaryRef)encryptQuery, &item);
if (status == errSecSuccess) {
        encryptCertificate = CFBridgingRelease(item);
}

// Export encrypted data
CFDataRef   dataRef = nil;
status = CMSEncodeContent((__bridge SecIdentityRef)signIdentity, nil, nil, false, kCMSAttrSmimeEncryptionKeyPrefs, rawData.bytes, rawData.length, &dataRef);

NSData* encodedData = CFBridgingRelease(dataRef);
[encodedData writeToFile:@"/Users/Shared/test-encrypted.p7m" atomically:true];

// Import encrypted data
CMSDecoderRef  cmsDecoderRef = nil;
status = CMSDecoderCreate(&cmsDecoderRef);
status = CMSDecoderUpdateMessage(cmsDecoderRef, encodedData.bytes, encodedData.length);

if (status == errSecSuccess) {
        status = CMSDecoderFinalizeMessage(cmsDecoderRef);  // Exception is sent here when signing + encrypting
}

// Get content
CFDataRef   content = nil;
status = CMSDecoderCopyContent(cmsDecoderRef, &content);   // nil is received when encrypting only - OK when signing only

CFRelease(cmsDecoderRef);

It’s hard to say whether this is a bug in the CMS decoder or whether you’re just ‘holding it wrong’. To start, can you post a crash report for he problem. See Posting a Crash Report for advice on how to do that.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Please find the related crash report.

Thanks for the crash report.

I’m not 100% sure what’s going on here but I suspect that this is a problem on the Apple side of the fence. I recommend that you file a bug about this. Please post your bug number, just for the record.

If you want to dig into this yourself, the code for this is all in Darwin so you can rummage through that. The place to start would be here.

If this is important to you should open a DTS tech support incident and that’ll allow me to allocate more time to look at it. However, fair warning: This might be Just a Bug™ and my conclusion might be that there’s no reasonable workaround.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks Eskimo for the suggestion. I filled a Feedback Assistant FB11420810 is that enough ?

I’ll start with Darwin hints and open a DTS if required.

I looked at Darwin source Security-Security-60158.140.3

Following call stack:

  • CMSDecoderFinalizeMessage (CMSDecoder.c)
  • SecCmsMessageIsEncrypted (cmsmessage.c)
  • SecCmsContentInfoGetChildContentInfo (cmscinfo.c)

On lines 115 or 119 or 123 or 127 of SecCmsContentInfoGetChildContentInfo if ptr is null ccinfo will memory fault. The ptr value is checked line 133 but this is too late. This would not solve my encryption but at least a fix here would avoid the exception.

In my situation it means one of data ptr is unexpectedly null. As the exception is only sent when signing & encrypting, I assumes this is SEC_OID_PKCS7_ENVELOPED_DATA case.

Looking at CMSEncoderCopyEncodedContent (CMSEncoder.cpp) line 1310 we can confirm that signed data is enveloped in encrypted data. Following call stack:

  • CMSEncoderCopyEncodedContent
  • CMSEncoderUpdateContent
  • SecCmsEncoderUpdate
  • cmsSetupForEnvelopedData
  • SecCmsEnvelopedDataCreate
  • SecCmsContentInfoSetContentEncAlg
  • SECOID_SetAlgorithmID

I'm not sure exactly what is asserted in SECOID_SetAlgorithmID but this might be an hint.

I filled a Feedback Assistant FB11420810 is that enough ?

Regarding that bug, AFAICT the engineering team asked for you a sysdiagnose and it seems like you thought you’d attached one but that didn’t happen. Please try again.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

CMSDecoderFinalizeMessage crashing with self-generated CMS message
 
 
Q