/** * Decrypt the string given as per the current config. * * Returns APR_SUCCESS if successful. */ static apr_status_t decrypt_string(request_rec * r, const apr_crypto_t *f, session_crypto_dir_conf *dconf, const char *in, char **out) { apr_status_t res; apr_crypto_key_t *key = NULL; apr_size_t ivSize = 0; apr_crypto_block_t *block = NULL; unsigned char *decrypted = NULL; apr_size_t decryptedlen, tlen; apr_size_t decodedlen; char *decoded; apr_size_t blockSize = 0; apr_crypto_block_key_type_e *cipher; int i = 0; /* strip base64 from the string */ decoded = apr_palloc(r->pool, apr_base64_decode_len(in)); decodedlen = apr_base64_decode(decoded, in); decoded[decodedlen] = '\0'; res = crypt_init(r, f, &cipher, dconf); if (res != APR_SUCCESS) { return res; } /* try each passphrase in turn */ for (; i < dconf->passphrases->nelts; i++) { const char *passphrase = APR_ARRAY_IDX(dconf->passphrases, i, char *); apr_size_t len = decodedlen; char *slider = decoded; /* encrypt using the first passphrase in the list */ res = apr_crypto_passphrase(&key, &ivSize, passphrase, strlen(passphrase), (unsigned char *)decoded, sizeof(apr_uuid_t), *cipher, APR_MODE_CBC, 1, 4096, f, r->pool); if (APR_STATUS_IS_ENOKEY(res)) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, res, r, APLOGNO(01832) "the passphrase '%s' was empty", passphrase); continue; } else if (APR_STATUS_IS_EPADDING(res)) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, res, r, APLOGNO(01833) "padding is not supported for cipher"); continue; } else if (APR_STATUS_IS_EKEYTYPE(res)) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, res, r, APLOGNO(01834) "the key type is not known"); continue; } else if (APR_SUCCESS != res) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, res, r, APLOGNO(01835) "encryption could not be configured."); continue; } /* sanity check - decoded too short? */ if (decodedlen < (sizeof(apr_uuid_t) + ivSize)) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, APLOGNO(01836) "too short to decrypt, skipping"); res = APR_ECRYPT; continue; } /* bypass the salt at the start of the decoded block */ slider += sizeof(apr_uuid_t); len -= sizeof(apr_uuid_t); res = apr_crypto_block_decrypt_init(&block, &blockSize, (unsigned char *)slider, key, r->pool); if (APR_SUCCESS != res) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, res, r, APLOGNO(01837) "apr_crypto_block_decrypt_init failed"); continue; } /* bypass the iv at the start of the decoded block */ slider += ivSize; len -= ivSize; /* decrypt the given string */ res = apr_crypto_block_decrypt(&decrypted, &decryptedlen, (unsigned char *)slider, len, block); if (res) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, res, r, APLOGNO(01838) "apr_crypto_block_decrypt failed"); continue; } *out = (char *) decrypted; res = apr_crypto_block_decrypt_finish(decrypted + decryptedlen, &tlen, block); if (APR_SUCCESS != res) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, res, r, APLOGNO(01839) "apr_crypto_block_decrypt_finish failed"); continue; } decryptedlen += tlen; decrypted[decryptedlen] = 0; break; } if (APR_SUCCESS != res) { ap_log_rerror(APLOG_MARK, APLOG_INFO, res, r, APLOGNO(01840) "decryption failed"); } return res; }
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 */ }
static unsigned char *decrypt_block(abts_case *tc, apr_pool_t *pool, const apr_crypto_driver_t *driver, const apr_crypto_t *f, const apr_crypto_key_t *key, unsigned char *cipherText, apr_size_t cipherTextLen, unsigned char **plainText, apr_size_t *plainTextLen, const unsigned char *iv, apr_size_t *blockSize, const char *description) { apr_crypto_block_t *block = NULL; const apu_err_t *result = NULL; apr_size_t len = 0; apr_status_t rv; if (!driver || !f || !key || !cipherText) { return NULL; } /* init the decryption */ rv = apr_crypto_block_decrypt_init(pool, f, key, iv, &block, blockSize); if (APR_ENOTIMPL == rv) { ABTS_NOT_IMPL(tc, "apr_crypto_block_decrypt_init returned APR_ENOTIMPL"); } else { if (APR_SUCCESS != rv) { apr_crypto_error(f, &result); fprintf(stderr, "decrypt_init: %s %s native error %d: %s (%s)\n", description, apr_crypto_driver_name(driver), result->rc, result->reason ? result->reason : "", result->msg ? result->msg : ""); } ABTS_ASSERT(tc, "apr_crypto_block_decrypt_init returned APR_ENOKEY", rv != APR_ENOKEY); ABTS_ASSERT(tc, "apr_crypto_block_decrypt_init returned APR_ENOIV", rv != APR_ENOIV); ABTS_ASSERT(tc, "apr_crypto_block_decrypt_init returned APR_EKEYTYPE", rv != APR_EKEYTYPE); ABTS_ASSERT(tc, "apr_crypto_block_decrypt_init returned APR_EKEYLENGTH", rv != APR_EKEYLENGTH); ABTS_ASSERT(tc, "failed to apr_crypto_block_decrypt_init", rv == APR_SUCCESS); ABTS_ASSERT(tc, "apr_crypto_block_decrypt_init returned NULL context", block != NULL); } if (!block || rv) { return NULL; } /* decrypt the block */ rv = apr_crypto_block_decrypt(f, block, plainText, plainTextLen, cipherText, cipherTextLen); if (APR_SUCCESS != rv) { apr_crypto_error(f, &result); fprintf(stderr, "decrypt: %s %s native error %d: %s (%s)\n", description, apr_crypto_driver_name(driver), result->rc, result->reason ? result->reason : "", result->msg ? result->msg : ""); } ABTS_ASSERT(tc, "apr_crypto_block_decrypt returned APR_ECRYPT", rv != APR_ECRYPT); ABTS_ASSERT(tc, "failed to apr_crypto_block_decrypt", rv == APR_SUCCESS); ABTS_ASSERT(tc, "apr_crypto_block_decrypt failed to allocate buffer", *plainText != NULL); if (rv) { return NULL; } /* finalise the decryption */ rv = apr_crypto_block_decrypt_finish(f, block, *plainText + *plainTextLen, &len); if (APR_SUCCESS != rv) { apr_crypto_error(f, &result); fprintf(stderr, "decrypt_finish: %s %s native error %d: %s (%s)\n", description, apr_crypto_driver_name(driver), result->rc, result->reason ? result->reason : "", result->msg ? result->msg : ""); } ABTS_ASSERT(tc, "apr_crypto_block_decrypt_finish returned APR_ECRYPT", rv != APR_ECRYPT); ABTS_ASSERT(tc, "apr_crypto_block_decrypt_finish returned APR_EPADDING", rv != APR_EPADDING); ABTS_ASSERT(tc, "failed to apr_crypto_block_decrypt_finish", rv == APR_SUCCESS); if (rv) { return NULL; } *plainTextLen += len; apr_crypto_block_cleanup(f, block); return *plainText; }
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 */ }