Move bn/ into crypto/fipsmodule/

Change-Id: I68aa4a740ee1c7f2a308a6536f408929f15b694c
Reviewed-on: https://boringssl-review.googlesource.com/15647
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9b7ff79..167a8fe 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -34,6 +34,10 @@
   set(C_CXX_FLAGS "-Wall -Werror -Wformat=2 -Wsign-compare -Wmissing-field-initializers -Wwrite-strings -ggdb -fvisibility=hidden -fno-common")
   if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
     set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wnewline-eof")
+  else()
+    # GCC (at least 4.8.4) has a bug where it'll find unreachable free() calls
+    # and declare that the code is trying to free a stack pointer.
+    set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wno-free-nonheap-object")
   endif()
   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_CXX_FLAGS} -Wmissing-prototypes -Wold-style-definition -Wstrict-prototypes")
   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${C_CXX_FLAGS} -Wmissing-declarations")
diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt
index 5996577..ccc3914 100644
--- a/crypto/CMakeLists.txt
+++ b/crypto/CMakeLists.txt
@@ -92,7 +92,7 @@
 add_subdirectory(cipher)
 add_subdirectory(rand_extra)
 add_subdirectory(bio)
-add_subdirectory(bn)
+add_subdirectory(bn_extra)
 add_subdirectory(obj)
 add_subdirectory(asn1)
 
@@ -175,7 +175,7 @@
   $<TARGET_OBJECTS:poly1305>
   $<TARGET_OBJECTS:curve25519>
   $<TARGET_OBJECTS:buf>
-  $<TARGET_OBJECTS:bn>
+  $<TARGET_OBJECTS:bn_extra>
   $<TARGET_OBJECTS:bio>
   $<TARGET_OBJECTS:rand_extra>
   $<TARGET_OBJECTS:obj>
diff --git a/crypto/bn/CMakeLists.txt b/crypto/bn/CMakeLists.txt
deleted file mode 100644
index 5da72e9..0000000
--- a/crypto/bn/CMakeLists.txt
+++ /dev/null
@@ -1,87 +0,0 @@
-include_directories(../../include)
-
-if (${ARCH} STREQUAL "x86_64")
-  set(
-    BN_ARCH_SOURCES
-
-    x86_64-mont.${ASM_EXT}
-    x86_64-mont5.${ASM_EXT}
-    rsaz-avx2.${ASM_EXT}
-
-    rsaz_exp.c
-  )
-endif()
-
-if (${ARCH} STREQUAL "x86")
-  set(
-    BN_ARCH_SOURCES
-
-    bn-586.${ASM_EXT}
-    co-586.${ASM_EXT}
-    x86-mont.${ASM_EXT}
-  )
-endif()
-
-if (${ARCH} STREQUAL "arm")
-  set(
-    BN_ARCH_SOURCES
-
-    armv4-mont.${ASM_EXT}
-  )
-endif()
-
-if (${ARCH} STREQUAL "aarch64")
-  set(
-    BN_ARCH_SOURCES
-
-    armv8-mont.${ASM_EXT}
-  )
-endif()
-
-add_library(
-  bn
-
-  OBJECT
-
-  add.c
-  asm/x86_64-gcc.c
-  bn.c
-  bn_asn1.c
-  cmp.c
-  convert.c
-  ctx.c
-  div.c
-  exponentiation.c
-  generic.c
-  gcd.c
-  jacobi.c
-  montgomery.c
-  montgomery_inv.c
-  mul.c
-  prime.c
-  random.c
-  shift.c
-  sqrt.c
-
-  ${BN_ARCH_SOURCES}
-)
-
-perlasm(x86_64-mont.${ASM_EXT} asm/x86_64-mont.pl)
-perlasm(x86_64-mont5.${ASM_EXT} asm/x86_64-mont5.pl)
-perlasm(rsaz-avx2.${ASM_EXT} asm/rsaz-avx2.pl)
-perlasm(bn-586.${ASM_EXT} asm/bn-586.pl)
-perlasm(co-586.${ASM_EXT} asm/co-586.pl)
-perlasm(x86-mont.${ASM_EXT} asm/x86-mont.pl)
-perlasm(armv4-mont.${ASM_EXT} asm/armv4-mont.pl)
-perlasm(armv8-mont.${ASM_EXT} asm/armv8-mont.pl)
-
-add_executable(
-  bn_test
-
-  bn_test.cc
-
-  $<TARGET_OBJECTS:test_support>
-)
-
-target_link_libraries(bn_test crypto)
-add_dependencies(all_tests bn_test)
diff --git a/crypto/bn_extra/CMakeLists.txt b/crypto/bn_extra/CMakeLists.txt
new file mode 100644
index 0000000..994b365
--- /dev/null
+++ b/crypto/bn_extra/CMakeLists.txt
@@ -0,0 +1,10 @@
+include_directories(../../include)
+
+add_library(
+  bn_extra
+
+  OBJECT
+
+  bn_asn1.c
+  convert.c
+)
diff --git a/crypto/bn/bn_asn1.c b/crypto/bn_extra/bn_asn1.c
similarity index 100%
rename from crypto/bn/bn_asn1.c
rename to crypto/bn_extra/bn_asn1.c
diff --git a/crypto/bn/convert.c b/crypto/bn_extra/convert.c
similarity index 68%
rename from crypto/bn/convert.c
rename to crypto/bn_extra/convert.c
index 5b077a8..b48a971 100644
--- a/crypto/bn/convert.c
+++ b/crypto/bn_extra/convert.c
@@ -60,191 +60,14 @@
 #include <ctype.h>
 #include <limits.h>
 #include <stdio.h>
-#include <string.h>
 
 #include <openssl/bio.h>
 #include <openssl/bytestring.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
-#include "internal.h"
+#include "../fipsmodule/bn/internal.h"
 
-BIGNUM *BN_bin2bn(const uint8_t *in, size_t len, BIGNUM *ret) {
-  size_t num_words;
-  unsigned m;
-  BN_ULONG word = 0;
-  BIGNUM *bn = NULL;
-
-  if (ret == NULL) {
-    ret = bn = BN_new();
-  }
-
-  if (ret == NULL) {
-    return NULL;
-  }
-
-  if (len == 0) {
-    ret->top = 0;
-    return ret;
-  }
-
-  num_words = ((len - 1) / BN_BYTES) + 1;
-  m = (len - 1) % BN_BYTES;
-  if (!bn_wexpand(ret, num_words)) {
-    if (bn) {
-      BN_free(bn);
-    }
-    return NULL;
-  }
-
-  /* |bn_wexpand| must check bounds on |num_words| to write it into
-   * |ret->dmax|. */
-  assert(num_words <= INT_MAX);
-  ret->top = (int)num_words;
-  ret->neg = 0;
-
-  while (len--) {
-    word = (word << 8) | *(in++);
-    if (m-- == 0) {
-      ret->d[--num_words] = word;
-      word = 0;
-      m = BN_BYTES - 1;
-    }
-  }
-
-  /* need to call this due to clear byte at top if avoiding having the top bit
-   * set (-ve number) */
-  bn_correct_top(ret);
-  return ret;
-}
-
-BIGNUM *BN_le2bn(const uint8_t *in, size_t len, BIGNUM *ret) {
-  BIGNUM *bn = NULL;
-  if (ret == NULL) {
-    bn = BN_new();
-    ret = bn;
-  }
-
-  if (ret == NULL) {
-    return NULL;
-  }
-
-  if (len == 0) {
-    ret->top = 0;
-    ret->neg = 0;
-    return ret;
-  }
-
-  /* Reserve enough space in |ret|. */
-  size_t num_words = ((len - 1) / BN_BYTES) + 1;
-  if (!bn_wexpand(ret, num_words)) {
-    BN_free(bn);
-    return NULL;
-  }
-  ret->top = num_words;
-
-  /* Make sure the top bytes will be zeroed. */
-  ret->d[num_words - 1] = 0;
-
-  /* We only support little-endian platforms, so we can simply memcpy the
-   * internal representation. */
-  OPENSSL_memcpy(ret->d, in, len);
-
-  bn_correct_top(ret);
-  return ret;
-}
-
-size_t BN_bn2bin(const BIGNUM *in, uint8_t *out) {
-  size_t n, i;
-  BN_ULONG l;
-
-  n = i = BN_num_bytes(in);
-  while (i--) {
-    l = in->d[i / BN_BYTES];
-    *(out++) = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff;
-  }
-  return n;
-}
-
-int BN_bn2le_padded(uint8_t *out, size_t len, const BIGNUM *in) {
-  /* If we don't have enough space, fail out. */
-  size_t num_bytes = BN_num_bytes(in);
-  if (len < num_bytes) {
-    return 0;
-  }
-
-  /* We only support little-endian platforms, so we can simply memcpy into the
-   * internal representation. */
-  OPENSSL_memcpy(out, in->d, num_bytes);
-
-  /* Pad out the rest of the buffer with zeroes. */
-  OPENSSL_memset(out + num_bytes, 0, len - num_bytes);
-
-  return 1;
-}
-
-/* constant_time_select_ulong returns |x| if |v| is 1 and |y| if |v| is 0. Its
- * behavior is undefined if |v| takes any other value. */
-static BN_ULONG constant_time_select_ulong(int v, BN_ULONG x, BN_ULONG y) {
-  BN_ULONG mask = v;
-  mask--;
-
-  return (~mask & x) | (mask & y);
-}
-
-/* constant_time_le_size_t returns 1 if |x| <= |y| and 0 otherwise. |x| and |y|
- * must not have their MSBs set. */
-static int constant_time_le_size_t(size_t x, size_t y) {
-  return ((x - y - 1) >> (sizeof(size_t) * 8 - 1)) & 1;
-}
-
-/* read_word_padded returns the |i|'th word of |in|, if it is not out of
- * bounds. Otherwise, it returns 0. It does so without branches on the size of
- * |in|, however it necessarily does not have the same memory access pattern. If
- * the access would be out of bounds, it reads the last word of |in|. |in| must
- * not be zero. */
-static BN_ULONG read_word_padded(const BIGNUM *in, size_t i) {
-  /* Read |in->d[i]| if valid. Otherwise, read the last word. */
-  BN_ULONG l = in->d[constant_time_select_ulong(
-      constant_time_le_size_t(in->dmax, i), in->dmax - 1, i)];
-
-  /* Clamp to zero if above |d->top|. */
-  return constant_time_select_ulong(constant_time_le_size_t(in->top, i), 0, l);
-}
-
-int BN_bn2bin_padded(uint8_t *out, size_t len, const BIGNUM *in) {
-  /* Special case for |in| = 0. Just branch as the probability is negligible. */
-  if (BN_is_zero(in)) {
-    OPENSSL_memset(out, 0, len);
-    return 1;
-  }
-
-  /* Check if the integer is too big. This case can exit early in non-constant
-   * time. */
-  if ((size_t)in->top > (len + (BN_BYTES - 1)) / BN_BYTES) {
-    return 0;
-  }
-  if ((len % BN_BYTES) != 0) {
-    BN_ULONG l = read_word_padded(in, len / BN_BYTES);
-    if (l >> (8 * (len % BN_BYTES)) != 0) {
-      return 0;
-    }
-  }
-
-  /* Write the bytes out one by one. Serialization is done without branching on
-   * the bits of |in| or on |in->top|, but if the routine would otherwise read
-   * out of bounds, the memory access pattern can't be fixed. However, for an
-   * RSA key of size a multiple of the word size, the probability of BN_BYTES
-   * leading zero octets is low.
-   *
-   * See Falko Stenzke, "Manger's Attack revisited", ICICS 2010. */
-  size_t i = len;
-  while (i--) {
-    BN_ULONG l = read_word_padded(in, i / BN_BYTES);
-    *(out++) = (uint8_t)(l >> (8 * (i % BN_BYTES))) & 0xff;
-  }
-  return 1;
-}
 
 int BN_bn2cbb_padded(CBB *out, size_t len, const BIGNUM *in) {
   uint8_t *ptr;
@@ -557,34 +380,6 @@
   return ret;
 }
 
-BN_ULONG BN_get_word(const BIGNUM *bn) {
-  switch (bn->top) {
-    case 0:
-      return 0;
-    case 1:
-      return bn->d[0];
-    default:
-      return BN_MASK2;
-  }
-}
-
-int BN_get_u64(const BIGNUM *bn, uint64_t *out) {
-  switch (bn->top) {
-    case 0:
-      *out = 0;
-      return 1;
-    case 1:
-      *out = bn->d[0];
-      return 1;
-#if defined(OPENSSL_32_BIT)
-    case 2:
-      *out = (uint64_t) bn->d[0] | (((uint64_t) bn->d[1]) << 32);
-      return 1;
-#endif
-    default:
-      return 0;
-  }
-}
 
 size_t BN_bn2mpi(const BIGNUM *in, uint8_t *out) {
   const size_t bits = BN_num_bits(in);
diff --git a/crypto/dh/params.c b/crypto/dh/params.c
index 4cec700..8f65bd3 100644
--- a/crypto/dh/params.c
+++ b/crypto/dh/params.c
@@ -54,7 +54,7 @@
 
 #include <openssl/bn.h>
 
-#include "../bn/internal.h"
+#include "../fipsmodule/bn/internal.h"
 
 
 static const BN_ULONG dh1024_160_p[] = {
diff --git a/crypto/dsa/dsa.c b/crypto/dsa/dsa.c
index e2b6695..a0d45bf 100644
--- a/crypto/dsa/dsa.c
+++ b/crypto/dsa/dsa.c
@@ -72,7 +72,7 @@
 #include <openssl/sha.h>
 #include <openssl/thread.h>
 
-#include "../bn/internal.h"
+#include "../fipsmodule/bn/internal.h"
 #include "../internal.h"
 
 
diff --git a/crypto/ec/ec_montgomery.c b/crypto/ec/ec_montgomery.c
index 4643fd2..2873cbb 100644
--- a/crypto/ec/ec_montgomery.c
+++ b/crypto/ec/ec_montgomery.c
@@ -71,7 +71,7 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
-#include "../bn/internal.h"
+#include "../fipsmodule/bn/internal.h"
 #include "internal.h"
 
 
diff --git a/crypto/ec/p256-x86_64.c b/crypto/ec/p256-x86_64.c
index 652d10c..ff23d08 100644
--- a/crypto/ec/p256-x86_64.c
+++ b/crypto/ec/p256-x86_64.c
@@ -30,7 +30,7 @@
 #include <openssl/crypto.h>
 #include <openssl/err.h>
 
-#include "../bn/internal.h"
+#include "../fipsmodule/bn/internal.h"
 #include "../internal.h"
 #include "internal.h"
 #include "p256-x86_64.h"
diff --git a/crypto/ec/p256-x86_64_test.cc b/crypto/ec/p256-x86_64_test.cc
index afc3b54..ad86f82 100644
--- a/crypto/ec/p256-x86_64_test.cc
+++ b/crypto/ec/p256-x86_64_test.cc
@@ -24,7 +24,7 @@
 #include <openssl/bn.h>
 #include <openssl/mem.h>
 
-#include "../bn/internal.h"
+#include "../fipsmodule/bn/internal.h"
 #include "../test/file_test.h"
 #include "p256-x86_64.h"
 
diff --git a/crypto/ecdsa/ecdsa.c b/crypto/ecdsa/ecdsa.c
index 99b1177..f83e05d 100644
--- a/crypto/ecdsa/ecdsa.c
+++ b/crypto/ecdsa/ecdsa.c
@@ -60,7 +60,7 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
-#include "../bn/internal.h"
+#include "../fipsmodule/bn/internal.h"
 #include "../ec/internal.h"
 #include "../internal.h"
 
diff --git a/crypto/fipsmodule/CMakeLists.txt b/crypto/fipsmodule/CMakeLists.txt
index fcda1db..c7cfcf6 100644
--- a/crypto/fipsmodule/CMakeLists.txt
+++ b/crypto/fipsmodule/CMakeLists.txt
@@ -11,10 +11,13 @@
     ghash-x86_64.${ASM_EXT}
     md5-x86_64.${ASM_EXT}
     rdrand-x86_64.${ASM_EXT}
+    rsaz-avx2.${ASM_EXT}
     sha1-x86_64.${ASM_EXT}
     sha256-x86_64.${ASM_EXT}
     sha512-x86_64.${ASM_EXT}
     vpaes-x86_64.${ASM_EXT}
+    x86_64-mont5.${ASM_EXT}
+    x86_64-mont.${ASM_EXT}
   )
 endif()
 
@@ -24,12 +27,15 @@
 
     aes-586.${ASM_EXT}
     aesni-x86.${ASM_EXT}
+    bn-586.${ASM_EXT}
+    co-586.${ASM_EXT}
     ghash-x86.${ASM_EXT}
     md5-586.${ASM_EXT}
     sha1-586.${ASM_EXT}
     sha256-586.${ASM_EXT}
     sha512-586.${ASM_EXT}
     vpaes-x86.${ASM_EXT}
+    x86-mont.${ASM_EXT}
   )
 endif()
 
@@ -39,6 +45,7 @@
 
     aes-armv4.${ASM_EXT}
     aesv8-armx.${ASM_EXT}
+    armv4-mont.${ASM_EXT}
     bsaes-armv7.${ASM_EXT}
     ghash-armv4.${ASM_EXT}
     ghashv8-armx.${ASM_EXT}
@@ -53,6 +60,7 @@
     BCM_ASM_SOURCES
 
     aesv8-armx.${ASM_EXT}
+    armv8-mont.${ASM_EXT}
     ghashv8-armx.${ASM_EXT}
     sha1-armv8.${ASM_EXT}
     sha256-armv8.${ASM_EXT}
@@ -77,8 +85,12 @@
 perlasm(aesp8-ppc.${ASM_EXT} aes/asm/aesp8-ppc.pl)
 perlasm(aesv8-armx.${ASM_EXT} aes/asm/aesv8-armx.pl)
 perlasm(aes-x86_64.${ASM_EXT} aes/asm/aes-x86_64.pl)
+perlasm(armv4-mont.${ASM_EXT} bn/asm/armv4-mont.pl)
+perlasm(armv8-mont.${ASM_EXT} bn/asm/armv8-mont.pl)
+perlasm(bn-586.${ASM_EXT} bn/asm/bn-586.pl)
 perlasm(bsaes-armv7.${ASM_EXT} aes/asm/bsaes-armv7.pl)
 perlasm(bsaes-x86_64.${ASM_EXT} aes/asm/bsaes-x86_64.pl)
+perlasm(co-586.${ASM_EXT} bn/asm/co-586.pl)
 perlasm(ghash-armv4.${ASM_EXT} modes/asm/ghash-armv4.pl)
 perlasm(ghashp8-ppc.${ASM_EXT} modes/asm/ghashp8-ppc.pl)
 perlasm(ghashv8-armx.${ASM_EXT} modes/asm/ghashv8-armx.pl)
@@ -87,6 +99,7 @@
 perlasm(md5-586.${ASM_EXT} md5/asm/md5-586.pl)
 perlasm(md5-x86_64.${ASM_EXT} md5/asm/md5-x86_64.pl)
 perlasm(rdrand-x86_64.${ASM_EXT} rand/asm/rdrand-x86_64.pl)
+perlasm(rsaz-avx2.${ASM_EXT} bn/asm/rsaz-avx2.pl)
 perlasm(sha1-586.${ASM_EXT} sha/asm/sha1-586.pl)
 perlasm(sha1-armv4-large.${ASM_EXT} sha/asm/sha1-armv4-large.pl)
 perlasm(sha1-armv8.${ASM_EXT} sha/asm/sha1-armv8.pl)
@@ -101,6 +114,9 @@
 perlasm(sha512-x86_64.${ASM_EXT} sha/asm/sha512-x86_64.pl)
 perlasm(vpaes-x86_64.${ASM_EXT} aes/asm/vpaes-x86_64.pl)
 perlasm(vpaes-x86.${ASM_EXT} aes/asm/vpaes-x86.pl)
+perlasm(x86_64-mont5.${ASM_EXT} bn/asm/x86_64-mont5.pl)
+perlasm(x86_64-mont.${ASM_EXT} bn/asm/x86_64-mont.pl)
+perlasm(x86-mont.${ASM_EXT} bn/asm/x86-mont.pl)
 
 if(FIPS)
   add_library(
@@ -187,6 +203,17 @@
 add_dependencies(all_tests aes_test)
 
 add_executable(
+  bn_test
+
+  bn/bn_test.cc
+
+  $<TARGET_OBJECTS:test_support>
+)
+
+target_link_libraries(bn_test crypto)
+add_dependencies(all_tests bn_test)
+
+add_executable(
   gcm_test
 
   modes/gcm_test.cc
diff --git a/crypto/fipsmodule/bcm.c b/crypto/fipsmodule/bcm.c
index e90f0a4..bd55bde 100644
--- a/crypto/fipsmodule/bcm.c
+++ b/crypto/fipsmodule/bcm.c
@@ -34,6 +34,25 @@
 #include "aes/aes.c"
 #include "aes/key_wrap.c"
 #include "aes/mode_wrappers.c"
+#include "bn/add.c"
+#include "bn/asm/x86_64-gcc.c"
+#include "bn/bn.c"
+#include "bn/bytes.c"
+#include "bn/cmp.c"
+#include "bn/ctx.c"
+#include "bn/div.c"
+#include "bn/exponentiation.c"
+#include "bn/gcd.c"
+#include "bn/generic.c"
+#include "bn/jacobi.c"
+#include "bn/montgomery.c"
+#include "bn/montgomery_inv.c"
+#include "bn/mul.c"
+#include "bn/prime.c"
+#include "bn/random.c"
+#include "bn/rsaz_exp.c"
+#include "bn/shift.c"
+#include "bn/sqrt.c"
 #include "digest/digest.c"
 #include "digest/digests.c"
 #include "hmac/hmac.c"
diff --git a/crypto/bn/add.c b/crypto/fipsmodule/bn/add.c
similarity index 100%
rename from crypto/bn/add.c
rename to crypto/fipsmodule/bn/add.c
diff --git a/crypto/bn/asm/armv4-mont.pl b/crypto/fipsmodule/bn/asm/armv4-mont.pl
similarity index 99%
rename from crypto/bn/asm/armv4-mont.pl
rename to crypto/fipsmodule/bn/asm/armv4-mont.pl
index d7298d2..acda9e5 100644
--- a/crypto/bn/asm/armv4-mont.pl
+++ b/crypto/fipsmodule/bn/asm/armv4-mont.pl
@@ -45,7 +45,7 @@
 if ($flavour && $flavour ne "void") {
     $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
     ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
-    ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+    ( $xlate="${dir}../../../perlasm/arm-xlate.pl" and -f $xlate) or
     die "can't locate arm-xlate.pl";
 
     open STDOUT,"| \"$^X\" $xlate $flavour $output";
diff --git a/crypto/bn/asm/armv8-mont.pl b/crypto/fipsmodule/bn/asm/armv8-mont.pl
similarity index 99%
rename from crypto/bn/asm/armv8-mont.pl
rename to crypto/fipsmodule/bn/asm/armv8-mont.pl
index f04aab1..ac737a3 100644
--- a/crypto/bn/asm/armv8-mont.pl
+++ b/crypto/fipsmodule/bn/asm/armv8-mont.pl
@@ -38,7 +38,7 @@
 
 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
 ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
-( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+( $xlate="${dir}../../../perlasm/arm-xlate.pl" and -f $xlate) or
 die "can't locate arm-xlate.pl";
 
 open OUT,"| \"$^X\" $xlate $flavour $output";
diff --git a/crypto/bn/asm/bn-586.pl b/crypto/fipsmodule/bn/asm/bn-586.pl
similarity index 99%
rename from crypto/bn/asm/bn-586.pl
rename to crypto/fipsmodule/bn/asm/bn-586.pl
index ccc9451..f46923c 100644
--- a/crypto/bn/asm/bn-586.pl
+++ b/crypto/fipsmodule/bn/asm/bn-586.pl
@@ -1,7 +1,7 @@
 #!/usr/bin/env perl
 
 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
-push(@INC,"${dir}","${dir}../../perlasm");
+push(@INC,"${dir}","${dir}../../../perlasm");
 require "x86asm.pl";
 
 $output = pop;
diff --git a/crypto/bn/asm/co-586.pl b/crypto/fipsmodule/bn/asm/co-586.pl
similarity index 98%
rename from crypto/bn/asm/co-586.pl
rename to crypto/fipsmodule/bn/asm/co-586.pl
index c63e562..d1bc8f0 100644
--- a/crypto/bn/asm/co-586.pl
+++ b/crypto/fipsmodule/bn/asm/co-586.pl
@@ -1,7 +1,7 @@
 #!/usr/local/bin/perl
 
 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
-push(@INC,"${dir}","${dir}../../perlasm");
+push(@INC,"${dir}","${dir}../../../perlasm");
 require "x86asm.pl";
 
 $output = pop;
diff --git a/crypto/bn/asm/rsaz-avx2.pl b/crypto/fipsmodule/bn/asm/rsaz-avx2.pl
similarity index 99%
rename from crypto/bn/asm/rsaz-avx2.pl
rename to crypto/fipsmodule/bn/asm/rsaz-avx2.pl
index 60c4ca2..14a28dc 100755
--- a/crypto/bn/asm/rsaz-avx2.pl
+++ b/crypto/fipsmodule/bn/asm/rsaz-avx2.pl
@@ -76,7 +76,7 @@
 
 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
-( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+( $xlate="${dir}../../../perlasm/x86_64-xlate.pl" and -f $xlate) or
 die "can't locate x86_64-xlate.pl";
 
 # In upstream, this is controlled by shelling out to the compiler to check
@@ -1772,7 +1772,8 @@
 .type	rsaz_avx2_eligible,\@abi-omnipotent
 .align	32
 rsaz_avx2_eligible:
-	mov	OPENSSL_ia32cap_P+8(%rip),%eax
+	leaq	OPENSSL_ia32cap_P(%rip),%rax
+	mov	8(%rax),%eax
 ___
 $code.=<<___	if ($addx);
 	mov	\$`1<<8|1<<19`,%ecx
diff --git a/crypto/bn/asm/x86-mont.pl b/crypto/fipsmodule/bn/asm/x86-mont.pl
similarity index 99%
rename from crypto/bn/asm/x86-mont.pl
rename to crypto/fipsmodule/bn/asm/x86-mont.pl
index 57fbf10..f0f8243 100755
--- a/crypto/bn/asm/x86-mont.pl
+++ b/crypto/fipsmodule/bn/asm/x86-mont.pl
@@ -27,7 +27,7 @@
 # gives ~40% on rsa512 sign benchmark...
 
 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
-push(@INC,"${dir}","${dir}../../perlasm");
+push(@INC,"${dir}","${dir}../../../perlasm");
 require "x86asm.pl";
 
 $output = pop;
diff --git a/crypto/bn/asm/x86_64-gcc.c b/crypto/fipsmodule/bn/asm/x86_64-gcc.c
similarity index 99%
rename from crypto/bn/asm/x86_64-gcc.c
rename to crypto/fipsmodule/bn/asm/x86_64-gcc.c
index 177d335..7b6fc20 100644
--- a/crypto/bn/asm/x86_64-gcc.c
+++ b/crypto/fipsmodule/bn/asm/x86_64-gcc.c
@@ -200,7 +200,8 @@
       "	subq	%0,%0		\n" /* clear carry */
       "	jmp	1f		\n"
       ".p2align 4			\n"
-      "1:	movq	(%4,%2,8),%0	\n"
+      "1:"
+      "	movq	(%4,%2,8),%0	\n"
       "	adcq	(%5,%2,8),%0	\n"
       "	movq	%0,(%3,%2,8)	\n"
       "	lea	1(%2),%2	\n"
@@ -226,7 +227,8 @@
       "	subq	%0,%0		\n" /* clear borrow */
       "	jmp	1f		\n"
       ".p2align 4			\n"
-      "1:	movq	(%4,%2,8),%0	\n"
+      "1:"
+      "	movq	(%4,%2,8),%0	\n"
       "	sbbq	(%5,%2,8),%0	\n"
       "	movq	%0,(%3,%2,8)	\n"
       "	lea	1(%2),%2	\n"
diff --git a/crypto/bn/asm/x86_64-mont.pl b/crypto/fipsmodule/bn/asm/x86_64-mont.pl
similarity index 99%
rename from crypto/bn/asm/x86_64-mont.pl
rename to crypto/fipsmodule/bn/asm/x86_64-mont.pl
index 5775f65..286e0a0 100755
--- a/crypto/bn/asm/x86_64-mont.pl
+++ b/crypto/fipsmodule/bn/asm/x86_64-mont.pl
@@ -47,7 +47,7 @@
 
 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
-( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+( $xlate="${dir}../../../perlasm/x86_64-xlate.pl" and -f $xlate) or
 die "can't locate x86_64-xlate.pl";
 
 open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
@@ -94,7 +94,8 @@
 	jb	.Lmul_enter
 ___
 $code.=<<___ if ($addx);
-	mov	OPENSSL_ia32cap_P+8(%rip),%r11d
+	leaq	OPENSSL_ia32cap_P(%rip),%r11
+	mov	8(%r11),%r11d
 ___
 $code.=<<___;
 	cmp	$ap,$bp
@@ -295,7 +296,8 @@
 	mov	$num,$j			# j=num
 	jmp	.Lsub
 .align	16
-.Lsub:	sbb	($np,$i,8),%rax
+.Lsub:
+	sbb	($np,$i,8),%rax
 	mov	%rax,($rp,$i,8)		# rp[i]=tp[i]-np[i]
 	mov	8($ap,$i,8),%rax	# tp[i+1]
 	lea	1($i),$i		# i++
@@ -900,7 +902,8 @@
 	movq	%r10, %xmm3		# -$num
 ___
 $code.=<<___ if ($addx);
-	mov	OPENSSL_ia32cap_P+8(%rip),%eax
+	leaq	OPENSSL_ia32cap_P(%rip),%rax
+	mov	8(%rax),%eax
 	and	\$0x80100,%eax
 	cmp	\$0x80100,%eax
 	jne	.Lsqr8x_nox
diff --git a/crypto/bn/asm/x86_64-mont5.pl b/crypto/fipsmodule/bn/asm/x86_64-mont5.pl
similarity index 99%
rename from crypto/bn/asm/x86_64-mont5.pl
rename to crypto/fipsmodule/bn/asm/x86_64-mont5.pl
index bf68aad..db09624 100755
--- a/crypto/bn/asm/x86_64-mont5.pl
+++ b/crypto/fipsmodule/bn/asm/x86_64-mont5.pl
@@ -32,7 +32,7 @@
 
 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
-( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+( $xlate="${dir}../../../perlasm/x86_64-xlate.pl" and -f $xlate) or
 die "can't locate x86_64-xlate.pl";
 
 open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
@@ -81,7 +81,8 @@
 	jnz	.Lmul_enter
 ___
 $code.=<<___ if ($addx);
-	mov	OPENSSL_ia32cap_P+8(%rip),%r11d
+	leaq	OPENSSL_ia32cap_P(%rip),%r11
+	mov	8(%r11),%r11d
 ___
 $code.=<<___;
 	jmp	.Lmul4x_enter
@@ -395,7 +396,8 @@
 	mov	$num,$j			# j=num
 	jmp	.Lsub
 .align	16
-.Lsub:	sbb	($np,$i,8),%rax
+.Lsub:
+	sbb	($np,$i,8),%rax
 	mov	%rax,($rp,$i,8)		# rp[i]=tp[i]-np[i]
 	mov	8($ap,$i,8),%rax	# tp[i+1]
 	lea	1($i),$i		# i++
@@ -1082,7 +1084,8 @@
 .cfi_def_cfa_register	%rax
 ___
 $code.=<<___ if ($addx);
-	mov	OPENSSL_ia32cap_P+8(%rip),%r11d
+	leaq	OPENSSL_ia32cap_P(%rip),%r11
+	mov	8(%r11),%r11d
 	and	\$0x80108,%r11d
 	cmp	\$0x80108,%r11d		# check for AD*X+BMI2+BMI1
 	je	.Lpowerx5_enter
@@ -2202,7 +2205,8 @@
 	movq	%r10, %xmm3		# -num
 ___
 $code.=<<___ if ($addx);
-	mov	OPENSSL_ia32cap_P+8(%rip),%r11d
+	leaq	OPENSSL_ia32cap_P(%rip),%r11
+	mov	8(%r11),%r11d
 	and	\$0x80108,%r11d
 	cmp	\$0x80108,%r11d		# check for AD*X+BMI2+BMI1
 	jne	.Lfrom_mont_nox
diff --git a/crypto/bn/bn.c b/crypto/fipsmodule/bn/bn.c
similarity index 97%
rename from crypto/bn/bn.c
rename to crypto/fipsmodule/bn/bn.c
index c2a74ba..af093e0 100644
--- a/crypto/bn/bn.c
+++ b/crypto/fipsmodule/bn/bn.c
@@ -63,6 +63,7 @@
 #include <openssl/mem.h>
 
 #include "internal.h"
+#include "../delocate.h"
 
 
 BIGNUM *BN_new(void) {
@@ -165,11 +166,13 @@
   bn->neg = 0;
 }
 
-const BIGNUM *BN_value_one(void) {
+DEFINE_METHOD_FUNCTION(BIGNUM, BN_value_one) {
   static const BN_ULONG kOneLimbs[1] = { 1 };
-  static const BIGNUM kOne = STATIC_BIGNUM(kOneLimbs);
-
-  return &kOne;
+  out->d = (BN_ULONG*) kOneLimbs;
+  out->top = 1;
+  out->dmax = 1;
+  out->neg = 0;
+  out->flags = BN_FLG_STATIC_DATA;
 }
 
 /* BN_num_bits_word returns the minimum number of bits needed to represent the
diff --git a/crypto/bn/bn_test.cc b/crypto/fipsmodule/bn/bn_test.cc
similarity index 99%
rename from crypto/bn/bn_test.cc
rename to crypto/fipsmodule/bn/bn_test.cc
index c5548db..88e8eb1 100644
--- a/crypto/bn/bn_test.cc
+++ b/crypto/fipsmodule/bn/bn_test.cc
@@ -91,9 +91,9 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
-#include "../internal.h"
-#include "../test/file_test.h"
-#include "../test/test_util.h"
+#include "../../internal.h"
+#include "../../test/file_test.h"
+#include "../../test/test_util.h"
 
 
 static int HexToBIGNUM(bssl::UniquePtr<BIGNUM> *out, const char *in) {
diff --git a/crypto/bn/bn_tests.txt b/crypto/fipsmodule/bn/bn_tests.txt
similarity index 100%
rename from crypto/bn/bn_tests.txt
rename to crypto/fipsmodule/bn/bn_tests.txt
diff --git a/crypto/fipsmodule/bn/bytes.c b/crypto/fipsmodule/bn/bytes.c
new file mode 100644
index 0000000..0988870
--- /dev/null
+++ b/crypto/fipsmodule/bn/bytes.c
@@ -0,0 +1,269 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/bn.h>
+
+#include <assert.h>
+#include <limits.h>
+
+#include "internal.h"
+
+
+BIGNUM *BN_bin2bn(const uint8_t *in, size_t len, BIGNUM *ret) {
+  size_t num_words;
+  unsigned m;
+  BN_ULONG word = 0;
+  BIGNUM *bn = NULL;
+
+  if (ret == NULL) {
+    ret = bn = BN_new();
+  }
+
+  if (ret == NULL) {
+    return NULL;
+  }
+
+  if (len == 0) {
+    ret->top = 0;
+    return ret;
+  }
+
+  num_words = ((len - 1) / BN_BYTES) + 1;
+  m = (len - 1) % BN_BYTES;
+  if (!bn_wexpand(ret, num_words)) {
+    if (bn) {
+      BN_free(bn);
+    }
+    return NULL;
+  }
+
+  /* |bn_wexpand| must check bounds on |num_words| to write it into
+   * |ret->dmax|. */
+  assert(num_words <= INT_MAX);
+  ret->top = (int)num_words;
+  ret->neg = 0;
+
+  while (len--) {
+    word = (word << 8) | *(in++);
+    if (m-- == 0) {
+      ret->d[--num_words] = word;
+      word = 0;
+      m = BN_BYTES - 1;
+    }
+  }
+
+  /* need to call this due to clear byte at top if avoiding having the top bit
+   * set (-ve number) */
+  bn_correct_top(ret);
+  return ret;
+}
+
+BIGNUM *BN_le2bn(const uint8_t *in, size_t len, BIGNUM *ret) {
+  BIGNUM *bn = NULL;
+  if (ret == NULL) {
+    bn = BN_new();
+    ret = bn;
+  }
+
+  if (ret == NULL) {
+    return NULL;
+  }
+
+  if (len == 0) {
+    ret->top = 0;
+    ret->neg = 0;
+    return ret;
+  }
+
+  /* Reserve enough space in |ret|. */
+  size_t num_words = ((len - 1) / BN_BYTES) + 1;
+  if (!bn_wexpand(ret, num_words)) {
+    BN_free(bn);
+    return NULL;
+  }
+  ret->top = num_words;
+
+  /* Make sure the top bytes will be zeroed. */
+  ret->d[num_words - 1] = 0;
+
+  /* We only support little-endian platforms, so we can simply memcpy the
+   * internal representation. */
+  OPENSSL_memcpy(ret->d, in, len);
+
+  bn_correct_top(ret);
+  return ret;
+}
+
+size_t BN_bn2bin(const BIGNUM *in, uint8_t *out) {
+  size_t n, i;
+  BN_ULONG l;
+
+  n = i = BN_num_bytes(in);
+  while (i--) {
+    l = in->d[i / BN_BYTES];
+    *(out++) = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff;
+  }
+  return n;
+}
+
+int BN_bn2le_padded(uint8_t *out, size_t len, const BIGNUM *in) {
+  /* If we don't have enough space, fail out. */
+  size_t num_bytes = BN_num_bytes(in);
+  if (len < num_bytes) {
+    return 0;
+  }
+
+  /* We only support little-endian platforms, so we can simply memcpy into the
+   * internal representation. */
+  OPENSSL_memcpy(out, in->d, num_bytes);
+
+  /* Pad out the rest of the buffer with zeroes. */
+  OPENSSL_memset(out + num_bytes, 0, len - num_bytes);
+
+  return 1;
+}
+
+/* constant_time_select_ulong returns |x| if |v| is 1 and |y| if |v| is 0. Its
+ * behavior is undefined if |v| takes any other value. */
+static BN_ULONG constant_time_select_ulong(int v, BN_ULONG x, BN_ULONG y) {
+  BN_ULONG mask = v;
+  mask--;
+
+  return (~mask & x) | (mask & y);
+}
+
+/* constant_time_le_size_t returns 1 if |x| <= |y| and 0 otherwise. |x| and |y|
+ * must not have their MSBs set. */
+static int constant_time_le_size_t(size_t x, size_t y) {
+  return ((x - y - 1) >> (sizeof(size_t) * 8 - 1)) & 1;
+}
+
+/* read_word_padded returns the |i|'th word of |in|, if it is not out of
+ * bounds. Otherwise, it returns 0. It does so without branches on the size of
+ * |in|, however it necessarily does not have the same memory access pattern. If
+ * the access would be out of bounds, it reads the last word of |in|. |in| must
+ * not be zero. */
+static BN_ULONG read_word_padded(const BIGNUM *in, size_t i) {
+  /* Read |in->d[i]| if valid. Otherwise, read the last word. */
+  BN_ULONG l = in->d[constant_time_select_ulong(
+      constant_time_le_size_t(in->dmax, i), in->dmax - 1, i)];
+
+  /* Clamp to zero if above |d->top|. */
+  return constant_time_select_ulong(constant_time_le_size_t(in->top, i), 0, l);
+}
+
+int BN_bn2bin_padded(uint8_t *out, size_t len, const BIGNUM *in) {
+  /* Special case for |in| = 0. Just branch as the probability is negligible. */
+  if (BN_is_zero(in)) {
+    OPENSSL_memset(out, 0, len);
+    return 1;
+  }
+
+  /* Check if the integer is too big. This case can exit early in non-constant
+   * time. */
+  if ((size_t)in->top > (len + (BN_BYTES - 1)) / BN_BYTES) {
+    return 0;
+  }
+  if ((len % BN_BYTES) != 0) {
+    BN_ULONG l = read_word_padded(in, len / BN_BYTES);
+    if (l >> (8 * (len % BN_BYTES)) != 0) {
+      return 0;
+    }
+  }
+
+  /* Write the bytes out one by one. Serialization is done without branching on
+   * the bits of |in| or on |in->top|, but if the routine would otherwise read
+   * out of bounds, the memory access pattern can't be fixed. However, for an
+   * RSA key of size a multiple of the word size, the probability of BN_BYTES
+   * leading zero octets is low.
+   *
+   * See Falko Stenzke, "Manger's Attack revisited", ICICS 2010. */
+  size_t i = len;
+  while (i--) {
+    BN_ULONG l = read_word_padded(in, i / BN_BYTES);
+    *(out++) = (uint8_t)(l >> (8 * (i % BN_BYTES))) & 0xff;
+  }
+  return 1;
+}
+
+BN_ULONG BN_get_word(const BIGNUM *bn) {
+  switch (bn->top) {
+    case 0:
+      return 0;
+    case 1:
+      return bn->d[0];
+    default:
+      return BN_MASK2;
+  }
+}
+
+int BN_get_u64(const BIGNUM *bn, uint64_t *out) {
+  switch (bn->top) {
+    case 0:
+      *out = 0;
+      return 1;
+    case 1:
+      *out = bn->d[0];
+      return 1;
+#if defined(OPENSSL_32_BIT)
+    case 2:
+      *out = (uint64_t) bn->d[0] | (((uint64_t) bn->d[1]) << 32);
+      return 1;
+#endif
+    default:
+      return 0;
+  }
+}
diff --git a/crypto/bn/check_bn_tests.go b/crypto/fipsmodule/bn/check_bn_tests.go
similarity index 100%
rename from crypto/bn/check_bn_tests.go
rename to crypto/fipsmodule/bn/check_bn_tests.go
diff --git a/crypto/bn/cmp.c b/crypto/fipsmodule/bn/cmp.c
similarity index 100%
rename from crypto/bn/cmp.c
rename to crypto/fipsmodule/bn/cmp.c
diff --git a/crypto/bn/ctx.c b/crypto/fipsmodule/bn/ctx.c
similarity index 99%
rename from crypto/bn/ctx.c
rename to crypto/fipsmodule/bn/ctx.c
index d1400a3..3819775 100644
--- a/crypto/bn/ctx.c
+++ b/crypto/fipsmodule/bn/ctx.c
@@ -59,7 +59,7 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
-#include "../internal.h"
+#include "../../internal.h"
 
 
 /* How many bignums are in each "pool item"; */
diff --git a/crypto/bn/div.c b/crypto/fipsmodule/bn/div.c
similarity index 100%
rename from crypto/bn/div.c
rename to crypto/fipsmodule/bn/div.c
diff --git a/crypto/bn/exponentiation.c b/crypto/fipsmodule/bn/exponentiation.c
similarity index 100%
rename from crypto/bn/exponentiation.c
rename to crypto/fipsmodule/bn/exponentiation.c
diff --git a/crypto/bn/gcd.c b/crypto/fipsmodule/bn/gcd.c
similarity index 100%
rename from crypto/bn/gcd.c
rename to crypto/fipsmodule/bn/gcd.c
diff --git a/crypto/bn/generic.c b/crypto/fipsmodule/bn/generic.c
similarity index 100%
rename from crypto/bn/generic.c
rename to crypto/fipsmodule/bn/generic.c
diff --git a/crypto/bn/internal.h b/crypto/fipsmodule/bn/internal.h
similarity index 99%
rename from crypto/bn/internal.h
rename to crypto/fipsmodule/bn/internal.h
index e90b435..092e759 100644
--- a/crypto/bn/internal.h
+++ b/crypto/fipsmodule/bn/internal.h
@@ -132,7 +132,7 @@
 #pragma intrinsic(__umulh, _umul128)
 #endif
 
-#include "../internal.h"
+#include "../../internal.h"
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/crypto/bn/jacobi.c b/crypto/fipsmodule/bn/jacobi.c
similarity index 100%
rename from crypto/bn/jacobi.c
rename to crypto/fipsmodule/bn/jacobi.c
diff --git a/crypto/bn/montgomery.c b/crypto/fipsmodule/bn/montgomery.c
similarity index 99%
rename from crypto/bn/montgomery.c
rename to crypto/fipsmodule/bn/montgomery.c
index 60a4129..d70509f 100644
--- a/crypto/bn/montgomery.c
+++ b/crypto/fipsmodule/bn/montgomery.c
@@ -116,7 +116,7 @@
 #include <openssl/thread.h>
 
 #include "internal.h"
-#include "../internal.h"
+#include "../../internal.h"
 
 
 #if !defined(OPENSSL_NO_ASM) &&                         \
diff --git a/crypto/bn/montgomery_inv.c b/crypto/fipsmodule/bn/montgomery_inv.c
similarity index 98%
rename from crypto/bn/montgomery_inv.c
rename to crypto/fipsmodule/bn/montgomery_inv.c
index 9264adb..aa2574b 100644
--- a/crypto/bn/montgomery_inv.c
+++ b/crypto/fipsmodule/bn/montgomery_inv.c
@@ -17,13 +17,13 @@
 #include <assert.h>
 
 #include "internal.h"
-#include "../internal.h"
+#include "../../internal.h"
 
 
 static uint64_t bn_neg_inv_mod_r_u64(uint64_t n);
 
 OPENSSL_COMPILE_ASSERT(BN_MONT_CTX_N0_LIMBS == 1 || BN_MONT_CTX_N0_LIMBS == 2,
-                       BN_MONT_CTX_N0_LIMBS_VALUE_INVALID);
+                       BN_MONT_CTX_N0_LIMBS_VALUE_INVALID_2);
 OPENSSL_COMPILE_ASSERT(sizeof(uint64_t) ==
                        BN_MONT_CTX_N0_LIMBS * sizeof(BN_ULONG),
                        BN_MONT_CTX_N0_LIMBS_DOES_NOT_MATCH_UINT64_T);
diff --git a/crypto/bn/mul.c b/crypto/fipsmodule/bn/mul.c
similarity index 100%
rename from crypto/bn/mul.c
rename to crypto/fipsmodule/bn/mul.c
diff --git a/crypto/bn/prime.c b/crypto/fipsmodule/bn/prime.c
similarity index 100%
rename from crypto/bn/prime.c
rename to crypto/fipsmodule/bn/prime.c
diff --git a/crypto/bn/random.c b/crypto/fipsmodule/bn/random.c
similarity index 97%
rename from crypto/bn/random.c
rename to crypto/fipsmodule/bn/random.c
index 4b3da75..97f9bc2 100644
--- a/crypto/bn/random.c
+++ b/crypto/fipsmodule/bn/random.c
@@ -116,11 +116,11 @@
 #include <openssl/sha.h>
 #include <openssl/type_check.h>
 
-#include "../internal.h"
-#include "../fipsmodule/rand/internal.h"
+#include "../../internal.h"
+#include "../rand/internal.h"
 
 
-static const uint8_t kZeroAdditionalData[32] = {0};
+static const uint8_t kDefaultAdditionalData[32] = {0};
 
 static int bn_rand_with_additional_data(BIGNUM *rnd, int bits, int top,
                                         int bottom,
@@ -197,7 +197,7 @@
 
 int BN_rand(BIGNUM *rnd, int bits, int top, int bottom) {
   return bn_rand_with_additional_data(rnd, bits, top, bottom,
-                                      kZeroAdditionalData);
+                                      kDefaultAdditionalData);
 }
 
 int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom) {
@@ -242,7 +242,7 @@
 int BN_rand_range_ex(BIGNUM *r, BN_ULONG min_inclusive,
                      const BIGNUM *max_exclusive) {
   return bn_rand_range_with_additional_data(r, min_inclusive, max_exclusive,
-                                            kZeroAdditionalData);
+                                            kDefaultAdditionalData);
 }
 
 int BN_rand_range(BIGNUM *r, const BIGNUM *range) {
diff --git a/crypto/bn/rsaz_exp.c b/crypto/fipsmodule/bn/rsaz_exp.c
similarity index 99%
rename from crypto/bn/rsaz_exp.c
rename to crypto/fipsmodule/bn/rsaz_exp.c
index c7eed38..d0090a6 100644
--- a/crypto/bn/rsaz_exp.c
+++ b/crypto/fipsmodule/bn/rsaz_exp.c
@@ -48,7 +48,7 @@
 
 #include <openssl/mem.h>
 
-#include "../internal.h"
+#include "../../internal.h"
 
 
 /*
diff --git a/crypto/bn/rsaz_exp.h b/crypto/fipsmodule/bn/rsaz_exp.h
similarity index 100%
rename from crypto/bn/rsaz_exp.h
rename to crypto/fipsmodule/bn/rsaz_exp.h
diff --git a/crypto/bn/shift.c b/crypto/fipsmodule/bn/shift.c
similarity index 100%
rename from crypto/bn/shift.c
rename to crypto/fipsmodule/bn/shift.c
diff --git a/crypto/bn/sqrt.c b/crypto/fipsmodule/bn/sqrt.c
similarity index 100%
rename from crypto/bn/sqrt.c
rename to crypto/fipsmodule/bn/sqrt.c
diff --git a/crypto/fipsmodule/delocate.go b/crypto/fipsmodule/delocate.go
index fd11a21..0ec5b0d 100644
--- a/crypto/fipsmodule/delocate.go
+++ b/crypto/fipsmodule/delocate.go
@@ -264,7 +264,7 @@
 		case "call", "callq", "jmp", "jne", "jb", "jz", "jnz", "ja":
 			target := args[0]
 			// indirect via register or local label
-			if strings.HasPrefix(target, "*") || strings.HasPrefix(target, ".L") {
+			if strings.HasPrefix(target, "*") || isLocalLabel(target) {
 				ret = append(ret, line)
 				continue
 			}
@@ -344,6 +344,11 @@
 
 					if isGlobal := symbols[target]; isGlobal {
 						line = strings.Replace(line, target, localTargetName(target), 1)
+					} else if !strings.HasPrefix(target, "BORINGSSL_bcm_") {
+						redirectorName := "bcm_redirector_" + target
+						redirectors[redirectorName] = target
+						line = strings.Replace(line, target, redirectorName, 1)
+						target = redirectorName
 					}
 
 					// Nobody actually wants to read the
@@ -533,6 +538,17 @@
 	return ret
 }
 
+func isLocalLabel(label string) bool {
+	if strings.HasPrefix(label, ".L") {
+		return true
+	}
+	if strings.HasSuffix(label, "f") || strings.HasSuffix(label, "b") {
+		label = label[:len(label)-1]
+		return strings.IndexFunc(label, func(r rune) bool { return !unicode.IsNumber(r) }) == -1
+	}
+	return false
+}
+
 // handleBSSSection reads lines from source until the next section and adds a
 // local symbol for each BSS symbol found.
 func handleBSSSection(lines []string, source *lineSource) (map[string]string, []string) {
diff --git a/crypto/rsa/rsa.c b/crypto/rsa/rsa.c
index aec8935..64ca969 100644
--- a/crypto/rsa/rsa.c
+++ b/crypto/rsa/rsa.c
@@ -69,7 +69,7 @@
 
 #include "internal.h"
 #include "../internal.h"
-#include "../bn/internal.h"
+#include "../fipsmodule/bn/internal.h"
 
 
 static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
diff --git a/crypto/rsa/rsa_impl.c b/crypto/rsa/rsa_impl.c
index c807831..4f9b4e6 100644
--- a/crypto/rsa/rsa_impl.c
+++ b/crypto/rsa/rsa_impl.c
@@ -67,7 +67,7 @@
 #include <openssl/type_check.h>
 
 #include "internal.h"
-#include "../bn/internal.h"
+#include "../fipsmodule/bn/internal.h"
 #include "../internal.h"
 
 
diff --git a/crypto/rsa/rsa_test.cc b/crypto/rsa/rsa_test.cc
index 217f455..cf0feca 100644
--- a/crypto/rsa/rsa_test.cc
+++ b/crypto/rsa/rsa_test.cc
@@ -67,7 +67,7 @@
 #include <openssl/err.h>
 #include <openssl/nid.h>
 
-#include "../bn/internal.h"
+#include "../fipsmodule/bn/internal.h"
 #include "../internal.h"
 #include "../test/test_util.h"
 #include "internal.h"
diff --git a/util/all_tests.json b/util/all_tests.json
index 83dc5e3..92e8487 100644
--- a/util/all_tests.json
+++ b/util/all_tests.json
@@ -1,5 +1,4 @@
 [
-	["crypto/bn/bn_test", "crypto/bn/bn_tests.txt"],
 	["crypto/cipher/aead_test", "aes-128-cbc-sha1-ssl3", "crypto/cipher/test/aes_128_cbc_sha1_ssl3_tests.txt"],
 	["crypto/cipher/aead_test", "aes-128-cbc-sha1-tls", "crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt"],
 	["crypto/cipher/aead_test", "aes-128-cbc-sha1-tls-implicit-iv", "crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt"],
@@ -44,6 +43,7 @@
 	["crypto/evp/evp_test", "crypto/evp/evp_tests.txt"],
 	["crypto/evp/pbkdf_test"],
 	["crypto/fipsmodule/aes_test", "crypto/fipsmodule/aes/aes_tests.txt"],
+	["crypto/fipsmodule/bn_test", "crypto/fipsmodule/bn/bn_tests.txt"],
 	["crypto/fipsmodule/ctrdrbg_vector_test", "crypto/fipsmodule/rand/ctrdrbg_vectors.txt"],
 	["crypto/fipsmodule/gcm_test"],
 	["crypto/hkdf/hkdf_test"],