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