-
Notifications
You must be signed in to change notification settings - Fork 226
crypto: support openssl crypto backend #354
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,7 +26,7 @@ | |
|
|
||
| #include "dislocker/common.h" | ||
|
|
||
| #include "dislocker/ssl_bindings.h" | ||
| #include "ssl_bindings.h" | ||
|
|
||
|
|
||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| /* -*- coding: utf-8 -*- */ | ||
| /* -*- mode: c -*- */ | ||
| /* | ||
| * Dislocker -- enables to read/write on BitLocker encrypted partitions under | ||
| * Linux | ||
| * Copyright (C) 2026 Arm Ltd. | ||
| * | ||
| * This program is free software; you can redistribute it and/or | ||
| * modify it under the terms of the GNU General Public License | ||
| * as published by the Free Software Foundation; either version 2 | ||
| * of the License, or (at your option) any later version. | ||
| * | ||
| * This program is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU General Public License | ||
| * along with this program; if not, write to the Free Software | ||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
| * USA. | ||
| */ | ||
| #ifndef SSL_BINDINGS_H | ||
| #define SSL_BINDINGS_H | ||
|
|
||
| #include <openssl/aes.h> | ||
| #include <openssl/evp.h> | ||
| #include <openssl/sha.h> | ||
|
|
||
| #define DIS_OSSL_MAX_AES_KEY_BYTES 512/8 | ||
|
|
||
| typedef struct dis_ossl_aes_ctx dis_ossl_aes_ctx; | ||
| struct dis_ossl_aes_ctx { | ||
| unsigned char key[DIS_OSSL_MAX_AES_KEY_BYTES]; | ||
| size_t len; | ||
| int enc_dec; | ||
| }; | ||
|
|
||
| #define AES_CONTEXT dis_ossl_aes_ctx | ||
|
|
||
| #define DIS_OSSL_CIPHER_ECB 0 | ||
| #define DIS_OSSL_CIPHER_CBC 1 | ||
|
|
||
| static inline const EVP_CIPHER *dis_ossle_get_cipher(size_t key_len, int ossl_mode) | ||
| { | ||
| if (ossl_mode == DIS_OSSL_CIPHER_ECB) | ||
| { | ||
| switch (key_len) | ||
| { | ||
| case 16: return EVP_aes_128_ecb(); | ||
| case 24: return EVP_aes_192_ecb(); | ||
| case 32: return EVP_aes_256_ecb(); | ||
| default: return NULL; | ||
| } | ||
| } | ||
| else if (ossl_mode == DIS_OSSL_CIPHER_CBC) | ||
| { | ||
| switch (key_len) | ||
| { | ||
| case 16: return EVP_aes_128_cbc(); | ||
| case 24: return EVP_aes_192_cbc(); | ||
| case 32: return EVP_aes_256_cbc(); | ||
| default: return NULL; | ||
| } | ||
| } | ||
| return NULL; | ||
| } | ||
|
|
||
| static inline int dis_ossl_set_key(AES_CONTEXT *ctx, const unsigned char *key, size_t key_bits, int enc_dec) | ||
| { | ||
| size_t key_len = key_bits / 8; | ||
| if (key_len > sizeof(ctx->key)) | ||
| return 1; | ||
|
|
||
| memcpy(ctx->key, key, key_len); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| ctx->len = key_bits / 8; | ||
| ctx->enc_dec = enc_dec; | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| static inline int dis_ossl_aes_crypt( | ||
| AES_CONTEXT *ctx, | ||
| int mode, | ||
| int size, | ||
| const unsigned char *iv, | ||
| const unsigned char *input, | ||
| unsigned char *output, | ||
| int cipher) | ||
| { | ||
| int rc = 1; /* fail unless otherwise changed */ | ||
| int out_len = 0; | ||
|
|
||
| const EVP_CIPHER *ossl_cipher = dis_ossle_get_cipher(ctx->len, cipher); | ||
| if (!ossl_cipher) | ||
| return rc; | ||
|
|
||
| EVP_CIPHER_CTX *ossl_ctx = EVP_CIPHER_CTX_new(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This allocates and tears down an EVP context on every call. Worth either caching the
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Probably not as much as one thinks, since alloc and free are fairly cheap unless the heap needs to grow. I didn't notice a decryption speed difference. But I didn't like this approach either because of what you state.
I think it would be cleaner if I just refactored the crypto interface, where we have an init, use, free pattern by the underlying crypto routines. |
||
| if (!ossl_ctx) | ||
| return rc; | ||
|
|
||
| if (mode == AES_ENCRYPT) | ||
| { | ||
| if (!EVP_EncryptInit(ossl_ctx, ossl_cipher, ctx->key, iv)) goto error; | ||
| if (!EVP_CIPHER_CTX_set_padding(ossl_ctx, 0)) goto error; | ||
| if (!EVP_EncryptUpdate(ossl_ctx, output, &out_len, input, size)) goto error; | ||
| if (!EVP_EncryptFinal(ossl_ctx, &output[out_len], &out_len)) goto error; | ||
| } else { | ||
| if (!EVP_DecryptInit(ossl_ctx, ossl_cipher, ctx->key, iv)) goto error; | ||
| if (!EVP_CIPHER_CTX_set_padding(ossl_ctx, 0)) goto error; | ||
| if (!EVP_DecryptUpdate(ossl_ctx, output, &out_len, input, size)) goto error; | ||
| if (!EVP_DecryptFinal(ossl_ctx, &output[out_len], &out_len)) goto error; | ||
| } | ||
|
|
||
| /* success */ | ||
| rc = 0; | ||
|
|
||
| error: | ||
| EVP_CIPHER_CTX_free(ossl_ctx); | ||
| return rc; | ||
| } | ||
|
|
||
| #define AES_SETENC_KEY(ctx, key, size) dis_ossl_set_key(ctx, key, size, AES_ENCRYPT) | ||
| #define AES_SETDEC_KEY(ctx, key, size) dis_ossl_set_key(ctx, key, size, AES_DECRYPT) | ||
| #define AES_ECB_ENC(ctx, mode, in, out) dis_ossl_aes_crypt(ctx, mode, 16, NULL, in, out, DIS_OSSL_CIPHER_ECB) | ||
| #define AES_CBC(ctx, mode, size, iv, in, out) dis_ossl_aes_crypt(ctx, mode, size, iv, in, out, DIS_OSSL_CIPHER_CBC) | ||
|
|
||
| /* | ||
| * OpenSSL doesn't provide XEX nor XTS, so just use the dislocker implementations. Note that | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't quite right — OpenSSL does provide XTS (
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ahh I see that it has XTS, I didn't see that before when I looked. |
||
| * the dislocker implementations use the OpenSSL primitives already defined, these are optional | ||
| */ | ||
| #include "dislocker/encryption/aes-xts.h" | ||
| #define AES_XEX(ctx1, ctx2, mode, size, iv, in, out) \ | ||
| dis_aes_crypt_xex(ctx1, ctx2, mode, size, iv, in, out) | ||
|
|
||
| #define AES_XTS(ctx1, ctx2, mode, size, iv, in, out) \ | ||
| dis_aes_crypt_xts(ctx1, ctx2, mode, size, iv, in, out) | ||
|
|
||
| #endif /* SSL_BINDINGS_H */ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -47,7 +47,6 @@ endif() | |
| if( NOT CMAKE_CROSSCOMPILING ) | ||
| include_directories (SYSTEM /usr/local/include) | ||
| endif() | ||
| include_directories (${PROJECT_SOURCE_DIR}/include) | ||
|
|
||
| set (LIB pthread) | ||
| set (SOURCES | ||
|
|
@@ -118,9 +117,6 @@ endif() | |
| # Libraries | ||
| set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) | ||
|
|
||
| find_package (MbedTLS 3 REQUIRED) | ||
| set (LIB ${LIB} MbedTLS::mbedcrypto) | ||
|
|
||
| # Ruby bindings | ||
| set(WITH_RUBY "AUTO" CACHE STRING "Enable Ruby bindings. Valid values are ON, OFF, or AUTO") | ||
| if (NOT "${WITH_RUBY}" STREQUAL "OFF") | ||
|
|
@@ -201,7 +197,8 @@ endif() | |
|
|
||
| # Targets | ||
| add_library (${PROJECT_NAME} SHARED ${SOURCES}) | ||
| target_link_libraries (${PROJECT_NAME} ${LIB}) | ||
| target_include_directories (${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include) | ||
| target_link_libraries (${PROJECT_NAME} PRIVATE ${LIB}) | ||
| set_target_properties (${PROJECT_NAME} PROPERTIES VERSION "${VERSION}" SOVERSION "${VERSION_MAJOR}.${VERSION_MINOR}") | ||
| install (TARGETS ${PROJECT_NAME} LIBRARY DESTINATION "${libdir}") | ||
|
|
||
|
|
@@ -213,12 +210,45 @@ if (${APPLE}) | |
| install (TARGETS ${BUNDLE_NAME} DESTINATION "${libdir}") | ||
| endif() | ||
|
|
||
| set(CRYPTO_BACKEND "mbedtls" CACHE STRING "Crypto library backend") | ||
| set_property(CACHE CRYPTO_BACKEND PROPERTY STRINGS "mbedtls" "openssl") | ||
|
|
||
| add_library(dislocker_crypto_backend INTERFACE) | ||
|
|
||
| message(STATUS "Crypto backend: ${CRYPTO_BACKEND}") | ||
| if(CRYPTO_BACKEND STREQUAL "mbedtls") | ||
| find_package (MbedTLS 3 REQUIRED) | ||
| target_link_libraries(${PROJECT_NAME} | ||
| PRIVATE | ||
| MbedTLS::mbedcrypto | ||
| ) | ||
| target_link_libraries(dislocker_crypto_backend INTERFACE MbedTLS::mbedcrypto) | ||
| target_include_directories(${PROJECT_NAME} | ||
| PUBLIC | ||
| ${CMAKE_SOURCE_DIR}/include/${PROJECT_NAME}/encryption/mbedtls | ||
| ) | ||
| elseif(CRYPTO_BACKEND STREQUAL "openssl") | ||
| find_package(OpenSSL REQUIRED) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The mbedtls path specifies a minimum version ( |
||
| target_link_libraries(${PROJECT_NAME} | ||
| PRIVATE | ||
| OpenSSL::Crypto | ||
| ) | ||
| target_link_libraries(dislocker_crypto_backend INTERFACE OpenSSL::Crypto) | ||
| target_include_directories(${PROJECT_NAME} | ||
| PUBLIC | ||
| ${CMAKE_SOURCE_DIR}/include/${PROJECT_NAME}/encryption/openssl | ||
| ) | ||
| else() | ||
| message(FATAL_ERROR "Unknown CRYPTO_BACKEND='${CRYPTO_BACKEND}'.") | ||
| endif() | ||
|
|
||
|
|
||
| set (CLEAN_FILES "") | ||
|
|
||
| if(FUSE_FOUND) | ||
| set (BIN_FUSE ${PROJECT_NAME}-fuse) | ||
| add_executable (${BIN_FUSE} ${BIN_FUSE}.c) | ||
| target_link_libraries (${BIN_FUSE} ${FUSE_LIBBRARIES} ${PROJECT_NAME}) | ||
| target_link_libraries (${BIN_FUSE} PRIVATE ${FUSE_LIBBRARIES} ${LIB} ${PROJECT_NAME}) | ||
| set_target_properties (${BIN_FUSE} PROPERTIES COMPILE_DEFINITIONS FUSE_USE_VERSION=314) | ||
| set_target_properties (${BIN_FUSE} PROPERTIES LINK_FLAGS "-pie -fPIE") | ||
| add_custom_command (TARGET ${BIN_FUSE} POST_BUILD | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # Dislocker -- enables to read/write on BitLocker encrypted partitions under | ||
| # Linux | ||
| # Copyright (C) 2026 Arm Ltd | ||
| # | ||
| # This program is free software; you can redistribute it and/or | ||
| # modify it under the terms of the GNU General Public License | ||
| # as published by the Free Software Foundation; either version 2 | ||
| # of the License, or (at your option) any later version. | ||
| # | ||
| # This program is distributed in the hope that it will be useful, | ||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| # GNU General Public License for more details. | ||
| # | ||
| # You should have received a copy of the GNU General Public License | ||
| # along with this program; if not, write to the Free Software | ||
| # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
| # USA. | ||
|
|
||
| add_executable(crypto_tests | ||
| test-crypto.c | ||
| ) | ||
|
|
||
| target_link_libraries(crypto_tests PRIVATE ${PROJECT_NAME} dislocker_crypto_backend) | ||
|
|
||
| add_test(NAME cyrpto_tests COMMAND crypto_tests) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typo: |
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo:
dis_ossle_get_cipher→dis_ossl_get_cipher(straye)