Slow progress.

This commit is contained in:
Ugljesa Jovanovic 2020-08-21 18:55:17 +02:00 committed by Ugljesa Jovanovic
parent cd90f964ab
commit be4468785d
No known key found for this signature in database
GPG Key ID: 178E6DFCECCB0E0F
9 changed files with 122 additions and 54 deletions

View File

@ -28,6 +28,27 @@ fun ClassDefinition.defineSecretStreamFunctions() {
) )
) )
+dataClassDef(
"DecryptedDataAndTag",
"""
This data class wraps the decrypted data and tag returned when decrypting
""".trimIndent(),
listOf(
ParameterDefinition(
parameterName = "decrypted",
parameterType = TypeDefinition.ARRAY_OF_UBYTES
),
ParameterDefinition(
parameterName = "tag",
parameterType = TypeDefinition.UBYTE
)
)
)
val jsSecretStreamInit = CodeBlockDefinition( val jsSecretStreamInit = CodeBlockDefinition(
""" """
val stateAndHeader = getSodium().crypto_secretstream_xchacha20poly1305_init_push(key.toUInt8Array()) val stateAndHeader = getSodium().crypto_secretstream_xchacha20poly1305_init_push(key.toUInt8Array())
@ -148,7 +169,7 @@ fun ClassDefinition.defineSecretStreamFunctions() {
codeDocumentation = """ codeDocumentation = """
Decrypt next block of data using the previously initialized state. Returns decrypted block. Decrypt next block of data using the previously initialized state. Returns decrypted block.
""".trimIndent(), """.trimIndent(),
returnType = TypeDefinition.ARRAY_OF_UBYTES returnType = CustomTypeDefinition(withPackageName("DecryptedDataAndTag"))
) { ) {
+ParameterDefinition( +ParameterDefinition(
"state", "state",
@ -167,7 +188,9 @@ fun ClassDefinition.defineSecretStreamFunctions() {
) )
+ParameterDefinition( +ParameterDefinition(
"tag_p", "tag_p",
TypeDefinition.NULL TypeDefinition.UBYTE,
dropParameterFromDefinition = true,
isActuallyAnOutputParam = true
) )
+ParameterDefinition( +ParameterDefinition(
"c", "c",

View File

@ -53,7 +53,7 @@ object CommonLibsodiumGenerator {
fun createCommonMethodSpec(methodDefinition: FunctionDefinition): FunSpec.Builder { fun createCommonMethodSpec(methodDefinition: FunctionDefinition): FunSpec.Builder {
val methodBuilder = FunSpec.builder(methodDefinition.name) val methodBuilder = FunSpec.builder(methodDefinition.name)
var actualReturnType : TypeName = Any::class.asTypeName() val actualReturnTypes = mutableListOf<TypeName>()
var actualReturnTypeFound : Boolean = false var actualReturnTypeFound : Boolean = false
for (paramDefinition in methodDefinition.parameterList) { for (paramDefinition in methodDefinition.parameterList) {
if ((paramDefinition.isStateType.not() || methodDefinition.isStateCreationFunction.not()) && paramDefinition.dropParameterFromDefinition.not()) { if ((paramDefinition.isStateType.not() || methodDefinition.isStateCreationFunction.not()) && paramDefinition.dropParameterFromDefinition.not()) {
@ -65,11 +65,11 @@ object CommonLibsodiumGenerator {
} }
if (paramDefinition.isActuallyAnOutputParam) { if (paramDefinition.isActuallyAnOutputParam) {
actualReturnTypeFound = true actualReturnTypeFound = true
actualReturnType = paramDefinition.parameterType.typeName actualReturnTypes += paramDefinition.parameterType.typeName
} }
} }
if (actualReturnTypeFound) { if (actualReturnTypeFound && actualReturnTypes.size == 1) {
methodBuilder.returns(actualReturnType) methodBuilder.returns(actualReturnTypes[0])
} else { } else {
methodBuilder.returns(methodDefinition.returnType.typeName) methodBuilder.returns(methodDefinition.returnType.typeName)
} }

View File

@ -8,6 +8,7 @@ import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.ParameterSpec import com.squareup.kotlinpoet.ParameterSpec
import com.squareup.kotlinpoet.PropertySpec import com.squareup.kotlinpoet.PropertySpec
import com.squareup.kotlinpoet.TypeAliasSpec import com.squareup.kotlinpoet.TypeAliasSpec
import com.squareup.kotlinpoet.TypeName
/** /**
* Created by Ugljesa Jovanovic * Created by Ugljesa Jovanovic
@ -56,7 +57,7 @@ object JvmLibsodiumGenerator {
methodBuilder.modifiers += MultiplatformModifier.ACTUAL.modifierList methodBuilder.modifiers += MultiplatformModifier.ACTUAL.modifierList
var returnModifierFound = false var returnModifierFound = false
var returnModifierValue = "" var returnModifierValue = ""
lateinit var actualReturnParameterDefinition: ParameterDefinition val actualReturnTypes = mutableListOf<ParameterDefinition>()
var actualReturnTypeFound: Boolean = false var actualReturnTypeFound: Boolean = false
for (paramDefinition in methodDefinition.parameterList) { for (paramDefinition in methodDefinition.parameterList) {
if (paramDefinition.isStateType && methodDefinition.isStateCreationFunction) { if (paramDefinition.isStateType && methodDefinition.isStateCreationFunction) {
@ -89,14 +90,14 @@ object JvmLibsodiumGenerator {
} }
} }
if (paramDefinition.isActuallyAnOutputParam) { if (paramDefinition.isActuallyAnOutputParam) {
actualReturnParameterDefinition = paramDefinition actualReturnTypes += paramDefinition
actualReturnTypeFound = true actualReturnTypeFound = true
} }
} }
if (actualReturnTypeFound) { if (actualReturnTypeFound) {
if (returnModifierFound) { if (returnModifierFound) {
createOutputParam( createOutputParam(
actualReturnParameterDefinition, actualReturnTypes,
returnModifierValue, returnModifierValue,
methodBuilder methodBuilder
) )
@ -105,7 +106,7 @@ object JvmLibsodiumGenerator {
throw RuntimeException("Function definition lacks a way to define output array length, function ${methodDefinition.name}") throw RuntimeException("Function definition lacks a way to define output array length, function ${methodDefinition.name}")
} }
createOutputParam( createOutputParam(
actualReturnParameterDefinition, actualReturnTypes,
methodDefinition.outputLengthWhenArray.toString(), methodDefinition.outputLengthWhenArray.toString(),
methodBuilder methodBuilder
) )
@ -125,10 +126,18 @@ object JvmLibsodiumGenerator {
methodBuilder.addStatement(constructJvmCall.toString()) methodBuilder.addStatement(constructJvmCall.toString())
methodBuilder.addStatement("return state") methodBuilder.addStatement("return state")
} else if (actualReturnTypeFound) { } else if (actualReturnTypeFound) {
constructJvmCall.append("sodium.${methodDefinition.nativeName}") if (actualReturnTypes.size == 1) {
constructJvmCall.append(paramsToString(methodDefinition)) constructJvmCall.append("sodium.${methodDefinition.nativeName}")
methodBuilder.addStatement(constructJvmCall.toString()) constructJvmCall.append(paramsToString(methodDefinition))
methodBuilder.addStatement("return ${actualReturnParameterDefinition.parameterName}") methodBuilder.addStatement(constructJvmCall.toString())
methodBuilder.addStatement("return ${actualReturnTypes[0].parameterName}")
} else {
constructJvmCall.append("sodium.${methodDefinition.nativeName}")
constructJvmCall.append(paramsToString(methodDefinition))
methodBuilder.addStatement(constructJvmCall.toString())
methodBuilder.addStatement(
"return ${methodDefinition.returnType.typeName}(${createTupleOutputParams(actualReturnTypes)})")
}
} else { } else {
when (methodDefinition.returnType) { when (methodDefinition.returnType) {
TypeDefinition.ARRAY_OF_UBYTES -> { TypeDefinition.ARRAY_OF_UBYTES -> {
@ -161,24 +170,31 @@ object JvmLibsodiumGenerator {
return methodBuilder return methodBuilder
} }
fun createOutputParam(outputParam: ParameterDefinition, length: String?, methodBuilder: FunSpec.Builder) { fun createOutputParam(outputParams: List<ParameterDefinition>, length: String?, methodBuilder: FunSpec.Builder) {
/* /*
val hashed = ByteArray(Sha256Properties.MAX_HASH_BYTES) val hashed = ByteArray(Sha256Properties.MAX_HASH_BYTES)
sodium.crypto_hash_sha256_final(state, hashed) sodium.crypto_hash_sha256_final(state, hashed)
return hashed.asUByteArray() return hashed.asUByteArray()
*/ */
when (outputParam.parameterType) { for (outputParam in outputParams) {
TypeDefinition.ARRAY_OF_UBYTES, TypeDefinition.ARRAY_OF_UBYTES_NO_SIZE, TypeDefinition.ARRAY_OF_UBYTES_LONG_SIZE -> { when (outputParam.parameterType) {
methodBuilder.addStatement("val ${outputParam.parameterName} = UByteArray($length)") TypeDefinition.ARRAY_OF_UBYTES, TypeDefinition.ARRAY_OF_UBYTES_NO_SIZE, TypeDefinition.ARRAY_OF_UBYTES_LONG_SIZE -> {
methodBuilder.addStatement("val ${outputParam.parameterName} = UByteArray($length)")
}
TypeDefinition.UBYTE -> {
methodBuilder.addStatement("var ${outputParam.parameterName} : UByte = 0U")
}
else -> {
throw RuntimeException("Unhandled native output param type: ${outputParam.parameterType.typeName}")
}
} }
else -> {
throw RuntimeException("Unhandled native output param type: ${outputParam.parameterType.typeName}")
}
} }
} }
fun createTupleOutputParams(outputParams: List<ParameterDefinition>) : String {
return outputParams.map { it.parameterName }.joinToString (separator = ", ")
}
fun createStateParam(stateParameterDefinition: ParameterDefinition, methodBuilder: FunSpec.Builder) { fun createStateParam(stateParameterDefinition: ParameterDefinition, methodBuilder: FunSpec.Builder) {
/* /*
val state = Hash.State256() val state = Hash.State256()

View File

@ -71,7 +71,7 @@ object NativeLibsodiumGenerator {
methodBuilder.modifiers += MultiplatformModifier.ACTUAL.modifierList methodBuilder.modifiers += MultiplatformModifier.ACTUAL.modifierList
var returnModifierFound = false var returnModifierFound = false
var returnModifierValue = "" var returnModifierValue = ""
lateinit var actualReturnParameterDefinition: ParameterDefinition val actualReturnTypes = mutableListOf<ParameterDefinition>()
var actualReturnTypeFound: Boolean = false var actualReturnTypeFound: Boolean = false
for (paramDefinition in methodDefinition.parameterList) { for (paramDefinition in methodDefinition.parameterList) {
if (paramDefinition.isStateType && methodDefinition.isStateCreationFunction) { if (paramDefinition.isStateType && methodDefinition.isStateCreationFunction) {
@ -104,18 +104,18 @@ object NativeLibsodiumGenerator {
} }
if (paramDefinition.isActuallyAnOutputParam) { if (paramDefinition.isActuallyAnOutputParam) {
actualReturnParameterDefinition = paramDefinition actualReturnTypes += paramDefinition
actualReturnTypeFound = true actualReturnTypeFound = true
} }
} }
if (actualReturnTypeFound) { if (actualReturnTypeFound) {
if (returnModifierFound) { if (returnModifierFound) {
createOutputParam(actualReturnParameterDefinition, returnModifierValue, methodBuilder) createOutputParam(actualReturnTypes, returnModifierValue, methodBuilder)
} else { } else {
if (methodDefinition.outputLengthWhenArray == -1) { if (methodDefinition.outputLengthWhenArray == -1) {
throw RuntimeException("Function definition lacks a way to define output array length, function ${methodDefinition.name}") throw RuntimeException("Function definition lacks a way to define output array length, function ${methodDefinition.name}")
} }
createOutputParam(actualReturnParameterDefinition, methodDefinition.outputLengthWhenArray.toString(), methodBuilder) createOutputParam(actualReturnTypes, methodDefinition.outputLengthWhenArray.toString(), methodBuilder)
} }
} }
methodBuilder.addStatement("println(\"Debug ${methodDefinition.name}\")") methodBuilder.addStatement("println(\"Debug ${methodDefinition.name}\")")
@ -134,11 +134,24 @@ object NativeLibsodiumGenerator {
unpinParams(methodDefinition, methodBuilder) unpinParams(methodDefinition, methodBuilder)
methodBuilder.addStatement("return state") methodBuilder.addStatement("return state")
} else if (actualReturnTypeFound) { } else if (actualReturnTypeFound) {
constructNativeCall.append("libsodium.${methodDefinition.nativeName}") if (actualReturnTypes.size == 1) {
constructNativeCall.append(paramsToString(methodDefinition)) constructNativeCall.append("libsodium.${methodDefinition.nativeName}")
methodBuilder.addStatement(constructNativeCall.toString()) constructNativeCall.append(paramsToString(methodDefinition))
unpinParams(methodDefinition, methodBuilder) methodBuilder.addStatement(constructNativeCall.toString())
methodBuilder.addStatement("return ${actualReturnParameterDefinition.parameterName}") unpinParams(methodDefinition, methodBuilder)
methodBuilder.addStatement("return ${actualReturnTypes[0].parameterName}")
} else {
constructNativeCall.append("libsodium.${methodDefinition.nativeName}")
constructNativeCall.append(paramsToString(methodDefinition))
methodBuilder.addStatement(constructNativeCall.toString())
unpinParams(methodDefinition, methodBuilder)
methodBuilder.addStatement(
"return ${methodDefinition.returnType.typeName}(${
JvmLibsodiumGenerator.createTupleOutputParams(
actualReturnTypes
)
})")
}
} else { } else {
when (methodDefinition.returnType) { when (methodDefinition.returnType) {
TypeDefinition.ARRAY_OF_UBYTES -> { TypeDefinition.ARRAY_OF_UBYTES -> {
@ -188,7 +201,7 @@ object NativeLibsodiumGenerator {
methodBuilder.addStatement("val state = allocated.reinterpret<${stateParameterDefinition.parameterType.typeName}>().pointed") methodBuilder.addStatement("val state = allocated.reinterpret<${stateParameterDefinition.parameterType.typeName}>().pointed")
} }
fun createOutputParam(outputParam: ParameterDefinition, length: String?, methodBuilder: FunSpec.Builder) { fun createOutputParam(outputParams: List<ParameterDefinition>, length: String?, methodBuilder: FunSpec.Builder) {
/* /*
val hashResult = UByteArray(Sha256Properties.MAX_HASH_BYTES) val hashResult = UByteArray(Sha256Properties.MAX_HASH_BYTES)
val hashResultPinned = hashResult.pin() val hashResultPinned = hashResult.pin()
@ -196,18 +209,25 @@ object NativeLibsodiumGenerator {
sodium_free(state.ptr) sodium_free(state.ptr)
return hashResult return hashResult
*/ */
when (outputParam.parameterType) { for (outputParam in outputParams) {
TypeDefinition.ARRAY_OF_UBYTES, TypeDefinition.ARRAY_OF_UBYTES_NO_SIZE, TypeDefinition.ARRAY_OF_UBYTES_LONG_SIZE -> { when (outputParam.parameterType) {
methodBuilder.addStatement("val ${outputParam.parameterName} = UByteArray($length)") TypeDefinition.ARRAY_OF_UBYTES, TypeDefinition.ARRAY_OF_UBYTES_NO_SIZE, TypeDefinition.ARRAY_OF_UBYTES_LONG_SIZE -> {
methodBuilder.addStatement("val ${outputParam.parameterName} = UByteArray($length)")
}
TypeDefinition.UBYTE -> {
methodBuilder.addStatement("var ${outputParam.parameterName} : UByte = 0U")
}
else -> {
throw RuntimeException("Unhandled native output param type: ${outputParam.parameterType.typeName}")
}
} }
else -> {
throw RuntimeException("Unhandled native output param type: ${outputParam.parameterType.typeName}")
}
} }
} }
fun createTupleOutputParams(outputParams: List<ParameterDefinition>) : String {
return outputParams.map { it.parameterName }.joinToString (separator = ", ")
}
fun pinParams(methodDefinition: FunctionDefinition, methodBuilder: FunSpec.Builder) { fun pinParams(methodDefinition: FunctionDefinition, methodBuilder: FunSpec.Builder) {
methodDefinition.parameterList.forEachIndexed { index, paramDefinition -> methodDefinition.parameterList.forEachIndexed { index, paramDefinition ->
if (paramDefinition.parameterType is TypeDefinition) { if (paramDefinition.parameterType is TypeDefinition) {

View File

@ -20,6 +20,13 @@ data class SecretStreamStateAndHeader(
val header: UByteArray val header: UByteArray
) )
data class DecryptedDataAndTag(
@JsName("decrypted")
val decrypted: UByteArray,
@JsName("tag")
val tag: UByte
)
expect class Crypto internal constructor() { expect class Crypto internal constructor() {
/** /**
* Initialize the SHA256 hash * Initialize the SHA256 hash
@ -68,5 +75,5 @@ expect class Crypto internal constructor() {
state: SecretStreamState, state: SecretStreamState,
c: UByteArray, c: UByteArray,
ad: UByteArray ad: UByteArray
): UByteArray ): DecryptedDataAndTag
} }

View File

@ -65,7 +65,7 @@ class SecretStreamTest {
encrypted.hexColumsPrint() encrypted.hexColumsPrint()
val decryptState = crypto.crypto_secretstream_xchacha20poly1305_init_pull(stateAndHeader.header, key) val decryptState = crypto.crypto_secretstream_xchacha20poly1305_init_pull(stateAndHeader.header, key)
val decrypted = val decrypted =
crypto.crypto_secretstream_xchacha20poly1305_pull(decryptState, encrypted, ubyteArrayOf()) //TODO JS pull returns a tag and a message!!! crypto.crypto_secretstream_xchacha20poly1305_pull(decryptState, encrypted, ubyteArrayOf())
decrypted.hexColumsPrint() decrypted.hexColumsPrint()
decrypted.contentEquals(message) decrypted.contentEquals(message)

View File

@ -77,10 +77,10 @@ actual class Crypto internal actual constructor() {
* Initialize state from header and key. The state can then be used for decryption. * Initialize state from header and key. The state can then be used for decryption.
*/ */
actual fun crypto_secretstream_xchacha20poly1305_init_pull(header: UByteArray, key: UByteArray): actual fun crypto_secretstream_xchacha20poly1305_init_pull(header: UByteArray, key: UByteArray):
SecretStreamState { dynamic {
println("Debug crypto_secretstream_xchacha20poly1305_init_pull") println("Debug crypto_secretstream_xchacha20poly1305_init_pull")
return getSodium().crypto_secretstream_xchacha20poly1305_init_pull(header.toUInt8Array(), return getSodium().crypto_secretstream_xchacha20poly1305_init_pull(header.toUInt8Array(),
key.toUInt8Array()) as SecretStreamState key.toUInt8Array())
} }
/** /**
@ -104,9 +104,9 @@ actual class Crypto internal actual constructor() {
state: SecretStreamState, state: SecretStreamState,
c: UByteArray, c: UByteArray,
ad: UByteArray ad: UByteArray
): UByteArray { ): UByte {
println("Debug crypto_secretstream_xchacha20poly1305_pull") println("Debug crypto_secretstream_xchacha20poly1305_pull")
return getSodium().crypto_secretstream_xchacha20poly1305_pull(state, c.toUInt8Array(), return getSodium().crypto_secretstream_xchacha20poly1305_pull(state, c.toUInt8Array(),
ad.toUInt8Array()).toUByteArray() ad.toUInt8Array())
} }
} }

View File

@ -117,11 +117,12 @@ actual class Crypto internal actual constructor() {
state: SecretStreamState, state: SecretStreamState,
c: UByteArray, c: UByteArray,
ad: UByteArray ad: UByteArray
): UByteArray { ): DecryptedDataAndTag {
val m = UByteArray(c.size - 17) val m = UByteArray(c.size - 17)
var tag_p : UByte = 0U
println("Debug crypto_secretstream_xchacha20poly1305_pull") println("Debug crypto_secretstream_xchacha20poly1305_pull")
sodium.crypto_secretstream_xchacha20poly1305_pull(state, m.asByteArray(), null, null, sodium.crypto_secretstream_xchacha20poly1305_pull(state, m.asByteArray(), null, tag_p.toByte(),
c.asByteArray(), c.size.toLong(), ad.asByteArray(), ad.size.toLong()) c.asByteArray(), c.size.toLong(), ad.asByteArray(), ad.size.toLong())
return m return debug.test.DecryptedDataAndTag(m, tag_p)
} }
} }

View File

@ -162,17 +162,18 @@ actual class Crypto internal actual constructor() {
state: SecretStreamState, state: SecretStreamState,
c: UByteArray, c: UByteArray,
ad: UByteArray ad: UByteArray
): UByteArray { ): DecryptedDataAndTag {
val m = UByteArray(c.size - 17) val m = UByteArray(c.size - 17)
var tag_p : UByte = 0U
println("Debug crypto_secretstream_xchacha20poly1305_pull") println("Debug crypto_secretstream_xchacha20poly1305_pull")
val pinnedM = m.pin() val pinnedM = m.pin()
val pinnedC = c.pin() val pinnedC = c.pin()
val pinnedAd = ad.pin() val pinnedAd = ad.pin()
libsodium.crypto_secretstream_xchacha20poly1305_pull(state.ptr, pinnedM.addressOf(0), null, libsodium.crypto_secretstream_xchacha20poly1305_pull(state.ptr, pinnedM.addressOf(0), null,
null, pinnedC.addressOf(0), c.size.convert(), pinnedAd.addressOf(0), ad.size.convert()) tag_p, pinnedC.addressOf(0), c.size.convert(), pinnedAd.addressOf(0), ad.size.convert())
pinnedM.unpin() pinnedM.unpin()
pinnedC.unpin() pinnedC.unpin()
pinnedAd.unpin() pinnedAd.unpin()
return m return debug.test.DecryptedDataAndTag(m, tag_p)
} }
} }