Beispiel #1
0
static void
report_errors(SSL* ssl)
{
  unsigned long	l;
  const char *file;
  const char *data;
  int line, flags;
  char buf[512];

  DBUG_ENTER("report_errors");

  while ((l= ERR_get_error_line_data(&file,&line,&data,&flags)))
  {
    DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf),
			 file,line,(flags&ERR_TXT_STRING)?data:"")) ;
  }

  if (ssl)
    DBUG_PRINT("error", ("error: %s",
                         ERR_error_string(SSL_get_error(ssl, l), buf)));

  DBUG_PRINT("info", ("socket_errno: %d", socket_errno));
  DBUG_VOID_RETURN;
}
Beispiel #2
0
static EVP_PKEY *load_key_file(const gchar *keyfile, GError **error)
{
	EVP_PKEY *res = NULL;
	BIO *key = NULL;
	unsigned long err;
	const gchar *data;
	int flags;

	g_return_val_if_fail(keyfile != NULL, NULL);
	g_return_val_if_fail(error == NULL || *error == NULL, NULL);

	key = BIO_new_file(keyfile, "r");
	if (key == NULL) {
		g_set_error(
				error,
				R_SIGNATURE_ERROR,
				R_SIGNATURE_ERROR_LOAD_FAILED,
				"failed to load key file '%s'", keyfile);
		goto out;
	}

	res = PEM_read_bio_PrivateKey(key, NULL, NULL, NULL);
	if (res == NULL) {
		err = ERR_get_error_line_data(NULL, NULL, &data, &flags);
		g_set_error(
				error,
				R_SIGNATURE_ERROR,
				R_SIGNATURE_ERROR_PARSE_ERROR,
				"failed to parse key file '%s': %s", keyfile,
				(flags & ERR_TXT_STRING) ? data : ERR_error_string(err, NULL));
		goto out;
	}
out:
	BIO_free_all(key);
	return res;
}
Beispiel #3
0
void _openssl_log_error (int rc, SSL * con, const char *location)
{
    const char *reason, *file, *data;

    unsigned long numerical_reason;

    int flags, line;

    snmp_log (LOG_ERR, "---- OpenSSL Related Errors: ----\n");

    /* SSL specific errors */
    if (con)
    {

        int sslnum = SSL_get_error (con, rc);

        switch (sslnum)
        {
            case SSL_ERROR_NONE:
                reason = "SSL_ERROR_NONE";
                break;

            case SSL_ERROR_SSL:
                reason = "SSL_ERROR_SSL";
                break;

            case SSL_ERROR_WANT_READ:
                reason = "SSL_ERROR_WANT_READ";
                break;

            case SSL_ERROR_WANT_WRITE:
                reason = "SSL_ERROR_WANT_WRITE";
                break;

            case SSL_ERROR_WANT_X509_LOOKUP:
                reason = "SSL_ERROR_WANT_X509_LOOKUP";
                break;

            case SSL_ERROR_SYSCALL:
                reason = "SSL_ERROR_SYSCALL";
                snmp_log (LOG_ERR, "TLS error: %s: rc=%d, sslerror = %d (%s): system_error=%d (%s)\n",
                          location, rc, sslnum, reason, errno, strerror (errno));
                snmp_log (LOG_ERR, "TLS Error: %s\n", ERR_reason_error_string (ERR_get_error ()));
                return;

            case SSL_ERROR_ZERO_RETURN:
                reason = "SSL_ERROR_ZERO_RETURN";
                break;

            case SSL_ERROR_WANT_CONNECT:
                reason = "SSL_ERROR_WANT_CONNECT";
                break;

            case SSL_ERROR_WANT_ACCEPT:
                reason = "SSL_ERROR_WANT_ACCEPT";
                break;

            default:
                reason = "unknown";
        }

        snmp_log (LOG_ERR, " TLS error: %s: rc=%d, sslerror = %d (%s)\n", location, rc, sslnum, reason);

        snmp_log (LOG_ERR, " TLS Error: %s\n", ERR_reason_error_string (ERR_get_error ()));

    }

    /* other errors */
    while ((numerical_reason = ERR_get_error_line_data (&file, &line, &data, &flags)) != 0)
    {
        snmp_log (LOG_ERR, " error: #%lu (file %s, line %d)\n", numerical_reason, file, line);

        /* if we have a text translation: */
        if (data && (flags & ERR_TXT_STRING))
        {
            snmp_log (LOG_ERR, "  Textual Error: %s\n", data);
            /*
             * per openssl man page: If it has been allocated by
             * OPENSSL_malloc(), *flags&ERR_TXT_MALLOCED is true.
             *
             * arggh... stupid openssl prototype for ERR_get_error_line_data
             * wants a const char **, but returns something that we might
             * need to free??
             */
            if (flags & ERR_TXT_MALLOCED)
                OPENSSL_free (NETSNMP_REMOVE_CONST (void *, data));
        }
    }

    snmp_log (LOG_ERR, "---- End of OpenSSL Errors ----\n");
}
Beispiel #4
0
/** Print errors in the TLS thread local error stack
 *
 * Drains the thread local OpenSSL error queue, and prints out errors.
 *
 * @param[in] request	The current request (may be NULL).
 * @param[in] msg	Error message describing the operation being attempted.
 * @param[in] ap	Arguments for msg.
 * @return the number of errors drained from the stack.
 */
static int tls_log_error_va(REQUEST *request, char const *msg, va_list ap)
{
	unsigned long	error;
	char		*p;
	int		in_stack = 0;
	char		buffer[256];

	int		line;
	char const	*file;
	char const	*data;
	int		flags = 0;

	/*
	 *	Pop the first error, so ERR_peek_error()
	 *	can be used to determine if there are
	 *	multiple errors.
	 */
	error = ERR_get_error_line_data(&file, &line, &data, &flags);
	if (!(flags & ERR_TXT_STRING)) data = NULL;

	if (msg) {
		p = talloc_vasprintf(request, msg, ap);

		/*
		 *	Single line mode (there's only one error)
		 */
		if (error && !ERR_peek_error()) {
			ERR_error_string_n(error, buffer, sizeof(buffer));

			/* Extra verbose */
			if ((request && RDEBUG_ENABLED3) || DEBUG_ENABLED3) {
				ROPTIONAL(REDEBUG, ERROR, "%s: %s[%i]:%s%c%s", p, file, line, buffer,
					  data ? ':' : '\0', data ? data : "");
			} else {
				ROPTIONAL(REDEBUG, ERROR, "%s: %s%c%s", p, buffer,
					  data ? ':' : '\0', data ? data : "");
			}

			talloc_free(p);

			return 1;
		}

		/*
		 *	Print the error we were given, irrespective
		 *	of whether there were any OpenSSL errors.
		 */
		ROPTIONAL(RERROR, ERROR, "%s", p);
		talloc_free(p);
	}

	/*
	 *	Stack mode (there are multiple errors)
	 */
	if (!error) return 0;
	do {
		if (!(flags & ERR_TXT_STRING)) data = NULL;

		ERR_error_string_n(error, buffer, sizeof(buffer));
		/* Extra verbose */
		if ((request && RDEBUG_ENABLED3) || DEBUG_ENABLED3) {
			ROPTIONAL(REDEBUG, ERROR, "%s[%i]:%s%c%s", file, line, buffer,
				  data ? ':' : '\0', data ? data : "");
		} else {
			ROPTIONAL(REDEBUG, ERROR, "%s%c%s", buffer,
				  data ? ':' : '\0', data ? data : "");
		}
		in_stack++;
	} while ((error = ERR_get_error_line_data(&file, &line, &data, &flags)));

	return in_stack;
}
Beispiel #5
0
static ENGINE *get_pkcs11_engine(GError **error)
{
	static ENGINE *e = NULL;
	unsigned long err;
	const gchar *data;
	const gchar *env;
	int flags;

	g_return_val_if_fail(error == NULL || *error == NULL, NULL);

	ENGINE_load_builtin_engines();

	e = ENGINE_by_id("pkcs11");
	if (e == NULL) {
		err = ERR_get_error_line_data(NULL, NULL, &data, &flags);
		g_set_error(
				error,
				R_SIGNATURE_ERROR,
				R_SIGNATURE_ERROR_LOAD_FAILED,
				"failed to load PKCS11 engine: %s",
				(flags & ERR_TXT_STRING) ? data : ERR_error_string(err, NULL));

		goto out;
	}

	env = g_getenv("RAUC_PKCS11_MODULE");
	if (env != NULL) {
		if (!ENGINE_ctrl_cmd_string(e, "MODULE_PATH", env, 0)) {
			err = ERR_get_error_line_data(NULL, NULL, &data, &flags);
			g_set_error(
					error,
					R_SIGNATURE_ERROR,
					R_SIGNATURE_ERROR_PARSE_ERROR,
					"failed to configure PKCS11 module path: %s",
					(flags & ERR_TXT_STRING) ? data : ERR_error_string(err, NULL));
			goto free;
		}
	}

	if (ENGINE_init(e) == 0) {
		err = ERR_get_error_line_data(NULL, NULL, &data, &flags);
		g_set_error(
				error,
				R_SIGNATURE_ERROR,
				R_SIGNATURE_ERROR_LOAD_FAILED,
				"failed to initialize PKCS11 engine: %s",
				(flags & ERR_TXT_STRING) ? data : ERR_error_string(err, NULL));

		goto free;
	}

	env = g_getenv("RAUC_PKCS11_PIN");
	if (env != NULL) {
		if (!ENGINE_ctrl_cmd_string(e, "PIN", env, 0)) {
			err = ERR_get_error_line_data(NULL, NULL, &data, &flags);
			g_set_error(
					error,
					R_SIGNATURE_ERROR,
					R_SIGNATURE_ERROR_PARSE_ERROR,
					"failed to configure PKCS11 PIN: %s",
					(flags & ERR_TXT_STRING) ? data : ERR_error_string(err, NULL));
			goto finish;
		}
	}

	goto out;

finish:
	ENGINE_finish(e);
free:
	ENGINE_free(e);
	e = NULL;
out:
	return e;
}
Beispiel #6
0
GBytes *cms_sign(GBytes *content, const gchar *certfile, const gchar *keyfile, gchar **interfiles, GError **error)
{
	GError *ierror = NULL;
	BIO *incontent = BIO_new_mem_buf((void *)g_bytes_get_data(content, NULL),
			g_bytes_get_size(content));
	BIO *outsig = BIO_new(BIO_s_mem());
	X509 *signcert = NULL;
	EVP_PKEY *pkey = NULL;
	STACK_OF(X509) *intercerts = NULL;
	CMS_ContentInfo *cms = NULL;
	GBytes *res = NULL;
	int flags = CMS_DETACHED | CMS_BINARY;

	g_return_val_if_fail(content != NULL, NULL);
	g_return_val_if_fail(certfile != NULL, NULL);
	g_return_val_if_fail(keyfile != NULL, NULL);
	g_return_val_if_fail(error == NULL || *error == NULL, NULL);

	signcert = load_cert(certfile, &ierror);
	if (signcert == NULL) {
		g_propagate_error(error, ierror);
		goto out;
	}

	pkey = load_key(keyfile, &ierror);
	if (pkey == NULL) {
		g_propagate_error(error, ierror);
		goto out;
	}

	intercerts = sk_X509_new_null();

	for (gchar **intercertpath = interfiles; intercertpath && *intercertpath != NULL; intercertpath++) {

		X509 *intercert = load_cert(*intercertpath, &ierror);
		if (intercert == NULL) {
			g_propagate_error(error, ierror);
			goto out;
		}

		sk_X509_push(intercerts, intercert);
	}

	cms = CMS_sign(signcert, pkey, intercerts, incontent, flags);
	if (cms == NULL) {
		unsigned long err;
		const gchar *data;
		int errflags;
		err = ERR_get_error_line_data(NULL, NULL, &data, &errflags);
		g_set_error(
				error,
				R_SIGNATURE_ERROR,
				R_SIGNATURE_ERROR_INVALID,
				"failed to create signature: %s", (errflags & ERR_TXT_STRING) ? data : ERR_error_string(err, NULL));
		goto out;
	}
	if (!i2d_CMS_bio(outsig, cms)) {
		g_set_error_literal(
				error,
				R_SIGNATURE_ERROR,
				R_SIGNATURE_ERROR_SERIALIZE_SIG,
				"failed to serialize signature");
		goto out;
	}

	res = bytes_from_bio(outsig);

	if (!res) {
		g_set_error_literal(
				error,
				R_SIGNATURE_ERROR,
				R_SIGNATURE_ERROR_UNKNOWN,
				"Read zero bytes");
		goto out;
	}

	/* keyring was given, perform verification to obtain trust chain */
	if (r_context()->config->keyring_path) {
		g_autoptr(CMS_ContentInfo) vcms = NULL;
		g_autoptr(X509_STORE) store = NULL;
		STACK_OF(X509) *verified_chain = NULL;

		g_message("Keyring given, doing signature verification");
		if (!cms_verify(content, res, &vcms, &store, &ierror)) {
			g_propagate_error(error, ierror);
			res = NULL;
			goto out;
		}

		if (!cms_get_cert_chain(vcms, store, &verified_chain, &ierror)) {
			g_propagate_error(error, ierror);
			res = NULL;
			goto out;
		}

		for (int i = 0; i < sk_X509_num(verified_chain); i++) {
			const ASN1_TIME *expiry_time;
			struct tm *next_month;
			time_t now;
			time_t comp;
			time(&now);

			next_month = gmtime(&now);
			next_month->tm_mon += 1;
			if (next_month->tm_mon == 12)
				next_month->tm_mon = 0;
			comp = timegm(next_month);

			expiry_time = X509_get0_notAfter(sk_X509_value(verified_chain, i));

			/* Check if expiry time is within last month */
			if (X509_cmp_current_time(expiry_time) == 1 && X509_cmp_time(expiry_time, &comp) == -1) {
				char buf[BUFSIZ];
				X509_NAME_oneline(X509_get_subject_name(sk_X509_value(verified_chain, i)),
						buf, sizeof buf);
				g_warning("Certificate %d (%s) will exipre in less than a month!", i + 1, buf);
			}
		}

		sk_X509_pop_free(verified_chain, X509_free);
	} else {
		g_message("No keyring given, skipping signature verification");
	}
out:
	ERR_print_errors_fp(stdout);
	BIO_free_all(incontent);
	BIO_free_all(outsig);
	return res;
}