Added AESCTR_DRBG implementation (beta).
[BearSSL] / src / inner.h
index 52bcaf0..c507102 100644 (file)
  * already set their root keys to RSA-4096, so we should be able to
  * process such keys.
  *
- * This value MUST be a multiple of 64.
+ * This value MUST be a multiple of 64. This value MUST NOT exceed 47666
+ * (some computations in RSA key generation rely on the factor size being
+ * no more than 23833 bits). RSA key sizes beyond 3072 bits don't make a
+ * lot of sense anyway.
  */
 #define BR_MAX_RSA_SIZE   4096
 
+/*
+ * Minimum size for a RSA modulus (in bits); this value is used only to
+ * filter out invalid parameters for key pair generation. Normally,
+ * applications should not use RSA keys smaller than 2048 bits; but some
+ * specific cases might need shorter keys, for legacy or research
+ * purposes.
+ */
+#define BR_MIN_RSA_SIZE   512
+
 /*
  * Maximum size for a RSA factor (in bits). This is for RSA private-key
  * operations. Default is to support factors up to a bit more than half
@@ -85,7 +97,7 @@
  *
  * The test on 'unsigned long' should already catch most cases, the one
  * notable exception being Windows code where 'unsigned long' is kept to
- * 32-bit for compatbility with all the legacy code that liberally uses
+ * 32-bit for compatibility with all the legacy code that liberally uses
  * the 'DWORD' type for 32-bit values.
  *
  * Macro names are taken from: http://nadeausoftware.com/articles/2012/02/c_c_tip_how_detect_processor_type_using_compiler_predefined_macros
@@ -1474,6 +1486,23 @@ uint32_t br_i31_modpow_opt(uint32_t *x, const unsigned char *e, size_t elen,
  */
 void br_i31_mulacc(uint32_t *d, const uint32_t *a, const uint32_t *b);
 
+/*
+ * Compute x/y mod m, result in x. Values x and y must be between 0 and
+ * m-1, and have the same announced bit length as m. Modulus m must be
+ * odd. The "m0i" parameter is equal to -1/m mod 2^31. The array 't'
+ * must point to a temporary area that can hold at least three integers
+ * of the size of m.
+ *
+ * m may not overlap x and y. x and y may overlap each other (this can
+ * be useful to test whether a value is invertible modulo m). t must be
+ * disjoint from all other arrays.
+ *
+ * Returned value is 1 on success, 0 otherwise. Success is attained if
+ * y is invertible modulo m.
+ */
+uint32_t br_i31_moddiv(uint32_t *x, const uint32_t *y,
+       const uint32_t *m, uint32_t m0i, uint32_t *t);
+
 /* ==================================================================== */
 
 /*
@@ -1528,9 +1557,36 @@ void br_i15_reduce(uint16_t *x, const uint16_t *a, const uint16_t *m);
 
 void br_i15_mulacc(uint16_t *d, const uint16_t *a, const uint16_t *b);
 
+uint32_t br_i15_moddiv(uint16_t *x, const uint16_t *y,
+       const uint16_t *m, uint16_t m0i, uint16_t *t);
+
+/*
+ * Variant of br_i31_modpow_opt() that internally uses 64x64->128
+ * multiplications. It expects the same parameters as br_i31_modpow_opt(),
+ * except that the temporaries should be 64-bit integers, not 32-bit
+ * integers.
+ */
 uint32_t br_i62_modpow_opt(uint32_t *x31, const unsigned char *e, size_t elen,
        const uint32_t *m31, uint32_t m0i31, uint64_t *tmp, size_t twlen);
 
+/*
+ * Type for a function with the same API as br_i31_modpow_opt() (some
+ * implementations of this type may have stricter alignment requirements
+ * on the temporaries).
+ */
+typedef uint32_t (*br_i31_modpow_opt_type)(uint32_t *x,
+       const unsigned char *e, size_t elen,
+       const uint32_t *m, uint32_t m0i, uint32_t *tmp, size_t twlen);
+
+/*
+ * Wrapper for br_i62_modpow_opt() that uses the same type as
+ * br_i31_modpow_opt(); however, it requires its 'tmp' argument to the
+ * 64-bit aligned.
+ */
+uint32_t br_i62_modpow_opt_as_i31(uint32_t *x,
+       const unsigned char *e, size_t elen,
+       const uint32_t *m, uint32_t m0i, uint32_t *tmp, size_t twlen);
+
 /* ==================================================================== */
 
 static inline size_t
@@ -1887,6 +1943,40 @@ uint32_t br_rsa_pkcs1_sig_unpad(const unsigned char *sig, size_t sig_len,
        const unsigned char *hash_oid, size_t hash_len,
        unsigned char *hash_out);
 
+/*
+ * Apply OAEP padding. Returned value is the actual padded string length,
+ * or zero on error.
+ */
+size_t br_rsa_oaep_pad(const br_prng_class **rnd, const br_hash_class *dig,
+       const void *label, size_t label_len, const br_rsa_public_key *pk,
+       void *dst, size_t dst_nax_len, const void *src, size_t src_len);
+
+/*
+ * Unravel and check OAEP padding. If the padding is correct, then 1 is
+ * returned, '*len' is adjusted to the length of the message, and the
+ * data is moved to the start of the 'data' buffer. If the padding is
+ * incorrect, then 0 is returned and '*len' is untouched. Either way,
+ * the complete buffer contents are altered.
+ */
+uint32_t br_rsa_oaep_unpad(const br_hash_class *dig,
+       const void *label, size_t label_len, void *data, size_t *len);
+
+/*
+ * Compute MGF1 for a given seed, and XOR the output into the provided
+ * buffer.
+ */
+void br_mgf1_xor(void *data, size_t len,
+       const br_hash_class *dig, const void *seed, size_t seed_len);
+
+/*
+ * Inner function for RSA key generation; used by the "i31" and "i62"
+ * implementations.
+ */
+uint32_t br_rsa_i31_keygen_inner(const br_prng_class **rng,
+       br_rsa_private_key *sk, unsigned char *kbuf_priv,
+       br_rsa_public_key *pk, unsigned char *kbuf_pub,
+       unsigned size, uint32_t pubexp, br_i31_modpow_opt_type mp31);
+
 /* ==================================================================== */
 /*
  * Elliptic curves.
@@ -2122,6 +2212,34 @@ void br_ssl_engine_switch_chapol_in(br_ssl_engine_context *cc,
 void br_ssl_engine_switch_chapol_out(br_ssl_engine_context *cc,
        int is_client, int prf_id);
 
+/*
+ * Switch to CCM decryption for incoming records.
+ *    cc               the engine context
+ *    is_client        non-zero for a client, zero for a server
+ *    prf_id           id of hash function for PRF
+ *    bc_impl          block cipher implementation (CTR+CBC)
+ *    cipher_key_len   block cipher key length (in bytes)
+ *    tag_len          tag length (in bytes)
+ */
+void br_ssl_engine_switch_ccm_in(br_ssl_engine_context *cc,
+       int is_client, int prf_id,
+       const br_block_ctrcbc_class *bc_impl,
+       size_t cipher_key_len, size_t tag_len);
+
+/*
+ * Switch to GCM encryption for outgoing records.
+ *    cc               the engine context
+ *    is_client        non-zero for a client, zero for a server
+ *    prf_id           id of hash function for PRF
+ *    bc_impl          block cipher implementation (CTR+CBC)
+ *    cipher_key_len   block cipher key length (in bytes)
+ *    tag_len          tag length (in bytes)
+ */
+void br_ssl_engine_switch_ccm_out(br_ssl_engine_context *cc,
+       int is_client, int prf_id,
+       const br_block_ctrcbc_class *bc_impl,
+       size_t cipher_key_len, size_t tag_len);
+
 /*
  * Calls to T0-generated code.
  */
@@ -2243,18 +2361,25 @@ int br_ssl_choose_hash(unsigned bf);
  */
 #if BR_i386 || BR_amd64
 
+/*
+ * On GCC before version 5.0, we need to use the pragma to enable the
+ * target options globally, because the 'target' function attribute
+ * appears to be unreliable. Before 4.6 we must also avoid the
+ * push_options / pop_options mechanism, because it tends to trigger
+ * some internal compiler errors.
+ */
 #if BR_GCC && !BR_GCC_5_0
 #if BR_GCC_4_6
 #define BR_TARGETS_X86_UP \
        _Pragma("GCC push_options") \
        _Pragma("GCC target(\"sse2,ssse3,sse4.1,aes,pclmul,rdrnd\")")
+#define BR_TARGETS_X86_DOWN \
+       _Pragma("GCC pop_options")
 #else
 #define BR_TARGETS_X86_UP \
-       _Pragma("GCC push_options") \
        _Pragma("GCC target(\"sse2,ssse3,sse4.1,aes,pclmul\")")
 #endif
-#define BR_TARGETS_X86_DOWN \
-       _Pragma("GCC pop_options")
+#define BR_TARGETS_X86_DOWN
 #pragma GCC diagnostic ignored "-Wpsabi"
 #endif
 
@@ -2286,7 +2411,7 @@ int br_ssl_choose_hash(unsigned bf);
 BR_TARGETS_X86_UP
 #include <x86intrin.h>
 #include <cpuid.h>
-#define bswap32   __builtin_bswap32
+#define br_bswap32   __builtin_bswap32
 BR_TARGETS_X86_DOWN
 #endif
 
@@ -2294,7 +2419,7 @@ BR_TARGETS_X86_DOWN
 #include <stdlib.h>
 #include <intrin.h>
 #include <immintrin.h>
-#define bswap32   _byteswap_ulong
+#define br_bswap32   _byteswap_ulong
 #endif
 
 static inline int