static int
convert_file(struct nettle_buffer *buffer,
	     FILE *f,
	     enum object_type type,
	     int base64)
{
  if (type)
    {
      read_file(buffer, f);
      if (base64 && !decode_base64(buffer, 0, &buffer->size))
	return 0;
      
      if (convert_type(buffer, type,
		       buffer->size, buffer->contents) != 1)
	return 0;

      return 1;
    }
  else
    {
      /* PEM processing */
      for (;;)
	{
	  struct pem_info info;
	  const uint8_t *marker;
	  
	  nettle_buffer_reset(buffer);
	  switch (read_pem(buffer, f, &info))
	    {
	    default:
	      return 0;
	    case 1:
	      break;
	    case -1:
	      /* EOF */
	      return 1;
	    }

	  if (!decode_base64(buffer, info.data_start, &info.data_length))
	    return 0;

	  marker = buffer->contents + info.marker_start;

	  type = 0;
	  switch (info.marker_length)
	    {
	    case 10:
	      if (memcmp(marker, "PUBLIC KEY", 10) == 0)
		{
		  type = GENERAL_PUBLIC_KEY;
		  break;
		}
	    case 14:
	      if (memcmp(marker, "RSA PUBLIC KEY", 14) == 0)
		{
		  type = RSA_PUBLIC_KEY;
		  break;
		}

	    case 15:
	      if (memcmp(marker, "RSA PRIVATE KEY", 15) == 0)
		{
		  type = RSA_PRIVATE_KEY;
		  break;
		}
	      if (memcmp(marker, "DSA PRIVATE KEY", 15) == 0)
		{
		  type = DSA_PRIVATE_KEY;
		  break;
		}
	    }
	  
	  if (!type)
	    werror("Ignoring unsupported object type `%s'.\n", marker);

	  else if (convert_type(buffer, type,
				info.data_length,
				buffer->contents + info.data_start) != 1)
	    return 0;
	}
    }
}
Esempio n. 2
0
void test_ssl() {
    interface ifs[16];
    active_interfaces(ifs, 16);

    char *passwd = "password";
    char *dir = chdir_temp_dir();

    kdfp kdfp = { .N = 2, .r = 1, .p = 1};
    uint8_t kek[KEY_LEN]  = { 0 };
    struct server_cfg cfg = {
        .passwd = passwd,
        .cert   = "server.pem",
        .ifa    = &ifs[0],
    };
    pthread_t tid;

    EC_GROUP *group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(EC_CURVE_NAME));
    EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
    init_certs(group, passwd, "server.pem", "client.pem");
    init_certs(group, passwd, "zerver.pem", "zlient.pem");
    init_index("index", kek, &kdfp);
    EC_GROUP_free(group);

    assert(pthread_create(&tid, NULL, &run_server, &cfg) == 0);

    struct timeval timeout = { .tv_usec = 500 };
    uint32_t usecs = 10000;
    sockaddr6 addr;
    X509 *cert = NULL, *sert = NULL;
    EVP_PKEY *pk = NULL, *sk = NULL;
    SSL_CTX *ctx = NULL;
    SSL *ssl = NULL;
    uint8_t data[KDFP_LEN];

    // client/server cert & pk mismatch
    read_pem("client.pem", NULL, passwd, &pk, 2, &sert, &cert);
    read_pem("server.pem", NULL, passwd, &sk, 0);

    assert(client_ctx(sert, cert, sk) == NULL);
    assert(server_sock(&ctx, sert, pk, cfg.ifa, &addr) == -1);
    assert(ctx == NULL);
    cleanup(&ctx, &ssl, &sert, &cert, &sk, &pk);

    // incorrect signature on pong
    read_pem("zerver.pem", NULL, passwd, &sk, 1, &sert);
    assert(find_server(sk, &addr, usecs, 30) == false);
    cleanup(&ctx, &ssl, &sert, &cert, &sk, &pk);

    // incorrect server certificate
    read_pem("server.pem", NULL, passwd, &sk, 1, &sert);
    assert(find_server(sk, &addr, usecs, 30) == true);
    cleanup(&ctx, &ssl, &sert, &cert, &sk, &pk);

    read_pem("client.pem", NULL, passwd, &pk, 2, &sert, &cert);
    X509_free(sert);
    read_pem("zerver.pem", NULL, passwd, &sk, 1, &sert);
    ctx = client_ctx(sert, cert, pk);
    assert(client_socket(ctx, &addr, &timeout) == NULL);
    assert(ERR_GET_REASON(ERR_get_error()) == SSL_R_CERTIFICATE_VERIFY_FAILED);
    cleanup(&ctx, &ssl, &sert, &cert, &sk, &pk);

    // incorrect client certificate
    read_pem("zlient.pem", NULL, passwd, &pk, 1, &cert);
    read_pem("server.pem", NULL, passwd, &sk, 1, &sert);
    ctx = client_ctx(sert, cert, pk);
    assert(client_socket(ctx, &addr, &timeout) == NULL);
    cleanup(&ctx, &ssl, &sert, &cert, &sk, &pk);

    // valid certificates
    read_pem("client.pem", NULL, passwd, &pk, 2, &sert, &cert);
    read_pem("server.pem", NULL, passwd, &sk, 0);
    ctx = client_ctx(sert, cert, pk);
    assert((ssl = client_socket(ctx, &addr, &timeout)));
    assert(SSL_read(ssl, &data, KDFP_LEN) == KDFP_LEN);
    cleanup(&ctx, &ssl, &sert, &cert, &sk, &pk);

    pthread_kill(tid, SIGINT);
    pthread_join(tid, NULL);

    unlink("server.pem");
    unlink("client.pem");
    unlink("zerver.pem");
    unlink("zlient.pem");
    unlink("index");

    rmdir_temp_dir(dir);
}