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