/**
* CBC block cipher mode.
- * 16-byte initialization vector is mandatory.
- * 16-byte initialization vector for AES,
- * 8-byte for other algorithms is mandatory.
++ * 16-byte initialization vector for AES,
++ * 8-byte for other algorithms is mandatory.
+ *
+ * By default the input data is padded using standard block padding (aka PKCS#5 padding).
+ * Padding can be disabled using yaca_context_set_property() and #YACA_PROPERTY_PADDING, #YACA_PADDING_NONE,
+ * then the total length of data passed until *_finalize() MUST be a multiple of block size.
+ * #YACA_PROPERTY_PADDING can be set at the latest before the *_finalize() call.
*/
YACA_BCM_CBC,
if (algo_name == NULL || bcm_name == NULL || key_bit_len == 0)
return YACA_ERROR_INVALID_PARAMETER;
+ ret = check_key_bit_length_for_algo(algo, key_bit_len);
+ if (ret != YACA_ERROR_NONE)
+ return ret;
+
switch (algo) {
case YACA_ENCRYPT_AES:
- ret = snprintf(cipher_name, sizeof(cipher_name), "%s-%zu-%s",
- algo_name, key_bit_len, bcm_name);
+ if (bcm == YACA_BCM_WRAP)
+ ret = snprintf(cipher_name, sizeof(cipher_name), "id-%s%zu-%s",
+ algo_name, key_bit_len, bcm_name);
+ else
+ ret = snprintf(cipher_name, sizeof(cipher_name), "%s-%zu-%s",
+ algo_name, key_bit_len, bcm_name);
break;
case YACA_ENCRYPT_UNSAFE_DES:
case YACA_ENCRYPT_UNSAFE_RC2:
if (c == NULL || input_len == 0 || output_len == NULL || op_type != c->op_type)
return YACA_ERROR_INVALID_PARAMETER;
- if (EVP_CIPHER_CTX_mode(c->cipher_ctx) != EVP_CIPH_CCM_MODE)
- if (input == NULL || output == NULL)
+ mode = EVP_CIPHER_CTX_mode(c->cipher_ctx);
+ type = EVP_CIPHER_type(c->cipher_ctx->cipher);
+
+ if (mode != EVP_CIPH_CCM_MODE && (input == NULL || output == NULL))
return YACA_ERROR_INVALID_PARAMETER;
+ if (mode == EVP_CIPH_WRAP_MODE && c->update_called == true)
+ return YACA_ERROR_INVALID_PARAMETER;
+
+ if (mode == EVP_CIPH_WRAP_MODE && op_type == OP_ENCRYPT) {
+ if (type == NID_id_aes128_wrap || type == NID_id_aes192_wrap || type == NID_id_aes256_wrap) {
+ if (input_len % 8 != 0 || input_len < (YACA_KEY_LENGTH_UNSAFE_128BIT / 8))
+ return YACA_ERROR_INVALID_PARAMETER;
+ } else if (type == NID_id_smime_alg_CMS3DESwrap) {
+ if (input_len != (YACA_KEY_LENGTH_UNSAFE_128BIT / 8) && input_len != (YACA_KEY_LENGTH_192BIT / 8))
+ return YACA_ERROR_INVALID_PARAMETER;
+ } else {
+ assert(false);
+ return YACA_ERROR_INTERNAL;
+ }
+ }
+
+ /* Fix for OpenSSL error in 3DES CFB1 */
+ if ((c->cipher_ctx->flags & EVP_CIPH_FLAG_LENGTH_BITS) != 0) {
+ if (input_len > INT_MAX / 8)
+ return YACA_ERROR_INVALID_PARAMETER;
+ input_len *= 8;
+ }
+
ret = EVP_CipherUpdate(c->cipher_ctx, output, &loutput_len, input, input_len);
if (ret != 1 || loutput_len < 0) {
ret = YACA_ERROR_INTERNAL;
}
*output_len = loutput_len;
+ c->update_called = true;
+
+ /* Fix for OpenSSL error in 3DES CFB1 */
+ if ((c->cipher_ctx->flags & EVP_CIPH_FLAG_LENGTH_BITS) != 0)
+ *output_len /= 8;
+
return YACA_ERROR_NONE;
}