digest: use oneshot context flag where approriate
speeds up digest calculation on some cases.cute-signatures
parent
0942832325
commit
e30834fdcb
11
src/apk_io.h
11
src/apk_io.h
|
@ -35,7 +35,10 @@ struct apk_istream {
|
|||
void (*close)(void *stream);
|
||||
};
|
||||
|
||||
#define APK_BSTREAM_SINGLE_READ 0x0001
|
||||
|
||||
struct apk_bstream {
|
||||
unsigned int flags;
|
||||
apk_blob_t (*read)(void *stream, apk_blob_t token);
|
||||
void (*close)(void *stream, size_t *size);
|
||||
};
|
||||
|
@ -45,11 +48,11 @@ struct apk_ostream {
|
|||
void (*close)(void *stream);
|
||||
};
|
||||
|
||||
#define APK_MPART_BEGIN 0
|
||||
#define APK_MPART_BOUNDARY 1
|
||||
#define APK_MPART_END 2
|
||||
#define APK_MPART_DATA 1 /* data processed so far */
|
||||
#define APK_MPART_BOUNDARY 2 /* final part of data, before boundary */
|
||||
#define APK_MPART_END 3 /* signals end of stream */
|
||||
|
||||
typedef int (*apk_multipart_cb)(void *ctx, EVP_MD_CTX *mdctx, int part);
|
||||
typedef int (*apk_multipart_cb)(void *ctx, int part, apk_blob_t data);
|
||||
|
||||
struct apk_istream *apk_bstream_gunzip_mpart(struct apk_bstream *,
|
||||
apk_multipart_cb cb, void *ctx);
|
||||
|
|
|
@ -45,6 +45,7 @@ struct apk_sign_ctx {
|
|||
int data_verified : 1;
|
||||
char data_checksum[EVP_MAX_MD_SIZE];
|
||||
struct apk_checksum identity;
|
||||
EVP_MD_CTX mdctx;
|
||||
|
||||
struct {
|
||||
apk_blob_t data;
|
||||
|
@ -97,7 +98,7 @@ void apk_sign_ctx_free(struct apk_sign_ctx *ctx);
|
|||
int apk_sign_ctx_process_file(struct apk_sign_ctx *ctx,
|
||||
const struct apk_file_info *fi,
|
||||
struct apk_istream *is);
|
||||
int apk_sign_ctx_mpart_cb(void *ctx, EVP_MD_CTX *mdctx, int part);
|
||||
int apk_sign_ctx_mpart_cb(void *ctx, int part, apk_blob_t blob);
|
||||
|
||||
int apk_deps_add(struct apk_dependency_array **depends,
|
||||
struct apk_dependency *dep);
|
||||
|
|
|
@ -1332,22 +1332,6 @@ static void apk_db_purge_pkg(struct apk_database *db,
|
|||
apk_pkg_set_state(db, pkg, APK_PKG_NOT_INSTALLED);
|
||||
}
|
||||
|
||||
static int apk_db_gzip_part(void *pctx, EVP_MD_CTX *mdctx, int part)
|
||||
{
|
||||
struct install_ctx *ctx = (struct install_ctx *) pctx;
|
||||
|
||||
switch (part) {
|
||||
case APK_MPART_BEGIN:
|
||||
EVP_DigestInit_ex(mdctx, EVP_md5(), NULL);
|
||||
break;
|
||||
case APK_MPART_END:
|
||||
ctx->data_csum.type = EVP_MD_CTX_size(mdctx);
|
||||
EVP_DigestFinal_ex(mdctx, ctx->data_csum.data, NULL);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apk_db_unpack_pkg(struct apk_database *db,
|
||||
struct apk_package *newpkg,
|
||||
int upgrade, apk_progress_cb cb, void *cb_ctx)
|
||||
|
@ -1355,6 +1339,7 @@ static int apk_db_unpack_pkg(struct apk_database *db,
|
|||
struct install_ctx ctx;
|
||||
struct apk_bstream *bs = NULL;
|
||||
struct apk_istream *tar;
|
||||
struct apk_sign_ctx sctx;
|
||||
char pkgname[256], file[256];
|
||||
int i, need_copy = FALSE;
|
||||
|
||||
|
@ -1411,8 +1396,9 @@ static int apk_db_unpack_pkg(struct apk_database *db,
|
|||
.cb = cb,
|
||||
.cb_ctx = cb_ctx,
|
||||
};
|
||||
|
||||
tar = apk_bstream_gunzip_mpart(bs, apk_db_gzip_part, &ctx);
|
||||
apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY);
|
||||
tar = apk_bstream_gunzip_mpart(bs, apk_sign_ctx_mpart_cb, &sctx);
|
||||
apk_sign_ctx_free(&sctx);
|
||||
if (apk_tar_parse(tar, apk_db_install_archive_entry, &ctx) != 0)
|
||||
goto err_close;
|
||||
tar->close(tar);
|
||||
|
|
44
src/gunzip.c
44
src/gunzip.c
|
@ -23,17 +23,16 @@ struct apk_gzip_istream {
|
|||
z_stream zs;
|
||||
int z_err;
|
||||
|
||||
EVP_MD_CTX mdctx;
|
||||
void *mdblock;
|
||||
|
||||
apk_multipart_cb cb;
|
||||
void *cbctx;
|
||||
void *cbprev;
|
||||
};
|
||||
|
||||
static size_t gzi_read(void *stream, void *ptr, size_t size)
|
||||
{
|
||||
struct apk_gzip_istream *gis =
|
||||
container_of(stream, struct apk_gzip_istream, is);
|
||||
int r;
|
||||
|
||||
if (gis->z_err == Z_DATA_ERROR || gis->z_err == Z_ERRNO)
|
||||
return -1;
|
||||
|
@ -50,22 +49,22 @@ static size_t gzi_read(void *stream, void *ptr, size_t size)
|
|||
if (gis->zs.avail_in == 0) {
|
||||
apk_blob_t blob;
|
||||
|
||||
if (gis->cb != NULL && gis->mdblock != NULL) {
|
||||
/* Digest the inflated bytes */
|
||||
EVP_DigestUpdate(&gis->mdctx, gis->mdblock,
|
||||
(void *)gis->zs.next_in - gis->mdblock);
|
||||
if (gis->cb != NULL && gis->cbprev != NULL) {
|
||||
gis->cb(gis->cbctx, APK_MPART_DATA,
|
||||
APK_BLOB_PTR_LEN(gis->cbprev,
|
||||
(void *)gis->zs.next_in - gis->cbprev));
|
||||
}
|
||||
blob = gis->bs->read(gis->bs, APK_BLOB_NULL);
|
||||
gis->mdblock = blob.ptr;
|
||||
gis->cbprev = blob.ptr;
|
||||
gis->zs.avail_in = blob.len;
|
||||
gis->zs.next_in = (void *) gis->mdblock;
|
||||
gis->zs.next_in = (void *) gis->cbprev;
|
||||
if (gis->zs.avail_in < 0) {
|
||||
gis->z_err = Z_DATA_ERROR;
|
||||
return size - gis->zs.avail_out;
|
||||
} else if (gis->zs.avail_in == 0) {
|
||||
if (gis->cb != NULL)
|
||||
gis->cb(gis->cbctx, &gis->mdctx,
|
||||
APK_MPART_END);
|
||||
gis->cb(gis->cbctx, APK_MPART_END,
|
||||
APK_BLOB_NULL);
|
||||
gis->z_err = Z_STREAM_END;
|
||||
return size - gis->zs.avail_out;
|
||||
}
|
||||
|
@ -75,14 +74,16 @@ static size_t gzi_read(void *stream, void *ptr, size_t size)
|
|||
if (gis->z_err == Z_STREAM_END) {
|
||||
/* Digest the inflated bytes */
|
||||
if (gis->cb != NULL) {
|
||||
EVP_DigestUpdate(&gis->mdctx, gis->mdblock,
|
||||
(void *)gis->zs.next_in - gis->mdblock);
|
||||
gis->mdblock = gis->zs.next_in;
|
||||
if (gis->cb(gis->cbctx, &gis->mdctx,
|
||||
APK_MPART_BOUNDARY)) {
|
||||
gis->z_err = Z_STREAM_END;
|
||||
break;
|
||||
r = gis->cb(gis->cbctx, APK_MPART_BOUNDARY,
|
||||
APK_BLOB_PTR_LEN(gis->cbprev,
|
||||
(void *)gis->zs.next_in - gis->cbprev));
|
||||
if (r != 0) {
|
||||
gis->z_err = Z_DATA_ERROR;
|
||||
if (r > 0)
|
||||
r = -1;
|
||||
return r;
|
||||
}
|
||||
gis->cbprev = gis->zs.next_in;
|
||||
}
|
||||
inflateEnd(&gis->zs);
|
||||
if (inflateInit2(&gis->zs, 15+32) != Z_OK)
|
||||
|
@ -102,8 +103,6 @@ static void gzi_close(void *stream)
|
|||
struct apk_gzip_istream *gis =
|
||||
container_of(stream, struct apk_gzip_istream, is);
|
||||
|
||||
if (gis->cb != NULL)
|
||||
EVP_MD_CTX_cleanup(&gis->mdctx);
|
||||
inflateEnd(&gis->zs);
|
||||
gis->bs->close(gis->bs, NULL);
|
||||
free(gis);
|
||||
|
@ -135,11 +134,6 @@ struct apk_istream *apk_bstream_gunzip_mpart(struct apk_bstream *bs,
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (gis->cb != NULL) {
|
||||
EVP_MD_CTX_init(&gis->mdctx);
|
||||
cb(ctx, &gis->mdctx, APK_MPART_BEGIN);
|
||||
}
|
||||
|
||||
return &gis->is;
|
||||
err:
|
||||
bs->close(bs, NULL);
|
||||
|
|
3
src/io.c
3
src/io.c
|
@ -295,6 +295,7 @@ static struct apk_bstream *apk_mmap_bstream_from_fd(int fd)
|
|||
}
|
||||
|
||||
mbs->bs = (struct apk_bstream) {
|
||||
.flags = APK_BSTREAM_SINGLE_READ,
|
||||
.read = mmap_read,
|
||||
.close = mmap_close,
|
||||
};
|
||||
|
@ -466,6 +467,8 @@ int apk_file_get_info(const char *filename, int checksum, struct apk_file_info *
|
|||
apk_blob_t blob;
|
||||
|
||||
EVP_DigestInit(&mdctx, apk_get_digest(checksum));
|
||||
if (bs->flags & APK_BSTREAM_SINGLE_READ)
|
||||
EVP_MD_CTX_set_flags(&mdctx, EVP_MD_CTX_FLAG_ONESHOT);
|
||||
while (!APK_BLOB_IS_NULL(blob = bs->read(bs, APK_BLOB_NULL)))
|
||||
EVP_DigestUpdate(&mdctx, (void*) blob.ptr, blob.len);
|
||||
fi->csum.type = EVP_MD_CTX_size(&mdctx);
|
||||
|
|
|
@ -275,6 +275,9 @@ void apk_sign_ctx_init(struct apk_sign_ctx *ctx, int action)
|
|||
ctx->md = EVP_sha1();
|
||||
break;
|
||||
}
|
||||
EVP_MD_CTX_init(&ctx->mdctx);
|
||||
EVP_DigestInit_ex(&ctx->mdctx, ctx->md, NULL);
|
||||
EVP_MD_CTX_set_flags(&ctx->mdctx, EVP_MD_CTX_FLAG_ONESHOT);
|
||||
}
|
||||
|
||||
|
||||
|
@ -338,22 +341,26 @@ int apk_sign_ctx_process_file(struct apk_sign_ctx *ctx,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int apk_sign_ctx_mpart_cb(void *ctx, EVP_MD_CTX *mdctx, int part)
|
||||
int apk_sign_ctx_mpart_cb(void *ctx, int part, apk_blob_t data)
|
||||
{
|
||||
struct apk_sign_ctx *sctx = (struct apk_sign_ctx *) ctx;
|
||||
unsigned char calculated[EVP_MAX_MD_SIZE];
|
||||
int r;
|
||||
|
||||
switch (part) {
|
||||
case APK_MPART_BEGIN:
|
||||
EVP_DigestInit_ex(mdctx, sctx->md, NULL);
|
||||
case APK_MPART_DATA:
|
||||
EVP_MD_CTX_clear_flags(&sctx->mdctx, EVP_MD_CTX_FLAG_ONESHOT);
|
||||
EVP_DigestUpdate(&sctx->mdctx, data.ptr, data.len);
|
||||
break;
|
||||
case APK_MPART_BOUNDARY:
|
||||
EVP_DigestUpdate(&sctx->mdctx, data.ptr, data.len);
|
||||
|
||||
/* We are not interested about checksums of signature,
|
||||
* reset checksum if we are still in signatures */
|
||||
if (!sctx->control_started) {
|
||||
EVP_DigestFinal_ex(mdctx, calculated, NULL);
|
||||
EVP_DigestInit_ex(mdctx, sctx->md, NULL);
|
||||
EVP_DigestFinal_ex(&sctx->mdctx, calculated, NULL);
|
||||
EVP_DigestInit_ex(&sctx->mdctx, sctx->md, NULL);
|
||||
EVP_MD_CTX_set_flags(&sctx->mdctx, EVP_MD_CTX_FLAG_ONESHOT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -367,7 +374,7 @@ int apk_sign_ctx_mpart_cb(void *ctx, EVP_MD_CTX *mdctx, int part)
|
|||
/* Verify the signature if we have public key */
|
||||
if (sctx->action == APK_SIGN_VERIFY &&
|
||||
sctx->signature.pkey != NULL) {
|
||||
r = EVP_VerifyFinal(mdctx,
|
||||
r = EVP_VerifyFinal(&sctx->mdctx,
|
||||
(unsigned char *) sctx->signature.data.ptr,
|
||||
sctx->signature.data.len,
|
||||
sctx->signature.pkey);
|
||||
|
@ -375,32 +382,34 @@ int apk_sign_ctx_mpart_cb(void *ctx, EVP_MD_CTX *mdctx, int part)
|
|||
return 1;
|
||||
|
||||
sctx->control_verified = 1;
|
||||
EVP_DigestInit_ex(mdctx, sctx->md, NULL);
|
||||
EVP_DigestInit_ex(&sctx->mdctx, sctx->md, NULL);
|
||||
EVP_MD_CTX_set_flags(&sctx->mdctx, EVP_MD_CTX_FLAG_ONESHOT);
|
||||
return 0;
|
||||
} else if (sctx->action == APK_SIGN_GENERATE &&
|
||||
sctx->has_data_checksum) {
|
||||
/* Package identity is checksum of control block */
|
||||
sctx->identity.type = EVP_MD_CTX_size(mdctx);
|
||||
EVP_DigestFinal_ex(mdctx, sctx->identity.data, NULL);
|
||||
sctx->identity.type = EVP_MD_CTX_size(&sctx->mdctx);
|
||||
EVP_DigestFinal_ex(&sctx->mdctx, sctx->identity.data, NULL);
|
||||
return 1;
|
||||
} else {
|
||||
/* Reset digest for hashing data */
|
||||
EVP_DigestFinal_ex(mdctx, calculated, NULL);
|
||||
EVP_DigestInit_ex(mdctx, sctx->md, NULL);
|
||||
EVP_DigestFinal_ex(&sctx->mdctx, calculated, NULL);
|
||||
EVP_DigestInit_ex(&sctx->mdctx, sctx->md, NULL);
|
||||
EVP_MD_CTX_set_flags(&sctx->mdctx, EVP_MD_CTX_FLAG_ONESHOT);
|
||||
}
|
||||
break;
|
||||
case APK_MPART_END:
|
||||
if (sctx->action == APK_SIGN_VERIFY) {
|
||||
if (sctx->has_data_checksum) {
|
||||
/* Check that data checksum matches */
|
||||
EVP_DigestFinal_ex(mdctx, calculated, NULL);
|
||||
if (EVP_MD_CTX_size(mdctx) != 0 &&
|
||||
EVP_DigestFinal_ex(&sctx->mdctx, calculated, NULL);
|
||||
if (EVP_MD_CTX_size(&sctx->mdctx) != 0 &&
|
||||
memcmp(calculated, sctx->data_checksum,
|
||||
EVP_MD_CTX_size(mdctx)) == 0)
|
||||
EVP_MD_CTX_size(&sctx->mdctx)) == 0)
|
||||
sctx->data_verified = 1;
|
||||
} else if (sctx->signature.pkey != NULL) {
|
||||
/* Assume that the data is fully signed */
|
||||
r = EVP_VerifyFinal(mdctx,
|
||||
r = EVP_VerifyFinal(&sctx->mdctx,
|
||||
(unsigned char *) sctx->signature.data.ptr,
|
||||
sctx->signature.data.len,
|
||||
sctx->signature.pkey);
|
||||
|
@ -411,8 +420,8 @@ int apk_sign_ctx_mpart_cb(void *ctx, EVP_MD_CTX *mdctx, int part)
|
|||
}
|
||||
} else if (!sctx->has_data_checksum) {
|
||||
/* Package identity is checksum of all data */
|
||||
sctx->identity.type = EVP_MD_CTX_size(mdctx);
|
||||
EVP_DigestFinal_ex(mdctx, sctx->identity.data, NULL);
|
||||
sctx->identity.type = EVP_MD_CTX_size(&sctx->mdctx);
|
||||
EVP_DigestFinal_ex(&sctx->mdctx, sctx->identity.data, NULL);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue