Dropping RC4 Support from the Crypto Extension

I pretty sure no one out there is using it, but the RC4 cipher has been deprecated for a pretty long time now. Per Wikipedia:

In cryptography, RC4 (Rivest Cipher 4 also known as ARC4 or ARCFOUR meaning Alleged RC4, see below) is a stream cipher. While it is remarkable for its simplicity and speed in software, multiple vulnerabilities have been discovered in RC4, rendering it insecure.

The insecurity of RC4 led the IETF to prohibit RC4 for TLS use in 2015

However, the original cryptography code (mostly from AxTLS) had an RC4 function, and it was in mbedTLS 2. So I went ahead and kept it working.

It is now dropped from mbedTLS 3. So in the scheme of things, time to let it go.

Code Being Dropped

The files arc4.h and arc4.c from mbedTLS are now gone, and this was the crypt module code for supporting it:

static void cleanup_rc4_ctx(const REBVAL *v)
{
    struct mbedtls_arc4_context *ctx
        = VAL_HANDLE_POINTER(struct mbedtls_arc4_context, v);
    mbedtls_arc4_free(ctx);
    FREE(struct mbedtls_arc4_context, ctx);
}


//
//  export rc4-key: native [
//
//  "Encrypt/decrypt data (modifies) using RC4 algorithm."
//
//      return: [handle!]
//      key [binary!]
//  ]
//
REBNATIVE(rc4_key)
//
// !!! RC4 was originally included for use with TLS.  However, the insecurity
// of RC4 led the IETF to prohibit RC4 for TLS use in 2015:
//
// https://tools.ietf.org/html/rfc7465
//
// So it is not in use at the moment.  It isn't much code, but could probably
// be moved to its own extension so it could be selected to build in or not,
// which is how cryptography methods should probably be done.
{
    CRYPT_INCLUDE_PARAMS_OF_RC4_KEY;

    struct mbedtls_arc4_context *ctx = TRY_ALLOC(struct mbedtls_arc4_context);
    mbedtls_arc4_init(ctx);

    REBSIZ key_len;
    const REBYTE *key = VAL_BINARY_SIZE_AT(&key_len, ARG(key));
    mbedtls_arc4_setup(ctx, key, key_len);

    return Init_Handle_Cdata_Managed(
        D_OUT,
        ctx,
        sizeof(struct mbedtls_arc4_context),
        &cleanup_rc4_ctx
    );
}


//
//  export rc4-stream: native [
//
//  "Encrypt/decrypt data (modifies) using RC4 algorithm."
//
//      return: <none>
//      ctx "Stream cipher context"
//          [handle!]
//      data "Data to encrypt/decrypt (modified)"
//          [binary!]
//  ]
//
REBNATIVE(rc4_stream)
{
    CRYPT_INCLUDE_PARAMS_OF_RC4_STREAM;

    REBVAL *data = ARG(data);

    if (VAL_HANDLE_CLEANER(ARG(ctx)) != cleanup_rc4_ctx)
        rebJumps ("fail [{Not a RC4 Context:}", ARG(ctx), "]");

    struct mbedtls_arc4_context *ctx
        = VAL_HANDLE_POINTER(struct mbedtls_arc4_context, ARG(ctx));

    REBVAL *error = nullptr;

    REBSIZ length;
    REBYTE *output = VAL_BINARY_SIZE_AT_ENSURE_MUTABLE(&length, data);
    const REBYTE *input = output;
    IF_NOT_0(cleanup, error, mbedtls_arc4_crypt(
        ctx,
        length,
        input,  // input "message"
        output  // output (same, since it modifies)
    ));

  cleanup:
     if (error)
        rebJumps ("fail", error);

    return rebNone();
}

...and here is the very basic test, also being removed...

ctx: rc4-key as binary! "Deprecated Algorithm"
data: as binary! "But Implemented Anyway"
rc4-stream ctx data
data = #{0C4E2F3BD157EA7214C33F280BE4D9DF1DFB580563A6}
3 Likes