From 9a02b27a6e11c9667427250a26589d17ad31e847 Mon Sep 17 00:00:00 2001 From: jkim Date: Wed, 15 Oct 2014 17:32:57 +0000 Subject: Import OpenSSL 1.0.1j. --- crypto/Makefile | 4 +- crypto/aes/asm/aesni-x86_64.pl | 52 +++---- crypto/asn1/a_strex.c | 1 + crypto/bn/asm/x86_64-gcc.c | 8 +- crypto/bn/bn_exp.c | 9 +- crypto/bn/bn_nist.c | 6 +- crypto/bn/exptest.c | 45 +++++- crypto/constant_time_locl.h | 216 +++++++++++++++++++++++++++ crypto/constant_time_test.c | 330 +++++++++++++++++++++++++++++++++++++++++ crypto/dsa/dsa_ameth.c | 7 +- crypto/ebcdic.h | 7 + crypto/ec/ec.h | 2 +- crypto/ec/ec2_smpl.c | 9 +- crypto/ec/ec_ameth.c | 14 +- crypto/ec/ec_asn1.c | 40 +++-- crypto/ec/ecp_mont.c | 9 +- crypto/ec/ecp_nist.c | 9 +- crypto/ec/ecp_smpl.c | 13 +- crypto/ec/ectest.c | 5 +- crypto/evp/Makefile | 2 +- crypto/evp/e_aes.c | 2 +- crypto/evp/evp_enc.c | 56 +++---- crypto/md5/asm/md5-x86_64.pl | 2 +- crypto/modes/modes.h | 6 + crypto/ocsp/ocsp_vfy.c | 7 +- crypto/opensslconf.h | 6 + crypto/opensslv.h | 13 +- crypto/ossl_typ.h | 7 + crypto/pkcs7/pkcs7.h | 4 - crypto/pqueue/pqueue.h | 6 + crypto/rsa/Makefile | 5 +- crypto/rsa/rsa.h | 1 + crypto/rsa/rsa_err.c | 1 + crypto/rsa/rsa_oaep.c | 150 +++++++++++-------- crypto/rsa/rsa_pk1.c | 103 +++++++++---- crypto/rsa/rsa_sign.c | 21 ++- crypto/stack/safestack.h | 8 + 37 files changed, 981 insertions(+), 205 deletions(-) create mode 100644 crypto/constant_time_locl.h create mode 100644 crypto/constant_time_test.c (limited to 'crypto') diff --git a/crypto/Makefile b/crypto/Makefile index a90809b..ee5bfbd 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -31,6 +31,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) @@ -43,7 +44,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/aes/asm/aesni-x86_64.pl b/crypto/aes/asm/aesni-x86_64.pl index 0dbb194..c9270df 100755 --- a/crypto/aes/asm/aesni-x86_64.pl +++ b/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/asn1/a_strex.c b/crypto/asn1/a_strex.c index ead37ac3..8fb4193 100644 --- a/crypto/asn1/a_strex.c +++ b/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/bn/asm/x86_64-gcc.c b/crypto/bn/asm/x86_64-gcc.c index acb0b40..31476ab 100644 --- a/crypto/bn/asm/x86_64-gcc.c +++ b/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/bn/bn_exp.c b/crypto/bn/bn_exp.c index 5e7eb33..611fa32 100644 --- a/crypto/bn/bn_exp.c +++ b/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/bn/bn_nist.c b/crypto/bn/bn_nist.c index e22968d..abb1570 100644 --- a/crypto/bn/bn_nist.c +++ b/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_RSHIFT; - val = t_d[i+1]; - t_d[i] = (tmp | val<>BN_NIST_521_RSHIFT | + (tmp=t_d[i+1])<>BN_NIST_521_RSHIFT; /* lower 521 bits */ diff --git a/crypto/bn/exptest.c b/crypto/bn/exptest.c index 074a8e8..5fa02a1 100644 --- a/crypto/bn/exptest.c +++ b/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/constant_time_locl.h b/crypto/constant_time_locl.h new file mode 100644 index 0000000..c048393 --- /dev/null +++ b/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/constant_time_test.c b/crypto/constant_time_test.c new file mode 100644 index 0000000..d9c6a44 --- /dev/null +++ b/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 +#include +#include + +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/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c index 376156e..5af76ea 100644 --- a/crypto/dsa/dsa_ameth.c +++ b/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/ebcdic.h b/crypto/ebcdic.h index 6d65afc..85f3cf7 100644 --- a/crypto/ebcdic.h +++ b/crypto/ebcdic.h @@ -5,6 +5,10 @@ #include +#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/ec/ec.h b/crypto/ec/ec.h index dfe8710..572111f 100644 --- a/crypto/ec/ec.h +++ b/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/ec/ec2_smpl.c b/crypto/ec/ec2_smpl.c index e0e59c7..62223cb 100644 --- a/crypto/ec/ec2_smpl.c +++ b/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/ec/ec_ameth.c b/crypto/ec/ec_ameth.c index f715a23..1128376 100644 --- a/crypto/ec/ec_ameth.c +++ b/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/ec/ec_asn1.c b/crypto/ec/ec_asn1.c index e94f34e..52d31c2 100644 --- a/crypto/ec/ec_asn1.c +++ b/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/ec/ecp_mont.c b/crypto/ec/ecp_mont.c index f04f132..3c5ec19 100644 --- a/crypto/ec/ecp_mont.c +++ b/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/ec/ecp_nist.c b/crypto/ec/ecp_nist.c index aad2d5f..db3b99e 100644 --- a/crypto/ec/ecp_nist.c +++ b/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/ec/ecp_smpl.c b/crypto/ec/ecp_smpl.c index ef52854..2d1f357 100644 --- a/crypto/ec/ecp_smpl.c +++ b/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/ec/ectest.c b/crypto/ec/ectest.c index 82c8c8b..d1bf980 100644 --- a/crypto/ec/ectest.c +++ b/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/evp/Makefile b/crypto/evp/Makefile index 5d0c6b7..fa25bff 100644 --- a/crypto/evp/Makefile +++ b/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/evp/e_aes.c b/crypto/evp/e_aes.c index 07bf83a..dc3c2a1 100644 --- a/crypto/evp/e_aes.c +++ b/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/evp/evp_enc.c b/crypto/evp/evp_enc.c index 0c54f05..7b1842a 100644 --- a/crypto/evp/evp_enc.c +++ b/crypto/evp/evp_enc.c @@ -67,6 +67,7 @@ #ifdef OPENSSL_FIPS #include #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; ifinal[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; ifinal[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/md5/asm/md5-x86_64.pl b/crypto/md5/asm/md5-x86_64.pl index f11224d..381bf77 100755 --- a/crypto/md5/asm/md5-x86_64.pl +++ b/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/modes/modes.h b/crypto/modes/modes.h index f18215b..7773c25 100644 --- a/crypto/modes/modes.h +++ b/crypto/modes/modes.h @@ -7,6 +7,9 @@ #include +#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/ocsp/ocsp_vfy.c b/crypto/ocsp/ocsp_vfy.c index 2767183..fc0d4cc 100644 --- a/crypto/ocsp/ocsp_vfy.c +++ b/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/opensslconf.h b/crypto/opensslconf.h index 57abb87..7513d14 100644 --- a/crypto/opensslconf.h +++ b/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/opensslv.h b/crypto/opensslv.h index 2411505..f375967 100644 --- a/crypto/opensslv.h +++ b/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 6 Aug 2014" +#define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1j 15 Oct 2014" #endif #define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT @@ -86,4 +90,7 @@ #define SHLIB_VERSION_NUMBER "1.0.0" +#ifdef __cplusplus +} +#endif #endif /* HEADER_OPENSSLV_H */ diff --git a/crypto/ossl_typ.h b/crypto/ossl_typ.h index ea9227f..12cdd43 100644 --- a/crypto/ossl_typ.h +++ b/crypto/ossl_typ.h @@ -55,6 +55,10 @@ #ifndef HEADER_OPENSSL_TYPES_H #define HEADER_OPENSSL_TYPES_H +#ifdef __cplusplus +extern "C" { +#endif + #include #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/pkcs7/pkcs7.h b/crypto/pkcs7/pkcs7.h index 04f6037..5d54c4a 100644 --- a/crypto/pkcs7/pkcs7.h +++ b/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/pqueue/pqueue.h b/crypto/pqueue/pqueue.h index 87fc903..26b5348 100644 --- a/crypto/pqueue/pqueue.h +++ b/crypto/pqueue/pqueue.h @@ -64,6 +64,9 @@ #include #include +#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/rsa/Makefile b/crypto/rsa/Makefile index f798d2f..e8121a4 100644 --- a/crypto/rsa/Makefile +++ b/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/rsa/rsa.h b/crypto/rsa/rsa.h index 5f269e5..11853fe 100644 --- a/crypto/rsa/rsa.h +++ b/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/rsa/rsa_err.c b/crypto/rsa/rsa_err.c index 46e0bf9..9da79d9 100644 --- a/crypto/rsa/rsa_err.c +++ b/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/rsa/rsa_oaep.c b/crypto/rsa/rsa_oaep.c index af4d24a..c363331 100644 --- a/crypto/rsa/rsa_oaep.c +++ b/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 @@ -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/rsa/rsa_pk1.c b/crypto/rsa/rsa_pk1.c index 8560755..c2da56f 100644 --- a/crypto/rsa/rsa_pk1.c +++ b/crypto/rsa/rsa_pk1.c @@ -56,6 +56,8 @@ * [including the GNU Public Licence.] */ +#include "constant_time_locl.h" + #include #include "cryptlib.h" #include @@ -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 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/rsa/rsa_sign.c b/crypto/rsa/rsa_sign.c index b6f6037..225bcfe 100644 --- a/crypto/rsa/rsa_sign.c +++ b/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/stack/safestack.h b/crypto/stack/safestack.h index ea3aa0d..bc194cb 100644 --- a/crypto/stack/safestack.h +++ b/crypto/stack/safestack.h @@ -57,6 +57,10 @@ #include +#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 */ -- cgit v1.1