guchar *
egg_openssl_decrypt_block (const gchar *dekinfo,
                           const gchar *password,
                           gssize n_password,
                           GBytes *data,
                           gsize *n_decrypted)
{
	gcry_cipher_hd_t ch;
	guchar *key = NULL;
	guchar *iv = NULL;
	int gcry, ivlen;
	int algo = 0;
	int mode = 0;
	guchar *decrypted;

	if (!parse_dekinfo (dekinfo, &algo, &mode, &iv))
		return FALSE;

	ivlen = gcry_cipher_get_algo_blklen (algo);

	/* We assume the iv is at least as long as at 8 byte salt */
	g_return_val_if_fail (ivlen >= 8, FALSE);

	/* IV is already set from the DEK info */
	if (!egg_symkey_generate_simple (algo, GCRY_MD_MD5, password,
	                                 n_password, iv, 8, 1, &key, NULL)) {
		g_free (iv);
		return NULL;
	}

	gcry = gcry_cipher_open (&ch, algo, mode, 0);
	g_return_val_if_fail (!gcry, NULL);

	gcry = gcry_cipher_setkey (ch, key, gcry_cipher_get_algo_keylen (algo));
	g_return_val_if_fail (!gcry, NULL);
	egg_secure_free (key);

	/* 16 = 128 bits */
	gcry = gcry_cipher_setiv (ch, iv, ivlen);
	g_return_val_if_fail (!gcry, NULL);
	g_free (iv);

	/* Allocate output area */
	*n_decrypted = g_bytes_get_size (data);
	decrypted = egg_secure_alloc (*n_decrypted);

	gcry = gcry_cipher_decrypt (ch, decrypted, *n_decrypted,
	                            g_bytes_get_data (data, NULL),
	                            g_bytes_get_size (data));
	if (gcry) {
		egg_secure_free (decrypted);
		g_return_val_if_reached (NULL);
	}

	gcry_cipher_close (ch);

	return decrypted;
}
static gboolean
decrypt_buffer (EggBuffer *buffer, GkmSecret *master,
		guchar salt[8], int iterations)
{
	const gchar *password = NULL;
	gcry_cipher_hd_t cih;
	gcry_error_t gerr;
        guchar *key, *iv;
        gsize n_password = 0;
	size_t pos;

	g_assert (buffer->len % 16 == 0);
	g_assert (16 == gcry_cipher_get_algo_blklen (GCRY_CIPHER_AES128));
	g_assert (16 == gcry_cipher_get_algo_keylen (GCRY_CIPHER_AES128));

	/* No password is set, try an null password */
	if (master == NULL) {
		password = NULL;
		n_password = 0;
	} else {
		password = gkm_secret_get_password (master, &n_password);
	}

	if (!egg_symkey_generate_simple (GCRY_CIPHER_AES128, GCRY_MD_SHA256,
	                                 password, n_password, salt, 8, iterations, &key, &iv))
		return FALSE;

	gerr = gcry_cipher_open (&cih, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, 0);
	if (gerr) {
		g_warning ("couldn't create aes cipher context: %s",
			   gcry_strerror (gerr));
		egg_secure_free (key);
		g_free (iv);
		return FALSE;
	}

	/* 16 = 128 bits */
	gerr = gcry_cipher_setkey (cih, key, 16);
	g_return_val_if_fail (!gerr, FALSE);
	egg_secure_free (key);

	/* 16 = 128 bits */
	gerr = gcry_cipher_setiv (cih, iv, 16);
	g_return_val_if_fail (!gerr, FALSE);
	g_free (iv);

	for (pos = 0; pos < buffer->len; pos += 16) {
		/* In place encryption */
		gerr = gcry_cipher_decrypt (cih, buffer->buf + pos, 16, NULL, 0);
		g_return_val_if_fail (!gerr, FALSE);
	}

	gcry_cipher_close (cih);

	return TRUE;
}
static gboolean
gcr_secret_exchange_default_derive_transport_key (GcrSecretExchange *exchange,
                                                  const guchar *peer,
                                                  gsize n_peer)
{
	GcrSecretExchangeDefault *data = exchange->pv->default_exchange;
	gpointer ikm;
	gsize n_ikm;
	gcry_mpi_t mpi;

	g_return_val_if_fail (data != NULL, FALSE);
	g_return_val_if_fail (data->priv != NULL, FALSE);

	mpi = mpi_from_data (peer, n_peer);
	if (mpi == NULL)
		return FALSE;

	/* Build up a key we can use */
	ikm = egg_dh_gen_secret (mpi, data->priv, data->prime, &n_ikm);
	g_return_val_if_fail (ikm != NULL, FALSE);

	if (data->key == NULL)
		data->key = egg_secure_alloc (EXCHANGE_1_KEY_LENGTH);

	if (!egg_hkdf_perform (EXCHANGE_1_HASH_ALGO, ikm, n_ikm, NULL, 0,
	                       NULL, 0, data->key, EXCHANGE_1_KEY_LENGTH))
		g_return_val_if_reached (FALSE);

	egg_secure_free (ikm);
	gcry_mpi_release (mpi);

	return TRUE;
}
static gboolean
gkm_mate2_private_key_real_save (GkmSerializable *base, GkmSecret *login, gpointer *data, gsize *n_data)
{
	GkmMate2PrivateKey *self = GKM_MATE2_PRIVATE_KEY (base);
	const gchar *password;
	gsize n_password;
	GkmSexp *sexp;
	guchar *key;

	g_return_val_if_fail (GKM_IS_MATE2_PRIVATE_KEY (self), FALSE);
	g_return_val_if_fail (data, FALSE);
	g_return_val_if_fail (n_data, FALSE);

	sexp = gkm_mate2_private_key_real_acquire_crypto_sexp (GKM_SEXP_KEY (self), NULL);
	g_return_val_if_fail (sexp, FALSE);

	password = gkm_secret_get_password (login, &n_password);
	if (password == NULL) {
		key = gkm_data_der_write_private_pkcs8_plain (gkm_sexp_get (sexp), n_data);

		/*
		 * Caller is expecting normal memory buffer, which makes sense since
		 * this is being written to disk, and won't be 'secure' anyway.
		 */
		*data = g_memdup (key, *n_data);
		egg_secure_free (key);
	} else {
		*data = gkm_data_der_write_private_pkcs8_crypted (gkm_sexp_get (sexp), password,
		                                                  n_password, n_data);
	}

	gkm_sexp_unref (sexp);
	return *data != NULL;
}
static gboolean
gcr_secret_exchange_default_generate_exchange_key (GcrSecretExchange *exchange,
                                                   const gchar *scheme,
                                                   guchar **public_key,
                                                   gsize *n_public_key)
{
	GcrSecretExchangeDefault *data = exchange->pv->default_exchange;

	if (data == NULL) {
		data = g_new0 (GcrSecretExchangeDefault, 1);
		if (!egg_dh_default_params (EXCHANGE_1_IKE_NAME, &data->prime, &data->base))
			g_return_val_if_reached (FALSE);

		exchange->pv->default_exchange = data;
		exchange->pv->destroy_exchange = gcr_secret_exchange_default_free;
	}

	gcry_mpi_release (data->priv);
	data->priv = NULL;
	gcry_mpi_release (data->pub);
	data->pub = NULL;
	egg_secure_free (data->key);
	data->key = NULL;

	if (!egg_dh_gen_pair (data->prime, data->base, 0,
	                      &data->pub, &data->priv))
		g_return_val_if_reached (FALSE);

	*public_key = mpi_to_data (data->pub, n_public_key);
	return *public_key != NULL;
}
Exemple #6
0
/**
 * gcr_secret_exchange_receive:
 * @self: a #GcrSecretExchange object
 * @exchange: the string received
 *
 * Receive a string from the other side of secret exchange. This string will
 * have been created by gcr_secret_exchange_begin() or gcr_secret_exchange_send().
 *
 * After this call completes successfully the value returned from
 * gcr_secret_exchange_get_secret() will have changed.
 *
 * Returns: whether the string was successfully parsed and received
 */
gboolean
gcr_secret_exchange_receive (GcrSecretExchange *self,
                             const gchar *exchange)
{
	GcrSecretExchangeClass *klass;
	gchar *secret = NULL;
	gsize n_secret = 0;
	GKeyFile *input;
	gboolean ret;

	g_return_val_if_fail (GCR_IS_SECRET_EXCHANGE (self), FALSE);
	g_return_val_if_fail (exchange != NULL, FALSE);

	klass = GCR_SECRET_EXCHANGE_GET_CLASS (self);
	g_return_val_if_fail (klass->generate_exchange_key, FALSE);
	g_return_val_if_fail (klass->derive_transport_key, FALSE);

	gchar *string = g_strescape (exchange, "");
	g_debug ("receiving secret exchange: %s", string);
	g_free (string);

	/* Parse the input */
	input = g_key_file_new ();
	if (!g_key_file_load_from_data (input, exchange, strlen (exchange),
	                                G_KEY_FILE_NONE, NULL)) {
		g_key_file_free (input);
		g_message ("couldn't parse secret exchange data");
		return FALSE;
	}

	if (!self->pv->generated) {
		if (!(klass->generate_exchange_key) (self, GCR_SECRET_EXCHANGE_PROTOCOL_1,
		                                     &self->pv->publi, &self->pv->n_publi))
			g_return_val_if_reached (FALSE);
		self->pv->generated = TRUE;
	}

	ret = TRUE;

	if (!self->pv->derived) {
		if (!derive_key (self, input))
			ret = FALSE;
	}

	if (ret && g_key_file_has_key (input, GCR_SECRET_EXCHANGE_PROTOCOL_1, "secret", NULL))
		ret = perform_decrypt (self, input, (guchar **)&secret, &n_secret);

	if (ret) {
		egg_secure_free (self->pv->secret);
		self->pv->secret = secret;
		self->pv->n_secret = n_secret;
	}

	g_key_file_free (input);
	return ret;
}
static void
clear_secret_exchange (GcrSecretExchange *self)
{
	g_free (self->pv->publi);
	self->pv->publi = NULL;
	self->pv->n_publi = 0;
	self->pv->derived = FALSE;
	self->pv->generated = TRUE;
	egg_secure_free (self->pv->secret);
	self->pv->secret = NULL;
	self->pv->n_secret = 0;
}
Exemple #8
0
static gchar*
read_login_password (int fd)
{
	/* We only accept a max of 8K as the login password */
	#define MAX_LENGTH 8192
	#define MAX_BLOCK 256

	/*
	 * When --login is specified then the login password is passed
	 * in on stdin. All data (including newlines) are part of the
	 * password. A zero length password is no password.
	 */

	gchar *buf = egg_secure_alloc (MAX_BLOCK);
	gchar *ret = NULL;
	int r, len = 0;

	for (;;) {
		r = read (fd, buf, MAX_BLOCK);
		if (r < 0) {
			if (errno == EAGAIN)
				continue;
			egg_secure_free (ret);
			egg_secure_free (buf);
			return NULL;

		} else if (r == 0 || len > MAX_LENGTH) {
			break;

		} else {
			ret = egg_secure_realloc (ret, len + r + 1);
			memset (ret + len, 0, r + 1);
			len = len + r;
			strncat (ret, buf, r);
		}
	}

	egg_secure_free (buf);
	return ret;
}
static void
gcr_secret_exchange_default_free (gpointer to_free)
{
	GcrSecretExchangeDefault *data = to_free;
	gcry_mpi_release (data->prime);
	gcry_mpi_release (data->base);
	gcry_mpi_release (data->pub);
	gcry_mpi_release (data->priv);
	if (data->key) {
		egg_secure_clear (data->key, EXCHANGE_1_KEY_LENGTH);
		egg_secure_free (data->key);
	}
	g_free (data);
}
guint
egg_openssl_pem_parse (const guchar *data, gsize n_data, 
                       EggOpensslPemCallback callback, gpointer user_data)
{
	const gchar *beg, *end;
	guint nfound = 0;
	guchar *decoded = NULL;
	gsize n_decoded = 0;
	GHashTable *headers = NULL;
	GQuark type;
	
	g_return_val_if_fail (data, 0);
	g_return_val_if_fail (n_data, 0);
	g_return_val_if_fail (callback, 0);

	while (n_data > 0) {
		
		/* This returns the first character after the PEM BEGIN header */
		beg = pem_find_begin ((const gchar*)data, n_data, &type);
		if (!beg)
			break;
			
		g_assert (type);
		
		/* This returns the character position before the PEM END header */
		end = pem_find_end ((const gchar*)beg, n_data - ((const guchar*)beg - data), type);
		if (!end)
			break;

		if (beg != end) {
			if (pem_parse_block (beg, end - beg, &decoded, &n_decoded, &headers)) {
				(callback) (type, decoded, n_decoded, headers, user_data);
				++nfound;
				egg_secure_free (decoded);
				if (headers)
					g_hash_table_remove_all (headers);
			}
		}
                     
		/* Try for another block */
		end += PEM_SUFF_L;
		n_data -= (const guchar*)end - data; 
		data = (const guchar*)end;
	}
	
	if (headers)
		g_hash_table_destroy (headers);

	return nfound;
}
static void
gkm_generic_key_finalize (GObject *obj)
{
	GkmGenericKey *self = GKM_GENERIC_KEY (obj);

	if (self->value) {
		egg_secure_clear (self->value, self->n_value);
		egg_secure_free (self->value);
		self->value = NULL;
		self->n_value = 0;
	}

	G_OBJECT_CLASS (gkm_generic_key_parent_class)->finalize (obj);
}
Exemple #12
0
void
_secret_session_free (gpointer data)
{
	SecretSession *session = data;

	if (session == NULL)
		return;

	g_free (session->path);
#ifdef WITH_GCRYPT
	gcry_mpi_release (session->publi);
	gcry_mpi_release (session->privat);
	gcry_mpi_release (session->prime);
#endif
	egg_secure_free (session->key);
	g_free (session);
}
static CK_RV
retrieve_value (GkmSession *session, GkmObject *wrapped,
                gpointer *value, gsize *n_value)
{
	CK_ATTRIBUTE attr;
	CK_RV rv;

	rv = retrieve_length (session, wrapped, n_value);
	if (rv != CKR_OK)
		return rv;

	attr.type = CKA_VALUE;
	attr.pValue = egg_secure_alloc (*n_value);
	attr.ulValueLen = *n_value;

	rv = gkm_object_get_attribute (wrapped, session, &attr);
	if (rv == CKR_OK)
		*value = attr.pValue;
	else
		egg_secure_free (attr.pValue);

	return rv;
}
static void
test_der_private (gcry_sexp_t key)
{
	guchar *data;
	gsize n_data;
	GkmDataResult ret;
	gcry_sexp_t sexp;

	/* Encode it */
	data = gkm_data_der_write_private_key (key, &n_data);
	g_assert ("couldn't encode private key" && data != NULL);
	g_assert ("encoding is empty" && n_data > 0);

	/* Now parse it */
	ret = gkm_data_der_read_private_key (data, n_data, &sexp);
	g_assert ("couldn't decode private key" && ret == GKM_DATA_SUCCESS);
	g_assert ("parsed key is empty" && sexp != NULL);

	/* Now compare them */
	g_assert ("key parsed differently" && compare_keys (key, sexp));

	egg_secure_free (data);
}
CK_RV
gkm_aes_mechanism_wrap (GkmSession *session, CK_MECHANISM_PTR mech,
                        GkmObject *wrapper, GkmObject *wrapped,
                        CK_BYTE_PTR output, CK_ULONG_PTR n_output)
{
	gcry_cipher_hd_t cih;
	gcry_error_t gcry;
	GkmAesKey *key;
	gpointer value, padded;
	gsize n_value, n_padded;
	gsize block, pos;
	gboolean ret;
	CK_RV rv;

	g_return_val_if_fail (GKM_IS_SESSION (session), CKR_GENERAL_ERROR);
	g_return_val_if_fail (mech, CKR_GENERAL_ERROR);
	g_return_val_if_fail (mech->mechanism == CKM_AES_CBC_PAD, CKR_GENERAL_ERROR);
	g_return_val_if_fail (GKM_IS_OBJECT (wrapped), CKR_GENERAL_ERROR);
	g_return_val_if_fail (n_output, CKR_GENERAL_ERROR);

	if (!GKM_IS_AES_KEY (wrapper))
		return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
	key = GKM_AES_KEY (wrapper);

	block = gkm_aes_key_get_block_size (key);
	g_return_val_if_fail (block != 0, CKR_GENERAL_ERROR);

	/* They just want the length */
	if (!output) {
		rv = retrieve_length (session, wrapped, &n_value);
		if (rv != CKR_OK)
			return rv;
		if (!egg_padding_pkcs7_pad (NULL, block, NULL, n_value, NULL, &n_padded))
			return CKR_KEY_SIZE_RANGE;
		*n_output = n_padded;
		return CKR_OK;
	}

	cih = gkm_aes_key_get_cipher (key, GCRY_CIPHER_MODE_CBC);
	if (cih == NULL)
		return CKR_FUNCTION_FAILED;

	if (!mech->pParameter || gcry_cipher_setiv (cih, mech->pParameter, mech->ulParameterLen) != 0) {
		gcry_cipher_close (cih);
		return CKR_MECHANISM_PARAM_INVALID;
	}

	rv = retrieve_value (session, wrapped, &value, &n_value);
	if (rv != CKR_OK) {
		gcry_cipher_close (cih);
		return rv;
	}

	ret = egg_padding_pkcs7_pad (egg_secure_realloc, block, value, n_value, &padded, &n_padded);
	egg_secure_free (value);

	if (ret == FALSE) {
		gcry_cipher_close (cih);
		return CKR_KEY_SIZE_RANGE;
	}

	/* In place encryption */
	for (pos = 0; pos < n_padded; pos += block) {
		gcry = gcry_cipher_encrypt (cih, (guchar*)padded + pos, block, NULL, 0);
		g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
	}

	gcry_cipher_close (cih);

	rv = gkm_util_return_data (output, n_output, padded, n_padded);
	egg_secure_free (padded);
	return rv;
}
gboolean
egg_symkey_generate_simple (int cipher_algo, int hash_algo, 
                            const gchar *password, gssize n_password, 
                            const guchar *salt, gsize n_salt, int iterations, 
                            guchar **key, guchar **iv)
{
	gcry_md_hd_t mdh;
	gcry_error_t gcry;
	guchar *digest;
	guchar *digested;
	guint n_digest;
	gint pass, i;
	gint needed_iv, needed_key;
	guchar *at_iv, *at_key;

	g_assert (cipher_algo);
	g_assert (hash_algo);

	g_return_val_if_fail (iterations >= 1, FALSE);
	
	if (!password)
		n_password = 0;
	if (n_password == -1)
		n_password = strlen (password);
	
	/* 
	 * If cipher algo needs more bytes than hash algo has available
	 * then the entire hashing process is done again (with the previous
	 * hash bytes as extra input), and so on until satisfied.
	 */ 
	
	needed_key = gcry_cipher_get_algo_keylen (cipher_algo);
	needed_iv = gcry_cipher_get_algo_blklen (cipher_algo);
	
	gcry = gcry_md_open (&mdh, hash_algo, 0);
	if (gcry) {
		g_warning ("couldn't create '%s' hash context: %s", 
			   gcry_md_algo_name (hash_algo), gcry_strerror (gcry));
		return FALSE;
	}

	n_digest = gcry_md_get_algo_dlen (hash_algo);
	g_return_val_if_fail (n_digest > 0, FALSE);
	
	digest = egg_secure_alloc (n_digest);
	g_return_val_if_fail (digest, FALSE);
	if (key) {
		*key = egg_secure_alloc (needed_key);
		g_return_val_if_fail (*key, FALSE);
	}
	if (iv) 
		*iv = g_new0 (guchar, needed_iv);

	at_key = key ? *key : NULL;
	at_iv = iv ? *iv : NULL;

	for (pass = 0; TRUE; ++pass) {
		gcry_md_reset (mdh);
		
		/* Hash in the previous buffer on later passes */
		if (pass > 0)
			gcry_md_write (mdh, digest, n_digest);

		if (password)
			gcry_md_write (mdh, password, n_password);
		if (salt && n_salt)
			gcry_md_write (mdh, salt, n_salt);
		gcry_md_final (mdh);
		digested = gcry_md_read (mdh, 0);
		g_return_val_if_fail (digested, FALSE);
		memcpy (digest, digested, n_digest);
		
		for (i = 1; i < iterations; ++i) {
			gcry_md_reset (mdh);
			gcry_md_write (mdh, digest, n_digest);
			gcry_md_final (mdh);
			digested = gcry_md_read (mdh, 0);
			g_return_val_if_fail (digested, FALSE);
			memcpy (digest, digested, n_digest);
		}
		
		/* Copy as much as possible into the destinations */
		i = 0; 
		while (needed_key && i < n_digest) {
			if (at_key)
				*(at_key++) = digest[i];
			needed_key--;
			i++;
		}
		while (needed_iv && i < n_digest) {
			if (at_iv) 
				*(at_iv++) = digest[i];
			needed_iv--;
			i++;
		}
		
		if (needed_key == 0 && needed_iv == 0)
			break;
	}

	egg_secure_free (digest);
	gcry_md_close (mdh);
	
	return TRUE;
}
gboolean
egg_symkey_generate_pbe (int cipher_algo, int hash_algo, const gchar *password, 
                         gssize n_password, const guchar *salt, gsize n_salt, int iterations, 
                         guchar **key, guchar **iv)
{
	gcry_md_hd_t mdh;
	gcry_error_t gcry;
	guchar *digest;
	guchar *digested;
	guint i, n_digest;
	gint needed_iv, needed_key;

	g_assert (cipher_algo);
	g_assert (hash_algo);

	g_return_val_if_fail (iterations >= 1, FALSE);
	
	if (!password)
		n_password = 0;
	if (n_password == -1)
		n_password = strlen (password);
	
	/* 
	 * We only do one pass here.
	 * 
	 * The key ends up as the first needed_key bytes of the hash buffer.
	 * The iv ends up as the last needed_iv bytes of the hash buffer. 
	 * 
	 * The IV may overlap the key (which is stupid) if the wrong pair of 
	 * hash/cipher algorithms are chosen.
	 */ 

	n_digest = gcry_md_get_algo_dlen (hash_algo);
	g_return_val_if_fail (n_digest > 0, FALSE);
	
	needed_key = gcry_cipher_get_algo_keylen (cipher_algo);
	needed_iv = gcry_cipher_get_algo_blklen (cipher_algo);
	if (needed_iv + needed_key > 16 || needed_iv + needed_key > n_digest) {
		g_warning ("using PBE symkey generation with %s using an algorithm that needs " 
		           "too many bytes of key and/or IV: %s",
		           gcry_cipher_algo_name (hash_algo), 
		           gcry_cipher_algo_name (cipher_algo));
		return FALSE;
	}
	
	gcry = gcry_md_open (&mdh, hash_algo, 0);
	if (gcry) {
		g_warning ("couldn't create '%s' hash context: %s", 
			   gcry_md_algo_name (hash_algo), gcry_strerror (gcry));
		return FALSE;
	}

	digest = egg_secure_alloc (n_digest);
	g_return_val_if_fail (digest, FALSE);
	if (key) {
		*key = egg_secure_alloc (needed_key);
		g_return_val_if_fail (*key, FALSE);
	}
	if (iv) 
		*iv = g_new0 (guchar, needed_iv);

	if (password)
		gcry_md_write (mdh, password, n_password);
	if (salt && n_salt)
		gcry_md_write (mdh, salt, n_salt);
	gcry_md_final (mdh);
	digested = gcry_md_read (mdh, 0);
	g_return_val_if_fail (digested, FALSE);
	memcpy (digest, digested, n_digest);
		
	for (i = 1; i < iterations; ++i)
		gcry_md_hash_buffer (hash_algo, digest, digest, n_digest);
	
	/* The first x bytes are the key */
	if (key) {
		g_assert (needed_key <= n_digest);
		memcpy (*key, digest, needed_key);
	}
	
	/* The last 16 - x bytes are the iv */
	if (iv) {
		g_assert (needed_iv <= n_digest && n_digest >= 16);
		memcpy (*iv, digest + (16 - needed_iv), needed_iv);
	}
		
	egg_secure_free (digest);
	gcry_md_close (mdh);
	
	return TRUE;	
}
static gcry_cipher_hd_t
prepare_and_encode_pkcs8_cipher (GNode *asn, const gchar *password,
                                 gsize n_password, gsize *n_block)
{
	GNode *asn1_params = NULL;
	gcry_cipher_hd_t cih;
	guchar *salt;
	gsize n_salt;
	gcry_error_t gcry;
	guchar *key, *iv;
	gsize n_key;
	int iterations;

	init_quarks ();

	/* Make sure the encryption algorithm works */
	g_return_val_if_fail (gcry_cipher_algo_info (gcry_cipher_map_name (g_quark_to_string (OID_PKCS12_PBE_3DES_SHA1)),
	                                             GCRYCTL_TEST_ALGO, NULL, 0) == 0, NULL);

	/* The encryption algorithm */
	if(!egg_asn1x_set_oid_as_quark (egg_asn1x_node (asn, "encryptionAlgorithm", "algorithm", NULL),
	                                OID_PKCS12_PBE_3DES_SHA1))
		g_return_val_if_reached (NULL);

	/* Randomize some input for the password based secret */
	iterations = g_random_int_range (1000, 4096);
	n_salt = 8;
	salt = g_malloc (n_salt);
	gcry_create_nonce (salt, n_salt);

	/* Allocate space for the key and iv */
	n_key = gcry_cipher_get_algo_keylen (GCRY_CIPHER_3DES);
	*n_block = gcry_cipher_get_algo_blklen (GCRY_MD_SHA1);
	g_return_val_if_fail (n_key && *n_block, NULL);

	if (!egg_symkey_generate_pkcs12 (GCRY_CIPHER_3DES, GCRY_MD_SHA1,
	                                        password, n_password, salt,
	                                        sizeof (salt), iterations, &key, &iv))
		g_return_val_if_reached (NULL);

	/* Now write out the parameters */
	asn1_params = egg_asn1x_create (pkix_asn1_tab, "pkcs-12-PbeParams");
	g_return_val_if_fail (asn1_params, NULL);
	egg_asn1x_set_string_as_raw (egg_asn1x_node (asn1_params, "salt", NULL), salt, n_salt, g_free);
	egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn1_params, "iterations", NULL), iterations);
	egg_asn1x_set_any_from (egg_asn1x_node (asn, "encryptionAlgorithm", "parameters", NULL), asn1_params);

	/* Now make a cipher that matches what we wrote out */
	gcry = gcry_cipher_open (&cih, GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, 0);
	g_return_val_if_fail (gcry == 0, NULL);
	g_return_val_if_fail (cih, NULL);

	gcry_cipher_setiv (cih, iv, *n_block);
	gcry_cipher_setkey (cih, key, n_key);

	g_free (iv);
	egg_secure_free (key);
	egg_asn1x_destroy (asn1_params);

	return cih;
}
/**
 * main:
 * @argc:
 * @argv[]: Sent to gtk_init
 *
 * Prompt for GnuPG and SSH. Communicates using stdin/stdout. Communication data
 * is in ini-file structures
 *
 * Returns: 0
 */
int
main (int argc, char *argv[])
{
	GError *err = NULL;
	gchar *data;
	gboolean ret;
	gsize length;

	/* Exit on HUP signal */
	signal(SIGINT,  hup_handler);

	prepare_logging ();

	egg_libgcrypt_initialize ();

	input_data = g_key_file_new ();
	output_data = g_key_file_new ();

	gtk_init (&argc, &argv);

#ifdef HAVE_LOCALE_H
	/* internationalisation */
	setlocale (LC_ALL, "");
#endif

#ifdef HAVE_GETTEXT
	bindtextdomain (GETTEXT_PACKAGE, MATELOCALEDIR);
	textdomain (GETTEXT_PACKAGE);
	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
#endif

	data = read_all_input ();
	g_assert (data);

	if (!data[0])
		fatal ("no auth dialog instructions", NULL);

	ret = g_key_file_load_from_data (input_data, data, strlen (data), G_KEY_FILE_NONE, &err);
	g_free (data);

	if (!ret)
		fatal ("couldn't parse auth dialog instructions", egg_error_message (err));

	run_dialog ();

	/* Cleanup after any key */
	if (the_key) {
		egg_secure_clear (the_key, n_the_key);
		egg_secure_free (the_key);
		the_key = NULL;
		n_the_key = 0;
	}

	g_key_file_free (input_data);
	data = g_key_file_to_data (output_data, &length, &err);
	g_key_file_free (output_data);

	if (!data)
		fatal ("couldn't format auth dialog response: %s", egg_error_message (err));

	write_all_output (data, length);
	g_free (data);

	return 0;
}
Exemple #20
0
GkmDataResult
gkm_data_der_read_private_pkcs8_crypted (const guchar *data, gsize n_data, const gchar *password,
                                         gsize n_password, gcry_sexp_t *s_key)
{
	GNode *asn = NULL;
	gcry_cipher_hd_t cih = NULL;
	gcry_error_t gcry;
	GkmDataResult ret, r;
	GQuark scheme;
	guchar *crypted = NULL;
	const guchar *params;
	gsize n_crypted, n_params;
	gint l;

	init_quarks ();

	ret = GKM_DATA_UNRECOGNIZED;

	asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-8-EncryptedPrivateKeyInfo", data, n_data);
	if (!asn)
		goto done;

	ret = GKM_DATA_FAILURE;

	/* Figure out the type of encryption */
	scheme = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "encryptionAlgorithm", "algorithm", NULL));
	if (!scheme)
		goto done;

	params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "encryptionAlgorithm", "parameters", NULL), &n_params);
	if (!params)
		goto done;

	/*
	 * Parse the encryption stuff into a cipher.
	 */
	r = egg_symkey_read_cipher (scheme, password, n_password, params, n_params, &cih);
	if (r == GKM_DATA_UNRECOGNIZED) {
		ret = GKM_DATA_FAILURE;
		goto done;
	} else if (r != GKM_DATA_SUCCESS) {
		ret = r;
		goto done;
	}

	crypted = egg_asn1x_get_string_as_raw (egg_asn1x_node (asn, "encryptedData", NULL),
	                                       egg_secure_realloc, &n_crypted);
	if (!crypted)
		goto done;

	gcry = gcry_cipher_decrypt (cih, crypted, n_crypted, NULL, 0);
	gcry_cipher_close (cih);
	cih = NULL;

	if (gcry != 0) {
		g_warning ("couldn't decrypt pkcs8 data: %s", gcry_strerror (gcry));
		goto done;
	}

	/* Unpad the DER data */
	l = egg_asn1x_element_length (crypted, n_crypted);
	if (l <= 0 || l > n_crypted) {
		ret = GKM_DATA_LOCKED;
		goto done;
	}
	n_crypted = l;

	/* Try to parse the resulting key */
	ret = gkm_data_der_read_private_pkcs8_plain (crypted, n_crypted, s_key);
	egg_secure_free (crypted);
	crypted = NULL;

	/* If unrecognized we assume bad password */
	if (ret == GKM_DATA_UNRECOGNIZED)
		ret = GKM_DATA_LOCKED;

done:
	if (cih)
		gcry_cipher_close (cih);
	egg_asn1x_destroy (asn);
	egg_secure_free (crypted);

	return ret;
}
Exemple #21
0
static gcry_cipher_hd_t
prepare_and_encode_pkcs8_cipher (GNode *asn, const gchar *password,
                                 gsize n_password, gsize *n_block)
{
	GNode *asn1_params = NULL;
	gcry_cipher_hd_t cih;
	guchar salt[8];
	gcry_error_t gcry;
	guchar *key, *iv, *portion;
	gsize n_key, n_portion;
	int iterations;

	init_quarks ();

	/* Make sure the encryption algorithm works */
	g_return_val_if_fail (gcry_cipher_algo_info (OID_PKCS12_PBE_3DES_SHA1,
	                                             GCRYCTL_TEST_ALGO, NULL, 0), NULL);

	/* The encryption algorithm */
	if(!egg_asn1x_set_oid_as_quark (egg_asn1x_node (asn, "encryptionAlgorithm", "algorithm", NULL),
	                                OID_PKCS12_PBE_3DES_SHA1))
		g_return_val_if_reached (NULL);

	/* Randomize some input for the password based secret */
	iterations = 1000 + (int) (1000.0 * rand () / (RAND_MAX + 1.0));
	gcry_create_nonce (salt, sizeof (salt));

	/* Allocate space for the key and iv */
	n_key = gcry_cipher_get_algo_keylen (GCRY_CIPHER_3DES);
	*n_block = gcry_cipher_get_algo_blklen (GCRY_MD_SHA1);
	g_return_val_if_fail (n_key && *n_block, NULL);

	if (!egg_symkey_generate_pkcs12 (GCRY_CIPHER_3DES, GCRY_MD_SHA1,
	                                        password, n_password, salt,
	                                        sizeof (salt), iterations, &key, &iv))
		g_return_val_if_reached (NULL);

	/* Now write out the parameters */
	asn1_params = egg_asn1x_create (pkix_asn1_tab, "pkcs-12-PbeParams");
	g_return_val_if_fail (asn1_params, NULL);
	if (!egg_asn1x_set_string_as_raw (egg_asn1x_node (asn1_params, "salt", NULL), salt, sizeof (salt), NULL))
		g_return_val_if_reached (NULL);
	if (!egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn1_params, "iterations", NULL), iterations))
		g_return_val_if_reached (NULL);
	portion = egg_asn1x_encode (asn1_params, NULL, &n_portion);
	if (portion == NULL) {
		g_warning ("couldn't encode pkcs8 params key: %s", egg_asn1x_message (asn1_params));
		g_return_val_if_reached (NULL);
	}

	if (!egg_asn1x_set_raw_element (egg_asn1x_node (asn, "encryptionAlgorithm", "parameters", NULL),
	                                portion, n_portion, g_free))
		g_return_val_if_reached (NULL);

	/* Now make a cipher that matches what we wrote out */
	gcry = gcry_cipher_open (&cih, GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, 0);
	g_return_val_if_fail (gcry == 0, NULL);
	g_return_val_if_fail (cih, NULL);

	gcry_cipher_setiv (cih, iv, *n_block);
	gcry_cipher_setkey (cih, key, n_key);

	g_free (iv);
	egg_secure_free (key);
	egg_asn1x_destroy (asn1_params);

	return cih;
}
Exemple #22
0
static gboolean
gcr_secret_exchange_default_encrypt_transport_data (GcrSecretExchange *exchange,
                                                    GckAllocator allocator,
                                                    const guchar *plain_text,
                                                    gsize n_plain_text,
                                                    guchar **iv,
                                                    gsize *n_iv,
                                                    guchar **cipher_text,
                                                    gsize *n_cipher_text)
{
	GcrSecretExchangeDefault *data = exchange->pv->default_exchange;
	gcry_cipher_hd_t cih;
	gcry_error_t gcry;
	guchar *padded;
	gsize n_result;
	guchar *result;
	gsize pos;

	g_return_val_if_fail (data != NULL, FALSE);
	g_return_val_if_fail (data->key != NULL, FALSE);

	gcry = gcry_cipher_open (&cih, EXCHANGE_1_CIPHER_ALGO, EXCHANGE_1_CIPHER_MODE, 0);
	if (gcry != 0) {
		g_warning ("couldn't create aes cipher context: %s", gcry_strerror (gcry));
		g_free (iv);
		return FALSE;
	}

	*iv = (allocator) (NULL, EXCHANGE_1_IV_LENGTH);
	g_return_val_if_fail (*iv != NULL, FALSE);
	gcry_create_nonce (*iv, EXCHANGE_1_IV_LENGTH);
	*n_iv = EXCHANGE_1_IV_LENGTH;

	/* 16 = 128 bits */
	gcry = gcry_cipher_setkey (cih, data->key, EXCHANGE_1_KEY_LENGTH);
	g_return_val_if_fail (gcry == 0, FALSE);

	/* 16 = 128 bits */
	gcry = gcry_cipher_setiv (cih, *iv, EXCHANGE_1_IV_LENGTH);
	g_return_val_if_fail (gcry == 0, FALSE);

	/* Pad the text properly */
	if (!egg_padding_pkcs7_pad (egg_secure_realloc, 16, plain_text, n_plain_text,
	                            (gpointer*)&padded, &n_result))
		g_return_val_if_reached (FALSE);
	result = (allocator) (NULL, n_result);
	g_return_val_if_fail (result != NULL, FALSE);

	for (pos = 0; pos < n_result; pos += 16) {
		gcry = gcry_cipher_encrypt (cih, result + pos, 16, padded + pos, 16);
		g_return_val_if_fail (gcry == 0, FALSE);
	}

	gcry_cipher_close (cih);

	egg_secure_clear (padded, n_result);
	egg_secure_free (padded);

	*cipher_text = result;
	*n_cipher_text = n_result;
	return TRUE;
}
Exemple #23
0
static gboolean
response_open_session_aes (SecretSession *session,
                           GVariant *response)
{
	gconstpointer buffer;
	GVariant *argument;
	const gchar *sig;
	gsize n_buffer;
	gcry_mpi_t peer;
	gcry_error_t gcry;
	gpointer ikm;
	gsize n_ikm;

	sig = g_variant_get_type_string (response);
	g_return_val_if_fail (sig != NULL, FALSE);

	if (!g_str_equal (sig, "(vo)")) {
		g_warning ("invalid OpenSession() response from daemon with signature: %s", sig);
		return FALSE;
	}

	g_assert (session->path == NULL);
	g_variant_get (response, "(vo)", &argument, &session->path);

	buffer = g_variant_get_fixed_array (argument, &n_buffer, sizeof (guchar));
	gcry = gcry_mpi_scan (&peer, GCRYMPI_FMT_USG, buffer, n_buffer, NULL);
	g_return_val_if_fail (gcry == 0, FALSE);
	g_variant_unref (argument);

#if 0
	g_printerr (" lib publi: ");
	gcry_mpi_dump (session->publi);
	g_printerr ("\n  lib peer: ");
	gcry_mpi_dump (peer);
	g_printerr ("\n");
#endif

	ikm = egg_dh_gen_secret (peer, session->privat, session->prime, &n_ikm);
	gcry_mpi_release (peer);

#if 0
	g_printerr ("   lib ikm:  %s\n", egg_hex_encode (ikm, n_ikm));
#endif

	if (ikm == NULL) {
		g_warning ("couldn't negotiate a valid AES session key");
		g_free (session->path);
		session->path = NULL;
		return FALSE;
	}

	session->n_key = 16;
	session->key = egg_secure_alloc (session->n_key);
	if (!egg_hkdf_perform ("sha256", ikm, n_ikm, NULL, 0, NULL, 0,
	                       session->key, session->n_key))
		g_return_val_if_reached (FALSE);
	egg_secure_free (ikm);

	session->algorithms = ALGORITHMS_AES;
	return TRUE;
}
static gboolean
pem_parse_block (const gchar *data, gsize n_data, guchar **decoded, gsize *n_decoded,
                 GHashTable **headers)
{
	const gchar *x, *hbeg, *hend;
	const gchar *p, *end;
	gint state = 0;
	guint save = 0;
	
	g_assert (data);
	g_assert (n_data);
	
	g_assert (decoded);
	g_assert (n_decoded);
	
	p = data;
	end = p + n_data;
	
	hbeg = hend = NULL;
	
	/* Try and find a pair of blank lines with only white space between */
	while (hend == NULL) {
		x = memchr (p, '\n', end - p);
		if (!x)
			break;
		++x;
		while (isspace (*x)) {
			/* Found a second line, with only spaces between */
			if (*x == '\n') {
				hbeg = data;
				hend = x;
				break;
			/* Found a space between two lines */
			} else {
				++x;
			}
		}
		
		/* Try next line */
		p = x;
	}

	/* Headers found? */	
	if (hbeg && hend) {
		data = hend;
		n_data = end - data;
	}
	
	*n_decoded = (n_data * 3) / 4 + 1;
	if (egg_secure_check (data))
		*decoded = egg_secure_alloc (*n_decoded);
	else
		*decoded = g_malloc0 (*n_decoded);
	g_return_val_if_fail (*decoded, FALSE);
	
	*n_decoded = g_base64_decode_step (data, n_data, *decoded, &state, &save);
	if (!*n_decoded) {
		egg_secure_free (*decoded);
		return FALSE;
	}
	
	if (headers && hbeg && hend) 
		parse_header_lines (hbeg, hend, headers);
	
	return TRUE;
}
Exemple #25
0
static SecretValue *
service_decode_aes_secret (SecretSession *session,
                           gconstpointer param,
                           gsize n_param,
                           gconstpointer value,
                           gsize n_value,
                           const gchar *content_type)
{
	gcry_cipher_hd_t cih;
	gsize n_padded;
	gcry_error_t gcry;
	guchar *padded;
	gsize pos;

	if (n_param != 16) {
		g_message ("received an encrypted secret structure with invalid parameter");
		return NULL;
	}

	if (n_value == 0 || n_value % 16 != 0) {
		g_message ("received an encrypted secret structure with bad secret length");
		return NULL;
	}

	gcry = gcry_cipher_open (&cih, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0);
	if (gcry != 0) {
		g_warning ("couldn't create AES cipher: %s", gcry_strerror (gcry));
		return NULL;
	}

#if 0
	g_printerr ("    lib iv:  %s\n", egg_hex_encode (param, n_param));
#endif

	gcry = gcry_cipher_setiv (cih, param, n_param);
	g_return_val_if_fail (gcry == 0, NULL);

#if 0
	g_printerr ("   lib key:  %s\n", egg_hex_encode (session->key, session->n_key));
#endif

	gcry = gcry_cipher_setkey (cih, session->key, session->n_key);
	g_return_val_if_fail (gcry == 0, NULL);

	/* Copy the memory buffer */
	n_padded = n_value;
	padded = egg_secure_alloc (n_padded);
	memcpy (padded, value, n_padded);

	/* Perform the decryption */
	for (pos = 0; pos < n_padded; pos += 16) {
		gcry = gcry_cipher_decrypt (cih, (guchar*)padded + pos, 16, NULL, 0);
		g_return_val_if_fail (gcry == 0, FALSE);
	}

	gcry_cipher_close (cih);

	/* Unpad the resulting value */
	if (!pkcs7_unpad_bytes_in_place (padded, &n_padded)) {
		egg_secure_clear (padded, n_padded);
		egg_secure_free (padded);
		g_message ("received an invalid or unencryptable secret");
		return FALSE;
	}

	return secret_value_new_full ((gchar *)padded, n_padded, content_type, egg_secure_free);
}
gboolean
egg_openssl_encrypt_block (const gchar *dekinfo, const gchar *password, 
                                gssize n_password, const guchar *data, gsize n_data,
                                guchar **encrypted, gsize *n_encrypted)
{
	gsize n_overflow, n_batch, n_padding;
	gcry_cipher_hd_t ch;
	guchar *key = NULL;
	guchar *iv = NULL;
	guchar *padded = NULL;
	int gcry, ivlen;
	int algo = 0;
	int mode = 0;
	
	if (!parse_dekinfo (dekinfo, &algo, &mode, &iv))
		g_return_val_if_reached (FALSE);
		
	ivlen = gcry_cipher_get_algo_blklen (algo);

	/* We assume the iv is at least as long as at 8 byte salt */
	g_return_val_if_fail (ivlen >= 8, FALSE);
	
	/* IV is already set from the DEK info */
	if (!egg_symkey_generate_simple (algo, GCRY_MD_MD5, password, 
	                                        n_password, iv, 8, 1, &key, NULL))
		g_return_val_if_reached (FALSE);
	
	gcry = gcry_cipher_open (&ch, algo, mode, 0);
	g_return_val_if_fail (!gcry, FALSE);
		
	gcry = gcry_cipher_setkey (ch, key, gcry_cipher_get_algo_keylen (algo));
	g_return_val_if_fail (!gcry, FALSE);
	egg_secure_free (key);

	/* 16 = 128 bits */
	gcry = gcry_cipher_setiv (ch, iv, ivlen);
	g_return_val_if_fail (!gcry, FALSE);
	g_free (iv);
	
	/* Allocate output area */
	n_overflow = (n_data % ivlen);
	n_padding = n_overflow ? (ivlen - n_overflow) : 0;
	n_batch = n_data - n_overflow;
	*n_encrypted = n_data + n_padding;
	*encrypted = g_malloc0 (*n_encrypted);
	
	g_assert (*n_encrypted % ivlen == 0);
	g_assert (*n_encrypted >= n_data);
	g_assert (*n_encrypted == n_batch + n_overflow + n_padding);

	/* Encrypt everything but the last bit */
	gcry = gcry_cipher_encrypt (ch, *encrypted, n_batch, (void*)data, n_batch);
	if (gcry) {
		g_free (*encrypted);
		g_return_val_if_reached (FALSE);
	}
	
	/* Encrypt the padded block */
	if (n_overflow) {
		padded = egg_secure_alloc (ivlen);
		memset (padded, 0, ivlen);
		memcpy (padded, data + n_batch, n_overflow);
		gcry = gcry_cipher_encrypt (ch, *encrypted + n_batch, ivlen, padded, ivlen);
		egg_secure_free (padded);
		if (gcry) {
			g_free (*encrypted);
			g_return_val_if_reached (FALSE);
		}
	}

	gcry_cipher_close (ch);
	return TRUE;
}
CK_RV
gkm_aes_mechanism_unwrap (GkmSession *session, CK_MECHANISM_PTR mech,
                          GkmObject *wrapper, CK_VOID_PTR input, CK_ULONG n_input,
                          CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs,
                          GkmObject **unwrapped)
{
	gcry_cipher_hd_t cih;
	gcry_error_t gcry;
	CK_ATTRIBUTE attr;
	GArray *array;
	GkmAesKey *key;
	gpointer padded, value;
	gsize n_padded, n_value;
	GkmTransaction *transaction;
	gsize block, pos;
	gboolean ret;

	g_return_val_if_fail (GKM_IS_SESSION (session), CKR_GENERAL_ERROR);
	g_return_val_if_fail (mech, CKR_GENERAL_ERROR);
	g_return_val_if_fail (mech->mechanism == CKM_AES_CBC_PAD, CKR_GENERAL_ERROR);
	g_return_val_if_fail (GKM_IS_OBJECT (wrapper), CKR_GENERAL_ERROR);

	if (!GKM_IS_AES_KEY (wrapper))
		return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
	key = GKM_AES_KEY (wrapper);

	block = gkm_aes_key_get_block_size (key);
	g_return_val_if_fail (block != 0, CKR_GENERAL_ERROR);

	if (n_input == 0 || n_input % block != 0)
		return CKR_WRAPPED_KEY_LEN_RANGE;

	cih = gkm_aes_key_get_cipher (key, GCRY_CIPHER_MODE_CBC);
	if (cih == NULL)
		return CKR_FUNCTION_FAILED;

	if (!mech->pParameter || gcry_cipher_setiv (cih, mech->pParameter, mech->ulParameterLen) != 0) {
		gcry_cipher_close (cih);
		return CKR_MECHANISM_PARAM_INVALID;
	}

	padded = egg_secure_alloc (n_input);
	memcpy (padded, input, n_input);
	n_padded = n_input;

	/* In place decryption */
	for (pos = 0; pos < n_padded; pos += block) {
		gcry = gcry_cipher_decrypt (cih, (guchar*)padded + pos, block, NULL, 0);
		g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
	}

	gcry_cipher_close (cih);

	/* Unpad the resulting value */
	ret = egg_padding_pkcs7_unpad (egg_secure_realloc, block, padded, n_padded, &value, &n_value);
	egg_secure_free (padded);

	/* TODO: This is dubious, there doesn't seem to be an rv for 'bad decrypt' */
	if (ret == FALSE)
		return CKR_WRAPPED_KEY_INVALID;

	/* Now setup the attributes with our new value */
	array = g_array_new (FALSE, FALSE, sizeof (CK_ATTRIBUTE));

	/* Prepend the value */
	attr.type = CKA_VALUE;
	attr.pValue = value;
	attr.ulValueLen = n_value;
	g_array_append_val (array, attr);

	/* Add the remainder of the attributes */
	g_array_append_vals (array, attrs, n_attrs);

	transaction = gkm_transaction_new ();

	/* Now create an object with these attributes */
	*unwrapped = gkm_session_create_object_for_attributes (session, transaction,
	                                                       (CK_ATTRIBUTE_PTR)array->data, array->len);

	egg_secure_free (value);
	g_array_free (array, TRUE);

	return gkm_transaction_complete_and_unref (transaction);
}