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; }
EpadResult ExtractFromWad(RandomInStream &in, OutStream &out, std::string &key_file) { WadMetadata metadata; auto result = ExtractWadMetadata(in, in.GetCount(), metadata); in.Seek(metadata.payload_offset); if(result != EpadResult::Success) return result; Botan::SecureVector<byte> buffer; buffer.resize(metadata.payload_size != 0 ? metadata.payload_size : in.GetCount()); in.Read(buffer.data(), buffer.size()); out.Write(buffer.data(), buffer.size()); key_file.clear(); if(metadata.key_file_offset != kInvalid) { key_file.resize(metadata.key_file_size); in.Seek(metadata.key_file_offset); in.Read(reinterpret_cast<byte *>(&*key_file.begin()), metadata.key_file_size); } return EpadResult::Success; }
// 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::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; }
void ne7ssh_string::addVectorField(const Botan::SecureVector<Botan::byte> &vector) { uint32 nLen = htonl(vector.size()); _buffer += SecureVector<Botan::byte>((Botan::byte*)&nLen, sizeof(uint32)); _buffer += vector; }
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; }
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; }
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; }
// 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; }
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; }
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; }
// 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; }
bool failed_test(const std::string& algo, std::vector<std::string> params, bool is_extension, bool exp_pass, std::string& last_missing, Botan::RandomNumberGenerator& rng) { #if !EXTRA_TESTS if(!exp_pass) return true; #endif std::map<std::string, std::string> vars; vars["input"] = params[0]; vars["output"] = params[1]; if(params.size() > 2) vars["key"] = params[2]; if(params.size() > 3) vars["iv"] = params[3]; std::map<std::string, bool> results = algorithm_kat(algo, vars, global_state().algorithm_factory()); if(results.size()) { for(std::map<std::string, bool>::const_iterator i = results.begin(); i != results.end(); ++i) { if(i->second == false) { std::cout << algo << " test with provider " << i->first << " failed\n"; return true; } } return false; // OK } const std::string in = params[0]; const std::string expected = params[1]; params.erase(params.begin()); params.erase(params.begin()); if(in.size() % 2 == 1) { std::cout << "Can't have an odd sized hex string!" << std::endl; return true; } Botan::Pipe pipe; try { Botan::Filter* test = lookup(algo, params); if(test == 0 && is_extension) return !exp_pass; if(test == 0) { if(algo != last_missing) { std::cout << "WARNING: \"" + algo + "\" is not a known " << "algorithm name." << std::endl; last_missing = algo; } return 0; } pipe.reset(); pipe.append(test); pipe.append(new Botan::Hex_Encoder); Botan::SecureVector<byte> data = Botan::hex_decode(in); const byte* data_ptr = &data[0]; // this can help catch errors with buffering, etc size_t len = data.size(); pipe.start_msg(); while(len) { u32bit how_much = random_word(rng, len); pipe.write(data_ptr, how_much); data_ptr += how_much; len -= how_much; } pipe.end_msg(); } catch(Botan::Algorithm_Not_Found& e) { std::cout << "Algorithm not found: " << e.what() << std::endl; return false; } catch(Botan::Exception& e) { if(exp_pass || DEBUG) std::cout << "Exception caught: " << e.what() << std::endl; return true; } catch(std::exception& e) { if(exp_pass || DEBUG) std::cout << "Standard library exception caught: " << e.what() << std::endl; return true; } catch(...) { if(exp_pass || DEBUG) std::cout << "Unknown exception caught." << std::endl; return true; } std::string output; if(pipe.remaining()) { /* Test peeking at an offset in Pipe/SecureQueue */ size_t offset = random_word(rng, pipe.remaining() - 1); size_t length = random_word(rng, pipe.remaining() - offset); Botan::SecureVector<byte> peekbuf(length); pipe.peek(&peekbuf[0], peekbuf.size(), offset); output = pipe.read_all_as_string(); bool OK = true; for(size_t j = offset; j != offset+length; j++) if(static_cast<byte>(output[j]) != peekbuf[j-offset]) OK = false; if(!OK) throw Botan::Self_Test_Failure("Peek testing failed in validate.cpp"); } if(output == expected && !exp_pass) { std::cout << "FAILED: " << expected << " == " << std::endl << " " << output << std::endl; return false; } if(output != expected && exp_pass) { std::cout << "\nFAILED: " << expected << " != " << std::endl << " " << output << std::endl; return true; } if(output != expected && !exp_pass) return true; return false; }
// 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; }
// 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; }
// 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()); }