Skip to content

Commit 85f5fdf

Browse files
authored
Migrate syscall for SYS_getrandom to C code (#45)
1 parent a06ce61 commit 85f5fdf

9 files changed

Lines changed: 69 additions & 121 deletions

File tree

library/crypto-rand/build.gradle.kts

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,18 @@ kmpConfiguration {
7171
.resolve("cinterop")
7272

7373
val interopTaskInfo = targets.filterIsInstance<KotlinNativeTarget>().map { target ->
74-
if (target.konanTarget.family == Family.ANDROID) {
75-
target.compilations["main"].cinterops.create("crypto_rand_sys") {
76-
definitionFile.set(cInteropDir.resolve("$name.def"))
77-
includeDirs(cInteropDir)
78-
}
74+
val hasSysGetRandom = when (target.konanTarget.family) {
75+
Family.ANDROID, Family.LINUX -> "-DCRYPTO_RAND_HAS_SYS_GETRANDOM=1"
76+
else -> null
7977
}
8078

81-
target.compilations["test"].cinterops.create("syscall") {
79+
val taskName = target.compilations["main"].cinterops.create("crypto_rand_sys") {
8280
definitionFile.set(cInteropDir.resolve("$name.def"))
83-
}.interopProcessingTaskName to target.konanTarget
81+
includeDirs(cInteropDir)
82+
if (hasSysGetRandom != null) compilerOpts.add(hasSysGetRandom)
83+
}.interopProcessingTaskName
84+
85+
Triple(taskName, target.konanTarget, hasSysGetRandom)
8486
}
8587

8688
project.extensions.configure<CompileToBitcodeExtension>("cklib") {
@@ -97,11 +99,21 @@ kmpConfiguration {
9799

98100
val kt = KonanTarget.predefinedTargets[target]!!
99101

100-
// Must add dependency on the test cinterop task to ensure
101-
// that Kotlin/Native dependencies get downloaded beforehand
102-
interopTaskInfo.forEach { (interopTaskName, konanTarget) ->
102+
interopTaskInfo.forEach { (interopTaskName, konanTarget, hasSysGetRandom) ->
103103
if (kt != konanTarget) return@forEach
104+
105+
// Must add dependency on the test cinterop task to ensure
106+
// that Kotlin/Native dependencies get downloaded beforehand
104107
this.dependsOn(interopTaskName)
108+
109+
if (hasSysGetRandom != null) {
110+
compilerArgs.add(hasSysGetRandom)
111+
112+
// Linux x86_64 is the only compilation w/o sys/random.h
113+
if (konanTarget != KonanTarget.LINUX_X64) {
114+
compilerArgs.add("-DCRYPTO_RAND_HAS_SYS_RANDOM_H=1")
115+
}
116+
}
105117
}
106118
}
107119
}

library/crypto-rand/src/androidNativeMain/kotlin/org/kotlincrypto/random/internal/AndroidNativePlatform.kt

Lines changed: 0 additions & 24 deletions
This file was deleted.

library/crypto-rand/src/androidNativeTest/kotlin/org/kotlincrypto/random/internal/CryptoRandAndroidNativeUnitTest.kt

Lines changed: 0 additions & 34 deletions
This file was deleted.

library/crypto-rand/src/linuxAndroidMain/kotlin/org/kotlincrypto/random/internal/LinuxAndroidPlatform.kt

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
**/
16-
@file:Suppress("KotlinRedundantDiagnosticSuppress", "NOTHING_TO_INLINE", "SpellCheckingInspection", "UnnecessaryOptInAnnotation")
16+
@file:Suppress("NOTHING_TO_INLINE", "RemoveRedundantCallsOfConversionMethods")
1717

1818
package org.kotlincrypto.random.internal
1919

@@ -24,20 +24,12 @@ import kotlin.contracts.ExperimentalContracts
2424
import kotlin.contracts.InvocationKind
2525
import kotlin.contracts.contract
2626

27-
@Suppress("FunctionName")
28-
internal expect inline fun _SYS_getrandom(): Int
29-
30-
@OptIn(ExperimentalForeignApi::class, UnsafeNumber::class)
31-
private inline fun getrandom2(buf: CPointer<ByteVar>, buflen: size_t, flags: u_int): Int {
32-
return syscall(_SYS_getrandom().convert(), buf, buflen, flags).convert()
33-
}
34-
3527
// getrandom(2) available for Linux Kernel 3.17+ (Android API 26+)
3628
@OptIn(ExperimentalForeignApi::class, UnsafeNumber::class)
3729
internal val HAS_GET_RANDOM: Boolean by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
3830
val buf = ByteArray(1)
3931
val result = buf.usePinned { pinned ->
40-
getrandom2(pinned.addressOf(0), buf.size.convert(), 0x0001u /* GRND_NONBLOCK */)
32+
__getrandom(__buf = pinned.addressOf(0), __len = buf.size.convert(), __is_nonblock = 1).toInt()
4133
}
4234
if (result >= 0) return@lazy true
4335

@@ -54,7 +46,7 @@ internal val HAS_GET_RANDOM: Boolean by lazy(LazyThreadSafetyMode.SYNCHRONIZED)
5446
@OptIn(ExperimentalForeignApi::class, UnsafeNumber::class)
5547
internal actual fun ByteArray.cryptoRandFill() {
5648
if (HAS_GET_RANDOM) {
57-
cryptoRandFill { ptr, len -> getrandom2(ptr, len.toULong().convert(), 0u) }
49+
cryptoRandFill { ptr, len -> __getrandom(__buf = ptr, __len = len.convert(), __is_nonblock = 0).toInt() }
5850
} else {
5951
cryptoRandFillURandom()
6052
}

library/crypto-rand/src/linuxMain/kotlin/org/kotlincrypto/random/internal/LinuxPlatform.kt

Lines changed: 0 additions & 22 deletions
This file was deleted.

library/crypto-rand/src/nativeInterop/cinterop/crypto_rand_sys.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,29 @@
1616

1717
#include "crypto_rand_sys.h"
1818

19-
#ifdef __ANDROID__
19+
#if CRYPTO_RAND_HAS_SYS_GETRANDOM
2020
#include <sys/syscall.h>
21+
#include <unistd.h>
2122

22-
int
23-
__SYS_getrandom()
23+
#ifndef CRYPTO_RAND_HAS_SYS_RANDOM_H
24+
#define CRYPTO_RAND_HAS_SYS_RANDOM_H 0
25+
#endif // CRYPTO_RAND_HAS_SYS_RANDOM_H
26+
27+
#if CRYPTO_RAND_HAS_SYS_RANDOM_H
28+
#include <sys/random.h>
29+
#endif // CRYPTO_RAND_HAS_SYS_RANDOM_H
30+
31+
#ifndef GRND_NONBLOCK
32+
#define GRND_NONBLOCK 0x01
33+
#endif // GRND_NONBLOCK
34+
35+
ssize_t
36+
__getrandom(void *__buf, size_t __len, int __is_nonblock)
2437
{
25-
return SYS_getrandom;
38+
unsigned int flags = 0;
39+
if (__is_nonblock) {
40+
flags = GRND_NONBLOCK;
41+
}
42+
return syscall(SYS_getrandom, __buf, __len, flags);
2643
}
27-
#endif /* !defined(__ANDROID__) */
44+
#endif // CRYPTO_RAND_HAS_SYS_GETRANDOM

library/crypto-rand/src/nativeInterop/cinterop/crypto_rand_sys.h

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,22 @@
1414
* limitations under the License.
1515
**/
1616

17-
/* https://youtrack.jetbrains.com/issue/KT-75722 */
1817
#ifndef CRYPTO_RAND_SYS_H
1918
#define CRYPTO_RAND_SYS_H
2019

21-
#ifdef __ANDROID__
22-
int __SYS_getrandom();
23-
#endif /* !defined(__ANDROID__) */
20+
#ifndef CRYPTO_RAND_HAS_SYS_GETRANDOM
21+
#define CRYPTO_RAND_HAS_SYS_GETRANDOM 0
22+
#endif // CRYPTO_RAND_HAS_SYS_GETRANDOM
2423

25-
#endif /* !defined(CRYPTO_RAND_SYS_H) */
24+
#if CRYPTO_RAND_HAS_SYS_GETRANDOM
25+
#include <sys/types.h>
26+
27+
/**
28+
* Performs syscall using SYS_getrandom and provided arguments.
29+
*
30+
* If __is_nonblock > 0, will use flag GRND_NONBLOCK, otherwise will use 0.
31+
* */
32+
ssize_t __getrandom(void *__buf, size_t __len, int __is_nonblock);
33+
#endif // CRYPTO_RAND_HAS_SYS_GETRANDOM
34+
35+
#endif // CRYPTO_RAND_SYS_H

library/crypto-rand/src/nativeInterop/cinterop/syscall.def

Lines changed: 0 additions & 6 deletions
This file was deleted.

test-android/src/androidInstrumentedTest/kotlin/org/kotlincrypto/random/test/android/AndroidNativeTest.kt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import androidx.test.core.app.ApplicationProvider
2020
import io.matthewnelson.kmp.file.toFile
2121
import io.matthewnelson.kmp.process.Process
2222
import kotlin.test.Test
23-
import kotlin.test.assertEquals
23+
import kotlin.test.fail
2424

2525
class AndroidNativeTest {
2626

@@ -35,8 +35,11 @@ class AndroidNativeTest {
3535
maxBuffer = Int.MAX_VALUE / 2
3636
}
3737

38-
assertEquals(0, out.processInfo.exitCode, out.stdout)
39-
println(out.stdout)
40-
println(out.stderr)
38+
if (out.processInfo.exitCode == 0) return
39+
40+
val sb = StringBuilder(out.toString()).appendLine()
41+
sb.appendLine(out.stdout).appendLine()
42+
sb.appendLine(out.stderr).appendLine()
43+
fail(sb.toString())
4144
}
4245
}

0 commit comments

Comments
 (0)