NEWS
====
-
+----------------------------------------------
+0.6.3 (to be announced) "generalized activity"
+----------------------------------------------
+
+- The ff command now accepts a negative argument to instruct the
+ virtual streaming system to jump backwards in the current audio
+ stream. The old syntax (e.g., "ff 30-") is still supported but it
+ is deprecated and no longer documented. The compatibility code is
+ sheduled for removal after 0.7.0.
+- para_afh: New option: --preserve to reset the modification time to
+ the value of the original file after meta data modification.
+- Overhaul of the compress filter code. The refined algorithm should
+ reduce clipping. The meaning of --aggressiveness has changed, see the
+ updated and extended documentation of the compress filter for details.
+- Cleanup of the audio format handler code.
+- We now build the tree using the .ONESHELL feature of GNU make,
+ which results in a significant speedup.
+- Two robustness fixes for FreeBSD.
++- para_client now supports RFC4716 private keys as generated with
++ ssh-keygen -m RFC4716. In fact, this key format has been made the
++ default, and the former PEM keys will be depreciated at some point.
+
--------------------------------------
0.6.2 (2018-06-30) "elastic diversity"
--------------------------------------
PARA_ERROR(OGG_PACKET_IN, "ogg_stream_packetin() failed"), \
PARA_ERROR(OGG_STREAM_FLUSH, "ogg_stream_flush() failed"), \
PARA_ERROR(OGG_SYNC, "internal ogg storage overflow"), \
+ PARA_ERROR(OPENSSH_PARSE, "could not parse openssh private key"), \
PARA_ERROR(OPUS_COMMENT, "invalid or corrupted opus comment"), \
PARA_ERROR(OPUS_DECODE, "opus decode error"), \
PARA_ERROR(OPUS_HEADER, "invalid opus header"), \
enum para_error_codes {PARA_ERRORS};
#undef PARA_ERROR
#define PARA_ERROR(err, msg) msg
-/** Array of error strings. */
+/** All .c files need the declararation of the array of error strings. */
extern const char * const para_errlist[];
+/** Exactly one .c file per executable must define the array. */
#define DEFINE_PARA_ERRLIST const char * const para_errlist[] = {PARA_ERRORS}
/**
*/
#define SYSTEM_ERROR_BIT 30
-/**
- * Like the SYSTEM_ERROR_BIT, but indicates an error from the osl library.
- */
+/** Like SYSTEM_ERROR_BIT, but for errors from the osl library. */
#define OSL_ERROR_BIT 29
+/** Like SYSTEM_ERROR_BIT, but for errors from the lopsub library. */
#define LLS_ERROR_BIT 28
/** Check whether the system error bit is set. */
void crypt_shutdown(void)
{
+#ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
CRYPTO_cleanup_all_ex_data();
+#endif
}
- static int get_private_key(const char *path, RSA **rsa)
- {
- EVP_PKEY *pkey;
- BIO *bio = BIO_new(BIO_s_file());
-
- *rsa = NULL;
- if (!bio)
- return -E_PRIVATE_KEY;
- if (BIO_read_filename(bio, path) <= 0)
- goto bio_free;
- pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
- if (!pkey)
- goto bio_free;
- *rsa = EVP_PKEY_get1_RSA(pkey);
- EVP_PKEY_free(pkey);
- bio_free:
- BIO_free(bio);
- return *rsa? RSA_size(*rsa) : -E_PRIVATE_KEY;
- }
-
/*
* The public key loading functions below were inspired by corresponding code
* of openssh-5.2p1, Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo,
return ret;
}
+ static int read_pem_private_key(const char *path, RSA **rsa)
+ {
+ EVP_PKEY *pkey;
+ BIO *bio = BIO_new(BIO_s_file());
+
+ *rsa = NULL;
+ if (!bio)
+ return -E_PRIVATE_KEY;
+ if (BIO_read_filename(bio, path) <= 0)
+ goto bio_free;
+ pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
+ if (!pkey)
+ goto bio_free;
+ *rsa = EVP_PKEY_get1_RSA(pkey);
+ EVP_PKEY_free(pkey);
+ bio_free:
+ BIO_free(bio);
+ return *rsa? RSA_size(*rsa) : -E_PRIVATE_KEY;
+ }
+
+ static int read_private_rsa_params(const unsigned char *blob,
+ const unsigned char *end, RSA **result)
+ {
+ int ret;
+ RSA *rsa;
+ BN_CTX *ctx;
+ BIGNUM *n, *e, *d, *iqmp, *p, *q; /* stored in the key file */
+ BIGNUM *dmp1, *dmq1; /* these will be computed */
+ BIGNUM *tmp;
+ const unsigned char *cp = blob;
+
+ rsa = RSA_new();
+ if (!rsa)
+ return -E_BIGNUM;
+ ret = -E_BIGNUM;
+ tmp = BN_new();
+ if (!tmp)
+ goto free_rsa;
+ ctx = BN_CTX_new();
+ if (!ctx)
+ goto free_tmp;
+ dmp1 = BN_new();
+ if (!dmp1)
+ goto free_ctx;
+ dmq1 = BN_new();
+ if (!dmq1)
+ goto free_dmp1;
+ ret = read_bignum(cp, end - cp, &n);
+ if (ret < 0)
+ goto free_dmq1;
+ cp += ret;
+ ret = read_bignum(cp, end - cp, &e);
+ if (ret < 0)
+ goto free_n;
+ cp += ret;
+ ret = read_bignum(cp, end - cp, &d);
+ if (ret < 0)
+ goto free_e;
+ cp += ret;
+ ret = read_bignum(cp, end - cp, &iqmp);
+ if (ret < 0)
+ goto free_d;
+ cp += ret;
+ ret = read_bignum(cp, end - cp, &p);
+ if (ret < 0)
+ goto free_iqmp;
+ cp += ret;
+ ret = read_bignum(cp, end - cp, &q);
+ if (ret < 0)
+ goto free_p;
+ ret = -E_BIGNUM;
+ if (!BN_sub(tmp, q, BN_value_one()))
+ goto free_q;
+ if (!BN_mod(dmp1, d, tmp, ctx))
+ goto free_q;
+ if (!BN_sub(tmp, q, BN_value_one()))
+ goto free_q;
+ if (!BN_mod(dmq1, d, tmp, ctx))
+ goto free_q;
+ #ifdef HAVE_RSA_SET0_KEY
+ RSA_set0_key(rsa, n, e, d);
+ RSA_set0_factors(rsa, p, q);
+ RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp);
+ #else
+ rsa->n = n;
+ rsa->e = e;
+ rsa->d = d;
+ rsa->p = p;
+ rsa->q = q;
+ rsa->dmp1 = dmp1;
+ rsa->dmq1 = dmq1;
+ rsa->iqmp = iqmp;
+ #endif
+ *result = rsa;
+ ret = 1;
+ goto free_ctx;
+ free_q:
+ BN_clear_free(q);
+ free_p:
+ BN_clear_free(p);
+ free_iqmp:
+ BN_clear_free(iqmp);
+ free_d:
+ BN_clear_free(d);
+ free_e:
+ BN_free(e);
+ free_n:
+ BN_free(n);
+ free_dmq1:
+ BN_clear_free(dmq1);
+ free_dmp1:
+ BN_clear_free(dmp1);
+ free_ctx:
+ BN_CTX_free(ctx);
+ free_tmp:
+ BN_clear_free(tmp);
+ free_rsa:
+ if (ret < 0)
+ RSA_free(rsa);
+ return ret;
+ }
+
+ static int get_private_key(const char *path, RSA **rsa)
+ {
+ int ret;
+ unsigned char *blob, *end;
+ size_t blob_size;
+
+ *rsa = NULL;
+ ret = decode_private_key(path, &blob, &blob_size);
+ if (ret < 0)
+ return ret;
+ end = blob + blob_size;
+ if (ret == PKT_OPENSSH) {
+ ret = find_openssh_bignum_offset(blob, blob_size);
+ if (ret < 0)
+ goto free_blob;
+ PARA_INFO_LOG("reading RSA params at offset %d\n", ret);
+ ret = read_private_rsa_params(blob + ret, end, rsa);
+ } else
+ ret = read_pem_private_key(path, rsa);
+ free_blob:
+ free(blob);
+ return ret;
+ }
+
int apc_get_pubkey(const char *key_file, struct asymmetric_key **result)
{
unsigned char *blob;
int ret;
struct asymmetric_key *key = para_malloc(sizeof(*key));
- ret = decode_ssh_key(key_file, &blob, &decoded_size);
+ ret = decode_public_key(key_file, &blob, &decoded_size);
if (ret < 0)
goto out;
ret = read_rsa_bignums(blob + ret, decoded_size - ret, &key->rsa);