Esempio n. 1
0
static int 
dsa_sign(pgp_hash_t *hash,
	 const pgp_dsa_pubkey_t *dsa,
	 const pgp_dsa_seckey_t *sdsa,
	 pgp_output_t *output)
{
	unsigned        hashsize;
	unsigned        t;
	uint8_t		hashbuf[NETPGP_BUFSIZ];
	DSA_SIG        *dsasig;

	/* hashsize must be "equal in size to the number of bits of q,  */
	/* the group generated by the DSA key's generator value */
	/* 160/8 = 20 */

	hashsize = 20;

	/* finalise hash */
	t = hash->finish(hash, &hashbuf[0]);
	if (t != 20) {
		(void) fprintf(stderr, "dsa_sign: hashfinish not 20\n");
		return 0;
	}

	pgp_write(output, &hashbuf[0], 2);

	/* write signature to buf */
	dsasig = pgp_dsa_sign(hashbuf, hashsize, sdsa, dsa);

	/* convert and write the sig out to memory */
	pgp_write_mpi(output, dsasig->r);
	pgp_write_mpi(output, dsasig->s);
	DSA_SIG_free(dsasig);
	return 1;
}
Esempio n. 2
0
/**
\ingroup Core_WritePackets
\brief Write Symmetrically Encrypted packet
\param data Data to encrypt
\param len Length of data
\param output Write settings
\return 1 if OK; else 0
\note Hard-coded to use AES256
*/
unsigned 
pgp_write_symm_enc_data(const uint8_t *data,
				       const int len,
				       pgp_output_t * output)
{
	pgp_crypt_t	crypt_info;
	uint8_t		*encrypted = (uint8_t *) NULL;
	size_t		encrypted_sz;
	int             done = 0;

	/* \todo assume AES256 for now */
	pgp_crypt_any(&crypt_info, PGP_SA_AES_256);
	pgp_encrypt_init(&crypt_info);

	encrypted_sz = (size_t)(len + crypt_info.blocksize + 2);
	if ((encrypted = calloc(1, encrypted_sz)) == NULL) {
		(void) fprintf(stderr, "can't allocate %" PRIsize "d\n",
			encrypted_sz);
		return 0;
	}

	done = (int)pgp_encrypt_se(&crypt_info, encrypted, data, (unsigned)len);
	if (done != len) {
		(void) fprintf(stderr,
			"pgp_write_symm_enc_data: done != len\n");
		return 0;
	}

	return pgp_write_ptag(output, PGP_PTAG_CT_SE_DATA) &&
		pgp_write_length(output, (unsigned)(1 + encrypted_sz)) &&
		pgp_write(output, data, (unsigned)len);
}
Esempio n. 3
0
/**
 * \ingroup Core_WritePackets
 * \brief Writes a User Id packet
 * \param id
 * \param output
 * \return 1 if OK, otherwise 0
 */
unsigned 
pgp_write_struct_userid(pgp_output_t *output, const uint8_t *id)
{
	return pgp_write_ptag(output, PGP_PTAG_CT_USER_ID) &&
		pgp_write_length(output, (unsigned)strlen((const char *) id)) &&
		pgp_write(output, id, (unsigned)strlen((const char *) id));
}
Esempio n. 4
0
unsigned 
pgp_write_mdc(pgp_output_t *output, const uint8_t *hashed)
{
	/* write it out */
	return pgp_write_ptag(output, PGP_PTAG_CT_MDC) &&
		pgp_write_length(output, PGP_SHA1_HASH_SIZE) &&
		pgp_write(output, hashed, PGP_SHA1_HASH_SIZE);
}
Esempio n. 5
0
unsigned 
pgp_add_issuer_keyid(pgp_create_sig_t *sig,
				const uint8_t keyid[PGP_KEY_ID_SIZE])
{
	return pgp_write_ss_header(sig->output, PGP_KEY_ID_SIZE + 1,
				PGP_PTAG_SS_ISSUER_KEY_ID) &&
		pgp_write(sig->output, keyid, PGP_KEY_ID_SIZE);
}
Esempio n. 6
0
/**
\ingroup Core_WritePackets
\brief Writes Public Key Session Key packet
\param info Write settings
\param pksk Public Key Session Key to write out
\return 1 if OK; else 0
*/
unsigned 
pgp_write_pk_sesskey(pgp_output_t *output, pgp_pk_sesskey_t *pksk)
{
	/* XXX - Flexelint - Pointer parameter 'pksk' (line 1076) could be declared as pointing to const */
	if (pksk == NULL) {
		(void) fprintf(stderr,
			"pgp_write_pk_sesskey: NULL pksk\n");
		return 0;
	}
	switch (pksk->alg) {
	case PGP_PKA_RSA:
		return pgp_write_ptag(output, PGP_PTAG_CT_PK_SESSION_KEY) &&
			pgp_write_length(output, (unsigned)(1 + 8 + 1 +
				BN_num_bytes(pksk->params.rsa.encrypted_m) + 2)) &&
			pgp_write_scalar(output, (unsigned)pksk->version, 1) &&
			pgp_write(output, pksk->key_id, 8) &&
			pgp_write_scalar(output, (unsigned)pksk->alg, 1) &&
			pgp_write_mpi(output, pksk->params.rsa.encrypted_m)
			/* ??	&& pgp_write_scalar(output, 0, 2); */
			;
	case PGP_PKA_DSA:
	case PGP_PKA_ELGAMAL:
		return pgp_write_ptag(output, PGP_PTAG_CT_PK_SESSION_KEY) &&
			pgp_write_length(output, (unsigned)(1 + 8 + 1 +
				BN_num_bytes(pksk->params.elgamal.g_to_k) + 2 +
				BN_num_bytes(pksk->params.elgamal.encrypted_m) + 2)) &&
			pgp_write_scalar(output, (unsigned)pksk->version, 1) &&
			pgp_write(output, pksk->key_id, 8) &&
			pgp_write_scalar(output, (unsigned)pksk->alg, 1) &&
			pgp_write_mpi(output, pksk->params.elgamal.g_to_k) &&
			pgp_write_mpi(output, pksk->params.elgamal.encrypted_m)
			/* ??	&& pgp_write_scalar(output, 0, 2); */
			;
	default:
		(void) fprintf(stderr,
			"pgp_write_pk_sesskey: bad algorithm\n");
		return 0;
	}
}
Esempio n. 7
0
unsigned 
pgp_write_mpi(pgp_output_t *output, const BIGNUM *bn)
{
	unsigned	bits;
	uint8_t		buf[NETPGP_BUFSIZ];

	bits = (unsigned)BN_num_bits(bn);
	if (bits > 65535) {
		(void) fprintf(stderr, "pgp_write_mpi: too large %u\n", bits);
		return 0;
	}
	BN_bn2bin(bn, buf);
	return pgp_write_scalar(output, bits, 2) &&
		pgp_write(output, buf, (bits + 7) / 8);
}
Esempio n. 8
0
unsigned 
pgp_write_xfer_seckey(pgp_output_t *output,
				const pgp_key_t *key,
				const uint8_t *passphrase,
				const size_t pplen,
				unsigned armoured)
{
	unsigned	i, j;

	if (armoured) {
		pgp_writer_push_armoured(output, PGP_PGP_PRIVATE_KEY_BLOCK);
	}
	/* public key */
	if (!pgp_write_struct_seckey(&key->key.seckey, passphrase,
			pplen, output)) {
		return 0;
	}

	/* TODO: revocation signatures go here */

	/* user ids and corresponding signatures */
	for (i = 0; i < key->uidc; i++) {
		if (!pgp_write_struct_userid(output, key->uids[i])) {
			return 0;
		}
		for (j = 0; j < key->packetc; j++) {
			if (!pgp_write(output, key->packets[j].raw, (unsigned)key->packets[j].length)) {
				return 0;
			}
		}
	}

	/* TODO: user attributes and corresponding signatures */

	/*
	 * subkey packets and corresponding signatures and optional
	 * revocation
	 */

	if (armoured) {
		pgp_writer_info_finalise(&output->errors, &output->writer);
		pgp_writer_pop(output);
	}
	return 1;
}
Esempio n. 9
0
/**
\ingroup Core_WritePackets
\brief Write a One Pass Signature packet
\param seckey Secret Key to use
\param hash_alg Hash Algorithm to use
\param sig_type Signature type
\param output Write settings
\return 1 if OK; else 0
*/
unsigned 
pgp_write_one_pass_sig(pgp_output_t *output, 
			const pgp_seckey_t *seckey,
			const pgp_hash_alg_t hash_alg,
			const pgp_sig_type_t sig_type)
{
	uint8_t   keyid[PGP_KEY_ID_SIZE];

	pgp_keyid(keyid, PGP_KEY_ID_SIZE, &seckey->pubkey, PGP_HASH_SHA1); /* XXX - hardcoded */
	return pgp_write_ptag(output, PGP_PTAG_CT_1_PASS_SIG) &&
		pgp_write_length(output, 1 + 1 + 1 + 1 + 8 + 1) &&
		pgp_write_scalar(output, 3, 1)	/* version */ &&
		pgp_write_scalar(output, (unsigned)sig_type, 1) &&
		pgp_write_scalar(output, (unsigned)hash_alg, 1) &&
		pgp_write_scalar(output, (unsigned)seckey->pubkey.alg, 1) &&
		pgp_write(output, keyid, 8) &&
		pgp_write_scalar(output, 1, 1);
}
Esempio n. 10
0
/**
\ingroup HighLevel_Crypto
Encrypt a file
\param infile Name of file to be encrypted
\param outfile Name of file to write to. If NULL, name is constructed from infile
\param pubkey Public Key to encrypt file for
\param use_armour Write armoured text, if set
\param allow_overwrite Allow output file to be overwrwritten if it exists
\return 1 if OK; else 0
*/
unsigned 
pgp_encrypt_file(pgp_io_t *io,
			const char *infile,
			const char *outfile,
			const pgp_key_t *key,
			const unsigned use_armour,
			const unsigned allow_overwrite,
			const char *cipher)
{
	pgp_output_t	*output;
	pgp_memory_t	*inmem;
	int		 fd_out;

	__PGP_USED(io);
	inmem = pgp_memory_new();
	if (!pgp_mem_readfile(inmem, infile)) {
		return 0;
	}
	fd_out = pgp_setup_file_write(&output, outfile, allow_overwrite);
	if (fd_out < 0) {
		pgp_memory_free(inmem);
		return 0;
	}

	/* set armoured/not armoured here */
	if (use_armour) {
		pgp_writer_push_armor_msg(output);
	}

	/* Push the encrypted writer */
	if (!pgp_push_enc_se_ip(output, key, cipher)) {
		pgp_memory_free(inmem);
		return 0;
	}

	/* This does the writing */
	pgp_write(output, pgp_mem_data(inmem), (unsigned)pgp_mem_len(inmem));

	/* tidy up */
	pgp_memory_free(inmem);
	pgp_teardown_file_write(output, fd_out);

	return 1;
}
Esempio n. 11
0
/**
\ingroup Core_WritePackets
\brief Writes Literal Data packet from buffer
\param data Buffer to write out
\param maxlen Max length of buffer
\param type Literal Data Type
\param output Write settings
\return 1 if OK; else 0
*/
unsigned 
pgp_write_litdata(pgp_output_t *output,
			const uint8_t *data,
			const int maxlen,
			const pgp_litdata_enum type)
{
	/*
         * RFC4880 does not specify a meaning for filename or date.
         * It is implementation-dependent.
         * We will not implement them.
         */
	/* \todo do we need to check text data for <cr><lf> line endings ? */
	return pgp_write_ptag(output, PGP_PTAG_CT_LITDATA) &&
		pgp_write_length(output, (unsigned)(1 + 1 + 4 + maxlen)) &&
		pgp_write_scalar(output, (unsigned)type, 1) &&
		pgp_write_scalar(output, 0, 1) &&
		pgp_write_scalar(output, 0, 4) &&
		pgp_write(output, data, (unsigned)maxlen);
}
Esempio n. 12
0
/* encrypt the contents of the input buffer, and return the mem structure */
pgp_memory_t *
pgp_encrypt_buf(pgp_io_t *io,
			const void *input,
			const size_t insize,
			const pgp_key_t *pubkey,
			const unsigned use_armour,
			const char *cipher)
{
	pgp_output_t	*output;
	pgp_memory_t	*outmem;

	__PGP_USED(io);
	if (input == NULL) {
		(void) fprintf(io->errs,
			"pgp_encrypt_buf: null memory\n");
		return 0;
	}

	pgp_setup_memory_write(&output, &outmem, insize);

	/* set armoured/not armoured here */
	if (use_armour) {
		pgp_writer_push_armor_msg(output);
	}

	/* Push the encrypted writer */
	pgp_push_enc_se_ip(output, pubkey, cipher);

	/* This does the writing */
	pgp_write(output, input, (unsigned)insize);

	/* tidy up */
	pgp_writer_close(output);
	pgp_output_delete(output);

	return outmem;
}
Esempio n. 13
0
/**
\ingroup HighLevel_Sign
\brief Sign a file
\param inname Input filename
\param outname Output filename. If NULL, a name is constructed from the input filename.
\param seckey Secret Key to use for signing
\param armored Write armoured text, if set.
\param overwrite May overwrite existing file, if set.
\return 1 if OK; else 0;

*/
unsigned 
pgp_sign_file(pgp_io_t *io,
		const char *inname,
		const char *outname,
		const pgp_seckey_t *seckey,
		const char *hashname,
		const int64_t from,
		const uint64_t duration,
		const unsigned armored,
		const unsigned cleartext,
		const unsigned overwrite)
{
	pgp_create_sig_t	*sig;
	pgp_sig_type_t	 sig_type;
	pgp_hash_alg_t	 hash_alg;
	pgp_memory_t		*infile;
	pgp_output_t		*output;
	pgp_hash_t		*hash;
	unsigned		 ret;
	uint8_t			 keyid[PGP_KEY_ID_SIZE];
	int			 fd_out;

	sig = NULL;
	sig_type = PGP_SIG_BINARY;
	infile = NULL;
	output = NULL;
	hash = NULL;
	fd_out = 0;

	/* find the hash algorithm */
	hash_alg = pgp_str_to_hash_alg(hashname);
	if (hash_alg == PGP_HASH_UNKNOWN) {
		(void) fprintf(io->errs,
			"pgp_sign_file: unknown hash algorithm: \"%s\"\n",
			hashname);
		return 0;
	}

	/* read input file into buf */
	infile = pgp_memory_new();
	if (!pgp_mem_readfile(infile, inname)) {
		return 0;
	}

	/* setup output file */
	fd_out = open_output_file(&output, inname, outname,
				(armored) ? "asc" : "gpg", overwrite);
	if (fd_out < 0) {
		pgp_memory_free(infile);
		return 0;
	}

	/* set up signature */
	sig = pgp_create_sig_new();
	if (!sig) {
		pgp_memory_free(infile);
		pgp_teardown_file_write(output, fd_out);
		return 0;
	}

	pgp_start_sig(sig, seckey, hash_alg, sig_type);

	if (cleartext) {
		if (pgp_writer_push_clearsigned(output, sig) != 1) {
			return 0;
		}

		/* Do the signing */
		pgp_write(output, pgp_mem_data(infile), (unsigned)pgp_mem_len(infile));
		pgp_memory_free(infile);

		/* add signature with subpackets: */
		/* - creation time */
		/* - key id */
		ret = pgp_writer_use_armored_sig(output) &&
				pgp_add_time(sig, (int64_t)from, "birth") &&
				pgp_add_time(sig, (int64_t)duration, "expiration");
		if (ret == 0) {
			pgp_teardown_file_write(output, fd_out);
			return 0;
		}

		pgp_keyid(keyid, PGP_KEY_ID_SIZE, &seckey->pubkey, hash_alg);
		ret = pgp_add_issuer_keyid(sig, keyid) &&
			pgp_end_hashed_subpkts(sig) &&
			pgp_write_sig(output, sig, &seckey->pubkey, seckey);

		pgp_teardown_file_write(output, fd_out);

		if (ret == 0) {
			PGP_ERROR_1(&output->errors, PGP_E_W, "%s",
			    "Cannot sign file as cleartext");
		}
	} else {
		/* set armoured/not armoured here */
		if (armored) {
			pgp_writer_push_armor_msg(output);
		}

		/* write one_pass_sig */
		pgp_write_one_pass_sig(output, seckey, hash_alg, sig_type);

		/* hash file contents */
		hash = pgp_sig_get_hash(sig);
		hash->add(hash, pgp_mem_data(infile), (unsigned)pgp_mem_len(infile));

#if 1
		/* output file contents as Literal Data packet */
		pgp_write_litdata(output, pgp_mem_data(infile),
			(const int)pgp_mem_len(infile),
			PGP_LDT_BINARY);
#else
		/* XXX - agc - sync with writer.c 1094 for ops_writez */
		pgp_setup_memory_write(&litoutput, &litmem, bufsz);
		pgp_setup_memory_write(&zoutput, &zmem, bufsz);
		pgp_write_litdata(litoutput,
			pgp_mem_data(pgp_mem_data(infile),
			(const int)pgp_mem_len(infile), PGP_LDT_BINARY);
		pgp_writez(zoutput, pgp_mem_data(litmem), pgp_mem_len(litmem));
#endif

		/* add creation time to signature */
		pgp_add_time(sig, (int64_t)from, "birth");
		pgp_add_time(sig, (int64_t)duration, "expiration");
		/* add key id to signature */
		pgp_keyid(keyid, PGP_KEY_ID_SIZE, &seckey->pubkey, hash_alg);
		pgp_add_issuer_keyid(sig, keyid);
		pgp_end_hashed_subpkts(sig);
		pgp_write_sig(output, sig, &seckey->pubkey, seckey);

		/* tidy up */
		pgp_teardown_file_write(output, fd_out);

		pgp_create_sig_delete(sig);
		pgp_memory_free(infile);

		ret = 1;
	}

	return ret;
}
Esempio n. 14
0
unsigned 
pgp_writez(pgp_output_t *out, const uint8_t *data, const unsigned len)
{
	compress_t	*zip;
	size_t		 sz_in;
	size_t		 sz_out;
	int              ret;
	int              r = 0;

	/* compress the data */
	const int       level = Z_DEFAULT_COMPRESSION;	/* \todo allow varying
							 * levels */

	if ((zip = calloc(1, sizeof(*zip))) == NULL) {
		(void) fprintf(stderr, "pgp_writez: bad alloc\n");
		return 0;
	}
	zip->stream.zalloc = Z_NULL;
	zip->stream.zfree = Z_NULL;
	zip->stream.opaque = NULL;

	/* all other fields set to zero by use of calloc */

	/* LINTED */ /* this is a lint problem in zlib.h header */
	if ((int)deflateInit(&zip->stream, level) != Z_OK) {
		(void) fprintf(stderr, "pgp_writez: can't initialise\n");
		return 0;
	}
	/* do necessary transformation */
	/* copy input to maintain const'ness of src */
	if (zip->src != NULL || zip->dst != NULL) {
		(void) fprintf(stderr, "pgp_writez: non-null streams\n");
		return 0;
	}

	sz_in = len * sizeof(uint8_t);
	sz_out = ((101 * sz_in) / 100) + 12;	/* from zlib webpage */
	if ((zip->src = calloc(1, sz_in)) == NULL) {
		free(zip);
		(void) fprintf(stderr, "pgp_writez: bad alloc2\n");
		return 0;
	}
	if ((zip->dst = calloc(1, sz_out)) == NULL) {
		free(zip->src);
		free(zip);
		(void) fprintf(stderr, "pgp_writez: bad alloc3\n");
		return 0;
	}
	(void) memcpy(zip->src, data, len);

	/* setup stream */
	zip->stream.next_in = zip->src;
	zip->stream.avail_in = (unsigned)sz_in;
	zip->stream.total_in = 0;

	zip->stream.next_out = zip->dst;
	zip->stream.avail_out = (unsigned)sz_out;
	zip->stream.total_out = 0;

	do {
		r = deflate(&zip->stream, Z_FINISH);
	} while (r != Z_STREAM_END);

	/* write it out */
	ret = pgp_write_ptag(out, PGP_PTAG_CT_COMPRESSED) &&
		pgp_write_length(out, (unsigned)(zip->stream.total_out + 1))&&
		pgp_write_scalar(out, PGP_C_ZLIB, 1) &&
		pgp_write(out, zip->dst, (unsigned)zip->stream.total_out);

	free(zip->src);
	free(zip->dst);
	free(zip);
	return ret;
}
Esempio n. 15
0
unsigned 
pgp_write_sig(pgp_output_t *output, 
			pgp_create_sig_t *sig,
			const pgp_pubkey_t *key,
			const pgp_seckey_t *seckey)
{
	unsigned	ret = 0;
	size_t		len = pgp_mem_len(sig->mem);

	/* check key not decrypted */
	switch (seckey->pubkey.alg) {
	case PGP_PKA_RSA:
	case PGP_PKA_RSA_ENCRYPT_ONLY:
	case PGP_PKA_RSA_SIGN_ONLY:
		if (seckey->key.rsa.d == NULL) {
			(void) fprintf(stderr, "pgp_write_sig: null rsa.d\n");
			return 0;
		}
		break;

	case PGP_PKA_DSA:
		if (seckey->key.dsa.x == NULL) {
			(void) fprintf(stderr, "pgp_write_sig: null dsa.x\n");
			return 0;
		}
		break;

	default:
		(void) fprintf(stderr, "Unsupported algorithm %d\n",
				seckey->pubkey.alg);
		return 0;
	}

	if (sig->hashlen == (unsigned) -1) {
		(void) fprintf(stderr,
				"ops_write_sig: bad hashed data len\n");
		return 0;
	}

	pgp_memory_place_int(sig->mem, sig->unhashoff,
			     (unsigned)(len - sig->unhashoff - 2), 2);

	/* add the packet from version number to end of hashed subpackets */
	if (pgp_get_debug_level(__FILE__)) {
		(void) fprintf(stderr, "ops_write_sig: hashed packet info\n");
	}
	sig->hash.add(&sig->hash, pgp_mem_data(sig->mem), sig->unhashoff);

	/* add final trailer */
	pgp_hash_add_int(&sig->hash, (unsigned)sig->sig.info.version, 1);
	pgp_hash_add_int(&sig->hash, 0xff, 1);
	/* +6 for version, type, pk alg, hash alg, hashed subpacket length */
	pgp_hash_add_int(&sig->hash, sig->hashlen + 6, 4);

	if (pgp_get_debug_level(__FILE__)) {
		(void) fprintf(stderr, "ops_write_sig: done writing hashed\n");
	}
	/* XXX: technically, we could figure out how big the signature is */
	/* and write it directly to the output instead of via memory. */
	switch (seckey->pubkey.alg) {
	case PGP_PKA_RSA:
	case PGP_PKA_RSA_ENCRYPT_ONLY:
	case PGP_PKA_RSA_SIGN_ONLY:
		if (!rsa_sign(&sig->hash, &key->key.rsa, &seckey->key.rsa,
				sig->output)) {
			(void) fprintf(stderr,
				"pgp_write_sig: rsa_sign failure\n");
			return 0;
		}
		break;

	case PGP_PKA_DSA:
		if (!dsa_sign(&sig->hash, &key->key.dsa, &seckey->key.dsa,
				sig->output)) {
			(void) fprintf(stderr,
				"pgp_write_sig: dsa_sign failure\n");
			return 0;
		}
		break;

	default:
		(void) fprintf(stderr, "Unsupported algorithm %d\n",
					seckey->pubkey.alg);
		return 0;
	}

	ret = pgp_write_ptag(output, PGP_PTAG_CT_SIGNATURE);
	if (ret) {
		len = pgp_mem_len(sig->mem);
		ret = pgp_write_length(output, (unsigned)len) &&
			pgp_write(output, pgp_mem_data(sig->mem), (unsigned)len);
	}
	pgp_memory_free(sig->mem);

	if (ret == 0) {
		PGP_ERROR_1(&output->errors, PGP_E_W, "%s",
		    "Cannot write signature");
	}
	return ret;
}
Esempio n. 16
0
int dc_pgp_symm_encrypt(dc_context_t* context,
                        const char* passphrase,
                        const void* plain, size_t plain_bytes,
                        char** ret_ctext_armored)
{
	int                    success = 0;
	uint8_t                salt[PGP_SALT_SIZE];
	pgp_crypt_t            crypt_info;
	uint8_t*               key = NULL;

	pgp_output_t*          payload_output = NULL;
	pgp_memory_t*          payload_mem = NULL;

	pgp_output_t*          encr_output = NULL;
	pgp_memory_t*          encr_mem = NULL;

	if (context==NULL || passphrase==NULL || plain==NULL || plain_bytes==0
	 || ret_ctext_armored==NULL ) {
		goto cleanup;
	}

	//printf("\n~~~~~~~~~~~~~~~~~~~~SETUP-PAYLOAD~~~~~~~~~~~~~~~~~~~~\n%s~~~~~~~~~~~~~~~~~~~~/SETUP-PAYLOAD~~~~~~~~~~~~~~~~~~~~\n",key_asc); // DEBUG OUTPUT

	/* put the payload into a literal data packet which will be encrypted then, see RFC 4880, 5.7 :
	"When it has been decrypted, it contains other packets (usually a literal data packet or compressed data
	packet, but in theory other Symmetrically Encrypted Data packets or sequences of packets that form whole OpenPGP messages)" */

	pgp_setup_memory_write(&payload_output, &payload_mem, 128);
	pgp_write_litdata(payload_output, (const uint8_t*)plain, plain_bytes, PGP_LDT_BINARY);

	/* create salt for the key */
	pgp_random(salt, PGP_SALT_SIZE);

	/* S2K */
	#define SYMM_ALGO PGP_SA_AES_128
	if (!pgp_crypt_any(&crypt_info, SYMM_ALGO)) {
		goto cleanup;
	}

	int s2k_spec = PGP_S2KS_ITERATED_AND_SALTED; // 0=simple, 1=salted, 3=salted+iterated
	int s2k_iter_id = 96; // 0=1024 iterations, 96=65536 iterations
	#define HASH_ALG  PGP_HASH_SHA256
	if ((key = pgp_s2k_do(passphrase, crypt_info.keysize, s2k_spec, HASH_ALG, salt, s2k_iter_id))==NULL) {
		goto cleanup;
	}

	/* encrypt the payload using the key using AES-128 and put it into
	OpenPGP's "Symmetric-Key Encrypted Session Key" (Tag 3, https://tools.ietf.org/html/rfc4880#section-5.3) followed by
	OpenPGP's "Symmetrically Encrypted Data Packet" (Tag 18, https://tools.ietf.org/html/rfc4880#section-5.13 , better than Tag 9) */

	pgp_setup_memory_write(&encr_output, &encr_mem, 128);
	pgp_writer_push_armor_msg(encr_output);

	/* Tag 3 - PGP_PTAG_CT_SK_SESSION_KEY */
	pgp_write_ptag     (encr_output, PGP_PTAG_CT_SK_SESSION_KEY);
	pgp_write_length   (encr_output, 1/*version*/
	                               + 1/*symm. algo*/
	                               + 1/*s2k_spec*/
	                               + 1/*S2 hash algo*/
	                               + ((s2k_spec==PGP_S2KS_SALTED || s2k_spec==PGP_S2KS_ITERATED_AND_SALTED)? PGP_SALT_SIZE : 0)/*the salt*/
	                               + ((s2k_spec==PGP_S2KS_ITERATED_AND_SALTED)? 1 : 0)/*number of iterations*/);

	pgp_write_scalar   (encr_output, 4, 1);                  // 1 octet: version
	pgp_write_scalar   (encr_output, SYMM_ALGO, 1);          // 1 octet: symm. algo

	pgp_write_scalar   (encr_output, s2k_spec, 1);           // 1 octet: s2k_spec
	pgp_write_scalar   (encr_output, HASH_ALG, 1);           // 1 octet: S2 hash algo
	if (s2k_spec==PGP_S2KS_SALTED || s2k_spec==PGP_S2KS_ITERATED_AND_SALTED) {
	  pgp_write        (encr_output, salt, PGP_SALT_SIZE);   // 8 octets: the salt
	}
	if (s2k_spec==PGP_S2KS_ITERATED_AND_SALTED) {
	  pgp_write_scalar (encr_output, s2k_iter_id, 1);        // 1 octet: number of iterations
	}

	// for(int j=0; j<AES_KEY_LENGTH; j++) { printf("%02x", key[j]); } printf("\n----------------\n");

	/* Tag 18 - PGP_PTAG_CT_SE_IP_DATA */
	//pgp_write_symm_enc_data((const uint8_t*)payload_mem->buf, payload_mem->length, PGP_SA_AES_128, key, encr_output); //-- would generate Tag 9
	{
		uint8_t* iv = calloc(1, crypt_info.blocksize); if (iv==NULL) { goto cleanup; }
		crypt_info.set_iv(&crypt_info, iv);
		free(iv);

		crypt_info.set_crypt_key(&crypt_info, &key[0]);
		pgp_encrypt_init(&crypt_info);

		pgp_write_se_ip_pktset(encr_output, payload_mem->buf, payload_mem->length, &crypt_info);

		crypt_info.decrypt_finish(&crypt_info);
	}

	/* done with symmetric key block */
	pgp_writer_close(encr_output);
	*ret_ctext_armored = dc_null_terminate((const char*)encr_mem->buf, encr_mem->length);

	//printf("\n~~~~~~~~~~~~~~~~~~~~SYMMETRICALLY ENCRYPTED~~~~~~~~~~~~~~~~~~~~\n%s~~~~~~~~~~~~~~~~~~~~/SYMMETRICALLY ENCRYPTED~~~~~~~~~~~~~~~~~~~~\n",encr_string); // DEBUG OUTPUT

	success = 1;

cleanup:
	if (payload_output) { pgp_output_delete(payload_output); }
	if (payload_mem) { pgp_memory_free(payload_mem); }
	if (encr_output) { pgp_output_delete(encr_output); }
	if (encr_mem) { pgp_memory_free(encr_mem); }
	free(key);
	return success;
}
Esempio n. 17
0
/* treated as an MPI. */
static int 
rsa_sign(pgp_hash_t *hash,
	const pgp_rsa_pubkey_t *pubrsa,
	const pgp_rsa_seckey_t *secrsa,
	pgp_output_t *out)
{
	unsigned        prefixsize;
	unsigned        expected;
	unsigned        hashsize;
	unsigned        keysize;
	unsigned        n;
	unsigned        t;
	uint8_t		hashbuf[NETPGP_BUFSIZ];
	uint8_t		sigbuf[NETPGP_BUFSIZ];
	uint8_t		*prefix;
	BIGNUM         *bn;

	if (strcmp(hash->name, "SHA1") == 0) {
		hashsize = PGP_SHA1_HASH_SIZE + sizeof(prefix_sha1);
		prefix = prefix_sha1;
		prefixsize = sizeof(prefix_sha1);
		expected = PGP_SHA1_HASH_SIZE;
	} else {
		hashsize = PGP_SHA256_HASH_SIZE + sizeof(prefix_sha256);
		prefix = prefix_sha256;
		prefixsize = sizeof(prefix_sha256);
		expected = PGP_SHA256_HASH_SIZE;
	}
	keysize = (BN_num_bits(pubrsa->n) + 7) / 8;
	if (keysize > sizeof(hashbuf)) {
		(void) fprintf(stderr, "rsa_sign: keysize too big\n");
		return 0;
	}
	if (10 + hashsize > keysize) {
		(void) fprintf(stderr, "rsa_sign: hashsize too big\n");
		return 0;
	}

	hashbuf[0] = 0;
	hashbuf[1] = 1;
	if (pgp_get_debug_level(__FILE__)) {
		printf("rsa_sign: PS is %d\n", keysize - hashsize - 1 - 2);
	}
	for (n = 2; n < keysize - hashsize - 1; ++n) {
		hashbuf[n] = 0xff;
	}
	hashbuf[n++] = 0;

	(void) memcpy(&hashbuf[n], prefix, prefixsize);
	n += prefixsize;
	if ((t = hash->finish(hash, &hashbuf[n])) != expected) {
		(void) fprintf(stderr, "rsa_sign: short %s hash\n", hash->name);
		return 0;
	}

	pgp_write(out, &hashbuf[n], 2);

	n += t;
	if (n != keysize) {
		(void) fprintf(stderr, "rsa_sign: n != keysize\n");
		return 0;
	}

	t = pgp_rsa_private_encrypt(sigbuf, hashbuf, keysize, secrsa, pubrsa);
	bn = BN_bin2bn(sigbuf, (int)t, NULL);
	pgp_write_mpi(out, bn);
	BN_free(bn);
	return 1;
}
Esempio n. 18
0
/**
\ingroup HighLevel_Sign
\brief Signs a buffer
\param input Input text to be signed
\param input_len Length of input text
\param sig_type Signature type
\param seckey Secret Key
\param armored Write armoured text, if set
\return New pgp_memory_t struct containing signed text
\note It is the caller's responsibility to call pgp_memory_free(me)

*/
pgp_memory_t *
pgp_sign_buf(pgp_io_t *io,
		const void *input,
		const size_t insize,
		const pgp_seckey_t *seckey,
		const int64_t from,
		const uint64_t duration,
		const char *hashname,
		const unsigned armored,
		const unsigned cleartext)
{
	pgp_litdata_enum	 ld_type;
	pgp_create_sig_t	*sig;
	pgp_sig_type_t	 sig_type;
	pgp_hash_alg_t	 hash_alg;
	pgp_output_t		*output;
	pgp_memory_t		*mem;
	uint8_t			 keyid[PGP_KEY_ID_SIZE];
	pgp_hash_t		*hash;
	unsigned		 ret;

	sig = NULL;
	sig_type = PGP_SIG_BINARY;
	output = NULL;
	mem = pgp_memory_new();
	hash = NULL;
	ret = 0;

	hash_alg = pgp_str_to_hash_alg(hashname);
	if (hash_alg == PGP_HASH_UNKNOWN) {
		(void) fprintf(io->errs,
			"pgp_sign_buf: unknown hash algorithm: \"%s\"\n",
			hashname);
		return NULL;
	}

	/* setup literal data packet type */
	ld_type = (cleartext) ? PGP_LDT_TEXT : PGP_LDT_BINARY;

	if (input == NULL) {
		(void) fprintf(io->errs,
			"pgp_sign_buf: null input\n");
		return NULL;
	}

	/* set up signature */
	if ((sig = pgp_create_sig_new()) == NULL) {
		return NULL;
	}
	pgp_start_sig(sig, seckey, hash_alg, sig_type);

	/* setup writer */
	pgp_setup_memory_write(&output, &mem, insize);

	if (cleartext) {
		/* Do the signing */
		/* add signature with subpackets: */
		/* - creation time */
		/* - key id */
		ret = pgp_writer_push_clearsigned(output, sig) &&
			pgp_write(output, input, (unsigned)insize) &&
			pgp_writer_use_armored_sig(output) &&
			pgp_add_time(sig, from, "birth") &&
			pgp_add_time(sig, (int64_t)duration, "expiration");
		if (ret == 0) {
			return NULL;
		}
		pgp_output_delete(output);
	} else {
		/* set armoured/not armoured here */
		if (armored) {
			pgp_writer_push_armor_msg(output);
		}
		if (pgp_get_debug_level(__FILE__)) {
			fprintf(io->errs, "** Writing out one pass sig\n");
		}
		/* write one_pass_sig */
		pgp_write_one_pass_sig(output, seckey, hash_alg, sig_type);

		/* hash memory */
		hash = pgp_sig_get_hash(sig);
		hash->add(hash, input, (unsigned)insize);

		/* output file contents as Literal Data packet */
		if (pgp_get_debug_level(__FILE__)) {
			(void) fprintf(stderr, "** Writing out data now\n");
		}
		pgp_write_litdata(output, input, (const int)insize, ld_type);
		if (pgp_get_debug_level(__FILE__)) {
			fprintf(stderr, "** After Writing out data now\n");
		}

		/* add creation time to signature */
		pgp_add_time(sig, from, "birth");
		pgp_add_time(sig, (int64_t)duration, "expiration");
		/* add key id to signature */
		pgp_keyid(keyid, PGP_KEY_ID_SIZE, &seckey->pubkey, hash_alg);
		pgp_add_issuer_keyid(sig, keyid);
		pgp_end_hashed_subpkts(sig);

		/* write out sig */
		pgp_write_sig(output, sig, &seckey->pubkey, seckey);

		/* tidy up */
		pgp_writer_close(output);
		pgp_create_sig_delete(sig);
	}
	return mem;
}
Esempio n. 19
0
/*
 * Note that we support v3 keys here because they're needed for
 * verification.
 */
static unsigned 
write_seckey_body(const pgp_seckey_t *key,
		      const uint8_t *passphrase,
		      const size_t pplen,
		      pgp_output_t *output)
{
	/* RFC4880 Section 5.5.3 Secret-Key Packet Formats */

	pgp_crypt_t   crypted;
	pgp_hash_t    hash;
	unsigned	done = 0;
	unsigned	i = 0;
	uint8_t		*hashed;
	uint8_t		sesskey[CAST_KEY_LENGTH];

	if (!write_pubkey_body(&key->pubkey, output)) {
		return 0;
	}
	if (key->s2k_usage != PGP_S2KU_ENCRYPTED_AND_HASHED) {
		(void) fprintf(stderr, "write_seckey_body: s2k usage\n");
		return 0;
	}
	if (!pgp_write_scalar(output, (unsigned)key->s2k_usage, 1)) {
		return 0;
	}

	if (key->alg != PGP_SA_CAST5) {
		(void) fprintf(stderr, "write_seckey_body: algorithm\n");
		return 0;
	}
	if (!pgp_write_scalar(output, (unsigned)key->alg, 1)) {
		return 0;
	}

	if (key->s2k_specifier != PGP_S2KS_SIMPLE &&
	    key->s2k_specifier != PGP_S2KS_SALTED) {
		/* = 1 \todo could also be iterated-and-salted */
		(void) fprintf(stderr, "write_seckey_body: s2k spec\n");
		return 0;
	}
	if (!pgp_write_scalar(output, (unsigned)key->s2k_specifier, 1)) {
		return 0;
	}
	if (!pgp_write_scalar(output, (unsigned)key->hash_alg, 1)) {
		return 0;
	}

	switch (key->s2k_specifier) {
	case PGP_S2KS_SIMPLE:
		/* nothing more to do */
		break;

	case PGP_S2KS_SALTED:
		/* 8-octet salt value */
		pgp_random(__UNCONST(&key->salt[0]), PGP_SALT_SIZE);
		if (!pgp_write(output, key->salt, PGP_SALT_SIZE)) {
			return 0;
		}
		break;

		/*
		 * \todo case PGP_S2KS_ITERATED_AND_SALTED: // 8-octet salt
		 * value // 1-octet count break;
		 */

	default:
		(void) fprintf(stderr,
			"invalid/unsupported s2k specifier %d\n",
			key->s2k_specifier);
		return 0;
	}

	if (!pgp_write(output, &key->iv[0], pgp_block_size(key->alg))) {
		return 0;
	}

	/*
	 * create the session key for encrypting the algorithm-specific
	 * fields
	 */

	switch (key->s2k_specifier) {
	case PGP_S2KS_SIMPLE:
	case PGP_S2KS_SALTED:
		/* RFC4880: section 3.7.1.1 and 3.7.1.2 */

		for (done = 0, i = 0; done < CAST_KEY_LENGTH; i++) {
			unsigned 	hashsize;
			unsigned 	j;
			unsigned	needed;
			unsigned	size;
			uint8_t		zero = 0;

			/* Hard-coded SHA1 for session key */
			pgp_hash_any(&hash, PGP_HASH_SHA1);
			hashsize = pgp_hash_size(key->hash_alg);
			needed = CAST_KEY_LENGTH - done;
			size = MIN(needed, hashsize);
			if ((hashed = calloc(1, hashsize)) == NULL) {
				(void) fprintf(stderr, "write_seckey_body: bad alloc\n");
				return 0;
			}
			if (!hash.init(&hash)) {
				(void) fprintf(stderr, "write_seckey_body: bad alloc\n");
				return 0;
			}

			/* preload if iterating  */
			for (j = 0; j < i; j++) {
				/*
				 * Coverity shows a DEADCODE error on this
				 * line. This is expected since the hardcoded
				 * use of SHA1 and CAST5 means that it will
				 * not used. This will change however when
				 * other algorithms are supported.
				 */
				hash.add(&hash, &zero, 1);
			}

			if (key->s2k_specifier == PGP_S2KS_SALTED) {
				hash.add(&hash, key->salt, PGP_SALT_SIZE);
			}
			hash.add(&hash, passphrase, (unsigned)pplen);
			hash.finish(&hash, hashed);

			/*
			 * if more in hash than is needed by session key, use
			 * the leftmost octets
			 */
			(void) memcpy(&sesskey[i * hashsize],
					hashed, (unsigned)size);
			done += (unsigned)size;
			if (done > CAST_KEY_LENGTH) {
				(void) fprintf(stderr,
					"write_seckey_body: short add\n");
				return 0;
			}
		}

		break;

		/*
		 * \todo case PGP_S2KS_ITERATED_AND_SALTED: * 8-octet salt
		 * value * 1-octet count break;
		 */

	default:
		(void) fprintf(stderr,
			"invalid/unsupported s2k specifier %d\n",
			key->s2k_specifier);
		return 0;
	}

	/* use this session key to encrypt */

	pgp_crypt_any(&crypted, key->alg);
	crypted.set_iv(&crypted, key->iv);
	crypted.set_crypt_key(&crypted, sesskey);
	pgp_encrypt_init(&crypted);

	if (pgp_get_debug_level(__FILE__)) {
		hexdump(stderr, "writing: iv=", key->iv, pgp_block_size(key->alg));
		hexdump(stderr, "key= ", sesskey, CAST_KEY_LENGTH);
		(void) fprintf(stderr, "\nturning encryption on...\n");
	}
	pgp_push_enc_crypt(output, &crypted);

	switch (key->pubkey.alg) {
	case PGP_PKA_RSA:
	case PGP_PKA_RSA_ENCRYPT_ONLY:
	case PGP_PKA_RSA_SIGN_ONLY:
		if (!pgp_write_mpi(output, key->key.rsa.d) ||
		    !pgp_write_mpi(output, key->key.rsa.p) ||
		    !pgp_write_mpi(output, key->key.rsa.q) ||
		    !pgp_write_mpi(output, key->key.rsa.u)) {
			if (pgp_get_debug_level(__FILE__)) {
				(void) fprintf(stderr,
					"4 x mpi not written - problem\n");
			}
			return 0;
		}
		break;
	case PGP_PKA_DSA:
		return pgp_write_mpi(output, key->key.dsa.x);
	case PGP_PKA_ELGAMAL:
		return pgp_write_mpi(output, key->key.elgamal.x);
	default:
		return 0;
	}

	if (!pgp_write(output, key->checkhash, PGP_CHECKHASH_SIZE)) {
		return 0;
	}

	pgp_writer_pop(output);

	return 1;
}