Index: generic/tlsDigest.c ================================================================== --- generic/tlsDigest.c +++ generic/tlsDigest.c @@ -32,14 +32,10 @@ #define TYPE_MD 0x10 #define TYPE_HMAC 0x20 #define TYPE_CMAC 0x40 #define TYPE_MAC 0x80 -#if OPENSSL_VERSION_NUMBER <= 0x30000000L -#define EVP_MAC void -#endif - /*******************************************************************/ /* * This structure defines the per-instance state of a digest operation. */ @@ -149,19 +145,22 @@ * Side effects: * No result or error message * *------------------------------------------------------------------- */ -int DigestInitialize(Tcl_Interp *interp, DigestState *statePtr, const EVP_MD *md, - const EVP_CIPHER *cipher, Tcl_Obj *keyObj, EVP_MAC *mac) { - int key_len = 0, res = 0; +int DigestInitialize(Tcl_Interp *interp, DigestState *statePtr, Tcl_Obj *digestObj, + Tcl_Obj *cipherObj, Tcl_Obj *keyObj, Tcl_Obj *macObj) { + int key_len = 0, type = statePtr->format & 0xFF0; + const char *digestName = NULL, *cipherName = NULL, *macName = NULL; + const EVP_MD *md = NULL; + const EVP_CIPHER *cipher = NULL; const unsigned char *key = NULL; dprintf("Called"); /* Create contexts */ - switch(statePtr->format & 0xFF0) { + switch(type) { case TYPE_MD: statePtr->ctx = EVP_MD_CTX_new(); res = (statePtr->ctx != NULL); break; case TYPE_HMAC: @@ -173,21 +172,68 @@ res = (statePtr->cctx != NULL); break; } if (!res) { - Tcl_AppendResult(interp, "Create context failed: ", REASON(), NULL); + Tcl_AppendResult(interp, "Create context failed", NULL); + return TCL_ERROR; + } + + /* Get MAC */ + if (macObj != NULL) { + macName = Tcl_GetStringFromObj(macObj, NULL); + if (strcmp(macName, "cmac") == 0) { + type = TYPE_CMAC; + } else if (strcmp(macName, "hmac") == 0) { + type = TYPE_HMAC; + } else { + Tcl_AppendResult(interp, "Invalid MAC \"", macName, "\"", NULL); + return TCL_ERROR; + } + } else if (type == TYPE_MAC) { + Tcl_AppendResult(interp, "No MAC specified", NULL); + return TCL_ERROR; + } + + /* Get digest */ + if (digestObj != NULL) { + digestName = Tcl_GetStringFromObj(digestObj, NULL); + md = EVP_get_digestbyname(digestName); + if (md == NULL) { + Tcl_AppendResult(interp, "Invalid digest \"", digestName, "\"", NULL); + return TCL_ERROR; + } else if (md == EVP_shake128() || md == EVP_shake256()) { + statePtr->format |= IS_XOF; + } + } else if (type != TYPE_CMAC) { + Tcl_AppendResult(interp, "No digest specified", NULL); + return TCL_ERROR; + } + + /* Get cipher */ + if (cipherObj != NULL) { + cipherName = Tcl_GetStringFromObj(cipherObj, NULL); + cipher = EVP_get_cipherbyname(cipherName); + if (cipher == NULL) { + Tcl_AppendResult(interp, "Invalid cipher \"", cipherName, "\"", NULL); + return TCL_ERROR; + } + } else if (type == TYPE_CMAC) { + Tcl_AppendResult(interp, "No cipher specified", NULL); return TCL_ERROR; } /* Get key */ if (keyObj != NULL) { key = Tcl_GetByteArrayFromObj(keyObj, &key_len); + } else if (type != TYPE_MD) { + Tcl_AppendResult(interp, "No key specified", NULL); + return TCL_ERROR; } /* Initialize cryptography function */ - switch(statePtr->format & 0xFF0) { + switch(type) { case TYPE_MD: res = EVP_DigestInit_ex(statePtr->ctx, md, NULL); break; case TYPE_HMAC: res = HMAC_Init_ex(statePtr->hctx, (const void *) key, key_len, md, NULL); @@ -762,12 +808,12 @@ * Side effects: * Adds transform to channel and sets result to channel id or error message. * *---------------------------------------------------------------------- */ -static int DigestChannelHandler(Tcl_Interp *interp, const char *channel, const EVP_MD *md, - const EVP_CIPHER *cipher, int format, Tcl_Obj *keyObj, EVP_MAC *mac) { +static int DigestChannelHandler(Tcl_Interp *interp, const char *channel, Tcl_Obj *digestObj, + Tcl_Obj *cipherObj, int format, Tcl_Obj *keyObj, Tcl_Obj *macObj) { int mode; /* OR-ed combination of TCL_READABLE and TCL_WRITABLE */ Tcl_Channel chan; DigestState *statePtr; dprintf("Called"); @@ -799,11 +845,12 @@ } statePtr->self = chan; statePtr->mode = mode; /* Initialize hash function */ - if (DigestInitialize(interp, statePtr, md, cipher, keyObj, mac) != TCL_OK) { + if (DigestInitialize(interp, statePtr, digestObj, cipherObj, keyObj, macObj) != TCL_OK) { + DigestStateFree(statePtr); return TCL_ERROR; } /* Stack channel */ statePtr->self = Tcl_StackChannel(interp, &digestChannelType, (ClientData) statePtr, mode, chan); @@ -965,12 +1012,12 @@ * Side effects: * Creates command or error message * *------------------------------------------------------------------- */ -int DigestCommandHandler(Tcl_Interp *interp, Tcl_Obj *cmdObj, const EVP_MD *md, - const EVP_CIPHER *cipher, int format, Tcl_Obj *keyObj, EVP_MAC *mac) { +int DigestCommandHandler(Tcl_Interp *interp, Tcl_Obj *cmdObj, Tcl_Obj *digestObj, + Tcl_Obj *cipherObj, int format, Tcl_Obj *keyObj, Tcl_Obj *macObj) { DigestState *statePtr; char *cmdName = Tcl_GetStringFromObj(cmdObj, NULL); dprintf("Called"); @@ -979,17 +1026,21 @@ Tcl_AppendResult(interp, "Memory allocation error", (char *) NULL); return TCL_ERROR; } /* Initialize hash function */ - if (DigestInitialize(interp, statePtr, md, cipher, keyObj, mac) != TCL_OK) { + if (DigestInitialize(interp, statePtr, digestObj, cipherObj, keyObj, macObj) != TCL_OK) { return TCL_ERROR; } /* Create instance command */ statePtr->token = Tcl_CreateObjCommand(interp, cmdName, DigestInstanceObjCmd, (ClientData) statePtr, DigestCommandDeleteHandler); + if (statePtr->token == NULL) { + DigestStateFree(statePtr); + return TCL_ERROR; + } /* Return command name */ Tcl_SetObjResult(interp, cmdObj); return TCL_OK; } @@ -1010,12 +1061,12 @@ * Side effects: * Sets result to message digest or error message * *------------------------------------------------------------------- */ -int DigestDataHandler(Tcl_Interp *interp, Tcl_Obj *dataObj, const EVP_MD *md, - const EVP_CIPHER *cipher, int format, Tcl_Obj *keyObj, EVP_MAC *mac) { +int DigestDataHandler(Tcl_Interp *interp, Tcl_Obj *dataObj, Tcl_Obj *digestObj, + Tcl_Obj *cipherObj, int format, Tcl_Obj *keyObj, Tcl_Obj *macObj) { char *data; int data_len; DigestState *statePtr; dprintf("Called"); @@ -1032,11 +1083,11 @@ Tcl_AppendResult(interp, "Memory allocation error", (char *) NULL); return TCL_ERROR; } /* Calc Digest */ - if (DigestInitialize(interp, statePtr, md, cipher, keyObj, mac) != TCL_OK || + if (DigestInitialize(interp, statePtr, digestObj, cipherObj, keyObj, macObj) != TCL_OK || DigestUpdate(statePtr, data, (size_t) data_len, 1) != TCL_OK || DigestFinalize(interp, statePtr, NULL) != TCL_OK) { DigestStateFree(statePtr); return TCL_ERROR; } @@ -1061,12 +1112,12 @@ * Side effects: * Result is message digest or error message * *------------------------------------------------------------------- */ -int DigestFileHandler(Tcl_Interp *interp, Tcl_Obj *inFileObj, const EVP_MD *md, - const EVP_CIPHER *cipher, int format, Tcl_Obj *keyObj, EVP_MAC *mac) { +int DigestFileHandler(Tcl_Interp *interp, Tcl_Obj *inFileObj, Tcl_Obj *digestObj, + Tcl_Obj *cipherObj, int format, Tcl_Obj *keyObj, Tcl_Obj *macObj) { DigestState *statePtr; Tcl_Channel chan = NULL; unsigned char buf[BUFFER_SIZE]; int res = TCL_OK, len; @@ -1090,20 +1141,19 @@ goto done; } Tcl_SetChannelBufferSize(chan, BUFFER_SIZE); /* Initialize hash function */ - if ((res = DigestInitialize(interp, statePtr, md, cipher, keyObj, mac)) != TCL_OK) { + if ((res = DigestInitialize(interp, statePtr, digestObj, cipherObj, keyObj, macObj)) != TCL_OK) { goto done; } /* Read file data and update hash function */ while (!Tcl_Eof(chan)) { len = Tcl_ReadRaw(chan, (char *) buf, BUFFER_SIZE); if (len > 0) { - if (DigestUpdate(statePtr, &buf[0], (size_t) len, 1) != TCL_OK) { - res = TCL_ERROR; + if ((res = DigestUpdate(statePtr, &buf[0], (size_t) len, 1)) != TCL_OK) { goto done; } } } @@ -1119,123 +1169,10 @@ /* Clean-up */ DigestStateFree(statePtr); return res; } -/*******************************************************************/ - -/* - *------------------------------------------------------------------- - * - * GetDigest -- Get message digest - * - * Returns: - * EVP_MD * or NULL - * - *------------------------------------------------------------------- - */ -EVP_MD *GetDigest(Tcl_Interp *interp, Tcl_Obj *objPtr, int *format) { - const EVP_MD *md = NULL; - char *digestName = Tcl_GetStringFromObj(objPtr, NULL); - - if (digestName != NULL) { - md = EVP_get_digestbyname(digestName); - if (md == NULL) { - Tcl_AppendResult(interp, "Invalid digest \"", digestName, "\"", NULL); - return NULL; - } else if (md == EVP_shake128() || md == EVP_shake256()) { - *format |= IS_XOF; - } - } else { - Tcl_AppendResult(interp, "No digest specified", NULL); - return NULL; - } - return md; -} - -/* - *------------------------------------------------------------------- - * - * GetCipher -- Get cipher - * - * Returns: - * EVP_CIPHER * or NULL - * - *------------------------------------------------------------------- - */ -EVP_CIPHER *GetCipher(Tcl_Interp *interp, Tcl_Obj *objPtr, int *type) { - const EVP_CIPHER *cipher = NULL; - char *cipherName = Tcl_GetStringFromObj(objPtr, NULL); - - if (cipherName != NULL) { - cipher = EVP_get_cipherbyname(cipherName); - *type = TYPE_CMAC; - if (cipher == NULL) { - Tcl_AppendResult(interp, "Invalid cipher \"", cipherName, "\"", NULL); - return NULL; - } - } else { - Tcl_AppendResult(interp, "No cipher specified", NULL); - return NULL; - } - return cipher; -} - -/* - *------------------------------------------------------------------- - * - * GetKey -- Get key - * - * Returns: - * unsigned char * or NULL - * - *------------------------------------------------------------------- - */ -unsigned char *GetKey(Tcl_Interp *interp, Tcl_Obj *objPtr, int *type) { - unsigned char *key = Tcl_GetByteArrayFromObj(objPtr, NULL); - - if (key == NULL) { - Tcl_AppendResult(interp, "No key specified", NULL); - return NULL; - } - if (*type == TYPE_MD) { - *type = TYPE_HMAC; - } - return key; -} - -/* - *------------------------------------------------------------------- - * - * GetMAC -- Get MAC - * - * Returns: - * EVP_MAC * or NULL - * - *------------------------------------------------------------------- - */ -EVP_MAC *GetMAC(Tcl_Interp *interp, Tcl_Obj *objPtr, int *type) { - EVP_MAC *mac = NULL; - char *macName = Tcl_GetStringFromObj(objPtr, NULL); - - if (macName != NULL) { - if (strcmp(macName, "cmac") == 0) { - *type = TYPE_CMAC; - } else if (strcmp(macName, "hmac") == 0) { - *type = TYPE_HMAC; - } else { - Tcl_AppendResult(interp, "Invalid MAC \"", macName, "\"", NULL); - return NULL; - } - mac = (void *) macName; - } else { - Tcl_AppendResult(interp, "No MAC specified", NULL); - return NULL; - } - return mac; -} - /*******************************************************************/ /* *------------------------------------------------------------------- * @@ -1255,13 +1192,10 @@ static int DigestMain(int type, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { int idx, start = 1, format = HEX_FORMAT, res = TCL_OK; Tcl_Obj *cipherObj = NULL, *cmdObj = NULL, *dataObj = NULL, *digestObj = NULL; Tcl_Obj *fileObj = NULL, *keyObj = NULL, *macObj = NULL; const char *channel = NULL, *opt; - const EVP_MD *md = NULL; - const EVP_CIPHER *cipher = NULL; - EVP_MAC *mac = NULL; dprintf("Called"); /* Clear interp result */ Tcl_ResetResult(interp); @@ -1317,59 +1251,26 @@ /* If only 1 arg left, it's the data */ if (idx < objc && dataObj == NULL) { dataObj = objv[idx]; } - /* Get cipher */ - if (cipherObj != NULL) { - if ((cipher = GetCipher(interp, cipherObj, &type)) == NULL) { - return TCL_ERROR; - } - } else if (type == TYPE_CMAC) { - Tcl_AppendResult(interp, "No cipher specified", NULL); - return TCL_ERROR; - } - - /* Get message digest */ - if (digestObj != NULL) { - if ((md = GetDigest(interp, digestObj, &format)) == NULL) { - return TCL_ERROR; - } - } else if (type == TYPE_MD || type == TYPE_HMAC) { - Tcl_AppendResult(interp, "No digest specified", NULL); - return TCL_ERROR; - } - - /* Get key */ - if (keyObj != NULL) { - if (GetKey(interp, keyObj, &type) == NULL) { - return TCL_ERROR; - } - } else if (type != TYPE_MD) { - Tcl_AppendResult(interp, "No key specified", NULL); - return TCL_ERROR; - } - - /* Get MAC */ - if (macObj != NULL) { - if ((mac = GetMAC(interp, macObj, &type)) == NULL) { - return TCL_ERROR; - } - } else if (type == TYPE_MAC) { - Tcl_AppendResult(interp, "No MAC specified", NULL); - return TCL_ERROR; + /* Check types */ + if (type == TYPE_MD && cipherObj != NULL) { + type = TYPE_CMAC; + } else if (type == TYPE_MD && keyObj != NULL) { + type = TYPE_HMAC; } /* Calc digest on file, stacked channel, using instance command, or data blob */ if (fileObj != NULL) { - res = DigestFileHandler(interp, fileObj, md, cipher, format | type, keyObj, mac); + res = DigestFileHandler(interp, fileObj, digestObj, cipherObj, format | type, keyObj, macObj); } else if (channel != NULL) { - res = DigestChannelHandler(interp, channel, md, cipher, format | type, keyObj, mac); + res = DigestChannelHandler(interp, channel, digestObj, cipherObj, format | type, keyObj, macObj); } else if (cmdObj != NULL) { - res = DigestCommandHandler(interp, cmdObj, md, cipher, format | type, keyObj, mac); + res = DigestCommandHandler(interp, cmdObj, digestObj, cipherObj, format | type, keyObj, macObj); } else if (dataObj != NULL) { - res = DigestDataHandler(interp, dataObj, md, cipher, format | type, keyObj, mac); + res = DigestDataHandler(interp, dataObj, digestObj, cipherObj, format | type, keyObj, macObj); } else { Tcl_AppendResult(interp, "No operation specified: Use -channel, -command, -data, or -file option", NULL); res = TCL_ERROR; } return res; Index: generic/tlsInfo.c ================================================================== --- generic/tlsInfo.c +++ generic/tlsInfo.c @@ -393,14 +393,17 @@ * None. * *------------------------------------------------------------------- */ int DigestInfo(Tcl_Interp *interp, char *digestName) { + EVP_MD *md; Tcl_Obj *objPtr, *listPtr; - EVP_MD *md = EVP_get_digestbyname(digestName); unsigned long flags; + /* Get message digest */ + md = EVP_get_digestbyname(digestName); + if (md == NULL) { Tcl_AppendResult(interp, "Invalid digest \"", digestName, "\"", NULL); return TCL_ERROR; } @@ -507,11 +510,26 @@ * None. * *------------------------------------------------------------------- */ int MacInfo(Tcl_Interp *interp, char *macName) { - return TCL_OK; + if (strcmp(macName, "cmac") != 0 && strcmp(macName, "hmac") != 0) { + Tcl_AppendResult(interp, "Invalid MAC \"", macName, "\"", NULL); + return TCL_ERROR; + } + + /* Get properties */ + objPtr = Tcl_NewListObj(0, NULL); + if (objPtr == NULL) { + return TCL_ERROR; + } + LAPPEND_STR(interp, objPtr, "name", macName, -1); + LAPPEND_STR(interp, objPtr, "description", "", -1); + LAPPEND_STR(interp, objPtr, "provider", "", -1); + + Tcl_SetObjResult(interp, objPtr); + return TCL_OK; } /* *------------------------------------------------------------------- * @@ -592,11 +610,36 @@ * None. * *------------------------------------------------------------------- */ int PkeyInfo(Tcl_Interp *interp, char *pkeyName) { - return TCL_OK; + Tcl_Obj *objPtr; + EVP_PKEY *pkey = NULL; + +/* In work */ + if (pkey == NULL) { + Tcl_AppendResult(interp, "Invalid public key method \"", pkeyName, "\"", NULL); + return TCL_ERROR; + } + + /* Get properties */ + objPtr = Tcl_NewListObj(0, NULL); + if (objPtr == NULL) { + return TCL_ERROR; + } + LAPPEND_STR(interp, objPtr, "name", OBJ_nid2ln(EVP_PKEY_id(pkey)), -1); + LAPPEND_STR(interp, objPtr, "description", "", -1); + LAPPEND_STR(interp, objPtr, "baseId", OBJ_nid2ln(EVP_PKEY_base_id(pkey)), -1); + LAPPEND_STR(interp, objPtr, "provider", "", -1); + LAPPEND_STR(interp, objPtr, "type", OBJ_nid2ln(EVP_PKEY_type(EVP_PKEY_id(pkey))), -1); + + LAPPEND_INT(interp, objPtr, "size", EVP_PKEY_size(pkey)); + LAPPEND_INT(interp, objPtr, "bits", EVP_PKEY_bits(pkey)); + LAPPEND_INT(interp, objPtr, "security_bits", EVP_PKEY_security_bits(pkey)); + + Tcl_SetObjResult(interp, objPtr); + return TCL_OK; } /* *------------------------------------------------------------------- *