181 lines
7.6 KiB
Objective-C
181 lines
7.6 KiB
Objective-C
#import "CommitPacket.h"
|
|
#import "Util.h"
|
|
#import "CryptoTools.h"
|
|
|
|
@implementation CommitPacket
|
|
|
|
@synthesize agreementSpecId, authSpecId, cipherSpecId, dhPart2HelloCommitment, h2, hashSpecId, sasSpecId, zid;
|
|
|
|
|
|
#define ZID_LENGTH 12
|
|
#define HASH_SPEC_LENGTH 4
|
|
#define CIPHER_SPEC_LENGTH 4
|
|
#define AUTH_SPEC_LENGTH 4
|
|
#define AGREE_SPEC_LENGTH 4
|
|
#define SAS_SPEC_LENGTH 4
|
|
#define COMMIT_LENGTH 32
|
|
|
|
#define HASH_SPEC_OFFSET HASH_CHAIN_ITEM_LENGTH + ZID_LENGTH
|
|
#define CIPHER_SPEC_OFFSET HASH_SPEC_OFFSET + HASH_SPEC_LENGTH
|
|
#define AUTH_SPEC_OFFSET CIPHER_SPEC_OFFSET + CIPHER_SPEC_LENGTH
|
|
#define AGREE_SPEC_OFFSET AUTH_SPEC_OFFSET + AUTH_SPEC_LENGTH
|
|
#define SAS_SPEC_OFFSET AGREE_SPEC_OFFSET + AGREE_SPEC_LENGTH
|
|
#define COMMIT_OFFSET SAS_SPEC_OFFSET + SAS_SPEC_LENGTH
|
|
|
|
|
|
+(CommitPacket*) commitPacketWithDefaultSpecsAndKeyAgreementProtocol:(id<KeyAgreementProtocol>)keyAgreementProtocol
|
|
andHashChain:(HashChain*)hashChain
|
|
andZid:(Zid*)zid
|
|
andCommitmentToHello:(HelloPacket*)hello
|
|
andDhPart2:(DhPacket*)dhPart2 {
|
|
|
|
require(keyAgreementProtocol != nil);
|
|
require(hashChain != nil);
|
|
require(zid != nil);
|
|
require(hello != nil);
|
|
require(dhPart2 != nil);
|
|
|
|
NSData* dhPart2Data = [[dhPart2 embeddedIntoHandshakePacket] dataUsedForAuthentication];
|
|
NSData* helloData = [[hello embeddedIntoHandshakePacket] dataUsedForAuthentication];
|
|
return [CommitPacket commitPacketWithHashChainH2:hashChain.h2
|
|
andZid:zid
|
|
andHashSpecId:COMMIT_DEFAULT_HASH_SPEC_ID
|
|
andCipherSpecId:COMMIT_DEFAULT_CIPHER_SPEC_ID
|
|
andAuthSpecId:COMMIT_DEFAULT_AUTH_SPEC_ID
|
|
andAgreeSpecId:keyAgreementProtocol.getId
|
|
andSasSpecId:COMMIT_DEFAULT_SAS_SPEC_ID
|
|
andDhPart2HelloCommitment:@[dhPart2Data, helloData].concatDatas.hashWithSha256
|
|
andHmacKey:hashChain.h1];
|
|
}
|
|
|
|
+(CommitPacket*) commitPacketWithHashChainH2:(NSData*)h2
|
|
andZid:(Zid*)zid
|
|
andHashSpecId:(NSData*)hashSpecId
|
|
andCipherSpecId:(NSData*)cipherSpecId
|
|
andAuthSpecId:(NSData*)authSpecId
|
|
andAgreeSpecId:(NSData*)agreeSpecId
|
|
andSasSpecId:(NSData*)sasSpecId
|
|
andDhPart2HelloCommitment:(NSData*)dhPart2HelloCommitment
|
|
andHmacKey:(NSData*)hmacKey {
|
|
|
|
require(h2 != nil);
|
|
require(zid != nil);
|
|
require(hashSpecId != nil);
|
|
require(cipherSpecId != nil);
|
|
require(authSpecId != nil);
|
|
require(agreeSpecId != nil);
|
|
require(sasSpecId != nil);
|
|
require(dhPart2HelloCommitment != nil);
|
|
require(hmacKey != nil);
|
|
|
|
require(h2.length == HASH_CHAIN_ITEM_LENGTH);
|
|
require(hashSpecId.length == HASH_SPEC_LENGTH);
|
|
require(cipherSpecId.length == CIPHER_SPEC_LENGTH);
|
|
require(authSpecId.length == AUTH_SPEC_LENGTH);
|
|
require(agreeSpecId.length == AGREE_SPEC_LENGTH);
|
|
require(sasSpecId.length == SAS_SPEC_LENGTH);
|
|
|
|
CommitPacket* p = [CommitPacket new];
|
|
|
|
p->h2 = h2;
|
|
p->zid = zid;
|
|
p->hashSpecId = hashSpecId;
|
|
p->cipherSpecId = cipherSpecId;
|
|
p->authSpecId = authSpecId;
|
|
p->agreementSpecId = agreeSpecId;
|
|
p->sasSpecId = sasSpecId;
|
|
p->dhPart2HelloCommitment = dhPart2HelloCommitment;
|
|
|
|
p->embedding = [p embedInHandshakePacketAuthenticatedWith:hmacKey];
|
|
|
|
return p;
|
|
}
|
|
-(HandshakePacket*) embedInHandshakePacketAuthenticatedWith:(NSData*)hmacKey {
|
|
|
|
require(hmacKey != nil);
|
|
requireState(h2.length == HASH_CHAIN_ITEM_LENGTH);
|
|
requireState(hashSpecId.length == HASH_SPEC_LENGTH);
|
|
requireState(cipherSpecId.length == CIPHER_SPEC_LENGTH);
|
|
requireState(authSpecId.length == AUTH_SPEC_LENGTH);
|
|
requireState(agreementSpecId.length == AGREE_SPEC_LENGTH);
|
|
requireState(sasSpecId.length == SAS_SPEC_LENGTH);
|
|
|
|
NSData* payload = @[
|
|
h2,
|
|
zid.getData,
|
|
hashSpecId,
|
|
cipherSpecId,
|
|
authSpecId,
|
|
agreementSpecId,
|
|
sasSpecId,
|
|
dhPart2HelloCommitment
|
|
].concatDatas;
|
|
|
|
return [[HandshakePacket handshakePacketWithTypeId:HANDSHAKE_TYPE_COMMIT andPayload:payload] withHmacAppended:hmacKey];
|
|
}
|
|
-(void) verifyCommitmentAgainstHello:(HelloPacket*)hello andDhPart2:(DhPacket*)dhPart2 {
|
|
require(hello != nil);
|
|
require(dhPart2 != nil);
|
|
|
|
NSData* expected = [[@[
|
|
[[dhPart2 embeddedIntoHandshakePacket] dataUsedForAuthentication],
|
|
[[hello embeddedIntoHandshakePacket] dataUsedForAuthentication]]
|
|
concatDatas] hashWithSha256];
|
|
checkOperation([dhPart2HelloCommitment isEqualToData_TimingSafe:expected]);
|
|
}
|
|
-(void) verifyMacWithHashChainH1:(NSData*)hashChainH1 {
|
|
checkOperation([[hashChainH1 hashWithSha256] isEqualToData_TimingSafe:h2]);
|
|
[embedding withHmacVerifiedAndRemoved:hashChainH1];
|
|
}
|
|
|
|
+(NSData*) getH2FromPayload:(NSData*)payload {
|
|
return [payload subdataWithRange:NSMakeRange(0, HASH_CHAIN_ITEM_LENGTH)];
|
|
}
|
|
+(Zid*) getZidFromPayload:(NSData*)payload {
|
|
return [Zid zidWithData:[payload subdataWithRange:NSMakeRange(HASH_CHAIN_ITEM_LENGTH, ZID_LENGTH)]];
|
|
}
|
|
+(NSData*) getHashSpecIdFromPayload:(NSData*)payload {
|
|
return [payload subdataWithRange:NSMakeRange(HASH_SPEC_OFFSET, HASH_SPEC_LENGTH)];
|
|
}
|
|
+(NSData*) getCipherSpecIdFromPayload:(NSData*)payload {
|
|
return [payload subdataWithRange:NSMakeRange(CIPHER_SPEC_OFFSET, CIPHER_SPEC_LENGTH)];
|
|
}
|
|
+(NSData*) getAuthSpecIdFromPayload:(NSData*)payload {
|
|
return [payload subdataWithRange:NSMakeRange(AUTH_SPEC_OFFSET, AUTH_SPEC_LENGTH)];
|
|
}
|
|
+(NSData*) getAgreeSpecIdFromPayload:(NSData*)payload {
|
|
return [payload subdataWithRange:NSMakeRange(AGREE_SPEC_OFFSET, AGREE_SPEC_LENGTH)];
|
|
}
|
|
+(NSData*) getSasSpecIdFromPayload:(NSData*)payload {
|
|
return [payload subdataWithRange:NSMakeRange(SAS_SPEC_OFFSET, SAS_SPEC_LENGTH)];
|
|
}
|
|
+(NSData*) getCommitmentFromPayload:(NSData*)payload {
|
|
return [payload subdataWithRange:NSMakeRange(COMMIT_OFFSET, COMMIT_LENGTH)];
|
|
}
|
|
+(CommitPacket*) commitPacketParsedFromHandshakePacket:(HandshakePacket*)handshakePacket {
|
|
require(handshakePacket != nil);
|
|
checkOperation([[handshakePacket typeId] isEqualToData:HANDSHAKE_TYPE_COMMIT]);
|
|
NSData* payload = [handshakePacket payload];
|
|
checkOperation(payload.length == COMMIT_OFFSET + COMMIT_LENGTH + HANDSHAKE_TRUNCATED_HMAC_LENGTH);
|
|
|
|
CommitPacket* p = [CommitPacket new];
|
|
|
|
p->h2 = [self getH2FromPayload:payload];
|
|
p->zid = [self getZidFromPayload:payload];
|
|
p->hashSpecId = [self getHashSpecIdFromPayload:payload];
|
|
p->cipherSpecId = [self getCipherSpecIdFromPayload:payload];
|
|
p->authSpecId = [self getAuthSpecIdFromPayload:payload];
|
|
p->agreementSpecId = [self getAgreeSpecIdFromPayload:payload];
|
|
p->sasSpecId = [self getSasSpecIdFromPayload:payload];
|
|
p->dhPart2HelloCommitment = [self getCommitmentFromPayload:payload];
|
|
p->embedding = handshakePacket;
|
|
|
|
return p;
|
|
}
|
|
|
|
-(HandshakePacket*) embeddedIntoHandshakePacket {
|
|
return embedding;
|
|
}
|
|
|
|
@end
|