diff --git a/.circleci/config.yml b/.circleci/config.yml index 074d28fa..ce75b772 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -253,6 +253,56 @@ jobs: command: | find . -type f -and '(' -name '*.h' -or -name '*.c' -or -name '*.inc' ')' | xargs clang-format --dry-run --Werror + check-ASan-tests: + docker: + - image: cimg/base:2022.12 + environment: + CC: "clang" + CXX: "clang++" + ASAN_C_FLAGS: "-fsanitize=address -fno-omit-frame-pointer" + ASAN_OPTIONS: "detect_stack_use_after_return=1,detect_leaks=1" + steps: + - checkout + - run: + name: Install dependencies + command: sudo apt-get update && sudo apt-get install -y clang llvm ninja-build + - run: + name: Clone and build OpenSSL(3) master with ASan + command: | + git clone --branch master git://git.openssl.org/openssl.git openssl + cd openssl + mkdir install + ./Configure --debug --openssldir="$PWD/install" --prefix="$PWD/install" enable-asan + make -j$(nproc) + make install_sw + cd .. + - run: + name: Clone and build liboqs with ASan + command: | + git clone --depth 1 --branch main https://github.com/open-quantum-safe/liboqs.git liboqs + cd liboqs + mkdir build install + cmake -GNinja -B build \ + -DCMAKE_BUILD_TYPE=Debug \ + -DOQS_USE_OPENSSL=OFF \ + -DCMAKE_C_FLAGS="${ASAN_C_FLAGS}" \ + -DCMAKE_EXE_LINKER_FLAGS="${ASAN_C_FLAGS}" \ + -DCMAKE_INSTALL_PREFIX="$PWD/install" + cmake --build build -j$(nproc) + cmake --install build + cd .. + - run: + name: Build oqs-provider with ASan + command: | + cmake -GNinja -B build \ + -DCMAKE_BUILD_TYPE=Debug \ + -DOPENSSL_ROOT_DIR="$PWD/openssl/install" \ + -Dliboqs_DIR="$PWD/liboqs/install/lib/cmake/liboqs" \ + -DCMAKE_C_FLAGS="${ASAN_C_FLAGS}" \ + -DCMAKE_EXE_LINKER_FLAGS="${ASAN_C_FLAGS}" + cmake --build build -j$(nproc) + ctest --test-dir build/ + trigger-downstream-ci: docker: - image: cimg/base:2020.01 @@ -278,6 +328,7 @@ workflows: build: jobs: - check-clang-format + - check-ASan-tests - ubuntu: name: ubuntu-focal context: openquantumsafe diff --git a/oqsprov/oqs_decode_der2key.c b/oqsprov/oqs_decode_der2key.c index 35c79a5d..da4d666b 100644 --- a/oqsprov/oqs_decode_der2key.c +++ b/oqsprov/oqs_decode_der2key.c @@ -197,6 +197,7 @@ OQSX_KEY *oqsx_d2i_PUBKEY(OQSX_KEY **a, const unsigned char **pp, long length) xpk = oqsx_d2i_X509_PUBKEY_INTERNAL(pp, length, NULL); key = oqsx_key_from_x509pubkey(xpk, NULL, NULL); + X509_PUBKEY_free(xpk); if (key == NULL) return NULL; diff --git a/oqsprov/oqsprov_keys.c b/oqsprov/oqsprov_keys.c index 9eb15552..7947f27e 100644 --- a/oqsprov/oqsprov_keys.c +++ b/oqsprov/oqsprov_keys.c @@ -580,16 +580,20 @@ static int oqsx_hybsig_init(int bit_security, OQSX_EVP_CTX *evp_ctx, if (idx < 3) { // EC ret = EVP_PKEY_paramgen_init(evp_ctx->ctx); - ON_ERR_GOTO(ret <= 0, err); + ON_ERR_GOTO(ret <= 0, free_evp_ctx); ret = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(evp_ctx->ctx, evp_ctx->evp_info->nid); - ON_ERR_GOTO(ret <= 0, err); + ON_ERR_GOTO(ret <= 0, free_evp_ctx); ret = EVP_PKEY_paramgen(evp_ctx->ctx, &evp_ctx->keyParam); - ON_ERR_GOTO(ret <= 0 || !evp_ctx->keyParam, err); + ON_ERR_GOTO(ret <= 0 || !evp_ctx->keyParam, free_evp_ctx); } // RSA bit length set only during keygen + goto err; + +free_evp_ctx: + EVP_PKEY_CTX_free(evp_ctx->ctx); err: return ret; @@ -867,12 +871,14 @@ void oqsx_key_free(OQSX_KEY *key) else if (key->keytype == KEY_TYPE_ECP_HYB_KEM || key->keytype == KEY_TYPE_ECX_HYB_KEM) { OQS_KEM_free(key->oqsx_provider_ctx.oqsx_qs_ctx.kem); + } else + OQS_SIG_free(key->oqsx_provider_ctx.oqsx_qs_ctx.sig); + EVP_PKEY_free(key->classical_pkey); + if (key->oqsx_provider_ctx.oqsx_evp_ctx) { EVP_PKEY_CTX_free(key->oqsx_provider_ctx.oqsx_evp_ctx->ctx); EVP_PKEY_free(key->oqsx_provider_ctx.oqsx_evp_ctx->keyParam); OPENSSL_free(key->oqsx_provider_ctx.oqsx_evp_ctx); - } else - OQS_SIG_free(key->oqsx_provider_ctx.oqsx_qs_ctx.sig); - OPENSSL_free(key->classical_pkey); + } #ifdef OQS_PROVIDER_NOATOMIC CRYPTO_THREAD_lock_free(key->lock); #endif @@ -1036,6 +1042,7 @@ static EVP_PKEY *oqsx_key_gen_evp_key(OQSX_EVP_CTX *ctx, unsigned char *pubkey, EVP_PKEY *ck2 = d2i_PrivateKey(ctx->evp_info->keytype, NULL, &privkey_enc2, privkeylen); ON_ERR_SET_GOTO(!ck2, ret, -14, errhyb); + EVP_PKEY_free(ck2); } ENCODE_UINT32(pubkey, pubkeylen); ENCODE_UINT32(privkey, privkeylen); @@ -1087,6 +1094,7 @@ int oqsx_key_gen(OQSX_KEY *key) ret = oqsx_key_gen_oqs(key, 0); } else { EVP_PKEY_free(pkey); + pkey = NULL; ret = oqsx_key_gen_oqs(key, 1); } } else if (key->keytype == KEY_TYPE_SIG) { diff --git a/test/oqs_test_endecode.c b/test/oqs_test_endecode.c index 55fa0f84..220f7d0b 100644 --- a/test/oqs_test_endecode.c +++ b/test/oqs_test_endecode.c @@ -78,8 +78,7 @@ static EVP_PKEY *oqstest_make_key(const char *type, EVP_PKEY *template, static int encode_EVP_PKEY_prov(const EVP_PKEY *pkey, const char *format, const char *structure, const char *pass, - const int selection, void **encoded, - long *encoded_len) + const int selection, BUF_MEM **encoded) { OSSL_ENCODER_CTX *ectx; BIO *mem_ser = NULL; @@ -110,8 +109,9 @@ static int encode_EVP_PKEY_prov(const EVP_PKEY *pkey, const char *format, goto end; /* pkey was successfully encoded into the bio */ - *encoded = mem_buf->data; - *encoded_len = mem_buf->length; + *encoded = BUF_MEM_new(); + (*encoded)->data = mem_buf->data; + (*encoded)->length = mem_buf->length; /* Detach the encoded output */ mem_buf->data = NULL; @@ -159,9 +159,9 @@ static int decode_EVP_PKEY_prov(const char *input_type, const char *structure, pkey = NULL; end: - EVP_PKEY_free(pkey); BIO_free(encoded_bio); OSSL_DECODER_CTX_free(dctx); + EVP_PKEY_free(pkey); return ok; } @@ -169,40 +169,45 @@ static int test_oqs_encdec(const char *sigalg_name) { EVP_PKEY *pkey = NULL; EVP_PKEY *decoded_pkey = NULL; - void *encoded = NULL; - long encoded_len = 0; + BUF_MEM *encoded = NULL; size_t i; int ok = 0; for (i = 0; i < nelem(test_params_list); i++) { - pkey = oqstest_make_key(sigalg_name, NULL, NULL); if (pkey == NULL) goto end; - if (!encode_EVP_PKEY_prov( - pkey, test_params_list[i].format, test_params_list[i].structure, - test_params_list[i].pass, test_params_list[i].selection, - &encoded, &encoded_len)) { + if (!encode_EVP_PKEY_prov(pkey, test_params_list[i].format, + test_params_list[i].structure, + test_params_list[i].pass, + test_params_list[i].selection, &encoded)) { printf("Failed encoding %s", sigalg_name); goto end; } if (!decode_EVP_PKEY_prov( test_params_list[i].format, test_params_list[i].structure, test_params_list[i].pass, test_params_list[i].keytype, - test_params_list[i].selection, &decoded_pkey, encoded, - encoded_len)) { + test_params_list[i].selection, &decoded_pkey, encoded->data, + encoded->length)) { printf("Failed decoding %s", sigalg_name); goto end; } if (EVP_PKEY_eq(pkey, decoded_pkey) != 1) goto end; + EVP_PKEY_free(pkey); + pkey = NULL; + EVP_PKEY_free(decoded_pkey); + decoded_pkey = NULL; + BUF_MEM_free(encoded); + encoded = NULL; } ok = 1; end: EVP_PKEY_free(pkey); EVP_PKEY_free(decoded_pkey); + BUF_MEM_free(encoded); return ok; } @@ -252,11 +257,11 @@ int main(int argc, char *argv[]) errcnt++; } - OSSL_LIB_CTX_free(libctx); OSSL_PROVIDER_unload(dfltprov); OSSL_PROVIDER_unload(keyprov); if (OPENSSL_VERSION_PREREQ(3, 1)) OSSL_PROVIDER_unload(oqsprov); // avoid crash in 3.0.x + OSSL_LIB_CTX_free(libctx); OSSL_LIB_CTX_free(keyctx); TEST_ASSERT(errcnt == 0) diff --git a/test/oqs_test_kems.c b/test/oqs_test_kems.c index 28179e8c..4b734aa9 100644 --- a/test/oqs_test_kems.c +++ b/test/oqs_test_kems.c @@ -15,7 +15,9 @@ static int test_oqs_kems(const char *kemalg_name) EVP_MD_CTX *mdctx = NULL; EVP_PKEY_CTX *ctx = NULL; EVP_PKEY *key = NULL; - unsigned char *out, *secenc, *secdec; + unsigned char *out = NULL; + unsigned char *secenc = NULL; + unsigned char *secdec = NULL; size_t outlen, seclen; int testresult = 1; @@ -34,7 +36,7 @@ static int test_oqs_kems(const char *kemalg_name) if (!testresult) goto err; - OPENSSL_free(ctx); + EVP_PKEY_CTX_free(ctx); ctx = NULL; testresult @@ -64,7 +66,10 @@ static int test_oqs_kems(const char *kemalg_name) err: EVP_PKEY_free(key); - OPENSSL_free(ctx); + EVP_PKEY_CTX_free(ctx); + OPENSSL_free(out); + OPENSSL_free(secenc); + OPENSSL_free(secdec); return testresult; } diff --git a/test/oqs_test_signatures.c b/test/oqs_test_signatures.c index 5aaf4dba..b1137839 100644 --- a/test/oqs_test_signatures.c +++ b/test/oqs_test_signatures.c @@ -57,7 +57,7 @@ static int test_oqs_signatures(const char *sigalg_name) EVP_MD_CTX_free(mdctx); EVP_PKEY_free(key); - OPENSSL_free(ctx); + EVP_PKEY_CTX_free(ctx); OPENSSL_free(sig); mdctx = NULL; key = NULL; @@ -84,7 +84,7 @@ static int test_oqs_signatures(const char *sigalg_name) EVP_MD_CTX_free(mdctx); EVP_PKEY_free(key); - OPENSSL_free(ctx); + EVP_PKEY_CTX_free(ctx); OPENSSL_free(sig); return testresult; }