pkg: cleanup the signing code
smaller callback and less cases to check. also reintroduce the oneshot digest flag, hopefully correct this time.cute-signatures
parent
9b63730d84
commit
9b77c053e8
|
@ -36,6 +36,7 @@ struct apk_istream {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define APK_BSTREAM_SINGLE_READ 0x0001
|
#define APK_BSTREAM_SINGLE_READ 0x0001
|
||||||
|
#define APK_BSTREAM_EOF 0x0002
|
||||||
|
|
||||||
struct apk_bstream {
|
struct apk_bstream {
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
|
11
src/gunzip.c
11
src/gunzip.c
|
@ -82,10 +82,13 @@ static ssize_t gzi_read(void *stream, void *ptr, size_t size)
|
||||||
switch (r) {
|
switch (r) {
|
||||||
case Z_STREAM_END:
|
case Z_STREAM_END:
|
||||||
/* Digest the inflated bytes */
|
/* Digest the inflated bytes */
|
||||||
|
if ((gis->bs->flags & APK_BSTREAM_EOF) &&
|
||||||
|
gis->zs.avail_in == 0)
|
||||||
|
gis->err = 1;
|
||||||
if (gis->cb != NULL) {
|
if (gis->cb != NULL) {
|
||||||
r = gis->cb(gis->cbctx, APK_MPART_BOUNDARY,
|
r = gis->cb(gis->cbctx,
|
||||||
APK_BLOB_PTR_LEN(gis->cbprev,
|
gis->err ? APK_MPART_END : APK_MPART_BOUNDARY,
|
||||||
(void *)gis->zs.next_in - gis->cbprev));
|
APK_BLOB_PTR_LEN(gis->cbprev, (void *) gis->zs.next_in - gis->cbprev));
|
||||||
if (r > 0)
|
if (r > 0)
|
||||||
r = -ECANCELED;
|
r = -ECANCELED;
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
|
@ -94,6 +97,8 @@ static ssize_t gzi_read(void *stream, void *ptr, size_t size)
|
||||||
}
|
}
|
||||||
gis->cbprev = gis->zs.next_in;
|
gis->cbprev = gis->zs.next_in;
|
||||||
}
|
}
|
||||||
|
if (gis->err)
|
||||||
|
goto ret;
|
||||||
inflateEnd(&gis->zs);
|
inflateEnd(&gis->zs);
|
||||||
if (inflateInit2(&gis->zs, 15+32) != Z_OK)
|
if (inflateInit2(&gis->zs, 15+32) != Z_OK)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
1
src/io.c
1
src/io.c
|
@ -260,6 +260,7 @@ static apk_blob_t mmap_read(void *stream, apk_blob_t token)
|
||||||
|
|
||||||
ret = mbs->left;
|
ret = mbs->left;
|
||||||
mbs->left = APK_BLOB_NULL;
|
mbs->left = APK_BLOB_NULL;
|
||||||
|
mbs->bs.flags |= APK_BSTREAM_EOF;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
173
src/package.c
173
src/package.c
|
@ -426,108 +426,91 @@ int apk_sign_ctx_mpart_cb(void *ctx, int part, apk_blob_t data)
|
||||||
{
|
{
|
||||||
struct apk_sign_ctx *sctx = (struct apk_sign_ctx *) ctx;
|
struct apk_sign_ctx *sctx = (struct apk_sign_ctx *) ctx;
|
||||||
unsigned char calculated[EVP_MAX_MD_SIZE];
|
unsigned char calculated[EVP_MAX_MD_SIZE];
|
||||||
int r;
|
int r, end_of_control;
|
||||||
|
|
||||||
switch (part) {
|
if ((part == APK_MPART_DATA) ||
|
||||||
case APK_MPART_DATA:
|
(part == APK_MPART_BOUNDARY && sctx->data_started))
|
||||||
EVP_DigestUpdate(&sctx->mdctx, data.ptr, data.len);
|
goto update_digest;
|
||||||
break;
|
|
||||||
case APK_MPART_BOUNDARY:
|
|
||||||
EVP_DigestUpdate(&sctx->mdctx, data.ptr, data.len);
|
|
||||||
|
|
||||||
/* We are not interested about checksums of signature,
|
/* Still in signature blocks? */
|
||||||
* reset checksum if we are still in signatures */
|
if (!sctx->control_started)
|
||||||
if (!sctx->control_started) {
|
goto reset_digest;
|
||||||
EVP_DigestFinal_ex(&sctx->mdctx, calculated, NULL);
|
|
||||||
EVP_DigestInit_ex(&sctx->mdctx, sctx->md, NULL);
|
/* Grab state and mark all remaining block as data */
|
||||||
return 0;
|
end_of_control = (sctx->data_started == 0);
|
||||||
|
sctx->data_started = 1;
|
||||||
|
|
||||||
|
/* End of control-block and control does not have data checksum? */
|
||||||
|
if (sctx->has_data_checksum == 0 && end_of_control)
|
||||||
|
goto update_digest;
|
||||||
|
|
||||||
|
/* Drool in the remaining of the digest block now, we will finish
|
||||||
|
* it on all cases */
|
||||||
|
EVP_DigestUpdate(&sctx->mdctx, data.ptr, data.len);
|
||||||
|
|
||||||
|
/* End of control-block and checking control hash/signature or
|
||||||
|
* end of data-block and checking its hash/signature */
|
||||||
|
if (sctx->has_data_checksum && !end_of_control) {
|
||||||
|
/* End of control-block and check it's hash */
|
||||||
|
EVP_DigestFinal_ex(&sctx->mdctx, calculated, NULL);
|
||||||
|
if (EVP_MD_CTX_size(&sctx->mdctx) == 0 ||
|
||||||
|
memcmp(calculated, sctx->data_checksum,
|
||||||
|
EVP_MD_CTX_size(&sctx->mdctx)) != 0)
|
||||||
|
return -EKEYREJECTED;
|
||||||
|
sctx->data_verified = 1;
|
||||||
|
if (!(apk_flags & APK_ALLOW_UNTRUSTED) &&
|
||||||
|
!sctx->control_verified)
|
||||||
|
return -ENOKEY;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (sctx->action) {
|
||||||
|
case APK_SIGN_VERIFY:
|
||||||
|
if (sctx->signature.pkey == NULL) {
|
||||||
|
if (apk_flags & APK_ALLOW_UNTRUSTED)
|
||||||
|
break;
|
||||||
|
return -ENOKEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Are we in control part?. */
|
r = EVP_VerifyFinal(&sctx->mdctx,
|
||||||
if ((!sctx->control_started) || sctx->data_started)
|
(unsigned char *) sctx->signature.data.ptr,
|
||||||
return 0;
|
sctx->signature.data.len,
|
||||||
|
sctx->signature.pkey);
|
||||||
/* End of control block, make sure rest is handled as data */
|
if (r != 1)
|
||||||
sctx->data_started = 1;
|
return -EKEYREJECTED;
|
||||||
if (!sctx->has_data_checksum)
|
sctx->control_verified = 1;
|
||||||
return 0;
|
if (!sctx->has_data_checksum && part == APK_MPART_END)
|
||||||
|
sctx->data_verified = 1;
|
||||||
/* Verify the signature if we have public key */
|
break;
|
||||||
if (sctx->action == APK_SIGN_VERIFY) {
|
case APK_SIGN_VERIFY_IDENTITY:
|
||||||
if (sctx->signature.pkey == NULL) {
|
/* Reset digest for hashing data */
|
||||||
if (!(apk_flags & APK_ALLOW_UNTRUSTED))
|
EVP_DigestFinal_ex(&sctx->mdctx, calculated, NULL);
|
||||||
return -ENOKEY;
|
if (memcmp(calculated, sctx->identity.data,
|
||||||
} else {
|
sctx->identity.type) != 0)
|
||||||
r = EVP_VerifyFinal(&sctx->mdctx,
|
return -EKEYREJECTED;
|
||||||
(unsigned char *) sctx->signature.data.ptr,
|
sctx->control_verified = 1;
|
||||||
sctx->signature.data.len,
|
if (!sctx->has_data_checksum && part == APK_MPART_END)
|
||||||
sctx->signature.pkey);
|
sctx->data_verified = 1;
|
||||||
if (r != 1)
|
break;
|
||||||
return -EKEYREJECTED;
|
case APK_SIGN_GENERATE:
|
||||||
|
case APK_SIGN_GENERATE_V1:
|
||||||
sctx->control_verified = 1;
|
/* Package identity is the checksum */
|
||||||
}
|
sctx->identity.type = EVP_MD_CTX_size(&sctx->mdctx);
|
||||||
EVP_DigestInit_ex(&sctx->mdctx, sctx->md, NULL);
|
EVP_DigestFinal_ex(&sctx->mdctx, sctx->identity.data, NULL);
|
||||||
return 0;
|
if (sctx->action == APK_SIGN_GENERATE &&
|
||||||
} 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(&sctx->mdctx);
|
|
||||||
EVP_DigestFinal_ex(&sctx->mdctx, sctx->identity.data, NULL);
|
|
||||||
return -ECANCELED;
|
return -ECANCELED;
|
||||||
} else {
|
|
||||||
/* Reset digest for hashing data */
|
|
||||||
EVP_DigestFinal_ex(&sctx->mdctx, calculated, NULL);
|
|
||||||
EVP_DigestInit_ex(&sctx->mdctx, sctx->md, NULL);
|
|
||||||
|
|
||||||
if (sctx->action == APK_SIGN_VERIFY_IDENTITY) {
|
|
||||||
if (memcmp(calculated, sctx->identity.data,
|
|
||||||
sctx->identity.type) != 0)
|
|
||||||
return -EKEYREJECTED;
|
|
||||||
sctx->control_verified = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case APK_MPART_END:
|
|
||||||
if (sctx->has_data_checksum) {
|
|
||||||
/* Check that data checksum matches */
|
|
||||||
EVP_DigestFinal_ex(&sctx->mdctx, calculated, NULL);
|
|
||||||
if (EVP_MD_CTX_size(&sctx->mdctx) == 0 ||
|
|
||||||
memcmp(calculated, sctx->data_checksum,
|
|
||||||
EVP_MD_CTX_size(&sctx->mdctx)) != 0)
|
|
||||||
return -EKEYREJECTED;
|
|
||||||
sctx->data_verified = 1;
|
|
||||||
if (!(apk_flags & APK_ALLOW_UNTRUSTED) &&
|
|
||||||
!sctx->control_verified)
|
|
||||||
return -ENOKEY;
|
|
||||||
} else if (sctx->action == APK_SIGN_VERIFY) {
|
|
||||||
if (sctx->signature.pkey == NULL)
|
|
||||||
return -EKEYREJECTED;
|
|
||||||
|
|
||||||
/* Assume that the data is fully signed */
|
|
||||||
r = EVP_VerifyFinal(&sctx->mdctx,
|
|
||||||
(unsigned char *) sctx->signature.data.ptr,
|
|
||||||
sctx->signature.data.len,
|
|
||||||
sctx->signature.pkey);
|
|
||||||
if (r != 1)
|
|
||||||
return -EKEYREJECTED;
|
|
||||||
|
|
||||||
sctx->control_verified = 1;
|
|
||||||
sctx->data_verified = 1;
|
|
||||||
} else if (sctx->action == APK_SIGN_VERIFY_IDENTITY) {
|
|
||||||
EVP_DigestFinal_ex(&sctx->mdctx, calculated, NULL);
|
|
||||||
if (EVP_MD_CTX_size(&sctx->mdctx) == 0 ||
|
|
||||||
memcmp(calculated, sctx->identity.data,
|
|
||||||
EVP_MD_CTX_size(&sctx->mdctx)) != 0)
|
|
||||||
return -EKEYREJECTED;
|
|
||||||
sctx->control_verified = 1;
|
|
||||||
sctx->data_verified = 1;
|
|
||||||
} else {
|
|
||||||
/* Package identity is checksum of all data */
|
|
||||||
sctx->identity.type = EVP_MD_CTX_size(&sctx->mdctx);
|
|
||||||
EVP_DigestFinal_ex(&sctx->mdctx, sctx->identity.data, NULL);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reset_digest:
|
||||||
|
EVP_DigestInit_ex(&sctx->mdctx, sctx->md, NULL);
|
||||||
|
EVP_MD_CTX_set_flags(&sctx->mdctx, EVP_MD_CTX_FLAG_ONESHOT);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
update_digest:
|
||||||
|
EVP_MD_CTX_clear_flags(&sctx->mdctx, EVP_MD_CTX_FLAG_ONESHOT);
|
||||||
|
EVP_DigestUpdate(&sctx->mdctx, data.ptr, data.len);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ static int verify_main(void *ctx, int argc, char **argv)
|
||||||
struct apk_istream *is;
|
struct apk_istream *is;
|
||||||
int i, r, ok, rc = 0;
|
int i, r, ok, rc = 0;
|
||||||
|
|
||||||
|
apk_flags |= APK_ALLOW_UNTRUSTED;
|
||||||
for (i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL);
|
apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL);
|
||||||
is = apk_bstream_gunzip_mpart(apk_bstream_from_file(argv[i]),
|
is = apk_bstream_gunzip_mpart(apk_bstream_from_file(argv[i]),
|
||||||
|
@ -28,7 +29,7 @@ static int verify_main(void *ctx, int argc, char **argv)
|
||||||
is->close(is);
|
is->close(is);
|
||||||
ok = sctx.control_verified && sctx.data_verified;
|
ok = sctx.control_verified && sctx.data_verified;
|
||||||
if (apk_verbosity >= 1)
|
if (apk_verbosity >= 1)
|
||||||
apk_message("%s: %s", argv[i],
|
apk_message("%s: %d - %s", argv[i], r,
|
||||||
ok ? "OK" :
|
ok ? "OK" :
|
||||||
sctx.data_verified ? "UNTRUSTED" : "FAILED");
|
sctx.data_verified ? "UNTRUSTED" : "FAILED");
|
||||||
if (!ok)
|
if (!ok)
|
||||||
|
|
Loading…
Reference in New Issue