mirror of
https://github.com/signalapp/libsignal.git
synced 2026-04-26 01:35:22 +02:00
154 lines
4.8 KiB
Swift
154 lines
4.8 KiB
Swift
//
|
|
// Copyright 2023 Signal Messenger, LLC.
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
//
|
|
|
|
import Foundation
|
|
import SignalFfi
|
|
|
|
public enum SizeChoice: Sendable {
|
|
case bytes(UInt32)
|
|
case chunkOf(UInt32)
|
|
|
|
fileprivate func sizeInBytes() throws -> UInt32 {
|
|
switch self {
|
|
case .bytes(let n):
|
|
return n
|
|
case .chunkOf(let n):
|
|
return try invokeFnReturningInteger {
|
|
signal_incremental_mac_calculate_chunk_size($0, n)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public class IncrementalMacContext: NativeHandleOwner<SignalMutPointerIncrementalMac> {
|
|
private var _digest: Data = .init()
|
|
|
|
public private(set) var chunkSizeInBytes: UInt32 = 0
|
|
|
|
public convenience init<Key: ContiguousBytes>(key: Key, chunkSize sizeChoice: SizeChoice) throws {
|
|
let chunkSize = try sizeChoice.sizeInBytes()
|
|
let handle = try key.withUnsafeBorrowedBuffer { keyBuffer in
|
|
try invokeFnReturningValueByPointer(.init()) {
|
|
signal_incremental_mac_initialize($0, keyBuffer, chunkSize)
|
|
}
|
|
}
|
|
self.init(owned: NonNull(handle)!)
|
|
self.chunkSizeInBytes = chunkSize
|
|
}
|
|
|
|
override internal class func destroyNativeHandle(
|
|
_ handle: NonNull<SignalMutPointerIncrementalMac>
|
|
) -> SignalFfiErrorRef? {
|
|
return signal_incremental_mac_destroy(handle.pointer)
|
|
}
|
|
|
|
public func update<Bytes: ContiguousBytes>(_ bytes: Bytes) throws {
|
|
let digest = try bytes.withUnsafeBorrowedBuffer { bytesPtr in
|
|
try withNativeHandle { nativeHandle in
|
|
try invokeFnReturningData {
|
|
signal_incremental_mac_update($0, nativeHandle, bytesPtr, 0, UInt32(bytesPtr.length))
|
|
}
|
|
}
|
|
}
|
|
self._digest.append(contentsOf: digest)
|
|
}
|
|
|
|
public func finalize() throws -> Data {
|
|
let digest =
|
|
try withNativeHandle { nativeHandle in
|
|
try invokeFnReturningData {
|
|
signal_incremental_mac_finalize($0, nativeHandle)
|
|
}
|
|
}
|
|
self._digest.append(contentsOf: digest)
|
|
return Data(self._digest)
|
|
}
|
|
}
|
|
|
|
extension SignalMutPointerIncrementalMac: SignalMutPointer {
|
|
public typealias ConstPointer = OpaquePointer?
|
|
|
|
public init(untyped: OpaquePointer?) {
|
|
self.init(raw: untyped)
|
|
}
|
|
|
|
public func toOpaque() -> OpaquePointer? {
|
|
self.raw
|
|
}
|
|
|
|
public func const() -> Self.ConstPointer {
|
|
nil
|
|
}
|
|
}
|
|
|
|
public class ValidatingMacContext: NativeHandleOwner<SignalMutPointerValidatingMac> {
|
|
public convenience init<
|
|
Key: ContiguousBytes,
|
|
Digest: ContiguousBytes
|
|
>(key: Key, chunkSize sizeChoice: SizeChoice, expectingDigest digest: Digest) throws {
|
|
let chunkSize = try sizeChoice.sizeInBytes()
|
|
let handle = try key.withUnsafeBorrowedBuffer { keyBuffer in
|
|
try digest.withUnsafeBorrowedBuffer { digestBuffer in
|
|
try invokeFnReturningValueByPointer(.init()) {
|
|
signal_validating_mac_initialize($0, keyBuffer, chunkSize, digestBuffer)
|
|
}
|
|
}
|
|
}
|
|
guard let checkedHandle = NonNull<SignalMutPointerValidatingMac>(handle) else {
|
|
throw SignalError.verificationFailed("invalid configuration data")
|
|
}
|
|
self.init(owned: checkedHandle)
|
|
}
|
|
|
|
override internal class func destroyNativeHandle(
|
|
_ handle: NonNull<SignalMutPointerValidatingMac>
|
|
) -> SignalFfiErrorRef? {
|
|
return signal_validating_mac_destroy(handle.pointer)
|
|
}
|
|
|
|
public func update<Bytes: ContiguousBytes>(_ bytes: Bytes) throws -> UInt32 {
|
|
let validBytesCount = try bytes.withUnsafeBorrowedBuffer { bytesPtr in
|
|
try withNativeHandle { nativeHandle in
|
|
try invokeFnReturningInteger {
|
|
signal_validating_mac_update($0, nativeHandle, bytesPtr, 0, UInt32(bytesPtr.length))
|
|
}
|
|
}
|
|
}
|
|
if validBytesCount < 0 {
|
|
throw SignalError.verificationFailed("Bad incremental MAC")
|
|
}
|
|
return UInt32(validBytesCount)
|
|
}
|
|
|
|
public func finalize() throws -> UInt32 {
|
|
let validBytesCount =
|
|
try withNativeHandle { nativeHandle in
|
|
try invokeFnReturningInteger {
|
|
signal_validating_mac_finalize($0, nativeHandle)
|
|
}
|
|
}
|
|
if validBytesCount < 0 {
|
|
throw SignalError.verificationFailed("Bad incremental MAC (finalize)")
|
|
}
|
|
return UInt32(validBytesCount)
|
|
}
|
|
}
|
|
|
|
extension SignalMutPointerValidatingMac: SignalMutPointer {
|
|
public typealias ConstPointer = OpaquePointer?
|
|
|
|
public init(untyped: OpaquePointer?) {
|
|
self.init(raw: untyped)
|
|
}
|
|
|
|
public func toOpaque() -> OpaquePointer? {
|
|
self.raw
|
|
}
|
|
|
|
public func const() -> Self.ConstPointer {
|
|
nil
|
|
}
|
|
}
|