Diff

Differences From Artifact [9989291d21]:

To Artifact [8cdbc99261]:


9
10
11
12
13
14
15







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

59

60
61



62
63
64

65


66

67

68


69


70
71
72
73
74
75



76


77
78
79

80






81

82
83

84
85



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

#include "tlsInt.h"
#include "tclOpts.h"
#include <openssl/crypto.h>

/*******************************************************************/








/*
 *-------------------------------------------------------------------
 *
 * DeriveKey --
 *
 *	PKCS5_PBKDF2_HMAC key derivation function (KDF) specified by PKCS #5.
 *	See RFC 6070.
 *
 * Returns:
 *	TCL_OK or TCL_ERROR
 *
 * Side effects:
 *	Sets result to a list of key and iv values, or an error message
 *
 *-------------------------------------------------------------------
 */
static int DeriveKey(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
    int key_len = 0, md_len = 0, pass_len = 0, salt_len = 0;
    int iklen, ivlen, iter = PKCS5_DEFAULT_ITER;
    unsigned char *passwd = NULL, *salt = NULL;
    Tcl_Obj *cipherObj = NULL, *digestObj = NULL, *passwdObj = NULL, *saltObj = NULL, *resultObj;
    const EVP_MD *md = NULL;
    const EVP_CIPHER *cipher = NULL;
    int max = EVP_MAX_KEY_LENGTH + EVP_MAX_IV_LENGTH, size = max;
    unsigned char tmpkeyiv[EVP_MAX_KEY_LENGTH + EVP_MAX_IV_LENGTH];


    dprintf("Called");

    /* Clear errors */
    Tcl_ResetResult(interp);
    ERR_clear_error();

    /* Validate arg count */
    if (objc < 3 || objc > 11) {
	Tcl_WrongNumArgs(interp, 1, objv, "[-cipher cipher | -size length] -digest digest ?-iterations count? ?-password string? ?-salt string?");
	return TCL_ERROR;
    }

    /* Init buffers */
    memset(tmpkeyiv, 0, EVP_MAX_KEY_LENGTH + EVP_MAX_IV_LENGTH);

    /* Get options */
    for (int idx = 1; idx < objc; idx++) {

	char *opt = Tcl_GetStringFromObj(objv[idx], NULL);


	if (opt[0] != '-') {



	    break;
	}


	OPTOBJ("-cipher", cipherObj);


	OPTOBJ("-digest", digestObj);

	OPTOBJ("-hash", digestObj);

	OPTINT("-iterations", iter);


	OPTOBJ("-password", passwdObj);


	OPTOBJ("-salt", saltObj);
	OPTINT("-size", size);

	OPTBAD("option", "-cipher, -digest, -iterations, -password, -salt, or -size option");
	return TCL_ERROR;
    }






    /* Validate options */
    if (cipherObj != NULL) {
	char *name = Tcl_GetByteArrayFromObj(cipherObj, NULL);

	cipher = EVP_get_cipherbyname(name);






    }

    if (digestObj != NULL) {
	char *name = Tcl_GetStringFromObj(digestObj, &md_len);

	md = EVP_get_digestbyname(name);
    } else {



	Tcl_AppendResult(interp, "No digest specified", NULL);
	return TCL_ERROR;
    }
    if (passwdObj != NULL) {
	passwd = Tcl_GetByteArrayFromObj(passwdObj, &pass_len);
    }
    if (saltObj != NULL) {
	salt = Tcl_GetByteArrayFromObj(saltObj, &salt_len);
    }
    if (iter < 1) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf("Invalid iterations count %d: must be > 0", iter));
	return TCL_ERROR;
    }
    if (size < 1 || size > max) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf("Invalid derived key length %d: must be 0 < size <= %d", size, max));







>
>
>
>
>
>
>

















|


|




>


















>
|
>
|
|
>
>
>
|
|

>
|
>
>
|
>
|
>
|
>
>
|
>
>
|
<
|
<
|
<
>
>
>
|
>
>

|
<
>
|
>
>
>
>
>
>
|
>
|
<
>
|
|
>
>
>
|
|
|
<
<
<
<
<







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

93

94

95
96
97
98
99
100
101
102

103
104
105
106
107
108
109
110
111
112
113

114
115
116
117
118
119
120
121
122





123
124
125
126
127
128
129

#include "tlsInt.h"
#include "tclOpts.h"
#include <openssl/crypto.h>

/*******************************************************************/

static const char *command_opts [] = { 
    "-cipher", "-digest", "-hash", "-iterations", "-password", "-salt", "-size", NULL};

enum _command_opts {
    _opt_cipher, _opt_digest, _opt_hash, _opt_iter, _opt_password, _opt_salt, _opt_size
};

/*
 *-------------------------------------------------------------------
 *
 * DeriveKey --
 *
 *	PKCS5_PBKDF2_HMAC key derivation function (KDF) specified by PKCS #5.
 *	See RFC 6070.
 *
 * Returns:
 *	TCL_OK or TCL_ERROR
 *
 * Side effects:
 *	Sets result to a list of key and iv values, or an error message
 *
 *-------------------------------------------------------------------
 */
static int DeriveKey(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
    int key_len = 0, md_len = 0, pass_len = 0, salt_len = 0, fn;
    int iklen, ivlen, iter = PKCS5_DEFAULT_ITER;
    unsigned char *passwd = NULL, *salt = NULL;
    Tcl_Obj *resultObj;
    const EVP_MD *md = NULL;
    const EVP_CIPHER *cipher = NULL;
    int max = EVP_MAX_KEY_LENGTH + EVP_MAX_IV_LENGTH, size = max;
    unsigned char tmpkeyiv[EVP_MAX_KEY_LENGTH + EVP_MAX_IV_LENGTH];
    char *cipherName = NULL, *digestName = NULL;

    dprintf("Called");

    /* Clear errors */
    Tcl_ResetResult(interp);
    ERR_clear_error();

    /* Validate arg count */
    if (objc < 3 || objc > 11) {
	Tcl_WrongNumArgs(interp, 1, objv, "[-cipher cipher | -size length] -digest digest ?-iterations count? ?-password string? ?-salt string?");
	return TCL_ERROR;
    }

    /* Init buffers */
    memset(tmpkeyiv, 0, EVP_MAX_KEY_LENGTH + EVP_MAX_IV_LENGTH);

    /* Get options */
    for (int idx = 1; idx < objc; idx++) {
	/* Get option */
	if (Tcl_GetIndexFromObj(interp, objv[idx], command_opts, "option", 0, &fn) != TCL_OK) {
	    return TCL_ERROR;
	}

	/* Validate arg has value */
	if (++idx >= objc) {
	    Tcl_AppendResult(interp, "No value for option \"", command_opts[fn], "\"", (char *) NULL);
	return TCL_ERROR;
    }

	switch(fn) {
	case _opt_cipher:
	    GET_OPT_STRING(objv[idx], cipherName, NULL);
	    break;
	case _opt_digest:
	case _opt_hash:
	    GET_OPT_STRING(objv[idx], digestName, NULL);
	    break;
	case _opt_iter:
	    GET_OPT_INT(objv[idx], &iter);
	    break;
	case _opt_password:
	    GET_OPT_BYTE_ARRAY(objv[idx], passwd, &pass_len);
	    break;
	case _opt_salt:

	    GET_OPT_BYTE_ARRAY(objv[idx], salt, &salt_len);

	    break;

	case _opt_size:
	    GET_OPT_INT(objv[idx], &size);
	    break;
	}
    }

    /* Validate options */
    if (cipherName != NULL) {

#if OPENSSL_VERSION_NUMBER < 0x30000000L
	cipher = EVP_get_cipherbyname(cipherName);
#else
	cipher = EVP_CIPHER_fetch(NULL, cipherName, NULL);
#endif
	if (cipher == NULL) {
	    Tcl_AppendResult(interp, "Invalid cipher: \"", cipherName, "\"", NULL);
	    return TCL_ERROR;
	}
    }
    if (digestName != NULL) {

#if OPENSSL_VERSION_NUMBER < 0x30000000L
	md = EVP_get_digestbyname(digestName);
#else
	md = EVP_MD_fetch(NULL, digestName, NULL);
#endif
	if (md == NULL) {
	    Tcl_AppendResult(interp, "Invalid digest: \"", digestName, "\"", NULL);
	    return TCL_ERROR;
	}





    }
    if (iter < 1) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf("Invalid iterations count %d: must be > 0", iter));
	return TCL_ERROR;
    }
    if (size < 1 || size > max) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf("Invalid derived key length %d: must be 0 < size <= %d", size, max));