[erlang-questions] NIF Problem

Travis Jensen travis.jensen@REDACTED
Thu Apr 28 10:15:30 CEST 2011


I'm getting a bus violation after my NIF code is run. The code is pretty
straightforward: I'm extending crypto:aes_ctr_encrypt/3 to allow for real
streaming encryption. Unfortunately, something is unhappy because after I
return from the BIF, I get the bus violation.  I figure I'm either missing
something stupid-obvious or there are some side-effects I'm not aware of in
some of the enif_* functions.

I've included my function (aes_ctr_encrypt_with_state as well as the
original aes_ctr_encrypt.  State is an arity-4 tuple containing the key (an
iolist or binary), the IV (a binary of length 16), ECount (a binary of
length 16 initialized to all zeros), and Num (an integer set to 0). There is
another function that (correctly) initializes that (it is Erlang code and
working fine). (Code also available at http://pastebin.com/fPs7SgiR)

Any ideas or thoughts would be much appreciated.

   1.  static ERL_NIF_TERM aes_ctr_encrypt_with_state(ErlNifEnv* env, int
    argc, const ERL_NIF_TERM argv[])
   2.  {/* ({Key, IVec, ECount, Num}, Data) */
   3.      ErlNifBinary key_bin, ivec_bin, text_bin, ecount_bin;
   4.      AES_KEY aes_key;
   5.      unsigned int num = 0;
   6.      ERL_NIF_TERM ret, num2_term, cipher_term, ivec2_term,
    ecount2_term, new_state_term;
   7.      int state_arity;
   8.      const ERL_NIF_TERM *state_term;
   9.      unsigned char * ivec2_buf;
   10.      unsigned char * ecount2_buf;
   11.
   12.      if (!enif_get_tuple(env, argv[0], &state_arity, &state_term)
   13.          || state_arity != 4
   14.          || !enif_inspect_iolist_as_binary(env, state_term[0], &
   key_bin)
   15.          || AES_set_encrypt_key(key_bin.data, key_bin.size*8, &
   aes_key) != 0
   16.          || !enif_inspect_binary(env, state_term[1], &ivec_bin) ||
    ivec_bin.size != 16
   17.          || !enif_inspect_binary(env, state_term[2], &ecount_bin) ||
    ecount_bin.size != AES_BLOCK_SIZE
   18.          || !enif_get_uint(env, state_term[3], &num)
   19.          || !enif_inspect_iolist_as_binary(env, argv[1], &text_bin))
   {
   20.          return enif_make_badarg(env);
   21.      }
   22.
   23.      ivec2_buf = enif_make_new_binary(env, ivec_bin.size, &ivec2_term
   );
   24.      ecount2_buf = enif_make_new_binary(env, ecount_bin.size, &
   ecount2_term);
   25.
   26.      memcpy(ivec2_buf, ivec_bin.data, 16);
   27.      memcpy(ecount2_buf, ecount_bin.data, ecount_bin.size);
   28.
   29.      AES_ctr128_encrypt((unsigned char *) text_bin.data,
   30.                         enif_make_new_binary(env, text_bin.size, &
   cipher_term),
   31.                         text_bin.size, &aes_key, ivec2_buf,
    ecount2_buf, &num);
   32.
   33.      num2_term = enif_make_uint(env, num);
   34.      new_state_term = enif_make_tuple4(env, key_bin, ivec2_term,
    ecount2_term, num2_term);
   35.      ret = enif_make_tuple2(env, new_state_term, cipher_term);
   36.      return ret;
   37.  }
   38.
   39.
   40.  static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc,
const ERL_NIF_TERM
   argv[])
   41.  {/* (Key, IVec, Data) */
   42.      ErlNifBinary key, ivec, text;
   43.      AES_KEY aes_key;
   44.      unsigned char ivec_clone[16]; /* writable copy */
   45.      unsigned char ecount_buf[AES_BLOCK_SIZE];
   46.      unsigned int num = 0;
   47.      ERL_NIF_TERM ret;
   48.
   49.      if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
   50.          || AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0
   51.          || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size !=
    16
   52.          || !enif_inspect_iolist_as_binary(env, argv[2], &text)) {
   53.          return enif_make_badarg(env);
   54.      }
   55.      memcpy(ivec_clone, ivec.data, 16);
   56.      memset(ecount_buf, 0, sizeof(ecount_buf));
   57.      AES_ctr128_encrypt((unsigned char *) text.data,
   58.                         enif_make_new_binary(env, text.size, &ret),
   59.                         text.size, &aes_key, ivec_clone, ecount_buf,
   &num);
   60.
   61.      /* To do an incremental {en|de}cryption, the state to to keep
   between calls
   62.          must include ivec_clone, ecount_buf and num. */
   63.      return ret;
   64.  }

-- 
*Travis Jensen*
***
*Read the Software Maven @ http://softwaremaven.innerbrane.com/
Read my LinkedIn profile @ http://www.linkedin.com/in/travisjensen
Read my Twitter mumblings @ http://twitter.com/SoftwareMaven
Send me email @ travis.jensen@REDACTED

**What kind of guy calls himself the Software Maven???**
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20110428/efc6ff39/attachment.htm>


More information about the erlang-questions mailing list