diff options
| author | Jung-uk Kim <jkim@FreeBSD.org> | 2018-11-20 19:01:17 +0000 |
|---|---|---|
| committer | Jung-uk Kim <jkim@FreeBSD.org> | 2018-11-20 19:01:17 +0000 |
| commit | f12dd99bc33eefb702280bdaed6156a57d867be1 (patch) | |
| tree | 3ced903ff59efa46be0b01f4cae665cd9c974b15 /crypto | |
| parent | 43a67e02da9068b94df1c07fc6f0d70bafd9263b (diff) | |
Notes
Diffstat (limited to 'crypto')
37 files changed, 791 insertions, 147 deletions
diff --git a/crypto/Makefile b/crypto/Makefile index ad1b9f018b1b..180707e6a824 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -36,9 +36,11 @@ TEST=constant_time_test.c LIB= $(TOP)/libcrypto.a SHARED_LIB= libcrypto$(SHLIB_EXT) LIBSRC= cryptlib.c mem.c mem_clr.c mem_dbg.c cversion.c ex_data.c cpt_err.c \ - ebcdic.c uid.c o_time.c o_str.c o_dir.c o_fips.c o_init.c fips_ers.c + ebcdic.c uid.c o_time.c o_str.c o_dir.c o_fips.c o_init.c fips_ers.c \ + getenv.c LIBOBJ= cryptlib.o mem.o mem_dbg.o cversion.o ex_data.o cpt_err.o ebcdic.o \ - uid.o o_time.o o_str.o o_dir.o o_fips.o o_init.o fips_ers.o $(CPUID_OBJ) + uid.o o_time.o o_str.o o_dir.o o_fips.o o_init.o fips_ers.o getenv.o \ + $(CPUID_OBJ) SRC= $(LIBSRC) @@ -178,6 +180,13 @@ ex_data.o: ../include/openssl/ossl_typ.h ../include/openssl/safestack.h ex_data.o: ../include/openssl/stack.h ../include/openssl/symhacks.h cryptlib.h ex_data.o: ex_data.c fips_ers.o: ../include/openssl/opensslconf.h fips_ers.c +getenv.o: ../e_os.h ../include/openssl/bio.h ../include/openssl/buffer.h +getenv.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h +getenv.o: ../include/openssl/err.h ../include/openssl/lhash.h +getenv.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +getenv.o: ../include/openssl/ossl_typ.h ../include/openssl/safestack.h +getenv.o: ../include/openssl/stack.h ../include/openssl/symhacks.h cryptlib.h +getenv.o: getenv.c mem.o: ../e_os.h ../include/openssl/bio.h ../include/openssl/buffer.h mem.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h mem.o: ../include/openssl/err.h ../include/openssl/lhash.h diff --git a/crypto/bio/b_sock.c b/crypto/bio/b_sock.c index 5bad0a2bada2..d32b76bc8ff8 100644 --- a/crypto/bio/b_sock.c +++ b/crypto/bio/b_sock.c @@ -56,6 +56,9 @@ * [including the GNU Public Licence.] */ +#define _DEFAULT_SOURCE +#define _BSD_SOURCE + #include <stdio.h> #include <stdlib.h> #include <errno.h> @@ -83,6 +86,11 @@ NETDB_DEFINE_CONTEXT static int wsa_init_done = 0; # endif +# if defined(__GLIBC__) +# define HAVE_GETHOSTBYNAME_R +# define GETHOSTNAME_R_BUF (2 * 1024) +# endif + /* * WSAAPI specifier is required to make indirect calls to run-time * linked WinSock 2 functions used in this module, to be specific @@ -116,7 +124,12 @@ int BIO_get_host_ip(const char *str, unsigned char *ip) int i; int err = 1; int locked = 0; - struct hostent *he; + struct hostent *he = NULL; +# ifdef HAVE_GETHOSTBYNAME_R + char buf[GETHOSTNAME_R_BUF]; + struct hostent hostent; + int h_errnop; +# endif i = get_ip(str, ip); if (i < 0) { @@ -138,10 +151,18 @@ int BIO_get_host_ip(const char *str, unsigned char *ip) if (i > 0) return (1); + /* if gethostbyname_r is supported, use it. */ +# ifdef HAVE_GETHOSTBYNAME_R + memset(&hostent, 0x00, sizeof(hostent)); + /* gethostbyname_r() sets |he| to NULL on error, we check it further down */ + gethostbyname_r(str, &hostent, buf, sizeof(buf), &he, &h_errnop); +# else /* do a gethostbyname */ CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME); locked = 1; he = BIO_gethostbyname(str); +# endif + if (he == NULL) { BIOerr(BIO_F_BIO_GET_HOST_IP, BIO_R_BAD_HOSTNAME_LOOKUP); goto err; diff --git a/crypto/bn/asm/x86_64-gcc.c b/crypto/bn/asm/x86_64-gcc.c index 1729b479d43e..aa94a13d3b1d 100644 --- a/crypto/bn/asm/x86_64-gcc.c +++ b/crypto/bn/asm/x86_64-gcc.c @@ -55,12 +55,6 @@ * machine. */ -# if defined(_WIN64) || !defined(__LP64__) -# define BN_ULONG unsigned long long -# else -# define BN_ULONG unsigned long -# endif - # undef mul # undef mul_add diff --git a/crypto/bn/bn_blind.c b/crypto/bn/bn_blind.c index d448daa3c77c..a1e5e139d127 100644 --- a/crypto/bn/bn_blind.c +++ b/crypto/bn/bn_blind.c @@ -1,6 +1,6 @@ /* crypto/bn/bn_blind.c */ /* ==================================================================== - * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * Copyright (c) 1998-2018 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 @@ -206,10 +206,15 @@ int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx) if (!BN_BLINDING_create_param(b, NULL, NULL, ctx, NULL, NULL)) goto err; } else if (!(b->flags & BN_BLINDING_NO_UPDATE)) { - if (!BN_mod_mul(b->A, b->A, b->A, b->mod, ctx)) - goto err; - if (!BN_mod_mul(b->Ai, b->Ai, b->Ai, b->mod, ctx)) - goto err; + if (b->m_ctx != NULL) { + if (!bn_mul_mont_fixed_top(b->Ai, b->Ai, b->Ai, b->m_ctx, ctx) + || !bn_mul_mont_fixed_top(b->A, b->A, b->A, b->m_ctx, ctx)) + goto err; + } else { + if (!BN_mod_mul(b->Ai, b->Ai, b->Ai, b->mod, ctx) + || !BN_mod_mul(b->A, b->A, b->A, b->mod, ctx)) + goto err; + } } ret = 1; @@ -241,13 +246,13 @@ int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *ctx) else if (!BN_BLINDING_update(b, ctx)) return (0); - if (r != NULL) { - if (!BN_copy(r, b->Ai)) - ret = 0; - } + if (r != NULL && (BN_copy(r, b->Ai) == NULL)) + return 0; - if (!BN_mod_mul(n, n, b->A, b->mod, ctx)) - ret = 0; + if (b->m_ctx != NULL) + ret = BN_mod_mul_montgomery(n, n, b->A, b->m_ctx, ctx); + else + ret = BN_mod_mul(n, n, b->A, b->mod, ctx); return ret; } @@ -264,14 +269,29 @@ int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, bn_check_top(n); - if (r != NULL) - ret = BN_mod_mul(n, n, r, b->mod, ctx); - else { - if (b->Ai == NULL) { - BNerr(BN_F_BN_BLINDING_INVERT_EX, BN_R_NOT_INITIALIZED); - return (0); + if (r == NULL && (r = b->Ai) == NULL) { + BNerr(BN_F_BN_BLINDING_INVERT_EX, BN_R_NOT_INITIALIZED); + return 0; + } + + if (b->m_ctx != NULL) { + /* ensure that BN_mod_mul_montgomery takes pre-defined path */ + if (n->dmax >= r->top) { + size_t i, rtop = r->top, ntop = n->top; + BN_ULONG mask; + + for (i = 0; i < rtop; i++) { + mask = (BN_ULONG)0 - ((i - ntop) >> (8 * sizeof(i) - 1)); + n->d[i] &= mask; + } + mask = (BN_ULONG)0 - ((rtop - ntop) >> (8 * sizeof(ntop) - 1)); + /* always true, if (rtop >= ntop) n->top = r->top; */ + n->top = (int)(rtop & ~mask) | (ntop & mask); + n->flags |= (BN_FLG_FIXED_TOP & ~mask); } - ret = BN_mod_mul(n, n, b->Ai, b->mod, ctx); + ret = BN_mod_mul_montgomery(n, n, r, b->m_ctx, ctx); + } else { + ret = BN_mod_mul(n, n, r, b->mod, ctx); } bn_check_top(n); @@ -366,14 +386,19 @@ BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b, } while (1); if (ret->bn_mod_exp != NULL && ret->m_ctx != NULL) { - if (!ret->bn_mod_exp - (ret->A, ret->A, ret->e, ret->mod, ctx, ret->m_ctx)) + if (!ret->bn_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx, ret->m_ctx)) goto err; } else { if (!BN_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx)) goto err; } + if (ret->m_ctx != NULL) { + if (!bn_to_mont_fixed_top(ret->Ai, ret->Ai, ret->m_ctx, ctx) + || !bn_to_mont_fixed_top(ret->A, ret->A, ret->m_ctx, ctx)) + goto err; + } + return ret; err: if (b == NULL && ret != NULL) { diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c index 03bd8cd183a6..9b95e5f2bd92 100644 --- a/crypto/bn/bn_lib.c +++ b/crypto/bn/bn_lib.c @@ -617,26 +617,40 @@ BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) static int bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) { int n; - size_t i, inc, lasti, j; + size_t i, lasti, j, atop, mask; BN_ULONG l; + /* + * In case |a| is fixed-top, BN_num_bytes can return bogus length, + * but it's assumed that fixed-top inputs ought to be "nominated" + * even for padded output, so it works out... + */ n = BN_num_bytes(a); - if (tolen == -1) + if (tolen == -1) { tolen = n; - else if (tolen < n) - return -1; + } else if (tolen < n) { /* uncommon/unlike case */ + BIGNUM temp = *a; - if (n == 0) { + bn_correct_top(&temp); + n = BN_num_bytes(&temp); + if (tolen < n) + return -1; + } + + /* Swipe through whole available data and don't give away padded zero. */ + atop = a->dmax * BN_BYTES; + if (atop == 0) { OPENSSL_cleanse(to, tolen); return tolen; } - lasti = n - 1; - for (i = 0, inc = 1, j = tolen; j > 0;) { + lasti = atop - 1; + atop = a->top * BN_BYTES; + for (i = 0, j = 0, to += tolen; j < (size_t)tolen; j++) { l = a->d[i / BN_BYTES]; - to[--j] = (unsigned char)(l >> (8 * (i % BN_BYTES)) & (0 - inc)); - inc = (i - lasti) >> (8 * sizeof(i) - 1); - i += inc; /* stay on top limb */ + mask = 0 - ((j - atop) >> (8 * sizeof(i) - 1)); + *--to = (unsigned char)(l >> (8 * (i % BN_BYTES)) & mask); + i += (i - lasti) >> (8 * sizeof(i) - 1); /* stay on last limb */ } return tolen; @@ -889,6 +903,38 @@ void BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords) a->top ^= t; b->top ^= t; + t = (a->neg ^ b->neg) & condition; + a->neg ^= t; + b->neg ^= t; + + /*- + * BN_FLG_STATIC_DATA: indicates that data may not be written to. Intention + * is actually to treat it as it's read-only data, and some (if not most) + * of it does reside in read-only segment. In other words observation of + * BN_FLG_STATIC_DATA in BN_consttime_swap should be treated as fatal + * condition. It would either cause SEGV or effectively cause data + * corruption. + * + * BN_FLG_MALLOCED: refers to BN structure itself, and hence must be + * preserved. + * + * BN_FLG_SECURE: must be preserved, because it determines how x->d was + * allocated and hence how to free it. + * + * BN_FLG_CONSTTIME: sufficient to mask and swap + * + * BN_FLG_FIXED_TOP: indicates that we haven't called bn_correct_top() on + * the data, so the d array may be padded with additional 0 values (i.e. + * top could be greater than the minimal value that it could be). We should + * be swapping it + */ + +#define BN_CONSTTIME_SWAP_FLAGS (BN_FLG_CONSTTIME | BN_FLG_FIXED_TOP) + + t = ((a->flags ^ b->flags) & BN_CONSTTIME_SWAP_FLAGS) & condition; + a->flags ^= t; + b->flags ^= t; + #define BN_CONSTTIME_SWAP(ind) \ do { \ t = (a->d[ind] ^ b->d[ind]) & condition; \ diff --git a/crypto/bn/bn_mod.c b/crypto/bn/bn_mod.c index 43da462d93b0..255e6e472391 100644 --- a/crypto/bn/bn_mod.c +++ b/crypto/bn/bn_mod.c @@ -172,7 +172,7 @@ int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, if (mtop > sizeof(storage) / sizeof(storage[0]) && (tp = OPENSSL_malloc(mtop * sizeof(BN_ULONG))) == NULL) - return 0; + return 0; ap = a->d != NULL ? a->d : tp; bp = b->d != NULL ? b->d : tp; @@ -197,6 +197,7 @@ int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, ((volatile BN_ULONG *)tp)[i] = 0; } r->top = mtop; + r->flags |= BN_FLG_FIXED_TOP; r->neg = 0; if (tp != storage) @@ -225,6 +226,70 @@ int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, } /* + * BN_mod_sub variant that may be used if both a and b are non-negative, + * a is less than m, while b is of same bit width as m. It's implemented + * as subtraction followed by two conditional additions. + * + * 0 <= a < m + * 0 <= b < 2^w < 2*m + * + * after subtraction + * + * -2*m < r = a - b < m + * + * Thus it takes up to two conditional additions to make |r| positive. + */ +int bn_mod_sub_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m) +{ + size_t i, ai, bi, mtop = m->top; + BN_ULONG borrow, carry, ta, tb, mask, *rp; + const BN_ULONG *ap, *bp; + + if (bn_wexpand(r, m->top) == NULL) + return 0; + + rp = r->d; + ap = a->d != NULL ? a->d : rp; + bp = b->d != NULL ? b->d : rp; + + for (i = 0, ai = 0, bi = 0, borrow = 0; i < mtop;) { + mask = (BN_ULONG)0 - ((i - a->top) >> (8 * sizeof(i) - 1)); + ta = ap[ai] & mask; + + mask = (BN_ULONG)0 - ((i - b->top) >> (8 * sizeof(i) - 1)); + tb = bp[bi] & mask; + rp[i] = ta - tb - borrow; + if (ta != tb) + borrow = (ta < tb); + + i++; + ai += (i - a->dmax) >> (8 * sizeof(i) - 1); + bi += (i - b->dmax) >> (8 * sizeof(i) - 1); + } + ap = m->d; + for (i = 0, mask = 0 - borrow, carry = 0; i < mtop; i++) { + ta = ((ap[i] & mask) + carry) & BN_MASK2; + carry = (ta < carry); + rp[i] = (rp[i] + ta) & BN_MASK2; + carry += (rp[i] < ta); + } + borrow -= carry; + for (i = 0, mask = 0 - borrow, carry = 0; i < mtop; i++) { + ta = ((ap[i] & mask) + carry) & BN_MASK2; + carry = (ta < carry); + rp[i] = (rp[i] + ta) & BN_MASK2; + carry += (rp[i] < ta); + } + + r->top = mtop; + r->flags |= BN_FLG_FIXED_TOP; + r->neg = 0; + + return 1; +} + +/* * BN_mod_sub variant that may be used if both a and b are non-negative and * less than m */ diff --git a/crypto/bn/bn_mont.c b/crypto/bn/bn_mont.c index d41434a14390..76eca50d32f0 100644 --- a/crypto/bn/bn_mont.c +++ b/crypto/bn/bn_mont.c @@ -164,10 +164,10 @@ int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, bn_check_top(tmp); if (a == b) { - if (!BN_sqr(tmp, a, ctx)) + if (!bn_sqr_fixed_top(tmp, a, ctx)) goto err; } else { - if (!BN_mul(tmp, a, b, ctx)) + if (!bn_mul_fixed_top(tmp, a, b, ctx)) goto err; } /* reduce from aRR to aR */ @@ -190,6 +190,7 @@ static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) BIGNUM *n; BN_ULONG *ap, *np, *rp, n0, v, carry; int nl, max, i; + unsigned int rtop; n = &(mont->N); nl = n->top; @@ -207,12 +208,10 @@ static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) rp = r->d; /* clear the top words of T */ -# if 1 - for (i = r->top; i < max; i++) /* memset? XXX */ - rp[i] = 0; -# else - memset(&(rp[r->top]), 0, (max - r->top) * sizeof(BN_ULONG)); -# endif + for (rtop = r->top, i = 0; i < max; i++) { + v = (BN_ULONG)0 - ((i - rtop) >> (8 * sizeof(rtop) - 1)); + rp[i] &= v; + } r->top = max; r->flags |= BN_FLG_FIXED_TOP; @@ -263,6 +262,18 @@ static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont, BN_CTX *ctx) { + int retn; + + retn = bn_from_mont_fixed_top(ret, a, mont, ctx); + bn_correct_top(ret); + bn_check_top(ret); + + return retn; +} + +int bn_from_mont_fixed_top(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx) +{ int retn = 0; #ifdef MONT_WORD BIGNUM *t; @@ -270,8 +281,6 @@ int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont, BN_CTX_start(ctx); if ((t = BN_CTX_get(ctx)) && BN_copy(t, a)) { retn = bn_from_montgomery_word(ret, t, mont); - bn_correct_top(ret); - bn_check_top(ret); } BN_CTX_end(ctx); #else /* !MONT_WORD */ diff --git a/crypto/bn/bn_mul.c b/crypto/bn/bn_mul.c index 6b455a755f71..f44e5e5c1e08 100644 --- a/crypto/bn/bn_mul.c +++ b/crypto/bn/bn_mul.c @@ -936,6 +936,16 @@ void bn_mul_high(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, BN_ULONG *l, int n2, int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { + int ret = bn_mul_fixed_top(r, a, b, ctx); + + bn_correct_top(r); + bn_check_top(r); + + return ret; +} + +int bn_mul_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) +{ int ret = 0; int top, al, bl; BIGNUM *rr; @@ -1042,7 +1052,7 @@ int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) #if defined(BN_MUL_COMBA) || defined(BN_RECURSION) end: #endif - bn_correct_top(rr); + rr->flags |= BN_FLG_FIXED_TOP; if (r != rr && BN_copy(r, rr) == NULL) goto err; diff --git a/crypto/bn/bn_sqr.c b/crypto/bn/bn_sqr.c index 5e692971c948..44bc55473f1a 100644 --- a/crypto/bn/bn_sqr.c +++ b/crypto/bn/bn_sqr.c @@ -66,6 +66,16 @@ */ int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) { + int ret = bn_sqr_fixed_top(r, a, ctx); + + bn_correct_top(r); + bn_check_top(r); + + return ret; +} + +int bn_sqr_fixed_top(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) +{ int max, al; int ret = 0; BIGNUM *tmp, *rr; @@ -136,7 +146,7 @@ int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) rr->neg = 0; rr->top = max; - bn_correct_top(rr); + rr->flags |= BN_FLG_FIXED_TOP; if (r != rr && BN_copy(r, rr) == NULL) goto err; diff --git a/crypto/bn/bn_x931p.c b/crypto/bn/bn_x931p.c index f444af3feabd..e40241ffc99e 100644 --- a/crypto/bn/bn_x931p.c +++ b/crypto/bn/bn_x931p.c @@ -4,7 +4,7 @@ * 2005. */ /* ==================================================================== - * Copyright (c) 2005 The OpenSSL Project. All rights reserved. + * Copyright (c) 2005-2018 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 @@ -223,8 +223,10 @@ int BN_X931_generate_Xpq(BIGNUM *Xp, BIGNUM *Xq, int nbits, BN_CTX *ctx) for (i = 0; i < 1000; i++) { if (!BN_rand(Xq, nbits, 1, 0)) goto err; + /* Check that |Xp - Xq| > 2^(nbits - 100) */ - BN_sub(t, Xp, Xq); + if (!BN_sub(t, Xp, Xq)) + goto err; if (BN_num_bits(t) > (nbits - 100)) break; } diff --git a/crypto/bn_int.h b/crypto/bn_int.h index 9c42d6f35dc3..a552cc20be95 100644 --- a/crypto/bn_int.h +++ b/crypto/bn_int.h @@ -7,9 +7,15 @@ */ int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_MONT_CTX *mont, BN_CTX *ctx); +int bn_from_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx); int bn_to_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, BN_CTX *ctx); int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m); +int bn_mod_sub_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m); +int bn_mul_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); +int bn_sqr_fixed_top(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx); int bn_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen); diff --git a/crypto/conf/Makefile b/crypto/conf/Makefile index d5f5c582414b..cd436f711c47 100644 --- a/crypto/conf/Makefile +++ b/crypto/conf/Makefile @@ -80,12 +80,13 @@ clean: # DO NOT DELETE THIS LINE -- make depend depends on it. conf_api.o: ../../e_os.h ../../include/openssl/bio.h -conf_api.o: ../../include/openssl/conf.h ../../include/openssl/conf_api.h -conf_api.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h +conf_api.o: ../../include/openssl/buffer.h ../../include/openssl/conf.h +conf_api.o: ../../include/openssl/conf_api.h ../../include/openssl/crypto.h +conf_api.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h conf_api.o: ../../include/openssl/lhash.h ../../include/openssl/opensslconf.h conf_api.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h conf_api.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h -conf_api.o: ../../include/openssl/symhacks.h conf_api.c +conf_api.o: ../../include/openssl/symhacks.h ../cryptlib.h conf_api.c conf_def.o: ../../e_os.h ../../include/openssl/bio.h conf_def.o: ../../include/openssl/buffer.h ../../include/openssl/conf.h conf_def.o: ../../include/openssl/conf_api.h ../../include/openssl/crypto.h diff --git a/crypto/conf/conf_api.c b/crypto/conf/conf_api.c index 60c9440120e8..480781d205c7 100644 --- a/crypto/conf/conf_api.c +++ b/crypto/conf/conf_api.c @@ -66,6 +66,7 @@ #include <assert.h> #include <stdlib.h> #include <string.h> +#include "cryptlib.h" #include <openssl/conf.h> #include <openssl/conf_api.h> #include "e_os.h" @@ -141,7 +142,7 @@ char *_CONF_get_string(const CONF *conf, const char *section, if (v != NULL) return (v->value); if (strcmp(section, "ENV") == 0) { - p = getenv(name); + p = ossl_safe_getenv(name); if (p != NULL) return (p); } @@ -154,7 +155,7 @@ char *_CONF_get_string(const CONF *conf, const char *section, else return (NULL); } else - return (getenv(name)); + return (ossl_safe_getenv(name)); } #if 0 /* There's no way to provide error checking diff --git a/crypto/conf/conf_mod.c b/crypto/conf/conf_mod.c index e2a9a81678ed..1df463dd1bc0 100644 --- a/crypto/conf/conf_mod.c +++ b/crypto/conf/conf_mod.c @@ -4,7 +4,7 @@ * 2001. */ /* ==================================================================== - * Copyright (c) 2001 The OpenSSL Project. All rights reserved. + * Copyright (c) 2001-2018 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 @@ -530,7 +530,7 @@ char *CONF_get1_default_config_file(void) char *file; int len; - file = getenv("OPENSSL_CONF"); + file = ossl_safe_getenv("OPENSSL_CONF"); if (file) return BUF_strdup(file); diff --git a/crypto/cryptlib.h b/crypto/cryptlib.h index fba180a6b2fb..cdbddf17350f 100644 --- a/crypto/cryptlib.h +++ b/crypto/cryptlib.h @@ -104,6 +104,8 @@ void OPENSSL_showfatal(const char *fmta, ...); void *OPENSSL_stderr(void); extern int OPENSSL_NONPIC_relocated; +char *ossl_safe_getenv(const char *); + #ifdef __cplusplus } #endif diff --git a/crypto/dsa/dsa_gen.c b/crypto/dsa/dsa_gen.c index db52a38a1882..e55d585890d9 100644 --- a/crypto/dsa/dsa_gen.c +++ b/crypto/dsa/dsa_gen.c @@ -435,6 +435,12 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N, EVP_MD_CTX_init(&mctx); + /* make sure L > N, otherwise we'll get trapped in an infinite loop */ + if (L <= N) { + DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN2, DSA_R_INVALID_PARAMETERS); + goto err; + } + if (evpmd == NULL) { if (N == 160) evpmd = EVP_sha1(); diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c index 2dcfedeeee7e..c887c3c34e37 100644 --- a/crypto/dsa/dsa_ossl.c +++ b/crypto/dsa/dsa_ossl.c @@ -73,6 +73,8 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, DSA *dsa); static int dsa_init(DSA *dsa); static int dsa_finish(DSA *dsa); +static BIGNUM *dsa_mod_inverse_fermat(const BIGNUM *k, const BIGNUM *q, + BN_CTX *ctx); static DSA_METHOD openssl_dsa_meth = { "OpenSSL DSA method", @@ -279,7 +281,7 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, goto err; /* Preallocate space */ - q_bits = BN_num_bits(dsa->q); + q_bits = BN_num_bits(dsa->q) + sizeof(dsa->q->d[0]) * 16; if (!BN_set_bit(&k, q_bits) || !BN_set_bit(&l, q_bits) || !BN_set_bit(&m, q_bits)) @@ -293,9 +295,9 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0) { BN_set_flags(&k, BN_FLG_CONSTTIME); + BN_set_flags(&l, BN_FLG_CONSTTIME); } - if (dsa->flags & DSA_FLAG_CACHE_MONT_P) { if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p, CRYPTO_LOCK_DSA, dsa->p, ctx)) @@ -333,8 +335,8 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, if (!BN_mod(r, r, dsa->q, ctx)) goto err; - /* Compute part of 's = inv(k) (m + xr) mod q' */ - if ((kinv = BN_mod_inverse(NULL, &k, dsa->q, ctx)) == NULL) + /* Compute part of 's = inv(k) (m + xr) mod q' */ + if ((kinv = dsa_mod_inverse_fermat(&k, dsa->q, ctx)) == NULL) goto err; if (*kinvp != NULL) @@ -468,3 +470,31 @@ static int dsa_finish(DSA *dsa) BN_MONT_CTX_free(dsa->method_mont_p); return (1); } + +/* + * Compute the inverse of k modulo q. + * Since q is prime, Fermat's Little Theorem applies, which reduces this to + * mod-exp operation. Both the exponent and modulus are public information + * so a mod-exp that doesn't leak the base is sufficient. A newly allocated + * BIGNUM is returned which the caller must free. + */ +static BIGNUM *dsa_mod_inverse_fermat(const BIGNUM *k, const BIGNUM *q, + BN_CTX *ctx) +{ + BIGNUM *res = NULL; + BIGNUM *r, e; + + if ((r = BN_new()) == NULL) + return NULL; + + BN_init(&e); + + if (BN_set_word(r, 2) + && BN_sub(&e, q, r) + && BN_mod_exp_mont(r, k, &e, q, ctx, NULL)) + res = r; + else + BN_free(r); + BN_free(&e); + return res; +} diff --git a/crypto/ec/ec_lcl.h b/crypto/ec/ec_lcl.h index 969fd147ef93..8665a4c9c7dd 100644 --- a/crypto/ec/ec_lcl.h +++ b/crypto/ec/ec_lcl.h @@ -3,7 +3,7 @@ * Originally written by Bodo Moeller for the OpenSSL project. */ /* ==================================================================== - * Copyright (c) 1998-2010 The OpenSSL Project. All rights reserved. + * Copyright (c) 1998-2018 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 @@ -214,7 +214,7 @@ struct ec_group_st { int asn1_flag; /* flag to control the asn1 encoding */ /* * Kludge: upper bit of ans1_flag is used to denote structure - * version. Is set, then last field is present. This is done + * version. If set, then last field is present. This is done * for interoperation with FIPS code. */ #define EC_GROUP_ASN1_FLAG_MASK 0x7fffffff @@ -549,7 +549,6 @@ void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array, void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign, unsigned char *digit, unsigned char in); #endif -int ec_precompute_mont_data(EC_GROUP *); #ifdef ECP_NISTZ256_ASM /** Returns GFp methods using montgomery multiplication, with x86-64 optimized diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c index 933745248d8d..df56484b5ee2 100644 --- a/crypto/ec/ec_lib.c +++ b/crypto/ec/ec_lib.c @@ -70,6 +70,10 @@ const char EC_version[] = "EC" OPENSSL_VERSION_PTEXT; +/* local function prototypes */ + +static int ec_precompute_mont_data(EC_GROUP *group); + /* functions for EC_GROUP objects */ EC_GROUP *EC_GROUP_new(const EC_METHOD *meth) @@ -318,17 +322,25 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, } else BN_zero(&group->cofactor); - /* - * Some groups have an order with - * factors of two, which makes the Montgomery setup fail. - * |group->mont_data| will be NULL in this case. + /*- + * Access to the `mont_data` field of an EC_GROUP struct should always be + * guarded by an EC_GROUP_VERSION(group) check to avoid OOB accesses, as the + * group might come from the FIPS module, which does not define the + * `mont_data` field inside the EC_GROUP structure. */ - if (BN_is_odd(&group->order)) { - return ec_precompute_mont_data(group); + if (EC_GROUP_VERSION(group)) { + /*- + * Some groups have an order with + * factors of two, which makes the Montgomery setup fail. + * |group->mont_data| will be NULL in this case. + */ + if (BN_is_odd(&group->order)) + return ec_precompute_mont_data(group); + + BN_MONT_CTX_free(group->mont_data); + group->mont_data = NULL; } - BN_MONT_CTX_free(group->mont_data); - group->mont_data = NULL; return 1; } @@ -1098,18 +1110,23 @@ int EC_GROUP_have_precompute_mult(const EC_GROUP *group) * been performed */ } -/* +/*- * ec_precompute_mont_data sets |group->mont_data| from |group->order| and * returns one on success. On error it returns zero. + * + * Note: this function must be called only after verifying that + * EC_GROUP_VERSION(group) returns true. + * The reason for this is that access to the `mont_data` field of an EC_GROUP + * struct should always be guarded by an EC_GROUP_VERSION(group) check to avoid + * OOB accesses, as the group might come from the FIPS module, which does not + * define the `mont_data` field inside the EC_GROUP structure. */ +static int ec_precompute_mont_data(EC_GROUP *group) { BN_CTX *ctx = BN_CTX_new(); int ret = 0; - if (!EC_GROUP_VERSION(group)) - goto err; - if (group->mont_data) { BN_MONT_CTX_free(group->mont_data); group->mont_data = NULL; diff --git a/crypto/ec/ec_mult.c b/crypto/ec/ec_mult.c index 2231f9957ef6..da71526818f8 100644 --- a/crypto/ec/ec_mult.c +++ b/crypto/ec/ec_mult.c @@ -3,7 +3,7 @@ * Originally written by Bodo Moeller and Nils Larsch for the OpenSSL project. */ /* ==================================================================== - * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * Copyright (c) 1998-2018 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 @@ -310,6 +310,224 @@ static signed char *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len) return r; } +#define EC_POINT_BN_set_flags(P, flags) do { \ + BN_set_flags(&(P)->X, (flags)); \ + BN_set_flags(&(P)->Y, (flags)); \ + BN_set_flags(&(P)->Z, (flags)); \ +} while(0) + +/*- + * This functions computes (in constant time) a point multiplication over the + * EC group. + * + * At a high level, it is Montgomery ladder with conditional swaps. + * + * It performs either a fixed scalar point multiplication + * (scalar * generator) + * when point is NULL, or a generic scalar point multiplication + * (scalar * point) + * when point is not NULL. + * + * scalar should be in the range [0,n) otherwise all constant time bets are off. + * + * NB: This says nothing about EC_POINT_add and EC_POINT_dbl, + * which of course are not constant time themselves. + * + * The product is stored in r. + * + * Returns 1 on success, 0 otherwise. + */ +static int ec_mul_consttime(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, const EC_POINT *point, + BN_CTX *ctx) +{ + int i, cardinality_bits, group_top, kbit, pbit, Z_is_one; + EC_POINT *s = NULL; + BIGNUM *k = NULL; + BIGNUM *lambda = NULL; + BIGNUM *cardinality = NULL; + BN_CTX *new_ctx = NULL; + int ret = 0; + + if (ctx == NULL && (ctx = new_ctx = BN_CTX_new()) == NULL) + return 0; + + BN_CTX_start(ctx); + + s = EC_POINT_new(group); + if (s == NULL) + goto err; + + if (point == NULL) { + if (!EC_POINT_copy(s, group->generator)) + goto err; + } else { + if (!EC_POINT_copy(s, point)) + goto err; + } + + EC_POINT_BN_set_flags(s, BN_FLG_CONSTTIME); + + cardinality = BN_CTX_get(ctx); + lambda = BN_CTX_get(ctx); + k = BN_CTX_get(ctx); + if (k == NULL || !BN_mul(cardinality, &group->order, &group->cofactor, ctx)) + goto err; + + /* + * Group cardinalities are often on a word boundary. + * So when we pad the scalar, some timing diff might + * pop if it needs to be expanded due to carries. + * So expand ahead of time. + */ + cardinality_bits = BN_num_bits(cardinality); + group_top = cardinality->top; + if ((bn_wexpand(k, group_top + 2) == NULL) + || (bn_wexpand(lambda, group_top + 2) == NULL)) + goto err; + + if (!BN_copy(k, scalar)) + goto err; + + BN_set_flags(k, BN_FLG_CONSTTIME); + + if ((BN_num_bits(k) > cardinality_bits) || (BN_is_negative(k))) { + /*- + * this is an unusual input, and we don't guarantee + * constant-timeness + */ + if (!BN_nnmod(k, k, cardinality, ctx)) + goto err; + } + + if (!BN_add(lambda, k, cardinality)) + goto err; + BN_set_flags(lambda, BN_FLG_CONSTTIME); + if (!BN_add(k, lambda, cardinality)) + goto err; + /* + * lambda := scalar + cardinality + * k := scalar + 2*cardinality + */ + kbit = BN_is_bit_set(lambda, cardinality_bits); + BN_consttime_swap(kbit, k, lambda, group_top + 2); + + group_top = group->field.top; + if ((bn_wexpand(&s->X, group_top) == NULL) + || (bn_wexpand(&s->Y, group_top) == NULL) + || (bn_wexpand(&s->Z, group_top) == NULL) + || (bn_wexpand(&r->X, group_top) == NULL) + || (bn_wexpand(&r->Y, group_top) == NULL) + || (bn_wexpand(&r->Z, group_top) == NULL)) + goto err; + + /* top bit is a 1, in a fixed pos */ + if (!EC_POINT_copy(r, s)) + goto err; + + EC_POINT_BN_set_flags(r, BN_FLG_CONSTTIME); + + if (!EC_POINT_dbl(group, s, s, ctx)) + goto err; + + pbit = 0; + +#define EC_POINT_CSWAP(c, a, b, w, t) do { \ + BN_consttime_swap(c, &(a)->X, &(b)->X, w); \ + BN_consttime_swap(c, &(a)->Y, &(b)->Y, w); \ + BN_consttime_swap(c, &(a)->Z, &(b)->Z, w); \ + t = ((a)->Z_is_one ^ (b)->Z_is_one) & (c); \ + (a)->Z_is_one ^= (t); \ + (b)->Z_is_one ^= (t); \ +} while(0) + + /*- + * The ladder step, with branches, is + * + * k[i] == 0: S = add(R, S), R = dbl(R) + * k[i] == 1: R = add(S, R), S = dbl(S) + * + * Swapping R, S conditionally on k[i] leaves you with state + * + * k[i] == 0: T, U = R, S + * k[i] == 1: T, U = S, R + * + * Then perform the ECC ops. + * + * U = add(T, U) + * T = dbl(T) + * + * Which leaves you with state + * + * k[i] == 0: U = add(R, S), T = dbl(R) + * k[i] == 1: U = add(S, R), T = dbl(S) + * + * Swapping T, U conditionally on k[i] leaves you with state + * + * k[i] == 0: R, S = T, U + * k[i] == 1: R, S = U, T + * + * Which leaves you with state + * + * k[i] == 0: S = add(R, S), R = dbl(R) + * k[i] == 1: R = add(S, R), S = dbl(S) + * + * So we get the same logic, but instead of a branch it's a + * conditional swap, followed by ECC ops, then another conditional swap. + * + * Optimization: The end of iteration i and start of i-1 looks like + * + * ... + * CSWAP(k[i], R, S) + * ECC + * CSWAP(k[i], R, S) + * (next iteration) + * CSWAP(k[i-1], R, S) + * ECC + * CSWAP(k[i-1], R, S) + * ... + * + * So instead of two contiguous swaps, you can merge the condition + * bits and do a single swap. + * + * k[i] k[i-1] Outcome + * 0 0 No Swap + * 0 1 Swap + * 1 0 Swap + * 1 1 No Swap + * + * This is XOR. pbit tracks the previous bit of k. + */ + + for (i = cardinality_bits - 1; i >= 0; i--) { + kbit = BN_is_bit_set(k, i) ^ pbit; + EC_POINT_CSWAP(kbit, r, s, group_top, Z_is_one); + if (!EC_POINT_add(group, s, r, s, ctx)) + goto err; + if (!EC_POINT_dbl(group, r, r, ctx)) + goto err; + /* + * pbit logic merges this cswap with that of the + * next iteration + */ + pbit ^= kbit; + } + /* one final cswap to move the right value into r */ + EC_POINT_CSWAP(pbit, r, s, group_top, Z_is_one); +#undef EC_POINT_CSWAP + + ret = 1; + + err: + EC_POINT_free(s); + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + + return ret; +} + +#undef EC_POINT_BN_set_flags + /* * TODO: table should be optimised for the wNAF-based implementation, * sometimes smaller windows will give better performance (thus the @@ -369,6 +587,34 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, return EC_POINT_set_to_infinity(group, r); } + if (!BN_is_zero(&group->order) && !BN_is_zero(&group->cofactor)) { + /*- + * Handle the common cases where the scalar is secret, enforcing a constant + * time scalar multiplication algorithm. + */ + if ((scalar != NULL) && (num == 0)) { + /*- + * In this case we want to compute scalar * GeneratorPoint: this + * codepath is reached most prominently by (ephemeral) key generation + * of EC cryptosystems (i.e. ECDSA keygen and sign setup, ECDH + * keygen/first half), where the scalar is always secret. This is why + * we ignore if BN_FLG_CONSTTIME is actually set and we always call the + * constant time version. + */ + return ec_mul_consttime(group, r, scalar, NULL, ctx); + } + if ((scalar == NULL) && (num == 1)) { + /*- + * In this case we want to compute scalar * GenericPoint: this codepath + * is reached most prominently by the second half of ECDH, where the + * secret scalar is multiplied by the peer's public point. To protect + * the secret scalar, we ignore if BN_FLG_CONSTTIME is actually set and + * we always call the constant time version. + */ + return ec_mul_consttime(group, r, scalars[0], points[0], ctx); + } + } + for (i = 0; i < num; i++) { if (group->meth != points[i]->meth) { ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS); diff --git a/crypto/engine/eng_list.c b/crypto/engine/eng_list.c index 83c95d56f466..5d7eee408520 100644 --- a/crypto/engine/eng_list.c +++ b/crypto/engine/eng_list.c @@ -4,7 +4,7 @@ * 2000. */ /* ==================================================================== - * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2018 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 @@ -62,6 +62,7 @@ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. */ +#include "cryptlib.h" #include "eng_int.h" /* @@ -369,10 +370,10 @@ ENGINE *ENGINE_by_id(const char *id) */ if (strcmp(id, "dynamic")) { # ifdef OPENSSL_SYS_VMS - if ((load_dir = getenv("OPENSSL_ENGINES")) == 0) + if ((load_dir = ossl_safe_getenv("OPENSSL_ENGINES")) == 0) load_dir = "SSLROOT:[ENGINES]"; # else - if ((load_dir = getenv("OPENSSL_ENGINES")) == 0) + if ((load_dir = ossl_safe_getenv("OPENSSL_ENGINES")) == 0) load_dir = ENGINESDIR; # endif iterator = ENGINE_by_id("dynamic"); diff --git a/crypto/getenv.c b/crypto/getenv.c new file mode 100644 index 000000000000..53f1dfd457a9 --- /dev/null +++ b/crypto/getenv.c @@ -0,0 +1,31 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +#include <stdlib.h> +#include "cryptlib.h" + +char *ossl_safe_getenv(const char *name) +{ +#if defined(__GLIBC__) && defined(__GLIBC_PREREQ) +# if __GLIBC_PREREQ(2, 17) +# define SECURE_GETENV + return secure_getenv(name); +# endif +#endif + +#ifndef SECURE_GETENV + if (OPENSSL_issetugid()) + return NULL; + return getenv(name); +#endif +} diff --git a/crypto/opensslconf.h b/crypto/opensslconf.h index f533508b152c..ac0ad5068f6d 100644 --- a/crypto/opensslconf.h +++ b/crypto/opensslconf.h @@ -53,6 +53,9 @@ extern "C" { #endif /* OPENSSL_DOING_MAKEDEPEND */ +#ifndef OPENSSL_THREADS +# define OPENSSL_THREADS +#endif #ifndef OPENSSL_NO_DYNAMIC_ENGINE # define OPENSSL_NO_DYNAMIC_ENGINE #endif @@ -106,6 +109,8 @@ extern "C" { # endif #endif +#define OPENSSL_CPUID_OBJ + /* crypto/opensslconf.h.in */ /* Generate 80386 code? */ @@ -152,7 +157,7 @@ extern "C" { * This enables code handling data aligned at natural CPU word * boundary. See crypto/rc4/rc4_enc.c for further details. */ -#undef RC4_CHUNK +#define RC4_CHUNK unsigned long #endif #endif @@ -160,7 +165,7 @@ extern "C" { /* If this is set to 'unsigned int' on a DEC Alpha, this gives about a * %20 speed up (longs are 8 bytes, int's are 4). */ #ifndef DES_LONG -#define DES_LONG unsigned long +#define DES_LONG unsigned int #endif #endif @@ -171,9 +176,9 @@ extern "C" { /* Should we define BN_DIV2W here? */ /* Only one for the following should be defined */ -#undef SIXTY_FOUR_BIT_LONG +#define SIXTY_FOUR_BIT_LONG #undef SIXTY_FOUR_BIT -#define THIRTY_TWO_BIT +#undef THIRTY_TWO_BIT #endif #if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H) @@ -215,7 +220,7 @@ extern "C" { /* Unroll the inner loop, this sometimes helps, sometimes hinders. * Very mucy CPU dependant */ #ifndef DES_UNROLL -#undef DES_UNROLL +#define DES_UNROLL #endif /* These default values were supplied by diff --git a/crypto/opensslv.h b/crypto/opensslv.h index 76a7b009d463..73d22b399a8a 100644 --- a/crypto/opensslv.h +++ b/crypto/opensslv.h @@ -30,11 +30,11 @@ extern "C" { * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for * major minor fix final patch/beta) */ -# define OPENSSL_VERSION_NUMBER 0x1000210fL +# define OPENSSL_VERSION_NUMBER 0x1000211fL # ifdef OPENSSL_FIPS -# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2p-fips 14 Aug 2018" +# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2q-fips 20 Nov 2018" # else -# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2p 14 Aug 2018" +# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2q 20 Nov 2018" # endif # define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT diff --git a/crypto/pkcs12/p12_init.c b/crypto/pkcs12/p12_init.c index 0322df944a4b..a074b94a0c59 100644 --- a/crypto/pkcs12/p12_init.c +++ b/crypto/pkcs12/p12_init.c @@ -4,7 +4,7 @@ * 1999. */ /* ==================================================================== - * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2018 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 @@ -70,7 +70,8 @@ PKCS12 *PKCS12_init(int mode) PKCS12err(PKCS12_F_PKCS12_INIT, ERR_R_MALLOC_FAILURE); return NULL; } - ASN1_INTEGER_set(pkcs12->version, 3); + if (!ASN1_INTEGER_set(pkcs12->version, 3)) + goto err; pkcs12->authsafes->type = OBJ_nid2obj(mode); switch (mode) { case NID_pkcs7_data: diff --git a/crypto/pkcs7/pk7_lib.c b/crypto/pkcs7/pk7_lib.c index 0c5fcaa6aa2d..866a863e54da 100644 --- a/crypto/pkcs7/pk7_lib.c +++ b/crypto/pkcs7/pk7_lib.c @@ -185,7 +185,6 @@ int PKCS7_set_type(PKCS7 *p7, int type) if ((p7->d.signed_and_enveloped = PKCS7_SIGN_ENVELOPE_new()) == NULL) goto err; - ASN1_INTEGER_set(p7->d.signed_and_enveloped->version, 1); if (!ASN1_INTEGER_set(p7->d.signed_and_enveloped->version, 1)) goto err; p7->d.signed_and_enveloped->enc_data->content_type diff --git a/crypto/rand/Makefile b/crypto/rand/Makefile index df44369a0823..1643a7416625 100644 --- a/crypto/rand/Makefile +++ b/crypto/rand/Makefile @@ -157,10 +157,11 @@ rand_win.o: ../../include/openssl/rand.h ../../include/openssl/safestack.h rand_win.o: ../../include/openssl/sha.h ../../include/openssl/stack.h rand_win.o: ../../include/openssl/symhacks.h ../cryptlib.h rand_lcl.h rand_win.o: rand_win.c -randfile.o: ../../e_os.h ../../include/openssl/buffer.h -randfile.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h -randfile.o: ../../include/openssl/opensslconf.h +randfile.o: ../../e_os.h ../../include/openssl/bio.h +randfile.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h +randfile.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h +randfile.o: ../../include/openssl/lhash.h ../../include/openssl/opensslconf.h randfile.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h randfile.o: ../../include/openssl/rand.h ../../include/openssl/safestack.h randfile.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h -randfile.o: randfile.c +randfile.o: ../cryptlib.h randfile.c diff --git a/crypto/rand/md_rand.c b/crypto/rand/md_rand.c index a7af9f9d8671..2983a3fda487 100644 --- a/crypto/rand/md_rand.c +++ b/crypto/rand/md_rand.c @@ -56,7 +56,7 @@ * [including the GNU Public Licence.] */ /* ==================================================================== - * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * Copyright (c) 1998-2018 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 @@ -345,7 +345,6 @@ int ssleay_rand_bytes(unsigned char *buf, int num, int pseudo, int lock) static volatile int stirred_pool = 0; int i, j, k; size_t num_ceil, st_idx, st_num; - int ok; long md_c[2]; unsigned char local_md[MD_DIGEST_LENGTH]; EVP_MD_CTX m; @@ -400,14 +399,13 @@ int ssleay_rand_bytes(unsigned char *buf, int num, int pseudo, int lock) if (!initialized) { RAND_poll(); - initialized = 1; + initialized = (entropy >= ENTROPY_NEEDED); } if (!stirred_pool) do_stir_pool = 1; - ok = (entropy >= ENTROPY_NEEDED); - if (!ok) { + if (!initialized) { /* * If the PRNG state is not yet unpredictable, then seeing the PRNG * output may help attackers to determine the new state; thus we have @@ -446,7 +444,7 @@ int ssleay_rand_bytes(unsigned char *buf, int num, int pseudo, int lock) ssleay_rand_add(DUMMY_SEED, MD_DIGEST_LENGTH, 0.0); n -= MD_DIGEST_LENGTH; } - if (ok) + if (initialized) stirred_pool = 1; } @@ -539,7 +537,7 @@ int ssleay_rand_bytes(unsigned char *buf, int num, int pseudo, int lock) CRYPTO_w_unlock(CRYPTO_LOCK_RAND); EVP_MD_CTX_cleanup(&m); - if (ok) + if (initialized) return (1); else if (pseudo) return 0; @@ -555,6 +553,18 @@ int ssleay_rand_bytes(unsigned char *buf, int num, int pseudo, int lock) return (0); } +/* + * Returns ssleay_rand_bytes(), enforcing a reseeding from the + * system entropy sources using RAND_poll() before generating +`* the random bytes. + */ + +int ssleay_rand_bytes_from_system(unsigned char *buf, int num) +{ + initialized = 0; + return ssleay_rand_bytes(buf, num, 0, 0); +} + static int ssleay_rand_nopseudo_bytes(unsigned char *buf, int num) { return ssleay_rand_bytes(buf, num, 0, 1); @@ -600,10 +610,10 @@ static int ssleay_rand_status(void) if (!initialized) { RAND_poll(); - initialized = 1; + initialized = (entropy >= ENTROPY_NEEDED); } - ret = entropy >= ENTROPY_NEEDED; + ret = initialized; if (!do_not_lock) { /* before unlocking, we must clear 'crypto_lock_rand' */ diff --git a/crypto/rand/rand_lcl.h b/crypto/rand/rand_lcl.h index f9fda3eb89c9..7b4dbcf5fb7c 100755 --- a/crypto/rand/rand_lcl.h +++ b/crypto/rand/rand_lcl.h @@ -56,7 +56,7 @@ * [including the GNU Public Licence.] */ /* ==================================================================== - * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. + * Copyright (c) 1998-2018 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 @@ -154,5 +154,5 @@ # endif int ssleay_rand_bytes(unsigned char *buf, int num, int pseudo, int lock); - +int ssleay_rand_bytes_from_system(unsigned char *buf, int num); #endif diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index 88a78d350656..6094c83e4074 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -185,7 +185,7 @@ int RAND_status(void) /* * Entropy gatherer: use standard OpenSSL PRNG to seed (this will gather - * entropy internally through RAND_poll(). + * entropy internally through RAND_poll()). */ static size_t drbg_get_entropy(DRBG_CTX *ctx, unsigned char **pout, @@ -196,6 +196,24 @@ static size_t drbg_get_entropy(DRBG_CTX *ctx, unsigned char **pout, *pout = OPENSSL_malloc(min_len); if (!*pout) return 0; + + /* Enforces a reseed of the SSLEAY PRNG before generating random bytes */ + if (ssleay_rand_bytes_from_system(*pout, min_len) <= 0) { + OPENSSL_free(*pout); + *pout = NULL; + return 0; + } + return min_len; +} + +static size_t drbg_get_nonce(DRBG_CTX *ctx, unsigned char **pout, + int entropy, size_t min_len, size_t max_len) +{ + /* Round up request to multiple of block size */ + min_len = ((min_len + 19) / 20) * 20; + *pout = OPENSSL_malloc(min_len); + if (!*pout) + return 0; if (ssleay_rand_bytes(*pout, min_len, 0, 0) <= 0) { OPENSSL_free(*pout); *pout = NULL; @@ -281,7 +299,7 @@ int RAND_init_fips(void) FIPS_drbg_set_callbacks(dctx, drbg_get_entropy, drbg_free_entropy, 20, - drbg_get_entropy, drbg_free_entropy); + drbg_get_nonce, drbg_free_entropy); FIPS_drbg_set_rand_callbacks(dctx, drbg_get_adin, 0, drbg_rand_seed, drbg_rand_add); /* Personalisation string: a string followed by date time vector */ diff --git a/crypto/rand/randfile.c b/crypto/rand/randfile.c index 728fd0a721b5..c93812cfb92b 100644 --- a/crypto/rand/randfile.c +++ b/crypto/rand/randfile.c @@ -61,6 +61,7 @@ #include <stdlib.h> #include <string.h> +#include "cryptlib.h" #include "e_os.h" #include <openssl/crypto.h> #include <openssl/rand.h> @@ -327,14 +328,12 @@ const char *RAND_file_name(char *buf, size_t size) struct stat sb; #endif - if (OPENSSL_issetugid() == 0) - s = getenv("RANDFILE"); + s = ossl_safe_getenv("RANDFILE"); if (s != NULL && *s && strlen(s) + 1 < size) { if (BUF_strlcpy(buf, s, size) >= size) return NULL; } else { - if (OPENSSL_issetugid() == 0) - s = getenv("HOME"); + s = ossl_safe_getenv("HOME"); #ifdef DEFAULT_HOME if (s == NULL) { s = DEFAULT_HOME; diff --git a/crypto/rsa/rsa_eay.c b/crypto/rsa/rsa_eay.c index 7ba24e362c56..be948a4cf8bd 100644 --- a/crypto/rsa/rsa_eay.c +++ b/crypto/rsa/rsa_eay.c @@ -224,8 +224,8 @@ static int RSA_eay_public_encrypt(int flen, const unsigned char *from, } if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) - if (!BN_MONT_CTX_set_locked - (&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx)) + if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, + rsa->n, ctx)) goto err; if (!rsa->meth->bn_mod_exp(ret, f, rsa->e, rsa->n, ctx, @@ -432,8 +432,8 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from, d = rsa->d; if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) - if (!BN_MONT_CTX_set_locked - (&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx)) + if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, + rsa->n, ctx)) goto err; if (!rsa->meth->bn_mod_exp(ret, f, d, rsa->n, ctx, @@ -554,8 +554,8 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from, d = rsa->d; if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) - if (!BN_MONT_CTX_set_locked - (&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx)) + if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, + rsa->n, ctx)) goto err; if (!rsa->meth->bn_mod_exp(ret, f, d, rsa->n, ctx, rsa->_method_mod_n)) @@ -660,8 +660,8 @@ static int RSA_eay_public_decrypt(int flen, const unsigned char *from, } if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) - if (!BN_MONT_CTX_set_locked - (&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx)) + if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, + rsa->n, ctx)) goto err; if (!rsa->meth->bn_mod_exp(ret, f, rsa->e, rsa->n, ctx, @@ -708,7 +708,7 @@ static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) BIGNUM *r1, *m1, *vrfy; BIGNUM local_dmp1, local_dmq1, local_c, local_r1; BIGNUM *dmp1, *dmq1, *c, *pr1; - int ret = 0; + int ret = 0, smooth = 0; BN_CTX_start(ctx); r1 = BN_CTX_get(ctx); @@ -737,20 +737,64 @@ static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) } if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) { - if (!BN_MONT_CTX_set_locked - (&rsa->_method_mod_p, CRYPTO_LOCK_RSA, p, ctx)) + if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_p, CRYPTO_LOCK_RSA, + p, ctx)) goto err; - if (!BN_MONT_CTX_set_locked - (&rsa->_method_mod_q, CRYPTO_LOCK_RSA, q, ctx)) + if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_q, CRYPTO_LOCK_RSA, + q, ctx)) goto err; + + smooth = (rsa->meth->bn_mod_exp == BN_mod_exp_mont) + && (BN_num_bits(q) == BN_num_bits(p)); } } if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) - if (!BN_MONT_CTX_set_locked - (&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx)) + if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, + rsa->n, ctx)) + goto err; + + if (smooth) { + /* + * Conversion from Montgomery domain, a.k.a. Montgomery reduction, + * accepts values in [0-m*2^w) range. w is m's bit width rounded up + * to limb width. So that at the very least if |I| is fully reduced, + * i.e. less than p*q, we can count on from-to round to perform + * below modulo operations on |I|. Unlike BN_mod it's constant time. + */ + if (/* m1 = I moq q */ + !bn_from_mont_fixed_top(m1, I, rsa->_method_mod_q, ctx) + || !bn_to_mont_fixed_top(m1, m1, rsa->_method_mod_q, ctx) + /* m1 = m1^dmq1 mod q */ + || !BN_mod_exp_mont_consttime(m1, m1, rsa->dmq1, rsa->q, ctx, + rsa->_method_mod_q) + /* r1 = I mod p */ + || !bn_from_mont_fixed_top(r1, I, rsa->_method_mod_p, ctx) + || !bn_to_mont_fixed_top(r1, r1, rsa->_method_mod_p, ctx) + /* r1 = r1^dmp1 mod p */ + || !BN_mod_exp_mont_consttime(r1, r1, rsa->dmp1, rsa->p, ctx, + rsa->_method_mod_p) + /* r1 = (r1 - m1) mod p */ + /* + * bn_mod_sub_fixed_top is not regular modular subtraction, + * it can tolerate subtrahend to be larger than modulus, but + * not bit-wise wider. This makes up for uncommon q>p case, + * when |m1| can be larger than |rsa->p|. + */ + || !bn_mod_sub_fixed_top(r1, r1, m1, rsa->p) + + /* r1 = r1 * iqmp mod p */ + || !bn_to_mont_fixed_top(r1, r1, rsa->_method_mod_p, ctx) + || !bn_mul_mont_fixed_top(r1, r1, rsa->iqmp, rsa->_method_mod_p, + ctx) + /* r0 = r1 * q + m1 */ + || !bn_mul_fixed_top(r0, r1, rsa->q, ctx) + || !bn_mod_add_fixed_top(r0, r0, m1, rsa->n)) goto err; + goto tail; + } + /* compute I mod q */ if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) { c = &local_c; @@ -828,10 +872,18 @@ static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) if (!BN_add(r0, r1, m1)) goto err; + tail: if (rsa->e && rsa->n) { - if (!rsa->meth->bn_mod_exp(vrfy, r0, rsa->e, rsa->n, ctx, - rsa->_method_mod_n)) - goto err; + if (rsa->meth->bn_mod_exp == BN_mod_exp_mont) { + if (!BN_mod_exp_mont(vrfy, r0, rsa->e, rsa->n, ctx, + rsa->_method_mod_n)) + goto err; + } else { + bn_correct_top(r0); + if (!rsa->meth->bn_mod_exp(vrfy, r0, rsa->e, rsa->n, ctx, + rsa->_method_mod_n)) + goto err; + } /* * If 'I' was greater than (or equal to) rsa->n, the operation will * be equivalent to using 'I mod n'. However, the result of the @@ -840,6 +892,11 @@ static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) */ if (!BN_sub(vrfy, vrfy, I)) goto err; + if (BN_is_zero(vrfy)) { + bn_correct_top(r0); + ret = 1; + goto err; /* not actually error */ + } if (!BN_mod(vrfy, vrfy, rsa->n, ctx)) goto err; if (BN_is_negative(vrfy)) @@ -865,6 +922,15 @@ static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) goto err; } } + /* + * It's unfortunate that we have to bn_correct_top(r0). What hopefully + * saves the day is that correction is highly unlike, and private key + * operations are customarily performed on blinded message. Which means + * that attacker won't observe correlation with chosen plaintext. + * Secondly, remaining code would still handle it in same computational + * time and even conceal memory access pattern around corrected top. + */ + bn_correct_top(r0); ret = 1; err: BN_CTX_end(ctx); diff --git a/crypto/ui/ui_openssl.c b/crypto/ui/ui_openssl.c index 1ad0cfc5b873..4b4eb81a5e66 100644 --- a/crypto/ui/ui_openssl.c +++ b/crypto/ui/ui_openssl.c @@ -509,6 +509,24 @@ static int open_console(UI *ui) is_a_tty = 0; else # endif +# ifdef ENXIO + /* + * Solaris can return ENXIO. + * This should be ok + */ + if (errno == ENXIO) + is_a_tty = 0; + else +# endif +# ifdef EIO + /* + * Linux can return EIO. + * This should be ok + */ + if (errno == EIO) + is_a_tty = 0; + else +# endif # ifdef ENODEV /* * MacOS X returns ENODEV (Operation not supported by device), diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c index 6f0209a275ef..92120763838e 100644 --- a/crypto/x509/by_dir.c +++ b/crypto/x509/by_dir.c @@ -128,7 +128,7 @@ static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, switch (cmd) { case X509_L_ADD_DIR: if (argl == X509_FILETYPE_DEFAULT) { - dir = (char *)getenv(X509_get_default_cert_dir_env()); + dir = (char *)ossl_safe_getenv(X509_get_default_cert_dir_env()); if (dir) ret = add_cert_dir(ld, dir, X509_FILETYPE_PEM); else diff --git a/crypto/x509/by_file.c b/crypto/x509/by_file.c index 82ce4e8d87c3..e6d0e6e1a644 100644 --- a/crypto/x509/by_file.c +++ b/crypto/x509/by_file.c @@ -97,7 +97,8 @@ static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, switch (cmd) { case X509_L_FILE_LOAD: if (argl == X509_FILETYPE_DEFAULT) { - file = getenv(X509_get_default_cert_file_env()); + file = ossl_safe_getenv(X509_get_default_cert_file_env()); + if (file) ok = (X509_load_cert_crl_file(ctx, file, X509_FILETYPE_PEM) != 0); diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index 869460d7cdba..da778d47b1cc 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -621,7 +621,7 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) * A hack to keep people who don't want to modify their software * happy */ - if (getenv("OPENSSL_ALLOW_PROXY_CERTS")) + if (ossl_safe_getenv("OPENSSL_ALLOW_PROXY_CERTS")) allow_proxy_certs = 1; purpose = ctx->param->purpose; } @@ -694,10 +694,9 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) goto end; } } - /* Check pathlen if not self issued */ - if ((i > 1) && !(x->ex_flags & EXFLAG_SI) - && (x->ex_pathlen != -1) - && (plen > (x->ex_pathlen + proxy_path_length + 1))) { + /* Check pathlen */ + if ((i > 1) && (x->ex_pathlen != -1) + && (plen > (x->ex_pathlen + proxy_path_length))) { ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED; ctx->error_depth = i; ctx->current_cert = x; @@ -705,8 +704,8 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) if (!ok) goto end; } - /* Increment path length if not self issued */ - if (!(x->ex_flags & EXFLAG_SI)) + /* Increment path length if not a self issued intermediate CA */ + if (i > 0 && (x->ex_flags & EXFLAG_SI) == 0) plen++; /* * If this certificate is a proxy certificate, the next certificate diff --git a/crypto/x509v3/v3_purp.c b/crypto/x509v3/v3_purp.c index 7080a51c4c5b..6d3aa8f731db 100644 --- a/crypto/x509v3/v3_purp.c +++ b/crypto/x509v3/v3_purp.c @@ -396,12 +396,8 @@ static void x509v3_cache_extensions(X509 *x) ASN1_BIT_STRING *ns; EXTENDED_KEY_USAGE *extusage; X509_EXTENSION *ex; - int i; - if (x->ex_flags & EXFLAG_SET) - return; - CRYPTO_w_lock(CRYPTO_LOCK_X509); if (x->ex_flags & EXFLAG_SET) { CRYPTO_w_unlock(CRYPTO_LOCK_X509); |
