Exemplo n.º 1
0
static void
on_feed_done_cb(void *data, struct sol_message_digest *md, struct sol_blob *input)
{
    struct update_get_hash_handle *handle = data;
    char buf[CHUNK_SIZE], *blob_backend = NULL;
    struct sol_blob *blob = NULL;
    size_t size;
    bool last;
    int r;

    size = fread(buf, 1, sizeof(buf), handle->file);
    if (ferror(handle->file)) {
        SOL_WRN("Could not read file for feed hash algorithm");
        goto err;
    }

    last = feof(handle->file);

    /* TODO Maybe this is a bug on sol_message_digest? Keeps calling on_feed_done
     * after send last chunk */
    if (!size && last && input) {
        SOL_WRN("Nothing more to feed hash algorithm, ignoring on_feed_done request");
        return;
    }

    blob_backend = malloc(size);
    SOL_NULL_CHECK_GOTO(blob_backend, err);

    blob = sol_blob_new(&SOL_BLOB_TYPE_DEFAULT, NULL, blob_backend, size);
    SOL_NULL_CHECK_GOTO(blob, err);

    memcpy(blob_backend, buf, size);

    r = sol_message_digest_feed(md, blob, last);
    SOL_INT_CHECK_GOTO(r, < 0, err);

    sol_blob_unref(blob);
    return;

err:
    SOL_WRN("Could not feed data to check update file hash");
    free(blob_backend);
    sol_blob_unref(blob);
    sol_message_digest_del(md);
    handle->cb((void *)handle->user_data, -EINVAL, NULL);
    delete_handle(handle);
}
Exemplo n.º 2
0
static void
on_digest_ready_cb(void *data, struct sol_message_digest *md, struct sol_blob *output)
{
    struct update_get_hash_handle *handle = data;
    struct sol_buffer buffer = SOL_BUFFER_INIT_EMPTY;
    struct sol_str_slice slice = sol_str_slice_from_blob(output);
    int r = 0;

    r = sol_buffer_append_as_base16(&buffer, slice, false);
    SOL_INT_CHECK_GOTO(r, < 0, end);

end:
    handle->cb((void *)handle->user_data, r, (char *)buffer.data);
    sol_message_digest_del(md);
    sol_buffer_fini(&buffer);
    delete_handle(handle);
}
Exemplo n.º 3
0
static void
on_digest_ready(void *data, struct sol_message_digest *handle, struct sol_blob *digest)
{
    struct feed_ctx *ctx = data;
    struct sol_buffer buf;
    int r;

    sol_buffer_init(&buf);
    r = sol_buffer_append_as_base16(&buf, sol_str_slice_from_blob(digest), false);
    if (r == 0) {
        printf("%s\t%s\n", (char *)buf.data, ctx->file);
    }

    sol_buffer_fini(&buf);

    print_time(ctx, ctx->done, "final");

    sol_message_digest_del(handle);
    free(ctx);

    pending--;
    if (pending == 0)
        sol_quit();
}
SOL_API struct sol_message_digest *
sol_message_digest_new(const struct sol_message_digest_config *config)
{
    int (*init_fn)(struct sol_message_digest *, const EVP_MD *, const struct sol_str_slice);
    struct sol_message_digest_common_new_params params;
    const EVP_MD *md;
    struct sol_message_digest *handle;
    int errno_bkp;

    errno = EINVAL;
    SOL_NULL_CHECK(config, NULL);
    SOL_NULL_CHECK(config->on_digest_ready, NULL);
    SOL_NULL_CHECK(config->algorithm, NULL);

#ifndef SOL_NO_API_VERSION
    if (config->api_version != SOL_MESSAGE_DIGEST_CONFIG_API_VERSION) {
        SOL_WRN("sol_message_digest_config->api_version=%" PRIu16 ", "
            "expected version is %" PRIu16 ".",
            config->api_version, SOL_MESSAGE_DIGEST_CONFIG_API_VERSION);
        return NULL;
    }
#endif

    if (!did_openssl_load_digests) {
        OpenSSL_add_all_digests();
        did_openssl_load_digests = true;
    }

    params.config = config;
    params.ops = NULL;

    md = EVP_get_digestbyname(config->algorithm);
    if (md) {
        params.context_handle = EVP_MD_CTX_new();
        params.context_free = (void (*)(void *))EVP_MD_CTX_free;
        init_fn = _sol_message_digest_evp_init;
        params.ops = &_sol_message_digest_evp_ops;
        SOL_DBG("using evp, md=%p, algorithm=\"%s\"", md, config->algorithm);
    } else if (streqn(config->algorithm, "hmac(", strlen("hmac("))) {
        const char *p = config->algorithm + strlen("hmac(");
        size_t len = strlen(p);
        params.context_handle = HMAC_CTX_new();
        params.context_free = (void (*)(void *))HMAC_CTX_free;
        if (len > 1 && p[len - 1] == ')') {
            char *mdname = strndupa(p, len - 1);
            md = EVP_get_digestbyname(mdname);
            if (!md) {
                SOL_WRN("failed to get digest algorithm \"%s\" for \"%s\".",
                    mdname, config->algorithm);
                return NULL;
            }
            init_fn = _sol_message_digest_hmac_init;
            params.ops = &_sol_message_digest_hmac_ops;
            SOL_DBG("using hmac, md=%p, algorithm=\"%s\"", md, mdname);
        }
    }

    if (!params.ops) {
        SOL_WRN("failed to get digest algorithm \"%s\".", config->algorithm);
        return NULL;
    }

    params.digest_size = EVP_MD_size(md);

    handle = sol_message_digest_common_new(params);
    SOL_NULL_CHECK(handle, NULL);

    errno = init_fn(handle, md, config->key);
    if (errno)
        goto error;

    return handle;

error:
    errno_bkp = errno;
    sol_message_digest_del(handle);
    errno = errno_bkp;
    return NULL;
}
Exemplo n.º 5
0
static void
startup(void)
{
    const char *algorithm = "sha256";
    const char *key = NULL;
    char **argv = sol_argv();
    int i, argc = sol_argc();
    size_t chunk_size = -1;

    if (argc < 2) {
        fprintf(stderr,
            "Usage:\n\t%s [-a <algorithm>] [-c chunk_size] [-k key] <file1> .. <fileN>\n", argv[0]);
        sol_quit_with_code(EXIT_FAILURE);
        return;
    }

    for (i = 1; i < argc; i++) {
        struct feed_ctx *ctx;
        struct sol_message_digest_config cfg = {
            SOL_SET_API_VERSION(.api_version = SOL_MESSAGE_DIGEST_CONFIG_API_VERSION, )
            .algorithm = algorithm,
            .on_feed_done = on_feed_done,
            .on_digest_ready = on_digest_ready,
        };
        struct sol_file_reader *fr;
        struct sol_blob *blob;
        struct sol_message_digest *mdh;
        int r;

        if (argv[i][0] == '-') {
            if (argv[i][1] == 'a') {
                if (i + 1 < argc) {
                    algorithm = argv[i + 1];
                    i++;
                    continue;
                } else
                    fputs("ERROR: argument -a missing value.\n", stderr);
            } else if (argv[i][1] == 'k') {
                if (i + 1 < argc) {
                    key = argv[i + 1];
                    i++;
                    continue;
                } else
                    fputs("ERROR: argument -a missing value.\n", stderr);
            } else if (argv[i][1] == 'c') {
                if (i + 1 < argc) {
                    chunk_size = atoi(argv[i + 1]);
                    i++;
                    continue;
                } else
                    fputs("ERROR: argument -c missing value.\n", stderr);
            } else
                fprintf(stderr, "ERROR: unknown option %s\n", argv[i]);
            sol_quit_with_code(EXIT_FAILURE);
            return;
        }

        fr = sol_file_reader_open(argv[i]);
        if (!fr) {
            fprintf(stderr, "ERROR: could not open file '%s': %s\n",
                argv[i], sol_util_strerrora(errno));
            continue;
        }

        blob = sol_file_reader_to_blob(fr);
        if (!blob) {
            fprintf(stderr, "ERROR: could not create blob for file '%s'\n",
                argv[i]);
            continue;
        }

        cfg.data = ctx = calloc(1, sizeof(struct feed_ctx));
        if (!ctx) {
            fprintf(stderr, "ERROR: could not allocate context memory "
                "to process file '%s'\n", argv[i]);
            sol_blob_unref(blob);
            continue;
        }

        ctx->file = argv[i];
        ctx->start = sol_util_timespec_get_current();
        ctx->done = 0;
        ctx->chunk_size = chunk_size;


        if (key)
            cfg.key = sol_str_slice_from_str(key);

        mdh = sol_message_digest_new(&cfg);
        if (!mdh) {
            fprintf(stderr, "ERROR: could not create message digest for "
                " algorithm \"%s\": %s\n",
                algorithm, sol_util_strerrora(errno));
            sol_blob_unref(blob);
            free(ctx);
            continue;
        }

        if (chunk_size <= 0) {
            r = sol_message_digest_feed(mdh, blob, true);
            if (r < 0) {
                fprintf(stderr, "ERROR: could not feed message for "
                    " algorithm \"%s\": %s\n",
                    algorithm, sol_util_strerrora(-r));
                sol_blob_unref(blob);
                sol_message_digest_del(mdh);
                free(ctx);
                continue;
            }
        } else {
            size_t offset = 0;
            while (offset < blob->size) {
                size_t remaining = blob->size - offset;
                size_t clen = remaining > chunk_size ? chunk_size : remaining;
                uint8_t *cmem = (uint8_t *)blob->mem + offset;
                bool is_last = offset + clen == blob->size;
                struct sol_blob *chunk = sol_blob_new(&SOL_BLOB_TYPE_NO_FREE_DATA,
                    blob, cmem, clen);
                if (!chunk) {
                    fprintf(stderr, "ERROR: could not create chunk blob at "
                        "mem %p, size=%zd\n", cmem, clen);
                    sol_blob_unref(blob);
                    sol_message_digest_del(mdh);
                    free(ctx);
                    continue;
                }

                r = sol_message_digest_feed(mdh, chunk, is_last);
                if (r < 0) {
                    fprintf(stderr, "ERROR: could not feed chunk for "
                        " algorithm \"%s\": %s\n",
                        algorithm, sol_util_strerrora(-r));
                    sol_blob_unref(blob);
                    sol_blob_unref(chunk);
                    sol_message_digest_del(mdh);
                    free(ctx);
                    continue;
                }

                sol_blob_unref(chunk);
                offset += clen;
            }
        }

        sol_blob_unref(blob);
        pending++;
    }