#include <tcl.h>
#include <stdint.h>
#include <limits.h>
#include "tweetnacl.h"
#if 0
#include <sys/random.h>
void randombytes(uint8_t *buffer, uint64_t length) {
ssize_t gr_ret;
while (length > 0) {
gr_ret = getrandom(buffer, length, 0);
if (gr_ret <= 0) {
continue;
}
buffer += gr_ret;
length -= gr_ret;
}
return;
}
#endif
#if 0
#include <unistd.h>
void randombytes(uint8_t *buffer, uint64_t length) {
int ge_ret;
int current_length;
while (length > 0) {
current_length = length;
if (current_length > 256) {
current_length = 256;
}
ge_ret = getentropy(buffer, current_length);
if (ge_ret != 0) {
continue;
}
buffer += current_length;
length -= current_length;
}
return;
}
#endif
/*
* XXX:TODO: NOT RANDOM: For testing only
*/
void randombytes(uint8_t *buffer, uint64_t length) {
while (length > 0) {
buffer[length - 1] = (length % 256);
length--;
}
return;
}
static int nano_sign(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
int cs_ret;
unsigned char *signature, *data, *secret_key;
unsigned long long signature_length;
int data_length, secret_key_length;
if (objc != 3) {
Tcl_WrongNumArgs(interp, 1, objv, "data secretKey");
return(TCL_ERROR);
}
data = Tcl_GetByteArrayFromObj(objv[1], &data_length);
secret_key = Tcl_GetByteArrayFromObj(objv[2], &secret_key_length);
if (secret_key_length != crypto_sign_SECRETKEYBYTES) {
Tcl_SetResult(interp, "Secret key is not the right size", NULL);
return(TCL_ERROR);
}
signature_length = data_length + crypto_sign_BYTES;
if (signature_length >= UINT_MAX) {
Tcl_SetResult(interp, "Input message too long", NULL);
return(TCL_ERROR);
}
signature = (unsigned char *) Tcl_AttemptAlloc(signature_length);
if (!signature) {
Tcl_SetResult(interp, "Unable to allocate memory", NULL);
return(TCL_ERROR);
}
cs_ret = crypto_sign(signature, &signature_length, data, data_length, secret_key);
if (cs_ret != 0) {
Tcl_SetResult(interp, "crypto_sign failed", NULL);
return(TCL_ERROR);
}
Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(signature, signature_length));
return(TCL_OK);
/* NOTREACH */
clientData = clientData;
}
int Nano_Init(Tcl_Interp *interp) {
#ifdef USE_TCL_STUBS
const char *tclInitStubs_ret;
/* Initialize Stubs */
tclInitStubs_ret = Tcl_InitStubs(interp, TCL_PATCH_LEVEL, 0);
if (!tclInitStubs_ret) {
return(TCL_ERROR);
}
#endif
Tcl_CreateObjCommand(interp, "::nano::internal::sign", nano_sign, NULL, NULL);
return(TCL_OK);
}