Add early data input from file.

Change-Id: I93a54e7a67acddb196ed53ce7fe49c718553948d
Reviewed-on: https://boringssl-review.googlesource.com/23604
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/tool/client.cc b/tool/client.cc
index 57e1b6e..fa279ae 100644
--- a/tool/client.cc
+++ b/tool/client.cc
@@ -122,7 +122,8 @@
     },
     {
         "-early-data", kOptionalArgument, "Enable early data. The argument to "
-        "this flag is the early data to send.",
+        "this flag is the early data to send or if it starts with '@', the "
+        "file to read from for early data.",
     },
     {
         "-tls13-variant", kOptionalArgument,
@@ -299,8 +300,19 @@
   }
 
   if (args_map.count("-early-data") != 0 && SSL_in_early_data(ssl.get())) {
-    int ed_size = args_map["-early-data"].size();
-    int ssl_ret = SSL_write(ssl.get(), args_map["-early-data"].data(), ed_size);
+    std::string early_data = args_map["-early-data"];
+    if (early_data.size() > 0 && early_data[0] == '@') {
+      const char *filename = early_data.c_str() + 1;
+      std::vector<uint8_t> data;
+      ScopedFILE f(fopen(filename, "rb"));
+      if (f == nullptr || !ReadAll(&data, f.get())) {
+        fprintf(stderr, "Error reading %s.\n", filename);
+        return false;
+      }
+      early_data = std::string(data.begin(), data.end());
+    }
+    int ed_size = early_data.size();
+    int ssl_ret = SSL_write(ssl.get(), early_data.data(), ed_size);
     if (ssl_ret <= 0) {
       int ssl_err = SSL_get_error(ssl.get(), ssl_ret);
       fprintf(stderr, "Error while writing: %d\n", ssl_err);
diff --git a/tool/generate_ed25519.cc b/tool/generate_ed25519.cc
index 35b57b9..6499dbe 100644
--- a/tool/generate_ed25519.cc
+++ b/tool/generate_ed25519.cc
@@ -21,14 +21,6 @@
 #include "internal.h"
 
 
-struct FileCloser {
-  void operator()(FILE *file) {
-    fclose(file);
-  }
-};
-
-using ScopedFILE = std::unique_ptr<FILE, FileCloser>;
-
 static const struct argument kArguments[] = {
     {
         "-out-public", kRequiredArgument, "The file to write the public key to",
diff --git a/tool/internal.h b/tool/internal.h
index a6c8eca..b626270 100644
--- a/tool/internal.h
+++ b/tool/internal.h
@@ -44,6 +44,14 @@
   #define BORINGSSL_WRITE write
 #endif
 
+struct FileCloser {
+  void operator()(FILE *file) {
+    fclose(file);
+  }
+};
+
+using ScopedFILE = std::unique_ptr<FILE, FileCloser>;
+
 enum ArgumentType {
   kRequiredArgument,
   kOptionalArgument,
diff --git a/tool/server.cc b/tool/server.cc
index 63d77e9..9963885 100644
--- a/tool/server.cc
+++ b/tool/server.cc
@@ -91,14 +91,6 @@
     },
 };
 
-struct FileCloser {
-  void operator()(FILE *file) {
-    fclose(file);
-  }
-};
-
-using ScopedFILE = std::unique_ptr<FILE, FileCloser>;
-
 static bool LoadOCSPResponse(SSL_CTX *ctx, const char *filename) {
   ScopedFILE f(fopen(filename, "rb"));
   std::vector<uint8_t> data;