OpenBSD Support

Includes bits by me and Robert Nagy <robert.nagy@gmail.com> who has a
google CLA.

Update-Note: Additionally, BoringSSL now requires macOS 10.12 or later
for getentropy support. This is consistent with
https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md

WANT_LGTM=all

Change-Id: I5ab74fa8a6677fac29c316aa29a954df401ba647
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/59225
Commit-Queue: Bob Beck <bbe@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt
index cdb5ddc..bc30702 100644
--- a/crypto/CMakeLists.txt
+++ b/crypto/CMakeLists.txt
@@ -126,10 +126,12 @@
   conf/conf.c
   cpu_aarch64_apple.c
   cpu_aarch64_freebsd.c
+  cpu_aarch64_openbsd.c
   cpu_aarch64_fuchsia.c
   cpu_aarch64_linux.c
   cpu_aarch64_win.c
   cpu_arm_freebsd.c
+  cpu_arm_openbsd.c
   cpu_arm_linux.c
   cpu_arm.c
   cpu_intel.c
diff --git a/crypto/cpu_aarch64_openbsd.c b/crypto/cpu_aarch64_openbsd.c
new file mode 100644
index 0000000..be271f2
--- /dev/null
+++ b/crypto/cpu_aarch64_openbsd.c
@@ -0,0 +1,62 @@
+/* Copyright (c) 2022, Robert Nagy <robert.nagy@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/cpu.h>
+
+#if defined(OPENSSL_AARCH64) && defined(OPENSSL_OPENBSD) && \
+    !defined(OPENSSL_STATIC_ARMCAP)
+
+#include <sys/sysctl.h>
+#include <machine/cpu.h>
+#include <machine/armreg.h>
+
+#include <openssl/arm_arch.h>
+
+#include "internal.h"
+
+extern uint32_t OPENSSL_armcap_P;
+
+void OPENSSL_cpuid_setup(void) {
+  int isar0_mib[] = { CTL_MACHDEP, CPU_ID_AA64ISAR0 };
+  uint64_t cpu_id = 0;
+  size_t len = sizeof(cpu_id);
+
+  if (sysctl(isar0_mib, 2, &cpu_id, &len, NULL, 0) < 0) {
+    return;
+  }
+
+  OPENSSL_armcap_P |= ARMV7_NEON;
+
+  if (ID_AA64ISAR0_AES(cpu_id) >= ID_AA64ISAR0_AES_BASE) {
+    OPENSSL_armcap_P |= ARMV8_AES;
+  }
+
+  if (ID_AA64ISAR0_AES(cpu_id) >= ID_AA64ISAR0_AES_PMULL) {
+    OPENSSL_armcap_P |= ARMV8_PMULL;
+  }
+
+  if (ID_AA64ISAR0_SHA1(cpu_id) >= ID_AA64ISAR0_SHA1_BASE) {
+    OPENSSL_armcap_P |= ARMV8_SHA1;
+  }
+
+  if (ID_AA64ISAR0_SHA2(cpu_id) >= ID_AA64ISAR0_SHA2_BASE) {
+    OPENSSL_armcap_P |= ARMV8_SHA256;
+  }
+
+  if (ID_AA64ISAR0_SHA2(cpu_id) >= ID_AA64ISAR0_SHA2_512) {
+    OPENSSL_armcap_P |= ARMV8_SHA512;
+  }
+}
+
+#endif  // OPENSSL_AARCH64 && OPENSSL_OPENBSD && !OPENSSL_STATIC_ARMCAP
diff --git a/crypto/cpu_arm_openbsd.c b/crypto/cpu_arm_openbsd.c
new file mode 100644
index 0000000..c3463c7
--- /dev/null
+++ b/crypto/cpu_arm_openbsd.c
@@ -0,0 +1,31 @@
+/* Copyright (c) 2023, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include "internal.h"
+
+#if defined(OPENSSL_ARM) && defined(OPENSSL_OPENBSD) && \
+    !defined(OPENSSL_STATIC_ARMCAP)
+
+#include <openssl/arm_arch.h>
+
+extern uint32_t OPENSSL_armcap_P;
+
+void OPENSSL_cpuid_setup(void) {
+  // OpenBSD does not support arm32 machines without NEON
+  OPENSSL_armcap_P |= ARMV7_NEON;
+
+  // OpenBSD does not support v8 features on non aarch64
+}
+
+#endif  // OPENSSL_ARM && OPENSSL_OPENBSD && !OPENSSL_STATIC_ARMCAP
diff --git a/crypto/fipsmodule/rand/urandom.c b/crypto/fipsmodule/rand/urandom.c
index 77dad74..a3fb15b 100644
--- a/crypto/fipsmodule/rand/urandom.c
+++ b/crypto/fipsmodule/rand/urandom.c
@@ -59,9 +59,15 @@
 #endif  // OPENSSL_LINUX
 
 #if defined(OPENSSL_MACOS)
+// getentropy exists in any supported version of MacOS (Sierra and later)
 #include <sys/random.h>
 #endif
 
+#if defined(OPENSSL_OPENBSD)
+// getentropy exists in any supported version of OpenBSD
+#include <unistd.h>
+#endif
+
 #if defined(OPENSSL_FREEBSD) && __FreeBSD__ >= 12
 // getrandom is supported in FreeBSD 12 and up.
 #define FREEBSD_GETRANDOM
@@ -173,18 +179,9 @@
   }
 #endif  // USE_NR_getrandom
 
-#if defined(OPENSSL_MACOS)
-  // getentropy is available in macOS 10.12 and up. iOS 10 and up may also
-  // support it, but the header is missing. See https://crbug.com/boringssl/287.
-  if (__builtin_available(macos 10.12, *)) {
+#if defined(OPENSSL_MACOS) || defined(OPENSSL_OPENBSD) || defined(FREEBSD_GETRANDOM)
     *urandom_fd_bss_get() = kHaveGetrandom;
     return;
-  }
-#endif
-
-#if defined(FREEBSD_GETRANDOM)
-  *urandom_fd_bss_get() = kHaveGetrandom;
-  return;
 #endif
 
   // FIPS builds must support getrandom.
@@ -300,19 +297,10 @@
       r = boringssl_getrandom(out, len, getrandom_flags);
 #elif defined(FREEBSD_GETRANDOM)
       r = getrandom(out, len, getrandom_flags);
-#elif defined(OPENSSL_MACOS)
-      if (__builtin_available(macos 10.12, *)) {
-        // |getentropy| can only request 256 bytes at a time.
-        size_t todo = len <= 256 ? len : 256;
-        if (getentropy(out, todo) != 0) {
-          r = -1;
-        } else {
-          r = (ssize_t)todo;
-        }
-      } else {
-        fprintf(stderr, "urandom fd corrupt.\n");
-        abort();
-      }
+#elif defined(OPENSSL_MACOS) || defined(OPENSSL_OPENBSD)
+      // |getentropy| can only request 256 bytes at a time.
+      size_t todo = len <= 256 ? len : 256;
+      r = getentropy(out, todo) != 0 ? -1 : (ssize_t)todo;
 #else  // USE_NR_getrandom
       fprintf(stderr, "urandom fd corrupt.\n");
       abort();
diff --git a/include/openssl/base.h b/include/openssl/base.h
index 67429c0..3141676 100644
--- a/include/openssl/base.h
+++ b/include/openssl/base.h
@@ -164,6 +164,10 @@
 #define OPENSSL_FREEBSD
 #endif
 
+#if defined(__OpenBSD__)
+#define OPENSSL_OPENBSD
+#endif
+
 // BoringSSL requires platform's locking APIs to make internal global state
 // thread-safe, including the PRNG. On some single-threaded embedded platforms,
 // locking APIs may not exist, so this dependency may be disabled with the
diff --git a/include/openssl/thread.h b/include/openssl/thread.h
index c6e357e..afa9f08 100644
--- a/include/openssl/thread.h
+++ b/include/openssl/thread.h
@@ -78,6 +78,10 @@
   void *handle;
 } CRYPTO_MUTEX;
 #elif !defined(__GLIBC__)
+#if defined(OPENSSL_OPENBSD)
+// OpenBSD does not guarantee pthread_rwlock_t in sys/types.h yet.
+#include <pthread.h>
+#endif
 typedef pthread_rwlock_t CRYPTO_MUTEX;
 #else
 // On glibc, |pthread_rwlock_t| is hidden under feature flags, and we can't
diff --git a/third_party/googletest/METADATA b/third_party/googletest/METADATA
index 5674bcc..c5156cf 100644
--- a/third_party/googletest/METADATA
+++ b/third_party/googletest/METADATA
@@ -12,4 +12,5 @@
   local_modifications:
       "Only googletest, not googlemock, is included."
       "Applied https://github.com/google/googletest/pull/3206."
+      "Applied cl/529512111"
 }
diff --git a/third_party/googletest/src/gtest-port.cc b/third_party/googletest/src/gtest-port.cc
index 3f39f71..fcac44c 100644
--- a/third_party/googletest/src/gtest-port.cc
+++ b/third_party/googletest/src/gtest-port.cc
@@ -202,8 +202,8 @@
   mib[5] = static_cast<int>(size / static_cast<size_t>(mib[4]));
 
   // populate array of structs
-  struct kinfo_proc info[mib[5]];
-  if (sysctl(mib, miblen, &info, &size, NULL, 0)) {
+  std::vector<struct kinfo_proc> info(mib[5]);
+  if (sysctl(mib, miblen, info.data(), &size, NULL, 0)) {
     return 0;
   }