Skip to content

Commit 5cabd28

Browse files
committed
Add native entropy for iOS
Collect some runtime statistics for iOS.
1 parent f03a3c9 commit 5cabd28

File tree

10 files changed

+125
-54
lines changed

10 files changed

+125
-54
lines changed

PhoenixCrypto/PhoenixCrypto.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
DC35ED842630A381002E441D /* NativeWeakRandom.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC35ED832630A381002E441D /* NativeWeakRandom.swift */; };
1011
DC9B8EC625D6D41400E13818 /* PhoenixCrypto.m in Sources */ = {isa = PBXBuildFile; fileRef = DC9B8EC525D6D41400E13818 /* PhoenixCrypto.m */; };
1112
DC9B8EC725D6D41400E13818 /* PhoenixCrypto.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DC9B8EC425D6D41400E13818 /* PhoenixCrypto.h */; };
1213
DC9B8ED425D6D7A100E13818 /* NativeChaChaPoly.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC9B8ED325D6D7A100E13818 /* NativeChaChaPoly.swift */; };
@@ -26,6 +27,7 @@
2627
/* End PBXCopyFilesBuildPhase section */
2728

2829
/* Begin PBXFileReference section */
30+
DC35ED832630A381002E441D /* NativeWeakRandom.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeWeakRandom.swift; sourceTree = "<group>"; };
2931
DC9B8EC125D6D41400E13818 /* libPhoenixCrypto.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPhoenixCrypto.a; sourceTree = BUILT_PRODUCTS_DIR; };
3032
DC9B8EC425D6D41400E13818 /* PhoenixCrypto.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PhoenixCrypto.h; sourceTree = "<group>"; };
3133
DC9B8EC525D6D41400E13818 /* PhoenixCrypto.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PhoenixCrypto.m; sourceTree = "<group>"; };
@@ -74,6 +76,7 @@
7476
DC9B8EC425D6D41400E13818 /* PhoenixCrypto.h */,
7577
DC9B8EC525D6D41400E13818 /* PhoenixCrypto.m */,
7678
DC9B8ED325D6D7A100E13818 /* NativeChaChaPoly.swift */,
79+
DC35ED832630A381002E441D /* NativeWeakRandom.swift */,
7780
DC9B8ED225D6D7A000E13818 /* PhoenixCrypto-Bridging-Header.h */,
7881
);
7982
path = Classes;
@@ -159,6 +162,7 @@
159162
buildActionMask = 2147483647;
160163
files = (
161164
DC9B8ED425D6D7A100E13818 /* NativeChaChaPoly.swift in Sources */,
165+
DC35ED842630A381002E441D /* NativeWeakRandom.swift in Sources */,
162166
DC9B8EC625D6D41400E13818 /* PhoenixCrypto.m in Sources */,
163167
);
164168
runOnlyForDeploymentPostprocessing = 0;

PhoenixCrypto/PhoenixCrypto/Classes/NativeChaChaPoly.swift

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,16 @@ import Foundation
22
import CryptoKit
33
import os.log
44

5-
//#if DEBUG && true
65
fileprivate var log = Logger(
76
subsystem: Bundle.main.bundleIdentifier!,
87
category: "NativeChaChaPoly"
98
)
10-
//#else
11-
//fileprivate var log = Logger(OSLog.disabled)
12-
//#endif
139

1410
@objc
1511
public class NativeChaChaPoly: NSObject {
1612

1713
@objc
18-
public class func chachapoly_encrypt(
14+
public class func encrypt(
1915
key: Data,
2016
nonce: Data,
2117
authenticatedData: Data,
@@ -50,7 +46,7 @@ public class NativeChaChaPoly: NSObject {
5046
}
5147

5248
@objc
53-
public class func chachapoly_decrypt(
49+
public class func decrypt(
5450
key: Data,
5551
nonce: Data,
5652
authenticatedData: Data,
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import Foundation
2+
import CryptoKit
3+
import os.log
4+
5+
fileprivate var log = Logger(
6+
subsystem: Bundle.main.bundleIdentifier!,
7+
category: "NativeWeakRandom"
8+
)
9+
10+
@objc
11+
public class NativeWeakRandom: NSObject {
12+
13+
@objc
14+
private class func toByteArr(i: UInt64) -> [UInt8] {
15+
let count = MemoryLayout<UInt64>.size
16+
var _i = i
17+
let bytePtr = withUnsafePointer(to: &_i) {
18+
$0.withMemoryRebound(to: UInt8.self, capacity: count) {
19+
UnsafeBufferPointer(start: $0, count: count)
20+
}
21+
}
22+
return [UInt8](bytePtr)
23+
}
24+
25+
@objc
26+
public class func sample() -> Data {
27+
28+
// Sample some entropy from the running process metrics.
29+
let pid = UInt64(getpid())
30+
let usage = rusage_info_current()
31+
var entropy : [UInt8] = toByteArr(i: pid)
32+
entropy += toByteArr(i: usage.ri_user_time)
33+
entropy += toByteArr(i: usage.ri_system_time)
34+
entropy += toByteArr(i: usage.ri_pkg_idle_wkups)
35+
entropy += toByteArr(i: usage.ri_interrupt_wkups)
36+
entropy += toByteArr(i: usage.ri_pageins)
37+
entropy += toByteArr(i: usage.ri_wired_size)
38+
entropy += toByteArr(i: usage.ri_resident_size)
39+
entropy += toByteArr(i: usage.ri_phys_footprint)
40+
entropy += toByteArr(i: usage.ri_proc_start_abstime)
41+
entropy += toByteArr(i: usage.ri_proc_exit_abstime)
42+
entropy += toByteArr(i: usage.ri_child_user_time)
43+
entropy += toByteArr(i: usage.ri_child_system_time)
44+
entropy += toByteArr(i: usage.ri_child_pkg_idle_wkups)
45+
entropy += toByteArr(i: usage.ri_child_interrupt_wkups)
46+
entropy += toByteArr(i: usage.ri_child_pageins)
47+
entropy += toByteArr(i: usage.ri_child_elapsed_abstime)
48+
entropy += toByteArr(i: usage.ri_diskio_bytesread)
49+
entropy += toByteArr(i: usage.ri_diskio_byteswritten)
50+
entropy += toByteArr(i: usage.ri_cpu_time_qos_default)
51+
entropy += toByteArr(i: usage.ri_cpu_time_qos_maintenance)
52+
entropy += toByteArr(i: usage.ri_cpu_time_qos_background)
53+
entropy += toByteArr(i: usage.ri_cpu_time_qos_utility)
54+
entropy += toByteArr(i: usage.ri_cpu_time_qos_legacy)
55+
entropy += toByteArr(i: usage.ri_cpu_time_qos_user_initiated)
56+
entropy += toByteArr(i: usage.ri_cpu_time_qos_user_interactive)
57+
entropy += toByteArr(i: usage.ri_billed_system_time)
58+
entropy += toByteArr(i: usage.ri_serviced_system_time)
59+
entropy += toByteArr(i: usage.ri_logical_writes)
60+
entropy += toByteArr(i: usage.ri_lifetime_max_phys_footprint)
61+
entropy += toByteArr(i: usage.ri_instructions)
62+
entropy += toByteArr(i: usage.ri_cycles)
63+
entropy += toByteArr(i: usage.ri_billed_energy)
64+
entropy += toByteArr(i: usage.ri_serviced_energy)
65+
entropy += toByteArr(i: usage.ri_interval_max_phys_footprint)
66+
entropy += toByteArr(i: usage.ri_runnable_time)
67+
68+
return Data(entropy)
69+
}
70+
}

PhoenixCrypto/PhoenixCrypto/Classes/PhoenixCrypto.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,3 @@
1-
//
2-
// PhoenixCrypto.h
3-
// PhoenixCrypto
4-
//
5-
// Created by Robbie Hanson on 2/12/21.
6-
//
7-
81
#import <Foundation/Foundation.h>
92
#import "PhoenixCrypto-Swift.h"
103

PhoenixCrypto/PhoenixCrypto/Classes/PhoenixCrypto.m

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,3 @@
1-
//
2-
// PhoenixCrypto.m
3-
// PhoenixCrypto
4-
//
5-
// Created by Robbie Hanson on 2/12/21.
6-
//
7-
81
#import "PhoenixCrypto.h"
92

103
@implementation PhoenixCrypto

src/iosMain/kotlin/fr/acinq/lightning/crypto/noise/Chacha20Poly1305CipherFunctions.kt

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,10 @@
11
package fr.acinq.lightning.crypto.noise
22

33
import swift.phoenix_crypto.*
4+
import fr.acinq.lightning.utils.toByteArray
5+
import fr.acinq.lightning.utils.toNSData
46
import fr.acinq.lightning.crypto.ChaCha20Poly1305
5-
import kotlinx.cinterop.addressOf
67
import kotlinx.cinterop.autoreleasepool
7-
import kotlinx.cinterop.pin
8-
import kotlinx.cinterop.usePinned
9-
import platform.Foundation.create
10-
import platform.Foundation.NSData
11-
import platform.posix.memcpy
12-
13-
fun NSData.toByteArray(): ByteArray {
14-
val data = this
15-
return ByteArray(data.length.toInt()).apply {
16-
if (data.length > 0uL) {
17-
usePinned { pinned ->
18-
memcpy(pinned.addressOf(0), data.bytes, data.length)
19-
}
20-
}
21-
}
22-
}
23-
24-
fun ByteArray.toNSData(): NSData {
25-
if (isEmpty()) return NSData()
26-
val pinned = pin()
27-
return NSData.create(
28-
bytesNoCopy = pinned.addressOf(0),
29-
length = size.toULong(),
30-
deallocator = { _, _ -> pinned.unpin() }
31-
)
32-
}
33-
348

359
actual object Chacha20Poly1305CipherFunctions : CipherFunctions {
3610
override fun name() = "ChaChaPoly"
@@ -41,7 +15,7 @@ actual object Chacha20Poly1305CipherFunctions : CipherFunctions {
4115
// Encrypts plaintext using the cipher key k of 32 bytes and an 8-byte unsigned integer nonce n which must be unique.
4216
override fun encrypt(k: ByteArray, n: Long, ad: ByteArray, plaintext: ByteArray): ByteArray {
4317
autoreleasepool {
44-
val ciphertextAndMac = NativeChaChaPoly.chachapoly_encryptWithKey(
18+
val ciphertextAndMac = NativeChaChaPoly.encryptWithKey(
4519
key = k.toNSData(),
4620
nonce = nonce(n).toNSData(),
4721
authenticatedData = ad.toNSData(),
@@ -55,7 +29,7 @@ actual object Chacha20Poly1305CipherFunctions : CipherFunctions {
5529
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
5630
override fun decrypt(k: ByteArray, n: Long, ad: ByteArray, ciphertextAndMac: ByteArray): ByteArray {
5731
autoreleasepool {
58-
val plaintext = NativeChaChaPoly.chachapoly_decryptWithKey(
32+
val plaintext = NativeChaChaPoly.decryptWithKey(
5933
key = k.toNSData(),
6034
nonce = nonce(n).toNSData(),
6135
authenticatedData = ad.toNSData(),
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package fr.acinq.lightning.utils
2+
3+
import kotlinx.cinterop.addressOf
4+
import kotlinx.cinterop.pin
5+
import kotlinx.cinterop.usePinned
6+
import platform.Foundation.create
7+
import platform.Foundation.NSData
8+
import platform.posix.memcpy
9+
10+
fun NSData.toByteArray(): ByteArray {
11+
val data = this
12+
return ByteArray(data.length.toInt()).apply {
13+
if (data.length > 0uL) {
14+
usePinned { pinned ->
15+
memcpy(pinned.addressOf(0), data.bytes, data.length)
16+
}
17+
}
18+
}
19+
}
20+
21+
fun ByteArray.toNSData(): NSData {
22+
if (isEmpty()) return NSData()
23+
val pinned = pin()
24+
return NSData.create(
25+
bytesNoCopy = pinned.addressOf(0),
26+
length = size.toULong(),
27+
deallocator = { _, _ -> pinned.unpin() }
28+
)
29+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package fr.acinq.lightning.utils
2+
3+
import swift.phoenix_crypto.*
4+
import kotlinx.cinterop.autoreleasepool
5+
6+
actual fun runtimeEntropy(): ByteArray {
7+
autoreleasepool {
8+
val result = NativeWeakRandom.sample()
9+
return result.toByteArray()
10+
}
11+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package fr.acinq.lightning.utils
2+
3+
actual fun runtimeEntropy(): ByteArray {
4+
return ByteArray(32)
5+
}

src/nativeMain/kotlin/fr/acinq/lightning/utils/SecureRandomPosix.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,3 @@ object SecureRandomPosix : Random() {
4747
}
4848

4949
actual fun Random.Default.secure(): Random = SecureRandomPosix
50-
51-
actual fun runtimeEntropy(): ByteArray {
52-
return ByteArray(32)
53-
}

0 commit comments

Comments
 (0)