diff options
-rw-r--r-- | src/apk_io.h | 11 | ||||
-rw-r--r-- | src/apk_package.h | 3 | ||||
-rw-r--r-- | src/database.c | 22 | ||||
-rw-r--r-- | src/gunzip.c | 44 | ||||
-rw-r--r-- | src/io.c | 3 | ||||
-rw-r--r-- | src/package.c | 43 |
6 files changed, 61 insertions, 65 deletions
diff --git a/src/apk_io.h b/src/apk_io.h index e547668..fe6baac 100644 --- a/src/apk_io.h +++ b/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); diff --git a/src/apk_package.h b/src/apk_package.h index 6b7e959..f77637a 100644 --- a/src/apk_package.h +++ b/src/apk_package.h @@ -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); diff --git a/src/database.c b/src/database.c index 5a1348e..db8f521 100644 --- a/src/database.c +++ b/src/database.c @@ -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); diff --git a/src/gunzip.c b/src/gunzip.c index 9c9ea69..fb0da05 100644 --- a/src/gunzip.c +++ b/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); @@ -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); diff --git a/src/package.c b/src/package.c index 632e93e..4a90993 100644 --- a/src/package.c +++ b/src/package.c @@ -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; } |