diff --git a/native/expo-modules/comm-expo-package/ios/AESCryptoModule.swift b/native/expo-modules/comm-expo-package/ios/AESCryptoModule.swift --- a/native/expo-modules/comm-expo-package/ios/AESCryptoModule.swift +++ b/native/expo-modules/comm-expo-package/ios/AESCryptoModule.swift @@ -37,7 +37,7 @@ } } -// ObjC-compatible module, used from Objective-C code in NSE +// ObjC-compatible module, used from Objective-C code in NSE and from Rust @objc(AESCryptoModuleObjCCompat) public class AESCryptoModuleObjCCompat: NSObject { @@ -48,6 +48,15 @@ try! generateKey(destinationPtr: destinationPtr, byteLength: destination.length) } + + @objc(generateKey:destinationLength:withError:) + public static func generateKeyCompat(destinationPtr: UnsafeMutableRawPointer, + destinationLength: Int) throws { + let destinationBufferPtr = UnsafeMutableRawBufferPointer(start: destinationPtr, + count: destinationLength) + try generateKey(destinationPtr: destinationBufferPtr, + byteLength: destinationLength) + } @objc(encryptedLength:) public func encryptedLengthCompat(plaintext: Data) -> NSInteger { @@ -67,6 +76,21 @@ destinationLength: destination.length) } + @objc(encryptWithKey:plaintext:destinationPtr:destinationLength:withError:) + public static func encryptCompat(rawKey: Data, + plaintext: Data, + destinationPtr: UnsafeMutableRawPointer, + destinationLength: Int) throws { + let destinationBufferPtr = UnsafeMutableRawBufferPointer(start: destinationPtr, + count: destinationLength) + + try encrypt(rawKey: rawKey, + plaintext: plaintext, + plaintextLength: plaintext.count, + destinationPtr: destinationBufferPtr, + destinationLength: destinationLength) + } + @objc(decryptedLength:) public func decryptedLengthCompat(sealedData: Data) -> NSInteger { return sealedData.count - IV_LENGTH - TAG_LENGTH @@ -85,6 +109,20 @@ destinationLength: destination.length) } + @objc(decryptWithKey:sealedData:destinationPtr:destinationLength:withError:) + public static func decryptCompat(rawKey: Data, + sealedData: Data, + destinationPtr: UnsafeMutableRawPointer, + destinationLength: Int) throws { + let destinationBufferPtr = UnsafeMutableRawBufferPointer(start: destinationPtr, + count: destinationLength) + try decrypt(rawKey: rawKey, + sealedData: sealedData, + sealedDataLength: sealedData.count, + destinationPtr: destinationBufferPtr, + destinationLength: destinationLength) + } + } // MARK: - Function implementations diff --git a/native/ios/Comm/AESCrypto.mm b/native/ios/Comm/AESCrypto.mm --- a/native/ios/Comm/AESCrypto.mm +++ b/native/ios/Comm/AESCrypto.mm @@ -1,20 +1,62 @@ #import "AESCrypto.h" +#import "AESCryptoModuleObjCCompat.h" +#import namespace comm { void AESCrypto::generateKey(rust::Slice buffer) { + NSError *keyGenerationError = nil; + [AESCryptoModuleObjCCompat generateKey:buffer.data() + destinationLength:buffer.size() + withError:&keyGenerationError]; + if (keyGenerationError) { + throw std::runtime_error( + [[keyGenerationError localizedDescription] UTF8String]); + } } void AESCrypto::encrypt( rust::Slice key, rust::Slice plaintext, rust::Slice sealedData) { + NSData *keyBuffer = [NSData dataWithBytesNoCopy:key.data() + length:key.size() + freeWhenDone:NO]; + NSData *plaintextBuffer = [NSData dataWithBytesNoCopy:plaintext.data() + length:plaintext.size() + freeWhenDone:NO]; + NSError *encryptError = nil; + [AESCryptoModuleObjCCompat encryptWithKey:keyBuffer + plaintext:plaintextBuffer + destinationPtr:sealedData.data() + destinationLength:sealedData.size() + withError:&encryptError]; + + if (encryptError) { + throw std::runtime_error([[encryptError localizedDescription] UTF8String]); + } } void AESCrypto::decrypt( rust::Slice key, rust::Slice sealedData, rust::Slice plaintext) { + NSData *keyBuffer = [NSData dataWithBytesNoCopy:key.data() + length:key.size() + freeWhenDone:NO]; + NSData *sealedDataBuffer = [NSData dataWithBytesNoCopy:sealedData.data() + length:sealedData.size() + freeWhenDone:NO]; + NSError *decryptError = nil; + [AESCryptoModuleObjCCompat decryptWithKey:keyBuffer + sealedData:sealedDataBuffer + destinationPtr:plaintext.data() + destinationLength:plaintext.size() + withError:&decryptError]; + + if (decryptError) { + throw std::runtime_error([[decryptError localizedDescription] UTF8String]); + } } } // namespace comm diff --git a/native/ios/Comm/CommAESCryptoUtils/AESCryptoModuleObjCCompat.h b/native/ios/Comm/CommAESCryptoUtils/AESCryptoModuleObjCCompat.h --- a/native/ios/Comm/CommAESCryptoUtils/AESCryptoModuleObjCCompat.h +++ b/native/ios/Comm/CommAESCryptoUtils/AESCryptoModuleObjCCompat.h @@ -3,15 +3,28 @@ @interface AESCryptoModuleObjCCompat : NSObject - (BOOL)generateKey:(NSMutableData *_Nonnull)destination withError:(NSError *_Nullable *_Nullable)error; ++ (BOOL)generateKey:(void *_Nonnull)destinationPtr + destinationLength:(NSInteger)destinationLength + withError:(NSError *_Nullable *_Nullable)error; - (NSInteger)encryptedLength:(NSData *_Nonnull)plaintext; - (BOOL)encryptWithKey:(NSData *_Nonnull)rawKey plaintext:(NSData *_Nonnull)plaintext destination:(NSMutableData *_Nonnull)destination withError:(NSError *_Nullable *_Nullable)error; ++ (BOOL)encryptWithKey:(NSData *_Nonnull)rawKey + plaintext:(NSData *_Nonnull)plaintext + destinationPtr:(void *_Nonnull)destinationPtr + destinationLength:(NSInteger)destinationLength + withError:(NSError *_Nullable *_Nullable)error; - (NSInteger)decryptedLength:(NSData *_Nonnull)sealedData; - (BOOL)decryptWithKey:(NSData *_Nonnull)rawKey sealedData:(NSData *_Nonnull)sealedData destination:(NSMutableData *_Nonnull)destination withError:(NSError *_Nullable *_Nullable)error; ++ (BOOL)decryptWithKey:(NSData *_Nonnull)rawKey + sealedData:(NSData *_Nonnull)sealedData + destinationPtr:(void *_Nonnull)destinationPtr + destinationLength:(NSInteger)destinationLength + withError:(NSError *_Nullable *_Nullable)error; - (nonnull instancetype)init; @end