Esempio n. 1
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. 2
0
/**
 * \ingroup Core_WritePackets
 * \brief Writes a Public Key packet
 * \param key
 * \param output
 * \return 1 if OK, otherwise 0
 */
static unsigned 
write_struct_pubkey(pgp_output_t *output, const pgp_pubkey_t *key)
{
	return pgp_write_ptag(output, PGP_PTAG_CT_PUBLIC_KEY) &&
		pgp_write_length(output, 1 + 4 + 1 + pubkey_length(key)) &&
		write_pubkey_body(key, output);
}
Esempio n. 3
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. 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_write_ss_header(pgp_output_t *output,
			unsigned length,
			pgp_content_enum type)
{
	return pgp_write_length(output, length) &&
		pgp_write_scalar(output, (unsigned)(type -
				(unsigned)PGP_PTAG_SIG_SUBPKT_BASE), 1);
}
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
/**
\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. 8
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. 9
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. 10
0
/**
 * \ingroup Core_WritePackets
 * \brief Writes a Secret Key packet.
 * \param key The secret key
 * \param passphrase The passphrase
 * \param pplen Length of passphrase
 * \param output
 * \return 1 if OK; else 0
 */
unsigned 
pgp_write_struct_seckey(const pgp_seckey_t *key,
			    const uint8_t *passphrase,
			    const size_t pplen,
			    pgp_output_t *output)
{
	int             length = 0;

	if (key->pubkey.version != 4) {
		(void) fprintf(stderr,
			"pgp_write_struct_seckey: public key version\n");
		return 0;
	}

	/* Ref: RFC4880 Section 5.5.3 */

	/* pubkey, excluding MPIs */
	length += 1 + 4 + 1 + 1;

	/* s2k usage */
	length += 1;

	switch (key->s2k_usage) {
	case PGP_S2KU_NONE:
		/* nothing to add */
		break;

	case PGP_S2KU_ENCRYPTED_AND_HASHED:	/* 254 */
	case PGP_S2KU_ENCRYPTED:	/* 255 */

		/* Ref: RFC4880 Section 3.7 */
		length += 1;	/* s2k_specifier */

		switch (key->s2k_specifier) {
		case PGP_S2KS_SIMPLE:
			length += 1;	/* hash algorithm */
			break;

		case PGP_S2KS_SALTED:
			length += 1 + 8;	/* hash algorithm + salt */
			break;

		case PGP_S2KS_ITERATED_AND_SALTED:
			length += 1 + 8 + 1;	/* hash algorithm, salt +
						 * count */
			break;

		default:
			(void) fprintf(stderr,
				"pgp_write_struct_seckey: s2k spec\n");
			return 0;
		}
		break;

	default:
		(void) fprintf(stderr,
			"pgp_write_struct_seckey: s2k usage\n");
		return 0;
	}

	/* IV */
	if (key->s2k_usage) {
		length += pgp_block_size(key->alg);
	}
	/* checksum or hash */
	switch (key->s2k_usage) {
	case PGP_S2KU_NONE:
	case PGP_S2KU_ENCRYPTED:
		length += 2;
		break;

	case PGP_S2KU_ENCRYPTED_AND_HASHED:
		length += PGP_CHECKHASH_SIZE;
		break;

	default:
		(void) fprintf(stderr,
			"pgp_write_struct_seckey: s2k cksum usage\n");
		return 0;
	}

	/* secret key and public key MPIs */
	length += (unsigned)seckey_length(key);

	return pgp_write_ptag(output, PGP_PTAG_CT_SECRET_KEY) &&
		/* pgp_write_length(output,1+4+1+1+seckey_length(key)+2) && */
		pgp_write_length(output, (unsigned)length) &&
		write_seckey_body(key, passphrase, pplen, output);
}
Esempio n. 11
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. 12
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;
}