summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/src/lib/prov/commoncrypto/commoncrypto_utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/botan/src/lib/prov/commoncrypto/commoncrypto_utils.cpp')
-rw-r--r--comm/third_party/botan/src/lib/prov/commoncrypto/commoncrypto_utils.cpp196
1 files changed, 196 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/prov/commoncrypto/commoncrypto_utils.cpp b/comm/third_party/botan/src/lib/prov/commoncrypto/commoncrypto_utils.cpp
new file mode 100644
index 0000000000..59e501dd7e
--- /dev/null
+++ b/comm/third_party/botan/src/lib/prov/commoncrypto/commoncrypto_utils.cpp
@@ -0,0 +1,196 @@
+/*
+* Cipher Modes via CommonCrypto
+* (C) 2018 Jose Pereira
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/internal/commoncrypto.h>
+#include <botan/internal/commoncrypto_utils.h>
+#include <botan/cipher_mode.h>
+#include <botan/parsing.h>
+#include <botan/internal/rounding.h>
+#include <botan/scan_name.h>
+
+namespace Botan {
+
+std::string CommonCrypto_Error::ccryptorstatus_to_string(CCCryptorStatus status)
+ {
+ switch(status)
+ {
+ case kCCSuccess:
+ return "Success";
+ case kCCParamError:
+ return "ParamError";
+ case kCCBufferTooSmall:
+ return "BufferTooSmall";
+ case kCCMemoryFailure:
+ return "MemoryFailure";
+ case kCCAlignmentError:
+ return "AlignmentError";
+ case kCCDecodeError:
+ return "DecodeError";
+ case kCCUnimplemented:
+ return "Unimplemented";
+ case kCCOverflow:
+ return "Overflow";
+ case kCCRNGFailure:
+ return "RNGFailure";
+ case kCCUnspecifiedError:
+ return "UnspecifiedError";
+ case kCCCallSequenceError:
+ return "CallSequenceError";
+ case kCCKeySizeError:
+ return "KeySizeError";
+ default:
+ return "Unknown";
+ }
+ };
+
+
+CommonCryptor_Opts commoncrypto_opts_from_algo_name(const std::string& algo_name)
+ {
+ CommonCryptor_Opts opts;
+
+ if(algo_name.compare(0, 3, "AES") == 0)
+ {
+ opts.algo = kCCAlgorithmAES;
+ opts.block_size = kCCBlockSizeAES128;
+ if(algo_name == "AES-128")
+ {
+ opts.key_spec = Key_Length_Specification(kCCKeySizeAES128);
+ }
+ else if(algo_name == "AES-192")
+ {
+ opts.key_spec = Key_Length_Specification(kCCKeySizeAES192);
+ }
+ else if(algo_name == "AES-256")
+ {
+ opts.key_spec = Key_Length_Specification(kCCKeySizeAES256);
+ }
+ else
+ {
+ throw CommonCrypto_Error("Unknown AES algorithm");
+ }
+ }
+ else if(algo_name == "DES")
+ {
+ opts.algo = kCCAlgorithmDES;
+ opts.block_size = kCCBlockSizeDES;
+ opts.key_spec = Key_Length_Specification(kCCKeySizeDES);
+ }
+ else if(algo_name == "TripleDES")
+ {
+ opts.algo = kCCAlgorithm3DES;
+ opts.block_size = kCCBlockSize3DES;
+ opts.key_spec = Key_Length_Specification(16, kCCKeySize3DES, 8);
+ }
+ else if(algo_name == "Blowfish")
+ {
+ opts.algo = kCCAlgorithmBlowfish;
+ opts.block_size = kCCBlockSizeBlowfish;
+ opts.key_spec = Key_Length_Specification(1, kCCKeySizeMaxBlowfish, 1);
+ }
+ else if(algo_name == "CAST-128")
+ {
+ opts.algo = kCCAlgorithmCAST;
+ opts.block_size = kCCBlockSizeCAST;
+ // Botan's base implementation of CAST does not support shorter keys
+ // so we limit its minimum key size to 11 here.
+ opts.key_spec = Key_Length_Specification(11, kCCKeySizeMaxCAST, 1);
+ }
+ else
+ {
+ throw CommonCrypto_Error("Unsupported cipher");
+ }
+
+ return opts;
+ }
+
+
+CommonCryptor_Opts commoncrypto_opts_from_algo(const std::string& algo)
+ {
+ SCAN_Name spec(algo);
+
+ std::string algo_name = spec.algo_name();
+ std::string cipher_mode = spec.cipher_mode();
+ std::string cipher_mode_padding = spec.cipher_mode_pad();
+
+ CommonCryptor_Opts opts = commoncrypto_opts_from_algo_name(algo_name);
+
+ //TODO add CFB and XTS support
+ if(cipher_mode.empty() || cipher_mode == "ECB")
+ {
+ opts.mode = kCCModeECB;
+ }
+ else if(cipher_mode == "CBC")
+ {
+ opts.mode = kCCModeCBC;
+ }
+ else if(cipher_mode == "CTR")
+ {
+ opts.mode = kCCModeCTR;
+ }
+ else if(cipher_mode == "OFB")
+ {
+ opts.mode = kCCModeOFB;
+ }
+ else
+ {
+ throw CommonCrypto_Error("Unsupported cipher mode!");
+ }
+
+ if(cipher_mode_padding == "NoPadding")
+ {
+ opts.padding = ccNoPadding;
+ }
+ /*
+ else if(cipher_mode_padding.empty() || cipher_mode_padding == "PKCS7")
+ {
+ opts.padding = ccPKCS7Padding;
+ }
+ */
+ else
+ {
+ throw CommonCrypto_Error("Unsupported cipher mode padding!");
+ }
+
+ return opts;
+ }
+
+
+void commoncrypto_adjust_key_size(const uint8_t key[], size_t length,
+ const CommonCryptor_Opts& opts, secure_vector<uint8_t>& full_key)
+ {
+
+ if(opts.algo == kCCAlgorithmBlowfish && length < 8)
+ {
+ size_t repeat;
+ switch(length)
+ {
+ case 1:
+ repeat = 8;
+ break;
+ case 2:
+ repeat = 4;
+ break;
+ case 3:
+ repeat = 3;
+ break;
+ default:
+ repeat = 2;
+ break;
+ }
+
+ full_key.resize(length * repeat);
+ for(size_t i = 0; i < repeat; i++)
+ {
+ copy_mem(full_key.data() + i * length, key, length);
+ }
+ }
+ else if(opts.algo == kCCAlgorithm3DES && length == 16)
+ {
+ full_key += std::make_pair(key, 8);
+ }
+ }
+}