Check-in [d4c2159faf]
Overview
Comment:Added KDF module to derive keys and ivs from passwords and salts. Added -hash option as alias for -digest.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | crypto
Files: files | file ages | folders
SHA3-256: d4c2159faf713eb129fa3b6bac515e9c7c9008fca261e733b9cad1e319735f36
User & Date: bohagan on 2023-12-11 05:24:46
Other Links: branch diff | manifest | tags
Context
2023-12-16
04:56
Changed options processing from using string compares in macros to using Tcl_GetIndexFromObj and switch. check-in: c7540ccbf1 user: bohagan tags: crypto
2023-12-11
05:24
Added KDF module to derive keys and ivs from passwords and salts. Added -hash option as alias for -digest. check-in: d4c2159faf user: bohagan tags: crypto
2023-12-10
05:55
Refactored tlsInfo.c file to clear errors, use Obj in var names, and pass name as object instead of string. Split cipher command from its info function. check-in: d7ab5a4ae1 user: bohagan tags: crypto
Changes

Modified configure from [2fc15c8cab] to [39b72b8793].

5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
# stub library C source files to compile in TEA_ADD_STUB_SOURCES,
# and runtime Tcl library files in TEA_ADD_TCL_SOURCES.
# 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 tlsX509.c"
    for i in $vars; do
	case $i in
	    \$*)
		# allow $-var names
		PKG_SOURCES="$PKG_SOURCES $i"
		PKG_OBJECTS="$PKG_OBJECTS $i"
		;;







|







5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
# stub library C source files to compile in TEA_ADD_STUB_SOURCES,
# and runtime Tcl library files in TEA_ADD_TCL_SOURCES.
# 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 tlsKey.c tlsX509.c"
    for i in $vars; do
	case $i in
	    \$*)
		# allow $-var names
		PKG_SOURCES="$PKG_SOURCES $i"
		PKG_OBJECTS="$PKG_OBJECTS $i"
		;;

Modified configure.ac from [d2a1dc5bcd] to [c43a3df459].

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# public headers that need to be installed in TEA_ADD_HEADERS,
# stub library C source files to compile in TEA_ADD_STUB_SOURCES,
# 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 tlsX509.c])
TEA_ADD_HEADERS([generic/tls.h])
TEA_ADD_INCLUDES([])
TEA_ADD_LIBS([])
TEA_ADD_CFLAGS([])
TEA_ADD_STUB_SOURCES([])
TEA_ADD_TCL_SOURCES([library/tls.tcl])








|







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# public headers that need to be installed in TEA_ADD_HEADERS,
# stub library C source files to compile in TEA_ADD_STUB_SOURCES,
# 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 tlsKey.c tlsX509.c])
TEA_ADD_HEADERS([generic/tls.h])
TEA_ADD_INCLUDES([])
TEA_ADD_LIBS([])
TEA_ADD_CFLAGS([])
TEA_ADD_STUB_SOURCES([])
TEA_ADD_TCL_SOURCES([library/tls.tcl])

Modified doc/cryptography.html from [c88e8b2743] to [b22c8f2c44].

36
37
38
39
40
41
42


43
44
45
46
47
48
49
	    <dd><b>tls::sha1</b> <em>data</em></dd>
	    <dd><b>tls::sha256</b> <em>data</em></dd>
	    <dd><b>tls::sha512</b> <em>data</em></dd>
	    <dd><b>tls::unstack</b> <em>channelId</em></dd>
	    <dt>&nbsp;</dt>
	    <dd><b>tls::encrypt</b> <b>-cipher</b> <em>name</em> <b>-key</b> <em>key ?options?</em></dd>
	    <dd><b>tls::decrypt</b> <b>-cipher</b> <em>name</em> <b>-key</b> <em>key ?options?</em></dd>


	</dl>
    </dd>
    <dd><a href="#OPTIONS">OPTIONS</a></dd>
    <dd><a href="#COMMANDS">COMMANDS</a></dd>
    <dd><a href="#GLOSSARY">GLOSSARY</a> </dd>
    <dd><a href="#EXAMPLES">EXAMPLES</a></dd>
    <dd><a href="#SPECIAL">SPECIAL CONSIDERATIONS</a></dd>







>
>







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
	    <dd><b>tls::sha1</b> <em>data</em></dd>
	    <dd><b>tls::sha256</b> <em>data</em></dd>
	    <dd><b>tls::sha512</b> <em>data</em></dd>
	    <dd><b>tls::unstack</b> <em>channelId</em></dd>
	    <dt>&nbsp;</dt>
	    <dd><b>tls::encrypt</b> <b>-cipher</b> <em>name</em> <b>-key</b> <em>key ?options?</em></dd>
	    <dd><b>tls::decrypt</b> <b>-cipher</b> <em>name</em> <b>-key</b> <em>key ?options?</em></dd>
	    <dt>&nbsp;</dt>
	    <dd><b>tls::derive_key</b> <em>key ?options?</em></dd>
	</dl>
    </dd>
    <dd><a href="#OPTIONS">OPTIONS</a></dd>
    <dd><a href="#COMMANDS">COMMANDS</a></dd>
    <dd><a href="#GLOSSARY">GLOSSARY</a> </dd>
    <dd><a href="#EXAMPLES">EXAMPLES</a></dd>
    <dd><a href="#SPECIAL">SPECIAL CONSIDERATIONS</a></dd>
83
84
85
86
87
88
89


90
91
92
93
94
95
96
<a href="#tls::sha1"><b>tls::sha1</b> <i>data</i></a><br>
<a href="#tls::sha256"><b>tls::sha256</b> <i>data</i></a><br>
<a href="#tls::sha512"><b>tls::sha512</b> <i>data</i></a><br>
<a href="#tls::unstack"><b>tls::unstack</b> <i>channelId</i></a><br>
<br>
<a href="#tls::encrypt"><b>tls::encrypt</b> <b>-cipher</b> <i>name</i> <b>-key</b> <i>key ?options?</i></a><br>
<a href="#tls::decrypt"><b>tls::decrypt</b> <b>-cipher</b> <i>name</i> <b>-key</b> <i>key ?options?</i></a><br>


</p>

<br>
<h3><a name="OPTIONS">OPTIONS</a></h3>

<p>The following options are used by the cryptography commands.</p>
<br>







>
>







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<a href="#tls::sha1"><b>tls::sha1</b> <i>data</i></a><br>
<a href="#tls::sha256"><b>tls::sha256</b> <i>data</i></a><br>
<a href="#tls::sha512"><b>tls::sha512</b> <i>data</i></a><br>
<a href="#tls::unstack"><b>tls::unstack</b> <i>channelId</i></a><br>
<br>
<a href="#tls::encrypt"><b>tls::encrypt</b> <b>-cipher</b> <i>name</i> <b>-key</b> <i>key ?options?</i></a><br>
<a href="#tls::decrypt"><b>tls::decrypt</b> <b>-cipher</b> <i>name</i> <b>-key</b> <i>key ?options?</i></a><br>
<br>
<a href="#tls::derive_key"><b>tls::derive_key</b> <i>?options?</i></a><br>
</p>

<br>
<h3><a name="OPTIONS">OPTIONS</a></h3>

<p>The following options are used by the cryptography commands.</p>
<br>
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148

149
150
151
152
153
154
155
156
157
158
159
160

161
162
163
164
165
166
167
    <dt><a name="-digest"><strong>-digest</strong> <em>name</em></a></dt>
    <dd>Name of hash function (aka message digest) to use.
    See <a href="#tls::digests"><b>tls::digests</b></a> for the valid values.</dd>
</dl>

<dl>
    <dt><a name="-iterations"><strong>-iterations</strong> <em>count</em></a></dt>
    <dd>Number (integer) of iterations on the password to use in deriving the
    encryption key. Default is 10000. Some KDF implementations require an
    iteration count.</dd>
</dl>

<dl>
    <dt><a name="-iv"><strong>-iv</strong> <em>string</em></a></dt>
    <dd>Initialization vector (IV) to use. Required for some ciphers and GMAC.
    Cipher modes CBC, CFB, OFB and CTR all need an IV while ECB mode does not.
    A new, random IV should be created for each use. Think of the IV as a nonce
    (number used once), it's public but random and unpredictable. See the
   <a href="#tls::cipher"><b>tls::cipher</b></a> for iv_length and
    when required (length > 0). If not set, it will default to \x00 fill data.</dd>
</dl>

<dl>
    <dt><a name="-key"><strong>-key</strong> <em>string</em></a></dt>
    <dd>Encryption key to use for cryptography function. Can be a binary or
    text string. Longer keys provide better protection. Used by ciphers, HMAC,
    some CMAC, and some KDF implementations. If the length of the key is &lt;
    <b>key_length</b> it will be padded. If &gt; key_length, it will be rejected.
    See the <a href="#tls::cipher"><b>tls::cipher</b></a> for key_length.</dd>
</dl>

<dl>
    <dt><a name="-mac"><strong>-mac</strong> <em>name</em></a></dt>
    <dd>Name of Message Authentication Code (MAC) to use.
    See <a href="#tls::mac"><b>tls::macs</b></a> for the valid values.</dd>
</dl>

<dl>
    <dt><a name="-password"><strong>-password</strong> <em>string</em></a></dt>
    <dd>Password to use for some KDF functions.</dd>

</dl>

<dl>
    <dt><a name="-properties"><strong>-properties</strong> <em>list</em></a></dt>
    <dd>List of additional properties to pass to cryptography function.</dd>
</dl>

<dl>
    <dt><a name="-salt"><strong>-salt</strong> <em>string</em></a></dt>
    <dd>Specifies salt value to use when encrypting data. Default is to use a
    randomly generated value. This option is used by BLAKE2 MAC and some KDF
    implementations use a non-secret unique cryptographic salt.</dd>

</dl>

<dl>
    <dt><a name="-size"><strong>-size</strong> <em>number</em></a></dt>
    <dd>Set the output hash size in bytes. Used by KMAC128 or KMAC256 to specify
    an output length. The default sizes are 32 or 64 bytes respectively.</dd>
</dl>







|
|
|





|



|







|











|
>




|




|
|
|
>







113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
    <dt><a name="-digest"><strong>-digest</strong> <em>name</em></a></dt>
    <dd>Name of hash function (aka message digest) to use.
    See <a href="#tls::digests"><b>tls::digests</b></a> for the valid values.</dd>
</dl>

<dl>
    <dt><a name="-iterations"><strong>-iterations</strong> <em>count</em></a></dt>
    <dd>Number (integer &gt; 0) of iterations to use in deriving the encryption
    key. Default is 2048. Some <a href="#KDF"><b>KDF</b></a> implementations
    require an iteration count.</dd>
</dl>

<dl>
    <dt><a name="-iv"><strong>-iv</strong> <em>string</em></a></dt>
    <dd>Initialization vector (IV) to use. Required for some ciphers and GMAC.
    Cipher modes CBC, CFB, and OFB all need an IV while ECB and CTR modes do not.
    A new, random IV should be created for each use. Think of the IV as a nonce
    (number used once), it's public but random and unpredictable. See the
   <a href="#tls::cipher"><b>tls::cipher</b></a> for iv_length and
    when required (length > 0). Max is 16 bytes. If not set, it will default to \x00 fill data.</dd>
</dl>

<dl>
    <dt><a name="-key"><strong>-key</strong> <em>string</em></a></dt>
    <dd>Encryption key to use for cryptography function. Can be a binary or
    text string. Longer keys provide better protection. Used by ciphers, HMAC,
    some CMAC, and some KDF implementations. If the length of the key is &lt;
    <b>key_length</b> it will be padded. Max is 64 bytes. If &gt; key_length, it will be rejected.
    See the <a href="#tls::cipher"><b>tls::cipher</b></a> for key_length.</dd>
</dl>

<dl>
    <dt><a name="-mac"><strong>-mac</strong> <em>name</em></a></dt>
    <dd>Name of Message Authentication Code (MAC) to use.
    See <a href="#tls::mac"><b>tls::macs</b></a> for the valid values.</dd>
</dl>

<dl>
    <dt><a name="-password"><strong>-password</strong> <em>string</em></a></dt>
    <dd>Password to use for some KDF functions. If not specified, the default
    value is used. Can be a binary or text string.</dd>
</dl>

<dl>
    <dt><a name="-properties"><strong>-properties</strong> <em>list</em></a></dt>
    <dd>List of additional properties to pass to cryptographic function.</dd>
</dl>

<dl>
    <dt><a name="-salt"><strong>-salt</strong> <em>string</em></a></dt>
    <dd>Specifies salt value to use when encrypting data. Can be a binary or
    text string. Default is to use a randomly generated value. This option is
    used by BLAKE2 MAC and some KDF implementations use a non-secret unique
    cryptographic salt.</dd>
</dl>

<dl>
    <dt><a name="-size"><strong>-size</strong> <em>number</em></a></dt>
    <dd>Set the output hash size in bytes. Used by KMAC128 or KMAC256 to specify
    an output length. The default sizes are 32 or 64 bytes respectively.</dd>
</dl>
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
<br>
<h3><a name="COMMANDS">COMMANDS</a></h3>

<p>The following commands provide access to the OpenSSL cryptography functions.</p>

<dl>

<h4>Info Commands</h4>

    <dt><a name="tls::cipher"><strong>tls::cipher</strong> <em>name</em></a></dt>
    <dd>Return a list of property names and values describing cipher
	<i>name</i>. Properties include name, description, block_size,
	key_length, iv_length, type, and mode list. If block-size is 1,
	then it's a stream cipher, otherwise it's a block cipher.</dd>








|







286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
<br>
<h3><a name="COMMANDS">COMMANDS</a></h3>

<p>The following commands provide access to the OpenSSL cryptography functions.</p>

<dl>

<h4><a name="Info">Info Commands</a></h4>

    <dt><a name="tls::cipher"><strong>tls::cipher</strong> <em>name</em></a></dt>
    <dd>Return a list of property names and values describing cipher
	<i>name</i>. Properties include name, description, block_size,
	key_length, iv_length, type, and mode list. If block-size is 1,
	then it's a stream cipher, otherwise it's a block cipher.</dd>

325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
	compile time flags.</dd>

    <dt><a name="tls::version"><strong>tls::version</strong></a></dt>
    <dd>Returns the OpenSSL version string.</dd>

<br>

<h4>Message Digest (MD) and Message Authentication Code (MAC) Commands</h4>

    <dt><a name="tls::cmac"><strong>tls::cmac</strong>
	<em>?</em><b>-cipher</b><em>? name</em>
	<b>-key</b> <em>key ?</em><b>-bin</b>|<b>-hex</b><em>?
	[</em><b>-chan</b> <em>channelId |</em> <b>-command</b> <em>cmdName |</em>
	<b>-file</b> <em>filename | ?</em><b>-data</b><em>? data]</em></a></dt>
    <dd>Calculate the Cipher-based Message Authentication Code (CMAC) where







|







331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
	compile time flags.</dd>

    <dt><a name="tls::version"><strong>tls::version</strong></a></dt>
    <dd>Returns the OpenSSL version string.</dd>

<br>

<h4><a name="MD_MAC">Message Digest (MD) and Message Authentication Code (MAC) Commands</a></h4>

    <dt><a name="tls::cmac"><strong>tls::cmac</strong>
	<em>?</em><b>-cipher</b><em>? name</em>
	<b>-key</b> <em>key ?</em><b>-bin</b>|<b>-hex</b><em>?
	[</em><b>-chan</b> <em>channelId |</em> <b>-command</b> <em>cmdName |</em>
	<b>-file</b> <em>filename | ?</em><b>-data</b><em>? data]</em></a></dt>
    <dd>Calculate the Cipher-based Message Authentication Code (CMAC) where
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
    <dd>Returns the SHA-2 SHA512 secure hash algorithm digest for <em>data</em> as a hex string.</dd>

    <dt><a name="tls::unstack"><strong>tls::unstack</strong> <em>channelId</em></a></dt>
    <dd>Removes the top level cryptographic transform from channel <em>channelId</em>.</dd>

<br>

<h4>Encryption and Decryption Commands</h4>

    <dt><a name="tls::encrypt"><strong>tls::encrypt</strong>
	<em>?</em><b>-cipher</b><em>? name</em> <b>-key</b> <em>key ?</em><b>-iv</b> <em>string?
	[</em><b>-chan</b> <em>channelId |</em> <b>-command</b> <em>cmdName |</em>
	<b>-infile</b> <em>filename</em> <b>-outfile</b> <em>filename |</em>
	<b>-data</b><em> data]</em></a></dt>
    <dd>Encrypt the data using cipher <em>cipher</em> and output the result per







|







396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
    <dd>Returns the SHA-2 SHA512 secure hash algorithm digest for <em>data</em> as a hex string.</dd>

    <dt><a name="tls::unstack"><strong>tls::unstack</strong> <em>channelId</em></a></dt>
    <dd>Removes the top level cryptographic transform from channel <em>channelId</em>.</dd>

<br>

<h4><a name="Cipher">Encryption and Decryption Commands</a></h4>

    <dt><a name="tls::encrypt"><strong>tls::encrypt</strong>
	<em>?</em><b>-cipher</b><em>? name</em> <b>-key</b> <em>key ?</em><b>-iv</b> <em>string?
	[</em><b>-chan</b> <em>channelId |</em> <b>-command</b> <em>cmdName |</em>
	<b>-infile</b> <em>filename</em> <b>-outfile</b> <em>filename |</em>
	<b>-data</b><em> data]</em></a></dt>
    <dd>Encrypt the data using cipher <em>cipher</em> and output the result per
417
418
419
420
421
422
423

















424
425
426
427
428
429
430
	the I/O options. This command is the opposite of the <b>tls::encrypt</b>
	command. See <a href="#OPTIONS"><b>options</b></a> for usage
	info. Option <b>-iv</b> is only used for some ciphers. See the
	&quot;<b>tls::cipher</b> <em>cipher</em>&quot; command for key and iv
	sizes and when the iv is used (iv_length &gt; 0).</dd>
</dl>


















<br>
<h3><a name="GLOSSARY">GLOSSARY</a></h3>

<p>The following is a list of the terminology used in this package along with
brief definitions. For more details, please consult with the OpenSSL documentation.</p>









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
	the I/O options. This command is the opposite of the <b>tls::encrypt</b>
	command. See <a href="#OPTIONS"><b>options</b></a> for usage
	info. Option <b>-iv</b> is only used for some ciphers. See the
	&quot;<b>tls::cipher</b> <em>cipher</em>&quot; command for key and iv
	sizes and when the iv is used (iv_length &gt; 0).</dd>
</dl>

<br>

<h4><a name="KDF">Key Derivation Function (KDF) Commands</a></h4>

    <dt><a name="tls::derive_key"><strong>tls::derive_key</strong>
	<em>[</em><b>-cipher</b> <em>cipher |</em> <b>-size</b> <em>size]</em>
	<b>-digest</b> <em>digest ?</em><b>-iterations</b> <em>count?
	?</em><b>-password</b> <em>string? ?</em><b>-salt</b> <em>string?</em></a></dt>
    <dd>Derive a key and initialization vector (iv) from a password and salt
	value using PKCS5_PBKDF2_HMAC. This is a more secure way to generate
	keys and ivs for use by <a href="#tls::encrypt"><b>tls::encrypt</b></a>.
	See <a href="#OPTIONS"><b>options</b></a> for usage info. If <b>-cipher</b>
	is specified, then the derived key and iv sized for that cipher are
	returned as a key-value list. If not or if <b>-size</b> is specified,
	then the derived key (dk) of <em>size</em> bytes is returned.</dd>
</dl>

<br>
<h3><a name="GLOSSARY">GLOSSARY</a></h3>

<p>The following is a list of the terminology used in this package along with
brief definitions. For more details, please consult with the OpenSSL documentation.</p>


Modified generic/tls.c from [63ca861d17] to [4273abe6e0].

2548
2549
2550
2551
2552
2553
2554

2555
2556
2557
2558
2559
2560
2561
    Tcl_CreateObjCommand(interp, "tls::misc", MiscObjCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    Tcl_CreateObjCommand(interp, "tls::unimport", UnimportObjCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    Tcl_CreateObjCommand(interp, "tls::status", StatusObjCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);

    Tls_DigestCommands(interp);
    Tls_EncryptCommands(interp);
    Tls_InfoCommands(interp);


    if (interp) {
	Tcl_Eval(interp, tlsTclInitScript);
    }

    return Tcl_PkgProvide(interp, PACKAGE_NAME, PACKAGE_VERSION);
}







>







2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
    Tcl_CreateObjCommand(interp, "tls::misc", MiscObjCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    Tcl_CreateObjCommand(interp, "tls::unimport", UnimportObjCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    Tcl_CreateObjCommand(interp, "tls::status", StatusObjCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);

    Tls_DigestCommands(interp);
    Tls_EncryptCommands(interp);
    Tls_InfoCommands(interp);
    Tls_KeyCommands(interp);

    if (interp) {
	Tcl_Eval(interp, tlsTclInitScript);
    }

    return Tcl_PkgProvide(interp, PACKAGE_NAME, PACKAGE_VERSION);
}

Modified generic/tlsDigest.c from [8122b24581] to [59f6eb5d91].

1237
1238
1239
1240
1241
1242
1243

1244
1245
1246
1247
1248
1249
1250
	OPTSTR("-channel", channel);
	OPTOBJ("-cipher", cipherObj);
	OPTOBJ("-command", cmdObj);
	OPTOBJ("-data", dataObj);
	OPTOBJ("-digest", digestObj);
	OPTOBJ("-file", fileObj);
	OPTOBJ("-filename", fileObj);

	OPTOBJ("-key", keyObj);
	OPTOBJ("-mac", macObj);

	OPTBAD("option", "-bin, -channel, -cipher, -command, -data, -digest, -file, -filename, -hex, -key, or -mac");
	return TCL_ERROR;
    }








>







1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
	OPTSTR("-channel", channel);
	OPTOBJ("-cipher", cipherObj);
	OPTOBJ("-command", cmdObj);
	OPTOBJ("-data", dataObj);
	OPTOBJ("-digest", digestObj);
	OPTOBJ("-file", fileObj);
	OPTOBJ("-filename", fileObj);
	OPTOBJ("-hash", digestObj);
	OPTOBJ("-key", keyObj);
	OPTOBJ("-mac", macObj);

	OPTBAD("option", "-bin, -channel, -cipher, -command, -data, -digest, -file, -filename, -hex, -key, or -mac");
	return TCL_ERROR;
    }

Modified generic/tlsEncrypt.c from [2a45eea685] to [6005ec3c3c].

1246
1247
1248
1249
1250
1251
1252

1253
1254
1255
1256
1257
1258
1259

	OPTSTR("-chan", channel);
	OPTSTR("-channel", channel);
	OPTOBJ("-cipher", cipherObj);
	OPTOBJ("-command", cmdObj);
	OPTOBJ("-data", dataObj);
	OPTOBJ("-digest", digestObj);

	OPTOBJ("-infile", inFileObj);
	OPTOBJ("-outfile", outFileObj);
	OPTOBJ("-key", keyObj);
	OPTOBJ("-iv", ivObj);
	OPTOBJ("-mac", macObj);

	OPTBAD("option", "-chan, -channel, -cipher, -command, -data, -digest, -infile, -key, -iv, -mac, -outfile");







>







1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260

	OPTSTR("-chan", channel);
	OPTSTR("-channel", channel);
	OPTOBJ("-cipher", cipherObj);
	OPTOBJ("-command", cmdObj);
	OPTOBJ("-data", dataObj);
	OPTOBJ("-digest", digestObj);
	OPTOBJ("-hash", digestObj);
	OPTOBJ("-infile", inFileObj);
	OPTOBJ("-outfile", outFileObj);
	OPTOBJ("-key", keyObj);
	OPTOBJ("-iv", ivObj);
	OPTOBJ("-mac", macObj);

	OPTBAD("option", "-chan, -channel, -cipher, -command, -data, -digest, -infile, -key, -iv, -mac, -outfile");

Modified generic/tlsInt.h from [5abc533285] to [0f4281d913].

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#ifndef CONST86
#   if TCL_MAJOR_VERSION > 8
#	define CONST86 const
#   else
#	define CONST86
#   endif
#endif

/*
 * Backwards compatibility for size type change
 */
#if TCL_MAJOR_VERSION < 9 && TCL_MINOR_VERSION < 7
#   define Tcl_Size int
#endif








<







33
34
35
36
37
38
39

40
41
42
43
44
45
46
#ifndef CONST86
#   if TCL_MAJOR_VERSION > 8
#	define CONST86 const
#   else
#	define CONST86
#   endif
#endif

/*
 * Backwards compatibility for size type change
 */
#if TCL_MAJOR_VERSION < 9 && TCL_MINOR_VERSION < 7
#   define Tcl_Size int
#endif

194
195
196
197
198
199
200

201
202
203
204
205
206
void            Tls_Error(State *statePtr, char *msg);
void            Tls_Free(char *blockPtr);
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);


BIO             *BIO_new_tcl(State* statePtr, int flags);

#define PTR2INT(x) ((int) ((intptr_t) (x)))

#endif /* _TLSINT_H */







>






193
194
195
196
197
198
199
200
201
202
203
204
205
206
void            Tls_Error(State *statePtr, char *msg);
void            Tls_Free(char *blockPtr);
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);

BIO             *BIO_new_tcl(State* statePtr, int flags);

#define PTR2INT(x) ((int) ((intptr_t) (x)))

#endif /* _TLSINT_H */

Added generic/tlsKey.c version [9989291d21].

















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*
 * Key Derivation Function (KDF) Module
 *
 * Provides commands to derive keys.
 *
 * Copyright (C) 2023 Brian O'Hagan
 *
 */

#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));
	return TCL_ERROR;
    }

    if (cipher == NULL) {
	if (size > max) size = max;
	iklen = size;
	ivlen = 0;
    } else {
	iklen = EVP_CIPHER_key_length(cipher);
	ivlen = EVP_CIPHER_iv_length(cipher);
	size = iklen+ivlen;
    }

    /* Perform password derivation */
    if (!PKCS5_PBKDF2_HMAC(passwd, pass_len, salt, salt_len, iter, md, size, tmpkeyiv)) {
	Tcl_AppendResult(interp, "Key derivation failed: ", REASON(), NULL);
	return TCL_ERROR;
    }

   /* Return key and iv */
    if (cipher == NULL) {
	resultObj = Tcl_NewByteArrayObj(tmpkeyiv, size);
    } else {
	resultObj = Tcl_NewListObj(0, NULL);
	LAPPEND_BARRAY(interp, resultObj, "key", tmpkeyiv, iklen);
	LAPPEND_BARRAY(interp, resultObj, "iv", tmpkeyiv+iklen, ivlen);
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
    	clientData = clientData;
}

/*
 *-------------------------------------------------------------------
 *
 * Tls_KeyCommands --
 *
 *	Create key commands
 *
 * Returns:
 *	TCL_OK or TCL_ERROR
 *
 * Side effects:
 *	Creates commands
 *
 *-------------------------------------------------------------------
 */
int Tls_KeyCommands(Tcl_Interp *interp) {
    Tcl_CreateObjCommand(interp, "tls::derive_key", DeriveKey, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    return TCL_OK;
}

Modified win/makefile.vc from [c94d145e50] to [ac05bd257a].

27
28
29
30
31
32
33

34
35
36
37
38
39
40
# defined by rules for object files.
PRJ_OBJS = $(TMP_DIR)\tls.obj \
	$(TMP_DIR)\tlsBIO.obj \
	$(TMP_DIR)\tlsDigest.obj \
	$(TMP_DIR)\tlsEncrypt.obj \
	$(TMP_DIR)\tlsInfo.obj \
	$(TMP_DIR)\tlsIO.obj \

	$(TMP_DIR)\tlsX509.obj

# Define any additional project include flags
# SSL_INSTALL_FOLDER = with the OpenSSL installation folder following.
PRJ_INCLUDES = -I"$(SSL_INSTALL_FOLDER)\include" -I"$(OPENSSL_INSTALL_DIR)\include"

# Define any additional compiler flags that might be required for the project







>







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# defined by rules for object files.
PRJ_OBJS = $(TMP_DIR)\tls.obj \
	$(TMP_DIR)\tlsBIO.obj \
	$(TMP_DIR)\tlsDigest.obj \
	$(TMP_DIR)\tlsEncrypt.obj \
	$(TMP_DIR)\tlsInfo.obj \
	$(TMP_DIR)\tlsIO.obj \
	$(TMP_DIR)\tlsKey.obj \
	$(TMP_DIR)\tlsX509.obj

# Define any additional project include flags
# SSL_INSTALL_FOLDER = with the OpenSSL installation folder following.
PRJ_INCLUDES = -I"$(SSL_INSTALL_FOLDER)\include" -I"$(OPENSSL_INSTALL_DIR)\include"

# Define any additional compiler flags that might be required for the project