You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
session-ios/SessionMessagingKit/SessionUtil/Config Handling/SessionUtil+GroupKeys.swift

131 lines
4.6 KiB
Swift

// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import GRDB
import SessionUtil
import SessionUtilitiesKit
// MARK: - Size Restrictions
public extension SessionUtil {
static var sizeAuthDataBytes: Int { 100 }
static var sizeSubaccountBytes: Int { 36 }
static var sizeSubaccountSigBytes: Int { 64 }
static var sizeSubaccountSignatureBytes: Int { 64 }
}
// MARK: - Group Info Handling
internal extension SessionUtil {
static let columnsRelatedToGroupKeys: [ColumnExpression] = []
// MARK: - Incoming Changes
static func handleGroupKeysUpdate(
_ db: Database,
in config: Config?,
groupSessionId: SessionId,
using dependencies: Dependencies
) throws {
guard config.needsDump else { return }
guard case .groupKeys(let conf, _, _) = config else { throw SessionUtilError.invalidConfigObject }
}
}
// MARK: - Outgoing Changes
internal extension SessionUtil {
static func rekey(
_ db: Database,
groupSessionId: SessionId,
using dependencies: Dependencies
) throws {
try SessionUtil.performAndPushChange(
db,
for: .groupKeys,
sessionId: groupSessionId,
using: dependencies
) { config in
guard case .groupKeys(let conf, let infoConf, let membersConf) = config else {
throw SessionUtilError.invalidConfigObject
}
// Performing a `rekey` returns the updated key data which we don't use directly, this updated
// key will now be returned by `groups_keys_pending_config` which the `ConfigurationSyncJob` uses
// when generating pending changes for group keys so we don't need to push it directly
var pushResult: UnsafePointer<UInt8>? = nil
var pushResultLen: Int = 0
guard groups_keys_rekey(conf, infoConf, membersConf, &pushResult, &pushResultLen) else {
throw SessionUtilError.failedToRekeyGroup
}
}
}
static func keySupplement(
_ db: Database,
groupSessionId: SessionId,
memberIds: Set<String>,
using dependencies: Dependencies
) throws {
try SessionUtil.performAndPushChange(
db,
for: .groupKeys,
sessionId: groupSessionId,
using: dependencies
) { config in
guard case .groupKeys(let conf, _, _) = config else { throw SessionUtilError.invalidConfigObject }
var cMemberIds: [UnsafePointer<CChar>?] = memberIds
.map { id in id.cArray.nullTerminated() }
.unsafeCopy()
defer { cMemberIds.forEach { $0?.deallocate() } }
// Performing a `key_supplement` returns the updated key data which we don't use directly, this updated
// key will now be returned by `groups_keys_pending_config` which the `ConfigurationSyncJob` uses
// when generating pending changes for group keys so we don't need to push it directly
var pushResult: UnsafeMutablePointer<UInt8>? = nil
var pushResultLen: Int = 0
guard groups_keys_key_supplement(conf, &cMemberIds, cMemberIds.count, &pushResult, &pushResultLen) else {
throw SessionUtilError.failedToKeySupplementGroup
}
// Must deallocate on success
pushResult?.deallocate()
}
}
static func generateAuthData(
groupSessionId: SessionId,
memberId: String,
using dependencies: Dependencies
) throws -> Authentication.Info {
try dependencies[singleton: .crypto].generate(
.memberAuthData(
config: dependencies[cache: .sessionUtil]
.config(for: .groupKeys, sessionId: groupSessionId)
.wrappedValue,
groupSessionId: groupSessionId,
memberId: memberId
)
)
}
static func generateSubaccountSignature(
groupSessionId: SessionId,
verificationBytes: [UInt8],
memberAuthData: Data,
using dependencies: Dependencies
) throws -> Authentication.Signature {
try dependencies[singleton: .crypto].generate(
.subaccountSignature(
config: dependencies[cache: .sessionUtil]
.config(for: .groupKeys, sessionId: groupSessionId)
.wrappedValue,
verificationBytes: verificationBytes,
memberAuthData: memberAuthData
)
)
}
}