The unified diff between revisions [869f0c37..] and [e24ccc23..] is displayed below. It can also be downloaded as a raw diff.

This diff has been restricted to the following files: 'keys.cc'

#
#
# patch "keys.cc"
#  from [a4ccef56d24ee9cda7a009144f5476e3cdcb07d7]
#    to [9c50dc0d669ffb6ad2328c46485bf3ae65dad4b5]
#
============================================================
--- keys.cc	a4ccef56d24ee9cda7a009144f5476e3cdcb07d7
+++ keys.cc	9c50dc0d669ffb6ad2328c46485bf3ae65dad4b5
@@ -166,7 +166,21 @@ write_der(T & val, SecByteBlock & sec)
     der_encoded[i] = '\0';
 }

+static bool
+blocking_rng(lua_hooks & lua)
+{
+  if (!lua.hook_non_blocking_rng_ok())
+    {
+#ifndef BLOCKING_RNG_AVAILABLE
+      throw oops("no blocking RNG available and non-blocking RNG rejected");
+#else
+      return true;
+#endif
+    };
+  return false;
+}

+
 void
 generate_key_pair(lua_hooks & lua,              // to hook for phrase
                   rsa_keypair_id const & id,    // to prompting user for phrase
@@ -176,17 +190,7 @@ generate_key_pair(lua_hooks & lua,
 {
   // we will panic here if the user doesn't like urandom and we can't give
   // them a real entropy-driven random.
-  bool request_blocking_rng = false;
-  if (!lua.hook_non_blocking_rng_ok())
-    {
-#ifndef BLOCKING_RNG_AVAILABLE
-      throw oops("no blocking RNG available and non-blocking RNG rejected");
-#else
-      request_blocking_rng = true;
-#endif
-    }
-
-  AutoSeededRandomPool rng(request_blocking_rng);
+  AutoSeededRandomPool rng(blocking_rng(lua));
   SecByteBlock phrase, pubkey, privkey;
   rsa_pub_key raw_pub_key;
   arc4<rsa_priv_key> raw_priv_key;
@@ -267,16 +271,7 @@ make_signature(lua_hooks & lua,

   // we will panic here if the user doesn't like urandom and we can't give
   // them a real entropy-driven random.
-  bool request_blocking_rng = false;
-  if (!lua.hook_non_blocking_rng_ok())
-    {
-#ifndef BLOCKING_RNG_AVAILABLE
-      throw oops("no blocking RNG available and non-blocking RNG rejected");
-#else
-      request_blocking_rng = true;
-#endif
-    }
-  AutoSeededRandomPool rng(request_blocking_rng);
+  AutoSeededRandomPool rng(blocking_rng(lua));

   // we permit the user to relax security here, by caching a decrypted key
   // (if they permit it) through the life of a program run. this helps when
@@ -396,6 +391,75 @@ check_signature(lua_hooks & lua,
   return vf->GetLastResult();
 }

+void encrypt_rsa(lua_hooks & lua,
+                 rsa_keypair_id const & id,
+                 base64<rsa_pub_key> & pub_encoded,
+                 std::string const & plaintext,
+                 rsa_oaep_sha_data & ciphertext)
+{
+  AutoSeededRandomPool rng(blocking_rng(lua));
+
+  rsa_pub_key pub;
+  decode_base64(pub_encoded, pub);
+  SecByteBlock pub_block;
+  pub_block.Assign(reinterpret_cast<byte const *>(pub().data()), pub().size());
+  StringSource keysource(pub_block.data(), pub_block.size(), true);
+
+  shared_ptr<RSAES_OAEP_SHA_Encryptor> encryptor;
+  encryptor = shared_ptr<RSAES_OAEP_SHA_Encryptor>
+    (new RSAES_OAEP_SHA_Encryptor(keysource));
+
+  string ciphertext_string;
+  StringSource tmp(plaintext, true,
+                   encryptor->CreateEncryptionFilter
+                   (rng, new StringSink(ciphertext_string)));
+
+  ciphertext = rsa_oaep_sha_data(ciphertext_string);
+}
+
+void decrypt_rsa(lua_hooks & lua,
+                 rsa_keypair_id const & id,
+                 base64< arc4<rsa_priv_key> > const & priv,
+                 rsa_oaep_sha_data const & ciphertext,
+                 std::string & plaintext)
+{
+  AutoSeededRandomPool rng(blocking_rng(lua));
+  arc4<rsa_priv_key> decoded_key;
+  SecByteBlock decrypted_key;
+  SecByteBlock phrase;
+  shared_ptr<RSAES_OAEP_SHA_Decryptor> decryptor;
+
+  for (int i = 0; i < 3; i++)
+    {
+      bool force = false;
+      decode_base64(priv, decoded_key);
+      decrypted_key.Assign(reinterpret_cast<byte const *>(decoded_key().data()),
+                           decoded_key().size());
+      get_passphrase(lua, id, phrase, false, force);
+
+      try
+        {
+          do_arc4(phrase, decrypted_key);
+          StringSource keysource(decrypted_key.data(), decrypted_key.size(), true);
+          decryptor = shared_ptr<RSAES_OAEP_SHA_Decryptor>
+            (new RSAES_OAEP_SHA_Decryptor(keysource));
+        }
+      catch (...)
+        {
+          if (i >= 2)
+            throw informative_failure("failed to decrypt private RSA key, "
+                                      "probably incorrect passphrase");
+          // don't use the cache bad one next time
+          force = true;
+          continue;
+        }
+    }
+
+  StringSource tmp(ciphertext(), true,
+                   decryptor->CreateDecryptionFilter
+                   (rng, new StringSink(plaintext)));
+}
+
 void
 read_pubkey(string const & in,
             rsa_keypair_id & id,