TM-SGNL-iOS/SignalServiceKit/Security/OWSRecipientIdentity.m
TeleMessage developers dde0620daf initial commit
2025-05-03 12:28:28 -07:00

202 lines
6.8 KiB
Objective-C

//
// Copyright 2017 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
#import "OWSRecipientIdentity.h"
#import <SignalServiceKit/SignalServiceKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
NSString *OWSVerificationStateToString(OWSVerificationState verificationState)
{
switch (verificationState) {
case OWSVerificationStateDefault:
return @"OWSVerificationStateDefault";
case OWSVerificationStateVerified:
return @"OWSVerificationStateVerified";
case OWSVerificationStateNoLongerVerified:
return @"OWSVerificationStateNoLongerVerified";
case OWSVerificationStateDefaultAcknowledged:
return @"OWSVerificationStateDefaultAcknowledged";
}
}
static SSKProtoVerifiedState OWSVerificationStateToProtoState(OWSVerificationState verificationState)
{
switch (verificationState) {
case OWSVerificationStateDefault:
case OWSVerificationStateDefaultAcknowledged:
return SSKProtoVerifiedStateDefault;
case OWSVerificationStateVerified:
return SSKProtoVerifiedStateVerified;
case OWSVerificationStateNoLongerVerified:
return SSKProtoVerifiedStateUnverified;
}
}
SSKProtoVerified *_Nullable BuildVerifiedProtoWithAddress(SignalServiceAddress *address,
NSData *identityKey,
OWSVerificationState verificationState,
NSUInteger paddingBytesLength)
{
OWSCAssertDebug(identityKey.length == OWSIdentityManagerObjCBridge.identityKeyLength);
OWSCAssertDebug(address.isValid);
// we only sync user's marking as un/verified. Never sync the conflicted state, the sibling device
// will figure that out on it's own.
OWSCAssertDebug(verificationState != OWSVerificationStateNoLongerVerified);
SSKProtoVerifiedBuilder *verifiedBuilder = [SSKProtoVerified builder];
verifiedBuilder.destinationAci = address.aciString;
verifiedBuilder.identityKey = identityKey;
verifiedBuilder.state = OWSVerificationStateToProtoState(verificationState);
if (paddingBytesLength > 0) {
// We add the same amount of padding in the VerificationStateSync message and it's corresponding NullMessage so
// that the sync message is indistinguishable from an outgoing Sent transcript corresponding to the NullMessage.
// We pad the NullMessage so as to obscure it's content. The sync message (like all sync messages) will be
// *additionally* padded by the superclass while being sent. The end result is we send a NullMessage of a
// non-distinct size, and a verification sync which is ~1-512 bytes larger then that.
verifiedBuilder.nullMessage = [Randomness generateRandomBytes:paddingBytesLength];
}
return [verifiedBuilder buildInfallibly];
}
NSUInteger const RecipientIdentitySchemaVersion = 1;
@interface OWSRecipientIdentity ()
@property (atomic) OWSVerificationState verificationState;
@property (nonatomic, readonly) NSUInteger recipientIdentitySchemaVersion;
@end
/**
* Record for a recipients identity key and some meta data around it used to make trust decisions.
*
* NOTE: Instances of this class MUST only be retrieved/persisted via it's internal `dbConnection`,
* which makes some special accommodations to enforce consistency.
*/
@implementation OWSRecipientIdentity
#pragma mark - Table Contents
- (nullable instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
if (![coder decodeObjectForKey:@"verificationState"]) {
_verificationState = OWSVerificationStateDefault;
}
if (_recipientIdentitySchemaVersion < 1) {
_accountId = [coder decodeObjectForKey:@"recipientId"];
OWSAssertDebug(_accountId);
}
_recipientIdentitySchemaVersion = RecipientIdentitySchemaVersion;
}
return self;
}
- (instancetype)initWithRecipientUniqueId:(NSString *)recipientUniqueId
identityKey:(NSData *)identityKey
isFirstKnownKey:(BOOL)isFirstKnownKey
createdAt:(NSDate *)createdAt
verificationState:(OWSVerificationState)verificationState
{
self = [super initWithUniqueId:recipientUniqueId];
if (!self) {
return self;
}
_accountId = recipientUniqueId;
_identityKey = identityKey;
_isFirstKnownKey = isFirstKnownKey;
_createdAt = createdAt;
_verificationState = verificationState;
_recipientIdentitySchemaVersion = RecipientIdentitySchemaVersion;
return self;
}
// --- CODE GENERATION MARKER
// This snippet is generated by /Scripts/sds_codegen/sds_generate.py. Do not manually edit it, instead run
// `sds_codegen.sh`.
// clang-format off
- (instancetype)initWithGrdbId:(int64_t)grdbId
uniqueId:(NSString *)uniqueId
accountId:(NSString *)accountId
createdAt:(NSDate *)createdAt
identityKey:(NSData *)identityKey
isFirstKnownKey:(BOOL)isFirstKnownKey
verificationState:(OWSVerificationState)verificationState
{
self = [super initWithGrdbId:grdbId
uniqueId:uniqueId];
if (!self) {
return self;
}
_accountId = accountId;
_createdAt = createdAt;
_identityKey = identityKey;
_isFirstKnownKey = isFirstKnownKey;
_verificationState = verificationState;
return self;
}
// clang-format on
// --- CODE GENERATION MARKER
- (void)updateWithVerificationState:(OWSVerificationState)verificationState
transaction:(SDSAnyWriteTransaction *)transaction
{
OWSAssertDebug(transaction);
// Ensure changes are persisted without clobbering any work done on another thread or instance.
[self
anyUpdateWithTransaction:transaction
block:^(OWSRecipientIdentity *_Nonnull obj) { obj.verificationState = verificationState; }];
}
- (BOOL)wasIdentityVerified
{
switch (self.verificationState) {
case OWSVerificationStateVerified:
case OWSVerificationStateNoLongerVerified:
return YES;
case OWSVerificationStateDefault:
case OWSVerificationStateDefaultAcknowledged:
return NO;
}
}
#pragma mark - debug
+ (void)printAllIdentities
{
OWSLogInfo(@"### All Recipient Identities ###");
__block int count = 0;
[SSKEnvironment.shared.databaseStorageRef readWithBlock:^(SDSAnyReadTransaction *transaction) {
[OWSRecipientIdentity
anyEnumerateWithTransaction:transaction
batched:YES
block:^(OWSRecipientIdentity *recipientIdentity, BOOL *stop) {
OWSLogInfo(@"Identity %d: %@", count, recipientIdentity.debugDescription);
}];
}];
}
@end
NS_ASSUME_NONNULL_END