Commit e22b2718 authored by Nick Mathewson's avatar Nick Mathewson 🦀
Browse files

Add certificate verification functions


svn:r438
parent 9955b265
Loading
Loading
Loading
Loading
+65 −4
Original line number Diff line number Diff line
@@ -38,6 +38,11 @@ static tor_tls_context *global_tls_context=NULL;
#define _TOR_TLS_SYSCALL    -6
#define _TOR_TLS_ZERORETURN -5


/* These functions are declared in crypto.c but not exported. */
RSA *_crypto_pk_env_get_rsa(crypto_pk_env_t *env);
crypto_pk_env_t *_crypto_new_pk_env_rsa(RSA *rsa);

static int
tor_tls_get_error(tor_tls *tls, int r, int extra)
{
@@ -83,8 +88,8 @@ tor_tls_write_certificate(char *certfile, crypto_pk_env_t *rsa, char *nickname)
  
  start_time = time(NULL);

  assert(rsa && rsa->type == CRYPTO_PK_RSA);
  if (!(_rsa = RSAPrivateKey_dup((RSA*)rsa->key)))
  assert(rsa);
  if (!(_rsa = RSAPrivateKey_dup(_crypto_pk_env_get_rsa(rsa))))
    /* XXX we have a crypto_pk_dup_key(), it's a shame we can't use it here */
    return -1;
  if (!(pkey = EVP_PKEY_new()))
@@ -144,7 +149,6 @@ tor_tls_context_new(char *certfile, crypto_pk_env_t *rsa, int isServer)
  EVP_PKEY *pkey = NULL;
  tor_tls_context *result;

  assert(!rsa || rsa->type == CRYPTO_PK_RSA);
  assert((certfile && rsa) || (!certfile && !rsa));

  result = tor_malloc(sizeof(tor_tls_context));
@@ -159,7 +163,7 @@ tor_tls_context_new(char *certfile, crypto_pk_env_t *rsa, int isServer)
    return -1;
  SSL_CTX_set_session_cache_mode(result->ctx, SSL_SESS_CACHE_OFF);
  if (rsa) {
    if (!(_rsa = RSAPrivateKey_dup((RSA*)rsa->key)))
    if (!(_rsa = RSAPrivateKey_dup(_crypto_pk_env_get_rsa(rsa))))
      return -1;
    if (!(pkey = EVP_PKEY_new()))
      return -1;
@@ -329,3 +333,60 @@ tor_tls_shutdown(tor_tls *tls)
  }
}

/* Return true iff this TLS connection is authenticated.
 */
int
tor_tls_peer_has_cert(tor_tls *tls)
{
  X509 *cert;
  if (!(cert = SSL_get_peer_certificate(tls->ssl)))
    return 0;
  X509_free(cert);
  return 1;
}

/* If the provided tls connection is authenticated and has a
 * certificate that is currently valid and is correctly self-signed,
 * return its public key.  Otherwise return NULL.
 */
crypto_pk_env_t *
tor_tls_verify(tor_tls *tls)
{
  X509 *cert = NULL;
  EVP_PKEY *pkey = NULL;
  RSA *rsa = NULL;
  time_t now;
  crypto_pk_env_t *r = NULL;
  if (!(cert = SSL_get_peer_certificate(tls->ssl)))
    return 0;
  
  now = time(NULL);
  if (X509_cmp_time(X509_get_notBefore(cert), &now) > 0)
    goto done;
  if (X509_cmp_time(X509_get_notAfter(cert), &now) < 0)
    goto done;
  
  /* Get the public key. */
  if (!(pkey = X509_get_pubkey(cert)))
    goto done;
  if (X509_verify(cert, pkey) <= 0)
    goto done;

  rsa = EVP_PKEY_get1_RSA(pkey);
  EVP_PKEY_free(pkey);
  pkey = NULL;
  if (!rsa)
    goto done;

  r = _crypto_new_pk_env_rsa(rsa);
  rsa = NULL;
  
 done:
  if (cert)
    X509_free(cert);
  if (pkey)
    EVP_PKEY_free(pkey);
  if (rsa)
    RSA_free(rsa);
  return r;
}
+2 −2
Original line number Diff line number Diff line
@@ -20,8 +20,8 @@ int tor_tls_write_certificate(char *certfile, crypto_pk_env_t *rsa, char *nickna
int tor_tls_context_new(char *certfile, crypto_pk_env_t *rsa, int isServer);
tor_tls *tor_tls_new(int sock, int isServer);
void tor_tls_free(tor_tls *tls);
int tor_tls_peer_is_valid(tor_tls *tls);
crypto_pk_env_t *tor_tls_get_peer_pk(tor_tls *tls);
int tor_tls_peer_has_cert(tor_tls *tls);
crypto_pk_env_t *tor_tls_verify(tor_tls *tls);
int tor_tls_read(tor_tls *tls, char *cp, int len);
int tor_tls_write(tor_tls *tls, char *cp, int n);
int tor_tls_handshake(tor_tls *tls);