Calculate MD5 without using a temporary file (#2252)

This mirrors the SHA256 code.
This commit is contained in:
Andrew Gaul 2023-08-07 00:17:15 +09:00 committed by GitHub
parent 779afe5d62
commit 3790a0f8b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 75 additions and 29 deletions

View File

@ -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<const unsigned char*>(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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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<unsigned int>(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<unsigned int>(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<unsigned int>(digest->size());
EVP_DigestFinal_ex(mdctx, digest->data(), &digestlen);
EVP_MD_CTX_destroy(mdctx);

View File

@ -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);