svn_error_t * svn_checksum(svn_checksum_t **checksum, svn_checksum_kind_t kind, const void *data, apr_size_t len, apr_pool_t *pool) { apr_sha1_ctx_t sha1_ctx; SVN_ERR(validate_kind(kind)); *checksum = svn_checksum_create(kind, pool); switch (kind) { case svn_checksum_md5: apr_md5((unsigned char *)(*checksum)->digest, data, len); break; case svn_checksum_sha1: apr_sha1_init(&sha1_ctx); apr_sha1_update(&sha1_ctx, data, 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); } return SVN_NO_ERROR; }
svn_error_t * svn_checksum_parse_hex(svn_checksum_t **checksum, svn_checksum_kind_t kind, const char *hex, apr_pool_t *pool) { int i, len; char is_nonzero = '\0'; char *digest; static const char xdigitval[256] = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, /* 0-9 */ -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* A-F */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* a-f */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, }; if (hex == NULL) { *checksum = NULL; return SVN_NO_ERROR; } SVN_ERR(validate_kind(kind)); *checksum = svn_checksum_create(kind, pool); digest = (char *)(*checksum)->digest; len = DIGESTSIZE(kind); for (i = 0; i < len; i++) { char x1 = xdigitval[(unsigned char)hex[i * 2]]; char x2 = xdigitval[(unsigned char)hex[i * 2 + 1]]; if (x1 == (char)-1 || x2 == (char)-1) return svn_error_create(SVN_ERR_BAD_CHECKSUM_PARSE, NULL, NULL); digest[i] = (x1 << 4) | x2; is_nonzero |= (x1 << 4) | x2; } if (!is_nonzero) *checksum = NULL; return SVN_NO_ERROR; }
svn_checksum_t * svn_checksum__from_digest(const unsigned char *digest, svn_checksum_kind_t kind, apr_pool_t *result_pool) { svn_checksum_t *checksum = svn_checksum_create(kind, result_pool); memcpy((unsigned char *)checksum->digest, digest, DIGESTSIZE(kind)); return checksum; }
static svn_error_t * zero_match(apr_pool_t *pool) { svn_checksum_t *zero_md5; svn_checksum_t *zero_sha1; svn_checksum_t *A_md5; svn_checksum_t *B_md5; svn_checksum_t *A_sha1; svn_checksum_t *B_sha1; zero_md5 = svn_checksum_create(svn_checksum_md5, pool); SVN_ERR(svn_checksum_clear(zero_md5)); SVN_ERR(svn_checksum(&A_md5, svn_checksum_md5, "A", 1, pool)); SVN_ERR(svn_checksum(&B_md5, svn_checksum_md5, "B", 1, pool)); zero_sha1 = svn_checksum_create(svn_checksum_sha1, pool); SVN_ERR(svn_checksum_clear(zero_sha1)); SVN_ERR(svn_checksum(&A_sha1, svn_checksum_sha1, "A", 1, pool)); SVN_ERR(svn_checksum(&B_sha1, svn_checksum_sha1, "B", 1, pool)); /* Different non-zero don't match. */ SVN_TEST_ASSERT(!svn_checksum_match(A_md5, B_md5)); SVN_TEST_ASSERT(!svn_checksum_match(A_sha1, B_sha1)); SVN_TEST_ASSERT(!svn_checksum_match(A_md5, A_sha1)); SVN_TEST_ASSERT(!svn_checksum_match(A_md5, B_sha1)); /* Zero matches anything of the same kind. */ SVN_TEST_ASSERT(svn_checksum_match(A_md5, zero_md5)); SVN_TEST_ASSERT(svn_checksum_match(zero_md5, B_md5)); SVN_TEST_ASSERT(svn_checksum_match(A_sha1, zero_sha1)); SVN_TEST_ASSERT(svn_checksum_match(zero_sha1, B_sha1)); /* Zero doesn't match anything of a different kind... */ SVN_TEST_ASSERT(!svn_checksum_match(zero_md5, A_sha1)); SVN_TEST_ASSERT(!svn_checksum_match(zero_sha1, A_md5)); /* ...even another zero. */ SVN_TEST_ASSERT(!svn_checksum_match(zero_md5, zero_sha1)); return SVN_NO_ERROR; }
svn_error_t * svn_checksum_parse_hex(svn_checksum_t **checksum, svn_checksum_kind_t kind, const char *hex, apr_pool_t *pool) { int len; int i; unsigned char is_zeros = '\0'; if (hex == NULL) { *checksum = NULL; return SVN_NO_ERROR; } SVN_ERR(validate_kind(kind)); *checksum = svn_checksum_create(kind, pool); len = DIGESTSIZE(kind); for (i = 0; i < len; i++) { if ((! isxdigit(hex[i * 2])) || (! isxdigit(hex[i * 2 + 1]))) return svn_error_create(SVN_ERR_BAD_CHECKSUM_PARSE, NULL, NULL); ((unsigned char *)(*checksum)->digest)[i] = (( isalpha(hex[i*2]) ? hex[i*2] - 'a' + 10 : hex[i*2] - '0') << 4) | ( isalpha(hex[i*2+1]) ? hex[i*2+1] - 'a' + 10 : hex[i*2+1] - '0'); is_zeros |= (*checksum)->digest[i]; } if (is_zeros == '\0') *checksum = NULL; return SVN_NO_ERROR; }
svn_error_t * svn_checksum_final(svn_checksum_t **checksum, const svn_checksum_ctx_t *ctx, apr_pool_t *pool) { *checksum = svn_checksum_create(ctx->kind, pool); switch (ctx->kind) { case svn_checksum_md5: apr_md5_final((unsigned char *)(*checksum)->digest, ctx->apr_ctx); break; case svn_checksum_sha1: 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); } return SVN_NO_ERROR; }