Exemplo n.º 1
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;
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
/* \todo remove code duplication between this and zlib_compressed_data_reader */
static int 
bzip2_compressed_data_reader(pgp_stream_t *stream, void *dest, size_t length,
			     pgp_error_t **errors,
			     pgp_reader_t *readinfo,
			     pgp_cbdata_t *cbinfo)
{
	bz_decompress_t *bz = pgp_reader_get_arg(readinfo);
	size_t		len;
	size_t		 cc;
	char		*cdest = dest;

	if (bz->type != PGP_C_BZIP2) {
		(void) fprintf(stderr, "Weird type %d\n", bz->type);
		return 0;
	}
	if (bz->inflate_ret == BZ_STREAM_END &&
	    bz->bzstream.next_out == &bz->out[bz->offset]) {
		return 0;
	}
	for (cc = 0 ; cc < length ; cc += len) {
		if (&bz->out[bz->offset] == bz->bzstream.next_out) {
			int             ret;

			bz->bzstream.next_out = (char *) bz->out;
			bz->bzstream.avail_out = sizeof(bz->out);
			bz->offset = 0;
			if (bz->bzstream.avail_in == 0) {
				unsigned        n = bz->region->length;

				if (!bz->region->indeterminate) {
					n -= bz->region->readc;
					if (n > sizeof(bz->in))
						n = sizeof(bz->in);
				} else
					n = sizeof(bz->in);

				if (!pgp_stacked_limited_read(stream,
						(uint8_t *) bz->in,
						n, bz->region,
						errors, readinfo, cbinfo))
					return -1;

				bz->bzstream.next_in = bz->in;
				bz->bzstream.avail_in =
					(bz->region->indeterminate) ?
					 bz->region->last_read : n;
			}
			ret = BZ2_bzDecompress(&bz->bzstream);
			if (ret == BZ_STREAM_END) {
				if (!bz->region->indeterminate &&
				    bz->region->readc != bz->region->length)
					PGP_ERROR_1(cbinfo->errors,
						PGP_E_P_DECOMPRESSION_ERROR,
						"%s",
						"Compressed stream ended before packet end.");
			} else if (ret != BZ_OK) {
				PGP_ERROR_1(cbinfo->errors,
					PGP_E_P_DECOMPRESSION_ERROR,
					"Invalid return %d from BZ2_bzDecompress", ret);
			}
			bz->inflate_ret = ret;
		}
		if (bz->bzstream.next_out <= &bz->out[bz->offset]) {
			(void) fprintf(stderr, "Out of bz memroy\n");
			return 0;
		}
		len = (size_t)(bz->bzstream.next_out - &bz->out[bz->offset]);
		if (len > length) {
			len = length;
		}
		(void) memcpy(&cdest[cc], &bz->out[bz->offset], len);
		bz->offset += len;
	}

	return (int)length;
}
Exemplo n.º 4
0
int 
pgp_decompress(pgp_region_t *region, pgp_stream_t *stream,
	       pgp_compression_type_t type)
{
	z_decompress_t z;
#ifdef HAVE_BZLIB_H
	bz_decompress_t bz;
#endif
	const int	printerrors = 1;
	int             ret;

	switch (type) {
	case PGP_C_ZIP:
	case PGP_C_ZLIB:
		(void) memset(&z, 0x0, sizeof(z));

		z.region = region;
		z.offset = 0;
		z.type = type;

		z.zstream.next_in = Z_NULL;
		z.zstream.avail_in = 0;
		z.zstream.next_out = z.out;
		z.zstream.zalloc = Z_NULL;
		z.zstream.zfree = Z_NULL;
		z.zstream.opaque = Z_NULL;

		break;

#ifdef HAVE_BZLIB_H
	case PGP_C_BZIP2:
		(void) memset(&bz, 0x0, sizeof(bz));

		bz.region = region;
		bz.offset = 0;
		bz.type = type;

		bz.bzstream.next_in = NULL;
		bz.bzstream.avail_in = 0;
		bz.bzstream.next_out = bz.out;
		bz.bzstream.bzalloc = NULL;
		bz.bzstream.bzfree = NULL;
		bz.bzstream.opaque = NULL;
#endif

		break;

	default:
		PGP_ERROR_1(&stream->errors,
			PGP_E_ALG_UNSUPPORTED_COMPRESS_ALG,
			"Compression algorithm %d is not yet supported", type);
		return 0;
	}

	switch (type) {
	case PGP_C_ZIP:
		/* LINTED */ /* this is a lint problem in zlib.h header */
		ret = (int)inflateInit2(&z.zstream, -15);
		break;

	case PGP_C_ZLIB:
		/* LINTED */ /* this is a lint problem in zlib.h header */
		ret = (int)inflateInit(&z.zstream);
		break;

#ifdef HAVE_BZLIB_H
	case PGP_C_BZIP2:
		ret = BZ2_bzDecompressInit(&bz.bzstream, 1, 0);
		break;
#endif

	default:
		PGP_ERROR_1(&stream->errors,
			PGP_E_ALG_UNSUPPORTED_COMPRESS_ALG,
			"Compression algorithm %d is not yet supported", type);
		return 0;
	}

	switch (type) {
	case PGP_C_ZIP:
	case PGP_C_ZLIB:
		if (ret != Z_OK) {
			PGP_ERROR_1(&stream->errors,
				PGP_E_P_DECOMPRESSION_ERROR,
"Cannot initialise ZIP or ZLIB stream for decompression: error=%d", ret);
			return 0;
		}
		pgp_reader_push(stream, zlib_compressed_data_reader,
					NULL, &z);
		break;

#ifdef HAVE_BZLIB_H
	case PGP_C_BZIP2:
		if (ret != BZ_OK) {
			PGP_ERROR_1(&stream->errors,
				PGP_E_P_DECOMPRESSION_ERROR,
"Cannot initialise BZIP2 stream for decompression: error=%d", ret);
			return 0;
		}
		pgp_reader_push(stream, bzip2_compressed_data_reader,
					NULL, &bz);
		break;
#endif

	default:
		PGP_ERROR_1(&stream->errors,
			PGP_E_ALG_UNSUPPORTED_COMPRESS_ALG,
			"Compression algorithm %d is not yet supported", type);
		return 0;
	}

	ret = pgp_parse(stream, !printerrors);

	pgp_reader_pop(stream);

	return ret;
}
Exemplo n.º 5
0
/*
 * \todo remove code duplication between this and
 * bzip2_compressed_data_reader
 */
static int 
zlib_compressed_data_reader(pgp_stream_t *stream, void *dest, size_t length,
			    pgp_error_t **errors,
			    pgp_reader_t *readinfo,
			    pgp_cbdata_t *cbinfo)
{
	z_decompress_t *z = pgp_reader_get_arg(readinfo);
	size_t           len;
	size_t		 cc;
	char		*cdest = dest;

	if (z->type != PGP_C_ZIP && z->type != PGP_C_ZLIB) {
		(void) fprintf(stderr,
			"zlib_compressed_data_reader: weird type %d\n",
			z->type);
		return 0;
	}

	if (z->inflate_ret == Z_STREAM_END &&
	    z->zstream.next_out == &z->out[z->offset]) {
		return 0;
	}
	if (pgp_get_debug_level(__FILE__)) {
		(void) fprintf(stderr,
			"zlib_compressed_data_reader: length %" PRIsize "d\n",
			length);
	}
	for (cc = 0 ; cc < length ; cc += len) {
		if (&z->out[z->offset] == z->zstream.next_out) {
			int             ret;

			z->zstream.next_out = z->out;
			z->zstream.avail_out = sizeof(z->out);
			z->offset = 0;
			if (z->zstream.avail_in == 0) {
				unsigned        n = z->region->length;

				if (!z->region->indeterminate) {
					n -= z->region->readc;
					if (n > sizeof(z->in)) {
						n = sizeof(z->in);
					}
				} else {
					n = sizeof(z->in);
				}
				if (!pgp_stacked_limited_read(stream, z->in, n,
						z->region,
						errors, readinfo, cbinfo)) {
					return -1;
				}

				z->zstream.next_in = z->in;
				z->zstream.avail_in = (z->region->indeterminate) ?
					z->region->last_read : n;
			}
			ret = inflate(&z->zstream, Z_SYNC_FLUSH);
			if (ret == Z_STREAM_END) {
				if (!z->region->indeterminate &&
				    z->region->readc != z->region->length) {
					PGP_ERROR_1(cbinfo->errors,
						PGP_E_P_DECOMPRESSION_ERROR,
						"%s",
						"Compressed stream ended before packet end.");
				}
			} else if (ret != Z_OK) {
				(void) fprintf(stderr, "ret=%d\n", ret);
				PGP_ERROR_1(cbinfo->errors,
					PGP_E_P_DECOMPRESSION_ERROR, "%s",
					z->zstream.msg);
			}
			z->inflate_ret = ret;
		}
		if (z->zstream.next_out <= &z->out[z->offset]) {
			(void) fprintf(stderr, "Out of memory in buffer\n");
			return 0;
		}
		len = (size_t)(z->zstream.next_out - &z->out[z->offset]);
		if (len > length) {
			len = length;
		}
		(void) memcpy(&cdest[cc], &z->out[z->offset], len);
		z->offset += len;
	}

	return (int)length;
}