aboutsummaryrefslogtreecommitdiffstats
path: root/test/monniaux/BearSSL/src/rsa
diff options
context:
space:
mode:
Diffstat (limited to 'test/monniaux/BearSSL/src/rsa')
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_default_keygen.c38
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_default_modulus.c36
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_default_oaep_decrypt.c38
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_default_oaep_encrypt.c38
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_default_pkcs1_sign.c38
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_default_pkcs1_vrfy.c38
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_default_priv.c38
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_default_privexp.c36
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_default_pss_sign.c38
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_default_pss_vrfy.c38
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_default_pub.c38
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_default_pubexp.c36
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i15_keygen.c583
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i15_modulus.c99
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i15_oaep_decrypt.c41
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i15_oaep_encrypt.c44
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i15_pkcs1_sign.c37
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i15_pkcs1_vrfy.c43
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i15_priv.c209
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i15_privexp.c320
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i15_pss_sign.c40
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i15_pss_vrfy.c44
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i15_pub.c113
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i15_pubexp.c152
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i31_keygen.c37
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i31_keygen_inner.c608
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i31_modulus.c99
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i31_oaep_decrypt.c41
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i31_oaep_encrypt.c44
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i31_pkcs1_sign.c37
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i31_pkcs1_vrfy.c43
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i31_priv.c203
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i31_privexp.c318
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i31_pss_sign.c40
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i31_pss_vrfy.c44
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i31_pub.c106
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i31_pubexp.c152
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i32_oaep_decrypt.c41
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i32_oaep_encrypt.c44
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i32_pkcs1_sign.c37
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i32_pkcs1_vrfy.c43
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i32_priv.c160
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i32_pss_sign.c40
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i32_pss_vrfy.c44
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i32_pub.c77
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i62_keygen.c57
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i62_oaep_decrypt.c61
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i62_oaep_encrypt.c64
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i62_pkcs1_sign.c57
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i62_pkcs1_vrfy.c63
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i62_priv.c223
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i62_pss_sign.c60
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i62_pss_vrfy.c64
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_i62_pub.c125
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_oaep_pad.c112
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_oaep_unpad.c145
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_pkcs1_sig_pad.c100
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_pkcs1_sig_unpad.c121
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_pss_sig_pad.c106
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_pss_sig_unpad.c121
-rw-r--r--test/monniaux/BearSSL/src/rsa/rsa_ssl_decrypt.c52
61 files changed, 5964 insertions, 0 deletions
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_default_keygen.c b/test/monniaux/BearSSL/src/rsa/rsa_default_keygen.c
new file mode 100644
index 00000000..f2e83c8d
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_default_keygen.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_keygen
+br_rsa_keygen_get_default(void)
+{
+#if BR_INT128 || BR_UMUL128
+ return &br_rsa_i62_keygen;
+#elif BR_LOMUL
+ return &br_rsa_i15_keygen;
+#else
+ return &br_rsa_i31_keygen;
+#endif
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_default_modulus.c b/test/monniaux/BearSSL/src/rsa/rsa_default_modulus.c
new file mode 100644
index 00000000..57d4be56
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_default_modulus.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_compute_modulus
+br_rsa_compute_modulus_get_default(void)
+{
+#if BR_LOMUL
+ return &br_rsa_i15_compute_modulus;
+#else
+ return &br_rsa_i31_compute_modulus;
+#endif
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_default_oaep_decrypt.c b/test/monniaux/BearSSL/src/rsa/rsa_default_oaep_decrypt.c
new file mode 100644
index 00000000..7345d64e
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_default_oaep_decrypt.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_oaep_decrypt
+br_rsa_oaep_decrypt_get_default(void)
+{
+#if BR_INT128 || BR_UMUL128
+ return &br_rsa_i62_oaep_decrypt;
+#elif BR_LOMUL
+ return &br_rsa_i15_oaep_decrypt;
+#else
+ return &br_rsa_i31_oaep_decrypt;
+#endif
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_default_oaep_encrypt.c b/test/monniaux/BearSSL/src/rsa/rsa_default_oaep_encrypt.c
new file mode 100644
index 00000000..ae33fcc6
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_default_oaep_encrypt.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_oaep_encrypt
+br_rsa_oaep_encrypt_get_default(void)
+{
+#if BR_INT128 || BR_UMUL128
+ return &br_rsa_i62_oaep_encrypt;
+#elif BR_LOMUL
+ return &br_rsa_i15_oaep_encrypt;
+#else
+ return &br_rsa_i31_oaep_encrypt;
+#endif
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_default_pkcs1_sign.c b/test/monniaux/BearSSL/src/rsa/rsa_default_pkcs1_sign.c
new file mode 100644
index 00000000..e926704f
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_default_pkcs1_sign.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_pkcs1_sign
+br_rsa_pkcs1_sign_get_default(void)
+{
+#if BR_INT128 || BR_UMUL128
+ return &br_rsa_i62_pkcs1_sign;
+#elif BR_LOMUL
+ return &br_rsa_i15_pkcs1_sign;
+#else
+ return &br_rsa_i31_pkcs1_sign;
+#endif
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_default_pkcs1_vrfy.c b/test/monniaux/BearSSL/src/rsa/rsa_default_pkcs1_vrfy.c
new file mode 100644
index 00000000..b3dbeb7b
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_default_pkcs1_vrfy.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_pkcs1_vrfy
+br_rsa_pkcs1_vrfy_get_default(void)
+{
+#if BR_INT128 || BR_UMUL128
+ return &br_rsa_i62_pkcs1_vrfy;
+#elif BR_LOMUL
+ return &br_rsa_i15_pkcs1_vrfy;
+#else
+ return &br_rsa_i31_pkcs1_vrfy;
+#endif
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_default_priv.c b/test/monniaux/BearSSL/src/rsa/rsa_default_priv.c
new file mode 100644
index 00000000..bb0b2c00
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_default_priv.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_private
+br_rsa_private_get_default(void)
+{
+#if BR_INT128 || BR_UMUL128
+ return &br_rsa_i62_private;
+#elif BR_LOMUL
+ return &br_rsa_i15_private;
+#else
+ return &br_rsa_i31_private;
+#endif
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_default_privexp.c b/test/monniaux/BearSSL/src/rsa/rsa_default_privexp.c
new file mode 100644
index 00000000..cda45559
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_default_privexp.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_compute_privexp
+br_rsa_compute_privexp_get_default(void)
+{
+#if BR_LOMUL
+ return &br_rsa_i15_compute_privexp;
+#else
+ return &br_rsa_i31_compute_privexp;
+#endif
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_default_pss_sign.c b/test/monniaux/BearSSL/src/rsa/rsa_default_pss_sign.c
new file mode 100644
index 00000000..ce4f3e07
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_default_pss_sign.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_pss_sign
+br_rsa_pss_sign_get_default(void)
+{
+#if BR_INT128 || BR_UMUL128
+ return &br_rsa_i62_pss_sign;
+#elif BR_LOMUL
+ return &br_rsa_i15_pss_sign;
+#else
+ return &br_rsa_i31_pss_sign;
+#endif
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_default_pss_vrfy.c b/test/monniaux/BearSSL/src/rsa/rsa_default_pss_vrfy.c
new file mode 100644
index 00000000..e3a9ad9f
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_default_pss_vrfy.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_pss_vrfy
+br_rsa_pss_vrfy_get_default(void)
+{
+#if BR_INT128 || BR_UMUL128
+ return &br_rsa_i62_pss_vrfy;
+#elif BR_LOMUL
+ return &br_rsa_i15_pss_vrfy;
+#else
+ return &br_rsa_i31_pss_vrfy;
+#endif
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_default_pub.c b/test/monniaux/BearSSL/src/rsa/rsa_default_pub.c
new file mode 100644
index 00000000..a1f03ef3
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_default_pub.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_public
+br_rsa_public_get_default(void)
+{
+#if BR_INT128 || BR_UMUL128
+ return &br_rsa_i62_public;
+#elif BR_LOMUL
+ return &br_rsa_i15_public;
+#else
+ return &br_rsa_i31_public;
+#endif
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_default_pubexp.c b/test/monniaux/BearSSL/src/rsa/rsa_default_pubexp.c
new file mode 100644
index 00000000..47bc0005
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_default_pubexp.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_compute_pubexp
+br_rsa_compute_pubexp_get_default(void)
+{
+#if BR_LOMUL
+ return &br_rsa_i15_compute_pubexp;
+#else
+ return &br_rsa_i31_compute_pubexp;
+#endif
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i15_keygen.c b/test/monniaux/BearSSL/src/rsa/rsa_i15_keygen.c
new file mode 100644
index 00000000..1c011fe0
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i15_keygen.c
@@ -0,0 +1,583 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/*
+ * Make a random integer of the provided size. The size is encoded.
+ * The header word is untouched.
+ */
+static void
+mkrand(const br_prng_class **rng, uint16_t *x, uint32_t esize)
+{
+ size_t u, len;
+ unsigned m;
+
+ len = (esize + 15) >> 4;
+ (*rng)->generate(rng, x + 1, len * sizeof(uint16_t));
+ for (u = 1; u < len; u ++) {
+ x[u] &= 0x7FFF;
+ }
+ m = esize & 15;
+ if (m == 0) {
+ x[len] &= 0x7FFF;
+ } else {
+ x[len] &= 0x7FFF >> (15 - m);
+ }
+}
+
+/*
+ * This is the big-endian unsigned representation of the product of
+ * all small primes from 13 to 1481.
+ */
+static const unsigned char SMALL_PRIMES[] = {
+ 0x2E, 0xAB, 0x92, 0xD1, 0x8B, 0x12, 0x47, 0x31, 0x54, 0x0A,
+ 0x99, 0x5D, 0x25, 0x5E, 0xE2, 0x14, 0x96, 0x29, 0x1E, 0xB7,
+ 0x78, 0x70, 0xCC, 0x1F, 0xA5, 0xAB, 0x8D, 0x72, 0x11, 0x37,
+ 0xFB, 0xD8, 0x1E, 0x3F, 0x5B, 0x34, 0x30, 0x17, 0x8B, 0xE5,
+ 0x26, 0x28, 0x23, 0xA1, 0x8A, 0xA4, 0x29, 0xEA, 0xFD, 0x9E,
+ 0x39, 0x60, 0x8A, 0xF3, 0xB5, 0xA6, 0xEB, 0x3F, 0x02, 0xB6,
+ 0x16, 0xC3, 0x96, 0x9D, 0x38, 0xB0, 0x7D, 0x82, 0x87, 0x0C,
+ 0xF7, 0xBE, 0x24, 0xE5, 0x5F, 0x41, 0x04, 0x79, 0x76, 0x40,
+ 0xE7, 0x00, 0x22, 0x7E, 0xB5, 0x85, 0x7F, 0x8D, 0x01, 0x50,
+ 0xE9, 0xD3, 0x29, 0x42, 0x08, 0xB3, 0x51, 0x40, 0x7B, 0xD7,
+ 0x8D, 0xCC, 0x10, 0x01, 0x64, 0x59, 0x28, 0xB6, 0x53, 0xF3,
+ 0x50, 0x4E, 0xB1, 0xF2, 0x58, 0xCD, 0x6E, 0xF5, 0x56, 0x3E,
+ 0x66, 0x2F, 0xD7, 0x07, 0x7F, 0x52, 0x4C, 0x13, 0x24, 0xDC,
+ 0x8E, 0x8D, 0xCC, 0xED, 0x77, 0xC4, 0x21, 0xD2, 0xFD, 0x08,
+ 0xEA, 0xD7, 0xC0, 0x5C, 0x13, 0x82, 0x81, 0x31, 0x2F, 0x2B,
+ 0x08, 0xE4, 0x80, 0x04, 0x7A, 0x0C, 0x8A, 0x3C, 0xDC, 0x22,
+ 0xE4, 0x5A, 0x7A, 0xB0, 0x12, 0x5E, 0x4A, 0x76, 0x94, 0x77,
+ 0xC2, 0x0E, 0x92, 0xBA, 0x8A, 0xA0, 0x1F, 0x14, 0x51, 0x1E,
+ 0x66, 0x6C, 0x38, 0x03, 0x6C, 0xC7, 0x4A, 0x4B, 0x70, 0x80,
+ 0xAF, 0xCA, 0x84, 0x51, 0xD8, 0xD2, 0x26, 0x49, 0xF5, 0xA8,
+ 0x5E, 0x35, 0x4B, 0xAC, 0xCE, 0x29, 0x92, 0x33, 0xB7, 0xA2,
+ 0x69, 0x7D, 0x0C, 0xE0, 0x9C, 0xDB, 0x04, 0xD6, 0xB4, 0xBC,
+ 0x39, 0xD7, 0x7F, 0x9E, 0x9D, 0x78, 0x38, 0x7F, 0x51, 0x54,
+ 0x50, 0x8B, 0x9E, 0x9C, 0x03, 0x6C, 0xF5, 0x9D, 0x2C, 0x74,
+ 0x57, 0xF0, 0x27, 0x2A, 0xC3, 0x47, 0xCA, 0xB9, 0xD7, 0x5C,
+ 0xFF, 0xC2, 0xAC, 0x65, 0x4E, 0xBD
+};
+
+/*
+ * We need temporary values for at least 7 integers of the same size
+ * as a factor (including header word); more space helps with performance
+ * (in modular exponentiations), but we much prefer to remain under
+ * 2 kilobytes in total, to save stack space. The macro TEMPS below
+ * exceeds 1024 (which is a count in 16-bit words) when BR_MAX_RSA_SIZE
+ * is greater than 4350 (default value is 4096, so the 2-kB limit is
+ * maintained unless BR_MAX_RSA_SIZE was modified).
+ */
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+#define TEMPS MAX(1024, 7 * ((((BR_MAX_RSA_SIZE + 1) >> 1) + 29) / 15))
+
+/*
+ * Perform trial division on a candidate prime. This computes
+ * y = SMALL_PRIMES mod x, then tries to compute y/y mod x. The
+ * br_i15_moddiv() function will report an error if y is not invertible
+ * modulo x. Returned value is 1 on success (none of the small primes
+ * divides x), 0 on error (a non-trivial GCD is obtained).
+ *
+ * This function assumes that x is odd.
+ */
+static uint32_t
+trial_divisions(const uint16_t *x, uint16_t *t)
+{
+ uint16_t *y;
+ uint16_t x0i;
+
+ y = t;
+ t += 1 + ((x[0] + 15) >> 4);
+ x0i = br_i15_ninv15(x[1]);
+ br_i15_decode_reduce(y, SMALL_PRIMES, sizeof SMALL_PRIMES, x);
+ return br_i15_moddiv(y, y, x, x0i, t);
+}
+
+/*
+ * Perform n rounds of Miller-Rabin on the candidate prime x. This
+ * function assumes that x = 3 mod 4.
+ *
+ * Returned value is 1 on success (all rounds completed successfully),
+ * 0 otherwise.
+ */
+static uint32_t
+miller_rabin(const br_prng_class **rng, const uint16_t *x, int n,
+ uint16_t *t, size_t tlen)
+{
+ /*
+ * Since x = 3 mod 4, the Miller-Rabin test is simple:
+ * - get a random base a (such that 1 < a < x-1)
+ * - compute z = a^((x-1)/2) mod x
+ * - if z != 1 and z != x-1, the number x is composite
+ *
+ * We generate bases 'a' randomly with a size which is
+ * one bit less than x, which ensures that a < x-1. It
+ * is not useful to verify that a > 1 because the probability
+ * that we get a value a equal to 0 or 1 is much smaller
+ * than the probability of our Miller-Rabin tests not to
+ * detect a composite, which is already quite smaller than the
+ * probability of the hardware misbehaving and return a
+ * composite integer because of some glitch (e.g. bad RAM
+ * or ill-timed cosmic ray).
+ */
+ unsigned char *xm1d2;
+ size_t xlen, xm1d2_len, xm1d2_len_u16, u;
+ uint32_t asize;
+ unsigned cc;
+ uint16_t x0i;
+
+ /*
+ * Compute (x-1)/2 (encoded).
+ */
+ xm1d2 = (unsigned char *)t;
+ xm1d2_len = ((x[0] - (x[0] >> 4)) + 7) >> 3;
+ br_i15_encode(xm1d2, xm1d2_len, x);
+ cc = 0;
+ for (u = 0; u < xm1d2_len; u ++) {
+ unsigned w;
+
+ w = xm1d2[u];
+ xm1d2[u] = (unsigned char)((w >> 1) | cc);
+ cc = w << 7;
+ }
+
+ /*
+ * We used some words of the provided buffer for (x-1)/2.
+ */
+ xm1d2_len_u16 = (xm1d2_len + 1) >> 1;
+ t += xm1d2_len_u16;
+ tlen -= xm1d2_len_u16;
+
+ xlen = (x[0] + 15) >> 4;
+ asize = x[0] - 1 - EQ0(x[0] & 15);
+ x0i = br_i15_ninv15(x[1]);
+ while (n -- > 0) {
+ uint16_t *a;
+ uint32_t eq1, eqm1;
+
+ /*
+ * Generate a random base. We don't need the base to be
+ * really uniform modulo x, so we just get a random
+ * number which is one bit shorter than x.
+ */
+ a = t;
+ a[0] = x[0];
+ a[xlen] = 0;
+ mkrand(rng, a, asize);
+
+ /*
+ * Compute a^((x-1)/2) mod x. We assume here that the
+ * function will not fail (the temporary array is large
+ * enough).
+ */
+ br_i15_modpow_opt(a, xm1d2, xm1d2_len,
+ x, x0i, t + 1 + xlen, tlen - 1 - xlen);
+
+ /*
+ * We must obtain either 1 or x-1. Note that x is odd,
+ * hence x-1 differs from x only in its low word (no
+ * carry).
+ */
+ eq1 = a[1] ^ 1;
+ eqm1 = a[1] ^ (x[1] - 1);
+ for (u = 2; u <= xlen; u ++) {
+ eq1 |= a[u];
+ eqm1 |= a[u] ^ x[u];
+ }
+
+ if ((EQ0(eq1) | EQ0(eqm1)) == 0) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*
+ * Create a random prime of the provided size. 'size' is the _encoded_
+ * bit length. The two top bits and the two bottom bits are set to 1.
+ */
+static void
+mkprime(const br_prng_class **rng, uint16_t *x, uint32_t esize,
+ uint32_t pubexp, uint16_t *t, size_t tlen)
+{
+ size_t len;
+
+ x[0] = esize;
+ len = (esize + 15) >> 4;
+ for (;;) {
+ size_t u;
+ uint32_t m3, m5, m7, m11;
+ int rounds;
+
+ /*
+ * Generate random bits. We force the two top bits and the
+ * two bottom bits to 1.
+ */
+ mkrand(rng, x, esize);
+ if ((esize & 15) == 0) {
+ x[len] |= 0x6000;
+ } else if ((esize & 15) == 1) {
+ x[len] |= 0x0001;
+ x[len - 1] |= 0x4000;
+ } else {
+ x[len] |= 0x0003 << ((esize & 15) - 2);
+ }
+ x[1] |= 0x0003;
+
+ /*
+ * Trial division with low primes (3, 5, 7 and 11). We
+ * use the following properties:
+ *
+ * 2^2 = 1 mod 3
+ * 2^4 = 1 mod 5
+ * 2^3 = 1 mod 7
+ * 2^10 = 1 mod 11
+ */
+ m3 = 0;
+ m5 = 0;
+ m7 = 0;
+ m11 = 0;
+ for (u = 0; u < len; u ++) {
+ uint32_t w;
+
+ w = x[1 + u];
+ m3 += w << (u & 1);
+ m3 = (m3 & 0xFF) + (m3 >> 8);
+ m5 += w << ((4 - u) & 3);
+ m5 = (m5 & 0xFF) + (m5 >> 8);
+ m7 += w;
+ m7 = (m7 & 0x1FF) + (m7 >> 9);
+ m11 += w << (5 & -(u & 1));
+ m11 = (m11 & 0x3FF) + (m11 >> 10);
+ }
+
+ /*
+ * Maximum values of m* at this point:
+ * m3: 511
+ * m5: 2310
+ * m7: 510
+ * m11: 2047
+ * We use the same properties to make further reductions.
+ */
+
+ m3 = (m3 & 0x0F) + (m3 >> 4); /* max: 46 */
+ m3 = (m3 & 0x0F) + (m3 >> 4); /* max: 16 */
+ m3 = ((m3 * 43) >> 5) & 3;
+
+ m5 = (m5 & 0xFF) + (m5 >> 8); /* max: 263 */
+ m5 = (m5 & 0x0F) + (m5 >> 4); /* max: 30 */
+ m5 = (m5 & 0x0F) + (m5 >> 4); /* max: 15 */
+ m5 -= 10 & -GT(m5, 9);
+ m5 -= 5 & -GT(m5, 4);
+
+ m7 = (m7 & 0x3F) + (m7 >> 6); /* max: 69 */
+ m7 = (m7 & 7) + (m7 >> 3); /* max: 14 */
+ m7 = ((m7 * 147) >> 7) & 7;
+
+ /*
+ * 2^5 = 32 = -1 mod 11.
+ */
+ m11 = (m11 & 0x1F) + 66 - (m11 >> 5); /* max: 97 */
+ m11 -= 88 & -GT(m11, 87);
+ m11 -= 44 & -GT(m11, 43);
+ m11 -= 22 & -GT(m11, 21);
+ m11 -= 11 & -GT(m11, 10);
+
+ /*
+ * If any of these modulo is 0, then the candidate is
+ * not prime. Also, if pubexp is 3, 5, 7 or 11, and the
+ * corresponding modulus is 1, then the candidate must
+ * be rejected, because we need e to be invertible
+ * modulo p-1. We can use simple comparisons here
+ * because they won't leak information on a candidate
+ * that we keep, only on one that we reject (and is thus
+ * not secret).
+ */
+ if (m3 == 0 || m5 == 0 || m7 == 0 || m11 == 0) {
+ continue;
+ }
+ if ((pubexp == 3 && m3 == 1)
+ || (pubexp == 5 && m5 == 5)
+ || (pubexp == 7 && m5 == 7)
+ || (pubexp == 11 && m5 == 11))
+ {
+ continue;
+ }
+
+ /*
+ * More trial divisions.
+ */
+ if (!trial_divisions(x, t)) {
+ continue;
+ }
+
+ /*
+ * Miller-Rabin algorithm. Since we selected a random
+ * integer, not a maliciously crafted integer, we can use
+ * relatively few rounds to lower the risk of a false
+ * positive (i.e. declaring prime a non-prime) under
+ * 2^(-80). It is not useful to lower the probability much
+ * below that, since that would be substantially below
+ * the probability of the hardware misbehaving. Sufficient
+ * numbers of rounds are extracted from the Handbook of
+ * Applied Cryptography, note 4.49 (page 149).
+ *
+ * Since we work on the encoded size (esize), we need to
+ * compare with encoded thresholds.
+ */
+ if (esize < 320) {
+ rounds = 12;
+ } else if (esize < 480) {
+ rounds = 9;
+ } else if (esize < 693) {
+ rounds = 6;
+ } else if (esize < 906) {
+ rounds = 4;
+ } else if (esize < 1386) {
+ rounds = 3;
+ } else {
+ rounds = 2;
+ }
+
+ if (miller_rabin(rng, x, rounds, t, tlen)) {
+ return;
+ }
+ }
+}
+
+/*
+ * Let p be a prime (p > 2^33, p = 3 mod 4). Let m = (p-1)/2, provided
+ * as parameter (with announced bit length equal to that of p). This
+ * function computes d = 1/e mod p-1 (for an odd integer e). Returned
+ * value is 1 on success, 0 on error (an error is reported if e is not
+ * invertible modulo p-1).
+ *
+ * The temporary buffer (t) must have room for at least 4 integers of
+ * the size of p.
+ */
+static uint32_t
+invert_pubexp(uint16_t *d, const uint16_t *m, uint32_t e, uint16_t *t)
+{
+ uint16_t *f;
+ uint32_t r;
+
+ f = t;
+ t += 1 + ((m[0] + 15) >> 4);
+
+ /*
+ * Compute d = 1/e mod m. Since p = 3 mod 4, m is odd.
+ */
+ br_i15_zero(d, m[0]);
+ d[1] = 1;
+ br_i15_zero(f, m[0]);
+ f[1] = e & 0x7FFF;
+ f[2] = (e >> 15) & 0x7FFF;
+ f[3] = e >> 30;
+ r = br_i15_moddiv(d, f, m, br_i15_ninv15(m[1]), t);
+
+ /*
+ * We really want d = 1/e mod p-1, with p = 2m. By the CRT,
+ * the result is either the d we got, or d + m.
+ *
+ * Let's write e*d = 1 + k*m, for some integer k. Integers e
+ * and m are odd. If d is odd, then e*d is odd, which implies
+ * that k must be even; in that case, e*d = 1 + (k/2)*2m, and
+ * thus d is already fine. Conversely, if d is even, then k
+ * is odd, and we must add m to d in order to get the correct
+ * result.
+ */
+ br_i15_add(d, m, (uint32_t)(1 - (d[1] & 1)));
+
+ return r;
+}
+
+/*
+ * Swap two buffers in RAM. They must be disjoint.
+ */
+static void
+bufswap(void *b1, void *b2, size_t len)
+{
+ size_t u;
+ unsigned char *buf1, *buf2;
+
+ buf1 = b1;
+ buf2 = b2;
+ for (u = 0; u < len; u ++) {
+ unsigned w;
+
+ w = buf1[u];
+ buf1[u] = buf2[u];
+ buf2[u] = w;
+ }
+}
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i15_keygen(const br_prng_class **rng,
+ br_rsa_private_key *sk, void *kbuf_priv,
+ br_rsa_public_key *pk, void *kbuf_pub,
+ unsigned size, uint32_t pubexp)
+{
+ uint32_t esize_p, esize_q;
+ size_t plen, qlen, tlen;
+ uint16_t *p, *q, *t;
+ uint16_t tmp[TEMPS];
+ uint32_t r;
+
+ if (size < BR_MIN_RSA_SIZE || size > BR_MAX_RSA_SIZE) {
+ return 0;
+ }
+ if (pubexp == 0) {
+ pubexp = 3;
+ } else if (pubexp == 1 || (pubexp & 1) == 0) {
+ return 0;
+ }
+
+ esize_p = (size + 1) >> 1;
+ esize_q = size - esize_p;
+ sk->n_bitlen = size;
+ sk->p = kbuf_priv;
+ sk->plen = (esize_p + 7) >> 3;
+ sk->q = sk->p + sk->plen;
+ sk->qlen = (esize_q + 7) >> 3;
+ sk->dp = sk->q + sk->qlen;
+ sk->dplen = sk->plen;
+ sk->dq = sk->dp + sk->dplen;
+ sk->dqlen = sk->qlen;
+ sk->iq = sk->dq + sk->dqlen;
+ sk->iqlen = sk->plen;
+
+ if (pk != NULL) {
+ pk->n = kbuf_pub;
+ pk->nlen = (size + 7) >> 3;
+ pk->e = pk->n + pk->nlen;
+ pk->elen = 4;
+ br_enc32be(pk->e, pubexp);
+ while (*pk->e == 0) {
+ pk->e ++;
+ pk->elen --;
+ }
+ }
+
+ /*
+ * We now switch to encoded sizes.
+ *
+ * floor((x * 17477) / (2^18)) is equal to floor(x/15) for all
+ * integers x from 0 to 23833.
+ */
+ esize_p += MUL15(esize_p, 17477) >> 18;
+ esize_q += MUL15(esize_q, 17477) >> 18;
+ plen = (esize_p + 15) >> 4;
+ qlen = (esize_q + 15) >> 4;
+ p = tmp;
+ q = p + 1 + plen;
+ t = q + 1 + qlen;
+ tlen = ((sizeof tmp) / sizeof(uint16_t)) - (2 + plen + qlen);
+
+ /*
+ * When looking for primes p and q, we temporarily divide
+ * candidates by 2, in order to compute the inverse of the
+ * public exponent.
+ */
+
+ for (;;) {
+ mkprime(rng, p, esize_p, pubexp, t, tlen);
+ br_i15_rshift(p, 1);
+ if (invert_pubexp(t, p, pubexp, t + 1 + plen)) {
+ br_i15_add(p, p, 1);
+ p[1] |= 1;
+ br_i15_encode(sk->p, sk->plen, p);
+ br_i15_encode(sk->dp, sk->dplen, t);
+ break;
+ }
+ }
+
+ for (;;) {
+ mkprime(rng, q, esize_q, pubexp, t, tlen);
+ br_i15_rshift(q, 1);
+ if (invert_pubexp(t, q, pubexp, t + 1 + qlen)) {
+ br_i15_add(q, q, 1);
+ q[1] |= 1;
+ br_i15_encode(sk->q, sk->qlen, q);
+ br_i15_encode(sk->dq, sk->dqlen, t);
+ break;
+ }
+ }
+
+ /*
+ * If p and q have the same size, then it is possible that q > p
+ * (when the target modulus size is odd, we generate p with a
+ * greater bit length than q). If q > p, we want to swap p and q
+ * (and also dp and dq) for two reasons:
+ * - The final step below (inversion of q modulo p) is easier if
+ * p > q.
+ * - While BearSSL's RSA code is perfectly happy with RSA keys such
+ * that p < q, some other implementations have restrictions and
+ * require p > q.
+ *
+ * Note that we can do a simple non-constant-time swap here,
+ * because the only information we leak here is that we insist on
+ * returning p and q such that p > q, which is not a secret.
+ */
+ if (esize_p == esize_q && br_i15_sub(p, q, 0) == 1) {
+ bufswap(p, q, (1 + plen) * sizeof *p);
+ bufswap(sk->p, sk->q, sk->plen);
+ bufswap(sk->dp, sk->dq, sk->dplen);
+ }
+
+ /*
+ * We have produced p, q, dp and dq. We can now compute iq = 1/d mod p.
+ *
+ * We ensured that p >= q, so this is just a matter of updating the
+ * header word for q (and possibly adding an extra word).
+ *
+ * Theoretically, the call below may fail, in case we were
+ * extraordinarily unlucky, and p = q. Another failure case is if
+ * Miller-Rabin failed us _twice_, and p and q are non-prime and
+ * have a factor is common. We report the error mostly because it
+ * is cheap and we can, but in practice this never happens (or, at
+ * least, it happens way less often than hardware glitches).
+ */
+ q[0] = p[0];
+ if (plen > qlen) {
+ q[plen] = 0;
+ t ++;
+ tlen --;
+ }
+ br_i15_zero(t, p[0]);
+ t[1] = 1;
+ r = br_i15_moddiv(t, q, p, br_i15_ninv15(p[1]), t + 1 + plen);
+ br_i15_encode(sk->iq, sk->iqlen, t);
+
+ /*
+ * Compute the public modulus too, if required.
+ */
+ if (pk != NULL) {
+ br_i15_zero(t, p[0]);
+ br_i15_mulacc(t, p, q);
+ br_i15_encode(pk->n, pk->nlen, t);
+ }
+
+ return r;
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i15_modulus.c b/test/monniaux/BearSSL/src/rsa/rsa_i15_modulus.c
new file mode 100644
index 00000000..16458c3e
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i15_modulus.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+size_t
+br_rsa_i15_compute_modulus(void *n, const br_rsa_private_key *sk)
+{
+ uint16_t tmp[4 * (((BR_MAX_RSA_SIZE / 2) + 14) / 15) + 5];
+ uint16_t *t, *p, *q;
+ const unsigned char *pbuf, *qbuf;
+ size_t nlen, plen, qlen, tlen;
+
+ /*
+ * Compute actual byte and lengths for p and q.
+ */
+ pbuf = sk->p;
+ plen = sk->plen;
+ while (plen > 0 && *pbuf == 0) {
+ pbuf ++;
+ plen --;
+ }
+ qbuf = sk->q;
+ qlen = sk->qlen;
+ while (qlen > 0 && *qbuf == 0) {
+ qbuf ++;
+ qlen --;
+ }
+
+ t = tmp;
+ tlen = (sizeof tmp) / (sizeof tmp[0]);
+
+ /*
+ * Decode p.
+ */
+ if ((15 * tlen) < (plen << 3) + 15) {
+ return 0;
+ }
+ br_i15_decode(t, pbuf, plen);
+ p = t;
+ plen = (p[0] + 31) >> 4;
+ t += plen;
+ tlen -= plen;
+
+ /*
+ * Decode q.
+ */
+ if ((15 * tlen) < (qlen << 3) + 15) {
+ return 0;
+ }
+ br_i15_decode(t, qbuf, qlen);
+ q = t;
+ qlen = (q[0] + 31) >> 4;
+ t += qlen;
+ tlen -= qlen;
+
+ /*
+ * Computation can proceed only if we have enough room for the
+ * modulus.
+ */
+ if (tlen < (plen + qlen + 1)) {
+ return 0;
+ }
+
+ /*
+ * Private key already contains the modulus bit length, from which
+ * we can infer the output length. Even if n is NULL, we still had
+ * to decode p and q to make sure that the product can be computed.
+ */
+ nlen = (sk->n_bitlen + 7) >> 3;
+ if (n != NULL) {
+ br_i15_zero(t, p[0]);
+ br_i15_mulacc(t, p, q);
+ br_i15_encode(n, nlen, t);
+ }
+ return nlen;
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i15_oaep_decrypt.c b/test/monniaux/BearSSL/src/rsa/rsa_i15_oaep_decrypt.c
new file mode 100644
index 00000000..927eecd8
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i15_oaep_decrypt.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i15_oaep_decrypt(const br_hash_class *dig,
+ const void *label, size_t label_len,
+ const br_rsa_private_key *sk, void *data, size_t *len)
+{
+ uint32_t r;
+
+ if (*len != ((sk->n_bitlen + 7) >> 3)) {
+ return 0;
+ }
+ r = br_rsa_i15_private(data, sk);
+ r &= br_rsa_oaep_unpad(dig, label, label_len, data, len);
+ return r;
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i15_oaep_encrypt.c b/test/monniaux/BearSSL/src/rsa/rsa_i15_oaep_encrypt.c
new file mode 100644
index 00000000..b9a6cfa4
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i15_oaep_encrypt.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+size_t
+br_rsa_i15_oaep_encrypt(
+ 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_max_len,
+ const void *src, size_t src_len)
+{
+ size_t dlen;
+
+ dlen = br_rsa_oaep_pad(rnd, dig, label, label_len,
+ pk, dst, dst_max_len, src, src_len);
+ if (dlen == 0) {
+ return 0;
+ }
+ return dlen & -(size_t)br_rsa_i15_public(dst, dlen, pk);
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i15_pkcs1_sign.c b/test/monniaux/BearSSL/src/rsa/rsa_i15_pkcs1_sign.c
new file mode 100644
index 00000000..f519423d
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i15_pkcs1_sign.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i15_pkcs1_sign(const unsigned char *hash_oid,
+ const unsigned char *hash, size_t hash_len,
+ const br_rsa_private_key *sk, unsigned char *x)
+{
+ if (!br_rsa_pkcs1_sig_pad(hash_oid, hash, hash_len, sk->n_bitlen, x)) {
+ return 0;
+ }
+ return br_rsa_i15_private(x, sk);
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i15_pkcs1_vrfy.c b/test/monniaux/BearSSL/src/rsa/rsa_i15_pkcs1_vrfy.c
new file mode 100644
index 00000000..2c351849
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i15_pkcs1_vrfy.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i15_pkcs1_vrfy(const unsigned char *x, size_t xlen,
+ const unsigned char *hash_oid, size_t hash_len,
+ const br_rsa_public_key *pk, unsigned char *hash_out)
+{
+ unsigned char sig[BR_MAX_RSA_SIZE >> 3];
+
+ if (xlen > (sizeof sig)) {
+ return 0;
+ }
+ memcpy(sig, x, xlen);
+ if (!br_rsa_i15_public(sig, xlen, pk)) {
+ return 0;
+ }
+ return br_rsa_pkcs1_sig_unpad(sig, xlen, hash_oid, hash_len, hash_out);
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i15_priv.c b/test/monniaux/BearSSL/src/rsa/rsa_i15_priv.c
new file mode 100644
index 00000000..177cc3a6
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i15_priv.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+#define U (2 + ((BR_MAX_RSA_FACTOR + 14) / 15))
+#define TLEN (8 * U)
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i15_private(unsigned char *x, const br_rsa_private_key *sk)
+{
+ const unsigned char *p, *q;
+ size_t plen, qlen;
+ size_t fwlen;
+ uint16_t p0i, q0i;
+ size_t xlen, u;
+ uint16_t tmp[1 + TLEN];
+ long z;
+ uint16_t *mp, *mq, *s1, *s2, *t1, *t2, *t3;
+ uint32_t r;
+
+ /*
+ * Compute the actual lengths of p and q, in bytes.
+ * These lengths are not considered secret (we cannot really hide
+ * them anyway in constant-time code).
+ */
+ p = sk->p;
+ plen = sk->plen;
+ while (plen > 0 && *p == 0) {
+ p ++;
+ plen --;
+ }
+ q = sk->q;
+ qlen = sk->qlen;
+ while (qlen > 0 && *q == 0) {
+ q ++;
+ qlen --;
+ }
+
+ /*
+ * Compute the maximum factor length, in words.
+ */
+ z = (long)(plen > qlen ? plen : qlen) << 3;
+ fwlen = 1;
+ while (z > 0) {
+ z -= 15;
+ fwlen ++;
+ }
+ /*
+ * Round up the word length to an even number.
+ */
+ fwlen += (fwlen & 1);
+
+ /*
+ * We need to fit at least 6 values in the stack buffer.
+ */
+ if (6 * fwlen > TLEN) {
+ return 0;
+ }
+
+ /*
+ * Compute signature length (in bytes).
+ */
+ xlen = (sk->n_bitlen + 7) >> 3;
+
+ /*
+ * Ensure 32-bit alignment for value words.
+ */
+ mq = tmp;
+ if (((uintptr_t)mq & 2) == 0) {
+ mq ++;
+ }
+
+ /*
+ * Decode q.
+ */
+ br_i15_decode(mq, q, qlen);
+
+ /*
+ * Decode p.
+ */
+ t1 = mq + fwlen;
+ br_i15_decode(t1, p, plen);
+
+ /*
+ * Compute the modulus (product of the two factors), to compare
+ * it with the source value. We use br_i15_mulacc(), since it's
+ * already used later on.
+ */
+ t2 = mq + 2 * fwlen;
+ br_i15_zero(t2, mq[0]);
+ br_i15_mulacc(t2, mq, t1);
+
+ /*
+ * We encode the modulus into bytes, to perform the comparison
+ * with bytes. We know that the product length, in bytes, is
+ * exactly xlen.
+ * The comparison actually computes the carry when subtracting
+ * the modulus from the source value; that carry must be 1 for
+ * a value in the correct range. We keep it in r, which is our
+ * accumulator for the error code.
+ */
+ t3 = mq + 4 * fwlen;
+ br_i15_encode(t3, xlen, t2);
+ u = xlen;
+ r = 0;
+ while (u > 0) {
+ uint32_t wn, wx;
+
+ u --;
+ wn = ((unsigned char *)t3)[u];
+ wx = x[u];
+ r = ((wx - (wn + r)) >> 8) & 1;
+ }
+
+ /*
+ * Move the decoded p to another temporary buffer.
+ */
+ mp = mq + 2 * fwlen;
+ memmove(mp, t1, fwlen * sizeof *t1);
+
+ /*
+ * Compute s2 = x^dq mod q.
+ */
+ q0i = br_i15_ninv15(mq[1]);
+ s2 = mq + fwlen;
+ br_i15_decode_reduce(s2, x, xlen, mq);
+ r &= br_i15_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i,
+ mq + 3 * fwlen, TLEN - 3 * fwlen);
+
+ /*
+ * Compute s1 = x^dq mod q.
+ */
+ p0i = br_i15_ninv15(mp[1]);
+ s1 = mq + 3 * fwlen;
+ br_i15_decode_reduce(s1, x, xlen, mp);
+ r &= br_i15_modpow_opt(s1, sk->dp, sk->dplen, mp, p0i,
+ mq + 4 * fwlen, TLEN - 4 * fwlen);
+
+ /*
+ * Compute:
+ * h = (s1 - s2)*(1/q) mod p
+ * s1 is an integer modulo p, but s2 is modulo q. PKCS#1 is
+ * unclear about whether p may be lower than q (some existing,
+ * widely deployed implementations of RSA don't tolerate p < q),
+ * but we want to support that occurrence, so we need to use the
+ * reduction function.
+ *
+ * Since we use br_i15_decode_reduce() for iq (purportedly, the
+ * inverse of q modulo p), we also tolerate improperly large
+ * values for this parameter.
+ */
+ t1 = mq + 4 * fwlen;
+ t2 = mq + 5 * fwlen;
+ br_i15_reduce(t2, s2, mp);
+ br_i15_add(s1, mp, br_i15_sub(s1, t2, 1));
+ br_i15_to_monty(s1, mp);
+ br_i15_decode_reduce(t1, sk->iq, sk->iqlen, mp);
+ br_i15_montymul(t2, s1, t1, mp, p0i);
+
+ /*
+ * h is now in t2. We compute the final result:
+ * s = s2 + q*h
+ * All these operations are non-modular.
+ *
+ * We need mq, s2 and t2. We use the t3 buffer as destination.
+ * The buffers mp, s1 and t1 are no longer needed, so we can
+ * reuse them for t3. Moreover, the first step of the computation
+ * is to copy s2 into t3, after which s2 is not needed. Right
+ * now, mq is in slot 0, s2 is in slot 1, and t2 in slot 5.
+ * Therefore, we have ample room for t3 by simply using s2.
+ */
+ t3 = s2;
+ br_i15_mulacc(t3, mq, t2);
+
+ /*
+ * Encode the result. Since we already checked the value of xlen,
+ * we can just use it right away.
+ */
+ br_i15_encode(x, xlen, t3);
+
+ /*
+ * The only error conditions remaining at that point are invalid
+ * values for p and q (even integers).
+ */
+ return p0i & q0i & r;
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i15_privexp.c b/test/monniaux/BearSSL/src/rsa/rsa_i15_privexp.c
new file mode 100644
index 00000000..57d6918e
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i15_privexp.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+size_t
+br_rsa_i15_compute_privexp(void *d,
+ const br_rsa_private_key *sk, uint32_t e)
+{
+ /*
+ * We want to invert e modulo phi = (p-1)(q-1). This first
+ * requires computing phi, which is easy since we have the factors
+ * p and q in the private key structure.
+ *
+ * Since p = 3 mod 4 and q = 3 mod 4, phi/4 is an odd integer.
+ * We could invert e modulo phi/4 then patch the result to
+ * modulo phi, but this would involve assembling three modulus-wide
+ * values (phi/4, 1 and e) and calling moddiv, that requires
+ * three more temporaries, for a total of six big integers, or
+ * slightly more than 3 kB of stack space for RSA-4096. This
+ * exceeds our stack requirements.
+ *
+ * Instead, we first use one step of the extended GCD:
+ *
+ * - We compute phi = k*e + r (Euclidean division of phi by e).
+ * If public exponent e is correct, then r != 0 (e must be
+ * invertible modulo phi). We also have k != 0 since we
+ * enforce non-ridiculously-small factors.
+ *
+ * - We find small u, v such that u*e - v*r = 1 (using a
+ * binary GCD; we can arrange for u < r and v < e, i.e. all
+ * values fit on 32 bits).
+ *
+ * - Solution is: d = u + v*k
+ * This last computation is exact: since u < r and v < e,
+ * the above implies d < r + e*((phi-r)/e) = phi
+ */
+
+ uint16_t tmp[4 * ((BR_MAX_RSA_FACTOR + 14) / 15) + 12];
+ uint16_t *p, *q, *k, *m, *z, *phi;
+ const unsigned char *pbuf, *qbuf;
+ size_t plen, qlen, u, len, dlen;
+ uint32_t r, a, b, u0, v0, u1, v1, he, hr;
+ int i;
+
+ /*
+ * Check that e is correct.
+ */
+ if (e < 3 || (e & 1) == 0) {
+ return 0;
+ }
+
+ /*
+ * Check lengths of p and q, and that they are both odd.
+ */
+ pbuf = sk->p;
+ plen = sk->plen;
+ while (plen > 0 && *pbuf == 0) {
+ pbuf ++;
+ plen --;
+ }
+ if (plen < 5 || plen > (BR_MAX_RSA_FACTOR / 8)
+ || (pbuf[plen - 1] & 1) != 1)
+ {
+ return 0;
+ }
+ qbuf = sk->q;
+ qlen = sk->qlen;
+ while (qlen > 0 && *qbuf == 0) {
+ qbuf ++;
+ qlen --;
+ }
+ if (qlen < 5 || qlen > (BR_MAX_RSA_FACTOR / 8)
+ || (qbuf[qlen - 1] & 1) != 1)
+ {
+ return 0;
+ }
+
+ /*
+ * Output length is that of the modulus.
+ */
+ dlen = (sk->n_bitlen + 7) >> 3;
+ if (d == NULL) {
+ return dlen;
+ }
+
+ p = tmp;
+ br_i15_decode(p, pbuf, plen);
+ plen = (p[0] + 15) >> 4;
+ q = p + 1 + plen;
+ br_i15_decode(q, qbuf, qlen);
+ qlen = (q[0] + 15) >> 4;
+
+ /*
+ * Compute phi = (p-1)*(q-1), then move it over p-1 and q-1 (that
+ * we do not need anymore). The mulacc function sets the announced
+ * bit length of t to be the sum of the announced bit lengths of
+ * p-1 and q-1, which is usually exact but may overshoot by one 1
+ * bit in some cases; we readjust it to its true length.
+ */
+ p[1] --;
+ q[1] --;
+ phi = q + 1 + qlen;
+ br_i15_zero(phi, p[0]);
+ br_i15_mulacc(phi, p, q);
+ len = (phi[0] + 15) >> 4;
+ memmove(tmp, phi, (1 + len) * sizeof *phi);
+ phi = tmp;
+ phi[0] = br_i15_bit_length(phi + 1, len);
+ len = (phi[0] + 15) >> 4;
+
+ /*
+ * Divide phi by public exponent e. The final remainder r must be
+ * non-zero (otherwise, the key is invalid). The quotient is k,
+ * which we write over phi, since we don't need phi after that.
+ */
+ r = 0;
+ for (u = len; u >= 1; u --) {
+ /*
+ * Upon entry, r < e, and phi[u] < 2^15; hence,
+ * hi:lo < e*2^15. Thus, the produced word k[u]
+ * must be lower than 2^15, and the new remainder r
+ * is lower than e.
+ */
+ uint32_t hi, lo;
+
+ hi = r >> 17;
+ lo = (r << 15) + phi[u];
+ phi[u] = br_divrem(hi, lo, e, &r);
+ }
+ if (r == 0) {
+ return 0;
+ }
+ k = phi;
+
+ /*
+ * Compute u and v such that u*e - v*r = GCD(e,r). We use
+ * a binary GCD algorithm, with 6 extra integers a, b,
+ * u0, u1, v0 and v1. Initial values are:
+ * a = e u0 = 1 v0 = 0
+ * b = r u1 = r v1 = e-1
+ * The following invariants are maintained:
+ * a = u0*e - v0*r
+ * b = u1*e - v1*r
+ * 0 < a <= e
+ * 0 < b <= r
+ * 0 <= u0 <= r
+ * 0 <= v0 <= e
+ * 0 <= u1 <= r
+ * 0 <= v1 <= e
+ *
+ * At each iteration, we reduce either a or b by one bit, and
+ * adjust u0, u1, v0 and v1 to maintain the invariants:
+ * - if a is even, then a <- a/2
+ * - otherwise, if b is even, then b <- b/2
+ * - otherwise, if a > b, then a <- (a-b)/2
+ * - otherwise, if b > a, then b <- (b-a)/2
+ * Algorithm stops when a = b. At that point, the common value
+ * is the GCD of e and r; it must be 1 (otherwise, the private
+ * key or public exponent is not valid). The (u0,v0) or (u1,v1)
+ * pairs are the solution we are looking for.
+ *
+ * Since either a or b is reduced by at least 1 bit at each
+ * iteration, 62 iterations are enough to reach the end
+ * condition.
+ *
+ * To maintain the invariants, we must compute the same operations
+ * on the u* and v* values that we do on a and b:
+ * - When a is divided by 2, u0 and v0 must be divided by 2.
+ * - When b is divided by 2, u1 and v1 must be divided by 2.
+ * - When b is subtracted from a, u1 and v1 are subtracted from
+ * u0 and v0, respectively.
+ * - When a is subtracted from b, u0 and v0 are subtracted from
+ * u1 and v1, respectively.
+ *
+ * However, we want to keep the u* and v* values in their proper
+ * ranges. The following remarks apply:
+ *
+ * - When a is divided by 2, then a is even. Therefore:
+ *
+ * * If r is odd, then u0 and v0 must have the same parity;
+ * if they are both odd, then adding r to u0 and e to v0
+ * makes them both even, and the division by 2 brings them
+ * back to the proper range.
+ *
+ * * If r is even, then u0 must be even; if v0 is odd, then
+ * adding r to u0 and e to v0 makes them both even, and the
+ * division by 2 brings them back to the proper range.
+ *
+ * Thus, all we need to do is to look at the parity of v0,
+ * and add (r,e) to (u0,v0) when v0 is odd. In order to avoid
+ * a 32-bit overflow, we can add ((r+1)/2,(e/2)+1) after the
+ * division (r+1 does not overflow since r < e; and (e/2)+1
+ * is equal to (e+1)/2 since e is odd).
+ *
+ * - When we subtract b from a, three cases may occur:
+ *
+ * * u1 <= u0 and v1 <= v0: just do the subtractions
+ *
+ * * u1 > u0 and v1 > v0: compute:
+ * (u0, v0) <- (u0 + r - u1, v0 + e - v1)
+ *
+ * * u1 <= u0 and v1 > v0: compute:
+ * (u0, v0) <- (u0 + r - u1, v0 + e - v1)
+ *
+ * The fourth case (u1 > u0 and v1 <= v0) is not possible
+ * because it would contradict "b < a" (which is the reason
+ * why we subtract b from a).
+ *
+ * The tricky case is the third one: from the equations, it
+ * seems that u0 may go out of range. However, the invariants
+ * and ranges of other values imply that, in that case, the
+ * new u0 does not actually exceed the range.
+ *
+ * We can thus handle the subtraction by adding (r,e) based
+ * solely on the comparison between v0 and v1.
+ */
+ a = e;
+ b = r;
+ u0 = 1;
+ v0 = 0;
+ u1 = r;
+ v1 = e - 1;
+ hr = (r + 1) >> 1;
+ he = (e >> 1) + 1;
+ for (i = 0; i < 62; i ++) {
+ uint32_t oa, ob, agtb, bgta;
+ uint32_t sab, sba, da, db;
+ uint32_t ctl;
+
+ oa = a & 1; /* 1 if a is odd */
+ ob = b & 1; /* 1 if b is odd */
+ agtb = GT(a, b); /* 1 if a > b */
+ bgta = GT(b, a); /* 1 if b > a */
+
+ sab = oa & ob & agtb; /* 1 if a <- a-b */
+ sba = oa & ob & bgta; /* 1 if b <- b-a */
+
+ /* a <- a-b, u0 <- u0-u1, v0 <- v0-v1 */
+ ctl = GT(v1, v0);
+ a -= b & -sab;
+ u0 -= (u1 - (r & -ctl)) & -sab;
+ v0 -= (v1 - (e & -ctl)) & -sab;
+
+ /* b <- b-a, u1 <- u1-u0 mod r, v1 <- v1-v0 mod e */
+ ctl = GT(v0, v1);
+ b -= a & -sba;
+ u1 -= (u0 - (r & -ctl)) & -sba;
+ v1 -= (v0 - (e & -ctl)) & -sba;
+
+ da = NOT(oa) | sab; /* 1 if a <- a/2 */
+ db = (oa & NOT(ob)) | sba; /* 1 if b <- b/2 */
+
+ /* a <- a/2, u0 <- u0/2, v0 <- v0/2 */
+ ctl = v0 & 1;
+ a ^= (a ^ (a >> 1)) & -da;
+ u0 ^= (u0 ^ ((u0 >> 1) + (hr & -ctl))) & -da;
+ v0 ^= (v0 ^ ((v0 >> 1) + (he & -ctl))) & -da;
+
+ /* b <- b/2, u1 <- u1/2 mod r, v1 <- v1/2 mod e */
+ ctl = v1 & 1;
+ b ^= (b ^ (b >> 1)) & -db;
+ u1 ^= (u1 ^ ((u1 >> 1) + (hr & -ctl))) & -db;
+ v1 ^= (v1 ^ ((v1 >> 1) + (he & -ctl))) & -db;
+ }
+
+ /*
+ * Check that the GCD is indeed 1. If not, then the key is invalid
+ * (and there's no harm in leaking that piece of information).
+ */
+ if (a != 1) {
+ return 0;
+ }
+
+ /*
+ * Now we have u0*e - v0*r = 1. Let's compute the result as:
+ * d = u0 + v0*k
+ * We still have k in the tmp[] array, and its announced bit
+ * length is that of phi.
+ */
+ m = k + 1 + len;
+ m[0] = (2 << 4) + 2; /* bit length is 32 bits, encoded */
+ m[1] = v0 & 0x7FFF;
+ m[2] = (v0 >> 15) & 0x7FFF;
+ m[3] = v0 >> 30;
+ z = m + 4;
+ br_i15_zero(z, k[0]);
+ z[1] = u0 & 0x7FFF;
+ z[2] = (u0 >> 15) & 0x7FFF;
+ z[3] = u0 >> 30;
+ br_i15_mulacc(z, k, m);
+
+ /*
+ * Encode the result.
+ */
+ br_i15_encode(d, dlen, z);
+ return dlen;
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i15_pss_sign.c b/test/monniaux/BearSSL/src/rsa/rsa_i15_pss_sign.c
new file mode 100644
index 00000000..dd9385b0
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i15_pss_sign.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i15_pss_sign(const br_prng_class **rng,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const unsigned char *hash, size_t salt_len,
+ const br_rsa_private_key *sk, unsigned char *x)
+{
+ if (!br_rsa_pss_sig_pad(rng, hf_data, hf_mgf1, hash,
+ salt_len, sk->n_bitlen, x))
+ {
+ return 0;
+ }
+ return br_rsa_i15_private(x, sk);
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i15_pss_vrfy.c b/test/monniaux/BearSSL/src/rsa/rsa_i15_pss_vrfy.c
new file mode 100644
index 00000000..7d9f2cbc
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i15_pss_vrfy.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i15_pss_vrfy(const unsigned char *x, size_t xlen,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const void *hash, size_t salt_len, const br_rsa_public_key *pk)
+{
+ unsigned char sig[BR_MAX_RSA_SIZE >> 3];
+
+ if (xlen > (sizeof sig)) {
+ return 0;
+ }
+ memcpy(sig, x, xlen);
+ if (!br_rsa_i15_public(sig, xlen, pk)) {
+ return 0;
+ }
+ return br_rsa_pss_sig_unpad(hf_data, hf_mgf1,
+ hash, salt_len, pk, sig);
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i15_pub.c b/test/monniaux/BearSSL/src/rsa/rsa_i15_pub.c
new file mode 100644
index 00000000..9eab5e84
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i15_pub.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/*
+ * As a strict minimum, we need four buffers that can hold a
+ * modular integer.
+ */
+#define TLEN (4 * (2 + ((BR_MAX_RSA_SIZE + 14) / 15)))
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i15_public(unsigned char *x, size_t xlen,
+ const br_rsa_public_key *pk)
+{
+ const unsigned char *n;
+ size_t nlen;
+ uint16_t tmp[1 + TLEN];
+ uint16_t *m, *a, *t;
+ size_t fwlen;
+ long z;
+ uint16_t m0i;
+ uint32_t r;
+
+ /*
+ * Get the actual length of the modulus, and see if it fits within
+ * our stack buffer. We also check that the length of x[] is valid.
+ */
+ n = pk->n;
+ nlen = pk->nlen;
+ while (nlen > 0 && *n == 0) {
+ n ++;
+ nlen --;
+ }
+ if (nlen == 0 || nlen > (BR_MAX_RSA_SIZE >> 3) || xlen != nlen) {
+ return 0;
+ }
+ z = (long)nlen << 3;
+ fwlen = 1;
+ while (z > 0) {
+ z -= 15;
+ fwlen ++;
+ }
+ /*
+ * Round up length to an even number.
+ */
+ fwlen += (fwlen & 1);
+
+ /*
+ * The modulus gets decoded into m[].
+ * The value to exponentiate goes into a[].
+ * The temporaries for modular exponentiations are in t[].
+ *
+ * We want the first value word of each integer to be aligned
+ * on a 32-bit boundary.
+ */
+ m = tmp;
+ if (((uintptr_t)m & 2) == 0) {
+ m ++;
+ }
+ a = m + fwlen;
+ t = m + 2 * fwlen;
+
+ /*
+ * Decode the modulus.
+ */
+ br_i15_decode(m, n, nlen);
+ m0i = br_i15_ninv15(m[1]);
+
+ /*
+ * Note: if m[] is even, then m0i == 0. Otherwise, m0i must be
+ * an odd integer.
+ */
+ r = m0i & 1;
+
+ /*
+ * Decode x[] into a[]; we also check that its value is proper.
+ */
+ r &= br_i15_decode_mod(a, x, xlen, m);
+
+ /*
+ * Compute the modular exponentiation.
+ */
+ br_i15_modpow_opt(a, pk->e, pk->elen, m, m0i, t, TLEN - 2 * fwlen);
+
+ /*
+ * Encode the result.
+ */
+ br_i15_encode(x, xlen, a);
+ return r;
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i15_pubexp.c b/test/monniaux/BearSSL/src/rsa/rsa_i15_pubexp.c
new file mode 100644
index 00000000..803bff79
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i15_pubexp.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/*
+ * Recompute public exponent, based on factor p and reduced private
+ * exponent dp.
+ */
+static uint32_t
+get_pubexp(const unsigned char *pbuf, size_t plen,
+ const unsigned char *dpbuf, size_t dplen)
+{
+ /*
+ * dp is the inverse of e modulo p-1. If p = 3 mod 4, then
+ * p-1 = 2*((p-1)/2). Taken modulo 2, e is odd and has inverse 1;
+ * thus, dp must be odd.
+ *
+ * We compute the inverse of dp modulo (p-1)/2. This requires
+ * first reducing dp modulo (p-1)/2 (this can be done with a
+ * conditional subtract, no need to use the generic modular
+ * reduction function); then, we use moddiv.
+ */
+
+ uint16_t tmp[6 * ((BR_MAX_RSA_FACTOR + 29) / 15)];
+ uint16_t *p, *dp, *x;
+ size_t len;
+ uint32_t e;
+
+ /*
+ * Compute actual factor length (in bytes) and check that it fits
+ * under our size constraints.
+ */
+ while (plen > 0 && *pbuf == 0) {
+ pbuf ++;
+ plen --;
+ }
+ if (plen == 0 || plen < 5 || plen > (BR_MAX_RSA_FACTOR / 8)) {
+ return 0;
+ }
+
+ /*
+ * Compute actual reduced exponent length (in bytes) and check that
+ * it is not longer than p.
+ */
+ while (dplen > 0 && *dpbuf == 0) {
+ dpbuf ++;
+ dplen --;
+ }
+ if (dplen > plen || dplen == 0
+ || (dplen == plen && dpbuf[0] > pbuf[0]))
+ {
+ return 0;
+ }
+
+ /*
+ * Verify that p = 3 mod 4 and that dp is odd.
+ */
+ if ((pbuf[plen - 1] & 3) != 3 || (dpbuf[dplen - 1] & 1) != 1) {
+ return 0;
+ }
+
+ /*
+ * Decode p and compute (p-1)/2.
+ */
+ p = tmp;
+ br_i15_decode(p, pbuf, plen);
+ len = (p[0] + 31) >> 4;
+ br_i15_rshift(p, 1);
+
+ /*
+ * Decode dp and make sure its announced bit length matches that of
+ * p (we already know that the size of dp, in bits, does not exceed
+ * the size of p, so we just have to copy the header word).
+ */
+ dp = p + len;
+ memset(dp, 0, len * sizeof *dp);
+ br_i15_decode(dp, dpbuf, dplen);
+ dp[0] = p[0];
+
+ /*
+ * Subtract (p-1)/2 from dp if necessary.
+ */
+ br_i15_sub(dp, p, NOT(br_i15_sub(dp, p, 0)));
+
+ /*
+ * If another subtraction is needed, then this means that the
+ * value was invalid. We don't care to leak information about
+ * invalid keys.
+ */
+ if (br_i15_sub(dp, p, 0) == 0) {
+ return 0;
+ }
+
+ /*
+ * Invert dp modulo (p-1)/2. If the inversion fails, then the
+ * key value was invalid.
+ */
+ x = dp + len;
+ br_i15_zero(x, p[0]);
+ x[1] = 1;
+ if (br_i15_moddiv(x, dp, p, br_i15_ninv15(p[1]), x + len) == 0) {
+ return 0;
+ }
+
+ /*
+ * We now have an inverse. We must set it to zero (error) if its
+ * length is greater than 32 bits and/or if it is an even integer.
+ * Take care that the bit_length function returns an encoded
+ * bit length.
+ */
+ e = (uint32_t)x[1] | ((uint32_t)x[2] << 15) | ((uint32_t)x[3] << 30);
+ e &= -LT(br_i15_bit_length(x + 1, len - 1), 35);
+ e &= -(e & 1);
+ return e;
+}
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i15_compute_pubexp(const br_rsa_private_key *sk)
+{
+ /*
+ * Get the public exponent from both p and q. This is the right
+ * exponent if we get twice the same value.
+ */
+ uint32_t ep, eq;
+
+ ep = get_pubexp(sk->p, sk->plen, sk->dp, sk->dplen);
+ eq = get_pubexp(sk->q, sk->qlen, sk->dq, sk->dqlen);
+ return ep & -EQ(ep, eq);
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i31_keygen.c b/test/monniaux/BearSSL/src/rsa/rsa_i31_keygen.c
new file mode 100644
index 00000000..77708f8b
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i31_keygen.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i31_keygen(const br_prng_class **rng,
+ br_rsa_private_key *sk, void *kbuf_priv,
+ br_rsa_public_key *pk, void *kbuf_pub,
+ unsigned size, uint32_t pubexp)
+{
+ return br_rsa_i31_keygen_inner(rng,
+ sk, kbuf_priv, pk, kbuf_pub, size, pubexp,
+ &br_i31_modpow_opt);
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i31_keygen_inner.c b/test/monniaux/BearSSL/src/rsa/rsa_i31_keygen_inner.c
new file mode 100644
index 00000000..9ec881b5
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i31_keygen_inner.c
@@ -0,0 +1,608 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/*
+ * Make a random integer of the provided size. The size is encoded.
+ * The header word is untouched.
+ */
+static void
+mkrand(const br_prng_class **rng, uint32_t *x, uint32_t esize)
+{
+ size_t u, len;
+ unsigned m;
+
+ len = (esize + 31) >> 5;
+ (*rng)->generate(rng, x + 1, len * sizeof(uint32_t));
+ for (u = 1; u < len; u ++) {
+ x[u] &= 0x7FFFFFFF;
+ }
+ m = esize & 31;
+ if (m == 0) {
+ x[len] &= 0x7FFFFFFF;
+ } else {
+ x[len] &= 0x7FFFFFFF >> (31 - m);
+ }
+}
+
+/*
+ * This is the big-endian unsigned representation of the product of
+ * all small primes from 13 to 1481.
+ */
+static const unsigned char SMALL_PRIMES[] = {
+ 0x2E, 0xAB, 0x92, 0xD1, 0x8B, 0x12, 0x47, 0x31, 0x54, 0x0A,
+ 0x99, 0x5D, 0x25, 0x5E, 0xE2, 0x14, 0x96, 0x29, 0x1E, 0xB7,
+ 0x78, 0x70, 0xCC, 0x1F, 0xA5, 0xAB, 0x8D, 0x72, 0x11, 0x37,
+ 0xFB, 0xD8, 0x1E, 0x3F, 0x5B, 0x34, 0x30, 0x17, 0x8B, 0xE5,
+ 0x26, 0x28, 0x23, 0xA1, 0x8A, 0xA4, 0x29, 0xEA, 0xFD, 0x9E,
+ 0x39, 0x60, 0x8A, 0xF3, 0xB5, 0xA6, 0xEB, 0x3F, 0x02, 0xB6,
+ 0x16, 0xC3, 0x96, 0x9D, 0x38, 0xB0, 0x7D, 0x82, 0x87, 0x0C,
+ 0xF7, 0xBE, 0x24, 0xE5, 0x5F, 0x41, 0x04, 0x79, 0x76, 0x40,
+ 0xE7, 0x00, 0x22, 0x7E, 0xB5, 0x85, 0x7F, 0x8D, 0x01, 0x50,
+ 0xE9, 0xD3, 0x29, 0x42, 0x08, 0xB3, 0x51, 0x40, 0x7B, 0xD7,
+ 0x8D, 0xCC, 0x10, 0x01, 0x64, 0x59, 0x28, 0xB6, 0x53, 0xF3,
+ 0x50, 0x4E, 0xB1, 0xF2, 0x58, 0xCD, 0x6E, 0xF5, 0x56, 0x3E,
+ 0x66, 0x2F, 0xD7, 0x07, 0x7F, 0x52, 0x4C, 0x13, 0x24, 0xDC,
+ 0x8E, 0x8D, 0xCC, 0xED, 0x77, 0xC4, 0x21, 0xD2, 0xFD, 0x08,
+ 0xEA, 0xD7, 0xC0, 0x5C, 0x13, 0x82, 0x81, 0x31, 0x2F, 0x2B,
+ 0x08, 0xE4, 0x80, 0x04, 0x7A, 0x0C, 0x8A, 0x3C, 0xDC, 0x22,
+ 0xE4, 0x5A, 0x7A, 0xB0, 0x12, 0x5E, 0x4A, 0x76, 0x94, 0x77,
+ 0xC2, 0x0E, 0x92, 0xBA, 0x8A, 0xA0, 0x1F, 0x14, 0x51, 0x1E,
+ 0x66, 0x6C, 0x38, 0x03, 0x6C, 0xC7, 0x4A, 0x4B, 0x70, 0x80,
+ 0xAF, 0xCA, 0x84, 0x51, 0xD8, 0xD2, 0x26, 0x49, 0xF5, 0xA8,
+ 0x5E, 0x35, 0x4B, 0xAC, 0xCE, 0x29, 0x92, 0x33, 0xB7, 0xA2,
+ 0x69, 0x7D, 0x0C, 0xE0, 0x9C, 0xDB, 0x04, 0xD6, 0xB4, 0xBC,
+ 0x39, 0xD7, 0x7F, 0x9E, 0x9D, 0x78, 0x38, 0x7F, 0x51, 0x54,
+ 0x50, 0x8B, 0x9E, 0x9C, 0x03, 0x6C, 0xF5, 0x9D, 0x2C, 0x74,
+ 0x57, 0xF0, 0x27, 0x2A, 0xC3, 0x47, 0xCA, 0xB9, 0xD7, 0x5C,
+ 0xFF, 0xC2, 0xAC, 0x65, 0x4E, 0xBD
+};
+
+/*
+ * We need temporary values for at least 7 integers of the same size
+ * as a factor (including header word); more space helps with performance
+ * (in modular exponentiations), but we much prefer to remain under
+ * 2 kilobytes in total, to save stack space. The macro TEMPS below
+ * exceeds 512 (which is a count in 32-bit words) when BR_MAX_RSA_SIZE
+ * is greater than 4464 (default value is 4096, so the 2-kB limit is
+ * maintained unless BR_MAX_RSA_SIZE was modified).
+ */
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+#define ROUND2(x) ((((x) + 1) >> 1) << 1)
+
+#define TEMPS MAX(512, ROUND2(7 * ((((BR_MAX_RSA_SIZE + 1) >> 1) + 61) / 31)))
+
+/*
+ * Perform trial division on a candidate prime. This computes
+ * y = SMALL_PRIMES mod x, then tries to compute y/y mod x. The
+ * br_i31_moddiv() function will report an error if y is not invertible
+ * modulo x. Returned value is 1 on success (none of the small primes
+ * divides x), 0 on error (a non-trivial GCD is obtained).
+ *
+ * This function assumes that x is odd.
+ */
+static uint32_t
+trial_divisions(const uint32_t *x, uint32_t *t)
+{
+ uint32_t *y;
+ uint32_t x0i;
+
+ y = t;
+ t += 1 + ((x[0] + 31) >> 5);
+ x0i = br_i31_ninv31(x[1]);
+ br_i31_decode_reduce(y, SMALL_PRIMES, sizeof SMALL_PRIMES, x);
+ return br_i31_moddiv(y, y, x, x0i, t);
+}
+
+/*
+ * Perform n rounds of Miller-Rabin on the candidate prime x. This
+ * function assumes that x = 3 mod 4.
+ *
+ * Returned value is 1 on success (all rounds completed successfully),
+ * 0 otherwise.
+ */
+static uint32_t
+miller_rabin(const br_prng_class **rng, const uint32_t *x, int n,
+ uint32_t *t, size_t tlen, br_i31_modpow_opt_type mp31)
+{
+ /*
+ * Since x = 3 mod 4, the Miller-Rabin test is simple:
+ * - get a random base a (such that 1 < a < x-1)
+ * - compute z = a^((x-1)/2) mod x
+ * - if z != 1 and z != x-1, the number x is composite
+ *
+ * We generate bases 'a' randomly with a size which is
+ * one bit less than x, which ensures that a < x-1. It
+ * is not useful to verify that a > 1 because the probability
+ * that we get a value a equal to 0 or 1 is much smaller
+ * than the probability of our Miller-Rabin tests not to
+ * detect a composite, which is already quite smaller than the
+ * probability of the hardware misbehaving and return a
+ * composite integer because of some glitch (e.g. bad RAM
+ * or ill-timed cosmic ray).
+ */
+ unsigned char *xm1d2;
+ size_t xlen, xm1d2_len, xm1d2_len_u32, u;
+ uint32_t asize;
+ unsigned cc;
+ uint32_t x0i;
+
+ /*
+ * Compute (x-1)/2 (encoded).
+ */
+ xm1d2 = (unsigned char *)t;
+ xm1d2_len = ((x[0] - (x[0] >> 5)) + 7) >> 3;
+ br_i31_encode(xm1d2, xm1d2_len, x);
+ cc = 0;
+ for (u = 0; u < xm1d2_len; u ++) {
+ unsigned w;
+
+ w = xm1d2[u];
+ xm1d2[u] = (unsigned char)((w >> 1) | cc);
+ cc = w << 7;
+ }
+
+ /*
+ * We used some words of the provided buffer for (x-1)/2.
+ */
+ xm1d2_len_u32 = (xm1d2_len + 3) >> 2;
+ t += xm1d2_len_u32;
+ tlen -= xm1d2_len_u32;
+
+ xlen = (x[0] + 31) >> 5;
+ asize = x[0] - 1 - EQ0(x[0] & 31);
+ x0i = br_i31_ninv31(x[1]);
+ while (n -- > 0) {
+ uint32_t *a, *t2;
+ uint32_t eq1, eqm1;
+ size_t t2len;
+
+ /*
+ * Generate a random base. We don't need the base to be
+ * really uniform modulo x, so we just get a random
+ * number which is one bit shorter than x.
+ */
+ a = t;
+ a[0] = x[0];
+ a[xlen] = 0;
+ mkrand(rng, a, asize);
+
+ /*
+ * Compute a^((x-1)/2) mod x. We assume here that the
+ * function will not fail (the temporary array is large
+ * enough).
+ */
+ t2 = t + 1 + xlen;
+ t2len = tlen - 1 - xlen;
+ if ((t2len & 1) != 0) {
+ /*
+ * Since the source array is 64-bit aligned and
+ * has an even number of elements (TEMPS), we
+ * can use the parity of the remaining length to
+ * detect and adjust alignment.
+ */
+ t2 ++;
+ t2len --;
+ }
+ mp31(a, xm1d2, xm1d2_len, x, x0i, t2, t2len);
+
+ /*
+ * We must obtain either 1 or x-1. Note that x is odd,
+ * hence x-1 differs from x only in its low word (no
+ * carry).
+ */
+ eq1 = a[1] ^ 1;
+ eqm1 = a[1] ^ (x[1] - 1);
+ for (u = 2; u <= xlen; u ++) {
+ eq1 |= a[u];
+ eqm1 |= a[u] ^ x[u];
+ }
+
+ if ((EQ0(eq1) | EQ0(eqm1)) == 0) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*
+ * Create a random prime of the provided size. 'size' is the _encoded_
+ * bit length. The two top bits and the two bottom bits are set to 1.
+ */
+static void
+mkprime(const br_prng_class **rng, uint32_t *x, uint32_t esize,
+ uint32_t pubexp, uint32_t *t, size_t tlen, br_i31_modpow_opt_type mp31)
+{
+ size_t len;
+
+ x[0] = esize;
+ len = (esize + 31) >> 5;
+ for (;;) {
+ size_t u;
+ uint32_t m3, m5, m7, m11;
+ int rounds, s7, s11;
+
+ /*
+ * Generate random bits. We force the two top bits and the
+ * two bottom bits to 1.
+ */
+ mkrand(rng, x, esize);
+ if ((esize & 31) == 0) {
+ x[len] |= 0x60000000;
+ } else if ((esize & 31) == 1) {
+ x[len] |= 0x00000001;
+ x[len - 1] |= 0x40000000;
+ } else {
+ x[len] |= 0x00000003 << ((esize & 31) - 2);
+ }
+ x[1] |= 0x00000003;
+
+ /*
+ * Trial division with low primes (3, 5, 7 and 11). We
+ * use the following properties:
+ *
+ * 2^2 = 1 mod 3
+ * 2^4 = 1 mod 5
+ * 2^3 = 1 mod 7
+ * 2^10 = 1 mod 11
+ */
+ m3 = 0;
+ m5 = 0;
+ m7 = 0;
+ m11 = 0;
+ s7 = 0;
+ s11 = 0;
+ for (u = 0; u < len; u ++) {
+ uint32_t w, w3, w5, w7, w11;
+
+ w = x[1 + u];
+ w3 = (w & 0xFFFF) + (w >> 16); /* max: 98302 */
+ w5 = (w & 0xFFFF) + (w >> 16); /* max: 98302 */
+ w7 = (w & 0x7FFF) + (w >> 15); /* max: 98302 */
+ w11 = (w & 0xFFFFF) + (w >> 20); /* max: 1050622 */
+
+ m3 += w3 << (u & 1);
+ m3 = (m3 & 0xFF) + (m3 >> 8); /* max: 1025 */
+
+ m5 += w5 << ((4 - u) & 3);
+ m5 = (m5 & 0xFFF) + (m5 >> 12); /* max: 4479 */
+
+ m7 += w7 << s7;
+ m7 = (m7 & 0x1FF) + (m7 >> 9); /* max: 1280 */
+ if (++ s7 == 3) {
+ s7 = 0;
+ }
+
+ m11 += w11 << s11;
+ if (++ s11 == 10) {
+ s11 = 0;
+ }
+ m11 = (m11 & 0x3FF) + (m11 >> 10); /* max: 526847 */
+ }
+
+ m3 = (m3 & 0x3F) + (m3 >> 6); /* max: 78 */
+ m3 = (m3 & 0x0F) + (m3 >> 4); /* max: 18 */
+ m3 = ((m3 * 43) >> 5) & 3;
+
+ m5 = (m5 & 0xFF) + (m5 >> 8); /* max: 271 */
+ m5 = (m5 & 0x0F) + (m5 >> 4); /* max: 31 */
+ m5 -= 20 & -GT(m5, 19);
+ m5 -= 10 & -GT(m5, 9);
+ m5 -= 5 & -GT(m5, 4);
+
+ m7 = (m7 & 0x3F) + (m7 >> 6); /* max: 82 */
+ m7 = (m7 & 0x07) + (m7 >> 3); /* max: 16 */
+ m7 = ((m7 * 147) >> 7) & 7;
+
+ /*
+ * 2^5 = 32 = -1 mod 11.
+ */
+ m11 = (m11 & 0x3FF) + (m11 >> 10); /* max: 1536 */
+ m11 = (m11 & 0x3FF) + (m11 >> 10); /* max: 1023 */
+ m11 = (m11 & 0x1F) + 33 - (m11 >> 5); /* max: 64 */
+ m11 -= 44 & -GT(m11, 43);
+ m11 -= 22 & -GT(m11, 21);
+ m11 -= 11 & -GT(m11, 10);
+
+ /*
+ * If any of these modulo is 0, then the candidate is
+ * not prime. Also, if pubexp is 3, 5, 7 or 11, and the
+ * corresponding modulus is 1, then the candidate must
+ * be rejected, because we need e to be invertible
+ * modulo p-1. We can use simple comparisons here
+ * because they won't leak information on a candidate
+ * that we keep, only on one that we reject (and is thus
+ * not secret).
+ */
+ if (m3 == 0 || m5 == 0 || m7 == 0 || m11 == 0) {
+ continue;
+ }
+ if ((pubexp == 3 && m3 == 1)
+ || (pubexp == 5 && m5 == 5)
+ || (pubexp == 7 && m5 == 7)
+ || (pubexp == 11 && m5 == 11))
+ {
+ continue;
+ }
+
+ /*
+ * More trial divisions.
+ */
+ if (!trial_divisions(x, t)) {
+ continue;
+ }
+
+ /*
+ * Miller-Rabin algorithm. Since we selected a random
+ * integer, not a maliciously crafted integer, we can use
+ * relatively few rounds to lower the risk of a false
+ * positive (i.e. declaring prime a non-prime) under
+ * 2^(-80). It is not useful to lower the probability much
+ * below that, since that would be substantially below
+ * the probability of the hardware misbehaving. Sufficient
+ * numbers of rounds are extracted from the Handbook of
+ * Applied Cryptography, note 4.49 (page 149).
+ *
+ * Since we work on the encoded size (esize), we need to
+ * compare with encoded thresholds.
+ */
+ if (esize < 309) {
+ rounds = 12;
+ } else if (esize < 464) {
+ rounds = 9;
+ } else if (esize < 670) {
+ rounds = 6;
+ } else if (esize < 877) {
+ rounds = 4;
+ } else if (esize < 1341) {
+ rounds = 3;
+ } else {
+ rounds = 2;
+ }
+
+ if (miller_rabin(rng, x, rounds, t, tlen, mp31)) {
+ return;
+ }
+ }
+}
+
+/*
+ * Let p be a prime (p > 2^33, p = 3 mod 4). Let m = (p-1)/2, provided
+ * as parameter (with announced bit length equal to that of p). This
+ * function computes d = 1/e mod p-1 (for an odd integer e). Returned
+ * value is 1 on success, 0 on error (an error is reported if e is not
+ * invertible modulo p-1).
+ *
+ * The temporary buffer (t) must have room for at least 4 integers of
+ * the size of p.
+ */
+static uint32_t
+invert_pubexp(uint32_t *d, const uint32_t *m, uint32_t e, uint32_t *t)
+{
+ uint32_t *f;
+ uint32_t r;
+
+ f = t;
+ t += 1 + ((m[0] + 31) >> 5);
+
+ /*
+ * Compute d = 1/e mod m. Since p = 3 mod 4, m is odd.
+ */
+ br_i31_zero(d, m[0]);
+ d[1] = 1;
+ br_i31_zero(f, m[0]);
+ f[1] = e & 0x7FFFFFFF;
+ f[2] = e >> 31;
+ r = br_i31_moddiv(d, f, m, br_i31_ninv31(m[1]), t);
+
+ /*
+ * We really want d = 1/e mod p-1, with p = 2m. By the CRT,
+ * the result is either the d we got, or d + m.
+ *
+ * Let's write e*d = 1 + k*m, for some integer k. Integers e
+ * and m are odd. If d is odd, then e*d is odd, which implies
+ * that k must be even; in that case, e*d = 1 + (k/2)*2m, and
+ * thus d is already fine. Conversely, if d is even, then k
+ * is odd, and we must add m to d in order to get the correct
+ * result.
+ */
+ br_i31_add(d, m, (uint32_t)(1 - (d[1] & 1)));
+
+ return r;
+}
+
+/*
+ * Swap two buffers in RAM. They must be disjoint.
+ */
+static void
+bufswap(void *b1, void *b2, size_t len)
+{
+ size_t u;
+ unsigned char *buf1, *buf2;
+
+ buf1 = b1;
+ buf2 = b2;
+ for (u = 0; u < len; u ++) {
+ unsigned w;
+
+ w = buf1[u];
+ buf1[u] = buf2[u];
+ buf2[u] = w;
+ }
+}
+
+/* see inner.h */
+uint32_t
+br_rsa_i31_keygen_inner(const br_prng_class **rng,
+ br_rsa_private_key *sk, void *kbuf_priv,
+ br_rsa_public_key *pk, void *kbuf_pub,
+ unsigned size, uint32_t pubexp, br_i31_modpow_opt_type mp31)
+{
+ uint32_t esize_p, esize_q;
+ size_t plen, qlen, tlen;
+ uint32_t *p, *q, *t;
+ union {
+ uint32_t t32[TEMPS];
+ uint64_t t64[TEMPS >> 1]; /* for 64-bit alignment */
+ } tmp;
+ uint32_t r;
+
+ if (size < BR_MIN_RSA_SIZE || size > BR_MAX_RSA_SIZE) {
+ return 0;
+ }
+ if (pubexp == 0) {
+ pubexp = 3;
+ } else if (pubexp == 1 || (pubexp & 1) == 0) {
+ return 0;
+ }
+
+ esize_p = (size + 1) >> 1;
+ esize_q = size - esize_p;
+ sk->n_bitlen = size;
+ sk->p = kbuf_priv;
+ sk->plen = (esize_p + 7) >> 3;
+ sk->q = sk->p + sk->plen;
+ sk->qlen = (esize_q + 7) >> 3;
+ sk->dp = sk->q + sk->qlen;
+ sk->dplen = sk->plen;
+ sk->dq = sk->dp + sk->dplen;
+ sk->dqlen = sk->qlen;
+ sk->iq = sk->dq + sk->dqlen;
+ sk->iqlen = sk->plen;
+
+ if (pk != NULL) {
+ pk->n = kbuf_pub;
+ pk->nlen = (size + 7) >> 3;
+ pk->e = pk->n + pk->nlen;
+ pk->elen = 4;
+ br_enc32be(pk->e, pubexp);
+ while (*pk->e == 0) {
+ pk->e ++;
+ pk->elen --;
+ }
+ }
+
+ /*
+ * We now switch to encoded sizes.
+ *
+ * floor((x * 16913) / (2^19)) is equal to floor(x/31) for all
+ * integers x from 0 to 34966; the intermediate product fits on
+ * 30 bits, thus we can use MUL31().
+ */
+ esize_p += MUL31(esize_p, 16913) >> 19;
+ esize_q += MUL31(esize_q, 16913) >> 19;
+ plen = (esize_p + 31) >> 5;
+ qlen = (esize_q + 31) >> 5;
+ p = tmp.t32;
+ q = p + 1 + plen;
+ t = q + 1 + qlen;
+ tlen = ((sizeof tmp.t32) / sizeof(uint32_t)) - (2 + plen + qlen);
+
+ /*
+ * When looking for primes p and q, we temporarily divide
+ * candidates by 2, in order to compute the inverse of the
+ * public exponent.
+ */
+
+ for (;;) {
+ mkprime(rng, p, esize_p, pubexp, t, tlen, mp31);
+ br_i31_rshift(p, 1);
+ if (invert_pubexp(t, p, pubexp, t + 1 + plen)) {
+ br_i31_add(p, p, 1);
+ p[1] |= 1;
+ br_i31_encode(sk->p, sk->plen, p);
+ br_i31_encode(sk->dp, sk->dplen, t);
+ break;
+ }
+ }
+
+ for (;;) {
+ mkprime(rng, q, esize_q, pubexp, t, tlen, mp31);
+ br_i31_rshift(q, 1);
+ if (invert_pubexp(t, q, pubexp, t + 1 + qlen)) {
+ br_i31_add(q, q, 1);
+ q[1] |= 1;
+ br_i31_encode(sk->q, sk->qlen, q);
+ br_i31_encode(sk->dq, sk->dqlen, t);
+ break;
+ }
+ }
+
+ /*
+ * If p and q have the same size, then it is possible that q > p
+ * (when the target modulus size is odd, we generate p with a
+ * greater bit length than q). If q > p, we want to swap p and q
+ * (and also dp and dq) for two reasons:
+ * - The final step below (inversion of q modulo p) is easier if
+ * p > q.
+ * - While BearSSL's RSA code is perfectly happy with RSA keys such
+ * that p < q, some other implementations have restrictions and
+ * require p > q.
+ *
+ * Note that we can do a simple non-constant-time swap here,
+ * because the only information we leak here is that we insist on
+ * returning p and q such that p > q, which is not a secret.
+ */
+ if (esize_p == esize_q && br_i31_sub(p, q, 0) == 1) {
+ bufswap(p, q, (1 + plen) * sizeof *p);
+ bufswap(sk->p, sk->q, sk->plen);
+ bufswap(sk->dp, sk->dq, sk->dplen);
+ }
+
+ /*
+ * We have produced p, q, dp and dq. We can now compute iq = 1/d mod p.
+ *
+ * We ensured that p >= q, so this is just a matter of updating the
+ * header word for q (and possibly adding an extra word).
+ *
+ * Theoretically, the call below may fail, in case we were
+ * extraordinarily unlucky, and p = q. Another failure case is if
+ * Miller-Rabin failed us _twice_, and p and q are non-prime and
+ * have a factor is common. We report the error mostly because it
+ * is cheap and we can, but in practice this never happens (or, at
+ * least, it happens way less often than hardware glitches).
+ */
+ q[0] = p[0];
+ if (plen > qlen) {
+ q[plen] = 0;
+ t ++;
+ tlen --;
+ }
+ br_i31_zero(t, p[0]);
+ t[1] = 1;
+ r = br_i31_moddiv(t, q, p, br_i31_ninv31(p[1]), t + 1 + plen);
+ br_i31_encode(sk->iq, sk->iqlen, t);
+
+ /*
+ * Compute the public modulus too, if required.
+ */
+ if (pk != NULL) {
+ br_i31_zero(t, p[0]);
+ br_i31_mulacc(t, p, q);
+ br_i31_encode(pk->n, pk->nlen, t);
+ }
+
+ return r;
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i31_modulus.c b/test/monniaux/BearSSL/src/rsa/rsa_i31_modulus.c
new file mode 100644
index 00000000..f5f997f5
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i31_modulus.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+size_t
+br_rsa_i31_compute_modulus(void *n, const br_rsa_private_key *sk)
+{
+ uint32_t tmp[4 * (((BR_MAX_RSA_SIZE / 2) + 30) / 31) + 5];
+ uint32_t *t, *p, *q;
+ const unsigned char *pbuf, *qbuf;
+ size_t nlen, plen, qlen, tlen;
+
+ /*
+ * Compute actual byte and lengths for p and q.
+ */
+ pbuf = sk->p;
+ plen = sk->plen;
+ while (plen > 0 && *pbuf == 0) {
+ pbuf ++;
+ plen --;
+ }
+ qbuf = sk->q;
+ qlen = sk->qlen;
+ while (qlen > 0 && *qbuf == 0) {
+ qbuf ++;
+ qlen --;
+ }
+
+ t = tmp;
+ tlen = (sizeof tmp) / (sizeof tmp[0]);
+
+ /*
+ * Decode p.
+ */
+ if ((31 * tlen) < (plen << 3) + 31) {
+ return 0;
+ }
+ br_i31_decode(t, pbuf, plen);
+ p = t;
+ plen = (p[0] + 63) >> 5;
+ t += plen;
+ tlen -= plen;
+
+ /*
+ * Decode q.
+ */
+ if ((31 * tlen) < (qlen << 3) + 31) {
+ return 0;
+ }
+ br_i31_decode(t, qbuf, qlen);
+ q = t;
+ qlen = (q[0] + 63) >> 5;
+ t += qlen;
+ tlen -= qlen;
+
+ /*
+ * Computation can proceed only if we have enough room for the
+ * modulus.
+ */
+ if (tlen < (plen + qlen + 1)) {
+ return 0;
+ }
+
+ /*
+ * Private key already contains the modulus bit length, from which
+ * we can infer the output length. Even if n is NULL, we still had
+ * to decode p and q to make sure that the product can be computed.
+ */
+ nlen = (sk->n_bitlen + 7) >> 3;
+ if (n != NULL) {
+ br_i31_zero(t, p[0]);
+ br_i31_mulacc(t, p, q);
+ br_i31_encode(n, nlen, t);
+ }
+ return nlen;
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i31_oaep_decrypt.c b/test/monniaux/BearSSL/src/rsa/rsa_i31_oaep_decrypt.c
new file mode 100644
index 00000000..06fdd93c
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i31_oaep_decrypt.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i31_oaep_decrypt(const br_hash_class *dig,
+ const void *label, size_t label_len,
+ const br_rsa_private_key *sk, void *data, size_t *len)
+{
+ uint32_t r;
+
+ if (*len != ((sk->n_bitlen + 7) >> 3)) {
+ return 0;
+ }
+ r = br_rsa_i31_private(data, sk);
+ r &= br_rsa_oaep_unpad(dig, label, label_len, data, len);
+ return r;
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i31_oaep_encrypt.c b/test/monniaux/BearSSL/src/rsa/rsa_i31_oaep_encrypt.c
new file mode 100644
index 00000000..367008ce
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i31_oaep_encrypt.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+size_t
+br_rsa_i31_oaep_encrypt(
+ 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_max_len,
+ const void *src, size_t src_len)
+{
+ size_t dlen;
+
+ dlen = br_rsa_oaep_pad(rnd, dig, label, label_len,
+ pk, dst, dst_max_len, src, src_len);
+ if (dlen == 0) {
+ return 0;
+ }
+ return dlen & -(size_t)br_rsa_i31_public(dst, dlen, pk);
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i31_pkcs1_sign.c b/test/monniaux/BearSSL/src/rsa/rsa_i31_pkcs1_sign.c
new file mode 100644
index 00000000..784d3c20
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i31_pkcs1_sign.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i31_pkcs1_sign(const unsigned char *hash_oid,
+ const unsigned char *hash, size_t hash_len,
+ const br_rsa_private_key *sk, unsigned char *x)
+{
+ if (!br_rsa_pkcs1_sig_pad(hash_oid, hash, hash_len, sk->n_bitlen, x)) {
+ return 0;
+ }
+ return br_rsa_i31_private(x, sk);
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i31_pkcs1_vrfy.c b/test/monniaux/BearSSL/src/rsa/rsa_i31_pkcs1_vrfy.c
new file mode 100644
index 00000000..e79a002d
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i31_pkcs1_vrfy.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i31_pkcs1_vrfy(const unsigned char *x, size_t xlen,
+ const unsigned char *hash_oid, size_t hash_len,
+ const br_rsa_public_key *pk, unsigned char *hash_out)
+{
+ unsigned char sig[BR_MAX_RSA_SIZE >> 3];
+
+ if (xlen > (sizeof sig)) {
+ return 0;
+ }
+ memcpy(sig, x, xlen);
+ if (!br_rsa_i31_public(sig, xlen, pk)) {
+ return 0;
+ }
+ return br_rsa_pkcs1_sig_unpad(sig, xlen, hash_oid, hash_len, hash_out);
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i31_priv.c b/test/monniaux/BearSSL/src/rsa/rsa_i31_priv.c
new file mode 100644
index 00000000..b1e1244e
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i31_priv.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+#define U (2 + ((BR_MAX_RSA_FACTOR + 30) / 31))
+#define TLEN (8 * U)
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i31_private(unsigned char *x, const br_rsa_private_key *sk)
+{
+ const unsigned char *p, *q;
+ size_t plen, qlen;
+ size_t fwlen;
+ uint32_t p0i, q0i;
+ size_t xlen, u;
+ uint32_t tmp[1 + TLEN];
+ long z;
+ uint32_t *mp, *mq, *s1, *s2, *t1, *t2, *t3;
+ uint32_t r;
+
+ /*
+ * Compute the actual lengths of p and q, in bytes.
+ * These lengths are not considered secret (we cannot really hide
+ * them anyway in constant-time code).
+ */
+ p = sk->p;
+ plen = sk->plen;
+ while (plen > 0 && *p == 0) {
+ p ++;
+ plen --;
+ }
+ q = sk->q;
+ qlen = sk->qlen;
+ while (qlen > 0 && *q == 0) {
+ q ++;
+ qlen --;
+ }
+
+ /*
+ * Compute the maximum factor length, in words.
+ */
+ z = (long)(plen > qlen ? plen : qlen) << 3;
+ fwlen = 1;
+ while (z > 0) {
+ z -= 31;
+ fwlen ++;
+ }
+
+ /*
+ * Round up the word length to an even number.
+ */
+ fwlen += (fwlen & 1);
+
+ /*
+ * We need to fit at least 6 values in the stack buffer.
+ */
+ if (6 * fwlen > TLEN) {
+ return 0;
+ }
+
+ /*
+ * Compute modulus length (in bytes).
+ */
+ xlen = (sk->n_bitlen + 7) >> 3;
+
+ /*
+ * Decode q.
+ */
+ mq = tmp;
+ br_i31_decode(mq, q, qlen);
+
+ /*
+ * Decode p.
+ */
+ t1 = mq + fwlen;
+ br_i31_decode(t1, p, plen);
+
+ /*
+ * Compute the modulus (product of the two factors), to compare
+ * it with the source value. We use br_i31_mulacc(), since it's
+ * already used later on.
+ */
+ t2 = mq + 2 * fwlen;
+ br_i31_zero(t2, mq[0]);
+ br_i31_mulacc(t2, mq, t1);
+
+ /*
+ * We encode the modulus into bytes, to perform the comparison
+ * with bytes. We know that the product length, in bytes, is
+ * exactly xlen.
+ * The comparison actually computes the carry when subtracting
+ * the modulus from the source value; that carry must be 1 for
+ * a value in the correct range. We keep it in r, which is our
+ * accumulator for the error code.
+ */
+ t3 = mq + 4 * fwlen;
+ br_i31_encode(t3, xlen, t2);
+ u = xlen;
+ r = 0;
+ while (u > 0) {
+ uint32_t wn, wx;
+
+ u --;
+ wn = ((unsigned char *)t3)[u];
+ wx = x[u];
+ r = ((wx - (wn + r)) >> 8) & 1;
+ }
+
+ /*
+ * Move the decoded p to another temporary buffer.
+ */
+ mp = mq + 2 * fwlen;
+ memmove(mp, t1, fwlen * sizeof *t1);
+
+ /*
+ * Compute s2 = x^dq mod q.
+ */
+ q0i = br_i31_ninv31(mq[1]);
+ s2 = mq + fwlen;
+ br_i31_decode_reduce(s2, x, xlen, mq);
+ r &= br_i31_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i,
+ mq + 3 * fwlen, TLEN - 3 * fwlen);
+
+ /*
+ * Compute s1 = x^dp mod p.
+ */
+ p0i = br_i31_ninv31(mp[1]);
+ s1 = mq + 3 * fwlen;
+ br_i31_decode_reduce(s1, x, xlen, mp);
+ r &= br_i31_modpow_opt(s1, sk->dp, sk->dplen, mp, p0i,
+ mq + 4 * fwlen, TLEN - 4 * fwlen);
+
+ /*
+ * Compute:
+ * h = (s1 - s2)*(1/q) mod p
+ * s1 is an integer modulo p, but s2 is modulo q. PKCS#1 is
+ * unclear about whether p may be lower than q (some existing,
+ * widely deployed implementations of RSA don't tolerate p < q),
+ * but we want to support that occurrence, so we need to use the
+ * reduction function.
+ *
+ * Since we use br_i31_decode_reduce() for iq (purportedly, the
+ * inverse of q modulo p), we also tolerate improperly large
+ * values for this parameter.
+ */
+ t1 = mq + 4 * fwlen;
+ t2 = mq + 5 * fwlen;
+ br_i31_reduce(t2, s2, mp);
+ br_i31_add(s1, mp, br_i31_sub(s1, t2, 1));
+ br_i31_to_monty(s1, mp);
+ br_i31_decode_reduce(t1, sk->iq, sk->iqlen, mp);
+ br_i31_montymul(t2, s1, t1, mp, p0i);
+
+ /*
+ * h is now in t2. We compute the final result:
+ * s = s2 + q*h
+ * All these operations are non-modular.
+ *
+ * We need mq, s2 and t2. We use the t3 buffer as destination.
+ * The buffers mp, s1 and t1 are no longer needed, so we can
+ * reuse them for t3. Moreover, the first step of the computation
+ * is to copy s2 into t3, after which s2 is not needed. Right
+ * now, mq is in slot 0, s2 is in slot 1, and t2 is in slot 5.
+ * Therefore, we have ample room for t3 by simply using s2.
+ */
+ t3 = s2;
+ br_i31_mulacc(t3, mq, t2);
+
+ /*
+ * Encode the result. Since we already checked the value of xlen,
+ * we can just use it right away.
+ */
+ br_i31_encode(x, xlen, t3);
+
+ /*
+ * The only error conditions remaining at that point are invalid
+ * values for p and q (even integers).
+ */
+ return p0i & q0i & r;
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i31_privexp.c b/test/monniaux/BearSSL/src/rsa/rsa_i31_privexp.c
new file mode 100644
index 00000000..eee62a09
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i31_privexp.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+size_t
+br_rsa_i31_compute_privexp(void *d,
+ const br_rsa_private_key *sk, uint32_t e)
+{
+ /*
+ * We want to invert e modulo phi = (p-1)(q-1). This first
+ * requires computing phi, which is easy since we have the factors
+ * p and q in the private key structure.
+ *
+ * Since p = 3 mod 4 and q = 3 mod 4, phi/4 is an odd integer.
+ * We could invert e modulo phi/4 then patch the result to
+ * modulo phi, but this would involve assembling three modulus-wide
+ * values (phi/4, 1 and e) and calling moddiv, that requires
+ * three more temporaries, for a total of six big integers, or
+ * slightly more than 3 kB of stack space for RSA-4096. This
+ * exceeds our stack requirements.
+ *
+ * Instead, we first use one step of the extended GCD:
+ *
+ * - We compute phi = k*e + r (Euclidean division of phi by e).
+ * If public exponent e is correct, then r != 0 (e must be
+ * invertible modulo phi). We also have k != 0 since we
+ * enforce non-ridiculously-small factors.
+ *
+ * - We find small u, v such that u*e - v*r = 1 (using a
+ * binary GCD; we can arrange for u < r and v < e, i.e. all
+ * values fit on 32 bits).
+ *
+ * - Solution is: d = u + v*k
+ * This last computation is exact: since u < r and v < e,
+ * the above implies d < r + e*((phi-r)/e) = phi
+ */
+
+ uint32_t tmp[4 * ((BR_MAX_RSA_FACTOR + 30) / 31) + 12];
+ uint32_t *p, *q, *k, *m, *z, *phi;
+ const unsigned char *pbuf, *qbuf;
+ size_t plen, qlen, u, len, dlen;
+ uint32_t r, a, b, u0, v0, u1, v1, he, hr;
+ int i;
+
+ /*
+ * Check that e is correct.
+ */
+ if (e < 3 || (e & 1) == 0) {
+ return 0;
+ }
+
+ /*
+ * Check lengths of p and q, and that they are both odd.
+ */
+ pbuf = sk->p;
+ plen = sk->plen;
+ while (plen > 0 && *pbuf == 0) {
+ pbuf ++;
+ plen --;
+ }
+ if (plen < 5 || plen > (BR_MAX_RSA_FACTOR / 8)
+ || (pbuf[plen - 1] & 1) != 1)
+ {
+ return 0;
+ }
+ qbuf = sk->q;
+ qlen = sk->qlen;
+ while (qlen > 0 && *qbuf == 0) {
+ qbuf ++;
+ qlen --;
+ }
+ if (qlen < 5 || qlen > (BR_MAX_RSA_FACTOR / 8)
+ || (qbuf[qlen - 1] & 1) != 1)
+ {
+ return 0;
+ }
+
+ /*
+ * Output length is that of the modulus.
+ */
+ dlen = (sk->n_bitlen + 7) >> 3;
+ if (d == NULL) {
+ return dlen;
+ }
+
+ p = tmp;
+ br_i31_decode(p, pbuf, plen);
+ plen = (p[0] + 31) >> 5;
+ q = p + 1 + plen;
+ br_i31_decode(q, qbuf, qlen);
+ qlen = (q[0] + 31) >> 5;
+
+ /*
+ * Compute phi = (p-1)*(q-1), then move it over p-1 and q-1 (that
+ * we do not need anymore). The mulacc function sets the announced
+ * bit length of t to be the sum of the announced bit lengths of
+ * p-1 and q-1, which is usually exact but may overshoot by one 1
+ * bit in some cases; we readjust it to its true length.
+ */
+ p[1] --;
+ q[1] --;
+ phi = q + 1 + qlen;
+ br_i31_zero(phi, p[0]);
+ br_i31_mulacc(phi, p, q);
+ len = (phi[0] + 31) >> 5;
+ memmove(tmp, phi, (1 + len) * sizeof *phi);
+ phi = tmp;
+ phi[0] = br_i31_bit_length(phi + 1, len);
+ len = (phi[0] + 31) >> 5;
+
+ /*
+ * Divide phi by public exponent e. The final remainder r must be
+ * non-zero (otherwise, the key is invalid). The quotient is k,
+ * which we write over phi, since we don't need phi after that.
+ */
+ r = 0;
+ for (u = len; u >= 1; u --) {
+ /*
+ * Upon entry, r < e, and phi[u] < 2^31; hence,
+ * hi:lo < e*2^31. Thus, the produced word k[u]
+ * must be lower than 2^31, and the new remainder r
+ * is lower than e.
+ */
+ uint32_t hi, lo;
+
+ hi = r >> 1;
+ lo = (r << 31) + phi[u];
+ phi[u] = br_divrem(hi, lo, e, &r);
+ }
+ if (r == 0) {
+ return 0;
+ }
+ k = phi;
+
+ /*
+ * Compute u and v such that u*e - v*r = GCD(e,r). We use
+ * a binary GCD algorithm, with 6 extra integers a, b,
+ * u0, u1, v0 and v1. Initial values are:
+ * a = e u0 = 1 v0 = 0
+ * b = r u1 = r v1 = e-1
+ * The following invariants are maintained:
+ * a = u0*e - v0*r
+ * b = u1*e - v1*r
+ * 0 < a <= e
+ * 0 < b <= r
+ * 0 <= u0 <= r
+ * 0 <= v0 <= e
+ * 0 <= u1 <= r
+ * 0 <= v1 <= e
+ *
+ * At each iteration, we reduce either a or b by one bit, and
+ * adjust u0, u1, v0 and v1 to maintain the invariants:
+ * - if a is even, then a <- a/2
+ * - otherwise, if b is even, then b <- b/2
+ * - otherwise, if a > b, then a <- (a-b)/2
+ * - otherwise, if b > a, then b <- (b-a)/2
+ * Algorithm stops when a = b. At that point, the common value
+ * is the GCD of e and r; it must be 1 (otherwise, the private
+ * key or public exponent is not valid). The (u0,v0) or (u1,v1)
+ * pairs are the solution we are looking for.
+ *
+ * Since either a or b is reduced by at least 1 bit at each
+ * iteration, 62 iterations are enough to reach the end
+ * condition.
+ *
+ * To maintain the invariants, we must compute the same operations
+ * on the u* and v* values that we do on a and b:
+ * - When a is divided by 2, u0 and v0 must be divided by 2.
+ * - When b is divided by 2, u1 and v1 must be divided by 2.
+ * - When b is subtracted from a, u1 and v1 are subtracted from
+ * u0 and v0, respectively.
+ * - When a is subtracted from b, u0 and v0 are subtracted from
+ * u1 and v1, respectively.
+ *
+ * However, we want to keep the u* and v* values in their proper
+ * ranges. The following remarks apply:
+ *
+ * - When a is divided by 2, then a is even. Therefore:
+ *
+ * * If r is odd, then u0 and v0 must have the same parity;
+ * if they are both odd, then adding r to u0 and e to v0
+ * makes them both even, and the division by 2 brings them
+ * back to the proper range.
+ *
+ * * If r is even, then u0 must be even; if v0 is odd, then
+ * adding r to u0 and e to v0 makes them both even, and the
+ * division by 2 brings them back to the proper range.
+ *
+ * Thus, all we need to do is to look at the parity of v0,
+ * and add (r,e) to (u0,v0) when v0 is odd. In order to avoid
+ * a 32-bit overflow, we can add ((r+1)/2,(e/2)+1) after the
+ * division (r+1 does not overflow since r < e; and (e/2)+1
+ * is equal to (e+1)/2 since e is odd).
+ *
+ * - When we subtract b from a, three cases may occur:
+ *
+ * * u1 <= u0 and v1 <= v0: just do the subtractions
+ *
+ * * u1 > u0 and v1 > v0: compute:
+ * (u0, v0) <- (u0 + r - u1, v0 + e - v1)
+ *
+ * * u1 <= u0 and v1 > v0: compute:
+ * (u0, v0) <- (u0 + r - u1, v0 + e - v1)
+ *
+ * The fourth case (u1 > u0 and v1 <= v0) is not possible
+ * because it would contradict "b < a" (which is the reason
+ * why we subtract b from a).
+ *
+ * The tricky case is the third one: from the equations, it
+ * seems that u0 may go out of range. However, the invariants
+ * and ranges of other values imply that, in that case, the
+ * new u0 does not actually exceed the range.
+ *
+ * We can thus handle the subtraction by adding (r,e) based
+ * solely on the comparison between v0 and v1.
+ */
+ a = e;
+ b = r;
+ u0 = 1;
+ v0 = 0;
+ u1 = r;
+ v1 = e - 1;
+ hr = (r + 1) >> 1;
+ he = (e >> 1) + 1;
+ for (i = 0; i < 62; i ++) {
+ uint32_t oa, ob, agtb, bgta;
+ uint32_t sab, sba, da, db;
+ uint32_t ctl;
+
+ oa = a & 1; /* 1 if a is odd */
+ ob = b & 1; /* 1 if b is odd */
+ agtb = GT(a, b); /* 1 if a > b */
+ bgta = GT(b, a); /* 1 if b > a */
+
+ sab = oa & ob & agtb; /* 1 if a <- a-b */
+ sba = oa & ob & bgta; /* 1 if b <- b-a */
+
+ /* a <- a-b, u0 <- u0-u1, v0 <- v0-v1 */
+ ctl = GT(v1, v0);
+ a -= b & -sab;
+ u0 -= (u1 - (r & -ctl)) & -sab;
+ v0 -= (v1 - (e & -ctl)) & -sab;
+
+ /* b <- b-a, u1 <- u1-u0 mod r, v1 <- v1-v0 mod e */
+ ctl = GT(v0, v1);
+ b -= a & -sba;
+ u1 -= (u0 - (r & -ctl)) & -sba;
+ v1 -= (v0 - (e & -ctl)) & -sba;
+
+ da = NOT(oa) | sab; /* 1 if a <- a/2 */
+ db = (oa & NOT(ob)) | sba; /* 1 if b <- b/2 */
+
+ /* a <- a/2, u0 <- u0/2, v0 <- v0/2 */
+ ctl = v0 & 1;
+ a ^= (a ^ (a >> 1)) & -da;
+ u0 ^= (u0 ^ ((u0 >> 1) + (hr & -ctl))) & -da;
+ v0 ^= (v0 ^ ((v0 >> 1) + (he & -ctl))) & -da;
+
+ /* b <- b/2, u1 <- u1/2 mod r, v1 <- v1/2 mod e */
+ ctl = v1 & 1;
+ b ^= (b ^ (b >> 1)) & -db;
+ u1 ^= (u1 ^ ((u1 >> 1) + (hr & -ctl))) & -db;
+ v1 ^= (v1 ^ ((v1 >> 1) + (he & -ctl))) & -db;
+ }
+
+ /*
+ * Check that the GCD is indeed 1. If not, then the key is invalid
+ * (and there's no harm in leaking that piece of information).
+ */
+ if (a != 1) {
+ return 0;
+ }
+
+ /*
+ * Now we have u0*e - v0*r = 1. Let's compute the result as:
+ * d = u0 + v0*k
+ * We still have k in the tmp[] array, and its announced bit
+ * length is that of phi.
+ */
+ m = k + 1 + len;
+ m[0] = (1 << 5) + 1; /* bit length is 32 bits, encoded */
+ m[1] = v0 & 0x7FFFFFFF;
+ m[2] = v0 >> 31;
+ z = m + 3;
+ br_i31_zero(z, k[0]);
+ z[1] = u0 & 0x7FFFFFFF;
+ z[2] = u0 >> 31;
+ br_i31_mulacc(z, k, m);
+
+ /*
+ * Encode the result.
+ */
+ br_i31_encode(d, dlen, z);
+ return dlen;
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i31_pss_sign.c b/test/monniaux/BearSSL/src/rsa/rsa_i31_pss_sign.c
new file mode 100644
index 00000000..b06f3e21
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i31_pss_sign.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i31_pss_sign(const br_prng_class **rng,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const unsigned char *hash, size_t salt_len,
+ const br_rsa_private_key *sk, unsigned char *x)
+{
+ if (!br_rsa_pss_sig_pad(rng, hf_data, hf_mgf1, hash,
+ salt_len, sk->n_bitlen, x))
+ {
+ return 0;
+ }
+ return br_rsa_i31_private(x, sk);
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i31_pss_vrfy.c b/test/monniaux/BearSSL/src/rsa/rsa_i31_pss_vrfy.c
new file mode 100644
index 00000000..77a9b28f
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i31_pss_vrfy.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i31_pss_vrfy(const unsigned char *x, size_t xlen,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const void *hash, size_t salt_len, const br_rsa_public_key *pk)
+{
+ unsigned char sig[BR_MAX_RSA_SIZE >> 3];
+
+ if (xlen > (sizeof sig)) {
+ return 0;
+ }
+ memcpy(sig, x, xlen);
+ if (!br_rsa_i31_public(sig, xlen, pk)) {
+ return 0;
+ }
+ return br_rsa_pss_sig_unpad(hf_data, hf_mgf1,
+ hash, salt_len, pk, sig);
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i31_pub.c b/test/monniaux/BearSSL/src/rsa/rsa_i31_pub.c
new file mode 100644
index 00000000..d5f3fe2c
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i31_pub.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/*
+ * As a strict minimum, we need four buffers that can hold a
+ * modular integer.
+ */
+#define TLEN (4 * (2 + ((BR_MAX_RSA_SIZE + 30) / 31)))
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i31_public(unsigned char *x, size_t xlen,
+ const br_rsa_public_key *pk)
+{
+ const unsigned char *n;
+ size_t nlen;
+ uint32_t tmp[1 + TLEN];
+ uint32_t *m, *a, *t;
+ size_t fwlen;
+ long z;
+ uint32_t m0i, r;
+
+ /*
+ * Get the actual length of the modulus, and see if it fits within
+ * our stack buffer. We also check that the length of x[] is valid.
+ */
+ n = pk->n;
+ nlen = pk->nlen;
+ while (nlen > 0 && *n == 0) {
+ n ++;
+ nlen --;
+ }
+ if (nlen == 0 || nlen > (BR_MAX_RSA_SIZE >> 3) || xlen != nlen) {
+ return 0;
+ }
+ z = (long)nlen << 3;
+ fwlen = 1;
+ while (z > 0) {
+ z -= 31;
+ fwlen ++;
+ }
+ /*
+ * Round up length to an even number.
+ */
+ fwlen += (fwlen & 1);
+
+ /*
+ * The modulus gets decoded into m[].
+ * The value to exponentiate goes into a[].
+ * The temporaries for modular exponentiation are in t[].
+ */
+ m = tmp;
+ a = m + fwlen;
+ t = m + 2 * fwlen;
+
+ /*
+ * Decode the modulus.
+ */
+ br_i31_decode(m, n, nlen);
+ m0i = br_i31_ninv31(m[1]);
+
+ /*
+ * Note: if m[] is even, then m0i == 0. Otherwise, m0i must be
+ * an odd integer.
+ */
+ r = m0i & 1;
+
+ /*
+ * Decode x[] into a[]; we also check that its value is proper.
+ */
+ r &= br_i31_decode_mod(a, x, xlen, m);
+
+ /*
+ * Compute the modular exponentiation.
+ */
+ br_i31_modpow_opt(a, pk->e, pk->elen, m, m0i, t, TLEN - 2 * fwlen);
+
+ /*
+ * Encode the result.
+ */
+ br_i31_encode(x, xlen, a);
+ return r;
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i31_pubexp.c b/test/monniaux/BearSSL/src/rsa/rsa_i31_pubexp.c
new file mode 100644
index 00000000..f26537d8
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i31_pubexp.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/*
+ * Recompute public exponent, based on factor p and reduced private
+ * exponent dp.
+ */
+static uint32_t
+get_pubexp(const unsigned char *pbuf, size_t plen,
+ const unsigned char *dpbuf, size_t dplen)
+{
+ /*
+ * dp is the inverse of e modulo p-1. If p = 3 mod 4, then
+ * p-1 = 2*((p-1)/2). Taken modulo 2, e is odd and has inverse 1;
+ * thus, dp must be odd.
+ *
+ * We compute the inverse of dp modulo (p-1)/2. This requires
+ * first reducing dp modulo (p-1)/2 (this can be done with a
+ * conditional subtract, no need to use the generic modular
+ * reduction function); then, we use moddiv.
+ */
+
+ uint32_t tmp[6 * ((BR_MAX_RSA_FACTOR + 61) / 31)];
+ uint32_t *p, *dp, *x;
+ size_t len;
+ uint32_t e;
+
+ /*
+ * Compute actual factor length (in bytes) and check that it fits
+ * under our size constraints.
+ */
+ while (plen > 0 && *pbuf == 0) {
+ pbuf ++;
+ plen --;
+ }
+ if (plen == 0 || plen < 5 || plen > (BR_MAX_RSA_FACTOR / 8)) {
+ return 0;
+ }
+
+ /*
+ * Compute actual reduced exponent length (in bytes) and check that
+ * it is not longer than p.
+ */
+ while (dplen > 0 && *dpbuf == 0) {
+ dpbuf ++;
+ dplen --;
+ }
+ if (dplen > plen || dplen == 0
+ || (dplen == plen && dpbuf[0] > pbuf[0]))
+ {
+ return 0;
+ }
+
+ /*
+ * Verify that p = 3 mod 4 and that dp is odd.
+ */
+ if ((pbuf[plen - 1] & 3) != 3 || (dpbuf[dplen - 1] & 1) != 1) {
+ return 0;
+ }
+
+ /*
+ * Decode p and compute (p-1)/2.
+ */
+ p = tmp;
+ br_i31_decode(p, pbuf, plen);
+ len = (p[0] + 63) >> 5;
+ br_i31_rshift(p, 1);
+
+ /*
+ * Decode dp and make sure its announced bit length matches that of
+ * p (we already know that the size of dp, in bits, does not exceed
+ * the size of p, so we just have to copy the header word).
+ */
+ dp = p + len;
+ memset(dp, 0, len * sizeof *dp);
+ br_i31_decode(dp, dpbuf, dplen);
+ dp[0] = p[0];
+
+ /*
+ * Subtract (p-1)/2 from dp if necessary.
+ */
+ br_i31_sub(dp, p, NOT(br_i31_sub(dp, p, 0)));
+
+ /*
+ * If another subtraction is needed, then this means that the
+ * value was invalid. We don't care to leak information about
+ * invalid keys.
+ */
+ if (br_i31_sub(dp, p, 0) == 0) {
+ return 0;
+ }
+
+ /*
+ * Invert dp modulo (p-1)/2. If the inversion fails, then the
+ * key value was invalid.
+ */
+ x = dp + len;
+ br_i31_zero(x, p[0]);
+ x[1] = 1;
+ if (br_i31_moddiv(x, dp, p, br_i31_ninv31(p[1]), x + len) == 0) {
+ return 0;
+ }
+
+ /*
+ * We now have an inverse. We must set it to zero (error) if its
+ * length is greater than 32 bits and/or if it is an even integer.
+ * Take care that the bit_length function returns an encoded
+ * bit length.
+ */
+ e = (uint32_t)x[1] | ((uint32_t)x[2] << 31);
+ e &= -LT(br_i31_bit_length(x + 1, len - 1), 34);
+ e &= -(e & 1);
+ return e;
+}
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i31_compute_pubexp(const br_rsa_private_key *sk)
+{
+ /*
+ * Get the public exponent from both p and q. This is the right
+ * exponent if we get twice the same value.
+ */
+ uint32_t ep, eq;
+
+ ep = get_pubexp(sk->p, sk->plen, sk->dp, sk->dplen);
+ eq = get_pubexp(sk->q, sk->qlen, sk->dq, sk->dqlen);
+ return ep & -EQ(ep, eq);
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i32_oaep_decrypt.c b/test/monniaux/BearSSL/src/rsa/rsa_i32_oaep_decrypt.c
new file mode 100644
index 00000000..ecfd92b1
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i32_oaep_decrypt.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i32_oaep_decrypt(const br_hash_class *dig,
+ const void *label, size_t label_len,
+ const br_rsa_private_key *sk, void *data, size_t *len)
+{
+ uint32_t r;
+
+ if (*len != ((sk->n_bitlen + 7) >> 3)) {
+ return 0;
+ }
+ r = br_rsa_i32_private(data, sk);
+ r &= br_rsa_oaep_unpad(dig, label, label_len, data, len);
+ return r;
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i32_oaep_encrypt.c b/test/monniaux/BearSSL/src/rsa/rsa_i32_oaep_encrypt.c
new file mode 100644
index 00000000..dc17f3f2
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i32_oaep_encrypt.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+size_t
+br_rsa_i32_oaep_encrypt(
+ 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_max_len,
+ const void *src, size_t src_len)
+{
+ size_t dlen;
+
+ dlen = br_rsa_oaep_pad(rnd, dig, label, label_len,
+ pk, dst, dst_max_len, src, src_len);
+ if (dlen == 0) {
+ return 0;
+ }
+ return dlen & -(size_t)br_rsa_i32_public(dst, dlen, pk);
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i32_pkcs1_sign.c b/test/monniaux/BearSSL/src/rsa/rsa_i32_pkcs1_sign.c
new file mode 100644
index 00000000..44b6e6d5
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i32_pkcs1_sign.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i32_pkcs1_sign(const unsigned char *hash_oid,
+ const unsigned char *hash, size_t hash_len,
+ const br_rsa_private_key *sk, unsigned char *x)
+{
+ if (!br_rsa_pkcs1_sig_pad(hash_oid, hash, hash_len, sk->n_bitlen, x)) {
+ return 0;
+ }
+ return br_rsa_i32_private(x, sk);
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i32_pkcs1_vrfy.c b/test/monniaux/BearSSL/src/rsa/rsa_i32_pkcs1_vrfy.c
new file mode 100644
index 00000000..6ee7a198
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i32_pkcs1_vrfy.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i32_pkcs1_vrfy(const unsigned char *x, size_t xlen,
+ const unsigned char *hash_oid, size_t hash_len,
+ const br_rsa_public_key *pk, unsigned char *hash_out)
+{
+ unsigned char sig[BR_MAX_RSA_SIZE >> 3];
+
+ if (xlen > (sizeof sig)) {
+ return 0;
+ }
+ memcpy(sig, x, xlen);
+ if (!br_rsa_i32_public(sig, xlen, pk)) {
+ return 0;
+ }
+ return br_rsa_pkcs1_sig_unpad(sig, xlen, hash_oid, hash_len, hash_out);
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i32_priv.c b/test/monniaux/BearSSL/src/rsa/rsa_i32_priv.c
new file mode 100644
index 00000000..05c22ec3
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i32_priv.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+#define U (1 + (BR_MAX_RSA_FACTOR >> 5))
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i32_private(unsigned char *x, const br_rsa_private_key *sk)
+{
+ const unsigned char *p, *q;
+ size_t plen, qlen;
+ uint32_t tmp[6 * U];
+ uint32_t *mp, *mq, *s1, *s2, *t1, *t2, *t3;
+ uint32_t p0i, q0i;
+ size_t xlen, u;
+ uint32_t r;
+
+ /*
+ * All our temporary buffers are from the tmp[] array.
+ *
+ * The mp, mq, s1, s2, t1 and t2 buffers are large enough to
+ * contain a RSA factor. The t3 buffer can contain a complete
+ * RSA modulus. t3 shares its storage space with s2, s1 and t1,
+ * in that order (this is important, see below).
+ */
+ mq = tmp;
+ mp = tmp + U;
+ t2 = tmp + 2 * U;
+ s2 = tmp + 3 * U;
+ s1 = tmp + 4 * U;
+ t1 = tmp + 5 * U;
+ t3 = s2;
+
+ /*
+ * Compute the actual lengths (in bytes) of p and q, and check
+ * that they fit within our stack buffers.
+ */
+ p = sk->p;
+ plen = sk->plen;
+ while (plen > 0 && *p == 0) {
+ p ++;
+ plen --;
+ }
+ q = sk->q;
+ qlen = sk->qlen;
+ while (qlen > 0 && *q == 0) {
+ q ++;
+ qlen --;
+ }
+ if (plen > (BR_MAX_RSA_FACTOR >> 3)
+ || qlen > (BR_MAX_RSA_FACTOR >> 3))
+ {
+ return 0;
+ }
+
+ /*
+ * Decode p and q.
+ */
+ br_i32_decode(mp, p, plen);
+ br_i32_decode(mq, q, qlen);
+
+ /*
+ * Recompute modulus, to compare with the source value.
+ */
+ br_i32_zero(t2, mp[0]);
+ br_i32_mulacc(t2, mp, mq);
+ xlen = (sk->n_bitlen + 7) >> 3;
+ br_i32_encode(t2 + 2 * U, xlen, t2);
+ u = xlen;
+ r = 0;
+ while (u > 0) {
+ uint32_t wn, wx;
+
+ u --;
+ wn = ((unsigned char *)(t2 + 2 * U))[u];
+ wx = x[u];
+ r = ((wx - (wn + r)) >> 8) & 1;
+ }
+
+ /*
+ * Compute s1 = x^dp mod p.
+ */
+ p0i = br_i32_ninv32(mp[1]);
+ br_i32_decode_reduce(s1, x, xlen, mp);
+ br_i32_modpow(s1, sk->dp, sk->dplen, mp, p0i, t1, t2);
+
+ /*
+ * Compute s2 = x^dq mod q.
+ */
+ q0i = br_i32_ninv32(mq[1]);
+ br_i32_decode_reduce(s2, x, xlen, mq);
+ br_i32_modpow(s2, sk->dq, sk->dqlen, mq, q0i, t1, t2);
+
+ /*
+ * Compute:
+ * h = (s1 - s2)*(1/q) mod p
+ * s1 is an integer modulo p, but s2 is modulo q. PKCS#1 is
+ * unclear about whether p may be lower than q (some existing,
+ * widely deployed implementations of RSA don't tolerate p < q),
+ * but we want to support that occurrence, so we need to use the
+ * reduction function.
+ *
+ * Since we use br_i32_decode_reduce() for iq (purportedly, the
+ * inverse of q modulo p), we also tolerate improperly large
+ * values for this parameter.
+ */
+ br_i32_reduce(t2, s2, mp);
+ br_i32_add(s1, mp, br_i32_sub(s1, t2, 1));
+ br_i32_to_monty(s1, mp);
+ br_i32_decode_reduce(t1, sk->iq, sk->iqlen, mp);
+ br_i32_montymul(t2, s1, t1, mp, p0i);
+
+ /*
+ * h is now in t2. We compute the final result:
+ * s = s2 + q*h
+ * All these operations are non-modular.
+ *
+ * We need mq, s2 and t2. We use the t3 buffer as destination.
+ * The buffers mp, s1 and t1 are no longer needed. Moreover,
+ * the first step is to copy s2 into the destination buffer t3.
+ * We thus arranged for t3 to actually share space with s2, and
+ * to be followed by the space formerly used by s1 and t1.
+ */
+ br_i32_mulacc(t3, mq, t2);
+
+ /*
+ * Encode the result. Since we already checked the value of xlen,
+ * we can just use it right away.
+ */
+ br_i32_encode(x, xlen, t3);
+
+ /*
+ * The only error conditions remaining at that point are invalid
+ * values for p and q (even integers).
+ */
+ return p0i & q0i & r;
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i32_pss_sign.c b/test/monniaux/BearSSL/src/rsa/rsa_i32_pss_sign.c
new file mode 100644
index 00000000..0f72f927
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i32_pss_sign.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i32_pss_sign(const br_prng_class **rng,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const unsigned char *hash, size_t salt_len,
+ const br_rsa_private_key *sk, unsigned char *x)
+{
+ if (!br_rsa_pss_sig_pad(rng, hf_data, hf_mgf1, hash,
+ salt_len, sk->n_bitlen, x))
+ {
+ return 0;
+ }
+ return br_rsa_i32_private(x, sk);
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i32_pss_vrfy.c b/test/monniaux/BearSSL/src/rsa/rsa_i32_pss_vrfy.c
new file mode 100644
index 00000000..2e70d234
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i32_pss_vrfy.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i32_pss_vrfy(const unsigned char *x, size_t xlen,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const void *hash, size_t salt_len, const br_rsa_public_key *pk)
+{
+ unsigned char sig[BR_MAX_RSA_SIZE >> 3];
+
+ if (xlen > (sizeof sig)) {
+ return 0;
+ }
+ memcpy(sig, x, xlen);
+ if (!br_rsa_i32_public(sig, xlen, pk)) {
+ return 0;
+ }
+ return br_rsa_pss_sig_unpad(hf_data, hf_mgf1,
+ hash, salt_len, pk, sig);
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i32_pub.c b/test/monniaux/BearSSL/src/rsa/rsa_i32_pub.c
new file mode 100644
index 00000000..6e8d8e3e
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i32_pub.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i32_public(unsigned char *x, size_t xlen,
+ const br_rsa_public_key *pk)
+{
+ const unsigned char *n;
+ size_t nlen;
+ uint32_t m[1 + (BR_MAX_RSA_SIZE >> 5)];
+ uint32_t a[1 + (BR_MAX_RSA_SIZE >> 5)];
+ uint32_t t1[1 + (BR_MAX_RSA_SIZE >> 5)];
+ uint32_t t2[1 + (BR_MAX_RSA_SIZE >> 5)];
+ uint32_t m0i, r;
+
+ /*
+ * Get the actual length of the modulus, and see if it fits within
+ * our stack buffer. We also check that the length of x[] is valid.
+ */
+ n = pk->n;
+ nlen = pk->nlen;
+ while (nlen > 0 && *n == 0) {
+ n ++;
+ nlen --;
+ }
+ if (nlen == 0 || nlen > (BR_MAX_RSA_SIZE >> 3) || xlen != nlen) {
+ return 0;
+ }
+ br_i32_decode(m, n, nlen);
+ m0i = br_i32_ninv32(m[1]);
+
+ /*
+ * Note: if m[] is even, then m0i == 0. Otherwise, m0i must be
+ * an odd integer.
+ */
+ r = m0i & 1;
+
+ /*
+ * Decode x[] into a[]; we also check that its value is proper.
+ */
+ r &= br_i32_decode_mod(a, x, xlen, m);
+
+ /*
+ * Compute the modular exponentiation.
+ */
+ br_i32_modpow(a, pk->e, pk->elen, m, m0i, t1, t2);
+
+ /*
+ * Encode the result.
+ */
+ br_i32_encode(x, xlen, a);
+ return r;
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i62_keygen.c b/test/monniaux/BearSSL/src/rsa/rsa_i62_keygen.c
new file mode 100644
index 00000000..8f55c375
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i62_keygen.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+#if BR_INT128 || BR_UMUL128
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i62_keygen(const br_prng_class **rng,
+ br_rsa_private_key *sk, void *kbuf_priv,
+ br_rsa_public_key *pk, void *kbuf_pub,
+ unsigned size, uint32_t pubexp)
+{
+ return br_rsa_i31_keygen_inner(rng,
+ sk, kbuf_priv, pk, kbuf_pub, size, pubexp,
+ &br_i62_modpow_opt_as_i31);
+}
+
+/* see bearssl_rsa.h */
+br_rsa_keygen
+br_rsa_i62_keygen_get()
+{
+ return &br_rsa_i62_keygen;
+}
+
+#else
+
+/* see bearssl_rsa.h */
+br_rsa_keygen
+br_rsa_i62_keygen_get()
+{
+ return 0;
+}
+
+#endif
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i62_oaep_decrypt.c b/test/monniaux/BearSSL/src/rsa/rsa_i62_oaep_decrypt.c
new file mode 100644
index 00000000..38470dd3
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i62_oaep_decrypt.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+#if BR_INT128 || BR_UMUL128
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i62_oaep_decrypt(const br_hash_class *dig,
+ const void *label, size_t label_len,
+ const br_rsa_private_key *sk, void *data, size_t *len)
+{
+ uint32_t r;
+
+ if (*len != ((sk->n_bitlen + 7) >> 3)) {
+ return 0;
+ }
+ r = br_rsa_i62_private(data, sk);
+ r &= br_rsa_oaep_unpad(dig, label, label_len, data, len);
+ return r;
+}
+
+/* see bearssl_rsa.h */
+br_rsa_oaep_decrypt
+br_rsa_i62_oaep_decrypt_get(void)
+{
+ return &br_rsa_i62_oaep_decrypt;
+}
+
+#else
+
+/* see bearssl_rsa.h */
+br_rsa_oaep_decrypt
+br_rsa_i62_oaep_decrypt_get(void)
+{
+ return 0;
+}
+
+#endif
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i62_oaep_encrypt.c b/test/monniaux/BearSSL/src/rsa/rsa_i62_oaep_encrypt.c
new file mode 100644
index 00000000..cf41ecb8
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i62_oaep_encrypt.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+#if BR_INT128 || BR_UMUL128
+
+/* see bearssl_rsa.h */
+size_t
+br_rsa_i62_oaep_encrypt(
+ 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_max_len,
+ const void *src, size_t src_len)
+{
+ size_t dlen;
+
+ dlen = br_rsa_oaep_pad(rnd, dig, label, label_len,
+ pk, dst, dst_max_len, src, src_len);
+ if (dlen == 0) {
+ return 0;
+ }
+ return dlen & -(size_t)br_rsa_i62_public(dst, dlen, pk);
+}
+
+/* see bearssl_rsa.h */
+br_rsa_oaep_encrypt
+br_rsa_i62_oaep_encrypt_get(void)
+{
+ return &br_rsa_i62_oaep_encrypt;
+}
+
+#else
+
+/* see bearssl_rsa.h */
+br_rsa_oaep_encrypt
+br_rsa_i62_oaep_encrypt_get(void)
+{
+ return 0;
+}
+
+#endif
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i62_pkcs1_sign.c b/test/monniaux/BearSSL/src/rsa/rsa_i62_pkcs1_sign.c
new file mode 100644
index 00000000..a20a0846
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i62_pkcs1_sign.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+#if BR_INT128 || BR_UMUL128
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i62_pkcs1_sign(const unsigned char *hash_oid,
+ const unsigned char *hash, size_t hash_len,
+ const br_rsa_private_key *sk, unsigned char *x)
+{
+ if (!br_rsa_pkcs1_sig_pad(hash_oid, hash, hash_len, sk->n_bitlen, x)) {
+ return 0;
+ }
+ return br_rsa_i62_private(x, sk);
+}
+
+/* see bearssl_rsa.h */
+br_rsa_pkcs1_sign
+br_rsa_i62_pkcs1_sign_get(void)
+{
+ return &br_rsa_i62_pkcs1_sign;
+}
+
+#else
+
+/* see bearssl_rsa.h */
+br_rsa_pkcs1_sign
+br_rsa_i62_pkcs1_sign_get(void)
+{
+ return 0;
+}
+
+#endif
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i62_pkcs1_vrfy.c b/test/monniaux/BearSSL/src/rsa/rsa_i62_pkcs1_vrfy.c
new file mode 100644
index 00000000..6519161b
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i62_pkcs1_vrfy.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+#if BR_INT128 || BR_UMUL128
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i62_pkcs1_vrfy(const unsigned char *x, size_t xlen,
+ const unsigned char *hash_oid, size_t hash_len,
+ const br_rsa_public_key *pk, unsigned char *hash_out)
+{
+ unsigned char sig[BR_MAX_RSA_SIZE >> 3];
+
+ if (xlen > (sizeof sig)) {
+ return 0;
+ }
+ memcpy(sig, x, xlen);
+ if (!br_rsa_i62_public(sig, xlen, pk)) {
+ return 0;
+ }
+ return br_rsa_pkcs1_sig_unpad(sig, xlen, hash_oid, hash_len, hash_out);
+}
+
+/* see bearssl_rsa.h */
+br_rsa_pkcs1_vrfy
+br_rsa_i62_pkcs1_vrfy_get(void)
+{
+ return &br_rsa_i62_pkcs1_vrfy;
+}
+
+#else
+
+/* see bearssl_rsa.h */
+br_rsa_pkcs1_vrfy
+br_rsa_i62_pkcs1_vrfy_get(void)
+{
+ return 0;
+}
+
+#endif
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i62_priv.c b/test/monniaux/BearSSL/src/rsa/rsa_i62_priv.c
new file mode 100644
index 00000000..f0da6006
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i62_priv.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+#if BR_INT128 || BR_UMUL128
+
+#define U (2 + ((BR_MAX_RSA_FACTOR + 30) / 31))
+#define TLEN (4 * U) /* TLEN is counted in 64-bit words */
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i62_private(unsigned char *x, const br_rsa_private_key *sk)
+{
+ const unsigned char *p, *q;
+ size_t plen, qlen;
+ size_t fwlen;
+ uint32_t p0i, q0i;
+ size_t xlen, u;
+ uint64_t tmp[TLEN];
+ long z;
+ uint32_t *mp, *mq, *s1, *s2, *t1, *t2, *t3;
+ uint32_t r;
+
+ /*
+ * Compute the actual lengths of p and q, in bytes.
+ * These lengths are not considered secret (we cannot really hide
+ * them anyway in constant-time code).
+ */
+ p = sk->p;
+ plen = sk->plen;
+ while (plen > 0 && *p == 0) {
+ p ++;
+ plen --;
+ }
+ q = sk->q;
+ qlen = sk->qlen;
+ while (qlen > 0 && *q == 0) {
+ q ++;
+ qlen --;
+ }
+
+ /*
+ * Compute the maximum factor length, in words.
+ */
+ z = (long)(plen > qlen ? plen : qlen) << 3;
+ fwlen = 1;
+ while (z > 0) {
+ z -= 31;
+ fwlen ++;
+ }
+
+ /*
+ * Convert size to 62-bit words.
+ */
+ fwlen = (fwlen + 1) >> 1;
+
+ /*
+ * We need to fit at least 6 values in the stack buffer.
+ */
+ if (6 * fwlen > TLEN) {
+ return 0;
+ }
+
+ /*
+ * Compute signature length (in bytes).
+ */
+ xlen = (sk->n_bitlen + 7) >> 3;
+
+ /*
+ * Decode q.
+ */
+ mq = (uint32_t *)tmp;
+ br_i31_decode(mq, q, qlen);
+
+ /*
+ * Decode p.
+ */
+ t1 = (uint32_t *)(tmp + fwlen);
+ br_i31_decode(t1, p, plen);
+
+ /*
+ * Compute the modulus (product of the two factors), to compare
+ * it with the source value. We use br_i31_mulacc(), since it's
+ * already used later on.
+ */
+ t2 = (uint32_t *)(tmp + 2 * fwlen);
+ br_i31_zero(t2, mq[0]);
+ br_i31_mulacc(t2, mq, t1);
+
+ /*
+ * We encode the modulus into bytes, to perform the comparison
+ * with bytes. We know that the product length, in bytes, is
+ * exactly xlen.
+ * The comparison actually computes the carry when subtracting
+ * the modulus from the source value; that carry must be 1 for
+ * a value in the correct range. We keep it in r, which is our
+ * accumulator for the error code.
+ */
+ t3 = (uint32_t *)(tmp + 4 * fwlen);
+ br_i31_encode(t3, xlen, t2);
+ u = xlen;
+ r = 0;
+ while (u > 0) {
+ uint32_t wn, wx;
+
+ u --;
+ wn = ((unsigned char *)t3)[u];
+ wx = x[u];
+ r = ((wx - (wn + r)) >> 8) & 1;
+ }
+
+ /*
+ * Move the decoded p to another temporary buffer.
+ */
+ mp = (uint32_t *)(tmp + 2 * fwlen);
+ memmove(mp, t1, 2 * fwlen * sizeof *t1);
+
+ /*
+ * Compute s2 = x^dq mod q.
+ */
+ q0i = br_i31_ninv31(mq[1]);
+ s2 = (uint32_t *)(tmp + fwlen);
+ br_i31_decode_reduce(s2, x, xlen, mq);
+ r &= br_i62_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i,
+ tmp + 3 * fwlen, TLEN - 3 * fwlen);
+
+ /*
+ * Compute s1 = x^dp mod p.
+ */
+ p0i = br_i31_ninv31(mp[1]);
+ s1 = (uint32_t *)(tmp + 3 * fwlen);
+ br_i31_decode_reduce(s1, x, xlen, mp);
+ r &= br_i62_modpow_opt(s1, sk->dp, sk->dplen, mp, p0i,
+ tmp + 4 * fwlen, TLEN - 4 * fwlen);
+
+ /*
+ * Compute:
+ * h = (s1 - s2)*(1/q) mod p
+ * s1 is an integer modulo p, but s2 is modulo q. PKCS#1 is
+ * unclear about whether p may be lower than q (some existing,
+ * widely deployed implementations of RSA don't tolerate p < q),
+ * but we want to support that occurrence, so we need to use the
+ * reduction function.
+ *
+ * Since we use br_i31_decode_reduce() for iq (purportedly, the
+ * inverse of q modulo p), we also tolerate improperly large
+ * values for this parameter.
+ */
+ t1 = (uint32_t *)(tmp + 4 * fwlen);
+ t2 = (uint32_t *)(tmp + 5 * fwlen);
+ br_i31_reduce(t2, s2, mp);
+ br_i31_add(s1, mp, br_i31_sub(s1, t2, 1));
+ br_i31_to_monty(s1, mp);
+ br_i31_decode_reduce(t1, sk->iq, sk->iqlen, mp);
+ br_i31_montymul(t2, s1, t1, mp, p0i);
+
+ /*
+ * h is now in t2. We compute the final result:
+ * s = s2 + q*h
+ * All these operations are non-modular.
+ *
+ * We need mq, s2 and t2. We use the t3 buffer as destination.
+ * The buffers mp, s1 and t1 are no longer needed, so we can
+ * reuse them for t3. Moreover, the first step of the computation
+ * is to copy s2 into t3, after which s2 is not needed. Right
+ * now, mq is in slot 0, s2 is in slot 1, and t2 is in slot 5.
+ * Therefore, we have ample room for t3 by simply using s2.
+ */
+ t3 = s2;
+ br_i31_mulacc(t3, mq, t2);
+
+ /*
+ * Encode the result. Since we already checked the value of xlen,
+ * we can just use it right away.
+ */
+ br_i31_encode(x, xlen, t3);
+
+ /*
+ * The only error conditions remaining at that point are invalid
+ * values for p and q (even integers).
+ */
+ return p0i & q0i & r;
+}
+
+/* see bearssl_rsa.h */
+br_rsa_private
+br_rsa_i62_private_get(void)
+{
+ return &br_rsa_i62_private;
+}
+
+#else
+
+/* see bearssl_rsa.h */
+br_rsa_private
+br_rsa_i62_private_get(void)
+{
+ return 0;
+}
+
+#endif
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i62_pss_sign.c b/test/monniaux/BearSSL/src/rsa/rsa_i62_pss_sign.c
new file mode 100644
index 00000000..7232f6d5
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i62_pss_sign.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+#if BR_INT128 || BR_UMUL128
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i62_pss_sign(const br_prng_class **rng,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const unsigned char *hash, size_t salt_len,
+ const br_rsa_private_key *sk, unsigned char *x)
+{
+ if (!br_rsa_pss_sig_pad(rng, hf_data, hf_mgf1, hash,
+ salt_len, sk->n_bitlen, x))
+ {
+ return 0;
+ }
+ return br_rsa_i62_private(x, sk);
+}
+
+/* see bearssl_rsa.h */
+br_rsa_pss_sign
+br_rsa_i62_pss_sign_get(void)
+{
+ return &br_rsa_i62_pss_sign;
+}
+
+#else
+
+/* see bearssl_rsa.h */
+br_rsa_pss_sign
+br_rsa_i62_pss_sign_get(void)
+{
+ return 0;
+}
+
+#endif
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i62_pss_vrfy.c b/test/monniaux/BearSSL/src/rsa/rsa_i62_pss_vrfy.c
new file mode 100644
index 00000000..e726e823
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i62_pss_vrfy.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+#if BR_INT128 || BR_UMUL128
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i62_pss_vrfy(const unsigned char *x, size_t xlen,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const void *hash, size_t salt_len, const br_rsa_public_key *pk)
+{
+ unsigned char sig[BR_MAX_RSA_SIZE >> 3];
+
+ if (xlen > (sizeof sig)) {
+ return 0;
+ }
+ memcpy(sig, x, xlen);
+ if (!br_rsa_i62_public(sig, xlen, pk)) {
+ return 0;
+ }
+ return br_rsa_pss_sig_unpad(hf_data, hf_mgf1,
+ hash, salt_len, pk, sig);
+}
+
+/* see bearssl_rsa.h */
+br_rsa_pss_vrfy
+br_rsa_i62_pss_vrfy_get(void)
+{
+ return &br_rsa_i62_pss_vrfy;
+}
+
+#else
+
+/* see bearssl_rsa.h */
+br_rsa_pss_vrfy
+br_rsa_i62_pss_vrfy_get(void)
+{
+ return 0;
+}
+
+#endif
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_i62_pub.c b/test/monniaux/BearSSL/src/rsa/rsa_i62_pub.c
new file mode 100644
index 00000000..70cf61bd
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_i62_pub.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+#if BR_INT128 || BR_UMUL128
+
+/*
+ * As a strict minimum, we need four buffers that can hold a
+ * modular integer. But TLEN is expressed in 64-bit words.
+ */
+#define TLEN (2 * (2 + ((BR_MAX_RSA_SIZE + 30) / 31)))
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i62_public(unsigned char *x, size_t xlen,
+ const br_rsa_public_key *pk)
+{
+ const unsigned char *n;
+ size_t nlen;
+ uint64_t tmp[TLEN];
+ uint32_t *m, *a;
+ size_t fwlen;
+ long z;
+ uint32_t m0i, r;
+
+ /*
+ * Get the actual length of the modulus, and see if it fits within
+ * our stack buffer. We also check that the length of x[] is valid.
+ */
+ n = pk->n;
+ nlen = pk->nlen;
+ while (nlen > 0 && *n == 0) {
+ n ++;
+ nlen --;
+ }
+ if (nlen == 0 || nlen > (BR_MAX_RSA_SIZE >> 3) || xlen != nlen) {
+ return 0;
+ }
+ z = (long)nlen << 3;
+ fwlen = 1;
+ while (z > 0) {
+ z -= 31;
+ fwlen ++;
+ }
+ /*
+ * Convert fwlen to a count in 62-bit words.
+ */
+ fwlen = (fwlen + 1) >> 1;
+
+ /*
+ * The modulus gets decoded into m[].
+ * The value to exponentiate goes into a[].
+ */
+ m = (uint32_t *)tmp;
+ a = (uint32_t *)(tmp + fwlen);
+
+ /*
+ * Decode the modulus.
+ */
+ br_i31_decode(m, n, nlen);
+ m0i = br_i31_ninv31(m[1]);
+
+ /*
+ * Note: if m[] is even, then m0i == 0. Otherwise, m0i must be
+ * an odd integer.
+ */
+ r = m0i & 1;
+
+ /*
+ * Decode x[] into a[]; we also check that its value is proper.
+ */
+ r &= br_i31_decode_mod(a, x, xlen, m);
+
+ /*
+ * Compute the modular exponentiation.
+ */
+ br_i62_modpow_opt(a, pk->e, pk->elen, m, m0i,
+ tmp + 2 * fwlen, TLEN - 2 * fwlen);
+
+ /*
+ * Encode the result.
+ */
+ br_i31_encode(x, xlen, a);
+ return r;
+}
+
+/* see bearssl_rsa.h */
+br_rsa_public
+br_rsa_i62_public_get(void)
+{
+ return &br_rsa_i62_public;
+}
+
+#else
+
+/* see bearssl_rsa.h */
+br_rsa_public
+br_rsa_i62_public_get(void)
+{
+ return 0;
+}
+
+#endif
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_oaep_pad.c b/test/monniaux/BearSSL/src/rsa/rsa_oaep_pad.c
new file mode 100644
index 00000000..5327dc26
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_oaep_pad.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/*
+ * Hash some data. This is put as a separate function so that stack
+ * allocation of the hash function context is done only for the duration
+ * of the hash.
+ */
+static void
+hash_data(const br_hash_class *dig, void *dst, const void *src, size_t len)
+{
+ br_hash_compat_context hc;
+
+ hc.vtable = dig;
+ dig->init(&hc.vtable);
+ dig->update(&hc.vtable, src, len);
+ dig->out(&hc.vtable, dst);
+}
+
+/* see inner.h */
+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_max_len,
+ const void *src, size_t src_len)
+{
+ size_t k, hlen;
+ unsigned char *buf;
+
+ hlen = br_digest_size(dig);
+
+ /*
+ * Compute actual modulus length (in bytes).
+ */
+ k = pk->nlen;
+ while (k > 0 && pk->n[k - 1] == 0) {
+ k --;
+ }
+
+ /*
+ * An error is reported if:
+ * - the modulus is too short;
+ * - the source message length is too long;
+ * - the destination buffer is too short.
+ */
+ if (k < ((hlen << 1) + 2)
+ || src_len > (k - (hlen << 1) - 2)
+ || dst_max_len < k)
+ {
+ return 0;
+ }
+
+ /*
+ * Apply padding. At this point, things cannot fail.
+ */
+ buf = dst;
+
+ /*
+ * Assemble: DB = lHash || PS || 0x01 || M
+ * We first place the source message M with memmove(), so that
+ * overlaps between source and destination buffers are supported.
+ */
+ memmove(buf + k - src_len, src, src_len);
+ hash_data(dig, buf + 1 + hlen, label, label_len);
+ memset(buf + 1 + (hlen << 1), 0, k - src_len - (hlen << 1) - 2);
+ buf[k - src_len - 1] = 0x01;
+
+ /*
+ * Make the random seed.
+ */
+ (*rnd)->generate(rnd, buf + 1, hlen);
+
+ /*
+ * Mask DB with the mask generated from the seed.
+ */
+ br_mgf1_xor(buf + 1 + hlen, k - hlen - 1, dig, buf + 1, hlen);
+
+ /*
+ * Mask the seed with the mask generated from the masked DB.
+ */
+ br_mgf1_xor(buf + 1, hlen, dig, buf + 1 + hlen, k - hlen - 1);
+
+ /*
+ * Padding result: EM = 0x00 || maskedSeed || maskedDB.
+ */
+ buf[0] = 0x00;
+ return k;
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_oaep_unpad.c b/test/monniaux/BearSSL/src/rsa/rsa_oaep_unpad.c
new file mode 100644
index 00000000..7c4be6a8
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_oaep_unpad.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/*
+ * Hash some data and XOR the result into the provided buffer. This is put
+ * as a separate function so that stack allocation of the hash function
+ * context is done only for the duration of the hash.
+ */
+static void
+xor_hash_data(const br_hash_class *dig, void *dst, const void *src, size_t len)
+{
+ br_hash_compat_context hc;
+ unsigned char tmp[64];
+ unsigned char *buf;
+ size_t u, hlen;
+
+ hc.vtable = dig;
+ dig->init(&hc.vtable);
+ dig->update(&hc.vtable, src, len);
+ dig->out(&hc.vtable, tmp);
+ buf = dst;
+ hlen = br_digest_size(dig);
+ for (u = 0; u < hlen; u ++) {
+ buf[u] ^= tmp[u];
+ }
+}
+
+/* see inner.h */
+uint32_t
+br_rsa_oaep_unpad(const br_hash_class *dig,
+ const void *label, size_t label_len,
+ void *data, size_t *len)
+{
+ size_t u, k, hlen;
+ unsigned char *buf;
+ uint32_t r, s, zlen;
+
+ hlen = br_digest_size(dig);
+ k = *len;
+ buf = data;
+
+ /*
+ * There must be room for the padding.
+ */
+ if (k < ((hlen << 1) + 2)) {
+ return 0;
+ }
+
+ /*
+ * Unmask the seed, then the DB value.
+ */
+ br_mgf1_xor(buf + 1, hlen, dig, buf + 1 + hlen, k - hlen - 1);
+ br_mgf1_xor(buf + 1 + hlen, k - hlen - 1, dig, buf + 1, hlen);
+
+ /*
+ * Hash the label and XOR it with the value in the array; if
+ * they are equal then these should yield only zeros.
+ */
+ xor_hash_data(dig, buf + 1 + hlen, label, label_len);
+
+ /*
+ * At that point, if the padding was correct, when we should
+ * have: 0x00 || seed || 0x00 ... 0x00 0x01 || M
+ * Padding is valid as long as:
+ * - There is at least hlen+1 leading bytes of value 0x00.
+ * - There is at least one non-zero byte.
+ * - The first (leftmost) non-zero byte has value 0x01.
+ *
+ * Ultimately, we may leak the resulting message length, i.e.
+ * the position of the byte of value 0x01, but we must take care
+ * to do so only if the number of zero bytes has been verified
+ * to be at least hlen+1.
+ *
+ * The loop below counts the number of bytes of value 0x00, and
+ * checks that the next byte has value 0x01, in constant-time.
+ *
+ * - If the initial byte (before the seed) is not 0x00, then
+ * r and s are set to 0, and stay there.
+ * - Value r is 1 until the first non-zero byte is reached
+ * (after the seed); it switches to 0 at that point.
+ * - Value s is set to 1 if and only if the data encountered
+ * at the time of the transition of r from 1 to 0 has value
+ * exactly 0x01.
+ * - Value zlen counts the number of leading bytes of value zero
+ * (after the seed).
+ */
+ r = 1 - ((buf[0] + 0xFF) >> 8);
+ s = 0;
+ zlen = 0;
+ for (u = hlen + 1; u < k; u ++) {
+ uint32_t w, nz;
+
+ w = buf[u];
+
+ /*
+ * nz == 1 only for the first non-zero byte.
+ */
+ nz = r & ((w + 0xFF) >> 8);
+ s |= nz & EQ(w, 0x01);
+ r &= NOT(nz);
+ zlen += r;
+ }
+
+ /*
+ * Padding is correct only if s == 1, _and_ zlen >= hlen.
+ */
+ s &= GE(zlen, (uint32_t)hlen);
+
+ /*
+ * At that point, padding was verified, and we are now allowed
+ * to make conditional jumps.
+ */
+ if (s) {
+ size_t plen;
+
+ plen = 2 + hlen + zlen;
+ k -= plen;
+ memmove(buf, buf + plen, k);
+ *len = k;
+ }
+ return s;
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_pkcs1_sig_pad.c b/test/monniaux/BearSSL/src/rsa/rsa_pkcs1_sig_pad.c
new file mode 100644
index 00000000..06c3bd70
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_pkcs1_sig_pad.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see inner.h */
+uint32_t
+br_rsa_pkcs1_sig_pad(const unsigned char *hash_oid,
+ const unsigned char *hash, size_t hash_len,
+ uint32_t n_bitlen, unsigned char *x)
+{
+ size_t u, x3, xlen;
+
+ /*
+ * Padded hash value has format:
+ * 00 01 FF .. FF 00 30 x1 30 x2 06 x3 OID 05 00 04 x4 HASH
+ *
+ * with the following rules:
+ *
+ * -- Total length is equal to the modulus length (unsigned
+ * encoding).
+ *
+ * -- There must be at least eight bytes of value 0xFF.
+ *
+ * -- x4 is equal to the hash length (hash_len).
+ *
+ * -- x3 is equal to the encoded OID value length (hash_oid[0]).
+ *
+ * -- x2 = x3 + 4.
+ *
+ * -- x1 = x2 + x4 + 4 = x3 + x4 + 8.
+ *
+ * Note: the "05 00" is optional (signatures with and without
+ * that sequence exist in practice), but notes in PKCS#1 seem to
+ * indicate that the presence of that sequence (specifically,
+ * an ASN.1 NULL value for the hash parameters) may be slightly
+ * more "standard" than the opposite.
+ */
+ xlen = (n_bitlen + 7) >> 3;
+
+ if (hash_oid == NULL) {
+ if (xlen < hash_len + 11) {
+ return 0;
+ }
+ x[0] = 0x00;
+ x[1] = 0x01;
+ u = xlen - hash_len;
+ memset(x + 2, 0xFF, u - 3);
+ x[u - 1] = 0x00;
+ } else {
+ x3 = hash_oid[0];
+
+ /*
+ * Check that there is enough room for all the elements,
+ * including at least eight bytes of value 0xFF.
+ */
+ if (xlen < (x3 + hash_len + 21)) {
+ return 0;
+ }
+ x[0] = 0x00;
+ x[1] = 0x01;
+ u = xlen - x3 - hash_len - 11;
+ memset(x + 2, 0xFF, u - 2);
+ x[u] = 0x00;
+ x[u + 1] = 0x30;
+ x[u + 2] = x3 + hash_len + 8;
+ x[u + 3] = 0x30;
+ x[u + 4] = x3 + 4;
+ x[u + 5] = 0x06;
+ memcpy(x + u + 6, hash_oid, x3 + 1);
+ u += x3 + 7;
+ x[u ++] = 0x05;
+ x[u ++] = 0x00;
+ x[u ++] = 0x04;
+ x[u ++] = hash_len;
+ }
+ memcpy(x + u, hash, hash_len);
+ return 1;
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_pkcs1_sig_unpad.c b/test/monniaux/BearSSL/src/rsa/rsa_pkcs1_sig_unpad.c
new file mode 100644
index 00000000..c8ae08fa
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_pkcs1_sig_unpad.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+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)
+{
+ static const unsigned char pad1[] = {
+ 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+ };
+
+ unsigned char pad2[43];
+ size_t u, x2, x3, pad_len, zlen;
+
+ if (sig_len < 11) {
+ return 0;
+ }
+
+ /*
+ * Expected format:
+ * 00 01 FF ... FF 00 30 x1 30 x2 06 x3 OID [ 05 00 ] 04 x4 HASH
+ *
+ * with the following rules:
+ *
+ * -- Total length is that of the modulus and the signature
+ * (this was already verified by br_rsa_i31_public()).
+ *
+ * -- There are at least eight bytes of value 0xFF.
+ *
+ * -- x4 is equal to the hash length (hash_len).
+ *
+ * -- x3 is equal to the encoded OID value length (so x3 is the
+ * first byte of hash_oid[]).
+ *
+ * -- If the "05 00" is present, then x2 == x3 + 4; otherwise,
+ * x2 == x3 + 2.
+ *
+ * -- x1 == x2 + x4 + 4.
+ *
+ * So the total length after the last "FF" is either x3 + x4 + 11
+ * (with the "05 00") or x3 + x4 + 9 (without the "05 00").
+ */
+
+ /*
+ * Check the "00 01 FF .. FF 00" with at least eight 0xFF bytes.
+ * The comparison is valid because we made sure that the signature
+ * is at least 11 bytes long.
+ */
+ if (memcmp(sig, pad1, sizeof pad1) != 0) {
+ return 0;
+ }
+ for (u = sizeof pad1; u < sig_len; u ++) {
+ if (sig[u] != 0xFF) {
+ break;
+ }
+ }
+
+ /*
+ * Remaining length is sig_len - u bytes (including the 00 just
+ * after the last FF). This must be equal to one of the two
+ * possible values (depending on whether the "05 00" sequence is
+ * present or not).
+ */
+ if (hash_oid == NULL) {
+ if (sig_len - u != hash_len + 1 || sig[u] != 0x00) {
+ return 0;
+ }
+ } else {
+ x3 = hash_oid[0];
+ pad_len = x3 + 9;
+ memset(pad2, 0, pad_len);
+ zlen = sig_len - u - hash_len;
+ if (zlen == pad_len) {
+ x2 = x3 + 2;
+ } else if (zlen == pad_len + 2) {
+ x2 = x3 + 4;
+ pad_len = zlen;
+ pad2[pad_len - 4] = 0x05;
+ } else {
+ return 0;
+ }
+ pad2[1] = 0x30;
+ pad2[2] = x2 + hash_len + 4;
+ pad2[3] = 0x30;
+ pad2[4] = x2;
+ pad2[5] = 0x06;
+ memcpy(pad2 + 6, hash_oid, x3 + 1);
+ pad2[pad_len - 2] = 0x04;
+ pad2[pad_len - 1] = hash_len;
+ if (memcmp(pad2, sig + u, pad_len) != 0) {
+ return 0;
+ }
+ }
+ memcpy(hash_out, sig + sig_len - hash_len, hash_len);
+ return 1;
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_pss_sig_pad.c b/test/monniaux/BearSSL/src/rsa/rsa_pss_sig_pad.c
new file mode 100644
index 00000000..13e90274
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_pss_sig_pad.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see inner.h */
+uint32_t
+br_rsa_pss_sig_pad(const br_prng_class **rng,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const unsigned char *hash, size_t salt_len,
+ uint32_t n_bitlen, unsigned char *x)
+{
+ size_t xlen, hash_len;
+ br_hash_compat_context hc;
+ unsigned char *salt, *seed;
+
+ hash_len = br_digest_size(hf_data);
+
+ /*
+ * The padded string is one bit smaller than the modulus;
+ * notably, if the modulus length is equal to 1 modulo 8, then
+ * the padded string will be one _byte_ smaller, and the first
+ * byte will be set to 0. We apply these transformations here.
+ */
+ n_bitlen --;
+ if ((n_bitlen & 7) == 0) {
+ *x ++ = 0;
+ }
+ xlen = (n_bitlen + 7) >> 3;
+
+ /*
+ * Check that the modulus is large enough for the hash value
+ * length combined with the intended salt length.
+ */
+ if (hash_len > xlen || salt_len > xlen
+ || (hash_len + salt_len + 2) > xlen)
+ {
+ return 0;
+ }
+
+ /*
+ * Produce a random salt.
+ */
+ salt = x + xlen - hash_len - salt_len - 1;
+ if (salt_len != 0) {
+ (*rng)->generate(rng, salt, salt_len);
+ }
+
+ /*
+ * Compute the seed for MGF1.
+ */
+ seed = x + xlen - hash_len - 1;
+ hf_data->init(&hc.vtable);
+ memset(seed, 0, 8);
+ hf_data->update(&hc.vtable, seed, 8);
+ hf_data->update(&hc.vtable, hash, hash_len);
+ hf_data->update(&hc.vtable, salt, salt_len);
+ hf_data->out(&hc.vtable, seed);
+
+ /*
+ * Prepare string PS (padded salt). The salt is already at the
+ * right place.
+ */
+ memset(x, 0, xlen - salt_len - hash_len - 2);
+ x[xlen - salt_len - hash_len - 2] = 0x01;
+
+ /*
+ * Generate the mask and XOR it into PS.
+ */
+ br_mgf1_xor(x, xlen - hash_len - 1, hf_mgf1, seed, hash_len);
+
+ /*
+ * Clear the top bits to ensure the value is lower than the
+ * modulus.
+ */
+ x[0] &= 0xFF >> (((uint32_t)xlen << 3) - n_bitlen);
+
+ /*
+ * The seed (H) is already in the right place. We just set the
+ * last byte.
+ */
+ x[xlen - 1] = 0xBC;
+
+ return 1;
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_pss_sig_unpad.c b/test/monniaux/BearSSL/src/rsa/rsa_pss_sig_unpad.c
new file mode 100644
index 00000000..a9f8ca3a
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_pss_sig_unpad.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see inner.h */
+uint32_t
+br_rsa_pss_sig_unpad(const br_hash_class *hf_data,
+ const br_hash_class *hf_mgf1,
+ const unsigned char *hash, size_t salt_len,
+ const br_rsa_public_key *pk, unsigned char *x)
+{
+ size_t u, xlen, hash_len;
+ br_hash_compat_context hc;
+ unsigned char *seed, *salt;
+ unsigned char tmp[64];
+ uint32_t r, n_bitlen;
+
+ hash_len = br_digest_size(hf_data);
+
+ /*
+ * Value r will be set to a non-zero value is any test fails.
+ */
+ r = 0;
+
+ /*
+ * The value bit length (as an integer) must be strictly less than
+ * that of the modulus.
+ */
+ for (u = 0; u < pk->nlen; u ++) {
+ if (pk->n[u] != 0) {
+ break;
+ }
+ }
+ if (u == pk->nlen) {
+ return 0;
+ }
+ n_bitlen = BIT_LENGTH(pk->n[u]) + ((uint32_t)(pk->nlen - u - 1) << 3);
+ n_bitlen --;
+ if ((n_bitlen & 7) == 0) {
+ r |= *x ++;
+ } else {
+ r |= x[0] & (0xFF << (n_bitlen & 7));
+ }
+ xlen = (n_bitlen + 7) >> 3;
+
+ /*
+ * Check that the modulus is large enough for the hash value
+ * length combined with the intended salt length.
+ */
+ if (hash_len > xlen || salt_len > xlen
+ || (hash_len + salt_len + 2) > xlen)
+ {
+ return 0;
+ }
+
+ /*
+ * Check value of rightmost byte.
+ */
+ r |= x[xlen - 1] ^ 0xBC;
+
+ /*
+ * Generate the mask and XOR it into the first bytes to reveal PS;
+ * we must also mask out the leading bits.
+ */
+ seed = x + xlen - hash_len - 1;
+ br_mgf1_xor(x, xlen - hash_len - 1, hf_mgf1, seed, hash_len);
+ if ((n_bitlen & 7) != 0) {
+ x[0] &= 0xFF >> (8 - (n_bitlen & 7));
+ }
+
+ /*
+ * Check that all padding bytes have the expected value.
+ */
+ for (u = 0; u < (xlen - hash_len - salt_len - 2); u ++) {
+ r |= x[u];
+ }
+ r |= x[xlen - hash_len - salt_len - 2] ^ 0x01;
+
+ /*
+ * Recompute H.
+ */
+ salt = x + xlen - hash_len - salt_len - 1;
+ hf_data->init(&hc.vtable);
+ memset(tmp, 0, 8);
+ hf_data->update(&hc.vtable, tmp, 8);
+ hf_data->update(&hc.vtable, hash, hash_len);
+ hf_data->update(&hc.vtable, salt, salt_len);
+ hf_data->out(&hc.vtable, tmp);
+
+ /*
+ * Check that the recomputed H value matches the one appearing
+ * in the string.
+ */
+ for (u = 0; u < hash_len; u ++) {
+ r |= tmp[u] ^ x[(xlen - salt_len - 1) + u];
+ }
+
+ return EQ0(r);
+}
diff --git a/test/monniaux/BearSSL/src/rsa/rsa_ssl_decrypt.c b/test/monniaux/BearSSL/src/rsa/rsa_ssl_decrypt.c
new file mode 100644
index 00000000..047eb18c
--- /dev/null
+++ b/test/monniaux/BearSSL/src/rsa/rsa_ssl_decrypt.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_ssl_decrypt(br_rsa_private core, const br_rsa_private_key *sk,
+ unsigned char *data, size_t len)
+{
+ uint32_t x;
+ size_t u;
+
+ /*
+ * A first check on length. Since this test works only on the
+ * buffer length, it needs not (and cannot) be constant-time.
+ */
+ if (len < 59 || len != (sk->n_bitlen + 7) >> 3) {
+ return 0;
+ }
+ x = core(data, sk);
+
+ x &= EQ(data[0], 0x00);
+ x &= EQ(data[1], 0x02);
+ for (u = 2; u < (len - 49); u ++) {
+ x &= NEQ(data[u], 0);
+ }
+ x &= EQ(data[len - 49], 0x00);
+ memmove(data, data + len - 48, 48);
+ return x;
+}