Add some more compatibility functions.

Change-Id: I56afcd896cb9de1c69c788b4f6395f4e78140d81
Reviewed-on: https://boringssl-review.googlesource.com/28265
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/crypto/cmac/cmac.c b/crypto/cmac/cmac.c
index fb4e69c..6805c43 100644
--- a/crypto/cmac/cmac.c
+++ b/crypto/cmac/cmac.c
@@ -124,6 +124,17 @@
   OPENSSL_free(ctx);
 }
 
+int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in) {
+  if (!EVP_CIPHER_CTX_copy(&out->cipher_ctx, &in->cipher_ctx)) {
+    return 0;
+  }
+  OPENSSL_memcpy(out->k1, in->k1, AES_BLOCK_SIZE);
+  OPENSSL_memcpy(out->k2, in->k2, AES_BLOCK_SIZE);
+  OPENSSL_memcpy(out->block, in->block, AES_BLOCK_SIZE);
+  out->block_used = in->block_used;
+  return 1;
+}
+
 // binary_field_mul_x treats the 128 bits at |in| as an element of GF(2¹²⁸)
 // with a hard-coded reduction polynomial and sets |out| as x times the
 // input.
diff --git a/crypto/cmac/cmac_test.cc b/crypto/cmac/cmac_test.cc
index dbd63ea..3d01e08 100644
--- a/crypto/cmac/cmac_test.cc
+++ b/crypto/cmac/cmac_test.cc
@@ -54,6 +54,18 @@
     ASSERT_TRUE(CMAC_Final(ctx.get(), out, &out_len));
     EXPECT_EQ(Bytes(expected, sizeof(out)), Bytes(out, out_len));
   }
+
+  // Test that |CMAC_CTX_copy| works.
+  ASSERT_TRUE(CMAC_Reset(ctx.get()));
+  size_t chunk = msg_len / 2;
+  ASSERT_TRUE(CMAC_Update(ctx.get(), msg, chunk));
+  bssl::UniquePtr<CMAC_CTX> ctx2(CMAC_CTX_new());
+  ASSERT_TRUE(ctx2);
+  ASSERT_TRUE(CMAC_CTX_copy(ctx2.get(), ctx.get()));
+  ASSERT_TRUE(CMAC_Update(ctx2.get(), msg + chunk, msg_len - chunk));
+  size_t out_len;
+  ASSERT_TRUE(CMAC_Final(ctx2.get(), out, &out_len));
+  EXPECT_EQ(Bytes(expected, sizeof(out)), Bytes(out, out_len));
 }
 
 TEST(CMACTest, RFC4493TestVectors) {
diff --git a/crypto/crypto.c b/crypto/crypto.c
index 5752712..8ee4c82 100644
--- a/crypto/crypto.c
+++ b/crypto/crypto.c
@@ -164,9 +164,14 @@
 #endif
 }
 
-const char *SSLeay_version(int unused) { return "BoringSSL"; }
+const char *SSLeay_version(int which) { return OpenSSL_version(which); }
 
-const char *OpenSSL_version(int unused) { return "BoringSSL"; }
+const char *OpenSSL_version(int which) {
+  if (which == OPENSSL_VERSION) {
+    return "BoringSSL";
+  }
+  return "";
+}
 
 unsigned long SSLeay(void) { return OPENSSL_VERSION_NUMBER; }
 
diff --git a/crypto/err/err.c b/crypto/err/err.c
index c7bff16..43d3909 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -781,6 +781,8 @@
 
 void ERR_load_ERR_strings(void) {}
 
+void ERR_load_RAND_strings(void) {}
+
 struct err_save_state_st {
   struct err_error_st *errors;
   size_t num_errors;
diff --git a/crypto/fipsmodule/is_fips.c b/crypto/fipsmodule/is_fips.c
index 4182dfb..2f8e408 100644
--- a/crypto/fipsmodule/is_fips.c
+++ b/crypto/fipsmodule/is_fips.c
@@ -25,3 +25,5 @@
   return 0;
 #endif
 }
+
+int FIPS_mode_set(int on) { return on == FIPS_mode(); }
diff --git a/crypto/obj/obj.c b/crypto/obj/obj.c
index a34d6dc..c928889 100644
--- a/crypto/obj/obj.c
+++ b/crypto/obj/obj.c
@@ -552,3 +552,5 @@
   }
   return op->nid;
 }
+
+void OBJ_cleanup(void) {}
diff --git a/include/openssl/cmac.h b/include/openssl/cmac.h
index dfcd37b..5e9f3d0 100644
--- a/include/openssl/cmac.h
+++ b/include/openssl/cmac.h
@@ -46,6 +46,10 @@
 // CMAC_CTX_free frees a |CMAC_CTX|.
 OPENSSL_EXPORT void CMAC_CTX_free(CMAC_CTX *ctx);
 
+// CMAC_CTX_copy sets |out| to be a duplicate of the current state |in|. It
+// returns one on success and zero on error.
+OPENSSL_EXPORT int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in);
+
 // CMAC_Init configures |ctx| to use the given |key| and |cipher|. The CMAC RFC
 // only specifies the use of AES-128 thus |key_len| should be 16 and |cipher|
 // should be |EVP_aes_128_cbc()|. However, this implementation also supports
diff --git a/include/openssl/crypto.h b/include/openssl/crypto.h
index cc6fc3c..6678f2a 100644
--- a/include/openssl/crypto.h
+++ b/include/openssl/crypto.h
@@ -69,17 +69,24 @@
 // “OpenSSL”. node.js requires a version number in this text.
 #define OPENSSL_VERSION_TEXT "OpenSSL 1.1.0 (compatible; BoringSSL)"
 
-#define SSLEAY_VERSION 0
-
-// SSLeay_version is a compatibility function that returns the string
-// "BoringSSL".
-OPENSSL_EXPORT const char *SSLeay_version(int unused);
-
 #define OPENSSL_VERSION 0
+#define OPENSSL_CFLAGS 1
+#define OPENSSL_BUILT_ON 2
+#define OPENSSL_PLATFORM 3
+#define OPENSSL_DIR 4
 
 // OpenSSL_version is a compatibility function that returns the string
-// "BoringSSL".
-OPENSSL_EXPORT const char *OpenSSL_version(int unused);
+// "BoringSSL" if |which| is |OPENSSL_VERSION| and "" otherwise.
+OPENSSL_EXPORT const char *OpenSSL_version(int which);
+
+#define SSLEAY_VERSION OPENSSL_VERSION
+#define SSLEAY_CFLAGS OPENSSL_CFLAGS
+#define SSLEAY_BUILT_ON OPENSSL_BUILT_ON
+#define SSLEAY_PLATFORM OPENSSL_PLATFORM
+#define SSLEAY_DIR OPENSSL_DIR
+
+// SSLeay_version calls |OpenSSL_version|.
+OPENSSL_EXPORT const char *SSLeay_version(int which);
 
 // SSLeay is a compatibility function that returns OPENSSL_VERSION_NUMBER from
 // base.h.
@@ -117,6 +124,10 @@
 OPENSSL_EXPORT int OPENSSL_init_crypto(uint64_t opts,
                                        const OPENSSL_INIT_SETTINGS *settings);
 
+// FIPS_mode_set returns one if |on| matches whether BoringSSL was built with
+// |BORINGSSL_FIPS| and zero otherwise.
+OPENSSL_EXPORT int FIPS_mode_set(int on);
+
 
 #if defined(__cplusplus)
 }  // extern C
diff --git a/include/openssl/err.h b/include/openssl/err.h
index a39c090..4721f75 100644
--- a/include/openssl/err.h
+++ b/include/openssl/err.h
@@ -152,6 +152,9 @@
 // ERR_load_crypto_strings does nothing.
 OPENSSL_EXPORT void ERR_load_crypto_strings(void);
 
+// ERR_load_RAND_strings does nothing.
+OPENSSL_EXPORT void ERR_load_RAND_strings(void);
+
 // ERR_free_strings does nothing.
 OPENSSL_EXPORT void ERR_free_strings(void);
 
diff --git a/include/openssl/obj.h b/include/openssl/obj.h
index 374658e..764188f 100644
--- a/include/openssl/obj.h
+++ b/include/openssl/obj.h
@@ -222,6 +222,9 @@
                                                                void *arg),
                                     void *arg);
 
+// OBJ_cleanup does nothing.
+OPENSSL_EXPORT void OBJ_cleanup(void);
+
 
 #if defined(__cplusplus)
 }  // extern C
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 1ad7042..4108c42 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -3471,14 +3471,20 @@
 OPENSSL_EXPORT void SSL_CTX_set_dos_protection_cb(
     SSL_CTX *ctx, int (*cb)(const SSL_CLIENT_HELLO *));
 
-// SSL_ST_* are possible values for |SSL_state| and the bitmasks that make them
-// up.
+// SSL_ST_* are possible values for |SSL_state|, the bitmasks that make them up,
+// and some historical values for compatibility. Only |SSL_ST_INIT| and
+// |SSL_ST_OK| are ever returned.
 #define SSL_ST_CONNECT 0x1000
 #define SSL_ST_ACCEPT 0x2000
 #define SSL_ST_MASK 0x0FFF
 #define SSL_ST_INIT (SSL_ST_CONNECT | SSL_ST_ACCEPT)
 #define SSL_ST_OK 0x03
 #define SSL_ST_RENEGOTIATE (0x04 | SSL_ST_INIT)
+#define SSL_ST_BEFORE (0x05 | SSL_ST_INIT)
+
+// TLS_ST_* are aliases for |SSL_ST_*| for OpenSSL 1.1.0 compatibility.
+#define TLS_ST_OK SSL_ST_OK
+#define TLS_ST_BEFORE SSL_ST_BEFORE
 
 // SSL_CB_* are possible values for the |type| parameter in the info
 // callback and the bitmasks that make them up.