Skip to content
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

lib: Add a lighter weight internal checksum wrapper #1256

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/libostree/ostree-core-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#pragma once

#include "ostree-core.h"
#include "otutil.h"
#include <sys/stat.h>

G_BEGIN_DECLS
Expand Down Expand Up @@ -77,7 +78,7 @@ gboolean _ostree_write_variant_with_size (GOutputStream *output,
GVariant *variant,
guint64 alignment_offset,
gsize *out_bytes_written,
GChecksum *checksum,
OtChecksum *checksum,
GCancellable *cancellable,
GError **error);

Expand Down
22 changes: 12 additions & 10 deletions src/libostree/ostree-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ write_padding (GOutputStream *output,
guint alignment,
gsize offset,
gsize *out_bytes_written,
GChecksum *checksum,
OtChecksum *checksum,
GCancellable *cancellable,
GError **error)
{
Expand Down Expand Up @@ -403,7 +403,7 @@ _ostree_write_variant_with_size (GOutputStream *output,
GVariant *variant,
guint64 alignment_offset,
gsize *out_bytes_written,
GChecksum *checksum,
OtChecksum *checksum,
GCancellable *cancellable,
GError **error)
{
Expand Down Expand Up @@ -458,7 +458,7 @@ _ostree_write_variant_with_size (GOutputStream *output,
static gboolean
write_file_header_update_checksum (GOutputStream *out,
GVariant *header,
GChecksum *checksum,
OtChecksum *checksum,
GCancellable *cancellable,
GError **error)
{
Expand Down Expand Up @@ -859,37 +859,39 @@ ostree_checksum_file_from_input (GFileInfo *file_info,
GError **error)
{

g_autoptr(GChecksum) checksum = g_checksum_new (G_CHECKSUM_SHA256);
g_auto(OtChecksum) checksum = { 0, };
ot_checksum_init (&checksum);

if (OSTREE_OBJECT_TYPE_IS_META (objtype))
{
if (!ot_gio_splice_update_checksum (NULL, in, checksum, cancellable, error))
if (!ot_gio_splice_update_checksum (NULL, in, &checksum, cancellable, error))
return FALSE;
}
else if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
{
g_autoptr(GVariant) dirmeta = ostree_create_directory_metadata (file_info, xattrs);
g_checksum_update (checksum, g_variant_get_data (dirmeta),
g_variant_get_size (dirmeta));
ot_checksum_update (&checksum, g_variant_get_data (dirmeta),
g_variant_get_size (dirmeta));
}
else
{
g_autoptr(GVariant) file_header = NULL;

file_header = _ostree_file_header_new (file_info, xattrs);

if (!write_file_header_update_checksum (NULL, file_header, checksum,
if (!write_file_header_update_checksum (NULL, file_header, &checksum,
cancellable, error))
return FALSE;

if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
{
if (!ot_gio_splice_update_checksum (NULL, in, checksum, cancellable, error))
if (!ot_gio_splice_update_checksum (NULL, in, &checksum, cancellable, error))
return FALSE;
}
}

*out_csum = ot_csum_from_gchecksum (checksum);
*out_csum = g_malloc (OSTREE_SHA256_DIGEST_LEN);
ot_checksum_get_digest (&checksum, *out_csum, OSTREE_SHA256_DIGEST_LEN);
return TRUE;
}

Expand Down
11 changes: 8 additions & 3 deletions src/libostree/ostree-repo-commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -811,14 +811,19 @@ write_metadata_object (OstreeRepo *self,
* *original* sha256 to say what commit was being killed.
*/
const gboolean is_tombstone = (objtype == OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT);
g_autofree char *actual_checksum = NULL;
char actual_checksum[OSTREE_SHA256_STRING_LEN+1];
if (is_tombstone)
{
actual_checksum = g_strdup (expected_checksum);
memcpy (actual_checksum, expected_checksum, sizeof (actual_checksum));
}
else
{
actual_checksum = g_compute_checksum_for_bytes (G_CHECKSUM_SHA256, buf);
OtChecksum checksum = { 0, };
ot_checksum_init (&checksum);
gsize len;
const guint8*bufdata = g_bytes_get_data (buf, &len);
ot_checksum_update (&checksum, bufdata, len);
ot_checksum_get_hexdigest (&checksum, actual_checksum, sizeof (actual_checksum));
gboolean have_obj;
if (!_ostree_repo_has_loose_object (self, actual_checksum, objtype, &have_obj,
cancellable, error))
Expand Down
19 changes: 10 additions & 9 deletions src/libostree/ostree-repo-static-delta-processing.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ typedef struct {
GLnxTmpfile tmpf;
guint64 content_size;
GOutputStream *content_out;
GChecksum *content_checksum;
OtChecksum content_checksum;
char checksum[OSTREE_SHA256_STRING_LEN+1];
char *read_source_object;
int read_source_fd;
Expand Down Expand Up @@ -277,7 +277,7 @@ _ostree_static_delta_part_execute (OstreeRepo *repo,
out:
glnx_tmpfile_clear (&state->tmpf);
g_clear_object (&state->content_out);
g_clear_pointer (&state->content_checksum, g_checksum_free);
ot_checksum_clear (&state->content_checksum);
return ret;
}

Expand Down Expand Up @@ -385,8 +385,8 @@ content_out_write (OstreeRepo *repo,
{
gsize bytes_written;

if (state->content_checksum)
g_checksum_update (state->content_checksum, buf, len);
if (state->content_checksum.initialized)
ot_checksum_update (&state->content_checksum, buf, len);

/* Ignore bytes_written since we discard partial content */
if (!g_output_stream_write_all (state->content_out,
Expand Down Expand Up @@ -503,10 +503,10 @@ handle_untrusted_content_checksum (OstreeRepo *repo,
g_autoptr(GFileInfo) finfo = _ostree_mode_uidgid_to_gfileinfo (state->mode, state->uid, state->gid);
g_autoptr(GVariant) header = _ostree_file_header_new (finfo, state->xattrs);

state->content_checksum = g_checksum_new (G_CHECKSUM_SHA256);
ot_checksum_init (&state->content_checksum);

gsize bytes_written;
if (!_ostree_write_variant_with_size (NULL, header, 0, &bytes_written, state->content_checksum,
if (!_ostree_write_variant_with_size (NULL, header, 0, &bytes_written, &state->content_checksum,
cancellable, error))
return FALSE;

Expand Down Expand Up @@ -827,9 +827,10 @@ dispatch_close (OstreeRepo *repo,
if (!g_output_stream_flush (state->content_out, cancellable, error))
return FALSE;

if (state->content_checksum)
if (state->content_checksum.initialized)
{
const char *actual_checksum = g_checksum_get_string (state->content_checksum);
char actual_checksum[OSTREE_SHA256_STRING_LEN+1];
ot_checksum_get_hexdigest (&state->content_checksum, actual_checksum, sizeof (actual_checksum));

if (strcmp (actual_checksum, state->checksum) != 0)
return glnx_throw (error, "Corrupted object %s (actual checksum is %s)",
Expand All @@ -848,7 +849,7 @@ dispatch_close (OstreeRepo *repo,
return FALSE;

g_clear_pointer (&state->xattrs, g_variant_unref);
g_clear_pointer (&state->content_checksum, g_checksum_free);
ot_checksum_clear (&state->content_checksum);

state->checksum_index++;
state->output_target = NULL;
Expand Down
11 changes: 7 additions & 4 deletions src/libostree/ostree-sysroot-deploy.c
Original file line number Diff line number Diff line change
Expand Up @@ -989,13 +989,14 @@ get_kernel_from_tree_usrlib_modules (int deployment_dfd,
}

/* We found a module directory, compute the checksum */
g_autoptr(GChecksum) checksum = g_checksum_new (G_CHECKSUM_SHA256);
g_auto(OtChecksum) checksum = { 0, };
ot_checksum_init (&checksum);
glnx_fd_close int fd = -1;
/* Checksum the kernel */
if (!glnx_openat_rdonly (ret_layout->boot_dfd, "vmlinuz", TRUE, &fd, error))
return FALSE;
g_autoptr(GInputStream) in = g_unix_input_stream_new (fd, FALSE);
if (!ot_gio_splice_update_checksum (NULL, in, checksum, cancellable, error))
if (!ot_gio_splice_update_checksum (NULL, in, &checksum, cancellable, error))
return FALSE;
g_clear_object (&in);
(void) close (fd); fd = -1;
Expand All @@ -1022,11 +1023,13 @@ get_kernel_from_tree_usrlib_modules (int deployment_dfd,
ret_layout->initramfs_srcpath = g_strdup (initramfs_path);
ret_layout->initramfs_namever = g_strdup_printf ("initramfs-%s.img", kver);
in = g_unix_input_stream_new (fd, FALSE);
if (!ot_gio_splice_update_checksum (NULL, in, checksum, cancellable, error))
if (!ot_gio_splice_update_checksum (NULL, in, &checksum, cancellable, error))
return FALSE;
}

ret_layout->bootcsum = g_strdup (g_checksum_get_string (checksum));
char hexdigest[OSTREE_SHA256_STRING_LEN+1];
ot_checksum_get_hexdigest (&checksum, hexdigest, sizeof (hexdigest));
ret_layout->bootcsum = g_strdup (hexdigest);

*out_layout = g_steal_pointer (&ret_layout);
return TRUE;
Expand Down
136 changes: 7 additions & 129 deletions src/libotutil/ot-checksum-instream.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,10 @@
#include "ot-checksum-instream.h"
#include "ot-checksum-utils.h"

#if defined(HAVE_OPENSSL)
#include <openssl/evp.h>
#elif defined(HAVE_GNUTLS)
#include <gnutls/gnutls.h>
#include <gnutls/crypto.h>
#endif

G_DEFINE_TYPE (OtChecksumInstream, ot_checksum_instream, G_TYPE_FILTER_INPUT_STREAM)

struct _OtChecksumInstreamPrivate {
#if defined(HAVE_OPENSSL)
EVP_MD_CTX *checksum;
#elif defined(HAVE_GNUTLS)
gnutls_digest_algorithm_t checksum_type;
gnutls_hash_hd_t checksum;
#else
GChecksumType checksum_type;
GChecksum *checksum;
#endif
OtChecksum checksum;
};

static gssize ot_checksum_instream_read (GInputStream *stream,
Expand All @@ -54,13 +39,7 @@ ot_checksum_instream_finalize (GObject *object)
{
OtChecksumInstream *self = (OtChecksumInstream*)object;

#if defined(HAVE_OPENSSL)
EVP_MD_CTX_destroy (self->priv->checksum);
#elif defined(HAVE_GNUTLS)
gnutls_hash_deinit (self->priv->checksum, NULL);
#else
g_checksum_free (self->priv->checksum);
#endif
ot_checksum_clear (&self->priv->checksum);

G_OBJECT_CLASS (ot_checksum_instream_parent_class)->finalize (object);
}
Expand All @@ -83,33 +62,6 @@ ot_checksum_instream_init (OtChecksumInstream *self)
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, OT_TYPE_CHECKSUM_INSTREAM, OtChecksumInstreamPrivate);
}

#if defined(HAVE_OPENSSL)
static const EVP_MD *
gchecksum_type_to_openssl (GChecksumType checksum_type)
{
switch (checksum_type)
{
case G_CHECKSUM_SHA256:
return EVP_sha256 ();
default:
/* If there's something else, fill in here */
g_assert_not_reached ();
}
}
#elif defined(HAVE_GNUTLS)
static gnutls_digest_algorithm_t
gchecksum_type_to_gnutls (GChecksumType checksum_type)
{
switch (checksum_type)
{
case G_CHECKSUM_SHA256:
return GNUTLS_DIG_SHA256;
default:
g_assert_not_reached ();
}
}
#endif

OtChecksumInstream *
ot_checksum_instream_new (GInputStream *base,
GChecksumType checksum_type)
Expand All @@ -124,18 +76,7 @@ ot_checksum_instream_new (GInputStream *base,

/* For now */
g_assert (checksum_type == G_CHECKSUM_SHA256);

#if defined(HAVE_OPENSSL)
stream->priv->checksum = EVP_MD_CTX_create ();
g_assert (stream->priv->checksum);
g_assert (EVP_DigestInit_ex (stream->priv->checksum, gchecksum_type_to_openssl (checksum_type), NULL));
#elif defined(HAVE_GNUTLS)
stream->priv->checksum_type = gchecksum_type_to_gnutls (checksum_type);
g_assert (!gnutls_hash_init (&stream->priv->checksum, stream->priv->checksum_type));
#else
stream->priv->checksum = g_checksum_new (checksum_type);
stream->priv->checksum_type = checksum_type;
#endif
ot_checksum_init (&stream->priv->checksum);

return (OtChecksumInstream*) (stream);
}
Expand All @@ -157,78 +98,15 @@ ot_checksum_instream_read (GInputStream *stream,
cancellable,
error);
if (res > 0)
{
#if defined(HAVE_OPENSSL)
g_assert (EVP_DigestUpdate (self->priv->checksum, buffer, res));
#elif defined(HAVE_GNUTLS)
g_assert (!gnutls_hash (self->priv->checksum, buffer, res));
#else
g_checksum_update (self->priv->checksum, buffer, res);
#endif
}
ot_checksum_update (&self->priv->checksum, buffer, res);

return res;
}

void
ot_checksum_instream_get_digest (OtChecksumInstream *stream,
guint8 *buffer,
gsize *digest_len)
{
#if defined(HAVE_OPENSSL)
unsigned len;
EVP_DigestFinal_ex (stream->priv->checksum, buffer, &len);
if (digest_len)
*digest_len = len;
#elif defined(HAVE_GNUTLS)
gnutls_hash_output (stream->priv->checksum, buffer);
if (digest_len)
*digest_len = gnutls_hash_get_len (stream->priv->checksum_type);
#else
g_checksum_get_digest (stream->priv->checksum, buffer, digest_len);
#endif
}

guint8*
ot_checksum_instream_dup_digest (OtChecksumInstream *stream,
gsize *ret_len)
{
#if defined(HAVE_OPENSSL)
guint len;
guchar *ret = g_malloc0 (EVP_MAX_MD_SIZE);
g_assert (EVP_DigestFinal_ex (stream->priv->checksum, ret, &len));
#elif defined(HAVE_GNUTLS)
guint len = gnutls_hash_get_len (stream->priv->checksum_type);
guchar *ret = g_malloc0 (len);
gnutls_hash_output (stream->priv->checksum, ret);
#else
gsize len = g_checksum_type_get_length (stream->priv->checksum_type);
guchar *ret = g_malloc (len);
g_checksum_get_digest (stream->priv->checksum, ret, &len);
#endif
if (ret_len)
*ret_len = len;
return ret;
}

char *
ot_checksum_instream_get_string (OtChecksumInstream *stream)
{
#if defined(HAVE_OPENSSL)
unsigned len;
guint8 csum[EVP_MAX_MD_SIZE];
g_assert (EVP_DigestFinal_ex (stream->priv->checksum, csum, &len));
char *buf = g_malloc (len * 2 + 1);
ot_bin2hex (buf, (guint8*)csum, len);
return buf;
#elif defined(HAVE_GNUTLS)
gsize len;
guint8 *csum = ot_checksum_instream_dup_digest(stream, &len);
char *buf = g_malloc0 (len * 2 + 1);
ot_bin2hex (buf, csum, len);
g_free (csum);
return buf;
#else
return g_strdup (g_checksum_get_string (stream->priv->checksum));
#endif
char buf[_OSTREE_SHA256_STRING_LEN+1];
ot_checksum_get_hexdigest (&stream->priv->checksum, buf, sizeof(buf));
return g_strndup (buf, sizeof(buf));
}
Loading