session-ios/SessionProtocolKit/Signal/Ratchet/ChainKey.m

97 lines
2.6 KiB
Objective-C

//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "ChainKey.h"
#import "TSDerivedSecrets.h"
#import <CommonCrypto/CommonCrypto.h>
#import <Curve25519Kit/Curve25519.h>
#import <SignalCoreKit/OWSAsserts.h>
NS_ASSUME_NONNULL_BEGIN
@implementation ChainKey
static NSString *const kCoderKey = @"kCoderKey";
static NSString *const kCoderIndex = @"kCoderIndex";
#define kTSKeySeedLength 1
static uint8_t kMessageKeySeed[kTSKeySeedLength] = { 01 };
static uint8_t kChainKeySeed[kTSKeySeedLength] = { 02 };
+ (BOOL)supportsSecureCoding
{
return YES;
}
- (nullable id)initWithCoder:(NSCoder *)aDecoder
{
NSData *key = [aDecoder decodeObjectOfClass:[NSData class] forKey:kCoderKey];
int index = [aDecoder decodeIntForKey:kCoderIndex];
return [self initWithData:key index:index];
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:_key forKey:kCoderKey];
[aCoder encodeInt:_index forKey:kCoderIndex];
}
- (instancetype)initWithData:(NSData *)chainKey index:(int)index
{
OWSAssert(chainKey.length == 32);
OWSAssert(index >= 0);
self = [super init];
if (self) {
_key = chainKey;
_index = index;
}
return self;
}
- (instancetype)nextChainKey
{
NSData *nextCK = [self baseMaterial:[NSData dataWithBytes:kChainKeySeed length:kTSKeySeedLength]];
OWSAssert(nextCK.length == 32);
int nextIndex;
ows_add_overflow(self.index, 1, &nextIndex);
return [[ChainKey alloc] initWithData:nextCK index:nextIndex];
}
- (MessageKeys *)throws_messageKeys
{
NSData *inputKeyMaterial = [self baseMaterial:[NSData dataWithBytes:kMessageKeySeed length:kTSKeySeedLength]];
TSDerivedSecrets *derivedSecrets = [TSDerivedSecrets throws_derivedMessageKeysWithData:inputKeyMaterial];
return [[MessageKeys alloc] initWithCipherKey:derivedSecrets.cipherKey
macKey:derivedSecrets.macKey
iv:derivedSecrets.iv
index:self.index];
}
- (NSData *)baseMaterial:(NSData *)seed
{
OWSAssert(self.key);
OWSAssert(self.key.length == 32);
OWSAssert(seed);
OWSAssert(seed.length == kTSKeySeedLength);
NSMutableData *_Nullable bufferData = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];
OWSAssert(bufferData);
CCHmacContext ctx;
CCHmacInit(&ctx, kCCHmacAlgSHA256, [self.key bytes], [self.key length]);
CCHmacUpdate(&ctx, [seed bytes], [seed length]);
CCHmacFinal(&ctx, bufferData.mutableBytes);
return [bufferData copy];
}
@end
NS_ASSUME_NONNULL_END