Introduce bssl::Array<T> and use it in SSLKeyShare.

An Array<T> is an owning Span<T>. It's similar to absl::FixedArray<T>
but plays well with OPENSSL_malloc and doesn't implement inlining. With
OPENSSL_cleanse folded into OPENSSL_free, we could go nuts with
UniquePtr<uint8_t>, but having the pointer and length tied together is
nice for other reasons. Notably, Array<T> plays great with Span<T>.

Also switch the other parameter to a Span.

Bug: 132
Change-Id: I4cdcf810cf2838208c8ba9fcc6215c1e369dffb8
Reviewed-on: https://boringssl-review.googlesource.com/20667
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/ssl/ssl_key_share.cc b/ssl/ssl_key_share.cc
index 207f11e..3ceb180 100644
--- a/ssl/ssl_key_share.cc
+++ b/ssl/ssl_key_share.cc
@@ -17,6 +17,8 @@
 #include <assert.h>
 #include <string.h>
 
+#include <utility>
+
 #include <openssl/bn.h>
 #include <openssl/bytestring.h>
 #include <openssl/curve25519.h>
@@ -71,8 +73,8 @@
     return true;
   }
 
-  bool Finish(uint8_t **out_secret, size_t *out_secret_len, uint8_t *out_alert,
-              const uint8_t *peer_key, size_t peer_key_len) override {
+  bool Finish(Array<uint8_t> *out_secret, uint8_t *out_alert,
+              Span<const uint8_t> peer_key) override {
     assert(private_key_);
     *out_alert = SSL_AD_INTERNAL_ERROR;
 
@@ -95,8 +97,8 @@
       return false;
     }
 
-    if (!EC_POINT_oct2point(group.get(), peer_point.get(), peer_key,
-                            peer_key_len, bn_ctx.get())) {
+    if (!EC_POINT_oct2point(group.get(), peer_point.get(), peer_key.data(),
+                            peer_key.size(), bn_ctx.get())) {
       *out_alert = SSL_AD_DECODE_ERROR;
       return false;
     }
@@ -110,14 +112,13 @@
     }
 
     // Encode the x-coordinate left-padded with zeros.
-    size_t secret_len = (EC_GROUP_get_degree(group.get()) + 7) / 8;
-    UniquePtr<uint8_t> secret((uint8_t *)OPENSSL_malloc(secret_len));
-    if (!secret || !BN_bn2bin_padded(secret.get(), secret_len, x)) {
+    Array<uint8_t> secret;
+    if (!secret.Init((EC_GROUP_get_degree(group.get()) + 7) / 8) ||
+        !BN_bn2bin_padded(secret.data(), secret.size(), x)) {
       return false;
     }
 
-    *out_secret = secret.release();
-    *out_secret_len = secret_len;
+    *out_secret = std::move(secret);
     return true;
   }
 
@@ -142,24 +143,24 @@
     return !!CBB_add_bytes(out, public_key, sizeof(public_key));
   }
 
-  bool Finish(uint8_t **out_secret, size_t *out_secret_len, uint8_t *out_alert,
-              const uint8_t *peer_key, size_t peer_key_len) override {
+  bool Finish(Array<uint8_t> *out_secret, uint8_t *out_alert,
+              Span<const uint8_t> peer_key) override {
     *out_alert = SSL_AD_INTERNAL_ERROR;
 
-    UniquePtr<uint8_t> secret((uint8_t *)OPENSSL_malloc(32));
-    if (!secret) {
+    Array<uint8_t> secret;
+    if (!secret.Init(32)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       return false;
     }
 
-    if (peer_key_len != 32 || !X25519(secret.get(), private_key_, peer_key)) {
+    if (peer_key.size() != 32 ||
+        !X25519(secret.data(), private_key_, peer_key.data())) {
       *out_alert = SSL_AD_DECODE_ERROR;
       OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
       return false;
     }
 
-    *out_secret = secret.release();
-    *out_secret_len = 32;
+    *out_secret = std::move(secret);
     return true;
   }
 
@@ -202,12 +203,11 @@
   }
 }
 
-bool SSLKeyShare::Accept(CBB *out_public_key, uint8_t **out_secret,
-                         size_t *out_secret_len, uint8_t *out_alert,
-                         const uint8_t *peer_key, size_t peer_key_len) {
+bool SSLKeyShare::Accept(CBB *out_public_key, Array<uint8_t> *out_secret,
+                         uint8_t *out_alert, Span<const uint8_t> peer_key) {
   *out_alert = SSL_AD_INTERNAL_ERROR;
   return Offer(out_public_key) &&
-         Finish(out_secret, out_secret_len, out_alert, peer_key, peer_key_len);
+         Finish(out_secret, out_alert, peer_key);
 }
 
 int ssl_nid_to_group_id(uint16_t *out_group_id, int nid) {