Alien-SVN
view release on metacpan or search on metacpan
src/subversion/subversion/libsvn_subr/crypto.c view on Meta::CPAN
_("OpenSSL crypto driver error"));
if (driver == NULL)
return svn_error_create(APR_EGENERAL,
err_from_apu_err(APR_EGENERAL, apu_err),
_("Bad return value while loading crypto "
"driver"));
apr_err = apr_crypto_make(&apr_crypto, driver, NULL, result_pool);
if (apr_err != APR_SUCCESS || apr_crypto == NULL)
return svn_error_create(apr_err, NULL,
_("Error creating OpenSSL crypto context"));
/* Allocate and initialize our crypto context. */
*ctx = apr_palloc(result_pool, sizeof(**ctx));
(*ctx)->crypto = apr_crypto;
return SVN_NO_ERROR;
#else /* SVN_HAVE_CRYPTO */
return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
"Cryptographic support is not available");
#endif /* SVN_HAVE_CRYPTO */
}
svn_error_t *
svn_crypto__encrypt_password(const svn_string_t **ciphertext,
const svn_string_t **iv,
const svn_string_t **salt,
svn_crypto__ctx_t *ctx,
const char *password,
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;
apr_size_t iv_len;
apr_crypto_key_t *key = NULL;
apr_status_t apr_err;
const unsigned char *prefix;
apr_crypto_block_t *block_ctx = NULL;
apr_size_t block_size;
unsigned char *assembled;
apr_size_t password_len, assembled_len = 0;
apr_size_t result_len;
unsigned char *result;
apr_size_t ignored_result_len = 0;
SVN_ERR_ASSERT(ctx != NULL);
/* Generate the salt. */
#define SALT_LEN 8
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 4-byte prefix. */
SVN_ERR(get_random_bytes(&prefix, ctx, RANDOM_PREFIX_LEN, scratch_pool));
/* Combine our prefix, original password, and appropriate padding.
We won't bother padding if the prefix and password combined
perfectly align on the block boundary. If they don't,
however, we'll drop a NUL byte after the password and pad with
random stuff after that to the block boundary. */
password_len = strlen(password);
assembled_len = RANDOM_PREFIX_LEN + password_len;
if ((assembled_len % block_size) == 0)
{
assembled = apr_palloc(scratch_pool, assembled_len);
memcpy(assembled, prefix, RANDOM_PREFIX_LEN);
memcpy(assembled + RANDOM_PREFIX_LEN, password, password_len);
}
else
{
const unsigned char *padding;
apr_size_t pad_len = block_size - (assembled_len % block_size) - 1;
SVN_ERR(get_random_bytes(&padding, ctx, pad_len, scratch_pool));
assembled_len = assembled_len + 1 + pad_len;
assembled = apr_palloc(scratch_pool, assembled_len);
memcpy(assembled, prefix, RANDOM_PREFIX_LEN);
memcpy(assembled + RANDOM_PREFIX_LEN, password, password_len);
*(assembled + RANDOM_PREFIX_LEN + password_len) = '\0';
memcpy(assembled + RANDOM_PREFIX_LEN + password_len + 1,
padding, pad_len);
}
/* Get the length that we need to allocate. */
apr_err = apr_crypto_block_encrypt(NULL, &result_len, assembled,
assembled_len, block_ctx);
if (apr_err != APR_SUCCESS)
src/subversion/subversion/libsvn_subr/crypto.c view on Meta::CPAN
/* Encrypt the block. */
apr_err = apr_crypto_block_encrypt(&result, &result_len, assembled,
assembled_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);
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 */
}
svn_error_t *
svn_crypto__decrypt_password(const char **plaintext,
svn_crypto__ctx_t *ctx,
const svn_string_t *ciphertext,
const svn_string_t *iv,
const svn_string_t *salt,
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;
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;
/* 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;
}
/* Copy the non-random bits of the resulting plaintext, skipping the
prefix and ignoring any trailing padding. */
*plaintext = apr_pstrndup(result_pool,
(const char *)(result + RANDOM_PREFIX_LEN),
result_len + final_len - RANDOM_PREFIX_LEN);
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 */
}
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 */
}
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;
( run in 0.562 second using v1.01-cache-2.11-cpan-39bf76dae61 )