Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate DTLS message before decryption #59

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ internal object MbedtlsApi {
external fun mbedtls_ssl_get_peer_cid(sslContext: Pointer, enabled: Pointer, peerCid: Pointer, peerCidLen: Pointer): Int
external fun mbedtls_ssl_context_save(sslContext: Pointer, buf: ByteArray, bufLen: Int, outputLen: ByteArray): Int
external fun mbedtls_ssl_context_load(sslContext: Pointer, buf: ByteArray, len: Int): Int
external fun mbedtls_ssl_check_record(sslContext: Pointer, buf: ByteBuffer, bufLen: Int): Int
JuhaPekkaa marked this conversation as resolved.
Show resolved Hide resolved
external fun mbedtls_ssl_conf_ca_chain(sslConfig: Pointer, caChain: Pointer, caCrl: Pointer?)
external fun mbedtls_ssl_conf_own_cert(sslConfig: Pointer, ownCert: Memory, pkKey: Pointer): Int
external fun mbedtls_ssl_set_mtu(sslContext: Pointer, mtu: Int)
Expand Down
21 changes: 21 additions & 0 deletions kotlin-mbedtls/src/main/kotlin/org/opencoap/ssl/SslContext.kt
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,27 @@ class SslSession internal constructor(
plainBuffer.limit(size + plainBuffer.position())
}

data class VerificationResult(val isValid: Boolean, val message: String)
JuhaPekkaa marked this conversation as resolved.
Show resolved Hide resolved

fun verifyRecord(encBuffer: ByteBuffer): VerificationResult {
JuhaPekkaa marked this conversation as resolved.
Show resolved Hide resolved
val buffer = clone(encBuffer)
JuhaPekkaa marked this conversation as resolved.
Show resolved Hide resolved
val result = MbedtlsApi.mbedtls_ssl_check_record(sslContext, buffer, buffer.remaining())
return if (result == 0) {
JuhaPekkaa marked this conversation as resolved.
Show resolved Hide resolved
VerificationResult(true, "Success")
} else {
VerificationResult(false, "Record verification failed: ${SslException.from(result)}")
}
}

private fun clone(original: ByteBuffer): ByteBuffer {
JuhaPekkaa marked this conversation as resolved.
Show resolved Hide resolved
val clone = ByteBuffer.allocate(original.capacity())
original.rewind()
clone.put(original)
original.rewind()
clone.flip()
return clone
}

fun decrypt(encBuffer: ByteBuffer, send: (ByteBuffer) -> Unit): ByteBuffer {
val buf = ByteBuffer.allocate(encBuffer.remaining())
decrypt(encBuffer, buf, send)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,11 @@ class DtlsServer(
fun decrypt(encPacket: ByteBuffer): ReceiveResult {
scheduledTask.cancel(false)
try {
val (isValid, message) = ctx.verifyRecord(encPacket)
JuhaPekkaa marked this conversation as resolved.
Show resolved Hide resolved
if (!isValid) {
logger.warn(message)
return ReceiveResult.Handled
}
val plainBuf = ctx.decrypt(encPacket, ::send)
scheduledTask = executor.schedule(::timeout, expireAfter)
return if (plainBuf.isNotEmpty()) {
Expand Down
12 changes: 12 additions & 0 deletions kotlin-mbedtls/src/test/kotlin/org/opencoap/ssl/SslContextTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import org.junit.jupiter.api.Assertions.assertNull
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import org.opencoap.ssl.transport.asByteBuffer
import org.opencoap.ssl.transport.copy
import org.opencoap.ssl.transport.decodeToString
import org.opencoap.ssl.transport.toByteBuffer
import org.opencoap.ssl.transport.toHex
Expand Down Expand Up @@ -123,6 +124,17 @@ class SslContextTest {
assertEquals("perse", serverSession.decrypt(encryptedDtls2, noSend).decodeToString())
}

@Test
fun `should verify session is valid authentic and decrypt`() {
JuhaPekkaa marked this conversation as resolved.
Show resolved Hide resolved
val clientSession = clientConf.loadSession(byteArrayOf(), StoredSessionPair.cliSession, localAddress(2_5684))
val serverSession = serverConf.loadSession(byteArrayOf(), StoredSessionPair.srvSession, localAddress(1_5684))

val encryptedDtls = clientSession.encrypt("auto".toByteBuffer()).copy()

assertTrue(serverSession.verifyRecord(encryptedDtls).isValid)
assertEquals("auto", serverSession.decrypt(encryptedDtls, noSend).decodeToString())
}

@Test
fun `should exchange data with direct byte buffer`() {
val clientSession = clientConf.loadSession(byteArrayOf(), StoredSessionPair.cliSession, localAddress(2_5684))
Expand Down
Loading