Add Botan, a C++ crypto library.

Current Stable Release 1.8.8
This commit is contained in:
kh1
2010-01-11 13:54:00 +01:00
parent b585cbdac4
commit c72a72653c
1494 changed files with 158357 additions and 0 deletions

105
src/libs/3rdparty/botan/checks/algos.cpp vendored Normal file
View File

@@ -0,0 +1,105 @@
#include <botan/botan.h>
#include <string>
using namespace Botan;
#include "common.h"
std::vector<algorithm> get_algos()
{
std::vector<algorithm> algos;
algos.push_back(algorithm("Block Cipher", "AES-128", "AES-128/ECB", 16));
algos.push_back(algorithm("Block Cipher", "AES-192", "AES-192/ECB", 24));
algos.push_back(algorithm("Block Cipher", "AES-256", "AES-256/ECB", 32));
algos.push_back(algorithm("Block Cipher", "Blowfish", "Blowfish/ECB", 32));
algos.push_back(algorithm("Block Cipher", "CAST-128", "CAST-128/ECB", 16));
algos.push_back(algorithm("Block Cipher", "CAST-256", "CAST-256/ECB", 32));
algos.push_back(algorithm("Block Cipher", "DES", "DES/ECB", 8));
algos.push_back(algorithm("Block Cipher", "DESX", "DESX/ECB", 24));
algos.push_back(algorithm("Block Cipher", "TripleDES",
"TripleDES/ECB", 24));
algos.push_back(algorithm("Block Cipher", "GOST", "GOST/ECB", 32));
algos.push_back(algorithm("Block Cipher", "IDEA", "IDEA/ECB", 16));
algos.push_back(algorithm("Block Cipher", "KASUMI", "KASUMI/ECB", 16));
algos.push_back(algorithm("Block Cipher",
"Lion",
"Lion(SHA-256,Turing,8192)/ECB", 32));
algos.push_back(algorithm("Block Cipher", "Luby-Rackoff(SHA-512)",
"Luby-Rackoff(SHA-512)/ECB", 16));
algos.push_back(algorithm("Block Cipher", "MARS", "MARS/ECB", 32));
algos.push_back(algorithm("Block Cipher", "MISTY1", "MISTY1/ECB", 16));
algos.push_back(algorithm("Block Cipher", "Noekeon", "Noekeon/ECB", 16));
algos.push_back(algorithm("Block Cipher", "RC2", "RC2/ECB", 16));
algos.push_back(algorithm("Block Cipher", "RC5(12)", "RC5(12)/ECB", 16));
algos.push_back(algorithm("Block Cipher", "RC5(16)", "RC5(16)/ECB", 16));
algos.push_back(algorithm("Block Cipher", "RC6", "RC6/ECB", 32));
algos.push_back(algorithm("Block Cipher", "SAFER-SK(10)",
"SAFER-SK(10)/ECB", 16));
algos.push_back(algorithm("Block Cipher", "SEED", "SEED/ECB", 16));
algos.push_back(algorithm("Block Cipher", "Serpent", "Serpent/ECB", 32));
algos.push_back(algorithm("Block Cipher", "Skipjack", "Skipjack/ECB", 10));
algos.push_back(algorithm("Block Cipher", "Square", "Square/ECB", 16));
algos.push_back(algorithm("Block Cipher", "TEA", "TEA/ECB", 16));
algos.push_back(algorithm("Block Cipher", "Twofish", "Twofish/ECB", 32));
algos.push_back(algorithm("Block Cipher", "XTEA", "XTEA/ECB", 16));
algos.push_back(algorithm("Cipher Mode", "DES/CBC/PKCS7", 8, 8));
algos.push_back(algorithm("Cipher Mode", "TripleDES/CBC/PKCS7", 24, 8));
algos.push_back(algorithm("Cipher Mode", "AES-128/CBC/PKCS7", 16, 16));
algos.push_back(algorithm("Cipher Mode", "AES-128/CBC/CTS", 16, 16));
algos.push_back(algorithm("Cipher Mode", "AES-128/CFB(128)", 16, 16));
algos.push_back(algorithm("Cipher Mode", "AES-128/CFB(64)", 16, 16));
algos.push_back(algorithm("Cipher Mode", "AES-128/CFB(32)", 16, 16));
algos.push_back(algorithm("Cipher Mode", "AES-128/CFB(16)", 16, 16));
algos.push_back(algorithm("Cipher Mode", "AES-128/CFB(8)", 16, 16));
algos.push_back(algorithm("Cipher Mode", "AES-128/OFB", 16, 16));
algos.push_back(algorithm("Cipher Mode", "AES-128/CTR",
"AES-128/CTR-BE", 16, 16));
algos.push_back(algorithm("Cipher Mode", "AES-128/EAX", 16, 16));
algos.push_back(algorithm("Cipher Mode", "AES-128/XTS", 32, 16));
algos.push_back(algorithm("Stream Cipher", "ARC4", 16));
algos.push_back(algorithm("Stream Cipher", "Salsa20", 32));
algos.push_back(algorithm("Stream Cipher", "Turing", 32));
algos.push_back(algorithm("Stream Cipher", "WiderWake4+1",
"WiderWake4+1-BE", 16, 8));
algos.push_back(algorithm("Hash", "Adler32"));
algos.push_back(algorithm("Hash", "CRC24"));
algos.push_back(algorithm("Hash", "CRC32"));
algos.push_back(algorithm("Hash", "FORK-256"));
algos.push_back(algorithm("Hash", "GOST-34.11"));
algos.push_back(algorithm("Hash", "HAS-160"));
algos.push_back(algorithm("Hash", "HAS-V"));
algos.push_back(algorithm("Hash", "MD2"));
algos.push_back(algorithm("Hash", "MD4"));
algos.push_back(algorithm("Hash", "MD5"));
algos.push_back(algorithm("Hash", "RIPEMD-128"));
algos.push_back(algorithm("Hash", "RIPEMD-160"));
algos.push_back(algorithm("Hash", "SHA-160"));
algos.push_back(algorithm("Hash", "SHA-256"));
algos.push_back(algorithm("Hash", "SHA-384"));
algos.push_back(algorithm("Hash", "SHA-512"));
algos.push_back(algorithm("Hash", "Skein-512"));
algos.push_back(algorithm("Hash", "Tiger"));
algos.push_back(algorithm("Hash", "Whirlpool"));
algos.push_back(algorithm("MAC", "CMAC(AES-128)", 16));
algos.push_back(algorithm("MAC", "HMAC(SHA-1)", 16));
algos.push_back(algorithm("MAC", "X9.19-MAC", 16));
algos.push_back(algorithm("RNG", "AutoSeeded", 4096));
algos.push_back(algorithm("RNG", "HMAC_RNG", 4096));
algos.push_back(algorithm("RNG", "Randpool", 4096));
algos.push_back(algorithm("RNG", "X9.31-RNG", 4096));
algos.push_back(algorithm("Codec", "Base64_Encode"));
algos.push_back(algorithm("Codec", "Base64_Decode"));
return algos;
}

198
src/libs/3rdparty/botan/checks/bench.cpp vendored Normal file
View File

@@ -0,0 +1,198 @@
#include <iostream>
#include <iomanip>
#include <cmath>
#include <string>
#include <exception>
#include <botan/filters.h>
using Botan::byte;
using Botan::u64bit;
#include "common.h"
#include "timer.h"
#include "bench.h"
/* Discard output to reduce overhead */
struct BitBucket : public Botan::Filter
{
void write(const byte[], u32bit) {}
};
Botan::Filter* lookup(const std::string&,
const std::vector<std::string>&,
const std::string& = "All");
namespace {
double bench_filter(std::string name, Botan::Filter* filter,
Botan::RandomNumberGenerator& rng,
bool html, double seconds)
{
Botan::Pipe pipe(filter, new BitBucket);
std::vector<byte> buf(128 * 1024);
rng.randomize(&buf[0], buf.size());
pipe.start_msg();
Timer timer(name, buf.size());
while(timer.seconds() < seconds)
{
timer.start();
pipe.write(&buf[0], buf.size());
timer.stop();
}
pipe.end_msg();
double bytes_per_sec = timer.events() / timer.seconds();
double mbytes_per_sec = bytes_per_sec / (1024.0 * 1024.0);
std::cout.setf(std::ios::fixed, std::ios::floatfield);
std::cout.precision(2);
if(html)
{
if(name.find("<") != std::string::npos)
name.replace(name.find("<"), 1, "&lt;");
if(name.find(">") != std::string::npos)
name.replace(name.find(">"), 1, "&gt;");
std::cout << " <TR><TH>" << name
<< std::string(25 - name.length(), ' ') << " <TH>";
std::cout.width(6);
std::cout << mbytes_per_sec << std::endl;
}
else
{
std::cout << name << ": " << std::string(25 - name.length(), ' ');
std::cout.width(6);
std::cout << mbytes_per_sec << " MiB/sec" << std::endl;
}
return (mbytes_per_sec);
}
double bench(const std::string& name, const std::string& filtername, bool html,
double seconds, u32bit keylen, u32bit ivlen,
Botan::RandomNumberGenerator& rng)
{
std::vector<std::string> params;
Botan::SecureVector<byte> key(keylen);
rng.randomize(key, key.size());
params.push_back(hex_encode(key, key.size()));
//params.push_back(std::string(int(2*keylen), 'A'));
params.push_back(std::string(int(2* ivlen), 'A'));
Botan::Filter* filter = lookup(filtername, params);
if(filter)
return bench_filter(name, filter, rng, html, seconds);
return 0;
}
}
void benchmark(const std::string& what,
Botan::RandomNumberGenerator& rng,
bool html, double seconds)
{
try {
if(html)
{
std::cout << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD "
<< "HTML 4.0 Transitional//EN\">\n"
<< "<HTML>\n\n"
<< "<TITLE>Botan Benchmarks</TITLE>\n\n"
<< "<BODY>\n\n"
<< "<P><TABLE BORDER CELLSPACING=1>\n"
<< "<THEAD>\n"
<< "<TR><TH>Algorithm "
<< "<TH>Mib / second\n"
<< "<TBODY>\n";
}
double sum = 0;
u32bit how_many = 0;
std::vector<algorithm> algos = get_algos();
for(u32bit j = 0; j != algos.size(); j++)
if(what == "All" || what == algos[j].type)
{
double speed = bench(algos[j].name, algos[j].filtername,
html, seconds, algos[j].keylen,
algos[j].ivlen, rng);
if(speed > .00001) /* log(0) == -inf -> messed up average */
sum += std::log(speed);
how_many++;
}
if(html)
std::cout << "</TABLE>\n\n";
double average = std::exp(sum / static_cast<double>(how_many));
if(what == "All" && html)
std::cout << "\n<P>Overall speed average: " << average
<< "\n\n";
else if(what == "All")
std::cout << "\nOverall speed average: " << average
<< std::endl;
if(html) std::cout << "</BODY></HTML>\n";
}
catch(Botan::Exception& e)
{
std::cout << "Botan exception caught: " << e.what() << std::endl;
return;
}
catch(std::exception& e)
{
std::cout << "Standard library exception caught: " << e.what()
<< std::endl;
return;
}
catch(...)
{
std::cout << "Unknown exception caught." << std::endl;
return;
}
}
u32bit bench_algo(const std::string& name,
Botan::RandomNumberGenerator& rng,
double seconds)
{
try {
std::vector<algorithm> algos = get_algos();
for(u32bit j = 0; j != algos.size(); j++)
{
if(algos[j].name == name)
{
bench(algos[j].name, algos[j].filtername, false, seconds,
algos[j].keylen, algos[j].ivlen, rng);
return 1;
}
}
return 0;
}
catch(Botan::Exception& e)
{
std::cout << "Botan exception caught: " << e.what() << std::endl;
return 0;
}
catch(std::exception& e)
{
std::cout << "Standard library exception caught: " << e.what()
<< std::endl;
return 0;
}
catch(...)
{
std::cout << "Unknown exception caught." << std::endl;
return 0;
}
}

37
src/libs/3rdparty/botan/checks/bench.h vendored Normal file
View File

@@ -0,0 +1,37 @@
#ifndef BOTAN_BENCHMARCH_H__
#define BOTAN_BENCHMARCH_H__
#include <botan/rng.h>
#include <string>
#include <map>
#include <set>
#include "timer.h"
#include <iostream>
class Benchmark_Report
{
public:
void report(const std::string& name, Timer timer)
{
std::cout << name << " " << timer << std::endl;
data[name].insert(timer);
}
private:
std::map<std::string, std::set<Timer> > data;
};
void benchmark(const std::string&, Botan::RandomNumberGenerator&,
bool html, double seconds);
void bench_pk(Botan::RandomNumberGenerator&,
const std::string&, bool html, double seconds);
u32bit bench_algo(const std::string&,
Botan::RandomNumberGenerator&,
double);
#endif

View File

@@ -0,0 +1,353 @@
#include <vector>
#include <string>
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <botan/bigint.h>
#include <botan/exceptn.h>
#include <botan/numthry.h>
using namespace Botan;
#include "common.h"
#include "validate.h"
#define DEBUG 0
u32bit check_add(const std::vector<std::string>&);
u32bit check_sub(const std::vector<std::string>&);
u32bit check_mul(const std::vector<std::string>&);
u32bit check_sqr(const std::vector<std::string>&);
u32bit check_div(const std::vector<std::string>&);
u32bit check_mod(const std::vector<std::string>&,
Botan::RandomNumberGenerator& rng);
u32bit check_shr(const std::vector<std::string>&);
u32bit check_shl(const std::vector<std::string>&);
u32bit check_powmod(const std::vector<std::string>&);
u32bit check_primetest(const std::vector<std::string>&,
Botan::RandomNumberGenerator&);
u32bit do_bigint_tests(const std::string& filename,
Botan::RandomNumberGenerator& rng)
{
std::ifstream test_data(filename.c_str());
if(!test_data)
throw Botan::Stream_IO_Error("Couldn't open test file " + filename);
u32bit errors = 0, alg_count = 0;
std::string algorithm;
bool first = true;
u32bit counter = 0;
while(!test_data.eof())
{
if(test_data.bad() || test_data.fail())
throw Botan::Stream_IO_Error("File I/O error reading from " +
filename);
std::string line;
std::getline(test_data, line);
strip(line);
if(line.size() == 0) continue;
// Do line continuation
while(line[line.size()-1] == '\\' && !test_data.eof())
{
line.replace(line.size()-1, 1, "");
std::string nextline;
std::getline(test_data, nextline);
strip(nextline);
if(nextline.size() == 0) continue;
line += nextline;
}
if(line[0] == '[' && line[line.size() - 1] == ']')
{
algorithm = line.substr(1, line.size() - 2);
alg_count = 0;
counter = 0;
if(!first)
std::cout << std::endl;
std::cout << "Testing BigInt " << algorithm << ": ";
std::cout.flush();
first = false;
continue;
}
std::vector<std::string> substr = parse(line);
#if DEBUG
std::cout << "Testing: " << algorithm << std::endl;
#endif
u32bit new_errors = 0;
if(algorithm.find("Addition") != std::string::npos)
new_errors = check_add(substr);
else if(algorithm.find("Subtraction") != std::string::npos)
new_errors = check_sub(substr);
else if(algorithm.find("Multiplication") != std::string::npos)
new_errors = check_mul(substr);
else if(algorithm.find("Square") != std::string::npos)
new_errors = check_sqr(substr);
else if(algorithm.find("Division") != std::string::npos)
new_errors = check_div(substr);
else if(algorithm.find("Modulo") != std::string::npos)
new_errors = check_mod(substr, rng);
else if(algorithm.find("LeftShift") != std::string::npos)
new_errors = check_shl(substr);
else if(algorithm.find("RightShift") != std::string::npos)
new_errors = check_shr(substr);
else if(algorithm.find("ModExp") != std::string::npos)
new_errors = check_powmod(substr);
else if(algorithm.find("PrimeTest") != std::string::npos)
new_errors = check_primetest(substr, rng);
else
std::cout << "Unknown MPI test " << algorithm << std::endl;
if(counter % 3 == 0)
{
std::cout << '.';
std::cout.flush();
}
counter++;
alg_count++;
errors += new_errors;
if(new_errors)
std::cout << "ERROR: BigInt " << algorithm << " failed test #"
<< std::dec << alg_count << std::endl;
}
std::cout << std::endl;
return errors;
}
namespace {
// c==expected, d==a op b, e==a op= b
u32bit results(std::string op,
const BigInt& a, const BigInt& b,
const BigInt& c, const BigInt& d, const BigInt& e)
{
std::string op1 = "operator" + op;
std::string op2 = op1 + "=";
if(c == d && d == e)
return 0;
else
{
std::cout << std::endl;
std::cout << "ERROR: " << op1 << std::endl;
std::cout << "a = " << std::hex << a << std::endl;
std::cout << "b = " << std::hex << b << std::endl;
std::cout << "c = " << std::hex << c << std::endl;
std::cout << "d = " << std::hex << d << std::endl;
std::cout << "e = " << std::hex << e << std::endl;
if(d != e)
{
std::cout << "ERROR: " << op1 << " | " << op2
<< " mismatch" << std::endl;
}
return 1;
}
}
}
u32bit check_add(const std::vector<std::string>& args)
{
BigInt a(args[0]);
BigInt b(args[1]);
BigInt c(args[2]);
BigInt d = a + b;
BigInt e = a;
e += b;
if(results("+", a, b, c, d, e))
return 1;
d = b + a;
e = b;
e += a;
return results("+", a, b, c, d, e);
}
u32bit check_sub(const std::vector<std::string>& args)
{
BigInt a(args[0]);
BigInt b(args[1]);
BigInt c(args[2]);
BigInt d = a - b;
BigInt e = a;
e -= b;
return results("-", a, b, c, d, e);
}
u32bit check_mul(const std::vector<std::string>& args)
{
BigInt a(args[0]);
BigInt b(args[1]);
BigInt c(args[2]);
/*
std::cout << "a = " << args[0] << "\n"
<< "b = " << args[1] << std::endl;
*/
/* This makes it more likely the fast multiply algorithms will be usable,
which is what we really want to test here (the simple n^2 multiply is
pretty well tested at this point).
*/
a.grow_reg(32);
b.grow_reg(32);
BigInt d = a * b;
BigInt e = a;
e *= b;
if(results("*", a, b, c, d, e))
return 1;
d = b * a;
e = b;
e *= a;
return results("*", a, b, c, d, e);
}
u32bit check_sqr(const std::vector<std::string>& args)
{
BigInt a(args[0]);
BigInt b(args[1]);
a.grow_reg(16);
b.grow_reg(16);
BigInt c = square(a);
BigInt d = a * a;
return results("sqr", a, a, b, c, d);
}
u32bit check_div(const std::vector<std::string>& args)
{
BigInt a(args[0]);
BigInt b(args[1]);
BigInt c(args[2]);
BigInt d = a / b;
BigInt e = a;
e /= b;
return results("/", a, b, c, d, e);
}
u32bit check_mod(const std::vector<std::string>& args,
Botan::RandomNumberGenerator& rng)
{
BigInt a(args[0]);
BigInt b(args[1]);
BigInt c(args[2]);
BigInt d = a % b;
BigInt e = a;
e %= b;
u32bit got = results("%", a, b, c, d, e);
if(got) return got;
word b_word = b.word_at(0);
/* Won't work for us, just pick one at random */
while(b_word == 0)
for(u32bit j = 0; j != 2*sizeof(word); j++)
b_word = (b_word << 4) ^ rng.next_byte();
b = b_word;
c = a % b; /* we declare the BigInt % BigInt version to be correct here */
word d2 = a % b_word;
e = a;
e %= b_word;
return results("%(word)", a, b, c, d2, e);
}
u32bit check_shl(const std::vector<std::string>& args)
{
BigInt a(args[0]);
u32bit b = std::atoi(args[1].c_str());
BigInt c(args[2]);
BigInt d = a << b;
BigInt e = a;
e <<= b;
return results("<<", a, b, c, d, e);
}
u32bit check_shr(const std::vector<std::string>& args)
{
BigInt a(args[0]);
u32bit b = std::atoi(args[1].c_str());
BigInt c(args[2]);
BigInt d = a >> b;
BigInt e = a;
e >>= b;
return results(">>", a, b, c, d, e);
}
/* Make sure that (a^b)%m == r */
u32bit check_powmod(const std::vector<std::string>& args)
{
BigInt a(args[0]);
BigInt b(args[1]);
BigInt m(args[2]);
BigInt c(args[3]);
BigInt r = power_mod(a, b, m);
if(c != r)
{
std::cout << "ERROR: power_mod" << std::endl;
std::cout << "a = " << std::hex << a << std::endl;
std::cout << "b = " << std::hex << b << std::endl;
std::cout << "m = " << std::hex << m << std::endl;
std::cout << "c = " << std::hex << c << std::endl;
std::cout << "r = " << std::hex << r << std::endl;
return 1;
}
return 0;
}
/* Make sure that n is prime or not prime, according to should_be_prime */
u32bit check_primetest(const std::vector<std::string>& args,
Botan::RandomNumberGenerator& rng)
{
BigInt n(args[0]);
bool should_be_prime = (args[1] == "1");
bool is_prime = Botan::verify_prime(n, rng);
if(is_prime != should_be_prime)
{
std::cout << "ERROR: verify_prime" << std::endl;
std::cout << "n = " << n << std::endl;
std::cout << is_prime << " != " << should_be_prime << std::endl;
}
return 0;
}

View File

@@ -0,0 +1,98 @@
/*
We don't use the standard issue ECB filter, because we also want to check
that the encryption and decryption operations are inverses (ie, it works).
This class only works with NoPadding mode, unlike the regular ECB filters
*/
#include <iostream>
#include <string>
#include <cstdlib>
#include <botan/filter.h>
#include <botan/lookup.h>
using namespace Botan;
#include "common.h"
class ECB_Encryption_ErrorCheck : public Filter
{
public:
void write(const byte[], u32bit);
void end_msg();
ECB_Encryption_ErrorCheck(const std::string& cipher_name,
const std::string&,
const SymmetricKey& key) :
BLOCKSIZE(block_size_of(cipher_name))
{
const std::string HASH = "CRC32";
cipher = get_block_cipher(cipher_name);
input_hash = get_hash(HASH);
decrypt_hash = get_hash(HASH);
buffer.create(BLOCKSIZE);
cipher->set_key(key);
position = 0;
}
~ECB_Encryption_ErrorCheck()
{ delete cipher; delete input_hash; delete decrypt_hash; }
private:
const u32bit BLOCKSIZE;
BlockCipher* cipher;
SecureVector<byte> buffer;
u32bit position;
HashFunction* input_hash, *decrypt_hash;
};
void ECB_Encryption_ErrorCheck::write(const byte input[], u32bit length)
{
input_hash->update(input, length);
buffer.copy(position, input, length);
if(position + length >= BLOCKSIZE)
{
cipher->encrypt(buffer);
send(buffer, BLOCKSIZE);
cipher->decrypt(buffer);
decrypt_hash->update(buffer, BLOCKSIZE);
input += (BLOCKSIZE - position);
length -= (BLOCKSIZE - position);
while(length >= BLOCKSIZE)
{
cipher->encrypt(input, buffer);
send(buffer, BLOCKSIZE);
cipher->decrypt(buffer);
decrypt_hash->update(buffer, BLOCKSIZE);
input += BLOCKSIZE;
length -= BLOCKSIZE;
}
buffer.copy(input, length);
position = 0;
}
position += length;
}
void ECB_Encryption_ErrorCheck::end_msg()
{
SecureVector<byte> hash1 = input_hash->final();
SecureVector<byte> hash2 = decrypt_hash->final();
if(hash1 != hash2)
{
std::cout << "In " << cipher->name()
<< " decryption check failed." << std::endl;
}
if(position)
throw Exception("ECB: input was not in full blocks");
}
Filter* lookup_block(const std::string& algname, const std::string& key)
{
Filter* cipher = 0;
try {
cipher = new ECB_Encryption_ErrorCheck(algname, "NoPadding", key);
}
catch(Algorithm_Not_Found) {}
return cipher;
}

240
src/libs/3rdparty/botan/checks/check.cpp vendored Normal file
View File

@@ -0,0 +1,240 @@
/*
* Test Driver for Botan
*/
#include <vector>
#include <string>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <exception>
#include <limits>
#include <memory>
#include <botan/botan.h>
#include <botan/libstate.h>
#include <botan/mp_types.h>
using namespace Botan;
#include "getopt.h"
#include "bench.h"
#include "validate.h"
#include "common.h"
const std::string VALIDATION_FILE = "checks/validate.dat";
const std::string BIGINT_VALIDATION_FILE = "checks/mp_valid.dat";
const std::string PK_VALIDATION_FILE = "checks/pk_valid.dat";
const std::string EXPECTED_FAIL_FILE = "checks/fail.dat";
int run_test_suite(RandomNumberGenerator& rng);
namespace {
template<typename T>
bool test(const char* type, int digits, bool is_signed)
{
if(std::numeric_limits<T>::is_specialized == false)
{
std::cout << "WARNING: Could not check parameters of " << type
<< " in std::numeric_limits" << std::endl;
// assume it's OK (full tests will catch it later)
return true;
}
// continue checking after failures
bool passed = true;
if(std::numeric_limits<T>::is_integer == false)
{
std::cout << "WARN: std::numeric_limits<> says " << type
<< " is not an integer" << std::endl;
passed = false;
}
if(std::numeric_limits<T>::is_signed != is_signed)
{
std::cout << "ERROR: numeric_limits<" << type << ">::is_signed == "
<< std::boolalpha << std::numeric_limits<T>::is_signed
<< std::endl;
passed = false;
}
if(std::numeric_limits<T>::digits != digits && digits != 0)
{
std::cout << "ERROR: numeric_limits<" << type << ">::digits == "
<< std::numeric_limits<T>::digits
<< " expected " << digits << std::endl;
passed = false;
}
return passed;
}
void test_types()
{
bool passed = true;
passed = passed && test<Botan::byte >("byte", 8, false);
passed = passed && test<Botan::u16bit>("u16bit", 16, false);
passed = passed && test<Botan::u32bit>("u32bit", 32, false);
passed = passed && test<Botan::u64bit>("u64bit", 64, false);
passed = passed && test<Botan::s32bit>("s32bit", 31, true);
passed = passed && test<Botan::word>("word", 0, false);
if(!passed)
std::cout << "Typedefs in include/types.h may be incorrect!\n";
}
}
int main(int argc, char* argv[])
{
try
{
OptionParser opts("help|html|test|validate|"
"benchmark|bench-type=|bench-algo=|seconds=");
opts.parse(argv);
test_types(); // do this always
Botan::LibraryInitializer init("thread_safe=no");
Botan::AutoSeeded_RNG rng;
if(opts.is_set("help") || argc <= 1)
{
std::cerr << "Test driver for "
<< Botan::version_string() << "\n"
<< "Options:\n"
<< " --test || --validate: Run tests (do this at least once)\n"
<< " --benchmark: Benchmark everything\n"
<< " --bench-type={block,mode,stream,hash,mac,rng,pk}:\n"
<< " Benchmark only algorithms of a particular type\n"
<< " --html: Produce HTML output for benchmarks\n"
<< " --seconds=n: Benchmark for n seconds\n"
<< " --init=<str>: Pass <str> to the library\n"
<< " --help: Print this message\n";
return 1;
}
if(opts.is_set("validate") || opts.is_set("test"))
{
return run_test_suite(rng);
}
if(opts.is_set("bench-algo") ||
opts.is_set("benchmark") ||
opts.is_set("bench-type"))
{
double seconds = 5;
if(opts.is_set("seconds"))
{
seconds = std::atof(opts.value("seconds").c_str());
if(seconds < 0.1 || seconds > (5 * 60))
{
std::cout << "Invalid argument to --seconds\n";
return 2;
}
}
const bool html = opts.is_set("html");
if(opts.is_set("benchmark"))
{
benchmark("All", rng, html, seconds);
}
else if(opts.is_set("bench-algo"))
{
std::vector<std::string> algs =
Botan::split_on(opts.value("bench-algo"), ',');
for(u32bit j = 0; j != algs.size(); j++)
{
const std::string alg = algs[j];
u32bit found = bench_algo(alg, rng, seconds);
if(!found) // maybe it's a PK algorithm
bench_pk(rng, alg, html, seconds);
}
}
else if(opts.is_set("bench-type"))
{
const std::string type = opts.value("bench-type");
if(type == "all")
benchmark("All", rng, html, seconds);
else if(type == "block")
benchmark("Block Cipher", rng, html, seconds);
else if(type == "stream")
benchmark("Stream Cipher", rng, html, seconds);
else if(type == "hash")
benchmark("Hash", rng, html, seconds);
else if(type == "mode")
benchmark("Cipher Mode", rng, html, seconds);
else if(type == "mac")
benchmark("MAC", rng, html, seconds);
else if(type == "rng")
benchmark("RNG", rng, html, seconds);
else if(type == "pk")
bench_pk(rng, "All", html, seconds);
else
std::cerr << "Unknown --bench-type " << type << "\n";
}
}
}
catch(std::exception& e)
{
std::cerr << "Exception: " << e.what() << std::endl;
return 1;
}
catch(...)
{
std::cerr << "Unknown (...) exception caught" << std::endl;
return 1;
}
return 0;
}
int run_test_suite(RandomNumberGenerator& rng)
{
std::cout << "Beginning tests..." << std::endl;
u32bit errors = 0;
try
{
errors += do_validation_tests(VALIDATION_FILE, rng);
errors += do_validation_tests(EXPECTED_FAIL_FILE, rng, false);
errors += do_bigint_tests(BIGINT_VALIDATION_FILE, rng);
errors += do_pk_validation_tests(PK_VALIDATION_FILE, rng);
//errors += do_cvc_tests(rng);
}
catch(Botan::Exception& e)
{
std::cout << "Exception caught: " << e.what() << std::endl;
return 1;
}
catch(std::exception& e)
{
std::cout << "Standard library exception caught: "
<< e.what() << std::endl;
return 1;
}
catch(...)
{
std::cout << "Unknown exception caught." << std::endl;
return 1;
}
if(errors)
{
std::cout << errors << " test" << ((errors == 1) ? "" : "s")
<< " failed." << std::endl;
return 1;
}
std::cout << "All tests passed!" << std::endl;
return 0;
}

View File

@@ -0,0 +1,82 @@
#include "timer.h"
#include <botan/build.h>
/*************************************************
* Platform specific settings for which clock type to use
*/
#if !defined(USE_CLOCK_GETTIME) && defined(BOTAN_TARGET_OS_IS_LINUX)
#define USE_GETTIMEOFDAY 1
#endif
#if !defined(USE_GETTIMEOFDAY) && defined(BOTAN_TARGET_OS_IS_FREEBSD)
#define USE_GETTIMEOFDAY 1
#endif
/*************************************************
Set the default, which is clock
*/
#ifndef USE_CLOCK_GETTIME
#define USE_CLOCK_GETTIME 0
#endif
#ifndef USE_GETTIMEOFDAY
#define USE_GETTIMEOFDAY 0
#endif
#ifndef USE_TIMES
#define USE_TIMES 0
#endif
/* the default: ANSI/ISO clock */
#ifndef USE_CLOCK
#define USE_CLOCK 1
#endif
#if USE_CLOCK_GETTIME
#include <time.h>
#elif USE_GETTIMEOFDAY
#include <sys/time.h>
#elif USE_TIMES
#include <sys/times.h>
#include <unistd.h>
#elif USE_CLOCK
#include <time.h>
#endif
/* The implementation: */
u64bit Timer::get_clock()
{
static const u64bit billion = 1000000000;
#if USE_CLOCK_GETTIME
struct timespec tv;
clock_gettime(CLOCK_REALTIME, &tv);
return (billion * tv.tv_sec + tv.tv_nsec);
#elif USE_GETTIMEOFDAY
struct timeval tv;
gettimeofday(&tv, 0);
return (billion * tv.tv_sec + 1000 * tv.tv_usec);
#elif USE_TIMES
struct tms tms;
times(&tms);
static const u64bit clocks_to_nanoseconds =
(billion / sysconf(_SC_CLK_TCK));
return (tms.tms_utime * clocks_to_nanoseconds);
#elif USE_CLOCK
static const u64bit clocks_to_nanoseconds =
(billion / CLOCKS_PER_SEC);
return clock() * clocks_to_nanoseconds;
#endif
}

100
src/libs/3rdparty/botan/checks/common.h vendored Normal file
View File

@@ -0,0 +1,100 @@
// common code for the validation and benchmark code
#ifndef BOTAN_CHECK_COMMON_H__
#define BOTAN_CHECK_COMMON_H__
#include <vector>
#include <string>
#include <deque>
#include <stdexcept>
#include <botan/secmem.h>
#include <botan/filter.h>
#include <botan/rng.h>
using Botan::byte;
using Botan::u32bit;
struct algorithm
{
algorithm(const char* t, const char* n,
u32bit k = 0, u32bit i = 0) :
type(t), name(n), filtername(n), keylen(k), ivlen(i) {}
algorithm(const char* t, const char* n,
const char* f, u32bit k = 0, u32bit i = 0) :
type(t), name(n), filtername(f), keylen(k), ivlen(i) {}
std::string type, name, filtername;
u32bit keylen, ivlen, weight;
};
std::vector<algorithm> get_algos();
void strip_comments(std::string& line);
void strip_newlines(std::string& line);
void strip(std::string& line);
std::vector<std::string> parse(const std::string& line);
std::string hex_encode(const byte in[], u32bit len);
Botan::SecureVector<byte> decode_hex(const std::string&);
Botan::Filter* lookup(const std::string& algname,
const std::vector<std::string>& params,
const std::string& section);
Botan::Filter* lookup_block(const std::string&, const std::string&);
Botan::Filter* lookup_cipher(const std::string&, const std::string&,
const std::string&, bool);
Botan::Filter* lookup_hash(const std::string&);
Botan::Filter* lookup_mac(const std::string&, const std::string&);
Botan::Filter* lookup_rng(const std::string&, const std::string&);
Botan::Filter* lookup_encoder(const std::string&);
Botan::Filter* lookup_s2k(const std::string&, const std::vector<std::string>&);
Botan::Filter* lookup_kdf(const std::string&, const std::string&,
const std::string&);
class Fixed_Output_RNG : public Botan::RandomNumberGenerator
{
public:
bool is_seeded() const { return !buf.empty(); }
byte random()
{
if(buf.empty())
throw std::runtime_error("Out of bytes");
byte out = buf.front();
buf.pop_front();
return out;
}
void reseed(u32bit) {}
void randomize(byte out[], u32bit len)
{
for(u32bit j = 0; j != len; j++)
out[j] = random();
}
std::string name() const { return "Fixed_Output_RNG"; }
void add_entropy_source(Botan::EntropySource* src) { delete src; }
void add_entropy(const byte[], u32bit) {};
void clear() throw() {}
Fixed_Output_RNG(const Botan::SecureVector<byte>& in)
{
buf.insert(buf.end(), in.begin(), in.begin() + in.size());
}
Fixed_Output_RNG(const std::string& in_str)
{
Botan::SecureVector<byte> in = decode_hex(in_str);
buf.insert(buf.end(), in.begin(), in.begin() + in.size());
}
Fixed_Output_RNG() {}
private:
std::deque<byte> buf;
};
#endif

View File

@@ -0,0 +1,600 @@
/******************************************************
* CVC EAC1.1 tests *
* *
* (C) 2008 Falko Strenzke *
* strenzke@flexsecure.de *
* 2008 Jack Lloyd *
******************************************************/
#include "validate.h"
#include <botan/build.h>
#if defined(BOTAN_HAS_CARD_VERIFIABLE_CERTIFICATES)
#include <iosfwd>
#include <iostream>
#include <iterator>
#include <algorithm>
#include <fstream>
#include <vector>
#include <botan/ecdsa.h>
#include <botan/rsa.h>
#include <botan/x509cert.h>
#include <botan/x509self.h>
#include <botan/oids.h>
#include <botan/look_pk.h>
#include <botan/cvc_self.h>
#include <botan/cvc_cert.h>
#include <botan/util.h>
#include <botan/cvc_ado.h>
#define TEST_DATA_DIR "checks/ecc_testdata"
using namespace Botan;
#define CHECK_MESSAGE(expr, print) try { if(!(expr)) std::cout << print << "\n"; } catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << "\n"; }
#define CHECK(expr) try { if(!(expr)) std::cout << #expr << "\n"; } catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << "\n"; }
namespace {
// helper functions
void helper_write_file(EAC_Signed_Object const& to_write, std::string const& file_path)
{
SecureVector<byte> sv = to_write.BER_encode();
std::ofstream cert_file(file_path.c_str(), std::ios::binary);
cert_file.write((char*)sv.begin(), sv.size());
cert_file.close();
}
bool helper_files_equal(std::string const& file_path1, std::string const& file_path2)
{
std::ifstream cert_1_in(file_path1.c_str());
std::ifstream cert_2_in(file_path2.c_str());
SecureVector<byte> sv1;
SecureVector<byte> sv2;
if (!cert_1_in || !cert_2_in)
{
return false;
}
while (!cert_1_in.eof())
{
char now;
cert_1_in.read(&now, 1);
sv1.append(now);
}
while (!cert_2_in.eof())
{
char now;
cert_2_in.read(&now, 1);
sv2.append(now);
}
if (sv1.size() == 0)
{
return false;
}
return sv1 == sv2;
}
void test_enc_gen_selfsigned(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
EAC1_1_CVC_Options opts;
//opts.cpi = 0;
opts.chr = ASN1_Chr("my_opt_chr"); // not used
opts.car = ASN1_Car("my_opt_car");
opts.cex = ASN1_Cex("2010 08 13");
opts.ced = ASN1_Ced("2010 07 27");
opts.holder_auth_templ = 0xC1;
opts.hash_alg = "SHA-256";
// creating a non sense selfsigned cert w/o dom pars
EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.36.3.3.2.8.1.1.11"));
ECDSA_PrivateKey key(rng, dom_pars);
key.set_parameter_encoding(ENC_IMPLICITCA);
EAC1_1_CVC cert = CVC_EAC::create_self_signed_cert(key, opts, rng);
SecureVector<byte> der(cert.BER_encode());
std::ofstream cert_file;
cert_file.open(TEST_DATA_DIR "/my_cv_cert.ber", std::ios::binary);
//cert_file << der; // this is bad !!!
cert_file.write((char*)der.begin(), der.size());
cert_file.close();
EAC1_1_CVC cert_in(TEST_DATA_DIR "/my_cv_cert.ber");
CHECK(cert == cert_in);
// encoding it again while it has no dp
SecureVector<byte> der2(cert_in.BER_encode());
std::ofstream cert_file2(TEST_DATA_DIR "/my_cv_cert2.ber", std::ios::binary);
cert_file2.write((char*)der2.begin(), der2.size());
cert_file2.close();
// read both and compare them
std::ifstream cert_1_in(TEST_DATA_DIR "/my_cv_cert.ber");
std::ifstream cert_2_in(TEST_DATA_DIR "/my_cv_cert2.ber");
SecureVector<byte> sv1;
SecureVector<byte> sv2;
if (!cert_1_in || !cert_2_in)
{
CHECK_MESSAGE(false, "could not read certificate files");
}
while (!cert_1_in.eof())
{
char now;
cert_1_in.read(&now, 1);
sv1.append(now);
}
while (!cert_2_in.eof())
{
char now;
cert_2_in.read(&now, 1);
sv2.append(now);
}
CHECK(sv1.size() > 10);
CHECK_MESSAGE(sv1 == sv2, "reencoded file of cert without domain parameters is different from original");
//cout << "reading cert again\n";
CHECK(cert_in.get_car().value() == "my_opt_car");
CHECK(cert_in.get_chr().value() == "my_opt_car");
CHECK(cert_in.get_ced().as_string() == "20100727");
CHECK(cert_in.get_ced().readable_string() == "2010/07/27 ");
bool ill_date_exc = false;
try
{
ASN1_Ced("1999 01 01");
}
catch (...)
{
ill_date_exc = true;
}
CHECK(ill_date_exc);
bool ill_date_exc2 = false;
try
{
ASN1_Ced("2100 01 01");
}
catch (...)
{
ill_date_exc2 = true;
}
CHECK(ill_date_exc2);
//cout << "readable = '" << cert_in.get_ced().readable_string() << "'\n";
std::auto_ptr<Public_Key> p_pk = cert_in.subject_public_key();
//auto_ptr<ECDSA_PublicKey> ecdsa_pk = dynamic_cast<auto_ptr<ECDSA_PublicKey> >(p_pk);
ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get());
// let´s see if encoding is truely implicitca, because this is what the key should have
// been set to when decoding (see above)(because it has no domain params):
//cout << "encoding = " << p_ecdsa_pk->get_parameter_encoding() << std::endl;
CHECK(p_ecdsa_pk->get_parameter_encoding() == ENC_IMPLICITCA);
bool exc = false;
try
{
std::cout << "order = " << p_ecdsa_pk->domain_parameters().get_order() << std::endl;
}
catch (Invalid_State)
{
exc = true;
}
CHECK(exc);
// set them and try again
//cert_in.set_domain_parameters(dom_pars);
std::auto_ptr<Public_Key> p_pk2 = cert_in.subject_public_key();
ECDSA_PublicKey* p_ecdsa_pk2 = dynamic_cast<ECDSA_PublicKey*>(p_pk2.get());
p_ecdsa_pk2->set_domain_parameters(dom_pars);
CHECK(p_ecdsa_pk2->domain_parameters().get_order() == dom_pars.get_order());
bool ver_ec = cert_in.check_signature(*p_pk2);
CHECK_MESSAGE(ver_ec, "could not positively verify correct selfsigned cvc certificate");
}
void test_enc_gen_req(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
EAC1_1_CVC_Options opts;
//opts.cpi = 0;
opts.chr = ASN1_Chr("my_opt_chr");
opts.hash_alg = "SHA-160";
// creating a non sense selfsigned cert w/o dom pars
EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.132.0.8"));
ECDSA_PrivateKey key(rng, dom_pars);
key.set_parameter_encoding(ENC_IMPLICITCA);
EAC1_1_Req req = CVC_EAC::create_cvc_req(key, opts.chr, opts.hash_alg, rng);
SecureVector<byte> der(req.BER_encode());
std::ofstream req_file(TEST_DATA_DIR "/my_cv_req.ber", std::ios::binary);
req_file.write((char*)der.begin(), der.size());
req_file.close();
// read and check signature...
EAC1_1_Req req_in(TEST_DATA_DIR "/my_cv_req.ber");
//req_in.set_domain_parameters(dom_pars);
std::auto_ptr<Public_Key> p_pk = req_in.subject_public_key();
ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get());
p_ecdsa_pk->set_domain_parameters(dom_pars);
CHECK(p_ecdsa_pk->domain_parameters().get_order() == dom_pars.get_order());
bool ver_ec = req_in.check_signature(*p_pk);
CHECK_MESSAGE(ver_ec, "could not positively verify correct selfsigned (created by myself) cvc request");
}
void test_cvc_req_ext(RandomNumberGenerator&)
{
std::cout << "." << std::flush;
EAC1_1_Req req_in(TEST_DATA_DIR "/DE1_flen_chars_cvcRequest_ECDSA.der");
EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.36.3.3.2.8.1.1.5")); // "german curve"
//req_in.set_domain_parameters(dom_pars);
std::auto_ptr<Public_Key> p_pk = req_in.subject_public_key();
ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get());
p_ecdsa_pk->set_domain_parameters(dom_pars);
CHECK(p_ecdsa_pk->domain_parameters().get_order() == dom_pars.get_order());
bool ver_ec = req_in.check_signature(*p_pk);
CHECK_MESSAGE(ver_ec, "could not positively verify correct selfsigned (external testdata) cvc request");
}
void test_cvc_ado_ext(RandomNumberGenerator&)
{
std::cout << "." << std::flush;
EAC1_1_ADO req_in(TEST_DATA_DIR "/ado.cvcreq");
EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.36.3.3.2.8.1.1.5")); // "german curve"
//cout << "car = " << req_in.get_car().value() << std::endl;
//req_in.set_domain_parameters(dom_pars);
}
void test_cvc_ado_creation(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
EAC1_1_CVC_Options opts;
//opts.cpi = 0;
opts.chr = ASN1_Chr("my_opt_chr");
opts.hash_alg = "SHA-256";
// creating a non sense selfsigned cert w/o dom pars
EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.36.3.3.2.8.1.1.11"));
//cout << "mod = " << hex << dom_pars.get_curve().get_p() << std::endl;
ECDSA_PrivateKey req_key(rng, dom_pars);
req_key.set_parameter_encoding(ENC_IMPLICITCA);
//EAC1_1_Req req = CVC_EAC::create_cvc_req(req_key, opts);
EAC1_1_Req req = CVC_EAC::create_cvc_req(req_key, opts.chr, opts.hash_alg, rng);
SecureVector<byte> der(req.BER_encode());
std::ofstream req_file(TEST_DATA_DIR "/my_cv_req.ber", std::ios::binary);
req_file.write((char*)der.begin(), der.size());
req_file.close();
// create an ado with that req
ECDSA_PrivateKey ado_key(rng, dom_pars);
EAC1_1_CVC_Options ado_opts;
ado_opts.car = ASN1_Car("my_ado_car");
ado_opts.hash_alg = "SHA-256"; // must be equal to req´s hash alg, because ado takes his sig_algo from it´s request
//EAC1_1_ADO ado = CVC_EAC::create_ado_req(ado_key, req, ado_opts);
EAC1_1_ADO ado = CVC_EAC::create_ado_req(ado_key, req, ado_opts.car, rng);
CHECK_MESSAGE(ado.check_signature(ado_key), "failure of ado verification after creation");
std::ofstream ado_file(TEST_DATA_DIR "/ado", std::ios::binary);
SecureVector<byte> ado_der(ado.BER_encode());
ado_file.write((char*)ado_der.begin(), ado_der.size());
ado_file.close();
// read it again and check the signature
EAC1_1_ADO ado2(TEST_DATA_DIR "/ado");
CHECK(ado == ado2);
//ECDSA_PublicKey* p_ado_pk = dynamic_cast<ECDSA_PublicKey*>(&ado_key);
//bool ver = ado2.check_signature(*p_ado_pk);
bool ver = ado2.check_signature(ado_key);
CHECK_MESSAGE(ver, "failure of ado verification after reloading");
}
void test_cvc_ado_comparison(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
EAC1_1_CVC_Options opts;
//opts.cpi = 0;
opts.chr = ASN1_Chr("my_opt_chr");
opts.hash_alg = "SHA-224";
// creating a non sense selfsigned cert w/o dom pars
EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.36.3.3.2.8.1.1.11"));
ECDSA_PrivateKey req_key(rng, dom_pars);
req_key.set_parameter_encoding(ENC_IMPLICITCA);
//EAC1_1_Req req = CVC_EAC::create_cvc_req(req_key, opts);
EAC1_1_Req req = CVC_EAC::create_cvc_req(req_key, opts.chr, opts.hash_alg, rng);
// create an ado with that req
ECDSA_PrivateKey ado_key(rng, dom_pars);
EAC1_1_CVC_Options ado_opts;
ado_opts.car = ASN1_Car("my_ado_car1");
ado_opts.hash_alg = "SHA-224"; // must be equal to req's hash alg, because ado takes his sig_algo from it's request
//EAC1_1_ADO ado = CVC_EAC::create_ado_req(ado_key, req, ado_opts);
EAC1_1_ADO ado = CVC_EAC::create_ado_req(ado_key, req, ado_opts.car, rng);
CHECK_MESSAGE(ado.check_signature(ado_key), "failure of ado verification after creation");
// make a second one for comparison
EAC1_1_CVC_Options opts2;
//opts2.cpi = 0;
opts2.chr = ASN1_Chr("my_opt_chr");
opts2.hash_alg = "SHA-160"; // this is the only difference
ECDSA_PrivateKey req_key2(rng, dom_pars);
req_key.set_parameter_encoding(ENC_IMPLICITCA);
//EAC1_1_Req req2 = CVC_EAC::create_cvc_req(req_key2, opts2, rng);
EAC1_1_Req req2 = CVC_EAC::create_cvc_req(req_key2, opts2.chr, opts2.hash_alg, rng);
ECDSA_PrivateKey ado_key2(rng, dom_pars);
EAC1_1_CVC_Options ado_opts2;
ado_opts2.car = ASN1_Car("my_ado_car1");
ado_opts2.hash_alg = "SHA-160"; // must be equal to req's hash alg, because ado takes his sig_algo from it's request
EAC1_1_ADO ado2 = CVC_EAC::create_ado_req(ado_key2, req2, ado_opts2.car, rng);
CHECK_MESSAGE(ado2.check_signature(ado_key2), "failure of ado verification after creation");
CHECK_MESSAGE(ado != ado2, "ado's found to be equal where they are not");
// std::ofstream ado_file(TEST_DATA_DIR "/ado");
// SecureVector<byte> ado_der(ado.BER_encode());
// ado_file.write((char*)ado_der.begin(), ado_der.size());
// ado_file.close();
// read it again and check the signature
// EAC1_1_ADO ado2(TEST_DATA_DIR "/ado");
// ECDSA_PublicKey* p_ado_pk = dynamic_cast<ECDSA_PublicKey*>(&ado_key);
// //bool ver = ado2.check_signature(*p_ado_pk);
// bool ver = ado2.check_signature(ado_key);
// CHECK_MESSAGE(ver, "failure of ado verification after reloading");
}
void test_eac_time(RandomNumberGenerator&)
{
std::cout << "." << std::flush;
const u64bit current_time = system_time();
EAC_Time time(current_time);
// std::cout << "time as std::string = " << time.as_string() << std::endl;
EAC_Time sooner("", ASN1_Tag(99));
//X509_Time sooner("", ASN1_Tag(99));
sooner.set_to("2007 12 12");
// std::cout << "sooner as std::string = " << sooner.as_string() << std::endl;
EAC_Time later("2007 12 13");
//X509_Time later("2007 12 13");
// std::cout << "later as std::string = " << later.as_string() << std::endl;
CHECK(sooner <= later);
CHECK(sooner == sooner);
ASN1_Cex my_cex("2007 08 01");
my_cex.add_months(12);
CHECK(my_cex.get_year() == 2008);
CHECK_MESSAGE(my_cex.get_month() == 8, "shoult be 8, was " << my_cex.get_month());
my_cex.add_months(4);
CHECK(my_cex.get_year() == 2008);
CHECK(my_cex.get_month() == 12);
my_cex.add_months(4);
CHECK(my_cex.get_year() == 2009);
CHECK(my_cex.get_month() == 4);
my_cex.add_months(41);
CHECK(my_cex.get_year() == 2012);
CHECK(my_cex.get_month() == 9);
}
void test_ver_cvca(RandomNumberGenerator&)
{
std::cout << "." << std::flush;
EAC1_1_CVC req_in(TEST_DATA_DIR "/cvca01.cv.crt");
//auto_ptr<ECDSA_PublicKey> ecdsa_pk = dynamic_cast<auto_ptr<ECDSA_PublicKey> >(p_pk);
//ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get());
bool exc = false;
std::auto_ptr<Public_Key> p_pk2 = req_in.subject_public_key();
ECDSA_PublicKey* p_ecdsa_pk2 = dynamic_cast<ECDSA_PublicKey*>(p_pk2.get());
bool ver_ec = req_in.check_signature(*p_pk2);
CHECK_MESSAGE(ver_ec, "could not positively verify correct selfsigned cvca certificate");
try
{
p_ecdsa_pk2->domain_parameters().get_order();
}
catch (Invalid_State)
{
exc = true;
}
CHECK(!exc);
}
void test_copy_and_assignment(RandomNumberGenerator&)
{
std::cout << "." << std::flush;
EAC1_1_CVC cert_in(TEST_DATA_DIR "/cvca01.cv.crt");
EAC1_1_CVC cert_cp(cert_in);
EAC1_1_CVC cert_ass = cert_in;
CHECK(cert_in == cert_cp);
CHECK(cert_in == cert_ass);
EAC1_1_ADO ado_in(TEST_DATA_DIR "/ado.cvcreq");
//EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.36.3.3.2.8.1.1.5")); // "german curve"
EAC1_1_ADO ado_cp(ado_in);
EAC1_1_ADO ado_ass = ado_in;
CHECK(ado_in == ado_cp);
CHECK(ado_in == ado_ass);
EAC1_1_Req req_in(TEST_DATA_DIR "/DE1_flen_chars_cvcRequest_ECDSA.der");
//EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.36.3.3.2.8.1.1.5")); // "german curve"
EAC1_1_Req req_cp(req_in);
EAC1_1_Req req_ass = req_in;
CHECK(req_in == req_cp);
CHECK(req_in == req_ass);
}
void test_eac_str_illegal_values(RandomNumberGenerator&)
{
std::cout << "." << std::flush;
bool exc = false;
try
{
EAC1_1_CVC(TEST_DATA_DIR "/cvca_illegal_chars.cv.crt");
}
catch (Decoding_Error)
{
exc = true;
}
CHECK(exc);
bool exc2 = false;
try
{
EAC1_1_CVC(TEST_DATA_DIR "/cvca_illegal_chars2.cv.crt");
}
catch (Decoding_Error)
{
exc2 = true;
}
CHECK(exc2);
}
void test_tmp_eac_str_enc(RandomNumberGenerator&)
{
std::cout << "." << std::flush;
bool exc = false;
try
{
ASN1_Car("abc!+-µ\n");
}
catch (Invalid_Argument)
{
exc = true;
}
CHECK(exc);
// std::string val = car.iso_8859();
// std::cout << "car 8859 = " << val << std::endl;
// std::cout << hex <<(unsigned char)val[1] << std::endl;
}
void test_cvc_chain(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.36.3.3.2.8.1.1.5")); // "german curve"
ECDSA_PrivateKey cvca_privk(rng, dom_pars);
std::string hash("SHA-224");
ASN1_Car car("DECVCA00001");
EAC1_1_CVC cvca_cert = DE_EAC::create_cvca(cvca_privk, hash, car, true, true, 12, rng);
std::ofstream cvca_file(TEST_DATA_DIR "/cvc_chain_cvca.cer", std::ios::binary);
SecureVector<byte> cvca_sv = cvca_cert.BER_encode();
cvca_file.write((char*)cvca_sv.begin(), cvca_sv.size());
cvca_file.close();
ECDSA_PrivateKey cvca_privk2(rng, dom_pars);
ASN1_Car car2("DECVCA00002");
EAC1_1_CVC cvca_cert2 = DE_EAC::create_cvca(cvca_privk2, hash, car2, true, true, 12, rng);
EAC1_1_CVC link12 = DE_EAC::link_cvca(cvca_cert, cvca_privk, cvca_cert2, rng);
SecureVector<byte> link12_sv = link12.BER_encode();
std::ofstream link12_file(TEST_DATA_DIR "/cvc_chain_link12.cer", std::ios::binary);
link12_file.write((char*)link12_sv.begin(), link12_sv.size());
link12_file.close();
// verify the link
CHECK(link12.check_signature(cvca_privk));
EAC1_1_CVC link12_reloaded(TEST_DATA_DIR "/cvc_chain_link12.cer");
EAC1_1_CVC cvca1_reloaded(TEST_DATA_DIR "/cvc_chain_cvca.cer");
std::auto_ptr<Public_Key> cvca1_rel_pk = cvca1_reloaded.subject_public_key();
CHECK(link12_reloaded.check_signature(*cvca1_rel_pk));
// create first round dvca-req
ECDSA_PrivateKey dvca_priv_key(rng, dom_pars);
EAC1_1_Req dvca_req = DE_EAC::create_cvc_req(dvca_priv_key, ASN1_Chr("DEDVCAEPASS"), hash, rng);
std::ofstream dvca_file(TEST_DATA_DIR "/cvc_chain_dvca_req.cer", std::ios::binary);
SecureVector<byte> dvca_sv = dvca_req.BER_encode();
dvca_file.write((char*)dvca_sv.begin(), dvca_sv.size());
dvca_file.close();
// sign the dvca_request
EAC1_1_CVC dvca_cert1 = DE_EAC::sign_request(cvca_cert, cvca_privk, dvca_req, 1, 5, true, 3, 1, rng);
CHECK(dvca_cert1.get_car().iso_8859() == "DECVCA00001");
CHECK(dvca_cert1.get_chr().iso_8859() == "DEDVCAEPASS00001");
helper_write_file(dvca_cert1, TEST_DATA_DIR "/cvc_chain_dvca_cert1.cer");
// make a second round dvca ado request
ECDSA_PrivateKey dvca_priv_key2(rng, dom_pars);
EAC1_1_Req dvca_req2 = DE_EAC::create_cvc_req(dvca_priv_key2, ASN1_Chr("DEDVCAEPASS"), hash, rng);
std::ofstream dvca_file2(TEST_DATA_DIR "/cvc_chain_dvca_req2.cer", std::ios::binary);
SecureVector<byte> dvca_sv2 = dvca_req2.BER_encode();
dvca_file2.write((char*)dvca_sv2.begin(), dvca_sv2.size());
dvca_file2.close();
EAC1_1_ADO dvca_ado2 = CVC_EAC::create_ado_req(dvca_priv_key, dvca_req2,
ASN1_Car(dvca_cert1.get_chr().iso_8859()), rng);
helper_write_file(dvca_ado2, TEST_DATA_DIR "/cvc_chain_dvca_ado2.cer");
// verify the ado and sign the request too
std::auto_ptr<Public_Key> ap_pk = dvca_cert1.subject_public_key();
ECDSA_PublicKey* cert_pk = dynamic_cast<ECDSA_PublicKey*>(ap_pk.get());
cert_pk->set_domain_parameters(dom_pars);
//std::cout << "dvca_cert.public_point.size() = " << ec::EC2OSP(cert_pk->get_public_point(), ec::PointGFp::COMPRESSED).size() << std::endl;
EAC1_1_CVC dvca_cert1_reread(TEST_DATA_DIR "/cvc_chain_cvca.cer");
CHECK(dvca_ado2.check_signature(*cert_pk));
CHECK(dvca_ado2.check_signature(dvca_priv_key)); // must also work
EAC1_1_Req dvca_req2b = dvca_ado2.get_request();
helper_write_file(dvca_req2b, TEST_DATA_DIR "/cvc_chain_dvca_req2b.cer");
CHECK(helper_files_equal(TEST_DATA_DIR "/cvc_chain_dvca_req2b.cer", TEST_DATA_DIR "/cvc_chain_dvca_req2.cer"));
EAC1_1_CVC dvca_cert2 = DE_EAC::sign_request(cvca_cert, cvca_privk, dvca_req2b, 2, 5, true, 3, 1, rng);
CHECK(dvca_cert2.get_car().iso_8859() == "DECVCA00001");
CHECK_MESSAGE(dvca_cert2.get_chr().iso_8859() == "DEDVCAEPASS00002",
"chr = " << dvca_cert2.get_chr().iso_8859());
// make a first round IS request
ECDSA_PrivateKey is_priv_key(rng, dom_pars);
EAC1_1_Req is_req = DE_EAC::create_cvc_req(is_priv_key, ASN1_Chr("DEIS"), hash, rng);
helper_write_file(is_req, TEST_DATA_DIR "/cvc_chain_is_req.cer");
// sign the IS request
//dvca_cert1.set_domain_parameters(dom_pars);
EAC1_1_CVC is_cert1 = DE_EAC::sign_request(dvca_cert1, dvca_priv_key, is_req, 1, 5, true, 3, 1, rng);
CHECK_MESSAGE(is_cert1.get_car().iso_8859() == "DEDVCAEPASS00001", "car = " << is_cert1.get_car().iso_8859());
CHECK(is_cert1.get_chr().iso_8859() == "DEIS00001");
helper_write_file(is_cert1, TEST_DATA_DIR "/cvc_chain_is_cert.cer");
// verify the signature of the certificate
CHECK(is_cert1.check_signature(dvca_priv_key));
}
}
u32bit do_cvc_tests(Botan::RandomNumberGenerator& rng)
{
test_enc_gen_selfsigned(rng);
test_enc_gen_req(rng);
test_cvc_req_ext(rng);
test_cvc_ado_ext(rng);
test_cvc_ado_creation(rng);
test_cvc_ado_comparison(rng);
test_eac_time(rng);
test_ver_cvca(rng);
test_copy_and_assignment(rng);
test_eac_str_illegal_values(rng);
test_tmp_eac_str_enc(rng);
test_cvc_chain(rng);
return 0;
}
#else
u32bit do_cvc_tests(Botan::RandomNumberGenerator&) { return 0; }
#endif

View File

@@ -0,0 +1,130 @@
#include <vector>
#include <string>
#include <botan/lookup.h>
#include <botan/filters.h>
#include <botan/libstate.h>
#ifdef BOTAN_HAS_COMPRESSOR_BZIP2
#include <botan/bzip2.h>
#endif
#ifdef BOTAN_HAS_COMPRESSOR_GZIP
#include <botan/gzip.h>
#endif
#ifdef BOTAN_HAS_COMPRESSOR_ZLIB
#include <botan/zlib.h>
#endif
using namespace Botan;
#include "common.h"
Filter* lookup(const std::string& algname,
const std::vector<std::string>& params,
const std::string& section)
{
std::string key = params[0];
std::string iv = params[1];
Filter* filter = 0;
// The order of the lookup has to change based on how the names are
// formatted and parsed.
filter = lookup_kdf(algname, key, iv);
if(filter) return filter;
if(section == "Cipher Modes (Decryption)")
filter = lookup_cipher(algname, key, iv, false);
else
filter = lookup_cipher(algname, key, iv, true);
if(filter) return filter;
filter = lookup_block(algname, key);
if(filter) return filter;
filter = lookup_rng(algname, key);
if(filter) return filter;
filter = lookup_encoder(algname);
if(filter) return filter;
filter = lookup_hash(algname);
if(filter) return filter;
filter = lookup_mac(algname, key);
if(filter) return filter;
filter = lookup_s2k(algname, params);
if(filter) return filter;
return 0;
}
Filter* lookup_hash(const std::string& algname)
{
Filter* hash = 0;
try {
hash = new Hash_Filter(algname);
}
catch(Algorithm_Not_Found) {}
return hash;
}
Filter* lookup_mac(const std::string& algname, const std::string& key)
{
Filter* mac = 0;
try {
mac = new MAC_Filter(algname, key);
}
catch(Algorithm_Not_Found) {}
return mac;
}
Filter* lookup_cipher(const std::string& algname, const std::string& key,
const std::string& iv, bool encrypt)
{
try {
if(encrypt)
return get_cipher(algname, key, iv, ENCRYPTION);
else
return get_cipher(algname, key, iv, DECRYPTION);
}
catch(Algorithm_Not_Found) {}
catch(Invalid_Algorithm_Name) {}
return 0;
}
Filter* lookup_encoder(const std::string& algname)
{
if(algname == "Base64_Encode")
return new Base64_Encoder;
if(algname == "Base64_Decode")
return new Base64_Decoder;
#ifdef BOTAN_HAS_COMPRESSOR_BZIP2
if(algname == "Bzip_Compression")
return new Bzip_Compression(9);
if(algname == "Bzip_Decompression")
return new Bzip_Decompression;
#endif
#ifdef BOTAN_HAS_COMPRESSOR_GZIP
if(algname == "Gzip_Compression")
return new Gzip_Compression(9);
if(algname == "Gzip_Decompression")
return new Gzip_Decompression;
#endif
#ifdef BOTAN_HAS_COMPRESSOR_ZLIB
if(algname == "Zlib_Compression")
return new Zlib_Compression(9);
if(algname == "Zlib_Decompression")
return new Zlib_Decompression;
#endif
return 0;
}

View File

@@ -0,0 +1,212 @@
#include <vector>
#include <string>
#include <cstdlib>
#include <botan/botan.h>
#include <botan/lookup.h>
#include <botan/filters.h>
#include <botan/hmac.h>
#include <botan/aes.h>
#include <botan/sha2_32.h>
#include <botan/sha2_64.h>
#if defined(BOTAN_HAS_RANDPOOL)
#include <botan/randpool.h>
#endif
#if defined(BOTAN_HAS_HMAC_RNG)
#include <botan/hmac_rng.h>
#endif
#if defined(BOTAN_HAS_X931_RNG)
#include <botan/x931_rng.h>
#include <botan/des.h>
#endif
#if defined(BOTAN_HAS_AUTO_SEEDING_RNG)
#include <botan/auto_rng.h>
#endif
#include "common.h"
using namespace Botan;
/* A weird little hack to fit S2K algorithms into the validation suite
You probably wouldn't ever want to actually use the S2K algorithms like
this, the raw S2K interface is more convenient for actually using them
*/
class S2K_Filter : public Filter
{
public:
void write(const byte in[], u32bit len)
{ passphrase += std::string(reinterpret_cast<const char*>(in), len); }
void end_msg()
{
s2k->change_salt(salt, salt.size());
s2k->set_iterations(iterations);
SymmetricKey x = s2k->derive_key(outlen, passphrase);
send(x.bits_of());
}
S2K_Filter(S2K* algo, const SymmetricKey& s, u32bit o, u32bit i)
{
s2k = algo;
outlen = o;
iterations = i;
salt = s.bits_of();
}
~S2K_Filter() { delete s2k; }
private:
std::string passphrase;
S2K* s2k;
SecureVector<byte> salt;
u32bit outlen, iterations;
};
/* Not too useful generally; just dumps random bits for benchmarking */
class RNG_Filter : public Filter
{
public:
void write(const byte[], u32bit);
RNG_Filter(RandomNumberGenerator* r) : rng(r) {}
~RNG_Filter() { delete rng; }
private:
RandomNumberGenerator* rng;
};
class KDF_Filter : public Filter
{
public:
void write(const byte in[], u32bit len)
{ secret.append(in, len); }
void end_msg()
{
SymmetricKey x = kdf->derive_key(outlen,
secret, secret.size(),
salt, salt.size());
send(x.bits_of(), x.length());
}
KDF_Filter(KDF* algo, const SymmetricKey& s, u32bit o)
{
kdf = algo;
outlen = o;
salt = s.bits_of();
}
~KDF_Filter() { delete kdf; }
private:
SecureVector<byte> secret;
SecureVector<byte> salt;
KDF* kdf;
u32bit outlen;
};
Filter* lookup_s2k(const std::string& algname,
const std::vector<std::string>& params)
{
S2K* s2k = 0;
try {
s2k = get_s2k(algname);
}
catch(...) { }
if(s2k)
return new S2K_Filter(s2k, params[0], to_u32bit(params[1]),
to_u32bit(params[2]));
return 0;
}
void RNG_Filter::write(const byte[], u32bit length)
{
if(length)
{
SecureVector<byte> out(length);
rng->randomize(out, out.size());
send(out);
}
}
Filter* lookup_rng(const std::string& algname,
const std::string& key)
{
RandomNumberGenerator* prng = 0;
#if defined(BOTAN_HAS_AUTO_SEEDING_RNG)
if(algname == "AutoSeeded")
prng = new AutoSeeded_RNG;
#endif
#if defined(BOTAN_HAS_X931_RNG)
if(algname == "X9.31-RNG(TripleDES)")
prng = new ANSI_X931_RNG(new TripleDES,
new Fixed_Output_RNG(decode_hex(key)));
else if(algname == "X9.31-RNG(AES-128)")
prng = new ANSI_X931_RNG(new AES_128,
new Fixed_Output_RNG(decode_hex(key)));
else if(algname == "X9.31-RNG(AES-192)")
prng = new ANSI_X931_RNG(new AES_192,
new Fixed_Output_RNG(decode_hex(key)));
else if(algname == "X9.31-RNG(AES-256)")
prng = new ANSI_X931_RNG(new AES_256,
new Fixed_Output_RNG(decode_hex(key)));
#endif
#if defined(BOTAN_HAS_RANDPOOL)
if(algname == "Randpool")
{
prng = new Randpool(new AES_256, new HMAC(new SHA_256));
prng->add_entropy(reinterpret_cast<const byte*>(key.c_str()),
key.length());
}
#endif
#if defined(BOTAN_HAS_X931_RNG)
// these are used for benchmarking: AES-256/SHA-256 matches library
// defaults, so benchmark reflects real-world performance (maybe)
if(algname == "X9.31-RNG")
{
RandomNumberGenerator* rng =
#if defined(BOTAN_HAS_HMAC_RNG)
new HMAC_RNG(new HMAC(new SHA_512), new HMAC(new SHA_256));
#elif defined(BOTAN_HAS_RANDPOOL)
new Randpool(new AES_256, new HMAC(new SHA_256));
#endif
prng = new ANSI_X931_RNG(new AES_256, rng);
}
#endif
#if defined(BOTAN_HAS_HMAC_RNG)
if(algname == "HMAC_RNG")
{
prng = new HMAC_RNG(new HMAC(new SHA_512), new HMAC(new SHA_256));
}
#endif
if(prng)
{
prng->add_entropy(reinterpret_cast<const byte*>(key.c_str()),
key.length());
return new RNG_Filter(prng);
}
return 0;
}
Filter* lookup_kdf(const std::string& algname, const std::string& salt,
const std::string& params)
{
KDF* kdf = 0;
try {
kdf = get_kdf(algname);
}
catch(...) { return 0; }
if(kdf)
return new KDF_Filter(kdf, salt, to_u32bit(params));
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDWjCCAwWgAwIBAgIBATAMBggqhkjOPQQDAQUAMFAxCzAJBgNVBAYTAkRFMQ0w
CwYDVQQKDARidW5kMQwwCgYDVQQLDANic2kxDTALBgNVBAUTBDQ1NjcxFTATBgNV
BAMMDGNzY2EtZ2VybWFueTAeFw0wNzA3MTkxNTI3MThaFw0yODAxMTkxNTE4MDBa
MFAxCzAJBgNVBAYTAkRFMQ0wCwYDVQQKDARidW5kMQwwCgYDVQQLDANic2kxDTAL
BgNVBAUTBDQ1NjcxFTATBgNVBAMMDGNzY2EtZ2VybWFueTCCARMwgdQGByqGSM49
AgEwgcgCAQEwKAYHKoZIzj0BAQIdANfBNKomQ2aGKhgwJXXR14ewnwdXl9qJ9X7I
wP8wPAQcaKXmLKnObBwpmAOmwVMLUU4YKtiwBCpZytKfQwQcJYD2PM/kQTiHBxOx
qSNp4z4hNdJm27NyOGxACwQ5BA2QKa0sflz0NAgjsqh9xoyeTOMXTB5u/e4SwH1Y
qlb3csBybyTGuJ5OzawkNUuemcqj9tN2FALNAh0A18E0qiZDZoYqGDAlddD7mNEW
vEtt3ryjpaeTnwIBAQM6AAQBNkpLDwEC6VAqudxoVdkLBlpvXl5IOV+DCdV8Eauv
8hdWYH72dX7JiGyiItg8oEsamfpDxam84aOCARAwggEMMDYGA1UdEQQvMC2BGGNz
Y2EtZ2VybWFueUBic2kuYnVuZC5kZYYRZmF4Ois0OTIyODk1ODI3MjIwDgYDVR0P
AQH/BAQDAgEGMB0GA1UdDgQWBBQAlkUt5Yj5ZsTM3xYd0fP1NBtx5zAfBgNVHSME
GDAWgBQAlkUt5Yj5ZsTM3xYd0fP1NBtx5zBBBgNVHSAEOjA4MDYGCQQAfwAHAwEB
ATApMCcGCCsGAQUFBwIBFhtodHRwOi8vd3d3LmJzaS5idW5kLmRlL2NzY2EwEgYD
VR0TAQH/BAgwBgEB/wIBADArBgNVHRAEJDAigA8yMDA3MDcxOTE1MjcxOFqBDzIw
MjcxMTE5MTUxODAwWjAMBggqhkjOPQQDAQUAA0EAMD4CHQDGtB6DAhf9TJO1np4r
E3NOCcGC+mP67kEVqO3VAh0A0nk42gG4lRqQZKG2lq7fGBt0logpwTjw6y9iOw==
-----END CERTIFICATE-----

Binary file not shown.

View File

@@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIID1TCCAz6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJERTEV
MBMGA1UECgwMVFUgRGFybXN0YWR0MQwwCgYDVQQLDANDREMxFjAUBgNVBAMMDUxp
RElBIENBIDE6UE4wHhcNMDQwNzA1MTQzNDM1WhcNMDkwNzA1MTQzMDM0WjBKMQsw
CQYDVQQGEwJERTEVMBMGA1UECgwMVFUgRGFybXN0YWR0MQwwCgYDVQQLDANDREMx
FjAUBgNVBAMMDUxpRElBIENBIDE6UE4wgaAwDQYJKoZIhvcNAQEBBQADgY4AMIGK
AoGBAJI+ARML7sZAYYGcmjhxAGCi7Iohg6/dWSP/WWv2dEtRQ1k0GOa7HV2j9aD5
myVRfNCs/9uFggTLuWGreDHE6+gAIpmGjbohQPopPwK8p0C4Lk+lPwOkXnoC3sQS
AMpfiIZ9URfkHQ4IdQCBkOtRBLiYN5PKycC4nVXUmf+hjUMNAgRAAACBo4IByDCC
AcQwDgYDVR0PAQH/BAQDAgIEMHEGA1UdIARqMGgwZgYLKwYBBAHAbQMEAgEwVzBV
BggrBgEFBQcCARZJaHR0cHM6Ly93d3cubGlkaWEtY2EuY2RjLmluZm9ybWF0aWsu
dHUtZGFybXN0YWR0LmRlL0FubWVsZHVuZy94NTA5djMuaHRtbDCB6gYDVR0fBIHi
MIHfMIHcoIHZoIHWhoHTbGRhcDovL2xpZGlhLWNhLmNkYy5pbmZvcm1hdGlrLnR1
LWRhcm1zdGFkdC5kZTozODkvY249TGlESUEtQ0ElMjBDUkwtU2lnbmVyJTIwMTpQ
TixvdT1DREMsbz1UVSUyMERhcm1zdGFkdCxjPURFLGRjPUxpRElBLUNBLGRjPWxp
ZGlhLWNhLGRjPWNkYyxkYz1pbmZvcm1hdGlrLGRjPXR1LWRhcm1zdGFkdCxkYz1k
ZT9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0O2JpbmFyeTASBgNVHRMBAf8ECDAG
AQH/AgEAMB8GA1UdIwQYMBaAFN8gbG59DBnAHra5WZDGLDT9Hd2PMB0GA1UdDgQW
BBTfIGxufQwZwB62uVmQxiw0/R3djzANBgkqhkiG9w0BAQUFAAOBgQA87i/oRFnF
2wvZjFOGozRQjXEK1BLqhJEz+atbQzuY0aBdg95zTC/xJR8MuV2PjHuvSnpwf7nt
Ff5qsD0ewYk41VIlymWDprX6QAAze4oHDmK05Da6E4IzeKFl+/fXF7qNhLNN/Qld
ETaAOM6MIA5WZtjwQPl1jZphtwm3F5ALwg==
-----END CERTIFICATE-----

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
MGQCMG+ULXRAhLe+GESTVKd+aT3tn46209cLl9LTxDoj1lz/G9Xlw4QpwuCP1TJnRwNySgIwUu+8u32frzcZ2EhNMRrFcyH9t/8GGdvAlszc4k4TSvMK+Rz+5eZ+6hYX3lEsusCY

View File

@@ -0,0 +1,7 @@
-----BEGIN PRIVATE KEY-----
MIHaAgEAMIG0BgcqhkjOPQIBMIGoAgEBMCIGByqGSM49AQECFw4aFhluYAAAAAC8
d5mvQORfIMKCpz8jMDIEFwpp6Dq3yY/XFMent6k68ZVN0TLoYuwCBBcF27ytezfC
QvUCsMLrgpmKMPgl7QmshQQvBAegDesPaZK6sjNlLdtcbzMdfScPlwnsBYlNHz+Z
VzzAHH+at1C946ahHkssjp4CFw4aFhluYAAAAAC8fxYY2GexW7hkdEGPAgEBBB4w
HAIBAQQXBJJ/aqWyXJt0gblb7AjQYjSqWnHULjY=
-----END PRIVATE KEY-----

Binary file not shown.

View File

@@ -0,0 +1 @@
!aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!

Binary file not shown.

View File

@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDJDCCAqmgAwIBAgIRAMIJXZsHSYcafmLTmEPf5m8wDAYIKoZIzj0EAwEFADA7
MQswCQYDVQQGEwJERTETMBEGA1UEChMKRmxleFNlY3VyZTEXMBUGA1UEAxMOSW5T
aVRvIFRlc3QgQ0EwHhcNMDgxMDA5MTg1MzUyWhcNMDkxMDA5MTg1MzUyWjA7MQsw
CQYDVQQGEwJERTETMBEGA1UEChMKRmxleFNlY3VyZTEXMBUGA1UEAxMOSW5TaVRv
IFRlc3QgQ0EwggGFMIIBTQYHKoZIzj0CATCCAUACAQEwPAYHKoZIzj0BAQIxAIy5
HoKjOG0oD11vflDmQd8VL3EJ7VRWtBKx2hl/txEjrNOnKZAdGnGHRwATMQfsUzBk
BDB7w4LGPYwVDDxyCArOBa+gwr6ijk+yJ4cTkWXvupH5D4qlgUpQOtTrBKjH3SLO
KCYEMASox90izigmizm1VBbwRHwvt33hB9zSpi6IDqU+62LVfLQ5ApXbyZQ6t4aW
+lBMEQRhBB0cZPBoz0X/oqY6gbfBP2uIR6PnfvFP49t/yv4MvRDo6CbgNDbWRqrv
h7LiR9SvHoq+HXUg+cKkXLHrjpXP1VJitwsp/uxYZOGcBU/5kSkoDkZGIXeRgRFC
ggNBJjxTFQIxAIy5HoKjOG0oD11vflDmQd8VL3EJ7VRWsx8WbmysBCWnzzq2r2t/
wxA7iDIC6QRlZQIBAQMyAAM3OveZo7xFgTJqYZ2C1nydlMMZ6d2KuHgS7Q3+SkbS
QGy4k7p87QwpLNRhjSPU/qejXjBcMB0GA1UdDgQWBBTLFJODc8gnNtBMOi5lf9qi
bQoStjAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0RBBAwDoEMdGVzdEB0ZXN0LmRlMBIG
A1UdEwEB/wQIMAYBAf8CAQgwDAYIKoZIzj0EAwEFAANnADBkAjAIqO6/nN20oxQx
maPvFCBdPXgTEfsZt8hc3GPO7nCiRGcdn877NNyO+vPGuffE47QCME3P8WHvuUU8
dcrs9ZP/dAX8rRWZ2pTatGjufkwRThYRanM5UMVycsJ6l5Miw1KCyA==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIIB5zCCAWygAwIBAgIRAKiVxgiRp/wH4oOF+uzoC/EwDAYIKoZIzj0EAwEFADA7
MQswCQYDVQQGEwJERTETMBEGA1UEChMKRmxleFNlY3VyZTEXMBUGA1UEAxMOSW5T
aVRvIFRlc3QgQ0EwHhcNMDgxMDA5MTg1MzUyWhcNMDkxMDA5MTg1MzUyWjA7MQsw
CQYDVQQGEwJERTETMBEGA1UEChMKRmxleFNlY3VyZTEXMBUGA1UEAxMOSW5TaVRv
IFRlc3QgQ0EwSjAUBgcqhkjOPQIBBgkrJAMDAggBAQsDMgACE6zPzVimCycfprq0
rfuJY1kBLJBvClZUkRP0qRBIU9c1pnZcJdoC4Nks3Mwf/QZoo14wXDAdBgNVHQ4E
FgQUJBauyO+U5gtgw2LqHCG40qle4+owDgYDVR0PAQH/BAQDAgEGMBcGA1UdEQQQ
MA6BDHRlc3RAdGVzdC5kZTASBgNVHRMBAf8ECDAGAQH/AgEIMAwGCCqGSM49BAMB
BQADZwAwZAIwMtaUw+Hqnm5hB1T1zIc9OEb3VvUAuWFhppbRO87Yo2UZBc/mSVf2
7KHGSRBBJBZ3AjB9KJIaRCacFYOb8aENOgDHlwwtAdQKrjPH1bEVdotmQePS2hIv
DNGNLlqllCnQWvU=
-----END CERTIFICATE-----

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,12 @@
-----BEGIN PRIVATE KEY-----
MIIB0QIBADCCAYcGByqGSM49AgEwggF6AgEBMEUGByqGSM49AQECOgthcsnViAAA
AAAAAAAAAAAAAAAAAAAAAAAAAEdshQ7mkmMLkJZUVU4Ol915g3uKHPNUo9AwD+x4
7PkweAQ6Cjd97ea1IzM9NseOmw6qO/SM6TBB9tT8NAFNCPaDOAdJje7dQpAQHFhm
6N+1iUhdEzV7nnjC1/vp/gQ6CprPjIumF3d+JIUJvLRxfU2zRiAr+eNSzVYzcx3Z
KlG3Kk3Ds9F8gj/Mj72k2gjyXeqJBGCHNCWVpwR1BAgVI9A9TxLNAoed6kv2pPOn
3ybtiI8QxbIjWhJ0w4ai8hgwDe5u0heEEWRTO83JA/B6CW+fv07pW6wJihEfKW9Y
MP5cNbPjRNXfOiJWmF9k++bQ7cxMYdGL72gd05nfPQGUxaQxXgEuAkXs6lY2W6qe
i+H3AjoLYXLJ1YgAAAAAAAAAAAAAAAAAAAAAAAAAAABHbIeQSOXYXqco7S6hwduS
xOT5ZSNk/c26d1X6bDYvAgEBBEEwPwIBAQQ6CQZ+cOjNmFKHK7JoXGdAPByb7XfI
kTIoUEiQxOiDRUH9pUqf0lpcCHhjtTb9hQZ1RGYrjqsccdL6ng==
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,11 @@
-----BEGIN PRIVATE KEY-----
MIIBjQIBADCCAU0GByqGSM49AgEwggFAAgEBMDwGByqGSM49AQECMQCMuR6Cozht
KA9db35Q5kHfFS9xCe1UVrQSsdoZf7cRI6zTpymQHRpxh0cAEzEH7FMwZAQwe8OC
xj2MFQw8cggKzgWvoMK+oo5PsieHE5Fl77qR+Q+KpYFKUDrU6wSox90izigmBDAE
qMfdIs4oJos5tVQW8ER8L7d94Qfc0qYuiA6lPuti1Xy0OQKV28mUOreGlvpQTBEE
YQQdHGTwaM9F/6KmOoG3wT9riEej537xT+Pbf8r+DL0Q6Ogm4DQ21kaq74ey4kfU
rx6Kvh11IPnCpFyx646Vz9VSYrcLKf7sWGThnAVP+ZEpKA5GRiF3kYERQoIDQSY8
UxUCMQCMuR6CozhtKA9db35Q5kHfFS9xCe1UVrMfFm5srAQlp886tq9rf8MQO4gy
AukEZWUCAQEENzA1AgEBBDB5HVMmAiyXDGqBKoKEHNIk02EMVKKdHqXG6kDInWC/
R4ZVuXK3T8DqJrRX7RHxndk=
-----END PRIVATE KEY-----

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,5 @@
-----BEGIN PRIVATE KEY-----
MGACAQAwGAYHKoZIzj0CAQYNKwYBBAHAbQMBAgkAIQRBMD8CAQEEOgG97/hDkXbJ
tgF36JmM7NliJIlDFzTm69KYouwhjPOsh6hKo5NPTtsmHafplOqpUf0TyAhB1Q88
3xA=
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIDFDCCApgCAQAwaTELMAkGA1UEBhMCREUxCzAJBgNVBAgTAk1EMRIwEAYDVQQH
EwlCYWx0aW1vcmUxEzARBgNVBAoTCkZsZXhTZWN1cmUxEDAOBgNVBAsTB1Rlc3Rp
bmcxEjAQBgNVBAMUCXRlc3RfemVydDCCAYUwggFNBgcqhkjOPQIBMIIBQAIBATA8
BgcqhkjOPQEBAjEAjLkegqM4bSgPXW9+UOZB3xUvcQntVFa0ErHaGX+3ESOs06cp
kB0acYdHABMxB+xTMGQEMHvDgsY9jBUMPHIICs4Fr6DCvqKOT7InhxORZe+6kfkP
iqWBSlA61OsEqMfdIs4oJgQwBKjH3SLOKCaLObVUFvBEfC+3feEH3NKmLogOpT7r
YtV8tDkCldvJlDq3hpb6UEwRBGEEHRxk8GjPRf+ipjqBt8E/a4hHo+d+8U/j23/K
/gy9EOjoJuA0NtZGqu+HsuJH1K8eir4ddSD5wqRcseuOlc/VUmK3Cyn+7Fhk4ZwF
T/mRKSgORkYhd5GBEUKCA0EmPFMVAjEAjLkegqM4bSgPXW9+UOZB3xUvcQntVFaz
HxZubKwEJafPOrava3/DEDuIMgLpBGVlAgEBAzIAAjv2NeapXSWoiFe/2KBvFS8x
lDmexNgl0TK6vgVCDoI2AOVkkJQ9wjqpFsrKG67YlqCBnjArBgkqhkiG9w0BCQcx
HhMcYSBmaXhlZCBjaGFsbGVuZ2UgcGFzc3BocmFzZTBvBgkqhkiG9w0BCQ4xYjBg
MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgbAMCcGA1UdJQQgMB4GCCsGAQUF
BwMCBggrBgEFBQcDBwYIKwYBBQUHAwQwFwYDVR0RBBAwDoEMdGVzdEB0ZXN0LmRl
MAwGCCqGSM49BAMBBQADaAAwZQIxAIOkl6jVpL8C2V6zpUqnLQEMC+T8ocxKGxnm
+0ZKEgwMCqfD9WJo2C1hZ/1iZPcQmgIwKNMUgDbn16AZZqJCk/2sU0JvqkR0D/Ue
FksrSdAxjpnauRDOXMTbzpdsnzAnDNIU
-----END CERTIFICATE REQUEST-----

View File

@@ -0,0 +1,12 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIB1jCCAVsCAQAwaTELMAkGA1UEBhMCREUxCzAJBgNVBAgTAk1EMRIwEAYDVQQH
EwlCYWx0aW1vcmUxEzARBgNVBAoTCkZsZXhTZWN1cmUxEDAOBgNVBAsTB1Rlc3Rp
bmcxEjAQBgNVBAMUCXRlc3RfemVydDBKMBQGByqGSM49AgEGCSskAwMCCAEBCwMy
AAMLt+cMOPYmbgVHwaUFmEJIfYCNpgPyWkIyYHPiY4SF2UC0nTQv7el1+Dpt4Ueo
mQGggZ4wKwYJKoZIhvcNAQkHMR4THGEgZml4ZWQgY2hhbGxlbmdlIHBhc3NwaHJh
c2UwbwYJKoZIhvcNAQkOMWIwYDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIG
wDAnBgNVHSUEIDAeBggrBgEFBQcDAgYIKwYBBQUHAwcGCCsGAQUFBwMEMBcGA1Ud
EQQQMA6BDHRlc3RAdGVzdC5kZTAMBggqhkjOPQQDAQUAA2cAMGQCMC4uFJYZ7CUN
rqQrCAxJAqWIuZrKvvlHyu+Q6VibIUjwh2guPNJDmbW/iorXcu3yAwIwbOjPSSMD
5XvumhMwuV6kHmn+5DjCPLUQLuLQhNeU06bExcCuutz5DMVix05w7gox
-----END CERTIFICATE REQUEST-----

View File

@@ -0,0 +1,13 @@
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIB4TBDBgkqhkiG9w0BBQ0wNjAeBgkqhkiG9w0BBQwwEQQIS+GhX0d3oQkCAggA
AgEYMBQGCCqGSIb3DQMHBAjSmLY2CqIVlgSCAZicGlQqDD2ZC8Tmnp43tqUnFnMc
ZU6RdY5ys1WQ2Blvn5eKhK0n9yz3b9LvIzs9U6shbBPN/GePeOFFZQi0M9+SIrjj
NjpjqaJtUvhPt3tDn0B3o0raWLsJ2TvXxO0UNRZYk1YniGEecCUY/shMPpop6Tns
079QXRNuAqGeEcouKIQcJjGR3GbPbccBUUbkAjrK7f4tMTHOzoei3SJ50IcSh1hh
vYbyKFBmxi30gYc95T9VO+XsrDLP4QZXrM6S6o8xkbx1o9hHuGeiSiSOpQ/6iVUt
nRMR1GW1MZGQeJazdnccx+8C4iuW9LOfyvA7HEC8F0LLZ6mCGtLcMt8Vk+en24nJ
od4W0EqJmcasfbF+VNPNuFzwIPvEzgeyYTp5P6wfc81cqlBMfl1AGKFR8u9372UW
PWPcsqrGR3OggRcXvRc+9UKtsLoALel8esZrJzNurqkU10XePUR9Vup3Ke7kvT/o
g+uA5vboio3Jy2FoJE/YF0jKDJfbzMWJeSetJwLfrKEvsmdpUf9jeUoaze0S4LzB
JHJ+NMg=
-----END ENCRYPTED PRIVATE KEY-----

View File

@@ -0,0 +1,13 @@
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIB4TBDBgkqhkiG9w0BBQ0wNjAeBgkqhkiG9w0BBQwwEQQIJ7F/jO3zVxQCAggA
AgEYMBQGCCqGSIb3DQMHBAjBY6p0ZIHowASCAZg/JGcpBr2lh1x9WUI7J/1jCdwn
HvJu+aes3+I57MdI75ca7Z5wixO50pYUWkfexfdkm5k11HVz7ETJuNvVw+p937kI
EJtX0ukBsdsgcGcoKFCZG1JIhClqyCnx38CIdE1C8TE/7Yyk5YFMeNP9LbMH9jC5
gAJV9+YSpw1F9q6OOXv61s9uKIHq7VWza77CJKjFNLpn1/5FqTISmDXV3V2Rs8eI
j7hFMRBpRnEAA+DOgjuEkTMgF7UR39YTTBooUSzUB4kSlRQxeP7HrulboLB0ukO3
CT5qa/kA9lHJgHYZXNjzS5NzsoZeZcU934AEBm7J2vr/voHYU8zPrgRAmz8D25Gf
UH4kaQLZ3LDGlbcba8yjlOYd+x5Rl9H6vKORoqAGN0sLPLAryjzs+vS486SUlRiy
LsNqcrSOYoW1MyOYAJajxvUsUDqZyxp64TMegZlyLZGIu2ngFOd1gZsh+T2X3g8C
Murum3ynFx+H3HF1JwpZB/gImz+BI8JigUnd4fG2gqvx7wu6cqoaRGJQayilj64O
AZU+x5c=
-----END ENCRYPTED PRIVATE KEY-----

556
src/libs/3rdparty/botan/checks/ecdsa.cpp vendored Normal file
View File

@@ -0,0 +1,556 @@
/******************************************************
* ECDSA tests *
* *
* (C) 2007 Falko Strenzke *
* Manuel Hartl *
* 2008 Jack Lloyd *
******************************************************/
#include "validate.h"
#if defined(BOTAN_HAS_ECDSA)
#include <botan/botan.h>
#include <botan/look_pk.h>
#include <botan/ecdsa.h>
#include <botan/rsa.h>
#include <botan/x509cert.h>
#include <botan/oids.h>
#include <iostream>
#include <fstream>
#include "common.h"
using namespace Botan;
#define TEST_DATA_DIR "checks/ecc_testdata"
#define CHECK_MESSAGE(expr, print) try { if(!(expr)) std::cout << print << "\n"; } catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << "\n"; }
#define CHECK(expr) try { if(!(expr)) std::cout << #expr << "\n"; } catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << "\n"; }
namespace {
std::string to_hex(const SecureVector<byte>& bin)
{
return hex_encode(bin.begin(), bin.size());
}
/**
* Tests whether the the signing routine will work correctly in case the integer e
* that is constructed from the message (thus the hash value) is larger than n, the order of the base point.
* Tests the signing function of the pk signer object
*/
void test_hash_larger_than_n(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.132.0.8"));
// n:
// 0x0100000000000000000001f4c8f927aed3ca752257 // 21 bytes
// -> shouldn't work with SHA224 which outputs 23 bytes
ECDSA_PrivateKey priv_key(rng, dom_pars);
SecureVector<byte> message;
for (unsigned j= 0; j<20; j++)
{
message.append(j);
}
for (int i = 0; i<3; i++)
{
//cout << "i = " << i << endl;
std::string format;
if(i==1)
{
format = "EMSA1_BSI(SHA-224)";
}
else
{
format = "EMSA1_BSI(SHA-1)";
}
std::auto_ptr<PK_Signer> pk_signer(get_pk_signer(priv_key, format));
SecureVector<byte> signature;
bool sig_exc = false;
try
{
signature = pk_signer->sign_message(message, rng);
}
catch(Encoding_Error e)
{
sig_exc = true;
}
if(i==1)
{
CHECK(sig_exc);
}
if(i==0)
{
CHECK(!sig_exc);
}
if(i==0) // makes no sense to check for sha224
{
std::auto_ptr<PK_Verifier> pk_verifier(get_pk_verifier(priv_key, format));
bool ver = pk_verifier->verify_message(message, signature);
CHECK(ver);
}
} // for
// now check that verification alone fails
// sign it with the normal EMSA1
std::auto_ptr<PK_Signer> pk_signer(get_pk_signer(priv_key, "EMSA1(SHA-224)"));
SecureVector<byte> signature = pk_signer->sign_message(message, rng);
std::auto_ptr<PK_Verifier> pk_verifier(get_pk_verifier(priv_key, "EMSA1_BSI(SHA-224)"));
// verify against EMSA1_BSI
// we make sure it doesn't fail because of the invalid signature,
// but because of the Encoding_Error
bool ver_exc = false;
try
{
pk_verifier->verify_message(message, signature);
}
catch(Encoding_Error e)
{
ver_exc = true;
}
CHECK(ver_exc);
}
/**
* Tests whether the the signing routine will work correctly in case the integer e
* that is constructed from the message is larger than n, the order of the base point
*/
void test_message_larger_than_n(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.132.0.8"));
ECDSA_PrivateKey priv_key(rng, dom_pars);
std::string str_message = ("12345678901234567890abcdef1212345678901234567890abcdef1212345678901234567890abcdef12");
SecureVector<byte> sv_message = decode_hex(str_message);
bool thrn = false;
SecureVector<byte> signature;
try
{
signature = priv_key.sign(sv_message.begin(), sv_message.size(), rng);
}
catch (Invalid_Argument e)
{
thrn = true;
}
//cout << "signature = " << hex_encode(signature.begin(), signature.size()) << "\n";
bool ver_success = priv_key.verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size());
CHECK_MESSAGE(ver_success, "generated signature could not be verified positively");
//CHECK_MESSAGE(thrn, "no exception was thrown although message to sign was too long");
}
void test_decode_ecdsa_X509()
{
std::cout << "." << std::flush;
X509_Certificate cert(TEST_DATA_DIR "/CSCA.CSCA.csca-germany.1.crt");
CHECK_MESSAGE(OIDS::lookup(cert.signature_algorithm().oid) == "ECDSA/EMSA1_BSI(SHA-224)", "error reading signature algorithm from x509 ecdsa certificate");
CHECK_MESSAGE(to_hex(cert.serial_number()) == "01", "error reading serial from x509 ecdsa certificate");
CHECK_MESSAGE(to_hex(cert.authority_key_id()) == "0096452DE588F966C4CCDF161DD1F3F5341B71E7", "error reading authority key id from x509 ecdsa certificate");
CHECK_MESSAGE(to_hex(cert.subject_key_id()) == "0096452DE588F966C4CCDF161DD1F3F5341B71E7", "error reading Subject key id from x509 ecdsa certificate");
std::auto_ptr<X509_PublicKey> pubkey(cert.subject_public_key());
bool ver_ec = cert.check_signature(*pubkey);
CHECK_MESSAGE(ver_ec, "could not positively verify correct selfsigned x509-ecdsa certificate");
}
void test_decode_ver_link_SHA256()
{
std::cout << "." << std::flush;
X509_Certificate root_cert(TEST_DATA_DIR "/root2_SHA256.cer");
X509_Certificate link_cert(TEST_DATA_DIR "/link_SHA256.cer");
std::auto_ptr<X509_PublicKey> pubkey(root_cert.subject_public_key());
bool ver_ec = link_cert.check_signature(*pubkey);
CHECK_MESSAGE(ver_ec, "could not positively verify correct SHA256 link x509-ecdsa certificate");
}
void test_decode_ver_link_SHA1()
{
std::cout << "." << std::flush;
X509_Certificate root_cert(TEST_DATA_DIR "/root_SHA1.163.crt");
X509_Certificate link_cert(TEST_DATA_DIR "/link_SHA1.166.crt");
std::auto_ptr<X509_PublicKey> pubkey(root_cert.subject_public_key());
bool ver_ec = link_cert.check_signature(*pubkey);
CHECK_MESSAGE(ver_ec, "could not positively verify correct SHA1 link x509-ecdsa certificate");
}
void test_sign_then_ver(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
std::string g_secp("024a96b5688ef573284664698968c38bb913cbfc82");
SecureVector<byte> sv_g_secp = decode_hex(g_secp);
BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff");
BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc");
BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45");
BigInt order = BigInt("0x0100000000000000000001f4c8f927aed3ca752257");
CurveGFp curve(GFpElement(bi_p_secp,bi_a_secp), GFpElement(bi_p_secp, bi_b_secp), bi_p_secp);
BigInt cofactor = BigInt(1);
PointGFp p_G = OS2ECP ( sv_g_secp, curve );
EC_Domain_Params dom_pars = EC_Domain_Params(curve, p_G, order, cofactor);
ECDSA_PrivateKey my_priv_key(rng, dom_pars);
std::string str_message = ("12345678901234567890abcdef12");
SecureVector<byte> sv_message = decode_hex(str_message);
SecureVector<byte> signature = my_priv_key.sign(sv_message.begin(), sv_message.size(), rng);
//cout << "signature = " << hex_encode(signature.begin(), signature.size()) << "\n";
bool ver_success = my_priv_key.verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size());
CHECK_MESSAGE(ver_success, "generated signature could not be verified positively");
signature[signature.size()-1] += 0x01;
bool ver_must_fail = my_priv_key.verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size());
CHECK_MESSAGE(!ver_must_fail, "corrupted signature could be verified positively");
}
bool test_ec_sign(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
try
{
EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.132.0.8"));
ECDSA_PrivateKey priv_key(rng, dom_pars);
std::string pem_encoded_key = PKCS8::PEM_encode(priv_key);
std::auto_ptr<PK_Signer> signer(get_pk_signer(priv_key, "EMSA1(SHA-224)"));
std::auto_ptr<PK_Verifier> verifier(get_pk_verifier(priv_key, "EMSA1(SHA-224)"));
for(u32bit i = 0; i != 256; ++i)
signer->update((byte)i);
SecureVector<byte> sig = signer->signature(rng);
for(u32bit i = 0; i != 256; ++i)
verifier->update((byte)i);
if(!verifier->check_signature(sig))
{
std::cout << "ECDSA self-test failed!";
return false;
}
// now check valid signature, different input
for(u32bit i = 1; i != 256; ++i) //starting from 1
verifier->update((byte)i);
if(verifier->check_signature(sig))
{
std::cout << "ECDSA with bad input passed validation";
return false;
}
// now check with original input, modified signature
sig[sig.size()/2]++;
for(u32bit i = 0; i != 256; ++i)
verifier->update((byte)i);
if(verifier->check_signature(sig))
{
std::cout << "ECDSA with bad signature passed validation";
return false;
}
}
catch (std::exception& e)
{
std::cout << "Exception in test_ec_sign - " << e.what() << "\n";
return false;
}
return true;
}
void test_create_pkcs8(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
try
{
RSA_PrivateKey rsa_key(rng, 1024);
//RSA_PrivateKey rsa_key2(1024);
//cout << "\nequal: " << (rsa_key == rsa_key2) << "\n";
//DSA_PrivateKey key(DL_Group("dsa/jce/1024"));
std::ofstream rsa_priv_key(TEST_DATA_DIR "/rsa_private.pkcs8.pem");
rsa_priv_key << PKCS8::PEM_encode(rsa_key);
EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.132.0.8"));
ECDSA_PrivateKey key(rng, dom_pars);
// later used by other tests :(
std::ofstream priv_key(TEST_DATA_DIR "/wo_dompar_private.pkcs8.pem");
priv_key << PKCS8::PEM_encode(key);
}
catch (std::exception& e)
{
std::cout << "Exception: " << e.what() << std::endl;
}
}
void test_create_and_verify(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.132.0.8"));
ECDSA_PrivateKey key(rng, dom_pars);
std::ofstream priv_key(TEST_DATA_DIR "/dompar_private.pkcs8.pem");
priv_key << PKCS8::PEM_encode(key);
std::auto_ptr<PKCS8_PrivateKey> loaded_key(PKCS8::load_key(TEST_DATA_DIR "/wo_dompar_private.pkcs8.pem", rng));
ECDSA_PrivateKey* loaded_ec_key = dynamic_cast<ECDSA_PrivateKey*>(loaded_key.get());
CHECK_MESSAGE(loaded_ec_key, "the loaded key could not be converted into an ECDSA_PrivateKey");
std::auto_ptr<PKCS8_PrivateKey> loaded_key_1(PKCS8::load_key(TEST_DATA_DIR "/rsa_private.pkcs8.pem", rng));
ECDSA_PrivateKey* loaded_rsa_key = dynamic_cast<ECDSA_PrivateKey*>(loaded_key_1.get());
CHECK_MESSAGE(!loaded_rsa_key, "the loaded key is ECDSA_PrivateKey -> shouldn't be, is a RSA-Key");
//calc a curve which is not in the registry
// string p_secp = "2117607112719756483104013348936480976596328609518055062007450442679169492999007105354629105748524349829824407773719892437896937279095106809";
std::string a_secp = "0a377dede6b523333d36c78e9b0eaa3bf48ce93041f6d4fc34014d08f6833807498deedd4290101c5866e8dfb589485d13357b9e78c2d7fbe9fe";
std::string b_secp = "0a9acf8c8ba617777e248509bcb4717d4db346202bf9e352cd5633731dd92a51b72a4dc3b3d17c823fcc8fbda4da08f25dea89046087342595a7";
std::string G_secp_comp = "04081523d03d4f12cd02879dea4bf6a4f3a7df26ed888f10c5b2235a1274c386a2f218300dee6ed217841164533bcdc903f07a096f9fbf4ee95bac098a111f296f5830fe5c35b3e344d5df3a2256985f64fbe6d0edcc4c61d18bef681dd399df3d0194c5a4315e012e0245ecea56365baa9e8be1f7";
std::string order_g = "0e1a16196e6000000000bc7f1618d867b15bb86474418f";
// ::SecureVector<byte> sv_p_secp = decode_hex ( p_secp );
SecureVector<byte> sv_a_secp = decode_hex ( a_secp );
SecureVector<byte> sv_b_secp = decode_hex ( b_secp );
SecureVector<byte> sv_G_secp_comp = decode_hex ( G_secp_comp );
SecureVector<byte> sv_order_g = decode_hex ( order_g );
// BigInt bi_p_secp = BigInt::decode ( sv_p_secp.begin(), sv_p_secp.size() );
BigInt bi_p_secp("2117607112719756483104013348936480976596328609518055062007450442679169492999007105354629105748524349829824407773719892437896937279095106809");
BigInt bi_a_secp = BigInt::decode ( sv_a_secp.begin(), sv_a_secp.size() );
BigInt bi_b_secp = BigInt::decode ( sv_b_secp.begin(), sv_b_secp.size() );
BigInt bi_order_g = BigInt::decode ( sv_order_g.begin(), sv_order_g.size() );
CurveGFp curve ( GFpElement ( bi_p_secp,bi_a_secp ), GFpElement ( bi_p_secp, bi_b_secp ), bi_p_secp );
PointGFp p_G = OS2ECP ( sv_G_secp_comp, curve );
EC_Domain_Params dom_params(curve, p_G, bi_order_g, BigInt(1));
p_G.check_invariants();
ECDSA_PrivateKey key_odd_oid(rng, dom_params);
std::string key_odd_oid_str = PKCS8::PEM_encode(key_odd_oid);
DataSource_Memory key_data_src(key_odd_oid_str);
std::auto_ptr<PKCS8_PrivateKey> loaded_key2(PKCS8::load_key(key_data_src, rng));
if(!dynamic_cast<ECDSA_PrivateKey*>(loaded_key.get()))
{
std::cout << "Failed to reload an ECDSA key with unusual parameter set\n";
}
}
void test_curve_registry(RandomNumberGenerator& rng)
{
std::vector<std::string> oids;
oids.push_back("1.3.132.0.8");
oids.push_back("1.2.840.10045.3.1.1");
oids.push_back("1.2.840.10045.3.1.2");
oids.push_back("1.2.840.10045.3.1.3");
oids.push_back("1.2.840.10045.3.1.4");
oids.push_back("1.2.840.10045.3.1.5");
oids.push_back("1.2.840.10045.3.1.6");
oids.push_back("1.2.840.10045.3.1.7");
oids.push_back("1.3.132.0.6");
oids.push_back("1.3.132.0.7");
oids.push_back("1.3.132.0.28");
oids.push_back("1.3.132.0.29");
oids.push_back("1.3.132.0.9");
oids.push_back("1.3.132.0.30");
oids.push_back("1.3.132.0.31");
oids.push_back("1.3.132.0.32");
oids.push_back("1.3.132.0.33");
oids.push_back("1.3.132.0.10");
oids.push_back("1.3.132.0.34");
oids.push_back("1.3.132.0.35");
oids.push_back("1.3.6.1.4.1.8301.3.1.2.9.0.38");
oids.push_back("1.3.36.3.3.2.8.1.1.1");
oids.push_back("1.3.36.3.3.2.8.1.1.3");
oids.push_back("1.3.36.3.3.2.8.1.1.5");
oids.push_back("1.3.36.3.3.2.8.1.1.7");
oids.push_back("1.3.36.3.3.2.8.1.1.9");
oids.push_back("1.3.36.3.3.2.8.1.1.11");
oids.push_back("1.3.36.3.3.2.8.1.1.13");
unsigned int i;
for (i = 0; i < oids.size(); i++)
{
std::cout << "." << std::flush;
try
{
EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid(oids[i]));
dom_pars.get_base_point().check_invariants();
ECDSA_PrivateKey key(rng, dom_pars);
std::string str_message = ("12345678901234567890abcdef12");
SecureVector<byte> sv_message = decode_hex(str_message);
SecureVector<byte> signature = key.sign(sv_message.begin(), sv_message.size(), rng);
bool ver_success = key.verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size());
CHECK_MESSAGE(ver_success, "generated signature could not be verified positively");
}
catch(Invalid_Argument& e)
{
std::cout << "Error testing curve " << oids[i] << " - " << e.what() << "\n";
}
}
// std::cout << "test_curve_registry finished" << endl;
}
void test_read_pkcs8(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
try
{
std::auto_ptr<PKCS8_PrivateKey> loaded_key(PKCS8::load_key(TEST_DATA_DIR "/wo_dompar_private.pkcs8.pem", rng));
ECDSA_PrivateKey* loaded_ec_key = dynamic_cast<ECDSA_PrivateKey*>(loaded_key.get());
CHECK_MESSAGE(loaded_ec_key, "the loaded key could not be converted into an ECDSA_PrivateKey");
std::string str_message = ("12345678901234567890abcdef12");
SecureVector<byte> sv_message = decode_hex(str_message);
SecureVector<byte> signature = loaded_ec_key->sign(sv_message.begin(), sv_message.size(), rng);
//cout << "signature = " << hex_encode(signature.begin(), signature.size()) << "\n";
bool ver_success = loaded_ec_key->verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size());
CHECK_MESSAGE(ver_success, "generated signature could not be verified positively");
std::auto_ptr<PKCS8_PrivateKey> loaded_key_nodp(PKCS8::load_key(TEST_DATA_DIR "/nodompar_private.pkcs8.pem", rng));
// anew in each test with unregistered domain-parameters
ECDSA_PrivateKey* loaded_ec_key_nodp = dynamic_cast<ECDSA_PrivateKey*>(loaded_key_nodp.get());
CHECK_MESSAGE(loaded_ec_key_nodp, "the loaded key could not be converted into an ECDSA_PrivateKey");
SecureVector<byte> signature_nodp = loaded_ec_key_nodp->sign(sv_message.begin(), sv_message.size(), rng);
//cout << "signature = " << hex_encode(signature.begin(), signature.size()) << "\n";
bool ver_success_nodp = loaded_ec_key_nodp->verify(sv_message.begin(), sv_message.size(), signature_nodp.begin(), signature_nodp.size());
CHECK_MESSAGE(ver_success_nodp, "generated signature could not be verified positively (no_dom)");
try
{
std::auto_ptr<PKCS8_PrivateKey> loaded_key_withdp(PKCS8::load_key(TEST_DATA_DIR "/withdompar_private.pkcs8.pem", rng));
std::cout << "Unexpected success: loaded key with unknown OID\n";
}
catch (std::exception& e) { /* OK */ }
}
catch (std::exception& e)
{
std::cout << "Exception in test_read_pkcs8 - " << e.what() << "\n";
}
}
/**
* The following test tests the copy ctors and and copy-assignment operators
*/
void test_cp_and_as_ctors(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
std::auto_ptr<PKCS8_PrivateKey> loaded_key(PKCS8::load_key(TEST_DATA_DIR "/wo_dompar_private.pkcs8.pem", rng));
ECDSA_PrivateKey* loaded_ec_key = dynamic_cast<ECDSA_PrivateKey*>(loaded_key.get());
CHECK_MESSAGE(loaded_ec_key, "the loaded key could not be converted into an ECDSA_PrivateKey");
std::string str_message = ("12345678901234567890abcdef12");
SecureVector<byte> sv_message = decode_hex(str_message);
SecureVector<byte> signature_1 = loaded_ec_key->sign(sv_message.begin(), sv_message.size(), rng);
//cout << "signature = " << hex_encode(signature.begin(), signature.size()) << "\n";
ECDSA_PrivateKey cp_priv_key(*loaded_ec_key); // priv-key, cp-ctor
SecureVector<byte> signature_2 = cp_priv_key.sign(sv_message.begin(), sv_message.size(), rng);
ECDSA_PrivateKey as_priv_key = *loaded_ec_key; //priv-key, as-op
SecureVector<byte> signature_3 = as_priv_key.sign(sv_message.begin(), sv_message.size(), rng);
ECDSA_PublicKey pk_1 = cp_priv_key; // pub-key, as-op
ECDSA_PublicKey pk_2(pk_1); // pub-key, cp-ctor
ECDSA_PublicKey pk_3;
pk_3 = pk_2; // pub-key, as-op
bool ver_success_1 = pk_1.verify(sv_message.begin(), sv_message.size(), signature_1.begin(), signature_1.size());
bool ver_success_2 = pk_2.verify(sv_message.begin(), sv_message.size(), signature_2.begin(), signature_2.size());
bool ver_success_3 = pk_3.verify(sv_message.begin(), sv_message.size(), signature_3.begin(), signature_3.size());
CHECK_MESSAGE((ver_success_1 && ver_success_2 && ver_success_3), "different results for copied keys");
}
/**
* The following test tests whether ECDSA keys exhibit correct behaviour when it is
* attempted to use them in an uninitialized state
*/
void test_non_init_ecdsa_keys(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
std::auto_ptr<PKCS8_PrivateKey> loaded_key(PKCS8::load_key(TEST_DATA_DIR "/wo_dompar_private.pkcs8.pem", rng));
//ECDSA_PrivateKey* loaded_ec_key = dynamic_cast<ECDSA_PrivateKey*>(loaded_key.get());
//CHECK_MESSAGE(loaded_ec_key, "the loaded key could not be converted into an ECDSA_PrivateKey");
std::string str_message = ("12345678901234567890abcdef12");
ECDSA_PrivateKey empty_priv;
ECDSA_PublicKey empty_pub;
SecureVector<byte> sv_message = decode_hex(str_message);
bool exc1 = false;
try
{
SecureVector<byte> signature_1 = empty_priv.sign(sv_message.begin(), sv_message.size(), rng);
}
catch (std::exception e)
{
exc1 = true;
}
CHECK_MESSAGE(exc1, "there was no exception thrown when attempting to use an uninitialized ECDSA key");
bool exc2 = false;
try
{
empty_pub.verify(sv_message.begin(), sv_message.size(), sv_message.begin(), sv_message.size());
}
catch (std::exception e)
{
exc2 = true;
}
CHECK_MESSAGE(exc2, "there was no exception thrown when attempting to use an uninitialized ECDSA key");
}
}
u32bit do_ecdsa_tests(Botan::RandomNumberGenerator& rng)
{
std::cout << "Testing ECDSA (InSiTo unit tests): ";
test_hash_larger_than_n(rng);
//test_message_larger_than_n();
test_decode_ecdsa_X509();
test_decode_ver_link_SHA256();
test_decode_ver_link_SHA1();
test_sign_then_ver(rng);
test_ec_sign(rng);
test_create_pkcs8(rng);
test_create_and_verify(rng);
test_curve_registry(rng);
test_read_pkcs8(rng);
test_cp_and_as_ctors(rng);
test_non_init_ecdsa_keys(rng);
std::cout << std::endl;
return 0;
}
#else
u32bit do_ecdsa_tests(Botan::RandomNumberGenerator&) { return 0; }
#endif

View File

@@ -0,0 +1,286 @@
/******************************************************
* ECKAEG tests *
* *
* (C) 2007 Manuel Hartl *
* hartl@flexsecure.de *
* 2008 Jack Lloyd *
******************************************************/
#include <botan/build.h>
#include "validate.h"
#include "common.h"
#if defined(BOTAN_HAS_ECKAEG)
#include <iostream>
#include <fstream>
#include <botan/symkey.h>
#include <botan/dh.h>
#include <botan/eckaeg.h>
#include <botan/x509self.h>
#include <botan/der_enc.h>
#include <botan/point_gfp.h>
#include <botan/curve_gfp.h>
#include <botan/gfp_element.h>
using namespace Botan;
#define CHECK_MESSAGE(expr, print) try { if(!(expr)) std::cout << print << "\n"; } catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << "\n"; }
#define CHECK(expr) try { if(!(expr)) std::cout << #expr << "\n"; } catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << "\n"; }
namespace {
void test_eckaeg_normal_derivation(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
/*
std::string p_secp = "ffffffffffffffffffffffffffffffff7fffffff";
std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc";
std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45";
std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82";
::Botan::SecureVector<byte> sv_p_secp = decode_hex(p_secp);
::Botan::SecureVector<byte> sv_a_secp = decode_hex(a_secp);
::Botan::SecureVector<byte> sv_b_secp = decode_hex(b_secp);
::Botan::SecureVector<byte> sv_G_secp_comp = decode_hex(G_secp_comp);
BigInt bi_p_secp = BigInt::decode(sv_p_secp.begin(), sv_p_secp.size());
BigInt bi_a_secp = BigInt::decode(sv_a_secp.begin(), sv_a_secp.size());
BigInt bi_b_secp = BigInt::decode(sv_b_secp.begin(), sv_b_secp.size());
CurveGFp secp160r1(GFpElement(bi_p_secp,bi_a_secp), GFpElement(bi_p_secp, bi_b_secp), bi_p_secp);
*/
std::string g_secp("024a96b5688ef573284664698968c38bb913cbfc82");
Botan::SecureVector<Botan::byte> sv_g_secp = decode_hex(g_secp);
BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff");
BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc");
BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45");
BigInt order = BigInt("0x0100000000000000000001f4c8f927aed3ca752257");
CurveGFp curve(GFpElement(bi_p_secp,bi_a_secp), GFpElement(bi_p_secp, bi_b_secp), bi_p_secp);
BigInt cofactor = BigInt(1);
PointGFp p_G = OS2ECP ( sv_g_secp, curve );
Botan::EC_Domain_Params dom_pars = Botan::EC_Domain_Params(curve, p_G, order, cofactor);
/**
* begin ECKAEG
*/
// alices key (a key constructed by domain parameters IS an ephimeral key!)
Botan::ECKAEG_PrivateKey private_a(rng, dom_pars);
Botan::ECKAEG_PublicKey public_a = private_a; // Bob gets this
// Bob creates a key with a matching group
Botan::ECKAEG_PrivateKey private_b(rng, dom_pars); //public_a.getCurve()
// Bob sends the key back to Alice
Botan::ECKAEG_PublicKey public_b = private_b; // Alice gets this
// Both of them create a key using their private key and the other's
// public key
Botan::SymmetricKey alice_key = private_a.derive_key(public_b);
Botan::SymmetricKey bob_key = private_b.derive_key(public_a);
if(alice_key != bob_key)
{
std::cout << "The two keys didn't match!\n";
std::cout << "Alice's key was: " << alice_key.as_string() << "\n";
std::cout << "Bob's key was: " << bob_key.as_string() << "\n";
}
}
void test_eckaeg_some_dp(RandomNumberGenerator& rng)
{
std::vector<std::string> oids;
oids.push_back("1.2.840.10045.3.1.7");
oids.push_back("1.3.132.0.8");
oids.push_back("1.2.840.10045.3.1.1");
for(Botan::u32bit i = 0; i< oids.size(); i++)
{
std::cout << "." << std::flush;
Botan::EC_Domain_Params dom_pars(Botan::get_EC_Dom_Pars_by_oid(oids[i]));
Botan::ECKAEG_PrivateKey private_a(rng, dom_pars);
Botan::ECKAEG_PublicKey public_a = private_a;
/*auto_ptr<Botan::X509_Encoder> x509_key_enc = public_a.x509_encoder();
Botan::MemoryVector<Botan::byte> enc_key_a = Botan::DER_Encoder()
.start_cons(Botan::SEQUENCE)
.encode(x509_key_enc->alg_id())
.encode(x509_key_enc->key_bits(), Botan::BIT_STRING)
.end_cons()
.get_contents();*/
Botan::ECKAEG_PrivateKey private_b(rng, dom_pars);
Botan::ECKAEG_PublicKey public_b = private_b;
// to test the equivalence, we
// use the direct derivation method here
Botan::SymmetricKey alice_key = private_a.derive_key(public_b);
//cout << "encoded key = " << hex_encode(enc_key_a.begin(), enc_key_a.size()) << endl;
Botan::SymmetricKey bob_key = private_b.derive_key(public_a);
CHECK_MESSAGE(alice_key == bob_key, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string());
//cout << "key: " << alice_key.as_string() << endl;
}
}
void test_eckaeg_der_derivation(RandomNumberGenerator& rng)
{
std::vector<std::string> oids;
oids.push_back("1.2.840.10045.3.1.7");
oids.push_back("1.3.132.0.8");
oids.push_back("1.2.840.10045.3.1.1");
for(Botan::u32bit i = 0; i< oids.size(); i++)
{
Botan::EC_Domain_Params dom_pars(Botan::get_EC_Dom_Pars_by_oid(oids[i]));
Botan::ECKAEG_PrivateKey private_a(rng, dom_pars);
Botan::ECKAEG_PublicKey public_a = private_a;
Botan::ECKAEG_PrivateKey private_b(rng, dom_pars);
Botan::ECKAEG_PublicKey public_b = private_b;
Botan::MemoryVector<Botan::byte> key_der_a = private_a.public_value();
Botan::MemoryVector<Botan::byte> key_der_b = private_b.public_value();
Botan::SymmetricKey alice_key = private_a.derive_key(key_der_b.begin(), key_der_b.size());
Botan::SymmetricKey bob_key = private_b.derive_key(key_der_a.begin(), key_der_a.size());
CHECK_MESSAGE(alice_key == bob_key, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string());
//cout << "key: " << alice_key.as_string() << endl;
}
}
/**
* The following test tests the copy ctors and and copy-assignment operators
*/
void test_eckaeg_cp_ctor_as_op(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
std::string g_secp("024a96b5688ef573284664698968c38bb913cbfc82");
Botan::SecureVector<Botan::byte> sv_g_secp = decode_hex(g_secp);
BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff");
BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc");
BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45");
BigInt order = BigInt("0x0100000000000000000001f4c8f927aed3ca752257");
CurveGFp curve(GFpElement(bi_p_secp,bi_a_secp), GFpElement(bi_p_secp, bi_b_secp), bi_p_secp);
BigInt cofactor = BigInt(1);
PointGFp p_G = OS2ECP ( sv_g_secp, curve );
Botan::EC_Domain_Params dom_pars = Botan::EC_Domain_Params(curve, p_G, order, cofactor);
/**
* begin ECKAEG
*/
// alices key (a key constructed by domain parameters IS an ephimeral key!)
Botan::ECKAEG_PrivateKey private_a(rng, dom_pars);
Botan::ECKAEG_PrivateKey private_a2(private_a);
Botan::ECKAEG_PrivateKey private_a3;
private_a3 = private_a2;
Botan::DH_PrivateKey dh_pr_empty;
Botan::DH_PublicKey dh_pub_empty;
Botan::ECKAEG_PublicKey public_a = private_a; // Bob gets this
Botan::ECKAEG_PublicKey public_a2(public_a);
Botan::ECKAEG_PublicKey public_a3;
public_a3 = public_a;
// Bob creates a key with a matching group
Botan::ECKAEG_PrivateKey private_b(rng, dom_pars); //public_a.getCurve()
// Bob sends the key back to Alice
Botan::ECKAEG_PublicKey public_b = private_b; // Alice gets this
// Both of them create a key using their private key and the other's
// public key
Botan::SymmetricKey alice_key = private_a.derive_key(public_b);
Botan::SymmetricKey alice_key_2 = private_a2.derive_key(public_b);
Botan::SymmetricKey alice_key_3 = private_a3.derive_key(public_b);
Botan::SymmetricKey bob_key = private_b.derive_key(public_a);
Botan::SymmetricKey bob_key_2 = private_b.derive_key(public_a2);
Botan::SymmetricKey bob_key_3 = private_b.derive_key(public_a3);
CHECK_MESSAGE(alice_key == bob_key, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string());
CHECK_MESSAGE(alice_key_2 == bob_key_2, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string());
CHECK_MESSAGE(alice_key_3 == bob_key_3, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string());
CHECK_MESSAGE(alice_key == bob_key_2, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string());
CHECK_MESSAGE(alice_key_2 == bob_key_3, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string());
}
/**
* The following test tests whether ECKAEG keys exhibit correct behaviour when it is
* attempted to use them in an uninitialized state
*/
void test_non_init_eckaeg_keys(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
// set up dom pars
std::string g_secp("024a96b5688ef573284664698968c38bb913cbfc82");
Botan::SecureVector<Botan::byte> sv_g_secp = decode_hex(g_secp);
BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff");
BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc");
BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45");
BigInt order = BigInt("0x0100000000000000000001f4c8f927aed3ca752257");
CurveGFp curve(GFpElement(bi_p_secp,bi_a_secp), GFpElement(bi_p_secp, bi_b_secp), bi_p_secp);
BigInt cofactor = BigInt(1);
PointGFp p_G = OS2ECP ( sv_g_secp, curve );
Botan::EC_Domain_Params dom_pars = Botan::EC_Domain_Params(curve, p_G, order, cofactor);
// alices key (a key constructed by domain parameters IS an emphemeral key!)
Botan::ECKAEG_PrivateKey private_a(rng, dom_pars);
Botan::ECKAEG_PrivateKey private_b(rng, dom_pars);
Botan::ECKAEG_PublicKey public_b;
Botan::ECKAEG_PrivateKey private_empty;
Botan::ECKAEG_PublicKey public_empty;
bool exc1 = false;
try
{
Botan::SymmetricKey void_key = private_empty.derive_key(public_b);
}
catch (Botan::Exception e)
{
exc1 = true;
}
CHECK_MESSAGE(exc1, "there was no exception thrown when attempting to use an uninitialized ECKAEG key");
bool exc2 = false;
try
{
Botan::SymmetricKey void_key = private_a.derive_key(public_empty);
}
catch (Botan::Exception e)
{
exc2 = true;
}
CHECK_MESSAGE(exc2, "there was no exception thrown when attempting to use an uninitialized ECKAEG key");
}
}
u32bit do_eckaeg_tests(Botan::RandomNumberGenerator& rng)
{
std::cout << "Testing ECKAEG (InSiTo unit tests): ";
test_eckaeg_normal_derivation(rng);
test_eckaeg_some_dp(rng);
test_eckaeg_der_derivation(rng);
test_eckaeg_cp_ctor_as_op(rng);
test_non_init_eckaeg_keys(rng);
std::cout << std::endl;
return 0;
}
#else
u32bit do_eckaeg_tests(Botan::RandomNumberGenerator&) { return 0; }
#endif

100
src/libs/3rdparty/botan/checks/fail.dat vendored Normal file
View File

@@ -0,0 +1,100 @@
# Botan validation file: expected failures
# Each sequence in here should induce an exception on the part of the
# filter, or produce the wrong output, or something like that.
# This needs a lot more work
# MARKER: Block Ciphers
[Blowfish]
0000000000000000:245946885754369B:
0000000000000000:245946885754369B:AA
0000000000000000:24594688575436:AA
00000000000000:24594688575436:
0000000000000000:245946885754369B:\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
0000000000000000:245946885754369B:\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[CAST5]
0123456789ABCDEF:238B4FE5847E44B2:0123456712
# MARKER: Hash Functions
[SHA-1]
A9:19DA91F2603889267DFD77786E07A5B8F067D6
A8:19DA91F2603889267DFD77786E07A5B8F067D62A
# MARKER: Cipher Modes (Encryption)
[DES/CBC/CTS]
9F8789F30E3ED728:48C597491E0C3C1706:9076D5A743FC9721:A9A6C2AD38E682C1
9F8789F30E3ED72800:48C597491E0C3C1706:9076D5A743FC9721:A9A6C2AD38E682
9F8789F30E3ED72800:48C597491E0C3C1706:76D5A743FC9721:A9A6C2AD38E682
# MARKER: Cipher Modes (Decryption)
[DES/CBC/PKCS7]
E5C7CDDE872BF27C43E934008C389C0F683788499A7C05F662C16A27E4FCF276:\
4E6F77206973207468652074696D6520666F7220616C6C20:\
0123456789ABCDEF:1234567890ABCDEF
E5C7CDDE872BF27C43E934008C389C0788499A7C05F662C16A27E4FCF276:\
4E6F77206973207468652074696D6520666F7220616C6C20:\
0123456789ABCDEF:1234567890ABCDEF
E5C7CDDE872BF27C43E934008C389C0F683788499A7C05F662C16A27E4FCF276:\
4E6F77206973207468652074696D6520666F7220616C6C20:\
1123456789ABCDEF:1234567890ABCDEF
E5C7CDDE872BF27C43E934008C389C0F683788499A7C05F662C16A27E4FCF276:\
4E6F77206973207468652074696D6520666F7220616C6C20:\
0123456789ABCDEF:1234567890ABCDEE
1D2FECD6F0F733F1:AA:DC3A72A9BA8138EC:67E51C4F8403BF6F
D90246C39C191E98:AA:45AAF3A76E729062:53C1F28656B05986
[DES/CBC/OneAndZeros]
28582FD8797D3DB5:AA:D404FD15970CB207:88269176E292DE0A
A2C23F6A496C7BE9:AA:829E7BE8C8A9B326:106E9D2E19FE874D
[DES/CBC/CTS]
1F807F8FB9678124B8:9E1CA14BE6538A35DB:88B23AFD0683D337:BAC170D943D262CE
[DES/CFB(1)]
105EFAA6251E7659:C5A1343F4AC4DD7B:C42B0F47482DABA0:48848E073CF89946
105EFAA6251E7659:C5A1343F4AC4DD7B:C42B0F47482DABA0:48848E073CF899
[Base64_Decode]
3D514D3E:31
[Bzip_Compress <EXTENSION>]
64484953204953204120425A49503220544553540A:\
525A6839314159265359FDAED210000009DE0000104000100032604C1020\
0021A4D1EA0FD2840D03401E19B4D4B254EE89F177245385090FDAED2105
[Bzip_Decompress <EXTENSION>]
523A683917724538509000000110:
425A6839314159265359FDAED210000009DE0000104000100032604C1020\
0021A4D1EA0FD2840D03401E19B4D4B254EE89F167245385090FDAED2100:\
54484953204953204120425A49503220544553540A
123A6839314159265359FDAED210000009DE0000104000100032604C1020\
0121A4D1EA0FD2840D03401E19B4D4B254EE89F166245385090FDAED2100:\
54484953204953204120425A49503220544553540A
[Zlib_Decompress <EXTENSION>]
68DA734C4A76042247C7A4A4246710D3392D3F3F29B1880B106C380868:\
416263416263414141626262436341626343666F6F6261720A
78DA73742416700100E0260AB5:\
3141414141414141414141414141414141414141414141414141414141414141\
414141414141414141410A

View File

@@ -0,0 +1,85 @@
#include "getopt.h"
#include <botan/parsing.h>
#include <botan/exceptn.h>
OptionParser::OptionParser(const std::string& opt_string)
{
std::vector<std::string> opts = Botan::split_on(opt_string, '|');
for(size_t j = 0; j != opts.size(); j++)
flags.push_back(OptionFlag(opts[j]));
}
OptionParser::OptionFlag
OptionParser::find_option(const std::string& name) const
{
for(size_t j = 0; j != flags.size(); j++)
if(flags[j].name() == name)
return flags[j];
throw Botan::Exception("Unknown option " + name);
}
bool OptionParser::is_set(const std::string& key) const
{
return (options.find(key) != options.end());
}
std::string OptionParser::value(const std::string& key) const
{
std::map<std::string, std::string>::const_iterator i = options.find(key);
if(i == options.end())
throw Botan::Exception("Option " + key + " not found");
return i->second;
}
std::string OptionParser::value_if_set(const std::string& key) const
{
return is_set(key) ? value(key) : "";
}
void OptionParser::parse(char* argv[])
{
std::vector<std::string> args;
for(int j = 1; argv[j]; j++)
args.push_back(argv[j]);
for(size_t j = 0; j != args.size(); j++)
{
std::string arg = args[j];
if(arg.size() > 2 && arg[0] == '-' && arg[1] == '-')
{
const std::string opt_name = arg.substr(0, arg.find('='));
arg = arg.substr(2);
std::string::size_type mark = arg.find('=');
OptionFlag opt = find_option(arg.substr(0, mark));
if(opt.takes_arg())
{
if(mark == std::string::npos)
throw Botan::Exception("Option " + opt_name +
" requires an argument");
std::string name = arg.substr(0, mark);
std::string value = arg.substr(mark+1);
options[name] = value;
}
else
{
if(mark != std::string::npos)
throw Botan::Exception("Option " + opt_name +
" does not take an argument");
options[arg] = "";
}
}
else
leftover.push_back(arg);
}
}

45
src/libs/3rdparty/botan/checks/getopt.h vendored Normal file
View File

@@ -0,0 +1,45 @@
#ifndef BOTAN_CHECK_GETOPT_H__
#define BOTAN_CHECK_GETOPT_H__
#include <string>
#include <vector>
#include <map>
class OptionParser
{
public:
std::vector<std::string> leftovers() const { return leftover; }
bool is_set(const std::string&) const;
std::string value(const std::string&) const;
std::string value_if_set(const std::string&) const;
void parse(char*[]);
OptionParser(const std::string&);
private:
class OptionFlag
{
public:
std::string name() const { return opt_name; }
bool takes_arg() const { return opt_takes_arg; }
OptionFlag(const std::string& opt_string)
{
std::string::size_type mark = opt_string.find('=');
opt_name = opt_string.substr(0, mark);
opt_takes_arg = (mark != std::string::npos);
}
private:
std::string opt_name;
bool opt_takes_arg;
};
OptionFlag find_option(const std::string&) const;
std::vector<OptionFlag> flags;
std::map<std::string, std::string> options;
std::vector<std::string> leftover;
};
#endif

View File

@@ -0,0 +1,818 @@
/******************************************************
* gfp_element tests *
* *
* (C) 2007 Patrick Sona *
* *
* Falko Strenzke *
* strenzke@flexsecure.de *
* (C) 2008 Jack Lloyd *
******************************************************/
#include "validate.h"
#if defined(BOTAN_HAS_BIGINT_GFP)
#include <botan/bigint.h>
#include <botan/numthry.h>
#include <botan/gfp_element.h>
#include <botan/gfp_modulus.h>
#include <botan/curve_gfp.h>
#include <botan/ec_dompar.h>
#include <iostream>
using namespace Botan;
#define CHECK_MESSAGE(expr, print) if(!(expr)) { std::cout << print << "\n"; pass = false; }
#define CHECK(expr) if(!(expr)) { std::cout << #expr << "\n"; pass = false; }
namespace {
bool test_turn_on_sp_red_mul()
{
std::cout << "." << std::flush;
bool pass = true;
GFpElement a1(23,15);
GFpElement b1(23,18);
GFpElement c1 = a1*b1;
GFpElement a2(23,15);
GFpElement b2(23,18);
a2.turn_on_sp_red_mul();
a2.turn_on_sp_red_mul();
b2.turn_on_sp_red_mul();
b2.turn_on_sp_red_mul();
GFpElement c2 = a2*b2;
if(c1 != c2)
{
std::cout << "test_turn_on_sp_red_mul: ";
std::cout << "c1 = " << c1 << " != ";
std::cout << "c2 = " << c2 << "\n";
return false; // test failed
}
return pass; // pass
}
bool test_bi_div_even()
{
std::cout << "." << std::flush;
bool pass = true;
std::string str_large("1552518092300708935148979488462502555256886017116696611139052038026050952686323255099158638440248181850494907312621195144895406865083132424709500362534691373159016049946612882688577088900506460909202178541447303914546699487373976586");
BigInt to_div(str_large);
BigInt half = to_div/2;
BigInt should_be_to_div = half*2;
CHECK_MESSAGE(should_be_to_div == to_div, "error in division/multiplication of large BigInt");
// also testing /=...
BigInt before_div = to_div;
to_div /= 2;
BigInt should_be_before(to_div*2);
CHECK_MESSAGE(should_be_before == before_div, "error in division/multiplication of large BigInt");
return pass;
}
bool test_bi_div_odd()
{
std::cout << '.' << std::flush;
bool pass = true;
std::string str_large("1552518092300708935148979488462502555256886017116696611139052038026050952686323255099158638440248181850494907312621195144895406865083132424709500362534691373159016049946612882688577088900506460909202178541447303914546699487373976585");
BigInt to_div(str_large);
BigInt half = to_div/2;
BigInt should_be_to_div = half*2;
BigInt diff = should_be_to_div-to_div;
CHECK_MESSAGE((diff <= 1) && (diff >= BigInt("-1")), "error in division/multiplication (/) of large BigInt, differnce = " << diff);
// also testing /=...
BigInt before_div = to_div;
to_div /= 2;
BigInt should_be_before(to_div*2);
BigInt diff2(should_be_before - before_div);
CHECK_MESSAGE((diff2 <= 1) && (diff2 >= BigInt("-1")), "error in division/multiplication (/=) of large BigInt, difference = " << diff2);
return pass;
}
bool test_deep_montgm()
{
std::cout << '.' << std::flush;
bool pass = true;
std::string s_prime = "5334243285367";
//std::string s_prime = "5";
BigInt bi_prime(s_prime);
std::string s_value_a = "3333333333334";
//std::string s_value_a = "4";
BigInt bi_value_a(s_value_a);
std::string s_value_b = "4444444444444";
//std::string s_value_b = "3";
BigInt bi_value_b(s_value_b);
GFpElement gfp_a_trf(bi_prime, bi_value_a, true);
GFpElement gfp_a_ntrf(bi_prime, bi_value_a, false);
GFpElement gfp_b_trf(bi_prime, bi_value_b, true);
GFpElement gfp_b_ntrf(bi_prime, bi_value_b, false);
//CHECK(!gfp_b_trf.is_trf_to_mres());
gfp_b_trf.get_mres();
gfp_a_trf.get_mres();
GFpElement c_trf(gfp_a_trf * gfp_b_trf);
GFpElement c_ntrf(gfp_a_ntrf * gfp_b_ntrf);
if(c_trf != c_ntrf)
{
std::cout << "test_deep_montgm - " << c_trf << " != " << c_ntrf << "\n";
}
return pass; // pass
}
bool test_gfp_div_small_numbers()
{
std::cout << '.' << std::flush;
bool pass = true;
std::string s_prime = "13";
BigInt bi_prime(s_prime);
std::string s_value_a = "2";
BigInt bi_value_a(s_value_a);
std::string s_value_b = "3";
BigInt bi_value_b(s_value_b);
GFpElement gfp_a(bi_prime, bi_value_a, true);
GFpElement gfp_b(bi_prime, bi_value_b, true);
GFpElement gfp_c(bi_prime, bi_value_b, false);
CHECK(!gfp_a.is_trf_to_mres());
//convert to montgomery
gfp_b.get_mres();
CHECK(gfp_b.is_trf_to_mres());
CHECK(!gfp_c.is_trf_to_mres());
GFpElement res_div_m = gfp_a / gfp_b;
CHECK(res_div_m.is_trf_to_mres());
GFpElement res_div_n = gfp_a / gfp_c;
CHECK(!res_div_n.is_trf_to_mres());
CHECK_MESSAGE(res_div_n.get_value() == res_div_m.get_value(), "transformed result is not equal to untransformed result");
CHECK_MESSAGE(gfp_a.get_value() == s_value_a, "GFpElement has changed while division operation");
CHECK_MESSAGE(gfp_b.get_value() == s_value_b, "GFpElement has changed while division operation");
GFpElement inverse_b = inverse(gfp_b);
GFpElement res_div_alternative = gfp_a * inverse_b;
if(res_div_m != res_div_alternative)
{
std::cout << "test_gfp_div_small_numbers - a/b != a*b^-1 where\n"
<< "a = " << gfp_a << "\n"
<< "b = " << gfp_b << "\n"
<< "b^-1 = " << inverse_b << "\n"
<< "a*b^-1 = " << res_div_alternative << "\n"
<< "a/b = " << res_div_n << "\n";
pass = false;
}
CHECK_MESSAGE(res_div_m == res_div_alternative, "a/b is not as equal to a * b^-1");
//cout << "Div-result transformed:" << res_div_m.get_value() << endl;
//cout << "Div-result untransformed:" << res_div_n.get_value() << endl;
//cout << "Div-Alternative: " << res_div_alternative.get_value() << endl;
return pass;
}
bool test_gfp_basics()
{
std::cout << '.' << std::flush;
bool pass = true;
std::string s_prime = "5334243285367";
BigInt bi_prime(s_prime);
std::string s_value_a = "3333333333333";
BigInt bi_value_a(s_value_a);
GFpElement gfp_a(bi_prime, bi_value_a, true);
CHECK(gfp_a.get_p() == s_prime);
CHECK(gfp_a.get_value() == s_value_a);
CHECK(!gfp_a.is_trf_to_mres());
gfp_a.get_mres();
CHECK(gfp_a.is_trf_to_mres());
return pass;
}
bool test_gfp_addSubNegate()
{
std::cout << '.' << std::flush;
bool pass = true;
std::string s_prime = "5334243285367";
BigInt bi_prime(s_prime);
std::string s_value_a = "3333333333333";
BigInt bi_value_a(s_value_a);
GFpElement gfp_a(bi_prime, bi_value_a, true);
GFpElement gfp_b(bi_prime, bi_value_a, true);
gfp_b.negate();
GFpElement zero = gfp_a + gfp_b;
BigInt bi_zero("0");
CHECK(zero.get_value() == bi_zero);
CHECK(gfp_a.get_value() == bi_value_a);
return pass;
}
bool test_gfp_mult()
{
std::cout << '.' << std::flush;
bool pass = true;
std::string s_prime = "5334243285367";
BigInt bi_prime(s_prime);
std::string s_value_a = "3333333333333";
BigInt bi_value_a(s_value_a);
std::string s_value_b = "4444444444444";
BigInt bi_value_b(s_value_b);
GFpElement gfp_a(bi_prime, bi_value_a, true);
GFpElement gfp_b(bi_prime, bi_value_b, true);
GFpElement gfp_c(bi_prime, bi_value_b, false);
CHECK(!gfp_a.is_trf_to_mres());
//convert to montgomery
gfp_b.get_mres();
CHECK(gfp_b.is_trf_to_mres());
CHECK(!gfp_c.is_trf_to_mres());
GFpElement res_mult_m = gfp_a * gfp_b;
CHECK(res_mult_m.is_trf_to_mres());
GFpElement res_mult_n = gfp_a * gfp_c;
CHECK(!res_mult_n.is_trf_to_mres());
if(res_mult_n != res_mult_m)
std::cout << gfp_a << " * " << gfp_b << " =? "
<< "n = " << res_mult_n << " != m = " << res_mult_m << "\n";
return pass;
}
bool test_gfp_div()
{
std::cout << '.' << std::flush;
bool pass = true;
std::string s_prime = "5334243285367";
BigInt bi_prime(s_prime);
std::string s_value_a = "3333333333333";
BigInt bi_value_a(s_value_a);
std::string s_value_b = "4444444444444";
BigInt bi_value_b(s_value_b);
GFpElement gfp_a(bi_prime, bi_value_a, true);
GFpElement gfp_b(bi_prime, bi_value_b, true);
GFpElement gfp_c(bi_prime, bi_value_b, false);
CHECK(!gfp_a.is_trf_to_mres());
//convert to montgomery
gfp_b.get_mres();
CHECK(gfp_b.is_trf_to_mres());
CHECK(!gfp_c.is_trf_to_mres());
GFpElement res_div_m = gfp_a / gfp_b;
CHECK(res_div_m.is_trf_to_mres());
GFpElement res_div_n = gfp_a / gfp_c;
CHECK(!res_div_n.is_trf_to_mres());
CHECK_MESSAGE(res_div_n.get_value() == res_div_m.get_value(), "transformed result is not equal to untransformed result");
CHECK_MESSAGE(gfp_a.get_value() == s_value_a, "GFpElement has changed while division operation");
CHECK_MESSAGE(gfp_b.get_value() == s_value_b, "GFpElement has changed while division operation");
GFpElement inverse_b = inverse(gfp_b);
GFpElement res_div_alternative = gfp_a * inverse_b;
CHECK_MESSAGE(res_div_m == res_div_alternative, "a/b is not as equal to a * b^-1");
//cout << "Div-result transformed:" << res_div_m.get_value() << endl;
//cout << "Div-result untransformed:" << res_div_n.get_value() << endl;
//cout << "Div-Alternative: " << res_div_alternative.get_value() << endl;
return pass;
}
bool test_gfp_add()
{
std::cout << '.' << std::flush;
bool pass = true;
std::string s_prime = "5334243285367";
BigInt bi_prime(s_prime);
std::string s_value_a = "3333333333333";
BigInt bi_value_a(s_value_a);
std::string s_value_b = "4444444444444";
BigInt bi_value_b(s_value_b);
GFpElement gfp_a(bi_prime, bi_value_a, true);
GFpElement gfp_b(bi_prime, bi_value_b, true);
GFpElement gfp_c(bi_prime, bi_value_b, true);
CHECK(!gfp_a.is_trf_to_mres());
//convert to montgomery
gfp_b.get_mres();
CHECK(gfp_b.is_trf_to_mres());
CHECK(!gfp_c.is_trf_to_mres());
GFpElement res_add_m = gfp_a + gfp_b;
CHECK(res_add_m.is_trf_to_mres());
GFpElement res_add_n = gfp_a + gfp_c;
// commented out by patrick, behavior is clear:
// rhs might be transformed, lhs never
// for now, this behavior is only intern, doesn't matter for programm function
// CHECK_MESSAGE(res_add_n.is_trf_to_mres(), "!! Falko: NO FAIL, wrong test, please repair"); // clear: rhs might be transformed, lhs never
CHECK(res_add_n.get_value() == res_add_m.get_value());
return pass;
}
bool test_gfp_sub()
{
std::cout << '.' << std::flush;
bool pass = true;
std::string s_prime = "5334243285367";
BigInt bi_prime(s_prime);
std::string s_value_a = "3333333333333";
BigInt bi_value_a(s_value_a);
std::string s_value_b = "4444444444444";
BigInt bi_value_b(s_value_b);
GFpElement gfp_a(bi_prime, bi_value_a, true);
GFpElement gfp_b(bi_prime, bi_value_b, true);
GFpElement gfp_c(bi_prime, bi_value_b, true);
CHECK(!gfp_a.is_trf_to_mres());
//convert to montgomery
gfp_b.get_mres();
CHECK(gfp_b.is_trf_to_mres());
CHECK(!gfp_c.is_trf_to_mres());
GFpElement res_sub_m = gfp_b - gfp_a;
CHECK(res_sub_m.is_trf_to_mres());
CHECK(gfp_a.is_trf_to_mres()); // added by Falko
GFpElement res_sub_n = gfp_c - gfp_a;
// commented out by psona, behavior is clear:
// rhs might be transformed, lhs never
// for now, this behavior is only intern, doesn't matter for programm function
// CHECK_MESSAGE(!res_sub_n.is_trf_to_mres(), "!! Falko: NO FAIL, wrong test, please repair"); // falsche
// Erwartung: a wurde durch die operation oben auch
// ins m-residue transformiert, daher passiert das hier auch mit
// c, und das Ergebnis ist es auch
CHECK(res_sub_n.get_value() == res_sub_m.get_value());
return pass;
}
bool test_more_gfp_div()
{
std::cout << '.' << std::flush;
bool pass = true;
std::string s_prime = "5334243285367";
BigInt bi_prime(s_prime);
std::string s_value_a = "3333333333333";
BigInt bi_value_a(s_value_a);
std::string s_value_b = "4444444444444";
BigInt bi_value_b(s_value_b);
GFpElement gfp_a(bi_prime, bi_value_a, true);
GFpElement gfp_b_trf(bi_prime, bi_value_b, true);
GFpElement gfp_b_ntrf(bi_prime, bi_value_b, false);
CHECK(!gfp_b_trf.is_trf_to_mres());
gfp_b_trf.get_mres();
CHECK(gfp_b_trf.is_trf_to_mres());
CHECK(!gfp_a.is_trf_to_mres());
bool exc_ntrf = false;
try
{
gfp_b_ntrf.get_mres();
}
catch(Botan::Illegal_Transformation e)
{
exc_ntrf = true;
}
CHECK(exc_ntrf);
CHECK(!gfp_b_ntrf.is_trf_to_mres());
CHECK_MESSAGE(gfp_b_trf == gfp_b_ntrf, "b is not equal to itself (trf)");
GFpElement b_trf_inv(gfp_b_trf);
b_trf_inv.inverse_in_place();
GFpElement b_ntrf_inv(gfp_b_ntrf);
b_ntrf_inv.inverse_in_place();
CHECK_MESSAGE(b_trf_inv == b_ntrf_inv, "b inverted is not equal to itself (trf)");
CHECK(gfp_b_trf/gfp_b_ntrf == GFpElement(bi_prime, 1));
CHECK(gfp_b_trf/gfp_b_trf == GFpElement(bi_prime, 1));
CHECK(gfp_b_ntrf/gfp_b_ntrf == GFpElement(bi_prime, 1));
GFpElement rhs(gfp_a/gfp_b_trf);
GFpElement lhs(gfp_a/gfp_b_ntrf);
if(lhs != rhs)
{
std::cout << "test_more_gfp_div - " << lhs << " != " << rhs << "\n";
pass = false;
}
return pass;
}
bool test_gfp_mult_u32bit()
{
std::cout << '.' << std::flush;
bool pass = true;
/*
Botan::EC_Domain_Params parA(Botan::get_EC_Dom_Pars_by_oid("1.2.840.10045.3.1.1"));
CurveGFp curve = parA.get_curve();
//CurveGFp curve2 = parA.get_curve();
BigInt p = curve.get_p();
GFpElement a = curve.get_a();
GFpElement a_mr = curve.get_mres_a();
Botan::u32bit u_x = 134234;
BigInt b_x(u_x);
GFpElement g_x(p, b_x);
CHECK(a*u_x == a*g_x);
CHECK(a*u_x == u_x*a);
CHECK(a*g_x == g_x*a);
CHECK(a_mr*u_x == a*g_x);
CHECK(u_x*a_mr == a*g_x);
*/
return pass;
}
/**
* This tests verifies the functionality of sharing pointers for modulus dependent values
*/
bool test_gfp_shared_vals()
{
std::cout << '.' << std::flush;
bool pass = true;
BigInt p("5334243285367");
GFpElement a(p, BigInt("234090"));
GFpElement shcpy_a(1,0);
shcpy_a.share_assign(a);
std::tr1::shared_ptr<GFpModulus> ptr1 = a.get_ptr_mod();
std::tr1::shared_ptr<GFpModulus> ptr2 = shcpy_a.get_ptr_mod();
CHECK_MESSAGE(ptr1.get() == ptr2.get(), "shared pointers for moduli aren´t equal");
GFpElement b(1,0);
b = a; // create a non shared copy
std::tr1::shared_ptr<GFpModulus> ptr_b_p = b.get_ptr_mod();
CHECK_MESSAGE(ptr1.get() != ptr_b_p.get(), "non shared pointers for moduli are equal");
a.turn_on_sp_red_mul();
GFpElement c1 = a * shcpy_a;
GFpElement c2 = a * a;
GFpElement c3 = shcpy_a * shcpy_a;
GFpElement c4 = shcpy_a * a;
shcpy_a.turn_on_sp_red_mul();
GFpElement c5 = shcpy_a * shcpy_a;
if(c1 != c2 || c2 != c3 || c3 != c4 || c4 != c5)
{
std::cout << "test_gfp_shared_vals failed"
<< " a=" << a
<< " shcpy_a=" << shcpy_a
<< " c1=" << c1 << " c2=" << c2
<< " c3=" << c3 << " c4=" << c4
<< " c5=" << c5 << "\n";
pass = false;
}
swap(a,shcpy_a);
std::tr1::shared_ptr<GFpModulus> ptr3 = a.get_ptr_mod();
std::tr1::shared_ptr<GFpModulus> ptr4 = shcpy_a.get_ptr_mod();
CHECK_MESSAGE(ptr3.get() == ptr4.get(), "shared pointers for moduli aren´t equal after swap");
CHECK(ptr1.get() == ptr4.get());
CHECK(ptr2.get() == ptr3.get());
swap(a,b);
std::tr1::shared_ptr<GFpModulus> ptr_a = a.get_ptr_mod();
std::tr1::shared_ptr<GFpModulus> ptr_b = shcpy_a.get_ptr_mod();
CHECK(ptr_a.get() == ptr_b_p.get());
CHECK(ptr_b.get() == ptr3.get());
return pass;
}
/**
* The following test checks the behaviour of GFpElements assignment operator, which
* has quite complex behaviour with respect to sharing groups and precomputed values
* (with respect to montgomery mult.)
*/
bool test_gfpel_ass_op()
{
std::cout << '.' << std::flush;
bool pass = true;
// test different moduli
GFpElement a(23,4);
GFpElement b(11,6);
GFpElement b2(11,6);
a = b;
CHECK(a==b2);
CHECK(a.get_value() == b2.get_value());
CHECK(a.get_p() == b2.get_p());
CHECK(a.get_ptr_mod().get() != b.get_ptr_mod().get()); // sharing groups
// may not be fused!
// also test some share_assign()...
a.share_assign(b);
CHECK(a==b2);
CHECK(a.get_value() == b2.get_value());
CHECK(a.get_p() == b2.get_p());
CHECK(a.get_ptr_mod().get() == b.get_ptr_mod().get()); // sharing groups
// shall be fused!
//---------------------------
// test assignment within sharing group
// with montg.mult.
GFpElement c(5,2);
GFpElement d(5,2);
d.share_assign(c);
CHECK(d.get_ptr_mod().get() == c.get_ptr_mod().get());
CHECK(d.get_ptr_mod()->get_p() == c.get_ptr_mod()->get_p());
CHECK(c.get_ptr_mod()->get_r().is_zero());
c.turn_on_sp_red_mul();
CHECK(d.get_ptr_mod().get() == c.get_ptr_mod().get());
CHECK(d.get_ptr_mod()->get_p() == c.get_ptr_mod()->get_p());
CHECK(!c.get_ptr_mod()->get_p().is_zero());
GFpElement f(11,5);
d = f;
CHECK(f.get_ptr_mod().get() != c.get_ptr_mod().get());
GFpElement e = c*c;
GFpElement g = d*d;
GFpElement h = f*f;
CHECK(h == g);
GFpElement c2(5,2);
GFpElement d2(5,2);
d2.share_assign(c2);
GFpElement f2(11,5);
d2 = f2;
c2.turn_on_sp_red_mul();
CHECK(d2.get_ptr_mod().get() != c2.get_ptr_mod().get()); // the sharing group was left
CHECK(d2.get_ptr_mod()->get_r() == f2.get_ptr_mod()->get_r());
CHECK(c2.get_p() == 5); // c2´s shared values weren´t modified because
// the sharing group with d2 was separated by
// the assignment "d2 = f2"
d2.turn_on_sp_red_mul();
CHECK(d2.get_ptr_mod()->get_p() != c2.get_ptr_mod()->get_p());
GFpElement e2 = c2*c2;
GFpElement g2 = d2*d2;
GFpElement h2 = f2*f2;
CHECK(h2 == g2);
GFpElement c3(5,2);
GFpElement d3(5,2);
d3.share_assign(c3);
GFpElement f3(11,2);
d3 = f3;
GFpElement e3 = c3*c3;
GFpElement g3 = d3*d3;
CHECK(e == e2);
CHECK(g == g2);
CHECK(e == e3);
CHECK(g == g2);
return pass;
}
bool test_gfp_swap()
{
std::cout << '.' << std::flush;
bool pass = true;
BigInt p("173");
GFpElement a(p, BigInt("2342"));
GFpElement b(p, BigInt("423420"));
GFpModulus* a_mod = a.get_ptr_mod().get();
GFpModulus* b_mod = b.get_ptr_mod().get();
//GFpModulus* a_d = a.get_ptr_mod()->get_p_dash();
//GFpModulus* b_d = b.get_ptr_mod()->get_p_dash();
swap(a,b);
CHECK_MESSAGE(b.get_value() == 2342%173, "actual value of b was: " << b.get_value() );
CHECK_MESSAGE(a.get_value() == 423420%173, "actual value of a was: " << a.get_value() );
CHECK(a_mod == b.get_ptr_mod().get());
CHECK(b_mod == a.get_ptr_mod().get());
//CHECK(a_d == b.get_ptr_mod()->get_p_dash());
//CHECK(b_d == a.get_ptr_p_dash()->get_p_dash());
GFpElement c(p, BigInt("2342329"));
GFpElement d(1,1);
d.share_assign(c);
d += d;
c.swap(d);
CHECK(d.get_value() == 2342329%173);
CHECK(c.get_value() == (d*2).get_value());
return pass;
}
bool test_inv_in_place()
{
std::cout << '.' << std::flush;
bool pass = true;
BigInt mod(173);
GFpElement a1(mod, 288);
a1.turn_on_sp_red_mul();
a1.get_mres(); // enforce the conversion
GFpElement a1_inv(a1);
a1_inv.inverse_in_place();
GFpElement a2(mod, 288);
GFpElement a2_inv(a2);
a2_inv.inverse_in_place();
/*cout << "a1_inv = " << a1_inv << endl;
cout << "a2_inv = " << a2_inv << endl;*/
CHECK_MESSAGE(a1_inv == a2_inv, "error with inverting tranformed GFpElement");
CHECK(a1_inv.inverse_in_place() == a1);
CHECK(a2_inv.inverse_in_place() == a2);
return pass;
}
bool test_op_eq()
{
std::cout << '.' << std::flush;
bool pass = true;
BigInt mod(173);
GFpElement a1(mod, 299);
a1.turn_on_sp_red_mul();
a1.get_mres(); // enforce the conversion
GFpElement a2(mod, 288);
CHECK_MESSAGE(a1 != a2, "error with GFpElement comparison");
return pass;
}
bool test_rand_int(RandomNumberGenerator& rng)
{
bool pass = true;
for(int i=0; i< 100; i++)
{
std::cout << '.' << std::flush;
BigInt x = BigInt::random_integer(rng, 1,3);
//cout << "x = " << x << "\n"; // only 1,2 are put out
CHECK(x == 1 || x==2);
}
return pass;
}
bool test_bi_bit_access()
{
std::cout << '.' << std::flush;
bool pass = true;
BigInt a(323);
CHECK(a.get_bit(1) == 1);
CHECK(a.get_bit(1000) == 0);
return pass;
}
#if 0
bool test_sec_mod_mul()
{
//cout << "starting test_sec_mod_mul" << endl;
bool pass = true;
//mod_mul_secure(BigInt const& a, BigInt const& b, BigInt const& m)
BigInt m("5334243285367");
BigInt a("3333333333333");
BigInt b("4444444444444");
for(int i = 0; i<10; i++)
{
std::cout << '.' << std::flush;
BigInt c1 = a * b;
c1 %= m;
BigInt c2 = mod_mul_secure(a, b, m);
CHECK_MESSAGE(c1 == c2, "should be " << c1 << ", was " << c2);
}
//cout << "ending test_sec_mod_mul" << endl;
return pass;
}
#endif
#if 0
bool test_sec_bi_mul()
{
//mod_mul_secure(BigInt const& a, BigInt const& b, BigInt const& m)
bool pass = true;
BigInt m("5334243285367");
BigInt a("3333333333333");
BigInt b("4444444444444");
for(int i = 0; i<10; i++)
{
std::cout << '.' << std::flush;
BigInt c1 = a * b;
//c1 %= m;
BigInt c2(a);
c2.mult_this_secure(b, m);
CHECK_MESSAGE(c1 == c2, "should be " << c1 << ", was " << c2);
}
return pass;
}
#endif
}
u32bit do_gfpmath_tests(Botan::RandomNumberGenerator& rng)
{
std::cout << "Testing GF(p) math " << std::flush;
u32bit failed = 0;
failed += !test_turn_on_sp_red_mul();
failed += !test_bi_div_even();
failed += !test_bi_div_odd();
failed += !test_deep_montgm();
failed += !test_gfp_div_small_numbers();
failed += !test_gfp_basics();
failed += !test_gfp_addSubNegate();
failed += !test_gfp_mult();
failed += !test_gfp_div();
failed += !test_gfp_add();
failed += !test_gfp_sub();
failed += !test_more_gfp_div();
failed += !test_gfp_mult_u32bit();
failed += !test_gfp_shared_vals();
failed += !test_gfpel_ass_op();
failed += !test_gfp_swap();
failed += !test_inv_in_place();
failed += !test_op_eq();
failed += !test_rand_int(rng);
failed += !test_bi_bit_access();
//failed += !test_sec_mod_mul();
//failed += !test_sec_bi_mul();
#if 0
if(failed == 0)
std::cout << " OK";
else
std::cout << ' ' << failed << " failed";
#endif
std::cout << std::endl;
return failed;
}
#else
u32bit do_gfpmath_tests(Botan::RandomNumberGenerator&) { return 0; }
#endif

77
src/libs/3rdparty/botan/checks/misc.cpp vendored Normal file
View File

@@ -0,0 +1,77 @@
#include <iostream>
#include <vector>
#include <string>
#include <botan/pipe.h>
#include <botan/hex.h>
using namespace Botan;
#include "common.h"
void strip_comments(std::string& line)
{
if(line.find('#') != std::string::npos)
line = line.erase(line.find('#'), std::string::npos);
}
void strip_newlines(std::string& line)
{
while(line.find('\n') != std::string::npos)
line = line.erase(line.find('\n'), 1);
}
/* Strip comments, whitespace, etc */
void strip(std::string& line)
{
strip_comments(line);
#if 0
while(line.find(' ') != std::string::npos)
line = line.erase(line.find(' '), 1);
#endif
while(line.find('\t') != std::string::npos)
line = line.erase(line.find('\t'), 1);
}
SecureVector<byte> decode_hex(const std::string& in)
{
SecureVector<byte> result;
try {
Botan::Pipe pipe(new Botan::Hex_Decoder);
pipe.process_msg(in);
result = pipe.read_all();
}
catch(std::exception& e)
{
result.destroy();
}
return result;
}
std::string hex_encode(const byte in[], u32bit len)
{
Botan::Pipe pipe(new Botan::Hex_Encoder);
pipe.process_msg(in, len);
return pipe.read_all_as_string();
}
std::vector<std::string> parse(const std::string& line)
{
const char DELIMITER = ':';
std::vector<std::string> substr;
std::string::size_type start = 0, end = line.find(DELIMITER);
while(end != std::string::npos)
{
substr.push_back(line.substr(start, end-start));
start = end+1;
end = line.find(DELIMITER, start);
}
if(line.size() > start)
substr.push_back(line.substr(start));
while(substr.size() <= 4) // at least 5 substr, some possibly empty
substr.push_back("");
return substr;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
Known Failures/Problems
Policy extensions are not implemented, so we skip tests #34-#53.
Tests #75 and #76 are skipped as they make use of relatively obscure CRL
extensions which are not supported.
In addition, please note that some of the tests have their results altered from
what the test result should be according to NIST's documentation. The changes
are clearly marked (see x509test.cpp; search for "CHANGE OF TEST RESULT") and
there are comments explaining why the results where changed. Currently, tests
#19, #65, and #67 have had their results changed from the official results.

View File

@@ -0,0 +1,26 @@
This package contains a program to exercise Botan's path validation
algorithm, as contained in the X509_Store object. The data used is
NIST's X.509v3 certificate path validation testing data, as found on
NIST's web site (version 1.0.7 of the testing data is currently
used). The PKCS #7 and PKCS #12 data files have been removed, as they
are not used in this test.
Currently, some tests fail or are not be run for various reasons (in
particular, we don't have support policy extensions yet, so that
excludes running a good number of the tests). Even if all of the tests
DO pass, that does not imply that Botan's path validation and
certificate processing code is bug free, as there are many (*very
many*) possible options in X.509 which this testing data does not make
use of at all. However, it is helpful for implementation testing and
assurance (I have found a good number of bugs using these tests).
Currently, we do not make use of the S/MIME or PKCS #12 testing data
contained in these tests, because Botan does not support either of
these standards.
To use this, compile x509test.cpp, and run the resulting
executable. The results are written to standard output. Your system
must have a POSIX.1 dirent.h, and the code assumes Unix-style paths.
Email me with any questions or comments about these tests.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More