Botan 3.3.0
Crypto and TLS for C&
commoncrypto_utils.cpp
Go to the documentation of this file.
1/*
2* Cipher Modes via CommonCrypto
3* (C) 2018 Jose Pereira
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/internal/commoncrypto.h>
9
10#include <botan/cipher_mode.h>
11#include <botan/mem_ops.h>
12#include <botan/internal/commoncrypto_utils.h>
13#include <botan/internal/fmt.h>
14#include <botan/internal/parsing.h>
15#include <botan/internal/scan_name.h>
16
17namespace Botan {
18
19CommonCrypto_Error::CommonCrypto_Error(std::string_view what) : Exception(what), m_rc(0) {}
20
21CommonCrypto_Error::CommonCrypto_Error(std::string_view what, int32_t status) :
22 Exception(fmt("CommonCrypto op {} failed with err {} ({})", what, status, ccryptorstatus_to_string(status))),
23 m_rc(status) {}
24
25std::string CommonCrypto_Error::ccryptorstatus_to_string(CCCryptorStatus status) {
26 switch(status) {
27 case kCCSuccess:
28 return "Success";
29 case kCCParamError:
30 return "ParamError";
31 case kCCBufferTooSmall:
32 return "BufferTooSmall";
33 case kCCMemoryFailure:
34 return "MemoryFailure";
35 case kCCAlignmentError:
36 return "AlignmentError";
37 case kCCDecodeError:
38 return "DecodeError";
39 case kCCUnimplemented:
40 return "Unimplemented";
41 case kCCOverflow:
42 return "Overflow";
43 case kCCRNGFailure:
44 return "RNGFailure";
45 case kCCUnspecifiedError:
46 return "UnspecifiedError";
47 case kCCCallSequenceError:
48 return "CallSequenceError";
49 case kCCKeySizeError:
50 return "KeySizeError";
51 default:
52 return "Unknown";
53 }
54};
55
58
59 if(algo_name.compare(0, 3, "AES") == 0) {
60 opts.algo = kCCAlgorithmAES;
61 opts.block_size = kCCBlockSizeAES128;
62 if(algo_name == "AES-128") {
63 opts.key_spec = Key_Length_Specification(kCCKeySizeAES128);
64 } else if(algo_name == "AES-192") {
65 opts.key_spec = Key_Length_Specification(kCCKeySizeAES192);
66 } else if(algo_name == "AES-256") {
67 opts.key_spec = Key_Length_Specification(kCCKeySizeAES256);
68 } else {
69 throw CommonCrypto_Error("Unknown AES algorithm");
70 }
71 } else if(algo_name == "DES") {
72 opts.algo = kCCAlgorithmDES;
73 opts.block_size = kCCBlockSizeDES;
74 opts.key_spec = Key_Length_Specification(kCCKeySizeDES);
75 } else if(algo_name == "TripleDES") {
76 opts.algo = kCCAlgorithm3DES;
77 opts.block_size = kCCBlockSize3DES;
78 opts.key_spec = Key_Length_Specification(16, kCCKeySize3DES, 8);
79 } else if(algo_name == "Blowfish") {
80 opts.algo = kCCAlgorithmBlowfish;
81 opts.block_size = kCCBlockSizeBlowfish;
82 opts.key_spec = Key_Length_Specification(1, kCCKeySizeMaxBlowfish, 1);
83 } else if(algo_name == "CAST-128") {
84 opts.algo = kCCAlgorithmCAST;
85 opts.block_size = kCCBlockSizeCAST;
86 // Botan's base implementation of CAST does not support shorter keys
87 // so we limit its minimum key size to 11 here.
88 opts.key_spec = Key_Length_Specification(11, kCCKeySizeMaxCAST, 1);
89 } else {
90 throw CommonCrypto_Error("Unsupported cipher");
91 }
92
93 return opts;
94}
95
97 SCAN_Name spec(algo);
98
99 std::string algo_name = spec.algo_name();
100 std::string cipher_mode = spec.cipher_mode();
101 std::string cipher_mode_padding = spec.cipher_mode_pad();
102
104
105 //TODO add CFB and XTS support
106 if(cipher_mode.empty() || cipher_mode == "ECB") {
107 opts.mode = kCCModeECB;
108 } else if(cipher_mode == "CBC") {
109 opts.mode = kCCModeCBC;
110 } else if(cipher_mode == "CTR") {
111 opts.mode = kCCModeCTR;
112 } else if(cipher_mode == "OFB") {
113 opts.mode = kCCModeOFB;
114 } else {
115 throw CommonCrypto_Error("Unsupported cipher mode!");
116 }
117
118 if(cipher_mode_padding == "NoPadding") {
119 opts.padding = ccNoPadding;
120 }
121 /*
122 else if(cipher_mode_padding.empty() || cipher_mode_padding == "PKCS7")
123 {
124 opts.padding = ccPKCS7Padding;
125 }
126 */
127 else {
128 throw CommonCrypto_Error("Unsupported cipher mode padding!");
129 }
130
131 return opts;
132}
133
134void commoncrypto_adjust_key_size(const uint8_t key[],
135 size_t length,
136 const CommonCryptor_Opts& opts,
137 secure_vector<uint8_t>& full_key) {
138 if(opts.algo == kCCAlgorithmBlowfish && length < 8) {
139 size_t repeat;
140 switch(length) {
141 case 1:
142 repeat = 8;
143 break;
144 case 2:
145 repeat = 4;
146 break;
147 case 3:
148 repeat = 3;
149 break;
150 default:
151 repeat = 2;
152 break;
153 }
154
155 full_key.resize(length * repeat);
156 for(size_t i = 0; i < repeat; i++) {
157 copy_mem(full_key.data() + i * length, key, length);
158 }
159 } else if(opts.algo == kCCAlgorithm3DES && length == 16) {
160 full_key += std::make_pair(key, 8);
161 }
162}
163} // namespace Botan
CommonCrypto_Error(std::string_view what)
const std::string & algo_name() const
Definition scan_name.h:44
std::string cipher_mode_pad() const
Definition scan_name.h:94
std::string cipher_mode() const
Definition scan_name.h:89
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
int32_t CCCryptorStatus
void commoncrypto_adjust_key_size(const uint8_t key[], size_t length, const CommonCryptor_Opts &opts, secure_vector< uint8_t > &full_key)
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:146
CommonCryptor_Opts commoncrypto_opts_from_algo(std::string_view algo)
CommonCryptor_Opts commoncrypto_opts_from_algo_name(std::string_view algo_name)
Key_Length_Specification key_spec