xar: Add support for SHA256 and SHA512

Extend the xar reader and writer to understand the SHA256 (header
cksum_alg 3, 32 bytes, style "sha256") and SHA512 (cksum_alg 4, 64
bytes, style "sha512") checksum algorithms in addition to the existing
SHA1 and MD5.  These are the algorithm codes defined by the canonical
xar format, so archives written with them interoperate with Apple's xar,
pkgutil, and PackageKit.

Both the TOC ("toc-checksum") and per-file ("checksum") algorithms are
supported for writing.  New algorithm handling is guarded by
ARCHIVE_HAS_SHA256 / ARCHIVE_HAS_SHA512 so builds without those digests
are unaffected.  MAX_SUM_SIZE grows from 20 to 64 to hold a SHA512
digest.
This commit is contained in:
Dag-Erling Smørgrav committed 2026-07-27 19:28:21 +02:00
1 parent 4d3bfca239
commit 6f10adcd59
4 files changed
+147 -12

No files matched your search

+59 -4
View File
@@ -108,10 +108,14 @@ archive_read_support_format_xar(struct archive *_a)
#define CKSUM_NONE 0
#define CKSUM_SHA1 1
#define CKSUM_MD5 2
#define CKSUM_SHA256 3
#define CKSUM_SHA512 4
#define MD5_SIZE 16
#define SHA1_SIZE 20
#define MAX_SUM_SIZE 20
#define SHA256_SIZE 32
#define SHA512_SIZE 64
#define MAX_SUM_SIZE 64
enum enctype {
NONE,
@@ -135,6 +139,12 @@ struct chksumwork {
#ifdef ARCHIVE_HAS_SHA1
archive_sha1_ctx sha1ctx;
#endif
#ifdef ARCHIVE_HAS_SHA256
archive_sha256_ctx sha256ctx;
#endif
#ifdef ARCHIVE_HAS_SHA512
archive_sha512_ctx sha512ctx;
#endif
};
struct xattr {
@@ -524,6 +534,8 @@ xar_bid(struct archive_read *a, int best_bid)
case CKSUM_NONE:
case CKSUM_SHA1:
case CKSUM_MD5:
case CKSUM_SHA256:
case CKSUM_SHA512:
bid += 32;
break;
default:
@@ -1343,6 +1355,16 @@ _checksum_init(struct chksumwork *sumwrk, int sum_alg)
case CKSUM_MD5:
archive_md5_init(&(sumwrk->md5ctx));
break;
#ifdef ARCHIVE_HAS_SHA256
case CKSUM_SHA256:
archive_sha256_init(&(sumwrk->sha256ctx));
break;
#endif
#ifdef ARCHIVE_HAS_SHA512
case CKSUM_SHA512:
archive_sha512_init(&(sumwrk->sha512ctx));
break;
#endif
}
}
@@ -1359,6 +1381,16 @@ _checksum_update(struct chksumwork *sumwrk, const void *buff, size_t size)
case CKSUM_MD5:
archive_md5_update(&(sumwrk->md5ctx), buff, size);
break;
#ifdef ARCHIVE_HAS_SHA256
case CKSUM_SHA256:
archive_sha256_update(&(sumwrk->sha256ctx), buff, size);
break;
#endif
#ifdef ARCHIVE_HAS_SHA512
case CKSUM_SHA512:
archive_sha512_update(&(sumwrk->sha512ctx), buff, size);
break;
#endif
}
}
@@ -1383,6 +1415,22 @@ _checksum_final(struct chksumwork *sumwrk, const void *val, size_t len)
memcmp(val, sum, MD5_SIZE) != 0)
r = ARCHIVE_FAILED;
break;
#ifdef ARCHIVE_HAS_SHA256
case CKSUM_SHA256:
archive_sha256_final(&(sumwrk->sha256ctx), sum);
if (len != SHA256_SIZE ||
memcmp(val, sum, SHA256_SIZE) != 0)
r = ARCHIVE_FAILED;
break;
#endif
#ifdef ARCHIVE_HAS_SHA512
case CKSUM_SHA512:
archive_sha512_final(&(sumwrk->sha512ctx), sum);
if (len != SHA512_SIZE ||
memcmp(val, sum, SHA512_SIZE) != 0)
r = ARCHIVE_FAILED;
break;
#endif
}
return (r);
}
@@ -1884,9 +1932,16 @@ getsumalgorithm(struct xmlattr_list *list)
const char *v = attr->value;
if ((v[0] == 'S' || v[0] == 's') &&
(v[1] == 'H' || v[1] == 'h') &&
(v[2] == 'A' || v[2] == 'a') &&
v[3] == '1' && v[4] == '\0')
alg = CKSUM_SHA1;
(v[2] == 'A' || v[2] == 'a')) {
if (v[3] == '1' && v[4] == '\0')
alg = CKSUM_SHA1;
else if (v[3] == '2' && v[4] == '5' &&
v[5] == '6' && v[6] == '\0')
alg = CKSUM_SHA256;
else if (v[3] == '5' && v[4] == '1' &&
v[5] == '2' && v[6] == '\0')
alg = CKSUM_SHA512;
}
if ((v[0] == 'M' || v[0] == 'm') &&
(v[1] == 'D' || v[1] == 'd') &&
v[2] == '5' && v[3] == '\0')
+70 -2
View File
@@ -129,14 +129,20 @@ static int xml_writer_destroy(struct xml_writer *ctx);
enum sumalg {
CKSUM_NONE = 0,
CKSUM_SHA1 = 1,
CKSUM_MD5 = 2
CKSUM_MD5 = 2,
CKSUM_SHA256 = 3,
CKSUM_SHA512 = 4
};
#define MD5_SIZE 16
#define SHA1_SIZE 20
#define MAX_SUM_SIZE 20
#define SHA256_SIZE 32
#define SHA512_SIZE 64
#define MAX_SUM_SIZE 64
#define MD5_NAME "md5"
#define SHA1_NAME "sha1"
#define SHA256_NAME "sha256"
#define SHA512_NAME "sha512"
enum enctype {
NONE,
@@ -154,6 +160,12 @@ struct chksumwork {
#ifdef ARCHIVE_HAS_SHA1
archive_sha1_ctx sha1ctx;
#endif
#ifdef ARCHIVE_HAS_SHA256
archive_sha256_ctx sha256ctx;
#endif
#ifdef ARCHIVE_HAS_SHA512
archive_sha512_ctx sha512ctx;
#endif
};
enum la_zaction {
@@ -445,6 +457,14 @@ xar_options(struct archive_write *a, const char *key, const char *value)
xar->opt_sumalg = CKSUM_SHA1;
else if (strcmp(value, "md5") == 0)
xar->opt_sumalg = CKSUM_MD5;
#ifdef ARCHIVE_HAS_SHA256
else if (strcmp(value, "sha256") == 0)
xar->opt_sumalg = CKSUM_SHA256;
#endif
#ifdef ARCHIVE_HAS_SHA512
else if (strcmp(value, "sha512") == 0)
xar->opt_sumalg = CKSUM_SHA512;
#endif
else {
archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC,
@@ -520,6 +540,14 @@ xar_options(struct archive_write *a, const char *key, const char *value)
xar->opt_toc_sumalg = CKSUM_SHA1;
else if (strcmp(value, "md5") == 0)
xar->opt_toc_sumalg = CKSUM_MD5;
#ifdef ARCHIVE_HAS_SHA256
else if (strcmp(value, "sha256") == 0)
xar->opt_toc_sumalg = CKSUM_SHA256;
#endif
#ifdef ARCHIVE_HAS_SHA512
else if (strcmp(value, "sha512") == 0)
xar->opt_toc_sumalg = CKSUM_SHA512;
#endif
else {
archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC,
@@ -2649,6 +2677,16 @@ checksum_init(struct chksumwork *sumwrk, enum sumalg sum_alg)
case CKSUM_MD5:
archive_md5_init(&(sumwrk->md5ctx));
break;
#ifdef ARCHIVE_HAS_SHA256
case CKSUM_SHA256:
archive_sha256_init(&(sumwrk->sha256ctx));
break;
#endif
#ifdef ARCHIVE_HAS_SHA512
case CKSUM_SHA512:
archive_sha512_init(&(sumwrk->sha512ctx));
break;
#endif
}
}
@@ -2665,6 +2703,16 @@ checksum_update(struct chksumwork *sumwrk, const void *buff, size_t size)
case CKSUM_MD5:
archive_md5_update(&(sumwrk->md5ctx), buff, size);
break;
#ifdef ARCHIVE_HAS_SHA256
case CKSUM_SHA256:
archive_sha256_update(&(sumwrk->sha256ctx), buff, size);
break;
#endif
#ifdef ARCHIVE_HAS_SHA512
case CKSUM_SHA512:
archive_sha512_update(&(sumwrk->sha512ctx), buff, size);
break;
#endif
}
}
@@ -2684,6 +2732,18 @@ checksum_final(struct chksumwork *sumwrk, struct chksumval *sumval)
archive_md5_final(&(sumwrk->md5ctx), sumval->val);
sumval->len = MD5_SIZE;
break;
#ifdef ARCHIVE_HAS_SHA256
case CKSUM_SHA256:
archive_sha256_final(&(sumwrk->sha256ctx), sumval->val);
sumval->len = SHA256_SIZE;
break;
#endif
#ifdef ARCHIVE_HAS_SHA512
case CKSUM_SHA512:
archive_sha512_final(&(sumwrk->sha512ctx), sumval->val);
sumval->len = SHA512_SIZE;
break;
#endif
}
sumval->alg = sumwrk->alg;
}
@@ -3311,6 +3371,10 @@ getalgsize(enum sumalg sumalg)
return (SHA1_SIZE);
case CKSUM_MD5:
return (MD5_SIZE);
case CKSUM_SHA256:
return (SHA256_SIZE);
case CKSUM_SHA512:
return (SHA512_SIZE);
}
}
@@ -3325,6 +3389,10 @@ getalgname(enum sumalg sumalg)
return (SHA1_NAME);
case CKSUM_MD5:
return (MD5_NAME);
case CKSUM_SHA256:
return (SHA256_NAME);
case CKSUM_SHA512:
return (SHA512_NAME);
}
}
+9 -5
View File
@@ -622,9 +622,11 @@ as file checksum method.
Supported values are
.Dq none ,
.Dq md5 ,
and
.Dq sha1
.Pq default .
.Pq default ,
.Dq sha256 ,
and
.Dq sha512 .
.It Cm compression Ns = Ns Ar type
Use
.Ar type
@@ -645,10 +647,12 @@ Use
as table of contents checksum method.
Supported values are
.Dq none ,
.Dq md5
and
.Dq md5 ,
.Dq sha1
.Pq default .
.Pq default ,
.Dq sha256 ,
and
.Dq sha512 .
.El
.It Format zip
.Bl -tag -compact -width indent
+9 -1
View File
@@ -34,7 +34,7 @@ static void
test_xar(const char *option)
{
char buff2[64];
size_t buffsize = 1500;
size_t buffsize = 4096;
char *buff;
struct archive_entry *ae;
struct archive *a;
@@ -325,6 +325,10 @@ DEFINE_TEST(test_write_format_xar)
test_xar("toc-checksum=sha1");
/* Specify TOC checksum type to md5. */
test_xar("toc-checksum=md5");
/* Specify TOC checksum type to sha256. */
test_xar("toc-checksum=sha256");
/* Specify TOC checksum type to sha512. */
test_xar("toc-checksum=sha512");
/* Disable file checksum. */
test_xar("!checksum");
@@ -333,6 +337,10 @@ DEFINE_TEST(test_write_format_xar)
test_xar("checksum=sha1");
/* Specify file checksum type to md5. */
test_xar("checksum=md5");
/* Specify file checksum type to sha256. */
test_xar("checksum=sha256");
/* Specify file checksum type to sha512. */
test_xar("checksum=sha512");
/* Disable compression. */
test_xar("!compression");