]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
xar: Add support for SHA256 and SHA512 3328/head
authorDag-Erling Smørgrav <des@des.dev>
Mon, 27 Jul 2026 17:20:07 +0000 (19:20 +0200)
committerDag-Erling Smørgrav <des@des.dev>
Mon, 27 Jul 2026 17:28:21 +0000 (19:28 +0200)
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.

libarchive/archive_read_support_format_xar.c
libarchive/archive_write_set_format_xar.c
libarchive/archive_write_set_options.3
libarchive/test/test_write_format_xar.c

index cd61342ab254114382542c403c6ccca2366b5b92..612b104f085fee8c94e20614de8c3b9881e970b8 100644 (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')
index c3e444f7e2cec1067ae992a9073d0e4b73670f9b..0058693792c1dd68ae45711822708567bcde34c6 100644 (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);
        }
 }
 
index 9fc24e699326ded5e96207f2690bdc2af71bb631..e03b5175771df5cc6bde13008b1a02221c885f95 100644 (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
index bb24fffc3f311036d674879e9e388469487266fc..2f185898feeda8ab108eab3c924ff20ebf2569d6 100644 (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");