#include <boost/scoped_ptr.hpp>
#include <openssl/pem.h>
+#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
#error "P-384 group is not known (NID_secp384r1)"
#endif
+namespace {
+
+/// @brief Class for the curves/groups
+class EcDsaGroup {
+public:
+ // @brief Constructor
+ // Get the group and set the curve name flag for ASN.1
+ EcDsaGroup(int nid) {
+ group_ = EC_GROUP_new_by_curve_name(nid);
+ if (!group_) {
+ isc_throw(isc::Unexpected, "EC_GROUP_new_by_curve_name");
+ }
+ EC_GROUP_set_asn1_flag(group_, OPENSSL_EC_NAMED_CURVE);
+ }
+
+ // @brief Destructor
+ ~EcDsaGroup() {
+ if (group_) {
+ EC_GROUP_free(group_);
+ group_ = NULL;
+ }
+ }
+
+ // @brief The group
+ EC_GROUP* group_;
+};
+
+const EcDsaGroup prime256v1(NID_X9_62_prime256v1);
+const EcDsaGroup secp384r1(NID_secp384r1);
+
+} // anonymous namespace
+
namespace isc {
namespace cryptolink {
kind_ = key_kind;
eckey_ = NULL;
x509_ = NULL;
- int curve_nid = 0;
switch (hash_) {
case SHA256:
- curve_nid = NID_X9_62_prime256v1;
+ md_ = EVP_sha256();
+ group_ = prime256v1.group_;
break;
case SHA384:
- curve_nid = NID_secp384r1;
+ md_ = EVP_sha512();
+ group_ = secp384r1.group_;
break;
default:
isc_throw(UnsupportedAlgorithm,
if (!privkey) {
throw std::bad_alloc();
}
- eckey_ = EC_KEY_new_by_curve_name(curve_nid);
+ eckey_ = EC_KEY_new();
if (!eckey_) {
BN_clear_free(privkey);
- isc_throw(LibraryError, "EC_KEY_new_by_curve_name");
+ isc_throw(LibraryError, "EC_KEY_new");
+ }
+ if (!EC_KEY_set_group(eckey_, group_)) {
+ BN_clear_free(privkey);
+ EC_KEY_free(eckey_);
+ eckey_ = NULL;
+ isc_throw(LibraryError, "EC_KEY_set_group");
}
- EC_KEY_set_asn1_flag(eckey_, OPENSSL_EC_NAMED_CURVE);
if (!EC_KEY_set_private_key(eckey_, privkey)) {
BN_clear_free(privkey);
EC_KEY_free(eckey_);
isc_throw(LibraryError, "EC_KEY_set_private_key");
}
// Compute the public key
- const EC_GROUP* grp = EC_KEY_get0_group(eckey_);
- EC_POINT* pubkey = EC_POINT_new(grp);
+ EC_POINT* pubkey = EC_POINT_new(group_);
if (!pubkey) {
BN_clear_free(privkey);
throw std::bad_alloc();
}
- if (!EC_POINT_mul(grp, pubkey, privkey, NULL, NULL, NULL)) {
+ if (!EC_POINT_mul(group_, pubkey, privkey, NULL, NULL, NULL)) {
EC_POINT_free(pubkey);
BN_clear_free(privkey);
EC_KEY_free(eckey_);
eckey_ = NULL;
isc_throw(BadKey, "EC_KEY_check_key");
}
- EC_GROUP* wanted = EC_GROUP_new_by_curve_name(curve_nid);
- if (!wanted) {
- EC_KEY_free(eckey_);
- eckey_ = NULL;
- isc_throw(LibraryError, "EC_GROUP_new_by_curve_name");
- }
const int status =
- EC_GROUP_cmp(EC_KEY_get0_group(eckey_), wanted, NULL);
- EC_GROUP_free(wanted);
+ EC_GROUP_cmp(EC_KEY_get0_group(eckey_), group_, NULL);
if (status < 0) {
EC_KEY_free(eckey_);
eckey_ = NULL;
pubbin[0] = POINT_CONVERSION_UNCOMPRESSED;
std::memcpy(&pubbin[1], key, len);
const uint8_t* p = &pubbin[0];
- eckey_ = EC_KEY_new_by_curve_name(curve_nid);
+ eckey_ = EC_KEY_new();
if (!eckey_) {
- isc_throw(LibraryError, "EC_KEY_new_by_curve_name");
+ isc_throw(LibraryError, "EC_KEY_new");
+ }
+ if (!EC_KEY_set_group(eckey_, group_)) {
+ EC_KEY_free(eckey_);
+ eckey_ = NULL;
+ isc_throw(LibraryError, "EC_KEY_set_group");
}
- EC_KEY_set_asn1_flag(eckey_, OPENSSL_EC_NAMED_CURVE);
if (o2i_ECPublicKey(&eckey_, &p,
static_cast<long>(len + 1)) == NULL) {
EC_KEY_free(eckey_);
isc_throw(UnsupportedAlgorithm,
"Unknown ECDSA Key kind: " << static_cast<int>(kind_));
}
+
+ mdctx_.reset(new EVP_MD_CTX);
+ EVP_MD_CTX_init(mdctx_.get());
+
+ if (!EVP_DigestInit_ex(mdctx_.get(), md_, NULL)) {
+ EVP_MD_CTX_cleanup(mdctx_.get());
+ EC_KEY_free(eckey_);
+ eckey_ = NULL;
+ isc_throw(LibraryError, "EVP_DigestInit_ex");
+ }
}
/// @brief Constructor from a key file with password,
kind_ = key_kind;
eckey_ = NULL;
x509_ = NULL;
- int curve_nid = 0;
switch (hash_) {
case SHA256:
- curve_nid = NID_X9_62_prime256v1;
+ md_ = EVP_sha256();
+ group_ = prime256v1.group_;
break;
case SHA384:
- curve_nid = NID_secp384r1;
+ md_ = EVP_sha512();
+ group_ = secp384r1.group_;
break;
default:
isc_throw(UnsupportedAlgorithm,
}
if (!EC_KEY_get0_public_key(eckey_)) {
// Compute the public key as a side effect
- const EC_GROUP* grp = EC_KEY_get0_group(eckey_);
const BIGNUM* privkey = EC_KEY_get0_private_key(eckey_);
- EC_POINT* pubkey = EC_POINT_new(grp);
+ EC_POINT* pubkey = EC_POINT_new(group_);
if (!pubkey) {
throw std::bad_alloc();
}
- if (!EC_POINT_mul(grp, pubkey, privkey, NULL, NULL, NULL)) {
+ if (!EC_POINT_mul(group_, pubkey, privkey, NULL, NULL, NULL)) {
EC_POINT_free(pubkey);
EC_KEY_free(eckey_);
eckey_ = NULL;
eckey_ = NULL;
isc_throw(BadKey, "EC_KEY_check_key");
}
- EC_GROUP* wanted = EC_GROUP_new_by_curve_name(curve_nid);
- if (!wanted) {
- EC_KEY_free(eckey_);
- eckey_ = NULL;
- isc_throw(LibraryError, "EC_GROUP_new_by_curve_name");
- }
const int status =
- EC_GROUP_cmp(EC_KEY_get0_group(eckey_), wanted, NULL);
- EC_GROUP_free(wanted);
+ EC_GROUP_cmp(EC_KEY_get0_group(eckey_), group_, NULL);
if (status < 0) {
EC_KEY_free(eckey_);
eckey_ = NULL;
BN_clear_free(privkey);
isc_throw(BadKey, "Missing Algorithm entry");
}
- eckey_ = EC_KEY_new_by_curve_name(curve_nid);
+ eckey_ = EC_KEY_new();
if (!eckey_) {
BN_clear_free(privkey);
- isc_throw(LibraryError, "EC_KEY_new_by_curve_name");
+ isc_throw(LibraryError, "EC_KEY_new");
+ }
+ if (!EC_KEY_set_group(eckey_, group_)) {
+ BN_clear_free(privkey);
+ EC_KEY_free(eckey_);
+ eckey_ = NULL;
+ isc_throw(LibraryError, "EC_KEY_set_group");
}
- EC_KEY_set_asn1_flag(eckey_, OPENSSL_EC_NAMED_CURVE);
if (!EC_KEY_set_private_key(eckey_, privkey)) {
BN_clear_free(privkey);
EC_KEY_free(eckey_);
eckey_ = NULL;
isc_throw(BadKey, "EC_KEY_check_key");
}
- EC_GROUP* wanted = EC_GROUP_new_by_curve_name(curve_nid);
- if (!wanted) {
- EC_KEY_free(eckey_);
- eckey_ = NULL;
- isc_throw(LibraryError, "EC_GROUP_new_by_curve_name");
- }
const int status =
- EC_GROUP_cmp(EC_KEY_get0_group(eckey_), wanted, NULL);
- EC_GROUP_free(wanted);
+ EC_GROUP_cmp(EC_KEY_get0_group(eckey_), group_, NULL);
if (status < 0) {
EC_KEY_free(eckey_);
eckey_ = NULL;
}
bin.insert(bin.begin(), POINT_CONVERSION_UNCOMPRESSED);
const uint8_t* p = &bin[0];
- eckey_ = EC_KEY_new_by_curve_name(curve_nid);
+ eckey_ = EC_KEY_new();
if (!eckey_) {
- isc_throw(LibraryError, "EC_KEY_new_by_curve_name");
+ isc_throw(LibraryError, "EC_KEY_new");
+ }
+ if (!EC_KEY_set_group(eckey_, group_)) {
+ EC_KEY_free(eckey_);
+ eckey_ = NULL;
+ isc_throw(LibraryError, "EC_KEY_set_group");
}
- EC_KEY_set_asn1_flag(eckey_, OPENSSL_EC_NAMED_CURVE);
if (o2i_ECPublicKey(&eckey_, &p,
static_cast<long>(len + 1)) == NULL) {
EC_KEY_free(eckey_);
isc_throw(UnsupportedAlgorithm,
"Unknown ECDSA Key kind: " << static_cast<int>(kind_));
}
+
+ mdctx_.reset(new EVP_MD_CTX);
+ EVP_MD_CTX_init(mdctx_.get());
+
+ if (!EVP_DigestInit_ex(mdctx_.get(), md_, NULL)) {
+ EVP_MD_CTX_cleanup(mdctx_.get());
+ EC_KEY_free(eckey_);
+ eckey_ = NULL;
+ isc_throw(LibraryError, "EVP_DigestInit_ex");
+ }
}
/// @brief Destructor
EcDsaAsymImpl::~EcDsaAsymImpl() {
- tbs_.clear();
+ if (mdctx_) {
+ EVP_MD_CTX_cleanup(mdctx_.get());
+ }
if (eckey_) {
EC_KEY_free(eckey_);
eckey_ = NULL;
/// @brief Add data to digest
void EcDsaAsymImpl::update(const void* data, const size_t len) {
- const size_t old = tbs_.size();
- tbs_.resize(old + len);
- std::memcpy(&tbs_[old], data, len);
+ if (!EVP_DigestUpdate(mdctx_.get(), data, len)) {
+ isc_throw(LibraryError, "EVP_DigestUpdate");
+ }
}
/// @brief Calculate the final signature
void EcDsaAsymImpl::sign(isc::util::OutputBuffer& result, size_t len,
const AsymFormat sig_format) {
+ // Check the signature format
if ((sig_format != BASIC) &&
(sig_format != ASN1) &&
(sig_format != DNS)) {
"Unknown Signature format: " <<
static_cast<int>(sig_format));
}
+
+ // Get the digest
+ size_t digest_len = EVP_MD_CTX_size(mdctx_.get());
+ ossl::SecBuf<uint8_t> digest(digest_len);
+ if (!EVP_DigestFinal_ex(mdctx_.get(), &digest[0], NULL)) {
+ isc_throw(LibraryError, "EVP_DigestFinal_ex");
+ }
+
+ // Get the signature
size_t size = getSignatureLength(sig_format);
ossl::SecBuf<uint8_t> buf(size);
- ECDSA_SIG* sig = ECDSA_do_sign(&tbs_[0],
- static_cast<int>(tbs_.size()),
+ ECDSA_SIG* sig = ECDSA_do_sign(&digest[0],
+ static_cast<int>(digest_len),
eckey_);
if (!sig) {
isc_throw(LibraryError, "ECDSA_do_sign");
}
+
+ // Build the result
if ((sig_format == BASIC) || (sig_format == DNS)) {
// Store the 2 integers with padding
BN_bn2bin(sig->r, &buf[(size / 2) - BN_num_bytes(sig->r)]);
/// @brief Calculate the final signature
void EcDsaAsymImpl::sign(void* result, size_t len,
const AsymFormat sig_format) {
+ // Check the signature format
if ((sig_format != BASIC) &&
(sig_format != ASN1) &&
(sig_format != DNS)) {
"Unknown Signature format: " <<
static_cast<int>(sig_format));
}
+
+ // Get the digest
+ size_t digest_len = EVP_MD_CTX_size(mdctx_.get());
+ ossl::SecBuf<uint8_t> digest(digest_len);
+ if (!EVP_DigestFinal_ex(mdctx_.get(), &digest[0], NULL)) {
+ isc_throw(LibraryError, "EVP_DigestFinal_ex");
+ }
+
+ // Get the signature
size_t size = getSignatureLength(sig_format);
ossl::SecBuf<uint8_t> buf(size);
- ECDSA_SIG* sig = ECDSA_do_sign(&tbs_[0],
- static_cast<int>(tbs_.size()),
+ ECDSA_SIG* sig = ECDSA_do_sign(&digest[0],
+ static_cast<int>(digest_len),
eckey_);
if (!sig) {
isc_throw(LibraryError, "ECDSA_do_sign");
}
+
+ // Build the result
if ((sig_format == BASIC) || (sig_format == DNS)) {
// Store the 2 integers with padding
BN_bn2bin(sig->r, &buf[(size / 2) - BN_num_bytes(sig->r)]);
/// @brief Calculate the final signature
std::vector<uint8_t> EcDsaAsymImpl::sign(size_t len,
const AsymFormat sig_format) {
+ // Check the signature format
if ((sig_format != BASIC) &&
(sig_format != ASN1) &&
(sig_format != DNS)) {
"Unknown Signature format: " <<
static_cast<int>(sig_format));
}
+
+ // Get the digest
+ size_t digest_len = EVP_MD_CTX_size(mdctx_.get());
+ ossl::SecBuf<uint8_t> digest(digest_len);
+ if (!EVP_DigestFinal_ex(mdctx_.get(), &digest[0], NULL)) {
+ isc_throw(LibraryError, "EVP_DigestFinal_ex");
+ }
+
+ // Get the signature
size_t size = getSignatureLength(sig_format);
ossl::SecBuf<uint8_t> buf(size);
- ECDSA_SIG* sig = ECDSA_do_sign(&tbs_[0],
- static_cast<int>(tbs_.size()),
+ ECDSA_SIG* sig = ECDSA_do_sign(&digest[0],
+ static_cast<int>(digest_len),
eckey_);
if (!sig) {
isc_throw(LibraryError, "ECDSA_do_sign");
}
+
+ // Build the result
if ((sig_format == BASIC) || (sig_format == DNS)) {
// Store the 2 integers with padding
BN_bn2bin(sig->r, &buf[(size / 2) - BN_num_bytes(sig->r)]);
/// @brief Verify an existing signature
bool EcDsaAsymImpl::verify(const void* sig, size_t len,
const AsymFormat sig_format) {
+ // Check the signature format
if ((sig_format != BASIC) &&
(sig_format != ASN1) &&
(sig_format != DNS)) {
"Unknown Signature format: " <<
static_cast<int>(sig_format));
}
+
+ // Get the digest from a copy of the context
+ EVP_MD_CTX tmp;
+ EVP_MD_CTX_init(&tmp);
+ if (!EVP_MD_CTX_copy_ex(&tmp, mdctx_.get())) {
+ isc_throw(LibraryError, "EVP_MD_CTX_copy_ex");
+ }
+ size_t digest_len = EVP_MD_CTX_size(mdctx_.get());
+ ossl::SecBuf<uint8_t> digest(digest_len);
+ if (!EVP_DigestFinal_ex(&tmp, &digest[0], NULL)) {
+ EVP_MD_CTX_cleanup(&tmp);
+ isc_throw(LibraryError, "EVP_DigestFinal_ex");
+ }
+ EVP_MD_CTX_cleanup(&tmp);
+
+ // Get the signature
ECDSA_SIG* asn_sig;
const uint8_t* sigbuf =
reinterpret_cast<const uint8_t*>(const_cast<void*>(sig));
return false;
}
}
- int status = ECDSA_do_verify(&tbs_[0], static_cast<int>(tbs_.size()),
+
+ // Check the signature
+ int status = ECDSA_do_verify(&digest[0],
+ static_cast<int>(digest_len),
asn_sig, eckey_);
ECDSA_SIG_free(asn_sig);
switch (status) {
/// @brief Clear the crypto state and go back to the initial state
void EcDsaAsymImpl::clear() {
- tbs_.clear();
+ if (mdctx_) {
+ EVP_MD_CTX_cleanup(mdctx_.get());
+ } else {
+ mdctx_.reset(new EVP_MD_CTX);
+ }
+ EVP_MD_CTX_init(mdctx_.get());
+ if (!EVP_DigestInit_ex(mdctx_.get(), md_, NULL)) {
+ EVP_MD_CTX_cleanup(mdctx_.get());
+ EC_KEY_free(eckey_);
+ eckey_ = NULL;
+ isc_throw(LibraryError, "EVP_DigestInit_ex");
+ }
}
/// @brief Export the key value (binary)
if (!other || (other->algo_ != ECDSA_)) {
return false;
}
- const EC_GROUP* grp = EC_KEY_get0_group(eckey_);
- const EC_GROUP* ogrp = EC_KEY_get0_group(other->eckey_);
const EC_POINT* pub = EC_KEY_get0_public_key(eckey_);
const EC_POINT* opub = EC_KEY_get0_public_key(other->eckey_);
int status;
return false;
}
cmppub:
- status = EC_GROUP_cmp(grp, ogrp, NULL);
+ status = EC_GROUP_cmp(group_, other->group_, NULL);
switch (status) {
case 0:
// match but not finished
// errors
return false;
}
- status = EC_POINT_cmp(grp, pub, opub, NULL);
+ status = EC_POINT_cmp(group_, pub, opub, NULL);
switch (status) {
case 0:
// match
#include <vector>
#include <stdlib.h>
-#include <boost/lexical_cast.hpp>
-
#include <gtest/gtest.h>
#include <util/encode/base64.h>
#include <cryptolink/cryptolink.h>
#include <cryptolink/crypto_asym.h>
-#include <util/buffer.h>
#include <exceptions/exceptions.h>
#include <boost/shared_ptr.hpp>
-using boost::lexical_cast;
-using namespace isc::util;
-using namespace isc::util::encode;
using namespace isc::cryptolink;
namespace {
#define PUBLIC_EXPONENT 0x01, 0x00, 0x01
-#define PUBLIC_KEY \
-0x30, 0x81, 0x89, \
-0x02, 0x81, 0x81, 0x00, MODULUS, \
-0x02, 0x03, PUBLIC_EXPONENT
-
-#define PRIVATE_EXPONENT \
-0xa8, 0xc9, 0x93, 0x5f, 0xe4, 0x94, 0xf6, 0x45, \
-0x26, 0xb2, 0x1b, 0x8a, 0x18, 0xf2, 0x4b, 0x1f, \
-0x54, 0x2a, 0x4c, 0x18, 0xe6, 0x72, 0xfd, 0x9b, \
-0x06, 0xa0, 0x26, 0x5f, 0xd6, 0xb9, 0x32, 0xa0, \
-0x8e, 0x5c, 0x79, 0x43, 0xdf, 0x03, 0x40, 0xb7, \
-0x76, 0x21, 0x90, 0xa0, 0x37, 0x24, 0x8d, 0x07, \
-0x4a, 0xd4, 0x02, 0x1a, 0x0a, 0x31, 0x6b, 0x95, \
-0x42, 0x0f, 0xc1, 0x2f, 0xc2, 0x42, 0x3c, 0x7f, \
-0x33, 0xb3, 0x54, 0x2f, 0x83, 0xf8, 0x5d, 0x7f, \
-0x86, 0xa5, 0xe8, 0xbe, 0xae, 0x40, 0x41, 0x20, \
-0x5d, 0xa2, 0x66, 0x9a, 0x82, 0x66, 0x03, 0xfc, \
-0xf0, 0x62, 0x24, 0x08, 0x25, 0x99, 0xc6, 0x2b, \
-0xef, 0x9d, 0x79, 0x54, 0x21, 0x91, 0x62, 0x76, \
-0xe5, 0x0b, 0x30, 0xe7, 0x96, 0x9c, 0xfa, 0x45, \
-0xf1, 0x6f, 0xa7, 0x6b, 0x94, 0xa2, 0x70, 0x3d, \
-0xdd, 0x74, 0x6d, 0x4c, 0x8e, 0x8e, 0xe7, 0x01
-
-#define PRIME1 \
-0xda, 0x36, 0xde, 0xd3, 0x0a, 0x15, 0x20, 0xac, \
-0x79, 0xa7, 0xe0, 0xa6, 0x55, 0x69, 0xea, 0xcd, \
-0xf7, 0xe7, 0xf3, 0xda, 0xf6, 0xeb, 0xdc, 0xdb, \
-0x7c, 0xdd, 0x13, 0x6c, 0xaa, 0xfd, 0x6e, 0x98, \
-0x7b, 0x54, 0x25, 0xc0, 0x3b, 0x7d, 0xf9, 0xb5, \
-0x5b, 0x97, 0x2f, 0xe6, 0xc1, 0x4d, 0x7d, 0x5e, \
-0x3b, 0x51, 0x9c, 0xc6, 0xb3, 0xd4, 0x23, 0x43, \
-0xbf, 0x42, 0x98, 0x50, 0x03, 0xfb, 0x0b, 0x51
-
-#define PRIME2 \
-0xd2, 0x2b, 0x1c, 0x29, 0x83, 0x01, 0xfd, 0x41, \
-0x49, 0xfb, 0x95, 0x89, 0x7c, 0xaf, 0x81, 0x81, \
-0xce, 0xd1, 0x77, 0x5f, 0x65, 0x61, 0x61, 0x07, \
-0xd5, 0x45, 0x58, 0xc5, 0xdd, 0x73, 0x6b, 0x63, \
-0x3a, 0x82, 0x92, 0xad, 0xa6, 0x71, 0xa1, 0xcf, \
-0xe3, 0xb5, 0x10, 0x52, 0x42, 0xe5, 0x76, 0x8a, \
-0x1b, 0xca, 0x6a, 0x52, 0x9d, 0x54, 0x78, 0x07, \
-0xcf, 0x1e, 0xed, 0xe4, 0xf2, 0xf2, 0xba, 0x91
-
-#define EXPONENT1 \
-0x6e, 0xf6, 0xa4, 0x0c, 0x90, 0xfd, 0xf9, 0x65, \
-0x7b, 0x5f, 0xa0, 0xdf, 0x34, 0x63, 0xed, 0xe0, \
-0xdb, 0x05, 0x7a, 0x7d, 0x88, 0x3e, 0x9c, 0x4a, \
-0x88, 0x8e, 0x2b, 0x08, 0x81, 0x52, 0xea, 0x60, \
-0x63, 0xa6, 0x80, 0xa3, 0xe6, 0x1c, 0xc3, 0x54, \
-0x33, 0xc5, 0x07, 0xb8, 0xc1, 0xe7, 0x53, 0xaf, \
-0x0d, 0x5f, 0x0c, 0xe8, 0x06, 0x1e, 0x03, 0xe8, \
-0xb9, 0x63, 0x75, 0xec, 0x8a, 0x79, 0xa8, 0x61
-
-#define EXPONENT2 \
-0x7c, 0x6d, 0x29, 0x6f, 0x2a, 0x30, 0xb3, 0x4f, \
-0x44, 0x0d, 0xbe, 0xaa, 0x77, 0x37, 0x30, 0xe5, \
-0x39, 0x1c, 0xaa, 0x1f, 0xc0, 0x55, 0xb6, 0xac, \
-0x7c, 0x87, 0x61, 0xd7, 0x43, 0x14, 0x62, 0x2f, \
-0x8d, 0x24, 0x60, 0xd2, 0x8e, 0x08, 0x18, 0x54, \
-0x8b, 0xeb, 0x56, 0x8e, 0x5d, 0x2c, 0x9c, 0xd1, \
-0x87, 0x42, 0x7f, 0x50, 0x09, 0xf5, 0x48, 0x5a, \
-0xd7, 0x34, 0xe8, 0x82, 0xf3, 0x92, 0xe1, 0x01
-
-#define COEFFICIENT \
-0x13, 0x5f, 0x97, 0x80, 0x10, 0x66, 0x54, 0x05, \
-0x55, 0x05, 0x03, 0x37, 0x96, 0xe0, 0xc0, 0xa7, \
-0x25, 0x7b, 0x70, 0x4a, 0xd2, 0x0e, 0xce, 0x82, \
-0x42, 0x3e, 0xb9, 0x5a, 0x2d, 0x87, 0xca, 0xfa, \
-0xaa, 0x82, 0xe4, 0xed, 0xdb, 0xbf, 0xbf, 0x26, \
-0x9b, 0x50, 0x84, 0x9e, 0xb0, 0xd0, 0x10, 0xb4, \
-0x79, 0x56, 0x1c, 0xd1, 0x49, 0xa1, 0x4f, 0xf8, \
-0x52, 0x6e, 0xb4, 0x1b, 0x1a, 0x5f, 0x48, 0x0c
-
-#define PRIVATE_KEY \
-0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, 0x00, \
-0x02, 0x81, 0x81, 0x00, MODULUS, \
-0x02, 0x03, PUBLIC_EXPONENT, \
-0x02, 0x81, 0x81, 0x00, PRIVATE_EXPONENT, \
-0x02, 0x41, 0x00, PRIME1, \
-0x02, 0x41, 0x00, PRIME2, \
-0x02, 0x40, EXPONENT1, \
-0x02, 0x40, EXPONENT2, \
-0x02, 0x40, COEFFICIENT
-
/// @brief Public Key in PKCS#1 format
const uint8_t pubpkcs1[] = {
0x30, // tag=SEQUENCE (RSAPublicKey)
};
size_t pubpkcs1len = 140;
- /// @brief Public Key in SubjectPublicKeyInfo format
- const uint8_t pubspki[] = {
- 0x30, // tag=SEQUENCE (SubjectPublicKeyInfo)
- 0x81, 0x9f, // length=159
- 0x30, // tag=SEQUENCE (algorithm : AlgorithmIdentifier)
- 0x0d, // length=13
- 0x06, // tag=OBJECTID (algorithm)
- 0x09, // length=9
- 0x2a, 0x86, 0x48, 0x86,
- 0xf7, 0x0d, 0x01, 0x01,
- 0x01, // value=rsaEncryption
- 0x05, // tag=NULL (parameter)
- 0x00, // length=00
- 0x03, // tag=BIT STRING (subjectPublicKey)
- 0x81, 0x8d, // length=141
- 0x00, PUBLIC_KEY
- };
- size_t pubspkilen = 162;
-
- /// @brief Public Key in DNSSEC format (length 132)
- const uint8_t pubdns[] = {
- 0x03, // length=3
- PUBLIC_EXPONENT,
- MODULUS
- };
- size_t pubdnslen = 132;
-
- /// @brief Private Key in PKCS#1 format
- const uint8_t privpkcs1[] = {
- 0x30, // tag=SEQUENCE (RSAPrivateKey)
- 0x82, 0x02, 0x5c, // length=604
- 0x02, // tag=INTEGER (version : Version)
- 0x01, // length=1
- 0x00, // value=0
- 0x02, // tag=INTEGER (modulus -- n)
- 0x81, 0x81, // length=129
- 0x00, MODULUS,
- 0x02, // tag=INTEGER (publicExponent -- e)
- 0x03, // length=3
- PUBLIC_EXPONENT,
- 0x02, // tag=INTEGER (privateExponent -- d)
- 0x81, 0x81, // length=129
- 0x00, PRIVATE_EXPONENT,
- 0x02, // tag=INTEGER (prime1 -- p)
- 0x41, // length=65
- 0x00, PRIME1,
- 0x02, // tag=INTEGER (prime2 -- q)
- 0x41, // length=65
- 0x00, PRIME2,
- 0x02, // tag=INTEGER (exponent1 -- d mod (p-1))
- 0x40, // length=64
- EXPONENT1,
- 0x02, // tag=INTEGER (exponent2 -- d mod (q-1))
- 0x40, // length=64
- EXPONENT2,
- 0x02, // tag=INTEGER (coefficient -- 1/q mod p)
- 0x40, // length=64
- COEFFICIENT
- };
- size_t privpkcs1len = 608;
-
/// @brief Public Key file (SubjectPublicKeyInfo in PEM)
const std::string pubfile = TEST_DATA_SRCDIR "/pub.pem";
/// @brief Certificate file (X.509 Public Key Certificate in PEM)
const std::string certfile = TEST_DATA_SRCDIR "/x509.pem";
-
- /// @brief Compare data with expected value
- /// @param data Value to compare
- /// @param expected Expected value
- /// @param len Length of the expected value
- void checkData(const uint8_t* data, const uint8_t* expected,
- size_t len) {
- for (size_t i = 0; i < len; ++i) {
- ASSERT_EQ(expected[i], data[i]);
- }
- }
-
- /// @brief Compare OutputBuffer with expected value
- /// encapsulated checkData()
- /// @param buf buffer to compare
- /// @param expected Expected value
- /// @param len Length of the expected value
- void checkBuffer(const OutputBuffer& buf, const uint8_t* expected,
- size_t len)
- {
- ASSERT_EQ(len, buf.getLength());
- checkData(static_cast<const uint8_t*>(buf.getData()), expected,
- len);
- }
-
- /// @brief Sign and verify with an instantiation of an asymmetrical
- /// cryptography object
- /// See @ref doAsymTest for parameters
- void doAsymTestDirect(const std::string& data,
- const std::string& privfilename,
- const std::string& password,
- const std::string& pubfilename,
- const AsymAlgorithm asym_algorithm,
- const HashAlgorithm hash_algorithm,
- const AsymFormat sig_format,
- const uint8_t* expected_sig,
- size_t sig_len) {
- OutputBuffer data_buf(data.size());
- data_buf.writeData(data.c_str(), data.size());
- OutputBuffer sig(1);
- CryptoLink& crypto = CryptoLink::getCryptoLink();
-
- // Sign it
- boost::shared_ptr<Asym> rsa_sign(crypto.createAsym(privfilename,
- password,
- asym_algorithm,
- hash_algorithm,
- PRIVATE,
- ASN1),
- deleteAsym);
- rsa_sign->update(data_buf.getData(), data_buf.getLength());
- rsa_sign->sign(sig, sig_len, sig_format);
-
- // Check if the signature is what we expect
- checkBuffer(sig, expected_sig, sig_len);
-
- // Check whether we can verify it ourselves
- boost::shared_ptr<Asym> rsa_verify(crypto.createAsym(pubfilename,
- "",
- asym_algorithm,
- hash_algorithm,
- PUBLIC,
- ASN1),
- deleteAsym);
- rsa_verify->update(data_buf.getData(), data_buf.getLength());
- EXPECT_TRUE(rsa_verify->verify(sig.getData(),
- sig.getLength(),
- sig_format));
-
- // Change the length and check whether verification fails then
- // Relies on the fact the length is checked first
- EXPECT_FALSE(rsa_verify->verify(sig.getData(),
- sig.getLength() - 1,
- sig_format));
- EXPECT_FALSE(rsa_verify->verify(sig.getData(),
- sig.getLength() + 1,
- sig_format));
-
- // Change the sig by flipping the first octet, and check
- // whether verification fails then
- sig.writeUint8At(~sig[0], 0);
- EXPECT_FALSE(rsa_verify->verify(sig.getData(),
- sig.getLength(),
- sig_format));
- }
-
- /// @brief Sign and verify with vector representation of signature
- /// cryptography object
- /// See @ref doAsymTest for parameters
- void doAsymTestVector(const std::string& data,
- const std::string& privfilename,
- const std::string& password,
- const std::string& pubfilename,
- const AsymAlgorithm asym_algorithm,
- const HashAlgorithm hash_algorithm,
- const AsymFormat sig_format,
- const uint8_t* expected_sig,
- size_t sig_len) {
- CryptoLink& crypto = CryptoLink::getCryptoLink();
- boost::shared_ptr<Asym> rsa_sign(crypto.createAsym(privfilename,
- password,
- asym_algorithm,
- hash_algorithm,
- PRIVATE,
- ASN1),
- deleteAsym);
- rsa_sign->update(data.c_str(), data.size());
- std::vector<uint8_t> sig = rsa_sign->sign(sig_len, sig_format);
- ASSERT_EQ(sig_len, sig.size());
- checkData(&sig[0], expected_sig, sig_len);
-
- boost::shared_ptr<Asym> rsa_verify(crypto.createAsym(pubfilename,
- "",
- asym_algorithm,
- hash_algorithm,
- PUBLIC,
- ASN1),
- deleteAsym);
- rsa_verify->update(data.c_str(), data.size());
- EXPECT_TRUE(rsa_verify->verify(&sig[0], sig.size(), sig_format));
-
- EXPECT_FALSE(rsa_verify->verify(&sig[0], sig.size() - 1, sig_format));
- EXPECT_FALSE(rsa_verify->verify(&sig[0], sig.size() + 1, sig_format));
-
- sig[0] = ~sig[0];
- EXPECT_FALSE(rsa_verify->verify(&sig[0], sig.size(), sig_format));
- }
-
- /// @brief Sign and verify with array representation of signature
- /// cryptography object
- /// See @ref doAsymTest for parameters
- void doAsymTestArray(const std::string& data,
- const std::string& privfilename,
- const std::string& password,
- const std::string& pubfilename,
- const AsymAlgorithm asym_algorithm,
- const HashAlgorithm hash_algorithm,
- const AsymFormat sig_format,
- const uint8_t* expected_sig,
- size_t sig_len) {
- CryptoLink& crypto = CryptoLink::getCryptoLink();
- boost::shared_ptr<Asym> rsa_sign(crypto.createAsym(privfilename,
- password,
- asym_algorithm,
- hash_algorithm,
- PRIVATE,
- ASN1),
- deleteAsym);
- rsa_sign->update(data.c_str(), data.size());
-
- // note: this is not exception-safe, and can leak, but
- // if there is an unexpected exception in the code below we
- // have more important things to fix.
- uint8_t* sig = new uint8_t[sig_len];
-
- rsa_sign->sign(sig, sig_len, sig_format);
- checkData(sig, expected_sig, sig_len);
-
- boost::shared_ptr<Asym> rsa_verify(crypto.createAsym(pubfilename,
- "",
- asym_algorithm,
- hash_algorithm,
- PUBLIC,
- ASN1),
- deleteAsym);
- rsa_verify->update(data.c_str(), data.size());
- EXPECT_TRUE(rsa_verify->verify(sig, sig_len, sig_format));
-
- EXPECT_FALSE(rsa_verify->verify(sig, sig_len - 1, sig_format));
- EXPECT_FALSE(rsa_verify->verify(sig, sig_len + 1, sig_format));
-
- sig[0] = ~sig[0];
- EXPECT_FALSE(rsa_verify->verify(sig, sig_len, sig_format));
-
- delete[] sig;
- }
-
- /// @brief Sign and verify using all variants
- /// @param data Input value
- /// @param privfilename Private key file name
- /// @param password Private key password
- /// @param pubfilename Public key file name
- /// @param asym_algorithm Asym algorithm enum
- /// @param hash_algorithm Hash algorithm enum
- /// @param sig_format Signature format enum
- /// @param expected_sig Expected value
- /// @param sig_len Expected value length
- void doAsymTest(const std::string& data,
- const std::string& privfilename,
- const std::string& password,
- const std::string& pubfilename,
- const AsymAlgorithm asym_algorithm,
- const HashAlgorithm hash_algorithm,
- const AsymFormat sig_format,
- const uint8_t* expected_sig,
- size_t sig_len) {
- doAsymTestDirect(data, privfilename, password, pubfilename,
- asym_algorithm, hash_algorithm, sig_format,
- expected_sig, sig_len);
- doAsymTestVector(data, privfilename, password, pubfilename,
- asym_algorithm, hash_algorithm, sig_format,
- expected_sig, sig_len);
- doAsymTestArray(data, privfilename, password, pubfilename,
- asym_algorithm, hash_algorithm, sig_format,
- expected_sig, sig_len);
- }
-}
-
-//
-// Test values
-//
-TEST(AsymTest, RSA_SHA1) {
- const uint8_t sig_expected[] = {
- 0x16, 0xaa, 0xd3, 0x27, 0x5b, 0x22, 0xff, 0x2b,
- 0x74, 0x77, 0x7a, 0x20, 0x6c, 0xdc, 0xa6, 0xb1,
- 0x88, 0x1a, 0xb3, 0xc6, 0x5a, 0xae, 0x35, 0x3a,
- 0x04, 0x8d, 0x7f, 0x81, 0x5b, 0xef, 0xd6, 0xe2,
- 0x07, 0xee, 0xec, 0x1e, 0xf4, 0x89, 0x82, 0x6c,
- 0x2c, 0x0c, 0x25, 0x8a, 0xf0, 0x8a, 0xde, 0x6c,
- 0xf7, 0x66, 0x9d, 0xa6, 0xd5, 0x69, 0x1e, 0x47,
- 0x76, 0xf3, 0xe7, 0x47, 0x12, 0xd5, 0x92, 0x45,
- 0xb5, 0xc6, 0x50, 0x32, 0xe1, 0x25, 0xd9, 0xa1,
- 0x23, 0xd1, 0x12, 0x6d, 0x1f, 0xa8, 0x9e, 0xc3,
- 0xdb, 0x41, 0xb3, 0x13, 0x0b, 0x7a, 0xea, 0x72,
- 0xa7, 0x60, 0xc8, 0xfd, 0x89, 0xee, 0x36, 0xe4,
- 0x5c, 0xa8, 0xfa, 0x86, 0x4b, 0xcc, 0x15, 0x7d,
- 0xcb, 0x79, 0x90, 0x51, 0xa2, 0x62, 0x43, 0xc7,
- 0xe1, 0x04, 0x08, 0x13, 0x68, 0x6d, 0x7b, 0x4d,
- 0x45, 0xca, 0x3e, 0x6c, 0xba, 0x62, 0x90, 0x0a,
- // pad
- 0x00
- };
- const size_t sig_len = 128;
- doAsymTest("Permission to use, copy, modify, and/or "
- "distribute this software\n",
- privfile, "1234", pubfile, RSA_, SHA1, BASIC,
- sig_expected, sig_len);
}
//
UnsupportedAlgorithm);
}
-TEST(AsymTest, RSA_PUB_PKCS1) {
- CryptoLink& crypto = CryptoLink::getCryptoLink();
- boost::shared_ptr<Asym> pub_key(crypto.createAsym(pubpkcs1, pubpkcs1len,
- RSA_, SHA1,
- PUBLIC, BASIC),
- deleteAsym);
- ASSERT_TRUE(pub_key->validate());
- EXPECT_EQ(RSA_, pub_key->getAsymAlgorithm());
- EXPECT_EQ(SHA1, pub_key->getHashAlgorithm());
- EXPECT_EQ(PUBLIC, pub_key->getAsymKeyKind());
- EXPECT_EQ(1024, pub_key->getKeySize());
- EXPECT_EQ(128, pub_key->getSignatureLength(BASIC));
- EXPECT_EQ(128, pub_key->getSignatureLength(ASN1));
- EXPECT_EQ(128, pub_key->getSignatureLength(DNS));
-
- EXPECT_THROW(crypto.createAsym(pubpkcs1, pubpkcs1len - 1,
- RSA_, SHA1, PUBLIC, BASIC),
- BadKey);
-
- boost::shared_ptr<Asym> ref_key(crypto.createAsym(pubfile, "",
- RSA_, SHA1,
- PUBLIC, ASN1),
- deleteAsym);
- EXPECT_TRUE(pub_key->compare(ref_key.get(), PUBLIC));
- EXPECT_TRUE(ref_key->compare(pub_key.get(), PUBLIC));
- EXPECT_FALSE(pub_key->compare(ref_key.get(), PRIVATE));
- EXPECT_FALSE(pub_key->compare(ref_key.get(), CERT));
-
- const std::vector<uint8_t> pubbin = ref_key->exportkey(PUBLIC, BASIC);
- checkData(&pubbin[0], pubpkcs1, pubpkcs1len);
-}
-
-TEST(AsymTest, RSA_PUB_SPKI) {
- CryptoLink& crypto = CryptoLink::getCryptoLink();
- boost::shared_ptr<Asym> pub_key(crypto.createAsym(pubspki, pubspkilen,
- RSA_, SHA1,
- PUBLIC, ASN1),
- deleteAsym);
- ASSERT_TRUE(pub_key->validate());
- EXPECT_EQ(RSA_, pub_key->getAsymAlgorithm());
- EXPECT_EQ(SHA1, pub_key->getHashAlgorithm());
- EXPECT_EQ(PUBLIC, pub_key->getAsymKeyKind());
- EXPECT_EQ(1024, pub_key->getKeySize());
-
- EXPECT_THROW(crypto.createAsym(pubspki, pubspkilen - 1,
- RSA_, SHA1, PUBLIC, ASN1),
- BadKey);
- EXPECT_THROW(crypto.createAsym(pubspki, pubspkilen,
- RSA_, SHA1, PUBLIC, BASIC),
- BadKey);
-
- boost::shared_ptr<Asym> ref_key(crypto.createAsym(pubfile, "",
- RSA_, SHA1,
- PUBLIC, ASN1),
- deleteAsym);
- EXPECT_TRUE(pub_key->compare(ref_key.get(), PUBLIC));
- EXPECT_TRUE(ref_key->compare(pub_key.get(), PUBLIC));
- EXPECT_FALSE(pub_key->compare(ref_key.get(), PRIVATE));
- EXPECT_FALSE(pub_key->compare(ref_key.get(), CERT));
-
- const std::vector<uint8_t> pubbin = ref_key->exportkey(PUBLIC, ASN1);
- checkData(&pubbin[0], pubspki, pubspkilen);
-}
-
-TEST(AsymTest, RSA_PUB_DNS) {
- CryptoLink& crypto = CryptoLink::getCryptoLink();
- boost::shared_ptr<Asym> pub_key(crypto.createAsym(pubdns, pubdnslen,
- RSA_, SHA1,
- PUBLIC, DNS),
- deleteAsym);
- ASSERT_TRUE(pub_key->validate());
- EXPECT_EQ(RSA_, pub_key->getAsymAlgorithm());
- EXPECT_EQ(SHA1, pub_key->getHashAlgorithm());
- EXPECT_EQ(PUBLIC, pub_key->getAsymKeyKind());
- EXPECT_EQ(1024, pub_key->getKeySize());
-
- boost::shared_ptr<Asym> ref_key(crypto.createAsym(pubfile, "",
- RSA_, SHA1,
- PUBLIC, ASN1),
- deleteAsym);
- EXPECT_TRUE(pub_key->compare(ref_key.get(), PUBLIC));
- EXPECT_TRUE(ref_key->compare(pub_key.get(), PUBLIC));
- EXPECT_FALSE(pub_key->compare(ref_key.get(), PRIVATE));
- EXPECT_FALSE(pub_key->compare(ref_key.get(), CERT));
-
- const std::vector<uint8_t> pubbin = ref_key->exportkey(PUBLIC, DNS);
- EXPECT_EQ(pubbin.size(), pubdnslen);
- checkData(&pubbin[0], pubdns, pubdnslen);
-
- const std::string keystr =
- "AwEAAbMlwgHujJFdo+pVkKIss7E1GHuhAIBPITKU0aLDGrwK7s1/IxJd+JLLh2n"
- "9hQ8lV4hpS16TEjqTqSNkD3yqIMpWk4HpZLIgrVUlh7GFyNb+X6nNUy6vnlOk+7r"
- "vMFOdAe63/6reevpX+99j85x3LqSXEDDBFUhrAR5XjV3r/ELh";
- std::vector<uint8_t> keybin;
- decodeBase64(keystr, keybin);
- EXPECT_EQ(keybin.size(), pubdnslen);
- checkData(&keybin[0], pubdns, pubdnslen);
-
- const std::string dnsfile = TEST_DATA_SRCDIR "/Kexample.+005+18330.key";
- boost::shared_ptr<Asym> dns_key(crypto.createAsym(dnsfile, "",
- RSA_, SHA1,
- PUBLIC, DNS),
- deleteAsym);
- EXPECT_TRUE(dns_key->compare(ref_key.get(), PUBLIC));
- EXPECT_TRUE(ref_key->compare(dns_key.get(), PUBLIC));
-}
-
-TEST(AsymTest, RSA_PRIV_PKCS1) {
- CryptoLink& crypto = CryptoLink::getCryptoLink();
- boost::shared_ptr<Asym> priv_key(crypto.createAsym(privpkcs1, privpkcs1len,
- RSA_, SHA1,
- PRIVATE, BASIC),
- deleteAsym);
- ASSERT_TRUE(priv_key->validate());
- EXPECT_EQ(RSA_, priv_key->getAsymAlgorithm());
- EXPECT_EQ(SHA1, priv_key->getHashAlgorithm());
- EXPECT_EQ(PRIVATE, priv_key->getAsymKeyKind());
- EXPECT_EQ(1024, priv_key->getKeySize());
- EXPECT_EQ(128, priv_key->getSignatureLength(BASIC));
- EXPECT_EQ(128, priv_key->getSignatureLength(ASN1));
- EXPECT_EQ(128, priv_key->getSignatureLength(DNS));
-
- EXPECT_THROW(crypto.createAsym(privpkcs1, privpkcs1len - 1,
- RSA_, SHA1, PRIVATE, BASIC),
- BadKey);
-
- boost::shared_ptr<Asym> ref_key(crypto.createAsym(privfile, "1234",
- RSA_, SHA1,
- PRIVATE, ASN1),
- deleteAsym);
- EXPECT_TRUE(priv_key->compare(ref_key.get(), PRIVATE));
- EXPECT_TRUE(ref_key->compare(priv_key.get(), PRIVATE));
- EXPECT_TRUE(priv_key->compare(ref_key.get(), PUBLIC));
- EXPECT_FALSE(priv_key->compare(ref_key.get(), CERT));
-
- const std::vector<uint8_t> privbin = ref_key->exportkey(PRIVATE, BASIC);
- checkData(&privbin[0], privpkcs1, privpkcs1len);
-
- boost::shared_ptr<Asym> pub_key(crypto.createAsym(pubfile, "",
- RSA_, SHA1,
- PUBLIC, ASN1),
- deleteAsym);
- EXPECT_TRUE(priv_key->compare(pub_key.get(), PUBLIC));
- EXPECT_TRUE(pub_key->compare(priv_key.get(), PUBLIC));
-}
-
-TEST(AsymTest, RSA_PRIV_PKCS) {
- CryptoLink& crypto = CryptoLink::getCryptoLink();
- boost::shared_ptr<Asym> ref_key(crypto.createAsym(privfile, "1234",
- RSA_, SHA1,
- PRIVATE, ASN1),
- deleteAsym);
-#ifndef WITH_BOTAN
- const std::string pkcs1file = TEST_DATA_SRCDIR "/priv.pem";
- boost::shared_ptr<Asym> pkcs1_key(crypto.createAsym(pkcs1file, "",
- RSA_, SHA1,
- PRIVATE, BASIC),
- deleteAsym);
- EXPECT_TRUE(pkcs1_key->validate());
- EXPECT_TRUE(pkcs1_key->compare(ref_key.get(), PRIVATE));
- EXPECT_TRUE(ref_key->compare(pkcs1_key.get(), PRIVATE));
-#endif
-
- // PKCS#8 without encryption
- const std::string nefile = TEST_DATA_SRCDIR "/pkcs8ne.pem";
- boost::shared_ptr<Asym> ne_key(crypto.createAsym(nefile, "",
- RSA_, SHA1,
- PRIVATE, ASN1),
- deleteAsym);
- EXPECT_TRUE(ne_key->validate());
- EXPECT_TRUE(ne_key->compare(ref_key.get(), PRIVATE));
- EXPECT_TRUE(ref_key->compare(ne_key.get(), PRIVATE));
-}
-
-TEST(AsymTest, RSA_PRIV_DNS) {
- CryptoLink& crypto = CryptoLink::getCryptoLink();
- const std::string privdnsfile =
- TEST_DATA_SRCDIR "/Kexample.+005+18330.private";
- boost::shared_ptr<Asym> dns_key(crypto.createAsym(privdnsfile, "",
- RSA_, SHA1,
- PRIVATE, DNS),
- deleteAsym);
- EXPECT_TRUE(dns_key->validate());
- EXPECT_EQ(RSA_, dns_key->getAsymAlgorithm());
- EXPECT_EQ(SHA1, dns_key->getHashAlgorithm());
- EXPECT_EQ(PRIVATE, dns_key->getAsymKeyKind());
- EXPECT_EQ(1024, dns_key->getKeySize());
-
-#ifndef WITH_BOTAN
- EXPECT_THROW(crypto.createAsym(privdnsfile, "",
- RSA_, SHA1, PRIVATE, BASIC),
- BadKey);
-#endif
- EXPECT_THROW(crypto.createAsym(privdnsfile, "",
- RSA_, SHA1, PRIVATE, ASN1),
- BadKey);
- EXPECT_THROW(crypto.createAsym(privdnsfile, "",
- RSA_, MD5, PRIVATE, DNS),
- BadKey);
- EXPECT_THROW(crypto.createAsym(privdnsfile, "",
- RSA_, SHA256, PRIVATE, DNS),
- BadKey);
- EXPECT_THROW(crypto.createAsym(privdnsfile, "",
- RSA_, SHA512, PRIVATE, DNS),
- BadKey);
- EXPECT_THROW(crypto.createAsym(privdnsfile, "",
- RSA_, SHA224, PRIVATE, DNS),
- UnsupportedAlgorithm);
- EXPECT_THROW(crypto.createAsym(privdnsfile, "",
- RSA_, SHA384, PRIVATE, DNS),
- UnsupportedAlgorithm);
-
- boost::shared_ptr<Asym> ref_key(crypto.createAsym(privfile, "1234",
- RSA_, SHA1,
- PRIVATE, ASN1),
- deleteAsym);
- EXPECT_TRUE(dns_key->compare(ref_key.get(), PRIVATE));
- EXPECT_TRUE(ref_key->compare(dns_key.get(), PRIVATE));
- EXPECT_TRUE(dns_key->compare(ref_key.get(), PUBLIC));
- EXPECT_FALSE(dns_key->compare(ref_key.get(), CERT));
-
- char tempname[] = "/tmp/privateXXXXXX";
- const std::string testfile = mktemp(tempname);
- ref_key->exportkey(testfile, "", PRIVATE, DNS);
- FILE* fp;
- fp = fopen(testfile.c_str(), "r");
- ASSERT_TRUE(fp != NULL);
- std::vector<char> testbuf(1024);
- size_t tcc = fread(&testbuf[0], 1024, 1, fp);
- testbuf.resize(tcc);
- fclose(fp);
- fp = fopen(privdnsfile.c_str(), "r");
- ASSERT_TRUE(fp != NULL);
- std::vector<char> refbuf(1024);
- int rcc = fread(&refbuf[0], 1024, 1, fp);
- refbuf.resize(rcc);
- fclose(fp);
- EXPECT_EQ(rcc, tcc);
- EXPECT_TRUE(testbuf == refbuf);
- unlink(testfile.c_str());
-}
-
-TEST(AsymTest, CERTIFICATE) {
- CryptoLink& crypto = CryptoLink::getCryptoLink();
- boost::shared_ptr<Asym> from_file(crypto.createAsym(certfile, "",
- RSA_, SHA1,
- CERT, ASN1),
- deleteAsym);
- EXPECT_TRUE(from_file->validate());
- EXPECT_EQ(RSA_, from_file->getAsymAlgorithm());
- EXPECT_EQ(SHA1, from_file->getHashAlgorithm());
- EXPECT_EQ(CERT, from_file->getAsymKeyKind());
- EXPECT_EQ(1024, from_file->getKeySize());
-
- EXPECT_THROW(crypto.createAsym(certfile, "", RSA_, SHA1, PUBLIC, ASN1),
- BadKey);
- EXPECT_THROW(crypto.createAsym(certfile, "", RSA_, SHA1, PRIVATE, ASN1),
- BadKey);
- EXPECT_THROW(crypto.createAsym(certfile, "", RSA_, SHA1, CERT, BASIC),
- UnsupportedAlgorithm);
- EXPECT_THROW(crypto.createAsym(certfile, "", RSA_, SHA1, CERT, DNS),
- UnsupportedAlgorithm);
- EXPECT_THROW(crypto.createAsym(certfile, "", RSA_, MD5, CERT, ASN1),
- BadKey);
- EXPECT_THROW(crypto.createAsym(certfile, "", RSA_, SHA224, CERT, ASN1),
- BadKey);
- EXPECT_THROW(crypto.createAsym(certfile, "", RSA_, SHA256, CERT, ASN1),
- BadKey);
- EXPECT_THROW(crypto.createAsym(certfile, "", RSA_, SHA384, CERT, ASN1),
- BadKey);
- EXPECT_THROW(crypto.createAsym(certfile, "", RSA_, SHA512, CERT, ASN1),
- BadKey);
-
- boost::shared_ptr<Asym> pub_key(crypto.createAsym(pubfile, "",
- RSA_, SHA1,
- PUBLIC, ASN1),
- deleteAsym);
- EXPECT_TRUE(from_file->compare(pub_key.get(), PUBLIC));
- EXPECT_TRUE(pub_key->compare(from_file.get(), PUBLIC));
- EXPECT_FALSE(from_file->compare(pub_key.get(), PRIVATE));
- EXPECT_FALSE(pub_key->compare(from_file.get(), PRIVATE));
-
- std::vector<uint8_t> certbin = from_file->exportkey(CERT, ASN1);
- boost::shared_ptr<Asym> from_bin(crypto.createAsym(&certbin[0],
- certbin.size(),
- RSA_, SHA1,
- CERT, ASN1),
- deleteAsym);
- EXPECT_TRUE(from_bin->validate());
- EXPECT_TRUE(from_file->compare(from_bin.get(), PUBLIC));
- EXPECT_TRUE(from_bin->compare(from_file.get(), PUBLIC));
- EXPECT_TRUE(from_file->compare(from_bin.get(), CERT));
- EXPECT_TRUE(from_bin->compare(from_file.get(), CERT));
-
- EXPECT_THROW(crypto.createAsym(&certbin[0], certbin.size() - 1,
- RSA_, SHA1, CERT, ASN1),
- BadKey);
- EXPECT_THROW(crypto.createAsym(&certbin[0], certbin.size(),
- RSA_, SHA1, CERT, BASIC),
- UnsupportedAlgorithm);
- EXPECT_THROW(crypto.createAsym(&certbin[0], certbin.size(),
- RSA_, SHA1, CERT, DNS),
- UnsupportedAlgorithm);
- EXPECT_THROW(crypto.createAsym(&certbin[0], certbin.size(),
- RSA_, MD5, CERT, ASN1),
- BadKey);
- EXPECT_THROW(crypto.createAsym(&certbin[0], certbin.size(),
- RSA_, SHA224, CERT, ASN1),
- BadKey);
- EXPECT_THROW(crypto.createAsym(&certbin[0], certbin.size(),
- RSA_, SHA256, CERT, ASN1),
- BadKey);
- EXPECT_THROW(crypto.createAsym(&certbin[0], certbin.size(),
- RSA_, SHA384, CERT, ASN1),
- BadKey);
- EXPECT_THROW(crypto.createAsym(&certbin[0], certbin.size(),
- RSA_, SHA512, CERT, ASN1),
- BadKey);
-
- certbin[certbin.size() - 1] = ~certbin[certbin.size() - 1];
- boost::shared_ptr<Asym> bad_bin(crypto.createAsym(&certbin[0],
- certbin.size(),
- RSA_, SHA1,
- CERT, ASN1),
- deleteAsym);
- EXPECT_FALSE(bad_bin->validate());
-}
-
-//
-// Multiple signatures
-//
-TEST(AsymTest, doubleSign) {
- std::string data = "Kea provides DHCPv4 and DHCPv6 servers";
- OutputBuffer data_buf(data.size());
- data_buf.writeData(data.c_str(), data.size());
- CryptoLink& crypto = CryptoLink::getCryptoLink();
-
- // Sign it
- boost::shared_ptr<Asym> rsa_sign(crypto.createAsym(privfile, "1234",
- RSA_, SHA1,
- PRIVATE, ASN1),
- deleteAsym);
- ASSERT_TRUE(rsa_sign);
-
- OutputBuffer sig1(1);
- size_t sig1_len = rsa_sign->getSignatureLength(BASIC);
- EXPECT_EQ(128, sig1_len);
- rsa_sign->update(data_buf.getData(), data_buf.getLength());
- rsa_sign->sign(sig1, sig1_len, BASIC);
- ASSERT_EQ(sig1_len, sig1.getLength());
-
- // Clear state
- rsa_sign->clear();
-
- // Sign it again
- OutputBuffer sig2(1);
- size_t sig2_len = rsa_sign->getSignatureLength(BASIC);
- EXPECT_EQ(128, sig2_len);
- rsa_sign->update(data_buf.getData(), data_buf.getLength());
- rsa_sign->sign(sig2, sig2_len, BASIC);
- EXPECT_EQ(sig2_len, sig2.getLength());
-
- // Compare
- ASSERT_EQ(sig1_len, sig2_len);
- EXPECT_TRUE(std::memcmp(sig1.getData(), sig2.getData(), sig1_len) == 0);
-}
-
-//
-// Multiple verifies
-//
-TEST(AsymTest, doubleVerify) {
- std::string data = "Kea provides DHCPv4 and DHCPv6 servers";
- OutputBuffer data_buf(data.size());
- data_buf.writeData(data.c_str(), data.size());
- CryptoLink& crypto = CryptoLink::getCryptoLink();
-
- // Sign it
- boost::shared_ptr<Asym> rsa_sign(crypto.createAsym(privfile, "1234",
- RSA_, SHA1,
- PRIVATE, ASN1),
- deleteAsym);
- ASSERT_TRUE(rsa_sign);
-
- OutputBuffer sig(1);
- size_t sig_len = rsa_sign->getSignatureLength(BASIC);
- EXPECT_EQ(128, sig_len);
- rsa_sign->update(data_buf.getData(), data_buf.getLength());
- rsa_sign->sign(sig, sig_len, BASIC);
- EXPECT_EQ(sig_len, sig.getLength());
-
- // Verify
- boost::shared_ptr<Asym> rsa_verify(crypto.createAsym(pubfile, "",
- RSA_, SHA1,
- PUBLIC, ASN1),
- deleteAsym);
- ASSERT_TRUE(rsa_verify);
-
- rsa_verify->update(data_buf.getData(), data_buf.getLength());
- EXPECT_TRUE(rsa_verify->verify(sig.getData(), sig.getLength(), BASIC));
-
- // Clear state
- rsa_verify->clear();
-
- // Verify again
- rsa_verify->update(data_buf.getData(), data_buf.getLength());
- EXPECT_TRUE(rsa_verify->verify(sig.getData(), sig.getLength(), BASIC));
-}
-
namespace {
std::string callout_name("");
EXPECT_TRUE(std::memcmp(&bin[0], &callout_cert[0], bin.size()) == 0);
ASSERT_EQ(1, callout_argument_names.size());
EXPECT_TRUE(callout_argument_names[0].compare("certificate") == 0);
+
+ EXPECT_NO_THROW(preCLH.deregisterCallout("validate_certificate",
+ validate_certificate_callout));
}