static svn_error_t * test_pseudo_md5(apr_pool_t *pool) { apr_uint32_t input[16] = { 0 }; apr_uint32_t digest_15[4] = { 0 }; apr_uint32_t digest_31[4] = { 0 }; apr_uint32_t digest_63[4] = { 0 }; svn_checksum_t *checksum; /* input is all 0s but the hash shall be different (due to different input sizes)*/ svn__pseudo_md5_15(digest_15, input); svn__pseudo_md5_31(digest_31, input); svn__pseudo_md5_63(digest_63, input); SVN_TEST_ASSERT(memcmp(digest_15, digest_31, sizeof(digest_15))); SVN_TEST_ASSERT(memcmp(digest_15, digest_63, sizeof(digest_15))); SVN_TEST_ASSERT(memcmp(digest_31, digest_63, sizeof(digest_15))); /* the checksums shall also be different from "proper" MD5 */ SVN_ERR(svn_checksum(&checksum, svn_checksum_md5, input, 15, pool)); SVN_TEST_ASSERT(memcmp(digest_15, checksum->digest, sizeof(digest_15))); SVN_ERR(svn_checksum(&checksum, svn_checksum_md5, input, 31, pool)); SVN_TEST_ASSERT(memcmp(digest_31, checksum->digest, sizeof(digest_15))); SVN_ERR(svn_checksum(&checksum, svn_checksum_md5, input, 63, pool)); SVN_TEST_ASSERT(memcmp(digest_63, checksum->digest, sizeof(digest_15))); return SVN_NO_ERROR; }
svn_error_t * svn_auth__file_path(const char **path, const char *cred_kind, const char *realmstring, const char *config_dir, apr_pool_t *pool) { const char *authdir_path, *hexname; svn_checksum_t *checksum; /* Construct the path to the directory containing the creds files, e.g. "~/.subversion/auth/svn.simple". The last component is simply the cred_kind. */ SVN_ERR(svn_config_get_user_config_path(&authdir_path, config_dir, SVN_CONFIG__AUTH_SUBDIR, pool)); if (authdir_path) { authdir_path = svn_dirent_join(authdir_path, cred_kind, pool); /* Construct the basename of the creds file. It's just the realmstring converted into an md5 hex string. */ SVN_ERR(svn_checksum(&checksum, svn_checksum_md5, realmstring, strlen(realmstring), pool)); hexname = svn_checksum_to_cstring(checksum, pool); *path = svn_dirent_join(authdir_path, hexname, pool); } else *path = NULL; return SVN_NO_ERROR; }
/* Escape ACTIVITY_ID to be safely usable as a filename. Simply returns the MD5 checksum of the id. */ static const char * escape_activity(const char *activity_id, apr_pool_t *pool) { svn_checksum_t *checksum; svn_error_clear(svn_checksum(&checksum, svn_checksum_md5, activity_id, strlen(activity_id), pool)); return svn_checksum_to_cstring_display(checksum, pool); }
static svn_error_t * test_checksum_empty(apr_pool_t *pool) { svn_checksum_t *checksum; char data = '\0'; checksum = svn_checksum_empty_checksum(svn_checksum_md5, pool); SVN_TEST_ASSERT(svn_checksum_is_empty_checksum(checksum)); checksum = svn_checksum_empty_checksum(svn_checksum_sha1, pool); SVN_TEST_ASSERT(svn_checksum_is_empty_checksum(checksum)); SVN_ERR(svn_checksum(&checksum, svn_checksum_md5, &data, 0, pool)); SVN_TEST_ASSERT(svn_checksum_is_empty_checksum(checksum)); SVN_ERR(svn_checksum(&checksum, svn_checksum_sha1, &data, 0, pool)); SVN_TEST_ASSERT(svn_checksum_is_empty_checksum(checksum)); return SVN_NO_ERROR; }
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; }
/* Set *DIGEST to the MD5 hash of STR. */ static svn_error_t * make_digest(const char **digest, const char *str, apr_pool_t *pool) { svn_checksum_t *checksum; SVN_ERR(svn_checksum(&checksum, svn_checksum_md5, str, strlen(str), pool)); *digest = svn_checksum_to_cstring_display(checksum, pool); return SVN_NO_ERROR; }
/* Generate the string CACHE_ID_P based on the REALMSTRING allocated in * RESULT_POOL using SCRATCH_POOL for temporary allocations. This is similar * to other password caching mechanisms. */ static svn_error_t * get_cache_id(const char **cache_id_p, const char *realmstring, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { const char *cache_id = NULL; svn_checksum_t *digest = NULL; SVN_ERR(svn_checksum(&digest, svn_checksum_md5, realmstring, strlen(realmstring), scratch_pool)); cache_id = svn_checksum_to_cstring(digest, result_pool); *cache_id_p = cache_id; return SVN_NO_ERROR; }
/* Set *MC_KEY to a memcache key for the given key KEY for CACHE, allocated in POOL. */ static svn_error_t * build_key(const char **mc_key, memcache_t *cache, const void *raw_key, apr_pool_t *pool) { const char *encoded_suffix; const char *long_key; apr_size_t long_key_len; if (cache->klen == APR_HASH_KEY_STRING) encoded_suffix = svn_path_uri_encode(raw_key, pool); else { const svn_string_t *raw = svn_string_ncreate(raw_key, cache->klen, pool); const svn_string_t *encoded = svn_base64_encode_string2(raw, FALSE, pool); encoded_suffix = encoded->data; } long_key = apr_pstrcat(pool, "SVN:", cache->prefix, ":", encoded_suffix, (char *)NULL); long_key_len = strlen(long_key); /* We don't want to have a key that's too big. If it was going to be too big, we MD5 the entire string, then replace the last bit with the checksum. Note that APR_MD5_DIGESTSIZE is for the pure binary digest; we have to double that when we convert to hex. Every key we use will either be at most MEMCACHED_KEY_UNHASHED_LEN bytes long, or be exactly MAX_MEMCACHED_KEY_LEN bytes long. */ if (long_key_len > MEMCACHED_KEY_UNHASHED_LEN) { svn_checksum_t *checksum; SVN_ERR(svn_checksum(&checksum, svn_checksum_md5, long_key, long_key_len, pool)); long_key = apr_pstrcat(pool, apr_pstrmemdup(pool, long_key, MEMCACHED_KEY_UNHASHED_LEN), svn_checksum_to_cstring_display(checksum, pool), (char *)NULL); } *mc_key = long_key; return SVN_NO_ERROR; }
static svn_error_t * stream_window_test(const char **msg, svn_boolean_t msg_only, svn_test_opts_t *opts, apr_pool_t *pool) { /* Note: put these in data segment, not the stack */ static char source[109001]; static char target[109001]; int i; char *p = &source[9]; svn_checksum_t *expected; svn_checksum_t *actual; svn_string_t source_str; svn_string_t target_str; svn_stream_t *source_stream; svn_stream_t *target_stream; svn_txdelta_stream_t *txstream; *msg = "txdelta stream and windows test"; if (msg_only) return SVN_NO_ERROR; memcpy(source, "a\nb\nc\nd\ne", 9); for (i = 100; i--; ) *p++ = '\n'; for (i = 999; i--; p += 109) memcpy(p, source, 109); source[109000] = '\0'; memcpy(target, source, 109001); for (i = 1000; i--; ) target[i*109 + 4] = 'X'; SVN_ERR(svn_checksum(&expected, svn_checksum_md5, target, 109000, pool)); /* f6fd44565e14c6e44b35292719deb77e */ printf("expected: %s\n", svn_checksum_to_cstring(expected, pool)); source_str.data = source; source_str.len = 109000; source_stream = svn_stream_from_string(&source_str, pool); target_str.data = target; target_str.len = 109000; target_stream = svn_stream_from_string(&target_str, pool); svn_txdelta(&txstream, source_stream, target_stream, pool); while (1) { svn_txdelta_window_t *window; SVN_ERR(svn_txdelta_next_window(&window, txstream, pool)); if (window == NULL) break; /* ### examine the window */ } actual = svn_checksum__from_digest(svn_txdelta_md5_digest(txstream), svn_checksum_md5, pool);; printf(" actual: %s\n", svn_checksum_to_cstring(actual, pool)); if (!svn_checksum_match(expected, actual)) { return svn_error_create(SVN_ERR_TEST_FAILED, NULL, "Checksums did not match."); } return SVN_NO_ERROR; }
svn_error_t * svn_crypto__verify_secret(svn_boolean_t *is_valid, svn_crypto__ctx_t *ctx, const svn_string_t *master, const svn_string_t *ciphertext, const svn_string_t *iv, const svn_string_t *salt, const char *checktext, apr_pool_t *scratch_pool) { #ifdef SVN_HAVE_CRYPTO svn_error_t *err = SVN_NO_ERROR; apr_status_t apr_err; apr_crypto_block_t *block_ctx = NULL; apr_size_t block_size, iv_len; apr_crypto_key_t *key = NULL; unsigned char *result; apr_size_t result_len = 0, final_len = 0; svn_checksum_t *result_sum; *is_valid = FALSE; /* Initialize the passphrase. */ apr_err = apr_crypto_passphrase(&key, &iv_len, master->data, master->len, (unsigned char *)salt->data, salt->len, APR_KEY_AES_256, APR_MODE_CBC, FALSE /* doPad */, NUM_ITERATIONS, ctx->crypto, scratch_pool); if (apr_err != APR_SUCCESS) return svn_error_trace(crypto_error_create( ctx, apr_err, _("Error creating derived key"))); if (! key) return svn_error_create(APR_EGENERAL, NULL, _("Error creating derived key")); if (iv_len == 0) return svn_error_create(APR_EGENERAL, NULL, _("Unexpected IV length returned")); if (iv_len != iv->len) return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL, _("Provided IV has incorrect length")); apr_err = apr_crypto_block_decrypt_init(&block_ctx, &block_size, (unsigned char *)iv->data, key, scratch_pool); if ((apr_err != APR_SUCCESS) || (! block_ctx)) return svn_error_trace(crypto_error_create( ctx, apr_err, _("Error initializing block decryption"))); apr_err = apr_crypto_block_decrypt(NULL, &result_len, (unsigned char *)ciphertext->data, ciphertext->len, block_ctx); if (apr_err != APR_SUCCESS) { err = crypto_error_create(ctx, apr_err, _("Error fetching result length")); goto cleanup; } result = apr_palloc(scratch_pool, result_len); apr_err = apr_crypto_block_decrypt(&result, &result_len, (unsigned char *)ciphertext->data, ciphertext->len, block_ctx); if (apr_err != APR_SUCCESS) { err = crypto_error_create(ctx, apr_err, _("Error during block decryption")); goto cleanup; } apr_err = apr_crypto_block_decrypt_finish(result + result_len, &final_len, block_ctx); if (apr_err != APR_SUCCESS) { err = crypto_error_create(ctx, apr_err, _("Error finalizing block decryption")); goto cleanup; } /* ### FIXME: This should be a SHA-256. */ SVN_ERR(svn_checksum(&result_sum, svn_checksum_sha1, result, result_len + final_len, scratch_pool)); *is_valid = strcmp(checktext, svn_checksum_to_cstring(result_sum, scratch_pool)) == 0; cleanup: apr_crypto_block_cleanup(block_ctx); return err; #else /* SVN_HAVE_CRYPTO */ *is_valid = FALSE; return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, "Cryptographic support is not available"); #endif /* SVN_HAVE_CRYPTO */ }
svn_error_t * svn_crypto__generate_secret_checktext(const svn_string_t **ciphertext, const svn_string_t **iv, const svn_string_t **salt, const char **checktext, svn_crypto__ctx_t *ctx, const svn_string_t *master, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { #ifdef SVN_HAVE_CRYPTO svn_error_t *err = SVN_NO_ERROR; const unsigned char *salt_vector; const unsigned char *iv_vector; const unsigned char *stuff_vector; apr_size_t iv_len; apr_crypto_key_t *key = NULL; apr_status_t apr_err; apr_crypto_block_t *block_ctx = NULL; apr_size_t block_size; apr_size_t result_len; unsigned char *result; apr_size_t ignored_result_len = 0; apr_size_t stuff_len; svn_checksum_t *stuff_sum; SVN_ERR_ASSERT(ctx != NULL); /* Generate the salt. */ SVN_ERR(get_random_bytes(&salt_vector, ctx, SALT_LEN, result_pool)); /* Initialize the passphrase. */ apr_err = apr_crypto_passphrase(&key, &iv_len, master->data, master->len, salt_vector, SALT_LEN, APR_KEY_AES_256, APR_MODE_CBC, FALSE /* doPad */, NUM_ITERATIONS, ctx->crypto, scratch_pool); if (apr_err != APR_SUCCESS) return svn_error_trace(crypto_error_create( ctx, apr_err, _("Error creating derived key"))); if (! key) return svn_error_create(APR_EGENERAL, NULL, _("Error creating derived key")); if (iv_len == 0) return svn_error_create(APR_EGENERAL, NULL, _("Unexpected IV length returned")); /* Generate the proper length IV. */ SVN_ERR(get_random_bytes(&iv_vector, ctx, iv_len, result_pool)); /* Initialize block encryption. */ apr_err = apr_crypto_block_encrypt_init(&block_ctx, &iv_vector, key, &block_size, scratch_pool); if ((apr_err != APR_SUCCESS) || (! block_ctx)) return svn_error_trace(crypto_error_create( ctx, apr_err, _("Error initializing block encryption"))); /* Generate a blob of random data, block-aligned per the requirements of the encryption algorithm, but with a minimum size of our choosing. */ #define MIN_STUFF_LEN 32 if (MIN_STUFF_LEN % block_size) stuff_len = MIN_STUFF_LEN + (block_size - (MIN_STUFF_LEN % block_size)); else stuff_len = MIN_STUFF_LEN; SVN_ERR(get_random_bytes(&stuff_vector, ctx, stuff_len, scratch_pool)); /* ### FIXME: This should be a SHA-256. */ SVN_ERR(svn_checksum(&stuff_sum, svn_checksum_sha1, stuff_vector, stuff_len, scratch_pool)); /* Get the length that we need to allocate. */ apr_err = apr_crypto_block_encrypt(NULL, &result_len, stuff_vector, stuff_len, block_ctx); if (apr_err != APR_SUCCESS) { err = crypto_error_create(ctx, apr_err, _("Error fetching result length")); goto cleanup; } /* Allocate our result buffer. */ result = apr_palloc(result_pool, result_len); /* Encrypt the block. */ apr_err = apr_crypto_block_encrypt(&result, &result_len, stuff_vector, stuff_len, block_ctx); if (apr_err != APR_SUCCESS) { err = crypto_error_create(ctx, apr_err, _("Error during block encryption")); goto cleanup; } /* Finalize the block encryption. Since we padded everything, this should not produce any more encrypted output. */ apr_err = apr_crypto_block_encrypt_finish(NULL, &ignored_result_len, block_ctx); if (apr_err != APR_SUCCESS) { err = crypto_error_create(ctx, apr_err, _("Error finalizing block encryption")); goto cleanup; } *ciphertext = wrap_as_string(result, result_len, result_pool); *iv = wrap_as_string(iv_vector, iv_len, result_pool); *salt = wrap_as_string(salt_vector, SALT_LEN, result_pool); *checktext = svn_checksum_to_cstring(stuff_sum, result_pool); cleanup: apr_crypto_block_cleanup(block_ctx); return err; #else /* SVN_HAVE_CRYPTO */ return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, "Cryptographic support is not available"); #endif /* SVN_HAVE_CRYPTO */ }