Check-in [c5c9b26ac8]
Overview
Comment:Add digest and MAC use of EVP_DigestFinalXOF for XOF hash functions. Renamed security level option from -securitylevel to -security_level. Added more description info to digest and hash documentation. Added examples for tls::digest command to documentation.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | crypto
Files: files | file ages | folders
SHA3-256: c5c9b26ac8ce20153a90ac77dbb79fee07b73e04000cef6d403a976aa327fe39
User & Date: bohagan on 2023-11-21 03:44:40
Other Links: branch diff | manifest | tags
Context
2023-11-21
22:03
Renamed digest command to md. Updated function names to use Digest prefix. check-in: 4134be17b3 user: bohagan tags: crypto
03:44
Add digest and MAC use of EVP_DigestFinalXOF for XOF hash functions. Renamed security level option from -securitylevel to -security_level. Added more description info to digest and hash documentation. Added examples for tls::digest command to documentation. check-in: c5c9b26ac8 user: bohagan tags: crypto
2023-11-20
19:07
Added CMAC test cases check-in: adfb4a0349 user: bohagan tags: crypto
Changes

Modified doc/tls.html from [cb37aa64df] to [e059630135].

123
124
125
126
127
128
129
130

131
132
133
134
135
136
137
123
124
125
126
127
128
129

130
131
132
133
134
135
136
137







-
+







	host port</em></a></dt>
    <dt><b>tls::socket</b><em> ?-server command? ?options? port</em></dt>
    <dd>This is a helper function that utilizes the underlying
	commands (<strong>tls::import</strong>). It behaves
	exactly the same as the native Tcl <strong>socket</strong>
	command except that the options can include any of the
	applicable <a href="#tls::import"><strong>tls:import</strong></a>
	options with one additional option:
	options with one additional option:</dd>
<blockquote>
    <dl>
	<dt><strong>-autoservername</strong> <em>bool</em></dt>
	<dd>Automatically send the -servername as the <em>host</em> argument
	    (default is <em>false</em>)</dd>
    </dl>
</blockquote>
203
204
205
206
207
208
209
210

211
212
213
214
215
216
217
203
204
205
206
207
208
209

210
211
212
213
214
215
216
217







-
+







	<dt><strong>-request </strong><em>bool</em></dt>
	<dd>Request a certificate from peer during SSL handshake.
	    (default is <em>true</em>)</dd>
	<dt><strong>-require</strong> <em>bool</em></dt>
	<dd>Require a valid certificate from peer during SSL handshake.
	    If this is set to true, then <strong>-request</strong> must
	    also be set to true. (default is <em>false</em>)</dd>
	<dt><strong>-securitylevel</strong> <em>integer</em></dt>
	<dt><strong>-security_level</strong> <em>integer</em></dt>
	<dd>Set security level. Must be 0 to 5. The security level affects
	    cipher suite encryption algorithms, supported ECC curves,
	    supported signature algorithms, DH parameter sizes, certificate
	    key sizes and signature algorithms. The default is 1.
	    Level 3 and higher disable support for session tickets and only
	    accept cipher suites that provide forward secrecy.</dd>
	<dt><strong>-server</strong> <em>bool</em></dt>
252
253
254
255
256
257
258
259

260
261
262
263


264
265
266
267
268
269
270
252
253
254
255
256
257
258

259
260
261


262
263
264
265
266
267
268
269
270







-
+


-
-
+
+







    <dt><a name="tls::handshake"><strong>tls::handshake</strong> <em>channel</em></a></dt>
    <dd>Forces handshake to take place, and returns 0 if
	handshake is still in progress (non-blocking), or 1 if
	the handshake was successful. If the handshake failed
	this routine will throw an error.</dd>
    <dt>&nbsp;</dt>
    <dt><a name="tls::status"><strong>tls::status</strong>
    <em>?-local? channel</em></a></dt>
    <em>?</em><b>-local</b><em>? channel</em></a></dt>
    <dd>Returns the current status of the certificate for an SSL
	channel. The result is a list of key-value pairs describing
	the certificate. If the result is an empty list then the
	SSL handshake has not yet completed. If <em>-local</em> is
	the certificate. If the SSL handshake has not yet completed,
	an empty list is returned. If <b>-local</b> is
	specified, then the local certificate is used.</dd>
<blockquote>
	<b>SSL Status</b>
    <dl>
	<dt><strong>alpn</strong> <em>protocol</em></dt>
	<dd>The protocol selected after Application-Layer Protocol
	    Negotiation (ALPN).</dd>
374
375
376
377
378
379
380
381

382
383

384
385
386
387
388
389
390
391
392


393
394
395
396
397
398
399
400
401
402

403
404
405
406
407



408

409
410
411


412
413
414
415
416
417
418
374
375
376
377
378
379
380

381
382

383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403

404
405
406
407
408
409
410
411
412

413
414
415
416
417
418
419
420
421
422
423
424
425







-
+

-
+









+
+









-
+





+
+
+
-
+



+
+







	<dt><strong>state</strong> <em>state</em></dt>
	<dd>State of the connection.</dd>
	<dt><strong>servername</strong> <em>name</em></dt>
	<dd>The name of the connected to server.</dd>
	<dt><strong>protocol</strong> <em>version</em></dt>
	<dd>The protocol version used for the connection:
	    SSL2, SSL3, TLS1, TLS1.1, TLS1.2, TLS1.3, or unknown.</dd>
	<dt><strong>renegotiation</strong> <em>boolean</em></dt>
	<dt><strong>renegotiation_allowed</strong> <em>boolean</em></dt>
	<dd>Whether protocol renegotiation is supported or not.</dd>
	<dt><strong>securitylevel</strong> <em>level</em></dt>
	<dt><strong>security_level</strong> <em>level</em></dt>
	<dd>The security level used for selection of ciphers, key size, etc.</dd>
	<dt><strong>session_reused</strong> <em>boolean</em></dt>
	<dd>Whether the session has been reused or not.</dd>
	<dt><strong>is_server</strong> <em>boolean</em></dt>
	<dd>Whether the connection is configured as a server (1) or client (0).</dd>
	<dt><strong>compression</strong> <em>mode</em></dt>
	<dd>Compression method.</dd>
	<dt><strong>expansion</strong> <em>mode</em></dt>
	<dd>Expansion method.</dd>
	<dt><strong>caList</strong> <em>list</em></dt>
	<dd>List of Certificate Authorities (CA) for X.509 certificate.</dd>
    </dl>
</blockquote>
<blockquote>
	<b>Cipher Info</b>
    <dl>
	<dt><strong>cipher</strong> <em>cipher</em></dt>
	<dd>The current cipher in use for the connection.</dd>
	<dt><strong>standard_name</strong> <em>name</em></dt>
	<dd>The standard RFC name of cipher.</dd>
	<dt><strong>bits</strong> <em>n</em></dt>
	<dt><strong>algorithm_bits</strong> <em>n</em></dt>
	<dd>The number of processed bits used for cipher.</dd>
	<dt><strong>secret_bits</strong> <em>n</em></dt>
	<dd>The number of secret bits used for cipher.</dd>
	<dt><strong>min_version</strong> <em>version</em></dt>
	<dd>The minimum protocol version for cipher.</dd>
	<dt><strong>cipher_is_aead</strong> <em>boolean</em></dt>
	<dd>Whether the cipher is Authenticated encryption with associated
	data (AEAD).</dd>
	<dt><strong>id</strong> <em>id</em></dt>
	<dt><strong>cipher_id</strong> <em>id</em></dt>
	<dd>The OpenSSL cipher id.</dd>
	<dt><strong>description</strong> <em>string</em></dt>
	<dd>A text description of the cipher.</dd>
	<dt><strong>handshake_digest</strong> <em>boolean</em></dt>
	<dd>Digest used during handshake.</dd>
    </dl>
</blockquote>
<blockquote>
	<b>Session Info</b>
    <dl>
	<dt><strong>alpn</strong> <em>protocol</em></dt>
	<dd>The protocol selected after Application-Layer Protocol
470
471
472
473
474
475
476
477
478
479
480
481
482







483
484


485
486
487
488




489
490
491
492
493




494
495
496
497


498





499
500
501
502
503







504
505
506
507
508
509
510
511







512
513
514
515
516
517
518
519









520
521
522
523
524
525
526
477
478
479
480
481
482
483






484
485
486
487
488
489
490
491

492
493
494
495


496
497
498
499
500
501
502


503
504
505
506
507
508
509
510
511
512

513
514
515
516
517
518
519
520
521

522
523
524
525
526
527
528
529
530
531





532
533
534
535
536
537
538
539
540






541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556







-
-
-
-
-
-
+
+
+
+
+
+
+

-
+
+


-
-
+
+
+
+



-
-
+
+
+
+




+
+
-
+
+
+
+
+




-
+
+
+
+
+
+
+



-
-
-
-
-
+
+
+
+
+
+
+


-
-
-
-
-
-
+
+
+
+
+
+
+
+
+







	compile time flags.</dd>

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

    <br>
    <dt><a name="tls::digest"><strong>tls::digest</strong> <b>-digest</b>
	<em>name ?-bin|-hex? [-file filename | -command cmdName |
	-chan channelId | -data data]</em></a></dt>
    <dd>Calculate the message digest for data using <em>digest</em> hash
	function. Returns value as a hex string (default) or as a binary value
	with <b>-bin</b> or <b>-binary</b> option. Digest can be any OpenSSL
	supported hash function including: <b>md4</b>, <b>md5</b>, <b>sha1</b>,
	<em>name ?</em><b>-bin</b>|<b>-hex</b><em>? [</em><b>-file</b> <em>filename | </em><b>-command</b> <em>cmdName |
	</em><b>-chan</b> <em>channelId | </em><b>-data</b> <em>data]</em></a></dt>
    <dd>Calculate the message digest (MD) of data using <em>name</em> hash
	function and return the resulting hash value as a hex string (default)
	or as a binary value with <b>-bin</b> or <b>-binary</b> option. MDs
	are used to ensure the integrity of data. The hash function can be any
	supported OpenSSL algorithm such as <b>md4</b>, <b>md5</b>, <b>sha1</b>,
	<b>sha256</b>, <b>sha512</b>, <b>sha3-256</b>, etc. See
	<b>tls::digests</b> command for a full list.
	<b>tls::digests</b> command for a full list. In OpenSSL 3.0+, older
	algorithms may reside in the legacy provider.
	<br>
	Using the <b>-data</b> option will immediately return the message
	digest for <em>data</em> in the specified format.
	<br>
	digest for <em>data</em> in the specified format. Example code:
<blockquote><code>
		set md [::tls::digest sha256 "Some example data."]<br>
</code></blockquote>
	Using the <b>-file</b> or <b>-filename</b> option will open file
	<em>filename</em>, read the file data, close the file, and return the
	message digest in the specified format. This uses the TCL APIs, so VFS
	files are supported.
	<br>
	files are supported. Example code:
<blockquote><code>
		set md [::tls::digest -digest sha256 -file test_file.txt]<br>
</code></blockquote>
	Using the <b>-chan</b> or <b>-channel</b> option, a stacked channel is
	created for <em>channelId</em> and data read from the channel is used
	to calculate a message digest with the result returned with the last
	read operation before EOF. Channel is automatically set to binary mode.
	Example code:
<blockquote><code>
	<br>
		set ch [open test_file.txt r]<br>
		::tls::digest -digest sha256 -chan $ch<br>
		while {![eof $ch]} {set md [read $ch 4096]}<br>
		close $ch
</code></blockquote>
	Using the <b>-command</b> option, a new command <em>cmdName</em> is
	created and returned. To add data to the hash function, call
	&quot;<em>cmdName</em> <b>update</b> <em>data</em>&quot;, where data is
	the data to add. When done, call &quot;<em>cmdName</em> <b>finalize</b>&quot;
	to return the message digest.
	to return the message digest. Example code:
<blockquote><code>
		set cmd [::tls::digest -digest sha256 -command ::tls::temp]<br>
		$cmd update "Some data. "<br>
		$cmd update "More data."<br>
		set md [$cmd finalize]
</code></blockquote>
	</dd>

    <dt><a name="tls::cmac"><strong>tls::cmac</strong> <b>-cipher</b> <em>name</em>
	<b>-key</b> <em>key ?-bin|-hex? [-file filename | -command cmdName |
	-chan channelId | -data data]</em></a></dt>
    <dd>Calculate the Cipher-based Message Authentication Code (CMAC). Same arguments
	as <b>tls::digest</b> with additional option <b>-cipher</b> to specify the
	cipher to use and for certain ciphers, <b>-key</b> to specify the key.</dd>
	<b>-key</b> <em>key ?</em><b>-bin</b>|<b>-hex</b><em>? [</em><b>-file</b> <em>filename | </em><b>-command</b> <em>cmdName |
	</em><b>-chan</b> <em>channelId | </em><b>-data</b> <em>data]</em></a></dt>
    <dd>Calculate the Cipher-based Message Authentication Code (CMAC). MACs
	are used to ensure authenticity and the integrity of data. It uses the
	same options as <b>tls::digest</b>, plus the additional option
	<b>-cipher</b> to specify the cipher to use and for certain ciphers,
	<b>-key</b> to specify the key.</dd>

    <dt><a name="tls::hmac"><strong>tls::hmac</strong> <b>-digest</b> <em>name</em>
	<b>-key</b> <em>key ?-bin|-hex? [-file filename | -command cmdName |
	-chan channelId | -data data]</em></a></dt>
    <dd>Calculate the Hashed Message Authentication Code (HMAC). Same arguments
	as <b>tls::digest</b> with additional option <b>-key</b> to specify the
	key to use. To salt a password, append or prepend the salt
	data to the password. </dd>
	<b>-key</b> <em>key ?</em><b>-bin</b>|<b>-hex</b><em>? [</em><b>-file</b> <em>filename | </em><b>-command</b> <em>cmdName |
	</em><b>-chan</b> <em>channelId | </em><b>-data</b> <em>data]</em></a></dt>
    <dd>Calculate the Hash-based Message Authentication Code (HMAC). HMACs are
	used to ensure the data integrity and authenticity of a message using a
	shared secret key. The cryptographic strength depends upon the size of
	the key and the security of the hash function used. It uses the same
	options as <b>tls::digest</b>, plus additional option <b>-key</b> to
	specify the key to use. To salt a password, append or prepend the salt
	data to the password.</dd>

    <dt><a name="tls::md4"><strong>tls::md4</strong> <em>data</em></a></dt>
    <dd>Returns the MD4 message-digest for <em>data</em> as a hex string.</dd>

    <dt><a name="tls::md5"><strong>tls::md5</strong> <em>data</em></a></dt>
    <dd>Returns the MD5 message-digest for <em>data</em> as a hex string.</dd>

Modified generic/tls.c from [0db9f8be24] to [66b088c361].

1110
1111
1112
1113
1114
1115
1116
1117

1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130

1131
1132
1133
1134
1135
1136
1137
1110
1111
1112
1113
1114
1115
1116

1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129

1130
1131
1132
1133
1134
1135
1136
1137







-
+












-
+







	OPTBYTE("-key", key, key_len);
	OPTSTR("-keyfile", keyfile);
	OPTSTR("-model", model);
	OPTOBJ("-password", password);
	OPTBOOL("-post_handshake", post_handshake);
	OPTBOOL("-request", request);
	OPTBOOL("-require", require);
	OPTINT("-securitylevel", level);
	OPTINT("-security_level", level);
	OPTBOOL("-server", server);
	OPTSTR("-servername", servername);
	OPTSTR("-session_id", session_id);
	OPTBOOL("-ssl2", ssl2);
	OPTBOOL("-ssl3", ssl3);
	OPTBOOL("-tls1", tls1);
	OPTBOOL("-tls1.1", tls1_1);
	OPTBOOL("-tls1.2", tls1_2);
	OPTBOOL("-tls1.3", tls1_3);
	OPTOBJ("-validatecommand", vcmd);
	OPTOBJ("-vcmd", vcmd);

	OPTBAD("option", "-alpn, -cadir, -cafile, -cert, -certfile, -cipher, -ciphersuites, -command, -dhparams, -key, -keyfile, -model, -password, -post_handshake, -request, -require, -securitylevel, -server, -servername, -session_id, -ssl2, -ssl3, -tls1, -tls1.1, -tls1.2, -tls1.3, or -validatecommand");
	OPTBAD("option", "-alpn, -cadir, -cafile, -cert, -certfile, -cipher, -ciphersuites, -command, -dhparams, -key, -keyfile, -model, -password, -post_handshake, -request, -require, -security_level, -server, -servername, -session_id, -ssl2, -ssl3, -tls1, -tls1.1, -tls1.2, -tls1.3, or -validatecommand");

	return TCL_ERROR;
    }
    if (request)		verify |= SSL_VERIFY_CLIENT_ONCE | SSL_VERIFY_PEER;
    if (request && require)	verify |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
    if (request && post_handshake)	verify |= SSL_VERIFY_POST_HANDSHAKE;
    if (verify == 0)		verify = SSL_VERIFY_NONE;
2004
2005
2006
2007
2008
2009
2010
2011

2012
2013
2014
2015
2016
2017
2018
2004
2005
2006
2007
2008
2009
2010

2011
2012
2013
2014
2015
2016
2017
2018







-
+







	/* Get protocol */
	LAPPEND_STR(interp, objPtr, "protocol", SSL_get_version(ssl), -1);

	/* Renegotiation allowed */
	LAPPEND_BOOL(interp, objPtr, "renegotiation_allowed", SSL_get_secure_renegotiation_support(ssl));

	/* Get security level */
	LAPPEND_INT(interp, objPtr, "securitylevel", SSL_get_security_level(ssl));
	LAPPEND_INT(interp, objPtr, "security_level", SSL_get_security_level(ssl));

	/* Session info */
	LAPPEND_BOOL(interp, objPtr, "session_reused", SSL_session_reused(ssl));

	/* Is server info */
	LAPPEND_BOOL(interp, objPtr, "is_server", SSL_is_server(ssl));

2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071




2072
2073
2074
2075
2076
2077
2078
2051
2052
2053
2054
2055
2056
2057




2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078







-
-
-
-










+
+
+
+







	LAPPEND_STR(interp, objPtr, "keyExchangeNID", (char *)OBJ_nid2ln(SSL_CIPHER_get_kx_nid(cipher)), -1);
	LAPPEND_STR(interp, objPtr, "authenticationNID", (char *)OBJ_nid2ln(SSL_CIPHER_get_auth_nid(cipher)), -1);

	/* message authentication code - Cipher is AEAD (e.g. GCM or ChaCha20/Poly1305) or not */
	/* Authenticated Encryption with associated data (AEAD) check */
	LAPPEND_BOOL(interp, objPtr, "cipher_is_aead", SSL_CIPHER_is_aead(cipher));

	/* Digest used during the SSL/TLS handshake when using the cipher. */
	md = SSL_CIPHER_get_handshake_digest(cipher);
	LAPPEND_STR(interp, objPtr, "handshake_digest", (char *)EVP_MD_name(md), -1);

	/* Get OpenSSL-specific ID, not IANA ID */
	LAPPEND_INT(interp, objPtr, "cipher_id", (int) SSL_CIPHER_get_id(cipher));

	/* Two-byte ID used in the TLS protocol of the given cipher */
	LAPPEND_INT(interp, objPtr, "protocol_id", (int) SSL_CIPHER_get_protocol_id(cipher));

	/* Textual description of the cipher */
	if (SSL_CIPHER_description(cipher, buf, sizeof(buf)) != NULL) {
	    LAPPEND_STR(interp, objPtr, "description", buf, -1);
	}

	/* Digest used during the SSL/TLS handshake when using the cipher. */
	md = SSL_CIPHER_get_handshake_digest(cipher);
	LAPPEND_STR(interp, objPtr, "handshake_digest", (char *)EVP_MD_name(md), -1);
    }

    /* Session info */
    session = SSL_get_session(ssl);
    if (session != NULL) {
	const unsigned char *ticket;
	size_t len2;

Modified generic/tlsDigest.c from [294d716507] to [766239257b].

24
25
26
27
28
29
30

31
32
33
34
35
36
37
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38







+







#define BUFFER_SIZE	65536
#define CHAN_EOF	0x10
#define READ_DELAY	5

/* Digest format and operation */
#define BIN_FORMAT	0x01
#define HEX_FORMAT	0x02
#define IS_XOF		0x08
#define TYPE_MD		0x10
#define TYPE_HMAC	0x20
#define TYPE_CMAC	0x40

/*
 * This structure defines the per-instance state of a digest operation.
 */
235
236
237
238
239
240
241

242





243
244

245
246
247
248
249
250
251
236
237
238
239
240
241
242
243

244
245
246
247
248
249
250
251
252
253
254
255
256
257
258







+
-
+
+
+
+
+


+







int Tls_DigestFinialize(Tcl_Interp *interp, DigestState *statePtr, Tcl_Obj **resultObj) {
    unsigned char md_buf[EVP_MAX_MD_SIZE];
    unsigned int md_len;
    int res = 0;

    /* Finalize hash function and calculate message digest */
    if (statePtr->format & TYPE_MD) {
	if (!(statePtr->format & IS_XOF)) {
	res = EVP_DigestFinal_ex(statePtr->ctx, md_buf, &md_len);
	    res = EVP_DigestFinal_ex(statePtr->ctx, md_buf, &md_len);
	} else {
	    res = EVP_DigestFinalXOF(statePtr->ctx, md_buf, EVP_MAX_MD_SIZE);
	}

    } else if (statePtr->format & TYPE_HMAC) {
	res = HMAC_Final(statePtr->hctx, md_buf, &md_len);

    } else if (statePtr->format & TYPE_CMAC) {
	size_t len;
	res = CMAC_Final(statePtr->cctx, md_buf, &len);
	md_len = (unsigned int) len;
    }

    if (!res) {
893
894
895
896
897
898
899
900

901
902
903
904
905
906
907
900
901
902
903
904
905
906

907
908
909
910
911
912
913
914







-
+







 *
 *	 Callback to clean-up when digest instance command is deleted.
 *
 * Returns:
 *	Nothing
 *
 * Side effects:
 *	Destroys struct
 *	Destroys state info structure
 *
 *-------------------------------------------------------------------
 */
void InstanceDelCallback(ClientData clientData) {
    DigestState *statePtr = (DigestState *) clientData;

    /* Clean-up */
1160
1161
1162
1163
1164
1165
1166


1167
1168
1169
1170
1171
1172
1173
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182







+
+








    /* Get digest */
    if (digestName != 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()) {
	    format |= IS_XOF;
	}
    } else if (type == TYPE_MD || type == TYPE_HMAC) {
	Tcl_AppendResult(interp, "No digest specified", NULL);
	return TCL_ERROR;
    }

    /* Get key */