/**
 * 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;

}
Exemple #2
0
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 */
}
Exemple #3
0
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;

}
Exemple #4
0
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 */
}