Operations/QCCAESCryptor.m
/* |
Copyright (C) 2016 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
Implements AES encryption and decryption without padding. |
*/ |
#import "QCCAESCryptor.h" |
#include <CommonCrypto/CommonCrypto.h> |
NS_ASSUME_NONNULL_BEGIN |
@interface QCCAESCryptor () |
- (instancetype)initWithOp:(CCOperation)op inputData:(NSData *)inputData keyData:(NSData *)keyData NS_DESIGNATED_INITIALIZER; |
@property (atomic, assign, readonly ) CCOperation op; |
// read/write versions of public properties |
@property (atomic, copy, readwrite, nullable) NSError * error; |
@property (atomic, copy, readwrite, nullable) NSData * outputData; |
@end |
NS_ASSUME_NONNULL_END |
@implementation QCCAESCryptor |
- (instancetype)init { |
abort(); |
} |
- (instancetype)initWithOp:(CCOperation)op inputData:(NSData *)inputData keyData:(NSData *)keyData { |
NSParameterAssert(inputData != nil); |
NSParameterAssert(keyData != nil); |
self = [super init]; |
if (self != nil) { |
self->_op = op; |
self->_inputData = [inputData copy]; |
self->_keyData = [keyData copy]; |
self->_ivData = [[NSMutableData alloc] initWithLength:kCCBlockSizeAES128]; |
} |
return self; |
} |
- (instancetype)initToEncryptInputData:(NSData *)inputData keyData:(NSData *)keyData { |
return [self initWithOp:kCCEncrypt inputData:inputData keyData:keyData]; |
} |
- (instancetype)initToDecryptInputData:(NSData *)inputData keyData:(NSData *)keyData { |
return [self initWithOp:kCCDecrypt inputData:inputData keyData:keyData]; |
} |
- (void)main { |
CCCryptorStatus err; |
NSUInteger keyDataLength; |
NSMutableData * result; |
size_t resultLength; |
// We check for common input problems to make it easier for someone tracing through |
// the code to find problems (rather than just getting a mysterious kCCParamError back |
// from CCCrypt). |
err = kCCSuccess; |
if ((self.inputData.length % kCCBlockSizeAES128) != 0) { |
err = kCCParamError; |
} |
keyDataLength = self.keyData.length; |
if ( (keyDataLength != kCCKeySizeAES128) && (keyDataLength != kCCKeySizeAES192) && (keyDataLength != kCCKeySizeAES256) ) { |
err = kCCParamError; |
} |
if ( (self.ivData != nil) && (self.ivData.length != kCCBlockSizeAES128) ) { |
err = kCCParamError; |
} |
if (err == kCCSuccess) { |
result = [[NSMutableData alloc] initWithLength:self.inputData.length]; |
err = CCCrypt( |
self.op, |
kCCAlgorithmAES128, |
(self.ivData == nil) ? kCCOptionECBMode : 0, |
self.keyData.bytes, self.keyData.length, |
self.ivData.bytes, // will be NULL if ivData is nil |
self.inputData.bytes, self.inputData.length, |
result.mutableBytes, result.length, |
&resultLength |
); |
} |
if (err == kCCSuccess) { |
// In the absence of padding the data out is always the same size as the data in. |
assert(resultLength == [result length]); |
self.outputData = result; |
} else { |
self.error = [NSError errorWithDomain:QCCAESCryptorErrorDomain code:err userInfo:nil]; |
} |
} |
@end |
NSString * QCCAESCryptorErrorDomain = @"QCCAESCryptorErrorDomain"; |
Copyright © 2016 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2016-11-17