From 3790a0f8b40897fd99eae1575915d78d872e8bf5 Mon Sep 17 00:00:00 2001 From: Andrew Gaul Date: Mon, 7 Aug 2023 00:17:15 +0900 Subject: [PATCH] Calculate MD5 without using a temporary file (#2252) This mirrors the SHA256 code. --- src/curl_util.cpp | 30 ++++-------------------------- src/gnutls_auth.cpp | 24 ++++++++++++++++++++++++ src/nss_auth.cpp | 13 +++++++++++++ src/openssl_auth.cpp | 36 +++++++++++++++++++++++++++++++++--- src/s3fs_auth.h | 1 + 5 files changed, 75 insertions(+), 29 deletions(-) diff --git a/src/curl_util.cpp b/src/curl_util.cpp index 9f9ecfc..341c802 100644 --- a/src/curl_util.cpp +++ b/src/curl_util.cpp @@ -292,40 +292,18 @@ std::string prepare_url(const char* url) return url_str; } -// [TODO] -// This function uses temporary file, but should not use it. -// For not using it, we implement function in each auth file(openssl, nss. gnutls). -// bool make_md5_from_binary(const char* pstr, size_t length, std::string& md5) { if(!pstr || '\0' == pstr[0]){ S3FS_PRN_ERR("Parameter is wrong."); return false; } - FILE* fp; - if(nullptr == (fp = tmpfile())){ - S3FS_PRN_ERR("Could not make tmpfile."); + md5_t binary; + if(!s3fs_md5(reinterpret_cast(pstr), length, &binary)){ return false; } - if(length != fwrite(pstr, sizeof(char), length, fp)){ - S3FS_PRN_ERR("Failed to write tmpfile."); - fclose(fp); - return false; - } - int fd; - if(0 != fflush(fp) || 0 != fseek(fp, 0L, SEEK_SET) || -1 == (fd = fileno(fp))){ - S3FS_PRN_ERR("Failed to make MD5."); - fclose(fp); - return false; - } - // base64 md5 - md5 = s3fs_get_content_md5(fd); - if(md5.empty()){ - S3FS_PRN_ERR("Failed to make MD5."); - fclose(fp); - return false; - } - fclose(fp); + + md5 = s3fs_base64(binary.data(), binary.size()); return true; } diff --git a/src/gnutls_auth.cpp b/src/gnutls_auth.cpp index 3223488..5b5f8f1 100644 --- a/src/gnutls_auth.cpp +++ b/src/gnutls_auth.cpp @@ -184,6 +184,16 @@ bool s3fs_HMAC256(const void* key, size_t keylen, const unsigned char* data, siz // Utility Function for MD5 //------------------------------------------------------------------- #ifdef USE_GNUTLS_NETTLE +bool s3fs_md5(const unsigned char* data, size_t datalen, md5_t* result) +{ + struct md5_ctx ctx_md5; + md5_init(&ctx_md5); + md5_update(&ctx_md5, datalen, data); + md5_digest(&ctx_md5, result->size(), result->data()); + + return true; +} + bool s3fs_md5_fd(int fd, off_t start, off_t size, md5_t* result) { struct md5_ctx ctx_md5; @@ -221,6 +231,20 @@ bool s3fs_md5_fd(int fd, off_t start, off_t size, md5_t* result) #else // USE_GNUTLS_NETTLE +bool s3fs_md5(const unsigned char* data, size_t datalen, md5_t* digest) +{ + gcry_md_hd_t ctx_md5; + gcry_error_t err; + if(GPG_ERR_NO_ERROR != (err = gcry_md_open(&ctx_md5, GCRY_MD_MD5, 0))){ + S3FS_PRN_ERR("MD5 context creation failure: %s/%s", gcry_strsource(err), gcry_strerror(err)); + return false; + } + gcry_md_write(ctx_md5, digest->data(), digest->size()); + gcry_md_close(ctx_md5); + + return true; +} + bool s3fs_md5_fd(int fd, off_t start, off_t size, md5_t* result) { gcry_md_hd_t ctx_md5; diff --git a/src/nss_auth.cpp b/src/nss_auth.cpp index 13309ff..8f3c2b2 100644 --- a/src/nss_auth.cpp +++ b/src/nss_auth.cpp @@ -146,6 +146,19 @@ bool s3fs_HMAC256(const void* key, size_t keylen, const unsigned char* data, siz //------------------------------------------------------------------- // Utility Function for MD5 //------------------------------------------------------------------- +bool s3fs_md5(const unsigned char* data, size_t datalen, md5_t* result) +{ + PK11Context* md5ctx; + unsigned int md5outlen; + md5ctx = PK11_CreateDigestContext(SEC_OID_MD5); + + PK11_DigestOp(md5ctx, data, datalen); + PK11_DigestFinal(md5ctx, result->data(), &md5outlen, result->size()); + PK11_DestroyContext(md5ctx, PR_TRUE); + + return true; +} + bool s3fs_md5_fd(int fd, off_t start, off_t size, md5_t* result) { PK11Context* md5ctx; diff --git a/src/openssl_auth.cpp b/src/openssl_auth.cpp index 34acaa9..9bd9f87 100644 --- a/src/openssl_auth.cpp +++ b/src/openssl_auth.cpp @@ -256,10 +256,25 @@ bool s3fs_HMAC256(const void* key, size_t keylen, const unsigned char* data, siz // OpenSSL 3.0 deprecated the MD5_*** low-level encryption functions, // so we should use the high-level EVP API instead. // + +bool s3fs_md5(const unsigned char* data, size_t datalen, md5_t* digest) +{ + unsigned int digestlen = static_cast(digest->size()); + + const EVP_MD* md = EVP_get_digestbyname("md5"); + EVP_MD_CTX* mdctx = EVP_MD_CTX_create(); + EVP_DigestInit_ex(mdctx, md, nullptr); + EVP_DigestUpdate(mdctx, data, datalen); + EVP_DigestFinal_ex(mdctx, digest->data(), &digestlen); + EVP_MD_CTX_destroy(mdctx); + + return true; +} + bool s3fs_md5_fd(int fd, off_t start, off_t size, md5_t* result) { EVP_MD_CTX* mdctx; - unsigned int md5_digest_len = result->size(); + unsigned int md5_digest_len = static_cast(result->size()); off_t bytes; if(-1 == size){ @@ -303,6 +318,22 @@ bool s3fs_md5_fd(int fd, off_t start, off_t size, md5_t* result) //------------------------------------------------------------------- // Utility Function for MD5 (OpenSSL < 3.0) //------------------------------------------------------------------- + +// TODO: Does this fail on OpenSSL < 3.0 and we need to use MD5_CTX functions? +bool s3fs_md5(const unsigned char* data, size_t datalen, md5_t* digest) +{ + unsigned int digestlen = digest->size(); + + const EVP_MD* md = EVP_get_digestbyname("md5"); + EVP_MD_CTX* mdctx = EVP_MD_CTX_create(); + EVP_DigestInit_ex(mdctx, md, nullptr); + EVP_DigestUpdate(mdctx, data, datalen); + EVP_DigestFinal_ex(mdctx, digest->data(), &digestlen); + EVP_MD_CTX_destroy(mdctx); + + return true; +} + bool s3fs_md5_fd(int fd, off_t start, off_t size, md5_t* result) { MD5_CTX md5ctx; @@ -349,8 +380,7 @@ bool s3fs_sha256(const unsigned char* data, size_t datalen, sha256_t* digest) EVP_MD_CTX* mdctx = EVP_MD_CTX_create(); EVP_DigestInit_ex(mdctx, md, nullptr); EVP_DigestUpdate(mdctx, data, datalen); - // TODO: strange - unsigned int digestlen = digest->size(); + unsigned int digestlen = static_cast(digest->size()); EVP_DigestFinal_ex(mdctx, digest->data(), &digestlen); EVP_MD_CTX_destroy(mdctx); diff --git a/src/s3fs_auth.h b/src/s3fs_auth.h index 5fd7b82..2d412bd 100644 --- a/src/s3fs_auth.h +++ b/src/s3fs_auth.h @@ -47,6 +47,7 @@ bool s3fs_init_crypt_mutex(); bool s3fs_destroy_crypt_mutex(); bool s3fs_HMAC(const void* key, size_t keylen, const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen); bool s3fs_HMAC256(const void* key, size_t keylen, const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen); +bool s3fs_md5(const unsigned char* data, size_t datalen, md5_t* result); bool s3fs_md5_fd(int fd, off_t start, off_t size, md5_t* result); bool s3fs_sha256(const unsigned char* data, size_t datalen, sha256_t* digest); bool s3fs_sha256_fd(int fd, off_t start, off_t size, sha256_t* result);