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;