EVP_EncryptUpdate() encrypts B<inl> bytes from the buffer B<in> and
writes the encrypted version to B<out>. This function can be called
multiple times to encrypt successive blocks of data. The amount
-of data written depends on the block alignment of the encrypted data:
-as a result the amount of data written may be anything from zero bytes
-to (inl + cipher_block_size - 1) so B<out> should contain sufficient
-room. The actual number of bytes written is placed in B<outl>. It also
+of data written depends on the block alignment of the encrypted data.
+For most ciphers and modes, the amount of data written can be anything
+from zero bytes to (inl + cipher_block_size - 1) bytes.
+For wrap cipher modes, the amount of data written can be anything
+from zero bytes to (inl + cipher_block_size) bytes.
+For stream ciphers, the amount of data written can be anything from zero
+bytes to inl bytes.
+Thus, B<out> should contain sufficient room for the operation being performed.
+The actual number of bytes written is placed in B<outl>. It also
checks if B<in> and B<out> are partially overlapping, and if they are
0 is returned to indicate failure.
return 1;
}
+Encryption using AES-CBC with a 256-bit key with "CS1" ciphertext stealing.
+
+ int encrypt(const unsigned char *key, const unsigned char *iv,
+ const unsigned char *msg, size_t msg_len, unsigned char *out)
+ {
+ /*
+ * This assumes that key size is 32 bytes and the iv is 16 bytes.
+ * For ciphertext stealing mode the length of the ciphertext "out" will be
+ * the same size as the plaintext size "msg_len".
+ * The "msg_len" can be any size >= 16.
+ */
+ int ret = 0, encrypt = 1, outlen, len;
+ EVP_CIPHER_CTX *ctx = NULL;
+ EVP_CIPHER *cipher = NULL;
+ OSSL_PARAM params[2];
+
+ ctx = EVP_CIPHER_CTX_new();
+ cipher = EVP_CIPHER_fetch(NULL, "AES-256-CBC-CTS", NULL);
+ if (ctx == NULL || cipher == NULL)
+ goto err;
+
+ if (!EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, encrypt))
+ goto err;
+ /*
+ * The default is "CS1" so this is not really needed,
+ * but would be needed to set either "CS2" or "CS3".
+ */
+ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_CIPHER_PARAM_CTS_MODE,
+ "CS1", 0);
+ params[1] = OSSL_PARAM_construct_end();
+ if (!EVP_CIPHER_CTX_set_params(ctx, params))
+ goto err;
+
+ /* NOTE: CTS mode does not support multiple calls to EVP_CipherUpdate() */
+ if (!EVP_CipherUpdate(ctx, encrypted, &outlen, msg, msglen))
+ goto err;
+ if (!EVP_CipherFinal_ex(ctx, encrypted + outlen, &len))
+ goto err;
+ ret = 1;
+ err:
+ EVP_CIPHER_free(cipher);
+ EVP_CIPHER_CTX_free(ctx);
+ return ret;
+ }
=head1 SEE ALSO