diff options
Diffstat (limited to 'openssl/crypto')
41 files changed, 1073 insertions, 239 deletions
diff --git a/openssl/crypto/LPdir_vms.c b/openssl/crypto/LPdir_vms.c index 7613bd254..3582fa6f0 100644 --- a/openssl/crypto/LPdir_vms.c +++ b/openssl/crypto/LPdir_vms.c @@ -1,4 +1,3 @@ -/* $LP: LPlib/source/LPdir_vms.c,v 1.20 2004/08/26 13:36:05 _cvs_levitte Exp $ */ /* * Copyright (c) 2004, Richard Levitte <richard@levitte.org> * All rights reserved. @@ -88,6 +87,12 @@ const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory) size_t filespeclen = strlen(directory); char *filespec = NULL; + if (filespeclen == 0) + { + errno = ENOENT; + return 0; + } + /* MUST be a VMS directory specification! Let's estimate if it is. */ if (directory[filespeclen-1] != ']' && directory[filespeclen-1] != '>' diff --git a/openssl/crypto/LPdir_win.c b/openssl/crypto/LPdir_win.c index 702dbc730..d5b5e2c90 100644 --- a/openssl/crypto/LPdir_win.c +++ b/openssl/crypto/LPdir_win.c @@ -1,4 +1,3 @@ -/* $LP: LPlib/source/LPdir_win.c,v 1.10 2004/08/26 13:36:05 _cvs_levitte Exp $ */ /* * Copyright (c) 2004, Richard Levitte <richard@levitte.org> * All rights reserved. @@ -63,6 +62,16 @@ const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory) errno = 0; if (*ctx == NULL) { + const char *extdir = directory; + char *extdirbuf = NULL; + size_t dirlen = strlen (directory); + + if (dirlen == 0) + { + errno = ENOENT; + return 0; + } + *ctx = (LP_DIR_CTX *)malloc(sizeof(LP_DIR_CTX)); if (*ctx == NULL) { @@ -71,15 +80,35 @@ const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory) } memset(*ctx, '\0', sizeof(LP_DIR_CTX)); + if (directory[dirlen-1] != '*') + { + extdirbuf = (char *)malloc(dirlen + 3); + if (extdirbuf == NULL) + { + free(*ctx); + *ctx = NULL; + errno = ENOMEM; + return 0; + } + if (directory[dirlen-1] != '/' && directory[dirlen-1] != '\\') + extdir = strcat(strcpy (extdirbuf,directory),"/*"); + else + extdir = strcat(strcpy (extdirbuf,directory),"*"); + } + if (sizeof(TCHAR) != sizeof(char)) { TCHAR *wdir = NULL; /* len_0 denotes string length *with* trailing 0 */ - size_t index = 0,len_0 = strlen(directory) + 1; + size_t index = 0,len_0 = strlen(extdir) + 1; - wdir = (TCHAR *)malloc(len_0 * sizeof(TCHAR)); + wdir = (TCHAR *)calloc(len_0, sizeof(TCHAR)); if (wdir == NULL) { + if (extdirbuf != NULL) + { + free (extdirbuf); + } free(*ctx); *ctx = NULL; errno = ENOMEM; @@ -87,17 +116,23 @@ const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory) } #ifdef LP_MULTIBYTE_AVAILABLE - if (!MultiByteToWideChar(CP_ACP, 0, directory, len_0, (WCHAR *)wdir, len_0)) + if (!MultiByteToWideChar(CP_ACP, 0, extdir, len_0, (WCHAR *)wdir, len_0)) #endif for (index = 0; index < len_0; index++) - wdir[index] = (TCHAR)directory[index]; + wdir[index] = (TCHAR)extdir[index]; (*ctx)->handle = FindFirstFile(wdir, &(*ctx)->ctx); free(wdir); } else - (*ctx)->handle = FindFirstFile((TCHAR *)directory, &(*ctx)->ctx); + { + (*ctx)->handle = FindFirstFile((TCHAR *)extdir, &(*ctx)->ctx); + } + if (extdirbuf != NULL) + { + free (extdirbuf); + } if ((*ctx)->handle == INVALID_HANDLE_VALUE) { @@ -114,7 +149,6 @@ const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory) return 0; } } - if (sizeof(TCHAR) != sizeof(char)) { TCHAR *wdir = (*ctx)->ctx.cFileName; diff --git a/openssl/crypto/Makefile b/openssl/crypto/Makefile index a90809b2b..ee5bfbda8 100644 --- a/openssl/crypto/Makefile +++ b/openssl/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/openssl/crypto/aes/asm/aesni-x86_64.pl b/openssl/crypto/aes/asm/aesni-x86_64.pl index 0dbb194b8..c9270dfdd 100644 --- a/openssl/crypto/aes/asm/aesni-x86_64.pl +++ b/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/openssl/crypto/asn1/a_strex.c b/openssl/crypto/asn1/a_strex.c index ead37ac32..8fb4193bc 100644 --- a/openssl/crypto/asn1/a_strex.c +++ b/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/openssl/crypto/bn/asm/x86_64-gcc.c b/openssl/crypto/bn/asm/x86_64-gcc.c index acb0b4011..31476abeb 100644 --- a/openssl/crypto/bn/asm/x86_64-gcc.c +++ b/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/openssl/crypto/bn/bn_exp.c b/openssl/crypto/bn/bn_exp.c index 5e7eb3373..611fa3262 100644 --- a/openssl/crypto/bn/bn_exp.c +++ b/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/openssl/crypto/bn/bn_nist.c b/openssl/crypto/bn/bn_nist.c index e22968d4a..abb157085 100644 --- a/openssl/crypto/bn/bn_nist.c +++ b/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/openssl/crypto/bn/exptest.c b/openssl/crypto/bn/exptest.c index 074a8e882..5fa02a122 100644 --- a/openssl/crypto/bn/exptest.c +++ b/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/openssl/crypto/constant_time_locl.h b/openssl/crypto/constant_time_locl.h new file mode 100644 index 000000000..c0483939f --- /dev/null +++ b/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/openssl/crypto/constant_time_test.c b/openssl/crypto/constant_time_test.c new file mode 100644 index 000000000..d9c6a44ae --- /dev/null +++ b/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/openssl/crypto/crypto-lib.com b/openssl/crypto/crypto-lib.com index dc8a8c174..a136f4b0b 100644 --- a/openssl/crypto/crypto-lib.com +++ b/openssl/crypto/crypto-lib.com @@ -111,8 +111,8 @@ $ ET_WHIRLPOOL = "WHRLPOOL" $ IF ARCH .EQS. "VAX" THEN ET_WHIRLPOOL = "" $ ENCRYPT_TYPES = "Basic,"+ - "OBJECTS,"+ - - "MD2,MD4,MD5,SHA,MDC2,HMAC,RIPEMD,"+ET_WHIRLPOOL+","+ - - "DES,AES,RC2,RC4,RC5,IDEA,BF,CAST,CAMELLIA,SEED,MODES,"+ - + "MD4,MD5,SHA,MDC2,HMAC,RIPEMD,"+ET_WHIRLPOOL+","+ - + "DES,AES,RC2,RC4,IDEA,BF,CAST,CAMELLIA,SEED,MODES,"+ - "BN,EC,RSA,DSA,ECDSA,DH,ECDH,DSO,ENGINE,"+ - "BUFFER,BIO,STACK,LHASH,RAND,ERR,"+ - "EVP,EVP_2,EVP_3,ASN1,ASN1_2,PEM,X509,X509V3,"+ - @@ -204,11 +204,18 @@ $ GOSUB CHECK_OPT_FILE $! $! Define The Different Encryption "library" Strings. $! -$ APPS_DES = "DES/DES,CBC3_ENC" -$ APPS_PKCS7 = "ENC/ENC;DEC/DEC;SIGN/SIGN;VERIFY/VERIFY,EXAMPLE" +$!!! Test apps disabled, as they aren't supported at all, +$!!! not even in the unix build +$!!! APPS_DES = "DES/DES,CBC3_ENC" +$!!! APPS_PKCS7 = "ENC/ENC;DEC/DEC;SIGN/SIGN;VERIFY/VERIFY,EXAMPLE" $ -$ LIB_ = "cryptlib,mem,mem_clr,mem_dbg,cversion,ex_data,cpt_err,"+ - - "ebcdic,uid,o_time,o_str,o_dir,o_fips.c,o_init,fips_ers" +$! These variables are ordered as the SDIRS variable from the top Makefile.org +$! The contents of these variables are copied from the LIBOBJ variable in the +$! corresponding Makefile from each corresponding subdirectory, with .o stripped +$! and spaces replaced with commas. +$ LIB_ = "cryptlib,mem,mem_dbg,cversion,ex_data,cpt_err,ebcdic,"+ - + "uid,o_time,o_str,o_dir,o_fips.c,o_init,fips_ers,mem_clr" +$ LIB_OBJECTS = "o_names,obj_dat,obj_lib,obj_err,obj_xref" $ LIB_MD2 = "md2_dgst,md2_one" $ LIB_MD4 = "md4_dgst,md4_one" $ LIB_MD5 = "md5_dgst,md5_one" @@ -225,13 +232,13 @@ $ LIB_DES = "set_key,ecb_enc,cbc_enc,"+ - "fcrypt,xcbc_enc,rpc_enc,cbc_cksm,"+ - "ede_cbcm_enc,des_old,des_old2,read2pwd" $ LIB_RC2 = "rc2_ecb,rc2_skey,rc2_cbc,rc2cfb64,rc2ofb64" -$ LIB_RC4 = "rc4_skey,rc4_enc,rc4_utl" +$ LIB_RC4 = "rc4_enc,rc4_skey,rc4_utl" $ LIB_RC5 = "rc5_skey,rc5_ecb,rc5_enc,rc5cfb64,rc5ofb64" $ LIB_IDEA = "i_cbc,i_cfb64,i_ofb64,i_ecb,i_skey" $ LIB_BF = "bf_skey,bf_ecb,bf_enc,bf_cfb64,bf_ofb64" $ LIB_CAST = "c_skey,c_ecb,c_enc,c_cfb64,c_ofb64" -$ LIB_CAMELLIA = "camellia,cmll_misc,cmll_ecb,cmll_cbc,cmll_ofb,"+ - - "cmll_cfb,cmll_ctr,cmll_utl" +$ LIB_CAMELLIA = "cmll_ecb,cmll_ofb,cmll_cfb,cmll_ctr,cmll_utl,"+ - + "camellia,cmll_misc,cmll_cbc" $ LIB_SEED = "seed,seed_ecb,seed_cbc,seed_cfb,seed_ofb" $ LIB_MODES = "cbc128,ctr128,cts128,cfb128,ofb128,gcm128,"+ - "ccm128,xts128" @@ -264,24 +271,23 @@ $ LIB_ENGINE = "eng_err,eng_lib,eng_list,eng_init,eng_ctrl,"+ - "eng_table,eng_pkey,eng_fat,eng_all,"+ - "tb_rsa,tb_dsa,tb_ecdsa,tb_dh,tb_ecdh,tb_rand,tb_store,"+ - "tb_cipher,tb_digest,tb_pkmeth,tb_asnmth,"+ - - "eng_openssl,eng_dyn,eng_cnf,eng_cryptodev,"+ - + "eng_openssl,eng_cnf,eng_dyn,eng_cryptodev,"+ - "eng_rsax,eng_rdrand" -$ LIB_AES = "aes_core,aes_misc,aes_ecb,aes_cbc,aes_cfb,aes_ofb,aes_ctr,"+ - - "aes_ige,aes_wrap" +$ LIB_AES = "aes_misc,aes_ecb,aes_cfb,aes_ofb,aes_ctr,aes_ige,aes_wrap,"+ - + "aes_core,aes_cbc" $ LIB_BUFFER = "buffer,buf_str,buf_err" $ LIB_BIO = "bio_lib,bio_cb,bio_err,"+ - "bss_mem,bss_null,bss_fd,"+ - "bss_file,bss_sock,bss_conn,"+ - "bf_null,bf_buff,b_print,b_dump,"+ - - "b_sock,bss_acpt,bf_nbio,bss_rtcp,bss_bio,bss_log,"+ - + "b_sock,bss_acpt,bf_nbio,bss_log,bss_bio,"+ - "bss_dgram,"+ - - "bf_lbuf" + "bf_lbuf,bss_rtcp" ! The last two are VMS specific $ LIB_STACK = "stack" $ LIB_LHASH = "lhash,lh_stats" $ LIB_RAND = "md_rand,randfile,rand_lib,rand_err,rand_egd,"+ - - "rand_vms" + "rand_vms" ! The last one is VMS specific $ LIB_ERR = "err,err_all,err_prn" -$ LIB_OBJECTS = "o_names,obj_dat,obj_lib,obj_err,obj_xref" $ LIB_EVP = "encode,digest,evp_enc,evp_key,evp_acnf,evp_cnf,"+ - "e_des,e_bf,e_idea,e_des3,e_camellia,"+ - "e_rc4,e_aes,names,e_seed,"+ - @@ -345,7 +351,7 @@ $ LIB_TS = "ts_err,ts_req_utils,ts_req_print,ts_rsp_utils,ts_rsp_print,"+ - $ LIB_JPAKE = "jpake,jpake_err" $ LIB_SRP = "srp_lib,srp_vfy" $ LIB_STORE = "str_err,str_lib,str_meth,str_mem" -$ LIB_CMAC = "cmac,cm_ameth.c,cm_pmeth" +$ LIB_CMAC = "cmac,cm_ameth,cm_pmeth" $! $! Setup exceptional compilations $! @@ -381,7 +387,7 @@ $ MODULE_NEXT: $! $! Extract The Module Name From The Encryption List. $! -$ MODULE_NAME = F$ELEMENT(MODULE_COUNTER,",",ENCRYPT_TYPES) +$ MODULE_NAME = F$EDIT(F$ELEMENT(MODULE_COUNTER,",",ENCRYPT_TYPES),"COLLAPSE") $ IF MODULE_NAME.EQS."Basic" THEN MODULE_NAME = "" $ MODULE_NAME1 = MODULE_NAME $! @@ -465,7 +471,7 @@ $ THEN $! $! O.K, Extract The File Name From The File List. $! -$ FILE_NAME = F$ELEMENT(FILE_COUNTER,",",'LIB_MODULE') +$ FILE_NAME = F$EDIT(F$ELEMENT(FILE_COUNTER,",",'LIB_MODULE'),"COLLAPSE") $! $! else $! @@ -492,7 +498,7 @@ $! SHOW SYMBOL APPLICATION* $! $ IF APPLICATION .NES. ";" $ THEN -$ FILE_NAME = F$ELEMENT(FILE_COUNTER,",",APPLICATION_OBJECTS) +$ FILE_NAME = F$EDIT(F$ELEMENT(FILE_COUNTER,",",APPLICATION_OBJECTS),"COLLAPSE") $ IF FILE_NAME .EQS. "," $ THEN $ APPLICATION = "" @@ -1132,9 +1138,12 @@ $ CCDEFS = "TCPIP_TYPE_''P4',DSO_VMS" $ IF F$TYPE(USER_CCDEFS) .NES. "" THEN CCDEFS = CCDEFS + "," + USER_CCDEFS $ CCEXTRAFLAGS = "" $ IF F$TYPE(USER_CCFLAGS) .NES. "" THEN CCEXTRAFLAGS = USER_CCFLAGS -$ CCDISABLEWARNINGS = "" !!! "LONGLONGTYPE,LONGLONGSUFX,FOUNDCR" -$ IF F$TYPE(USER_CCDISABLEWARNINGS) .NES. "" THEN - - CCDISABLEWARNINGS = CCDISABLEWARNINGS + "," + USER_CCDISABLEWARNINGS +$ CCDISABLEWARNINGS = "" !!! "MAYLOSEDATA3" !!! "LONGLONGTYPE,LONGLONGSUFX,FOUNDCR" +$ IF F$TYPE(USER_CCDISABLEWARNINGS) .NES. "" +$ THEN +$ IF CCDISABLEWARNINGS .NES. "" THEN CCDISABLEWARNINGS = CCDISABLEWARNINGS + "," +$ CCDISABLEWARNINGS = CCDISABLEWARNINGS + USER_CCDISABLEWARNINGS +$ ENDIF $! $! Check To See If We Have A ZLIB Option. $! @@ -1299,6 +1308,18 @@ $! Finish up the definition of CC. $! $ IF COMPILER .EQS. "DECC" $ THEN +$! Not all compiler versions support MAYLOSEDATA3. +$ OPT_TEST = "MAYLOSEDATA3" +$ DEFINE /USER_MODE SYS$ERROR NL: +$ DEFINE /USER_MODE SYS$OUTPUT NL: +$ 'CC' /NOCROSS_REFERENCE /NOLIST /NOOBJECT - + /WARNINGS = DISABLE = ('OPT_TEST', EMPTYFILE) NL: +$ IF ($SEVERITY) +$ THEN +$ IF CCDISABLEWARNINGS .NES. "" THEN - + CCDISABLEWARNINGS = CCDISABLEWARNINGS+ "," +$ CCDISABLEWARNINGS = CCDISABLEWARNINGS+ OPT_TEST +$ ENDIF $ IF CCDISABLEWARNINGS .EQS. "" $ THEN $ CC4DISABLEWARNINGS = "DOLLARID" diff --git a/openssl/crypto/dsa/dsa_ameth.c b/openssl/crypto/dsa/dsa_ameth.c index 376156ec5..5af76eade 100644 --- a/openssl/crypto/dsa/dsa_ameth.c +++ b/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/openssl/crypto/ebcdic.h b/openssl/crypto/ebcdic.h index 6d65afcf9..85f3cf7f6 100644 --- a/openssl/crypto/ebcdic.h +++ b/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/openssl/crypto/ec/ec.h b/openssl/crypto/ec/ec.h index dfe8710d3..572111f16 100644 --- a/openssl/crypto/ec/ec.h +++ b/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/openssl/crypto/ec/ec2_smpl.c b/openssl/crypto/ec/ec2_smpl.c index e0e59c7d8..62223cbb0 100644 --- a/openssl/crypto/ec/ec2_smpl.c +++ b/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/openssl/crypto/ec/ec_ameth.c b/openssl/crypto/ec/ec_ameth.c index f715a238a..11283769b 100644 --- a/openssl/crypto/ec/ec_ameth.c +++ b/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/openssl/crypto/ec/ec_asn1.c b/openssl/crypto/ec/ec_asn1.c index e94f34e11..52d31c2f9 100644 --- a/openssl/crypto/ec/ec_asn1.c +++ b/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/openssl/crypto/ec/ecp_mont.c b/openssl/crypto/ec/ecp_mont.c index f04f132c7..3c5ec1965 100644 --- a/openssl/crypto/ec/ecp_mont.c +++ b/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/openssl/crypto/ec/ecp_nist.c b/openssl/crypto/ec/ecp_nist.c index aad2d5f44..db3b99e06 100644 --- a/openssl/crypto/ec/ecp_nist.c +++ b/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/openssl/crypto/ec/ecp_smpl.c b/openssl/crypto/ec/ecp_smpl.c index ef5285477..2d1f35768 100644 --- a/openssl/crypto/ec/ecp_smpl.c +++ b/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/openssl/crypto/ec/ectest.c b/openssl/crypto/ec/ectest.c index 82c8c8bfb..d1bf98059 100644 --- a/openssl/crypto/ec/ectest.c +++ b/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/openssl/crypto/err/openssl.ec b/openssl/crypto/err/openssl.ec index e0554b434..bafbc35d3 100644 --- a/openssl/crypto/err/openssl.ec +++ b/openssl/crypto/err/openssl.ec @@ -71,6 +71,7 @@ R SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION 1060 R SSL_R_TLSV1_ALERT_PROTOCOL_VERSION 1070 R SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY 1071 R SSL_R_TLSV1_ALERT_INTERNAL_ERROR 1080 +R SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK 1086 R SSL_R_TLSV1_ALERT_USER_CANCELLED 1090 R SSL_R_TLSV1_ALERT_NO_RENEGOTIATION 1100 R SSL_R_TLSV1_UNSUPPORTED_EXTENSION 1110 diff --git a/openssl/crypto/evp/Makefile b/openssl/crypto/evp/Makefile index 5d0c6b7db..fa25bff6b 100644 --- a/openssl/crypto/evp/Makefile +++ b/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/openssl/crypto/evp/e_aes.c b/openssl/crypto/evp/e_aes.c index 07bf83a60..dc3c2a162 100644 --- a/openssl/crypto/evp/e_aes.c +++ b/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/openssl/crypto/evp/evp_enc.c b/openssl/crypto/evp/evp_enc.c index 0c54f05e6..7b1842a52 100644 --- a/openssl/crypto/evp/evp_enc.c +++ b/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/openssl/crypto/install-crypto.com b/openssl/crypto/install-crypto.com index 85b3d583c..d19081d4d 100644 --- a/openssl/crypto/install-crypto.com +++ b/openssl/crypto/install-crypto.com @@ -75,13 +75,13 @@ $! $ sdirs := , - 'archd', - objects, - - md2, md4, md5, sha, mdc2, hmac, ripemd, whrlpool, - - des, aes, rc2, rc4, rc5, idea, bf, cast, camellia, seed, - + md4, md5, sha, mdc2, hmac, ripemd, whrlpool, - + des, aes, rc2, rc4, idea, bf, cast, camellia, seed, - bn, ec, rsa, dsa, ecdsa, dh, ecdh, dso, engine, - buffer, bio, stack, lhash, rand, err, - evp, asn1, pem, x509, x509v3, conf, txt_db, pkcs7, pkcs12, comp, ocsp, - ui, krb5, - - store, cms, pqueue, ts, jpake + cms, pqueue, ts, jpake, srp, store, cmac $! $ exheader_ := crypto.h, opensslv.h, ebcdic.h, symhacks.h, ossl_typ.h $ exheader_'archd' := opensslconf.h @@ -139,6 +139,9 @@ $ exheader_cms := cms.h $ exheader_pqueue := pqueue.h $ exheader_ts := ts.h $ exheader_jpake := jpake.h +$ exheader_srp := srp.h +$ exheader_store := store.h +$ exheader_cmac := cmac.h $ libs := ssl_libcrypto $! $ exe_dir := [-.'archd'.exe.crypto] diff --git a/openssl/crypto/md5/asm/md5-x86_64.pl b/openssl/crypto/md5/asm/md5-x86_64.pl index f11224d17..381bf77e1 100644 --- a/openssl/crypto/md5/asm/md5-x86_64.pl +++ b/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/openssl/crypto/modes/modes.h b/openssl/crypto/modes/modes.h index f18215bb2..7773c2542 100644 --- a/openssl/crypto/modes/modes.h +++ b/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/openssl/crypto/ocsp/ocsp_vfy.c b/openssl/crypto/ocsp/ocsp_vfy.c index 276718304..fc0d4cc0f 100644 --- a/openssl/crypto/ocsp/ocsp_vfy.c +++ b/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/openssl/crypto/opensslv.h b/openssl/crypto/opensslv.h index 241150530..f375967ef 100644 --- a/openssl/crypto/opensslv.h +++ b/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 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/openssl/crypto/ossl_typ.h b/openssl/crypto/ossl_typ.h index ea9227f6f..12cdd43be 100644 --- a/openssl/crypto/ossl_typ.h +++ b/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/openssl/crypto/pkcs7/pkcs7.h b/openssl/crypto/pkcs7/pkcs7.h index 04f60379f..5d54c4ac2 100644 --- a/openssl/crypto/pkcs7/pkcs7.h +++ b/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/openssl/crypto/pqueue/pqueue.h b/openssl/crypto/pqueue/pqueue.h index 87fc9037c..26b534808 100644 --- a/openssl/crypto/pqueue/pqueue.h +++ b/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/openssl/crypto/rsa/Makefile b/openssl/crypto/rsa/Makefile index f798d2f74..e8121a496 100644 --- a/openssl/crypto/rsa/Makefile +++ b/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/openssl/crypto/rsa/rsa.h b/openssl/crypto/rsa/rsa.h index 5f269e577..11853fee5 100644 --- a/openssl/crypto/rsa/rsa.h +++ b/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/openssl/crypto/rsa/rsa_err.c b/openssl/crypto/rsa/rsa_err.c index 46e0bf998..9da79d920 100644 --- a/openssl/crypto/rsa/rsa_err.c +++ b/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/openssl/crypto/rsa/rsa_oaep.c b/openssl/crypto/rsa/rsa_oaep.c index af4d24a56..c36333199 100644 --- a/openssl/crypto/rsa/rsa_oaep.c +++ b/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/openssl/crypto/rsa/rsa_pk1.c b/openssl/crypto/rsa/rsa_pk1.c index 8560755f1..c2da56f6c 100644 --- a/openssl/crypto/rsa/rsa_pk1.c +++ b/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/openssl/crypto/rsa/rsa_sign.c b/openssl/crypto/rsa/rsa_sign.c index b6f6037ae..225bcfe2d 100644 --- a/openssl/crypto/rsa/rsa_sign.c +++ b/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/openssl/crypto/stack/safestack.h b/openssl/crypto/stack/safestack.h index ea3aa0d80..bc194cb26 100644 --- a/openssl/crypto/stack/safestack.h +++ b/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 */ |