EVP_AES_128_CBC(3)

πŸ“¦ version 4.4.0, in alpine 3.24, arch rolling

πŸ’… EVP_AES_128_CBC β€” like, the EVP AES cipher page (libcrypto, section 3)

Ok so bestie, this is the libcrypto manual page for the AES cipher family, and honestly it's kind of a bop. We're talking 31 functions here. Thirty-one. Don't panic β€” they're all literally the same shape, just different flavors, and by the end you'll be picking AES modes like you pick a Starbucks order.


✨ NAME ✨

Say hi to the whole squad, because they all show up on this page:

  • EVP_aes_128_cbc, EVP_aes_192_cbc, EVP_aes_256_cbc
  • EVP_aes_128_cfb1, EVP_aes_192_cfb1, EVP_aes_256_cfb1
  • EVP_aes_128_cfb8, EVP_aes_192_cfb8, EVP_aes_256_cfb8
  • EVP_aes_128_cfb128, EVP_aes_192_cfb128, EVP_aes_256_cfb128
  • EVP_aes_128_cfb, EVP_aes_192_cfb, EVP_aes_256_cfb
  • EVP_aes_128_ctr, EVP_aes_192_ctr, EVP_aes_256_ctr
  • EVP_aes_128_ecb, EVP_aes_192_ecb, EVP_aes_256_ecb
  • EVP_aes_128_ofb, EVP_aes_192_ofb, EVP_aes_256_ofb
  • EVP_aes_128_cbc_hmac_sha1, EVP_aes_256_cbc_hmac_sha1
  • EVP_aes_128_wrap, EVP_aes_192_wrap, EVP_aes_256_wrap
  • EVP_aes_128_xts, EVP_aes_256_xts

…all collectively known as the EVP AES cipher. πŸ’–


πŸŽ€ SYNOPSIS πŸŽ€

Pull up libcrypto and include the header, bestie:

library β€œlibcrypto” #include <openssl/evp.h>

And then… yeah. Prepare yourself. Every single one of these bad boys has the exact same signature β€” they take nothing, they give you back a const EVP_CIPHER *. No cap, that's the whole vibe:

const EVP_CIPHER *
EVP_aes_128_cbc(void);

const EVP_CIPHER *
EVP_aes_192_cbc(void);

const EVP_CIPHER *
EVP_aes_256_cbc(void);

const EVP_CIPHER *
EVP_aes_128_cfb1(void);

const EVP_CIPHER *
EVP_aes_192_cfb1(void);

const EVP_CIPHER *
EVP_aes_256_cfb1(void);

const EVP_CIPHER *
EVP_aes_128_cfb8(void);

const EVP_CIPHER *
EVP_aes_192_cfb8(void);

const EVP_CIPHER *
EVP_aes_256_cfb8(void);

const EVP_CIPHER *
EVP_aes_128_cfb128(void);

const EVP_CIPHER *
EVP_aes_192_cfb128(void);

const EVP_CIPHER *
EVP_aes_256_cfb128(void);

const EVP_CIPHER *
EVP_aes_128_cfb(void);

const EVP_CIPHER *
EVP_aes_192_cfb(void);

const EVP_CIPHER *
EVP_aes_256_cfb(void);

const EVP_CIPHER *
EVP_aes_128_ctr(void);

const EVP_CIPHER *
EVP_aes_192_ctr(void);

const EVP_CIPHER *
EVP_aes_256_ctr(void);

const EVP_CIPHER *
EVP_aes_128_ecb(void);

const EVP_CIPHER *
EVP_aes_192_ecb(void);

const EVP_CIPHER *
EVP_aes_256_ecb(void);

const EVP_CIPHER *
EVP_aes_128_ofb(void);

const EVP_CIPHER *
EVP_aes_192_ofb(void);

const EVP_CIPHER *
EVP_aes_256_ofb(void);

const EVP_CIPHER *
EVP_aes_128_cbc_hmac_sha1(void);

const EVP_CIPHER *
EVP_aes_256_cbc_hmac_sha1(void);

const EVP_CIPHER *
EVP_aes_128_wrap(void);

const EVP_CIPHER *
EVP_aes_192_wrap(void);

const EVP_CIPHER *
EVP_aes_256_wrap(void);

const EVP_CIPHER *
EVP_aes_128_xts(void);

const EVP_CIPHER *
EVP_aes_256_xts(void);

Yes, that's all of them. Yes, I counted. 🫢


🌸 DESCRIPTION 🌸

So here's the tea: these functions hand you the AES encryption algorithm, packaged for the evp(3) framework. AES is a family of block ciphers β€” think of them as little 128-bit block-processing machines β€” and they run on key lengths of 128, 192, and 256 bits. ⭐

πŸ¦‹ The classic mode squad

EVP_aes_128_cbc(), EVP_aes_192_cbc(), EVP_aes_256_cbc(), EVP_aes_128_cfb1(), EVP_aes_192_cfb1(), EVP_aes_256_cfb1(), EVP_aes_128_cfb8(), EVP_aes_192_cfb8(), EVP_aes_256_cfb8(), EVP_aes_128_cfb128(), EVP_aes_192_cfb128(), EVP_aes_256_cfb128(), EVP_aes_128_ctr(), EVP_aes_192_ctr(), EVP_aes_256_ctr(), EVP_aes_128_ecb(), EVP_aes_192_ecb(), EVP_aes_256_ecb(), EVP_aes_128_ofb(), EVP_aes_192_ofb(), and EVP_aes_256_ofb() β€” that whole list up there β€” give you AES for 128, 192, and 256-bit keys in these modes, and yes I'm listing them all because they all ate:

  • CBC
  • CFB with 1-bit shift
  • CFB with 8-bit shift
  • CFB with 128-bit shift
  • CTR
  • ECB
  • OFB

Pick your fighter. πŸ’…

🌈 The aliases (aka the shortcuts)

EVP_aes_128_cfb(), EVP_aes_192_cfb(), and EVP_aes_256_cfb() are literally just aliases for EVP_aes_128_cfb128(), EVP_aes_192_cfb128(), and EVP_aes_256_cfb128(). They're implemented as macros, so don't come for them, they're doing their best and their best is identical. 😌

πŸ”₯ The authenticated encryption girlies

EVP_aes_128_cbc_hmac_sha1() and EVP_aes_256_cbc_hmac_sha1() give you authenticated encryption with AES in CBC mode using SHA-1 as the HMAC β€” with keys of 128 and 256-bit length respectively. The authentication tag is 160 bits long. πŸŽ€

⚠️ Okay important: these are not intended for usage outside of TLS, and they require calling some undocumented control functions. Also β€” and this is the part where you go "oh 😭" β€” these ciphers do not conform to the EVP AEAD interface. So like, don't just vibe with them anywhere.

🧚 The key wrap trio

EVP_aes_128_wrap(), EVP_aes_192_wrap(), and EVP_aes_256_wrap() give you AES key wrap with 128, 192, and 256-bit keys, according to RFC 3394 section 2.2.1 ("wrap"). Iconic citation behavior. πŸ‘‘

But listen β€” there's a whole ritual here. When you later pass the returned EVP_CIPHER object to EVP_CipherInit_ex(3), EVP_EncryptInit_ex(3), or EVP_DecryptInit_ex(3) alongside an EVP_CIPHER_CTX object, the flag EVP_CIPHER_CTX_FLAG_WRAP_ALLOW must have been set in the EVP_CIPHER_CTX using EVP_CIPHER_CTX_set_flags(3).

πŸ’€ If you don't do that β€” or if you pass the returned EVP_CIPHER object to EVP_CipherInit(3), EVP_EncryptInit(3), or EVP_DecryptInit(3) β€” initialization fails with a β€œwrap not allowed” error. Not me forgetting the flag. πŸ™ˆ

πŸ’œ The storage-device one

EVP_aes_128_xts() and EVP_aes_256_xts() provide XEX-based tweaked-codebook mode with ciphertext stealing (XTS-AES, iykyk) as specified in IEEE Std. 1619-2007 and described in NIST SP 800-38E. πŸ“š

Quick rundown of what that means:

  • It was designed for encrypting data on a storage device πŸ“
  • It provides confidentiality but not authentication of data β€” so, no integrity check, just vibes and secrecy, be aware
  • It requires a key of double length for protection of a certain key size

Specifically: XTS-AES-128 takes input of a 256-bit key to achieve AES 128-bit security, and XTS-AES-256 takes input of a 512-bit key to achieve AES 256-bit security. Math is math. ✨


πŸ‘‘ RETURN VALUES πŸ‘‘

These functions return an EVP_CIPHER structure that provides the implementation of the symmetric cipher. That's it. That's the return value. Short, sweet, slays. πŸ’–


πŸŽ€ SEE ALSO πŸŽ€

Go read these next, bestie β€” they're all linked and they're all valid:


⭐ HISTORY ⭐

Storytime. πŸ•°οΈ

  • EVP_aes_128_cbc(), EVP_aes_192_cbc(), EVP_aes_256_cbc(), EVP_aes_128_cfb(), EVP_aes_192_cfb(), EVP_aes_256_cfb(), EVP_aes_128_ebc(), EVP_aes_192_ebc(), EVP_aes_256_ebc(), EVP_aes_128_ofb(), EVP_aes_192_ofb(), and EVP_aes_256_ofb() first appeared in OpenSSL 0.9.7 and have been available since OpenBSD 3.2. (And yes, the page really does say EVP_aes_128_ebc() β€” I'm copying it exactly, not my typo, don't @ me πŸ’€)
  • EVP_aes_128_cfb1(), EVP_aes_192_cfb1(), EVP_aes_256_cfb1(), EVP_aes_128_cfb8(), EVP_aes_192_cfb8(), EVP_aes_256_cfb8(), EVP_aes_128_cfb128(), EVP_aes_192_cfb128(), and EVP_aes_256_cfb128() first appeared in OpenSSL 0.9.7e and have been available since OpenBSD 3.8.
  • EVP_aes_128_ctr(), EVP_aes_192_ctr(), EVP_aes_256_ctr(), EVP_aes_128_cbc_hmac_sha1(), EVP_aes_256_cbc_hmac_sha1(), EVP_aes_128_xts(), and EVP_aes_256_xts() first appeared in OpenSSL 1.0.1 and have been available since OpenBSD 5.3.
  • EVP_aes_128_wrap(), EVP_aes_192_wrap(), and EVP_aes_256_wrap() first appeared in OpenSSL 1.0.2 and have been available since OpenBSD 6.5.

✨ That's the whole page, bestie! ✨ This masterpiece landed in the Debian build of the manual, dated June 8, 2025, and it lives at EVP_AES_128_CBC(3). Go encrypt something responsibly, set your EVP_CIPHER_CTX_FLAG_WRAP_ALLOW flags, and remember: confidentiality β‰  authentication, periodt. πŸ’…πŸ¦‹πŸ’–

πŸ“¦ where this page comes from