Esempio n. 1
0
/**
 * @brief
 *  Load an EC public key from a file.
 * @param filename
 *  the name of the file from which the key should be loaded
 * @return
 *  a pointer to the deserialized public key from the the file.
 */
EC_KEY * _load_ec_pubkey(char const *filename) {
	char *filedata;
	unsigned char *bin;
	size_t binsize;
	EC_KEY *result;

	if (!filename) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	}

	if (!(filedata = _read_pem_data(filename, "PUBLIC KEY", 1))) {
		RET_ERROR_PTR(ERR_UNSPEC, "could not read ec pubkey pem file");
	}

	bin = _b64decode(filedata, strlen(filedata), &binsize);
	_secure_wipe(filedata, strlen(filedata));
	free(filedata);
	if (!bin) {
		RET_ERROR_PTR(ERR_UNSPEC, "could not decode b64 data");
	}

	result = _deserialize_ec_pubkey(bin, binsize);
	_secure_wipe(bin, binsize);
	free(bin);
	if (!result) {
		RET_ERROR_PTR(ERR_UNSPEC, "could not deserialize binary ec pubkey");
	}

	return result;
}
Esempio n. 2
0
/**
 * @brief	Retrieves the encryption key from the keys file.
 * @param	filename	Null terminated filename string.
 * @return	Pointer to the elliptic curve encryption key.
 * @free_using{free_ec_key}
*/
static EC_KEY *keys_fetch_enc_key(const char *filename) {

	size_t keys_len;
	unsigned char *keys_bin;
	EC_KEY *key;

	if(!filename) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	} else if(!strlen(filename)) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	}

	if(!(keys_bin = keys_file_serialize(filename, &keys_len))) {
		RET_ERROR_PTR(ERR_UNSPEC, "could not retrieve keys binary string");
	}

	key = keys_serial_get_enc_key(keys_bin, keys_len);
	_secure_wipe(keys_bin, keys_len);
	free(keys_bin);

	if (!key) {
		RET_ERROR_PTR_FMT(ERR_UNSPEC, "could not retrieve ed25519 signing key from %s", filename);
	}

	return key;
}
Esempio n. 3
0
/**
 * @brief
 *  Free an ed25519 keypair.
 * @param key
 *  a pointer to the ed25519 keypair to be freed.
 */
void _free_ed25519_key(ED25519_KEY *key) {
	if (!key) {
		return;
	}

	_secure_wipe(key, sizeof(ED25519_KEY));
	free(key);
}
Esempio n. 4
0
/**
 * @brief
 *  Load an ed25519 private key from a file.
 * @param filename
 *  the path of the armored file from which the ed25519 private key will be
 *  loaded.
 * @return
 *  a pointer to a newly allocated ed25519 keypair on success, or NULL on
 *  failure.
 */
ED25519_KEY * _load_ed25519_privkey(char const *filename) {
	ED25519_KEY *result;
	unsigned char *keydata;
	char *pemdata;
	size_t klen;

	if (!filename) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	}

	if (!(pemdata = _read_pem_data(filename, "ED25519 PRIVATE KEY", 1))) {
		RET_ERROR_PTR(ERR_UNSPEC, "unable to read ed25519 private key data from PEM file");
	}

	keydata = _b64decode(pemdata, strlen(pemdata), &klen);
	_secure_wipe(pemdata, strlen(pemdata));
	free(pemdata);

	if (!keydata || (klen != ED25519_KEY_SIZE)) {

		if (keydata) {
			_secure_wipe(keydata, klen);
			free(keydata);
		}

		RET_ERROR_PTR(ERR_UNSPEC, "bad ED25519 key data was read from file");
	}

	if (!(result = malloc(sizeof(ED25519_KEY)))) {
		PUSH_ERROR_SYSCALL("malloc");
		_secure_wipe(keydata, klen);
		free(keydata);
		RET_ERROR_PTR(ERR_NOMEM, "unable to allocate space for ED25519 key");
	}

	memset(result, 0, sizeof(ED25519_KEY));
	memcpy(result->private_key, keydata, sizeof(result->private_key));
	_secure_wipe(keydata, klen);
	free(keydata);
	ed25519_publickey_donna(result->private_key, result->public_key);

	return result;
}
Esempio n. 5
0
/**
 * @brief
 *  Compute a derived AES-256 key from the intersection of a public EC key and
 *  a private EC key.
 */
int _compute_aes256_kek(EC_KEY *public_key, EC_KEY *private_key, unsigned char *keybuf) {
	unsigned char aeskey[SHA_512_SIZE];

	if (!public_key || !private_key || !keybuf) {
		RET_ERROR_INT(ERR_BAD_PARAM, NULL);
	}

	if (ECDH_compute_key_d(aeskey, sizeof(aeskey), EC_KEY_get0_public_key_d(public_key), private_key, _ecies_env_derivation) != SHA_512_SIZE) {
		PUSH_ERROR_OPENSSL();
		RET_ERROR_INT(ERR_UNSPEC, "could not derive AES key from EC keypair");
	}

	for (size_t i = 0; i < 16; ++i) {
		keybuf[i] = aeskey[i] ^ aeskey[i + 16];
	}

	memcpy(keybuf + 16, aeskey + 32, 32);
	_secure_wipe(aeskey, sizeof(aeskey));

	return 0;
}
Esempio n. 6
0
/**
 * @brief
 *  Generate an ed25519 key pair.
 * @return
 *  a newly allocated and generated ed25519 key pair on success, or NULL on
 *  failure.
 */
ED25519_KEY * _generate_ed25519_keypair(void) {
	ED25519_KEY *result;

	if (!(result = malloc(sizeof(ED25519_KEY)))) {
		PUSH_ERROR_SYSCALL("malloc");
		RET_ERROR_PTR(ERR_NOMEM, "could not generate ed25519 key because of "
			"memory allocation error");
	}

	memset(result, 0, sizeof(ED25519_KEY));

	if (RAND_bytes_d(result->private_key, sizeof(result->private_key)) != 1) {
		PUSH_ERROR_OPENSSL();
		_secure_wipe(result, sizeof(ED25519_KEY));
		free(result);
		RET_ERROR_PTR(ERR_UNSPEC, "could not generate ed25519 secret key");
	}

	ed25519_publickey_donna(result->private_key, result->public_key);

	return result;
}
Esempio n. 7
0
/**
 * @brief	Creates a keys file with specified signing and encryption keys.
 * @param	type	        Type of keys file, whether the keys correspond to a user or organizational signet.
 * @param	sign_key        Pointer to the specified ed25519 key, the private portion of which will be stored in the keys file as the signing key.
 * @param	enc_key		Pointer to the specified elliptic curve key, the private portion of which will be stored in the keys file as the encryption key.
 * @param	filename	Pointer to the NULL terminated string containing the filename for the keys file.
 * @return	0 on success, -1 on failure.
*/
static int keys_file_create(keys_type_t type, ED25519_KEY *sign_key, EC_KEY *enc_key, const char *filename) {

	char *b64_keys = NULL;
	int res;
	size_t serial_size = 0, enc_size = 0, at = 0;;
	unsigned char *serial_keys = NULL, *serial_enc = NULL, serial_sign[ED25519_KEY_SIZE], sign_fid, enc_fid;
	dime_number_t number;

	if(!sign_key || !enc_key || !filename) {
		RET_ERROR_INT(ERR_BAD_PARAM, NULL);
	}

	switch(type) {

	case KEYS_TYPE_ORG:
		number = DIME_ORG_KEYS;
		sign_fid = KEYS_ORG_PRIVATE_POK;
		enc_fid = KEYS_ORG_PRIVATE_ENC;
		break;
	case KEYS_TYPE_USER:
		number = DIME_USER_KEYS;
		sign_fid = KEYS_USER_PRIVATE_SIGN;
		enc_fid = KEYS_USER_PRIVATE_ENC;
		break;
	default:
		RET_ERROR_INT(ERR_BAD_PARAM, NULL);
		break;

	}

	memcpy(serial_sign, sign_key->private_key, ED25519_KEY_SIZE);

	if(!(serial_enc = _serialize_ec_privkey(enc_key, &enc_size))) {
		_secure_wipe(serial_sign, ED25519_KEY_SIZE);
		RET_ERROR_INT(ERR_UNSPEC, "could not serialize private key");
	}

	serial_size = KEYS_HEADER_SIZE + 1 + 1 + ED25519_KEY_SIZE + 1 + 2 + enc_size;

	if(!(serial_keys = malloc(serial_size))) {
		PUSH_ERROR_SYSCALL("malloc");
		_secure_wipe(serial_sign, ED25519_KEY_SIZE);
		_secure_wipe(serial_enc, enc_size);
		free(serial_enc);
		RET_ERROR_INT(ERR_NOMEM, NULL);
	}

	memset(serial_keys, 0, serial_size);
	_int_no_put_2b(serial_keys, (uint16_t)number);
	_int_no_put_3b(serial_keys + 2, (uint32_t)(serial_size - KEYS_HEADER_SIZE));
	at = KEYS_HEADER_SIZE;
	serial_keys[at++] = sign_fid;
	serial_keys[at++] = ED25519_KEY_SIZE;
	memcpy(serial_keys + at, serial_sign, ED25519_KEY_SIZE);
	at += ED25519_KEY_SIZE;
	_secure_wipe(serial_sign, ED25519_KEY_SIZE);
	serial_keys[at++] = enc_fid;
	_int_no_put_2b(serial_keys + at, (uint16_t)enc_size);
	at += 2;
	memcpy(serial_keys + at, serial_enc, enc_size);
	_secure_wipe(serial_enc, enc_size);
	free(serial_enc);

	b64_keys = _b64encode(serial_keys, serial_size);
	_secure_wipe(serial_keys, serial_size);
	free(serial_keys);

	if (!b64_keys) {
		RET_ERROR_INT(ERR_UNSPEC, "could not base64 encode the keys");
	}

	res = _write_pem_data(b64_keys, SIGNET_PRIVATE_KEYCHAIN, filename);
	_secure_wipe(b64_keys, strlen(b64_keys));
	free(b64_keys);

	if(res < 0) {
		RET_ERROR_INT(ERR_UNSPEC, "could not store keys in PEM file.");
	}

	return 0;
}