+static int compare_certificates (X509 *cert, X509 *peercert,
+ unsigned char *peermd,
+ unsigned int peermdlen) {
+ unsigned char md[EVP_MAX_MD_SIZE];
+ unsigned int mdlen;
+
+ /* Avoid CPU-intensive digest calculation if the certificates are
+ * not even remotely equal.
+ */
+ if (X509_subject_name_cmp (cert, peercert) != 0 ||
+ X509_issuer_name_cmp (cert, peercert) != 0)
+ return -1;
+
+ if (!X509_digest (cert, EVP_sha1(), md, &mdlen) || peermdlen != mdlen)
+ return -1;
+
+ if (memcmp(peermd, md, mdlen) != 0)
+ return -1;
+
+ return 0;
+}
+
+static int check_certificate_cache (X509 *peercert) {
+ unsigned char peermd[EVP_MAX_MD_SIZE];
+ unsigned int peermdlen;
+ X509 *cert;
+ LIST *scert;
+
+ if (!X509_digest (peercert, EVP_sha1(), peermd, &peermdlen))
+ return 0;
+
+ for (scert = SslSessionCerts; scert; scert = scert->next) {
+ cert = *(X509**)scert->data;
+ if (!compare_certificates (cert, peercert, peermd, peermdlen)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int tls_close (CONNECTION * conn)