Compare commits

...

1 Commits

Author SHA1 Message Date
Jordan Rose
f4cff38765 Type-safe context parameters for the stores
This first commit is just a prototype using SenderKeyStore.
2020-10-05 11:10:44 -07:00
6 changed files with 63 additions and 37 deletions

View File

@ -1,5 +1,7 @@
class InMemorySignalProtocolStore : IdentityKeyStore, PreKeyStore, SignedPreKeyStore, SessionStore, SenderKeyStore {
typealias Context = Void
private var public_keys : [ProtocolAddress : IdentityKey] = [:]
private var private_key : IdentityKeyPair;
private var device_id : UInt32;
@ -77,10 +79,10 @@ class InMemorySignalProtocolStore : IdentityKeyStore, PreKeyStore, SignedPreKeyS
session_map[address] = record;
}
func storeSenderKey(name: SenderKeyName, record: SenderKeyRecord, ctx: UnsafeMutableRawPointer?) throws {
func storeSenderKey(name: SenderKeyName, record: SenderKeyRecord, ctx: Void) throws {
sender_key_map[name] = record
}
func loadSenderKey(name: SenderKeyName, ctx: UnsafeMutableRawPointer?) throws -> SenderKeyRecord? {
func loadSenderKey(name: SenderKeyName, ctx: Void) throws -> SenderKeyRecord? {
return sender_key_map[name]
}
}

View File

@ -6,6 +6,12 @@ enum Direction {
case Receiving
}
protocol SignalFfiStore {
associatedtype FfiStore
associatedtype Context
func withFfiStore<Result>(context: Context, _ body: (_ store: UnsafePointer<FfiStore>, _ opaqueContextPointer: UnsafeMutableRawPointer) throws -> Result) rethrows -> Result
}
protocol IdentityKeyStore: AnyObject {
func getIdentityKeyPair(ctx: UnsafeMutableRawPointer?) throws -> IdentityKeyPair
func getLocalRegistrationId(ctx: UnsafeMutableRawPointer?) throws -> UInt32
@ -30,7 +36,21 @@ protocol SessionStore: AnyObject {
func storeSession(address: ProtocolAddress, record: SessionRecord, ctx: UnsafeMutableRawPointer?) throws
}
protocol SenderKeyStore: AnyObject {
func storeSenderKey(name: SenderKeyName, record: SenderKeyRecord, ctx: UnsafeMutableRawPointer?) throws
func loadSenderKey(name: SenderKeyName, ctx: UnsafeMutableRawPointer?) throws -> SenderKeyRecord?
protocol AnySenderKeyStore {
func _storeSenderKey(name: SenderKeyName, record: SenderKeyRecord, ctx: UnsafeMutableRawPointer?) throws
func _loadSenderKey(name: SenderKeyName, ctx: UnsafeMutableRawPointer?) throws -> SenderKeyRecord?
}
protocol SenderKeyStore: AnySenderKeyStore, SignalFfiStore where FfiStore == SignalSenderKeyStore {
func storeSenderKey(name: SenderKeyName, record: SenderKeyRecord, ctx: Context) throws
func loadSenderKey(name: SenderKeyName, ctx: Context) throws -> SenderKeyRecord?
}
extension SenderKeyStore {
func _storeSenderKey(name: SenderKeyName, record: SenderKeyRecord, ctx: UnsafeMutableRawPointer?) throws {
try storeSenderKey(name: name, record: record, ctx: ctx!.assumingMemoryBound(to: Context.self).pointee)
}
func _loadSenderKey(name: SenderKeyName, ctx: UnsafeMutableRawPointer?) throws -> SenderKeyRecord? {
return try loadSenderKey(name: name, ctx: ctx!.assumingMemoryBound(to: Context.self).pointee)
}
}

View File

@ -97,35 +97,35 @@ func ProcessPreKeyBundle(bundle: PreKeyBundle,
}
}
func GroupEncrypt(group_id: SenderKeyName,
message: [UInt8],
store: SenderKeyStore,
ctx: UnsafeMutableRawPointer?) throws -> [UInt8] {
return try withSenderKeyStore(store) { ffiStore in
func GroupEncrypt<Store: SenderKeyStore>(group_id: SenderKeyName,
message: [UInt8],
store: Store,
ctx: Store.Context) throws -> [UInt8] {
return try store.withFfiStore(context: ctx) { ffiStore, ctxPtr in
return try invokeFnReturningArray {
signal_group_encrypt_message($0, $1, group_id.nativeHandle(), message, message.count, ffiStore, ctx)
signal_group_encrypt_message($0, $1, group_id.nativeHandle(), message, message.count, ffiStore, ctxPtr)
}
}
}
func GroupDecrypt(group_id: SenderKeyName,
message: [UInt8],
store: SenderKeyStore,
ctx: UnsafeMutableRawPointer?) throws -> [UInt8] {
return try withSenderKeyStore(store) { ffiStore in
func GroupDecrypt<Store: SenderKeyStore>(group_id: SenderKeyName,
message: [UInt8],
store: Store,
ctx: Store.Context) throws -> [UInt8] {
return try store.withFfiStore(context: ctx) { ffiStore, ctxPtr in
return try invokeFnReturningArray {
signal_group_decrypt_message($0, $1, group_id.nativeHandle(), message, message.count, ffiStore, ctx)
signal_group_decrypt_message($0, $1, group_id.nativeHandle(), message, message.count, ffiStore, ctxPtr)
}
}
}
func ProcessSenderKeyDistributionMessage(sender_name: SenderKeyName,
msg: SenderKeyDistributionMessage,
store: SenderKeyStore,
ctx: UnsafeMutableRawPointer?) throws {
try withSenderKeyStore(store) {
func ProcessSenderKeyDistributionMessage<Store: SenderKeyStore>(sender_name: SenderKeyName,
msg: SenderKeyDistributionMessage,
store: Store,
ctx: Store.Context) throws {
try store.withFfiStore(context: ctx) {
try CheckError(signal_process_sender_key_distribution_message(sender_name.nativeHandle(),
msg.nativeHandle(),
$0, ctx))
$0, $1))
}
}

View File

@ -306,18 +306,19 @@ func withSessionStore<Result>(_ store: SessionStore, _ body: (UnsafePointer<Sign
}
}
func withSenderKeyStore<Result>(_ store: SenderKeyStore, _ body: (UnsafePointer<SignalSenderKeyStore>) throws -> Result) rethrows -> Result {
extension SenderKeyStore {
func withFfiStore<Result>(context: Context, _ body: (UnsafePointer<SignalSenderKeyStore>, UnsafeMutableRawPointer) throws -> Result) rethrows -> Result {
func ffiShimStoreSenderKey(store_ctx: UnsafeMutableRawPointer?,
sender_name: OpaquePointer?,
record: OpaquePointer?,
ctx: UnsafeMutableRawPointer?) -> Int32 {
do {
let store = store_ctx!.assumingMemoryBound(to: SenderKeyStore.self).pointee
let store = store_ctx!.assumingMemoryBound(to: AnySenderKeyStore.self).pointee
var sender_name = SenderKeyName(unowned: sender_name)
defer { cloneOrForgetAsNeeded(&sender_name) }
var record = SenderKeyRecord(unowned: record)
defer { cloneOrForgetAsNeeded(&record) }
try store.storeSenderKey(name: sender_name, record: record, ctx: ctx)
try store._storeSenderKey(name: sender_name, record: record, ctx: ctx)
return 0
}
catch {
@ -330,10 +331,10 @@ func withSenderKeyStore<Result>(_ store: SenderKeyStore, _ body: (UnsafePointer<
sender_name: OpaquePointer?,
ctx: UnsafeMutableRawPointer?) -> Int32 {
do {
let store = store_ctx!.assumingMemoryBound(to: SenderKeyStore.self).pointee
let store = store_ctx!.assumingMemoryBound(to: AnySenderKeyStore.self).pointee
var sender_name = SenderKeyName(unowned: sender_name)
defer { cloneOrForgetAsNeeded(&sender_name) }
if var record = try store.loadSenderKey(name: sender_name, ctx: ctx) {
if var record = try store._loadSenderKey(name: sender_name, ctx: ctx) {
recordp!.pointee = try cloneOrTakeHandle(from: &record)
} else {
recordp!.pointee = nil
@ -345,13 +346,16 @@ func withSenderKeyStore<Result>(_ store: SenderKeyStore, _ body: (UnsafePointer<
}
}
return try withUnsafePointer(to: store) {
return try withUnsafePointer(to: self as AnySenderKeyStore) {
// We're not actually going to mutate through 'ffiStore.ctx';
// it's just the usual convention of `void *` for context fields.
var ffiStore = SignalSenderKeyStore(
ctx: UnsafeMutableRawPointer(mutating: $0),
load_sender_key: ffiShimLoadSenderKey,
store_sender_key: ffiShimStoreSenderKey)
return try body(&ffiStore)
return try withUnsafePointer(to: context) {
try body(&ffiStore, UnsafeMutableRawPointer(mutating: $0))
}
}
}
}

View File

@ -12,10 +12,10 @@ class SenderKeyDistributionMessage {
return handle
}
init(name: SenderKeyName, store: SenderKeyStore, ctx: UnsafeMutableRawPointer?) throws {
try withSenderKeyStore(store) {
init<Store: SenderKeyStore>(name: SenderKeyName, store: Store, ctx: Store.Context) throws {
try store.withFfiStore(context: ctx) {
try CheckError(signal_create_sender_key_distribution_message(&handle, name.nativeHandle(),
$0, ctx))
$0, $1))
}
}

View File

@ -185,20 +185,20 @@ class SwiftSignalTests: XCTestCase {
let a_store = try! InMemorySignalProtocolStore()
let skdm = try! SenderKeyDistributionMessage(name: group_id, store: a_store, ctx: nil)
let skdm = try! SenderKeyDistributionMessage(name: group_id, store: a_store, ctx: ())
let skdm_bits = try! skdm.serialize()
let skdm_r = try! SenderKeyDistributionMessage(bytes: skdm_bits)
let a_ctext = try! GroupEncrypt(group_id: group_id, message: [1,2,3], store: a_store, ctx: nil)
let a_ctext = try! GroupEncrypt(group_id: group_id, message: [1,2,3], store: a_store, ctx: ())
let b_store = try! InMemorySignalProtocolStore()
try! ProcessSenderKeyDistributionMessage(sender_name: group_id,
msg: skdm_r,
store: b_store,
ctx: nil)
let b_ptext = try! GroupDecrypt(group_id: group_id, message: a_ctext, store: b_store, ctx: nil)
ctx: ())
let b_ptext = try! GroupDecrypt(group_id: group_id, message: a_ctext, store: b_store, ctx: ())
XCTAssertEqual(b_ptext, [1,2,3])
}