8#include <botan/internal/commoncrypto.h>
10#include <botan/cipher_mode.h>
11#include <botan/mem_ops.h>
12#include <botan/internal/commoncrypto_utils.h>
13#include <botan/internal/rounding.h>
21class CommonCrypto_Cipher_Mode
final :
public Cipher_Mode {
23 CommonCrypto_Cipher_Mode(std::string_view
name,
Cipher_Dir direction,
const CommonCryptor_Opts& opts);
25 ~CommonCrypto_Cipher_Mode();
27 std::string provider()
const override {
return "commoncrypto"; }
29 std::string
name()
const override {
return m_mode_name; }
31 size_t output_length(
size_t input_length)
const override;
32 size_t update_granularity()
const override;
33 size_t ideal_granularity()
const override;
34 size_t minimum_final_size()
const override;
35 size_t default_nonce_length()
const override;
36 bool valid_nonce_length(
size_t nonce_len)
const override;
37 void clear()
override;
38 void reset()
override;
39 Key_Length_Specification key_spec()
const override;
41 bool has_keying_material()
const override {
return m_key_set; }
44 void key_schedule(std::span<const uint8_t> key)
override;
46 void start_msg(
const uint8_t nonce[],
size_t nonce_len)
override;
47 size_t process_msg(uint8_t msg[],
size_t msg_len)
override;
50 const std::string m_mode_name;
53 CCCryptorRef m_cipher =
nullptr;
58CommonCrypto_Cipher_Mode::CommonCrypto_Cipher_Mode(std::string_view
name,
60 const CommonCryptor_Opts& opts) :
61 m_mode_name(
name), m_direction(direction),
m_opts(opts),
m_key_set(false), m_nonce_set(false) {}
63CommonCrypto_Cipher_Mode::~CommonCrypto_Cipher_Mode() {
65 CCCryptorRelease(m_cipher);
69void CommonCrypto_Cipher_Mode::start_msg(
const uint8_t nonce[],
size_t nonce_len) {
70 assert_key_material_set();
72 if(!valid_nonce_length(nonce_len)) {
73 throw Invalid_IV_Length(
name(), nonce_len);
77 if(status != kCCSuccess) {
78 throw CommonCrypto_Error(
"CCCryptorReset on start_msg", status);
84size_t CommonCrypto_Cipher_Mode::process_msg(uint8_t msg[],
size_t msg_len) {
85 assert_key_material_set();
91 if(msg_len > INT_MAX) {
94 size_t outl = CCCryptorGetOutputLength(m_cipher, msg_len,
false);
96 secure_vector<uint8_t> out(
outl);
98 if(
m_opts.padding == ccNoPadding && msg_len %
m_opts.block_size) {
103 if(status != kCCSuccess) {
104 throw CommonCrypto_Error(
"CCCryptorUpdate", status);
111void CommonCrypto_Cipher_Mode::finish_msg(secure_vector<uint8_t>& buffer,
size_t offset) {
112 assert_key_material_set();
116 uint8_t* buf = buffer.data() + offset;
117 const size_t buf_size = buffer.size() - offset;
119 size_t written = process(buf, buf_size);
121 size_t outl = CCCryptorGetOutputLength(m_cipher, buf_size - written,
true);
122 secure_vector<uint8_t> out(
outl);
125 if(status != kCCSuccess) {
126 throw CommonCrypto_Error(
"CCCryptorFinal", status);
129 size_t new_len = offset + written +
outl;
130 if(
m_opts.padding != ccNoPadding || buffer.size() < new_len) {
131 buffer.resize(new_len);
133 copy_mem(buffer.data() - offset + written, out.data(),
outl);
137size_t CommonCrypto_Cipher_Mode::update_granularity()
const {
141size_t CommonCrypto_Cipher_Mode::ideal_granularity()
const {
145size_t CommonCrypto_Cipher_Mode::minimum_final_size()
const {
146 if(m_direction == Cipher_Dir::Encryption)
152size_t CommonCrypto_Cipher_Mode::default_nonce_length()
const {
156bool CommonCrypto_Cipher_Mode::valid_nonce_length(
size_t nonce_len)
const {
157 return (nonce_len == 0 || nonce_len ==
m_opts.block_size);
160size_t CommonCrypto_Cipher_Mode::output_length(
size_t input_length)
const {
161 if(input_length == 0) {
168void CommonCrypto_Cipher_Mode::clear() {
171 if(m_cipher ==
nullptr) {
176 CCCryptorRelease(m_cipher);
181void CommonCrypto_Cipher_Mode::reset() {
182 if(m_cipher ==
nullptr) {
189 if(status != kCCSuccess) {
190 throw CommonCrypto_Error(
"CCCryptorReset", status);
194Key_Length_Specification CommonCrypto_Cipher_Mode::key_spec()
const {
198void CommonCrypto_Cipher_Mode::key_schedule(std::span<const uint8_t> key) {
200 CCOperation op = m_direction == Cipher_Dir::Encryption ? kCCEncrypt : kCCDecrypt;
201 status = CCCryptorCreateWithMode(
202 op,
m_opts.mode,
m_opts.algo,
m_opts.padding,
nullptr, key.data(), key.size(),
nullptr, 0, 0, 0, &m_cipher);
203 if(status != kCCSuccess) {
204 throw CommonCrypto_Error(
"CCCryptorCreate", status);
215 return std::make_unique<CommonCrypto_Cipher_Mode>(
name, direction, opts);
#define BOTAN_STATE_CHECK(expr)
#define BOTAN_ASSERT(expr, assertion_made)
CommonCryptor_Opts m_opts
int(* final)(unsigned char *, CTX *)
#define BOTAN_BLOCK_CIPHER_PAR_MULT
std::unique_ptr< Cipher_Mode > make_commoncrypto_cipher_mode(std::string_view name, Cipher_Dir direction)
constexpr size_t round_up(size_t n, size_t align_to)
std::vector< T, secure_allocator< T > > secure_vector
constexpr void copy_mem(T *out, const T *in, size_t n)
CommonCryptor_Opts commoncrypto_opts_from_algo(std::string_view algo)