Index: configure ================================================================== --- configure +++ configure @@ -5394,11 +5394,11 @@ # This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS # and PKG_TCL_SOURCES. #----------------------------------------------------------------------- - vars="tls.c tlsBIO.c tlsDigest.c tlsEncrypt.c tlsInfo.c tlsIO.c tlsKDF.c tlsUtil.c tlsX509.c" + vars="tls.c tlsBIO.c tlsDigest.c tlsEncrypt.c tlsInfo.c tlsIO.c tlsKDF.c tlsRand.c tlsUtil.c tlsX509.c" for i in $vars; do case $i in \$*) # allow $-var names PKG_SOURCES="$PKG_SOURCES $i" Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -69,11 +69,11 @@ # and runtime Tcl library files in TEA_ADD_TCL_SOURCES. # This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS # and PKG_TCL_SOURCES. #----------------------------------------------------------------------- -TEA_ADD_SOURCES([tls.c tlsBIO.c tlsDigest.c tlsEncrypt.c tlsInfo.c tlsIO.c tlsKDF.c tlsUtil.c tlsX509.c]) +TEA_ADD_SOURCES([tls.c tlsBIO.c tlsDigest.c tlsEncrypt.c tlsInfo.c tlsIO.c tlsKDF.c tlsRand.c tlsUtil.c tlsX509.c]) TEA_ADD_HEADERS([generic/tls.h]) TEA_ADD_INCLUDES([]) TEA_ADD_LIBS([]) TEA_ADD_CFLAGS([]) TEA_ADD_STUB_SOURCES([]) Index: generic/tls.c ================================================================== --- generic/tls.c +++ generic/tls.c @@ -2618,11 +2618,12 @@ Tcl_CreateObjCommand(interp, "tls::status", StatusObjCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tls_DigestCommands(interp); Tls_EncryptCommands(interp); Tls_InfoCommands(interp); - Tls_KeyCommands(interp); + Tls_KDFCommands(interp); + Tls_RandCommands(interp); if (interp) { Tcl_Eval(interp, tlsTclInitScript); } Index: generic/tlsInt.h ================================================================== --- generic/tlsInt.h +++ generic/tlsInt.h @@ -195,11 +195,12 @@ void Tls_Clean(State *statePtr); int Tls_WaitForConnect(State *statePtr, int *errorCodePtr, int handshakeFailureIsPermanent); int Tls_DigestCommands(Tcl_Interp *interp); int Tls_EncryptCommands(Tcl_Interp *interp); int Tls_InfoCommands(Tcl_Interp *interp); -int Tls_KeyCommands(Tcl_Interp *interp); +int Tls_KDFCommands(Tcl_Interp *interp); +int Tls_RandCommands(Tcl_Interp *interp); BIO *BIO_new_tcl(State* statePtr, int flags); EVP_CIPHER *Util_GetCipher(Tcl_Interp *interp, Tcl_Obj *cipherObj, int no_null); EVP_MD *Util_GetDigest(Tcl_Interp *interp, Tcl_Obj *digestObj, int no_null); Index: generic/tlsKDF.c ================================================================== --- generic/tlsKDF.c +++ generic/tlsKDF.c @@ -465,11 +465,11 @@ * Side effects: * Creates commands * *------------------------------------------------------------------- */ -int Tls_KeyCommands(Tcl_Interp *interp) { +int Tls_KDFCommands(Tcl_Interp *interp) { Tcl_CreateObjCommand(interp, "tls::hkdf", KDF_HKDF, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateObjCommand(interp, "tls::pbkdf2", KDF_PBKDF2, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateObjCommand(interp, "tls::scrypt", KDF_Scrypt, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); return TCL_OK; } ADDED generic/tlsRand.c Index: generic/tlsRand.c ================================================================== --- /dev/null +++ generic/tlsRand.c @@ -0,0 +1,117 @@ +/* + * Key Derivation Function (KDF) Module + * + * Provides commands to derive keys. + * + * Copyright (C) 2023 Brian O'Hagan + * + */ + +#include "tlsInt.h" +#include "tclOpts.h" +#include + +/*******************************************************************/ + +/* Options for Random commands */ + +static const char *command_opts [] = { + "-private", NULL}; + +enum _command_opts { + _opt_private +}; + +/* + *------------------------------------------------------------------- + * + * RAND_Random -- + * + * Generate random byes using a random bytes using a cryptographically + * secure pseudo random generator (CSPRNG). + * + * Returns: + * TCL_OK or TCL_ERROR + * + * Side effects: + * Sets result to the random bytes, or an error message + * + *------------------------------------------------------------------- + */ +static int RAND_Random(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { + int out_len = 0, res; + unsigned char *out_buf; + Tcl_Obj *resultObj; + + dprintf("Called"); + + /* Clear errors */ + Tcl_ResetResult(interp); + ERR_clear_error(); + + /* Validate arg count */ + if (objc < 2 || objc > 3) { + Tcl_WrongNumArgs(interp, 1, objv, "?-private? length"); + return TCL_ERROR; + } else if (objc == 3) { + int fn; + if (Tcl_GetIndexFromObj(interp, objv[1], command_opts, "option", 0, &fn) != TCL_OK) { + return TCL_ERROR; + } + } + + /* Get length */ + if (Tcl_GetIntFromObj(interp, objv[objc - 1], &out_len) != TCL_OK) { + return TCL_ERROR; + } + if (out_len < 0) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad count \"%d\": must be integer >= 0", out_len)); + return TCL_ERROR; + } + + /* Allocate storage for result */ + resultObj = Tcl_NewObj(); + out_buf = Tcl_SetByteArrayLength(resultObj, out_len); + if (resultObj == NULL || out_buf == NULL) { + Tcl_AppendResult(interp, "Memory allocation error", (char *) NULL); + Tcl_DecrRefCount(resultObj); + return TCL_ERROR; + } + + /* Get random bytes */ + if (objc == 2) { + res = RAND_bytes(out_buf, out_len); + } else { + res = RAND_priv_bytes(out_buf, out_len); + } + if (!res) { + Tcl_AppendResult(interp, "Generate failed: ", REASON(), (char *) NULL); + Tcl_DecrRefCount(resultObj); + return TCL_ERROR; + } + + Tcl_SetObjResult(interp, resultObj); + return TCL_OK; + clientData = clientData; +} + +/* + *------------------------------------------------------------------- + * + * Tls_RandCommands -- + * + * Create key commands + * + * Returns: + * TCL_OK or TCL_ERROR + * + * Side effects: + * Creates commands + * + *------------------------------------------------------------------- + */ +int Tls_RandCommands(Tcl_Interp *interp) { + Tcl_CreateObjCommand(interp, "tls::random", RAND_Random, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); + return TCL_OK; +} + Index: win/makefile.vc ================================================================== --- win/makefile.vc +++ win/makefile.vc @@ -30,10 +30,11 @@ $(TMP_DIR)\tlsDigest.obj \ $(TMP_DIR)\tlsEncrypt.obj \ $(TMP_DIR)\tlsInfo.obj \ $(TMP_DIR)\tlsIO.obj \ $(TMP_DIR)\tlsKDF.obj \ + $(TMP_DIR)\tlsRand.obj \ $(TMP_DIR)\tlsUtil.obj \ $(TMP_DIR)\tlsX509.obj # Define any additional project include flags # SSL_INSTALL_FOLDER = with the OpenSSL installation folder following.