bool BotanDSA::signFinal(ByteString& signature) { if (!AsymmetricAlgorithm::signFinal(signature)) { return false; } // Perform the signature operation Botan::SecureVector<Botan::byte> signResult; try { BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); signResult = signer->signature(*rng->getRNG()); } catch (...) { ERROR_MSG("Could not sign the data"); delete signer; signer = NULL; return false; } // Return the result signature.resize(signResult.size()); memcpy(&signature[0], signResult.begin(), signResult.size()); delete signer; signer = NULL; return true; }
// Create the Botan representation of the key void BotanRSAPrivateKey::createBotanKey() { // d and n is not needed, they can be calculated if (p.size() != 0 && q.size() != 0 && e.size() != 0) { if (rsa) { delete rsa; rsa = NULL; } try { BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); rsa = new Botan::RSA_PrivateKey(*rng->getRNG(), BotanUtil::byteString2bigInt(p), BotanUtil::byteString2bigInt(q), BotanUtil::byteString2bigInt(e), BotanUtil::byteString2bigInt(d), BotanUtil::byteString2bigInt(n)); } catch (...) { ERROR_MSG("Could not create the Botan private key"); } } }
// Create the Botan representation of the key void BotanDSAPrivateKey::createBotanKey() { // y is not needed // Todo: Either q or x is needed. Both is not needed if (this->p.size() != 0 && this->q.size() != 0 && this->g.size() != 0 && this->x.size() != 0) { if (dsa) { delete dsa; dsa = NULL; } try { BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); dsa = new Botan::DSA_PrivateKey(*rng->getRNG(), Botan::DL_Group(BotanUtil::byteString2bigInt(this->p), BotanUtil::byteString2bigInt(this->q), BotanUtil::byteString2bigInt(this->g)), BotanUtil::byteString2bigInt(this->x)); } catch (...) { ERROR_MSG("Could not create the Botan private key"); } } }
// Create the Botan representation of the key void BotanECDHPrivateKey::createBotanKey() { if (this->ec.size() != 0 && this->d.size() != 0) { if (eckey) { delete eckey; eckey = NULL; } try { BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); Botan::EC_Group group = BotanUtil::byteString2ECGroup(this->ec); eckey = new Botan::ECDH_PrivateKey(*rng->getRNG(), group, BotanUtil::byteString2bigInt(this->d)); } catch (...) { ERROR_MSG("Could not create the Botan public key"); } } }
// Key factory bool BotanDH::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */) { // Check parameters if ((ppKeyPair == NULL) || (parameters == NULL)) { return false; } if (!parameters->areOfType(DHParameters::type)) { ERROR_MSG("Invalid parameters supplied for DH key generation"); return false; } DHParameters* params = (DHParameters*) parameters; // Generate the key-pair BotanDH_PrivateKey* dh = NULL; try { BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); // PKCS#3: 2^(l-1) <= x < 2^l Botan::BigInt x; if (params->getXBitLength() > 0) { x.randomize(*rng->getRNG(), params->getXBitLength()); } dh = new BotanDH_PrivateKey(*rng->getRNG(), Botan::DL_Group(BotanUtil::byteString2bigInt(params->getP()), BotanUtil::byteString2bigInt(params->getG())), x); } catch (std::exception& e) { ERROR_MSG("DH key generation failed with %s", e.what()); return false; } // Create an asymmetric key-pair object to return BotanDHKeyPair* kp = new BotanDHKeyPair(); ((BotanDHPublicKey*) kp->getPublicKey())->setFromBotan(dh); ((BotanDHPrivateKey*) kp->getPrivateKey())->setFromBotan(dh); *ppKeyPair = kp; // Release the key delete dh; return true; }
// Key factory bool BotanDSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng /* = NULL */) { // Check parameters if ((ppKeyPair == NULL) || (parameters == NULL)) { return false; } if (!parameters->areOfType(DSAParameters::type)) { ERROR_MSG("Invalid parameters supplied for DSA key generation"); return false; } DSAParameters* params = (DSAParameters*) parameters; // Generate the key-pair Botan::DSA_PrivateKey* dsa = NULL; try { BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); dsa = new Botan::DSA_PrivateKey(*rng->getRNG(), Botan::DL_Group(BotanUtil::byteString2bigInt(params->getP()), BotanUtil::byteString2bigInt(params->getQ()), BotanUtil::byteString2bigInt(params->getG()))); } catch (...) { ERROR_MSG("DSA key generation failed"); return false; } // Create an asymmetric key-pair object to return BotanDSAKeyPair* kp = new BotanDSAKeyPair(); ((BotanDSAPublicKey*) kp->getPublicKey())->setFromBotan(dsa); ((BotanDSAPrivateKey*) kp->getPrivateKey())->setFromBotan(dsa); *ppKeyPair = kp; // Release the key delete dsa; return true; }
bool BotanDSA::generateParameters(AsymmetricParameters** ppParams, void* parameters /* = NULL */, RNG* rng /* = NULL*/) { if ((ppParams == NULL) || (parameters == NULL)) { return false; } size_t bitLen = (size_t) parameters; if (bitLen < getMinKeySize() || bitLen > getMaxKeySize()) { ERROR_MSG("This DSA key size is not supported"); return false; } Botan::DL_Group* group = NULL; // Taken from OpenSSL size_t qLen = bitLen >= 2048 ? 256 : 160; try { BotanRNG* brng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); group = new Botan::DL_Group(*brng->getRNG(), Botan::DL_Group::Prime_Subgroup, bitLen, qLen); } catch (...) { ERROR_MSG("Failed to generate %d bit DSA parameters", bitLen); return false; } // Store the DSA parameters DSAParameters* params = new DSAParameters(); ByteString p = BotanUtil::bigInt2ByteString(group->get_p()); params->setP(p); ByteString q = BotanUtil::bigInt2ByteString(group->get_q()); params->setQ(q); ByteString g = BotanUtil::bigInt2ByteString(group->get_g()); params->setG(g); *ppParams = params; delete group; return true; }
// Decode from PKCS#8 BER bool BotanRSAPrivateKey::PKCS8Decode(const ByteString& ber) { Botan::DataSource_Memory source(ber.const_byte_str(), ber.size()); if (source.end_of_data()) return false; #if BOTAN_VERSION_MINOR == 11 Botan::secure_vector<Botan::byte> keydata; #else Botan::SecureVector<Botan::byte> keydata; #endif Botan::AlgorithmIdentifier alg_id; Botan::RSA_PrivateKey* key = NULL; try { Botan::BER_Decoder(source) .start_cons(Botan::SEQUENCE) .decode_and_check<size_t>(0, "Unknown PKCS #8 version number") .decode(alg_id) .decode(keydata, Botan::OCTET_STRING) .discard_remaining() .end_cons(); if (keydata.empty()) throw Botan::Decoding_Error("PKCS #8 private key decoding failed"); if (Botan::OIDS::lookup(alg_id.oid).compare("RSA")) { ERROR_MSG("Decoded private key not RSA"); return false; } BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); key = new Botan::RSA_PrivateKey(alg_id, keydata, *rng->getRNG()); if (key == NULL) return false; setFromBotan(key); delete key; } catch (std::exception& e) { ERROR_MSG("Decode failed on %s", e.what()); return false; } return true; }
// Key factory bool BotanECDH::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */) { // Check parameters if ((ppKeyPair == NULL) || (parameters == NULL)) { return false; } if (!parameters->areOfType(ECParameters::type)) { ERROR_MSG("Invalid parameters supplied for ECDH key generation"); return false; } ECParameters* params = (ECParameters*) parameters; // Generate the key-pair Botan::ECDH_PrivateKey* eckp = NULL; try { BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); eckp = new Botan::ECDH_PrivateKey(*rng->getRNG(), BotanUtil::byteString2ECGroup(params->getEC())); } catch (...) { ERROR_MSG("ECDH key generation failed"); return false; } // Create an asymmetric key-pair object to return BotanECDHKeyPair* kp = new BotanECDHKeyPair(); ((BotanECDHPublicKey*) kp->getPublicKey())->setFromBotan(eckp); ((BotanECDHPrivateKey*) kp->getPrivateKey())->setFromBotan(eckp); *ppKeyPair = kp; // Release the key delete eckp; return true; }
bool BotanDH::generateParameters(AsymmetricParameters** ppParams, void* parameters /* = NULL */, RNG* rng /* = NULL*/) { if ((ppParams == NULL) || (parameters == NULL)) { return false; } size_t bitLen = (size_t) parameters; if (bitLen < getMinKeySize() || bitLen > getMaxKeySize()) { ERROR_MSG("This DH key size is not supported"); return false; } Botan::DL_Group* group = NULL; try { BotanRNG* brng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); group = new Botan::DL_Group(*brng->getRNG(), Botan::DL_Group::Strong, bitLen); } catch (...) { ERROR_MSG("Failed to generate %d bit DH parameters", bitLen); return false; } // Store the DH parameters DHParameters* params = new DHParameters(); ByteString p = BotanUtil::bigInt2ByteString(group->get_p()); params->setP(p); ByteString g = BotanUtil::bigInt2ByteString(group->get_g()); params->setG(g); *ppParams = params; delete group; return true; }
bool BotanGOST::signFinal(ByteString& signature) { if (!AsymmetricAlgorithm::signFinal(signature)) { return false; } // Perform the signature operation #if BOTAN_VERSION_MINOR == 11 std::vector<Botan::byte> signResult; #else Botan::SecureVector<Botan::byte> signResult; #endif try { BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); signResult = signer->signature(*rng->getRNG()); } catch (...) { ERROR_MSG("Could not sign the data"); delete signer; signer = NULL; return false; } // Return the result signature.resize(signResult.size()); #if BOTAN_VERSION_MINOR == 11 memcpy(&signature[0], signResult.data(), signResult.size()); #else memcpy(&signature[0], signResult.begin(), signResult.size()); #endif delete signer; signer = NULL; return true; }
// Encryption functions bool BotanRSA::encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const std::string padding) { // Check if the public key is the right type if (!publicKey->isOfType(BotanRSAPublicKey::type)) { ERROR_MSG("Invalid key type supplied"); return false; } std::string lowerPadding; lowerPadding.resize(padding.size()); std::transform(padding.begin(), padding.end(), lowerPadding.begin(), tolower); std::string eme; if (!lowerPadding.compare("rsa-pkcs")) { eme = "PKCS1v15"; } else if (!lowerPadding.compare("rsa-pkcs-oaep")) { eme = "EME1(SHA-160)"; } else if (!lowerPadding.compare("rsa-raw")) { eme = "Raw"; } else { ERROR_MSG("Invalid padding mechanism supplied (%s)", padding.c_str()); return false; } BotanRSAPublicKey* pk = (BotanRSAPublicKey*) publicKey; Botan::RSA_PublicKey* botanKey = pk->getBotanKey(); if (!botanKey) { ERROR_MSG("Could not get the Botan public key"); return false; } Botan::PK_Encryptor_EME* encryptor = NULL; try { encryptor = new Botan::PK_Encryptor_EME(*botanKey, eme); } catch (...) { ERROR_MSG("Could not create the encryptor token"); return false; } // Perform the encryption operation Botan::SecureVector<Botan::byte> encResult; try { BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); encResult = encryptor->encrypt(data.const_byte_str(), data.size(), *rng->getRNG()); } catch (...) { ERROR_MSG("Could not encrypt the data"); delete encryptor; return false; } // Return the result encryptedData.resize(encResult.size()); memcpy(&encryptedData[0], encResult.begin(), encResult.size()); delete encryptor; return true; }
// Key factory bool BotanRSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */) { // Check parameters if ((ppKeyPair == NULL) || (parameters == NULL)) { return false; } if (!parameters->areOfType(RSAParameters::type)) { ERROR_MSG("Invalid parameters supplied for RSA key generation"); return false; } RSAParameters* params = (RSAParameters*) parameters; if (params->getBitLength() < getMinKeySize() || params->getBitLength() > getMaxKeySize()) { ERROR_MSG("This RSA key size (%lu) is not supported", params->getBitLength()); return false; } // Retrieve the desired public exponent unsigned long e = params->getE().long_val(); // Check the public exponent if ((e == 0) || (e % 2 != 1)) { ERROR_MSG("Invalid RSA public exponent %d", e); return false; } // Create an asymmetric key-pair object to return BotanRSAKeyPair* kp = new BotanRSAKeyPair(); // Generate the key-pair Botan::RSA_PrivateKey* rsa = NULL; try { BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); rsa = new Botan::RSA_PrivateKey(*rng->getRNG(), params->getBitLength(), e); } catch (std::exception& ex) { ERROR_MSG("RSA key generation failed: %s", ex.what()); delete kp; return false; } ((BotanRSAPublicKey*) kp->getPublicKey())->setFromBotan(rsa); ((BotanRSAPrivateKey*) kp->getPrivateKey())->setFromBotan(rsa); *ppKeyPair = kp; // Release the key delete rsa; return true; }
// Encryption functions bool BotanRSA::encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const AsymMech::Type padding) { // Check if the public key is the right type if (!publicKey->isOfType(BotanRSAPublicKey::type)) { ERROR_MSG("Invalid key type supplied"); return false; } std::string eme; switch (padding) { case AsymMech::RSA_PKCS: eme = "PKCS1v15"; break; case AsymMech::RSA_PKCS_OAEP: eme = "EME1(SHA-160)"; break; case AsymMech::RSA: eme = "Raw"; break; default: ERROR_MSG("Invalid padding mechanism supplied (%i)", padding); return false; } BotanRSAPublicKey* pk = (BotanRSAPublicKey*) publicKey; Botan::RSA_PublicKey* botanKey = pk->getBotanKey(); if (!botanKey) { ERROR_MSG("Could not get the Botan public key"); return false; } Botan::PK_Encryptor_EME* encryptor = NULL; try { encryptor = new Botan::PK_Encryptor_EME(*botanKey, eme); } catch (...) { ERROR_MSG("Could not create the encryptor token"); return false; } // Perform the encryption operation #if BOTAN_VERSION_MINOR == 11 std::vector<Botan::byte> encResult; #else Botan::SecureVector<Botan::byte> encResult; #endif try { BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); encResult = encryptor->encrypt(data.const_byte_str(), data.size(), *rng->getRNG()); } catch (...) { ERROR_MSG("Could not encrypt the data"); delete encryptor; return false; } // Return the result encryptedData.resize(encResult.size()); #if BOTAN_VERSION_MINOR == 11 memcpy(&encryptedData[0], encResult.data(), encResult.size()); #else memcpy(&encryptedData[0], encResult.begin(), encResult.size()); #endif delete encryptor; return true; }
// Signing functions bool BotanRSA::sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const AsymMech::Type mechanism, const void* param /* = NULL */, const size_t paramLen /* = 0 */) { std::string emsa = ""; switch (mechanism) { case AsymMech::RSA: emsa = "Raw"; break; case AsymMech::RSA_PKCS: emsa = "EMSA3(Raw)"; break; default: // Call default implementation return AsymmetricAlgorithm::sign(privateKey, dataToSign, signature, mechanism, param, paramLen); } // Check if the private key is the right type if (!privateKey->isOfType(BotanRSAPrivateKey::type)) { ERROR_MSG("Invalid key type supplied"); return false; } BotanRSAPrivateKey* pk = (BotanRSAPrivateKey*) privateKey; Botan::RSA_PrivateKey* botanKey = pk->getBotanKey(); if (!botanKey) { ERROR_MSG("Could not get the Botan private key"); return false; } try { signer = new Botan::PK_Signer(*botanKey, emsa); // Should we add DISABLE_FAULT_PROTECTION? Makes this operation faster. } catch (...) { ERROR_MSG("Could not create the signer token"); return false; } // Perform the signature operation #if BOTAN_VERSION_MINOR == 11 std::vector<Botan::byte> signResult; #else Botan::SecureVector<Botan::byte> signResult; #endif try { BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); signResult = signer->sign_message(dataToSign.const_byte_str(), dataToSign.size(), *rng->getRNG()); } catch (std::exception& e) { ERROR_MSG("Could not sign the data: %s", e.what()); delete signer; signer = NULL; return false; } // Return the result signature.resize(signResult.size()); #if BOTAN_VERSION_MINOR == 11 memcpy(&signature[0], signResult.data(), signResult.size()); #else memcpy(&signature[0], signResult.begin(), signResult.size()); #endif delete signer; signer = NULL; return true; }
bool BotanDH::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey) { // Check parameters if ((ppSymmetricKey == NULL) || (publicKey == NULL) || (privateKey == NULL)) { return false; } // Get keys Botan::DH_PublicKey* pub = ((BotanDHPublicKey*) publicKey)->getBotanKey(); BotanDH_PrivateKey* priv = ((BotanDHPrivateKey*) privateKey)->getBotanKey(); if (pub == NULL || priv == NULL || priv->impl == NULL) { ERROR_MSG("Failed to get Botan DH keys"); return false; } // Derive the secret Botan::SymmetricKey sk; try { #if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33) BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); Botan::PK_Key_Agreement ka(*priv->impl, *rng->getRNG(), "Raw"); #else Botan::PK_Key_Agreement ka(*priv->impl, "Raw"); #endif sk = ka.derive_key(0, pub->public_value()); } catch (std::exception& e) { ERROR_MSG("Botan DH key agreement failed: %s", e.what()); return false; } ByteString secret; // We compensate that Botan removes leading zeros int size = ((BotanDHPublicKey*) publicKey)->getOutputLength(); int keySize = sk.length(); secret.wipe(size); memcpy(&secret[0] + size - keySize, sk.begin(), keySize); *ppSymmetricKey = new SymmetricKey(secret.size() * 8); if (*ppSymmetricKey == NULL) { ERROR_MSG("Can't create DH secret"); return false; } if (!(*ppSymmetricKey)->setKeyBits(secret)) { delete *ppSymmetricKey; *ppSymmetricKey = NULL; return false; } return true; }
// Signing functions bool BotanDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const std::string mechanism) { std::string lowerMechanism; lowerMechanism.resize(mechanism.size()); std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower); std::string emsa; if (!lowerMechanism.compare("dsa")) { emsa = "Raw"; } else { // Call default implementation return AsymmetricAlgorithm::sign(privateKey, dataToSign, signature, mechanism); } // Check if the private key is the right type if (!privateKey->isOfType(BotanDSAPrivateKey::type)) { ERROR_MSG("Invalid key type supplied"); return false; } BotanDSAPrivateKey* pk = (BotanDSAPrivateKey*) privateKey; Botan::DSA_PrivateKey* botanKey = pk->getBotanKey(); if (!botanKey) { ERROR_MSG("Could not get the Botan private key"); return false; } try { signer = new Botan::PK_Signer(*botanKey, emsa); // Should we add DISABLE_FAULT_PROTECTION? Makes this operation faster. } catch (...) { ERROR_MSG("Could not create the signer token"); return false; } // Perform the signature operation Botan::SecureVector<Botan::byte> signResult; try { BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); signResult = signer->sign_message(dataToSign.const_byte_str(), dataToSign.size(), *rng->getRNG()); } catch (...) { ERROR_MSG("Could not sign the data"); delete signer; signer = NULL; return false; } // Return the result signature.resize(signResult.size()); memcpy(&signature[0], signResult.begin(), signResult.size()); delete signer; signer = NULL; return true; }