diff options
Diffstat (limited to 'botan/src/utils')
31 files changed, 2573 insertions, 0 deletions
diff --git a/botan/src/utils/asm_amd64/asm_macr.h b/botan/src/utils/asm_amd64/asm_macr.h new file mode 100644 index 0000000..287fa3e --- /dev/null +++ b/botan/src/utils/asm_amd64/asm_macr.h @@ -0,0 +1,127 @@ +/* +* Assembly Macros +* (C) 1999-2008 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_AMD64_ASM_MACROS_H__ +#define BOTAN_AMD64_ASM_MACROS_H__ + +/* +* General/Global Macros +*/ +#define ALIGN .p2align 4,,15 + +#define START_LISTING(FILENAME) \ + .file #FILENAME; \ + .text; \ + ALIGN; + +#if defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif + +/* +* Function Definitions +*/ +#define START_FUNCTION(func_name) \ + ALIGN; \ + .global func_name; \ + .type func_name,@function; \ +func_name: + +#define END_FUNCTION(func_name) \ + ret + +/* +* Conditional Jumps +*/ +#define JUMP_IF_ZERO(REG, LABEL) \ + cmp IMM(0), REG; \ + jz LABEL + +#define JUMP_IF_LT(REG, NUM, LABEL) \ + cmp IMM(NUM), REG; \ + jl LABEL + +/* +* Register Names +*/ +#define R0 %rax +#define R1 %rbx +#define R2 %rcx +#define R2_32 %ecx +#define R3 %rdx +#define R3_32 %edx +#define R4 %rsp +#define R5 %rbp +#define R6 %rsi +#define R6_32 %esi +#define R7 %rdi +#define R8 %r8 +#define R9 %r9 +#define R9_32 %r9d +#define R10 %r10 +#define R11 %r11 +#define R12 %r12 +#define R13 %r13 +#define R14 %r14 +#define R15 %r15 +#define R16 %r16 + +#define ARG_1 R7 +#define ARG_2 R6 +#define ARG_2_32 R6_32 +#define ARG_3 R3 +#define ARG_3_32 R3_32 +#define ARG_4 R2 +#define ARG_4_32 R2_32 +#define ARG_5 R8 +#define ARG_6 R9 +#define ARG_6_32 R9_32 + +#define TEMP_1 R10 +#define TEMP_2 R11 +#define TEMP_3 ARG_6 +#define TEMP_4 ARG_5 +#define TEMP_5 ARG_4 +#define TEMP_5_32 ARG_4_32 +#define TEMP_6 ARG_3 +#define TEMP_7 ARG_2 +#define TEMP_8 ARG_1 +#define TEMP_9 R0 + +/* +* Memory Access Operations +*/ +#define ARRAY8(REG, NUM) 8*(NUM)(REG) +#define ARRAY4(REG, NUM) 4*(NUM)(REG) + +#define ASSIGN(TO, FROM) mov FROM, TO + +/* +* ALU Operations +*/ +#define IMM(VAL) $VAL + +#define ADD(TO, FROM) add FROM, TO +#define ADD_LAST_CARRY(REG) adc IMM(0), REG +#define ADD_IMM(TO, NUM) ADD(TO, IMM(NUM)) +#define ADD_W_CARRY(TO1, TO2, FROM) add FROM, TO1; adc IMM(0), TO2; +#define SUB_IMM(TO, NUM) sub IMM(NUM), TO +#define MUL(REG) mul REG + +#define XOR(TO, FROM) xor FROM, TO +#define AND(TO, FROM) and FROM, TO +#define OR(TO, FROM) or FROM, TO +#define NOT(REG) not REG +#define ZEROIZE(REG) XOR(REG, REG) + +#define RETURN_VALUE_IS(V) ASSIGN(%rax, V) + +#define ROTL_IMM(REG, NUM) rol IMM(NUM), REG +#define ROTR_IMM(REG, NUM) ror IMM(NUM), REG +#define ADD3_IMM(TO, FROM, NUM) lea NUM(TO,FROM,1), TO + +#endif diff --git a/botan/src/utils/asm_amd64/info.txt b/botan/src/utils/asm_amd64/info.txt new file mode 100644 index 0000000..19035b5 --- /dev/null +++ b/botan/src/utils/asm_amd64/info.txt @@ -0,0 +1,16 @@ +realname "Assembler Macros (x86-64)" + +load_on dep + +<add> +asm_macr.h +</add> + +<arch> +amd64 +</arch> + +<cc> +gcc +icc +</cc> diff --git a/botan/src/utils/asm_ia32/asm_macr.h b/botan/src/utils/asm_ia32/asm_macr.h new file mode 100644 index 0000000..2ea6951 --- /dev/null +++ b/botan/src/utils/asm_ia32/asm_macr.h @@ -0,0 +1,128 @@ +/* +* Assembly Macros +* (C) 1999-2008 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_IA32_ASM_MACROS_H__ +#define BOTAN_IA32_ASM_MACROS_H__ + +/* +* General/Global Macros +*/ +#define ALIGN .p2align 4,,15 + +#define START_LISTING(FILENAME) \ + .file #FILENAME; \ + .text; \ + ALIGN; + +#if defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif + +/* +* Function Definitions +*/ +#define START_FUNCTION(func_name) \ + ALIGN; \ + .global func_name; \ + .type func_name,@function; \ +func_name: + +#define END_FUNCTION(func_name) \ + ret + +/* +* Loop Control +*/ +#define START_LOOP(LABEL) \ + ALIGN; \ + LABEL##_LOOP: + +#define LOOP_UNTIL_EQ(REG, NUM, LABEL) \ + cmpl IMM(NUM), REG; \ + jne LABEL##_LOOP + +#define LOOP_UNTIL_LT(REG, NUM, LABEL) \ + cmpl IMM(NUM), REG; \ + jge LABEL##_LOOP + +/* + Conditional Jumps +*/ +#define JUMP_IF_ZERO(REG, LABEL) \ + cmpl IMM(0), REG; \ + jz LABEL + +#define JUMP_IF_LT(REG, NUM, LABEL) \ + cmpl IMM(NUM), REG; \ + jl LABEL + +/* +* Register Names +*/ +#define EAX %eax +#define EBX %ebx +#define ECX %ecx +#define EDX %edx +#define EBP %ebp +#define EDI %edi +#define ESI %esi +#define ESP %esp + +/* +* Memory Access Operations +*/ +#define ARRAY1(REG, NUM) (NUM)(REG) +#define ARRAY4(REG, NUM) 4*(NUM)(REG) +#define ARRAY4_INDIRECT(BASE, OFFSET, NUM) 4*(NUM)(BASE,OFFSET,4) +#define ARG(NUM) 4*(PUSHED) + ARRAY4(ESP, NUM) + +#define ASSIGN(TO, FROM) movl FROM, TO +#define ASSIGN_BYTE(TO, FROM) movzbl FROM, TO + +#define PUSH(REG) pushl REG +#define POP(REG) popl REG + +#define SPILL_REGS() \ + PUSH(EBP) ; \ + PUSH(EDI) ; \ + PUSH(ESI) ; \ + PUSH(EBX) + +#define RESTORE_REGS() \ + POP(EBX) ; \ + POP(ESI) ; \ + POP(EDI) ; \ + POP(EBP) + +/* +* ALU Operations +*/ +#define IMM(VAL) $VAL + +#define ADD(TO, FROM) addl FROM, TO +#define ADD_IMM(TO, NUM) ADD(TO, IMM(NUM)) +#define ADD_W_CARRY(TO1, TO2, FROM) addl FROM, TO1; adcl IMM(0), TO2; +#define SUB_IMM(TO, NUM) subl IMM(NUM), TO +#define ADD2_IMM(TO, FROM, NUM) leal NUM(FROM), TO +#define ADD3_IMM(TO, FROM, NUM) leal NUM(TO,FROM,1), TO +#define MUL(REG) mull REG + +#define SHL_IMM(REG, SHIFT) shll IMM(SHIFT), REG +#define SHR_IMM(REG, SHIFT) shrl IMM(SHIFT), REG +#define SHL2_3(TO, FROM) leal 0(,FROM,8), TO + +#define XOR(TO, FROM) xorl FROM, TO +#define AND(TO, FROM) andl FROM, TO +#define OR(TO, FROM) orl FROM, TO +#define NOT(REG) notl REG +#define ZEROIZE(REG) XOR(REG, REG) + +#define ROTL_IMM(REG, NUM) roll IMM(NUM), REG +#define ROTR_IMM(REG, NUM) rorl IMM(NUM), REG +#define BSWAP(REG) bswapl REG + +#endif diff --git a/botan/src/utils/asm_ia32/info.txt b/botan/src/utils/asm_ia32/info.txt new file mode 100644 index 0000000..4340c35 --- /dev/null +++ b/botan/src/utils/asm_ia32/info.txt @@ -0,0 +1,16 @@ +realname "Assembler Macros (IA-32)" + +load_on dep + +<add> +asm_macr.h +</add> + +<arch> +ia32 +</arch> + +<cc> +gcc +icc +</cc> diff --git a/botan/src/utils/bit_ops.h b/botan/src/utils/bit_ops.h new file mode 100644 index 0000000..c02ec53 --- /dev/null +++ b/botan/src/utils/bit_ops.h @@ -0,0 +1,91 @@ +/* +* Bit/Word Operations +* (C) 1999-2008 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_BIT_OPS_H__ +#define BOTAN_BIT_OPS_H__ + +#include <botan/types.h> + +namespace Botan { + +/* +* Return true iff arg is 2**n for some n > 0 +* T should be an unsigned integer type +*/ +template<typename T> +inline bool power_of_2(T arg) + { + return ((arg != 0 && arg != 1) && ((arg & (arg-1)) == 0)); + } + +/* +* Return the index of the highest set bit +* T is an unsigned integer type +*/ +template<typename T> +inline u32bit high_bit(T n) + { + for(u32bit i = 8*sizeof(T); i > 0; --i) + if((n >> (i - 1)) & 0x01) + return i; + return 0; + } + +/* +* Return the index of the lowest set bit +*/ +template<typename T> +inline u32bit low_bit(T n) + { + for(u32bit i = 0; i != 8*sizeof(T); ++i) + if((n >> i) & 0x01) + return (i + 1); + return 0; + } + +/* +* Return the number of significant bytes in n +*/ +template<typename T> +inline u32bit significant_bytes(T n) + { + for(u32bit j = 0; j != sizeof(T); ++j) + if(get_byte(j, n)) + return sizeof(T)-j; + return 0; + } + +/* +* Return the Hamming weight of n +*/ +template<typename T> +inline u32bit hamming_weight(T n) + { + const byte NIBBLE_WEIGHTS[] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; + + u32bit weight = 0; + for(u32bit i = 0; i != 2*sizeof(T); ++i) + weight += NIBBLE_WEIGHTS[(n >> (4*i)) & 0x0F]; + return weight; + } + +/* +* Count the trailing zero bits in n +*/ +template<typename T> +inline u32bit ctz(T n) + { + for(u32bit i = 0; i != 8*sizeof(T); ++i) + if((n >> i) & 0x01) + return i; + return 8*sizeof(T); + } + +} + +#endif diff --git a/botan/src/utils/bswap.h b/botan/src/utils/bswap.h new file mode 100644 index 0000000..ec1e814 --- /dev/null +++ b/botan/src/utils/bswap.h @@ -0,0 +1,62 @@ +/* +* Byte Swapping Operations +* (C) 1999-2008 Jack Lloyd +* (C) 2007 Yves Jerschow +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_BYTE_SWAP_H__ +#define BOTAN_BYTE_SWAP_H__ + +#include <botan/types.h> +#include <botan/rotate.h> + +namespace Botan { + +/* +* Byte Swapping Functions +*/ +inline u16bit reverse_bytes(u16bit input) + { + return rotate_left(input, 8); + } + +inline u32bit reverse_bytes(u32bit input) + { +#if BOTAN_USE_GCC_INLINE_ASM && \ + (defined(BOTAN_TARGET_ARCH_IS_IA32) || defined(BOTAN_TARGET_ARCH_IS_AMD64)) + + /* GCC-style inline assembly for x86 or x86-64 */ + asm("bswapl %0" : "=r" (input) : "0" (input)); + return input; + +#elif defined(_MSC_VER) && defined(BOTAN_TARGET_ARCH_IS_IA32) + /* Visual C++ inline asm for 32-bit x86, by Yves Jerschow */ + __asm mov eax, input; + __asm bswap eax; + +#else + /* Generic implementation */ + input = ((input & 0xFF00FF00) >> 8) | ((input & 0x00FF00FF) << 8); + return rotate_left(input, 16); +#endif + } + +inline u64bit reverse_bytes(u64bit input) + { +#if BOTAN_USE_GCC_INLINE_ASM && defined(BOTAN_TARGET_ARCH_IS_AMD64) + asm("bswapq %0" : "=r" (input) : "0" (input)); + return input; +#else + u32bit hi = ((input >> 40) & 0x00FF00FF) | ((input >> 24) & 0xFF00FF00); + u32bit lo = ((input & 0xFF00FF00) >> 8) | ((input & 0x00FF00FF) << 8); + hi = (hi << 16) | (hi >> 16); + lo = (lo << 16) | (lo >> 16); + return (static_cast<u64bit>(lo) << 32) | hi; +#endif + } + +} + +#endif diff --git a/botan/src/utils/buf_comp/buf_comp.h b/botan/src/utils/buf_comp/buf_comp.h new file mode 100644 index 0000000..3f1e90b --- /dev/null +++ b/botan/src/utils/buf_comp/buf_comp.h @@ -0,0 +1,126 @@ +/** +* BufferedComputation +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_BUFFERED_COMPUTATION_H__ +#define BOTAN_BUFFERED_COMPUTATION_H__ + +#include <botan/secmem.h> + +namespace Botan { + +/** +* This class represents any kind of computation which +* uses an internal state, +* such as hash functions. +*/ +class BOTAN_DLL BufferedComputation + { + public: + + /** + * The length of the output of this function in bytes. + */ + const u32bit OUTPUT_LENGTH; + + /** + * Add new input to process. + * @param in the input to process as a byte array + * @param the length of the byte array + */ + void update(const byte in[], u32bit length) { add_data(in, length); } + + /** + * Add new input to process. + * @param in the input to process as a MemoryRegion + */ + void update(const MemoryRegion<byte>& in) { add_data(in, in.size()); } + + /** + * Add new input to process. + * @param str the input to process as a std::string. Will be interpreted + * as a byte array based on + * the strings encoding. + */ + void update(const std::string& str) + { + add_data(reinterpret_cast<const byte*>(str.data()), str.size()); + } + + /** + * Process a single byte. + * @param in the byte to process + */ + void update(byte in) { add_data(&in, 1); } + + /** + * Complete the computation and retrieve the + * final result. + * @param out The byte array to be filled with the result. + * Must be of length OUTPUT_LENGTH. + */ + void final(byte out[]) { final_result(out); } + + /** + * Complete the computation and retrieve the + * final result. + * @return a SecureVector holding the result + */ + SecureVector<byte> final() + { + SecureVector<byte> output(OUTPUT_LENGTH); + final_result(output); + return output; + } + + /** + * Update and finalize computation. Does the same as calling update() + * and final() consecutively. + * @param in the input to process as a byte array + * @param length the length of the byte array + * @result the result of the call to final() + */ + SecureVector<byte> process(const byte in[], u32bit length) + { + add_data(in, length); + return final(); + } + + /** + * Update and finalize computation. Does the same as calling update() + * and final() consecutively. + * @param in the input to process + * @result the result of the call to final() + */ + SecureVector<byte> process(const MemoryRegion<byte>& in) + { + add_data(in, in.size()); + return final(); + } + + /** + * Update and finalize computation. Does the same as calling update() + * and final() consecutively. + * @param in the input to process as a string + * @result the result of the call to final() + */ + SecureVector<byte> process(const std::string& in) + { + update(in); + return final(); + } + + BufferedComputation(u32bit out_len) : OUTPUT_LENGTH(out_len) {} + virtual ~BufferedComputation() {} + private: + BufferedComputation& operator=(const BufferedComputation&); + virtual void add_data(const byte[], u32bit) = 0; + virtual void final_result(byte[]) = 0; + }; + +} + +#endif diff --git a/botan/src/utils/buf_comp/info.txt b/botan/src/utils/buf_comp/info.txt new file mode 100644 index 0000000..bcbbc23 --- /dev/null +++ b/botan/src/utils/buf_comp/info.txt @@ -0,0 +1,11 @@ +realname "Buffered Computation" + +load_on auto + +<add> +buf_comp.h +</add> + +<requires> +alloc +</requires> diff --git a/botan/src/utils/charset.cpp b/botan/src/utils/charset.cpp new file mode 100644 index 0000000..53125ca --- /dev/null +++ b/botan/src/utils/charset.cpp @@ -0,0 +1,201 @@ +/* +* Character Set Handling +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/charset.h> +#include <botan/parsing.h> +#include <botan/exceptn.h> +#include <cctype> + +namespace Botan { + +namespace Charset { + +namespace { + +/* +* Convert from UCS-2 to ISO 8859-1 +*/ +std::string ucs2_to_latin1(const std::string& ucs2) + { + if(ucs2.size() % 2 == 1) + throw Decoding_Error("UCS-2 string has an odd number of bytes"); + + std::string latin1; + + for(u32bit j = 0; j != ucs2.size(); j += 2) + { + const byte c1 = ucs2[j]; + const byte c2 = ucs2[j+1]; + + if(c1 != 0) + throw Decoding_Error("UCS-2 has non-Latin1 characters"); + + latin1 += static_cast<char>(c2); + } + + return latin1; + } + +/* +* Convert from UTF-8 to ISO 8859-1 +*/ +std::string utf8_to_latin1(const std::string& utf8) + { + std::string iso8859; + + u32bit position = 0; + while(position != utf8.size()) + { + const byte c1 = static_cast<byte>(utf8[position++]); + + if(c1 <= 0x7F) + iso8859 += static_cast<char>(c1); + else if(c1 >= 0xC0 && c1 <= 0xC7) + { + if(position == utf8.size()) + throw Decoding_Error("UTF-8: sequence truncated"); + + const byte c2 = static_cast<byte>(utf8[position++]); + const byte iso_char = ((c1 & 0x07) << 6) | (c2 & 0x3F); + + if(iso_char <= 0x7F) + throw Decoding_Error("UTF-8: sequence longer than needed"); + + iso8859 += static_cast<char>(iso_char); + } + else + throw Decoding_Error("UTF-8: Unicode chars not in Latin1 used"); + } + + return iso8859; + } + +/* +* Convert from ISO 8859-1 to UTF-8 +*/ +std::string latin1_to_utf8(const std::string& iso8859) + { + std::string utf8; + for(u32bit j = 0; j != iso8859.size(); ++j) + { + const byte c = static_cast<byte>(iso8859[j]); + + if(c <= 0x7F) + utf8 += static_cast<char>(c); + else + { + utf8 += static_cast<char>((0xC0 | (c >> 6))); + utf8 += static_cast<char>((0x80 | (c & 0x3F))); + } + } + return utf8; + } + +} + +/* +* Perform character set transcoding +*/ +std::string transcode(const std::string& str, + Character_Set to, Character_Set from) + { + if(to == LOCAL_CHARSET) + to = LATIN1_CHARSET; + if(from == LOCAL_CHARSET) + from = LATIN1_CHARSET; + + if(to == from) + return str; + + if(from == LATIN1_CHARSET && to == UTF8_CHARSET) + return latin1_to_utf8(str); + if(from == UTF8_CHARSET && to == LATIN1_CHARSET) + return utf8_to_latin1(str); + if(from == UCS2_CHARSET && to == LATIN1_CHARSET) + return ucs2_to_latin1(str); + + throw Invalid_Argument("Unknown transcoding operation from " + + to_string(from) + " to " + to_string(to)); + } + +/* +* Check if a character represents a digit +*/ +bool is_digit(char c) + { + if(c == '0' || c == '1' || c == '2' || c == '3' || c == '4' || + c == '5' || c == '6' || c == '7' || c == '8' || c == '9') + return true; + return false; + } + +/* +* Check if a character represents whitespace +*/ +bool is_space(char c) + { + if(c == ' ' || c == '\t' || c == '\n' || c == '\r') + return true; + return false; + } + +/* +* Convert a character to a digit +*/ +byte char2digit(char c) + { + switch(c) + { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + } + + throw Invalid_Argument("char2digit: Input is not a digit character"); + } + +/* +* Convert a digit to a character +*/ +char digit2char(byte b) + { + switch(b) + { + case 0: return '0'; + case 1: return '1'; + case 2: return '2'; + case 3: return '3'; + case 4: return '4'; + case 5: return '5'; + case 6: return '6'; + case 7: return '7'; + case 8: return '8'; + case 9: return '9'; + } + + throw Invalid_Argument("digit2char: Input is not a digit"); + } + +/* +* Case-insensitive character comparison +*/ +bool caseless_cmp(char a, char b) + { + return (std::tolower(static_cast<unsigned char>(a)) == + std::tolower(static_cast<unsigned char>(b))); + } + +} + +} diff --git a/botan/src/utils/charset.h b/botan/src/utils/charset.h new file mode 100644 index 0000000..eebb199 --- /dev/null +++ b/botan/src/utils/charset.h @@ -0,0 +1,44 @@ +/* +* Character Set Handling +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_CHARSET_H__ +#define BOTAN_CHARSET_H__ + +#include <botan/types.h> +#include <string> + +namespace Botan { + +/** +* The different charsets (nominally) supported by Botan. +*/ +enum Character_Set { + LOCAL_CHARSET, + UCS2_CHARSET, + UTF8_CHARSET, + LATIN1_CHARSET +}; + +namespace Charset { + +/* +* Character Set Handling +*/ +std::string transcode(const std::string&, Character_Set, Character_Set); + +bool is_digit(char); +bool is_space(char); +bool caseless_cmp(char, char); + +byte char2digit(char); +char digit2char(byte); + +} + +} + +#endif diff --git a/botan/src/utils/datastor/datastor.cpp b/botan/src/utils/datastor/datastor.cpp new file mode 100644 index 0000000..129dad9 --- /dev/null +++ b/botan/src/utils/datastor/datastor.cpp @@ -0,0 +1,172 @@ +/* +* Data Store +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/datastor.h> +#include <botan/exceptn.h> +#include <botan/parsing.h> +#include <botan/stl_util.h> +#include <botan/filters.h> + +namespace Botan { + +/* +* Default Matcher transform operation (identity) +*/ +std::pair<std::string, std::string> +Data_Store::Matcher::transform(const std::string& key, + const std::string& value) const + { + return std::make_pair(key, value); + } + +/* +* Data_Store Equality Comparison +*/ +bool Data_Store::operator==(const Data_Store& other) const + { + return (contents == other.contents); + } + +/* +* Check if this key has at least one value +*/ +bool Data_Store::has_value(const std::string& key) const + { + return (contents.lower_bound(key) != contents.end()); + } + +/* +* Search based on an arbitrary predicate +*/ +std::multimap<std::string, std::string> +Data_Store::search_with(const Matcher& matcher) const + { + std::multimap<std::string, std::string> out; + + std::multimap<std::string, std::string>::const_iterator i = + contents.begin(); + + while(i != contents.end()) + { + if(matcher(i->first, i->second)) + out.insert(matcher.transform(i->first, i->second)); + ++i; + } + + return out; + } + +/* +* Search based on key equality +*/ +std::vector<std::string> Data_Store::get(const std::string& looking_for) const + { + typedef std::multimap<std::string, std::string>::const_iterator iter; + + std::pair<iter, iter> range = contents.equal_range(looking_for); + + std::vector<std::string> out; + for(iter i = range.first; i != range.second; ++i) + out.push_back(i->second); + return out; + } + +/* +* Get a single atom +*/ +std::string Data_Store::get1(const std::string& key) const + { + std::vector<std::string> vals = get(key); + + if(vals.empty()) + throw Invalid_State("Data_Store::get1: Not values for " + key); + if(vals.size() > 1) + throw Invalid_State("Data_Store::get1: More than one value for " + key); + + return vals[0]; + } + +/* +* Get a single MemoryVector atom +*/ +MemoryVector<byte> +Data_Store::get1_memvec(const std::string& key) const + { + std::vector<std::string> vals = get(key); + + if(vals.size() > 1) + throw Invalid_State("Data_Store::get1_memvec: Multiple values for " + + key); + + if(vals.empty()) + return MemoryVector<byte>(); + + Pipe pipe(new Hex_Decoder(FULL_CHECK)); + pipe.start_msg(); + if(vals.size()) + pipe.write(vals[0]); + pipe.end_msg(); + return pipe.read_all(); + } + +/* +* Get a single u32bit atom +*/ +u32bit Data_Store::get1_u32bit(const std::string& key, + u32bit default_val) const + { + std::vector<std::string> vals = get(key); + + if(vals.empty()) + return default_val; + else if(vals.size() > 1) + throw Invalid_State("Data_Store::get1_u32bit: Multiple values for " + + key); + + return to_u32bit(vals[0]); + } + +/* +* Insert a single key and value +*/ +void Data_Store::add(const std::string& key, const std::string& val) + { + multimap_insert(contents, key, val); + } + +/* +* Insert a single key and value +*/ +void Data_Store::add(const std::string& key, u32bit val) + { + add(key, to_string(val)); + } + +/* +* Insert a single key and value +*/ +void Data_Store::add(const std::string& key, const MemoryRegion<byte>& val) + { + Pipe pipe(new Hex_Encoder); + pipe.process_msg(val); + add(key, pipe.read_all_as_string()); + } + +/* +* Insert a mapping of key/value pairs +*/ +void Data_Store::add(const std::multimap<std::string, std::string>& in) + { + std::multimap<std::string, std::string>::const_iterator i = in.begin(); + while(i != in.end()) + { + contents.insert(*i); + ++i; + } + } + +} diff --git a/botan/src/utils/datastor/datastor.h b/botan/src/utils/datastor/datastor.h new file mode 100644 index 0000000..7ee626f --- /dev/null +++ b/botan/src/utils/datastor/datastor.h @@ -0,0 +1,61 @@ +/* +* Data Store +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_DATA_STORE_H__ +#define BOTAN_DATA_STORE_H__ + +#include <botan/secmem.h> +#include <utility> +#include <string> +#include <vector> +#include <map> + +namespace Botan { + +/** +* Data Store +*/ +class BOTAN_DLL Data_Store + { + public: + class BOTAN_DLL Matcher + { + public: + virtual bool operator()(const std::string&, + const std::string&) const = 0; + + virtual std::pair<std::string, std::string> + transform(const std::string&, const std::string&) const; + + virtual ~Matcher() {} + }; + + bool operator==(const Data_Store&) const; + + std::multimap<std::string, std::string> + search_with(const Matcher&) const; + + std::vector<std::string> get(const std::string&) const; + + std::string get1(const std::string&) const; + + MemoryVector<byte> get1_memvec(const std::string&) const; + u32bit get1_u32bit(const std::string&, u32bit = 0) const; + + bool has_value(const std::string&) const; + + void add(const std::multimap<std::string, std::string>&); + void add(const std::string&, const std::string&); + void add(const std::string&, u32bit); + void add(const std::string&, const MemoryRegion<byte>&); + private: + std::multimap<std::string, std::string> contents; + }; + +} + +#endif diff --git a/botan/src/utils/datastor/info.txt b/botan/src/utils/datastor/info.txt new file mode 100644 index 0000000..8c38a3a --- /dev/null +++ b/botan/src/utils/datastor/info.txt @@ -0,0 +1,13 @@ +realname "Datastore" + +load_on auto + +<add> +datastor.cpp +datastor.h +</add> + +<requires> +alloc +filters +</requires> diff --git a/botan/src/utils/exceptn.cpp b/botan/src/utils/exceptn.cpp new file mode 100644 index 0000000..753d634 --- /dev/null +++ b/botan/src/utils/exceptn.cpp @@ -0,0 +1,62 @@ +/* +* Exceptions +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/exceptn.h> +#include <botan/parsing.h> + +namespace Botan { + +/* +* Constructor for Invalid_Key_Length +*/ +Invalid_Key_Length::Invalid_Key_Length(const std::string& name, u32bit length) + { + set_msg(name + " cannot accept a key of length " + to_string(length)); + } + +/* +* Constructor for Invalid_Block_Size +*/ +Invalid_Block_Size::Invalid_Block_Size(const std::string& mode, + const std::string& pad) + { + set_msg("Padding method " + pad + " cannot be used with " + mode); + } + +/* +* Constructor for Invalid_IV_Length +*/ +Invalid_IV_Length::Invalid_IV_Length(const std::string& mode, u32bit bad_len) + { + set_msg("IV length " + to_string(bad_len) + " is invalid for " + mode); + } + +/* +* Constructor for Algorithm_Not_Found +*/ +Algorithm_Not_Found::Algorithm_Not_Found(const std::string& name) + { + set_msg("Could not find any algorithm named \"" + name + "\""); + } + +/* +* Constructor for Invalid_Algorithm_Name +*/ +Invalid_Algorithm_Name::Invalid_Algorithm_Name(const std::string& name) + { + set_msg("Invalid algorithm name: " + name); + } + +/* +* Constructor for Config_Error +*/ +Config_Error::Config_Error(const std::string& err, u32bit line) + { + set_msg("Config error at line " + to_string(line) + ": " + err); + } + +} diff --git a/botan/src/utils/exceptn.h b/botan/src/utils/exceptn.h new file mode 100644 index 0000000..a55d842 --- /dev/null +++ b/botan/src/utils/exceptn.h @@ -0,0 +1,197 @@ +/* +* Exceptions +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_EXCEPTION_H__ +#define BOTAN_EXCEPTION_H__ + +#include <botan/types.h> +#include <exception> +#include <string> + +namespace Botan { + +/* +* Exception Base Class +*/ +class BOTAN_DLL Exception : public std::exception + { + public: + const char* what() const throw() { return msg.c_str(); } + Exception(const std::string& m = "Unknown error") { set_msg(m); } + virtual ~Exception() throw() {} + protected: + void set_msg(const std::string& m) { msg = "Botan: " + m; } + private: + std::string msg; + }; + +/* +* Invalid_Argument Exception +*/ +struct BOTAN_DLL Invalid_Argument : public Exception + { + Invalid_Argument(const std::string& err = "") : Exception(err) {} + }; + +/* +* Invalid_Key_Length Exception +*/ +struct BOTAN_DLL Invalid_Key_Length : public Invalid_Argument + { + Invalid_Key_Length(const std::string&, u32bit); + }; + +/* +* Invalid_Block_Size Exception +*/ +struct BOTAN_DLL Invalid_Block_Size : public Invalid_Argument + { + Invalid_Block_Size(const std::string&, const std::string&); + }; + +/* +* Invalid_IV_Length Exception +*/ +struct BOTAN_DLL Invalid_IV_Length : public Invalid_Argument + { + Invalid_IV_Length(const std::string&, u32bit); + }; + +/* +* Invalid_State Exception +*/ +struct BOTAN_DLL Invalid_State : public Exception + { + Invalid_State(const std::string& err) : Exception(err) {} + }; + +/* +* PRNG_Unseeded Exception +*/ +struct BOTAN_DLL PRNG_Unseeded : public Invalid_State + { + PRNG_Unseeded(const std::string& algo) : + Invalid_State("PRNG not seeded: " + algo) {} + }; + +/* +* Policy_Violation Exception +*/ +struct BOTAN_DLL Policy_Violation : public Invalid_State + { + Policy_Violation(const std::string& err) : + Invalid_State("Policy violation: " + err) {} + }; + +/* +* Lookup_Error Exception +*/ +struct BOTAN_DLL Lookup_Error : public Exception + { + Lookup_Error(const std::string& err) : Exception(err) {} + }; + +/* +* Algorithm_Not_Found Exception +*/ +struct BOTAN_DLL Algorithm_Not_Found : public Exception + { + Algorithm_Not_Found(const std::string&); + }; + +/* +* Format_Error Exception +*/ +struct BOTAN_DLL Format_Error : public Exception + { + Format_Error(const std::string& err = "") : Exception(err) {} + }; + +/* +* Invalid_Algorithm_Name Exception +*/ +struct BOTAN_DLL Invalid_Algorithm_Name : public Format_Error + { + Invalid_Algorithm_Name(const std::string&); + }; + +/* +* Encoding_Error Exception +*/ +struct BOTAN_DLL Encoding_Error : public Format_Error + { + Encoding_Error(const std::string& name) : + Format_Error("Encoding error: " + name) {} + }; + +/* +* Decoding_Error Exception +*/ +struct BOTAN_DLL Decoding_Error : public Format_Error + { + Decoding_Error(const std::string& name) : + Format_Error("Decoding error: " + name) {} + }; + +/* +* Invalid_OID Exception +*/ +struct BOTAN_DLL Invalid_OID : public Decoding_Error + { + Invalid_OID(const std::string& oid) : + Decoding_Error("Invalid ASN.1 OID: " + oid) {} + }; + +/* +* Stream_IO_Error Exception +*/ +struct BOTAN_DLL Stream_IO_Error : public Exception + { + Stream_IO_Error(const std::string& err) : + Exception("I/O error: " + err) {} + }; + +/* +* Configuration Error Exception +*/ +struct BOTAN_DLL Config_Error : public Format_Error + { + Config_Error(const std::string& err) : + Format_Error("Config error: " + err) {} + Config_Error(const std::string&, u32bit); + }; + +/* +* Integrity Failure Exception +*/ +struct BOTAN_DLL Integrity_Failure : public Exception + { + Integrity_Failure(const std::string& err) : + Exception("Integrity failure: " + err) {} + }; + +/* +* Internal_Error Exception +*/ +struct BOTAN_DLL Internal_Error : public Exception + { + Internal_Error(const std::string& err) : + Exception("Internal error: " + err) {} + }; + +/* +* Self Test Failure Exception +*/ +struct BOTAN_DLL Self_Test_Failure : public Internal_Error + { + Self_Test_Failure(const std::string& err) : + Internal_Error("Self test failed: " + err) {} + }; + +} + +#endif diff --git a/botan/src/utils/info.txt b/botan/src/utils/info.txt new file mode 100644 index 0000000..ab50b88 --- /dev/null +++ b/botan/src/utils/info.txt @@ -0,0 +1,33 @@ +realname "Utility Functions" + +define UTIL_FUNCTIONS + +load_on always + +<libs> +tru64 -> rt +</libs> + +<add> +bit_ops.h +bswap.h +charset.cpp +charset.h +exceptn.cpp +exceptn.h +loadstor.h +mem_ops.h +mlock.cpp +parsing.cpp +parsing.h +rotate.h +stl_util.h +types.h +ui.cpp +ui.h +util.cpp +util.h +version.cpp +version.h +xor_buf.h +</add> diff --git a/botan/src/utils/loadstor.h b/botan/src/utils/loadstor.h new file mode 100644 index 0000000..77ed155 --- /dev/null +++ b/botan/src/utils/loadstor.h @@ -0,0 +1,281 @@ +/* +* Load/Store Operators +* (C) 1999-2007 Jack Lloyd +* 2007 Yves Jerschow +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_LOAD_STORE_H__ +#define BOTAN_LOAD_STORE_H__ + +#include <botan/types.h> +#include <botan/bswap.h> +#include <botan/rotate.h> + +#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK + +#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN) + +#define BOTAN_ENDIAN_N2B(x) (x) +#define BOTAN_ENDIAN_B2N(x) (x) + +#define BOTAN_ENDIAN_N2L(x) reverse_bytes(x) +#define BOTAN_ENDIAN_L2N(x) reverse_bytes(x) + +#elif defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN) + +#define BOTAN_ENDIAN_N2L(x) (x) +#define BOTAN_ENDIAN_L2N(x) (x) + +#define BOTAN_ENDIAN_N2B(x) reverse_bytes(x) +#define BOTAN_ENDIAN_B2N(x) reverse_bytes(x) + +#endif + +#endif + +namespace Botan { + +/* +* Byte Extraction Function +*/ +template<typename T> inline byte get_byte(u32bit byte_num, T input) + { + return (input >> ((sizeof(T)-1-(byte_num&(sizeof(T)-1))) << 3)); + } + +/* +* Byte to Word Conversions +*/ +inline u16bit make_u16bit(byte i0, byte i1) + { + return ((static_cast<u16bit>(i0) << 8) | i1); + } + +inline u32bit make_u32bit(byte i0, byte i1, byte i2, byte i3) + { + return ((static_cast<u32bit>(i0) << 24) | + (static_cast<u32bit>(i1) << 16) | + (static_cast<u32bit>(i2) << 8) | + (static_cast<u32bit>(i3))); + } + +inline u64bit make_u64bit(byte i0, byte i1, byte i2, byte i3, + byte i4, byte i5, byte i6, byte i7) + { + return ((static_cast<u64bit>(i0) << 56) | + (static_cast<u64bit>(i1) << 48) | + (static_cast<u64bit>(i2) << 40) | + (static_cast<u64bit>(i3) << 32) | + (static_cast<u64bit>(i4) << 24) | + (static_cast<u64bit>(i5) << 16) | + (static_cast<u64bit>(i6) << 8) | + (static_cast<u64bit>(i7))); + } + +/* +* Endian-Specific Word Loading Operations +*/ +template<typename T> +inline T load_be(const byte in[], u32bit off) + { + in += off * sizeof(T); + T out = 0; + for(u32bit j = 0; j != sizeof(T); j++) + out = (out << 8) | in[j]; + return out; + } + +template<typename T> +inline T load_le(const byte in[], u32bit off) + { + in += off * sizeof(T); + T out = 0; + for(u32bit j = 0; j != sizeof(T); j++) + out = (out << 8) | in[sizeof(T)-1-j]; + return out; + } + +template<> +inline u16bit load_be<u16bit>(const byte in[], u32bit off) + { +#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK + return BOTAN_ENDIAN_N2B(*(reinterpret_cast<const u16bit*>(in) + off)); +#else + in += off * sizeof(u16bit); + return make_u16bit(in[0], in[1]); +#endif + } + +template<> +inline u16bit load_le<u16bit>(const byte in[], u32bit off) + { +#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK + return BOTAN_ENDIAN_N2L(*(reinterpret_cast<const u16bit*>(in) + off)); +#else + in += off * sizeof(u16bit); + return make_u16bit(in[1], in[0]); +#endif + } + +template<> +inline u32bit load_be<u32bit>(const byte in[], u32bit off) + { +#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK + return BOTAN_ENDIAN_N2B(*(reinterpret_cast<const u32bit*>(in) + off)); +#else + in += off * sizeof(u32bit); + return make_u32bit(in[0], in[1], in[2], in[3]); +#endif + } + +template<> +inline u32bit load_le<u32bit>(const byte in[], u32bit off) + { +#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK + return BOTAN_ENDIAN_N2L(*(reinterpret_cast<const u32bit*>(in) + off)); +#else + in += off * sizeof(u32bit); + return make_u32bit(in[3], in[2], in[1], in[0]); +#endif + } + +template<> +inline u64bit load_be<u64bit>(const byte in[], u32bit off) + { +#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK + return BOTAN_ENDIAN_N2B(*(reinterpret_cast<const u64bit*>(in) + off)); +#else + in += off * sizeof(u64bit); + return make_u64bit(in[0], in[1], in[2], in[3], + in[4], in[5], in[6], in[7]); +#endif + } + +template<> +inline u64bit load_le<u64bit>(const byte in[], u32bit off) + { +#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK + return BOTAN_ENDIAN_N2L(*(reinterpret_cast<const u64bit*>(in) + off)); +#else + in += off * sizeof(u64bit); + return make_u64bit(in[7], in[6], in[5], in[4], + in[3], in[2], in[1], in[0]); +#endif + } + +/* +* Endian-Specific Word Storing Operations +*/ +inline void store_be(u16bit in, byte out[2]) + { +#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK + *reinterpret_cast<u16bit*>(out) = BOTAN_ENDIAN_B2N(in); +#else + out[0] = get_byte(0, in); + out[1] = get_byte(1, in); +#endif + } + +inline void store_le(u16bit in, byte out[2]) + { +#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK + *reinterpret_cast<u16bit*>(out) = BOTAN_ENDIAN_L2N(in); +#else + out[0] = get_byte(1, in); + out[1] = get_byte(0, in); +#endif + } + +inline void store_be(u32bit in, byte out[4]) + { +#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK + *reinterpret_cast<u32bit*>(out) = BOTAN_ENDIAN_B2N(in); +#else + out[0] = get_byte(0, in); + out[1] = get_byte(1, in); + out[2] = get_byte(2, in); + out[3] = get_byte(3, in); +#endif + } + +inline void store_le(u32bit in, byte out[4]) + { +#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK + *reinterpret_cast<u32bit*>(out) = BOTAN_ENDIAN_L2N(in); +#else + out[0] = get_byte(3, in); + out[1] = get_byte(2, in); + out[2] = get_byte(1, in); + out[3] = get_byte(0, in); +#endif + } + +inline void store_be(u64bit in, byte out[8]) + { +#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK + *reinterpret_cast<u64bit*>(out) = BOTAN_ENDIAN_B2N(in); +#else + out[0] = get_byte(0, in); + out[1] = get_byte(1, in); + out[2] = get_byte(2, in); + out[3] = get_byte(3, in); + out[4] = get_byte(4, in); + out[5] = get_byte(5, in); + out[6] = get_byte(6, in); + out[7] = get_byte(7, in); +#endif + } + +inline void store_le(u64bit in, byte out[8]) + { +#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK + *reinterpret_cast<u64bit*>(out) = BOTAN_ENDIAN_L2N(in); +#else + out[0] = get_byte(7, in); + out[1] = get_byte(6, in); + out[2] = get_byte(5, in); + out[3] = get_byte(4, in); + out[4] = get_byte(3, in); + out[5] = get_byte(2, in); + out[6] = get_byte(1, in); + out[7] = get_byte(0, in); +#endif + } + +template<typename T> +inline void store_le(byte out[], T a, T b) + { + store_le(a, out + (0 * sizeof(T))); + store_le(b, out + (1 * sizeof(T))); + } + +template<typename T> +inline void store_be(byte out[], T a, T b) + { + store_be(a, out + (0 * sizeof(T))); + store_be(b, out + (1 * sizeof(T))); + } + +template<typename T> +inline void store_le(byte out[], T a, T b, T c, T d) + { + store_le(a, out + (0 * sizeof(T))); + store_le(b, out + (1 * sizeof(T))); + store_le(c, out + (2 * sizeof(T))); + store_le(d, out + (3 * sizeof(T))); + } + +template<typename T> +inline void store_be(byte out[], T a, T b, T c, T d) + { + store_be(a, out + (0 * sizeof(T))); + store_be(b, out + (1 * sizeof(T))); + store_be(c, out + (2 * sizeof(T))); + store_be(d, out + (3 * sizeof(T))); + } + +} + +#endif diff --git a/botan/src/utils/mem_ops.h b/botan/src/utils/mem_ops.h new file mode 100644 index 0000000..0fcf34b --- /dev/null +++ b/botan/src/utils/mem_ops.h @@ -0,0 +1,40 @@ +/* +* Memory Operations +* (C) 1999-2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_MEMORY_OPS_H__ +#define BOTAN_MEMORY_OPS_H__ + +#include <botan/types.h> +#include <cstring> + +namespace Botan { + +/* +* Memory Manipulation Functions +*/ +template<typename T> inline void copy_mem(T* out, const T* in, u32bit n) + { std::memmove(out, in, sizeof(T)*n); } + +template<typename T> inline void clear_mem(T* ptr, u32bit n) + { if(n) std::memset(ptr, 0, sizeof(T)*n); } + +template<typename T> inline void set_mem(T* ptr, u32bit n, byte val) + { std::memset(ptr, val, sizeof(T)*n); } + +template<typename T> inline bool same_mem(const T* p1, const T* p2, u32bit n) + { + bool is_same = true; + + for(u32bit i = 0; i != n; ++i) + is_same &= (p1[i] == p2[i]); + + return is_same; + } + +} + +#endif diff --git a/botan/src/utils/mlock.cpp b/botan/src/utils/mlock.cpp new file mode 100644 index 0000000..ea0da26 --- /dev/null +++ b/botan/src/utils/mlock.cpp @@ -0,0 +1,55 @@ +/* +* Memory Locking Functions +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/util.h> + +#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK) + #include <sys/types.h> + #include <sys/mman.h> +#elif defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK) + #include <windows.h> +#endif + +namespace Botan { + +/* +* Lock an area of memory into RAM +*/ +#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK) \ + || defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK) +bool lock_mem(void* ptr, u32bit bytes) +#else +bool lock_mem(void*, u32bit) +#endif + { +#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK) + return (mlock(ptr, bytes) == 0); +#elif defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK) + return (VirtualLock(ptr, bytes) != 0); +#else + return false; +#endif + } + +/* +* Unlock a previously locked region of memory +*/ +#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK) \ + || defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK) +void unlock_mem(void* ptr, u32bit bytes) +#else +void unlock_mem(void*, u32bit) +#endif + { +#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK) + munlock(ptr, bytes); +#elif defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK) + VirtualUnlock(ptr, bytes); +#endif + } + +} diff --git a/botan/src/utils/parsing.cpp b/botan/src/utils/parsing.cpp new file mode 100644 index 0000000..bdb9e79 --- /dev/null +++ b/botan/src/utils/parsing.cpp @@ -0,0 +1,288 @@ +/* +* Parser Functions +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/parsing.h> +#include <botan/exceptn.h> +#include <botan/charset.h> +#include <botan/loadstor.h> + +namespace Botan { + +/* +* Convert a string into an integer +*/ +u32bit to_u32bit(const std::string& number) + { + u32bit n = 0; + + for(std::string::const_iterator j = number.begin(); j != number.end(); ++j) + { + const u32bit OVERFLOW_MARK = 0xFFFFFFFF / 10; + + byte digit = Charset::char2digit(*j); + + if((n > OVERFLOW_MARK) || (n == OVERFLOW_MARK && digit > 5)) + throw Decoding_Error("to_u32bit: Integer overflow"); + n *= 10; + n += digit; + } + return n; + } + +/* +* Convert an integer into a string +*/ +std::string to_string(u64bit n, u32bit min_len) + { + std::string lenstr; + if(n) + { + while(n > 0) + { + lenstr = Charset::digit2char(n % 10) + lenstr; + n /= 10; + } + } + else + lenstr = "0"; + + while(lenstr.size() < min_len) + lenstr = "0" + lenstr; + + return lenstr; + } + +/* +* Convert a string into a time duration +*/ +u32bit timespec_to_u32bit(const std::string& timespec) + { + if(timespec == "") + return 0; + + const char suffix = timespec[timespec.size()-1]; + std::string value = timespec.substr(0, timespec.size()-1); + + u32bit scale = 1; + + if(Charset::is_digit(suffix)) + value += suffix; + else if(suffix == 's') + scale = 1; + else if(suffix == 'm') + scale = 60; + else if(suffix == 'h') + scale = 60 * 60; + else if(suffix == 'd') + scale = 24 * 60 * 60; + else if(suffix == 'y') + scale = 365 * 24 * 60 * 60; + else + throw Decoding_Error("timespec_to_u32bit: Bad input " + timespec); + + return scale * to_u32bit(value); + } + +/* +* Parse a SCAN-style algorithm name +*/ +std::vector<std::string> parse_algorithm_name(const std::string& namex) + { + if(namex.find('(') == std::string::npos && + namex.find(')') == std::string::npos) + return std::vector<std::string>(1, namex); + + std::string name = namex, substring; + std::vector<std::string> elems; + u32bit level = 0; + + elems.push_back(name.substr(0, name.find('('))); + name = name.substr(name.find('(')); + + for(std::string::const_iterator j = name.begin(); j != name.end(); ++j) + { + char c = *j; + + if(c == '(') + ++level; + if(c == ')') + { + if(level == 1 && j == name.end() - 1) + { + if(elems.size() == 1) + elems.push_back(substring.substr(1)); + else + elems.push_back(substring); + return elems; + } + + if(level == 0 || (level == 1 && j != name.end() - 1)) + throw Invalid_Algorithm_Name(namex); + --level; + } + + if(c == ',' && level == 1) + { + if(elems.size() == 1) + elems.push_back(substring.substr(1)); + else + elems.push_back(substring); + substring.clear(); + } + else + substring += c; + } + + if(substring != "") + throw Invalid_Algorithm_Name(namex); + + return elems; + } + +/* +* Split the string on slashes +*/ +std::vector<std::string> split_on(const std::string& str, char delim) + { + std::vector<std::string> elems; + if(str == "") return elems; + + std::string substr; + for(std::string::const_iterator j = str.begin(); j != str.end(); ++j) + { + if(*j == delim) + { + if(substr != "") + elems.push_back(substr); + substr.clear(); + } + else + substr += *j; + } + + if(substr == "") + throw Format_Error("Unable to split string: " + str); + elems.push_back(substr); + + return elems; + } + +/* +* Parse an ASN.1 OID string +*/ +std::vector<u32bit> parse_asn1_oid(const std::string& oid) + { + std::string substring; + std::vector<u32bit> oid_elems; + + for(std::string::const_iterator j = oid.begin(); j != oid.end(); ++j) + { + char c = *j; + + if(c == '.') + { + if(substring == "") + throw Invalid_OID(oid); + oid_elems.push_back(to_u32bit(substring)); + substring.clear(); + } + else + substring += c; + } + + if(substring == "") + throw Invalid_OID(oid); + oid_elems.push_back(to_u32bit(substring)); + + if(oid_elems.size() < 2) + throw Invalid_OID(oid); + + return oid_elems; + } + +/* +* X.500 String Comparison +*/ +bool x500_name_cmp(const std::string& name1, const std::string& name2) + { + std::string::const_iterator p1 = name1.begin(); + std::string::const_iterator p2 = name2.begin(); + + while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1; + while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2; + + while(p1 != name1.end() && p2 != name2.end()) + { + if(Charset::is_space(*p1)) + { + if(!Charset::is_space(*p2)) + return false; + + while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1; + while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2; + + if(p1 == name1.end() && p2 == name2.end()) + return true; + } + + if(!Charset::caseless_cmp(*p1, *p2)) + return false; + ++p1; + ++p2; + } + + while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1; + while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2; + + if((p1 != name1.end()) || (p2 != name2.end())) + return false; + return true; + } + +/* +* Convert a decimal-dotted string to binary IP +*/ +u32bit string_to_ipv4(const std::string& str) + { + std::vector<std::string> parts = split_on(str, '.'); + + if(parts.size() != 4) + throw Decoding_Error("Invalid IP string " + str); + + u32bit ip = 0; + + for(size_t j = 0; j != parts.size(); j++) + { + u32bit octet = to_u32bit(parts[j]); + + if(octet > 255) + throw Decoding_Error("Invalid IP string " + str); + + ip = (ip << 8) | (octet & 0xFF); + } + + return ip; + } + +/* +* Convert an IP address to decimal-dotted string +*/ +std::string ipv4_to_string(u32bit ip) + { + std::string str; + + for(size_t j = 0; j != sizeof(ip); j++) + { + if(j) + str += "."; + str += to_string(get_byte(j, ip)); + } + + return str; + } + +} diff --git a/botan/src/utils/parsing.h b/botan/src/utils/parsing.h new file mode 100644 index 0000000..2c29d5b --- /dev/null +++ b/botan/src/utils/parsing.h @@ -0,0 +1,41 @@ +/* +* Parser Functions +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_PARSER_H__ +#define BOTAN_PARSER_H__ + +#include <botan/types.h> +#include <string> +#include <vector> + +namespace Botan { + +/* +* String Parsing Functions +*/ +BOTAN_DLL std::vector<std::string> parse_algorithm_name(const std::string&); +BOTAN_DLL std::vector<std::string> split_on(const std::string&, char); +BOTAN_DLL std::vector<u32bit> parse_asn1_oid(const std::string&); +BOTAN_DLL bool x500_name_cmp(const std::string&, const std::string&); + +/* +* String/Integer Conversions +*/ +BOTAN_DLL std::string to_string(u64bit, u32bit = 0); +BOTAN_DLL u32bit to_u32bit(const std::string&); + +BOTAN_DLL u32bit timespec_to_u32bit(const std::string& timespec); + +/* +* String/Network Address Conversions +*/ +BOTAN_DLL u32bit string_to_ipv4(const std::string&); +BOTAN_DLL std::string ipv4_to_string(u32bit); + +} + +#endif diff --git a/botan/src/utils/rotate.h b/botan/src/utils/rotate.h new file mode 100644 index 0000000..c8f8d4a --- /dev/null +++ b/botan/src/utils/rotate.h @@ -0,0 +1,30 @@ +/* +* Word Rotation Operations +* (C) 1999-2008 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_WORD_ROTATE_H__ +#define BOTAN_WORD_ROTATE_H__ + +#include <botan/types.h> + +namespace Botan { + +/* +* Word Rotation Functions +*/ +template<typename T> inline T rotate_left(T input, u32bit rot) + { + return static_cast<T>((input << rot) | (input >> (8*sizeof(T)-rot)));; + } + +template<typename T> inline T rotate_right(T input, u32bit rot) + { + return static_cast<T>((input >> rot) | (input << (8*sizeof(T)-rot))); + } + +} + +#endif diff --git a/botan/src/utils/stl_util.h b/botan/src/utils/stl_util.h new file mode 100644 index 0000000..18c8b14 --- /dev/null +++ b/botan/src/utils/stl_util.h @@ -0,0 +1,86 @@ +/* +* STL Utility Functions +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_STL_UTIL_H__ +#define BOTAN_STL_UTIL_H__ + +#include <map> + +namespace Botan { + +/* +* Copy-on-Predicate Algorithm +*/ +template<typename InputIterator, typename OutputIterator, typename Predicate> +OutputIterator copy_if(InputIterator current, InputIterator end, + OutputIterator dest, Predicate copy_p) + { + while(current != end) + { + if(copy_p(*current)) + *dest++ = *current; + ++current; + } + return dest; + } + +/* +* Searching through a std::map +*/ +template<typename K, typename V> +inline V search_map(const std::map<K, V>& mapping, + const K& key, + const V& null_result = V()) + { + typename std::map<K, V>::const_iterator i = mapping.find(key); + if(i == mapping.end()) + return null_result; + return i->second; + } + +template<typename K, typename V, typename R> +inline R search_map(const std::map<K, V>& mapping, const K& key, + const R& null_result, const R& found_result) + { + typename std::map<K, V>::const_iterator i = mapping.find(key); + if(i == mapping.end()) + return null_result; + return found_result; + } + +/* +* Function adaptor for delete operation +*/ +template<class T> +class del_fun : public std::unary_function<T, void> + { + public: + void operator()(T* ptr) { delete ptr; } + }; + +/* +* Delete the second half of a pair of objects +*/ +template<typename Pair> +void delete2nd(Pair& pair) + { + delete pair.second; + } + +/* +* Insert a key/value pair into a multimap +*/ +template<typename K, typename V> +void multimap_insert(std::multimap<K, V>& multimap, + const K& key, const V& value) + { + multimap.insert(std::make_pair(key, value)); + } + +} + +#endif diff --git a/botan/src/utils/types.h b/botan/src/utils/types.h new file mode 100644 index 0000000..304628d --- /dev/null +++ b/botan/src/utils/types.h @@ -0,0 +1,42 @@ +/* +* Low Level Types +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_TYPES_H__ +#define BOTAN_TYPES_H__ + +#include <botan/build.h> + +namespace Botan { + +typedef unsigned char byte; +typedef unsigned short u16bit; +typedef unsigned int u32bit; + +typedef signed int s32bit; + +#if defined(_MSC_VER) || defined(__BORLANDC__) + typedef unsigned __int64 u64bit; +#elif defined(__KCC) + typedef unsigned __long_long u64bit; +#elif defined(__GNUG__) + __extension__ typedef unsigned long long u64bit; +#else + typedef unsigned long long u64bit; +#endif + +static const u32bit DEFAULT_BUFFERSIZE = BOTAN_DEFAULT_BUFFER_SIZE; + +} + +namespace Botan_types { + +using Botan::byte; +using Botan::u32bit; + +} + +#endif diff --git a/botan/src/utils/ui.cpp b/botan/src/utils/ui.cpp new file mode 100644 index 0000000..e6c3430 --- /dev/null +++ b/botan/src/utils/ui.cpp @@ -0,0 +1,36 @@ +/* +* User Interface +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/ui.h> + +namespace Botan { + +/* +* Get a passphrase from the user +*/ +std::string User_Interface::get_passphrase(const std::string&, + const std::string&, + UI_Result& action) const + { + action = OK; + + if(!first_try) + action = CANCEL_ACTION; + + return preset_passphrase; + } + +/* +* User_Interface Constructor +*/ +User_Interface::User_Interface(const std::string& preset) : + preset_passphrase(preset) + { + first_try = true; + } + +} diff --git a/botan/src/utils/ui.h b/botan/src/utils/ui.h new file mode 100644 index 0000000..fe62c60 --- /dev/null +++ b/botan/src/utils/ui.h @@ -0,0 +1,36 @@ +/* +* User Interface +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_UI_H__ +#define BOTAN_UI_H__ + +#include <botan/build.h> +#include <string> + +namespace Botan { + +/* +* User Interface +*/ +class BOTAN_DLL User_Interface + { + public: + enum UI_Result { OK, CANCEL_ACTION }; + + virtual std::string get_passphrase(const std::string&, + const std::string&, + UI_Result&) const; + User_Interface(const std::string& = ""); + virtual ~User_Interface() {} + protected: + std::string preset_passphrase; + mutable bool first_try; + }; + +} + +#endif diff --git a/botan/src/utils/util.cpp b/botan/src/utils/util.cpp new file mode 100644 index 0000000..84dfd1a --- /dev/null +++ b/botan/src/utils/util.cpp @@ -0,0 +1,68 @@ +/* +* Utility Functions +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/util.h> +#include <algorithm> +#include <cmath> + +namespace Botan { + +/* +* Round up n to multiple of align_to +*/ +u32bit round_up(u32bit n, u32bit align_to) + { + if(n % align_to || n == 0) + n += align_to - (n % align_to); + return n; + } + +/* +* Round down n to multiple of align_to +*/ +u32bit round_down(u32bit n, u32bit align_to) + { + return (n - (n % align_to)); + } + +/* +* Choose the exponent size for a DL group +*/ +u32bit dl_work_factor(u32bit bits) + { +#if 0 + /* + These values were taken from RFC 3526 + */ + if(bits <= 1536) + return 90; + else if(bits <= 2048) + return 110; + else if(bits <= 3072) + return 130; + else if(bits <= 4096) + return 150; + else if(bits <= 6144) + return 170; + else if(bits <= 8192) + return 190; + return 256; +#else + const u32bit MIN_ESTIMATE = 64; + + const double log_x = bits / 1.44; + + const double strength = + 2.76 * std::pow(log_x, 1.0/3.0) * std::pow(std::log(log_x), 2.0/3.0); + + if(strength > MIN_ESTIMATE) + return static_cast<u32bit>(strength); + return MIN_ESTIMATE; +#endif + } + +} diff --git a/botan/src/utils/util.h b/botan/src/utils/util.h new file mode 100644 index 0000000..ac78673 --- /dev/null +++ b/botan/src/utils/util.h @@ -0,0 +1,39 @@ +/* +* Utility Functions +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_UTIL_H__ +#define BOTAN_UTIL_H__ + +#include <botan/types.h> + +namespace Botan { + +/* +* Time Access Functions +*/ +BOTAN_DLL u64bit system_time(); + +/* +* Memory Locking Functions +*/ +BOTAN_DLL bool lock_mem(void*, u32bit); +BOTAN_DLL void unlock_mem(void*, u32bit); + +/* +* Misc Utility Functions +*/ +BOTAN_DLL u32bit round_up(u32bit, u32bit); +BOTAN_DLL u32bit round_down(u32bit, u32bit); + +/* +* Work Factor Estimates +*/ +BOTAN_DLL u32bit dl_work_factor(u32bit); + +} + +#endif diff --git a/botan/src/utils/version.cpp b/botan/src/utils/version.cpp new file mode 100644 index 0000000..d540864 --- /dev/null +++ b/botan/src/utils/version.cpp @@ -0,0 +1,36 @@ +/* +* Version Information +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/version.h> +#include <botan/parsing.h> + +namespace Botan { + +/* + These are intentionally compiled rather than inlined, so an + application running against a shared library can test the true + version they are running against. +*/ + +/* +* Return the version as a string +*/ +std::string version_string() + { + return to_string(version_major()) + "." + + to_string(version_minor()) + "." + + to_string(version_patch()); + } + +/* +* Return parts of the version as integers +*/ +u32bit version_major() { return BOTAN_VERSION_MAJOR; } +u32bit version_minor() { return BOTAN_VERSION_MINOR; } +u32bit version_patch() { return BOTAN_VERSION_PATCH; } + +} diff --git a/botan/src/utils/version.h b/botan/src/utils/version.h new file mode 100644 index 0000000..3cc44e8 --- /dev/null +++ b/botan/src/utils/version.h @@ -0,0 +1,61 @@ +/* +* Version Information +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_VERSION_H__ +#define BOTAN_VERSION_H__ + +#include <botan/types.h> +#include <string> + +namespace Botan { + +/* +* Get information describing the version +*/ + +/** +* Get the version string identifying the version of Botan. +* @return the version string +*/ +BOTAN_DLL std::string version_string(); + +/** +* Get the major version number. +* @return the major version number +*/ +BOTAN_DLL u32bit version_major(); + +/** +* Get the minor version number. +* @return the minor version number +*/ +BOTAN_DLL u32bit version_minor(); + +/** +* Get the patch number. +* @return the patch number +*/ +BOTAN_DLL u32bit version_patch(); + +/* +* Macros for compile-time version checks +*/ +#define BOTAN_VERSION_CODE_FOR(a,b,c) ((a << 16) | (b << 8) | (c)) + +/** +* Compare using BOTAN_VERSION_CODE_FOR, as in +* # if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,8,0) +* # error "Botan version too old" +* # endif +*/ +#define BOTAN_VERSION_CODE BOTAN_VERSION_CODE_FOR(BOTAN_VERSION_MAJOR, \ + BOTAN_VERSION_MINOR, \ + BOTAN_VERSION_PATCH) + +} + +#endif diff --git a/botan/src/utils/xor_buf.h b/botan/src/utils/xor_buf.h new file mode 100644 index 0000000..39781f0 --- /dev/null +++ b/botan/src/utils/xor_buf.h @@ -0,0 +1,74 @@ +/** +* XOR operations +* (C) 1999-2008 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_XOR_BUF_H__ +#define BOTAN_XOR_BUF_H__ + +#include <botan/types.h> + +namespace Botan { + +/** +* XOR arrays. Postcondition out[i] = in[i] ^ out[i] forall i = 0...length +* @param out the input/output buffer +* @param in the read-only input buffer +* @param length the length of the buffers +*/ +inline void xor_buf(byte out[], const byte in[], u32bit length) + { + while(length >= 8) + { +#if BOTAN_UNALIGNED_LOADSTOR_OK + *reinterpret_cast<u64bit*>(out) ^= *reinterpret_cast<const u64bit*>(in); +#else + out[0] ^= in[0]; out[1] ^= in[1]; + out[2] ^= in[2]; out[3] ^= in[3]; + out[4] ^= in[4]; out[5] ^= in[5]; + out[6] ^= in[6]; out[7] ^= in[7]; +#endif + + out += 8; in += 8; length -= 8; + } + for(u32bit j = 0; j != length; ++j) + out[j] ^= in[j]; + } + +/** +* XOR arrays. Postcondition out[i] = in[i] ^ in2[i] forall i = 0...length +* @param out the output buffer +* @param in the first input buffer +* @param in2 the second output buffer +* @param length the length of the three buffers +*/ +inline void xor_buf(byte out[], + const byte in[], + const byte in2[], + u32bit length) + { + while(length >= 8) + { +#if BOTAN_UNALIGNED_LOADSTOR_OK + *reinterpret_cast<u64bit*>(out) = + *reinterpret_cast<const u64bit*>(in) ^ + *reinterpret_cast<const u64bit*>(in2); +#else + out[0] = in[0] ^ in2[0]; out[1] = in[1] ^ in2[1]; + out[2] = in[2] ^ in2[2]; out[3] = in[3] ^ in2[3]; + out[4] = in[4] ^ in2[4]; out[5] = in[5] ^ in2[5]; + out[6] = in[6] ^ in2[6]; out[7] = in[7] ^ in2[7]; +#endif + + in += 8; in2 += 8; out += 8; length -= 8; + } + + for(u32bit j = 0; j != length; ++j) + out[j] = in[j] ^ in2[j]; + } + +} + +#endif |