Index: generic/tls.c ================================================================== --- generic/tls.c +++ generic/tls.c @@ -384,10 +384,12 @@ if (statePtr->vflags & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) { return ok; } else { return 1; } + } else if (cert == NULL || ssl == NULL) { + return 0; } /* Create command to eval */ cmdPtr = Tcl_DuplicateObj(statePtr->vcmd); Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj("verify", -1)); @@ -855,11 +857,11 @@ dprintf("Called"); if (statePtr->vcmd == (Tcl_Obj*)NULL) { return SSL_CLIENT_HELLO_SUCCESS; - } else if (ssl == NULL || arg == NULL) { + } else if (ssl == (const SSL *)NULL || arg == (void *)NULL) { return SSL_CLIENT_HELLO_ERROR; } /* Get names */ if (!SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &p, &remaining) || remaining <= 2) { @@ -2308,15 +2310,20 @@ /* Session ticket lifetime hint (in seconds) */ Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("lifetime", -1)); Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewLongObj(SSL_SESSION_get_ticket_lifetime_hint(session))); - /* Session id */ + /* Session id - TLSv1.2 and below only */ session_id = SSL_SESSION_get_id(session, &ulen); Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("session_id", -1)); Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewByteArrayObj(session_id, (int) ulen)); + /* Session context */ + session_id = SSL_SESSION_get0_id_context(session, &ulen); + Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("session_context", -1)); + Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewByteArrayObj(session_id, (int) ulen)); + /* Session ticket - client only */ SSL_SESSION_get0_ticket(session, &ticket, &len2); Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("session_ticket", -1)); Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewByteArrayObj(ticket, (int) len2)); Index: generic/tlsX509.c ================================================================== --- generic/tlsX509.c +++ generic/tlsX509.c @@ -197,10 +197,19 @@ key = X509_get0_pubkey_bitstr(cert); len = String_to_Hex(key->data, key->length, buffer, BUFSIZ); Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("publicKey", -1)); Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj(buffer, len)); + + if (X509_pubkey_digest(cert, EVP_get_digestbynid(pknid), md, &n)) { + len = String_to_Hex(md, (int)n, buffer, BUFSIZ); + } else { + len = 0; + } + Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("publicKeyHash", -1)); + Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj(buffer, len)); + /* Check if cert was issued by CA cert issuer or self signed */ Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("self_signed", -1)); Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewBooleanObj(X509_check_issued(cert, cert) == X509_V_OK)); @@ -441,12 +450,19 @@ of the subject. RFC 5280 section 4.2.1.8 (subjectDirectoryAttributes) */ /* Basic Constraints identifies whether the subject of the cert is a CA and the max depth of valid cert paths that include this cert. RFC 5280 section 4.2.1.9 (basicConstraints, NID_basic_constraints) */ - if (xflags & EXFLAG_BCONS || xflags & EXFLAG_CA) { + if (xflags & EXFLAG_BCONS) { + long len2 = X509_get_pathlen(cert); + Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("pathLen", -1)); + Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewLongObj(len2)); } + Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("basicConstraintsCA", -1)); + Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewBooleanObj(xflags & EXFLAG_CA)); + Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("basicConstraintsCritical", -1)); + Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewBooleanObj(xflags & EXFLAG_CRITICAL)); /* Name Constraints is only used in CA certs to indicate a name space within which all subject names in subsequent certificates in a certification path MUST be located. RFC 5280 section 4.2.1.10, NID_name_constraints */