Пример #1
0
ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Bytes) */
    unsigned bytes;
    unsigned char* data;
    ERL_NIF_TERM ret;

    if (!enif_get_uint(env, argv[0], &bytes)) {
	return enif_make_badarg(env);
    }
    data = enif_make_new_binary(env, bytes, &ret);
    if ( RAND_bytes(data, bytes) != 1) {
        return atom_false;
    }
    ERL_VALGRIND_MAKE_MEM_DEFINED(data, bytes);
    return ret;
}
Пример #2
0
static ERL_NIF_TERM tree_pair_dsha256_hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    ErlNifBinary bin1, bin2;
    if (!enif_inspect_binary(env, argv[0], &bin1) || bin1.size != 32 || !enif_inspect_binary(env, argv[1], &bin2) || bin2.size != 32)
        return enif_make_badarg(env);
    
    ERL_NIF_TERM ret;
    unsigned char in[64];
    unsigned char *final_hash = enif_make_new_binary(env, 32, &ret);
    reverse32(&in[0], bin1.data);
    reverse32(&in[32], bin2.data);
    double_sha256(in, 64, final_hash);
    reverse32(final_hash, final_hash);
    
    return ret;
}
Пример #3
0
static ERL_NIF_TERM mem_to_binary(ErlNifEnv *env, const unsigned char *cstr, size_t len)
{
    unsigned char *bin;
    ERL_NIF_TERM term;

    if(cstr)
    {
        bin = enif_make_new_binary(env, len, &term);
        memcpy(bin, cstr, len);
        return term;
    }
    else
    {
        return enif_make_atom(env, "null");
    }
}
Пример #4
0
static ERL_NIF_TERM escape_cdata(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    ErlNifBinary input;
    ERL_NIF_TERM output;
    struct buf *rbuf;
    int i;

    if (argc != 1) {
        return enif_make_badarg(env);
    }

    // CData should be iolist() or binary()
    if (enif_is_binary(env, argv[0])) {
        if (!enif_inspect_binary(env, argv[0], &input)) {
            return enif_make_badarg(env);
        }
    } else {
        if (!enif_inspect_iolist_as_binary(env, argv[0], &input)) {
            return enif_make_badarg(env);
        }
    }

    rbuf = init_buf(env, EXML_CDATA_BUF_SIZE);

    for (i = 0; i < input.size; i++) {
        switch (input.data[i]) {
            case '&':
                buf_add_str(env, EXML_CDATA_BUF_SIZE, rbuf, "&amp;", 5);
                break;
            case '<':
                buf_add_str(env, EXML_CDATA_BUF_SIZE, rbuf, "&lt;", 4);
                break;
            case '>':
                buf_add_str(env, EXML_CDATA_BUF_SIZE, rbuf, "&gt;", 4);
                break;
            default:
                buf_add_char(env, EXML_CDATA_BUF_SIZE, rbuf, input.data[i]);
                break;
        };
    };

    unsigned char* data = enif_make_new_binary(env, rbuf->len, &output);
    memcpy(data, rbuf->b, rbuf->len);
    destroy_buf(env, rbuf);
    return output;
}
Пример #5
0
static ERL_NIF_TERM
sum_r(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
  ErlNifBinary bin;
  ErlNifSInt64 chunk;         // size to be compressed

  ERL_NIF_TERM r;
  ErlNifSInt64* vs;
  ErlNifSInt64* target;
  ErlNifSInt64 aggr;          // Aggregator

  uint32_t target_i = 0;      // target position
  uint32_t count;
  uint32_t pos = 0;
  uint32_t target_size;

  if (argc != 2)
    return enif_make_badarg(env);

  GET_CHUNK(chunk);
  GET_BIN(0, bin, count, vs);

  target_size = ceil((double) count / chunk) * sizeof(ErlNifSInt64);
  if (! (target = (ErlNifSInt64*) enif_make_new_binary(env, target_size, &r)))
    return enif_make_badarg(env); // TODO return propper error
  if (count > 0) {
    aggr = vs[0];
    pos = 2;
    for (uint32_t i = 1; i < count; i++, pos++) {
      if (pos == count) {
        target[target_i] = aggr;
        target_i++;
        aggr = vs[i];
        pos = 0;
      } else {
        aggr += vs[i];
      }
    }
    if (count % chunk) {
      target[target_i] = aggr + vs[count - 1] * (chunk - (count % chunk));
    } else {
      target[target_i] = aggr;
    }
  }
  return r;
}
Пример #6
0
static ERL_NIF_TERM
empty(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
  ErlNifBinary bin;
  ERL_NIF_TERM r;
  ErlNifSInt64* vs;
  ErlNifSInt64* target;
  ErlNifSInt64 chunk;         // size to be compressed
  ErlNifSInt64 target_i = 0;  // target position
  ErlNifSInt64 pos = 0;       // position in chunk
  ErlNifSInt64 aggr = 0;      // aggregated value for this chunk
  int count;
  int target_size;

  if (argc != 2)
    return enif_make_badarg(env);

  GET_CHUNK(chunk);
  GET_BIN(0, bin, count, vs);

  target_size = ceil((double) count / chunk) * sizeof(ErlNifSInt64);
  if (! (target = (ErlNifSInt64*) enif_make_new_binary(env, target_size, &r)))
    return enif_make_badarg(env); // TODO return propper error

  if (count == 0)
    return r;
  pos = 0;
  for (int i = 0; i < count; i++, pos++) {
    if (pos == chunk) {
      target[target_i] = TO_DDB(aggr);
      target_i++;
      aggr = !IS_SET(vs[i]);
      pos = 0;
    } else {
      aggr += !IS_SET(vs[i]);
    }
  }

  if (count % chunk) {
    aggr += (chunk - (count % chunk));
  }
  target[target_i] = TO_DDB(aggr);

  return r;
}
Пример #7
0
static ERL_NIF_TERM
hex(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    md5ctx* ctx;
    ERL_NIF_TERM ret;
    unsigned char* hash = enif_make_new_binary(env, 16, &ret);

    if(argc != 1)
        return enif_make_badarg(env);
    if(!enif_get_resource(env, argv[0], md5_type, (void**) &ctx))
        return enif_make_badarg(env);

    if(!MD5_Final(hash, &(ctx->md5)))
        return make_atom(env, "finalization_error");
    ctx->finalized = 1;

    return ret;
}
Пример #8
0
static ERL_NIF_TERM gdal_nif_tile_to_binary(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    gdal_tile_handle* ti;
    if (!enif_get_resource(env, argv[0], gdal_tile_RESOURCE, (void**)&ti)) {
        return enif_make_badarg(env);
    }

    ErlNifBinary tilefilenameBin;
    if (!enif_inspect_iolist_as_binary(env, argv[1], &tilefilenameBin) || (tilefilenameBin.size >= FILENAME_LEN)) {
        return make_error_msg(env, "filename error, maybe too long");
    }

    char rasterFormatCode[16] = "";
    if (enif_get_string(env, argv[2], rasterFormatCode, 16, ERL_NIF_LATIN1) <= 0) {
        return enif_make_badarg(env);
    }

    char tilefilename[FILENAME_LEN] = "";
    memcpy(tilefilename, tilefilenameBin.data, tilefilenameBin.size);
    DEBUG("passed tilefilename: %s\r\n", tilefilename);

    GDALDriverH hOutDriver = GDALGetDriverByName(rasterFormatCode);
    if ( ! ti->options_resampling || (strcmp("antialias", ti->options_resampling) != 0) ) {
        char vsimemFileName[128] = "";
        sprintf(vsimemFileName, "/vsimem/%s", tilefilename);
        GDALDatasetH tileBinDataset = GDALCreateCopy(hOutDriver,
                                                     vsimemFileName, ti->dstile, 
                                                     FALSE, NULL, NULL, NULL);
        vsi_l_offset binDataLength;
        int bUnlinkAndSeize = FALSE;
        GByte* binData = VSIGetMemFileBuffer(vsimemFileName, &binDataLength, bUnlinkAndSeize);
        DEBUG("vsimem: %s, bin len: %d\r\n", vsimemFileName, binDataLength);

        ERL_NIF_TERM binTerm;
        unsigned char* buf = enif_make_new_binary(env, binDataLength, &binTerm);
        memcpy(buf, binData, binDataLength);
 //       CPLFree(binData);

        GDALClose(tileBinDataset);
        return enif_make_tuple2(env, ATOM_OK, binTerm);
    }

    return make_error_msg(env, "wrong resampling");
}
Пример #9
0
ERL_NIF_TERM ucrypto_ripemd160_update_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    RIPEMD160_CTX *new_context;
    ErlNifBinary context_binary, data_binary;
    ERL_NIF_TERM result;

    if (! enif_inspect_binary(env, argv[0], &context_binary) || context_binary.size != sizeof(RIPEMD160_CTX))
        return enif_make_badarg(env);

    if (! enif_inspect_iolist_as_binary(env, argv[1], &data_binary))
        return enif_make_badarg(env);

    new_context = (RIPEMD160_CTX *)enif_make_new_binary(env, sizeof(RIPEMD160_CTX), &result);
    memcpy(new_context, context_binary.data, sizeof(RIPEMD160_CTX));

    RIPEMD160_Update(new_context, data_binary.data, data_binary.size);

    return result;
}
Пример #10
0
Файл: bn.c Проект: HansN/otp
ERL_NIF_TERM bin_from_bn(ErlNifEnv* env, const BIGNUM *bn)
{
    int bn_len;
    unsigned char *bin_ptr;
    ERL_NIF_TERM term;

    /* Copy the bignum into an erlang binary. */
    if ((bn_len = BN_num_bytes(bn)) < 0)
        goto err;
    if ((bin_ptr = enif_make_new_binary(env, (size_t)bn_len, &term)) == NULL)
        goto err;

    if (BN_bn2bin(bn, bin_ptr) < 0)
        goto err;

    return term;

 err:
    return atom_error;
}
Пример #11
0
static ERL_NIF_TERM last_resource_dtor_call(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    ERL_NIF_TERM ret;
    if (resource_dtor_last != NULL) {
	ERL_NIF_TERM bin;	
	memcpy(enif_make_new_binary(env, resource_dtor_last_sz, &bin),
	       resource_dtor_last_data, resource_dtor_last_sz);
	ret = enif_make_tuple3(env,
				enif_make_long(env, (long)resource_dtor_last),
				bin,  
				enif_make_int(env, resource_dtor_cnt));
    }
    else {
	ret = enif_make_list(env,0);
    }
    resource_dtor_last = NULL;
    resource_dtor_last_sz = 0;
    resource_dtor_cnt = 0;
    return ret;
}
Пример #12
0
static ERL_NIF_TERM
transpose(ErlNifEnv *env, int32_t argc, const ERL_NIF_TERM *argv) {
    ErlNifBinary  matrix;
    ERL_NIF_TERM  result;
    float        *matrix_data, *result_data;
    int32_t       data_size;
    size_t        result_size;

    (void)(argc);

    if (!enif_inspect_binary(env, argv[0], &matrix)) return enif_make_badarg(env);

    matrix_data = (float *) matrix.data;
    data_size   = (int32_t) (matrix_data[0] * matrix_data[1] + 2);

    result_size = sizeof(float) * data_size;
    result_data = (float *) enif_make_new_binary(env, result_size, &result);

    matrix_transpose(matrix_data, result_data);

    return result;
}
Пример #13
0
Файл: bn.c Проект: HansN/otp
ERL_NIF_TERM bn2term(ErlNifEnv* env, const BIGNUM *bn)
{
    int dlen;
    unsigned char* ptr;
    ERL_NIF_TERM ret;

    if (bn == NULL)
        return atom_undefined;

    dlen = BN_num_bytes(bn);
    if (dlen < 0)
        goto err;
    if ((ptr = enif_make_new_binary(env, (size_t)dlen, &ret)) == NULL)
        goto err;

    BN_bn2bin(bn, ptr);

    ERL_VALGRIND_MAKE_MEM_DEFINED(ptr, dlen);
    return ret;

 err:
    return enif_make_badarg(env);
}
Пример #14
0
posix_errno_t efile_list_dir(ErlNifEnv *env, const efile_path_t *path, ERL_NIF_TERM *result) {
    ERL_NIF_TERM list_head;

    struct dirent *dir_entry;
    DIR *dir_stream;

    dir_stream = opendir((const char*)path->data);
    if(dir_stream == NULL) {
        posix_errno_t saved_errno = errno;
        *result = enif_make_list(env, 0);
        return saved_errno;
    }

    list_head = enif_make_list(env, 0);
    dir_entry = readdir(dir_stream);

    while(dir_entry != NULL) {
        int name_length = strlen(dir_entry->d_name);

        if(!is_ignored_name(name_length, dir_entry->d_name)) {
            unsigned char *name_bytes;
            ERL_NIF_TERM name_term;

            name_bytes = enif_make_new_binary(env, name_length, &name_term);
            sys_memcpy(name_bytes, dir_entry->d_name, name_length);

            list_head = enif_make_list_cell(env, name_term, list_head);
        }

        dir_entry = readdir(dir_stream);
    }

    (*result) = list_head;
    closedir(dir_stream);

    return 0;
}
Пример #15
0
static ERL_NIF_TERM make_call_history(ErlNifEnv* env, CallInfo** headp)
{
    ERL_NIF_TERM list = enif_make_list(env, 0); /* NIL */

    while (*headp != NULL) {
	CallInfo* call = *headp;
	ERL_NIF_TERM func_term = enif_make_atom(env,call->func_name);
	ERL_NIF_TERM tpl;
	if (call->arg != NULL) {
	    ERL_NIF_TERM arg_bin;	    
	    memcpy(enif_make_new_binary(env, call->arg_sz, &arg_bin),
		   call->arg, call->arg_sz);
	    func_term = enif_make_tuple2(env, func_term, arg_bin);
	}
	tpl = enif_make_tuple4(env, func_term, 					    
			       enif_make_int(env,call->lib_ver),
			       enif_make_int(env,call->static_cntA),
			       enif_make_int(env,call->static_cntB));
	list = enif_make_list_cell(env, tpl, list);
	*headp = call->next;
	enif_free(call);
    }
    return list;
}
Пример #16
0
static ERL_NIF_TERM
dot(ErlNifEnv *env, int32_t argc, const ERL_NIF_TERM *argv) {
    ErlNifBinary  first, second;
    ERL_NIF_TERM  result;
    float        *first_data, *second_data, *result_data;
    int32_t       data_size;
    size_t        result_size;

    (void)(argc);

    if (!enif_inspect_binary(env, argv[0], &first )) return enif_make_badarg(env);
    if (!enif_inspect_binary(env, argv[1], &second)) return enif_make_badarg(env);

    first_data  = (float *) first.data;
    second_data = (float *) second.data;
    data_size   = (int32_t) (first_data[0] * second_data[1] + 2);

    result_size = sizeof(float) * data_size;
    result_data = (float *) enif_make_new_binary(env, result_size, &result);

    matrix_dot(first_data, second_data, result_data);

    return result;
}
Пример #17
0
static ERL_NIF_TERM
avg(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
  ErlNifBinary bin;
  ERL_NIF_TERM r;
  ErlNifSInt64* vs;
  ErlNifSInt64* target;
  ErlNifSInt64 chunk;         // size to be compressed
  ErlNifSInt64 target_i = 0;  // target position
  ErlNifSInt64 pos = 0;       // position in chunk
  ErlNifSInt64 aggr = 0;      // aggregated value for this chunk
  ErlNifSInt64 last = 0;
  int count;
  int has_value = 0;
  int has_last = 0;
  int target_size;

  if (argc != 2)
    return enif_make_badarg(env);

  GET_CHUNK(chunk);
  GET_BIN(0, bin, count, vs);

  target_size = ceil((double) count / chunk) * sizeof(ErlNifSInt64);
  if (! (target = (ErlNifSInt64*) enif_make_new_binary(env, target_size, &r)))
    return enif_make_badarg(env); // TODO return propper error

  // If we don't have any input data we can return right away.
  if (count == 0)
    return r;

  // We know we have at least one element in the list so our
  // aggregator will start with this
  if (IS_SET(vs[0])) {
    aggr = FROM_DDB(vs[0]);
    last = aggr;
    has_value = 1;
    has_last = 1;
  };
  pos = 1;
  // We itterate over the remining i .. count-1 elements

  for (int i = 1; i < count; i++, pos++) {
    if (pos == chunk) {
      if (has_value) {
        target[target_i] = TO_DDB(aggr / chunk);
      } else {
        target[target_i] = 0;
      }

      target_i++;
      has_value = IS_SET(vs[i]);
      if (has_value) {
        aggr = FROM_DDB(vs[i]);
        last = aggr;
        has_last = 1;
      } else if (has_last) {
        aggr = last;
        has_value = 1;
      }
      pos = 0;
    } else if (!has_value) {
      if (IS_SET(vs[i])) {
        aggr = FROM_DDB(vs[i]);
        last = aggr;
        has_value = 1;
        has_last = 1;
      };
    } else {
      if (IS_SET(vs[i])) {
        last = FROM_DDB(vs[i]);
        aggr += last;
        has_last = 1;
        has_value = 1;
      } else if (has_last) {
        aggr += last;
        has_value = 1;
      }
    }
  }

  if (has_value) {
    if (count % chunk) {
      aggr += (last * (chunk - (count % chunk)));
    }
    target[target_i] = TO_DDB(aggr / chunk);
  } else {
    target[target_i] = 0;
  }
  return r;
}
Пример #18
0
int
dec_string(Decoder* d, ERL_NIF_TERM* value)
{
    int has_escape = 0;
    int num_escapes = 0;
    int st;
    int ulen;
    int ui;
    int hi;
    int lo;
    char* chrbuf;
    int chrpos;

    if(d->p[d->i] != '\"') {
        return 0;
    }
    d->i++;

    st = d->i;

    while(d->i < d->len) {
        if(d->u[d->i] < 0x20) {
            return 0;
        } else if(d->p[d->i] == '\"') {
            d->i++;
            goto parse;
        } else if(d->p[d->i] == '\\') {
            if(d->i+1 >= d->len) {
                return 0;
            }
            has_escape = 1;
            num_escapes += 1;
            d->i++;
            switch(d->p[d->i]) {
                case '\"':
                case '\\':
                case '/':
                case 'b':
                case 'f':
                case 'n':
                case 'r':
                case 't':
                    d->i++;
                    break;
                case 'u':
                    hi = 0;
                    lo = 0;
                    d->i++;
                    if(d->i + 4 >= d->len) {
                        return 0;
                    }
                    hi = int_from_hex(&(d->u[d->i]));
                    if(hi < 0) {
                        return 0;
                    }
                    d->i += 4;
                    if(hi >= 0xD800 && hi < 0xDC00) {
                        if(d->i + 6 >= d->len) {
                            return 0;
                        }
                        if(d->p[d->i++] != '\\') {
                            return 0;
                        } else if(d->p[d->i++] != 'u') {
                            return 0;
                        }
                        lo = int_from_hex(&(d->u[d->i]));
                        if(lo < 0) {
                            return 0;
                        }
                        hi = unicode_from_pair(hi, lo);
                        if(hi < 0) {
                            return 0;
                        }
                    }
                    hi = utf8_len(hi);
                    if(hi < 0) {
                        return 0;
                    }
                    if(lo == 0) {
                        num_escapes += 5 - hi;
                    } else {
                        num_escapes += 11 - hi;
                    }
                    break;
                default:
                    return 0;
            }
        } else if(d->u[d->i] < 0x80) {
            d->i++;
        } else {
            ulen = utf8_validate(&(d->u[d->i]), d->len - d->i);
            if(ulen < 0) {
                return 0;
            }
            d->i += ulen;
        }
    }

    // The goto above ensures that we only
    // hit this when a string is not terminated
    // correctly.
    return 0;

parse:
    if(!has_escape) {
        *value = enif_make_sub_binary(d->env, d->arg, st, (d->i - st - 1));
        return 1;
    }

    hi = 0;
    lo = 0;

    ulen = (d->i - 1) - st - num_escapes;
    chrbuf = (char*) enif_make_new_binary(d->env, ulen, value);
    chrpos = 0;
    ui = st;
    while(ui < d->i - 1) {
        if(d->p[ui] != '\\') {
            chrbuf[chrpos++] = d->p[ui++];
            continue;
        }
        ui++;
        switch(d->p[ui]) {
            case '\"':
            case '\\':
            case '/':
                chrbuf[chrpos++] = d->p[ui];
                ui++;
                break;
            case 'b':
                chrbuf[chrpos++] = '\b';
                ui++;
                break;
            case 'f':
                chrbuf[chrpos++] = '\f';
                ui++;
                break;
            case 'n':
                chrbuf[chrpos++] = '\n';
                ui++;
                break;
            case 'r':
                chrbuf[chrpos++] = '\r';
                ui++;
                break;
            case 't':
                chrbuf[chrpos++] = '\t';
                ui++;
                break;
            case 'u':
                ui++;
                hi = int_from_hex(&(d->u[ui]));
                if(hi < 0) {
                    return 0;
                }
                if(hi >= 0xD800 && hi < 0xDC00) {
                    lo = int_from_hex(&(d->u[ui+6]));
                    if(lo < 0) {
                        return 0;
                    }
                    hi = unicode_from_pair(hi, lo);
                    ui += 10;
                } else {
                    ui += 4;
                }
                hi = unicode_to_utf8(hi, (unsigned char*) chrbuf+chrpos);
                if(hi < 0) {
                    return 0;
                }
                chrpos += hi;
                break;
            default:
                return 0;
        }
    }

    return 1;
}
Пример #19
0
Файл: dh.c Проект: KennethL/otp
ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (PrivKey|undefined, DHParams=[P,G], Mpint, Len|0) */
    DH *dh_params = NULL;
    int mpint; /* 0 or 4 */

    {
        ERL_NIF_TERM head, tail;
        BIGNUM
            *dh_p = NULL,
            *dh_g = NULL,
            *priv_key_in = NULL;
        unsigned long
            len = 0;

        if (!(get_bn_from_bin(env, argv[0], &priv_key_in)
              || argv[0] == atom_undefined)
            || !enif_get_list_cell(env, argv[1], &head, &tail)
            || !get_bn_from_bin(env, head, &dh_p)
            || !enif_get_list_cell(env, tail, &head, &tail)
            || !get_bn_from_bin(env, head, &dh_g)
            || !enif_is_empty_list(env, tail)
            || !enif_get_int(env, argv[2], &mpint) || (mpint & ~4)
            || !enif_get_ulong(env, argv[3], &len)

            /* Load dh_params with values to use by the generator.
               Mem mgmnt transfered from dh_p etc to dh_params */
            || !(dh_params = DH_new())
            || (priv_key_in && !DH_set0_key(dh_params, NULL, priv_key_in))
            || !DH_set0_pqg(dh_params, dh_p, NULL, dh_g)
            ) {
            if (priv_key_in) BN_free(priv_key_in);
            if (dh_p) BN_free(dh_p);
            if (dh_g) BN_free(dh_g);
            if (dh_params) DH_free(dh_params);
            return enif_make_badarg(env);
        }

        if (len) {
            if (len < BN_num_bits(dh_p))
                DH_set_length(dh_params, len);
            else {
                if (priv_key_in) BN_free(priv_key_in);
                if (dh_p) BN_free(dh_p);
                if (dh_g) BN_free(dh_g);
                if (dh_params) DH_free(dh_params);
                return enif_make_badarg(env);
            }
        }
    }

#ifdef HAS_EVP_PKEY_CTX
    {
        EVP_PKEY_CTX *ctx;
        EVP_PKEY *dhkey, *params;
        int success;

        params = EVP_PKEY_new();
        success = EVP_PKEY_set1_DH(params, dh_params);   /* set the key referenced by params to dh_params... */
        DH_free(dh_params);                              /* ...dh_params (and params) must be freed */
        if (!success) return atom_error;

        ctx = EVP_PKEY_CTX_new(params, NULL);
        EVP_PKEY_free(params);
        if (!ctx) {
            return atom_error;
        }

        if (!EVP_PKEY_keygen_init(ctx)) {
            /* EVP_PKEY_CTX_free(ctx); */
            return atom_error;
        }

        dhkey = EVP_PKEY_new();
        if (!EVP_PKEY_keygen(ctx, &dhkey)) {         /* "performs a key generation operation, the ... */
                                                     /*... generated key is written to ppkey." (=last arg) */
             /* EVP_PKEY_CTX_free(ctx); */
             /* EVP_PKEY_free(dhkey); */
             return atom_error;
        }

        dh_params = EVP_PKEY_get1_DH(dhkey); /* return the referenced key. dh_params and dhkey must be freed */
        EVP_PKEY_free(dhkey);
        if (!dh_params) {
            /* EVP_PKEY_CTX_free(ctx); */
            return atom_error;
        }
        EVP_PKEY_CTX_free(ctx);
    }
#else
    if (!DH_generate_key(dh_params)) return atom_error;
#endif
    {
        unsigned char *pub_ptr, *prv_ptr;
        int pub_len, prv_len;
        ERL_NIF_TERM ret_pub, ret_prv;
        const BIGNUM *pub_key_gen, *priv_key_gen;

        DH_get0_key(dh_params,
                    &pub_key_gen, &priv_key_gen); /* Get pub_key_gen and priv_key_gen.
                                                     "The values point to the internal representation of
                                                     the public key and private key values. This memory
                                                     should not be freed directly." says man */
        pub_len = BN_num_bytes(pub_key_gen);
        prv_len = BN_num_bytes(priv_key_gen);
        pub_ptr = enif_make_new_binary(env, pub_len+mpint, &ret_pub);
        prv_ptr = enif_make_new_binary(env, prv_len+mpint, &ret_prv);
        if (mpint) {
            put_int32(pub_ptr, pub_len); pub_ptr += 4;
            put_int32(prv_ptr, prv_len); prv_ptr += 4;
        }
        BN_bn2bin(pub_key_gen, pub_ptr);
        BN_bn2bin(priv_key_gen, prv_ptr);
        ERL_VALGRIND_MAKE_MEM_DEFINED(pub_ptr, pub_len);
        ERL_VALGRIND_MAKE_MEM_DEFINED(prv_ptr, prv_len);

        DH_free(dh_params);

        return enif_make_tuple2(env, ret_pub, ret_prv);
    }
}
Пример #20
0
static ERL_NIF_TERM x509_make_cert_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
  int expiry, serial;
  ASN1_INTEGER *asn1serial = NULL;
  BIGNUM *bn_rsa_genkey=NULL;
  BIO *bio_signing_private=NULL, *bio_issuer_cert = NULL, *bio_newcert_public = NULL;
  BIO *bio_x509=NULL;
  char *issuer_cert_pem=NULL;
  X509 *pX509 = NULL;
  X509 *pIssuerX509 = NULL;
  X509_NAME *pX509Name = NULL;
  X509_NAME *pIssuerName = NULL;
  x509_subject_entry *subject_entries;
  int num_subject_entries;
  int iret = 0;
  RSA *rsa=NULL;
  unsigned long f4=RSA_F4;
  unsigned args_len=-1;
  char *signing_keys[2], *cert_keys[2];
  ERL_NIF_TERM tail, *arg_terms=NULL;
  int idx;
  ERL_NIF_TERM ret, x509term;
  int x509len;
  unsigned char *x509data;

  EVP_PKEY *evp_signing_private = EVP_PKEY_new();
  EVP_PKEY *evp_newcert_public_key = EVP_PKEY_new();
  /* set RSA key gen type */
  bn_rsa_genkey = BN_new();
  BN_set_word(bn_rsa_genkey, f4);

  //
  // 1. stick subject of CA cert into NewCert
  // 2. stick public key of NewKeypair into NewCert
  // 3. sign NewCert with CA keypair

  /* Should be 6 elements in the list of X509 parameters.  We'll check each */
  if(!enif_get_list_length(env, argv[0], &args_len) || args_len != 6 ||
     NULL == (arg_terms = (ERL_NIF_TERM*)malloc(args_len * sizeof(ERL_NIF_TERM)))) return enif_make_badarg(env);
  
  enif_get_list_cell(env, argv[0], &arg_terms[0], &tail);
  for(idx=1; idx<args_len; idx++){
    if(!enif_get_list_cell(env, tail, &arg_terms[idx], &tail)){
      free(arg_terms);
      return enif_make_badarg(env);
    }
  }
  
  idx=0;
  /* get the signing private key */
  x509_parse_keypair(env, "signing_key", arg_terms[idx++], signing_keys);

  /* get the issuer cert */
  x509_parse_issuer_cert(env, arg_terms[idx++], &issuer_cert_pem);

  /* get the soon-to-be cert's public key */
  x509_parse_keypair(env, "newcert_public_key", arg_terms[idx++], cert_keys);

  /* get the subject */
  x509_parse_subject(env, arg_terms[idx++], &num_subject_entries, &subject_entries);

  /* get the serial number */
  x509_parse_int_tuple(env, arg_terms[idx++], "serial", &serial);

  /* get the expiry */
  x509_parse_int_tuple(env, arg_terms[idx++], "expiry", &expiry);

  /* work the OpenSSL cert creation magic */
  if ((bio_signing_private = BIO_new_mem_buf(signing_keys[1], -1))
      && (rsa = PEM_read_bio_RSAPrivateKey(bio_signing_private, NULL, NULL, NULL))
      && (iret = EVP_PKEY_assign_RSA(evp_signing_private, rsa))
              
      && (bio_newcert_public = BIO_new_mem_buf(cert_keys[0], -1))
      && (evp_newcert_public_key = PEM_read_bio_PUBKEY(bio_newcert_public, NULL, NULL, NULL))
              
      && (bio_issuer_cert = BIO_new_mem_buf(issuer_cert_pem, -1))
      && (pIssuerX509 = PEM_read_bio_X509(bio_issuer_cert, NULL, NULL, NULL))
      && (pX509 = X509_new())) {
    /* if we've managed to generate a key and allocate structure memory,
       set X509 fields */
    asn1serial = ASN1_INTEGER_new();
    X509_set_version(pX509, 2); /* cert_helper uses '3' here */
    ASN1_INTEGER_set(asn1serial, serial);
    X509_set_serialNumber(pX509, asn1serial);
    X509_gmtime_adj(X509_get_notBefore(pX509),0);
    X509_gmtime_adj(X509_get_notAfter(pX509),(long)60*60*24*expiry);
    X509_set_pubkey(pX509, evp_newcert_public_key);
    pX509Name = X509_get_subject_name(pX509);
    
    while(--num_subject_entries >= 0){
      X509_NAME_add_entry_by_txt(pX509Name, (subject_entries[num_subject_entries]).name,
                                 MBSTRING_ASC, (unsigned char*)(subject_entries[num_subject_entries]).value, -1, -1, 0);
    }
    
    pIssuerName = X509_get_issuer_name(pIssuerX509);
    X509_set_issuer_name(pX509, pIssuerName);
    X509_sign(pX509, evp_signing_private, digest);
    
    bio_x509 = BIO_new(BIO_s_mem());
    PEM_write_bio_X509(bio_x509, pX509);
    
    x509len = BIO_get_mem_data(bio_x509, &x509data);
    memcpy(enif_make_new_binary(env, x509len, &x509term), x509data, x509len);
    ret = enif_make_tuple2(env, atom_x509_cert, x509term);
  }
    
 done:
  if(arg_terms) free(arg_terms);
  free_keys(signing_keys);
  free_keys(cert_keys);
  free_subject_entries(num_subject_entries, subject_entries);
  if(pX509) X509_free(pX509);
  if(pIssuerX509) X509_free(pIssuerX509);
  if(issuer_cert_pem) free(issuer_cert_pem);
  if(bio_issuer_cert) { BIO_set_close(bio_issuer_cert, BIO_NOCLOSE); BIO_free_all(bio_issuer_cert); }
  if(bio_signing_private) { BIO_set_close(bio_signing_private, BIO_NOCLOSE); BIO_free_all(bio_signing_private); }
  if(bio_newcert_public) { BIO_set_close(bio_newcert_public, BIO_NOCLOSE); BIO_free_all(bio_newcert_public); }
  if(bio_x509) BIO_free_all(bio_x509);
  if(asn1serial) ASN1_INTEGER_free(asn1serial);
  if(bn_rsa_genkey) BN_free(bn_rsa_genkey);
  if(rsa) RSA_free(rsa);

  return ret;
}
Пример #21
0
static ERL_NIF_TERM rsa_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
  ERL_NIF_TERM ret;
  ERL_NIF_TERM private_keyterm, public_keyterm;
  BIO *bio_private_pem=NULL, *bio_public_pem=NULL;
  RSA *rsa = NULL;
  BIGNUM *bn_rsa_genkey=NULL;
  int rsa_keylen=-1;
  int private_pemlen, public_pemlen;
  unsigned long f4=RSA_F4;
  int dlen;

  /* BUGBUG: Need better validation of key length here [cb] */
  if (!enif_get_int(env, argv[0], &rsa_keylen)) {
	return enif_make_badarg(env);
  }

  /* Do all allocations and fail function call if any single alloc failed */
  rsa = RSA_new();
  bn_rsa_genkey = BN_new();
  bio_private_pem = BIO_new(BIO_s_mem());
  bio_public_pem = BIO_new(BIO_s_mem());

  /* Do actual OpenSSL work */
  if(rsa && bn_rsa_genkey && bio_private_pem && bio_public_pem){
    BN_set_word(bn_rsa_genkey, f4);

    if (RSA_generate_key_ex(rsa, rsa_keylen, bn_rsa_genkey, NULL)) {
      unsigned char *private_pemdata;
      unsigned char *public_pemdata;

      PEM_write_bio_RSA_PUBKEY(bio_public_pem,rsa);
      PEM_write_bio_RSAPrivateKey(bio_private_pem,rsa,NULL,NULL,0,NULL,NULL);
        
      private_pemlen = BIO_get_mem_data(bio_private_pem, &private_pemdata);
      public_pemlen = BIO_get_mem_data(bio_public_pem, &public_pemdata);
        
      dlen = sizeof(int)+private_pemlen+sizeof(int)+public_pemlen;
      private_pemdata[private_pemlen]=0;
      public_pemdata[public_pemlen]=0;

      memcpy(enif_make_new_binary(env, private_pemlen, &private_keyterm), private_pemdata, private_pemlen);
      memcpy(enif_make_new_binary(env, public_pemlen, &public_keyterm), public_pemdata, public_pemlen);
      ret = enif_make_tuple3(env, atom_ok, public_keyterm, private_keyterm);
    }
    else {
      ret = enif_make_tuple2(env, atom_error, atom_bad_keylen);
    }

  } else {
    ret = enif_make_tuple2(env, atom_error, atom_bad_ssl_init);
  }

  /* dealloc */
  if(bio_private_pem)
    BIO_free_all(bio_private_pem);
  if(bio_public_pem)
    BIO_free_all(bio_public_pem);
  if(bn_rsa_genkey)
    BN_free(bn_rsa_genkey);
  if(rsa)
    RSA_free(rsa);

  return ret;
}
Пример #22
0
Файл: bn.c Проект: HansN/otp
ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Base,Exponent,Modulo,bin_hdr) */
    BIGNUM *bn_base = NULL, *bn_exponent = NULL, *bn_modulo = NULL, *bn_result = NULL;
    BN_CTX *bn_ctx = NULL;
    unsigned char* ptr;
    int dlen;
    unsigned bin_hdr; /* return type: 0=plain binary, 4: mpint */
    unsigned extra_byte;
    ERL_NIF_TERM ret;

    ASSERT(argc == 4);

    if (!get_bn_from_bin(env, argv[0], &bn_base))
        goto bad_arg;
    if (!get_bn_from_bin(env, argv[1], &bn_exponent))
        goto bad_arg;
    if (!get_bn_from_bin(env, argv[2], &bn_modulo))
        goto bad_arg;
    if (!enif_get_uint(env, argv[3], &bin_hdr))
        goto bad_arg;
    if (bin_hdr != 0 && bin_hdr != 4)
        goto bad_arg;

    if ((bn_result = BN_new()) == NULL)
        goto err;
    if ((bn_ctx = BN_CTX_new()) == NULL)
        goto err;

    if (!BN_mod_exp(bn_result, bn_base, bn_exponent, bn_modulo, bn_ctx))
        goto err;

    dlen = BN_num_bytes(bn_result);
    if (dlen < 0 || dlen > INT_MAX / 8)
        goto bad_arg;
    extra_byte = bin_hdr && BN_is_bit_set(bn_result, dlen * 8 - 1);

    if ((ptr = enif_make_new_binary(env, bin_hdr + extra_byte + (unsigned int)dlen, &ret)) == NULL)
        goto err;

    if (bin_hdr) {
        put_uint32(ptr, extra_byte + (unsigned int)dlen);
        ptr[4] = 0; /* extra zeroed byte to ensure a positive mpint */
        ptr += bin_hdr + extra_byte;
    }

    BN_bn2bin(bn_result, ptr);
    goto done;

 bad_arg:
 err:
    ret = enif_make_badarg(env);

 done:
    if (bn_base)
        BN_free(bn_base);
    if (bn_exponent)
        BN_free(bn_exponent);
    if (bn_modulo)
        BN_free(bn_modulo);
    if (bn_result)
        BN_free(bn_result);
    if (bn_ctx)
        BN_CTX_free(bn_ctx);
    return ret;
}