bool ne7ssh_crypt::negotiatedKex (Botan::SecureVector<Botan::byte> &kexAlgo) { if (!memcmp (kexAlgo.begin(), "diffie-hellman-group1-sha1", kexAlgo.size())) { kexMethod = DH_GROUP1_SHA1; return true; } else if (!memcmp (kexAlgo.begin(), "diffie-hellman-group14-sha1", kexAlgo.size())) { kexMethod = DH_GROUP14_SHA1; return true; } ne7ssh::errors()->push (session->getSshChannel(), "KEX algorithm: '%B' not defined.", &kexAlgo); return false; }
bool ne7ssh_crypt::negotiatedHostkey (Botan::SecureVector<Botan::byte> &hostkeyAlgo) { if (!memcmp (hostkeyAlgo.begin(), "ssh-dss", hostkeyAlgo.size())) { hostkeyMethod = SSH_DSS; return true; } else if (!memcmp (hostkeyAlgo.begin(), "ssh-rsa", hostkeyAlgo.size())) { hostkeyMethod = SSH_RSA; return true; } ne7ssh::errors()->push (session->getSshChannel(), "Hostkey algorithm: '%B' not defined.", &hostkeyAlgo); return false; }
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; }
bool ne7ssh_crypt::negotiatedCmprsS2c (Botan::SecureVector<Botan::byte> &cmprsAlgo) { if (!memcmp (cmprsAlgo.begin(), "none", cmprsAlgo.size())) { s2cCmprsMethod = NONE; return true; } else if (!memcmp (cmprsAlgo.begin(), "zlib", cmprsAlgo.size())) { s2cCmprsMethod = ZLIB; return true; } ne7ssh::errors()->push (session->getSshChannel(), "Compression algorithm: '%B' not defined.", &cmprsAlgo); return false; }
// Encode into PKCS#8 DER ByteString BotanDSAPrivateKey::PKCS8Encode() { ByteString der; createBotanKey(); if (dsa == NULL) return der; const Botan::SecureVector<Botan::byte> ber = Botan::PKCS8::BER_encode(*dsa); der.resize(ber.size()); memcpy(&der[0], ber.begin(), ber.size()); return der; }
bool ne7ssh_crypt::negotiatedMacS2c (Botan::SecureVector<Botan::byte> &macAlgo) { if (!memcmp (macAlgo.begin(), "hmac-sha1", macAlgo.size())) { s2cMacMethod = HMAC_SHA1; return true; } else if (!memcmp (macAlgo.begin(), "hmac-md5", macAlgo.size())) { s2cMacMethod = HMAC_MD5; return true; } else if (!memcmp (macAlgo.begin(), "none", macAlgo.size())) { s2cMacMethod = HMAC_NONE; return true; } ne7ssh::errors()->push (session->getSshChannel(), "HMAC algorithm: '%B' not defined.", &macAlgo); return false; }
bool ne7ssh_crypt::decryptPacket (Botan::SecureVector<Botan::byte> &decrypted, Botan::SecureVector<Botan::byte> &packet, uint32 len) { uint32 pLen = packet.size(); if (len % decryptBlock) len = len + (len % decryptBlock); if (len > pLen) len = pLen; decrypt->process_msg (packet.begin(), len); decrypted = decrypt->read_all (decrypt->message_count() - 1); return true; }
bool ne7ssh_crypt::encryptPacket (Botan::SecureVector<Botan::byte> &crypted, Botan::SecureVector<Botan::byte> &hmac, Botan::SecureVector<Botan::byte> &packet, uint32 seq) { SecureVector<Botan::byte> macStr; uint32 nSeq = (uint32)htonl (seq); encrypt->start_msg(); encrypt->write (packet.begin(), packet.size()); encrypt->end_msg(); // encrypt->process_msg (packet); crypted = encrypt->read_all (encrypt->message_count() - 1); if (hmacOut) { macStr = Botan::SecureVector<Botan::byte>((Botan::byte*)&nSeq, 4); macStr += packet; hmac = hmacOut->process (macStr); } 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; }
char* digestPIN(CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) { // We do not use any salt Botan::Pipe *digestPIN = new Botan::Pipe(new Botan::Hash_Filter(new Botan::SHA_256), new Botan::Hex_Encoder); digestPIN->start_msg(); digestPIN->write((Botan::byte*)pPin, (Botan::u32bit)ulPinLen); digestPIN->write((Botan::byte*)pPin, (Botan::u32bit)ulPinLen); digestPIN->write((Botan::byte*)pPin, (Botan::u32bit)ulPinLen); digestPIN->end_msg(); // Get the digested PIN Botan::SecureVector<Botan::byte> pinVector = digestPIN->read_all(); int size = pinVector.size(); char *tmpPIN = (char *)malloc(size + 1); if(tmpPIN != NULL_PTR) { tmpPIN[size] = '\0'; memcpy(tmpPIN, pinVector.begin(), size); } delete digestPIN; return tmpPIN; }
bool ne7ssh_crypt::negotiatedCryptoS2c (Botan::SecureVector<Botan::byte> &cryptoAlgo) { if (!memcmp (cryptoAlgo.begin(), "3des-cbc", cryptoAlgo.size())) { s2cCryptoMethod = TDES_CBC; return true; } else if (!memcmp (cryptoAlgo.begin(), "aes128-cbc", cryptoAlgo.size())) { s2cCryptoMethod = AES128_CBC; return true; } else if (!memcmp (cryptoAlgo.begin(), "aes192-cbc", cryptoAlgo.size())) { s2cCryptoMethod = AES192_CBC; return true; } else if (!memcmp (cryptoAlgo.begin(), "aes256-cbc", cryptoAlgo.size())) { s2cCryptoMethod = AES256_CBC; return true; } else if (!memcmp (cryptoAlgo.begin(), "blowfish-cbc", cryptoAlgo.size())) { s2cCryptoMethod = BLOWFISH_CBC; return true; } else if (!memcmp (cryptoAlgo.begin(), "cast128-cbc", cryptoAlgo.size())) { s2cCryptoMethod = CAST128_CBC; return true; } else if (!memcmp (cryptoAlgo.begin(), "twofish-cbc", cryptoAlgo.size()) || !memcmp (cryptoAlgo.begin(), "twofish256-cbc", cryptoAlgo.size())) { s2cCryptoMethod = TWOFISH_CBC; return true; } ne7ssh::errors()->push (session->getSshChannel(), "Cryptographic method: '%B' not defined.", &cryptoAlgo); return false; }
// Encode into PKCS#8 DER ByteString BotanECDHPrivateKey::PKCS8Encode() { ByteString der; createBotanKey(); if (eckey == NULL) return der; const size_t PKCS8_VERSION = 0; // No OID for ECDH const Botan::OID oid("1.2.840.10045.2.1"); // Force EC_DOMPAR_ENC_OID const Botan::MemoryVector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID); const Botan::AlgorithmIdentifier alg_id(oid, parameters); const Botan::SecureVector<Botan::byte> ber = Botan::DER_Encoder() .start_cons(Botan::SEQUENCE) .encode(PKCS8_VERSION) .encode(alg_id) .encode(eckey->pkcs8_private_key(), Botan::OCTET_STRING) .end_cons() .get_contents(); der.resize(ber.size()); memcpy(&der[0], ber.begin(), ber.size()); return der; }
// 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; }
// 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; }
// Decryption functions bool BotanRSA::decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const std::string padding) { // Check if the private key is the right type if (!privateKey->isOfType(BotanRSAPrivateKey::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; } BotanRSAPrivateKey* pk = (BotanRSAPrivateKey*) privateKey; Botan::RSA_PrivateKey* botanKey = pk->getBotanKey(); if (!botanKey) { ERROR_MSG("Could not get the Botan private key"); return false; } Botan::PK_Decryptor_EME* decryptor = NULL; try { decryptor = new Botan::PK_Decryptor_EME(*botanKey, eme); } catch (...) { ERROR_MSG("Could not create the decryptor token"); return false; } // Perform the decryption operation Botan::SecureVector<Botan::byte> decResult; try { decResult = decryptor->decrypt(encryptedData.const_byte_str(), encryptedData.size()); } catch (...) { ERROR_MSG("Could not decrypt the data"); delete decryptor; return false; } // Return the result if (!eme.compare("Raw")) { // We compensate that Botan removes leading zeros int modSize = pk->getN().size(); int decSize = decResult.size(); data.resize(modSize); memcpy(&data[0] + modSize - decSize, decResult.begin(), decSize); } else { data.resize(decResult.size()); memcpy(&data[0], decResult.begin(), decResult.size()); } delete decryptor; return true; }
Fixed_Output_RNG(const Botan::SecureVector<byte>& in) { buf.insert(buf.end(), in.begin(), in.end()); }
Fixed_Output_RNG(const std::string& in_str) { Botan::SecureVector<byte> in = Botan::hex_decode(in_str); buf.insert(buf.end(), in.begin(), in.end()); }
// 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; }
ne7ssh_string::ne7ssh_string(Botan::SecureVector<Botan::byte>& var, uint32 position) : _currentPart(0), _buffer(SecureVector<Botan::byte>((var.begin() + position), (var.size() - position))) { }
// 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; }
void ne7ssh_string::addVector(Botan::SecureVector<Botan::byte> &secvec) { _buffer += SecureVector<Botan::byte>(secvec.begin(), secvec.size()); }