aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/openssl/crypto
diff options
context:
space:
mode:
authorJung-uk Kim <jkim@FreeBSD.org>2014-10-15 19:12:05 +0000
committerJung-uk Kim <jkim@FreeBSD.org>2014-10-15 19:12:05 +0000
commitfa5fddf17153bfcd7ee6e86d24ca4b3f71689aa4 (patch)
treec23fa858f36ae42eb7fe9898b481a136f3f8733b /crypto/openssl/crypto
parent99b9076c210de967b6a9a34209b53285a8e64b3b (diff)
parent58ab7656b2c140e06d60a7831a9f5b6e1ddc2fe5 (diff)
downloadsrc-fa5fddf17153bfcd7ee6e86d24ca4b3f71689aa4.tar.gz
src-fa5fddf17153bfcd7ee6e86d24ca4b3f71689aa4.zip
Merge OpenSSL 1.0.1j.
Notes
Notes: svn path=/head/; revision=273144
Diffstat (limited to 'crypto/openssl/crypto')
-rw-r--r--crypto/openssl/crypto/Makefile4
-rwxr-xr-xcrypto/openssl/crypto/aes/asm/aesni-x86_64.pl52
-rw-r--r--crypto/openssl/crypto/asn1/a_strex.c1
-rw-r--r--crypto/openssl/crypto/bn/asm/x86_64-gcc.c8
-rw-r--r--crypto/openssl/crypto/bn/bn_exp.c9
-rw-r--r--crypto/openssl/crypto/bn/bn_nist.c6
-rw-r--r--crypto/openssl/crypto/bn/exptest.c45
-rw-r--r--crypto/openssl/crypto/constant_time_locl.h216
-rw-r--r--crypto/openssl/crypto/constant_time_test.c330
-rw-r--r--crypto/openssl/crypto/dsa/dsa_ameth.c7
-rw-r--r--crypto/openssl/crypto/ebcdic.h7
-rw-r--r--crypto/openssl/crypto/ec/ec.h2
-rw-r--r--crypto/openssl/crypto/ec/ec2_smpl.c9
-rw-r--r--crypto/openssl/crypto/ec/ec_ameth.c14
-rw-r--r--crypto/openssl/crypto/ec/ec_asn1.c40
-rw-r--r--crypto/openssl/crypto/ec/ecp_mont.c9
-rw-r--r--crypto/openssl/crypto/ec/ecp_nist.c9
-rw-r--r--crypto/openssl/crypto/ec/ecp_smpl.c13
-rw-r--r--crypto/openssl/crypto/ec/ectest.c5
-rw-r--r--crypto/openssl/crypto/evp/Makefile2
-rw-r--r--crypto/openssl/crypto/evp/e_aes.c2
-rw-r--r--crypto/openssl/crypto/evp/evp_enc.c56
-rwxr-xr-xcrypto/openssl/crypto/md5/asm/md5-x86_64.pl2
-rw-r--r--crypto/openssl/crypto/modes/modes.h6
-rw-r--r--crypto/openssl/crypto/ocsp/ocsp_vfy.c7
-rw-r--r--crypto/openssl/crypto/opensslconf.h6
-rw-r--r--crypto/openssl/crypto/opensslv.h13
-rw-r--r--crypto/openssl/crypto/ossl_typ.h7
-rw-r--r--crypto/openssl/crypto/pkcs7/pkcs7.h4
-rw-r--r--crypto/openssl/crypto/pqueue/pqueue.h6
-rw-r--r--crypto/openssl/crypto/rsa/Makefile5
-rw-r--r--crypto/openssl/crypto/rsa/rsa.h1
-rw-r--r--crypto/openssl/crypto/rsa/rsa_err.c1
-rw-r--r--crypto/openssl/crypto/rsa/rsa_oaep.c150
-rw-r--r--crypto/openssl/crypto/rsa/rsa_pk1.c103
-rw-r--r--crypto/openssl/crypto/rsa/rsa_sign.c21
-rw-r--r--crypto/openssl/crypto/stack/safestack.h8
37 files changed, 981 insertions, 205 deletions
diff --git a/crypto/openssl/crypto/Makefile b/crypto/openssl/crypto/Makefile
index 2498df2d5509..b57dd78bbf27 100644
--- a/crypto/openssl/crypto/Makefile
+++ b/crypto/openssl/crypto/Makefile
@@ -32,6 +32,7 @@ CPUID_OBJ=mem_clr.o
LIBS=
GENERAL=Makefile README crypto-lib.com install.com
+TEST=constant_time_test.c
LIB= $(TOP)/libcrypto.a
SHARED_LIB= libcrypto$(SHLIB_EXT)
@@ -44,7 +45,8 @@ SRC= $(LIBSRC)
EXHEADER= crypto.h opensslv.h opensslconf.h ebcdic.h symhacks.h \
ossl_typ.h
-HEADER= cryptlib.h buildinf.h md32_common.h o_time.h o_str.h o_dir.h $(EXHEADER)
+HEADER= cryptlib.h buildinf.h md32_common.h o_time.h o_str.h o_dir.h \
+ constant_time_locl.h $(EXHEADER)
ALL= $(GENERAL) $(SRC) $(HEADER)
diff --git a/crypto/openssl/crypto/aes/asm/aesni-x86_64.pl b/crypto/openssl/crypto/aes/asm/aesni-x86_64.pl
index 0dbb194b8d74..c9270dfddc18 100755
--- a/crypto/openssl/crypto/aes/asm/aesni-x86_64.pl
+++ b/crypto/openssl/crypto/aes/asm/aesni-x86_64.pl
@@ -525,6 +525,16 @@ $code.=<<___;
.type aesni_ecb_encrypt,\@function,5
.align 16
aesni_ecb_encrypt:
+___
+$code.=<<___ if ($win64);
+ lea -0x58(%rsp),%rsp
+ movaps %xmm6,(%rsp)
+ movaps %xmm7,0x10(%rsp)
+ movaps %xmm8,0x20(%rsp)
+ movaps %xmm9,0x30(%rsp)
+.Lecb_enc_body:
+___
+$code.=<<___;
and \$-16,$len
jz .Lecb_ret
@@ -805,6 +815,16 @@ $code.=<<___;
movups $inout5,0x50($out)
.Lecb_ret:
+___
+$code.=<<___ if ($win64);
+ movaps (%rsp),%xmm6
+ movaps 0x10(%rsp),%xmm7
+ movaps 0x20(%rsp),%xmm8
+ movaps 0x30(%rsp),%xmm9
+ lea 0x58(%rsp),%rsp
+.Lecb_enc_ret:
+___
+$code.=<<___;
ret
.size aesni_ecb_encrypt,.-aesni_ecb_encrypt
___
@@ -2730,28 +2750,9 @@ $code.=<<___;
.extern __imp_RtlVirtualUnwind
___
$code.=<<___ if ($PREFIX eq "aesni");
-.type ecb_se_handler,\@abi-omnipotent
-.align 16
-ecb_se_handler:
- push %rsi
- push %rdi
- push %rbx
- push %rbp
- push %r12
- push %r13
- push %r14
- push %r15
- pushfq
- sub \$64,%rsp
-
- mov 152($context),%rax # pull context->Rsp
-
- jmp .Lcommon_seh_tail
-.size ecb_se_handler,.-ecb_se_handler
-
-.type ccm64_se_handler,\@abi-omnipotent
+.type ecb_ccm64_se_handler,\@abi-omnipotent
.align 16
-ccm64_se_handler:
+ecb_ccm64_se_handler:
push %rsi
push %rdi
push %rbx
@@ -2788,7 +2789,7 @@ ccm64_se_handler:
lea 0x58(%rax),%rax # adjust stack pointer
jmp .Lcommon_seh_tail
-.size ccm64_se_handler,.-ccm64_se_handler
+.size ecb_ccm64_se_handler,.-ecb_ccm64_se_handler
.type ctr32_se_handler,\@abi-omnipotent
.align 16
@@ -2993,14 +2994,15 @@ ___
$code.=<<___ if ($PREFIX eq "aesni");
.LSEH_info_ecb:
.byte 9,0,0,0
- .rva ecb_se_handler
+ .rva ecb_ccm64_se_handler
+ .rva .Lecb_enc_body,.Lecb_enc_ret # HandlerData[]
.LSEH_info_ccm64_enc:
.byte 9,0,0,0
- .rva ccm64_se_handler
+ .rva ecb_ccm64_se_handler
.rva .Lccm64_enc_body,.Lccm64_enc_ret # HandlerData[]
.LSEH_info_ccm64_dec:
.byte 9,0,0,0
- .rva ccm64_se_handler
+ .rva ecb_ccm64_se_handler
.rva .Lccm64_dec_body,.Lccm64_dec_ret # HandlerData[]
.LSEH_info_ctr32:
.byte 9,0,0,0
diff --git a/crypto/openssl/crypto/asn1/a_strex.c b/crypto/openssl/crypto/asn1/a_strex.c
index ead37ac32582..8fb4193bc0b2 100644
--- a/crypto/openssl/crypto/asn1/a_strex.c
+++ b/crypto/openssl/crypto/asn1/a_strex.c
@@ -568,6 +568,7 @@ int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in)
mbflag |= MBSTRING_FLAG;
stmp.data = NULL;
stmp.length = 0;
+ stmp.flags = 0;
ret = ASN1_mbstring_copy(&str, in->data, in->length, mbflag, B_ASN1_UTF8STRING);
if(ret < 0) return ret;
*out = stmp.data;
diff --git a/crypto/openssl/crypto/bn/asm/x86_64-gcc.c b/crypto/openssl/crypto/bn/asm/x86_64-gcc.c
index acb0b401181e..31476abebfb7 100644
--- a/crypto/openssl/crypto/bn/asm/x86_64-gcc.c
+++ b/crypto/openssl/crypto/bn/asm/x86_64-gcc.c
@@ -189,7 +189,7 @@ BN_ULONG bn_add_words (BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int
if (n <= 0) return 0;
- asm (
+ asm volatile (
" subq %2,%2 \n"
".p2align 4 \n"
"1: movq (%4,%2,8),%0 \n"
@@ -200,7 +200,7 @@ BN_ULONG bn_add_words (BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int
" sbbq %0,%0 \n"
: "=&a"(ret),"+c"(n),"=&r"(i)
: "r"(rp),"r"(ap),"r"(bp)
- : "cc"
+ : "cc", "memory"
);
return ret&1;
@@ -212,7 +212,7 @@ BN_ULONG bn_sub_words (BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int
if (n <= 0) return 0;
- asm (
+ asm volatile (
" subq %2,%2 \n"
".p2align 4 \n"
"1: movq (%4,%2,8),%0 \n"
@@ -223,7 +223,7 @@ BN_ULONG bn_sub_words (BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int
" sbbq %0,%0 \n"
: "=&a"(ret),"+c"(n),"=&r"(i)
: "r"(rp),"r"(ap),"r"(bp)
- : "cc"
+ : "cc", "memory"
);
return ret&1;
diff --git a/crypto/openssl/crypto/bn/bn_exp.c b/crypto/openssl/crypto/bn/bn_exp.c
index 5e7eb3373ffd..611fa3262bed 100644
--- a/crypto/openssl/crypto/bn/bn_exp.c
+++ b/crypto/openssl/crypto/bn/bn_exp.c
@@ -874,7 +874,14 @@ int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
bits = BN_num_bits(p);
if (bits == 0)
{
- ret = BN_one(rr);
+ /* x**0 mod 1 is still zero. */
+ if (BN_is_one(m))
+ {
+ ret = 1;
+ BN_zero(rr);
+ }
+ else
+ ret = BN_one(rr);
return ret;
}
if (a == 0)
diff --git a/crypto/openssl/crypto/bn/bn_nist.c b/crypto/openssl/crypto/bn/bn_nist.c
index e22968d4a33b..abb1570853ec 100644
--- a/crypto/openssl/crypto/bn/bn_nist.c
+++ b/crypto/openssl/crypto/bn/bn_nist.c
@@ -1088,9 +1088,9 @@ int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
/* ... and right shift */
for (val=t_d[0],i=0; i<BN_NIST_521_TOP-1; i++)
{
- tmp = val>>BN_NIST_521_RSHIFT;
- val = t_d[i+1];
- t_d[i] = (tmp | val<<BN_NIST_521_LSHIFT) & BN_MASK2;
+ t_d[i] = ( val>>BN_NIST_521_RSHIFT |
+ (tmp=t_d[i+1])<<BN_NIST_521_LSHIFT ) & BN_MASK2;
+ val=tmp;
}
t_d[i] = val>>BN_NIST_521_RSHIFT;
/* lower 521 bits */
diff --git a/crypto/openssl/crypto/bn/exptest.c b/crypto/openssl/crypto/bn/exptest.c
index 074a8e882a8e..5fa02a1229e8 100644
--- a/crypto/openssl/crypto/bn/exptest.c
+++ b/crypto/openssl/crypto/bn/exptest.c
@@ -71,6 +71,43 @@
static const char rnd_seed[] = "string to make the random number generator think it has entropy";
+/* test_exp_mod_zero tests that x**0 mod 1 == 0. It returns zero on success. */
+static int test_exp_mod_zero() {
+ BIGNUM a, p, m;
+ BIGNUM r;
+ BN_CTX *ctx = BN_CTX_new();
+ int ret = 1;
+
+ BN_init(&m);
+ BN_one(&m);
+
+ BN_init(&a);
+ BN_one(&a);
+
+ BN_init(&p);
+ BN_zero(&p);
+
+ BN_init(&r);
+ BN_mod_exp(&r, &a, &p, &m, ctx);
+ BN_CTX_free(ctx);
+
+ if (BN_is_zero(&r))
+ ret = 0;
+ else
+ {
+ printf("1**0 mod 1 = ");
+ BN_print_fp(stdout, &r);
+ printf(", should be 0\n");
+ }
+
+ BN_free(&r);
+ BN_free(&a);
+ BN_free(&p);
+ BN_free(&m);
+
+ return ret;
+}
+
int main(int argc, char *argv[])
{
BN_CTX *ctx;
@@ -190,7 +227,13 @@ int main(int argc, char *argv[])
ERR_remove_thread_state(NULL);
CRYPTO_mem_leaks(out);
BIO_free(out);
- printf(" done\n");
+ printf("\n");
+
+ if (test_exp_mod_zero() != 0)
+ goto err;
+
+ printf("done\n");
+
EXIT(0);
err:
ERR_load_crypto_strings();
diff --git a/crypto/openssl/crypto/constant_time_locl.h b/crypto/openssl/crypto/constant_time_locl.h
new file mode 100644
index 000000000000..c0483939fe3d
--- /dev/null
+++ b/crypto/openssl/crypto/constant_time_locl.h
@@ -0,0 +1,216 @@
+/* crypto/constant_time_locl.h */
+/*
+ * Utilities for constant-time cryptography.
+ *
+ * Author: Emilia Kasper (emilia@openssl.org)
+ * Based on previous work by Bodo Moeller, Emilia Kasper, Adam Langley
+ * (Google).
+ * ====================================================================
+ * Copyright (c) 2014 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_CONSTANT_TIME_LOCL_H
+#define HEADER_CONSTANT_TIME_LOCL_H
+
+#include "e_os.h" /* For 'inline' */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The boolean methods return a bitmask of all ones (0xff...f) for true
+ * and 0 for false. This is useful for choosing a value based on the result
+ * of a conditional in constant time. For example,
+ *
+ * if (a < b) {
+ * c = a;
+ * } else {
+ * c = b;
+ * }
+ *
+ * can be written as
+ *
+ * unsigned int lt = constant_time_lt(a, b);
+ * c = constant_time_select(lt, a, b);
+ */
+
+/*
+ * Returns the given value with the MSB copied to all the other
+ * bits. Uses the fact that arithmetic shift shifts-in the sign bit.
+ * However, this is not ensured by the C standard so you may need to
+ * replace this with something else on odd CPUs.
+ */
+static inline unsigned int constant_time_msb(unsigned int a);
+
+/*
+ * Returns 0xff..f if a < b and 0 otherwise.
+ */
+static inline unsigned int constant_time_lt(unsigned int a, unsigned int b);
+/* Convenience method for getting an 8-bit mask. */
+static inline unsigned char constant_time_lt_8(unsigned int a, unsigned int b);
+
+/*
+ * Returns 0xff..f if a >= b and 0 otherwise.
+ */
+static inline unsigned int constant_time_ge(unsigned int a, unsigned int b);
+/* Convenience method for getting an 8-bit mask. */
+static inline unsigned char constant_time_ge_8(unsigned int a, unsigned int b);
+
+/*
+ * Returns 0xff..f if a == 0 and 0 otherwise.
+ */
+static inline unsigned int constant_time_is_zero(unsigned int a);
+/* Convenience method for getting an 8-bit mask. */
+static inline unsigned char constant_time_is_zero_8(unsigned int a);
+
+
+/*
+ * Returns 0xff..f if a == b and 0 otherwise.
+ */
+static inline unsigned int constant_time_eq(unsigned int a, unsigned int b);
+/* Convenience method for getting an 8-bit mask. */
+static inline unsigned char constant_time_eq_8(unsigned int a, unsigned int b);
+/* Signed integers. */
+static inline unsigned int constant_time_eq_int(int a, int b);
+/* Convenience method for getting an 8-bit mask. */
+static inline unsigned char constant_time_eq_int_8(int a, int b);
+
+
+/*
+ * Returns (mask & a) | (~mask & b).
+ *
+ * When |mask| is all 1s or all 0s (as returned by the methods above),
+ * the select methods return either |a| (if |mask| is nonzero) or |b|
+ * (if |mask| is zero).
+ */
+static inline unsigned int constant_time_select(unsigned int mask,
+ unsigned int a, unsigned int b);
+/* Convenience method for unsigned chars. */
+static inline unsigned char constant_time_select_8(unsigned char mask,
+ unsigned char a, unsigned char b);
+/* Convenience method for signed integers. */
+static inline int constant_time_select_int(unsigned int mask, int a, int b);
+
+static inline unsigned int constant_time_msb(unsigned int a)
+ {
+ return (unsigned int)((int)(a) >> (sizeof(int) * 8 - 1));
+ }
+
+static inline unsigned int constant_time_lt(unsigned int a, unsigned int b)
+ {
+ unsigned int lt;
+ /* Case 1: msb(a) == msb(b). a < b iff the MSB of a - b is set.*/
+ lt = ~(a ^ b) & (a - b);
+ /* Case 2: msb(a) != msb(b). a < b iff the MSB of b is set. */
+ lt |= ~a & b;
+ return constant_time_msb(lt);
+ }
+
+static inline unsigned char constant_time_lt_8(unsigned int a, unsigned int b)
+ {
+ return (unsigned char)(constant_time_lt(a, b));
+ }
+
+static inline unsigned int constant_time_ge(unsigned int a, unsigned int b)
+ {
+ unsigned int ge;
+ /* Case 1: msb(a) == msb(b). a >= b iff the MSB of a - b is not set.*/
+ ge = ~((a ^ b) | (a - b));
+ /* Case 2: msb(a) != msb(b). a >= b iff the MSB of a is set. */
+ ge |= a & ~b;
+ return constant_time_msb(ge);
+ }
+
+static inline unsigned char constant_time_ge_8(unsigned int a, unsigned int b)
+ {
+ return (unsigned char)(constant_time_ge(a, b));
+ }
+
+static inline unsigned int constant_time_is_zero(unsigned int a)
+ {
+ return constant_time_msb(~a & (a - 1));
+ }
+
+static inline unsigned char constant_time_is_zero_8(unsigned int a)
+ {
+ return (unsigned char)(constant_time_is_zero(a));
+ }
+
+static inline unsigned int constant_time_eq(unsigned int a, unsigned int b)
+ {
+ return constant_time_is_zero(a ^ b);
+ }
+
+static inline unsigned char constant_time_eq_8(unsigned int a, unsigned int b)
+ {
+ return (unsigned char)(constant_time_eq(a, b));
+ }
+
+static inline unsigned int constant_time_eq_int(int a, int b)
+ {
+ return constant_time_eq((unsigned)(a), (unsigned)(b));
+ }
+
+static inline unsigned char constant_time_eq_int_8(int a, int b)
+ {
+ return constant_time_eq_8((unsigned)(a), (unsigned)(b));
+ }
+
+static inline unsigned int constant_time_select(unsigned int mask,
+ unsigned int a, unsigned int b)
+ {
+ return (mask & a) | (~mask & b);
+ }
+
+static inline unsigned char constant_time_select_8(unsigned char mask,
+ unsigned char a, unsigned char b)
+ {
+ return (unsigned char)(constant_time_select(mask, a, b));
+ }
+
+inline int constant_time_select_int(unsigned int mask, int a, int b)
+ {
+ return (int)(constant_time_select(mask, (unsigned)(a), (unsigned)(b)));
+ }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HEADER_CONSTANT_TIME_LOCL_H */
diff --git a/crypto/openssl/crypto/constant_time_test.c b/crypto/openssl/crypto/constant_time_test.c
new file mode 100644
index 000000000000..d9c6a44aed05
--- /dev/null
+++ b/crypto/openssl/crypto/constant_time_test.c
@@ -0,0 +1,330 @@
+/* crypto/constant_time_test.c */
+/*
+ * Utilities for constant-time cryptography.
+ *
+ * Author: Emilia Kasper (emilia@openssl.org)
+ * Based on previous work by Bodo Moeller, Emilia Kasper, Adam Langley
+ * (Google).
+ * ====================================================================
+ * Copyright (c) 2014 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "../crypto/constant_time_locl.h"
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static const unsigned int CONSTTIME_TRUE = (unsigned)(~0);
+static const unsigned int CONSTTIME_FALSE = 0;
+static const unsigned char CONSTTIME_TRUE_8 = 0xff;
+static const unsigned char CONSTTIME_FALSE_8 = 0;
+
+static int test_binary_op(unsigned int (*op)(unsigned int a, unsigned int b),
+ const char* op_name, unsigned int a, unsigned int b, int is_true)
+ {
+ unsigned c = op(a, b);
+ if (is_true && c != CONSTTIME_TRUE)
+ {
+ fprintf(stderr, "Test failed for %s(%du, %du): expected %du "
+ "(TRUE), got %du\n", op_name, a, b, CONSTTIME_TRUE, c);
+ return 1;
+ }
+ else if (!is_true && c != CONSTTIME_FALSE)
+ {
+ fprintf(stderr, "Test failed for %s(%du, %du): expected %du "
+ "(FALSE), got %du\n", op_name, a, b, CONSTTIME_FALSE,
+ c);
+ return 1;
+ }
+ return 0;
+ }
+
+static int test_binary_op_8(unsigned char (*op)(unsigned int a, unsigned int b),
+ const char* op_name, unsigned int a, unsigned int b, int is_true)
+ {
+ unsigned char c = op(a, b);
+ if (is_true && c != CONSTTIME_TRUE_8)
+ {
+ fprintf(stderr, "Test failed for %s(%du, %du): expected %u "
+ "(TRUE), got %u\n", op_name, a, b, CONSTTIME_TRUE_8, c);
+ return 1;
+ }
+ else if (!is_true && c != CONSTTIME_FALSE_8)
+ {
+ fprintf(stderr, "Test failed for %s(%du, %du): expected %u "
+ "(FALSE), got %u\n", op_name, a, b, CONSTTIME_FALSE_8,
+ c);
+ return 1;
+ }
+ return 0;
+ }
+
+static int test_is_zero(unsigned int a)
+ {
+ unsigned int c = constant_time_is_zero(a);
+ if (a == 0 && c != CONSTTIME_TRUE)
+ {
+ fprintf(stderr, "Test failed for constant_time_is_zero(%du): "
+ "expected %du (TRUE), got %du\n", a, CONSTTIME_TRUE, c);
+ return 1;
+ }
+ else if (a != 0 && c != CONSTTIME_FALSE)
+ {
+ fprintf(stderr, "Test failed for constant_time_is_zero(%du): "
+ "expected %du (FALSE), got %du\n", a, CONSTTIME_FALSE,
+ c);
+ return 1;
+ }
+ return 0;
+ }
+
+static int test_is_zero_8(unsigned int a)
+ {
+ unsigned char c = constant_time_is_zero_8(a);
+ if (a == 0 && c != CONSTTIME_TRUE_8)
+ {
+ fprintf(stderr, "Test failed for constant_time_is_zero(%du): "
+ "expected %u (TRUE), got %u\n", a, CONSTTIME_TRUE_8, c);
+ return 1;
+ }
+ else if (a != 0 && c != CONSTTIME_FALSE)
+ {
+ fprintf(stderr, "Test failed for constant_time_is_zero(%du): "
+ "expected %u (FALSE), got %u\n", a, CONSTTIME_FALSE_8,
+ c);
+ return 1;
+ }
+ return 0;
+ }
+
+static int test_select(unsigned int a, unsigned int b)
+ {
+ unsigned int selected = constant_time_select(CONSTTIME_TRUE, a, b);
+ if (selected != a)
+ {
+ fprintf(stderr, "Test failed for constant_time_select(%du, %du,"
+ "%du): expected %du(first value), got %du\n",
+ CONSTTIME_TRUE, a, b, a, selected);
+ return 1;
+ }
+ selected = constant_time_select(CONSTTIME_FALSE, a, b);
+ if (selected != b)
+ {
+ fprintf(stderr, "Test failed for constant_time_select(%du, %du,"
+ "%du): expected %du(second value), got %du\n",
+ CONSTTIME_FALSE, a, b, b, selected);
+ return 1;
+ }
+ return 0;
+ }
+
+static int test_select_8(unsigned char a, unsigned char b)
+ {
+ unsigned char selected = constant_time_select_8(CONSTTIME_TRUE_8, a, b);
+ if (selected != a)
+ {
+ fprintf(stderr, "Test failed for constant_time_select(%u, %u,"
+ "%u): expected %u(first value), got %u\n",
+ CONSTTIME_TRUE, a, b, a, selected);
+ return 1;
+ }
+ selected = constant_time_select_8(CONSTTIME_FALSE_8, a, b);
+ if (selected != b)
+ {
+ fprintf(stderr, "Test failed for constant_time_select(%u, %u,"
+ "%u): expected %u(second value), got %u\n",
+ CONSTTIME_FALSE, a, b, b, selected);
+ return 1;
+ }
+ return 0;
+ }
+
+static int test_select_int(int a, int b)
+ {
+ int selected = constant_time_select_int(CONSTTIME_TRUE, a, b);
+ if (selected != a)
+ {
+ fprintf(stderr, "Test failed for constant_time_select(%du, %d,"
+ "%d): expected %d(first value), got %d\n",
+ CONSTTIME_TRUE, a, b, a, selected);
+ return 1;
+ }
+ selected = constant_time_select_int(CONSTTIME_FALSE, a, b);
+ if (selected != b)
+ {
+ fprintf(stderr, "Test failed for constant_time_select(%du, %d,"
+ "%d): expected %d(second value), got %d\n",
+ CONSTTIME_FALSE, a, b, b, selected);
+ return 1;
+ }
+ return 0;
+ }
+
+static int test_eq_int(int a, int b)
+ {
+ unsigned int equal = constant_time_eq_int(a, b);
+ if (a == b && equal != CONSTTIME_TRUE)
+ {
+ fprintf(stderr, "Test failed for constant_time_eq_int(%d, %d): "
+ "expected %du(TRUE), got %du\n",
+ a, b, CONSTTIME_TRUE, equal);
+ return 1;
+ }
+ else if (a != b && equal != CONSTTIME_FALSE)
+ {
+ fprintf(stderr, "Test failed for constant_time_eq_int(%d, %d): "
+ "expected %du(FALSE), got %du\n",
+ a, b, CONSTTIME_FALSE, equal);
+ return 1;
+ }
+ return 0;
+ }
+
+static int test_eq_int_8(int a, int b)
+ {
+ unsigned char equal = constant_time_eq_int_8(a, b);
+ if (a == b && equal != CONSTTIME_TRUE_8)
+ {
+ fprintf(stderr, "Test failed for constant_time_eq_int_8(%d, %d): "
+ "expected %u(TRUE), got %u\n",
+ a, b, CONSTTIME_TRUE_8, equal);
+ return 1;
+ }
+ else if (a != b && equal != CONSTTIME_FALSE_8)
+ {
+ fprintf(stderr, "Test failed for constant_time_eq_int_8(%d, %d): "
+ "expected %u(FALSE), got %u\n",
+ a, b, CONSTTIME_FALSE_8, equal);
+ return 1;
+ }
+ return 0;
+ }
+
+static unsigned int test_values[] = {0, 1, 1024, 12345, 32000, UINT_MAX/2-1,
+ UINT_MAX/2, UINT_MAX/2+1, UINT_MAX-1,
+ UINT_MAX};
+
+static unsigned char test_values_8[] = {0, 1, 2, 20, 32, 127, 128, 129, 255};
+
+static int signed_test_values[] = {0, 1, -1, 1024, -1024, 12345, -12345,
+ 32000, -32000, INT_MAX, INT_MIN, INT_MAX-1,
+ INT_MIN+1};
+
+
+int main(int argc, char *argv[])
+ {
+ unsigned int a, b, i, j;
+ int c, d;
+ unsigned char e, f;
+ int num_failed = 0, num_all = 0;
+ fprintf(stdout, "Testing constant time operations...\n");
+
+ for (i = 0; i < sizeof(test_values)/sizeof(int); ++i)
+ {
+ a = test_values[i];
+ num_failed += test_is_zero(a);
+ num_failed += test_is_zero_8(a);
+ num_all += 2;
+ for (j = 0; j < sizeof(test_values)/sizeof(int); ++j)
+ {
+ b = test_values[j];
+ num_failed += test_binary_op(&constant_time_lt,
+ "constant_time_lt", a, b, a < b);
+ num_failed += test_binary_op_8(&constant_time_lt_8,
+ "constant_time_lt_8", a, b, a < b);
+ num_failed += test_binary_op(&constant_time_lt,
+ "constant_time_lt_8", b, a, b < a);
+ num_failed += test_binary_op_8(&constant_time_lt_8,
+ "constant_time_lt_8", b, a, b < a);
+ num_failed += test_binary_op(&constant_time_ge,
+ "constant_time_ge", a, b, a >= b);
+ num_failed += test_binary_op_8(&constant_time_ge_8,
+ "constant_time_ge_8", a, b, a >= b);
+ num_failed += test_binary_op(&constant_time_ge,
+ "constant_time_ge", b, a, b >= a);
+ num_failed += test_binary_op_8(&constant_time_ge_8,
+ "constant_time_ge_8", b, a, b >= a);
+ num_failed += test_binary_op(&constant_time_eq,
+ "constant_time_eq", a, b, a == b);
+ num_failed += test_binary_op_8(&constant_time_eq_8,
+ "constant_time_eq_8", a, b, a == b);
+ num_failed += test_binary_op(&constant_time_eq,
+ "constant_time_eq", b, a, b == a);
+ num_failed += test_binary_op_8(&constant_time_eq_8,
+ "constant_time_eq_8", b, a, b == a);
+ num_failed += test_select(a, b);
+ num_all += 13;
+ }
+ }
+
+ for (i = 0; i < sizeof(signed_test_values)/sizeof(int); ++i)
+ {
+ c = signed_test_values[i];
+ for (j = 0; j < sizeof(signed_test_values)/sizeof(int); ++j)
+ {
+ d = signed_test_values[j];
+ num_failed += test_select_int(c, d);
+ num_failed += test_eq_int(c, d);
+ num_failed += test_eq_int_8(c, d);
+ num_all += 3;
+ }
+ }
+
+ for (i = 0; i < sizeof(test_values_8); ++i)
+ {
+ e = test_values_8[i];
+ for (j = 0; j < sizeof(test_values_8); ++j)
+ {
+ f = test_values_8[j];
+ num_failed += test_select_8(e, f);
+ num_all += 1;
+ }
+ }
+
+ if (!num_failed)
+ {
+ fprintf(stdout, "ok (ran %d tests)\n", num_all);
+ return EXIT_SUCCESS;
+ }
+ else
+ {
+ fprintf(stdout, "%d of %d tests failed!\n", num_failed, num_all);
+ return EXIT_FAILURE;
+ }
+ }
diff --git a/crypto/openssl/crypto/dsa/dsa_ameth.c b/crypto/openssl/crypto/dsa/dsa_ameth.c
index 376156ec5ef3..5af76eade59a 100644
--- a/crypto/openssl/crypto/dsa/dsa_ameth.c
+++ b/crypto/openssl/crypto/dsa/dsa_ameth.c
@@ -307,6 +307,12 @@ static int dsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
unsigned char *dp = NULL;
int dplen;
+ if (!pkey->pkey.dsa || !pkey->pkey.dsa->priv_key)
+ {
+ DSAerr(DSA_F_DSA_PRIV_ENCODE,DSA_R_MISSING_PARAMETERS);
+ goto err;
+ }
+
params = ASN1_STRING_new();
if (!params)
@@ -701,4 +707,3 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[] =
old_dsa_priv_encode
}
};
-
diff --git a/crypto/openssl/crypto/ebcdic.h b/crypto/openssl/crypto/ebcdic.h
index 6d65afcf9e75..85f3cf7f66b9 100644
--- a/crypto/openssl/crypto/ebcdic.h
+++ b/crypto/openssl/crypto/ebcdic.h
@@ -5,6 +5,10 @@
#include <sys/types.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* Avoid name clashes with other applications */
#define os_toascii _openssl_os_toascii
#define os_toebcdic _openssl_os_toebcdic
@@ -16,4 +20,7 @@ extern const unsigned char os_toebcdic[256];
void *ebcdic2ascii(void *dest, const void *srce, size_t count);
void *ascii2ebcdic(void *dest, const void *srce, size_t count);
+#ifdef __cplusplus
+}
+#endif
#endif
diff --git a/crypto/openssl/crypto/ec/ec.h b/crypto/openssl/crypto/ec/ec.h
index dfe8710d3309..572111f16cd1 100644
--- a/crypto/openssl/crypto/ec/ec.h
+++ b/crypto/openssl/crypto/ec/ec.h
@@ -629,7 +629,7 @@ int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN
int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx);
int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx);
-/** Computes r = generator * n sum_{i=0}^num p[i] * m[i]
+/** Computes r = generator * n sum_{i=0}^{num-1} p[i] * m[i]
* \param group underlying EC_GROUP object
* \param r EC_POINT object for the result
* \param n BIGNUM with the multiplier for the group generator (optional)
diff --git a/crypto/openssl/crypto/ec/ec2_smpl.c b/crypto/openssl/crypto/ec/ec2_smpl.c
index e0e59c7d8299..62223cbb01f2 100644
--- a/crypto/openssl/crypto/ec/ec2_smpl.c
+++ b/crypto/openssl/crypto/ec/ec2_smpl.c
@@ -80,9 +80,6 @@
const EC_METHOD *EC_GF2m_simple_method(void)
{
-#ifdef OPENSSL_FIPS
- return fips_ec_gf2m_simple_method();
-#else
static const EC_METHOD ret = {
EC_FLAGS_DEFAULT_OCT,
NID_X9_62_characteristic_two_field,
@@ -125,8 +122,12 @@ const EC_METHOD *EC_GF2m_simple_method(void)
0 /* field_decode */,
0 /* field_set_to_one */ };
- return &ret;
+#ifdef OPENSSL_FIPS
+ if (FIPS_mode())
+ return fips_ec_gf2m_simple_method();
#endif
+
+ return &ret;
}
diff --git a/crypto/openssl/crypto/ec/ec_ameth.c b/crypto/openssl/crypto/ec/ec_ameth.c
index f715a238a6fc..11283769b939 100644
--- a/crypto/openssl/crypto/ec/ec_ameth.c
+++ b/crypto/openssl/crypto/ec/ec_ameth.c
@@ -453,14 +453,16 @@ static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype)
if (ktype > 0)
{
public_key = EC_KEY_get0_public_key(x);
- if ((pub_key = EC_POINT_point2bn(group, public_key,
- EC_KEY_get_conv_form(x), NULL, ctx)) == NULL)
+ if (public_key != NULL)
{
- reason = ERR_R_EC_LIB;
- goto err;
- }
- if (pub_key)
+ if ((pub_key = EC_POINT_point2bn(group, public_key,
+ EC_KEY_get_conv_form(x), NULL, ctx)) == NULL)
+ {
+ reason = ERR_R_EC_LIB;
+ goto err;
+ }
buf_len = (size_t)BN_num_bytes(pub_key);
+ }
}
if (ktype == 2)
diff --git a/crypto/openssl/crypto/ec/ec_asn1.c b/crypto/openssl/crypto/ec/ec_asn1.c
index e94f34e11b7c..52d31c2f9642 100644
--- a/crypto/openssl/crypto/ec/ec_asn1.c
+++ b/crypto/openssl/crypto/ec/ec_asn1.c
@@ -1183,29 +1183,46 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
goto err;
}
+ if (ret->pub_key)
+ EC_POINT_clear_free(ret->pub_key);
+ ret->pub_key = EC_POINT_new(ret->group);
+ if (ret->pub_key == NULL)
+ {
+ ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
+ goto err;
+ }
+
if (priv_key->publicKey)
{
const unsigned char *pub_oct;
- size_t pub_oct_len;
+ int pub_oct_len;
- if (ret->pub_key)
- EC_POINT_clear_free(ret->pub_key);
- ret->pub_key = EC_POINT_new(ret->group);
- if (ret->pub_key == NULL)
+ pub_oct = M_ASN1_STRING_data(priv_key->publicKey);
+ pub_oct_len = M_ASN1_STRING_length(priv_key->publicKey);
+ /* The first byte - point conversion form - must be present. */
+ if (pub_oct_len <= 0)
{
- ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
+ ECerr(EC_F_D2I_ECPRIVATEKEY, EC_R_BUFFER_TOO_SMALL);
goto err;
}
- pub_oct = M_ASN1_STRING_data(priv_key->publicKey);
- pub_oct_len = M_ASN1_STRING_length(priv_key->publicKey);
- /* save the point conversion form */
+ /* Save the point conversion form. */
ret->conv_form = (point_conversion_form_t)(pub_oct[0] & ~0x01);
if (!EC_POINT_oct2point(ret->group, ret->pub_key,
- pub_oct, pub_oct_len, NULL))
+ pub_oct, (size_t)(pub_oct_len), NULL))
+ {
+ ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
+ goto err;
+ }
+ }
+ else
+ {
+ if (!EC_POINT_mul(ret->group, ret->pub_key, ret->priv_key, NULL, NULL, NULL))
{
ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
goto err;
}
+ /* Remember the original private-key-only encoding. */
+ ret->enc_flag |= EC_PKEY_NO_PUBKEY;
}
ok = 1;
@@ -1230,7 +1247,8 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
size_t buf_len=0, tmp_len;
EC_PRIVATEKEY *priv_key=NULL;
- if (a == NULL || a->group == NULL || a->priv_key == NULL)
+ if (a == NULL || a->group == NULL || a->priv_key == NULL ||
+ (!(a->enc_flag & EC_PKEY_NO_PUBKEY) && a->pub_key == NULL))
{
ECerr(EC_F_I2D_ECPRIVATEKEY,
ERR_R_PASSED_NULL_PARAMETER);
diff --git a/crypto/openssl/crypto/ec/ecp_mont.c b/crypto/openssl/crypto/ec/ecp_mont.c
index f04f132c7ad6..3c5ec1965ac8 100644
--- a/crypto/openssl/crypto/ec/ecp_mont.c
+++ b/crypto/openssl/crypto/ec/ecp_mont.c
@@ -72,9 +72,6 @@
const EC_METHOD *EC_GFp_mont_method(void)
{
-#ifdef OPENSSL_FIPS
- return fips_ec_gfp_mont_method();
-#else
static const EC_METHOD ret = {
EC_FLAGS_DEFAULT_OCT,
NID_X9_62_prime_field,
@@ -114,8 +111,12 @@ const EC_METHOD *EC_GFp_mont_method(void)
ec_GFp_mont_field_decode,
ec_GFp_mont_field_set_to_one };
- return &ret;
+#ifdef OPENSSL_FIPS
+ if (FIPS_mode())
+ return fips_ec_gfp_mont_method();
#endif
+
+ return &ret;
}
diff --git a/crypto/openssl/crypto/ec/ecp_nist.c b/crypto/openssl/crypto/ec/ecp_nist.c
index aad2d5f44389..db3b99e06a5f 100644
--- a/crypto/openssl/crypto/ec/ecp_nist.c
+++ b/crypto/openssl/crypto/ec/ecp_nist.c
@@ -73,9 +73,6 @@
const EC_METHOD *EC_GFp_nist_method(void)
{
-#ifdef OPENSSL_FIPS
- return fips_ec_gfp_nist_method();
-#else
static const EC_METHOD ret = {
EC_FLAGS_DEFAULT_OCT,
NID_X9_62_prime_field,
@@ -115,8 +112,12 @@ const EC_METHOD *EC_GFp_nist_method(void)
0 /* field_decode */,
0 /* field_set_to_one */ };
- return &ret;
+#ifdef OPENSSL_FIPS
+ if (FIPS_mode())
+ return fips_ec_gfp_nist_method();
#endif
+
+ return &ret;
}
int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src)
diff --git a/crypto/openssl/crypto/ec/ecp_smpl.c b/crypto/openssl/crypto/ec/ecp_smpl.c
index ef5285477a2a..2d1f35768623 100644
--- a/crypto/openssl/crypto/ec/ecp_smpl.c
+++ b/crypto/openssl/crypto/ec/ecp_smpl.c
@@ -73,9 +73,6 @@
const EC_METHOD *EC_GFp_simple_method(void)
{
-#ifdef OPENSSL_FIPS
- return fips_ec_gfp_simple_method();
-#else
static const EC_METHOD ret = {
EC_FLAGS_DEFAULT_OCT,
NID_X9_62_prime_field,
@@ -115,8 +112,12 @@ const EC_METHOD *EC_GFp_simple_method(void)
0 /* field_decode */,
0 /* field_set_to_one */ };
- return &ret;
+#ifdef OPENSSL_FIPS
+ if (FIPS_mode())
+ return fips_ec_gfp_simple_method();
#endif
+
+ return &ret;
}
@@ -1317,8 +1318,8 @@ int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT
{
for (i = 0; i < num; i++)
{
- if (prod_Z[i] != NULL)
- BN_clear_free(prod_Z[i]);
+ if (prod_Z[i] == NULL) break;
+ BN_clear_free(prod_Z[i]);
}
OPENSSL_free(prod_Z);
}
diff --git a/crypto/openssl/crypto/ec/ectest.c b/crypto/openssl/crypto/ec/ectest.c
index 82c8c8bfb119..d1bf980599c8 100644
--- a/crypto/openssl/crypto/ec/ectest.c
+++ b/crypto/openssl/crypto/ec/ectest.c
@@ -251,14 +251,15 @@ static void group_order_tests(EC_GROUP *group)
if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
/* Exercise EC_POINTs_mul, including corner cases. */
+ if (EC_POINT_is_at_infinity(group, P)) ABORT;
scalars[0] = n1; points[0] = Q; /* => infinity */
scalars[1] = n2; points[1] = P; /* => -P */
scalars[2] = n1; points[2] = Q; /* => infinity */
scalars[3] = n2; points[3] = Q; /* => infinity */
scalars[4] = n1; points[4] = P; /* => P */
scalars[5] = n2; points[5] = Q; /* => infinity */
- if (!EC_POINTs_mul(group, Q, NULL, 5, points, scalars, ctx)) ABORT;
- if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
+ if (!EC_POINTs_mul(group, P, NULL, 6, points, scalars, ctx)) ABORT;
+ if (!EC_POINT_is_at_infinity(group, P)) ABORT;
}
fprintf(stdout, "ok\n");
diff --git a/crypto/openssl/crypto/evp/Makefile b/crypto/openssl/crypto/evp/Makefile
index 5d0c6b7db4c9..fa25bff6b5ca 100644
--- a/crypto/openssl/crypto/evp/Makefile
+++ b/crypto/openssl/crypto/evp/Makefile
@@ -383,7 +383,7 @@ evp_enc.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h
evp_enc.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
evp_enc.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
evp_enc.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
-evp_enc.o: ../cryptlib.h evp_enc.c evp_locl.h
+evp_enc.o: ../constant_time_locl.h ../cryptlib.h evp_enc.c evp_locl.h
evp_err.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
evp_err.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
evp_err.o: ../../include/openssl/err.h ../../include/openssl/evp.h
diff --git a/crypto/openssl/crypto/evp/e_aes.c b/crypto/openssl/crypto/evp/e_aes.c
index 07bf83a608d8..dc3c2a162a5e 100644
--- a/crypto/openssl/crypto/evp/e_aes.c
+++ b/crypto/openssl/crypto/evp/e_aes.c
@@ -166,7 +166,7 @@ extern unsigned int OPENSSL_ia32cap_P[2];
#define VPAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
#endif
#ifdef BSAES_ASM
-#define BSAES_CAPABLE VPAES_CAPABLE
+#define BSAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
#endif
/*
* AES-NI section
diff --git a/crypto/openssl/crypto/evp/evp_enc.c b/crypto/openssl/crypto/evp/evp_enc.c
index 0c54f05e6ef5..7b1842a52a6d 100644
--- a/crypto/openssl/crypto/evp/evp_enc.c
+++ b/crypto/openssl/crypto/evp/evp_enc.c
@@ -67,6 +67,7 @@
#ifdef OPENSSL_FIPS
#include <openssl/fips.h>
#endif
+#include "constant_time_locl.h"
#include "evp_locl.h"
#ifdef OPENSSL_FIPS
@@ -500,21 +501,21 @@ int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
{
- int i,n;
- unsigned int b;
+ unsigned int i, b;
+ unsigned char pad, padding_good;
*outl=0;
if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER)
{
- i = M_do_cipher(ctx, out, NULL, 0);
- if (i < 0)
+ int ret = M_do_cipher(ctx, out, NULL, 0);
+ if (ret < 0)
return 0;
else
- *outl = i;
+ *outl = ret;
return 1;
}
- b=ctx->cipher->block_size;
+ b=(unsigned int)(ctx->cipher->block_size);
if (ctx->flags & EVP_CIPH_NO_PADDING)
{
if(ctx->buf_len)
@@ -533,28 +534,34 @@ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
return(0);
}
OPENSSL_assert(b <= sizeof ctx->final);
- n=ctx->final[b-1];
- if (n == 0 || n > (int)b)
- {
- EVPerr(EVP_F_EVP_DECRYPTFINAL_EX,EVP_R_BAD_DECRYPT);
- return(0);
- }
- for (i=0; i<n; i++)
+ pad=ctx->final[b-1];
+
+ padding_good = (unsigned char)(~constant_time_is_zero_8(pad));
+ padding_good &= constant_time_ge_8(b, pad);
+
+ for (i = 1; i < b; ++i)
{
- if (ctx->final[--b] != n)
- {
- EVPerr(EVP_F_EVP_DECRYPTFINAL_EX,EVP_R_BAD_DECRYPT);
- return(0);
- }
+ unsigned char is_pad_index = constant_time_lt_8(i, pad);
+ unsigned char pad_byte_good = constant_time_eq_8(ctx->final[b-i-1], pad);
+ padding_good &= constant_time_select_8(is_pad_index, pad_byte_good, 0xff);
}
- n=ctx->cipher->block_size-n;
- for (i=0; i<n; i++)
- out[i]=ctx->final[i];
- *outl=n;
+
+ /*
+ * At least 1 byte is always padding, so we always write b - 1
+ * bytes to avoid a timing leak. The caller is required to have |b|
+ * bytes space in |out| by the API contract.
+ */
+ for (i = 0; i < b - 1; ++i)
+ out[i] = ctx->final[i] & padding_good;
+ /* Safe cast: for a good padding, EVP_MAX_IV_LENGTH >= b >= pad */
+ *outl = padding_good & ((unsigned char)(b - pad));
+ return padding_good & 1;
}
else
- *outl=0;
- return(1);
+ {
+ *outl = 0;
+ return 1;
+ }
}
void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
@@ -678,4 +685,3 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
return in->cipher->ctrl((EVP_CIPHER_CTX *)in, EVP_CTRL_COPY, 0, out);
return 1;
}
-
diff --git a/crypto/openssl/crypto/md5/asm/md5-x86_64.pl b/crypto/openssl/crypto/md5/asm/md5-x86_64.pl
index f11224d17220..381bf77e1c6b 100755
--- a/crypto/openssl/crypto/md5/asm/md5-x86_64.pl
+++ b/crypto/openssl/crypto/md5/asm/md5-x86_64.pl
@@ -108,6 +108,7 @@ sub round4_step
EOF
}
+no warnings qw(uninitialized);
my $flavour = shift;
my $output = shift;
if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
@@ -119,7 +120,6 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; my $dir=$1; my $xlate;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
-no warnings qw(uninitialized);
open OUT,"| \"$^X\" $xlate $flavour $output";
*STDOUT=*OUT;
diff --git a/crypto/openssl/crypto/modes/modes.h b/crypto/openssl/crypto/modes/modes.h
index f18215bb2b25..7773c2542e5c 100644
--- a/crypto/openssl/crypto/modes/modes.h
+++ b/crypto/openssl/crypto/modes/modes.h
@@ -7,6 +7,9 @@
#include <stddef.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
typedef void (*block128_f)(const unsigned char in[16],
unsigned char out[16],
const void *key);
@@ -133,3 +136,6 @@ typedef struct xts128_context XTS128_CONTEXT;
int CRYPTO_xts128_encrypt(const XTS128_CONTEXT *ctx, const unsigned char iv[16],
const unsigned char *inp, unsigned char *out, size_t len, int enc);
+#ifdef __cplusplus
+}
+#endif
diff --git a/crypto/openssl/crypto/ocsp/ocsp_vfy.c b/crypto/openssl/crypto/ocsp/ocsp_vfy.c
index 276718304dd2..fc0d4cc0f5f7 100644
--- a/crypto/openssl/crypto/ocsp/ocsp_vfy.c
+++ b/crypto/openssl/crypto/ocsp/ocsp_vfy.c
@@ -436,8 +436,11 @@ static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, X509_NAME *nm
if(!(flags & OCSP_NOINTERN))
{
signer = X509_find_by_subject(req->optionalSignature->certs, nm);
- *psigner = signer;
- return 1;
+ if (signer)
+ {
+ *psigner = signer;
+ return 1;
+ }
}
signer = X509_find_by_subject(certs, nm);
diff --git a/crypto/openssl/crypto/opensslconf.h b/crypto/openssl/crypto/opensslconf.h
index 57abb87d9bc6..7513d14c7530 100644
--- a/crypto/openssl/crypto/opensslconf.h
+++ b/crypto/openssl/crypto/opensslconf.h
@@ -1,6 +1,9 @@
/* opensslconf.h */
/* WARNING: Generated automatically from opensslconf.h.in by Configure. */
+#ifdef __cplusplus
+extern "C" {
+#endif
/* OpenSSL was configured with the following options: */
#ifndef OPENSSL_DOING_MAKEDEPEND
@@ -233,3 +236,6 @@ YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!!
#endif /* DES_DEFAULT_OPTIONS */
#endif /* HEADER_DES_LOCL_H */
+#ifdef __cplusplus
+}
+#endif
diff --git a/crypto/openssl/crypto/opensslv.h b/crypto/openssl/crypto/opensslv.h
index e03bece35450..2f94b878042d 100644
--- a/crypto/openssl/crypto/opensslv.h
+++ b/crypto/openssl/crypto/opensslv.h
@@ -1,6 +1,10 @@
#ifndef HEADER_OPENSSLV_H
#define HEADER_OPENSSLV_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* Numeric release version identifier:
* MNNFFPPS: major minor fix patch status
* The status nibble has one of the values 0 for development, 1 to e for betas
@@ -25,11 +29,11 @@
* (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for
* major minor fix final patch/beta)
*/
-#define OPENSSL_VERSION_NUMBER 0x1000109fL
+#define OPENSSL_VERSION_NUMBER 0x100010afL
#ifdef OPENSSL_FIPS
-#define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1i-fips 6 Aug 2014"
+#define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1j-fips 15 Oct 2014"
#else
-#define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1i-freebsd 6 Aug 2014"
+#define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1j-freebsd 15 Oct 2014"
#endif
#define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT
@@ -86,4 +90,7 @@
#define SHLIB_VERSION_NUMBER "7"
+#ifdef __cplusplus
+}
+#endif
#endif /* HEADER_OPENSSLV_H */
diff --git a/crypto/openssl/crypto/ossl_typ.h b/crypto/openssl/crypto/ossl_typ.h
index ea9227f6f95a..12cdd43be9dc 100644
--- a/crypto/openssl/crypto/ossl_typ.h
+++ b/crypto/openssl/crypto/ossl_typ.h
@@ -55,6 +55,10 @@
#ifndef HEADER_OPENSSL_TYPES_H
#define HEADER_OPENSSL_TYPES_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include <openssl/e_os2.h>
#ifdef NO_ASN1_TYPEDEFS
@@ -199,4 +203,7 @@ typedef struct ocsp_req_ctx_st OCSP_REQ_CTX;
typedef struct ocsp_response_st OCSP_RESPONSE;
typedef struct ocsp_responder_id_st OCSP_RESPID;
+#ifdef __cplusplus
+}
+#endif
#endif /* def HEADER_OPENSSL_TYPES_H */
diff --git a/crypto/openssl/crypto/pkcs7/pkcs7.h b/crypto/openssl/crypto/pkcs7/pkcs7.h
index 04f60379fb6d..5d54c4ac2723 100644
--- a/crypto/openssl/crypto/pkcs7/pkcs7.h
+++ b/crypto/openssl/crypto/pkcs7/pkcs7.h
@@ -233,10 +233,6 @@ DECLARE_PKCS12_STACK_OF(PKCS7)
(OBJ_obj2nid((a)->type) == NID_pkcs7_signedAndEnveloped)
#define PKCS7_type_is_data(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_data)
#define PKCS7_type_is_digest(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_digest)
-#define PKCS7_type_is_encrypted(a) \
- (OBJ_obj2nid((a)->type) == NID_pkcs7_encrypted)
-
-#define PKCS7_type_is_digest(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_digest)
#define PKCS7_set_detached(p,v) \
PKCS7_ctrl(p,PKCS7_OP_SET_DETACHED_SIGNATURE,v,NULL)
diff --git a/crypto/openssl/crypto/pqueue/pqueue.h b/crypto/openssl/crypto/pqueue/pqueue.h
index 87fc9037c8f3..26b534808900 100644
--- a/crypto/openssl/crypto/pqueue/pqueue.h
+++ b/crypto/openssl/crypto/pqueue/pqueue.h
@@ -64,6 +64,9 @@
#include <stdlib.h>
#include <string.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
typedef struct _pqueue *pqueue;
typedef struct _pitem
@@ -91,4 +94,7 @@ pitem *pqueue_next(piterator *iter);
void pqueue_print(pqueue pq);
int pqueue_size(pqueue pq);
+#ifdef __cplusplus
+}
+#endif
#endif /* ! HEADER_PQUEUE_H */
diff --git a/crypto/openssl/crypto/rsa/Makefile b/crypto/openssl/crypto/rsa/Makefile
index f798d2f74932..e8121a496750 100644
--- a/crypto/openssl/crypto/rsa/Makefile
+++ b/crypto/openssl/crypto/rsa/Makefile
@@ -212,7 +212,7 @@ rsa_oaep.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
rsa_oaep.o: ../../include/openssl/rand.h ../../include/openssl/rsa.h
rsa_oaep.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
rsa_oaep.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
-rsa_oaep.o: ../cryptlib.h rsa_oaep.c
+rsa_oaep.o: ../constant_time_locl.h ../cryptlib.h rsa_oaep.c
rsa_pk1.o: ../../e_os.h ../../include/openssl/asn1.h
rsa_pk1.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
rsa_pk1.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
@@ -221,7 +221,8 @@ rsa_pk1.o: ../../include/openssl/lhash.h ../../include/openssl/opensslconf.h
rsa_pk1.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
rsa_pk1.o: ../../include/openssl/rand.h ../../include/openssl/rsa.h
rsa_pk1.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
-rsa_pk1.o: ../../include/openssl/symhacks.h ../cryptlib.h rsa_pk1.c
+rsa_pk1.o: ../../include/openssl/symhacks.h ../constant_time_locl.h
+rsa_pk1.o: ../cryptlib.h rsa_pk1.c
rsa_pmeth.o: ../../e_os.h ../../include/openssl/asn1.h
rsa_pmeth.o: ../../include/openssl/asn1t.h ../../include/openssl/bio.h
rsa_pmeth.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h
diff --git a/crypto/openssl/crypto/rsa/rsa.h b/crypto/openssl/crypto/rsa/rsa.h
index 5f269e577af4..11853fee5fe4 100644
--- a/crypto/openssl/crypto/rsa/rsa.h
+++ b/crypto/openssl/crypto/rsa/rsa.h
@@ -559,6 +559,7 @@ void ERR_load_RSA_strings(void);
#define RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE 158
#define RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 148
#define RSA_R_PADDING_CHECK_FAILED 114
+#define RSA_R_PKCS_DECODING_ERROR 159
#define RSA_R_P_NOT_PRIME 128
#define RSA_R_Q_NOT_PRIME 129
#define RSA_R_RSA_OPERATIONS_NOT_SUPPORTED 130
diff --git a/crypto/openssl/crypto/rsa/rsa_err.c b/crypto/openssl/crypto/rsa/rsa_err.c
index 46e0bf99806c..9da79d920ee9 100644
--- a/crypto/openssl/crypto/rsa/rsa_err.c
+++ b/crypto/openssl/crypto/rsa/rsa_err.c
@@ -175,6 +175,7 @@ static ERR_STRING_DATA RSA_str_reasons[]=
{ERR_REASON(RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE),"operation not allowed in fips mode"},
{ERR_REASON(RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE),"operation not supported for this keytype"},
{ERR_REASON(RSA_R_PADDING_CHECK_FAILED) ,"padding check failed"},
+{ERR_REASON(RSA_R_PKCS_DECODING_ERROR) ,"pkcs decoding error"},
{ERR_REASON(RSA_R_P_NOT_PRIME) ,"p not prime"},
{ERR_REASON(RSA_R_Q_NOT_PRIME) ,"q not prime"},
{ERR_REASON(RSA_R_RSA_OPERATIONS_NOT_SUPPORTED),"rsa operations not supported"},
diff --git a/crypto/openssl/crypto/rsa/rsa_oaep.c b/crypto/openssl/crypto/rsa/rsa_oaep.c
index af4d24a56ef5..c363331992e0 100644
--- a/crypto/openssl/crypto/rsa/rsa_oaep.c
+++ b/crypto/openssl/crypto/rsa/rsa_oaep.c
@@ -18,6 +18,7 @@
* an equivalent notion.
*/
+#include "constant_time_locl.h"
#if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1)
#include <stdio.h>
@@ -95,92 +96,117 @@ int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,
const unsigned char *from, int flen, int num,
const unsigned char *param, int plen)
{
- int i, dblen, mlen = -1;
- const unsigned char *maskeddb;
- int lzero;
- unsigned char *db = NULL, seed[SHA_DIGEST_LENGTH], phash[SHA_DIGEST_LENGTH];
- unsigned char *padded_from;
- int bad = 0;
-
- if (--num < 2 * SHA_DIGEST_LENGTH + 1)
- /* 'num' is the length of the modulus, i.e. does not depend on the
- * particular ciphertext. */
- goto decoding_err;
+ int i, dblen, mlen = -1, one_index = 0, msg_index;
+ unsigned int good, found_one_byte;
+ const unsigned char *maskedseed, *maskeddb;
+ /* |em| is the encoded message, zero-padded to exactly |num| bytes:
+ * em = Y || maskedSeed || maskedDB */
+ unsigned char *db = NULL, *em = NULL, seed[EVP_MAX_MD_SIZE],
+ phash[EVP_MAX_MD_SIZE];
- lzero = num - flen;
- if (lzero < 0)
- {
- /* signalling this error immediately after detection might allow
- * for side-channel attacks (e.g. timing if 'plen' is huge
- * -- cf. James H. Manger, "A Chosen Ciphertext Attack on RSA Optimal
- * Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001),
- * so we use a 'bad' flag */
- bad = 1;
- lzero = 0;
- flen = num; /* don't overflow the memcpy to padded_from */
- }
+ if (tlen <= 0 || flen <= 0)
+ return -1;
- dblen = num - SHA_DIGEST_LENGTH;
- db = OPENSSL_malloc(dblen + num);
- if (db == NULL)
+ /*
+ * |num| is the length of the modulus; |flen| is the length of the
+ * encoded message. Therefore, for any |from| that was obtained by
+ * decrypting a ciphertext, we must have |flen| <= |num|. Similarly,
+ * num < 2 * SHA_DIGEST_LENGTH + 2 must hold for the modulus
+ * irrespective of the ciphertext, see PKCS #1 v2.2, section 7.1.2.
+ * This does not leak any side-channel information.
+ */
+ if (num < flen || num < 2 * SHA_DIGEST_LENGTH + 2)
+ goto decoding_err;
+
+ dblen = num - SHA_DIGEST_LENGTH - 1;
+ db = OPENSSL_malloc(dblen);
+ em = OPENSSL_malloc(num);
+ if (db == NULL || em == NULL)
{
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, ERR_R_MALLOC_FAILURE);
- return -1;
+ goto cleanup;
}
- /* Always do this zero-padding copy (even when lzero == 0)
- * to avoid leaking timing info about the value of lzero. */
- padded_from = db + dblen;
- memset(padded_from, 0, lzero);
- memcpy(padded_from + lzero, from, flen);
+ /*
+ * Always do this zero-padding copy (even when num == flen) to avoid
+ * leaking that information. The copy still leaks some side-channel
+ * information, but it's impossible to have a fixed memory access
+ * pattern since we can't read out of the bounds of |from|.
+ *
+ * TODO(emilia): Consider porting BN_bn2bin_padded from BoringSSL.
+ */
+ memset(em, 0, num);
+ memcpy(em + num - flen, from, flen);
- maskeddb = padded_from + SHA_DIGEST_LENGTH;
+ /*
+ * The first byte must be zero, however we must not leak if this is
+ * true. See James H. Manger, "A Chosen Ciphertext Attack on RSA
+ * Optimal Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001).
+ */
+ good = constant_time_is_zero(em[0]);
+
+ maskedseed = em + 1;
+ maskeddb = em + 1 + SHA_DIGEST_LENGTH;
if (MGF1(seed, SHA_DIGEST_LENGTH, maskeddb, dblen))
- return -1;
+ goto cleanup;
for (i = 0; i < SHA_DIGEST_LENGTH; i++)
- seed[i] ^= padded_from[i];
-
+ seed[i] ^= maskedseed[i];
+
if (MGF1(db, dblen, seed, SHA_DIGEST_LENGTH))
- return -1;
+ goto cleanup;
for (i = 0; i < dblen; i++)
db[i] ^= maskeddb[i];
if (!EVP_Digest((void *)param, plen, phash, NULL, EVP_sha1(), NULL))
- return -1;
+ goto cleanup;
+
+ good &= constant_time_is_zero(CRYPTO_memcmp(db, phash, SHA_DIGEST_LENGTH));
- if (CRYPTO_memcmp(db, phash, SHA_DIGEST_LENGTH) != 0 || bad)
+ found_one_byte = 0;
+ for (i = SHA_DIGEST_LENGTH; i < dblen; i++)
+ {
+ /* Padding consists of a number of 0-bytes, followed by a 1. */
+ unsigned int equals1 = constant_time_eq(db[i], 1);
+ unsigned int equals0 = constant_time_is_zero(db[i]);
+ one_index = constant_time_select_int(~found_one_byte & equals1,
+ i, one_index);
+ found_one_byte |= equals1;
+ good &= (found_one_byte | equals0);
+ }
+
+ good &= found_one_byte;
+
+ /*
+ * At this point |good| is zero unless the plaintext was valid,
+ * so plaintext-awareness ensures timing side-channels are no longer a
+ * concern.
+ */
+ if (!good)
goto decoding_err;
+
+ msg_index = one_index + 1;
+ mlen = dblen - msg_index;
+
+ if (tlen < mlen)
+ {
+ RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_DATA_TOO_LARGE);
+ mlen = -1;
+ }
else
{
- for (i = SHA_DIGEST_LENGTH; i < dblen; i++)
- if (db[i] != 0x00)
- break;
- if (i == dblen || db[i] != 0x01)
- goto decoding_err;
- else
- {
- /* everything looks OK */
-
- mlen = dblen - ++i;
- if (tlen < mlen)
- {
- RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_DATA_TOO_LARGE);
- mlen = -1;
- }
- else
- memcpy(to, db + i, mlen);
- }
+ memcpy(to, db + msg_index, mlen);
+ goto cleanup;
}
- OPENSSL_free(db);
- return mlen;
decoding_err:
- /* to avoid chosen ciphertext attacks, the error message should not reveal
- * which kind of decoding error happened */
+ /* To avoid chosen ciphertext attacks, the error message should not reveal
+ * which kind of decoding error happened. */
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_OAEP_DECODING_ERROR);
+cleanup:
if (db != NULL) OPENSSL_free(db);
- return -1;
+ if (em != NULL) OPENSSL_free(em);
+ return mlen;
}
int PKCS1_MGF1(unsigned char *mask, long len,
diff --git a/crypto/openssl/crypto/rsa/rsa_pk1.c b/crypto/openssl/crypto/rsa/rsa_pk1.c
index 8560755f1d12..c2da56f6cad8 100644
--- a/crypto/openssl/crypto/rsa/rsa_pk1.c
+++ b/crypto/openssl/crypto/rsa/rsa_pk1.c
@@ -56,6 +56,8 @@
* [including the GNU Public Licence.]
*/
+#include "constant_time_locl.h"
+
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/bn.h>
@@ -181,44 +183,87 @@ int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen,
int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
const unsigned char *from, int flen, int num)
{
- int i,j;
- const unsigned char *p;
+ int i;
+ /* |em| is the encoded message, zero-padded to exactly |num| bytes */
+ unsigned char *em = NULL;
+ unsigned int good, found_zero_byte;
+ int zero_index = 0, msg_index, mlen = -1;
- p=from;
- if ((num != (flen+1)) || (*(p++) != 02))
- {
- RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2,RSA_R_BLOCK_TYPE_IS_NOT_02);
- return(-1);
- }
-#ifdef PKCS1_CHECK
- return(num-11);
-#endif
+ if (tlen < 0 || flen < 0)
+ return -1;
- /* scan over padding data */
- j=flen-1; /* one for type. */
- for (i=0; i<j; i++)
- if (*(p++) == 0) break;
+ /* PKCS#1 v1.5 decryption. See "PKCS #1 v2.2: RSA Cryptography
+ * Standard", section 7.2.2. */
- if (i == j)
+ if (flen > num)
+ goto err;
+
+ if (num < 11)
+ goto err;
+
+ em = OPENSSL_malloc(num);
+ if (em == NULL)
{
- RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2,RSA_R_NULL_BEFORE_BLOCK_MISSING);
- return(-1);
+ RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2, ERR_R_MALLOC_FAILURE);
+ return -1;
}
+ memset(em, 0, num);
+ /*
+ * Always do this zero-padding copy (even when num == flen) to avoid
+ * leaking that information. The copy still leaks some side-channel
+ * information, but it's impossible to have a fixed memory access
+ * pattern since we can't read out of the bounds of |from|.
+ *
+ * TODO(emilia): Consider porting BN_bn2bin_padded from BoringSSL.
+ */
+ memcpy(em + num - flen, from, flen);
- if (i < 8)
+ good = constant_time_is_zero(em[0]);
+ good &= constant_time_eq(em[1], 2);
+
+ found_zero_byte = 0;
+ for (i = 2; i < num; i++)
{
- RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2,RSA_R_BAD_PAD_BYTE_COUNT);
- return(-1);
+ unsigned int equals0 = constant_time_is_zero(em[i]);
+ zero_index = constant_time_select_int(~found_zero_byte & equals0, i, zero_index);
+ found_zero_byte |= equals0;
}
- i++; /* Skip over the '\0' */
- j-=i;
- if (j > tlen)
+
+ /*
+ * PS must be at least 8 bytes long, and it starts two bytes into |em|.
+ * If we never found a 0-byte, then |zero_index| is 0 and the check
+ * also fails.
+ */
+ good &= constant_time_ge((unsigned int)(zero_index), 2 + 8);
+
+ /* Skip the zero byte. This is incorrect if we never found a zero-byte
+ * but in this case we also do not copy the message out. */
+ msg_index = zero_index + 1;
+ mlen = num - msg_index;
+
+ /* For good measure, do this check in constant time as well; it could
+ * leak something if |tlen| was assuming valid padding. */
+ good &= constant_time_ge((unsigned int)(tlen), (unsigned int)(mlen));
+
+ /*
+ * We can't continue in constant-time because we need to copy the result
+ * and we cannot fake its length. This unavoidably leaks timing
+ * information at the API boundary.
+ * TODO(emilia): this could be addressed at the call site,
+ * see BoringSSL commit 0aa0767340baf925bda4804882aab0cb974b2d26.
+ */
+ if (!good)
{
- RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2,RSA_R_DATA_TOO_LARGE);
- return(-1);
+ mlen = -1;
+ goto err;
}
- memcpy(to,p,(unsigned int)j);
- return(j);
- }
+ memcpy(to, em + msg_index, mlen);
+err:
+ if (em != NULL)
+ OPENSSL_free(em);
+ if (mlen == -1)
+ RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2, RSA_R_PKCS_DECODING_ERROR);
+ return mlen;
+ }
diff --git a/crypto/openssl/crypto/rsa/rsa_sign.c b/crypto/openssl/crypto/rsa/rsa_sign.c
index b6f6037ae002..225bcfe2dcab 100644
--- a/crypto/openssl/crypto/rsa/rsa_sign.c
+++ b/crypto/openssl/crypto/rsa/rsa_sign.c
@@ -151,6 +151,25 @@ int RSA_sign(int type, const unsigned char *m, unsigned int m_len,
return(ret);
}
+/*
+ * Check DigestInfo structure does not contain extraneous data by reencoding
+ * using DER and checking encoding against original.
+ */
+static int rsa_check_digestinfo(X509_SIG *sig, const unsigned char *dinfo, int dinfolen)
+ {
+ unsigned char *der = NULL;
+ int derlen;
+ int ret = 0;
+ derlen = i2d_X509_SIG(sig, &der);
+ if (derlen <= 0)
+ return 0;
+ if (derlen == dinfolen && !memcmp(dinfo, der, derlen))
+ ret = 1;
+ OPENSSL_cleanse(der, derlen);
+ OPENSSL_free(der);
+ return ret;
+ }
+
int int_rsa_verify(int dtype, const unsigned char *m,
unsigned int m_len,
unsigned char *rm, size_t *prm_len,
@@ -228,7 +247,7 @@ int int_rsa_verify(int dtype, const unsigned char *m,
if (sig == NULL) goto err;
/* Excess data can be used to create forgeries */
- if(p != s+i)
+ if(p != s+i || !rsa_check_digestinfo(sig, s, i))
{
RSAerr(RSA_F_INT_RSA_VERIFY,RSA_R_BAD_SIGNATURE);
goto err;
diff --git a/crypto/openssl/crypto/stack/safestack.h b/crypto/openssl/crypto/stack/safestack.h
index ea3aa0d800ec..bc194cb26817 100644
--- a/crypto/openssl/crypto/stack/safestack.h
+++ b/crypto/openssl/crypto/stack/safestack.h
@@ -57,6 +57,10 @@
#include <openssl/stack.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#ifndef CHECKED_PTR_OF
#define CHECKED_PTR_OF(type, p) \
((void*) (1 ? p : (type*)0))
@@ -2660,4 +2664,8 @@ DECLARE_SPECIAL_STACK_OF(OPENSSL_BLOCK, void)
#define lh_SSL_SESSION_free(lh) LHM_lh_free(SSL_SESSION,lh)
/* End of util/mkstack.pl block, you may now edit :-) */
+
+#ifdef __cplusplus
+}
+#endif
#endif /* !defined HEADER_SAFESTACK_H */