Skip to content
This repository has been archived by the owner on Aug 12, 2024. It is now read-only.

Commit

Permalink
Rename key detection utility to KeyReaderHelper and add some document…
Browse files Browse the repository at this point in the history
…ation
  • Loading branch information
Cach30verfl0w committed Jun 14, 2024
1 parent e90a1d8 commit 4e1fe51
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,67 @@ import libssl.EVP_PKEY
import libssl.PEM_read_bio_PUBKEY
import libssl.PEM_read_bio_PrivateKey

// TODO: Detect key format, key size and algorithm (etc)

/**
* This utility is used to read keys from a raw memory pointer, size and purpose. This is used in
* the default keystore to create keys from byte arrays, strings and files. This class uses a few
* methods to try to interpret the key with different formats. The format that doesn't fails is
* being chosen and returned to the caller. Otherwise this helper returns null to the caller.
*
* This utility is 100% based on OpenSSL and it's BIO interface. We try to hold secret information
* like private keys as secure as possible. So we try to instrument system features to hide that
* information.
*
* @author Cedric Hammes
* @since 14/06/2024
*/
@OptIn(ExperimentalForeignApi::class)
object KeyDetectionUtil {
object KeyReaderHelper {

/**
* This method creates a BIO (Basic Input/Output) object in secured memory and writes the
* specified data into it. This memory is more protected against memory leakage as normal
* memory.
*
* This buffer is marked secure because is holds secret/private keys and the leakage of
* them is a security concern and this memory tries to prevent that.
*
* @author Cedric Hammes
* @since 14/06/2024
*/
private fun createSecureMemoryBuffer(pointer: CPointer<ByteVar>, size: ULong): CPointer<BIO> =
BIO_new(BIO_s_secmem()).apply {
BIO_write(this, pointer, size.toInt())
}?: throw RuntimeException("Error while writing key into secure memory BIO")

/**
* This method constructs a key buffer and try to interpret it as PEM-formated private key. If
* that doesn't work, it tries to create a new buffer and interpret it as PEM-formatted public
* key. If one of these worked, this function creates the key from the content and returns it
* to the caller. Otherwise this function returns null
*
* This method is try-to-parse and only works if the key it PEM-formatted. Otherwise we return
* null (like mentioned before). All buffers created a being freed by the method itself and
* the key returned is being freed because of the [AutoCloseable].
*
* @param pointer Pointer to the (encoded) data to try to interpret
* @param size The size of the data provided by the pointer
* @param purposes The purposes of the key or the key creation
* @return The key if one of the parses succeeds, otherwise null
*
* @author Cedric Hammes
* @since 14/06/2024
*/
private fun tryParseAsPEM(pointer: CPointer<ByteVar>, size: ULong, purposes: UByte): Key? {
fun getPEMKey(pointer: CPointer<ByteVar>, size: ULong): Pair<CPointer<EVP_PKEY>, KeyType>? {
// Try to interpret the key as private key. If it works, we return it
val privateKeyBuffer = createSecureMemoryBuffer(pointer, size)
val privateKey = PEM_read_bio_PrivateKey(privateKeyBuffer, null, null, null)
BIO_free(privateKeyBuffer)
if (privateKey != null) {
return Pair(privateKey, KeyType.PRIVATE)
}

// Try to interpret the key as public key. If it works, we return it
val publicKeyBuffer = createSecureMemoryBuffer(pointer, size)
val publicKey = PEM_read_bio_PUBKEY(publicKeyBuffer, null, null, null)
BIO_free(publicKeyBuffer)
Expand All @@ -60,6 +102,7 @@ object KeyDetectionUtil {
return null
}

// Try to interpret the key as PEM-formatted key and return
val pemParsedKey = getPEMKey(pointer, size)
if (pemParsedKey != null) {
return OpenSSLPKey(pemParsedKey.first, purposes, pemParsedKey.second, KeyFormat.PEM)
Expand Down
2 changes: 1 addition & 1 deletion kmp-advcrypto/src/nativeInterop/cinterop/libssl.def
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
headers = openssl/crypto.h openssl/err.h openssl/aes.h openssl/rsa.h openssl/rand.h openssl/evp.h openssl/pem.h openssl/bio.h openssl/md5.h
headers = openssl/crypto.h openssl/err.h openssl/aes.h openssl/rsa.h openssl/rand.h openssl/evp.h openssl/pem.h openssl/bio.h openssl/md5.h openssl/pkcs7.h
linkerOpts = -L/usr/lib/x86_64-linux-gnu -L/usr/lib -ldl -lpthread -lc -lm -lssl -lcrypto
compilerOpts = -I/usr/include -I/usr/include/x86_64-linux-gnu

0 comments on commit 4e1fe51

Please sign in to comment.