diff --git a/CMakeLists.txt b/CMakeLists.txt index 4421ff12..0310d678 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,9 +29,7 @@ option(SUPRESS_MSVC_WARNINGS "Suppresses a lot of the warnings when compiling wi option(ENABLE_CERT_COMPRESS "Enable/disable compression of certificate" OFF) if (ENABLE_CERT_COMPRESS) - if(NOT MSVC) - add_definitions(-DUSE_CERT_COMPRESS="1") - endif() + add_definitions(-DUSE_CERT_COMPRESS="1") endif() include(${CMAKE_SOURCE_DIR}/cmake/SecurityFlags.cmake) diff --git a/common/data_compress.c b/common/data_compress.c new file mode 100644 index 00000000..a1211e40 --- /dev/null +++ b/common/data_compress.c @@ -0,0 +1,83 @@ +/* +* Copyright 2024 Yubico AB +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "data_compress.h" + +#include +#include + +int compress_data(uint8_t* data, size_t data_len, uint8_t *compressed_data, size_t *compressed_data_len) { + + z_stream zs; + zs.zalloc = Z_NULL; + zs.zfree = Z_NULL; + zs.opaque = Z_NULL; + zs.avail_in = (uInt)data_len; + zs.next_in = (Bytef *)data; + zs.avail_out = (uInt) *compressed_data_len; + zs.next_out = (Bytef *)compressed_data; + + if(deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS | 16, 8, Z_DEFAULT_STRATEGY) != Z_OK) { + fprintf(stderr, "Failed to compress data\n"); + return -1; + } + if(deflate(&zs, Z_FINISH) != Z_STREAM_END) { + fprintf(stderr, "Failed to compress data\n"); + return -1; + } + if(deflateEnd(&zs) != Z_OK) { + fprintf(stderr, "Failed to compress data\n"); + return -1; + } + + *compressed_data_len = zs.total_out; + return 0; +} + + +int uncompress_data(uint8_t *compressed_data, size_t compressed_data_len, uint8_t *data, size_t *data_len) { + uint8_t *dataptr = compressed_data; + + z_stream zs; + zs.zalloc = Z_NULL; + zs.zfree = Z_NULL; + zs.opaque = Z_NULL; + zs.avail_in = (uInt) compressed_data_len; + zs.next_in = (Bytef *) dataptr; + zs.avail_out = (uInt) *data_len; + zs.next_out = (Bytef *) data; + + if (inflateInit2(&zs, MAX_WBITS | 16) != Z_OK) { + fprintf(stderr, "Failed to initialize data decompression\n"); + return -1; + } + + int res = inflate(&zs, Z_FINISH); + if (res != Z_STREAM_END) { + if (res == Z_BUF_ERROR) { + fprintf(stderr, "Failed to decompress data. Allocated buffer is too small\n"); + } else { + fprintf(stderr, "Failed to decompress data\n"); + } + return -1; + } + if (inflateEnd(&zs) != Z_OK) { + fprintf(stderr, "Failed to finish data decompression\n"); + return -1; + } + *data_len = zs.total_out; + return 0; +} diff --git a/common/x509_compress.h b/common/data_compress.h similarity index 64% rename from common/x509_compress.h rename to common/data_compress.h index 277fec0b..e2b6ce08 100644 --- a/common/x509_compress.h +++ b/common/data_compress.h @@ -19,16 +19,12 @@ ** Implements platform specific operations to compress and uncompress X509Cert */ -#ifndef YUBIHSM_SHELL_X509_COMPRESS_H -#define YUBIHSM_SHELL_X509_COMPRESS_H - -#ifndef _WIN32_BCRYPT -// Only inlcude this if OpenSSL can be used +#ifndef YUBIHSM_SHELL_DATA_COMPRESS_H +#define YUBIHSM_SHELL_DATA_COMPRESS_H #include "../common/platform-config.h" #include #include -#include #ifdef __cplusplus extern "C" { @@ -36,9 +32,11 @@ extern "C" { #define YH_INTERNAL __attribute__((visibility("hidden"))) -int YH_INTERNAL compress_cert(X509 *cert, uint8_t *compressed_data); -X509* uncompress_cert(uint8_t *data, size_t data_len); - -#endif +int YH_INTERNAL compress_data(uint8_t *data, size_t data_len, + uint8_t *compressed_data, + size_t *compressed_data_len); +int YH_INTERNAL uncompress_data(uint8_t *compressed_data, + size_t compressed_data_len, uint8_t *data, + size_t *data_len); -#endif // YUBIHSM_SHELL_X509_COMPRESS_H +#endif // YUBIHSM_SHELL_DATA_COMPRESS_H diff --git a/common/x509_compress.c b/common/x509_compress.c deleted file mode 100644 index 40977863..00000000 --- a/common/x509_compress.c +++ /dev/null @@ -1,100 +0,0 @@ -/* -* Copyright 2024 Yubico AB -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#ifndef _WIN32_BCRYPT - -#include "x509_compress.h" - -#include -#include - -int compress_cert(X509 *cert, uint8_t *compressed_data) { - - unsigned char uncompressed_certdata[4096] = {0}; - unsigned char *uncompressed_certptr = uncompressed_certdata; - int cert_len = i2d_X509(cert, &uncompressed_certptr); - - if( cert_len < 0) { - fprintf(stderr, "Failed to encode X509 certificate before compression\n"); - return 0; - } - - z_stream zs; - zs.zalloc = Z_NULL; - zs.zfree = Z_NULL; - zs.opaque = Z_NULL; - zs.avail_in = (uInt)cert_len; - zs.next_in = (Bytef *)uncompressed_certdata; - zs.avail_out = (uInt) sizeof(uncompressed_certdata); - zs.next_out = (Bytef *)compressed_data; - - if(deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS | 16, 8, Z_DEFAULT_STRATEGY) != Z_OK) { - fprintf(stderr, "Failed to compress certificate: deflateInit2()\n"); - return 0; - } - if(deflate(&zs, Z_FINISH) != Z_STREAM_END) { - fprintf(stderr, "Failed to compress certificate: deflate()\n"); - return 0; - } - if(deflateEnd(&zs) != Z_OK) { - fprintf(stderr, "Failed to compress certificate: deflateEnd()\n"); - return 0; - } - - return zs.total_out; -} - - -X509* uncompress_cert(uint8_t *data, size_t data_len) { - uint8_t *dataptr = data; - uint8_t certdata[4096] = {0}; - size_t certdata_len = sizeof(certdata); - - z_stream zs; - zs.zalloc = Z_NULL; - zs.zfree = Z_NULL; - zs.opaque = Z_NULL; - zs.avail_in = (uInt) data_len; - zs.next_in = (Bytef *) dataptr; - zs.avail_out = (uInt) certdata_len; - zs.next_out = (Bytef *) certdata; - - if (inflateInit2(&zs, MAX_WBITS | 16) != Z_OK) { - fprintf(stderr, "Failed to initialize certificate decompression\n"); - return NULL; - } - - int res = inflate(&zs, Z_FINISH); - if (res != Z_STREAM_END) { - if (res == Z_BUF_ERROR) { - fprintf(stderr, "Failed to decompress certificate. Allocated buffer is too small\n"); - } else { - fprintf(stderr, "Failed to decompress certificate\n"); - } - return NULL; - } - if (inflateEnd(&zs) != Z_OK) { - fprintf(stderr, "Failed to finish certificate decompression\n"); - return NULL; - } - certdata_len = zs.total_out; - - const unsigned char *certdata_ptr = certdata; - return d2i_X509(NULL, &certdata_ptr, certdata_len); -} - - -#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 57991864..7425ca20 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,6 +27,17 @@ set ( ../common/openssl-compat.c ) +if (ENABLE_CERT_COMPRESS) + set(SOURCE ${SOURCE} ../common/data_compress.c) + + find_library(ZLIB zlib PATHS ${ZLIB_LIB_DIR}) + include_directories(${ZLIB_INCL_DIR}) + + find_package(ZLIB REQUIRED) + + set(ZLIB_LIBS "ZLIB::ZLIB") +endif() + if(WIN32) set(SOURCE ${SOURCE} cmdline.c) include(${CMAKE_SOURCE_DIR}/cmake/getopt.cmake) @@ -36,17 +47,6 @@ else(WIN32) find_gengetopt () add_gengetopt_files (cmdline "--conf-parser") set(SOURCE ${SOURCE} ${GGO_C}) - - if (ENABLE_CERT_COMPRESS) - set(SOURCE ${SOURCE} ../common/x509_compress.c) - - find_library(ZLIB zlib PATHS ${ZLIB_LIB_DIR}) - include_directories(${ZLIB_INCL_DIR}) - - find_package(ZLIB REQUIRED) - - set(ZLIB_LIBS "ZLIB::ZLIB") - endif() endif(WIN32) include_directories ( diff --git a/src/commands.c b/src/commands.c index eb687965..bc16412e 100644 --- a/src/commands.c +++ b/src/commands.c @@ -24,7 +24,7 @@ #include "../common/insecure_memzero.h" #include "../common/parsing.h" #ifdef USE_CERT_COMPRESS -#include "../common/x509_compress.h" +#include "../common/data_compress.h" #endif #include "time_win.h" @@ -920,9 +920,16 @@ int yh_com_get_opaque(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, fprintf(stderr, "Failed parsing x509 information.\n"); #ifdef USE_CERT_COMPRESS fprintf(stderr, "Trying to parse it as compressed certificate\n"); - x509 = uncompress_cert(response, response_len); - if(!x509) { - fprintf(stderr, "Failed parsing x509 information.\n"); + uint8_t certdata[4096] = {0}; + size_t certdata_len = sizeof(certdata); + if(uncompress_data(response, response_len, certdata, &certdata_len) != 0) { + fprintf(stderr, "Failed to decompress data.\n"); + } else { + const unsigned char *certdata_ptr = certdata; + x509 = d2i_X509(NULL, &certdata_ptr, certdata_len); + if(!x509) { + fprintf(stderr, "Failed parsing x509 information.\n"); + } } #endif } @@ -2332,12 +2339,17 @@ int yh_com_put_opaque(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, } #ifdef USE_CERT_COMPRESS - if (argv[5].a == YH_ALGO_OPAQUE_X509_COMPRESSED) { - len = compress_cert(cert, data); - if (len == 0) { + if (cert && argv[5].a == YH_ALGO_OPAQUE_X509_COMPRESSED) { + + uint8_t compressed_data[YH_MSG_BUF_SIZE] = {0}; + size_t compressed_data_len = sizeof(compressed_data); + + if (compress_data(data, len, compressed_data, &compressed_data_len) != 0) { fprintf(stderr, "Couldn't compress certificate\n"); return 0; } + memcpy(data, compressed_data, compressed_data_len); + len = compressed_data_len; } #endif X509_free(cert);