Sí, esto se explica por cómo funcionan estos modos.
Nota: La entrada al modo debe ser un múltiplo del tamaño de bloque. (Es por eso que esto puede ser inferior a 128 bits para un cifrado de 128 bits)
Ahora observa cómo funciona CBC:
NewBlock(LastCiphertextBlock,PlaintextBlock):=Encrypt(LastCiphertextBlock XOR PlaintextBlock)
Como puede ver, esto solo puede cifrar un múltiplo del tamaño de bloque real del cifrado.
Ahora veamos cómo funciona OFB:
NewBlock(State,Plaintext):=State=Encrypt(State);return State XOR Plaintext
Así que básicamente estás cifrando un estado una y otra vez y utilizas este estado como relleno para cifrar el texto plano. Por lo tanto, estás convirtiendo tu blockcipher en un streamcipher. Como la aplicación ahora puede almacenar el estado y solo generar nuevos estados como se ha usado cada bit anterior, uno puede cifrar tamaños de datos arbitrarios.
Ahora investiguemos CTR:
NewBlock(Counter,Plaintext):=Counter++;return Encrypt(Counter) XOR Plaintext
Como ves, esta es exactamente la misma lógica que con OFB, generas el pad usando algún estado (el contador). Como puede almacenar este pad hasta que se necesite el siguiente bloque de pads, puede cifrar los datos bit a bit.
Finalmente vamos a sumergirnos en (n-bit-) CFB:
NewBlock(LastCipherTextBlock,Plaintext):=Plaintext XOR Encrypt(LastCipherTextBlock)
De nuevo, estás convirtiendo a un cifrado de flujo, pero esta vez tomas el bloque de texto cifrado anterior (que es conocido), lo cifras y lo XORAS contra el texto plano. Como puede volver a almacenar el pad y no realizar ninguna operación de tamaño de bloque en el texto plano, puede usar tamaños de texto simple arbitrarios.