Hi,
I found the following documentation addressing how to use POSIX semaphores for multiple apps in an app group.
https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW24
It's not that clear that this is macOS only and I saw some blog posts where people got Mach ports running on iOS, so I speculated POSIX semaphores may also work and I tried it like this.
func doExternalHardwareInit() {
var sema = sem_open("our.app.group/A", O_CREAT, 0o660, 1)
guard sema != SEM_FAILED else {
perror("sem_open")
exit(EXIT_FAILURE)
}
defer { sem_close(sema) }
print("Waiting for semaphore")
sem_wait(sema) // stuck here
print("Got semaphore")
// run code that must not run multiple times
sem_post(sema)
}
It seems that this is not working. It is stuck sem_wait(sema) even when only one of the app groups is executing this.
Is this intended not work on iOS?
Background:
We have a few apps in an app group that need to access a external hardware connected via ethernet to an iOS device.
There are certain initialisation tasks involving this hardware where we need to make sure that only one of the apps is talking to that hardware. We do that for example automatically when the app starts.
With iOS 15 came the pre heat start of apps and we recognised that our apps may run in parallel and are starting those initialisations at the same time.
But we also would like make sure that certain interactions with the hardware are finished carefully when the apps are switched.
Best
Alex
Post
Replies
Boosts
Views
Activity
Hi,I'm playing around with the new CryptoKit framework on iOS. I'm trying to generate eliptic curve keys, sign some data with them, export the signature and the public key and verify the signature externaly (in this case with openssl).I'm not getting this to work with the format that ECDSASignature.derRepresentation provides. However, I can make it work when using SecKeyRawSign from the old Security framework.Here is the code for both singings using the same key. It creates a shell script that demonstrate the signature verification with on baord openssl.import Foundation
import CryptoKit
struct SignDemo {
private let secp384r1header: [UInt8] = [0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00]
func run() {
var shell: [String] = []
shell.append("\n\n#! /bin/sh")
// The data to sign
let dataToSign = "The data to sign!".data(using: .utf8)!
shell.append("echo \(dataToSign.map { String(format: "%02hhx", $0) }.joined()) | xxd -r -p > dataToSign.dat")
// Keys
let privKey = P384.Signing.PrivateKey()
let pubKey = privKey.publicKey
var pubKeyDER = Data(secp384r1header)
pubKeyDER.append(pubKey.x963Representation)
shell.append("echo \(pubKeyDER.map { String(format: "%02hhx", $0) }.joined()) | xxd -r -p > key.der")
shell.append("cat > key.pem <<eof\n-----begin public="" key-----\n\(pubkeyder.base64encodedstring().separate())\n-----end="" key-----\neof")<br="">
// Sign with Sec
let secSignature = try! secSing(digest: dataToSign, privKeyData: privKey.x963Representation)
shell.append("echo \(secSignature.map { String(format: "%02hhx", $0) }.joined()) | xxd -r -p > sig-sec.dat")
shell.append("/usr/local/opt/openssl/bin/openssl dgst -SHA256 -verify key.pem -signature sig-sec.dat dataToSign.dat")
// Sign with CryptoKit
let ckSignature = try! cryptoKitSing(digest: dataToSign, privKey: privKey)
shell.append("echo \(ckSignature.map { String(format: "%02hhx", $0) }.joined()) | xxd -r -p > sig-ck.dat")
shell.append("/usr/local/opt/openssl/bin/openssl dgst -SHA256 -verify key.pem -signature sig-ck.dat dataToSign.dat")
print(shell.joined(separator: "\n"))
}
private func cryptoKitSing(digest: Data, privKey: P384.Signing.PrivateKey) throws -> Data {
return try privKey.signature(for: digest).derRepresentation
}
private func secSing(digest: Data, privKeyData: Data) throws -> Data {
let attributes: [String:Any] =
[
kSecAttrKeyClass as String: kSecAttrKeyClassPrivate,
kSecAttrKeyType as String: kSecAttrKeyTypeEC,
kSecAttrKeySizeInBits as String: 384,
]
guard let secKey = SecKeyCreateWithData(privKeyData as CFData, attributes as CFDictionary, nil) else {
throw MyError(msg: "Error: Problem in SecKeyCreateWithData()")
}
// TODO: I guess that can be done easier
let digestToSign = SHA256.hash(data: digest).makeIterator()
var digestToSignBytes = [UInt8]()
digestToSign.forEach { byte in
digestToSignBytes.append(byte)
}
var signatureLength = 103
var signatureBytes = [UInt8](repeating: 0, count: signatureLength)
let signErr = SecKeyRawSign(secKey, .PKCS1SHA256, &digestToSignBytes, digestToSignBytes.count, &signatureBytes, &signatureLength)
guard signErr == errSecSuccess else {
throw MyError(msg: "Could not create signature. OSStatus: \(signErr)")
}
return Data(signatureBytes)
}
}
struct MyError: Error {
let msg: String
}
extension String {
func separate(every stride: Int = 64, with separator: Character = "\n") -> String {
return String(enumerated().map { $0 > 0 && $0 % stride == 0 ? [separator, $1] : [$1]}.joined())
}Wenn running that code in an iOS App and then use the script to verify, the following happens:bash-3.2$
bash-3.2$ echo 546865206461746120746f207369676e21 | xxd -r -p > dataToSign.dat
bash-3.2$ echo 3076301006072a8648ce3d020106052b8104002203620004d2d3225b5c46dea5e39a0592e20ae25b8ba823374a110fde409ad6c71bcc334d7b0b5916d7fb0256b7c5716f0a9f339b35c0b96813101e24b8d5849bde61d710b62b71fc3e0e7e59dbdc6ed77820aecd5857ae1545c0d7eaefb43d02641e9b4a | xxd -r -p > key.der
cat > key.pem <<eof
-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE0tMiW1xG3qXjmgWS4griW4uoIzdKEQ/e
QJrWxxvMM017C1kW1/sCVrfFcW8KnzObNcC5aBMQHiS41YSb3mHXELYrcfw+Dn5Z
29xu13ggrs1YV64VRcDX6u+0PQJkHptK
-----END PUBLIC KEY-----
EOF
echo 3065023100e4ad6c0d5fbd68fe0ee6754e4d8651af07e49d72edcd1dffdf2fc3c79d7690ce91196ffe6d5aa67b85560c1283a0db3502307c8769b38f75e7f90ef64432c2746021bf3198507edbc95eefbf43dde7b83d95efd2e06549efc73742439d0aab057a86 | xxd -r -p > sig-sec.dat
/usr/local/opt/openssl/bin/openssl dgst -SHA256 -verify key.pem -signature sig-sec.dat dataToSign.dat
echo 30640230702fd094ca99e0736fa0f7cd005a9d68105d2c3be7de4ecf3e8f47531b6692629449e13abc8162f4bdcf0e6a340f59de023001d45750caf603615eed2404b05007ef44dcc10460a66bc346e62299808bd430a93e96b70e68c73bcd6b320dd026e9c9 | xxd -r -p > sig-ck.dat
/usr/local/opt/openssl/bin/openssl dgst -SHA256 -verify key.pem -signature sig-ck.dat dataToSign.datbash-3.2$ cat > key.pem <<eof
> -----BEGIN PUBLIC KEY-----
> MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE0tMiW1xG3qXjmgWS4griW4uoIzdKEQ/e
> QJrWxxvMM017C1kW1/sCVrfFcW8KnzObNcC5aBMQHiS41YSb3mHXELYrcfw+Dn5Z
> 29xu13ggrs1YV64VRcDX6u+0PQJkHptK
> -----END PUBLIC KEY-----
> EOF
bash-3.2$ echo 3065023100e4ad6c0d5fbd68fe0ee6754e4d8651af07e49d72edcd1dffdf2fc3c79d7690ce91196ffe6d5aa67b85560c1283a0db3502307c8769b38f75e7f90ef64432c2746021bf3198507edbc95eefbf43dde7b83d95efd2e06549efc73742439d0aab057a86 | xxd -r -p > sig-sec.dat
bash-3.2$ /usr/local/opt/openssl/bin/openssl dgst -SHA256 -verify key.pem -signature sig-sec.dat dataToSign.dat
Verified OK
bash-3.2$ echo 30640230702fd094ca99e0736fa0f7cd005a9d68105d2c3be7de4ecf3e8f47531b6692629449e13abc8162f4bdcf0e6a340f59de023001d45750caf603615eed2404b05007ef44dcc10460a66bc346e62299808bd430a93e96b70e68c73bcd6b320dd026e9c9 | xxd -r -p > sig-ck.dat
bash-3.2$ /usr/local/opt/openssl/bin/openssl dgst -SHA256 -verify key.pem -signature sig-ck.dat dataToSign.dat
Verification FailureYou can see in line 22 and 23 that verification works with the signature of the Secutity framework and this also shows that the exported key works. At line 25 and 26 you can see the verification of the CryptoKit signature, which failes.Did anyone got verification of a crypto kit signature to work with external tools (like openssl)?Thanks!BestAlex