Skip to content

Commit

Permalink
Use Swift to set attributes for seckey
Browse files Browse the repository at this point in the history
  • Loading branch information
LandryNorris committed Feb 9, 2023
1 parent 8dbebc2 commit 14d5781
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 69 deletions.
23 changes: 23 additions & 0 deletions compile-ios.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

cd prebuilt

xcodebuild build -scheme Attributes -configuration Release -arch arm64 -sdk 'iphoneos' \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES \
-derivedDataPath './Attributes/build/' \
-project Attributes/Attributes.xcodeproj
cp Attributes/build/Build/Products/Release-iphoneos/libAttributes.a Attributes/binaries/arm64
rm -rf Attributes/build

xcodebuild build -scheme Attributes -configuration Release -arch arm64 -sdk 'iphonesimulator' \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES \
-derivedDataPath './Attributes/build/' \
-project Attributes/Attributes.xcodeproj
cp Attributes/build/Build/Products/Release-iphonesimulator/libAttributes.a Attributes/binaries/arm64-simulator
rm -rf Attributes/build

xcodebuild build -scheme Attributes -configuration Release -arch x86_64 -sdk 'iphonesimulator' \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES \
-derivedDataPath './Attributes/build/' \
-project Attributes/Attributes.xcodeproj
cp Attributes/build/Build/Products/Release-iphonesimulator/libAttributes.a Attributes/binaries/x64
rm -rf Attributes/build
18 changes: 15 additions & 3 deletions encryption/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ val kryptoVersion: String by project
plugins {
kotlin("multiplatform")
id("com.android.library")
id("io.github.ttypic.swiftklib") version "0.1.0"
}

kotlin {
Expand All @@ -14,8 +15,12 @@ kotlin {
iosArm64(),
iosSimulatorArm64()
).forEach {
it.binaries.framework {
baseName = "shared"
it.compilations {
val main by getting {
cinterops {
create("Attributes")
}
}
}
}

Expand Down Expand Up @@ -61,4 +66,11 @@ android {
targetSdk = 32
}
namespace = "io.github.landrynorris.encryption"
}
}

swiftklib {
create("Attributes") {
path = file("src/swift")
packageName("io.github.landrynorris.encryption.swift")
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package io.github.landrynorris.encryption

import io.github.landrynorris.encryption.swift.Attributes
import kotlinx.cinterop.*
import platform.CoreFoundation.*
import platform.Foundation.*
import platform.Foundation.CFBridgingRelease
import platform.Foundation.NSString
import platform.Security.*
import platform.darwin.OSStatus

Expand All @@ -16,38 +18,11 @@ actual object SecureCrypto: Crypto {
kSecAttrAccessibleWhenUnlockedThisDeviceOnly?.reinterpret(),
kSecAccessControlPrivateKeyUsage, null)

val aliasData = (alias as NSString).dataUsingEncoding(NSUTF8StringEncoding)

val privateKeyProperties = cfDictionaryOf(
mapOf(
kSecAttrIsPermanent to kCFBooleanTrue,
kSecAttrApplicationTag to CFBridgingRetain(aliasData),
kSecAttrAccessControl to access
)
)

val publicKeyProperties = cfDictionaryOf(
mapOf(
kSecAttrIsPermanent to kCFBooleanTrue,
kSecAttrApplicationTag to CFBridgingRetain(aliasData),
kSecAttrAccessControl to access
)
)

val properties = cfDictionaryOf(
mapOf(
kSecAttrKeyType to kSecAttrKeyTypeEC,
kSecAttrKeySizeInBits to CFBridgingRetain(NSNumber(256)),
//kSecAttrTokenID to kSecAttrTokenIDSecureEnclave,
kSecPrivateKeyAttrs to privateKeyProperties,
kSecPublicKeyAttrs to publicKeyProperties
)
)

val error = alloc<CFErrorRefVar>()

println("Generating key")
SecKeyCreateRandomKey(properties, error.ptr)
val props = Attributes.keyAttributes(access, ALIAS)
SecKeyCreateRandomKey(props, error.ptr)

if(error.value != null) {
val errorText = error.value?.errorString()
Expand All @@ -67,17 +42,7 @@ actual object SecureCrypto: Crypto {

private fun loadKey(alias: String): SecKeyRef? = memScoped {
println("Loading key")
val aliasData = (alias as NSString).dataUsingEncoding(NSUTF8StringEncoding)

val query = cfDictionaryOf(
mapOf(
kSecClass to kSecClassKey,
kSecAttrApplicationTag to CFBridgingRetain(aliasData),
kSecAttrKeyType to kSecAttrKeyTypeEC,
kSecMatchLimit to kSecMatchLimitOne,
kSecReturnRef to kCFBooleanTrue
)
)
val query = Attributes.keyQuery(alias)

val item = alloc<CFArrayRefVar>()
val result = SecItemCopyMatching(query, item.ptr.reinterpret())
Expand Down Expand Up @@ -146,13 +111,3 @@ actual object SecureCrypto: Crypto {
return nsErrorText as String
}
}

internal inline fun MemScope.cfDictionaryOf(map: Map<CFStringRef?, CFTypeRef?>): CFDictionaryRef? {
val size = map.size
val keys = allocArrayOf(*map.keys.toTypedArray())
val values = allocArrayOf(*map.values.toTypedArray())
return CFDictionaryCreate(kCFAllocatorDefault,
keys.reinterpret(), values.reinterpret(),
size.convert(), kCFTypeDictionaryKeyCallBacks.ptr,
kCFTypeDictionaryValueCallBacks.ptr)
}
31 changes: 31 additions & 0 deletions encryption/src/swift/Attributes.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Foundation
import Security

@objc public class Attributes: NSObject {
@objc public class func test() -> Int {
return 12
}

@objc public class func keyAttributes(_ access: SecAccessControl, tag: String) -> CFDictionary {
return [
kSecAttrKeyType as String : kSecAttrKeyTypeEC,
kSecAttrKeySizeInBits as String : 256,
kSecAttrTokenID as String : kSecAttrTokenIDSecureEnclave,
kSecPrivateKeyAttrs as String : [
kSecAttrIsPermanent as String : true,
kSecAttrApplicationTag as String : tag,
kSecAttrAccessControl as String : access
]
] as CFDictionary
}

@objc public class func keyQuery(_ tag: String) -> CFDictionary {
return [
kSecClass as String : kSecClassKey,
kSecAttrApplicationTag as String : tag,
kSecAttrKeyType as String : kSecAttrKeyTypeEC,
kSecMatchLimit as String : kSecMatchLimitOne,
kSecReturnRef as String : true
] as CFDictionary
}
}
2 changes: 0 additions & 2 deletions mobileapp/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import org.jetbrains.compose.ExperimentalComposeLibrary
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
import org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.TestExecutable
import java.io.File
import java.util.*

val keystoreProperties =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import io.github.landrynorris.multifactor.components.CreateOtpLogic
import io.github.landrynorris.multifactor.platform.Dialog

@Composable
fun CreateOtpDialog(logic: CreateOtpLogic, onDismiss: () -> Unit) {
internal fun CreateOtpDialog(logic: CreateOtpLogic, onDismiss: () -> Unit) {
val state by logic.state.collectAsState()
Dialog(onDismissRequest = onDismiss) {
CreateOtpItem(state, onNameChanged = logic::nameChanged,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import androidx.compose.ui.unit.dp

@OptIn(ExperimentalMaterialApi::class, ExperimentalFoundationApi::class)
@Composable
fun LazyItemScope.SwipeToDelete(onDelete: () -> Unit, content: @Composable () -> Unit) {
internal fun LazyItemScope.SwipeToDelete(onDelete: () -> Unit, content: @Composable () -> Unit) {
val state = rememberDismissState(confirmStateChange = {
if(it == DismissValue.DismissedToStart) {
onDelete()
Expand All @@ -38,7 +38,7 @@ fun LazyItemScope.SwipeToDelete(onDelete: () -> Unit, content: @Composable () ->

@OptIn(ExperimentalMaterialApi::class)
@Composable
fun SwipeBackground(state: DismissState) {
internal fun SwipeBackground(state: DismissState) {
val direction = state.dismissDirection ?: return
val color by animateColorAsState(
when (state.targetValue) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
package io.github.landrynorris.multifactor.platform

import com.russhwolf.settings.AppleSettings
import com.russhwolf.settings.ExperimentalSettingsApi
import com.russhwolf.settings.coroutines.FlowSettings
import com.russhwolf.settings.NSUserDefaultsSettings
import com.russhwolf.settings.coroutines.SuspendSettings
import com.russhwolf.settings.coroutines.toFlowSettings
import com.squareup.sqldelight.drivers.native.NativeSqliteDriver
import io.github.landrynorris.database.AppDatabase
import io.github.landrynorris.multifactor.repository.SettingsRepository
import kotlinx.coroutines.ExperimentalCoroutinesApi
import org.koin.dsl.module
import platform.Foundation.NSUserDefaults

@OptIn(ExperimentalSettingsApi::class, ExperimentalCoroutinesApi::class)
@OptIn(ExperimentalSettingsApi::class)
actual val platformModule = module {
single {
val driver = NativeSqliteDriver(AppDatabase.Schema, "otpdatabase")
AppDatabase(driver)
}

single {
AppleSettings(NSUserDefaults()).toFlowSettings()
single<SuspendSettings> {
NSUserDefaultsSettings(NSUserDefaults()).toFlowSettings()
}

single {
Expand Down
4 changes: 0 additions & 4 deletions mobileapp/src/nativeInterop/cinterop/secure.def
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,3 @@ package=secure

#import <Foundation/Foundation.h>

@interface Extensions: NSObject {}
+ (CFDataRef) toCFData:(NSData*) data;
@end

0 comments on commit 14d5781

Please sign in to comment.