Beispiel #1
0
int sftp_mac_set_read_key(pool *p, const EVP_MD *hash, const BIGNUM *k,
    const char *h, uint32_t hlen) {
  const unsigned char *id = NULL;
  char *buf, *ptr;
  uint32_t buflen, bufsz, id_len;
  char letter;
  size_t blocksz;
  struct sftp_mac *mac;
  HMAC_CTX *mac_ctx;

  switch_read_mac();

  mac = &(read_macs[read_mac_idx]);
  mac_ctx = &(read_ctxs[read_mac_idx]);

  bufsz = buflen = 1024;
  ptr = buf = sftp_msg_getbuf(p, bufsz);

  /* Need to use SSH2-style format of K for the key. */
  sftp_msg_write_mpint(&buf, &buflen, k);

  id_len = sftp_session_get_id(&id);

  /* HASH(K || H || "E" || session_id) */
  letter = 'E';
  set_mac_key(mac, hash, ptr, (bufsz - buflen), h, hlen, &letter, id, id_len);

#if OPENSSL_VERSION_NUMBER > 0x000907000L
  HMAC_CTX_init(mac_ctx);

# if OPENSSL_VERSION_NUMBER >= 0x10000001L
  if (HMAC_Init_ex(mac_ctx, mac->key, mac->key_len, mac->digest, NULL) != 1) {
    pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "error initializing HMAC: %s", sftp_crypto_get_errors());
    errno = EPERM;
    return -1;
  }

# else
  HMAC_Init_ex(mac_ctx, mac->key, mac->key_len, mac->digest, NULL);
# endif /* OpenSSL-1.0.0 and later */

#else
  /* Reset the HMAC context. */
  HMAC_Init(mac_ctx, NULL, 0, NULL);
  HMAC_Init(mac_ctx, mac->key, mac->key_len, mac->digest);
#endif

  if (mac->mac_len == 0) {
    blocksz = EVP_MD_size(mac->digest);

  } else {
    blocksz = mac->mac_len;
  }

  pr_memscrub(ptr, bufsz);
  sftp_mac_set_block_size(blocksz);
  return 0;
}
Beispiel #2
0
int sftp_cipher_write_data(struct ssh2_packet *pkt, unsigned char *buf,
    size_t *buflen) {
  struct sftp_cipher *cipher;
  EVP_CIPHER_CTX *cipher_ctx;

  cipher = &(write_ciphers[write_cipher_idx]);
  cipher_ctx = write_ctxs[write_cipher_idx];

  if (cipher->key) {
    int res;
    unsigned char *data, *ptr;
    uint32_t datalen, datasz = sizeof(uint32_t) + pkt->packet_len;

    datalen = datasz;
    ptr = data = palloc(pkt->pool, datasz);

    sftp_msg_write_int(&data, &datalen, pkt->packet_len);
    sftp_msg_write_byte(&data, &datalen, pkt->padding_len);
    sftp_msg_write_data(&data, &datalen, pkt->payload, pkt->payload_len, FALSE);
    sftp_msg_write_data(&data, &datalen, pkt->padding, pkt->padding_len, FALSE);

    res = EVP_Cipher(cipher_ctx, buf, ptr, (datasz - datalen));
    if (res != 1) {
      (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "error encrypting %s data for client: %s", cipher->algo,
        sftp_crypto_get_errors());
      errno = EIO;
      return -1;
    }

    *buflen = (datasz - datalen);

#ifdef SFTP_DEBUG_PACKET
{
  unsigned int i;

  (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
    "encrypted packet data (len %lu):", (unsigned long) *buflen);
  for (i = 0; i < *buflen;) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "  %02x%02x %02x%02x %02x%02x %02x%02x",
      ((unsigned char *) buf)[i], ((unsigned char *) buf)[i+1],
      ((unsigned char *) buf)[i+2], ((unsigned char *) buf)[i+3],
      ((unsigned char *) buf)[i+4], ((unsigned char *) buf)[i+5],
      ((unsigned char *) buf)[i+6], ((unsigned char *) buf)[i+7]);
    i += 8;
  }
}
#endif

    return 0;
  }

  *buflen = 0;
  return 0;
}
Beispiel #3
0
int sftp_cipher_read_data(pool *p, unsigned char *data, uint32_t data_len,
    unsigned char **buf, uint32_t *buflen) {
  struct sftp_cipher *cipher;
  EVP_CIPHER_CTX *cipher_ctx;
  size_t cipher_blocksz;

  cipher = &(read_ciphers[read_cipher_idx]);
  cipher_ctx = read_ctxs[read_cipher_idx];
  cipher_blocksz = cipher_blockszs[read_cipher_idx];

  if (cipher->key) {
    int res;
    unsigned char *ptr = NULL;
    size_t bufsz;

    if (*buflen % cipher_blocksz != 0) {
      (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "bad input length for decryption (%u bytes, %u block size)", *buflen,
        (unsigned int) cipher_blocksz);
      return -1;
    }

    if (*buf == NULL) {
      /* Allocate a buffer that's large enough. */
      bufsz = (data_len + cipher_blocksz - 1);
      ptr = palloc(p, bufsz);

    } else {
      ptr = *buf;
    }

    res = EVP_Cipher(cipher_ctx, ptr, data, data_len);
    if (res != 1) {
      (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "error decrypting %s data from client: %s", cipher->algo,
        sftp_crypto_get_errors());
      return -1;
    }

    *buflen = data_len;
    *buf = ptr;

    return 0;
  }

  *buf = data;
  *buflen = data_len;
  return 0;
}
Beispiel #4
0
static void switch_read_cipher(void) {
  /* First, clear the context of the existing read cipher, if any. */
  if (read_ciphers[read_cipher_idx].key) {
    clear_cipher(&(read_ciphers[read_cipher_idx]));
    if (EVP_CIPHER_CTX_cleanup(read_ctxs[read_cipher_idx]) != 1) {
      (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "error clearing cipher context: %s", sftp_crypto_get_errors());
    }
 
    cipher_blockszs[read_cipher_idx] = SFTP_CIPHER_DEFAULT_BLOCK_SZ; 

    /* Now we can switch the index. */
    if (read_cipher_idx == 1) {
      read_cipher_idx = 0;
      return;
    }

    read_cipher_idx = 1;
  }
}
Beispiel #5
0
/* If the chosen cipher requires that we discard some of the initial bytes of
 * the cipher stream, then do so.  (This is mostly for any RC4 ciphers.)
 */
static int set_cipher_discarded(struct sftp_cipher *cipher,
    EVP_CIPHER_CTX *cipher_ctx) {
  unsigned char *garbage_in, *garbage_out;

  if (cipher->discard_len == 0) {
    return 0;
  }

  garbage_in = malloc(cipher->discard_len);
  if (garbage_in == NULL) {
    pr_log_pri(PR_LOG_ALERT, MOD_SFTP_VERSION ": Out of memory!");
    _exit(1);
  }

  garbage_out = malloc(cipher->discard_len);
  if (garbage_out == NULL) {
    pr_log_pri(PR_LOG_ALERT, MOD_SFTP_VERSION ": Out of memory!");
    free(garbage_in);
    _exit(1);
  }

  if (EVP_Cipher(cipher_ctx, garbage_out, garbage_in,
      cipher->discard_len) != 1) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "error ciphering discard data: %s", sftp_crypto_get_errors());
    free(garbage_in);
    pr_memscrub(garbage_out, cipher->discard_len);
    free(garbage_out);

    return -1;
  }

  free(garbage_in);
  pr_memscrub(garbage_out, cipher->discard_len);
  free(garbage_out);

  return 0;
}
Beispiel #6
0
static struct filestore_key *filestore_get_key(sftp_keystore_t *store,
    pool *p) {
  char *line;
  BIO *bio = NULL;
  struct filestore_key *key = NULL;
  struct filestore_data *store_data = store->keystore_data;
  size_t begin_markerlen = 0, end_markerlen = 0;

  line = filestore_getline(store, p);
  while (line == NULL &&
         errno == EINVAL) {
    line = filestore_getline(store, p);
  }

  begin_markerlen = strlen(SFTP_SSH2_PUBKEY_BEGIN_MARKER);
  end_markerlen = strlen(SFTP_SSH2_PUBKEY_END_MARKER);

  while (line) {
    pr_signals_handle();

    if (key == NULL &&
        strncmp(line, SFTP_SSH2_PUBKEY_BEGIN_MARKER,
        begin_markerlen + 1) == 0) {
      key = pcalloc(p, sizeof(struct filestore_key));
      bio = BIO_new(BIO_s_mem());

    } else if (key != NULL &&
               strncmp(line, SFTP_SSH2_PUBKEY_END_MARKER,
                 end_markerlen + 1) == 0) {
      if (bio) {
        BIO *b64 = NULL, *bmem = NULL;
        char chunk[1024], *data = NULL;
        int chunklen;
        long datalen = 0;

        /* Add a base64 filter BIO, and read the data out, thus base64-decoding
         * the key.  Write the decoded data into another memory BIO.
         */
        b64 = BIO_new(BIO_f_base64());
        BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
        bio = BIO_push(b64, bio);

        bmem = BIO_new(BIO_s_mem());

        memset(chunk, '\0', sizeof(chunk));
        chunklen = BIO_read(bio, chunk, sizeof(chunk));

        if (chunklen < 0 &&
            !BIO_should_retry(bio)) {
          (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
            "unable to base64-decode data in '%s': %s",
            store_data->path, sftp_crypto_get_errors());
          BIO_free_all(bio);
          BIO_free_all(bmem);

          errno = EPERM;
          return NULL;
        }

        while (chunklen > 0) {
          pr_signals_handle();

          if (BIO_write(bmem, chunk, chunklen) < 0) {
            (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
              "error writing to memory BIO: %s", sftp_crypto_get_errors());
            BIO_free_all(bio);
            BIO_free_all(bmem);

            errno = EPERM;
            return NULL;
          }

          memset(chunk, '\0', sizeof(chunk));
          chunklen = BIO_read(bio, chunk, sizeof(chunk));
        }

        datalen = BIO_get_mem_data(bmem, &data);

        if (data != NULL &&
            datalen > 0) {
          key->key_data = palloc(p, datalen);
          key->key_datalen = datalen;
          memcpy(key->key_data, data, datalen);

        } else {
          (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
            "error base64-decoding key data in '%s'", store_data->path);
        }

        BIO_free_all(bio);
        bio = NULL;

        BIO_free_all(bmem);
      }

      break;

    } else {
      if (key) {
        if (strstr(line, ": ") != NULL) {
          if (strncasecmp(line, "Subject: ", 9) == 0) {
            key->subject = pstrdup(p, line + 9);
          }

        } else {
          if (BIO_write(bio, line, strlen(line)) < 0) {
            (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
              "error buffering base64 data");
          }
        }
      }
    }

    line = filestore_getline(store, p);
    while (line == NULL &&
           errno == EINVAL) {
      line = filestore_getline(store, p);
    }
  }

  return key;
}
Beispiel #7
0
int sftp_mac_write_data(struct ssh2_packet *pkt) {
  struct sftp_mac *mac;
  HMAC_CTX *mac_ctx;

  mac = &(write_macs[write_mac_idx]);
  mac_ctx = &(write_ctxs[write_mac_idx]);

  if (mac->key) {
    unsigned char *mac_data;
    char *buf, *ptr;
    uint32_t buflen, bufsz = (sizeof(uint32_t) * 2) + pkt->packet_len,
      mac_len = 0;

    mac_data = pcalloc(pkt->pool, EVP_MAX_MD_SIZE);

    buflen = bufsz;
    ptr = buf = sftp_msg_getbuf(pkt->pool, bufsz);

    sftp_msg_write_int(&buf, &buflen, pkt->seqno);
    sftp_msg_write_int(&buf, &buflen, pkt->packet_len);
    sftp_msg_write_byte(&buf, &buflen, pkt->padding_len);
    sftp_msg_write_data(&buf, &buflen, pkt->payload, pkt->payload_len, FALSE);
    sftp_msg_write_data(&buf, &buflen, pkt->padding, pkt->padding_len, FALSE);

#if OPENSSL_VERSION_NUMBER > 0x000907000L
# if OPENSSL_VERSION_NUMBER >= 0x10000001L
    if (HMAC_Init_ex(mac_ctx, NULL, 0, NULL, NULL) != 1) {
      pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "error resetting HMAC context: %s", sftp_crypto_get_errors());
      errno = EPERM;
      return -1;
    }
# else
    HMAC_Init_ex(mac_ctx, NULL, 0, NULL, NULL);
# endif /* OpenSSL-1.0.0 and later */

#else
    HMAC_Init(mac_ctx, NULL, 0, NULL);
#endif /* OpenSSL-0.9.7 and later */

#if OPENSSL_VERSION_NUMBER >= 0x10000001L
    if (HMAC_Update(mac_ctx, (unsigned char *) ptr, (bufsz - buflen)) != 1) {
      pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "error adding %lu bytes of data to  HMAC context: %s",
        (unsigned long) (bufsz - buflen), sftp_crypto_get_errors());
      errno = EPERM;
      return -1;
    }

    if (HMAC_Final(mac_ctx, mac_data, &mac_len) != 1) {
      pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "error finalizing HMAC context: %s", sftp_crypto_get_errors());
      errno = EPERM;
      return -1;
    }
#else
    HMAC_Update(mac_ctx, (unsigned char *) ptr, (bufsz - buflen));
    HMAC_Final(mac_ctx, mac_data, &mac_len);
#endif /* OpenSSL-1.0.0 and later */

    if (mac_len == 0) {
      pkt->mac = NULL;
      pkt->mac_len = 0;

      (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "error computing MAC using %s: %s", mac->algo,
        sftp_crypto_get_errors());
      return -1;
    }

    if (mac->mac_len != 0) {
      mac_len = mac->mac_len;
    }

    pkt->mac_len = mac_len;
    pkt->mac = pcalloc(pkt->pool, pkt->mac_len);
    memcpy(pkt->mac, mac_data, mac_len);

#ifdef SFTP_DEBUG_PACKET
{
  unsigned int i;

  (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
    "server MAC (len %lu, seqno %lu):",
    (unsigned long) pkt->mac_len, (unsigned long) pkt->seqno);
  for (i = 0; i < mac_len;) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "  %02x%02x %02x%02x %02x%02x %02x%02x",
      ((unsigned char *) pkt->mac)[i], ((unsigned char *) pkt->mac)[i+1],
      ((unsigned char *) pkt->mac)[i+2], ((unsigned char *) pkt->mac)[i+3],
      ((unsigned char *) pkt->mac)[i+4], ((unsigned char *) pkt->mac)[i+5],
      ((unsigned char *) pkt->mac)[i+6], ((unsigned char *) pkt->mac)[i+7]);
    i += 8;
  }
}
#endif

    return 0;
  }

  pkt->mac = NULL;
  pkt->mac_len = 0;

  return 0;
}
Beispiel #8
0
static int set_mac_key(struct sftp_mac *mac, const EVP_MD *hash,
    const char *k, uint32_t klen, const char *h, uint32_t hlen, char *letter,
    const unsigned char *id, uint32_t id_len) {
 
  EVP_MD_CTX ctx;
  unsigned char *key = NULL;
  size_t key_sz;
  uint32_t key_len = 0;
 
  key_sz = sftp_crypto_get_size(EVP_MD_block_size(mac->digest),
    EVP_MD_size(hash)); 

  if (key_sz == 0) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "unable to determine key length for MAC '%s'", mac->algo);
    errno = EINVAL;
    return -1;
  }

  key = malloc(key_sz);
  if (key == NULL) {
    pr_log_pri(PR_LOG_CRIT, MOD_SFTP_VERSION ": Out of memory!");
    _exit(1);
  }

  /* In OpenSSL 0.9.6, many of the EVP_Digest* functions returned void, not
   * int.  Without these ugly OpenSSL version preprocessor checks, the
   * compiler will error out with "void value not ignored as it ought to be".
   */

#if OPENSSL_VERSION_NUMBER >= 0x000907000L
  if (EVP_DigestInit(&ctx, hash) != 1) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "error initializing message digest: %s", sftp_crypto_get_errors());
    free(key);
    return -1;
  }
#else
  EVP_DigestInit(&ctx, hash);
#endif

#if OPENSSL_VERSION_NUMBER >= 0x000907000L
  if (EVP_DigestUpdate(&ctx, k, klen) != 1) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "error updating message digest with K: %s", sftp_crypto_get_errors());
    free(key);
    return -1;
  }
#else
  EVP_DigestUpdate(&ctx, k, klen);
#endif

#if OPENSSL_VERSION_NUMBER >= 0x000907000L
  if (EVP_DigestUpdate(&ctx, h, hlen) != 1) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "error updating message digest with H: %s", sftp_crypto_get_errors());
    free(key);
    return -1;
  }
#else
  EVP_DigestUpdate(&ctx, h, hlen);
#endif

#if OPENSSL_VERSION_NUMBER >= 0x000907000L
  if (EVP_DigestUpdate(&ctx, letter, sizeof(char)) != 1) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "error updating message digest with '%c': %s", *letter,
      sftp_crypto_get_errors());
    free(key);
    return -1;
  }
#else
  EVP_DigestUpdate(&ctx, letter, sizeof(char));
#endif

#if OPENSSL_VERSION_NUMBER >= 0x000907000L
  if (EVP_DigestUpdate(&ctx, (char *) id, id_len) != 1) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "error updating message digest with ID: %s", sftp_crypto_get_errors());
    free(key);
    return -1;
  }
#else
  EVP_DigestUpdate(&ctx, (char *) id, id_len);
#endif

#if OPENSSL_VERSION_NUMBER >= 0x000907000L
  if (EVP_DigestFinal(&ctx, key, &key_len) != 1) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "error finalizing message digest: %s", sftp_crypto_get_errors());
    pr_memscrub(key, key_sz);
    free(key);
    return -1;
  }
#else
  EVP_DigestFinal(&ctx, key, &key_len);
#endif

  /* If we need more, keep hashing, as per RFC, until we have enough
   * material.
   */
  while (key_sz > key_len) {
    uint32_t len = key_len;

    pr_signals_handle();

#if OPENSSL_VERSION_NUMBER >= 0x000907000L
    if (EVP_DigestInit(&ctx, hash) != 1) {
      (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "error initializing message digest: %s", sftp_crypto_get_errors());
      pr_memscrub(key, key_sz);
      free(key);
      return -1;
    }
#else
    EVP_DigestInit(&ctx, hash);
#endif

#if OPENSSL_VERSION_NUMBER >= 0x000907000L
    if (EVP_DigestUpdate(&ctx, k, klen) != 1) {
      (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "error updating message digest with K: %s", sftp_crypto_get_errors());
      pr_memscrub(key, key_sz);
      free(key);
      return -1;
    }
#else
    EVP_DigestUpdate(&ctx, k, klen);
#endif

#if OPENSSL_VERSION_NUMBER >= 0x000907000L
    if (EVP_DigestUpdate(&ctx, h, hlen) != 1) {
      (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "error updating message digest with H: %s", sftp_crypto_get_errors());
      pr_memscrub(key, key_sz);
      free(key);
      return -1;
    }
#else
    EVP_DigestUpdate(&ctx, h, hlen);
#endif

#if OPENSSL_VERSION_NUMBER >= 0x000907000L
    if (EVP_DigestUpdate(&ctx, key, len) != 1) {
      (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "error updating message digest with data: %s",
        sftp_crypto_get_errors());
      pr_memscrub(key, key_sz);
      free(key);
      return -1;
    }
#else
    EVP_DigestUpdate(&ctx, key, len);
#endif

#if OPENSSL_VERSION_NUMBER >= 0x000907000L
    if (EVP_DigestFinal(&ctx, key + len, &len) != 1) {
      (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "error finalizing message digest: %s", sftp_crypto_get_errors());
      pr_memscrub(key, key_sz);
      free(key);
      return -1;
    }
#else
    EVP_DigestFinal(&ctx, key + len, &len);
#endif

    key_len += len;
  }

  mac->key = key;
  mac->keysz = key_sz;

  mac->key_len = EVP_MD_size(mac->digest);
  if (!sftp_interop_supports_feature(SFTP_SSH2_FEAT_MAC_LEN)) {
    mac->key_len = 16;
  }

  return 0;
}
Beispiel #9
0
int sftp_cipher_set_write_key(pool *p, const EVP_MD *hash, const BIGNUM *k,
    const char *h, uint32_t hlen) {
  const unsigned char *id = NULL;
  unsigned char *buf, *ptr;
  char letter;
  uint32_t buflen, bufsz, id_len;
  int key_len;
  struct sftp_cipher *cipher;
  EVP_CIPHER_CTX *cipher_ctx;

  switch_write_cipher();

  cipher = &(write_ciphers[write_cipher_idx]);
  cipher_ctx = write_ctxs[write_cipher_idx];

  /* XXX EVP_CIPHER_CTX_init() first appeared in OpenSSL 0.9.7.  What to do
   * for older OpenSSL installations?
   */
  EVP_CIPHER_CTX_init(cipher_ctx);

  bufsz = buflen = SFTP_CIPHER_BUFSZ;
  ptr = buf = sftp_msg_getbuf(p, bufsz);

  /* Need to use SSH2-style format of K for the IV and key. */
  sftp_msg_write_mpint(&buf, &buflen, k);

  id_len = sftp_session_get_id(&id);

  /* IV: HASH(K || H || "B" || session_id) */
  letter = 'B';
  if (set_cipher_iv(cipher, hash, ptr, (bufsz - buflen), h, hlen, &letter, id,
      id_len) < 0) {
    pr_memscrub(ptr, bufsz);
    return -1;
  }

  key_len = (int) cipher->key_len;

  /* Key: HASH(K || H || "D" || session_id) */
  letter = 'D';
  if (set_cipher_key(cipher, hash, ptr, (bufsz - buflen), h, hlen, &letter,
      id, id_len) < 0) {
    pr_memscrub(ptr, bufsz);
    return -1;
  }

  if (EVP_CipherInit(cipher_ctx, cipher->cipher, cipher->key,
      cipher->iv, 1) != 1) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "error initializing %s cipher for encryption: %s", cipher->algo,
      sftp_crypto_get_errors());
    pr_memscrub(ptr, bufsz);
    return -1;
  }

  if (key_len > 0) {
    /* Next, set the key length. */
    if (EVP_CIPHER_CTX_set_key_length(cipher_ctx, key_len) != 1) {
      (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "error setting key length (%d bytes) for %s cipher for decryption: %s",
        key_len, cipher->algo, sftp_crypto_get_errors());
      pr_memscrub(ptr, bufsz);
      return -1;
    }
  }

  if (set_cipher_discarded(cipher, cipher_ctx) < 0) {
    pr_memscrub(ptr, bufsz);
    return -1;
  }

  pr_memscrub(ptr, bufsz);
  return 0;
}