Exemple #1
0
sencode* sencode_decode (const std::string& str)
{
	std::list<sencode*> stk;
	int pos = 0;
	int len = str.length();

	for (; pos < len; ++pos) {

		/* try to get a token */
		if (str[pos] == 's') {
			//push a new s-exp and don't allow closing it yet.
			stk.push_back (new sencode_list);
			continue;
		} else if (str[pos] == 'e') {
			//push nothing (so the TOS s-exp gets terminated)
		} else if (str[pos] == 'i') {
			//parse an integer (it's unsigned!)
			unsigned int res;
			parse_int (str, pos, len, res);
			if (pos < 0) break;
			stk.push_back (new sencode_int (res) );

		} else if ( (str[pos] >= '0') && (str[pos] <= '9') ) {
			//parse a bytestring
			std::string res;
			parse_string (str, pos, len, res);
			if (pos < 0) break;
			stk.push_back (new sencode_bytes (res) );
		}

		/* if there's nothing on the stack now, it's an error. */
		if (stk.empty() ) break;

		/* reduce stack. (return positively if it would
		 * get empty and there's nothing more to parse.) */
		if (stk.size() > 1) {
			std::list<sencode*>::iterator i = stk.end();
			--i;
			sencode*tos = *i;
			--i;
			sencode_list*se = dynamic_cast<sencode_list*> (*i);
			if (!se) break; //shouldn't happen, but keep eyes open!
			se->items.push_back (tos);
			stk.pop_back();
		} else if (pos + 1 == len) {
			return stk.front();
		}
	}

	/* error handling. Destroy the stack, return false. */

	for (std::list<sencode*>::iterator i = stk.begin(), e = stk.end();
	     i != e; ++i)
		sencode_destroy (*i);

	return NULL;
}
Exemple #2
0
int action_hash_verify (bool armor, const std::string&symmetric)
{
	// first, input the hashfile
	std::ifstream hf_in;
	hf_in.open (symmetric == "-" ? "/dev/stdin" : symmetric.c_str(),
	            std::ios::in | std::ios::binary);
	if (!hf_in) {
		err ("error: can't open hashfile");
		return 1;
	}

	std::string hf_data;
	if (!read_all_input (hf_data, hf_in)) {
		err ("error: can't read hashfile");
		return 1;
	}
	hf_in.close();

	if (armor) {
		std::vector<std::string> parts;
		std::string type;
		if (!envelope_read (hf_data, 0, type, parts)) {
			err ("error: no data envelope found");
			return 1;
		}

		if (type != ENVELOPE_HASHFILE || parts.size() != 1) {
			err ("error: wrong envelope format");
			return 1;
		}

		if (!base64_decode (parts[0], hf_data)) {
			err ("error: malformed data");
			return 1;
		}
	}

	sencode*H = sencode_decode (hf_data);
	if (!H) {
		err ("error: could not parse input sencode");
		return 1;
	}

	hashfile hf;
	if (!hf.unserialize (H)) {
		err ("error: could not parse input structure");
		return 1;
	}

	sencode_destroy (H);

	int ret = hf.verify (std::cin);
	if (ret) err ("error: hashfile verification failed");

	return ret;
}
Exemple #3
0
int action_sym_decrypt (const std::string&symmetric, bool armor)
{
	std::ifstream sk_in;
	sk_in.open (symmetric == "-" ? "/dev/stdin" : symmetric.c_str(),
	            std::ios::in | std::ios::binary);

	if (!sk_in) {
		err ("error: can't open symkey file");
		return 1;
	}

	std::string sk_data;
	if (!read_all_input (sk_data, sk_in)) {
		err ("error: can't read symkey");
		return 1;
	}
	sk_in.close();

	if (armor) {
		std::vector<std::string> parts;
		std::string type;
		if (!envelope_read (sk_data, 0, type, parts)) {
			err ("error: no data envelope found");
			return 1;
		}

		if (type != ENVELOPE_SYMKEY || parts.size() != 1) {
			err ("error: wrong envelope format");
			return 1;
		}

		if (!base64_decode (parts[0], sk_data)) {
			err ("error: malformed data");
			return 1;
		}
	}

	sencode*SK = sencode_decode (sk_data);
	if (!SK) {
		err ("error: could not parse input sencode");
		return 1;
	}

	symkey sk;
	if (!sk.unserialize (SK)) {
		err ("error: could not parse input structure");
		return 1;
	}

	sencode_destroy (SK);

	int ret = sk.decrypt (std::cin, std::cout);

	if (ret) err ("error: decryption failed");
	return ret;
}
Exemple #4
0
void sencode_list::destroy()
{
	for (std::vector<sencode*>::iterator
	     i = items.begin(),
	     e = items.end();
	     i != e; ++i)
		sencode_destroy (*i);

	items.clear();
}
Exemple #5
0
int action_export (bool armor,
                   const std::string & filter, const std::string & name,
                   keyring & KR)
{
	PREPARE_KEYRING;

	keyring::pubkey_storage s;

	for (keyring::keypair_storage::iterator
	     i = KR.pairs.begin(), e = KR.pairs.end();
	     i != e; ++i) {
		if (keyspec_matches (filter, i->second.pub.name, i->first)) {
			s[i->first] = i->second.pub;
			if (name.length())
				s[i->first].name = name;
		}
	}

	for (keyring::pubkey_storage::iterator
	     i = KR.pubs.begin(), e = KR.pubs.end();
	     i != e; ++i) {
		if (keyspec_matches (filter, i->second.name, i->first)) {
			s[i->first] = i->second;
			if (name.length())
				s[i->first].name = name;
		}
	}

	if (!s.size()) {
		err ("error: no such public keys");
		return 1;
	}

	sencode*S = keyring::serialize_pubkeys (s);
	if (!S) return 1;
	std::string data = S->encode();
	sencode_destroy (S);

	if (armor) {
		std::vector<std::string> parts;
		parts.resize (1);
		base64_encode (data, parts[0]);
		ccr_rng r;
		r.seed (128);
		data = envelope_format (ENVELOPE_PUBKEYS, parts, r);
	}

	out_bin (data);

	return 0;
}
Exemple #6
0
int action_export_sec (bool armor, bool yes,
                       const std::string & filter, const std::string & name,
                       keyring & KR)
{
	PREPARE_KEYRING;

	keyring::keypair_storage s;
	for (keyring::keypair_storage::iterator
	     i = KR.pairs.begin(), e = KR.pairs.end();
	     i != e; ++i) {
		if (keyspec_matches (filter, i->second.pub.name, i->first)) {
			s[i->first] = i->second;
			if (name.length())
				s[i->first].pub.name = name;
		}
	}

	if (!s.size()) {
		err ("error: no such secret");
		return 1;
	}

	if (!yes) {
		bool okay = false;
		ask_for_yes (okay, "This will export " << s.size()
		             << " secret keys! Continue?");
		if (!okay) return 0;
	}

	sencode*S = keyring::serialize_keypairs (s);
	if (!S) return 1; //weird.
	std::string data = S->encode();
	sencode_destroy (S);

	if (armor) {
		std::vector<std::string> parts;
		parts.resize (1);
		base64_encode (data, parts[0]);
		ccr_rng r;
		r.seed (128);
		data = envelope_format (ENVELOPE_SECRETS, parts, r);
	}

	out_bin (data);

	return 0;
}
Exemple #7
0
int action_gen_symkey (const std::string&algspec,
                       const std::string&symmetric, bool armor)
{
	symkey sk;
	ccr_rng r;
	r.seed (256);

	if (!sk.create (algspec, r)) {
		err ("error: symkey creation failed");
		return 1;
	}

	sencode*SK = sk.serialize();
	std::string data = SK->encode();
	sencode_destroy (SK);

	std::ofstream sk_out;
	sk_out.open (symmetric == "-" ? "/dev/stdout" : symmetric.c_str(),
	             std::ios::out | std::ios::binary);
	if (!sk_out) {
		err ("error: can't open symkey file for writing");
		return 1;
	}

	if (armor) {
		std::vector<std::string> parts;
		parts.resize (1);
		base64_encode (data, parts[0]);
		data = envelope_format (ENVELOPE_SYMKEY, parts, r);
	}

	sk_out << data;
	if (!sk_out.good()) {
		err ("error: can't write to symkey file");
		return 1;
	}

	sk_out.close();
	if (!sk_out.good()) {
		err ("error: couldn't close symkey file");
		return 1;
	}

	return 0;
}
Exemple #8
0
int action_hash_sign (bool armor, const std::string&symmetric)
{
	hashfile hf;
	if (!hf.create (std::cin)) {
		err ("error: hashing failed");
		return 1;
	}

	sencode*H = hf.serialize();
	std::string data = H->encode();
	sencode_destroy (H);

	std::ofstream hf_out;
	hf_out.open (symmetric == "-" ? "/dev/stdout" : symmetric.c_str(),
	             std::ios::out | std::ios::binary);
	if (!hf_out) {
		err ("error: can't open hashfile for writing");
		return 1;
	}

	if (armor) {
		std::vector<std::string> parts;
		parts.resize (1);
		base64_encode (data, parts[0]);
		ccr_rng r;
		r.seed (128);
		data = envelope_format (ENVELOPE_HASHFILE, parts, r);
	}

	hf_out << data;
	if (!hf_out.good()) {
		err ("error: can't write to hashfile");
		return 1;
	}

	hf_out.close();
	if (!hf_out.good()) {
		err ("error: couldn't close hashfile");
		return 1;
	}

	return 0;
}
Exemple #9
0
int action_verify (bool armor, const std::string&detach,
                   bool clearsign, bool yes, const std::string&symmetric,
                   keyring&KR, algorithm_suite&AS)
{
	//symmetric processing has its own function
	if (symmetric.length())
		return action_hash_verify (armor, symmetric);

	/*
	 * check flags validity, open detach if possible
	 */
	if (clearsign && (detach.length() || armor)) {
		err ("error: clearsign cannot be combined "
		     "with armor or detach-sign");
		return 1;
	}

	std::ifstream detf;
	if (detach.length()) {
		detf.open (detach == "-" ? "/dev/stdin" : detach.c_str(),
		           std::ios::in | std::ios::binary);
		if (!detf) {
			err ("error: can't open detached signature file");
			return 1;
		}
	}

	/*
	 * read input and unpack the whole thing into message.
	 * Takes a lot of effort. :)
	 */

	signed_msg msg;
	std::string data;

	read_all_input (data);

	if (clearsign) {
		std::string type;
		std::vector<std::string> parts;

		if (!envelope_read (data, 0, type, parts)) {
			err ("error: no data envelope found");
			return 1;
		}

		if (type != ENVELOPE_CLEARSIGN || parts.size() != 2) {
			err ("error: wrong envelope format");
			return 1;
		}

		std::string sig;
		if (!base64_decode (parts[1], sig)) {
			err ("error: malformed data");
			return 1;
		}

		sencode*M = sencode_decode (sig);
		if (!M) {
			err ("error: could not parse input sencode");
			return 1;
		}

		if (!msg.unserialize (M)) {
			err ("error: could not parse input structure");
			sencode_destroy (M);
			return 1;
		}

		sencode_destroy (M);

		std::string tmp;
		if (!msg.message.to_string_check (tmp)
		    || tmp != MSG_CLEARTEXT) {
			err ("error: malformed cleartext signature");
			return 1;
		}

		msg.message.from_string (parts[0]);

	} else if (detach.length()) {

		std::string sig;
		if (!read_all_input (sig, detf)) {
			err ("error: can't read detached signature file");
			return 1;
		}

		detf.close();

		if (armor) {
			std::vector<std::string> parts;
			std::string type;
			if (!envelope_read (sig, 0, type, parts)) {
				err ("error: no data envelope found");
				return 1;
			}

			if (type != ENVELOPE_DETACHSIGN || parts.size() != 1) {
				err ("error: wrong envelope format");
				return 1;
			}

			if (!base64_decode (parts[0], sig)) {
				err ("error: malformed data");
				return 1;
			}
		}

		sencode*M = sencode_decode (sig);
		if (!M) {
			err ("error: could not parse input sencode");
			return 1;
		}

		if (!msg.unserialize (M)) {
			err ("error: could not parse input structure");
			sencode_destroy (M);
			return 1;
		}

		sencode_destroy (M);

		std::string tmp;
		if (!msg.message.to_string_check (tmp)
		    || tmp != MSG_DETACHED) {
			err ("error: malformed detached signature");
			return 1;
		}

		msg.message.from_string (data);

	} else {
		//classical sig
		if (armor) {
			std::string type;
			std::vector<std::string> parts;

			if (!envelope_read (data, 0, type, parts)) {
				err ("error: no data envelope found");
				return 1;
			}

			if (type != ENVELOPE_SIG || parts.size() != 1) {
				err ("error: wrong envelope format");
				return 1;
			}

			if (!base64_decode (parts[0], data)) {
				err ("error: malformed data");
				return 1;
			}
		}

		sencode*M = sencode_decode (data);
		if (!M) {
			err ("error: could not parse input sencode");
			if (!armor && envelope_lookalike (data))
				err ("notice: input looks ascii-armored, "
				     "try using the armor option");
			return 1;
		}

		if (!msg.unserialize (M)) {
			err ("error: could not parse input structure");
			sencode_destroy (M);
			return 1;
		}

		sencode_destroy (M);
	}

	//check that the message can be converted to bytes
	if (msg.message.size() & 0x7) {
		err ("error: bad message size");
		return 1;
	}

	PREPARE_KEYRING;

	//check pubkey availability
	keyring::pubkey_entry*pke;
	pke = KR.get_pubkey (msg.key_id);
	if (!pke) {
		err ("error: verification pubkey unavailable");
		err ("info: requires key @" << msg.key_id);
		if (!yes) {
			err ("notice: not displaying unverified message");
			err ("info: to see it, use yes option");
		} else {
			err ("warning: following message is UNVERIFIED");
			msg.message.to_string (data);
			out_bin (data);
		}
		return 2; //missing key flag
	}

	if ( (!AS.count (msg.alg_id))
	     || (!AS[msg.alg_id]->provides_signatures())) {
		err ("error: verification algorithm unsupported");
		err ("info: requires algorithm " << escape_output (msg.alg_id)
		     << " with signature support");
		return 1;
	}

	//do the verification
	int r = msg.verify (AS, KR);

	err ("incoming signed message details:");
	err ("  algorithm: " << escape_output (msg.alg_id));
	err ("  signed by: @" << msg.key_id);
	err ("  signed local name: `" << escape_output (pke->name) << "'");
	err ("  verification status: "
	     << (r == 0 ?
	         "GOOD signature ;-)" :
	         "BAD signature :-("));

	if (r) {
		if (!yes) {
			err ("notice: not displaying unverified message");
			err ("info: to see it, use yes option");
		} else {
			err ("warning: following message is UNVERIFIED");
		}
	}

	if (yes || !r) {
		msg.message.to_string (data);
		out_bin (data);
	}

	if (r) return 3; //verification failed flag
	else return 0;
}
Exemple #10
0
int action_sign (const std::string&user, bool armor, const std::string&detach,
                 bool clearsign, const std::string&symmetric,
                 keyring&KR, algorithm_suite&AS)
{
	//symmetric processing has its own function
	if (symmetric.length())
		return action_hash_sign (armor, symmetric);

	/*
	 * check detach/armor/clearsign validity first.
	 * Allowed combinations are:
	 *  - nothing
	 *  - armor
	 *  - detach
	 *  - armor+detach
	 *  - clearsign (which is always armored)
	 */

	if (clearsign && (detach.length() || armor)) {
		err ("error: clearsign cannot be combined "
		     "with armor or detach-sign");
		return 1;
	}

	std::ofstream detf;
	if (detach.length()) {
		detf.open (detach == "-" ? "/dev/stdout" : detach.c_str(),
		           std::ios::out | std::ios::binary);
		if (!detf) {
			err ("error: can't open detached signature file");
			return 1;
		}
	}

	//eat data for signature
	std::string data;
	read_all_input (data);

	PREPARE_KEYRING;

	//some common checks on user key
	keyring::keypair_entry *u = NULL;

	for (keyring::keypair_storage::iterator
	     i = KR.pairs.begin(), e = KR.pairs.end(); i != e; ++i) {
		if (keyspec_matches (user, i->second.pub.name, i->first)) {
			/*
			 * also match having signature alg availability,
			 * because it saves time when you only have one locally
			 * available signature privkey. Also, no need to check
			 * it again later.
			 */
			if (!AS.count (i->second.pub.alg)) continue;
			if (!AS[i->second.pub.alg]->provides_signatures())
				continue;

			if (u) {
				err ("error: ambiguous local user specified");
				return 1;
			} else u = & (i->second);
		}
	}

	if (!u) {
		err ("error: no such supported local privkey");
		return 1;
	}

	//signature production part
	signed_msg msg;
	ccr_rng r;
	r.seed (256);

	bvector message;
	message.from_string (data);

	if (msg.sign (message, u->pub.alg, u->pub.keyid, AS, KR, r)) {
		err ("error: digital signature failed");
		return 1;
	}

	//now deal with all the output possibilities

	if (clearsign) {
		std::vector<std::string> parts;
		parts.resize (2);

		msg.message.to_string (parts[0]);
		msg.message.from_string (MSG_CLEARTEXT);

		sencode*M = msg.serialize();
		base64_encode (M->encode(), parts[1]);
		sencode_destroy (M);

		out_bin (envelope_format (ENVELOPE_CLEARSIGN, parts, r));

	} else if (detach.length()) {
		msg.message.from_string (MSG_DETACHED);
		sencode*M = msg.serialize();
		data = M->encode();
		sencode_destroy (M);

		if (armor) {
			std::vector<std::string> parts;
			parts.resize (1);
			base64_encode (data, parts[0]);
			data = envelope_format (ENVELOPE_DETACHSIGN, parts, r);
		}

		detf << data;
		if (!detf.good()) {
			err ("error: could not write detached signature file");
			return 1;
		}
		detf.close();
		if (!detf.good()) {
			err ("error: could not close detached signature file");
			return 1;
		}

	} else {
		sencode*M = msg.serialize();
		data = M->encode();
		sencode_destroy (M);

		if (armor) {
			std::vector<std::string> parts;
			parts.resize (1);
			base64_encode (data, parts[0]);
			data = envelope_format (ENVELOPE_SIG, parts, r);
		}

		out_bin (data);
	}

	return 0;
}
Exemple #11
0
int action_decrypt (bool armor, const std::string&symmetric,
                    keyring&KR, algorithm_suite&AS)
{
	if (symmetric.length())
		return action_sym_decrypt (symmetric, armor);

	std::string data;
	read_all_input (data);

	if (armor) {
		std::string type;
		std::vector<std::string> parts;
		if (!envelope_read (data, 0, type, parts)) {
			err ("error: no data envelope found");
			return 1;
		}

		if (type != ENVELOPE_ENC || parts.size() != 1) {
			err ("error: wrong envelope format");
			return 1;
		}
		if (!base64_decode (parts[0], data)) {
			err ("error: malformed data");
			return 1;
		}
	}

	sencode*M = sencode_decode (data);
	if (!M) {
		err ("error: could not parse input sencode");
		if (!armor && envelope_lookalike (data))
			err ("notice: input looks ascii-armored, "
			     "try using the armor option");
		return 1;
	}

	encrypted_msg msg;
	if (!msg.unserialize (M)) {
		err ("error: could not parse input structure");
		sencode_destroy (M);
		return 1;
	}

	sencode_destroy (M);

	PREPARE_KEYRING;

	//check if we have the privkey
	keyring::keypair_entry*kpe;
	kpe = KR.get_keypair (msg.key_id);
	if (!kpe) {
		err ("error: decryption privkey unavailable");
		err ("info: requires key @" << msg.key_id);
		return 2; //missing key flag
	}

	//and the algorithm
	if ( (!AS.count (msg.alg_id))
	     || (!AS[msg.alg_id]->provides_encryption())) {
		err ("error: decryption algorithm unsupported");
		err ("info: requires algorithm " << escape_output (msg.alg_id)
		     << " with encryption support");
		return 1;
	}


	//actual decryption
	bvector plaintext;
	if (msg.decrypt (plaintext, AS, KR)) {
		err ("error: decryption failed");
		return 1;
	}

	if (!plaintext.to_string_check (data)) {
		err ("error: malformed data");
		return 1;
	}

	//SEEMS OKAY, let's print some info.
	err ("incoming encrypted message details:");
	err ("  algorithm: " << escape_output (msg.alg_id));
	err ("  recipient: @" << msg.key_id);
	err ("  recipient local name: `" <<
	     escape_output (kpe->pub.name) << "'");

	/*
	 * because there's no possibility to distinguish encrypted from
	 * sign+encrypted messages, just try to parse a message out of this,
	 * and if it comes out, give user a hint.
	 */
	M = sencode_decode (data);
	if (M) {
		signed_msg m;
		if (m.unserialize (M)) {
			err ("notice: message content looks signed");
			err ("hint: try also decrypt+verify operation");
		}
		sencode_destroy (M);
	}

	//finally pump the decrypted stuff to stdout
	out_bin (data);

	return 0;
}
Exemple #12
0
int action_encrypt (const std::string&recipient, bool armor,
                    const std::string&symmetric,
                    keyring&KR, algorithm_suite&AS)
{
	if (symmetric.length())
		return action_sym_encrypt (symmetric, armor);

	//first, read plaintext
	std::string data;
	read_all_input (data);

	//find a recipient
	keyring::pubkey_entry *recip = NULL;

	PREPARE_KEYRING;

	//search both publickeys and keypairs that are valid for encryption
	for (keyring::pubkey_storage::iterator
	     i = KR.pubs.begin(), e = KR.pubs.end(); i != e; ++i) {
		if (keyspec_matches (recipient, i->second.name, i->first)) {
			if (!AS.count (i->second.alg)) continue;
			if (!AS[i->second.alg]->provides_encryption())
				continue;

			if (recip) {
				err ("error: ambiguous recipient specified");
				return 1;
			} else recip = & (i->second);
		}
	}

	for (keyring::keypair_storage::iterator
	     i = KR.pairs.begin(), e = KR.pairs.end(); i != e; ++i) {
		if (keyspec_matches (recipient, i->second.pub.name, i->first)) {
			if (!AS.count (i->second.pub.alg)) continue;
			if (!AS[i->second.pub.alg]->provides_encryption())
				continue;

			if (recip) {
				err ("error: ambiguous recipient specified");
				return 1;
			} else recip = & (i->second.pub);
		}
	}

	if (!recip) {
		err ("error: no such recipient with suitable pubkey");
		return 1;
	}

	//encryption part
	encrypted_msg msg;
	ccr_rng r;
	r.seed (256);

	bvector plaintext;
	plaintext.from_string (data);

	if (msg.encrypt (plaintext, recip->alg, recip->keyid, AS, KR, r)) {
		err ("error: encryption failed");
		return 1;
	}

	sencode*M = msg.serialize();
	data = M->encode();
	sencode_destroy (M);

	if (armor) {
		std::vector<std::string> parts;
		parts.resize (1);
		base64_encode (data, parts[0]);
		data = envelope_format (ENVELOPE_ENC, parts, r);
	}

	out_bin (data);
	return 0;
}
Exemple #13
0
int action_import_sec (bool armor, bool no_action, bool yes, bool fp,
                       const std::string & filter, const std::string & name,
                       keyring & KR)
{
	std::string data;
	read_all_input (data);

	if (armor) {
		std::string type;
		std::vector<std::string> parts;
		if (!envelope_read (data, 0, type, parts)) {
			err ("error: no data envelope found");
			return 1;
		}

		if (type != ENVELOPE_SECRETS || parts.size() != 1) {
			err ("error: wrong envelope format");
			return 1;
		}

		if (!base64_decode (parts[0], data)) {
			err ("error: malformed data");
			return 1;
		}
	}

	sencode*S = sencode_decode (data);
	if (!S) {
		err ("error: could not parse input sencode");
		if (!armor && envelope_lookalike (data))
			err ("notice: input looks ascii-armored, "
			     "try using the armor option");
		return 1;
	}

	keyring::keypair_storage s;
	if (!keyring::parse_keypairs (S, s)) {
		err ("error: could not parse input structure");
		sencode_destroy (S);
		return 1;
	}
	sencode_destroy (S);

	if (!s.size()) {
		err ("notice: keyring was empty");
		return 0;
	}

	if (no_action) {
		for (keyring::keypair_storage::iterator
		     i = s.begin(), e = s.end(); i != e; ++i) {
			if (keyspec_matches (filter, i->second.pub.name,
			                     i->first))
				output_key (fp,
				            "keypair", "key pair",
				            i->second.pub.alg, i->first,
				            i->second.pub.name);
		}
		return 0;
	}

	PREPARE_KEYRING;

	int rewrites = 0;
	for (keyring::keypair_storage::iterator
	     i = s.begin(), e = s.end(); i != e; ++i) {
		if (keyspec_matches (filter, i->second.pub.name, i->first)
		    && (KR.pubs.count (i->first)
		        || KR.pairs.count (i->first)))
			++rewrites;
	}

	if (rewrites && !yes) {
		err ("error: this would overwrite "
		     << rewrites << " of your keys. "
		     "Use Yes option to confirm.");
		return 1;
	}

	//merge into KR. Also prevent keyID collisions
	for (keyring::keypair_storage::iterator
	     i = s.begin(), e = s.end(); i != e; ++i) {
		if (keyspec_matches (filter, i->second.pub.name, i->first)) {
			KR.remove_pubkey (i->first);
			KR.remove_keypair (i->first);
			KR.store_keypair (i->first,
			                  name.length() ?
			                  name : i->second.pub.name,
			                  i->second.pub.alg,
			                  i->second.pub.key, i->second.privkey);
		}
	}

	if (!KR.save()) {
		err ("error: couldn't save keyring");
		return 1;
	}

	return 0;
}
Exemple #14
0
int action_decrypt_verify (bool armor, bool yes,
                           keyring&KR, algorithm_suite&AS)
{
	std::string data;
	read_all_input (data);

	if (armor) {
		std::string type;
		std::vector<std::string> parts;
		if (!envelope_read (data, 0, type, parts)) {
			err ("error: no data envelope found");
			return 1;
		}

		if (type != ENVELOPE_ENC || parts.size() != 1) {
			err ("error: wrong envelope format");
			return 1;
		}
		if (!base64_decode (parts[0], data)) {
			err ("error: malformed data");
			return 1;
		}
	}

	sencode*M = sencode_decode (data);
	if (!M) {
		err ("error: could not parse input sencode");
		if (!armor && envelope_lookalike (data))
			err ("notice: input looks ascii-armored, "
			     "try using the armor option");
		return 1;
	}

	encrypted_msg emsg;
	if (!emsg.unserialize (M)) {
		err ("error: could not parse input structure");
		sencode_destroy (M);
		return 1;
	}

	sencode_destroy (M);

	PREPARE_KEYRING;

	//check if we will be able to decrypt
	keyring::keypair_entry*kpe;
	kpe = KR.get_keypair (emsg.key_id);
	if (!kpe) {
		err ("error: decryption privkey unavailable");
		err ("info: requires key @" << emsg.key_id);
		return 2; //missing key flag
	}

	if ( (!AS.count (emsg.alg_id))
	     || (!AS[emsg.alg_id]->provides_encryption())) {
		err ("error: decryption algorithm unsupported");
		err ("info: requires algorithm " << escape_output (emsg.alg_id)
		     << " with encryption support");
		return 1;
	}

	bvector bv;
	if (emsg.decrypt (bv, AS, KR)) {
		err ("error: decryption failed");
		return 1;
	}

	if (!bv.to_string_check (data)) {
		err ("error: malformed data");
		return 1;
	}

	//looks okay, print decryption status
	err ("incoming encrypted message details:");
	err ("  algorithm: " << escape_output (emsg.alg_id));
	err ("  recipient: @" << emsg.key_id);
	err ("  recipient local name: `" <<
	     escape_output (kpe->pub.name) << "'");

	//continue with verification
	M = sencode_decode (data);
	if (!M) {
		err ("error: could not parse input sencode");
		return 1;
	}

	signed_msg smsg;
	if (!smsg.unserialize (M)) {
		err ("error: could not parse input structure");
		sencode_destroy (M);
		return 1;
	}

	sencode_destroy (M);

	if (smsg.message.size() & 0x7) {
		err ("error: bad message size");
		return 1;
	}

	keyring::pubkey_entry*pke;
	pke = KR.get_pubkey (smsg.key_id);
	if (!pke) {
		err ("error: verification pubkey unavailable");
		err ("info: requires key @" << smsg.key_id);
		if (!yes) {
			err ("notice: not displaying unverified message");
			err ("info: to see it, use yes option");
		} else {
			err ("warning: following message is UNVERIFIED");
			smsg.message.to_string (data);
			out_bin (data);
		}
		return 2; //missing key flag
	}

	if ( (!AS.count (smsg.alg_id))
	     || (!AS[smsg.alg_id]->provides_signatures())) {
		err ("error: verification algorithm unsupported");
		err ("info: requires algorithm " << escape_output (smsg.alg_id)
		     << " with signature support");
		return 1;
	}

	//do the verification
	int r = smsg.verify (AS, KR);

	err ("incoming signed message details:");
	err ("  algorithm: " << escape_output (smsg.alg_id));
	err ("  signed by: @" << smsg.key_id);
	err ("  signed local name: `" << escape_output (pke->name) << "'");
	err ("  verification status: "
	     << (r == 0 ?
	         "GOOD signature ;-)" :
	         "BAD signature :-("));

	if (r) {
		if (!yes) {
			err ("notice: not displaying unverified message");
			err ("info: to see it, use the `yes' option");
		} else {
			err ("warning: following message is UNVERIFIED");
		}
	}

	if (yes || !r) {
		smsg.message.to_string (data);
		out_bin (data);
	}

	if (r) return 3; //verification failed flag
	else return 0;
}
Exemple #15
0
int action_sign_encrypt (const std::string&user, const std::string&recipient,
                         bool armor, keyring&KR, algorithm_suite&AS)
{
	/*
	 * Signed+encrypted messages must not have a separate envelope header
	 * (it would leak the information that inner message is signed).
	 */

	//eat al input first
	std::string data;
	read_all_input (data);

	PREPARE_KEYRING;

	//find some good local user
	keyring::keypair_entry *u = NULL;

	for (keyring::keypair_storage::iterator
	     i = KR.pairs.begin(), e = KR.pairs.end(); i != e; ++i) {
		if (keyspec_matches (user, i->second.pub.name, i->first)) {
			if (!AS.count (i->second.pub.alg)) continue;
			if (!AS[i->second.pub.alg]->provides_signatures())
				continue;

			if (u) {
				err ("error: ambiguous local user specified");
				return 1;
			} else u = & (i->second);
		}
	}

	if (!u) {
		err ("error: no such supported local privkey");
		return 1;
	}

	//find a recipient (don't waste a signature if it'd fail anyway)
	keyring::pubkey_entry *recip = NULL;

	for (keyring::pubkey_storage::iterator
	     i = KR.pubs.begin(), e = KR.pubs.end(); i != e; ++i) {
		if (keyspec_matches (recipient, i->second.name, i->first)) {
			if (!AS.count (i->second.alg)) continue;
			if (!AS[i->second.alg]->provides_encryption())
				continue;

			if (recip) {
				err ("error: ambiguous recipient specified");
				return 1;
			} else recip = & (i->second);
		}
	}

	for (keyring::keypair_storage::iterator
	     i = KR.pairs.begin(), e = KR.pairs.end(); i != e; ++i) {
		if (keyspec_matches (recipient, i->second.pub.name, i->first)) {
			if (!AS.count (i->second.pub.alg)) continue;
			if (!AS[i->second.pub.alg]->provides_encryption())
				continue;

			if (recip) {
				err ("error: ambiguous recipient specified");
				return 1;
			} else recip = & (i->second.pub);
		}
	}

	if (!recip) {
		err ("error: no such recipient with suitable pubkey");
		return 1;
	}

	//make a signature
	signed_msg smsg;
	ccr_rng r;
	r.seed (256);

	bvector bv;
	bv.from_string (data);

	if (smsg.sign (bv, u->pub.alg, u->pub.keyid, AS, KR, r)) {
		err ("error: digital signature failed");
		return 1;
	}

	sencode*M = smsg.serialize();
	data = M->encode();
	sencode_destroy (M);

	//encrypt it
	encrypted_msg emsg;
	bv.from_string (data);
	if (emsg.encrypt (bv, recip->alg, recip->keyid, AS, KR, r)) {
		err ("error: encryption failed");
		return 1;
	}

	M = emsg.serialize();
	data = M->encode();
	sencode_destroy (M);

	if (armor) {
		std::vector<std::string> parts;
		parts.resize (1);
		base64_encode (data, parts[0]);
		data = envelope_format (ENVELOPE_ENC, parts, r);
	}

	out_bin (data);
	return 0;
}