Allow forcing 64-bit integer type

Allow forcing 64-bit integer type for bignum operations. Also introduce
the macro MBEDTLS_TYPE_UDBL to allow configuration of the double length
integer in unknown compilers.
diff --git a/include/mbedtls/bignum.h b/include/mbedtls/bignum.h
index ac89069..3b76c1c 100644
--- a/include/mbedtls/bignum.h
+++ b/include/mbedtls/bignum.h
@@ -103,13 +103,28 @@
 /*
  * Define the base integer type, architecture-wise.
  *
- * 32-bit integers can be forced on 64-bit arches (eg. for testing purposes)
- * by defining MBEDTLS_HAVE_INT32 and undefining MBEDTLS_HAVE_ASM
+ * 32 or 64-bit integer types can be forced regardless of the underlying
+ * architecture by defining MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64
+ * respectively and undefining MBEDTLS_HAVE_ASM.
+ *
+ * Double length integers (e.g. 128-bit in 64-bit architectures) can be
+ * disabled by defining MBEDTLS_NO_UDBL_DIVISION.
+ *
+ * The double length integer types can be configured by defining
+ * MBEDTLS_TYPE_UDBL when the type cannot be automatically deduced by the
+ * library (e.g. the compiler is unknown). The definition of MBEDTLS_TYPE_UDBL
+ * must be a complete statement of the form:
+ *      typedef <UDBL_TYPE> mbedtls_t_udbl <OTHER_DIRECTIVES>
+ * for example:
+ *      #define MBEDTLS_TYPE_UDBL       \
+ *          typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI)))
  */
 #if !defined(MBEDTLS_HAVE_INT32)
     #if defined(_MSC_VER) && defined(_M_AMD64)
         /* Always choose 64-bit when using MSC */
-        #define MBEDTLS_HAVE_INT64
+        #if !defined(MBEDTLS_HAVE_INT64)
+            #define MBEDTLS_HAVE_INT64
+        #endif /* !MBEDTLS_HAVE_INT64 */
         typedef  int64_t mbedtls_mpi_sint;
         typedef uint64_t mbedtls_mpi_uint;
     #elif defined(__GNUC__) && (                         \
@@ -118,22 +133,39 @@
         defined(__ia64__)  || defined(__alpha__)      || \
         ( defined(__sparc__) && defined(__arch64__) ) || \
         defined(__s390x__) || defined(__mips64) )
-        #define MBEDTLS_HAVE_INT64
+        #if !defined(MBEDTLS_HAVE_INT64)
+            #define MBEDTLS_HAVE_INT64
+        #endif /* MBEDTLS_HAVE_INT64 */
         typedef  int64_t mbedtls_mpi_sint;
         typedef uint64_t mbedtls_mpi_uint;
-        /* mbedtls_t_udbl defined as 128-bit unsigned int */
-        typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI)));
-        #define MBEDTLS_HAVE_UDBL
+        #if !defined(MBEDTLS_NO_UDBL_DIVISION)
+            /* mbedtls_t_udbl defined as 128-bit unsigned int */
+            typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI)));
+            #define MBEDTLS_HAVE_UDBL
+        #endif /* !MBEDTLS_NO_UDBL_DIVISION */
     #elif defined(__ARMCC_VERSION) && defined(__aarch64__)
-        /* __ARMCC_VERSION is defined for both armcc and armclang and
+        /*
+         * __ARMCC_VERSION is defined for both armcc and armclang and
          * __aarch64__ is only defined by armclang when compiling 64-bit code
          */
-        #define MBEDTLS_HAVE_INT64
+        #if !defined(MBEDTLS_HAVE_INT64)
+            #define MBEDTLS_HAVE_INT64
+        #endif /* !MBEDTLS_HAVE_INT64 */
         typedef  int64_t mbedtls_mpi_sint;
         typedef uint64_t mbedtls_mpi_uint;
-        /* mbedtls_t_udbl defined as 128-bit unsigned int */
-        typedef __uint128_t mbedtls_t_udbl;
-        #define MBEDTLS_HAVE_UDBL
+        #if !defined(MBEDTLS_NO_UDBL_DIVISION)
+            /* mbedtls_t_udbl defined as 128-bit unsigned int */
+            typedef __uint128_t mbedtls_t_udbl;
+            #define MBEDTLS_HAVE_UDBL
+        #endif /* !MBEDTLS_NO_UDBL_DIVISION */
+    #elif defined(MBEDTLS_HAVE_INT64)
+        /* Force 64-bit integers with unknown compiler */
+        typedef  int64_t mbedtls_mpi_sint;
+        typedef uint64_t mbedtls_mpi_uint;
+        #if !defined(MBEDTLS_NO_UDBL_DIVISION) && defined(MBEDTLS_TYPE_UDBL)
+            MBEDTLS_TYPE_UDBL;
+            #define MBEDTLS_HAVE_UDBL
+        #endif /* !MBEDTLS_NO_UDBL_DIVISION && MBEDTLS_TYPE_UDBL */
     #endif
 #endif /* !MBEDTLS_HAVE_INT32 */
 
@@ -144,8 +176,9 @@
     #endif /* !MBEDTLS_HAVE_INT32 */
     typedef  int32_t mbedtls_mpi_sint;
     typedef uint32_t mbedtls_mpi_uint;
-    typedef uint64_t mbedtls_t_udbl;
-    #define MBEDTLS_HAVE_UDBL
+    #if !defined(MBEDTLS_NO_UDBL_DIVISION)
+        typedef uint64_t mbedtls_t_udbl;
+    #endif /* !MBEDTLS_NO_UDBL_DIVISION */
 #endif /* !MBEDTLS_HAVE_INT64 */
 
 #ifdef __cplusplus
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index dab1113..7261e7d 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -650,6 +650,16 @@
 #error "MBEDTLS_X509_CSR_WRITE_C defined, but not all prerequisites"
 #endif
 
+#if defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64)
+#error "MBEDTLS_HAVE_INT32 and MBEDTLS_HAVE_INT64 cannot be defined simultaneously"
+#endif /* MBEDTLS_HAVE_INT32 && MBEDTLS_HAVE_INT64 */
+
+#if (defined(MBEDTLS_HAVE_INT32) || define(MBEDTLS_HAVE_INT64)) && \
+    defined(MBEDTLS_HAVE_ASM
+#error "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_INT64 cannot be"
+    "defined simultaneously"
+#endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */
+
 /*
  * Avoid warning from -pedantic. This is a convenient place for this
  * workaround since this is included by every single file before the