Puck.js Crashes w/ Custom Firmware

Posted on
  • I have built a new firmware for the Puck.js in order to add a C function that does some Elliptic Curve math that would be too slow in JS. I have gotten this firmware to build and load onto the puck successfully, but when I try to run the function I wrote it crashes for some reason (puck becomes unresponsive, disconnects from Web IDE). The function is included below for reference. I used LED lighting to narrow down where exactly it stops working and it appears to be on the line with "mbedtls_ecp_group_load".

    When I build Espruino with a LINUX target, this code works completely fine, so there doesn't appear to be anything wrong with the code itself. I'm having trouble debugging what could be wrong here. Is there any way to attach a debugger to the Puck or something else I could do here? It seems very difficult to debug C code on the Puck because if anything goes wrong it just disconnects from the Web IDE.

    Thank you.

    /*JSON{
      "type" : "staticmethod",
      "class" : "crypto",
      "name" : "PointGen",
      "generate" : "jswrap_crypto_PointGen",
      "params" : [
        ["pkey","JsVar","Private key to multiply P-224 generator with, should be a string up to 100 chars"]
      ],
      "return" : ["JsVar","Returns an X coordinate string"],
      "ifdef" : "USE_TLS"
    }
    
    Key generator
    */
    JsVar *jswrap_crypto_PointGen(JsVar * pkey){
    
      jshPinOutput(LED1_PININDEX, 1);
    
      //jsiConsolePrintf("Allocating buffers...\n");
      char* pkeystr = malloc(20);
      char* outputbuf = malloc(80);
    
    
    
      //jsiConsolePrintf("Retrieving string from jvar...\n");
      jsvGetString(pkey, pkeystr, 19);
    
      //jsiConsolePrintf("%s\n", pkeystr);
    
      mbedtls_mpi * mpikey = malloc(sizeof(mbedtls_mpi));
      mbedtls_mpi_init(mpikey);
    
     
    
      //jsiConsolePrintf("Converting to MPI...\n");
      int ret = mbedtls_mpi_read_string(mpikey, 10, pkeystr);
      if(ret != 0)
      {
        return jsvVarPrintf("MPI READ - %d\n", ret);
      }
    
      mbedtls_ecp_group * grp = malloc(sizeof(mbedtls_ecp_group));
    
      jshPinOutput(LED2_PININDEX, 1);
    
      //jsiConsolePrintf("Loading group parameters...\n");
      ret = mbedtls_ecp_group_load(grp, MBEDTLS_ECP_DP_SECP224R1);
      if(ret != 0)
      {
        jshPinOutput(LED2_PININDEX, 0);
        jshPinOutput(LED3_PININDEX, 1);
        return jsvVarPrintf("GROUP LOAD FAILED - %d\n", ret);
      }
    
      jshPinOutput(LED3_PININDEX, 1);
    
      mbedtls_ecp_point * pt = malloc(sizeof(mbedtls_ecp_point));
      mbedtls_ecp_point_init(pt);
    
      //jsiConsolePrintf("Multiplying points...\n");
      ret = mbedtls_ecp_mul(grp, pt, mpikey, &grp->G, NULL, NULL);
      if(ret != 0)
      {
        return jsvVarPrintf("ECP MUL - %d\n", ret);
      }
    
      //jsiConsolePrintf("Writing to string...\n");
      size_t outputlen;
      ret = mbedtls_mpi_write_string(&pt->X, 10, outputbuf, 120, &outputlen);
      if(ret != 0)
      {
        return jsvVarPrintf("MPI WRITE - %d\n", ret);
      }
    
      JsVar * returnstring = jsvNewFromString(outputbuf);
    
      free(pkeystr);
      free(outputbuf);
    
      return returnstring;
    }
    
  • Fixed it by adding mbedtls_ecp_group_init before the line that was crashing. Not sure why this is necessary since the first line of the load function immediately frees the group, and it worked fine in Linux the way it was originally written, but it works now on the puck.

  • Weird, I am using malloc in several places and it works fine now after I fixed the init thing, so that note can't be correct. I will change it to static buffers just to be safe. Thanks for the help!

  • whole 64KB of RAM is allocated to nordic softdevice for bluetooth then static variables including big static array of js variables (as per value in board file) and then cpu stack. Can you print addresses that malloc gives you? maybe it grows from the bottom of cpu stack so few bytes will not corrupt it

  • Yeah, using malloc itself is iffy. If you use it, it'll pull in malloc and everything it needs (adding a few kB flash usage) and will take the data it needs out of stack. Allocate too much and you get stack overflow, which might be the instability.

    For mbedtls we actually use jsvMalloc and jsvFree which allocate memory like malloc/free, but out of JsVars instead: https://github.com/espruino/Espruino/blob/master/libs/crypto/mbedtls/config.h#L115-L116

    That's the main difference between PC and embedded (apart from total stack size) so I'd say it's good thing to look into.

    If you look at other Espruino functions we tend to use alloca to allocate data on the stack if it's just for use within as function call. In fact, as pkeystr/outputbuf are fixed size, I'd say you should just define them as an array? char outputbuf[80]. Much faster and safer

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Puck.js Crashes w/ Custom Firmware

Posted by Avatar for Cryptizard @Cryptizard

Actions