Example #1
0
/* Note that the option --one-button is a hack to allow the use of old
   pinentries while the caller is ignoring the result.  Given that
   options have never been used or flagged as an error the new option
   is an easy way to enable the messsage mode while not requiring to
   update pinentry or to have the caller test for the message
   command.  New applications which are free to require an updated
   pinentry should use MESSAGE instead. */
static int
cmd_confirm (ASSUAN_CONTEXT ctx, char *line)
{
  int result;

  pinentry.one_button = !!strstr (line, "--one-button");
  pinentry.quality_bar = 0;
  pinentry.close_button = 0;
  pinentry.locale_err = 0;
  pinentry.canceled = 0;
  result = (*pinentry_cmd_handler) (&pinentry);
  if (pinentry.error)
    {
      free (pinentry.error);
      pinentry.error = NULL;
    }

  if (pinentry.close_button)
    assuan_write_status (ctx, "BUTTON_INFO", "close");

  return result ? 0
                : (pinentry.locale_err? ASSUAN_Locale_Problem
                                      : (pinentry.one_button 
                                         ? 0
                                         : (pinentry.canceled
                                            ? ASSUAN_Canceled
                                            : ASSUAN_Not_Confirmed)));
}
Example #2
0
static gpg_error_t
pass_status_thru (void *opaque, const char *line)
{
  assuan_context_t ctx = opaque;
  char keyword[200];
  int i;

  if (line[0] == '#' && (!line[1] || spacep (line+1)))
    {
      /* We are called in convey comments mode.  Now, if we see a
         comment marker as keyword we forward the line verbatim to the
         the caller.  This way the comment lines from scdaemon won't
         appear as status lines with keyword '#'.  */
      assuan_write_line (ctx, line);
    }
  else
    {
      for (i=0; *line && !spacep (line) && i < DIM(keyword)-1; line++, i++)
        keyword[i] = *line;
      keyword[i] = 0;

      /* Truncate any remaining keyword stuff.  */
      for (; *line && !spacep (line); line++)
        ;
      while (spacep (line))
        line++;

      assuan_write_status (ctx, keyword, line);
    }
  return 0;
}
Example #3
0
static int
cmd_getpin (ASSUAN_CONTEXT ctx, char *line)
{
  int result;
  int set_prompt = 0;

  pinentry.pin = secmem_malloc (pinentry.pin_len);
  if (!pinentry.pin)
    return ASSUAN_Out_Of_Core;
  if (!pinentry.prompt)
    {
      pinentry.prompt = pinentry.default_prompt?pinentry.default_prompt:"PIN:";
      set_prompt = 1;
    }
  pinentry.locale_err = 0;
  pinentry.close_button = 0;
  pinentry.one_button = 0;
  pinentry.ctx_assuan = ctx;
  result = (*pinentry_cmd_handler) (&pinentry);
  pinentry.ctx_assuan = NULL;
  if (pinentry.error)
    {
      free (pinentry.error);
      pinentry.error = NULL;
    }
  if (set_prompt)
    pinentry.prompt = NULL;

  pinentry.quality_bar = 0;  /* Reset it after the command.  */

  if (pinentry.close_button)
    assuan_write_status (ctx, "BUTTON_INFO", "close");

  if (result < 0)
    {
      if (pinentry.pin)
	{
	  secmem_free (pinentry.pin);
	  pinentry.pin = NULL;
	}
      return pinentry.locale_err? ASSUAN_Locale_Problem: ASSUAN_Canceled;
    }

  if (result)
    {
      result = assuan_send_data (ctx, pinentry.pin, result);
      if (!result)
	result = assuan_send_data (ctx, NULL, 0);
    }

  if (pinentry.pin)
    {
      secmem_free (pinentry.pin);
      pinentry.pin = NULL;
    }

  return result;
}
Example #4
0
gpg_error_t cmd_serialno (assuan_context_t ctx, char *line)
{
	gpg_err_code_t error = GPG_ERR_GENERAL;
	char *serial = NULL;

	if (
		(error = get_serial(ctx, &serial)) != GPG_ERR_NO_ERROR
	) {
		goto cleanup;
	}

	if (serial != NULL) {
		char buffer[1024];

		sprintf(buffer, "%s 0", serial);

		if (
			(error = assuan_write_status (
				ctx,
				"SERIALNO",
				buffer
			)) != GPG_ERR_NO_ERROR
		) {
			goto cleanup;
		}
	}

	error = GPG_ERR_NO_ERROR;

cleanup:

	if (serial != NULL) {
		free(serial);
		serial = NULL;
	}

	return gpg_error (error);
}
Example #5
0
static int
cmd_message (ASSUAN_CONTEXT ctx, char *line)
{
  int result;

  pinentry.one_button = 1;
  pinentry.quality_bar = 0;
  pinentry.close_button = 0;
  pinentry.locale_err = 0;
  result = (*pinentry_cmd_handler) (&pinentry);
  if (pinentry.error)
    {
      free (pinentry.error);
      pinentry.error = NULL;
    }

  if (pinentry.close_button)
    assuan_write_status (ctx, "BUTTON_INFO", "close");

  return result ? 0 
                : (pinentry.locale_err? ASSUAN_Locale_Problem
                                      : 0);
}
Example #6
0
/** TODO: handle --force option! */
gpg_error_t cmd_learn (assuan_context_t ctx, char *line)
{
	gpg_err_code_t error = GPG_ERR_GENERAL;
	pkcs11h_certificate_id_list_t user_certificates = NULL;
	pkcs11h_certificate_id_list_t issuer_certificates = NULL;
	char *serial = NULL;

	(void)line;

	if (
		(error = get_serial(ctx, &serial)) != GPG_ERR_NO_ERROR
	) {
		goto cleanup;
	}

	if (
		(error = assuan_write_status (
			ctx,
			"SERIALNO",
			serial
		)) != GPG_ERR_NO_ERROR ||
		(error = assuan_write_status (
			ctx,
			"APPTYPE",
			"PKCS11"
		)) != GPG_ERR_NO_ERROR
	) {
		goto cleanup;
	}

	if (
		(error = common_map_pkcs11_error (
			pkcs11h_certificate_enumCertificateIds (
				PKCS11H_ENUM_METHOD_CACHE_EXIST,
				ctx,
				PKCS11H_PROMPT_MASK_ALLOW_ALL,
				&issuer_certificates,
				&user_certificates
			)
		)) != GPG_ERR_NO_ERROR ||
		(error = send_certificate_list (
			ctx,
			user_certificates,
			0
		)) != GPG_ERR_NO_ERROR ||
		(error = send_certificate_list (
			ctx,
			issuer_certificates,
			1
		)) != GPG_ERR_NO_ERROR
	) {
		goto cleanup;
	}

	error = GPG_ERR_NO_ERROR;

cleanup:

	if (issuer_certificates != NULL) {
		pkcs11h_certificate_freeCertificateIdList (issuer_certificates);
		issuer_certificates = NULL;
	}

	if (user_certificates != NULL) {
		pkcs11h_certificate_freeCertificateIdList (user_certificates);
		user_certificates = NULL;
	}

	if (serial != NULL) {
		free(serial);
		serial = NULL;
	}

	return gpg_error (error);
}
Example #7
0
/**
   Send status lines in the format

   S KEYPAIRINFO <hexstring_with_keygrip> <hexstring_with_id>
   S CERTINFO <certtype> <hexstring_with_id>

   If certificate is issuer, we set type to 102 (useful); otherwise it is
   assumed that we're in posession of private key, so the type is set to 101
   (trusted).  The certificate ID is percent-plus escaped displayName.
*/
static
int
send_certificate_list (
	assuan_context_t ctx,
	pkcs11h_certificate_id_list_t head,	/* list head */
	int is_issuer				/* true if issuer certificate */
) {
	cmd_data_t *data = (cmd_data_t *)assuan_get_pointer (ctx);
	gpg_err_code_t error = GPG_ERR_GENERAL;
	pkcs11h_certificate_id_list_t curr_cert;

	for (
		curr_cert = head;
		curr_cert != NULL;
		curr_cert = curr_cert->next
	) {
		char *certid = NULL;
		char *key_hexgrip = NULL;
		char *keypairinfo = NULL;
		char *gpginfo = NULL;
		char *info_cert = NULL;
		gcry_sexp_t sexp = NULL;
		size_t ser_len;
		char *key_prefix = NULL;
		char *nameinfo = NULL;

		if ((error = get_cert_sexp (ctx, curr_cert->certificate_id, &sexp)) != GPG_ERR_NO_ERROR) {
			goto retry;
		}

		if ((key_hexgrip = keyutil_get_cert_hexgrip (sexp)) == NULL) {
			error = GPG_ERR_ENOMEM;
			goto retry;
		}

		if (
			(error = common_map_pkcs11_error (
				pkcs11h_certificate_serializeCertificateId (
					NULL,
					&ser_len,
					curr_cert->certificate_id
				)
			)) != GPG_ERR_NO_ERROR
		) {
			goto retry;
		}

		if ((certid = (char *)malloc (ser_len)) == NULL	) {
			error = GPG_ERR_ENOMEM;
			goto retry;
		}

		if (
			(error = common_map_pkcs11_error (
				pkcs11h_certificate_serializeCertificateId (
					certid,
					&ser_len,
					curr_cert->certificate_id
				)
			)) != GPG_ERR_NO_ERROR
		) {
			goto retry;
		}

		if ((info_cert = strdup (is_issuer ? "102 " : "101 ")) == NULL) {
			error = GPG_ERR_ENOMEM;
			goto retry;
		}

		if (!encoding_strappend (&info_cert, certid)) {
			error = GPG_ERR_ENOMEM;
			goto retry;
		}

		if (
			data->config->openpgp_sign != NULL &&
			!strcmp (data->config->openpgp_sign, key_hexgrip)
		) {
			key_prefix = M2S(OPENPGP_SIGN) " ";
		}
		else if (
			data->config->openpgp_encr != NULL &&
			!strcmp (data->config->openpgp_encr, key_hexgrip)
		) {
			key_prefix = M2S(OPENPGP_ENCR) " ";
		}
		else if (
			data->config->openpgp_auth != NULL &&
			!strcmp (data->config->openpgp_auth, key_hexgrip)
		) {
			key_prefix = M2S(OPENPGP_AUTH) " ";
		}

		if (
			(nameinfo = strdup (key_hexgrip)) == NULL ||
			!encoding_strappend (&nameinfo, " ") ||
			!encoding_strappend (&nameinfo, curr_cert->certificate_id->displayName)
		) {
			error = GPG_ERR_ENOMEM;
			goto retry;
		}

		if (
			(error = assuan_write_status (
				ctx,
				"KEY-FRIEDNLY",
				nameinfo
			)) != GPG_ERR_NO_ERROR
		) {
			goto retry;
		}

		if (key_prefix != NULL) {
			if (
				(gpginfo = strdup (key_prefix)) == NULL ||
				!encoding_strappend (&gpginfo, key_hexgrip)
			) {
				error = GPG_ERR_ENOMEM;
				goto retry;
			}


			if (
				(error = assuan_write_status (
					ctx,
					"KEY-FPR",
					gpginfo
				)) != GPG_ERR_NO_ERROR
			) {
				goto retry;
			}

		}
		if (
			(error = assuan_write_status (
				ctx,
				"CERTINFO",
				info_cert
			)) != GPG_ERR_NO_ERROR
		) {
			goto retry;
		}

		/* send keypairinfo if not issuer certificate */
		if(!is_issuer) {
			if (
				(keypairinfo = strdup (key_hexgrip)) == NULL ||
				!encoding_strappend (&keypairinfo, " ") ||
				!encoding_strappend (&keypairinfo, certid)
			) {
				error = GPG_ERR_ENOMEM;
				goto retry;
			}

			if (
				(error = assuan_write_status (
					ctx,
					"KEYPAIRINFO",
					keypairinfo
				)) != GPG_ERR_NO_ERROR
			) {
				goto retry;
			}
		}

		error = GPG_ERR_NO_ERROR;

	retry:

		if (info_cert != NULL) {
			free (info_cert);
			info_cert = NULL;
		}

		if (certid != NULL) {
			free (certid);
			certid = NULL;
		}

		if (key_hexgrip != NULL) {
			free (key_hexgrip);
			key_hexgrip = NULL;
		}

		if (keypairinfo != NULL) {
			free (keypairinfo);
			keypairinfo = NULL;
		}

		if (gpginfo != NULL) {
			free (gpginfo);
			gpginfo = NULL;
		}

		if (nameinfo != NULL) {
			free (nameinfo);
			nameinfo = NULL;
		}

		if (error != GPG_ERR_NO_ERROR) {
			goto cleanup;
		}
	}

	error = GPG_ERR_NO_ERROR;

cleanup:

	return error;
}
Example #8
0
gpg_error_t cmd_genkey (assuan_context_t ctx, char *line)
{
	gpg_err_code_t error = GPG_ERR_GENERAL;
	pkcs11h_certificate_id_t cert_id = NULL;
	gcry_mpi_t n_mpi = NULL;
	gcry_mpi_t e_mpi = NULL;
	unsigned char *n_hex = NULL;
	unsigned char *e_hex = NULL;
	char *n_resp = strdup ("n ");
	char *e_resp = strdup ("e ");
	unsigned char *blob = NULL;
	char *serial = NULL;
	char *key = NULL;
	size_t blob_size;
	char timestamp[100] = {0};

	while (*line != '\x0' && !isdigit (*line)) {
		if (*line == '-') {
			static const char *ts = "--timestamp=";
			char *p = line;

			while (*line != '\x0' && !isspace (*line)) {
				line++;
			}
			line++;

			if (!strncmp (p, ts, strlen (ts))) {
				p += strlen (ts);
				sprintf (timestamp, "%d", (int)isotime2epoch (p));
			}
		}
		else {
			line++;
		}
	}

	if (*line == '\x0') {
		error = GPG_ERR_INV_DATA;
		goto cleanup;
	}

	if (strlen (timestamp) == 0) {
		sprintf (timestamp, "%d", (int)time (NULL));
	}

	if (
		(error = _get_certificate_by_name (
			ctx,
			NULL,
			atoi(line),
			&cert_id,
			&key
		)) != GPG_ERR_NO_ERROR
	) {
		goto cleanup;
	}

	if (
		(error = assuan_write_status (
			ctx,
			"KEY-FPR",
			key
		)) != GPG_ERR_NO_ERROR ||
		(error = assuan_write_status(
			ctx,
			"KEY-CREATED-AT",
			timestamp
		)) != GPG_ERR_NO_ERROR
	) {
		goto cleanup;
	}

	if ((error = get_serial_of_tokenid(cert_id->token_id, &serial)) != GPG_ERR_NO_ERROR) {
		goto cleanup;
	}

	if (
		(error = assuan_write_status (
			ctx,
			"SERIALNO",
			serial
		)) != GPG_ERR_NO_ERROR ||
		(error = get_cert_blob (
			ctx,
			cert_id,
			&blob,
			&blob_size
		)) != GPG_ERR_NO_ERROR ||
		(error = keyutil_get_cert_mpi (
			blob,
			blob_size,
			&n_mpi,
			&e_mpi
		)) != GPG_ERR_NO_ERROR
	) {
		goto cleanup;
	}

	if (
		gcry_mpi_aprint (
			GCRYMPI_FMT_HEX,
			&n_hex,
			NULL,
			n_mpi
		) ||
		gcry_mpi_aprint (
			GCRYMPI_FMT_HEX,
			&e_hex,
			NULL,
			e_mpi
		)
	) {
		error = GPG_ERR_BAD_KEY;
		goto cleanup;
	}

	if (
		!encoding_strappend (&n_resp, (char *)n_hex) ||
		!encoding_strappend (&e_resp, (char *)e_hex)
	) {
		error = GPG_ERR_ENOMEM;
		goto cleanup;
	}

	if (
		(error = assuan_write_status(
			ctx,
			"KEY-DATA",
			n_resp
		)) != GPG_ERR_NO_ERROR
	) {
		goto cleanup;
	}

	if (
		(error = assuan_write_status(
			ctx,
			"KEY-DATA",
			e_resp
		)) != GPG_ERR_NO_ERROR
	) {
		goto cleanup;
	}

	error = GPG_ERR_NO_ERROR;

cleanup:

	if (n_mpi != NULL) {
		gcry_mpi_release (n_mpi);
		n_mpi = NULL;
	}

	if (e_mpi != NULL) {
		gcry_mpi_release (e_mpi);
		e_mpi = NULL;
	}

	if (n_hex != NULL) {
		gcry_free (n_hex);
		n_hex = NULL;
	}

	if (e_hex != NULL) {
		gcry_free (e_hex);
		e_hex = NULL;
	}

	if (n_resp != NULL) {
		free (n_resp);
		n_resp = NULL;
	}

	if (e_resp != NULL) {
		free (e_resp);
		e_resp = NULL;
	}

	if (blob != NULL) {
		free (blob);
		blob = NULL;
	}

	if (cert_id != NULL) {
		pkcs11h_certificate_freeCertificateId (cert_id);
		cert_id = NULL;
	}

	if (serial != NULL) {
		free(serial);
		serial = NULL;
	}

	return gpg_error (error);
}
Example #9
0
gpg_error_t cmd_getattr (assuan_context_t ctx, char *line)
{
	pkcs11h_certificate_id_list_t user_certificates = NULL;
	char *serial = NULL;
	gpg_err_code_t error = GPG_ERR_GENERAL;

	if (!strcmp (line, "SERIALNO")) {
		if (
			(error = get_serial(ctx, &serial)) != GPG_ERR_NO_ERROR
		) {
			goto cleanup;
		}

		if (serial != NULL) {
			if (
				(error = assuan_write_status (
					ctx,
					"SERIALNO",
					serial
				)) != GPG_ERR_NO_ERROR
			) {
				goto cleanup;
			}
		}
	}
	else if (!strcmp (line, "KEY-FPR")) {
		if (
			(error = common_map_pkcs11_error (
				pkcs11h_certificate_enumCertificateIds (
					PKCS11H_ENUM_METHOD_CACHE_EXIST,
					ctx,
					PKCS11H_PROMPT_MASK_ALLOW_ALL,
					NULL,
					&user_certificates
				)
			)) != GPG_ERR_NO_ERROR ||
			(error = send_certificate_list (
				ctx,
				user_certificates,
				0
			)) != GPG_ERR_NO_ERROR
		) {
			goto cleanup;
		}
	}
	else if (!strcmp (line, "CHV-STATUS")) {
		if (
			(error = assuan_write_status(
				ctx,
				"CHV-STATUS",
				"1 1 1 1 1 1 1"
			)) != GPG_ERR_NO_ERROR
		) {
			goto cleanup;
		}
	}
	else if (!strcmp (line, "DISP-NAME")) {
		if (
			(error = assuan_write_status(
				ctx,
				"DISP-NAME",
				"PKCS#11"
			)) != GPG_ERR_NO_ERROR
		) {
			goto cleanup;
		}
	}
	else if (!strcmp (line, "KEY-ATTR")) {
		int i;
		for (i=0;i<3;i++) {
			char buffer[1024];

			/* I am not sure 2048 is right here... */
			snprintf(buffer, sizeof(buffer), "%d 1 %u %u %d", i+1, GCRY_PK_RSA, 2048, 0);

			if (
				(error = assuan_write_status(
					ctx,
					"KEY-ATTR",
					buffer
				)) != GPG_ERR_NO_ERROR
			) {
				goto cleanup;
			}
		}
	}
	else if (!strcmp (line, "EXTCAP")) {
		int i;
		for (i=0;i<3;i++) {
			char buffer[1024];

			/* I am not sure what these are... */
			snprintf(buffer, sizeof(buffer), "gc=%d ki=%d fc=%d pd=%d mcl3=%u aac=%d sm=%d",
				0, 0, 0, 0, 2048, 0, 0);

			if (
				(error = assuan_write_status(
					ctx,
					"EXTCAP",
					buffer
				)) != GPG_ERR_NO_ERROR
			) {
				goto cleanup;
			}
		}
	}
	else {
		error = GPG_ERR_INV_DATA;
		goto cleanup;
	}

	error = GPG_ERR_NO_ERROR;

cleanup:

	if (user_certificates != NULL) {
		pkcs11h_certificate_freeCertificateIdList (user_certificates);
		user_certificates = NULL;
	}

	if (serial != NULL) {
		free(serial);
		serial = NULL;
	}

	return gpg_error (error);
}
Example #10
0
/** Decrypt data (set by SETDATA) with certificate id in line. */
gpg_error_t cmd_pkdecrypt (assuan_context_t ctx, char *line)
{
	gpg_err_code_t error = GPG_ERR_GENERAL;
	pkcs11h_certificate_id_t cert_id = NULL;
	pkcs11h_certificate_t cert = NULL;
	unsigned char *ptext = NULL;
	size_t ptext_len;
	int session_locked = 0;
	cmd_data_t *data = (cmd_data_t *)assuan_get_pointer (ctx);
	cmd_data_t _data;

	if (
		data == NULL ||
		data->data == NULL
	) {
		error = GPG_ERR_INV_DATA;
		goto cleanup;
	}

	/*
	 * Guess.. taken from openpgp card implementation
	 * and java PKCS#11 provider.
	 */
	_data.data = data->data;
	_data.size = data->size;
	if (
		*_data.data == 0 && (
			_data.size == 129 ||
			_data.size == 193 ||
			_data.size == 257 ||
			_data.size == 385 ||
			_data.size == 513
		)
	) {
		_data.data++;
		_data.size--;
	}

	if (
		(error = _get_certificate_by_name (
			ctx,
			line,
			OPENPGP_ENCR,
			&cert_id,
			NULL
		)) != GPG_ERR_NO_ERROR
	) {
		goto cleanup;
	}

	if (
		(error = common_map_pkcs11_error (
			pkcs11h_certificate_create (
				cert_id,
				ctx,
				PKCS11H_PROMPT_MASK_ALLOW_ALL,
				PKCS11H_PIN_CACHE_INFINITE,
				&cert
			)
		)) != GPG_ERR_NO_ERROR
	) {
		goto cleanup;
	}

	if (
		(error = common_map_pkcs11_error (
			pkcs11h_certificate_lockSession (cert)
		)) != GPG_ERR_NO_ERROR
	) {
		goto cleanup;
	}
	session_locked = 1;

	if (
		(error = common_map_pkcs11_error (
			pkcs11h_certificate_decryptAny (
				cert,
				CKM_RSA_PKCS, 
				_data.data,
				_data.size,
				NULL,
				&ptext_len
			)
		)) != GPG_ERR_NO_ERROR
	) {
		goto cleanup;
	}

	if ((ptext = (unsigned char *)malloc (ptext_len)) == NULL) {
		error = GPG_ERR_ENOMEM;
		goto cleanup;
	}

	if (
		(error = common_map_pkcs11_error (
			pkcs11h_certificate_decryptAny (
				cert,
				CKM_RSA_PKCS, 
				_data.data,
				_data.size,
				ptext,
				&ptext_len
			)
		)) != GPG_ERR_NO_ERROR ||
		(error = assuan_write_status(ctx, "PADDING", "0")) != GPG_ERR_NO_ERROR ||
		(error = assuan_send_data(ctx, ptext, ptext_len)) != GPG_ERR_NO_ERROR
	) {
		goto cleanup;
	}

	error = GPG_ERR_NO_ERROR;

cleanup:

	if (session_locked) {
		pkcs11h_certificate_releaseSession (cert);
		session_locked = 0;
	}

	if (cert != NULL) {
		pkcs11h_certificate_freeCertificate (cert);
		cert = NULL;
	}

	if (cert_id != NULL) {
		pkcs11h_certificate_freeCertificateId (cert_id);
		cert_id = NULL;
	}

	if (ptext != NULL) {
		free (ptext);
		ptext = NULL;
	}

	return gpg_error (error);
}