0

I write the AES256Decrypt method using objective-c.

But When I return the decrypt NSData , the memory is not release ,

my code below:

- (NSData*)AES256DecryptWithKey:(NSString*)key andIv:(NSData*)iv{

    char keyPtr[kCCKeySizeAES256 + 1];
    bzero(keyPtr, sizeof(keyPtr));

    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    NSUInteger dataLength = [self length];

    size_t bufferSize           = dataLength + kCCBlockSizeAES128;
    void* buffer                = malloc(bufferSize);

    size_t numBytesDecrypted    = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                          keyPtr, kCCKeySizeAES256,
                                          iv.bytes /* initialization vector (optional) */,
                                          [self bytes], dataLength, /* input */
                                          buffer, bufferSize, /* output */
                                          &numBytesDecrypted);

    if (cryptStatus == kCCSuccess)
    {
        // ==============here==============
        return  [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted freeWhenDone:YES];
    }
    free(buffer); //free the buffer;
    return nil;

}

I found cryptStatus == kCCSuccess status,

it return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted freeWhenDone:YES];

the code not free(buffer);

If I move the free(buffer) up to

[NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted freeWhenDone:YES];

The buffer data will release so early.

How can I cost down the memory to prevent the memory leak in the decrypt method?

thank you very much.

zaph
  • 111,848
  • 21
  • 189
  • 228
dickfala
  • 3,246
  • 3
  • 31
  • 52
  • 1
    You don't need to free it in that case. The point of passing `YES` to the `freeWhenDone` parameter is that the `NSData` instance will free the buffer itself when it deallocates. – dan Mar 07 '17 at 13:53
  • But I found when I call the method, NSData *contentDecryptedData = [myEncryptedData myKey andIv:myIV]; The next line set the break point , I see the memory , it is add more memory. So I think it is not release the buffer. – dickfala Mar 07 '17 at 13:58
  • 1
    Because the buffer is still being used at that point. If you released it your `contentDecryptedData` would have its data released out from under it and your app would probably crash when you tried to use it. – dan Mar 07 '17 at 14:03
  • Sorry, If I want to using contentDecryptedData cast to the NSMutableData, I set NSMutableData *contentDecryptedMutableData = [NSMutableData dataWithData:contentDecryptedData ]; contentDecryptedData = nil; The memory is double, how to release the contentDecryptedData. thank you. – dickfala Mar 07 '17 at 14:08
  • Note: An easy way to handle the IV is to prefix the encrypted data with the IV , it does not need to be secret. That way it is available for decryption and does not need to be explicitly shared. Of course the IV should be a series of random bytes. – zaph Mar 07 '17 at 15:28

1 Answers1

0

A simple way is to use NSMutableData for the buffer, pass mutable bytes and resize after decryption.

Allocate the output data:

NSMutableData  *dataOut = [NSMutableData dataWithLength:dataIn.length];

Pass the output data:

dataOut.mutableBytes, dataOut.length

Set the decrypted data length:

dataOut.length = numBytesDecrypted;

Return the decrypted data:

return dataOut;

See SO example

Community
  • 1
  • 1
zaph
  • 111,848
  • 21
  • 189
  • 228