• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5123321399

30 May 2023 04:06PM UTC coverage: 92.213% (+0.004%) from 92.209%
5123321399

Pull #3558

github

web-flow
Merge dd72f7389 into 057bcbc35
Pull Request #3558: Add braces around all if/else statements

75602 of 81986 relevant lines covered (92.21%)

11859779.3 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.25
/src/cli/pk_crypt.cpp
1
/*
2
* (C) 2018 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include "cli.h"
8

9
#if defined(BOTAN_HAS_RSA) && defined(BOTAN_HAS_AEAD_MODES) && defined(BOTAN_HAS_EME_OAEP) && \
10
   defined(BOTAN_HAS_SHA2_32) && defined(BOTAN_HAS_PEM_CODEC) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
11

12
   #include <botan/aead.h>
13
   #include <botan/ber_dec.h>
14
   #include <botan/der_enc.h>
15
   #include <botan/pem.h>
16
   #include <botan/pkcs8.h>
17
   #include <botan/pubkey.h>
18
   #include <botan/rng.h>
19
   #include <botan/x509_key.h>
20

21
namespace Botan_CLI {
22

23
namespace {
24

25
class PK_Encrypt final : public Command {
26
   public:
27
      PK_Encrypt() : Command("pk_encrypt --aead=AES-256/GCM pubkey datafile") {}
4✔
28

29
      std::string group() const override { return "pubkey"; }
1✔
30

31
      std::string description() const override { return "Encrypt a file using a RSA public key"; }
1✔
32

33
      void go() override {
1✔
34
         auto key = Botan::X509::load_key(get_arg("pubkey"));
2✔
35
         if(!key) {
1✔
36
            throw CLI_Error("Unable to load public key");
×
37
         }
38

39
         if(key->algo_name() != "RSA") {
1✔
40
            throw CLI_Usage_Error("This function requires an RSA key");
×
41
         }
42

43
         const std::string OAEP_HASH = "SHA-256";
1✔
44
         const std::string aead_algo = get_arg("aead");
1✔
45

46
         std::unique_ptr<Botan::AEAD_Mode> aead = Botan::AEAD_Mode::create(aead_algo, Botan::Cipher_Dir::Encryption);
1✔
47

48
         if(!aead) {
1✔
49
            throw CLI_Usage_Error("The AEAD '" + aead_algo + "' is not available");
×
50
         }
51

52
         const Botan::OID aead_oid = Botan::OID::from_string(aead_algo);
1✔
53
         if(aead_oid.empty()) {
1✔
54
            throw CLI_Usage_Error("No OID defined for AEAD '" + aead_algo + "'");
×
55
         }
56

57
         Botan::secure_vector<uint8_t> data;
1✔
58
         auto insert_fn = [&](const uint8_t b[], size_t l) { data.insert(data.end(), b, b + l); };
1✔
59
         Command::read_file(get_arg("datafile"), insert_fn);
2✔
60

61
         const Botan::AlgorithmIdentifier hash_id(OAEP_HASH, Botan::AlgorithmIdentifier::USE_EMPTY_PARAM);
1✔
62
         const Botan::AlgorithmIdentifier pk_alg_id("RSA/OAEP", hash_id.BER_encode());
1✔
63

64
         Botan::PK_Encryptor_EME enc(*key, rng(), "OAEP(" + OAEP_HASH + ")");
2✔
65

66
         const Botan::secure_vector<uint8_t> file_key = rng().random_vec(aead->key_spec().maximum_keylength());
1✔
67

68
         const std::vector<uint8_t> encrypted_key = enc.encrypt(file_key, rng());
1✔
69

70
         const Botan::secure_vector<uint8_t> nonce = rng().random_vec(aead->default_nonce_length());
1✔
71
         aead->set_key(file_key);
1✔
72
         aead->set_associated_data(encrypted_key);
1✔
73
         aead->start(nonce);
1✔
74

75
         aead->finish(data);
1✔
76

77
         std::vector<uint8_t> buf;
1✔
78
         Botan::DER_Encoder der(buf);
1✔
79

80
         der.start_sequence()
1✔
81
            .encode(pk_alg_id)
1✔
82
            .encode(encrypted_key, Botan::ASN1_Type::OctetString)
1✔
83
            .encode(aead_oid)
1✔
84
            .encode(nonce, Botan::ASN1_Type::OctetString)
1✔
85
            .encode(data, Botan::ASN1_Type::OctetString)
1✔
86
            .end_cons();
1✔
87

88
         output() << Botan::PEM_Code::encode(buf, "PUBKEY ENCRYPTED MESSAGE", 72);
1✔
89
      }
8✔
90
};
91

92
BOTAN_REGISTER_COMMAND("pk_encrypt", PK_Encrypt);
2✔
93

94
class PK_Decrypt final : public Command {
95
   public:
96
      PK_Decrypt() : Command("pk_decrypt privkey datafile") {}
4✔
97

98
      std::string group() const override { return "pubkey"; }
1✔
99

100
      std::string description() const override { return "Decrypt a file using a RSA private key"; }
1✔
101

102
      void go() override {
1✔
103
         Botan::DataSource_Stream input_stream(get_arg("privkey"));
2✔
104
         auto get_pass = [this]() { return get_passphrase("Password"); };
×
105
         std::unique_ptr<Botan::Private_Key> key = Botan::PKCS8::load_key(input_stream, get_pass);
1✔
106

107
         if(!key) {
1✔
108
            throw CLI_Error("Unable to load public key");
×
109
         }
110

111
         if(key->algo_name() != "RSA") {
1✔
112
            throw CLI_Usage_Error("This function requires an RSA key");
×
113
         }
114

115
         Botan::secure_vector<uint8_t> data;
1✔
116
         std::vector<uint8_t> encrypted_key;
1✔
117
         std::vector<uint8_t> nonce;
1✔
118
         Botan::AlgorithmIdentifier pk_alg_id;
1✔
119
         Botan::OID aead_oid;
1✔
120

121
         try {
1✔
122
            Botan::DataSource_Stream input(get_arg("datafile"));
2✔
123

124
            Botan::BER_Decoder(Botan::PEM_Code::decode_check_label(input, "PUBKEY ENCRYPTED MESSAGE"))
2✔
125
               .start_sequence()
1✔
126
               .decode(pk_alg_id)
1✔
127
               .decode(encrypted_key, Botan::ASN1_Type::OctetString)
1✔
128
               .decode(aead_oid)
1✔
129
               .decode(nonce, Botan::ASN1_Type::OctetString)
1✔
130
               .decode(data, Botan::ASN1_Type::OctetString)
1✔
131
               .end_cons();
1✔
132
         } catch(Botan::Decoding_Error&) {
1✔
133
            error_output() << "Parsing input file failed: invalid format?\n";
×
134
            return set_return_code(1);
×
135
         }
×
136

137
         const std::string aead_algo = aead_oid.human_name_or_empty();
1✔
138
         if(aead_algo.empty()) {
1✔
139
            error_output() << "Ciphertext was encrypted with an unknown algorithm";
×
140
            return set_return_code(1);
×
141
         }
142

143
         if(pk_alg_id.oid() != Botan::OID::from_string("RSA/OAEP")) {
1✔
144
            error_output() << "Ciphertext was encrypted with something other than RSA/OAEP";
×
145
            return set_return_code(1);
×
146
         }
147

148
         Botan::AlgorithmIdentifier oaep_hash_id;
1✔
149
         Botan::BER_Decoder(pk_alg_id.parameters()).decode(oaep_hash_id);
1✔
150

151
         const std::string oaep_hash = oaep_hash_id.oid().human_name_or_empty();
1✔
152

153
         if(oaep_hash.empty()) {
1✔
154
            error_output() << "Unknown hash function used with OAEP, OID " << oaep_hash_id.oid().to_string() << "\n";
×
155
            return set_return_code(1);
×
156
         }
157

158
         if(oaep_hash_id.parameters().empty() == false) {
1✔
159
            error_output() << "Unknown OAEP parameters used\n";
×
160
            return set_return_code(1);
×
161
         }
162

163
         std::unique_ptr<Botan::AEAD_Mode> aead =
1✔
164
            Botan::AEAD_Mode::create_or_throw(aead_algo, Botan::Cipher_Dir::Decryption);
1✔
165

166
         const size_t expected_keylen = aead->key_spec().maximum_keylength();
1✔
167

168
         Botan::PK_Decryptor_EME dec(*key, rng(), "OAEP(" + oaep_hash + ")");
2✔
169

170
         const Botan::secure_vector<uint8_t> file_key =
1✔
171
            dec.decrypt_or_random(encrypted_key.data(), encrypted_key.size(), expected_keylen, rng());
1✔
172

173
         aead->set_key(file_key);
1✔
174
         aead->set_associated_data(encrypted_key);
1✔
175
         aead->start(nonce);
1✔
176

177
         try {
1✔
178
            aead->finish(data);
1✔
179

180
            output().write(reinterpret_cast<const char*>(data.data()), data.size());
1✔
181
         } catch(Botan::Integrity_Failure&) {
×
182
            error_output() << "Message authentication failure, possible ciphertext tampering\n";
×
183
            return set_return_code(1);
×
184
         }
×
185
      }
6✔
186
};
187

188
BOTAN_REGISTER_COMMAND("pk_decrypt", PK_Decrypt);
2✔
189

190
}  // namespace
191

192
}  // namespace Botan_CLI
193

194
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc