int ret;
unsigned char rand_buf[APC_CHALLENGE_SIZE + 2 * SESSION_KEY_LEN];
unsigned char challenge_hash[HASH2_SIZE];
- char *command = NULL, *buf = alloc(HANDSHAKE_BUFSIZE) /* must be on the heap */;
+ char *command = NULL, *buf = NULL, hsbuf[HANDSHAKE_BUFSIZE];
+ unsigned char *crypt_buf;
size_t numbytes;
struct command_context cc_struct = {.u = NULL}, *cc = &cc_struct;
struct iovec iov;
if (ret < 0)
goto net_err;
/* recv auth request line */
- ret = recv_buffer(fd, buf, HANDSHAKE_BUFSIZE);
+ ret = recv_buffer(fd, hsbuf, HANDSHAKE_BUFSIZE);
if (ret < 0)
goto net_err;
- ret = parse_auth_request(buf, ret, &cc->u, &cf);
+ ret = parse_auth_request(hsbuf, ret, &cc->u, &cf);
if (ret < 0)
goto net_err;
if (cc->u) {
get_random_bytes_or_die(rand_buf, sizeof(rand_buf));
ret = apc_pub_encrypt(cc->u->pubkey, rand_buf, sizeof(rand_buf),
- (unsigned char *)buf);
+ &crypt_buf);
if (ret < 0)
goto net_err;
numbytes = ret;
* fail the authentication later.
*/
numbytes = 256;
- get_random_bytes_or_die((unsigned char *)buf, numbytes);
+ crypt_buf = alloc(numbytes);
+ get_random_bytes_or_die(crypt_buf, numbytes);
}
PARA_DEBUG_LOG("sending %d byte challenge + session key (%zu bytes)\n",
APC_CHALLENGE_SIZE, numbytes);
- ret = send_sb(&cc->scc, buf, numbytes, SBD_CHALLENGE, false);
- buf = NULL;
+ ret = send_sb(&cc->scc, crypt_buf, numbytes, SBD_CHALLENGE, false);
if (ret < 0)
goto net_err;
ret = recv_sb(&cc->scc, SBD_CHALLENGE_RESPONSE,
* \param pub: The public key.
* \param inbuf The input buffer.
* \param len The length of \a inbuf.
- * \param outbuf The output buffer.
+ * \param outbuf The output buffer will be allocated by the callee.
*
* \return The size of the encrypted data on success, negative on errors.
*/
int apc_pub_encrypt(struct asymmetric_key *pub, unsigned char *inbuf,
- unsigned len, unsigned char *outbuf);
+ unsigned len, unsigned char **outbuf);
/**
* Decrypt a buffer using a private key.
struct asymmetric_key {
gcry_sexp_t sexp;
+ int bits;
};
static const char *gcrypt_strerror(gcry_error_t gret)
PARA_INFO_LOG("successfully read %u bit ssh public key\n", bits);
key = alloc(sizeof(*key));
key->sexp = sexp;
+ key->bits = bits;
*result = key;
ret = bits / 8;
release_n:
}
int apc_pub_encrypt(struct asymmetric_key *pub, unsigned char *inbuf,
- unsigned len, unsigned char *outbuf)
+ unsigned len, unsigned char **outbuf)
{
gcry_error_t gret;
gcry_sexp_t pub_key, in, out, out_a;
size_t nbytes;
int ret;
+ *outbuf = NULL;
/* get pub key */
pub_key = gcry_sexp_find_token(pub->sexp, "public-key", 0);
if (!pub_key)
ret = -E_SEXP_FIND;
goto out_a_release;
}
- gret = gcry_mpi_print(GCRYMPI_FMT_USG, outbuf, 512 /* FIXME */, &nbytes, out_mpi);
+ *outbuf = alloc(pub->bits);
+ gret = gcry_mpi_print(GCRYMPI_FMT_USG, *outbuf, pub->bits, &nbytes,
+ out_mpi);
if (gret) {
+ free(*outbuf);
+ *outbuf = NULL;
PARA_ERROR_LOG("%s\n", gcrypt_strerror(gret));
ret = -E_SEXP_ENCRYPT;
goto out_mpi_release;
}
PARA_INFO_LOG("encrypted buffer is %zu bytes\n", nbytes);
- dump_buffer("enc buf", outbuf, nbytes);
+ dump_buffer("enc buf", *outbuf, nbytes);
ret = nbytes;
out_mpi_release:
}
int apc_pub_encrypt(struct asymmetric_key *pub, unsigned char *inbuf,
- unsigned len, unsigned char *outbuf)
+ unsigned len, unsigned char **outbuf)
{
int ret, flen = len; /* RSA_public_encrypt expects a signed int */
+ *outbuf = NULL;
if (flen < 0)
return -E_ENCRYPT;
- ret = RSA_public_encrypt(flen, inbuf, outbuf, pub->rsa,
+ *outbuf = alloc(RSA_size(pub->rsa));
+ ret = RSA_public_encrypt(flen, inbuf, *outbuf, pub->rsa,
RSA_PKCS1_OAEP_PADDING);
- return ret < 0? -E_ENCRYPT : ret;
+ if (ret < 0) {
+ free(*outbuf);
+ *outbuf = NULL;
+ return -E_ENCRYPT;
+ }
+ return ret;
}
struct stream_cipher {