Marino Faggiana 7 年之前
父節點
當前提交
21dfd5de43

+ 0 - 0
Libraries external/AesGcm/.gitkeep


+ 40 - 0
Libraries external/AesGcm/Components/IAGAesComponents.h

@@ -0,0 +1,40 @@
+//
+//  IAGAesComponents.h
+//  Pods
+//
+//  Created by Enrique de la Torre (dev) on 20/09/2016.
+//
+//
+
+#import <Foundation/Foundation.h>
+
+#import "IAGTypes.h"
+
+/**
+ [As mentioned in the documentation](http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf): "The operations of GCM depend on the choice of an underlying symmetric key block cipher ...". In this case, the chosen algorithm is AES and here you can find the "forward cipher function" used in this implementation of GCM.
+ */
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface IAGAesComponents : NSObject
+
+/**
+ "Forward cipher function" required by GCM and based on AES.
+
+ @param cipheredBlock Output parameter with the resulting ciphered data
+ @param block Input parameter with the data to cipher
+ @param key Key used to cipher the data with length: kCCKeySizeAES128 (16), kCCKeySizeAES192 (24) or kCCKeySizeAES256 (32) bytes
+ @param error Set to a value if the operation fails
+ 
+ @return YES if the operation is successful, NO in other case
+ 
+ @see IAGErrorFactory
+ */
++ (BOOL)getCipheredBlock:(IAGBlockType _Nonnull )cipheredBlock
+       byUsingAESOnBlock:(IAGBlockType _Nonnull )block
+                 withKey:(NSData *)key
+                   error:(NSError **)error;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 46 - 0
Libraries external/AesGcm/Components/IAGAesComponents.m

@@ -0,0 +1,46 @@
+//
+//  IAGAesComponents.m
+//  Pods
+//
+//  Created by Enrique de la Torre (dev) on 20/09/2016.
+//
+//
+
+#import <CommonCrypto/CommonCryptor.h>
+
+#import "IAGAesComponents.h"
+
+#import "IAGError.h"
+
+@implementation IAGAesComponents
+
+#pragma mark - Public class methods
+
++ (BOOL)getCipheredBlock:(IAGBlockType)cipheredBlock
+       byUsingAESOnBlock:(IAGBlockType)block
+                 withKey:(NSData *)key
+                   error:(NSError **)error
+{
+    size_t dataOutMoved = 0;
+    CCCryptorStatus status = CCCrypt(kCCEncrypt,
+                                     kCCAlgorithmAES,
+                                     kCCOptionECBMode,
+                                     key.bytes,
+                                     key.length,
+                                     nil,
+                                     block,
+                                     sizeof(IAGBlockType),
+                                     cipheredBlock,
+                                     sizeof(IAGBlockType),
+                                     &dataOutMoved);
+    BOOL success = ((status == kCCSuccess) && (dataOutMoved  == sizeof(IAGBlockType)));
+
+    if (!success && error)
+    {
+        *error = [IAGErrorFactory errorAESFailed];
+    }
+
+    return success;
+}
+
+@end

+ 102 - 0
Libraries external/AesGcm/Components/IAGBitwiseComponents.h

@@ -0,0 +1,102 @@
+//
+//  IAGBitwiseComponents.h
+//  Pods
+//
+//  Created by Enrique de la Torre (dev) on 25/09/2016.
+//
+//
+
+#import <Foundation/Foundation.h>
+
+#import "IAGTypes.h"
+
+/**
+ Number of bits in a byte ... obviously 8 ... the only purpose of this constant is to easily track where this value is used and what for.
+ */
+extern const IAGUInt8Type IAGBitsInUChar;
+
+/**
+ Position of the last bit in a block.
+ 
+ @see [IAGBitwiseComponents isMostSignificantBitActivatedAtPosition:inBlock:]
+ @see [IAGBitwiseComponents isLeastSignificantBitActivatedAtPosition:inBlock:]
+ */
+extern const IAGUInt8Type IAGMaxBitPositionInABlock;
+
+/**
+ This class provides a bunch of methods able to work with data on bit or byte level.
+ */
+
+@interface IAGBitwiseComponents : NSObject
+
+/**
+ Perform a XOR operation with 2 blocks and copy the result in a third one.
+ 
+ @param buffer Output parameter
+ @param value1 Input parameter
+ @param value2 Input parameter
+ */
++ (void)getXorBlock:(IAGBlockType)buffer
+          withBlock:(IAGBlockType)value1
+           andBlock:(IAGBlockType)value2;
+
+/**
+ Perform a XOR operation with 2 buffers of the same size and copy the result in a third one.
+ 
+ @param buffer Output parameter
+ @param value1 Input parameter
+ @param value2 Input parameter
+ @param bufferSize Size of the 3 buffers
+ */
++ (void)getXorBuffer:(IAGUCharType *)buffer
+          withBuffer:(IAGUCharType *)value1
+              buffer:(IAGUCharType *)value2
+          bufferSize:(IAGSizeType)bufferSize;
+
+/**
+ Move one bit to the right a block.
+ 
+ @param shiftedBlock Output parameter
+ @param block Input parameter
+ */
++ (void)getSingleRightShiftedBlock:(IAGBlockType)shiftedBlock withBlock:(IAGBlockType)block;
+
+/**
+ Get left-most msbSyze bytes out of an input buffer.
+
+ @param msb Ouput parameter
+ @param msbSyze Size of msb, it has to be less than or equal to bufferSize
+ @param buffer Input parameter
+ @param bufferSize Size of buffer
+ */
++ (void)getMostSignificantBytes:(IAGUCharType *)msb
+                       withSize:(IAGSizeType)msbSyze
+                       inBuffer:(IAGUCharType *)buffer
+                       withSize:(IAGSizeType)bufferSize;
+
+/**
+ Get right-most lsbSyze bytes out of an input buffer.
+
+ @param lsb Ouput parameter
+ @param lsbSyze Size of lsb, it has to be less than or equal to bufferSize
+ @param buffer Input parameter
+ @param bufferSize Size of buffer
+ */
++ (void)getLeastSignificantBytes:(IAGUCharType *)lsb
+                        withSize:(IAGSizeType)lsbSyze
+                        inBuffer:(IAGUCharType *)buffer
+                        withSize:(IAGSizeType)bufferSize;
+
+/**
+ @return YES if the left-most bit at the given position is 1
+ */
++ (BOOL)isMostSignificantBitActivatedAtPosition:(IAGUInt8Type)position
+                                        inBlock:(IAGBlockType)block;
+
+/**
+ @return YES if the right-most bit at the given position is 1
+ */
++ (BOOL)isLeastSignificantBitActivatedAtPosition:(IAGUInt8Type)position
+                                         inBlock:(IAGBlockType)block;
+
+@end

+ 94 - 0
Libraries external/AesGcm/Components/IAGBitwiseComponents.m

@@ -0,0 +1,94 @@
+//
+//  IAGBitwiseComponents.m
+//  Pods
+//
+//  Created by Enrique de la Torre (dev) on 25/09/2016.
+//
+//
+
+#import "IAGBitwiseComponents.h"
+
+const IAGUInt8Type IAGBitsInUChar = 8;
+const IAGUInt8Type IAGMaxBitPositionInABlock = (IAGBitsInUChar * sizeof(IAGBlockType) - 1);
+
+@implementation IAGBitwiseComponents
+
++ (void)getXorBlock:(IAGBlockType)buffer
+          withBlock:(IAGBlockType)value1
+           andBlock:(IAGBlockType)value2
+{
+    [IAGBitwiseComponents getXorBuffer:buffer
+                            withBuffer:value1
+                                buffer:value2
+                            bufferSize:sizeof(IAGBlockType)];
+}
+
++ (void)getXorBuffer:(IAGUCharType *)buffer
+          withBuffer:(IAGUCharType *)value1
+              buffer:(IAGUCharType *)value2
+          bufferSize:(IAGSizeType)bufferSize
+{
+    for (IAGSizeType i = 0; i < bufferSize; i++)
+    {
+        buffer[i] = (value1[i] ^ value2[i]);
+    }
+}
+
++ (void)getSingleRightShiftedBlock:(IAGBlockType)shiftedBlock withBlock:(IAGBlockType)block
+{
+    for (IAGSizeType i = 0; i < sizeof(IAGBlockType); i++)
+    {
+        shiftedBlock[i] = block[i] >> 1;
+
+        if ((i > 0) && (block[i - 1] & 0x01))
+        {
+            shiftedBlock[i] = (shiftedBlock[i] | 0x80);
+        }
+    }
+}
+
++ (void)getMostSignificantBytes:(IAGUCharType *)msb
+                       withSize:(IAGSizeType)msbSyze
+                       inBuffer:(IAGUCharType *)buffer
+                       withSize:(IAGSizeType)bufferSize
+{
+    NSParameterAssert(msbSyze <= bufferSize);
+
+    memcpy(msb, buffer, msbSyze);
+}
+
++ (void)getLeastSignificantBytes:(IAGUCharType *)lsb
+                        withSize:(IAGSizeType)lsbSyze
+                        inBuffer:(IAGUCharType *)buffer
+                        withSize:(IAGSizeType)bufferSize
+{
+    NSParameterAssert(lsbSyze <= bufferSize);
+
+    memcpy(lsb, buffer + (bufferSize - lsbSyze), lsbSyze);
+}
+
++ (BOOL)isMostSignificantBitActivatedAtPosition:(IAGUInt8Type)position
+                                        inBlock:(IAGBlockType)block
+{
+    NSParameterAssert(position <= IAGMaxBitPositionInABlock);
+
+    IAGUCharType mostSignificantByte = block[position / IAGBitsInUChar];
+    IAGUCharType mask = 0x80 >> (position % IAGBitsInUChar);
+    IAGUCharType mostSignificantBit = (mostSignificantByte & mask);
+
+    return (mostSignificantBit != 0);
+}
+
++ (BOOL)isLeastSignificantBitActivatedAtPosition:(IAGUInt8Type)position
+                                         inBlock:(IAGBlockType)block
+{
+    NSParameterAssert(position <= IAGMaxBitPositionInABlock);
+
+    IAGUCharType leastSignificantByte = block[(IAGMaxBitPositionInABlock - position) / IAGBitsInUChar];
+    IAGUCharType mask = 0x01 << (position % IAGBitsInUChar);
+    IAGUCharType leastSignificantBit = (leastSignificantByte & mask);
+
+    return (leastSignificantBit != 0);
+}
+
+@end

+ 45 - 0
Libraries external/AesGcm/Components/IAGGcmEndianness.h

@@ -0,0 +1,45 @@
+//
+//  IAGGcmEndianness.h
+//  Pods
+//
+//  Created by Enrique de la Torre (dev) on 25/09/2016.
+//
+//
+
+#import <Foundation/Foundation.h>
+
+#import "IAGTypes.h"
+
+/**
+ Use the methods in this class to converts integers from/to GCM format to/from the host’s native byte order.
+ */
+@interface IAGGcmEndianness : NSObject
+
+/**
+ Convert a 32-bit unsigned integer with host’s native byte order to GCM format.
+
+ @param arg 32-bit unsigned integer with host’s native byte order
+ 
+ @return 32-bit unsigned integer in GCM format
+ */
++ (IAGUInt32Type)swapUInt32HostToGcm:(IAGUInt32Type)arg;
+
+/**
+ Convert a 32-bit unsigned integer in GCM format to host’s native byte order.
+
+ @param arg 32-bit unsigned integer in GCM format
+
+ @return 32-bit unsigned integer with host’s native byte order
+ */
++ (IAGUInt32Type)swapUInt32GcmToHost:(IAGUInt32Type)arg;
+
+/**
+ Convert a 64-bit unsigned integer with host’s native byte order to GCM format.
+
+ @param arg 64-bit unsigned integer with host’s native byte order
+
+ @return 64-bit unsigned integer in GCM format
+ */
++ (IAGUInt64Type)swapUInt64HostToGcm:(IAGUInt64Type)arg;
+
+@end

+ 28 - 0
Libraries external/AesGcm/Components/IAGGcmEndianness.m

@@ -0,0 +1,28 @@
+//
+//  IAGGcmEndianness.m
+//  Pods
+//
+//  Created by Enrique de la Torre (dev) on 25/09/2016.
+//
+//
+
+#import "IAGGcmEndianness.h"
+
+@implementation IAGGcmEndianness
+
++ (IAGUInt32Type)swapUInt32HostToGcm:(IAGUInt32Type)arg
+{
+    return CFSwapInt32HostToBig(arg);
+}
+
++ (IAGUInt32Type)swapUInt32GcmToHost:(IAGUInt32Type)arg
+{
+    return CFSwapInt32BigToHost(arg);
+}
+
++ (IAGUInt64Type)swapUInt64HostToGcm:(IAGUInt64Type)arg
+{
+    return CFSwapInt64HostToBig(arg);
+}
+
+@end

+ 72 - 0
Libraries external/AesGcm/Components/IAGGcmMathComponents.h

@@ -0,0 +1,72 @@
+//
+//  IAGGcmMathComponents.h
+//  Pods
+//
+//  Created by Enrique de la Torre (dev) on 20/09/2016.
+//
+//
+
+#import <Foundation/Foundation.h>
+
+#import "IAGTypes.h"
+
+/**
+ Mathematical components used by the authenticated encryption and authenticated decryption functions.
+ 
+ @see IAGAesGcm
+ */
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface IAGGcmMathComponents : NSObject
+
+/**
+ Quoting the documentation [here](http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf): "The authentication mechanism within GCM is based on a hash function, called GHASH, that features multiplication by a fixed parameter, called the hash subkey, within a binary Galois field.".
+
+ @param ghashBlock Output parameter with the hash block
+ @param buffer Input parameter with the data to hash
+ @param bufferSize Length of the buffer, it has to be a multiple of sizeof(IAGBlockType)
+ @param hashSubkey The hash subkey
+ */
++ (void)getGhashBlock:(IAGBlockType _Nonnull )ghashBlock
+           withBuffer:(IAGUCharType *)buffer
+           bufferSize:(IAGSizeType)bufferSize
+           hashSubkey:(IAGBlockType _Nonnull )hashSubkey;
+
+/**
+ This method generates the counter buffers used during the encryption/decryption process.
+
+ @param gcounterBuffer Output paramter with same size than inpit buffer
+ @param buffer Input parameter
+ @param bufferSize Size of the input buffer
+ @param icb Initial Counter Block
+ @param key Key used by the "Forward cipher function"
+ @param error Set to a value if the operation fails
+
+ @return YES if the operation is successful, NO in other case
+
+ @see IAGAesGcm
+ @see IAGErrorFactory
+ @see [IAGAesComponents getCipheredBlock:byUsingAESOnBlock:withKey:error:]
+ */
++ (BOOL)getGCounterBuffer:(IAGUCharType *)gcounterBuffer
+               withBuffer:(IAGUCharType *)buffer
+               bufferSize:(IAGSizeType)bufferSize
+      initialCounterBlock:(IAGBlockType _Nonnull )icb
+                      key:(NSData *)key
+                    error:(NSError **)error;
+
+/**
+ Increment the right-most 32 bits of the input buffer, regarded as an integer (modulo 2^32), and leave the remaining left-most bits unchanged.
+
+ @param incBuffer Output parameter
+ @param buffer Input paramater
+ @param size Size of both buffers, it has to be greater than or equal to sizeof(IAGUInt32Type)
+ */
++ (void)get32BitIncrementedBuffer:(IAGUCharType *)incBuffer
+                       withBuffer:(IAGUCharType *)buffer
+                             size:(IAGSizeType)size;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 212 - 0
Libraries external/AesGcm/Components/IAGGcmMathComponents.m

@@ -0,0 +1,212 @@
+//
+//  IAGGcmMathComponents.m
+//  Pods
+//
+//  Created by Enrique de la Torre (dev) on 20/09/2016.
+//
+//
+
+#import "IAGGcmMathComponents.h"
+
+#import "IAGAesComponents.h"
+#import "IAGBitwiseComponents.h"
+#import "IAGError.h"
+#import "IAGGcmEndianness.h"
+
+@implementation IAGGcmMathComponents
+
+#pragma mark - Public class methods
+
++ (void)getGhashBlock:(IAGBlockType)ghashBlock
+           withBuffer:(IAGUCharType *)buffer
+           bufferSize:(IAGSizeType)bufferSize
+           hashSubkey:(IAGBlockType)hashSubkey
+{
+    NSParameterAssert((bufferSize % sizeof(IAGBlockType)) == 0);
+
+    // Steps:
+    // 1. Let X1, X 2, ... , X m-1, X m denote the unique sequence of blocks such that
+    //    X = X 1 || X 2 || ... || X m-1 || X m.
+    // 2. Let Y0 be the “zero block,” 0^128.
+    IAGBlockType y;
+    memset(y, 0x00, sizeof(IAGBlockType));
+
+    // 3. For i = 1, ..., m, let Yi = (Yi-1 ⊕ Xi) • H.
+    for (IAGSizeType i = 0; i < bufferSize; i += sizeof(IAGBlockType))
+    {
+        IAGBlockType xor;
+        [IAGBitwiseComponents getXorBlock:xor withBlock:y andBlock:(buffer + i)];
+
+        [IAGGcmMathComponents getProductBlock:y byMultiplyingBlock:xor andBlock:hashSubkey];
+    }
+
+    // 4. Return Ym.
+    memcpy(ghashBlock, y, sizeof(IAGBlockType));
+}
+
++ (BOOL)getGCounterBuffer:(IAGUCharType *)gcounterBuffer
+               withBuffer:(IAGUCharType *)buffer
+               bufferSize:(IAGSizeType)bufferSize
+      initialCounterBlock:(IAGBlockType)icb
+                      key:(NSData *)key
+                    error:(NSError **)error
+{
+    //Steps:
+    // 1. If X is the empty string, then return the empty string as Y.
+    if (bufferSize == 0)
+    {
+        return YES;
+    }
+
+    // 2. Let n = ⎡len(X)/128⎤.
+    // 3. Let X1, X2, ... , Xn-1, Xn
+    //    denote the unique sequence of bit strings such that
+    //    X = X1 || X2 || ... || Xn-1 || Xn;
+    //    X1, X2,..., Xn-1 are complete blocks.
+    // 4. Let CB1 = ICB.
+    // 5. For i = 2 to n, let CBi = inc32(CBi-1).
+    // 6. For i = 1 to n - 1, let Yi = Xi ⊕ CIPH(CBi).
+    // 7. Let Yn = Xn ⊕ MSB(CIPH(CBn)).
+    // 8. Let Y = Y1 || Y2 || ... || Yn.
+    // 9. Return Y.
+
+    IAGUCharType y[bufferSize];
+
+    IAGBlockType cb;
+    memcpy(cb, icb, sizeof(IAGBlockType));
+
+    IAGSizeType uncompleteBlockSize = (bufferSize % sizeof(IAGBlockType));
+
+    for (IAGSizeType i = 0; i < (bufferSize - uncompleteBlockSize); i += sizeof(IAGBlockType))
+    {
+        IAGBlockType cipheredBlock;
+        BOOL success = [IAGAesComponents getCipheredBlock:cipheredBlock
+                                        byUsingAESOnBlock:cb
+                                                  withKey:key
+                                                    error:error];
+        if (!success)
+        {
+            return NO;
+        }
+        [IAGBitwiseComponents getXorBlock:(y + i)
+                                withBlock:(buffer + i)
+                                 andBlock:cipheredBlock];
+
+        IAGBlockType intermediateCb;
+        memcpy(intermediateCb, cb, sizeof(IAGBlockType));
+        [IAGGcmMathComponents get32BitIncrementedBuffer:cb
+                                             withBuffer:intermediateCb
+                                                   size:sizeof(IAGBlockType)];
+    }
+
+    if (uncompleteBlockSize > 0)
+    {
+        IAGBlockType cipheredBlock;
+        BOOL success = [IAGAesComponents getCipheredBlock:cipheredBlock
+                                        byUsingAESOnBlock:cb
+                                                  withKey:key
+                                                    error:error];
+        if (!success)
+        {
+            return NO;
+        }
+
+        IAGUCharType msb[uncompleteBlockSize];
+        [IAGBitwiseComponents getMostSignificantBytes:msb
+                                             withSize:uncompleteBlockSize
+                                             inBuffer:cipheredBlock
+                                             withSize:sizeof(IAGBlockType)];
+
+        [IAGBitwiseComponents getXorBuffer:(y + bufferSize - uncompleteBlockSize)
+                                withBuffer:(buffer + bufferSize - uncompleteBlockSize)
+                                    buffer:msb
+                                bufferSize:uncompleteBlockSize];
+    }
+
+    memcpy(gcounterBuffer, y, bufferSize);
+
+    return YES;
+}
+
++ (void)get32BitIncrementedBuffer:(IAGUCharType *)incBuffer
+                       withBuffer:(IAGUCharType *)buffer
+                             size:(IAGSizeType)size
+{
+    NSParameterAssert(size >= sizeof(IAGUInt32Type));
+
+    // From http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf:
+    // ... the function increments the right-most s bits of the string, regarded as the binary
+    // representation of an integer, modulo 2^s; the remaining, left-most len(X)-s bits
+    // remain unchanged.
+
+    IAGUInt32Type lsb;
+    [IAGBitwiseComponents getLeastSignificantBytes:(IAGUCharType *)&lsb
+                                          withSize:sizeof(IAGUInt32Type)
+                                          inBuffer:buffer
+                                          withSize:size];
+
+    // Notice that the increment is modulo 2^32, therefore even if it overflows, the result is
+    // still correct
+    lsb = [IAGGcmEndianness swapUInt32HostToGcm:([IAGGcmEndianness swapUInt32GcmToHost:lsb] + 1)];
+
+    if (size != sizeof(IAGUInt32Type))
+    {
+        [IAGBitwiseComponents getMostSignificantBytes:incBuffer
+                                             withSize:(size - sizeof(IAGUInt32Type))
+                                             inBuffer:buffer
+                                             withSize:size];
+    }
+    memcpy(incBuffer + (size - sizeof(IAGUInt32Type)), &lsb, sizeof(IAGUInt32Type));
+}
+
+#pragma mark - Private class methods
+
++ (void)getProductBlock:(IAGBlockType)product
+     byMultiplyingBlock:(IAGBlockType)x
+               andBlock:(IAGBlockType)y
+{
+    // Let R be the bit string 11100001 || 0^120
+    IAGBlockType r;
+    memset(r, 0x00, sizeof(IAGBlockType));
+    r[0] = 0xE1U;
+
+    // Steps:
+    // 1. Let x0 x1 ... x127 denote the sequence of bits in X
+    // 2. Let Z0 = 0^128 and V0 = Y.
+    IAGBlockType z;
+    memset(z, 0x00, sizeof(IAGBlockType));
+
+    IAGBlockType v;
+    memcpy(v, y, sizeof(IAGBlockType));
+
+    // 3. For i = 0 to 127, calculate blocks Zi+1 and Vi+1 as follows:
+    for (IAGUInt8Type i = 0; i <= IAGMaxBitPositionInABlock; i++)
+    {
+        // Zi+1 = Zi if xi = 0; Zi ⊕ Vi if xi = 1.
+        if ([IAGBitwiseComponents isMostSignificantBitActivatedAtPosition:i inBlock:x])
+        {
+            IAGBlockType zi;
+            memcpy(zi, z, sizeof(IAGBlockType));
+
+            [IAGBitwiseComponents getXorBlock:z withBlock:zi andBlock:v];
+        }
+
+        // Vi+1 = Vi >> 1 if LSB1(Vi) = 0; (Vi >> 1) ⊕ R if LSB1(Vi) = 1.
+        IAGBlockType vi;
+        memcpy(vi, v, sizeof(IAGBlockType));
+
+        [IAGBitwiseComponents getSingleRightShiftedBlock:v withBlock:vi];
+
+        if ([IAGBitwiseComponents isLeastSignificantBitActivatedAtPosition:0 inBlock:vi])
+        {
+            memcpy(vi, v, sizeof(IAGBlockType));
+
+            [IAGBitwiseComponents getXorBlock:v withBlock:vi andBlock:r];
+        }
+    }
+
+    // 4. Return Z128.
+    memcpy(product, z, sizeof(IAGBlockType));
+}
+
+@end

+ 22 - 0
Libraries external/AesGcm/Components/IAGTypes.h

@@ -0,0 +1,22 @@
+//
+//  IAGTypes.h
+//  Pods
+//
+//  Created by Enrique de la Torre (dev) on 20/09/2016.
+//
+//
+
+#ifndef IAGTypes_h
+#define IAGTypes_h
+
+typedef size_t IAGSizeType;
+
+typedef u_char IAGUCharType;
+
+typedef u_int8_t IAGUInt8Type;
+typedef u_int32_t IAGUInt32Type;
+typedef u_int64_t IAGUInt64Type;
+
+typedef IAGUCharType IAGBlockType[16];
+
+#endif /* IAGTypes_h */

+ 67 - 0
Libraries external/AesGcm/IAGAesGcm.h

@@ -0,0 +1,67 @@
+//
+//  IAGAesGcm.h
+//  Pods
+//
+//  Created by Enrique de la Torre (dev) on 17/09/2016.
+//
+//
+
+#import <Foundation/Foundation.h>
+
+#import "IAGCipheredData.h"
+
+/**
+ This class provides the methods that implement the GCM algorithm with AES.
+ */
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface IAGAesGcm : NSObject
+
+/**
+ Given an initialization vector,a key, a plaintext and an additional authenticated data,
+ this method returns the corresponding ciphertext and authentication tag.
+
+ @param plainData Data to cipher: byte length(plainData) <= 2^36 - 32
+ @param aad Additional Authenticated Data: byte length(aad) <= 2^61 - 1
+ @param tagLength Supported authentication tag length, used to build the returned ciphered data
+ @param iv Initialization Vector: 1 <= byte length(iv) <= 2^61 - 1
+ @param key Key used to cipher the data with length: kCCKeySizeAES128 (16), kCCKeySizeAES192 (24) or kCCKeySizeAES256 (32) bytes
+ @param error Set to a value if the operation fails
+ 
+ @return Ciphered data or nil, if there is an error
+ 
+ @see IAGAuthenticationTagLength
+ @see IAGCipheredData
+ @see IAGErrorFactory
+ */
++ (nullable IAGCipheredData *)cipheredDataByAuthenticatedEncryptingPlainData:(NSData *)plainData
+                                             withAdditionalAuthenticatedData:(NSData *)aad
+                                                     authenticationTagLength:(IAGAuthenticationTagLength)tagLength
+                                                        initializationVector:(NSData *)iv
+                                                                         key:(NSData *)key
+                                                                       error:(NSError **)error;
+
+/**
+ Given an initialization vector, a key, a ciphertext with its associated authentication tag and an
+ additional authenticated tag, this method return the corresponding plaintext.
+
+ @param cipheredData Data to decipher: byte length(plainData) <= 2^36 - 32
+ @param aad Additional Authenticated Data: byte length(aad) <= 2^61 - 1
+ @param iv Initialization Vector: 1 <= byte length(iv) <= 2^61 - 1
+ @param key Key used to decipher the data with length: kCCKeySizeAES128 (16), kCCKeySizeAES192 (24) or kCCKeySizeAES256 (32) bytes
+ @param error Set to a value if the operation fails
+ 
+ @return Plain data or nil, if there is an error
+ 
+ @see IAGErrorFactory
+ */
++ (nullable NSData *)plainDataByAuthenticatedDecryptingCipheredData:(IAGCipheredData *)cipheredData
+                                    withAdditionalAuthenticatedData:(NSData *)aad
+                                               initializationVector:(NSData *)iv
+                                                                key:(NSData *)key
+                                                              error:(NSError **)error;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 323 - 0
Libraries external/AesGcm/IAGAesGcm.m

@@ -0,0 +1,323 @@
+//
+//  IAGAesGcm.m
+//  Pods
+//
+//  Created by Enrique de la Torre (dev) on 17/09/2016.
+//
+//
+
+#import "IAGAesGcm.h"
+
+#import "IAGAesComponents.h"
+#import "IAGBitwiseComponents.h"
+#import "IAGError.h"
+#import "IAGGcmEndianness.h"
+#import "IAGGcmMathComponents.h"
+#import "IAGTypes.h"
+
+static const IAGUInt64Type kInputDataMaxLength = (0x1000000000ULL - 0x20ULL);
+static const IAGUInt64Type kAdditionalAuthenticatedDataMaxLength = (0x2000000000000000ULL - 0x1ULL);
+static const IAGUInt64Type kInitializationVectorMinLength = 0x1ULL;
+static const IAGUInt64Type kInitializationVectorMaxLength = (0x2000000000000000ULL - 0x1ULL);
+static const IAGSizeType kInitializationVectorRecommendedSize = 12;
+
+@implementation IAGAesGcm
+
+#pragma mark - Public class methods
+
++ (IAGCipheredData *)cipheredDataByAuthenticatedEncryptingPlainData:(NSData *)plainData
+                                    withAdditionalAuthenticatedData:(NSData *)aad
+                                            authenticationTagLength:(IAGAuthenticationTagLength)tagLength
+                                               initializationVector:(NSData *)iv
+                                                                key:(NSData *)key
+                                                              error:(NSError **)error
+{
+    if ((plainData.length > kInputDataMaxLength) ||
+        (aad.length > kAdditionalAuthenticatedDataMaxLength) ||
+        (iv.length < kInitializationVectorMinLength) ||
+        (iv.length > kInitializationVectorMaxLength))
+    {
+        if (error)
+        {
+            *error = [IAGErrorFactory errorInputDataLengthNotSupported];
+        }
+
+        return nil;
+    }
+
+    // Steps:
+    // 1. Let H = CIPH(0^128).
+    IAGBlockType h;
+    BOOL success = [IAGAesGcm getHashSubkey:h withKey:key error:error];
+    if (!success)
+    {
+        return nil;
+    }
+
+    // 2. Define a block, J0, as follows:
+    //    If len(IV) = 96, then let J0 = IV || 0^31 || 1.
+    //    If len(IV) != 96, then let s = 128 * ⎡len(IV) / 128⎤ - len(IV),
+    //      and let J0 = GHASH(IV || 0^s+64|| [len(IV)]64).
+    IAGBlockType j;
+    [IAGAesGcm getPrecounterBlock:j withInitializationVector:iv hashSubkey:h];
+
+    // 3. Let C = GCTR(inc32(J0), P).
+    IAGUCharType c[plainData.length];
+    success = [IAGAesGcm getGCounterBuffer:c
+                                withBuffer:(IAGUCharType *)plainData.bytes
+                                bufferSize:plainData.length
+                           precounterBlock:j
+                                       key:key
+                                     error:error];
+    if (!success)
+    {
+        return nil;
+    }
+
+    // 4. Let u = 128 * ⎡len(C) / 128⎤ - len(C) and let v = 128 * ⎡len(A) / 128⎤ - len(A)
+    // 5. Define a block, S, as follows:
+    //      S = GHASH(A || 0^v || C || 0^u || [len(A)]64 || [len(C)]64).
+    IAGBlockType s;
+    [IAGAesGcm getGhashBlock:s
+               withAadBuffer:(IAGUCharType *)aad.bytes
+               aadBufferSize:aad.length
+              gCounterBuffer:c
+          gCounterBufferSize:plainData.length
+                  hashSubkey:h];
+
+    // 6. Let T = MSB(GCTR(J0, S)).
+    IAGBlockType entireT;
+    success = [IAGGcmMathComponents getGCounterBuffer:entireT
+                                           withBuffer:s
+                                           bufferSize:sizeof(IAGBlockType)
+                                  initialCounterBlock:j
+                                                  key:key
+                                                error:error];
+    if (!success)
+    {
+        return nil;
+    }
+
+    IAGUCharType t[tagLength];
+    [IAGBitwiseComponents getMostSignificantBytes:t
+                                         withSize:tagLength
+                                         inBuffer:entireT
+                                         withSize:sizeof(IAGBlockType)];
+
+    // 7. Return (C, T).
+    return [[IAGCipheredData alloc] initWithCipheredBuffer:c
+                                      cipheredBufferLength:plainData.length
+                                         authenticationTag:t
+                                   authenticationTagLength:tagLength];
+}
+
++ (NSData *)plainDataByAuthenticatedDecryptingCipheredData:(IAGCipheredData *)cipheredData
+                           withAdditionalAuthenticatedData:(NSData *)aad
+                                      initializationVector:(NSData *)iv
+                                                       key:(NSData *)key
+                                                     error:(NSError **)error
+{
+    // Steps:
+    // 1. If the bit lengths of IV, A or C are not supported, or if len(T) != t, then return FAIL.
+    if ((cipheredData.cipheredBufferLength > kInputDataMaxLength) ||
+        (aad.length > kAdditionalAuthenticatedDataMaxLength) ||
+        (iv.length < kInitializationVectorMinLength) ||
+        (iv.length > kInitializationVectorMaxLength))
+    {
+        if (error)
+        {
+            *error = [IAGErrorFactory errorInputDataLengthNotSupported];
+        }
+
+        return nil;
+    }
+
+    // 2. Let H = CIPHK(0^128).
+    IAGBlockType h;
+    BOOL success = [IAGAesGcm getHashSubkey:h withKey:key error:error];
+    if (!success)
+    {
+        return nil;
+    }
+
+    // 3. Define a block, J0, as follows:
+    //    If len(IV) = 96, then let J0 = IV || 0^31 || 1.
+    //    If len(IV) != 96, then let s = 128 * ⎡len(IV) / 128⎤ - len(IV),
+    //      and let J0 = GHASH(IV || 0^s+64|| [len(IV)]64).
+    IAGBlockType j;
+    [IAGAesGcm getPrecounterBlock:j withInitializationVector:iv hashSubkey:h];
+
+    // 4. Let P = GCTR(inc32(J0),C).
+    IAGUCharType p[cipheredData.cipheredBufferLength];
+    success = [IAGAesGcm getGCounterBuffer:p
+                                withBuffer:(IAGUCharType *)cipheredData.cipheredBuffer
+                                bufferSize:cipheredData.cipheredBufferLength
+                           precounterBlock:j
+                                       key:key
+                                     error:error];
+    if (!success)
+    {
+        return nil;
+    }
+
+    // 5. Let u = 128 * ⎡len(C) / 128⎤ - len(C) and let v = 128 * ⎡len(A) / 128⎤ - len(A)
+    // 6. Define a block, S, as follows:
+    //      S = GHASH(A || 0^v || C || 0^u || [len(A)]64 || [len(C)]64).
+    IAGBlockType s;
+    [IAGAesGcm getGhashBlock:s
+               withAadBuffer:(IAGUCharType *)aad.bytes
+               aadBufferSize:aad.length
+              gCounterBuffer:(IAGUCharType *)cipheredData.cipheredBuffer
+          gCounterBufferSize:cipheredData.cipheredBufferLength
+                  hashSubkey:h];
+
+    // 7. Let T' = MSB(GCTR(J0, S)).
+    IAGBlockType entireT;
+    success = [IAGGcmMathComponents getGCounterBuffer:entireT
+                                           withBuffer:s
+                                           bufferSize:sizeof(IAGBlockType)
+                                  initialCounterBlock:j
+                                                  key:key
+                                                error:error];
+    if (!success)
+    {
+        return nil;
+    }
+
+    IAGUCharType t[cipheredData.authenticationTagLength];
+    [IAGBitwiseComponents getMostSignificantBytes:t
+                                         withSize:cipheredData.authenticationTagLength
+                                         inBuffer:entireT
+                                         withSize:sizeof(IAGBlockType)];
+
+    // 8. If T = T', then return P; else return FAIL.
+    if (memcmp(t, cipheredData.authenticationTag, cipheredData.authenticationTagLength) == 0)
+    {
+        return [NSData dataWithBytes:p length:cipheredData.cipheredBufferLength];
+    }
+
+    if (error)
+    {
+        *error = [IAGErrorFactory errorAuthenticationTagsNotIdentical];
+    }
+
+    return nil;
+}
+
+#pragma mark - Private class methods
+
++ (BOOL)getHashSubkey:(IAGBlockType)hashSubkey withKey:(NSData *)key error:(NSError **)error
+{
+    IAGBlockType zeros;
+    memset(zeros, 0x00, sizeof(IAGBlockType));
+
+    return [IAGAesComponents getCipheredBlock:hashSubkey
+                            byUsingAESOnBlock:zeros
+                                      withKey:key
+                                        error:error];
+}
+
++ (void)getPrecounterBlock:(IAGBlockType)precounterBlock
+  withInitializationVector:(NSData *)iv
+                hashSubkey:(IAGBlockType)hashSubkey;
+{
+    // Define a block, J0, as follows:
+    // If len(IV) = 96, then let J0 = IV || 0^31 || 1.
+    if (iv.length == kInitializationVectorRecommendedSize)
+    {
+        memset(precounterBlock, 0x00, sizeof(IAGBlockType));
+        memcpy(precounterBlock, iv.bytes, iv.length);
+        memset(precounterBlock + sizeof(IAGBlockType) - 1, 0x01, 1);
+
+        return;
+    }
+
+    // If len(IV) != 96, then let s = 128 * ⎡len(IV) / 128⎤ - len(IV),
+    //   and let J0 = GHASH(IV || 0^s+64|| [len(IV)]64).
+    IAGSizeType s = (iv.length % sizeof(IAGBlockType) == 0 ?
+                     0 :
+                     sizeof(IAGBlockType) - (iv.length % sizeof(IAGBlockType)));
+
+    IAGSizeType bufferSize = (iv.length + s + 2 * sizeof(IAGUInt64Type));
+    IAGUCharType buffer[bufferSize];
+
+    memset(buffer, 0x00, bufferSize);
+
+    memcpy(buffer, iv.bytes, iv.length);
+
+    IAGUInt64Type len = [IAGGcmEndianness swapUInt64HostToGcm:(IAGBitsInUChar * iv.length)];
+    memcpy(buffer + bufferSize - sizeof(IAGUInt64Type), &len, sizeof(IAGUInt64Type));
+
+    [IAGGcmMathComponents getGhashBlock:precounterBlock
+                             withBuffer:buffer
+                             bufferSize:bufferSize
+                             hashSubkey:hashSubkey];
+}
+
++ (BOOL)getGCounterBuffer:(IAGUCharType *)gcounterBuffer
+               withBuffer:(IAGUCharType *)buffer
+               bufferSize:(IAGSizeType)bufferSize
+          precounterBlock:(IAGBlockType)precounterBlock
+                      key:(NSData *)key
+                    error:(NSError **)error
+{
+    IAGBlockType inc32;
+    [IAGGcmMathComponents get32BitIncrementedBuffer:inc32
+                                         withBuffer:precounterBlock
+                                               size:sizeof(IAGBlockType)];
+
+    return [IAGGcmMathComponents getGCounterBuffer:gcounterBuffer
+                                        withBuffer:buffer
+                                        bufferSize:bufferSize
+                               initialCounterBlock:inc32
+                                               key:key
+                                             error:error];
+}
+
++ (void)getGhashBlock:(IAGBlockType)ghashBlock
+        withAadBuffer:(IAGUCharType *)aadBuffer
+        aadBufferSize:(IAGSizeType)aadBufferSize
+       gCounterBuffer:(IAGUCharType *)gcounterBuffer
+   gCounterBufferSize:(IAGSizeType)gCounterBufferSize
+           hashSubkey:(IAGBlockType)hashSubkey
+{
+    // Steps:
+    // 1. Let u = 128 * ⎡len(C) / 128⎤ - len(C) and let v = 128 * ⎡len(A) / 128⎤ - len(A)
+    // 2. Define a block, S, as follows:
+    //      S = GHASH(A || 0^v || C || 0^u || [len(A)]64 || [len(C)]64).
+
+    IAGSizeType u = (gCounterBufferSize % sizeof(IAGBlockType) == 0 ?
+                     0 :
+                     sizeof(IAGBlockType) - (gCounterBufferSize % sizeof(IAGBlockType)));
+    IAGSizeType v = (aadBufferSize % sizeof(IAGBlockType) == 0 ?
+                     0 :
+                     sizeof(IAGBlockType) - (aadBufferSize % sizeof(IAGBlockType)));
+
+    IAGSizeType bufferSize = (aadBufferSize + v +
+                              gCounterBufferSize + u +
+                              2 * sizeof(IAGUInt64Type));
+    IAGUCharType buffer[bufferSize];
+
+    memset(buffer, 0x00, bufferSize);
+
+    IAGSizeType pos = 0;
+    memcpy(buffer + pos, aadBuffer, aadBufferSize);
+
+    pos += (aadBufferSize + v);
+    memcpy(buffer + pos, gcounterBuffer, gCounterBufferSize);
+
+    pos += (gCounterBufferSize + u);
+    IAGUInt64Type len = [IAGGcmEndianness swapUInt64HostToGcm:(IAGBitsInUChar * aadBufferSize)];
+    memcpy(buffer + pos, &len, sizeof(IAGUInt64Type));
+
+    pos += sizeof(IAGUInt64Type);
+    len = [IAGGcmEndianness swapUInt64HostToGcm:(IAGBitsInUChar * gCounterBufferSize)];
+    memcpy(buffer + pos, &len, sizeof(IAGUInt64Type));
+
+    [IAGGcmMathComponents getGhashBlock:ghashBlock
+                             withBuffer:buffer
+                             bufferSize:bufferSize
+                             hashSubkey:hashSubkey];
+}
+
+@end

+ 69 - 0
Libraries external/AesGcm/IAGCipheredData.h

@@ -0,0 +1,69 @@
+//
+//  IAGCipheredData.h
+//  Pods
+//
+//  Created by Enrique de la Torre (dev) on 17/09/2016.
+//
+//
+
+#import <Foundation/Foundation.h>
+
+/** List of valid authentication tag lengths */
+typedef NS_ENUM(NSUInteger, IAGAuthenticationTagLength) {
+    /** 128 bits (16 bytes) */
+    IAGAuthenticationTagLength128 = 16,
+    /** 120 bits (15 bytes) */
+    IAGAuthenticationTagLength120 = 15,
+    /** 112 bits (14 bytes) */
+    IAGAuthenticationTagLength112 = 14,
+    /** 104 bits (13 bytes) */
+    IAGAuthenticationTagLength104 = 13,
+    /** 96 bits (12 bytes) */
+    IAGAuthenticationTagLength96 = 12
+};
+
+/**
+ Data type of the ciphered data generated/consumed by the methods in this pod.
+ 
+ @see IAGAesGcm
+ */
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface IAGCipheredData : NSObject
+
+/** Ciphered data generated after encrypting some plain data. */
+@property (nonatomic, readonly) const void *cipheredBuffer NS_RETURNS_INNER_POINTER;
+
+/** Length of the ciphered buffer */
+@property (nonatomic, readonly) NSUInteger cipheredBufferLength;
+
+/**
+ Authentication Tag generated after encrypting some plain data.
+ 
+ @see [IAGAesGcm cipheredDataByAuthenticatedEncryptingPlainData:withAdditionalAuthenticatedData:authenticationTagLength:initializationVector:key:error:]
+ */
+@property (nonatomic, readonly) const void *authenticationTag NS_RETURNS_INNER_POINTER;
+
+/**
+ Length of the authentication tag, also passed by parameter before encrypting the plain data.
+ 
+ @see [IAGAesGcm cipheredDataByAuthenticatedEncryptingPlainData:withAdditionalAuthenticatedData:authenticationTagLength:initializationVector:key:error:]
+ */
+@property (nonatomic, readonly) IAGAuthenticationTagLength authenticationTagLength;
+
+/** Unavailable. Use the designated initializer */
+- (instancetype)init NS_UNAVAILABLE;
+
+/** Designated initializer */
+- (instancetype)initWithCipheredBuffer:(const void *)cipheredBuffer
+                  cipheredBufferLength:(NSUInteger)cipheredBufferLength
+                     authenticationTag:(const void *)authenticationTag
+               authenticationTagLength:(IAGAuthenticationTagLength)authenticationTagLength;
+
+/** Class-specific equality method */
+- (BOOL)isEqualToCipheredData:(IAGCipheredData *)object;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 97 - 0
Libraries external/AesGcm/IAGCipheredData.m

@@ -0,0 +1,97 @@
+//
+//  IAGCipheredData.m
+//  Pods
+//
+//  Created by Enrique de la Torre (dev) on 17/09/2016.
+//
+//
+
+#import "IAGCipheredData.h"
+
+@interface IAGCipheredData ()
+
+@property (nonatomic) NSData *cipheredData;
+@property (nonatomic) NSData *authenticationTagData;
+
+@end
+
+@implementation IAGCipheredData
+
+#pragma mark - Synthesize properties
+
+- (const void *)cipheredBuffer
+{
+    return self.cipheredData.bytes;
+}
+
+- (NSUInteger)cipheredBufferLength
+{
+    return self.cipheredData.length;
+}
+
+- (const void *)authenticationTag
+{
+    return self.authenticationTagData.bytes;
+}
+
+- (IAGAuthenticationTagLength)authenticationTagLength
+{
+    return self.authenticationTagData.length;
+}
+
+#pragma mark - NSObject methods
+
+- (NSString *)description
+{
+    return [NSString stringWithFormat:@"Ciphertext: %@. Auth tag: %@",
+            self.cipheredData, self.authenticationTagData];
+}
+
+#pragma mark - Init object
+
+- (instancetype)initWithCipheredBuffer:(const void *)cipheredBuffer
+                  cipheredBufferLength:(NSUInteger)cipheredBufferLength
+                     authenticationTag:(const void *)authenticationTag
+               authenticationTagLength:(IAGAuthenticationTagLength)authenticationTagLength
+{
+    self = [super init];
+
+    if (self)
+    {
+        _cipheredData = [NSData dataWithBytes:cipheredBuffer length:cipheredBufferLength];
+        _authenticationTagData = [NSData dataWithBytes:authenticationTag
+                                                length:authenticationTagLength];
+    }
+
+    return self;
+}
+
+#pragma mark - Equality
+
+- (NSUInteger)hash
+{
+    return self.cipheredData.hash;
+}
+
+- (BOOL)isEqual:(id)object
+{
+    if ([self class] == [object class])
+    {
+        return [self isEqualToCipheredData:object];
+    }
+
+    return [super isEqual:object];
+}
+
+- (BOOL)isEqualToCipheredData:(IAGCipheredData *)object
+{
+    if (self == object)
+    {
+        return YES;
+    }
+
+    return ([self.cipheredData isEqualToData:object.cipheredData] &&
+            [self.authenticationTagData isEqualToData:object.authenticationTagData]);
+}
+
+@end

+ 55 - 0
Libraries external/AesGcm/IAGError.h

@@ -0,0 +1,55 @@
+//
+//  IAGError.h
+//  Pods
+//
+//  Created by Enrique de la Torre (dev) on 20/09/2016.
+//
+//
+
+#import <Foundation/Foundation.h>
+
+/** "One and only" list of error codes in this pod */
+typedef NS_ENUM(NSInteger, IAGErrorCode) {
+    /** @see [IAGErrorFactory errorAESFailed] */
+    IAGErrorCodeAESFailed = 0,
+    /** @see [IAGErrorFactory errorInputDataLengthNotSupported] */
+    IAGErrorCodeInputDataLengthNotSupported,
+    /** @see [IAGErrorFactory errorAuthenticationTagsNotIdentical] */
+    IAGErrorCodeAuthenticationTagsNotIdentical
+};
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** "One and only" error domain in this pod */
+extern NSString * const IAGErrorDomain;
+
+/**
+ Simple factory to easily build each of the errors generated while ciphering/deciphering data.
+ */
+@interface IAGErrorFactory : NSObject
+
+/**
+ Error returned if something goes wrong while ciphering a block with AES.
+ 
+ @see IAGBlockType
+ @see [IAGAesComponents getCipheredBlock:byUsingAESOnBlock:withKey:error:]
+ */
++ (NSError *)errorAESFailed;
+
+/**
+ Error returned when the data passed to cipher/decipher methods does not have a supported length.
+ 
+ @see IAGAesGcm
+ */
++ (NSError *)errorInputDataLengthNotSupported;
+
+/**
+ Error returned when the authentication tag generated after deciphering some data is not identical to the tag passed by parameter.
+
+ @see [IAGAesGcm plainDataByAuthenticatedDecryptingCipheredData:withAdditionalAuthenticatedData:initializationVector:key:error:]
+ */
++ (NSError *)errorAuthenticationTagsNotIdentical;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 38 - 0
Libraries external/AesGcm/IAGError.m

@@ -0,0 +1,38 @@
+//
+//  IAGError.m
+//  Pods
+//
+//  Created by Enrique de la Torre (dev) on 20/09/2016.
+//
+//
+
+#import "IAGError.h"
+
+NSString * const IAGErrorDomain = @"IAGErrorDomain";
+
+@implementation IAGErrorFactory
+
+#pragma mark - Public class methods
+
++ (NSError *)errorAESFailed
+{
+    return [NSError errorWithDomain:IAGErrorDomain
+                               code:IAGErrorCodeAESFailed
+                           userInfo:nil];
+}
+
++ (NSError *)errorInputDataLengthNotSupported
+{
+    return [NSError errorWithDomain:IAGErrorDomain
+                               code:IAGErrorCodeInputDataLengthNotSupported
+                           userInfo:nil];
+}
+
++ (NSError *)errorAuthenticationTagsNotIdentical
+{
+    return [NSError errorWithDomain:IAGErrorDomain
+                               code:IAGErrorCodeAuthenticationTagsNotIdentical
+                           userInfo:nil];
+}
+
+@end

+ 102 - 0
Nextcloud.xcodeproj/project.pbxproj

@@ -544,6 +544,34 @@
 		F7D424741F063B82009C9782 /* CTAssetThumbnailView.m in Sources */ = {isa = PBXBuildFile; fileRef = F7D423EA1F063B82009C9782 /* CTAssetThumbnailView.m */; };
 		F7DC5FEC1F011EB700A903C7 /* MGSwipeButton.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC5FE91F011EB700A903C7 /* MGSwipeButton.m */; };
 		F7DC5FED1F011EB700A903C7 /* MGSwipeTableCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC5FEB1F011EB700A903C7 /* MGSwipeTableCell.m */; };
+		F7DC6B961F8AC20F002FDA6A /* IAGAesComponents.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B841F8AC20E002FDA6A /* IAGAesComponents.m */; };
+		F7DC6B971F8AC20F002FDA6A /* IAGAesComponents.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B841F8AC20E002FDA6A /* IAGAesComponents.m */; };
+		F7DC6B981F8AC20F002FDA6A /* IAGAesComponents.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B841F8AC20E002FDA6A /* IAGAesComponents.m */; };
+		F7DC6B991F8AC20F002FDA6A /* IAGAesComponents.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B841F8AC20E002FDA6A /* IAGAesComponents.m */; };
+		F7DC6B9A1F8AC20F002FDA6A /* IAGBitwiseComponents.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B861F8AC20E002FDA6A /* IAGBitwiseComponents.m */; };
+		F7DC6B9B1F8AC20F002FDA6A /* IAGBitwiseComponents.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B861F8AC20E002FDA6A /* IAGBitwiseComponents.m */; };
+		F7DC6B9C1F8AC20F002FDA6A /* IAGBitwiseComponents.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B861F8AC20E002FDA6A /* IAGBitwiseComponents.m */; };
+		F7DC6B9D1F8AC20F002FDA6A /* IAGBitwiseComponents.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B861F8AC20E002FDA6A /* IAGBitwiseComponents.m */; };
+		F7DC6B9E1F8AC20F002FDA6A /* IAGGcmEndianness.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B881F8AC20E002FDA6A /* IAGGcmEndianness.m */; };
+		F7DC6B9F1F8AC20F002FDA6A /* IAGGcmEndianness.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B881F8AC20E002FDA6A /* IAGGcmEndianness.m */; };
+		F7DC6BA01F8AC20F002FDA6A /* IAGGcmEndianness.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B881F8AC20E002FDA6A /* IAGGcmEndianness.m */; };
+		F7DC6BA11F8AC20F002FDA6A /* IAGGcmEndianness.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B881F8AC20E002FDA6A /* IAGGcmEndianness.m */; };
+		F7DC6BA21F8AC20F002FDA6A /* IAGGcmMathComponents.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B8A1F8AC20E002FDA6A /* IAGGcmMathComponents.m */; };
+		F7DC6BA31F8AC20F002FDA6A /* IAGGcmMathComponents.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B8A1F8AC20E002FDA6A /* IAGGcmMathComponents.m */; };
+		F7DC6BA41F8AC20F002FDA6A /* IAGGcmMathComponents.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B8A1F8AC20E002FDA6A /* IAGGcmMathComponents.m */; };
+		F7DC6BA51F8AC20F002FDA6A /* IAGGcmMathComponents.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B8A1F8AC20E002FDA6A /* IAGGcmMathComponents.m */; };
+		F7DC6BA61F8AC20F002FDA6A /* IAGAesGcm.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B8D1F8AC20E002FDA6A /* IAGAesGcm.m */; };
+		F7DC6BA71F8AC20F002FDA6A /* IAGAesGcm.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B8D1F8AC20E002FDA6A /* IAGAesGcm.m */; };
+		F7DC6BA81F8AC20F002FDA6A /* IAGAesGcm.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B8D1F8AC20E002FDA6A /* IAGAesGcm.m */; };
+		F7DC6BA91F8AC20F002FDA6A /* IAGAesGcm.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B8D1F8AC20E002FDA6A /* IAGAesGcm.m */; };
+		F7DC6BAA1F8AC20F002FDA6A /* IAGCipheredData.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B8F1F8AC20E002FDA6A /* IAGCipheredData.m */; };
+		F7DC6BAB1F8AC20F002FDA6A /* IAGCipheredData.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B8F1F8AC20E002FDA6A /* IAGCipheredData.m */; };
+		F7DC6BAC1F8AC20F002FDA6A /* IAGCipheredData.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B8F1F8AC20E002FDA6A /* IAGCipheredData.m */; };
+		F7DC6BAD1F8AC20F002FDA6A /* IAGCipheredData.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B8F1F8AC20E002FDA6A /* IAGCipheredData.m */; };
+		F7DC6BAE1F8AC20F002FDA6A /* IAGError.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B911F8AC20E002FDA6A /* IAGError.m */; };
+		F7DC6BAF1F8AC20F002FDA6A /* IAGError.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B911F8AC20E002FDA6A /* IAGError.m */; };
+		F7DC6BB01F8AC20F002FDA6A /* IAGError.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B911F8AC20E002FDA6A /* IAGError.m */; };
+		F7DC6BB11F8AC20F002FDA6A /* IAGError.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DC6B911F8AC20E002FDA6A /* IAGError.m */; };
 		F7DFE2521EBDC3A400CF5202 /* Realm.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7DFE24F1EBDC3A400CF5202 /* Realm.framework */; };
 		F7DFE2531EBDC3A400CF5202 /* Realm.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7DFE24F1EBDC3A400CF5202 /* Realm.framework */; };
 		F7DFE2541EBDC3A400CF5202 /* RealmSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7DFE2501EBDC3A400CF5202 /* RealmSwift.framework */; };
@@ -1424,6 +1452,21 @@
 		F7DC5FE91F011EB700A903C7 /* MGSwipeButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGSwipeButton.m; sourceTree = "<group>"; };
 		F7DC5FEA1F011EB700A903C7 /* MGSwipeTableCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGSwipeTableCell.h; sourceTree = "<group>"; };
 		F7DC5FEB1F011EB700A903C7 /* MGSwipeTableCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGSwipeTableCell.m; sourceTree = "<group>"; };
+		F7DC6B831F8AC20E002FDA6A /* IAGAesComponents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IAGAesComponents.h; sourceTree = "<group>"; };
+		F7DC6B841F8AC20E002FDA6A /* IAGAesComponents.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IAGAesComponents.m; sourceTree = "<group>"; };
+		F7DC6B851F8AC20E002FDA6A /* IAGBitwiseComponents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IAGBitwiseComponents.h; sourceTree = "<group>"; };
+		F7DC6B861F8AC20E002FDA6A /* IAGBitwiseComponents.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IAGBitwiseComponents.m; sourceTree = "<group>"; };
+		F7DC6B871F8AC20E002FDA6A /* IAGGcmEndianness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IAGGcmEndianness.h; sourceTree = "<group>"; };
+		F7DC6B881F8AC20E002FDA6A /* IAGGcmEndianness.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IAGGcmEndianness.m; sourceTree = "<group>"; };
+		F7DC6B891F8AC20E002FDA6A /* IAGGcmMathComponents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IAGGcmMathComponents.h; sourceTree = "<group>"; };
+		F7DC6B8A1F8AC20E002FDA6A /* IAGGcmMathComponents.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IAGGcmMathComponents.m; sourceTree = "<group>"; };
+		F7DC6B8B1F8AC20E002FDA6A /* IAGTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IAGTypes.h; sourceTree = "<group>"; };
+		F7DC6B8C1F8AC20E002FDA6A /* IAGAesGcm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IAGAesGcm.h; sourceTree = "<group>"; };
+		F7DC6B8D1F8AC20E002FDA6A /* IAGAesGcm.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IAGAesGcm.m; sourceTree = "<group>"; };
+		F7DC6B8E1F8AC20E002FDA6A /* IAGCipheredData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IAGCipheredData.h; sourceTree = "<group>"; };
+		F7DC6B8F1F8AC20E002FDA6A /* IAGCipheredData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IAGCipheredData.m; sourceTree = "<group>"; };
+		F7DC6B901F8AC20E002FDA6A /* IAGError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IAGError.h; sourceTree = "<group>"; };
+		F7DC6B911F8AC20E002FDA6A /* IAGError.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IAGError.m; sourceTree = "<group>"; };
 		F7DE9AAD1F482FA5008DFE10 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/CTAssetsPicker.strings; sourceTree = "<group>"; };
 		F7DE9AAE1F482FA5008DFE10 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/SwiftWebVC.strings; sourceTree = "<group>"; };
 		F7DE9AAF1F482FA5008DFE10 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/BKPasscodeView.strings; sourceTree = "<group>"; };
@@ -1707,6 +1750,7 @@
 		F70F02A81C889183008DAB36 /* Libraries external */ = {
 			isa = PBXGroup;
 			children = (
+				F7DC6B801F8AC20E002FDA6A /* AesGcm */,
 				F70F02B21C889183008DAB36 /* AFViewShaker */,
 				F73CCE221DC13788007E38D8 /* DZNEmptyDataSet */,
 				F7659A211DC0B726004860C4 /* EAIntroView */,
@@ -2758,6 +2802,36 @@
 			path = MGSwipeTableCell;
 			sourceTree = "<group>";
 		};
+		F7DC6B801F8AC20E002FDA6A /* AesGcm */ = {
+			isa = PBXGroup;
+			children = (
+				F7DC6B821F8AC20E002FDA6A /* Components */,
+				F7DC6B8C1F8AC20E002FDA6A /* IAGAesGcm.h */,
+				F7DC6B8D1F8AC20E002FDA6A /* IAGAesGcm.m */,
+				F7DC6B8E1F8AC20E002FDA6A /* IAGCipheredData.h */,
+				F7DC6B8F1F8AC20E002FDA6A /* IAGCipheredData.m */,
+				F7DC6B901F8AC20E002FDA6A /* IAGError.h */,
+				F7DC6B911F8AC20E002FDA6A /* IAGError.m */,
+			);
+			path = AesGcm;
+			sourceTree = "<group>";
+		};
+		F7DC6B821F8AC20E002FDA6A /* Components */ = {
+			isa = PBXGroup;
+			children = (
+				F7DC6B831F8AC20E002FDA6A /* IAGAesComponents.h */,
+				F7DC6B841F8AC20E002FDA6A /* IAGAesComponents.m */,
+				F7DC6B851F8AC20E002FDA6A /* IAGBitwiseComponents.h */,
+				F7DC6B861F8AC20E002FDA6A /* IAGBitwiseComponents.m */,
+				F7DC6B871F8AC20E002FDA6A /* IAGGcmEndianness.h */,
+				F7DC6B881F8AC20E002FDA6A /* IAGGcmEndianness.m */,
+				F7DC6B891F8AC20E002FDA6A /* IAGGcmMathComponents.h */,
+				F7DC6B8A1F8AC20E002FDA6A /* IAGGcmMathComponents.m */,
+				F7DC6B8B1F8AC20E002FDA6A /* IAGTypes.h */,
+			);
+			path = Components;
+			sourceTree = "<group>";
+		};
 		F7DFE24E1EBDC3A400CF5202 /* Realm */ = {
 			isa = PBXGroup;
 			children = (
@@ -3386,12 +3460,15 @@
 				F70022A51EC4C9100080073F /* AFNetworkReachabilityManager.m in Sources */,
 				F73CC0731E813DFF006E3047 /* BKPasscodeLockScreenManager.m in Sources */,
 				F73CC06A1E813DFF006E3047 /* BKPasscodeDummyViewController.m in Sources */,
+				F7DC6B9F1F8AC20F002FDA6A /* IAGGcmEndianness.m in Sources */,
 				F73CC07C1E813DFF006E3047 /* BKTouchIDManager.m in Sources */,
 				F70022B71EC4C9100080073F /* OCCapabilities.m in Sources */,
 				F734E5891F019D860060CB77 /* UIScrollView+EmptyDataSet.m in Sources */,
+				F7DC6BA31F8AC20F002FDA6A /* IAGGcmMathComponents.m in Sources */,
 				F70022FF1EC4C9100080073F /* UtilsFramework.m in Sources */,
 				F70022BA1EC4C9100080073F /* OCCommunication.m in Sources */,
 				F70022ED1EC4C9100080073F /* OCXMLSharedParser.m in Sources */,
+				F7DC6B971F8AC20F002FDA6A /* IAGAesComponents.m in Sources */,
 				F70022D51EC4C9100080073F /* NSDate+ISO8601.m in Sources */,
 				F70022FC1EC4C9100080073F /* NSString+Encode.m in Sources */,
 				F70022E41EC4C9100080073F /* OCXMLParser.m in Sources */,
@@ -3400,6 +3477,7 @@
 				F70022E11EC4C9100080073F /* OCXMLListParser.m in Sources */,
 				F73CC0791E813DFF006E3047 /* BKShiftingView.m in Sources */,
 				F71459D21D12E3B700CAFEEC /* CCUtility.m in Sources */,
+				F7DC6BA71F8AC20F002FDA6A /* IAGAesGcm.m in Sources */,
 				F71459D31D12E3B700CAFEEC /* CCBKPasscode.m in Sources */,
 				F7F8D71C1ED6183000E711F3 /* CCCellShareExt.m in Sources */,
 				F71459D51D12E3B700CAFEEC /* MBProgressHUD.m in Sources */,
@@ -3420,6 +3498,8 @@
 				F7BAADC91ED5A87C00B7EAD4 /* NCDatabase.swift in Sources */,
 				F70022BD1EC4C9100080073F /* OCExternalSites.m in Sources */,
 				F780710A1EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m in Sources */,
+				F7DC6BAF1F8AC20F002FDA6A /* IAGError.m in Sources */,
+				F7DC6BAB1F8AC20F002FDA6A /* IAGCipheredData.m in Sources */,
 				F70022A81EC4C9100080073F /* AFSecurityPolicy.m in Sources */,
 				F70022AB1EC4C9100080073F /* AFURLRequestSerialization.m in Sources */,
 				F7145A001D12E3B700CAFEEC /* CCGlobal.m in Sources */,
@@ -3435,6 +3515,7 @@
 				F72756731F7153FC0011E2FC /* NCClientEncryption.m in Sources */,
 				F7BAADCC1ED5A87C00B7EAD4 /* NCManageDatabase.swift in Sources */,
 				F70022DE1EC4C9100080073F /* OCWebDAVClient.m in Sources */,
+				F7DC6B9B1F8AC20F002FDA6A /* IAGBitwiseComponents.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -3443,9 +3524,12 @@
 			buildActionMask = 2147483647;
 			files = (
 				F70022AF1EC4C9100080073F /* AFURLResponseSerialization.m in Sources */,
+				F7DC6BAC1F8AC20F002FDA6A /* IAGCipheredData.m in Sources */,
+				F7DC6BA01F8AC20F002FDA6A /* IAGGcmEndianness.m in Sources */,
 				F7BAADCA1ED5A87C00B7EAD4 /* NCDatabase.swift in Sources */,
 				F7BAADCD1ED5A87C00B7EAD4 /* NCManageDatabase.swift in Sources */,
 				F725437C1E12A44A009BF4C2 /* CCSection.m in Sources */,
+				F7DC6B9C1F8AC20F002FDA6A /* IAGBitwiseComponents.m in Sources */,
 				F74344651E127DE9001CC831 /* CCNetworking.m in Sources */,
 				F74344641E127DE6001CC831 /* OCNetworking.m in Sources */,
 				F72756741F7153FC0011E2FC /* NCClientEncryption.m in Sources */,
@@ -3469,6 +3553,7 @@
 				F74344171E1264EE001CC831 /* DocumentPickerViewController.swift in Sources */,
 				F70022D61EC4C9100080073F /* NSDate+ISO8601.m in Sources */,
 				F74344811E127F49001CC831 /* AFViewShaker.m in Sources */,
+				F7DC6BB01F8AC20F002FDA6A /* IAGError.m in Sources */,
 				F70022E81EC4C9100080073F /* OCXMLServerErrorsParser.m in Sources */,
 				F70022D31EC4C9100080073F /* OCUserProfile.m in Sources */,
 				F74344791E127EA1001CC831 /* CCError.m in Sources */,
@@ -3478,6 +3563,8 @@
 				F70022A91EC4C9100080073F /* AFSecurityPolicy.m in Sources */,
 				F70022BE1EC4C9100080073F /* OCExternalSites.m in Sources */,
 				F77EB6291EC08037003F814F /* CCExifGeo.m in Sources */,
+				F7DC6BA41F8AC20F002FDA6A /* IAGGcmMathComponents.m in Sources */,
+				F7DC6BA81F8AC20F002FDA6A /* IAGAesGcm.m in Sources */,
 				F70022CD1EC4C9100080073F /* OCSharedDto.m in Sources */,
 				F70022AC1EC4C9100080073F /* AFURLRequestSerialization.m in Sources */,
 				F780710B1EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m in Sources */,
@@ -3491,6 +3578,7 @@
 				F70022D91EC4C9100080073F /* NSDate+RFC1123.m in Sources */,
 				F73CC06E1E813DFF006E3047 /* BKPasscodeField.m in Sources */,
 				F74344881E127F9C001CC831 /* UIImage+animatedGIF.m in Sources */,
+				F7DC6B981F8AC20F002FDA6A /* IAGAesComponents.m in Sources */,
 				F73CC0771E813DFF006E3047 /* BKPasscodeViewController.m in Sources */,
 				F70022DF1EC4C9100080073F /* OCWebDAVClient.m in Sources */,
 				F743448A1E127FF2001CC831 /* CCHud.m in Sources */,
@@ -3509,7 +3597,9 @@
 			buildActionMask = 2147483647;
 			files = (
 				F7BB50D91F2238A300C47094 /* OCXMLParser.m in Sources */,
+				F7DC6B991F8AC20F002FDA6A /* IAGAesComponents.m in Sources */,
 				F7BB50D11F22388900C47094 /* OCSharedDto.m in Sources */,
+				F7DC6B9D1F8AC20F002FDA6A /* IAGBitwiseComponents.m in Sources */,
 				F7BB50CB1F22386900C47094 /* OCCommunication.m in Sources */,
 				F7BB50D31F22388E00C47094 /* OCUserProfile.m in Sources */,
 				F7BB50BF1F22378800C47094 /* CCExifGeo.m in Sources */,
@@ -3521,6 +3611,7 @@
 				F7BB50F71F2239BF00C47094 /* BKPasscodeLockScreenManager.m in Sources */,
 				F7BB50DB1F2238A900C47094 /* OCXMLShareByLinkParser.m in Sources */,
 				F7BB50E21F2238D000C47094 /* AFURLRequestSerialization.m in Sources */,
+				F7DC6BA51F8AC20F002FDA6A /* IAGGcmMathComponents.m in Sources */,
 				F7BB50BC1F22375D00C47094 /* CCBKPasscode.m in Sources */,
 				F7BB50D81F2238A000C47094 /* OCXMLListParser.m in Sources */,
 				F7BB50E41F2238D500C47094 /* AFURLSessionManager.m in Sources */,
@@ -3532,6 +3623,7 @@
 				F7BB50FA1F2239CB00C47094 /* BKTouchIDManager.m in Sources */,
 				F7BB50BB1F22374E00C47094 /* OCNetworking.m in Sources */,
 				F7BB50C11F22378E00C47094 /* CCHud.m in Sources */,
+				F7DC6BAD1F8AC20F002FDA6A /* IAGCipheredData.m in Sources */,
 				F7BB50DE1F2238B700C47094 /* UtilsFramework.m in Sources */,
 				F7BB50D61F22389900C47094 /* OCHTTPRequestOperation.m in Sources */,
 				F7BB50BD1F22376000C47094 /* CCCertificate.m in Sources */,
@@ -3540,12 +3632,14 @@
 				F72756751F7153FC0011E2FC /* NCClientEncryption.m in Sources */,
 				F7BB50D71F22389C00C47094 /* OCWebDAVClient.m in Sources */,
 				F7BB50C01F22378B00C47094 /* CCError.m in Sources */,
+				F7DC6BB11F8AC20F002FDA6A /* IAGError.m in Sources */,
 				F7BB50E01F2238CA00C47094 /* AFNetworkReachabilityManager.m in Sources */,
 				F7BB50F81F2239C400C47094 /* BKPasscodeViewController.m in Sources */,
 				F74344251E1264EE001CC831 /* FileProvider.swift in Sources */,
 				F7BB50BA1F22374A00C47094 /* CCNetworking.m in Sources */,
 				F7BB50DD1F2238B100C47094 /* NSString+Encode.m in Sources */,
 				F7BB50D51F22389600C47094 /* NSDate+RFC1123.m in Sources */,
+				F7DC6BA11F8AC20F002FDA6A /* IAGGcmEndianness.m in Sources */,
 				F7BB50A31F2236C500C47094 /* CCGlobal.m in Sources */,
 				F76B3CD11EAE01BD00921AC9 /* NCBrand.swift in Sources */,
 				F7BB50CF1F22388300C47094 /* OCNotificationsAction.m in Sources */,
@@ -3558,6 +3652,7 @@
 				F7BB50F41F2239B600C47094 /* BKPasscodeDummyViewController.m in Sources */,
 				F7BB50C41F22379800C47094 /* NSString+TruncateToWidth.m in Sources */,
 				F7BB50E31F2238D200C47094 /* AFURLResponseSerialization.m in Sources */,
+				F7DC6BA91F8AC20F002FDA6A /* IAGAesGcm.m in Sources */,
 				F7BB50EB1F22391000C47094 /* MBProgressHUD.m in Sources */,
 				F7BB50D21F22388B00C47094 /* OCShareUser.m in Sources */,
 				F7BB50F31F22396300C47094 /* UIImage+animatedGIF.m in Sources */,
@@ -3598,6 +3693,7 @@
 				F77B0E031D118A16002130FE /* CCShareInfoCMOC.m in Sources */,
 				F77B0E041D118A16002130FE /* UIImage+animatedGIF.m in Sources */,
 				F7D423881F0596C6009C9782 /* ReaderThumbView.m in Sources */,
+				F7DC6BA21F8AC20F002FDA6A /* IAGGcmMathComponents.m in Sources */,
 				F73CCE301DC13798007E38D8 /* UICKeyChainStore.m in Sources */,
 				F73B4EFE1F470D9100BBEE4B /* LangHungarianModel.cpp in Sources */,
 				F7D4238A1F0596C6009C9782 /* ThumbsMainToolbar.m in Sources */,
@@ -3626,6 +3722,7 @@
 				F77B0E141D118A16002130FE /* CCError.m in Sources */,
 				F73B4F131F470D9100BBEE4B /* nsUniversalDetector.cpp in Sources */,
 				F72756721F7153FC0011E2FC /* NCClientEncryption.m in Sources */,
+				F7DC6BAE1F8AC20F002FDA6A /* IAGError.m in Sources */,
 				F7B0C1751EE839A30033AC24 /* NCAutoUpload.m in Sources */,
 				F77B0E161D118A16002130FE /* AFViewShaker.m in Sources */,
 				F73B4F111F470D9100BBEE4B /* nsSBCSGroupProber.cpp in Sources */,
@@ -3693,6 +3790,7 @@
 				F762CB171EACB66200B38484 /* XLFormRegexValidator.m in Sources */,
 				F73CC0691E813DFF006E3047 /* BKPasscodeDummyViewController.m in Sources */,
 				F762CB1A1EACB66200B38484 /* XLForm.m in Sources */,
+				F7DC6BAA1F8AC20F002FDA6A /* IAGCipheredData.m in Sources */,
 				F73B4EFC1F470D9100BBEE4B /* LangGreekModel.cpp in Sources */,
 				F762CB051EACB66200B38484 /* XLFormTextFieldCell.m in Sources */,
 				F7B4F1CB1F44356F00B53B42 /* NCUchardet.m in Sources */,
@@ -3702,9 +3800,12 @@
 				F7D4237D1F0596C6009C9782 /* ReaderContentView.m in Sources */,
 				F73B4EFA1F470D9100BBEE4B /* LangFrenchModel.cpp in Sources */,
 				F7D4245D1F063B82009C9782 /* CTAssetCollectionViewCell.m in Sources */,
+				F7DC6B9A1F8AC20F002FDA6A /* IAGBitwiseComponents.m in Sources */,
+				F7DC6B961F8AC20F002FDA6A /* IAGAesComponents.m in Sources */,
 				F7D4245E1F063B82009C9782 /* CTAssetCollectionViewController.m in Sources */,
 				F762CAF91EACB66200B38484 /* XLFormCheckCell.m in Sources */,
 				F7BE6E2F1D2D5C3B00106933 /* CCQuickActions.m in Sources */,
+				F7DC6BA61F8AC20F002FDA6A /* IAGAesGcm.m in Sources */,
 				F762CB101EACB66200B38484 /* NSPredicate+XLFormAdditions.m in Sources */,
 				F7D424691F063B82009C9782 /* CTAssetsGridViewLayout.m in Sources */,
 				F7D4237E1F0596C6009C9782 /* ReaderDocument.m in Sources */,
@@ -3818,6 +3919,7 @@
 				F70022FE1EC4C9100080073F /* UtilsFramework.m in Sources */,
 				F7D424561F063B82009C9782 /* NSNumberFormatter+CTAssetsPickerController.m in Sources */,
 				F70022AA1EC4C9100080073F /* AFURLRequestSerialization.m in Sources */,
+				F7DC6B9E1F8AC20F002FDA6A /* IAGGcmEndianness.m in Sources */,
 				F7D423851F0596C6009C9782 /* ReaderThumbRender.m in Sources */,
 				F72AAECA1E5C60C700BB17E1 /* AHKActionSheet.m in Sources */,
 				F73B4F141F470D9100BBEE4B /* nsUTF8Prober.cpp in Sources */,

+ 29 - 26
iOSClient/Security/NCClientEncryption.m

@@ -24,6 +24,8 @@
 #import "NCClientEncryption.h"
 #import "NCBridgeSwift.h"
 
+#import "IAGAesGcm.h"
+
 #import <CommonCrypto/CommonCryptor.h>
 #import <CommonCrypto/CommonDigest.h>
 #import <Security/Security.h>
@@ -270,44 +272,45 @@ cleanup:
 
 NSData *cipherOperation(NSData *contentData, NSData *keyData, NSData *initVectorData, CCOperation operation)
 {
-    void *operationBytes = malloc(contentData.length);
-        
+    NSError *error;
+    
     // setup key
     unsigned char cKey[kCCKeySizeAES128];
     bzero(cKey, sizeof(cKey));
     [keyData getBytes:cKey length:kCCKeySizeAES128];
-    
+    NSData *key = [NSData dataWithBytes:cKey length:kCCKeySizeAES128];
+    NSData *key2 = [NSData dataWithBytesNoCopy:@"bGzWfQBj2lE4ZnysDWwsIg==" length:kCCKeySizeAES128];
+
     // setup iv
     char cIv[kCCBlockSizeAES128];
     bzero(cIv, kCCBlockSizeAES128);
     [initVectorData getBytes:cIv length:kCCBlockSizeAES128];
-    
+    NSData *iv = [NSData dataWithBytes:cIv length:kCCKeySizeAES128];
+    NSData *iv2 = [NSData dataWithBytesNoCopy:@"rTBECYNekKF+a1HR7z32/Q==" length:kCCKeySizeAES128];
+
     // tag
     NSMutableData *tag = [NSMutableData dataWithLength:kCCBlockSizeAES128];
     size_t tagLength = kCCBlockSizeAES128;
     
-    /*CCCryptorStatus cryptStatus = CCCryptorGCM(operation,
-                                               kCCAlgorithmAES128,
-                                               cKey,
-                                               kCCKeySizeAES128,
-                                               cIv,
-                                               kCCBlockSizeAES128,
-                                               nil,
-                                               0,
-                                               contentData.bytes,
-                                               contentData.length,
-                                               operationBytes,
-                                               tag.bytes,
-                                               &tagLength);
-    
-    if (cryptStatus == kCCSuccess) {
-        return [NSData dataWithBytesNoCopy:operationBytes length:contentData.length];
-    }
-    */
-    
-    free(operationBytes);
-    
-    return nil;
+    IAGCipheredData *cipheredData = [IAGCipheredData init];
+    IAGCipheredData *cipheredData2 = [IAGCipheredData initWithCipheredBuffer:nil cipheredBufferLength:contentData.lenght authenticationTag:tag authenticationTagLength:tagLength];
+    
+                                     
+                                      /*
+                                       - (instancetype)initWithCipheredBuffer:(const void *)cipheredBuffer
+                                       cipheredBufferLength:(NSUInteger)cipheredBufferLength
+                                       authenticationTag:(const void *)authenticationTag
+                                       authenticationTagLength:(IAGAuthenticationTagLength)authenticationTagLength
+                                       */
+                                      
+                                      
+    NSData *plainData = [IAGAesGcm plainDataByAuthenticatedDecryptingCipheredData:cipheredData
+                                                  withAdditionalAuthenticatedData:[@"" dataUsingEncoding:NSUTF8StringEncoding]
+                                                             initializationVector:iv
+                                                                              key:key
+                                                                            error:&error];
+    
+    return plainData;
 }
 
 @end