]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
apc_pub_encrypt: Let the callee allocate the buffer.
authorAndre Noll <maan@tuebingen.mpg.de>
Tue, 2 May 2023 21:56:26 +0000 (23:56 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Thu, 16 May 2024 23:36:55 +0000 (01:36 +0200)
Change the encryption routine of the apc API to allocate a suitably
sized buffer itself. Currently, the caller has to guess the size of the
buffer to pass to the function and we reuse our 4k handshake buffer for
that. While 4k is is plenty at the moment, that may change, and it's
always better to use the exact size if it is readily available. This
is the case here because the required buffer size is just the number
of bits of the modulus of the key.

command.c
crypt.h
gcrypt.c
openssl.c

index bddb9cf0b16ed7387fc8f3520ff92db699dac28d..78c9106c9ff84062e874b326a386f7073e09aeca 100644 (file)
--- a/command.c
+++ b/command.c
@@ -922,7 +922,8 @@ int handle_connect(int fd)
        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;
@@ -942,16 +943,16 @@ int handle_connect(int fd)
        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;
@@ -962,12 +963,12 @@ int handle_connect(int fd)
                 * 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,
diff --git a/crypt.h b/crypt.h
index 5578cd563fae4dc24d673e653dcf21329eba90bc..6507099507b1eb336fc9509732099319884665ca 100644 (file)
--- a/crypt.h
+++ b/crypt.h
@@ -20,12 +20,12 @@ struct asymmetric_key;
  * \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.
index b46f8f9555824eb86b7bbf600b4352558ed2db26..68f80f27fc30ff70fed05d5a7f7f8c89ef995260 100644 (file)
--- a/gcrypt.c
+++ b/gcrypt.c
@@ -114,6 +114,7 @@ void crypt_shutdown(void)
 
 struct asymmetric_key {
        gcry_sexp_t sexp;
+       int bits;
 };
 
 static const char *gcrypt_strerror(gcry_error_t gret)
@@ -457,6 +458,7 @@ int apc_get_pubkey(const char *key_file, struct asymmetric_key **result)
        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:
@@ -554,7 +556,7 @@ free_key:
 }
 
 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;
@@ -562,6 +564,7 @@ int apc_pub_encrypt(struct asymmetric_key *pub, unsigned char *inbuf,
        size_t nbytes;
        int ret;
 
+       *outbuf = NULL;
        /* get pub key */
        pub_key = gcry_sexp_find_token(pub->sexp, "public-key", 0);
        if (!pub_key)
@@ -590,14 +593,18 @@ int apc_pub_encrypt(struct asymmetric_key *pub, unsigned char *inbuf,
                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:
index 495d83c2bae0671a7f7d9f0e75a89900bfb4cecb..acf1120dd139aeb121a1533108f0f07b24dc6e61 100644 (file)
--- a/openssl.c
+++ b/openssl.c
@@ -310,15 +310,22 @@ out:
 }
 
 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 {