Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 22 additions & 10 deletions library/crypto-rand/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,18 @@ kmpConfiguration {
.resolve("cinterop")

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

target.compilations["test"].cinterops.create("syscall") {
val taskName = target.compilations["main"].cinterops.create("crypto_rand_sys") {
definitionFile.set(cInteropDir.resolve("$name.def"))
}.interopProcessingTaskName to target.konanTarget
includeDirs(cInteropDir)
if (hasSysGetRandom != null) compilerOpts.add(hasSysGetRandom)
}.interopProcessingTaskName

Triple(taskName, target.konanTarget, hasSysGetRandom)
}

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

val kt = KonanTarget.predefinedTargets[target]!!

// Must add dependency on the test cinterop task to ensure
// that Kotlin/Native dependencies get downloaded beforehand
interopTaskInfo.forEach { (interopTaskName, konanTarget) ->
interopTaskInfo.forEach { (interopTaskName, konanTarget, hasSysGetRandom) ->
if (kt != konanTarget) return@forEach

// Must add dependency on the test cinterop task to ensure
// that Kotlin/Native dependencies get downloaded beforehand
this.dependsOn(interopTaskName)

if (hasSysGetRandom != null) {
compilerArgs.add(hasSysGetRandom)

// Linux x86_64 is the only compilation w/o sys/random.h
if (konanTarget != KonanTarget.LINUX_X64) {
compilerArgs.add("-DCRYPTO_RAND_HAS_SYS_RANDOM_H=1")
}
}
}
}
}
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
**/
@file:Suppress("KotlinRedundantDiagnosticSuppress", "NOTHING_TO_INLINE", "SpellCheckingInspection", "UnnecessaryOptInAnnotation")
@file:Suppress("NOTHING_TO_INLINE", "RemoveRedundantCallsOfConversionMethods")

package org.kotlincrypto.random.internal

Expand All @@ -24,20 +24,12 @@ import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract

@Suppress("FunctionName")
internal expect inline fun _SYS_getrandom(): Int

@OptIn(ExperimentalForeignApi::class, UnsafeNumber::class)
private inline fun getrandom2(buf: CPointer<ByteVar>, buflen: size_t, flags: u_int): Int {
return syscall(_SYS_getrandom().convert(), buf, buflen, flags).convert()
}

// getrandom(2) available for Linux Kernel 3.17+ (Android API 26+)
@OptIn(ExperimentalForeignApi::class, UnsafeNumber::class)
internal val HAS_GET_RANDOM: Boolean by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
val buf = ByteArray(1)
val result = buf.usePinned { pinned ->
getrandom2(pinned.addressOf(0), buf.size.convert(), 0x0001u /* GRND_NONBLOCK */)
__getrandom(__buf = pinned.addressOf(0), __len = buf.size.convert(), __is_nonblock = 1).toInt()
}
if (result >= 0) return@lazy true

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

This file was deleted.

27 changes: 22 additions & 5 deletions library/crypto-rand/src/nativeInterop/cinterop/crypto_rand_sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,29 @@

#include "crypto_rand_sys.h"

#ifdef __ANDROID__
#if CRYPTO_RAND_HAS_SYS_GETRANDOM
#include <sys/syscall.h>
#include <unistd.h>

int
__SYS_getrandom()
#ifndef CRYPTO_RAND_HAS_SYS_RANDOM_H
#define CRYPTO_RAND_HAS_SYS_RANDOM_H 0
#endif // CRYPTO_RAND_HAS_SYS_RANDOM_H

#if CRYPTO_RAND_HAS_SYS_RANDOM_H
#include <sys/random.h>
#endif // CRYPTO_RAND_HAS_SYS_RANDOM_H

#ifndef GRND_NONBLOCK
#define GRND_NONBLOCK 0x01
#endif // GRND_NONBLOCK

ssize_t
__getrandom(void *__buf, size_t __len, int __is_nonblock)
{
return SYS_getrandom;
unsigned int flags = 0;
if (__is_nonblock) {
flags = GRND_NONBLOCK;
}
return syscall(SYS_getrandom, __buf, __len, flags);
}
#endif /* !defined(__ANDROID__) */
#endif // CRYPTO_RAND_HAS_SYS_GETRANDOM
20 changes: 15 additions & 5 deletions library/crypto-rand/src/nativeInterop/cinterop/crypto_rand_sys.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,22 @@
* limitations under the License.
**/

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

#ifdef __ANDROID__
int __SYS_getrandom();
#endif /* !defined(__ANDROID__) */
#ifndef CRYPTO_RAND_HAS_SYS_GETRANDOM
#define CRYPTO_RAND_HAS_SYS_GETRANDOM 0
#endif // CRYPTO_RAND_HAS_SYS_GETRANDOM

#endif /* !defined(CRYPTO_RAND_SYS_H) */
#if CRYPTO_RAND_HAS_SYS_GETRANDOM
#include <sys/types.h>

/**
* Performs syscall using SYS_getrandom and provided arguments.
*
* If __is_nonblock > 0, will use flag GRND_NONBLOCK, otherwise will use 0.
* */
ssize_t __getrandom(void *__buf, size_t __len, int __is_nonblock);
#endif // CRYPTO_RAND_HAS_SYS_GETRANDOM

#endif // CRYPTO_RAND_SYS_H
6 changes: 0 additions & 6 deletions library/crypto-rand/src/nativeInterop/cinterop/syscall.def

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import androidx.test.core.app.ApplicationProvider
import io.matthewnelson.kmp.file.toFile
import io.matthewnelson.kmp.process.Process
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.fail

class AndroidNativeTest {

Expand All @@ -35,8 +35,11 @@ class AndroidNativeTest {
maxBuffer = Int.MAX_VALUE / 2
}

assertEquals(0, out.processInfo.exitCode, out.stdout)
println(out.stdout)
println(out.stderr)
if (out.processInfo.exitCode == 0) return

val sb = StringBuilder(out.toString()).appendLine()
sb.appendLine(out.stdout).appendLine()
sb.appendLine(out.stderr).appendLine()
fail(sb.toString())
}
}