Index: doc/tls.html
==================================================================
--- doc/tls.html
+++ doc/tls.html
@@ -120,11 +120,12 @@
 
 <blockquote>
     <dl>
 	<dt><strong>-alpn</strong> <em>list</em></dt>
 	<dd>List of protocols to offer during Application-Layer
-	    Protocol Negotiation (ALPN). For example: h2, http/1.1, etc.</dd>
+	    Protocol Negotiation (ALPN). For example: <em>h2</em> and
+	    <em>http/1.1</em>, but not <em>h3</em> or <em>quic</em>.</dd>
 	<dt><strong>-cadir</strong> <em>dir</em></dt>
 	<dd>Set the CA certificates path. The default directory is platform
 	    specific and can be set at compile time. This can be overridden
 	    via the <b>SSL_CERT_DIR</b> environment variable.</dd>
 	<dt><strong>-cafile </strong><em>filename</em></dt>
@@ -434,22 +435,23 @@
 As indicated above, individual channels can be given their own callbacks
 to handle intermediate processing by the OpenSSL library, using the
 <strong>-command</strong>, <strong>-password</strong>, and
 <strong>-validate_command</strong> options passed to either of
 <strong>tls::socket</strong> or <strong>tls::import</strong>.
+If the callback generates an error, the <b>bgerror</b> command with be
+invoked with the error information.
 </p>
 
 <blockquote>
 <dl>
 
     <dt><strong>-command</strong> <em>callback</em></dt>
     <dd>
-	Invokes the specified <em>callback</em> script at
-	several points during the OpenSSL handshake.
-	Values returned from the callback are ignored.
-	Arguments appended to the script upon callback take one of the
-	following forms:
+	Invokes the specified <em>callback</em> script at several points
+	during the OpenSSL handshake and use. See below for the possible
+	arguments passed to the callback script. Values returned from the
+	callback are ignored.
 
 	<br>
 	<br>
 
 	<dl>
@@ -477,11 +479,11 @@
 	  <code>handshake, alert, connect, accept</code>.</li>
 	  <li>Possible values for <em>minor</em> are:
 	  <code>start, done, read, write, loop, exit</code>.</li>
 	  <li>The <em>message</em> argument is a descriptive string which may
 	  be generated either by <code>SSL_state_string_long()</code> or by
-	  <code>SSL_alert_desc_string_long()</code>, depending on context.</li>
+	  <code>SSL_alert_desc_string_long()</code>, depending on the context.</li>
 	  <li>For alerts, the possible values for <em>type</em> are:
 	  <code>warning, fatal, and unknown</code>. For others,
 	  <code>info</code> is used.</li>
 	  </ul>
 	</dd>
@@ -517,24 +519,41 @@
     <br>
 
     <dt><strong>-password</strong> <em>callback</em></dt>
     <dd>
 	Invokes the specified <em>callback</em> script when OpenSSL needs to
-	obtain a password.  The callback should return the password as a string.
-	No arguments are appended to the script upon callback.
+	obtain a password. See below for the possible arguments passed to
+	the callback script. See below for valid return values.
+
+	<br>
+	<br>
+
+	<dl>
+
+	<dt>
+	  <strong>password</strong> <em>rwflag size</em>
+	</dt>
+	<dd>
+	  Invoked when loading or storing a PEM certificate with encryption.
+	  Where <em>rwflag</em> is 0 for reading/decryption or 1 for
+	  writing/encryption (can prompt user to confirm) and
+	  <em>size</em> is the max password length in bytes.
+	  The callback should return the password as a string.
+	</dd>
     </dd>
 
     <br>
 
 
     <dt><strong>-validatecommand</strong> <em>callback</em></dt>
     <dd>
 	Invokes the specified <em>callback</em> script during handshake in
-	order to validate the provided value(s). 
+	order to validate the provided value(s). See below for the possible
+	arguments passed to the callback script.
 	To reject the value and abort connection, the callback should return 0.
-	To accept the value, it should return 1.  To reject the value, but
-	continue the connection, it should return 2.
+	To accept the value and continue the connection, it should return 1.
+	To reject the value, but continue the connection, it should return 2.
 
 	<br>
 	<br>
 
 	<dl>
@@ -545,10 +564,11 @@
 	<dd>
 	  For servers, this form of callback is invoked when the client ALPN
 	  extension is received. Where <em>protocol</em> is the first
 	  <b>-alpn</b> specified protocol common to the both the client and
 	  server. If none, the first client specified protocol is used.
+	  Called after hello and ALPN callbacks.
 	</dd>
 
 	<br>
 
 	<dt>

Index: generic/tls.c
==================================================================
--- generic/tls.c
+++ generic/tls.c
@@ -489,18 +489,27 @@
 /*
  *-------------------------------------------------------------------
  *
  * Password Callback --
  *
- *	Called when a password is needed to unpack RSA and PEM keys.
- *	Evals any bound password script and returns the result as
- *	the password string.
+ *	Called when a password for a private key loading/storing a PEM
+ *	certificate with encryption. Evals callback script and returns
+ *	the result as the password string in buf.
+ *
+ * Results:
+ *	None
+ *
+ * Side effects:
+ *	Calls callback (if defined)
+ *
+ * Returns:
+ *	Password size in bytes or -1 for an error.
  *
  *-------------------------------------------------------------------
  */
 static int
-PasswordCallback(char *buf, int size, int verify, void *udata) {
+PasswordCallback(char *buf, int size, int rwflag, void *udata) {
     State *statePtr	= (State *) udata;
     Tcl_Interp *interp	= statePtr->interp;
     Tcl_Obj *cmdPtr;
     int code;
 
@@ -517,15 +526,18 @@
 	}
     }
 
     /* Create command to eval */
     cmdPtr = Tcl_DuplicateObj(statePtr->password);
+    Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj("password", -1));
+    Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewIntObj(rwflag));
+    Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewIntObj(size));
 
     Tcl_Preserve((ClientData) interp);
     Tcl_Preserve((ClientData) statePtr);
 
-    /* Eval callback and success for ok, abort for error, continue for continue */
+    /* Eval callback command */
     Tcl_IncrRefCount(cmdPtr);
     code = Tcl_EvalObjEx(interp, cmdPtr, TCL_EVAL_GLOBAL);
     if (code != TCL_OK) {
 #if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION < 6)
 	Tcl_BackgroundError(interp);
@@ -535,21 +547,24 @@
     }
     Tcl_DecrRefCount(cmdPtr);
 
     Tcl_Release((ClientData) statePtr);
 
+    /* If successful, pass back password string and truncate if too long */
     if (code == TCL_OK) {
-	char *ret = (char *) Tcl_GetStringResult(interp);
-	if (strlen(ret) < size - 1) {
-	    strncpy(buf, ret, (size_t) size);
-	    Tcl_Release((ClientData) interp);
-	    return (int)strlen(ret);
+	int len;
+	char *ret = (char *) Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &len);
+	if (len > size-1) {
+	    len = size-1;
 	}
+	strncpy(buf, ret, (size_t) len);
+	buf[len] = '\0';
+	Tcl_Release((ClientData) interp);
+	return(len);
     }
     Tcl_Release((ClientData) interp);
     return -1;
-	verify = verify;
 }
 
 /*
  *-------------------------------------------------------------------
  *