Add ABI tests for MD5.

This does not actually matter, but writing new CFI directives with the
tester seemed like fun. (It caught two typos, one intentional and one
accidental.)

Change-Id: Iff3e0358f2e56caa26079f658fa7a682772150a1
Reviewed-on: https://boringssl-review.googlesource.com/c/34185
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt
index 2b81faa..8565977 100644
--- a/crypto/CMakeLists.txt
+++ b/crypto/CMakeLists.txt
@@ -456,6 +456,7 @@
   fipsmodule/ec/ec_test.cc
   fipsmodule/ec/p256-x86_64_test.cc
   fipsmodule/ecdsa/ecdsa_test.cc
+  fipsmodule/md5/md5_test.cc
   fipsmodule/modes/gcm_test.cc
   fipsmodule/rand/ctrdrbg_test.cc
   fipsmodule/sha/sha_test.cc
diff --git a/crypto/fipsmodule/md5/asm/md5-x86_64.pl b/crypto/fipsmodule/md5/asm/md5-x86_64.pl
index 568f4f5..6eb33c0 100644
--- a/crypto/fipsmodule/md5/asm/md5-x86_64.pl
+++ b/crypto/fipsmodule/md5/asm/md5-x86_64.pl
@@ -130,11 +130,17 @@
 .globl md5_block_asm_data_order
 .type md5_block_asm_data_order,\@function,3
 md5_block_asm_data_order:
+.cfi_startproc
 	push	%rbp
+.cfi_push	rbp
 	push	%rbx
+.cfi_push	rbx
 	push	%r12
+.cfi_push	r12
 	push	%r14
+.cfi_push	r14
 	push	%r15
+.cfi_push	r15
 .Lprologue:
 
 	# rdi = arg #1 (ctx, MD5_CTX pointer)
@@ -251,13 +257,20 @@
 	mov	%edx,		3*4(%rbp)	# ctx->D = D
 
 	mov	(%rsp),%r15
+.cfi_restore r15
 	mov	8(%rsp),%r14
+.cfi_restore r14
 	mov	16(%rsp),%r12
+.cfi_restore r12
 	mov	24(%rsp),%rbx
+.cfi_restore rbx
 	mov	32(%rsp),%rbp
+.cfi_restore rbp
 	add	\$40,%rsp
+.cfi_adjust_cfa_offset	-40
 .Lepilogue:
 	ret
+.cfi_endproc
 .size md5_block_asm_data_order,.-md5_block_asm_data_order
 EOF
 
diff --git a/crypto/fipsmodule/md5/internal.h b/crypto/fipsmodule/md5/internal.h
new file mode 100644
index 0000000..9ee9f13
--- /dev/null
+++ b/crypto/fipsmodule/md5/internal.h
@@ -0,0 +1,37 @@
+/* Copyright (c) 2018, 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. */
+
+#ifndef OPENSSL_HEADER_MD5_INTERNAL_H
+#define OPENSSL_HEADER_MD5_INTERNAL_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#if !defined(OPENSSL_NO_ASM) && \
+    (defined(OPENSSL_X86_64) || defined(OPENSSL_X86))
+#define MD5_ASM
+extern void md5_block_asm_data_order(uint32_t *state, const uint8_t *data,
+                                     size_t num);
+#endif
+
+
+#if defined(__cplusplus)
+}  // extern "C"
+#endif
+
+#endif  // OPENSSL_HEADER_MD5_INTERNAL_H
diff --git a/crypto/fipsmodule/md5/md5.c b/crypto/fipsmodule/md5/md5.c
index 370b42a..66c65a6 100644
--- a/crypto/fipsmodule/md5/md5.c
+++ b/crypto/fipsmodule/md5/md5.c
@@ -60,6 +60,7 @@
 
 #include <openssl/mem.h>
 
+#include "internal.h"
 #include "../../internal.h"
 
 
@@ -81,12 +82,8 @@
   return 1;
 }
 
-#if !defined(OPENSSL_NO_ASM) && \
-    (defined(OPENSSL_X86_64) || defined(OPENSSL_X86))
-#define MD5_ASM
+#if defined(MD5_ASM)
 #define md5_block_data_order md5_block_asm_data_order
-extern void md5_block_data_order(uint32_t *state, const uint8_t *data,
-                                 size_t num);
 #else
 static void md5_block_data_order(uint32_t *state, const uint8_t *data,
                                  size_t num);
diff --git a/crypto/fipsmodule/md5/md5_test.cc b/crypto/fipsmodule/md5/md5_test.cc
new file mode 100644
index 0000000..7df5bb2
--- /dev/null
+++ b/crypto/fipsmodule/md5/md5_test.cc
@@ -0,0 +1,34 @@
+/* Copyright (c) 2018, 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 <openssl/md5.h>
+
+#include <gtest/gtest.h>
+
+#include "internal.h"
+#include "../../test/abi_test.h"
+
+
+#if defined(MD5_ASM) && defined(SUPPORTS_ABI_TEST)
+TEST(MD5Test, ABI) {
+  MD5_CTX ctx;
+  MD5_Init(&ctx);
+
+  static const uint8_t kBuf[MD5_CBLOCK * 8] = {0};
+  CHECK_ABI(md5_block_asm_data_order, ctx.h, kBuf, 1);
+  CHECK_ABI(md5_block_asm_data_order, ctx.h, kBuf, 2);
+  CHECK_ABI(md5_block_asm_data_order, ctx.h, kBuf, 4);
+  CHECK_ABI(md5_block_asm_data_order, ctx.h, kBuf, 8);
+}
+#endif  // MD5_ASM && SUPPORTS_ABI_TEST