Author: kotkov
Date: Thu Jan 19 18:50:06 2023
New Revision: 1906820

URL: http://svn.apache.org/viewvc?rev=1906820&view=rev
Log:
On the 'pristine-checksum-kind' branch: Lay some groundwork for making the
working copy pristine checksum kind configurable by implementing a salted
SHA-1 checksum function.

We'll temporarily use it as the new pristine checksum kind for working copies
of the latest format, as a proof-of-concept.  For the production-ready state,
we could later support using multiple new checksum types such as SHA-256.
That would be useful for future compatibility, because if we encounter any
issues with one checksum kind, we could then switch to a different kind
without having to change the working copy format.

* subversion/include/svn_checksum.h
  (svn_checksum_kind_t): Add `svn_checksum_sha1_salted`.

* subversion/libsvn_subr/checksum.c
  (sha1_salted_empty_string_digest_array, sha1_salt): New.
  (empty_string_digests,
   digest_sizes,
   ckind_str,
   DIGESTSIZE,
   validate_kind,
   svn_checksum_create,
   svn_checksum_match,
   svn_checksum_to_cstring,
   svn_checksum_serialize,
   svn_checksum_deserialize,
   svn_checksum_dup,
   svn_checksum,
   svn_checksum_empty_checksum,
   svn_checksum_ctx_create,
   svn_checksum_ctx_reset,
   svn_checksum_update,
   svn_checksum_final,
   svn_checksum_is_empty_checksum): Provide implementation for the new
   checksum kind.

* subversion/tests/libsvn_subr/checksum-test.c
  (test_checksum_parse,
   test_checksum_empty,
   zero_match,
   zero_cross_match,
   test_serialization,
   test_checksum_parse_all_zero,
   test_checksummed_stream_read,
   test_checksummed_stream_reset): Test the new checksum kind.

Modified:
    subversion/branches/pristine-checksum-kind/subversion/include/svn_checksum.h
    subversion/branches/pristine-checksum-kind/subversion/libsvn_subr/checksum.c
    
subversion/branches/pristine-checksum-kind/subversion/tests/libsvn_subr/checksum-test.c

Modified: 
subversion/branches/pristine-checksum-kind/subversion/include/svn_checksum.h
URL: 
http://svn.apache.org/viewvc/subversion/branches/pristine-checksum-kind/subversion/include/svn_checksum.h?rev=1906820&r1=1906819&r2=1906820&view=diff
==============================================================================
--- 
subversion/branches/pristine-checksum-kind/subversion/include/svn_checksum.h 
(original)
+++ 
subversion/branches/pristine-checksum-kind/subversion/include/svn_checksum.h 
Thu Jan 19 18:50:06 2023
@@ -58,7 +58,11 @@ typedef enum svn_checksum_kind_t
   /** The checksum is (or should be set to) a modified FNV-1a 32 bit,
    * in big endian byte order.
    * @since New in 1.9. */
-  svn_checksum_fnv1a_32x4
+  svn_checksum_fnv1a_32x4,
+
+  /** The checksum is (or should be set to) a salted SHA1 checksum.
+   * @since New in 1.15. */
+  svn_checksum_sha1_salted
 } svn_checksum_kind_t;
 
 /**

Modified: 
subversion/branches/pristine-checksum-kind/subversion/libsvn_subr/checksum.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/pristine-checksum-kind/subversion/libsvn_subr/checksum.c?rev=1906820&r1=1906819&r2=1906820&view=diff
==============================================================================
--- 
subversion/branches/pristine-checksum-kind/subversion/libsvn_subr/checksum.c 
(original)
+++ 
subversion/branches/pristine-checksum-kind/subversion/libsvn_subr/checksum.c 
Thu Jan 19 18:50:06 2023
@@ -64,12 +64,19 @@ static const unsigned char fnv1a_32x4_em
   0xcd, 0x6d, 0x9a, 0x85
 };
 
+/* The salted-SHA1 digest for the empty string. */
+static const unsigned char sha1_salted_empty_string_digest_array[] = {
+  0x1f, 0x5d, 0xae, 0x8c, 0x03, 0xf9, 0x6f, 0x6c, 0xc4, 0xd1,
+  0x5c, 0xcc, 0x52, 0x7d, 0xf2, 0xf9, 0x14, 0xa4, 0x33, 0xbb
+};
+
 /* Digests for an empty string, indexed by checksum type */
 static const unsigned char * empty_string_digests[] = {
   md5_empty_string_digest_array,
   sha1_empty_string_digest_array,
   fnv1a_32_empty_string_digest_array,
-  fnv1a_32x4_empty_string_digest_array
+  fnv1a_32x4_empty_string_digest_array,
+  sha1_salted_empty_string_digest_array
 };
 
 /* Digest sizes in bytes, indexed by checksum type */
@@ -77,7 +84,8 @@ static const apr_size_t digest_sizes[] =
   APR_MD5_DIGESTSIZE,
   APR_SHA1_DIGESTSIZE,
   sizeof(apr_uint32_t),
-  sizeof(apr_uint32_t)
+  sizeof(apr_uint32_t),
+  APR_SHA1_DIGESTSIZE
 };
 
 /* Checksum type prefixes used in serialized checksums. */
@@ -86,16 +94,25 @@ static const char *ckind_str[] = {
   "$sha1$",
   "$fnv1$",
   "$fnvm$",
+  "$ssh1$",
   /* ### svn_checksum_deserialize() assumes all these have the same strlen() */
 };
 
 /* Returns the digest size of it's argument. */
 #define DIGESTSIZE(k) \
-  (((k) < svn_checksum_md5 || (k) > svn_checksum_fnv1a_32x4) ? 0 : 
digest_sizes[k])
+  (((k) < svn_checksum_md5 || (k) > svn_checksum_sha1_salted) ? 0 : 
digest_sizes[k])
 
 /* Largest supported digest size */
 #define MAX_DIGESTSIZE (MAX(APR_MD5_DIGESTSIZE,APR_SHA1_DIGESTSIZE))
 
+/* The salt we use for salted-SHA1 checksum. */
+static const unsigned char sha1_salt[] = {
+  0x2e, 0x95, 0x1d, 0xb1, 0xd7, 0x11, 0xa0, 0x77,
+  0xe7, 0x22, 0xbc, 0x1d, 0xc0, 0x93, 0x1f, 0x63,
+  0x24, 0xee, 0x28, 0x3b, 0x6d, 0x3f, 0x08, 0x33,
+  0x57, 0x50, 0xfb, 0x80, 0xd3, 0xa2, 0x03, 0xf4
+};
+
 const unsigned char *
 svn__empty_string_digest(svn_checksum_kind_t kind)
 {
@@ -153,7 +170,7 @@ svn__digests_match(const unsigned char d
 static svn_error_t *
 validate_kind(svn_checksum_kind_t kind)
 {
-  if (kind >= svn_checksum_md5 && kind <= svn_checksum_fnv1a_32x4)
+  if (kind >= svn_checksum_md5 && kind <= svn_checksum_sha1_salted)
     return SVN_NO_ERROR;
   else
     return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL, NULL);
@@ -202,6 +219,7 @@ svn_checksum_create(svn_checksum_kind_t
       case svn_checksum_sha1:
       case svn_checksum_fnv1a_32:
       case svn_checksum_fnv1a_32x4:
+      case svn_checksum_sha1_salted:
         digest_size = digest_sizes[kind];
         break;
 
@@ -267,6 +285,7 @@ svn_checksum_match(const svn_checksum_t
       case svn_checksum_sha1:
       case svn_checksum_fnv1a_32:
       case svn_checksum_fnv1a_32x4:
+      case svn_checksum_sha1_salted:
         return svn__digests_match(checksum1->digest,
                                   checksum2->digest,
                                   digest_sizes[checksum1->kind]);
@@ -287,6 +306,7 @@ svn_checksum_to_cstring_display(const sv
       case svn_checksum_sha1:
       case svn_checksum_fnv1a_32:
       case svn_checksum_fnv1a_32x4:
+      case svn_checksum_sha1_salted:
         return svn__digest_to_cstring_display(checksum->digest,
                                               digest_sizes[checksum->kind],
                                               pool);
@@ -310,6 +330,7 @@ svn_checksum_to_cstring(const svn_checks
       case svn_checksum_sha1:
       case svn_checksum_fnv1a_32:
       case svn_checksum_fnv1a_32x4:
+      case svn_checksum_sha1_salted:
         return svn__digest_to_cstring(checksum->digest,
                                       digest_sizes[checksum->kind],
                                       pool);
@@ -327,7 +348,7 @@ svn_checksum_serialize(const svn_checksu
                        apr_pool_t *scratch_pool)
 {
   SVN_ERR_ASSERT_NO_RETURN(checksum->kind >= svn_checksum_md5
-                           || checksum->kind <= svn_checksum_fnv1a_32x4);
+                           || checksum->kind <= svn_checksum_sha1_salted);
   return apr_pstrcat(result_pool,
                      ckind_str[checksum->kind],
                      svn_checksum_to_cstring(checksum, scratch_pool),
@@ -353,7 +374,7 @@ svn_checksum_deserialize(const svn_check
                              _("Invalid prefix in checksum '%s'"),
                              data);
 
-  for (kind = svn_checksum_md5; kind <= svn_checksum_fnv1a_32x4; ++kind)
+  for (kind = svn_checksum_md5; kind <= svn_checksum_sha1_salted; ++kind)
     if (strncmp(ckind_str[kind], data, prefix_len) == 0)
       {
         SVN_ERR(svn_checksum_parse_hex(&parsed_checksum, kind,
@@ -460,6 +481,7 @@ svn_checksum_dup(const svn_checksum_t *c
       case svn_checksum_sha1:
       case svn_checksum_fnv1a_32:
       case svn_checksum_fnv1a_32x4:
+      case svn_checksum_sha1_salted:
         return checksum_create(checksum->kind, checksum->digest, pool);
 
       default:
@@ -502,6 +524,13 @@ svn_checksum(svn_checksum_t **checksum,
           = htonl(svn__fnv1a_32x4(data, len));
         break;
 
+      case svn_checksum_sha1_salted:
+        apr_sha1_init(&sha1_ctx);
+        apr_sha1_update(&sha1_ctx, (const char *)sha1_salt, sizeof(sha1_salt));
+        apr_sha1_update(&sha1_ctx, data, (unsigned int)len);
+        apr_sha1_final((unsigned char *)(*checksum)->digest, &sha1_ctx);
+        break;
+
       default:
         /* We really shouldn't get here, but if we do... */
         return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL, NULL);
@@ -521,6 +550,7 @@ svn_checksum_empty_checksum(svn_checksum
       case svn_checksum_sha1:
       case svn_checksum_fnv1a_32:
       case svn_checksum_fnv1a_32x4:
+      case svn_checksum_sha1_salted:
         return checksum_create(kind, empty_string_digests[kind], pool);
 
       default:
@@ -562,6 +592,12 @@ svn_checksum_ctx_create(svn_checksum_kin
         ctx->apr_ctx = svn_fnv1a_32x4__context_create(pool);
         break;
 
+      case svn_checksum_sha1_salted:
+        ctx->apr_ctx = apr_palloc(pool, sizeof(apr_sha1_ctx_t));
+        apr_sha1_init(ctx->apr_ctx);
+        apr_sha1_update(ctx->apr_ctx, (const char *)sha1_salt, 
sizeof(sha1_salt));
+        break;
+
       default:
         SVN_ERR_MALFUNCTION_NO_RETURN();
     }
@@ -592,6 +628,12 @@ svn_checksum_ctx_reset(svn_checksum_ctx_
         svn_fnv1a_32x4__context_reset(ctx->apr_ctx);
         break;
 
+      case svn_checksum_sha1_salted:
+        memset(ctx->apr_ctx, 0, sizeof(apr_sha1_ctx_t));
+        apr_sha1_init(ctx->apr_ctx);
+        apr_sha1_update(ctx->apr_ctx, (const char *)sha1_salt, 
sizeof(sha1_salt));
+        break;
+
       default:
         SVN_ERR_MALFUNCTION();
     }
@@ -622,6 +664,10 @@ svn_checksum_update(svn_checksum_ctx_t *
         svn_fnv1a_32x4__update(ctx->apr_ctx, data, len);
         break;
 
+      case svn_checksum_sha1_salted:
+        apr_sha1_update(ctx->apr_ctx, data, (unsigned int)len);
+        break;
+
       default:
         /* We really shouldn't get here, but if we do... */
         return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL, NULL);
@@ -657,6 +703,10 @@ svn_checksum_final(svn_checksum_t **chec
           = htonl(svn_fnv1a_32x4__finalize(ctx->apr_ctx));
         break;
 
+      case svn_checksum_sha1_salted:
+        apr_sha1_final((unsigned char *)(*checksum)->digest, ctx->apr_ctx);
+        break;
+
       default:
         /* We really shouldn't get here, but if we do... */
         return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL, NULL);
@@ -708,6 +758,7 @@ svn_checksum_is_empty_checksum(svn_check
       case svn_checksum_sha1:
       case svn_checksum_fnv1a_32:
       case svn_checksum_fnv1a_32x4:
+      case svn_checksum_sha1_salted:
         return svn__digests_match(checksum->digest,
                                   svn__empty_string_digest(checksum->kind),
                                   digest_sizes[checksum->kind]);

Modified: 
subversion/branches/pristine-checksum-kind/subversion/tests/libsvn_subr/checksum-test.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/pristine-checksum-kind/subversion/tests/libsvn_subr/checksum-test.c?rev=1906820&r1=1906819&r2=1906820&view=diff
==============================================================================
--- 
subversion/branches/pristine-checksum-kind/subversion/tests/libsvn_subr/checksum-test.c
 (original)
+++ 
subversion/branches/pristine-checksum-kind/subversion/tests/libsvn_subr/checksum-test.c
 Thu Jan 19 18:50:06 2023
@@ -68,6 +68,8 @@ test_checksum_parse(apr_pool_t *pool)
   SVN_ERR(checksum_parse_kind("cafeaffe",
                               svn_checksum_fnv1a_32x4,
                               "modified fnv-1a", pool));
+  SVN_ERR(checksum_parse_kind("c4fb4f348b4b13bb28bf03c2f6f2352f049d66d2",
+                              svn_checksum_sha1_salted, "sha1-salted", pool));
 
   return SVN_NO_ERROR;
 }
@@ -76,7 +78,7 @@ static svn_error_t *
 test_checksum_empty(apr_pool_t *pool)
 {
   svn_checksum_kind_t kind;
-  for (kind = svn_checksum_md5; kind <= svn_checksum_fnv1a_32x4; ++kind)
+  for (kind = svn_checksum_md5; kind <= svn_checksum_sha1_salted; ++kind)
     {
       svn_checksum_t *checksum;
       char data = '\0';
@@ -119,7 +121,7 @@ static svn_error_t *
 zero_match(apr_pool_t *pool)
 {
   svn_checksum_kind_t kind;
-  for (kind = svn_checksum_md5; kind <= svn_checksum_fnv1a_32x4; ++kind)
+  for (kind = svn_checksum_md5; kind <= svn_checksum_sha1_salted; ++kind)
     SVN_ERR(zero_match_kind(kind, pool));
 
   return SVN_NO_ERROR;
@@ -132,7 +134,7 @@ zero_cross_match(apr_pool_t *pool)
   svn_checksum_kind_t k_kind;
 
   for (i_kind = svn_checksum_md5;
-       i_kind <= svn_checksum_fnv1a_32x4;
+       i_kind <= svn_checksum_sha1_salted;
        ++i_kind)
     {
       svn_checksum_t *i_zero;
@@ -143,7 +145,7 @@ zero_cross_match(apr_pool_t *pool)
       SVN_ERR(svn_checksum(&i_A, i_kind, "A", 1, pool));
 
       for (k_kind = svn_checksum_md5;
-           k_kind <= svn_checksum_fnv1a_32x4;
+           k_kind <= svn_checksum_sha1_salted;
            ++k_kind)
         {
           svn_checksum_t *k_zero;
@@ -258,7 +260,7 @@ static svn_error_t *
 test_serialization(apr_pool_t *pool)
 {
   svn_checksum_kind_t kind;
-  for (kind = svn_checksum_md5; kind <= svn_checksum_fnv1a_32x4; ++kind)
+  for (kind = svn_checksum_md5; kind <= svn_checksum_sha1_salted; ++kind)
     {
       const svn_checksum_t *parsed_checksum;
       svn_checksum_t *checksum = svn_checksum_empty_checksum(kind, pool);
@@ -278,7 +280,7 @@ static svn_error_t *
 test_checksum_parse_all_zero(apr_pool_t *pool)
 {
   svn_checksum_kind_t kind;
-  for (kind = svn_checksum_md5; kind <= svn_checksum_fnv1a_32x4; ++kind)
+  for (kind = svn_checksum_md5; kind <= svn_checksum_sha1_salted; ++kind)
     {
       svn_checksum_t *checksum;
       const char *hex;
@@ -302,7 +304,7 @@ test_checksummed_stream_read(apr_pool_t
   const svn_string_t *str = svn_string_create("abcde", pool);
   svn_checksum_kind_t kind;
 
-  for (kind = svn_checksum_md5; kind <= svn_checksum_fnv1a_32x4; ++kind)
+  for (kind = svn_checksum_md5; kind <= svn_checksum_sha1_salted; ++kind)
     {
       svn_stream_t *stream;
       svn_checksum_t *expected_checksum;
@@ -333,7 +335,7 @@ test_checksummed_stream_reset(apr_pool_t
   const svn_string_t *str = svn_string_create("abcde", pool);
   svn_checksum_kind_t kind;
 
-  for (kind = svn_checksum_md5; kind <= svn_checksum_fnv1a_32x4; ++kind)
+  for (kind = svn_checksum_md5; kind <= svn_checksum_sha1_salted; ++kind)
     {
       svn_stream_t *stream;
       svn_checksum_t *expected_checksum;


Reply via email to