aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2016-08-29 02:21:50 +0900
committerKazuki Yamaguchi <k@rhe.jp>2016-08-29 02:21:50 +0900
commitfbb5b7a6aee9a2afb7feb98885abedf066639f8a (patch)
tree26bb5e78bd5c14b1701b8a9ad3a6d381ce9bdc76
parent814931e32985229c74c5309f805d62a859fa00a8 (diff)
parent7fb82d06746f7503323a7846448e095bf8f5ef9e (diff)
downloadopenssl-OpenSSL_1_0_2-stable.tar.gz
Merge branch 'OpenSSL_1_0_2-stable' of https://github.com/openssl/openssl into OpenSSL_1_0_2-stableOpenSSL_1_0_2-stable
* 'OpenSSL_1_0_2-stable' of https://github.com/openssl/openssl: (57 commits) SRP_create_verifier does not check for NULL before OPENSSL_cleanse Improve the definition of STITCHED_CALL in e_rc4_hmac_md5.c Fix a few leaks in X509_REQ_to_X509. Fix a possible leak on NETSCAPE_SPKI_verify failure. Add basic test for Cisco DTLS1_BAD_VER and record replay handling Fix ubsan 'left shift of negative value -1' error in satsub64be() Fix SSL_export_keying_material() for DTLS1_BAD_VER Fix the no-tls1 option ec/asm/ecp_nistz256-x86_64.pl: /cmovb/cmovc/ as nasm doesn't recognize cmovb. ec/ecp_nistz256: harmonize is_infinity with ec_GFp_simple_is_at_infinity. ec/asm/ecp_nistz256-x86_64.pl: addition to perform stricter reduction. Always use session_ctx when removing a session Avoid overflow in MDC2_Update() SWEET32 (CVE-2016-2183): Move DES from HIGH to MEDIUM Fix no-ec Sanity check ticket length. mk1mf: dtlstest needs ssltestlib, include it with a hack Don't check for malloc failure twice. Fix overflow check in BN_bn2dec() RT2676: Reject RSA eponent if even or 1 VMS: Use strict refdef extern model when building library object files ...
-rw-r--r--.gitignore1
-rw-r--r--CHANGES4
-rwxr-xr-xConfigure14
-rw-r--r--apps/apps.c3
-rw-r--r--apps/ca.c23
-rw-r--r--apps/req.c7
-rw-r--r--apps/speed.c4
-rw-r--r--apps/srp.c2
-rw-r--r--crypto/asn1/a_bytes.c58
-rw-r--r--crypto/asn1/a_object.c8
-rw-r--r--crypto/asn1/a_set.c9
-rw-r--r--crypto/asn1/asn1_lib.c2
-rw-r--r--crypto/asn1/asn_mime.c2
-rw-r--r--crypto/asn1/f_enum.c4
-rw-r--r--crypto/asn1/f_int.c4
-rw-r--r--crypto/asn1/f_string.c4
-rw-r--r--crypto/asn1/tasn_prn.c2
-rw-r--r--crypto/bio/bss_rtcp.c2
-rwxr-xr-xcrypto/bn/asm/x86-mont.pl41
-rwxr-xr-xcrypto/bn/asm/x86_64-mont.pl185
-rwxr-xr-xcrypto/bn/asm/x86_64-mont5.pl227
-rw-r--r--crypto/bn/bn_print.c12
-rw-r--r--crypto/conf/conf_mod.c4
-rw-r--r--crypto/crypto-lib.com2
-rw-r--r--crypto/ec/Makefile2
-rwxr-xr-xcrypto/ec/asm/ecp_nistz256-x86_64.pl139
-rw-r--r--crypto/ec/ecp_nistz256.c125
-rw-r--r--crypto/engine/eng_cryptodev.c6
-rw-r--r--crypto/evp/e_rc4_hmac_md5.c2
-rwxr-xr-x[-rw-r--r--]crypto/evp/evp_test.c4
-rw-r--r--crypto/evp/openbsd_hw.c22
-rw-r--r--crypto/jpake/jpake.c4
-rw-r--r--crypto/mdc2/mdc2dgst.c2
-rw-r--r--crypto/mem.c20
-rwxr-xr-x[-rw-r--r--]crypto/o_time.c73
-rw-r--r--crypto/pem/pem.h6
-rw-r--r--crypto/pem/pem_err.c3
-rw-r--r--crypto/pem/pvkfmt.c7
-rw-r--r--crypto/pkcs12/p12_utl.c4
-rw-r--r--crypto/pkcs7/pk7_doit.c2
-rwxr-xr-x[-rw-r--r--]crypto/rand/rand_vms.c123
-rw-r--r--crypto/rand/randfile.c21
-rw-r--r--crypto/rsa/rsa_chk.c89
-rw-r--r--crypto/rsa/rsa_pmeth.c4
-rwxr-xr-xcrypto/sha/asm/sha1-x86_64.pl4
-rw-r--r--crypto/srp/srp_vfy.c3
-rw-r--r--crypto/ts/ts.h3
-rw-r--r--crypto/ts/ts_rsp_verify.c4
-rw-r--r--crypto/ui/ui_lib.c2
-rw-r--r--crypto/x509/by_dir.c4
-rw-r--r--crypto/x509/x509_r2x.c14
-rw-r--r--crypto/x509/x509_vfy.c2
-rw-r--r--crypto/x509v3/v3_alt.c2
-rw-r--r--doc/apps/cms.pod3
-rw-r--r--doc/apps/smime.pod3
-rw-r--r--doc/crypto/OBJ_nid2obj.pod4
-rw-r--r--engines/ccgost/gost2001.c10
-rw-r--r--engines/ccgost/gost2001_keyx.c2
-rw-r--r--engines/ccgost/gost94_keyx.c2
-rw-r--r--engines/ccgost/gost_ameth.c14
-rw-r--r--engines/ccgost/gost_pmeth.c4
-rw-r--r--engines/e_4758cca.c8
-rw-r--r--engines/e_aep.c3
-rw-r--r--engines/e_capi.c13
-rw-r--r--engines/e_chil.c33
-rw-r--r--ssl/Makefile2
-rw-r--r--ssl/bad_dtls_test.c923
-rw-r--r--ssl/d1_both.c36
-rw-r--r--ssl/d1_clnt.c1
-rw-r--r--ssl/d1_lib.c37
-rw-r--r--ssl/d1_pkt.c152
-rw-r--r--ssl/d1_srvr.c3
-rw-r--r--ssl/dtlstest.c147
-rw-r--r--ssl/s3_clnt.c4
-rw-r--r--ssl/s3_enc.c4
-rw-r--r--ssl/s3_lib.c34
-rw-r--r--ssl/s3_pkt.c4
-rw-r--r--ssl/ssl-lib.com2
-rw-r--r--ssl/ssl.h1
-rw-r--r--ssl/ssl_ciph.c5
-rw-r--r--ssl/ssl_err.c4
-rw-r--r--ssl/ssl_lib.c2
-rw-r--r--ssl/ssl_locl.h3
-rw-r--r--ssl/ssl_sess.c6
-rw-r--r--ssl/ssltest.c3
-rw-r--r--ssl/sslv2conftest.c2
-rw-r--r--ssl/t1_lib.c13
-rw-r--r--test/Makefile89
-rw-r--r--test/maketests.com31
-rw-r--r--test/ssltestlib.c687
-rw-r--r--test/ssltestlib.h36
-rw-r--r--test/tests.com29
-rwxr-xr-xutil/mk1mf.pl5
93 files changed, 3082 insertions, 602 deletions
diff --git a/.gitignore b/.gitignore
index 36c3a37507..cf8877916f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,6 +31,7 @@
!/test/igetest.c
!/test/r160test.c
!/test/fips_algvs.c
+!/test/ssltestlib.c
/test/*.ss
/test/*.srl
diff --git a/CHANGES b/CHANGES
index c3d3d7aab1..6502fc3efc 100644
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,10 @@
*)
+ *) In order to mitigate the SWEET32 attack (CVE-2016-2183),
+ the DES ciphers were moved from HIGH to MEDIUM.
+ [Rich Salz]
+
Changes between 1.0.2g and 1.0.2h [3 May 2016]
*) Prevent padding oracle in AES-NI CBC MAC check
diff --git a/Configure b/Configure
index 997a751894..2b8880e73a 100755
--- a/Configure
+++ b/Configure
@@ -1083,11 +1083,6 @@ if (defined($disabled{"md5"}) || defined($disabled{"sha"})
$disabled{"tls1"} = "forced";
}
-if (defined($disabled{"tls1"}))
- {
- $disabled{"tlsext"} = "forced";
- }
-
if (defined($disabled{"ec"}) || defined($disabled{"dsa"})
|| defined($disabled{"dh"}))
{
@@ -1564,8 +1559,15 @@ $cpuid_obj="mem_clr.o" unless ($cpuid_obj =~ /\.o$/);
$des_obj=$des_enc unless ($des_obj =~ /\.o$/);
$bf_obj=$bf_enc unless ($bf_obj =~ /\.o$/);
$cast_obj=$cast_enc unless ($cast_obj =~ /\.o$/);
-$rc4_obj=$rc4_enc unless ($rc4_obj =~ /\.o$/);
$rc5_obj=$rc5_enc unless ($rc5_obj =~ /\.o$/);
+if ($rc4_obj =~ /\.o$/)
+ {
+ $cflags.=" -DRC4_ASM";
+ }
+else
+ {
+ $rc4_obj=$rc4_enc;
+ }
if ($sha1_obj =~ /\.o$/)
{
# $sha1_obj=$sha1_enc;
diff --git a/apps/apps.c b/apps/apps.c
index 0385490306..08ddbc4db8 100644
--- a/apps/apps.c
+++ b/apps/apps.c
@@ -215,7 +215,8 @@ int args_from_file(char *file, int *argc, char **argv[])
if (arg != NULL)
OPENSSL_free(arg);
arg = (char **)OPENSSL_malloc(sizeof(char *) * (i * 2));
-
+ if (arg == NULL)
+ return 0;
*argv = arg;
num = 0;
p = buf;
diff --git a/apps/ca.c b/apps/ca.c
index 0b66095b83..a0ec5838fa 100644
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -2103,25 +2103,23 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
goto err;
/* We now just add it to the database */
- row[DB_type] = (char *)OPENSSL_malloc(2);
-
tm = X509_get_notAfter(ret);
- row[DB_exp_date] = (char *)OPENSSL_malloc(tm->length + 1);
- memcpy(row[DB_exp_date], tm->data, tm->length);
- row[DB_exp_date][tm->length] = '\0';
-
- row[DB_rev_date] = NULL;
-
- /* row[DB_serial] done already */
- row[DB_file] = (char *)OPENSSL_malloc(8);
+ row[DB_type] = OPENSSL_malloc(2);
+ row[DB_exp_date] = OPENSSL_malloc(tm->length + 1);
+ row[DB_rev_date] = OPENSSL_malloc(1);
+ row[DB_file] = OPENSSL_malloc(8);
row[DB_name] = X509_NAME_oneline(X509_get_subject_name(ret), NULL, 0);
-
if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
+ (row[DB_rev_date] == NULL) ||
(row[DB_file] == NULL) || (row[DB_name] == NULL)) {
BIO_printf(bio_err, "Memory allocation failure\n");
goto err;
}
- BUF_strlcpy(row[DB_file], "unknown", 8);
+
+ memcpy(row[DB_exp_date], tm->data, tm->length);
+ row[DB_exp_date][tm->length] = '\0';
+ row[DB_rev_date][0] = '\0';
+ strcpy(row[DB_file], "unknown");
row[DB_type][0] = 'V';
row[DB_type][1] = '\0';
@@ -2307,6 +2305,7 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey,
j = NETSCAPE_SPKI_verify(spki, pktmp);
if (j <= 0) {
+ EVP_PKEY_free(pktmp);
BIO_printf(bio_err,
"signature verification failed on SPKAC public key\n");
goto err;
diff --git a/apps/req.c b/apps/req.c
index 46255f5fe6..d1411c91bb 100644
--- a/apps/req.c
+++ b/apps/req.c
@@ -332,9 +332,10 @@ int MAIN(int argc, char **argv)
subject = 1;
else if (strcmp(*argv, "-text") == 0)
text = 1;
- else if (strcmp(*argv, "-x509") == 0)
+ else if (strcmp(*argv, "-x509") == 0) {
+ newreq = 1;
x509 = 1;
- else if (strcmp(*argv, "-asn1-kludge") == 0)
+ } else if (strcmp(*argv, "-asn1-kludge") == 0)
kludge = 1;
else if (strcmp(*argv, "-no-asn1-kludge") == 0)
kludge = 0;
@@ -756,7 +757,7 @@ int MAIN(int argc, char **argv)
}
}
- if (newreq || x509) {
+ if (newreq) {
if (pkey == NULL) {
BIO_printf(bio_err, "you need to specify a private key\n");
goto end;
diff --git a/apps/speed.c b/apps/speed.c
index 95adcc19cc..b862868eac 100644
--- a/apps/speed.c
+++ b/apps/speed.c
@@ -2614,6 +2614,10 @@ static int do_multi(int multi)
static char sep[] = ":";
fds = malloc(multi * sizeof *fds);
+ if (fds == NULL) {
+ fprintf(stderr, "Out of memory in speed (do_multi)\n");
+ exit(1);
+ }
for (n = 0; n < multi; ++n) {
if (pipe(fd) == -1) {
fprintf(stderr, "pipe failure\n");
diff --git a/apps/srp.c b/apps/srp.c
index c0ff4171ca..c75052f38d 100644
--- a/apps/srp.c
+++ b/apps/srp.c
@@ -765,4 +765,6 @@ int MAIN(int argc, char **argv)
OPENSSL_EXIT(ret);
}
+#else
+static void *dummy = &dummy;
#endif
diff --git a/crypto/asn1/a_bytes.c b/crypto/asn1/a_bytes.c
index 385b53986a..65e5394664 100644
--- a/crypto/asn1/a_bytes.c
+++ b/crypto/asn1/a_bytes.c
@@ -60,7 +60,12 @@
#include "cryptlib.h"
#include <openssl/asn1.h>
-static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c);
+static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c,
+ int depth);
+static ASN1_STRING *int_d2i_ASN1_bytes(ASN1_STRING **a,
+ const unsigned char **pp, long length,
+ int Ptag, int Pclass, int depth,
+ int *perr);
/*
* type is a 'bitmap' of acceptable string types.
*/
@@ -99,7 +104,7 @@ ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a, const unsigned char **pp,
ret = (*a);
if (len != 0) {
- s = (unsigned char *)OPENSSL_malloc((int)len + 1);
+ s = OPENSSL_malloc((int)len + 1);
if (s == NULL) {
i = ERR_R_MALLOC_FAILURE;
goto err;
@@ -154,15 +159,38 @@ int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass)
return (r);
}
+/*
+ * Maximum recursion depth of d2i_ASN1_bytes(): much more than should be
+ * encountered in pratice.
+ */
+
+#define ASN1_BYTES_MAXDEPTH 20
+
ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
long length, int Ptag, int Pclass)
{
+ int err = 0;
+ ASN1_STRING *s = int_d2i_ASN1_bytes(a, pp, length, Ptag, Pclass, 0, &err);
+ if (err != 0)
+ ASN1err(ASN1_F_D2I_ASN1_BYTES, err);
+ return s;
+}
+
+static ASN1_STRING *int_d2i_ASN1_bytes(ASN1_STRING **a,
+ const unsigned char **pp, long length,
+ int Ptag, int Pclass,
+ int depth, int *perr)
+{
ASN1_STRING *ret = NULL;
const unsigned char *p;
unsigned char *s;
long len;
int inf, tag, xclass;
- int i = 0;
+
+ if (depth > ASN1_BYTES_MAXDEPTH) {
+ *perr = ASN1_R_NESTED_ASN1_STRING;
+ return NULL;
+ }
if ((a == NULL) || ((*a) == NULL)) {
if ((ret = ASN1_STRING_new()) == NULL)
@@ -173,18 +201,19 @@ ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
p = *pp;
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
if (inf & 0x80) {
- i = ASN1_R_BAD_OBJECT_HEADER;
+ *perr = ASN1_R_BAD_OBJECT_HEADER;
goto err;
}
if (tag != Ptag) {
- i = ASN1_R_WRONG_TAG;
+ *perr = ASN1_R_WRONG_TAG;
goto err;
}
if (inf & V_ASN1_CONSTRUCTED) {
ASN1_const_CTX c;
+ c.error = 0;
c.pp = pp;
c.p = p;
c.inf = inf;
@@ -192,17 +221,18 @@ ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
c.tag = Ptag;
c.xclass = Pclass;
c.max = (length == 0) ? 0 : (p + length);
- if (!asn1_collate_primitive(ret, &c))
+ if (!asn1_collate_primitive(ret, &c, depth)) {
+ *perr = c.error;
goto err;
- else {
+ } else {
p = c.p;
}
} else {
if (len != 0) {
if ((ret->length < len) || (ret->data == NULL)) {
- s = (unsigned char *)OPENSSL_malloc((int)len + 1);
+ s = OPENSSL_malloc((int)len + 1);
if (s == NULL) {
- i = ERR_R_MALLOC_FAILURE;
+ *perr = ERR_R_MALLOC_FAILURE;
goto err;
}
if (ret->data != NULL)
@@ -230,7 +260,6 @@ ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
err:
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
ASN1_STRING_free(ret);
- ASN1err(ASN1_F_D2I_ASN1_BYTES, i);
return (NULL);
}
@@ -242,7 +271,8 @@ ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
* There have been a few bug fixes for this function from Paul Keogh
* <paul.keogh@sse.ie>, many thanks to him
*/
-static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c)
+static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c,
+ int depth)
{
ASN1_STRING *os = NULL;
BUF_MEM b;
@@ -270,9 +300,8 @@ static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c)
}
c->q = c->p;
- if (d2i_ASN1_bytes(&os, &c->p, c->max - c->p, c->tag, c->xclass)
- == NULL) {
- c->error = ERR_R_ASN1_LIB;
+ if (int_d2i_ASN1_bytes(&os, &c->p, c->max - c->p, c->tag, c->xclass,
+ depth + 1, &c->error) == NULL) {
goto err;
}
@@ -297,7 +326,6 @@ static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c)
ASN1_STRING_free(os);
return (1);
err:
- ASN1err(ASN1_F_ASN1_COLLATE_PRIMITIVE, c->error);
if (os != NULL)
ASN1_STRING_free(os);
if (b.data != NULL)
diff --git a/crypto/asn1/a_object.c b/crypto/asn1/a_object.c
index fba9f66454..229a40ffa3 100644
--- a/crypto/asn1/a_object.c
+++ b/crypto/asn1/a_object.c
@@ -174,8 +174,12 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
if (!tmp)
goto err;
}
- while (blsize--)
- tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L);
+ while (blsize--) {
+ BN_ULONG t = BN_div_word(bl, 0x80L);
+ if (t == (BN_ULONG)-1)
+ goto err;
+ tmp[i++] = (unsigned char)t;
+ }
} else {
for (;;) {
diff --git a/crypto/asn1/a_set.c b/crypto/asn1/a_set.c
index bf3f971889..5fb5865575 100644
--- a/crypto/asn1/a_set.c
+++ b/crypto/asn1/a_set.c
@@ -57,6 +57,7 @@
*/
#include <stdio.h>
+#include <limits.h>
#include "cryptlib.h"
#include <openssl/asn1_mac.h>
@@ -98,10 +99,14 @@ int i2d_ASN1_SET(STACK_OF(OPENSSL_BLOCK) *a, unsigned char **pp,
if (a == NULL)
return (0);
- for (i = sk_OPENSSL_BLOCK_num(a) - 1; i >= 0; i--)
+ for (i = sk_OPENSSL_BLOCK_num(a) - 1; i >= 0; i--) {
+ int tmplen = i2d(sk_OPENSSL_BLOCK_value(a, i), NULL);
+ if (tmplen > INT_MAX - ret)
+ return -1;
ret += i2d(sk_OPENSSL_BLOCK_value(a, i), NULL);
+ }
r = ASN1_object_size(1, ret, ex_tag);
- if (pp == NULL)
+ if (pp == NULL || r == -1)
return (r);
p = *pp;
diff --git a/crypto/asn1/asn1_lib.c b/crypto/asn1/asn1_lib.c
index 80f5f2b014..e63e82a8b4 100644
--- a/crypto/asn1/asn1_lib.c
+++ b/crypto/asn1/asn1_lib.c
@@ -370,7 +370,7 @@ int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
else
len = strlen(data);
}
- if ((str->length < len) || (str->data == NULL)) {
+ if ((str->length <= len) || (str->data == NULL)) {
c = str->data;
if (c == NULL)
str->data = OPENSSL_malloc(len + 1);
diff --git a/crypto/asn1/asn_mime.c b/crypto/asn1/asn_mime.c
index 9fd5bef0fc..5170906c62 100644
--- a/crypto/asn1/asn_mime.c
+++ b/crypto/asn1/asn_mime.c
@@ -623,6 +623,8 @@ static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret)
if (bpart)
sk_BIO_push(parts, bpart);
bpart = BIO_new(BIO_s_mem());
+ if (bpart == NULL)
+ return 1;
BIO_set_mem_eof_return(bpart, 0);
} else if (eol)
BIO_write(bpart, "\r\n", 2);
diff --git a/crypto/asn1/f_enum.c b/crypto/asn1/f_enum.c
index 591c3b5781..94cd54dbee 100644
--- a/crypto/asn1/f_enum.c
+++ b/crypto/asn1/f_enum.c
@@ -160,8 +160,6 @@ int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size)
i * 2);
if (sp == NULL) {
ASN1err(ASN1_F_A2I_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE);
- if (s != NULL)
- OPENSSL_free(s);
goto err;
}
s = sp;
@@ -199,5 +197,7 @@ int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size)
err_sl:
ASN1err(ASN1_F_A2I_ASN1_ENUMERATED, ASN1_R_SHORT_LINE);
}
+ if (ret != 1)
+ OPENSSL_free(s);
return (ret);
}
diff --git a/crypto/asn1/f_int.c b/crypto/asn1/f_int.c
index 4a81f81c88..2bdc78d744 100644
--- a/crypto/asn1/f_int.c
+++ b/crypto/asn1/f_int.c
@@ -172,8 +172,6 @@ int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
sp = OPENSSL_realloc_clean(s, slen, num + i * 2);
if (sp == NULL) {
ASN1err(ASN1_F_A2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
- if (s != NULL)
- OPENSSL_free(s);
goto err;
}
s = sp;
@@ -211,5 +209,7 @@ int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
err_sl:
ASN1err(ASN1_F_A2I_ASN1_INTEGER, ASN1_R_SHORT_LINE);
}
+ if (ret != 1)
+ OPENSSL_free(s);
return (ret);
}
diff --git a/crypto/asn1/f_string.c b/crypto/asn1/f_string.c
index 6a6cf34714..0f7b9cfb11 100644
--- a/crypto/asn1/f_string.c
+++ b/crypto/asn1/f_string.c
@@ -166,8 +166,6 @@ int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
i * 2);
if (sp == NULL) {
ASN1err(ASN1_F_A2I_ASN1_STRING, ERR_R_MALLOC_FAILURE);
- if (s != NULL)
- OPENSSL_free(s);
goto err;
}
s = sp;
@@ -205,5 +203,7 @@ int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
err_sl:
ASN1err(ASN1_F_A2I_ASN1_STRING, ASN1_R_SHORT_LINE);
}
+ if (ret != 1)
+ OPENSSL_free(s);
return (ret);
}
diff --git a/crypto/asn1/tasn_prn.c b/crypto/asn1/tasn_prn.c
index 1dae46bc3d..f628caddbd 100644
--- a/crypto/asn1/tasn_prn.c
+++ b/crypto/asn1/tasn_prn.c
@@ -447,6 +447,8 @@ static int asn1_print_integer_ctx(BIO *out, ASN1_INTEGER *str,
char *s;
int ret = 1;
s = i2s_ASN1_INTEGER(NULL, str);
+ if (s == NULL)
+ return 0;
if (BIO_puts(out, s) <= 0)
ret = 0;
OPENSSL_free(s);
diff --git a/crypto/bio/bss_rtcp.c b/crypto/bio/bss_rtcp.c
index 09f14f48dc..5c98a8234d 100644
--- a/crypto/bio/bss_rtcp.c
+++ b/crypto/bio/bss_rtcp.c
@@ -170,6 +170,8 @@ static int rtcp_new(BIO *bi)
bi->num = 0;
bi->flags = 0;
bi->ptr = OPENSSL_malloc(sizeof(struct rpc_ctx));
+ if (bi->ptr == NULL)
+ return (0);
ctx = (struct rpc_ctx *)bi->ptr;
ctx->filled = 0;
ctx->pos = 0;
diff --git a/crypto/bn/asm/x86-mont.pl b/crypto/bn/asm/x86-mont.pl
index 89f4de61e8..1c4003efc2 100755
--- a/crypto/bn/asm/x86-mont.pl
+++ b/crypto/bn/asm/x86-mont.pl
@@ -63,27 +63,26 @@ $frame=32; # size of above frame rounded up to 16n
&lea ("esi",&wparam(0)); # put aside pointer to argument block
&lea ("edx",&wparam(1)); # load ap
- &mov ("ebp","esp"); # saved stack pointer!
&add ("edi",2); # extra two words on top of tp
&neg ("edi");
- &lea ("esp",&DWP(-$frame,"esp","edi",4)); # alloca($frame+4*(num+2))
+ &lea ("ebp",&DWP(-$frame,"esp","edi",4)); # future alloca($frame+4*(num+2))
&neg ("edi");
# minimize cache contention by arraning 2K window between stack
# pointer and ap argument [np is also position sensitive vector,
# but it's assumed to be near ap, as it's allocated at ~same
# time].
- &mov ("eax","esp");
+ &mov ("eax","ebp");
&sub ("eax","edx");
&and ("eax",2047);
- &sub ("esp","eax"); # this aligns sp and ap modulo 2048
+ &sub ("ebp","eax"); # this aligns sp and ap modulo 2048
- &xor ("edx","esp");
+ &xor ("edx","ebp");
&and ("edx",2048);
&xor ("edx",2048);
- &sub ("esp","edx"); # this splits them apart modulo 4096
+ &sub ("ebp","edx"); # this splits them apart modulo 4096
- &and ("esp",-64); # align to cache line
+ &and ("ebp",-64); # align to cache line
# Some OSes, *cough*-dows, insist on stack being "wired" to
# physical memory in strictly sequential manner, i.e. if stack
@@ -91,20 +90,28 @@ $frame=32; # size of above frame rounded up to 16n
# be punishable by SEGV. But page walking can do good even on
# other OSes, because it guarantees that villain thread hits
# the guard page before it can make damage to innocent one...
- &mov ("eax","ebp");
- &sub ("eax","esp");
+ &mov ("eax","esp");
+ &sub ("eax","ebp");
&and ("eax",-4096);
-&set_label("page_walk");
- &mov ("edx",&DWP(0,"esp","eax"));
- &sub ("eax",4096);
- &data_byte(0x2e);
- &jnc (&label("page_walk"));
+ &mov ("edx","esp"); # saved stack pointer!
+ &lea ("esp",&DWP(0,"ebp","eax"));
+ &mov ("eax",&DWP(0,"esp"));
+ &cmp ("esp","ebp");
+ &ja (&label("page_walk"));
+ &jmp (&label("page_walk_done"));
+
+&set_label("page_walk",16);
+ &lea ("esp",&DWP(-4096,"esp"));
+ &mov ("eax",&DWP(0,"esp"));
+ &cmp ("esp","ebp");
+ &ja (&label("page_walk"));
+&set_label("page_walk_done");
################################# load argument block...
&mov ("eax",&DWP(0*4,"esi"));# BN_ULONG *rp
&mov ("ebx",&DWP(1*4,"esi"));# const BN_ULONG *ap
&mov ("ecx",&DWP(2*4,"esi"));# const BN_ULONG *bp
- &mov ("edx",&DWP(3*4,"esi"));# const BN_ULONG *np
+ &mov ("ebp",&DWP(3*4,"esi"));# const BN_ULONG *np
&mov ("esi",&DWP(4*4,"esi"));# const BN_ULONG *n0
#&mov ("edi",&DWP(5*4,"esi"));# int num
@@ -112,11 +119,11 @@ $frame=32; # size of above frame rounded up to 16n
&mov ($_rp,"eax"); # ... save a copy of argument block
&mov ($_ap,"ebx");
&mov ($_bp,"ecx");
- &mov ($_np,"edx");
+ &mov ($_np,"ebp");
&mov ($_n0,"esi");
&lea ($num,&DWP(-3,"edi")); # num=num-1 to assist modulo-scheduling
#&mov ($_num,$num); # redundant as $num is not reused
- &mov ($_sp,"ebp"); # saved stack pointer!
+ &mov ($_sp,"edx"); # saved stack pointer!
if($sse2) {
$acc0="mm0"; # mmx register bank layout
diff --git a/crypto/bn/asm/x86_64-mont.pl b/crypto/bn/asm/x86_64-mont.pl
index 8fb6c994e1..044fd7ecc0 100755
--- a/crypto/bn/asm/x86_64-mont.pl
+++ b/crypto/bn/asm/x86_64-mont.pl
@@ -97,6 +97,8 @@ $code=<<___;
.type bn_mul_mont,\@function,6
.align 16
bn_mul_mont:
+ mov ${num}d,${num}d
+ mov %rsp,%rax
test \$3,${num}d
jnz .Lmul_enter
cmp \$8,${num}d
@@ -121,29 +123,36 @@ $code.=<<___;
push %r14
push %r15
- mov ${num}d,${num}d
- lea 2($num),%r10
+ neg $num
mov %rsp,%r11
- neg %r10
- lea (%rsp,%r10,8),%rsp # tp=alloca(8*(num+2))
- and \$-1024,%rsp # minimize TLB usage
+ lea -16(%rsp,$num,8),%r10 # future alloca(8*(num+2))
+ neg $num # restore $num
+ and \$-1024,%r10 # minimize TLB usage
- mov %r11,8(%rsp,$num,8) # tp[num+1]=%rsp
-.Lmul_body:
# Some OSes, *cough*-dows, insist on stack being "wired" to
# physical memory in strictly sequential manner, i.e. if stack
# allocation spans two pages, then reference to farmost one can
# be punishable by SEGV. But page walking can do good even on
# other OSes, because it guarantees that villain thread hits
# the guard page before it can make damage to innocent one...
- sub %rsp,%r11
+ sub %r10,%r11
and \$-4096,%r11
+ lea (%r10,%r11),%rsp
+ mov (%rsp),%r11
+ cmp %r10,%rsp
+ ja .Lmul_page_walk
+ jmp .Lmul_page_walk_done
+
+.align 16
.Lmul_page_walk:
- mov (%rsp,%r11),%r10
- sub \$4096,%r11
- .byte 0x66,0x2e # predict non-taken
- jnc .Lmul_page_walk
+ lea -4096(%rsp),%rsp
+ mov (%rsp),%r11
+ cmp %r10,%rsp
+ ja .Lmul_page_walk
+.Lmul_page_walk_done:
+ mov %rax,8(%rsp,$num,8) # tp[num+1]=%rsp
+.Lmul_body:
mov $bp,%r12 # reassign $bp
___
$bp="%r12";
@@ -314,13 +323,13 @@ $code.=<<___;
mov 8(%rsp,$num,8),%rsi # restore %rsp
mov \$1,%rax
- mov (%rsi),%r15
- mov 8(%rsi),%r14
- mov 16(%rsi),%r13
- mov 24(%rsi),%r12
- mov 32(%rsi),%rbp
- mov 40(%rsi),%rbx
- lea 48(%rsi),%rsp
+ mov -48(%rsi),%r15
+ mov -40(%rsi),%r14
+ mov -32(%rsi),%r13
+ mov -24(%rsi),%r12
+ mov -16(%rsi),%rbp
+ mov -8(%rsi),%rbx
+ lea (%rsi),%rsp
.Lmul_epilogue:
ret
.size bn_mul_mont,.-bn_mul_mont
@@ -332,6 +341,8 @@ $code.=<<___;
.type bn_mul4x_mont,\@function,6
.align 16
bn_mul4x_mont:
+ mov ${num}d,${num}d
+ mov %rsp,%rax
.Lmul4x_enter:
___
$code.=<<___ if ($addx);
@@ -347,23 +358,29 @@ $code.=<<___;
push %r14
push %r15
- mov ${num}d,${num}d
- lea 4($num),%r10
+ neg $num
mov %rsp,%r11
- neg %r10
- lea (%rsp,%r10,8),%rsp # tp=alloca(8*(num+4))
- and \$-1024,%rsp # minimize TLB usage
+ lea -32(%rsp,$num,8),%r10 # future alloca(8*(num+4))
+ neg $num # restore
+ and \$-1024,%r10 # minimize TLB usage
- mov %r11,8(%rsp,$num,8) # tp[num+1]=%rsp
-.Lmul4x_body:
- sub %rsp,%r11
+ sub %r10,%r11
and \$-4096,%r11
+ lea (%r10,%r11),%rsp
+ mov (%rsp),%r11
+ cmp %r10,%rsp
+ ja .Lmul4x_page_walk
+ jmp .Lmul4x_page_walk_done
+
.Lmul4x_page_walk:
- mov (%rsp,%r11),%r10
- sub \$4096,%r11
- .byte 0x2e # predict non-taken
- jnc .Lmul4x_page_walk
+ lea -4096(%rsp),%rsp
+ mov (%rsp),%r11
+ cmp %r10,%rsp
+ ja .Lmul4x_page_walk
+.Lmul4x_page_walk_done:
+ mov %rax,8(%rsp,$num,8) # tp[num+1]=%rsp
+.Lmul4x_body:
mov $rp,16(%rsp,$num,8) # tp[num+2]=$rp
mov %rdx,%r12 # reassign $bp
___
@@ -742,13 +759,13 @@ ___
$code.=<<___;
mov 8(%rsp,$num,8),%rsi # restore %rsp
mov \$1,%rax
- mov (%rsi),%r15
- mov 8(%rsi),%r14
- mov 16(%rsi),%r13
- mov 24(%rsi),%r12
- mov 32(%rsi),%rbp
- mov 40(%rsi),%rbx
- lea 48(%rsi),%rsp
+ mov -48(%rsi),%r15
+ mov -40(%rsi),%r14
+ mov -32(%rsi),%r13
+ mov -24(%rsi),%r12
+ mov -16(%rsi),%rbp
+ mov -8(%rsi),%rbx
+ lea (%rsi),%rsp
.Lmul4x_epilogue:
ret
.size bn_mul4x_mont,.-bn_mul4x_mont
@@ -778,14 +795,15 @@ $code.=<<___;
.type bn_sqr8x_mont,\@function,6
.align 32
bn_sqr8x_mont:
-.Lsqr8x_enter:
mov %rsp,%rax
+.Lsqr8x_enter:
push %rbx
push %rbp
push %r12
push %r13
push %r14
push %r15
+.Lsqr8x_prologue:
mov ${num}d,%r10d
shl \$3,${num}d # convert $num to bytes
@@ -798,33 +816,42 @@ bn_sqr8x_mont:
# do its job.
#
lea -64(%rsp,$num,2),%r11
+ mov %rsp,%rbp
mov ($n0),$n0 # *n0
sub $aptr,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lsqr8x_sp_alt
- sub %r11,%rsp # align with $aptr
- lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
+ sub %r11,%rbp # align with $aptr
+ lea -64(%rbp,$num,2),%rbp # future alloca(frame+2*$num)
jmp .Lsqr8x_sp_done
.align 32
.Lsqr8x_sp_alt:
lea 4096-64(,$num,2),%r10 # 4096-frame-2*$num
- lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
+ lea -64(%rbp,$num,2),%rbp # future alloca(frame+2*$num)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
- sub %r11,%rsp
+ sub %r11,%rbp
.Lsqr8x_sp_done:
- and \$-64,%rsp
- mov %rax,%r11
- sub %rsp,%r11
+ and \$-64,%rbp
+ mov %rsp,%r11
+ sub %rbp,%r11
and \$-4096,%r11
+ lea (%rbp,%r11),%rsp
+ mov (%rsp),%r10
+ cmp %rbp,%rsp
+ ja .Lsqr8x_page_walk
+ jmp .Lsqr8x_page_walk_done
+
+.align 16
.Lsqr8x_page_walk:
- mov (%rsp,%r11),%r10
- sub \$4096,%r11
- .byte 0x2e # predict non-taken
- jnc .Lsqr8x_page_walk
+ lea -4096(%rsp),%rsp
+ mov (%rsp),%r10
+ cmp %rbp,%rsp
+ ja .Lsqr8x_page_walk
+.Lsqr8x_page_walk_done:
mov $num,%r10
neg $num
@@ -948,30 +975,38 @@ $code.=<<___;
.type bn_mulx4x_mont,\@function,6
.align 32
bn_mulx4x_mont:
-.Lmulx4x_enter:
mov %rsp,%rax
+.Lmulx4x_enter:
push %rbx
push %rbp
push %r12
push %r13
push %r14
push %r15
+.Lmulx4x_prologue:
shl \$3,${num}d # convert $num to bytes
- .byte 0x67
xor %r10,%r10
sub $num,%r10 # -$num
mov ($n0),$n0 # *n0
- lea -72(%rsp,%r10),%rsp # alloca(frame+$num+8)
- and \$-128,%rsp
- mov %rax,%r11
- sub %rsp,%r11
+ lea -72(%rsp,%r10),%rbp # future alloca(frame+$num+8)
+ and \$-128,%rbp
+ mov %rsp,%r11
+ sub %rbp,%r11
and \$-4096,%r11
+ lea (%rbp,%r11),%rsp
+ mov (%rsp),%r10
+ cmp %rbp,%rsp
+ ja .Lmulx4x_page_walk
+ jmp .Lmulx4x_page_walk_done
+
+.align 16
.Lmulx4x_page_walk:
- mov (%rsp,%r11),%r10
- sub \$4096,%r11
- .byte 0x66,0x2e # predict non-taken
- jnc .Lmulx4x_page_walk
+ lea -4096(%rsp),%rsp
+ mov (%rsp),%r10
+ cmp %rbp,%rsp
+ ja .Lmulx4x_page_walk
+.Lmulx4x_page_walk_done:
lea ($bp,$num),%r10
##############################################################
@@ -1332,22 +1367,8 @@ mul_handler:
mov 192($context),%r10 # pull $num
mov 8(%rax,%r10,8),%rax # pull saved stack pointer
- lea 48(%rax),%rax
-
- mov -8(%rax),%rbx
- mov -16(%rax),%rbp
- mov -24(%rax),%r12
- mov -32(%rax),%r13
- mov -40(%rax),%r14
- mov -48(%rax),%r15
- mov %rbx,144($context) # restore context->Rbx
- mov %rbp,160($context) # restore context->Rbp
- mov %r12,216($context) # restore context->R12
- mov %r13,224($context) # restore context->R13
- mov %r14,232($context) # restore context->R14
- mov %r15,240($context) # restore context->R15
- jmp .Lcommon_seh_tail
+ jmp .Lcommon_pop_regs
.size mul_handler,.-mul_handler
.type sqr_handler,\@abi-omnipotent
@@ -1375,15 +1396,21 @@ sqr_handler:
cmp %r10,%rbx # context->Rip<.Lsqr_body
jb .Lcommon_seh_tail
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # body label
+ cmp %r10,%rbx # context->Rip>=.Lsqr_epilogue
+ jb .Lcommon_pop_regs
+
mov 152($context),%rax # pull context->Rsp
- mov 4(%r11),%r10d # HandlerData[1]
+ mov 8(%r11),%r10d # HandlerData[2]
lea (%rsi,%r10),%r10 # epilogue label
cmp %r10,%rbx # context->Rip>=.Lsqr_epilogue
jae .Lcommon_seh_tail
mov 40(%rax),%rax # pull saved stack pointer
+.Lcommon_pop_regs:
mov -8(%rax),%rbx
mov -16(%rax),%rbp
mov -24(%rax),%r12
@@ -1470,13 +1497,15 @@ $code.=<<___;
.LSEH_info_bn_sqr8x_mont:
.byte 9,0,0,0
.rva sqr_handler
- .rva .Lsqr8x_body,.Lsqr8x_epilogue # HandlerData[]
+ .rva .Lsqr8x_prologue,.Lsqr8x_body,.Lsqr8x_epilogue # HandlerData[]
+.align 8
___
$code.=<<___ if ($addx);
.LSEH_info_bn_mulx4x_mont:
.byte 9,0,0,0
.rva sqr_handler
- .rva .Lmulx4x_body,.Lmulx4x_epilogue # HandlerData[]
+ .rva .Lmulx4x_prologue,.Lmulx4x_body,.Lmulx4x_epilogue # HandlerData[]
+.align 8
___
}
diff --git a/crypto/bn/asm/x86_64-mont5.pl b/crypto/bn/asm/x86_64-mont5.pl
index 938e170818..f1fbb45b53 100755
--- a/crypto/bn/asm/x86_64-mont5.pl
+++ b/crypto/bn/asm/x86_64-mont5.pl
@@ -86,6 +86,8 @@ $code=<<___;
.type bn_mul_mont_gather5,\@function,6
.align 64
bn_mul_mont_gather5:
+ mov ${num}d,${num}d
+ mov %rsp,%rax
test \$7,${num}d
jnz .Lmul_enter
___
@@ -97,10 +99,7 @@ $code.=<<___;
.align 16
.Lmul_enter:
- mov ${num}d,${num}d
- mov %rsp,%rax
movd `($win64?56:8)`(%rsp),%xmm5 # load 7th argument
- lea .Linc(%rip),%r10
push %rbx
push %rbp
push %r12
@@ -108,26 +107,36 @@ $code.=<<___;
push %r14
push %r15
- lea 2($num),%r11
- neg %r11
- lea -264(%rsp,%r11,8),%rsp # tp=alloca(8*(num+2)+256+8)
- and \$-1024,%rsp # minimize TLB usage
+ neg $num
+ mov %rsp,%r11
+ lea -280(%rsp,$num,8),%r10 # future alloca(8*(num+2)+256+8)
+ neg $num # restore $num
+ and \$-1024,%r10 # minimize TLB usage
- mov %rax,8(%rsp,$num,8) # tp[num+1]=%rsp
-.Lmul_body:
# Some OSes, *cough*-dows, insist on stack being "wired" to
# physical memory in strictly sequential manner, i.e. if stack
# allocation spans two pages, then reference to farmost one can
# be punishable by SEGV. But page walking can do good even on
# other OSes, because it guarantees that villain thread hits
# the guard page before it can make damage to innocent one...
- sub %rsp,%rax
- and \$-4096,%rax
+ sub %r10,%r11
+ and \$-4096,%r11
+ lea (%r10,%r11),%rsp
+ mov (%rsp),%r11
+ cmp %r10,%rsp
+ ja .Lmul_page_walk
+ jmp .Lmul_page_walk_done
+
.Lmul_page_walk:
- mov (%rsp,%rax),%r11
- sub \$4096,%rax
- .byte 0x2e # predict non-taken
- jnc .Lmul_page_walk
+ lea -4096(%rsp),%rsp
+ mov (%rsp),%r11
+ cmp %r10,%rsp
+ ja .Lmul_page_walk
+.Lmul_page_walk_done:
+
+ lea .Linc(%rip),%r10
+ mov %rax,8(%rsp,$num,8) # tp[num+1]=%rsp
+.Lmul_body:
lea 128($bp),%r12 # reassign $bp (+size optimization)
___
@@ -433,6 +442,8 @@ $code.=<<___;
.type bn_mul4x_mont_gather5,\@function,6
.align 32
bn_mul4x_mont_gather5:
+ .byte 0x67
+ mov %rsp,%rax
.Lmul4x_enter:
___
$code.=<<___ if ($addx);
@@ -441,14 +452,13 @@ $code.=<<___ if ($addx);
je .Lmulx4x_enter
___
$code.=<<___;
- .byte 0x67
- mov %rsp,%rax
push %rbx
push %rbp
push %r12
push %r13
push %r14
push %r15
+.Lmul4x_prologue:
.byte 0x67
shl \$3,${num}d # convert $num to bytes
@@ -465,32 +475,40 @@ $code.=<<___;
# calculated from 7th argument, the index.]
#
lea -320(%rsp,$num,2),%r11
+ mov %rsp,%rbp
sub $rp,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lmul4xsp_alt
- sub %r11,%rsp # align with $rp
- lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256)
+ sub %r11,%rbp # align with $rp
+ lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*num*8+256)
jmp .Lmul4xsp_done
.align 32
.Lmul4xsp_alt:
lea 4096-320(,$num,2),%r10
- lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256)
+ lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*num*8+256)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
- sub %r11,%rsp
+ sub %r11,%rbp
.Lmul4xsp_done:
- and \$-64,%rsp
- mov %rax,%r11
- sub %rsp,%r11
+ and \$-64,%rbp
+ mov %rsp,%r11
+ sub %rbp,%r11
and \$-4096,%r11
+ lea (%rbp,%r11),%rsp
+ mov (%rsp),%r10
+ cmp %rbp,%rsp
+ ja .Lmul4x_page_walk
+ jmp .Lmul4x_page_walk_done
+
.Lmul4x_page_walk:
- mov (%rsp,%r11),%r10
- sub \$4096,%r11
- .byte 0x2e # predict non-taken
- jnc .Lmul4x_page_walk
+ lea -4096(%rsp),%rsp
+ mov (%rsp),%r10
+ cmp %rbp,%rsp
+ ja .Lmul4x_page_walk
+.Lmul4x_page_walk_done:
neg $num
@@ -1034,6 +1052,7 @@ $code.=<<___;
.type bn_power5,\@function,6
.align 32
bn_power5:
+ mov %rsp,%rax
___
$code.=<<___ if ($addx);
mov OPENSSL_ia32cap_P+8(%rip),%r11d
@@ -1042,13 +1061,13 @@ $code.=<<___ if ($addx);
je .Lpowerx5_enter
___
$code.=<<___;
- mov %rsp,%rax
push %rbx
push %rbp
push %r12
push %r13
push %r14
push %r15
+.Lpower5_prologue:
shl \$3,${num}d # convert $num to bytes
lea ($num,$num,2),%r10d # 3*$num
@@ -1063,32 +1082,40 @@ $code.=<<___;
# calculated from 7th argument, the index.]
#
lea -320(%rsp,$num,2),%r11
+ mov %rsp,%rbp
sub $rptr,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lpwr_sp_alt
- sub %r11,%rsp # align with $aptr
- lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256)
+ sub %r11,%rbp # align with $aptr
+ lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*num*8+256)
jmp .Lpwr_sp_done
.align 32
.Lpwr_sp_alt:
lea 4096-320(,$num,2),%r10
- lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256)
+ lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*num*8+256)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
- sub %r11,%rsp
+ sub %r11,%rbp
.Lpwr_sp_done:
- and \$-64,%rsp
- mov %rax,%r11
- sub %rsp,%r11
+ and \$-64,%rbp
+ mov %rsp,%r11
+ sub %rbp,%r11
and \$-4096,%r11
+ lea (%rbp,%r11),%rsp
+ mov (%rsp),%r10
+ cmp %rbp,%rsp
+ ja .Lpwr_page_walk
+ jmp .Lpwr_page_walk_done
+
.Lpwr_page_walk:
- mov (%rsp,%r11),%r10
- sub \$4096,%r11
- .byte 0x2e # predict non-taken
- jnc .Lpwr_page_walk
+ lea -4096(%rsp),%rsp
+ mov (%rsp),%r10
+ cmp %rbp,%rsp
+ ja .Lpwr_page_walk
+.Lpwr_page_walk_done:
mov $num,%r10
neg $num
@@ -2028,6 +2055,7 @@ bn_from_mont8x:
push %r13
push %r14
push %r15
+.Lfrom_prologue:
shl \$3,${num}d # convert $num to bytes
lea ($num,$num,2),%r10 # 3*$num in bytes
@@ -2042,32 +2070,40 @@ bn_from_mont8x:
# last operation, we use the opportunity to cleanse it.
#
lea -320(%rsp,$num,2),%r11
+ mov %rsp,%rbp
sub $rptr,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lfrom_sp_alt
- sub %r11,%rsp # align with $aptr
- lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
+ sub %r11,%rbp # align with $aptr
+ lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*$num*8+256)
jmp .Lfrom_sp_done
.align 32
.Lfrom_sp_alt:
lea 4096-320(,$num,2),%r10
- lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
+ lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*$num*8+256)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
- sub %r11,%rsp
+ sub %r11,%rbp
.Lfrom_sp_done:
- and \$-64,%rsp
- mov %rax,%r11
- sub %rsp,%r11
+ and \$-64,%rbp
+ mov %rsp,%r11
+ sub %rbp,%r11
and \$-4096,%r11
+ lea (%rbp,%r11),%rsp
+ mov (%rsp),%r10
+ cmp %rbp,%rsp
+ ja .Lfrom_page_walk
+ jmp .Lfrom_page_walk_done
+
.Lfrom_page_walk:
- mov (%rsp,%r11),%r10
- sub \$4096,%r11
- .byte 0x2e # predict non-taken
- jnc .Lfrom_page_walk
+ lea -4096(%rsp),%rsp
+ mov (%rsp),%r10
+ cmp %rbp,%rsp
+ ja .Lfrom_page_walk
+.Lfrom_page_walk_done:
mov $num,%r10
neg $num
@@ -2173,14 +2209,15 @@ $code.=<<___;
.type bn_mulx4x_mont_gather5,\@function,6
.align 32
bn_mulx4x_mont_gather5:
-.Lmulx4x_enter:
mov %rsp,%rax
+.Lmulx4x_enter:
push %rbx
push %rbp
push %r12
push %r13
push %r14
push %r15
+.Lmulx4x_prologue:
shl \$3,${num}d # convert $num to bytes
lea ($num,$num,2),%r10 # 3*$num in bytes
@@ -2197,31 +2234,39 @@ bn_mulx4x_mont_gather5:
# calculated from 7th argument, the index.]
#
lea -320(%rsp,$num,2),%r11
+ mov %rsp,%rbp
sub $rp,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lmulx4xsp_alt
- sub %r11,%rsp # align with $aptr
- lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
+ sub %r11,%rbp # align with $aptr
+ lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*$num*8+256)
jmp .Lmulx4xsp_done
.Lmulx4xsp_alt:
lea 4096-320(,$num,2),%r10
- lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
+ lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*$num*8+256)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
- sub %r11,%rsp
+ sub %r11,%rbp
.Lmulx4xsp_done:
- and \$-64,%rsp # ensure alignment
- mov %rax,%r11
- sub %rsp,%r11
+ and \$-64,%rbp # ensure alignment
+ mov %rsp,%r11
+ sub %rbp,%r11
and \$-4096,%r11
+ lea (%rbp,%r11),%rsp
+ mov (%rsp),%r10
+ cmp %rbp,%rsp
+ ja .Lmulx4x_page_walk
+ jmp .Lmulx4x_page_walk_done
+
.Lmulx4x_page_walk:
- mov (%rsp,%r11),%r10
- sub \$4096,%r11
- .byte 0x2e # predict non-taken
- jnc .Lmulx4x_page_walk
+ lea -4096(%rsp),%rsp
+ mov (%rsp),%r10
+ cmp %rbp,%rsp
+ ja .Lmulx4x_page_walk
+.Lmulx4x_page_walk_done:
##############################################################
# Stack layout
@@ -2629,14 +2674,15 @@ $code.=<<___;
.type bn_powerx5,\@function,6
.align 32
bn_powerx5:
-.Lpowerx5_enter:
mov %rsp,%rax
+.Lpowerx5_enter:
push %rbx
push %rbp
push %r12
push %r13
push %r14
push %r15
+.Lpowerx5_prologue:
shl \$3,${num}d # convert $num to bytes
lea ($num,$num,2),%r10 # 3*$num in bytes
@@ -2651,32 +2697,40 @@ bn_powerx5:
# calculated from 7th argument, the index.]
#
lea -320(%rsp,$num,2),%r11
+ mov %rsp,%rbp
sub $rptr,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lpwrx_sp_alt
- sub %r11,%rsp # align with $aptr
- lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
+ sub %r11,%rbp # align with $aptr
+ lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*$num*8+256)
jmp .Lpwrx_sp_done
.align 32
.Lpwrx_sp_alt:
lea 4096-320(,$num,2),%r10
- lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
+ lea -320(%rbp,$num,2),%rbp # alloca(frame+2*$num*8+256)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
- sub %r11,%rsp
+ sub %r11,%rbp
.Lpwrx_sp_done:
- and \$-64,%rsp
- mov %rax,%r11
- sub %rsp,%r11
+ and \$-64,%rbp
+ mov %rsp,%r11
+ sub %rbp,%r11
and \$-4096,%r11
+ lea (%rbp,%r11),%rsp
+ mov (%rsp),%r10
+ cmp %rbp,%rsp
+ ja .Lpwrx_page_walk
+ jmp .Lpwrx_page_walk_done
+
.Lpwrx_page_walk:
- mov (%rsp,%r11),%r10
- sub \$4096,%r11
- .byte 0x2e # predict non-taken
- jnc .Lpwrx_page_walk
+ lea -4096(%rsp),%rsp
+ mov (%rsp),%r10
+ cmp %rbp,%rsp
+ ja .Lpwrx_page_walk
+.Lpwrx_page_walk_done:
mov $num,%r10
neg $num
@@ -3607,9 +3661,14 @@ mul_handler:
cmp %r10,%rbx # context->Rip<end of prologue label
jb .Lcommon_seh_tail
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=epilogue label
+ jb .Lcommon_pop_regs
+
mov 152($context),%rax # pull context->Rsp
- mov 4(%r11),%r10d # HandlerData[1]
+ mov 8(%r11),%r10d # HandlerData[2]
lea (%rsi,%r10),%r10 # epilogue label
cmp %r10,%rbx # context->Rip>=epilogue label
jae .Lcommon_seh_tail
@@ -3621,11 +3680,11 @@ mul_handler:
mov 192($context),%r10 # pull $num
mov 8(%rax,%r10,8),%rax # pull saved stack pointer
- jmp .Lbody_proceed
+ jmp .Lcommon_pop_regs
.Lbody_40:
mov 40(%rax),%rax # pull saved stack pointer
-.Lbody_proceed:
+.Lcommon_pop_regs:
mov -8(%rax),%rbx
mov -16(%rax),%rbp
mov -24(%rax),%r12
@@ -3716,34 +3775,34 @@ $code.=<<___;
.LSEH_info_bn_mul_mont_gather5:
.byte 9,0,0,0
.rva mul_handler
- .rva .Lmul_body,.Lmul_epilogue # HandlerData[]
+ .rva .Lmul_body,.Lmul_body,.Lmul_epilogue # HandlerData[]
.align 8
.LSEH_info_bn_mul4x_mont_gather5:
.byte 9,0,0,0
.rva mul_handler
- .rva .Lmul4x_body,.Lmul4x_epilogue # HandlerData[]
+ .rva .Lmul4x_prologue,.Lmul4x_body,.Lmul4x_epilogue # HandlerData[]
.align 8
.LSEH_info_bn_power5:
.byte 9,0,0,0
.rva mul_handler
- .rva .Lpower5_body,.Lpower5_epilogue # HandlerData[]
+ .rva .Lpower5_prologue,.Lpower5_body,.Lpower5_epilogue # HandlerData[]
.align 8
.LSEH_info_bn_from_mont8x:
.byte 9,0,0,0
.rva mul_handler
- .rva .Lfrom_body,.Lfrom_epilogue # HandlerData[]
+ .rva .Lfrom_prologue,.Lfrom_body,.Lfrom_epilogue # HandlerData[]
___
$code.=<<___ if ($addx);
.align 8
.LSEH_info_bn_mulx4x_mont_gather5:
.byte 9,0,0,0
.rva mul_handler
- .rva .Lmulx4x_body,.Lmulx4x_epilogue # HandlerData[]
+ .rva .Lmulx4x_prologue,.Lmulx4x_body,.Lmulx4x_epilogue # HandlerData[]
.align 8
.LSEH_info_bn_powerx5:
.byte 9,0,0,0
.rva mul_handler
- .rva .Lpowerx5_body,.Lpowerx5_epilogue # HandlerData[]
+ .rva .Lpowerx5_prologue,.Lpowerx5_body,.Lpowerx5_epilogue # HandlerData[]
___
$code.=<<___;
.align 8
diff --git a/crypto/bn/bn_print.c b/crypto/bn/bn_print.c
index bfa31efc56..a9ff271b9a 100644
--- a/crypto/bn/bn_print.c
+++ b/crypto/bn/bn_print.c
@@ -111,6 +111,7 @@ char *BN_bn2dec(const BIGNUM *a)
char *p;
BIGNUM *t = NULL;
BN_ULONG *bn_data = NULL, *lp;
+ int bn_data_num;
/*-
* get an upper bound for the length of the decimal integer
@@ -120,9 +121,9 @@ char *BN_bn2dec(const BIGNUM *a)
*/
i = BN_num_bits(a) * 3;
num = (i / 10 + i / 1000 + 1) + 1;
- bn_data =
- (BN_ULONG *)OPENSSL_malloc((num / BN_DEC_NUM + 1) * sizeof(BN_ULONG));
- buf = (char *)OPENSSL_malloc(num + 3);
+ bn_data_num = num / BN_DEC_NUM + 1;
+ bn_data = OPENSSL_malloc(bn_data_num * sizeof(BN_ULONG));
+ buf = OPENSSL_malloc(num + 3);
if ((buf == NULL) || (bn_data == NULL)) {
BNerr(BN_F_BN_BN2DEC, ERR_R_MALLOC_FAILURE);
goto err;
@@ -140,9 +141,12 @@ char *BN_bn2dec(const BIGNUM *a)
if (BN_is_negative(t))
*p++ = '-';
- i = 0;
while (!BN_is_zero(t)) {
+ if (lp - bn_data >= bn_data_num)
+ goto err;
*lp = BN_div_word(t, BN_DEC_CONV);
+ if (*lp == (BN_ULONG)-1)
+ goto err;
lp++;
}
lp--;
diff --git a/crypto/conf/conf_mod.c b/crypto/conf/conf_mod.c
index 9acfca4f71..e0c9a67ff6 100644
--- a/crypto/conf/conf_mod.c
+++ b/crypto/conf/conf_mod.c
@@ -288,6 +288,10 @@ static CONF_MODULE *module_add(DSO *dso, const char *name,
tmod->dso = dso;
tmod->name = BUF_strdup(name);
+ if (tmod->name == NULL) {
+ OPENSSL_free(tmod);
+ return NULL;
+ }
tmod->init = ifunc;
tmod->finish = ffunc;
tmod->links = 0;
diff --git a/crypto/crypto-lib.com b/crypto/crypto-lib.com
index 1423cac288..37dc418bf5 100644
--- a/crypto/crypto-lib.com
+++ b/crypto/crypto-lib.com
@@ -1222,7 +1222,7 @@ $ CC = "CC"
$ IF ARCH.EQS."VAX" .AND. F$TRNLNM("DECC$CC_DEFAULT").NES."/DECC" -
THEN CC = "CC/DECC"
$ CC = CC + " /''CC_OPTIMIZE' /''DEBUGGER' /STANDARD=RELAXED"+ -
- "''POINTER_SIZE' /NOLIST /PREFIX=ALL" + -
+ "''POINTER_SIZE' /NOLIST /PREFIX=ALL /EXTERN_MODEL=STRICT_REFDEF" + -
" /INCLUDE=(''CC_INCLUDES')"+ -
CCEXTRAFLAGS
$!
diff --git a/crypto/ec/Makefile b/crypto/ec/Makefile
index 89491454a4..6628390ba4 100644
--- a/crypto/ec/Makefile
+++ b/crypto/ec/Makefile
@@ -131,7 +131,7 @@ ec_ameth.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
ec_ameth.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
ec_ameth.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
ec_ameth.o: ../../include/openssl/x509_vfy.h ../asn1/asn1_locl.h ../cryptlib.h
-ec_ameth.o: ec_ameth.c
+ec_ameth.o: ec_ameth.c ec_lcl.h
ec_asn1.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
ec_asn1.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
ec_asn1.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
diff --git a/crypto/ec/asm/ecp_nistz256-x86_64.pl b/crypto/ec/asm/ecp_nistz256-x86_64.pl
index 7140860e24..7948bf71b5 100755
--- a/crypto/ec/asm/ecp_nistz256-x86_64.pl
+++ b/crypto/ec/asm/ecp_nistz256-x86_64.pl
@@ -128,6 +128,7 @@ ecp_nistz256_mul_by_2:
push %r13
mov 8*0($a_ptr), $a0
+ xor $t4,$t4
mov 8*1($a_ptr), $a1
add $a0, $a0 # a0:a3+a0:a3
mov 8*2($a_ptr), $a2
@@ -138,7 +139,7 @@ ecp_nistz256_mul_by_2:
adc $a2, $a2
adc $a3, $a3
mov $a1, $t1
- sbb $t4, $t4
+ adc \$0, $t4
sub 8*0($a_ptr), $a0
mov $a2, $t2
@@ -146,14 +147,14 @@ ecp_nistz256_mul_by_2:
sbb 8*2($a_ptr), $a2
mov $a3, $t3
sbb 8*3($a_ptr), $a3
- test $t4, $t4
+ sbb \$0, $t4
- cmovz $t0, $a0
- cmovz $t1, $a1
+ cmovc $t0, $a0
+ cmovc $t1, $a1
mov $a0, 8*0($r_ptr)
- cmovz $t2, $a2
+ cmovc $t2, $a2
mov $a1, 8*1($r_ptr)
- cmovz $t3, $a3
+ cmovc $t3, $a3
mov $a2, 8*2($r_ptr)
mov $a3, 8*3($r_ptr)
@@ -250,12 +251,12 @@ ecp_nistz256_mul_by_3:
sbb \$0, $a2
mov $a3, $t3
sbb .Lpoly+8*3(%rip), $a3
- test $t4, $t4
+ sbb \$0, $t4
- cmovz $t0, $a0
- cmovz $t1, $a1
- cmovz $t2, $a2
- cmovz $t3, $a3
+ cmovc $t0, $a0
+ cmovc $t1, $a1
+ cmovc $t2, $a2
+ cmovc $t3, $a3
xor $t4, $t4
add 8*0($a_ptr), $a0 # a0:a3+=a_ptr[0:3]
@@ -272,14 +273,14 @@ ecp_nistz256_mul_by_3:
sbb \$0, $a2
mov $a3, $t3
sbb .Lpoly+8*3(%rip), $a3
- test $t4, $t4
+ sbb \$0, $t4
- cmovz $t0, $a0
- cmovz $t1, $a1
+ cmovc $t0, $a0
+ cmovc $t1, $a1
mov $a0, 8*0($r_ptr)
- cmovz $t2, $a2
+ cmovc $t2, $a2
mov $a1, 8*1($r_ptr)
- cmovz $t3, $a3
+ cmovc $t3, $a3
mov $a2, 8*2($r_ptr)
mov $a3, 8*3($r_ptr)
@@ -318,14 +319,14 @@ ecp_nistz256_add:
sbb 8*2($a_ptr), $a2
mov $a3, $t3
sbb 8*3($a_ptr), $a3
- test $t4, $t4
+ sbb \$0, $t4
- cmovz $t0, $a0
- cmovz $t1, $a1
+ cmovc $t0, $a0
+ cmovc $t1, $a1
mov $a0, 8*0($r_ptr)
- cmovz $t2, $a2
+ cmovc $t2, $a2
mov $a1, 8*1($r_ptr)
- cmovz $t3, $a3
+ cmovc $t3, $a3
mov $a2, 8*2($r_ptr)
mov $a3, 8*3($r_ptr)
@@ -1840,13 +1841,14 @@ $code.=<<___;
.type __ecp_nistz256_add_toq,\@abi-omnipotent
.align 32
__ecp_nistz256_add_toq:
+ xor $t4,$t4
add 8*0($b_ptr), $a0
adc 8*1($b_ptr), $a1
mov $a0, $t0
adc 8*2($b_ptr), $a2
adc 8*3($b_ptr), $a3
mov $a1, $t1
- sbb $t4, $t4
+ adc \$0, $t4
sub \$-1, $a0
mov $a2, $t2
@@ -1854,14 +1856,14 @@ __ecp_nistz256_add_toq:
sbb \$0, $a2
mov $a3, $t3
sbb $poly3, $a3
- test $t4, $t4
+ sbb \$0, $t4
- cmovz $t0, $a0
- cmovz $t1, $a1
+ cmovc $t0, $a0
+ cmovc $t1, $a1
mov $a0, 8*0($r_ptr)
- cmovz $t2, $a2
+ cmovc $t2, $a2
mov $a1, 8*1($r_ptr)
- cmovz $t3, $a3
+ cmovc $t3, $a3
mov $a2, 8*2($r_ptr)
mov $a3, 8*3($r_ptr)
@@ -1929,13 +1931,14 @@ __ecp_nistz256_subq:
.type __ecp_nistz256_mul_by_2q,\@abi-omnipotent
.align 32
__ecp_nistz256_mul_by_2q:
+ xor $t4, $t4
add $a0, $a0 # a0:a3+a0:a3
adc $a1, $a1
mov $a0, $t0
adc $a2, $a2
adc $a3, $a3
mov $a1, $t1
- sbb $t4, $t4
+ adc \$0, $t4
sub \$-1, $a0
mov $a2, $t2
@@ -1943,14 +1946,14 @@ __ecp_nistz256_mul_by_2q:
sbb \$0, $a2
mov $a3, $t3
sbb $poly3, $a3
- test $t4, $t4
+ sbb \$0, $t4
- cmovz $t0, $a0
- cmovz $t1, $a1
+ cmovc $t0, $a0
+ cmovc $t1, $a1
mov $a0, 8*0($r_ptr)
- cmovz $t2, $a2
+ cmovc $t2, $a2
mov $a1, 8*1($r_ptr)
- cmovz $t3, $a3
+ cmovc $t3, $a3
mov $a2, 8*2($r_ptr)
mov $a3, 8*3($r_ptr)
@@ -2241,16 +2244,14 @@ $code.=<<___;
mov $b_org, $a_ptr # reassign
movdqa %xmm0, $in1_x(%rsp)
movdqa %xmm1, $in1_x+0x10(%rsp)
- por %xmm0, %xmm1
movdqa %xmm2, $in1_y(%rsp)
movdqa %xmm3, $in1_y+0x10(%rsp)
- por %xmm2, %xmm3
movdqa %xmm4, $in1_z(%rsp)
movdqa %xmm5, $in1_z+0x10(%rsp)
- por %xmm1, %xmm3
+ por %xmm4, %xmm5
movdqu 0x00($a_ptr), %xmm0 # copy *(P256_POINT *)$b_ptr
- pshufd \$0xb1, %xmm3, %xmm5
+ pshufd \$0xb1, %xmm5, %xmm3
movdqu 0x10($a_ptr), %xmm1
movdqu 0x20($a_ptr), %xmm2
por %xmm3, %xmm5
@@ -2262,14 +2263,14 @@ $code.=<<___;
movdqa %xmm0, $in2_x(%rsp)
pshufd \$0x1e, %xmm5, %xmm4
movdqa %xmm1, $in2_x+0x10(%rsp)
- por %xmm0, %xmm1
- movq $r_ptr, %xmm0 # save $r_ptr
+ movdqu 0x40($a_ptr),%xmm0 # in2_z again
+ movdqu 0x50($a_ptr),%xmm1
movdqa %xmm2, $in2_y(%rsp)
movdqa %xmm3, $in2_y+0x10(%rsp)
- por %xmm2, %xmm3
por %xmm4, %xmm5
pxor %xmm4, %xmm4
- por %xmm1, %xmm3
+ por %xmm0, %xmm1
+ movq $r_ptr, %xmm0 # save $r_ptr
lea 0x40-$bias($a_ptr), $a_ptr # $a_ptr is still valid
mov $src0, $in2_z+8*0(%rsp) # make in2_z copy
@@ -2280,8 +2281,8 @@ $code.=<<___;
call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Z2sqr, in2_z);
pcmpeqd %xmm4, %xmm5
- pshufd \$0xb1, %xmm3, %xmm4
- por %xmm3, %xmm4
+ pshufd \$0xb1, %xmm1, %xmm4
+ por %xmm1, %xmm4
pshufd \$0, %xmm5, %xmm5 # in1infty
pshufd \$0x1e, %xmm4, %xmm3
por %xmm3, %xmm4
@@ -2405,6 +2406,7 @@ $code.=<<___;
#lea $Hsqr(%rsp), $r_ptr # 2*U1*H^2
#call __ecp_nistz256_mul_by_2 # ecp_nistz256_mul_by_2(Hsqr, U2);
+ xor $t4, $t4
add $acc0, $acc0 # a0:a3+a0:a3
lea $Rsqr(%rsp), $a_ptr
adc $acc1, $acc1
@@ -2412,7 +2414,7 @@ $code.=<<___;
adc $acc2, $acc2
adc $acc3, $acc3
mov $acc1, $t1
- sbb $t4, $t4
+ adc \$0, $t4
sub \$-1, $acc0
mov $acc2, $t2
@@ -2420,15 +2422,15 @@ $code.=<<___;
sbb \$0, $acc2
mov $acc3, $t3
sbb $poly3, $acc3
- test $t4, $t4
+ sbb \$0, $t4
- cmovz $t0, $acc0
+ cmovc $t0, $acc0
mov 8*0($a_ptr), $t0
- cmovz $t1, $acc1
+ cmovc $t1, $acc1
mov 8*1($a_ptr), $t1
- cmovz $t2, $acc2
+ cmovc $t2, $acc2
mov 8*2($a_ptr), $t2
- cmovz $t3, $acc3
+ cmovc $t3, $acc3
mov 8*3($a_ptr), $t3
call __ecp_nistz256_sub$x # p256_sub(res_x, Rsqr, Hsqr);
@@ -2612,16 +2614,14 @@ $code.=<<___;
mov 0x40+8*3($a_ptr), $acc0
movdqa %xmm0, $in1_x(%rsp)
movdqa %xmm1, $in1_x+0x10(%rsp)
- por %xmm0, %xmm1
movdqa %xmm2, $in1_y(%rsp)
movdqa %xmm3, $in1_y+0x10(%rsp)
- por %xmm2, %xmm3
movdqa %xmm4, $in1_z(%rsp)
movdqa %xmm5, $in1_z+0x10(%rsp)
- por %xmm1, %xmm3
+ por %xmm4, %xmm5
movdqu 0x00($b_ptr), %xmm0 # copy *(P256_POINT_AFFINE *)$b_ptr
- pshufd \$0xb1, %xmm3, %xmm5
+ pshufd \$0xb1, %xmm5, %xmm3
movdqu 0x10($b_ptr), %xmm1
movdqu 0x20($b_ptr), %xmm2
por %xmm3, %xmm5
@@ -2710,6 +2710,7 @@ $code.=<<___;
#lea $Hsqr(%rsp), $r_ptr # 2*U1*H^2
#call __ecp_nistz256_mul_by_2 # ecp_nistz256_mul_by_2(Hsqr, U2);
+ xor $t4, $t4
add $acc0, $acc0 # a0:a3+a0:a3
lea $Rsqr(%rsp), $a_ptr
adc $acc1, $acc1
@@ -2717,7 +2718,7 @@ $code.=<<___;
adc $acc2, $acc2
adc $acc3, $acc3
mov $acc1, $t1
- sbb $t4, $t4
+ adc \$0, $t4
sub \$-1, $acc0
mov $acc2, $t2
@@ -2725,15 +2726,15 @@ $code.=<<___;
sbb \$0, $acc2
mov $acc3, $t3
sbb $poly3, $acc3
- test $t4, $t4
+ sbb \$0, $t4
- cmovz $t0, $acc0
+ cmovc $t0, $acc0
mov 8*0($a_ptr), $t0
- cmovz $t1, $acc1
+ cmovc $t1, $acc1
mov 8*1($a_ptr), $t1
- cmovz $t2, $acc2
+ cmovc $t2, $acc2
mov 8*2($a_ptr), $t2
- cmovz $t3, $acc3
+ cmovc $t3, $acc3
mov 8*3($a_ptr), $t3
call __ecp_nistz256_sub$x # p256_sub(res_x, Rsqr, Hsqr);
@@ -2885,14 +2886,14 @@ __ecp_nistz256_add_tox:
sbb \$0, $a2
mov $a3, $t3
sbb $poly3, $a3
+ sbb \$0, $t4
- bt \$0, $t4
- cmovnc $t0, $a0
- cmovnc $t1, $a1
+ cmovc $t0, $a0
+ cmovc $t1, $a1
mov $a0, 8*0($r_ptr)
- cmovnc $t2, $a2
+ cmovc $t2, $a2
mov $a1, 8*1($r_ptr)
- cmovnc $t3, $a3
+ cmovc $t3, $a3
mov $a2, 8*2($r_ptr)
mov $a3, 8*3($r_ptr)
@@ -2980,14 +2981,14 @@ __ecp_nistz256_mul_by_2x:
sbb \$0, $a2
mov $a3, $t3
sbb $poly3, $a3
+ sbb \$0, $t4
- bt \$0, $t4
- cmovnc $t0, $a0
- cmovnc $t1, $a1
+ cmovc $t0, $a0
+ cmovc $t1, $a1
mov $a0, 8*0($r_ptr)
- cmovnc $t2, $a2
+ cmovc $t2, $a2
mov $a1, 8*1($r_ptr)
- cmovnc $t3, $a3
+ cmovc $t3, $a3
mov $a2, 8*2($r_ptr)
mov $a3, 8*3($r_ptr)
diff --git a/crypto/ec/ecp_nistz256.c b/crypto/ec/ecp_nistz256.c
index ca44d0aaee..99b8d613c8 100644
--- a/crypto/ec/ecp_nistz256.c
+++ b/crypto/ec/ecp_nistz256.c
@@ -82,19 +82,36 @@ typedef struct ec_pre_comp_st {
} EC_PRE_COMP;
/* Functions implemented in assembly */
+/*
+ * Most of below mentioned functions *preserve* the property of inputs
+ * being fully reduced, i.e. being in [0, modulus) range. Simply put if
+ * inputs are fully reduced, then output is too. Note that reverse is
+ * not true, in sense that given partially reduced inputs output can be
+ * either, not unlikely reduced. And "most" in first sentence refers to
+ * the fact that given the calculations flow one can tolerate that
+ * addition, 1st function below, produces partially reduced result *if*
+ * multiplications by 2 and 3, which customarily use addition, fully
+ * reduce it. This effectively gives two options: a) addition produces
+ * fully reduced result [as long as inputs are, just like remaining
+ * functions]; b) addition is allowed to produce partially reduced
+ * result, but multiplications by 2 and 3 perform additional reduction
+ * step. Choice between the two can be platform-specific, but it was a)
+ * in all cases so far...
+ */
+/* Modular add: res = a+b mod P */
+void ecp_nistz256_add(BN_ULONG res[P256_LIMBS],
+ const BN_ULONG a[P256_LIMBS],
+ const BN_ULONG b[P256_LIMBS]);
/* Modular mul by 2: res = 2*a mod P */
void ecp_nistz256_mul_by_2(BN_ULONG res[P256_LIMBS],
const BN_ULONG a[P256_LIMBS]);
-/* Modular div by 2: res = a/2 mod P */
-void ecp_nistz256_div_by_2(BN_ULONG res[P256_LIMBS],
- const BN_ULONG a[P256_LIMBS]);
/* Modular mul by 3: res = 3*a mod P */
void ecp_nistz256_mul_by_3(BN_ULONG res[P256_LIMBS],
const BN_ULONG a[P256_LIMBS]);
-/* Modular add: res = a+b mod P */
-void ecp_nistz256_add(BN_ULONG res[P256_LIMBS],
- const BN_ULONG a[P256_LIMBS],
- const BN_ULONG b[P256_LIMBS]);
+
+/* Modular div by 2: res = a/2 mod P */
+void ecp_nistz256_div_by_2(BN_ULONG res[P256_LIMBS],
+ const BN_ULONG a[P256_LIMBS]);
/* Modular sub: res = a-b mod P */
void ecp_nistz256_sub(BN_ULONG res[P256_LIMBS],
const BN_ULONG a[P256_LIMBS],
@@ -205,21 +222,29 @@ static BN_ULONG is_equal(const BN_ULONG a[P256_LIMBS],
return is_zero(res);
}
-static BN_ULONG is_one(const BN_ULONG a[P256_LIMBS])
+static BN_ULONG is_one(const BIGNUM *z)
{
- BN_ULONG res;
-
- res = a[0] ^ ONE[0];
- res |= a[1] ^ ONE[1];
- res |= a[2] ^ ONE[2];
- res |= a[3] ^ ONE[3];
- if (P256_LIMBS == 8) {
- res |= a[4] ^ ONE[4];
- res |= a[5] ^ ONE[5];
- res |= a[6] ^ ONE[6];
+ BN_ULONG res = 0;
+ BN_ULONG *a = z->d;
+
+ if (z->top == (P256_LIMBS - P256_LIMBS / 8)) {
+ res = a[0] ^ ONE[0];
+ res |= a[1] ^ ONE[1];
+ res |= a[2] ^ ONE[2];
+ res |= a[3] ^ ONE[3];
+ if (P256_LIMBS == 8) {
+ res |= a[4] ^ ONE[4];
+ res |= a[5] ^ ONE[5];
+ res |= a[6] ^ ONE[6];
+ /*
+ * no check for a[7] (being zero) on 32-bit platforms,
+ * because value of "one" takes only 7 limbs.
+ */
+ }
+ res = is_zero(res);
}
- return is_zero(res);
+ return res;
}
static int ecp_nistz256_set_words(BIGNUM *a, BN_ULONG words[P256_LIMBS])
@@ -315,19 +340,16 @@ static void ecp_nistz256_point_add(P256_POINT *r,
const BN_ULONG *in2_y = b->Y;
const BN_ULONG *in2_z = b->Z;
- /* We encode infinity as (0,0), which is not on the curve,
- * so it is OK. */
- in1infty = (in1_x[0] | in1_x[1] | in1_x[2] | in1_x[3] |
- in1_y[0] | in1_y[1] | in1_y[2] | in1_y[3]);
+ /*
+ * Infinity in encoded as (,,0)
+ */
+ in1infty = (in1_z[0] | in1_z[1] | in1_z[2] | in1_z[3]);
if (P256_LIMBS == 8)
- in1infty |= (in1_x[4] | in1_x[5] | in1_x[6] | in1_x[7] |
- in1_y[4] | in1_y[5] | in1_y[6] | in1_y[7]);
+ in1infty |= (in1_z[4] | in1_z[5] | in1_z[6] | in1_z[7]);
- in2infty = (in2_x[0] | in2_x[1] | in2_x[2] | in2_x[3] |
- in2_y[0] | in2_y[1] | in2_y[2] | in2_y[3]);
+ in2infty = (in2_z[0] | in2_z[1] | in2_z[2] | in2_z[3]);
if (P256_LIMBS == 8)
- in2infty |= (in2_x[4] | in2_x[5] | in2_x[6] | in2_x[7] |
- in2_y[4] | in2_y[5] | in2_y[6] | in2_y[7]);
+ in2infty |= (in2_z[4] | in2_z[5] | in2_z[6] | in2_z[7]);
in1infty = is_zero(in1infty);
in2infty = is_zero(in2infty);
@@ -416,15 +438,16 @@ static void ecp_nistz256_point_add_affine(P256_POINT *r,
const BN_ULONG *in2_y = b->Y;
/*
- * In affine representation we encode infty as (0,0), which is not on the
- * curve, so it is OK
+ * Infinity in encoded as (,,0)
*/
- in1infty = (in1_x[0] | in1_x[1] | in1_x[2] | in1_x[3] |
- in1_y[0] | in1_y[1] | in1_y[2] | in1_y[3]);
+ in1infty = (in1_z[0] | in1_z[1] | in1_z[2] | in1_z[3]);
if (P256_LIMBS == 8)
- in1infty |= (in1_x[4] | in1_x[5] | in1_x[6] | in1_x[7] |
- in1_y[4] | in1_y[5] | in1_y[6] | in1_y[7]);
+ in1infty |= (in1_z[4] | in1_z[5] | in1_z[6] | in1_z[7]);
+ /*
+ * In affine representation we encode infinity as (0,0), which is
+ * not on the curve, so it is OK
+ */
in2infty = (in2_x[0] | in2_x[1] | in2_x[2] | in2_x[3] |
in2_y[0] | in2_y[1] | in2_y[2] | in2_y[3]);
if (P256_LIMBS == 8)
@@ -741,9 +764,8 @@ static int ecp_nistz256_is_affine_G(const EC_POINT *generator)
{
return (generator->X.top == P256_LIMBS) &&
(generator->Y.top == P256_LIMBS) &&
- (generator->Z.top == (P256_LIMBS - P256_LIMBS / 8)) &&
is_equal(generator->X.d, def_xG) &&
- is_equal(generator->Y.d, def_yG) && is_one(generator->Z.d);
+ is_equal(generator->Y.d, def_yG) && is_one(&generator->Z);
}
static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx)
@@ -1249,6 +1271,8 @@ static int ecp_nistz256_points_mul(const EC_GROUP *group,
} else
#endif
{
+ BN_ULONG infty;
+
/* First window */
wvalue = (p_str[0] << 1) & mask;
index += window_size;
@@ -1260,7 +1284,30 @@ static int ecp_nistz256_points_mul(const EC_GROUP *group,
ecp_nistz256_neg(p.p.Z, p.p.Y);
copy_conditional(p.p.Y, p.p.Z, wvalue & 1);
- memcpy(p.p.Z, ONE, sizeof(ONE));
+ /*
+ * Since affine infinity is encoded as (0,0) and
+ * Jacobian ias (,,0), we need to harmonize them
+ * by assigning "one" or zero to Z.
+ */
+ infty = (p.p.X[0] | p.p.X[1] | p.p.X[2] | p.p.X[3] |
+ p.p.Y[0] | p.p.Y[1] | p.p.Y[2] | p.p.Y[3]);
+ if (P256_LIMBS == 8)
+ infty |= (p.p.X[4] | p.p.X[5] | p.p.X[6] | p.p.X[7] |
+ p.p.Y[4] | p.p.Y[5] | p.p.Y[6] | p.p.Y[7]);
+
+ infty = 0 - is_zero(infty);
+ infty = ~infty;
+
+ p.p.Z[0] = ONE[0] & infty;
+ p.p.Z[1] = ONE[1] & infty;
+ p.p.Z[2] = ONE[2] & infty;
+ p.p.Z[3] = ONE[3] & infty;
+ if (P256_LIMBS == 8) {
+ p.p.Z[4] = ONE[4] & infty;
+ p.p.Z[5] = ONE[5] & infty;
+ p.p.Z[6] = ONE[6] & infty;
+ p.p.Z[7] = ONE[7] & infty;
+ }
for (i = 1; i < 37; i++) {
unsigned int off = (index - 1) / 8;
@@ -1331,7 +1378,7 @@ static int ecp_nistz256_points_mul(const EC_GROUP *group,
!ecp_nistz256_set_words(&r->Z, p.p.Z)) {
goto err;
}
- r->Z_is_one = is_one(p.p.Z) & 1;
+ r->Z_is_one = is_one(&r->Z) & 1;
ret = 1;
diff --git a/crypto/engine/eng_cryptodev.c b/crypto/engine/eng_cryptodev.c
index 5a2ca6d72e..65a74df236 100644
--- a/crypto/engine/eng_cryptodev.c
+++ b/crypto/engine/eng_cryptodev.c
@@ -935,11 +935,15 @@ static int cryptodev_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
return (0);
}
+ dstate->mac_len = fstate->mac_len;
if (fstate->mac_len != 0) {
if (fstate->mac_data != NULL) {
dstate->mac_data = OPENSSL_malloc(fstate->mac_len);
+ if (dstate->ac_data == NULL) {
+ printf("cryptodev_digest_init: malloc failed\n");
+ return 0;
+ }
memcpy(dstate->mac_data, fstate->mac_data, fstate->mac_len);
- dstate->mac_len = fstate->mac_len;
}
}
diff --git a/crypto/evp/e_rc4_hmac_md5.c b/crypto/evp/e_rc4_hmac_md5.c
index ba5979d47a..5e92855dfd 100644
--- a/crypto/evp/e_rc4_hmac_md5.c
+++ b/crypto/evp/e_rc4_hmac_md5.c
@@ -99,7 +99,7 @@ static int rc4_hmac_md5_init_key(EVP_CIPHER_CTX *ctx,
return 1;
}
-# if !defined(OPENSSL_NO_ASM) && ( \
+# if defined(RC4_ASM) && defined(MD5_ASM) && ( \
defined(__x86_64) || defined(__x86_64__) || \
defined(_M_AMD64) || defined(_M_X64) || \
defined(__INTEL__) ) && \
diff --git a/crypto/evp/evp_test.c b/crypto/evp/evp_test.c
index d7441ec7b7..98796427bf 100644..100755
--- a/crypto/evp/evp_test.c
+++ b/crypto/evp/evp_test.c
@@ -76,6 +76,7 @@ static void hexdump(FILE *f, const char *title, const unsigned char *s, int l)
static int convert(unsigned char *s)
{
unsigned char *d;
+ int digits = 0;
for (d = s; *s; s += 2, ++d) {
unsigned int n;
@@ -86,8 +87,9 @@ static int convert(unsigned char *s)
}
sscanf((char *)s, "%2x", &n);
*d = (unsigned char)n;
+ digits++;
}
- return s - d;
+ return digits;
}
static char *sstrsep(char **string, const char *delim)
diff --git a/crypto/evp/openbsd_hw.c b/crypto/evp/openbsd_hw.c
index 75d12e2330..07decf2674 100644
--- a/crypto/evp/openbsd_hw.c
+++ b/crypto/evp/openbsd_hw.c
@@ -133,6 +133,10 @@ static int dev_crypto_init_key(EVP_CIPHER_CTX *ctx, int cipher,
return 0;
CDATA(ctx)->key = OPENSSL_malloc(MAX_HW_KEY);
+ if (CDATA(ctx)->key == NULL {
+ err("CDATA(ctx)->key memory allocation failed");
+ return 0;
+ }
assert(ctx->cipher->iv_len <= MAX_HW_IV);
@@ -186,6 +190,11 @@ static int dev_crypto_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (((unsigned long)in & 3) || cinl != inl) {
cin = OPENSSL_malloc(cinl);
+ if (cin == NULL) {
+ err("cin - memory allocation failed");
+ abort();
+ return 0;
+ }
memcpy(cin, in, inl);
cryp.src = cin;
}
@@ -334,6 +343,11 @@ static int do_digest(int ses, unsigned char *md, const void *data, int len)
char *dcopy;
dcopy = OPENSSL_malloc(len);
+ if (dcopy == NULL) {
+ err("dcopy - memory allocation failed");
+ abort();
+ return 0;
+ }
memcpy(dcopy, data, len);
cryp.src = dcopy;
cryp.dst = cryp.src; // FIXME!!!
@@ -364,6 +378,10 @@ static int dev_crypto_md5_update(EVP_MD_CTX *ctx, const void *data,
return do_digest(md_data->sess.ses, md_data->md, data, len);
md_data->data = OPENSSL_realloc(md_data->data, md_data->len + len);
+ if (md_data->data == NULL) {
+ err("DEV_CRYPTO_MD5_UPDATE: unable to allocate memory");
+ abort();
+ }
memcpy(md_data->data + md_data->len, data, len);
md_data->len += len;
@@ -397,6 +415,10 @@ static int dev_crypto_md5_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
assert(from->digest->flags & EVP_MD_FLAG_ONESHOT);
to_md->data = OPENSSL_malloc(from_md->len);
+ if (to_md->data == NULL) {
+ err("DEV_CRYPTO_MD5_COPY: unable to allocate memory");
+ abort();
+ }
memcpy(to_md->data, from_md->data, from_md->len);
return 1;
diff --git a/crypto/jpake/jpake.c b/crypto/jpake/jpake.c
index ebc0975575..2ba75f0172 100644
--- a/crypto/jpake/jpake.c
+++ b/crypto/jpake/jpake.c
@@ -116,6 +116,8 @@ JPAKE_CTX *JPAKE_CTX_new(const char *name, const char *peer_name,
const BIGNUM *secret)
{
JPAKE_CTX *ctx = OPENSSL_malloc(sizeof *ctx);
+ if (ctx == NULL)
+ return NULL;
JPAKE_CTX_init(ctx, name, peer_name, p, g, q, secret);
@@ -151,6 +153,8 @@ static void hashbn(SHA_CTX *sha, const BIGNUM *bn)
size_t l = BN_num_bytes(bn);
unsigned char *bin = OPENSSL_malloc(l);
+ if (bin == NULL)
+ return;
hashlength(sha, l);
BN_bn2bin(bn, bin);
SHA1_Update(sha, bin, l);
diff --git a/crypto/mdc2/mdc2dgst.c b/crypto/mdc2/mdc2dgst.c
index 6615cf84d7..2dce493633 100644
--- a/crypto/mdc2/mdc2dgst.c
+++ b/crypto/mdc2/mdc2dgst.c
@@ -91,7 +91,7 @@ int MDC2_Update(MDC2_CTX *c, const unsigned char *in, size_t len)
i = c->num;
if (i != 0) {
- if (i + len < MDC2_BLOCK) {
+ if (len < MDC2_BLOCK - i) {
/* partial block */
memcpy(&(c->data[i]), in, len);
c->num += (int)len;
diff --git a/crypto/mem.c b/crypto/mem.c
index 1e873e3428..9c45135529 100644
--- a/crypto/mem.c
+++ b/crypto/mem.c
@@ -82,6 +82,14 @@ static void *default_malloc_ex(size_t num, const char *file, int line)
static void *(*malloc_ex_func) (size_t, const char *file, int line)
= default_malloc_ex;
+#ifdef OPENSSL_SYS_VMS
+# if __INITIAL_POINTER_SIZE == 64
+# define realloc _realloc64
+# else
+# define realloc _realloc32
+# endif
+#endif
+
static void *(*realloc_func) (void *, size_t) = realloc;
static void *default_realloc_ex(void *str, size_t num,
const char *file, int line)
@@ -92,7 +100,11 @@ static void *default_realloc_ex(void *str, size_t num,
static void *(*realloc_ex_func) (void *, size_t, const char *file, int line)
= default_realloc_ex;
-static void (*free_func) (void *) = free;
+#ifdef OPENSSL_SYS_VMS
+ static void (*free_func) (__void_ptr64) = free;
+#else
+ static void (*free_func) (void *) = free;
+#endif
static void *(*malloc_locked_func) (size_t) = malloc;
static void *default_malloc_locked_ex(size_t num, const char *file, int line)
@@ -103,7 +115,11 @@ static void *default_malloc_locked_ex(size_t num, const char *file, int line)
static void *(*malloc_locked_ex_func) (size_t, const char *file, int line)
= default_malloc_locked_ex;
-static void (*free_locked_func) (void *) = free;
+#ifdef OPENSSL_SYS_VMS
+ static void (*free_locked_func) (__void_ptr64) = free;
+#else
+ static void (*free_locked_func) (void *) = free;
+#endif
/* may be changed as long as 'allow_customize_debug' is set */
/* XXX use correct function pointer types */
diff --git a/crypto/o_time.c b/crypto/o_time.c
index 635dae184d..b99e5990b4 100644..100755
--- a/crypto/o_time.c
+++ b/crypto/o_time.c
@@ -78,7 +78,28 @@
# include <descrip.h>
# include <stdlib.h>
# endif /* ndef VMS_GMTIME_OK */
-#endif
+
+
+/*
+ * Needed to pick up the correct definitions and declarations in some of the
+ * DEC C Header Files (*.H).
+ */
+# define __NEW_STARLET 1
+
+# if (defined(__alpha) || defined(__ia64))
+# include <iledef.h>
+# else
+
+/* VAX */
+typedef struct _ile3 { /* Copied from ILEDEF.H for Alpha */
+# pragma __nomember_alignment
+ unsigned short int ile3$w_length; /* Length of buffer in bytes */
+ unsigned short int ile3$w_code; /* Item code value */
+ void *ile3$ps_bufaddr; /* Buffer address */
+ unsigned short int *ile3$ps_retlen_addr; /* Address of word for returned length */
+} ILE3;
+# endif /* alpha || ia64 */
+#endif /* OPENSSL_SYS_VMS */
struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result)
{
@@ -105,26 +126,42 @@ struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result)
static $DESCRIPTOR(lognam, "SYS$TIMEZONE_DIFFERENTIAL");
char logvalue[256];
unsigned int reslen = 0;
- struct {
- short buflen;
- short code;
- void *bufaddr;
- unsigned int *reslen;
- } itemlist[] = {
- {
- 0, LNM$_STRING, 0, 0
- },
- {
- 0, 0, 0, 0
- },
- };
+# if __INITIAL_POINTER_SIZE == 64
+ ILEB_64 itemlist[2], *pitem;
+# else
+ ILE3 itemlist[2], *pitem;
+# endif
int status;
time_t t;
+
+ /*
+ * Setup an itemlist for the call to $TRNLNM - Translate Logical Name.
+ */
+ pitem = itemlist;
+
+# if __INITIAL_POINTER_SIZE == 64
+ pitem->ileb_64$w_mbo = 1;
+ pitem->ileb_64$w_code = LNM$_STRING;
+ pitem->ileb_64$l_mbmo = -1;
+ pitem->ileb_64$q_length = sizeof (logvalue);
+ pitem->ileb_64$pq_bufaddr = logvalue;
+ pitem->ileb_64$pq_retlen_addr = (unsigned __int64 *) &reslen;
+ pitem++;
+ /* Last item of the item list is null terminated */
+ pitem->ileb_64$q_length = pitem->ileb_64$w_code = 0;
+# else
+ pitem->ile3$w_length = sizeof (logvalue);
+ pitem->ile3$w_code = LNM$_STRING;
+ pitem->ile3$ps_bufaddr = logvalue;
+ pitem->ile3$ps_retlen_addr = (unsigned short int *) &reslen;
+ pitem++;
+ /* Last item of the item list is null terminated */
+ pitem->ile3$w_length = pitem->ile3$w_code = 0;
+# endif
+
+
/* Get the value for SYS$TIMEZONE_DIFFERENTIAL */
- itemlist[0].buflen = sizeof(logvalue);
- itemlist[0].bufaddr = logvalue;
- itemlist[0].reslen = &reslen;
status = sys$trnlnm(0, &tabnam, &lognam, 0, itemlist);
if (!(status & 1))
return NULL;
@@ -132,7 +169,7 @@ struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result)
t = *timer;
-/* The following is extracted from the DEC C header time.h */
+ /* The following is extracted from the DEC C header time.h */
/*
** Beginning in OpenVMS Version 7.0 mktime, time, ctime, strftime
** have two implementations. One implementation is provided
diff --git a/crypto/pem/pem.h b/crypto/pem/pem.h
index d3b23fc997..aac72fb21e 100644
--- a/crypto/pem/pem.h
+++ b/crypto/pem/pem.h
@@ -531,6 +531,7 @@ int i2b_PVK_bio(BIO *out, EVP_PKEY *pk, int enclevel,
* The following lines are auto generated by the script mkerr.pl. Any changes
* made after this point may be overwritten when the script is next run.
*/
+
void ERR_load_PEM_strings(void);
/* Error codes for the PEM functions. */
@@ -592,6 +593,7 @@ void ERR_load_PEM_strings(void);
# define PEM_R_ERROR_CONVERTING_PRIVATE_KEY 115
# define PEM_R_EXPECTING_PRIVATE_KEY_BLOB 119
# define PEM_R_EXPECTING_PUBLIC_KEY_BLOB 120
+# define PEM_R_HEADER_TOO_LONG 128
# define PEM_R_INCONSISTENT_HEADER 121
# define PEM_R_KEYBLOB_HEADER_PARSE_ERROR 122
# define PEM_R_KEYBLOB_TOO_SHORT 123
@@ -609,7 +611,7 @@ void ERR_load_PEM_strings(void);
# define PEM_R_UNSUPPORTED_ENCRYPTION 114
# define PEM_R_UNSUPPORTED_KEY_COMPONENTS 126
-#ifdef __cplusplus
+# ifdef __cplusplus
}
-#endif
+# endif
#endif
diff --git a/crypto/pem/pem_err.c b/crypto/pem/pem_err.c
index e1f4fdb432..4e5f8e936c 100644
--- a/crypto/pem/pem_err.c
+++ b/crypto/pem/pem_err.c
@@ -1,6 +1,6 @@
/* crypto/pem/pem_err.c */
/* ====================================================================
- * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2016 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
@@ -132,6 +132,7 @@ static ERR_STRING_DATA PEM_str_reasons[] = {
"expecting private key blob"},
{ERR_REASON(PEM_R_EXPECTING_PUBLIC_KEY_BLOB),
"expecting public key blob"},
+ {ERR_REASON(PEM_R_HEADER_TOO_LONG), "header too long"},
{ERR_REASON(PEM_R_INCONSISTENT_HEADER), "inconsistent header"},
{ERR_REASON(PEM_R_KEYBLOB_HEADER_PARSE_ERROR),
"keyblob header parse error"},
diff --git a/crypto/pem/pvkfmt.c b/crypto/pem/pvkfmt.c
index 61864468f6..1ce5a1e319 100644
--- a/crypto/pem/pvkfmt.c
+++ b/crypto/pem/pvkfmt.c
@@ -127,6 +127,9 @@ static int read_lebn(const unsigned char **in, unsigned int nbyte, BIGNUM **r)
# define MS_KEYTYPE_KEYX 0x1
# define MS_KEYTYPE_SIGN 0x2
+/* Maximum length of a blob after header */
+# define BLOB_MAX_LENGTH 102400
+
/* The PVK file magic number: seems to spell out "bobsfile", who is Bob? */
# define MS_PVKMAGIC 0xb0b5f11eL
/* Salt length for PVK files */
@@ -272,6 +275,10 @@ static EVP_PKEY *do_b2i_bio(BIO *in, int ispub)
return NULL;
length = blob_length(bitlen, isdss, ispub);
+ if (length > BLOB_MAX_LENGTH) {
+ PEMerr(PEM_F_DO_B2I_BIO, PEM_R_HEADER_TOO_LONG);
+ return NULL;
+ }
buf = OPENSSL_malloc(length);
if (!buf) {
PEMerr(PEM_F_DO_B2I_BIO, ERR_R_MALLOC_FAILURE);
diff --git a/crypto/pkcs12/p12_utl.c b/crypto/pkcs12/p12_utl.c
index a0b992eab6..e466f762ff 100644
--- a/crypto/pkcs12/p12_utl.c
+++ b/crypto/pkcs12/p12_utl.c
@@ -91,6 +91,10 @@ char *OPENSSL_uni2asc(unsigned char *uni, int unilen)
{
int asclen, i;
char *asctmp;
+
+ /* string must contain an even number of bytes */
+ if (unilen & 1)
+ return NULL;
asclen = unilen / 2;
/* If no terminating zero allow for one */
if (!unilen || uni[unilen - 1])
diff --git a/crypto/pkcs7/pk7_doit.c b/crypto/pkcs7/pk7_doit.c
index 1ab6d5ae71..6cf8253bc2 100644
--- a/crypto/pkcs7/pk7_doit.c
+++ b/crypto/pkcs7/pk7_doit.c
@@ -642,6 +642,8 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
} else {
# if 0
bio = BIO_new(BIO_s_mem());
+ if (bio == NULL)
+ goto err;
/*
* We need to set this so that when we have read all the data, the
* encrypt BIO, if present, will read EOF and encode the last few
diff --git a/crypto/rand/rand_vms.c b/crypto/rand/rand_vms.c
index 0e10c363e2..be4ff4cc87 100644..100755
--- a/crypto/rand/rand_vms.c
+++ b/crypto/rand/rand_vms.c
@@ -3,6 +3,11 @@
* Written by Richard Levitte <richard@levitte.org> for the OpenSSL project
* 2000.
*/
+/*
+ * Modified by VMS Software, Inc (2016)
+ * Eliminate looping through all processes (performance)
+ * Add additional randomizations using rand() function
+ */
/* ====================================================================
* Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
*
@@ -61,11 +66,11 @@
#include "rand_lcl.h"
#if defined(OPENSSL_SYS_VMS)
-
# include <descrip.h>
# include <jpidef.h>
# include <ssdef.h>
# include <starlet.h>
+# include <efndef>
# ifdef __DECC
# pragma message disable DOLLARID
# endif
@@ -83,77 +88,93 @@
# endif /* __INITIAL_POINTER_SIZE == 64 [else] */
static struct items_data_st {
- short length, code; /* length is amount of bytes */
+ short length, code; /* length is number of bytes */
} items_data[] = {
- {
- 4, JPI$_BUFIO
- },
- {
- 4, JPI$_CPUTIM
- },
- {
- 4, JPI$_DIRIO
- },
- {
- 8, JPI$_LOGINTIM
- },
- {
- 4, JPI$_PAGEFLTS
- },
- {
- 4, JPI$_PID
- },
- {
- 4, JPI$_WSSIZE
- },
- {
- 0, 0
- }
+ {4, JPI$_BUFIO},
+ {4, JPI$_CPUTIM},
+ {4, JPI$_DIRIO},
+ {4, JPI$_IMAGECOUNT},
+ {8, JPI$_LAST_LOGIN_I},
+ {8, JPI$_LOGINTIM},
+ {4, JPI$_PAGEFLTS},
+ {4, JPI$_PID},
+ {4, JPI$_PPGCNT},
+ {4, JPI$_WSPEAK},
+ {4, JPI$_FINALEXC},
+ {0, 0} /* zero terminated */
};
int RAND_poll(void)
{
- long pid, iosb[2];
- int status = 0;
+
+ /* determine the number of items in the JPI array */
+
+ struct items_data_st item_entry;
+ int item_entry_count = sizeof(items_data)/sizeof(item_entry);
+
+ /* Create the JPI itemlist array to hold item_data content */
+
struct {
short length, code;
- long *buffer;
+ int *buffer;
int *retlen;
- } item[32], *pitem;
- unsigned char data_buffer[256];
- short total_length = 0;
- struct items_data_st *pitems_data;
+ } item[item_entry_count], *pitem; /* number of entries in items_data */
+ struct items_data_st *pitems_data;
pitems_data = items_data;
pitem = item;
+ int data_buffer[(item_entry_count*2)+4]; /* 8 bytes per entry max */
+ int iosb[2];
+ int sys_time[2];
+ int *ptr;
+ int i, j ;
+ int tmp_length = 0;
+ int total_length = 0;
+
+ /* Setup itemlist for GETJPI */
- /* Setup */
- while (pitems_data->length && (total_length + pitems_data->length <= 256)) {
+ while (pitems_data->length) {
pitem->length = pitems_data->length;
- pitem->code = pitems_data->code;
- pitem->buffer = (long *)&data_buffer[total_length];
+ pitem->code = pitems_data->code;
+ pitem->buffer = &data_buffer[total_length];
pitem->retlen = 0;
- total_length += pitems_data->length;
+ /* total_length is in longwords */
+ total_length += pitems_data->length/4;
pitems_data++;
pitem ++;
}
pitem->length = pitem->code = 0;
- /*
- * Scan through all the processes in the system and add entropy with
- * results from the processes that were possible to look at.
- * However, view the information as only half trustable.
- */
- pid = -1; /* search context */
- while ((status = sys$getjpiw(0, &pid, 0, item, iosb, 0, 0))
- != SS$_NOMOREPROC) {
- if (status == SS$_NORMAL) {
- RAND_add((PTR_T) data_buffer, total_length, total_length / 2);
+ /* Fill data_buffer with various info bits from this process */
+ /* and twist that data to seed the SSL random number init */
+
+ if (sys$getjpiw(EFN$C_ENF, NULL, NULL, item, &iosb, 0, 0) == SS$_NORMAL) {
+ for (i = 0; i < total_length; i++) {
+ sys$gettim((struct _generic_64 *)&sys_time[0]);
+ srand(sys_time[0] * data_buffer[0] * data_buffer[1] + i);
+
+ if (i == (total_length - 1)) { /* for JPI$_FINALEXC */
+ ptr = &data_buffer[i];
+ for (j = 0; j < 4; j++) {
+ data_buffer[i + j] = ptr[j];
+ /* OK to use rand() just to scramble the seed */
+ data_buffer[i + j] ^= (sys_time[0] ^ rand());
+ tmp_length++;
+ }
+ } else {
+ /* OK to use rand() just to scramble the seed */
+ data_buffer[i] ^= (sys_time[0] ^ rand());
+ }
}
+
+ total_length += (tmp_length - 1);
+
+ /* size of seed is total_length*4 bytes (64bytes) */
+ RAND_add((PTR_T) data_buffer, total_length*4, total_length * 2);
+ } else {
+ return 0;
}
- sys$gettim(iosb);
- RAND_add((PTR_T) iosb, sizeof(iosb), sizeof(iosb) / 2);
+
return 1;
}
-
#endif
diff --git a/crypto/rand/randfile.c b/crypto/rand/randfile.c
index 76bdb9a5d5..728fd0a721 100644
--- a/crypto/rand/randfile.c
+++ b/crypto/rand/randfile.c
@@ -111,7 +111,7 @@
#define BUFSIZE 1024
#define RAND_DATA 1024
-#ifdef OPENSSL_SYS_VMS
+#if (defined(OPENSSL_SYS_VMS) && (defined(__alpha) || defined(__ia64)))
/*
* This declaration is a nasty hack to get around vms' extension to fopen for
* passing in sharing options being disabled by our /STANDARD=ANSI89
@@ -140,7 +140,24 @@ int RAND_load_file(const char *file, long bytes)
struct stat sb;
#endif
int i, ret = 0, n;
+/*
+ * If setvbuf() is to be called, then the FILE pointer
+ * to it must be 32 bit.
+*/
+
+#if !defined OPENSSL_NO_SETVBUF_IONBF && defined(OPENSSL_SYS_VMS) && defined(__VMS_VER) && (__VMS_VER >= 70000000)
+ /* For 64-bit-->32 bit API Support*/
+#if __INITIAL_POINTER_SIZE == 64
+#pragma __required_pointer_size __save
+#pragma __required_pointer_size 32
+#endif
+ FILE *in; /* setvbuf() requires 32-bit pointers */
+#if __INITIAL_POINTER_SIZE == 64
+#pragma __required_pointer_size __restore
+#endif
+#else
FILE *in;
+#endif /* OPENSSL_SYS_VMS */
if (file == NULL)
return (0);
@@ -249,7 +266,7 @@ int RAND_write_file(const char *file)
}
#endif
-#ifdef OPENSSL_SYS_VMS
+#if (defined(OPENSSL_SYS_VMS) && (defined(__alpha) || defined(__ia64)))
/*
* VMS NOTE: Prior versions of this routine created a _new_ version of
* the rand file for each call into this routine, then deleted all
diff --git a/crypto/rsa/rsa_chk.c b/crypto/rsa/rsa_chk.c
index 607faa0017..475dfc5628 100644
--- a/crypto/rsa/rsa_chk.c
+++ b/crypto/rsa/rsa_chk.c
@@ -56,7 +56,6 @@ int RSA_check_key(const RSA *key)
{
BIGNUM *i, *j, *k, *l, *m;
BN_CTX *ctx;
- int r;
int ret = 1;
if (!key->p || !key->q || !key->n || !key->e || !key->d) {
@@ -70,75 +69,68 @@ int RSA_check_key(const RSA *key)
l = BN_new();
m = BN_new();
ctx = BN_CTX_new();
- if (i == NULL || j == NULL || k == NULL || l == NULL ||
- m == NULL || ctx == NULL) {
+ if (i == NULL || j == NULL || k == NULL || l == NULL
+ || m == NULL || ctx == NULL) {
ret = -1;
RSAerr(RSA_F_RSA_CHECK_KEY, ERR_R_MALLOC_FAILURE);
goto err;
}
+ if (BN_is_one(key->e)) {
+ ret = 0;
+ RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_BAD_E_VALUE);
+ }
+ if (!BN_is_odd(key->e)) {
+ ret = 0;
+ RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_BAD_E_VALUE);
+ }
+
/* p prime? */
- r = BN_is_prime_ex(key->p, BN_prime_checks, NULL, NULL);
- if (r != 1) {
- ret = r;
- if (r != 0)
- goto err;
+ if (BN_is_prime_ex(key->p, BN_prime_checks, NULL, NULL) != 1) {
+ ret = 0;
RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_P_NOT_PRIME);
}
/* q prime? */
- r = BN_is_prime_ex(key->q, BN_prime_checks, NULL, NULL);
- if (r != 1) {
- ret = r;
- if (r != 0)
- goto err;
+ if (BN_is_prime_ex(key->q, BN_prime_checks, NULL, NULL) != 1) {
+ ret = 0;
RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_Q_NOT_PRIME);
}
/* n = p*q? */
- r = BN_mul(i, key->p, key->q, ctx);
- if (!r) {
+ if (!BN_mul(i, key->p, key->q, ctx)) {
ret = -1;
goto err;
}
-
if (BN_cmp(i, key->n) != 0) {
ret = 0;
RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_N_DOES_NOT_EQUAL_P_Q);
}
/* d*e = 1 mod lcm(p-1,q-1)? */
-
- r = BN_sub(i, key->p, BN_value_one());
- if (!r) {
+ if (!BN_sub(i, key->p, BN_value_one())) {
ret = -1;
goto err;
}
- r = BN_sub(j, key->q, BN_value_one());
- if (!r) {
+ if (!BN_sub(j, key->q, BN_value_one())) {
ret = -1;
goto err;
}
/* now compute k = lcm(i,j) */
- r = BN_mul(l, i, j, ctx);
- if (!r) {
+ if (!BN_mul(l, i, j, ctx)) {
ret = -1;
goto err;
}
- r = BN_gcd(m, i, j, ctx);
- if (!r) {
+ if (!BN_gcd(m, i, j, ctx)) {
ret = -1;
goto err;
}
- r = BN_div(k, NULL, l, m, ctx); /* remainder is 0 */
- if (!r) {
+ if (!BN_div(k, NULL, l, m, ctx)) { /* remainder is 0 */
ret = -1;
goto err;
}
-
- r = BN_mod_mul(i, key->d, key->e, k, ctx);
- if (!r) {
+ if (!BN_mod_mul(i, key->d, key->e, k, ctx)) {
ret = -1;
goto err;
}
@@ -150,36 +142,28 @@ int RSA_check_key(const RSA *key)
if (key->dmp1 != NULL && key->dmq1 != NULL && key->iqmp != NULL) {
/* dmp1 = d mod (p-1)? */
- r = BN_sub(i, key->p, BN_value_one());
- if (!r) {
+ if (!BN_sub(i, key->p, BN_value_one())) {
ret = -1;
goto err;
}
-
- r = BN_mod(j, key->d, i, ctx);
- if (!r) {
+ if (!BN_mod(j, key->d, i, ctx)) {
ret = -1;
goto err;
}
-
if (BN_cmp(j, key->dmp1) != 0) {
ret = 0;
RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_DMP1_NOT_CONGRUENT_TO_D);
}
/* dmq1 = d mod (q-1)? */
- r = BN_sub(i, key->q, BN_value_one());
- if (!r) {
+ if (!BN_sub(i, key->q, BN_value_one())) {
ret = -1;
goto err;
}
-
- r = BN_mod(j, key->d, i, ctx);
- if (!r) {
+ if (!BN_mod(j, key->d, i, ctx)) {
ret = -1;
goto err;
}
-
if (BN_cmp(j, key->dmq1) != 0) {
ret = 0;
RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_DMQ1_NOT_CONGRUENT_TO_D);
@@ -190,7 +174,6 @@ int RSA_check_key(const RSA *key)
ret = -1;
goto err;
}
-
if (BN_cmp(i, key->iqmp) != 0) {
ret = 0;
RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_IQMP_NOT_INVERSE_OF_Q);
@@ -198,17 +181,11 @@ int RSA_check_key(const RSA *key)
}
err:
- if (i != NULL)
- BN_free(i);
- if (j != NULL)
- BN_free(j);
- if (k != NULL)
- BN_free(k);
- if (l != NULL)
- BN_free(l);
- if (m != NULL)
- BN_free(m);
- if (ctx != NULL)
- BN_CTX_free(ctx);
- return (ret);
+ BN_free(i);
+ BN_free(j);
+ BN_free(k);
+ BN_free(l);
+ BN_free(m);
+ BN_CTX_free(ctx);
+ return ret;
}
diff --git a/crypto/rsa/rsa_pmeth.c b/crypto/rsa/rsa_pmeth.c
index 203635595f..94db87a063 100644
--- a/crypto/rsa/rsa_pmeth.c
+++ b/crypto/rsa/rsa_pmeth.c
@@ -545,8 +545,10 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
return 1;
case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP:
- if (!p2)
+ if (p2 == NULL || !BN_is_odd((BIGNUM *)p2) || BN_is_one((BIGNUM *)p2)) {
+ RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_BAD_E_VALUE);
return -2;
+ }
BN_free(rctx->pub_exp);
rctx->pub_exp = p2;
return 1;
diff --git a/crypto/sha/asm/sha1-x86_64.pl b/crypto/sha/asm/sha1-x86_64.pl
index 5f375fc688..752138b0ea 100755
--- a/crypto/sha/asm/sha1-x86_64.pl
+++ b/crypto/sha/asm/sha1-x86_64.pl
@@ -372,9 +372,9 @@ $code.=<<___;
.align 16
.Loop_shaext:
dec $num
- lea 0x40($inp),%rax # next input block
+ lea 0x40($inp),%r8 # next input block
paddd @MSG[0],$E
- cmovne %rax,$inp
+ cmovne %r8,$inp
movdqa $ABCD,$ABCD_SAVE # offload $ABCD
___
for($i=0;$i<20-4;$i+=2) {
diff --git a/crypto/srp/srp_vfy.c b/crypto/srp/srp_vfy.c
index 986babfd49..af557a1ac3 100644
--- a/crypto/srp/srp_vfy.c
+++ b/crypto/srp/srp_vfy.c
@@ -635,7 +635,8 @@ char *SRP_create_verifier(const char *user, const char *pass, char **salt,
BN_free(N_bn);
BN_free(g_bn);
}
- OPENSSL_cleanse(vf, vfsize);
+ if (vf != NULL)
+ OPENSSL_cleanse(vf, vfsize);
OPENSSL_free(vf);
BN_clear_free(s);
BN_clear_free(v);
diff --git a/crypto/ts/ts.h b/crypto/ts/ts.h
index 16eccbb38d..2daa1b2fb5 100644
--- a/crypto/ts/ts.h
+++ b/crypto/ts/ts.h
@@ -565,6 +565,9 @@ int TS_RESP_CTX_set_clock_precision_digits(TS_RESP_CTX *ctx,
/* At most we accept usec precision. */
# define TS_MAX_CLOCK_PRECISION_DIGITS 6
+/* Maximum status message length */
+# define TS_MAX_STATUS_LENGTH (1024 * 1024)
+
/* No flags are set by default. */
void TS_RESP_CTX_add_flags(TS_RESP_CTX *ctx, int flags);
diff --git a/crypto/ts/ts_rsp_verify.c b/crypto/ts/ts_rsp_verify.c
index 97d9c81db6..7918236287 100644
--- a/crypto/ts/ts_rsp_verify.c
+++ b/crypto/ts/ts_rsp_verify.c
@@ -555,13 +555,15 @@ static int TS_check_status_info(TS_RESP *response)
static char *TS_get_status_text(STACK_OF(ASN1_UTF8STRING) *text)
{
int i;
- unsigned int length = 0;
+ int length = 0;
char *result = NULL;
char *p;
/* Determine length first. */
for (i = 0; i < sk_ASN1_UTF8STRING_num(text); ++i) {
ASN1_UTF8STRING *current = sk_ASN1_UTF8STRING_value(text, i);
+ if (ASN1_STRING_length(current) > TS_MAX_STATUS_LENGTH - length - 1)
+ return NULL;
length += ASN1_STRING_length(current);
length += 1; /* separator character */
}
diff --git a/crypto/ui/ui_lib.c b/crypto/ui/ui_lib.c
index 2f580352ce..d25b4f37bd 100644
--- a/crypto/ui/ui_lib.c
+++ b/crypto/ui/ui_lib.c
@@ -413,6 +413,8 @@ char *UI_construct_prompt(UI *ui, const char *object_desc,
len += sizeof(prompt3) - 1;
prompt = (char *)OPENSSL_malloc(len + 1);
+ if (prompt == NULL)
+ return NULL;
BUF_strlcpy(prompt, prompt1, len + 1);
BUF_strlcat(prompt, object_desc, len + 1);
if (object_name) {
diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c
index 9ee8f8d859..bbc3189381 100644
--- a/crypto/x509/by_dir.c
+++ b/crypto/x509/by_dir.c
@@ -401,6 +401,10 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
}
if (!hent) {
hent = OPENSSL_malloc(sizeof(BY_DIR_HASH));
+ if (hent == NULL) {
+ X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE);
+ goto finish;
+ }
hent->hash = h;
hent->suffix = k;
if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) {
diff --git a/crypto/x509/x509_r2x.c b/crypto/x509/x509_r2x.c
index 0ff439c99f..2879569ead 100644
--- a/crypto/x509/x509_r2x.c
+++ b/crypto/x509/x509_r2x.c
@@ -70,10 +70,12 @@ X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey)
X509 *ret = NULL;
X509_CINF *xi = NULL;
X509_NAME *xn;
+ EVP_PKEY *pubkey = NULL;
+ int res;
if ((ret = X509_new()) == NULL) {
X509err(X509_F_X509_REQ_TO_X509, ERR_R_MALLOC_FAILURE);
- goto err;
+ return NULL;
}
/* duplicate the request */
@@ -89,9 +91,9 @@ X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey)
}
xn = X509_REQ_get_subject_name(r);
- if (X509_set_subject_name(ret, X509_NAME_dup(xn)) == 0)
+ if (X509_set_subject_name(ret, xn) == 0)
goto err;
- if (X509_set_issuer_name(ret, X509_NAME_dup(xn)) == 0)
+ if (X509_set_issuer_name(ret, xn) == 0)
goto err;
if (X509_gmtime_adj(xi->validity->notBefore, 0) == NULL)
@@ -100,9 +102,11 @@ X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey)
NULL)
goto err;
- X509_set_pubkey(ret, X509_REQ_get_pubkey(r));
+ pubkey = X509_REQ_get_pubkey(r);
+ res = X509_set_pubkey(ret, pubkey);
+ EVP_PKEY_free(pubkey);
- if (!X509_sign(ret, pkey, EVP_md5()))
+ if (!res || !X509_sign(ret, pkey, EVP_md5()))
goto err;
if (0) {
err:
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index ade5985db5..8334b3fcff 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -992,6 +992,8 @@ static int check_cert(X509_STORE_CTX *ctx)
ctx->current_issuer = NULL;
ctx->current_crl_score = 0;
ctx->current_reasons = 0;
+ if (x->ex_flags & EXFLAG_PROXY)
+ return 1;
while (ctx->current_reasons != CRLDP_ALL_REASONS) {
last_reasons = ctx->current_reasons;
/* Try to retrieve relevant CRL */
diff --git a/crypto/x509v3/v3_alt.c b/crypto/x509v3/v3_alt.c
index 22ec202846..7f1e71dd1a 100644
--- a/crypto/x509v3/v3_alt.c
+++ b/crypto/x509v3/v3_alt.c
@@ -573,6 +573,8 @@ static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
return 0;
objlen = p - value;
objtmp = OPENSSL_malloc(objlen + 1);
+ if (objtmp == NULL)
+ return 0;
strncpy(objtmp, value, objlen);
objtmp[objlen] = 0;
gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
diff --git a/doc/apps/cms.pod b/doc/apps/cms.pod
index 4eaedbcd34..ac69804228 100644
--- a/doc/apps/cms.pod
+++ b/doc/apps/cms.pod
@@ -86,6 +86,9 @@ encrypt mail for the given recipient certificates. Input file is the message
to be encrypted. The output file is the encrypted mail in MIME format. The
actual CMS type is <B>EnvelopedData<B>.
+Note that no revocation check is done for the recipient cert, so if that
+key has been compromised, others may be able to decrypt the text.
+
=item B<-decrypt>
decrypt mail using the supplied certificate and private key. Expects an
diff --git a/doc/apps/smime.pod b/doc/apps/smime.pod
index d5618c8ff0..04a83ca8e4 100644
--- a/doc/apps/smime.pod
+++ b/doc/apps/smime.pod
@@ -53,6 +53,9 @@ The meaning of the other options varies according to the operation type.
encrypt mail for the given recipient certificates. Input file is the message
to be encrypted. The output file is the encrypted mail in MIME format.
+Note that no revocation check is done for the recipient cert, so if that
+key has been compromised, others may be able to decrypt the text.
+
=item B<-decrypt>
decrypt mail using the supplied certificate and private key. Expects an
diff --git a/doc/crypto/OBJ_nid2obj.pod b/doc/crypto/OBJ_nid2obj.pod
index 24313986a3..b8d289673d 100644
--- a/doc/crypto/OBJ_nid2obj.pod
+++ b/doc/crypto/OBJ_nid2obj.pod
@@ -122,7 +122,7 @@ Create an object for B<commonName>:
Check if an object is B<commonName>
if (OBJ_obj2nid(obj) == NID_commonName)
- /* Do something */
+ /* Do something */
Create a new NID and initialize an object from it:
@@ -150,6 +150,8 @@ than enough to handle any OID encountered in practice.
OBJ_nid2obj() returns an B<ASN1_OBJECT> structure or B<NULL> is an
error occurred.
+It returns a pointer to an internal table and does not
+allocate memory; ASN1_OBJECT_free() will have no effect.
OBJ_nid2ln() and OBJ_nid2sn() returns a valid string or B<NULL>
on error.
diff --git a/engines/ccgost/gost2001.c b/engines/ccgost/gost2001.c
index 9536295430..881d0d3c90 100644
--- a/engines/ccgost/gost2001.c
+++ b/engines/ccgost/gost2001.c
@@ -434,8 +434,16 @@ int gost2001_compute_public(EC_KEY *ec)
int gost2001_keygen(EC_KEY *ec)
{
BIGNUM *order = BN_new(), *d = BN_new();
- const EC_GROUP *group = EC_KEY_get0_group(ec);
+ const EC_GROUP *group = NULL;
+
+ if (order == NULL || d == NULL) {
+ GOSTerr(GOST_F_GOST2001_KEYGEN, ERR_R_MALLOC_FAILURE);
+ BN_free(d);
+ BN_free(order);
+ return 0;
+ }
+ group = EC_KEY_get0_group(ec);
if(!group || !EC_GROUP_get_order(group, order, NULL)) {
GOSTerr(GOST_F_GOST2001_KEYGEN, ERR_R_INTERNAL_ERROR);
BN_free(d);
diff --git a/engines/ccgost/gost2001_keyx.c b/engines/ccgost/gost2001_keyx.c
index db1bdc18fd..ac7862eab5 100644
--- a/engines/ccgost/gost2001_keyx.c
+++ b/engines/ccgost/gost2001_keyx.c
@@ -147,6 +147,8 @@ int pkey_GOST01cp_encrypt(EVP_PKEY_CTX *pctx, unsigned char *out,
key_is_ephemeral = 1;
if (out) {
sec_key = EVP_PKEY_new();
+ if (sec_key == NULL)
+ goto err;
EVP_PKEY_assign(sec_key, EVP_PKEY_base_id(pubk), EC_KEY_new());
EVP_PKEY_copy_parameters(sec_key, pubk);
if (!gost2001_keygen(EVP_PKEY_get0(sec_key))) {
diff --git a/engines/ccgost/gost94_keyx.c b/engines/ccgost/gost94_keyx.c
index ce57f17cbf..3532bfff3e 100644
--- a/engines/ccgost/gost94_keyx.c
+++ b/engines/ccgost/gost94_keyx.c
@@ -126,6 +126,8 @@ int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out,
key_is_ephemeral = 1;
if (out) {
mykey = EVP_PKEY_new();
+ if (!mykey)
+ goto memerr;
EVP_PKEY_assign(mykey, EVP_PKEY_base_id(pubk), DSA_new());
EVP_PKEY_copy_parameters(mykey, pubk);
if (!gost_sign_keygen(EVP_PKEY_get0(mykey))) {
diff --git a/engines/ccgost/gost_ameth.c b/engines/ccgost/gost_ameth.c
index b7c5354c1a..8283f192f4 100644
--- a/engines/ccgost/gost_ameth.c
+++ b/engines/ccgost/gost_ameth.c
@@ -617,6 +617,10 @@ static int pub_decode_gost94(EVP_PKEY *pk, X509_PUBKEY *pub)
return 0;
}
databuf = OPENSSL_malloc(octet->length);
+ if (databuf == NULL) {
+ GOSTerr(GOST_F_PUB_DECODE_GOST94, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
for (i = 0, j = octet->length - 1; i < octet->length; i++, j--) {
databuf[j] = octet->data[i];
}
@@ -646,6 +650,8 @@ static int pub_encode_gost94(X509_PUBKEY *pub, const EVP_PKEY *pk)
}
data_len = BN_num_bytes(dsa->pub_key);
databuf = OPENSSL_malloc(data_len);
+ if (databuf == NULL)
+ return 0;
BN_bn2bin(dsa->pub_key, databuf);
octet = ASN1_OCTET_STRING_new();
ASN1_STRING_set(octet, NULL, data_len);
@@ -686,6 +692,10 @@ static int pub_decode_gost01(EVP_PKEY *pk, X509_PUBKEY *pub)
return 0;
}
databuf = OPENSSL_malloc(octet->length);
+ if (databuf == NULL) {
+ GOSTerr(GOST_F_PUB_DECODE_GOST01, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
for (i = 0, j = octet->length - 1; i < octet->length; i++, j--) {
databuf[j] = octet->data[i];
}
@@ -760,6 +770,10 @@ static int pub_encode_gost01(X509_PUBKEY *pub, const EVP_PKEY *pk)
data_len = 2 * BN_num_bytes(order);
BN_free(order);
databuf = OPENSSL_malloc(data_len);
+ if (databuf == NULL) {
+ GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
memset(databuf, 0, data_len);
store_bignum(X, databuf + data_len / 2, data_len / 2);
diff --git a/engines/ccgost/gost_pmeth.c b/engines/ccgost/gost_pmeth.c
index 4a79a85cfc..696829253b 100644
--- a/engines/ccgost/gost_pmeth.c
+++ b/engines/ccgost/gost_pmeth.c
@@ -107,6 +107,8 @@ static int pkey_gost_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
return 1;
case EVP_PKEY_CTRL_SET_IV:
pctx->shared_ukm = OPENSSL_malloc((int)p1);
+ if (pctx->shared_ukm == NULL)
+ return 0;
memcpy(pctx->shared_ukm, p2, (int)p1);
return 1;
case EVP_PKEY_CTRL_PEER_KEY:
@@ -533,6 +535,8 @@ static int pkey_gost_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
return 0;
}
keydata = OPENSSL_malloc(32);
+ if (keydata == NULL)
+ return 0;
memcpy(keydata, data->key, 32);
EVP_PKEY_assign(pkey, NID_id_Gost28147_89_MAC, keydata);
return 1;
diff --git a/engines/e_4758cca.c b/engines/e_4758cca.c
index 5f771986cf..60ba4abcdf 100644
--- a/engines/e_4758cca.c
+++ b/engines/e_4758cca.c
@@ -463,6 +463,10 @@ static EVP_PKEY *ibm_4758_load_privkey(ENGINE *e, const char *key_id,
(*(long *)keyToken) = keyTokenLength;
rtmp = RSA_new_method(e);
+ if (rtmp == NULL) {
+ CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
RSA_set_ex_data(rtmp, hndidx, (char *)keyToken);
rtmp->e = BN_bin2bn(exponent, exponentLength, NULL);
@@ -535,6 +539,10 @@ static EVP_PKEY *ibm_4758_load_pubkey(ENGINE *e, const char *key_id,
(*(long *)keyToken) = keyTokenLength;
rtmp = RSA_new_method(e);
+ if (rtmp == NULL) {
+ CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
RSA_set_ex_data(rtmp, hndidx, (char *)keyToken);
rtmp->e = BN_bin2bn(exponent, exponentLength, NULL);
rtmp->n = BN_bin2bn(modulus, modulusFieldLength, NULL);
diff --git a/engines/e_aep.c b/engines/e_aep.c
index 9bfda76a92..4e97d29497 100644
--- a/engines/e_aep.c
+++ b/engines/e_aep.c
@@ -1137,7 +1137,8 @@ static AEP_RV ConvertAEPBigNum(void *ArbBigNum, AEP_U32 BigNumSize,
/*
* Expand the result bn so that it can hold our big num. Size is in bits
*/
- bn_expand(bn, (int)(BigNumSize << 3));
+ if (bn_expand(bn, (int)(BigNumSize << 3)) == NULL)
+ return AEP_R_HOST_MEMORY;
# ifdef SIXTY_FOUR_BIT_LONG
bn->top = BigNumSize >> 3;
diff --git a/engines/e_capi.c b/engines/e_capi.c
index 6e524633f3..8c08872bfd 100644
--- a/engines/e_capi.c
+++ b/engines/e_capi.c
@@ -1106,6 +1106,10 @@ static int capi_get_provname(CAPI_CTX * ctx, LPSTR * pname, DWORD * ptype,
name = alloca(len);
else
name = OPENSSL_malloc(len);
+ if (name == NULL) {
+ CAPIerr(CAPI_F_CAPI_GET_PROVNAME, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
if (!CryptEnumProviders(idx, NULL, 0, ptype, name, &len)) {
err = GetLastError();
if (err == ERROR_NO_MORE_ITEMS)
@@ -1286,6 +1290,10 @@ char *capi_cert_get_fname(CAPI_CTX * ctx, PCCERT_CONTEXT cert)
(cert, CERT_FRIENDLY_NAME_PROP_ID, NULL, &dlen))
return NULL;
wfname = OPENSSL_malloc(dlen);
+ if (wfname == NULL) {
+ CAPIerr(CAPI_F_CAPI_CERT_GET_FNAME, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
if (CertGetCertificateContextProperty
(cert, CERT_FRIENDLY_NAME_PROP_ID, wfname, &dlen)) {
char *fname = wide_to_asc(wfname);
@@ -1436,6 +1444,11 @@ static CAPI_KEY *capi_get_key(CAPI_CTX * ctx, const TCHAR *contname,
CAPI_KEY *key;
DWORD dwFlags = 0;
key = OPENSSL_malloc(sizeof(CAPI_KEY));
+ if (key == NULL) {
+ CAPIerr(CAPI_F_CAPI_GET_KEY, ERR_R_MALLOC_FAILURE);
+ capi_addlasterror();
+ goto err;
+ }
if (sizeof(TCHAR) == sizeof(char))
CAPI_trace(ctx, "capi_get_key, contname=%s, provname=%s, type=%d\n",
contname, provname, ptype);
diff --git a/engines/e_chil.c b/engines/e_chil.c
index 5e725f5fb1..d5e4cb67c4 100644
--- a/engines/e_chil.c
+++ b/engines/e_chil.c
@@ -810,9 +810,17 @@ static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
# endif
# ifndef OPENSSL_NO_RSA
rtmp = RSA_new_method(eng);
+ if (rtmp == NULL) {
+ HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
rtmp->e = BN_new();
rtmp->n = BN_new();
+ if (rtmp->e == NULL || rtmp->n == NULL) {
+ HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
rtmp->flags |= RSA_FLAG_EXT_PKEY;
MPI2BN(rtmp->e, e);
MPI2BN(rtmp->n, n);
@@ -823,8 +831,14 @@ static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
goto err;
}
- bn_expand2(rtmp->e, e.size / sizeof(BN_ULONG));
- bn_expand2(rtmp->n, n.size / sizeof(BN_ULONG));
+ if (bn_expand2(rtmp->e, e.size / sizeof(BN_ULONG)) == NULL) {
+ HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (bn_expand2(rtmp->n, n.size / sizeof(BN_ULONG)) == NULL) {
+ HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
MPI2BN(rtmp->e, e);
MPI2BN(rtmp->n, n);
@@ -923,7 +937,10 @@ static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
goto err;
}
/* Prepare the params */
- bn_expand2(r, m->top); /* Check for error !! */
+ if (bn_expand2(r, m->top) == NULL) { /* Check for error !! */
+ HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
BN2MPI(m_a, a);
BN2MPI(m_p, p);
BN2MPI(m_n, m);
@@ -989,7 +1006,10 @@ static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa,
}
/* Prepare the params */
- bn_expand2(r, rsa->n->top); /* Check for error !! */
+ if (bn_expand2(r, rsa->n->top) == NULL) { /* Check for error !! */
+ HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
BN2MPI(m_a, I);
MPI2BN(r, m_r);
@@ -1026,7 +1046,10 @@ static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa,
}
/* Prepare the params */
- bn_expand2(r, rsa->n->top); /* Check for error !! */
+ if (bn_expand2(r, rsa->n->top) == NULL) { /* Check for error !! */
+ HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
BN2MPI(m_a, I);
BN2MPI(m_p, rsa->p);
BN2MPI(m_q, rsa->q);
diff --git a/ssl/Makefile b/ssl/Makefile
index b6dee5b5ea..dd12962250 100644
--- a/ssl/Makefile
+++ b/ssl/Makefile
@@ -15,7 +15,7 @@ KRB5_INCLUDES=
CFLAGS= $(INCLUDES) $(CFLAG)
GENERAL=Makefile README ssl-lib.com install.com
-TEST=ssltest.c heartbeat_test.c clienthellotest.c sslv2conftest.c
+TEST=ssltest.c heartbeat_test.c clienthellotest.c sslv2conftest.c dtlstest.c bad_dtls_test.c
APPS=
LIB=$(TOP)/libssl.a
diff --git a/ssl/bad_dtls_test.c b/ssl/bad_dtls_test.c
new file mode 100644
index 0000000000..d42817fc32
--- /dev/null
+++ b/ssl/bad_dtls_test.c
@@ -0,0 +1,923 @@
+/*
+ * Copyright 2016 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
+ */
+
+/*
+ * Unit test for Cisco DTLS1_BAD_VER session resume, as used by
+ * AnyConnect VPN protocol.
+ *
+ * This is designed to exercise the code paths in
+ * http://git.infradead.org/users/dwmw2/openconnect.git/blob/HEAD:/dtls.c
+ * which have frequently been affected by regressions in DTLS1_BAD_VER
+ * support.
+ *
+ * Note that unlike other SSL tests, we don't test against our own SSL
+ * server method. Firstly because we don't have one; we *only* support
+ * DTLS1_BAD_VER as a client. And secondly because even if that were
+ * fixed up it's the wrong thing to test against — because if changes
+ * are made in generic DTLS code which don't take DTLS1_BAD_VER into
+ * account, there's plenty of scope for making those changes such that
+ * they break *both* the client and the server in the same way.
+ *
+ * So we handle the server side manually. In a session resume there isn't
+ * much to be done anyway.
+ */
+#include <string.h>
+
+/* On Windows this will include <winsock2.h> and thus it needs to be
+ * included *before* anything that includes <windows.h>. Ick. */
+#include "e_os.h" /* for 'inline' */
+
+#include <openssl/bio.h>
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+
+/* PACKET functions lifted from OpenSSL 1.1's ssl/packet_locl.h */
+typedef struct {
+ /* Pointer to where we are currently reading from */
+ const unsigned char *curr;
+ /* Number of bytes remaining */
+ size_t remaining;
+} PACKET;
+
+/* Internal unchecked shorthand; don't use outside this file. */
+static inline void packet_forward(PACKET *pkt, size_t len)
+{
+ pkt->curr += len;
+ pkt->remaining -= len;
+}
+
+/*
+ * Returns the number of bytes remaining to be read in the PACKET
+ */
+static inline size_t PACKET_remaining(const PACKET *pkt)
+{
+ return pkt->remaining;
+}
+
+/*
+ * Initialise a PACKET with |len| bytes held in |buf|. This does not make a
+ * copy of the data so |buf| must be present for the whole time that the PACKET
+ * is being used.
+ */
+static inline int PACKET_buf_init(PACKET *pkt,
+ const unsigned char *buf,
+ size_t len)
+{
+ /* Sanity check for negative values. */
+ if (len > (size_t)65536)
+ return 0;
+
+ pkt->curr = buf;
+ pkt->remaining = len;
+ return 1;
+}
+
+/*
+ * Returns 1 if the packet has length |num| and its contents equal the |num|
+ * bytes read from |ptr|. Returns 0 otherwise (lengths or contents not equal).
+ * If lengths are equal, performs the comparison in constant time.
+ */
+static inline int PACKET_equal(const PACKET *pkt, const void *ptr,
+ size_t num)
+{
+ if (PACKET_remaining(pkt) != num)
+ return 0;
+ return CRYPTO_memcmp(pkt->curr, ptr, num) == 0;
+}
+
+/*
+ * Peek ahead at 2 bytes in network order from |pkt| and store the value in
+ * |*data|
+ */
+static inline int PACKET_peek_net_2(const PACKET *pkt,
+ unsigned int *data)
+{
+ if (PACKET_remaining(pkt) < 2)
+ return 0;
+
+ *data = ((unsigned int)(*pkt->curr)) << 8;
+ *data |= *(pkt->curr + 1);
+
+ return 1;
+}
+
+/* Equivalent of n2s */
+/* Get 2 bytes in network order from |pkt| and store the value in |*data| */
+static inline int PACKET_get_net_2(PACKET *pkt,
+ unsigned int *data)
+{
+ if (!PACKET_peek_net_2(pkt, data))
+ return 0;
+
+ packet_forward(pkt, 2);
+
+ return 1;
+}
+
+/* Peek ahead at 1 byte from |pkt| and store the value in |*data| */
+static inline int PACKET_peek_1(const PACKET *pkt,
+ unsigned int *data)
+{
+ if (!PACKET_remaining(pkt))
+ return 0;
+
+ *data = *pkt->curr;
+
+ return 1;
+}
+
+/* Get 1 byte from |pkt| and store the value in |*data| */
+static inline int PACKET_get_1(PACKET *pkt, unsigned int *data)
+{
+ if (!PACKET_peek_1(pkt, data))
+ return 0;
+
+ packet_forward(pkt, 1);
+
+ return 1;
+}
+
+/*
+ * Peek ahead at |len| bytes from the |pkt| and store a pointer to them in
+ * |*data|. This just points at the underlying buffer that |pkt| is using. The
+ * caller should not free this data directly (it will be freed when the
+ * underlying buffer gets freed
+ */
+static inline int PACKET_peek_bytes(const PACKET *pkt,
+ const unsigned char **data,
+ size_t len)
+{
+ if (PACKET_remaining(pkt) < len)
+ return 0;
+
+ *data = pkt->curr;
+
+ return 1;
+}
+
+/*
+ * Read |len| bytes from the |pkt| and store a pointer to them in |*data|. This
+ * just points at the underlying buffer that |pkt| is using. The caller should
+ * not free this data directly (it will be freed when the underlying buffer gets
+ * freed
+ */
+static inline int PACKET_get_bytes(PACKET *pkt,
+ const unsigned char **data,
+ size_t len)
+{
+ if (!PACKET_peek_bytes(pkt, data, len))
+ return 0;
+
+ packet_forward(pkt, len);
+
+ return 1;
+}
+
+/* Peek ahead at |len| bytes from |pkt| and copy them to |data| */
+static inline int PACKET_peek_copy_bytes(const PACKET *pkt,
+ unsigned char *data,
+ size_t len)
+{
+ if (PACKET_remaining(pkt) < len)
+ return 0;
+
+ memcpy(data, pkt->curr, len);
+
+ return 1;
+}
+
+/*
+ * Read |len| bytes from |pkt| and copy them to |data|.
+ * The caller is responsible for ensuring that |data| can hold |len| bytes.
+ */
+static inline int PACKET_copy_bytes(PACKET *pkt,
+ unsigned char *data,
+ size_t len)
+{
+ if (!PACKET_peek_copy_bytes(pkt, data, len))
+ return 0;
+
+ packet_forward(pkt, len);
+
+ return 1;
+}
+
+
+/* Move the current reading position forward |len| bytes */
+static inline int PACKET_forward(PACKET *pkt, size_t len)
+{
+ if (PACKET_remaining(pkt) < len)
+ return 0;
+
+ packet_forward(pkt, len);
+
+ return 1;
+}
+
+/*
+ * Reads a variable-length vector prefixed with a one-byte length, and stores
+ * the contents in |subpkt|. |pkt| can equal |subpkt|.
+ * Data is not copied: the |subpkt| packet will share its underlying buffer with
+ * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
+ * Upon failure, the original |pkt| and |subpkt| are not modified.
+ */
+static inline int PACKET_get_length_prefixed_1(PACKET *pkt,
+ PACKET *subpkt)
+{
+ unsigned int length;
+ const unsigned char *data;
+ PACKET tmp = *pkt;
+ if (!PACKET_get_1(&tmp, &length) ||
+ !PACKET_get_bytes(&tmp, &data, (size_t)length)) {
+ return 0;
+ }
+
+ *pkt = tmp;
+ subpkt->curr = data;
+ subpkt->remaining = length;
+
+ return 1;
+}
+
+#define OSSL_NELEM(x) (sizeof(x)/sizeof(x[0]))
+
+/* For DTLS1_BAD_VER packets the MAC doesn't include the handshake header */
+#define MAC_OFFSET (DTLS1_RT_HEADER_LENGTH + DTLS1_HM_HEADER_LENGTH)
+
+static unsigned char client_random[SSL3_RANDOM_SIZE];
+static unsigned char server_random[SSL3_RANDOM_SIZE];
+
+/* These are all generated locally, sized purely according to our own whim */
+static unsigned char session_id[32];
+static unsigned char master_secret[48];
+static unsigned char cookie[20];
+
+/* We've hard-coded the cipher suite; we know it's 104 bytes */
+static unsigned char key_block[104];
+#define mac_key (key_block + 20)
+#define dec_key (key_block + 40)
+#define enc_key (key_block + 56)
+
+static EVP_MD_CTX handshake_md5;
+static EVP_MD_CTX handshake_sha1;
+
+/* PRF lifted from ssl/t1_enc.c since we can't easily use it directly */
+static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
+ int sec_len,
+ const void *seed1, int seed1_len,
+ const void *seed2, int seed2_len,
+ const void *seed3, int seed3_len,
+ unsigned char *out, int olen)
+{
+ int chunk;
+ size_t j;
+ EVP_MD_CTX ctx, ctx_tmp, ctx_init;
+ EVP_PKEY *prf_mac_key;
+ unsigned char A1[EVP_MAX_MD_SIZE];
+ size_t A1_len;
+ int ret = 0;
+
+ chunk = EVP_MD_size(md);
+ OPENSSL_assert(chunk >= 0);
+
+ EVP_MD_CTX_init(&ctx);
+ EVP_MD_CTX_init(&ctx_tmp);
+ EVP_MD_CTX_init(&ctx_init);
+ EVP_MD_CTX_set_flags(&ctx_init, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+ prf_mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, sec, sec_len);
+ if (!prf_mac_key)
+ goto err;
+ if (!EVP_DigestSignInit(&ctx_init, NULL, md, NULL, prf_mac_key))
+ goto err;
+ if (!EVP_MD_CTX_copy_ex(&ctx, &ctx_init))
+ goto err;
+ if (seed1 && !EVP_DigestSignUpdate(&ctx, seed1, seed1_len))
+ goto err;
+ if (seed2 && !EVP_DigestSignUpdate(&ctx, seed2, seed2_len))
+ goto err;
+ if (seed3 && !EVP_DigestSignUpdate(&ctx, seed3, seed3_len))
+ goto err;
+ if (!EVP_DigestSignFinal(&ctx, A1, &A1_len))
+ goto err;
+
+ for (;;) {
+ /* Reinit mac contexts */
+ if (!EVP_MD_CTX_copy_ex(&ctx, &ctx_init))
+ goto err;
+ if (!EVP_DigestSignUpdate(&ctx, A1, A1_len))
+ goto err;
+ if (olen > chunk && !EVP_MD_CTX_copy_ex(&ctx_tmp, &ctx))
+ goto err;
+ if (seed1 && !EVP_DigestSignUpdate(&ctx, seed1, seed1_len))
+ goto err;
+ if (seed2 && !EVP_DigestSignUpdate(&ctx, seed2, seed2_len))
+ goto err;
+ if (seed3 && !EVP_DigestSignUpdate(&ctx, seed3, seed3_len))
+ goto err;
+
+ if (olen > chunk) {
+ if (!EVP_DigestSignFinal(&ctx, out, &j))
+ goto err;
+ out += j;
+ olen -= j;
+ /* calc the next A1 value */
+ if (!EVP_DigestSignFinal(&ctx_tmp, A1, &A1_len))
+ goto err;
+ } else { /* last one */
+
+ if (!EVP_DigestSignFinal(&ctx, A1, &A1_len))
+ goto err;
+ memcpy(out, A1, olen);
+ break;
+ }
+ }
+ ret = 1;
+ err:
+ EVP_PKEY_free(prf_mac_key);
+ EVP_MD_CTX_cleanup(&ctx);
+ EVP_MD_CTX_cleanup(&ctx_tmp);
+ EVP_MD_CTX_cleanup(&ctx_init);
+ OPENSSL_cleanse(A1, sizeof(A1));
+ return ret;
+}
+
+/* seed1 through seed5 are virtually concatenated */
+static int do_PRF(const void *seed1, int seed1_len,
+ const void *seed2, int seed2_len,
+ const void *seed3, int seed3_len,
+ unsigned char *out, int olen)
+{
+ unsigned char out2[104];
+ int i, len;
+
+ if (olen > (int)sizeof(out2))
+ return 0;
+
+ len = sizeof(master_secret) / 2;
+
+ if (!tls1_P_hash(EVP_md5(), master_secret, len,
+ seed1, seed1_len, seed2, seed2_len, seed3,
+ seed3_len, out, olen))
+ return 0;
+
+ if (!tls1_P_hash(EVP_sha1(), master_secret + len, len,
+ seed1, seed1_len, seed2, seed2_len, seed3,
+ seed3_len, out2, olen))
+ return 0;
+
+ for (i = 0; i < olen; i++) {
+ out[i] ^= out2[i];
+ }
+
+ return 1;
+}
+
+static SSL_SESSION *client_session(void)
+{
+ static unsigned char session_asn1[] = {
+ 0x30, 0x5F, /* SEQUENCE, length 0x5F */
+ 0x02, 0x01, 0x01, /* INTEGER, SSL_SESSION_ASN1_VERSION */
+ 0x02, 0x02, 0x01, 0x00, /* INTEGER, DTLS1_BAD_VER */
+ 0x04, 0x02, 0x00, 0x2F, /* OCTET_STRING, AES128-SHA */
+ 0x04, 0x20, /* OCTET_STRING, session id */
+#define SS_SESSID_OFS 15 /* Session ID goes here */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x30, /* OCTET_STRING, master secret */
+#define SS_SECRET_OFS 49 /* Master secret goes here */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+ const unsigned char *p = session_asn1;
+
+ /* Copy the randomly-generated fields into the above ASN1 */
+ memcpy(session_asn1 + SS_SESSID_OFS, session_id, sizeof(session_id));
+ memcpy(session_asn1 + SS_SECRET_OFS, master_secret, sizeof(master_secret));
+
+ return d2i_SSL_SESSION(NULL, &p, sizeof(session_asn1));
+}
+
+/* Returns 1 for initial ClientHello, 2 for ClientHello with cookie */
+static int validate_client_hello(BIO *wbio)
+{
+ PACKET pkt, pkt2;
+ long len;
+ unsigned char *data;
+ int cookie_found = 0;
+ unsigned int u;
+
+ len = BIO_get_mem_data(wbio, (char **)&data);
+ if (!PACKET_buf_init(&pkt, data, len))
+ return 0;
+
+ /* Check record header type */
+ if (!PACKET_get_1(&pkt, &u) || u != SSL3_RT_HANDSHAKE)
+ return 0;
+ /* Version */
+ if (!PACKET_get_net_2(&pkt, &u) || u != DTLS1_BAD_VER)
+ return 0;
+ /* Skip the rest of the record header */
+ if (!PACKET_forward(&pkt, DTLS1_RT_HEADER_LENGTH - 3))
+ return 0;
+
+ /* Check it's a ClientHello */
+ if (!PACKET_get_1(&pkt, &u) || u != SSL3_MT_CLIENT_HELLO)
+ return 0;
+ /* Skip the rest of the handshake message header */
+ if (!PACKET_forward(&pkt, DTLS1_HM_HEADER_LENGTH - 1))
+ return 0;
+
+ /* Check client version */
+ if (!PACKET_get_net_2(&pkt, &u) || u != DTLS1_BAD_VER)
+ return 0;
+
+ /* Store random */
+ if (!PACKET_copy_bytes(&pkt, client_random, SSL3_RANDOM_SIZE))
+ return 0;
+
+ /* Check session id length and content */
+ if (!PACKET_get_length_prefixed_1(&pkt, &pkt2) ||
+ !PACKET_equal(&pkt2, session_id, sizeof(session_id)))
+ return 0;
+
+ /* Check cookie */
+ if (!PACKET_get_length_prefixed_1(&pkt, &pkt2))
+ return 0;
+ if (PACKET_remaining(&pkt2)) {
+ if (!PACKET_equal(&pkt2, cookie, sizeof(cookie)))
+ return 0;
+ cookie_found = 1;
+ }
+
+ /* Skip ciphers */
+ if (!PACKET_get_net_2(&pkt, &u) || !PACKET_forward(&pkt, u))
+ return 0;
+
+ /* Skip compression */
+ if (!PACKET_get_1(&pkt, &u) || !PACKET_forward(&pkt, u))
+ return 0;
+
+ /* Skip extensions */
+ if (!PACKET_get_net_2(&pkt, &u) || !PACKET_forward(&pkt, u))
+ return 0;
+
+ /* Now we are at the end */
+ if (PACKET_remaining(&pkt))
+ return 0;
+
+ /* Update handshake MAC for second ClientHello (with cookie) */
+ if (cookie_found && (!EVP_DigestUpdate(&handshake_md5, data + MAC_OFFSET,
+ len - MAC_OFFSET) ||
+ !EVP_DigestUpdate(&handshake_sha1, data + MAC_OFFSET,
+ len - MAC_OFFSET)))
+ printf("EVP_DigestUpdate() failed\n");
+
+ (void)BIO_reset(wbio);
+
+ return 1 + cookie_found;
+}
+
+static int send_hello_verify(BIO *rbio)
+{
+ static unsigned char hello_verify[] = {
+ 0x16, /* Handshake */
+ 0x01, 0x00, /* DTLS1_BAD_VER */
+ 0x00, 0x00, /* Epoch 0 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Seq# 0 */
+ 0x00, 0x23, /* Length */
+ 0x03, /* Hello Verify */
+ 0x00, 0x00, 0x17, /* Length */
+ 0x00, 0x00, /* Seq# 0 */
+ 0x00, 0x00, 0x00, /* Fragment offset */
+ 0x00, 0x00, 0x17, /* Fragment length */
+ 0x01, 0x00, /* DTLS1_BAD_VER */
+ 0x14, /* Cookie length */
+#define HV_COOKIE_OFS 28 /* Cookie goes here */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ };
+
+ memcpy(hello_verify + HV_COOKIE_OFS, cookie, sizeof(cookie));
+
+ BIO_write(rbio, hello_verify, sizeof(hello_verify));
+
+ return 1;
+}
+
+static int send_server_hello(BIO *rbio)
+{
+ static unsigned char server_hello[] = {
+ 0x16, /* Handshake */
+ 0x01, 0x00, /* DTLS1_BAD_VER */
+ 0x00, 0x00, /* Epoch 0 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* Seq# 1 */
+ 0x00, 0x52, /* Length */
+ 0x02, /* Server Hello */
+ 0x00, 0x00, 0x46, /* Length */
+ 0x00, 0x01, /* Seq# */
+ 0x00, 0x00, 0x00, /* Fragment offset */
+ 0x00, 0x00, 0x46, /* Fragment length */
+ 0x01, 0x00, /* DTLS1_BAD_VER */
+#define SH_RANDOM_OFS 27 /* Server random goes here */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, /* Session ID length */
+#define SH_SESSID_OFS 60 /* Session ID goes here */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x2f, /* Cipher suite AES128-SHA */
+ 0x00, /* Compression null */
+ };
+ static unsigned char change_cipher_spec[] = {
+ 0x14, /* Change Cipher Spec */
+ 0x01, 0x00, /* DTLS1_BAD_VER */
+ 0x00, 0x00, /* Epoch 0 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, /* Seq# 2 */
+ 0x00, 0x03, /* Length */
+ 0x01, 0x00, 0x02, /* Message */
+ };
+
+ memcpy(server_hello + SH_RANDOM_OFS, server_random, sizeof(server_random));
+ memcpy(server_hello + SH_SESSID_OFS, session_id, sizeof(session_id));
+
+ if (!EVP_DigestUpdate(&handshake_md5, server_hello + MAC_OFFSET,
+ sizeof(server_hello) - MAC_OFFSET) ||
+ !EVP_DigestUpdate(&handshake_sha1, server_hello + MAC_OFFSET,
+ sizeof(server_hello) - MAC_OFFSET))
+ printf("EVP_DigestUpdate() failed\n");
+
+ BIO_write(rbio, server_hello, sizeof(server_hello));
+ BIO_write(rbio, change_cipher_spec, sizeof(change_cipher_spec));
+
+ return 1;
+}
+
+/* Create header, HMAC, pad, encrypt and send a record */
+static int send_record(BIO *rbio, unsigned char type, unsigned long seqnr,
+ const void *msg, size_t len)
+{
+ /* Note that the order of the record header fields on the wire,
+ * and in the HMAC, is different. So we just keep them in separate
+ * variables and handle them individually. */
+ static unsigned char epoch[2] = { 0x00, 0x01 };
+ static unsigned char seq[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ static unsigned char ver[2] = { 0x01, 0x00 }; /* DTLS1_BAD_VER */
+ unsigned char lenbytes[2];
+ HMAC_CTX ctx;
+ EVP_CIPHER_CTX enc_ctx;
+ unsigned char iv[16];
+ unsigned char pad;
+ unsigned char *enc;
+
+#ifdef SIXTY_FOUR_BIT_LONG
+ seq[0] = (seqnr >> 40) & 0xff;
+ seq[1] = (seqnr >> 32) & 0xff;
+#endif
+ seq[2] = (seqnr >> 24) & 0xff;
+ seq[3] = (seqnr >> 16) & 0xff;
+ seq[4] = (seqnr >> 8) & 0xff;
+ seq[5] = seqnr & 0xff;
+
+ pad = 15 - ((len + SHA_DIGEST_LENGTH) % 16);
+ enc = OPENSSL_malloc(len + SHA_DIGEST_LENGTH + 1 + pad);
+ if (enc == NULL)
+ return 0;
+
+ /* Copy record to encryption buffer */
+ memcpy(enc, msg, len);
+
+ /* Append HMAC to data */
+ HMAC_Init(&ctx, mac_key, 20, EVP_sha1());
+ HMAC_Update(&ctx, epoch, 2);
+ HMAC_Update(&ctx, seq, 6);
+ HMAC_Update(&ctx, &type, 1);
+ HMAC_Update(&ctx, ver, 2); /* Version */
+ lenbytes[0] = len >> 8;
+ lenbytes[1] = len & 0xff;
+ HMAC_Update(&ctx, lenbytes, 2); /* Length */
+ HMAC_Update(&ctx, enc, len); /* Finally the data itself */
+ HMAC_Final(&ctx, enc + len, NULL);
+ HMAC_CTX_cleanup(&ctx);
+
+ /* Append padding bytes */
+ len += SHA_DIGEST_LENGTH;
+ do {
+ enc[len++] = pad;
+ } while (len % 16);
+
+ /* Generate IV, and encrypt */
+ RAND_bytes(iv, sizeof(iv));
+ EVP_CIPHER_CTX_init(&enc_ctx);
+ EVP_CipherInit_ex(&enc_ctx, EVP_aes_128_cbc(), NULL, enc_key, iv, 1);
+ EVP_Cipher(&enc_ctx, enc, enc, len);
+ EVP_CIPHER_CTX_cleanup(&enc_ctx);
+
+ /* Finally write header (from fragmented variables), IV and encrypted record */
+ BIO_write(rbio, &type, 1);
+ BIO_write(rbio, ver, 2);
+ BIO_write(rbio, epoch, 2);
+ BIO_write(rbio, seq, 6);
+ lenbytes[0] = (len + sizeof(iv)) >> 8;
+ lenbytes[1] = (len + sizeof(iv)) & 0xff;
+ BIO_write(rbio, lenbytes, 2);
+
+ BIO_write(rbio, iv, sizeof(iv));
+ BIO_write(rbio, enc, len);
+
+ OPENSSL_free(enc);
+ return 1;
+}
+
+static int send_finished(SSL *s, BIO *rbio)
+{
+ static unsigned char finished_msg[DTLS1_HM_HEADER_LENGTH +
+ TLS1_FINISH_MAC_LENGTH] = {
+ 0x14, /* Finished */
+ 0x00, 0x00, 0x0c, /* Length */
+ 0x00, 0x03, /* Seq# 3 */
+ 0x00, 0x00, 0x00, /* Fragment offset */
+ 0x00, 0x00, 0x0c, /* Fragment length */
+ /* Finished MAC (12 bytes) */
+ };
+ unsigned char handshake_hash[EVP_MAX_MD_SIZE * 2];
+
+ /* Derive key material */
+ do_PRF(TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
+ server_random, SSL3_RANDOM_SIZE,
+ client_random, SSL3_RANDOM_SIZE,
+ key_block, sizeof(key_block));
+
+ /* Generate Finished MAC */
+ if (!EVP_DigestFinal_ex(&handshake_md5, handshake_hash, NULL) ||
+ !EVP_DigestFinal_ex(&handshake_sha1, handshake_hash + EVP_MD_CTX_size(&handshake_md5), NULL))
+ printf("EVP_DigestFinal_ex() failed\n");
+
+ do_PRF(TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
+ handshake_hash, EVP_MD_CTX_size(&handshake_md5) + EVP_MD_CTX_size(&handshake_sha1),
+ NULL, 0,
+ finished_msg + DTLS1_HM_HEADER_LENGTH, TLS1_FINISH_MAC_LENGTH);
+
+ return send_record(rbio, SSL3_RT_HANDSHAKE, 0,
+ finished_msg, sizeof(finished_msg));
+}
+
+static int validate_ccs(BIO *wbio)
+{
+ PACKET pkt;
+ long len;
+ unsigned char *data;
+ unsigned int u;
+
+ len = BIO_get_mem_data(wbio, (char **)&data);
+ if (!PACKET_buf_init(&pkt, data, len))
+ return 0;
+
+ /* Check record header type */
+ if (!PACKET_get_1(&pkt, &u) || u != SSL3_RT_CHANGE_CIPHER_SPEC)
+ return 0;
+ /* Version */
+ if (!PACKET_get_net_2(&pkt, &u) || u != DTLS1_BAD_VER)
+ return 0;
+ /* Skip the rest of the record header */
+ if (!PACKET_forward(&pkt, DTLS1_RT_HEADER_LENGTH - 3))
+ return 0;
+
+ /* Check ChangeCipherSpec message */
+ if (!PACKET_get_1(&pkt, &u) || u != SSL3_MT_CCS)
+ return 0;
+ /* A DTLS1_BAD_VER ChangeCipherSpec also contains the
+ * handshake sequence number (which is 2 here) */
+ if (!PACKET_get_net_2(&pkt, &u) || u != 0x0002)
+ return 0;
+
+ /* Now check the Finished packet */
+ if (!PACKET_get_1(&pkt, &u) || u != SSL3_RT_HANDSHAKE)
+ return 0;
+ if (!PACKET_get_net_2(&pkt, &u) || u != DTLS1_BAD_VER)
+ return 0;
+
+ /* Check epoch is now 1 */
+ if (!PACKET_get_net_2(&pkt, &u) || u != 0x0001)
+ return 0;
+
+ /* That'll do for now. If OpenSSL accepted *our* Finished packet
+ * then it's evidently remembered that DTLS1_BAD_VER doesn't
+ * include the handshake header in the MAC. There's not a lot of
+ * point in implementing decryption here, just to check that it
+ * continues to get it right for one more packet. */
+
+ return 1;
+}
+
+#define NODROP(x) { x##UL, 0 }
+#define DROP(x) { x##UL, 1 }
+
+static struct {
+ unsigned long seq;
+ int drop;
+} tests[] = {
+ NODROP(1), NODROP(3), NODROP(2),
+ NODROP(0x1234), NODROP(0x1230), NODROP(0x1235),
+ NODROP(0xffff), NODROP(0x10001), NODROP(0xfffe), NODROP(0x10000),
+ DROP(0x10001), DROP(0xff), NODROP(0x100000), NODROP(0x800000), NODROP(0x7fffe1),
+ NODROP(0xffffff), NODROP(0x1000000), NODROP(0xfffffe), DROP(0xffffff), NODROP(0x1000010),
+ NODROP(0xfffffd), NODROP(0x1000011), DROP(0x12), NODROP(0x1000012),
+ NODROP(0x1ffffff), NODROP(0x2000000), DROP(0x1ff00fe), NODROP(0x2000001),
+ NODROP(0x20fffff), NODROP(0x2105500), DROP(0x20ffffe), NODROP(0x21054ff),
+ NODROP(0x211ffff), DROP(0x2110000), NODROP(0x2120000)
+ /* The last test should be NODROP, because a DROP wouldn't get tested. */
+};
+
+int main(int argc, char *argv[])
+{
+ SSL_SESSION *sess;
+ SSL_CTX *ctx;
+ SSL *con;
+ BIO *rbio;
+ BIO *wbio;
+ BIO *err;
+ int testresult = 0;
+ int ret;
+ int i;
+
+ SSL_library_init();
+ SSL_load_error_strings();
+
+ err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT);
+
+ CRYPTO_malloc_debug_init();
+ CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
+
+ RAND_bytes(session_id, sizeof(session_id));
+ RAND_bytes(master_secret, sizeof(master_secret));
+ RAND_bytes(cookie, sizeof(cookie));
+ RAND_bytes(server_random + 4, sizeof(server_random) - 4);
+ time((void *)server_random);
+
+ sess = client_session();
+ if (sess == NULL) {
+ printf("Failed to generate SSL_SESSION\n");
+ goto end;
+ }
+
+ if (!EVP_DigestInit_ex(&handshake_md5, EVP_md5(), NULL) ||
+ !EVP_DigestInit_ex(&handshake_sha1, EVP_sha1(), NULL)) {
+ printf("Failed to initialise handshake_md\n");
+ goto end;
+ }
+
+ ctx = SSL_CTX_new(DTLSv1_client_method());
+ if (ctx == NULL) {
+ printf("Failed to allocate SSL_CTX\n");
+ goto end_md;
+ }
+ SSL_CTX_set_options(ctx, SSL_OP_CISCO_ANYCONNECT);
+
+ if (!SSL_CTX_set_cipher_list(ctx, "AES128-SHA")) {
+ printf("SSL_CTX_set_cipher_list() failed\n");
+ goto end_ctx;
+ }
+
+ con = SSL_new(ctx);
+ if (!SSL_set_session(con, sess)) {
+ printf("SSL_set_session() failed\n");
+ goto end_con;
+ }
+ SSL_SESSION_free(sess);
+
+ rbio = BIO_new(BIO_s_mem());
+ wbio = BIO_new(BIO_s_mem());
+
+ BIO_set_nbio(rbio, 1);
+ BIO_set_nbio(wbio, 1);
+
+ SSL_set_bio(con, rbio, wbio);
+ SSL_set_connect_state(con);
+
+ /* Send initial ClientHello */
+ ret = SSL_do_handshake(con);
+ if (ret > 0 || SSL_get_error(con, ret) != SSL_ERROR_WANT_READ) {
+ printf("Unexpected handshake result at initial call!\n");
+ goto end_con;
+ }
+
+ if (validate_client_hello(wbio) != 1) {
+ printf("Initial ClientHello failed validation\n");
+ goto end_con;
+ }
+ if (send_hello_verify(rbio) != 1) {
+ printf("Failed to send HelloVerify\n");
+ goto end_con;
+ }
+ ret = SSL_do_handshake(con);
+ if (ret > 0 || SSL_get_error(con, ret) != SSL_ERROR_WANT_READ) {
+ printf("Unexpected handshake result after HelloVerify!\n");
+ goto end_con;
+ }
+ if (validate_client_hello(wbio) != 2) {
+ printf("Second ClientHello failed validation\n");
+ goto end_con;
+ }
+ if (send_server_hello(rbio) != 1) {
+ printf("Failed to send ServerHello\n");
+ goto end_con;
+ }
+ ret = SSL_do_handshake(con);
+ if (ret > 0 || SSL_get_error(con, ret) != SSL_ERROR_WANT_READ) {
+ printf("Unexpected handshake result after ServerHello!\n");
+ goto end_con;
+ }
+ if (send_finished(con, rbio) != 1) {
+ printf("Failed to send Finished\n");
+ goto end_con;
+ }
+ ret = SSL_do_handshake(con);
+ if (ret < 1) {
+ printf("Handshake not successful after Finished!\n");
+ goto end_con;
+ }
+ if (validate_ccs(wbio) != 1) {
+ printf("Failed to validate client CCS/Finished\n");
+ goto end_con;
+ }
+
+ /* While we're here and crafting packets by hand, we might as well do a
+ bit of a stress test on the DTLS record replay handling. Not Cisco-DTLS
+ specific but useful anyway for the general case. It's been broken
+ before, and in fact was broken even for a basic 0, 2, 1 test case
+ when this test was first added.... */
+ for (i = 0; i < (int)OSSL_NELEM(tests); i++) {
+ unsigned long recv_buf[2];
+
+ if (send_record(rbio, SSL3_RT_APPLICATION_DATA, tests[i].seq,
+ &tests[i].seq, sizeof(unsigned long)) != 1) {
+ printf("Failed to send data seq #0x%lx (%d)\n",
+ tests[i].seq, i);
+ goto end_con;
+ }
+
+ if (tests[i].drop)
+ continue;
+
+ ret = SSL_read(con, recv_buf, 2 * sizeof(unsigned long));
+ if (ret != sizeof(unsigned long)) {
+ printf("SSL_read failed or wrong size on seq#0x%lx (%d)\n",
+ tests[i].seq, i);
+ goto end_con;
+ }
+ if (recv_buf[0] != tests[i].seq) {
+ printf("Wrong data packet received (0x%lx not 0x%lx) at packet %d\n",
+ recv_buf[0], tests[i].seq, i);
+ goto end_con;
+ }
+ }
+ if (tests[i-1].drop) {
+ printf("Error: last test cannot be DROP()\n");
+ goto end_con;
+ }
+ testresult=1;
+
+ end_con:
+ SSL_free(con);
+ end_ctx:
+ SSL_CTX_free(ctx);
+ end_md:
+ EVP_MD_CTX_cleanup(&handshake_md5);
+ EVP_MD_CTX_cleanup(&handshake_sha1);
+ end:
+ ERR_print_errors_fp(stderr);
+
+ if (!testresult) {
+ printf("Cisco BadDTLS test: FAILED\n");
+ }
+
+ ERR_free_strings();
+ ERR_remove_thread_state(NULL);
+ EVP_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+ CRYPTO_mem_leaks(err);
+ BIO_free(err);
+
+ return testresult?0:1;
+}
diff --git a/ssl/d1_both.c b/ssl/d1_both.c
index b5900dea8f..46c70d8ad5 100644
--- a/ssl/d1_both.c
+++ b/ssl/d1_both.c
@@ -618,11 +618,23 @@ static int dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)
int al;
*ok = 0;
- item = pqueue_peek(s->d1->buffered_messages);
- if (item == NULL)
- return 0;
+ do {
+ item = pqueue_peek(s->d1->buffered_messages);
+ if (item == NULL)
+ return 0;
+
+ frag = (hm_fragment *)item->data;
+
+ if (frag->msg_header.seq < s->d1->handshake_read_seq) {
+ /* This is a stale message that has been buffered so clear it */
+ pqueue_pop(s->d1->buffered_messages);
+ dtls1_hm_fragment_free(frag);
+ pitem_free(item);
+ item = NULL;
+ frag = NULL;
+ }
+ } while (item == NULL);
- frag = (hm_fragment *)item->data;
/* Don't return if reassembly still in progress */
if (frag->reassembly != NULL)
@@ -1211,7 +1223,7 @@ dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off,
unsigned long header_length;
unsigned char seq64be[8];
struct dtls1_retransmit_state saved_state;
- unsigned char save_write_sequence[8];
+ unsigned char save_write_sequence[8] = {0, 0, 0, 0, 0, 0, 0, 0};
/*-
OPENSSL_assert(s->init_num == 0);
@@ -1296,18 +1308,6 @@ dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off,
return ret;
}
-/* call this function when the buffered messages are no longer needed */
-void dtls1_clear_record_buffer(SSL *s)
-{
- pitem *item;
-
- for (item = pqueue_pop(s->d1->sent_messages);
- item != NULL; item = pqueue_pop(s->d1->sent_messages)) {
- dtls1_hm_fragment_free((hm_fragment *)item->data);
- pitem_free(item);
- }
-}
-
unsigned char *dtls1_set_message_header(SSL *s, unsigned char *p,
unsigned char mt, unsigned long len,
unsigned long frag_off,
@@ -1546,6 +1546,8 @@ int dtls1_heartbeat(SSL *s)
* - Padding
*/
buf = OPENSSL_malloc(1 + 2 + payload + padding);
+ if (buf == NULL)
+ goto err;
p = buf;
/* Message Type */
*p++ = TLS1_HB_REQUEST;
diff --git a/ssl/d1_clnt.c b/ssl/d1_clnt.c
index 3ddfa7bca4..7e2f5c2830 100644
--- a/ssl/d1_clnt.c
+++ b/ssl/d1_clnt.c
@@ -769,6 +769,7 @@ int dtls1_connect(SSL *s)
/* done with handshaking */
s->d1->handshake_read_seq = 0;
s->d1->next_handshake_write_seq = 0;
+ dtls1_clear_received_buffer(s);
goto end;
/* break; */
diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c
index ee78921ba8..debd4fd5dc 100644
--- a/ssl/d1_lib.c
+++ b/ssl/d1_lib.c
@@ -170,7 +170,6 @@ int dtls1_new(SSL *s)
static void dtls1_clear_queues(SSL *s)
{
pitem *item = NULL;
- hm_fragment *frag = NULL;
DTLS1_RECORD_DATA *rdata;
while ((item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL) {
@@ -191,28 +190,44 @@ static void dtls1_clear_queues(SSL *s)
pitem_free(item);
}
+ while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) {
+ rdata = (DTLS1_RECORD_DATA *)item->data;
+ if (rdata->rbuf.buf) {
+ OPENSSL_free(rdata->rbuf.buf);
+ }
+ OPENSSL_free(item->data);
+ pitem_free(item);
+ }
+
+ dtls1_clear_received_buffer(s);
+ dtls1_clear_sent_buffer(s);
+}
+
+void dtls1_clear_received_buffer(SSL *s)
+{
+ pitem *item = NULL;
+ hm_fragment *frag = NULL;
+
while ((item = pqueue_pop(s->d1->buffered_messages)) != NULL) {
frag = (hm_fragment *)item->data;
dtls1_hm_fragment_free(frag);
pitem_free(item);
}
+}
+
+void dtls1_clear_sent_buffer(SSL *s)
+{
+ pitem *item = NULL;
+ hm_fragment *frag = NULL;
while ((item = pqueue_pop(s->d1->sent_messages)) != NULL) {
frag = (hm_fragment *)item->data;
dtls1_hm_fragment_free(frag);
pitem_free(item);
}
-
- while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) {
- rdata = (DTLS1_RECORD_DATA *)item->data;
- if (rdata->rbuf.buf) {
- OPENSSL_free(rdata->rbuf.buf);
- }
- OPENSSL_free(item->data);
- pitem_free(item);
- }
}
+
void dtls1_free(SSL *s)
{
ssl3_free(s);
@@ -456,7 +471,7 @@ void dtls1_stop_timer(SSL *s)
BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
&(s->d1->next_timeout));
/* Clear retransmission buffer */
- dtls1_clear_record_buffer(s);
+ dtls1_clear_sent_buffer(s);
}
int dtls1_check_timeout_num(SSL *s)
diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c
index fe30ec7d00..df2e42e988 100644
--- a/ssl/d1_pkt.c
+++ b/ssl/d1_pkt.c
@@ -125,7 +125,7 @@
/* mod 128 saturating subtract of two 64-bit values in big-endian order */
static int satsub64be(const unsigned char *v1, const unsigned char *v2)
{
- int ret, sat, brw, i;
+ int ret, i;
if (sizeof(long) == 8)
do {
@@ -157,28 +157,51 @@ static int satsub64be(const unsigned char *v1, const unsigned char *v2)
return (int)l;
} while (0);
- ret = (int)v1[7] - (int)v2[7];
- sat = 0;
- brw = ret >> 8; /* brw is either 0 or -1 */
- if (ret & 0x80) {
- for (i = 6; i >= 0; i--) {
- brw += (int)v1[i] - (int)v2[i];
- sat |= ~brw;
- brw >>= 8;
- }
- } else {
- for (i = 6; i >= 0; i--) {
- brw += (int)v1[i] - (int)v2[i];
- sat |= brw;
- brw >>= 8;
+ ret = 0;
+ for (i=0; i<7; i++) {
+ if (v1[i] > v2[i]) {
+ /* v1 is larger... but by how much? */
+ if (v1[i] != v2[i] + 1)
+ return 128;
+ while (++i <= 6) {
+ if (v1[i] != 0x00 || v2[i] != 0xff)
+ return 128; /* too much */
+ }
+ /* We checked all the way to the penultimate byte,
+ * so despite higher bytes changing we actually
+ * know that it only changed from (e.g.)
+ * ... (xx) ff ff ff ??
+ * to ... (xx+1) 00 00 00 ??
+ * so we add a 'bias' of 256 for the carry that
+ * happened, and will eventually return
+ * 256 + v1[7] - v2[7]. */
+ ret = 256;
+ break;
+ } else if (v2[i] > v1[i]) {
+ /* v2 is larger... but by how much? */
+ if (v2[i] != v1[i] + 1)
+ return -128;
+ while (++i <= 6) {
+ if (v2[i] != 0x00 || v1[i] != 0xff)
+ return -128; /* too much */
+ }
+ /* Similar to the case above, we know it changed
+ * from ... (xx) 00 00 00 ??
+ * to ... (xx-1) ff ff ff ??
+ * so we add a 'bias' of -256 for the borrow,
+ * to return -256 + v1[7] - v2[7]. */
+ ret = -256;
}
}
- brw <<= 8; /* brw is either 0 or -256 */
- if (sat & 0xff)
- return brw | 0x80;
+ ret += (int)v1[7] - (int)v2[7];
+
+ if (ret > 128)
+ return 128;
+ else if (ret < -128)
+ return -128;
else
- return brw + (ret & 0xFF);
+ return ret;
}
static int have_handshake_fragment(SSL *s, int type, unsigned char *buf,
@@ -194,7 +217,7 @@ static int dtls1_record_needs_buffering(SSL *s, SSL3_RECORD *rr,
#endif
static int dtls1_buffer_record(SSL *s, record_pqueue *q,
unsigned char *priority);
-static int dtls1_process_record(SSL *s);
+static int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap);
/* copy buffered record into SSL structure */
static int dtls1_copy_record(SSL *s, pitem *item)
@@ -319,21 +342,70 @@ static int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue)
static int dtls1_process_buffered_records(SSL *s)
{
pitem *item;
+ SSL3_BUFFER *rb;
+ SSL3_RECORD *rr;
+ DTLS1_BITMAP *bitmap;
+ unsigned int is_next_epoch;
+ int replayok = 1;
item = pqueue_peek(s->d1->unprocessed_rcds.q);
if (item) {
/* Check if epoch is current. */
if (s->d1->unprocessed_rcds.epoch != s->d1->r_epoch)
- return (1); /* Nothing to do. */
+ return 1; /* Nothing to do. */
+
+ rr = &s->s3->rrec;
+ rb = &s->s3->rbuf;
+
+ if (rb->left > 0) {
+ /*
+ * We've still got data from the current packet to read. There could
+ * be a record from the new epoch in it - so don't overwrite it
+ * with the unprocessed records yet (we'll do it when we've
+ * finished reading the current packet).
+ */
+ return 1;
+ }
+
/* Process all the records. */
while (pqueue_peek(s->d1->unprocessed_rcds.q)) {
dtls1_get_unprocessed_record(s);
- if (!dtls1_process_record(s))
- return (0);
+ bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
+ if (bitmap == NULL) {
+ /*
+ * Should not happen. This will only ever be NULL when the
+ * current record is from a different epoch. But that cannot
+ * be the case because we already checked the epoch above
+ */
+ SSLerr(SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+#ifndef OPENSSL_NO_SCTP
+ /* Only do replay check if no SCTP bio */
+ if (!BIO_dgram_is_sctp(SSL_get_rbio(s)))
+#endif
+ {
+ /*
+ * Check whether this is a repeat, or aged record. We did this
+ * check once already when we first received the record - but
+ * we might have updated the window since then due to
+ * records we subsequently processed.
+ */
+ replayok = dtls1_record_replay_check(s, bitmap);
+ }
+
+ if (!replayok || !dtls1_process_record(s, bitmap)) {
+ /* dump this record */
+ rr->length = 0;
+ s->packet_length = 0;
+ continue;
+ }
+
if (dtls1_buffer_record(s, &(s->d1->processed_rcds),
s->s3->rrec.seq_num) < 0)
- return -1;
+ return 0;
}
}
@@ -344,7 +416,7 @@ static int dtls1_process_buffered_records(SSL *s)
s->d1->processed_rcds.epoch = s->d1->r_epoch;
s->d1->unprocessed_rcds.epoch = s->d1->r_epoch + 1;
- return (1);
+ return 1;
}
#if 0
@@ -391,7 +463,7 @@ static int dtls1_get_buffered_record(SSL *s)
#endif
-static int dtls1_process_record(SSL *s)
+static int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
{
int i, al;
int enc_err;
@@ -551,6 +623,10 @@ static int dtls1_process_record(SSL *s)
/* we have pulled in a full packet so zero things */
s->packet_length = 0;
+
+ /* Mark receipt of record. */
+ dtls1_record_bitmap_update(s, bitmap);
+
return (1);
f_err:
@@ -581,11 +657,12 @@ int dtls1_get_record(SSL *s)
rr = &(s->s3->rrec);
+ again:
/*
* The epoch may have changed. If so, process all the pending records.
* This is a non-blocking operation.
*/
- if (dtls1_process_buffered_records(s) < 0)
+ if (!dtls1_process_buffered_records(s))
return -1;
/* if we're renegotiating, then there may be buffered records */
@@ -593,7 +670,6 @@ int dtls1_get_record(SSL *s)
return 1;
/* get something from the wire */
- again:
/* check if we have the header */
if ((s->rstate != SSL_ST_READ_BODY) ||
(s->packet_length < DTLS1_RT_HEADER_LENGTH)) {
@@ -721,20 +797,17 @@ int dtls1_get_record(SSL *s)
if (dtls1_buffer_record
(s, &(s->d1->unprocessed_rcds), rr->seq_num) < 0)
return -1;
- /* Mark receipt of record. */
- dtls1_record_bitmap_update(s, bitmap);
}
rr->length = 0;
s->packet_length = 0;
goto again;
}
- if (!dtls1_process_record(s)) {
+ if (!dtls1_process_record(s, bitmap)) {
rr->length = 0;
s->packet_length = 0; /* dump this record */
goto again; /* get another record */
}
- dtls1_record_bitmap_update(s, bitmap); /* Mark receipt of record. */
return (1);
@@ -1201,7 +1274,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
BIO_snprintf(tmp, sizeof tmp, "%d", alert_descr);
ERR_add_error_data(2, "SSL alert number ", tmp);
s->shutdown |= SSL_RECEIVED_SHUTDOWN;
- SSL_CTX_remove_session(s->ctx, s->session);
+ SSL_CTX_remove_session(s->session_ctx, s->session);
return (0);
} else {
al = SSL_AD_ILLEGAL_PARAMETER;
@@ -1830,8 +1903,13 @@ static DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
if (rr->epoch == s->d1->r_epoch)
return &s->d1->bitmap;
- /* Only HM and ALERT messages can be from the next epoch */
+ /*
+ * Only HM and ALERT messages can be from the next epoch and only if we
+ * have already processed all of the unprocessed records from the last
+ * epoch
+ */
else if (rr->epoch == (unsigned long)(s->d1->r_epoch + 1) &&
+ s->d1->unprocessed_rcds.epoch != s->d1->r_epoch &&
(rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) {
*is_next_epoch = 1;
return &s->d1->next_bitmap;
@@ -1910,6 +1988,12 @@ void dtls1_reset_seq_numbers(SSL *s, int rw)
s->d1->r_epoch++;
memcpy(&(s->d1->bitmap), &(s->d1->next_bitmap), sizeof(DTLS1_BITMAP));
memset(&(s->d1->next_bitmap), 0x00, sizeof(DTLS1_BITMAP));
+
+ /*
+ * We must not use any buffered messages received from the previous
+ * epoch
+ */
+ dtls1_clear_received_buffer(s);
} else {
seq = s->s3->write_sequence;
memcpy(s->d1->last_write_sequence, seq,
diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c
index e677d880f0..bc875b53c9 100644
--- a/ssl/d1_srvr.c
+++ b/ssl/d1_srvr.c
@@ -313,7 +313,7 @@ int dtls1_accept(SSL *s)
case SSL3_ST_SW_HELLO_REQ_B:
s->shutdown = 0;
- dtls1_clear_record_buffer(s);
+ dtls1_clear_sent_buffer(s);
dtls1_start_timer(s);
ret = ssl3_send_hello_request(s);
if (ret <= 0)
@@ -894,6 +894,7 @@ int dtls1_accept(SSL *s)
/* next message is server hello */
s->d1->handshake_write_seq = 0;
s->d1->next_handshake_write_seq = 0;
+ dtls1_clear_received_buffer(s);
goto end;
/* break; */
diff --git a/ssl/dtlstest.c b/ssl/dtlstest.c
new file mode 100644
index 0000000000..78ebc67744
--- /dev/null
+++ b/ssl/dtlstest.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2016 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
+ */
+
+#include <openssl/bio.h>
+#include <openssl/crypto.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+#include "ssltestlib.h"
+#include "testutil.h"
+
+static char *cert = NULL;
+static char *privkey = NULL;
+
+#define NUM_TESTS 2
+
+
+#define DUMMY_CERT_STATUS_LEN 12
+
+unsigned char certstatus[] = {
+ SSL3_RT_HANDSHAKE, /* Content type */
+ 0xfe, 0xfd, /* Record version */
+ 0, 1, /* Epoch */
+ 0, 0, 0, 0, 0, 0x0f, /* Record sequence number */
+ 0, DTLS1_HM_HEADER_LENGTH + DUMMY_CERT_STATUS_LEN - 2,
+ SSL3_MT_CERTIFICATE_STATUS, /* Cert Status handshake message type */
+ 0, 0, DUMMY_CERT_STATUS_LEN, /* Message len */
+ 0, 5, /* Message sequence */
+ 0, 0, 0, /* Fragment offset */
+ 0, 0, DUMMY_CERT_STATUS_LEN - 2, /* Fragment len */
+ 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80 /* Dummy data */
+};
+
+#define RECORD_SEQUENCE 10
+
+static int test_dtls_unprocessed(int testidx)
+{
+ SSL_CTX *sctx = NULL, *cctx = NULL;
+ SSL *serverssl1 = NULL, *clientssl1 = NULL;
+ BIO *c_to_s_fbio, *c_to_s_mempacket;
+ int testresult = 0;
+
+ printf("Starting Test %d\n", testidx);
+
+ if (!create_ssl_ctx_pair(DTLS_server_method(), DTLS_client_method(), &sctx,
+ &cctx, cert, privkey)) {
+ printf("Unable to create SSL_CTX pair\n");
+ return 0;
+ }
+
+ if (!SSL_CTX_set_ecdh_auto(sctx, 1)) {
+ printf("Failed configuring auto ECDH\n");
+ }
+
+ if (!SSL_CTX_set_cipher_list(cctx, "AES128-SHA")) {
+ printf("Failed setting cipher list\n");
+ }
+
+ c_to_s_fbio = BIO_new(bio_f_tls_dump_filter());
+ if (c_to_s_fbio == NULL) {
+ printf("Failed to create filter BIO\n");
+ goto end;
+ }
+
+ /* BIO is freed by create_ssl_connection on error */
+ if (!create_ssl_objects(sctx, cctx, &serverssl1, &clientssl1, NULL,
+ c_to_s_fbio)) {
+ printf("Unable to create SSL objects\n");
+ ERR_print_errors_fp(stdout);
+ goto end;
+ }
+
+ if (testidx == 1)
+ certstatus[RECORD_SEQUENCE] = 0xff;
+
+ /*
+ * Inject a dummy record from the next epoch. In test 0, this should never
+ * get used because the message sequence number is too big. In test 1 we set
+ * the record sequence number to be way off in the future. This should not
+ * have an impact on the record replay protection because the record should
+ * be dropped before it is marked as arrivedg
+ */
+ c_to_s_mempacket = SSL_get_wbio(clientssl1);
+ c_to_s_mempacket = BIO_next(c_to_s_mempacket);
+ mempacket_test_inject(c_to_s_mempacket, (char *)certstatus,
+ sizeof(certstatus), 1, INJECT_PACKET_IGNORE_REC_SEQ);
+
+ if (!create_ssl_connection(serverssl1, clientssl1)) {
+ printf("Unable to create SSL connection\n");
+ ERR_print_errors_fp(stdout);
+ goto end;
+ }
+
+ testresult = 1;
+ end:
+ SSL_free(serverssl1);
+ SSL_free(clientssl1);
+ SSL_CTX_free(sctx);
+ SSL_CTX_free(cctx);
+
+ return testresult;
+}
+
+int main(int argc, char *argv[])
+{
+ BIO *err = NULL;
+ int testresult = 0;
+
+ if (argc != 3) {
+ printf("Invalid argument count\n");
+ return 1;
+ }
+
+ cert = argv[1];
+ privkey = argv[2];
+
+ err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT);
+
+ SSL_library_init();
+ SSL_load_error_strings();
+
+ CRYPTO_malloc_debug_init();
+ CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL);
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
+
+ if (!test_dtls_unprocessed(0) || !test_dtls_unprocessed(1))
+ testresult = 1;
+
+ ERR_free_strings();
+ ERR_remove_thread_state(NULL);
+ EVP_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+ CRYPTO_mem_leaks(err);
+ BIO_free(err);
+
+ if (!testresult)
+ printf("PASS\n");
+
+ return testresult;
+}
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 19dc8648b9..36833f7304 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -2111,6 +2111,10 @@ int ssl3_get_certificate_request(SSL *s)
if (ctype_num > SSL3_CT_NUMBER) {
/* If we exceed static buffer copy all to cert structure */
s->cert->ctypes = OPENSSL_malloc(ctype_num);
+ if (s->cert->ctypes == NULL) {
+ SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
memcpy(s->cert->ctypes, p, ctype_num);
s->cert->ctype_num = (size_t)ctype_num;
ctype_num = SSL3_CT_NUMBER;
diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c
index b9fc0c7049..fbc954d43c 100644
--- a/ssl/s3_enc.c
+++ b/ssl/s3_enc.c
@@ -607,6 +607,10 @@ int ssl3_digest_cached_records(SSL *s)
ssl3_free_digest_list(s);
s->s3->handshake_dgst =
OPENSSL_malloc(SSL_MAX_DIGEST * sizeof(EVP_MD_CTX *));
+ if (s->s3->handshake_dgst == NULL) {
+ SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
memset(s->s3->handshake_dgst, 0, SSL_MAX_DIGEST * sizeof(EVP_MD_CTX *));
hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
if (hdatalen <= 0) {
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index f2aaf36c40..0385e039c8 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -329,7 +329,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_SSLV3,
- SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -382,7 +382,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_SSLV3,
- SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -434,7 +434,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_SSLV3,
- SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -487,7 +487,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_SSLV3,
- SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -539,7 +539,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_SSLV3,
- SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -625,7 +625,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_SSLV3,
- SSL_NOT_DEFAULT | SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_DEFAULT | SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -712,7 +712,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_SSLV3,
- SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -778,7 +778,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_MD5,
SSL_SSLV3,
- SSL_NOT_EXP | SSL_HIGH,
+ SSL_NOT_EXP | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -1728,7 +1728,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -2120,7 +2120,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -2200,7 +2200,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -2280,7 +2280,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -2360,7 +2360,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -2440,7 +2440,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_DEFAULT | SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_DEFAULT | SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -2490,7 +2490,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP | SSL_HIGH,
+ SSL_NOT_EXP | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -2506,7 +2506,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP | SSL_HIGH,
+ SSL_NOT_EXP | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -2522,7 +2522,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP | SSL_HIGH,
+ SSL_NOT_EXP | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c
index 379890237e..df124cf52c 100644
--- a/ssl/s3_pkt.c
+++ b/ssl/s3_pkt.c
@@ -1473,7 +1473,7 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
BIO_snprintf(tmp, sizeof tmp, "%d", alert_descr);
ERR_add_error_data(2, "SSL alert number ", tmp);
s->shutdown |= SSL_RECEIVED_SHUTDOWN;
- SSL_CTX_remove_session(s->ctx, s->session);
+ SSL_CTX_remove_session(s->session_ctx, s->session);
return (0);
} else {
al = SSL_AD_ILLEGAL_PARAMETER;
@@ -1698,7 +1698,7 @@ int ssl3_send_alert(SSL *s, int level, int desc)
return -1;
/* If a fatal one, remove from cache */
if ((level == 2) && (s->session != NULL))
- SSL_CTX_remove_session(s->ctx, s->session);
+ SSL_CTX_remove_session(s->session_ctx, s->session);
s->s3->alert_dispatch = 1;
s->s3->send_alert[0] = level;
diff --git a/ssl/ssl-lib.com b/ssl/ssl-lib.com
index 43fea17541..bf67265a46 100644
--- a/ssl/ssl-lib.com
+++ b/ssl/ssl-lib.com
@@ -941,7 +941,7 @@ $ CC = "CC"
$ IF ARCH.EQS."VAX" .AND. F$TRNLNM("DECC$CC_DEFAULT").NES."/DECC" -
THEN CC = "CC/DECC"
$ CC = CC + " /''CC_OPTIMIZE' /''DEBUGGER' /STANDARD=RELAXED"+ -
- "''POINTER_SIZE' /NOLIST /PREFIX=ALL" + -
+ "''POINTER_SIZE' /NOLIST /PREFIX=ALL /EXTERN_MODEL=STRICT_REFDEF" + -
" /INCLUDE=(''CC_INCLUDES') " + CCEXTRAFLAGS
$!
$! Define The Linker Options File Name.
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 028681a0cb..2638755891 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -2615,6 +2615,7 @@ void ERR_load_SSL_strings(void);
# define SSL_F_DTLS1_HEARTBEAT 305
# define SSL_F_DTLS1_OUTPUT_CERT_CHAIN 255
# define SSL_F_DTLS1_PREPROCESS_FRAGMENT 288
+# define SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS 424
# define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE 256
# define SSL_F_DTLS1_PROCESS_RECORD 257
# define SSL_F_DTLS1_READ_BYTES 258
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index d500dac414..2ad8f43922 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -2006,6 +2006,11 @@ int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm)
MemCheck_off();
comp = (SSL_COMP *)OPENSSL_malloc(sizeof(SSL_COMP));
+ if (comp == NULL) {
+ MemCheck_on();
+ SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD, ERR_R_MALLOC_FAILURE);
+ return 1;
+ }
comp->id = id;
comp->method = cm;
load_builtin_compressions();
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 704088dc46..79aaf1a838 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -1,6 +1,6 @@
/* ssl/ssl_err.c */
/* ====================================================================
- * Copyright (c) 1999-2015 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2016 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
@@ -93,6 +93,8 @@ static ERR_STRING_DATA SSL_str_functs[] = {
{ERR_FUNC(SSL_F_DTLS1_HEARTBEAT), "dtls1_heartbeat"},
{ERR_FUNC(SSL_F_DTLS1_OUTPUT_CERT_CHAIN), "dtls1_output_cert_chain"},
{ERR_FUNC(SSL_F_DTLS1_PREPROCESS_FRAGMENT), "DTLS1_PREPROCESS_FRAGMENT"},
+ {ERR_FUNC(SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS),
+ "DTLS1_PROCESS_BUFFERED_RECORDS"},
{ERR_FUNC(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE),
"DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE"},
{ERR_FUNC(SSL_F_DTLS1_PROCESS_RECORD), "DTLS1_PROCESS_RECORD"},
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index a707612fb0..42b980ac26 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1828,7 +1828,7 @@ int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen,
const unsigned char *p, size_t plen,
int use_context)
{
- if (s->version < TLS1_VERSION)
+ if (s->version < TLS1_VERSION && s->version != DTLS1_BAD_VER)
return -1;
return s->method->ssl3_enc->export_keying_material(s, out, olen, label,
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 3dd2a54b22..e358031db4 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -1248,7 +1248,8 @@ int dtls1_retransmit_message(SSL *s, unsigned short seq,
unsigned long frag_off, int *found);
int dtls1_get_queue_priority(unsigned short seq, int is_ccs);
int dtls1_retransmit_buffered_messages(SSL *s);
-void dtls1_clear_record_buffer(SSL *s);
+void dtls1_clear_received_buffer(SSL *s);
+void dtls1_clear_sent_buffer(SSL *s);
void dtls1_get_message_header(unsigned char *data,
struct hm_header_st *msg_hdr);
void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr);
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
index ba5737f006..ed9855f90c 100644
--- a/ssl/ssl_sess.c
+++ b/ssl/ssl_sess.c
@@ -919,6 +919,10 @@ int SSL_set_session(SSL *s, SSL_SESSION *session)
session->krb5_client_princ_len > 0) {
s->kssl_ctx->client_princ =
(char *)OPENSSL_malloc(session->krb5_client_princ_len + 1);
+ if (s->kssl_ctx->client_princ == NULL) {
+ SSLerr(SSL_F_SSL_SET_SESSION, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
memcpy(s->kssl_ctx->client_princ, session->krb5_client_princ,
session->krb5_client_princ_len);
s->kssl_ctx->client_princ[session->krb5_client_princ_len] = '\0';
@@ -1123,7 +1127,7 @@ int ssl_clear_bad_session(SSL *s)
if ((s->session != NULL) &&
!(s->shutdown & SSL_SENT_SHUTDOWN) &&
!(SSL_in_init(s) || SSL_in_before(s))) {
- SSL_CTX_remove_session(s->ctx, s->session);
+ SSL_CTX_remove_session(s->session_ctx, s->session);
return (1);
} else
return (0);
diff --git a/ssl/ssltest.c b/ssl/ssltest.c
index 1db84ad5f9..890e476853 100644
--- a/ssl/ssltest.c
+++ b/ssl/ssltest.c
@@ -3141,9 +3141,12 @@ static unsigned int psk_server_callback(SSL *ssl, const char *identity,
static int do_test_cipherlist(void)
{
+#if !defined(OPENSSL_NO_SSL2) || !defined(OPENSSL_NO_SSL3) || \
+ !defined(OPENSSL_NO_TLS1)
int i = 0;
const SSL_METHOD *meth;
const SSL_CIPHER *ci, *tci = NULL;
+#endif
#ifndef OPENSSL_NO_SSL2
fprintf(stderr, "testing SSLv2 cipher list order: ");
diff --git a/ssl/sslv2conftest.c b/ssl/sslv2conftest.c
index 1fd748b118..2aed9950b9 100644
--- a/ssl/sslv2conftest.c
+++ b/ssl/sslv2conftest.c
@@ -84,7 +84,7 @@ int main(int argc, char *argv[])
{
BIO *err;
int testresult = 0;
- int currtest;
+ int currtest = 0;
SSL_library_init();
SSL_load_error_strings();
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 8071b4ab7d..fbcf2e663c 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -3401,9 +3401,7 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
HMAC_CTX hctx;
EVP_CIPHER_CTX ctx;
SSL_CTX *tctx = s->initial_ctx;
- /* Need at least keyname + iv + some encrypted data */
- if (eticklen < 48)
- return 2;
+
/* Initialize session ticket encryption and HMAC contexts */
HMAC_CTX_init(&hctx);
EVP_CIPHER_CTX_init(&ctx);
@@ -3437,6 +3435,13 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
if (mlen < 0) {
goto err;
}
+ /* Sanity check ticket length: must exceed keyname + IV + HMAC */
+ if (eticklen <= 16 + EVP_CIPHER_CTX_iv_length(&ctx) + mlen) {
+ HMAC_CTX_cleanup(&hctx);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ return 2;
+ }
+
eticklen -= mlen;
/* Check HMAC of encrypted ticket */
if (HMAC_Update(&hctx, etick, eticklen) <= 0
@@ -3984,6 +3989,8 @@ int tls1_heartbeat(SSL *s)
* - Padding
*/
buf = OPENSSL_malloc(1 + 2 + payload + padding);
+ if (buf == NULL)
+ return -1;
p = buf;
/* Message Type */
*p++ = TLS1_HB_REQUEST;
diff --git a/test/Makefile b/test/Makefile
index e566babfa5..bda1899bab 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -70,7 +70,9 @@ HEARTBEATTEST= heartbeat_test
CONSTTIMETEST= constant_time_test
VERIFYEXTRATEST= verify_extra_test
CLIENTHELLOTEST= clienthellotest
+BADDTLSTEST= bad_dtls_test
SSLV2CONFTEST = sslv2conftest
+DTLSTEST = dtlstest
TESTS= alltests
@@ -84,7 +86,8 @@ EXE= $(BNTEST)$(EXE_EXT) $(ECTEST)$(EXE_EXT) $(ECDSATEST)$(EXE_EXT) $(ECDHTEST)
$(EVPTEST)$(EXE_EXT) $(EVPEXTRATEST)$(EXE_EXT) $(IGETEST)$(EXE_EXT) $(JPAKETEST)$(EXE_EXT) $(SRPTEST)$(EXE_EXT) \
$(ASN1TEST)$(EXE_EXT) $(V3NAMETEST)$(EXE_EXT) $(HEARTBEATTEST)$(EXE_EXT) \
$(CONSTTIMETEST)$(EXE_EXT) $(VERIFYEXTRATEST)$(EXE_EXT) \
- $(CLIENTHELLOTEST)$(EXE_EXT) $(SSLV2CONFTEST)$(EXE_EXT)
+ $(CLIENTHELLOTEST)$(EXE_EXT) $(SSLV2CONFTEST)$(EXE_EXT) $(DTLSTEST)$(EXE_EXT) \
+ $(BADDTLSTEST)$(EXE_EXT)
# $(METHTEST)$(EXE_EXT)
@@ -98,7 +101,8 @@ OBJ= $(BNTEST).o $(ECTEST).o $(ECDSATEST).o $(ECDHTEST).o $(IDEATEST).o \
$(BFTEST).o $(SSLTEST).o $(DSATEST).o $(EXPTEST).o $(RSATEST).o \
$(EVPTEST).o $(EVPEXTRATEST).o $(IGETEST).o $(JPAKETEST).o $(ASN1TEST).o $(V3NAMETEST).o \
$(HEARTBEATTEST).o $(CONSTTIMETEST).o $(VERIFYEXTRATEST).o \
- $(CLIENTHELLOTEST).o $(SSLV2CONFTEST).o
+ $(CLIENTHELLOTEST).o $(SSLV2CONFTEST).o $(DTLSTEST).o ssltestlib.o \
+ $(BADDTLSTEST).o
SRC= $(BNTEST).c $(ECTEST).c $(ECDSATEST).c $(ECDHTEST).c $(IDEATEST).c \
$(MD2TEST).c $(MD4TEST).c $(MD5TEST).c \
@@ -109,10 +113,11 @@ SRC= $(BNTEST).c $(ECTEST).c $(ECDSATEST).c $(ECDHTEST).c $(IDEATEST).c \
$(BFTEST).c $(SSLTEST).c $(DSATEST).c $(EXPTEST).c $(RSATEST).c \
$(EVPTEST).c $(EVPEXTRATEST).c $(IGETEST).c $(JPAKETEST).c $(SRPTEST).c $(ASN1TEST).c \
$(V3NAMETEST).c $(HEARTBEATTEST).c $(CONSTTIMETEST).c $(VERIFYEXTRATEST).c \
- $(CLIENTHELLOTEST).c $(SSLV2CONFTEST).c
+ $(CLIENTHELLOTEST).c $(SSLV2CONFTEST).c $(DTLSTEST).c ssltestlib.c \
+ $(BADDTLSTEST).c
EXHEADER=
-HEADER= testutil.h $(EXHEADER)
+HEADER= testutil.h ssltestlib.h $(EXHEADER)
ALL= $(GENERAL) $(SRC) $(HEADER)
@@ -153,7 +158,8 @@ alltests: \
test_gen test_req test_pkcs7 test_verify test_dh test_dsa \
test_ss test_ca test_engine test_evp test_evp_extra test_ssl test_tsa test_ige \
test_jpake test_srp test_cms test_ocsp test_v3name test_heartbeat \
- test_constant_time test_verify_extra test_clienthello test_sslv2conftest
+ test_constant_time test_verify_extra test_clienthello test_sslv2conftest \
+ test_dtls test_bad_dtls
test_evp: $(EVPTEST)$(EXE_EXT) evptests.txt
../util/shlib_wrap.sh ./$(EVPTEST) evptests.txt
@@ -362,10 +368,18 @@ test_clienthello: $(CLIENTHELLOTEST)$(EXE_EXT)
@echo $(START) $@
../util/shlib_wrap.sh ./$(CLIENTHELLOTEST)
+test_bad_dtls: $(BADDTLSTEST)$(EXE_EXT)
+ @echo $(START) $@
+ ../util/shlib_wrap.sh ./$(BADDTLSTEST)
+
test_sslv2conftest: $(SSLV2CONFTEST)$(EXE_EXT)
@echo $(START) $@
../util/shlib_wrap.sh ./$(SSLV2CONFTEST)
+test_dtls: $(DTLSTEST)$(EXE_EXT)
+ @echo $(START) $@
+ ../util/shlib_wrap.sh ./$(DTLSTEST) ../apps/server.pem ../apps/server.pem
+
lint:
lint -DLINT $(INCLUDES) $(SRC)>fluff
@@ -397,7 +411,7 @@ BUILD_CMD=shlib_target=; if [ -n "$(SHARED_LIBS)" ]; then \
fi; \
LIBRARIES="$(LIBSSL) $(LIBCRYPTO) $(LIBKRB5)"; \
$(MAKE) -f $(TOP)/Makefile.shared -e \
- CC="$${CC}" APPNAME=$$target$(EXE_EXT) OBJECTS="$$target.o" \
+ CC="$${CC}" APPNAME=$$target$(EXE_EXT) OBJECTS="$$target.o $$exobj" \
LIBDEPS="$(PEX_LIBS) $$LIBRARIES $(EX_LIBS)" \
link_app.$${shlib_target}
@@ -543,9 +557,15 @@ $(VERIFYEXTRATEST)$(EXE_EXT): $(VERIFYEXTRATEST).o
$(CLIENTHELLOTEST)$(EXE_EXT): $(CLIENTHELLOTEST).o
@target=$(CLIENTHELLOTEST) $(BUILD_CMD)
+$(BADDTLSTEST)$(EXE_EXT): $(BADDTLSTEST).o
+ @target=$(BADDTLSTEST) $(BUILD_CMD)
+
$(SSLV2CONFTEST)$(EXE_EXT): $(SSLV2CONFTEST).o
@target=$(SSLV2CONFTEST) $(BUILD_CMD)
+$(DTLSTEST)$(EXE_EXT): $(DTLSTEST).o ssltestlib.o $(DLIBSSL) $(DLIBCRYPTO)
+ @target=$(DTLSTEST); exobj=ssltestlib.o; $(BUILD_CMD)
+
#$(AESTEST).o: $(AESTEST).c
# $(CC) -c $(CFLAGS) -DINTERMEDIATE_VALUE_KAT -DTRACE_KAT_MCT $(AESTEST).c
@@ -573,6 +593,26 @@ asn1test.o: ../include/openssl/pkcs7.h ../include/openssl/safestack.h
asn1test.o: ../include/openssl/sha.h ../include/openssl/stack.h
asn1test.o: ../include/openssl/symhacks.h ../include/openssl/x509.h
asn1test.o: ../include/openssl/x509_vfy.h asn1test.c
+bad_dtls_test.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
+bad_dtls_test.o: ../include/openssl/bn.h ../include/openssl/buffer.h
+bad_dtls_test.o: ../include/openssl/comp.h ../include/openssl/crypto.h
+bad_dtls_test.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
+bad_dtls_test.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+bad_dtls_test.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
+bad_dtls_test.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+bad_dtls_test.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+bad_dtls_test.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+bad_dtls_test.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+bad_dtls_test.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+bad_dtls_test.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+bad_dtls_test.o: ../include/openssl/pqueue.h ../include/openssl/rand.h
+bad_dtls_test.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+bad_dtls_test.o: ../include/openssl/srtp.h ../include/openssl/ssl.h
+bad_dtls_test.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+bad_dtls_test.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+bad_dtls_test.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
+bad_dtls_test.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h
+bad_dtls_test.o: bad_dtls_test.c
bftest.o: ../e_os.h ../include/openssl/blowfish.h ../include/openssl/e_os2.h
bftest.o: ../include/openssl/opensslconf.h bftest.c
bntest.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
@@ -634,6 +674,25 @@ dsatest.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
dsatest.o: ../include/openssl/ossl_typ.h ../include/openssl/rand.h
dsatest.o: ../include/openssl/safestack.h ../include/openssl/stack.h
dsatest.o: ../include/openssl/symhacks.h dsatest.c
+dtlstest.o: ../include/openssl/asn1.h ../include/openssl/bio.h
+dtlstest.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+dtlstest.o: ../include/openssl/crypto.h ../include/openssl/dtls1.h
+dtlstest.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
+dtlstest.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h
+dtlstest.o: ../include/openssl/err.h ../include/openssl/evp.h
+dtlstest.o: ../include/openssl/hmac.h ../include/openssl/kssl.h
+dtlstest.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
+dtlstest.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+dtlstest.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+dtlstest.o: ../include/openssl/pem.h ../include/openssl/pem2.h
+dtlstest.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h
+dtlstest.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+dtlstest.o: ../include/openssl/srtp.h ../include/openssl/ssl.h
+dtlstest.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+dtlstest.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+dtlstest.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
+dtlstest.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h dtlstest.c
+dtlstest.o: ssltestlib.h testutil.h
ecdhtest.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
ecdhtest.o: ../include/openssl/bn.h ../include/openssl/crypto.h
ecdhtest.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
@@ -856,6 +915,24 @@ ssltest.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
ssltest.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
ssltest.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h
ssltest.o: ../include/openssl/x509v3.h ssltest.c
+ssltestlib.o: ../include/openssl/asn1.h ../include/openssl/bio.h
+ssltestlib.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+ssltestlib.o: ../include/openssl/crypto.h ../include/openssl/dtls1.h
+ssltestlib.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
+ssltestlib.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h
+ssltestlib.o: ../include/openssl/evp.h ../include/openssl/hmac.h
+ssltestlib.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
+ssltestlib.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+ssltestlib.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+ssltestlib.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+ssltestlib.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+ssltestlib.o: ../include/openssl/pqueue.h ../include/openssl/safestack.h
+ssltestlib.o: ../include/openssl/sha.h ../include/openssl/srtp.h
+ssltestlib.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+ssltestlib.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+ssltestlib.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+ssltestlib.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+ssltestlib.o: ../include/openssl/x509_vfy.h ssltestlib.c ssltestlib.h
sslv2conftest.o: ../include/openssl/asn1.h ../include/openssl/bio.h
sslv2conftest.o: ../include/openssl/buffer.h ../include/openssl/comp.h
sslv2conftest.o: ../include/openssl/crypto.h ../include/openssl/dtls1.h
diff --git a/test/maketests.com b/test/maketests.com
index 7e2d939bbe..6223659fb0 100644
--- a/test/maketests.com
+++ b/test/maketests.com
@@ -147,9 +147,10 @@ $ TEST_FILES = "BNTEST,ECTEST,ECDSATEST,ECDHTEST,IDEATEST,"+ -
"MDC2TEST,RMDTEST,"+ -
"RANDTEST,DHTEST,ENGINETEST,"+ -
"BFTEST,CASTTEST,SSLTEST,EXPTEST,DSATEST,RSA_TEST,"+ -
- "EVP_TEST,IGETEST,JPAKETEST,SRPTEST,"+ -
+ "EVP_TEST,EVP_EXTRA_TEST,IGETEST,JPAKETEST,SRPTEST,"+ -
"ASN1TEST,V3NAMETEST,HEARTBEAT_TEST,"+ -
- "CONSTANT_TIME_TEST"
+ "CONSTANT_TIME_TEST,VERIFY_EXTRA_TEST,"+ -
+ "CLIENTHELLOTEST,SSLV2CONFTEST,DTLSTEST"
$! Should we add MTTEST,PQ_TEST,LH_TEST,DIVTEST,TABTEST as well?
$!
$! Additional directory information.
@@ -183,6 +184,7 @@ $ T_D_EXPTEST := [-.crypto.bn]
$ T_D_DSATEST := [-.crypto.dsa]
$ T_D_RSA_TEST := [-.crypto.rsa]
$ T_D_EVP_TEST := [-.crypto.evp]
+$ T_D_EVP_EXTRA_TEST := [-.crypto.evp]
$ T_D_IGETEST := [-.test]
$ T_D_JPAKETEST := [-.crypto.jpake]
$ T_D_SRPTEST := [-.crypto.srp]
@@ -190,6 +192,12 @@ $ T_D_V3NAMETEST := [-.crypto.x509v3]
$ T_D_ASN1TEST := [-.test]
$ T_D_HEARTBEAT_TEST := [-.ssl]
$ T_D_CONSTANT_TIME_TEST := [-.crypto]
+$ T_D_VERIFY_EXTRA_TEST := [-.crypto.x509]
+$ T_D_CLIENTHELLOTEST := [-.ssl]
+$ T_D_SSLV2CONFTEST := [-.ssl]
+$ T_D_DTLSTEST := [-.ssl]
+$
+$ EXOBJ_DTLSTEST := SSLTESTLIB
$!
$ TCPIP_PROGRAMS = ",,"
$ IF COMPILER .EQS. "VAXC" THEN -
@@ -222,10 +230,21 @@ $!
$! Create The Object File Name.
$!
$ OBJECT_FILE = OBJ_DIR + FILE_NAME + ".OBJ"
+$ OBJECT_FILES = OBJECT_FILE
$!
$! Create The Executable File Name.
$!
$ EXE_FILE = EXE_DIR + FILE_NAME + ".EXE"
+$!
+$! Do the same for the possible extra unit
+$!
+$ IF F$TYPE(EXOBJ_'FILE_NAME') .NES. ""
+$ THEN
+$ EXOBJ_SOURCE_FILE = "SYS$DISK:" + EXOBJ_'FILE_NAME' + ".C"
+$ EXOBJ_OBJECT_FILE = OBJ_DIR + EXOBJ_'FILE_NAME' + ".OBJ"
+$ OBJECT_FILES = OBJECT_FILES + "," + EXOBJ_OBJECT_FILE
+$ ENDIF
+$!
$ ON WARNING THEN GOTO NEXT_FILE
$!
$! Check To See If The File We Want To Compile Actually Exists.
@@ -252,6 +271,10 @@ $! Compile The File.
$!
$ ON ERROR THEN GOTO NEXT_FILE
$ CC /OBJECT='OBJECT_FILE' 'SOURCE_FILE'
+$ IF F$TYPE(EXOBJ_'FILE_NAME') .NES. ""
+$ THEN
+$ CC /OBJECT='EXOBJ_OBJECT_FILE' 'EXOBJ_SOURCE_FILE'
+$ ENDIF
$ ON WARNING THEN GOTO NEXT_FILE
$!
$! Check If What We Are About To Compile Works Without A TCP/IP Library.
@@ -275,7 +298,7 @@ $!
$! Don't Link With The RSAREF Routines And TCP/IP Library.
$!
$ LINK /'DEBUGGER' /'LINKMAP' /'TRACEBACK' /EXECTABLE = 'EXE_FILE' -
- 'OBJECT_FILE', -
+ 'OBJECT_FILES', -
'SSL_LIB' /LIBRARY, -
'CRYPTO_LIB' /LIBRARY -
'TCPIP_LIB' -
@@ -475,7 +498,7 @@ $ CHECK_OPTIONS:
$!
$! Set basic C compiler /INCLUDE directories.
$!
-$ CC_INCLUDES = "SYS$DISK:[-],SYS$DISK:[-.CRYPTO]"
+$ CC_INCLUDES = "SYS$DISK:[-],SYS$DISK:[-.CRYPTO],SYS$DISK:[-.TEST]"
$!
$! Check To See If P1 Is Blank.
$!
diff --git a/test/ssltestlib.c b/test/ssltestlib.c
new file mode 100644
index 0000000000..a52669c82a
--- /dev/null
+++ b/test/ssltestlib.c
@@ -0,0 +1,687 @@
+/*
+ * Copyright 2016 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
+ */
+
+#include <string.h>
+#include <openssl/safestack.h>
+
+#include "ssltestlib.h"
+
+#define SSL_IS_DTLS(s) (s->method->version == DTLS_ANY_VERSION \
+ || s->method->version == DTLS1_2_VERSION \
+ || s->method->version == DTLS1_VERSION)
+
+static int tls_dump_new(BIO *bi);
+static int tls_dump_free(BIO *a);
+static int tls_dump_read(BIO *b, char *out, int outl);
+static int tls_dump_write(BIO *b, const char *in, int inl);
+static long tls_dump_ctrl(BIO *b, int cmd, long num, void *ptr);
+static int tls_dump_gets(BIO *bp, char *buf, int size);
+static int tls_dump_puts(BIO *bp, const char *str);
+
+/* Choose a sufficiently large type likely to be unused for this custom BIO */
+# define BIO_TYPE_TLS_DUMP_FILTER (0x80 | BIO_TYPE_FILTER)
+
+# define BIO_TYPE_MEMPACKET_TEST 0x81
+
+static BIO_METHOD method_tls_dump = {
+ BIO_TYPE_TLS_DUMP_FILTER,
+ "TLS dump filter",
+ tls_dump_write,
+ tls_dump_read,
+ tls_dump_puts,
+ tls_dump_gets,
+ tls_dump_ctrl,
+ tls_dump_new,
+ tls_dump_free
+};
+
+BIO_METHOD *bio_f_tls_dump_filter(void)
+{
+ return &method_tls_dump;
+}
+
+static int tls_dump_new(BIO *bio)
+{
+ bio->init = 1;
+ return 1;
+}
+
+static int tls_dump_free(BIO *bio)
+{
+ bio->init = 0;
+
+ return 1;
+}
+
+static void copy_flags(BIO *bio)
+{
+ int flags;
+ BIO *next = BIO_next(bio);
+
+ flags = BIO_test_flags(next, BIO_FLAGS_SHOULD_RETRY | BIO_FLAGS_RWS);
+ BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY | BIO_FLAGS_RWS);
+ BIO_set_flags(bio, flags);
+}
+
+#define RECORD_CONTENT_TYPE 0
+#define RECORD_VERSION_HI 1
+#define RECORD_VERSION_LO 2
+#define RECORD_EPOCH_HI 3
+#define RECORD_EPOCH_LO 4
+#define RECORD_SEQUENCE_START 5
+#define RECORD_SEQUENCE_END 10
+#define RECORD_LEN_HI 11
+#define RECORD_LEN_LO 12
+
+#define MSG_TYPE 0
+#define MSG_LEN_HI 1
+#define MSG_LEN_MID 2
+#define MSG_LEN_LO 3
+#define MSG_SEQ_HI 4
+#define MSG_SEQ_LO 5
+#define MSG_FRAG_OFF_HI 6
+#define MSG_FRAG_OFF_MID 7
+#define MSG_FRAG_OFF_LO 8
+#define MSG_FRAG_LEN_HI 9
+#define MSG_FRAG_LEN_MID 10
+#define MSG_FRAG_LEN_LO 11
+
+
+static void dump_data(const char *data, int len)
+{
+ int rem, i, content, reclen, msglen, fragoff, fraglen, epoch;
+ unsigned char *rec;
+
+ printf("---- START OF PACKET ----\n");
+
+ rem = len;
+ rec = (unsigned char *)data;
+
+ while (rem > 0) {
+ if (rem != len)
+ printf("*\n");
+ printf("*---- START OF RECORD ----\n");
+ if (rem < DTLS1_RT_HEADER_LENGTH) {
+ printf("*---- RECORD TRUNCATED ----\n");
+ break;
+ }
+ content = rec[RECORD_CONTENT_TYPE];
+ printf("** Record Content-type: %d\n", content);
+ printf("** Record Version: %02x%02x\n",
+ rec[RECORD_VERSION_HI], rec[RECORD_VERSION_LO]);
+ epoch = (rec[RECORD_EPOCH_HI] << 8) | rec[RECORD_EPOCH_LO];
+ printf("** Record Epoch: %d\n", epoch);
+ printf("** Record Sequence: ");
+ for (i = RECORD_SEQUENCE_START; i <= RECORD_SEQUENCE_END; i++)
+ printf("%02x", rec[i]);
+ reclen = (rec[RECORD_LEN_HI] << 8) | rec[RECORD_LEN_LO];
+ printf("\n** Record Length: %d\n", reclen);
+
+ /* Now look at message */
+ rec += DTLS1_RT_HEADER_LENGTH;
+ rem -= DTLS1_RT_HEADER_LENGTH;
+ if (content == SSL3_RT_HANDSHAKE) {
+ printf("**---- START OF HANDSHAKE MESSAGE FRAGMENT ----\n");
+ if (epoch > 0) {
+ printf("**---- HANDSHAKE MESSAGE FRAGMENT ENCRYPTED ----\n");
+ } else if (rem < DTLS1_HM_HEADER_LENGTH
+ || reclen < DTLS1_HM_HEADER_LENGTH) {
+ printf("**---- HANDSHAKE MESSAGE FRAGMENT TRUNCATED ----\n");
+ } else {
+ printf("*** Message Type: %d\n", rec[MSG_TYPE]);
+ msglen = (rec[MSG_LEN_HI] << 16) | (rec[MSG_LEN_MID] << 8)
+ | rec[MSG_LEN_LO];
+ printf("*** Message Length: %d\n", msglen);
+ printf("*** Message sequence: %d\n",
+ (rec[MSG_SEQ_HI] << 8) | rec[MSG_SEQ_LO]);
+ fragoff = (rec[MSG_FRAG_OFF_HI] << 16)
+ | (rec[MSG_FRAG_OFF_MID] << 8)
+ | rec[MSG_FRAG_OFF_LO];
+ printf("*** Message Fragment offset: %d\n", fragoff);
+ fraglen = (rec[MSG_FRAG_LEN_HI] << 16)
+ | (rec[MSG_FRAG_LEN_MID] << 8)
+ | rec[MSG_FRAG_LEN_LO];
+ printf("*** Message Fragment len: %d\n", fraglen);
+ if (fragoff + fraglen > msglen)
+ printf("***---- HANDSHAKE MESSAGE FRAGMENT INVALID ----\n");
+ else if(reclen < fraglen)
+ printf("**---- HANDSHAKE MESSAGE FRAGMENT TRUNCATED ----\n");
+ else
+ printf("**---- END OF HANDSHAKE MESSAGE FRAGMENT ----\n");
+ }
+ }
+ if (rem < reclen) {
+ printf("*---- RECORD TRUNCATED ----\n");
+ rem = 0;
+ } else {
+ rec += reclen;
+ rem -= reclen;
+ printf("*---- END OF RECORD ----\n");
+ }
+ }
+ printf("---- END OF PACKET ----\n\n");
+ fflush(stdout);
+}
+
+static int tls_dump_read(BIO *bio, char *out, int outl)
+{
+ int ret;
+ BIO *next = BIO_next(bio);
+
+ ret = BIO_read(next, out, outl);
+ copy_flags(bio);
+
+ if (ret > 0) {
+ dump_data(out, ret);
+ }
+
+ return ret;
+}
+
+static int tls_dump_write(BIO *bio, const char *in, int inl)
+{
+ int ret;
+ BIO *next = BIO_next(bio);
+
+ ret = BIO_write(next, in, inl);
+ copy_flags(bio);
+
+ return ret;
+}
+
+static long tls_dump_ctrl(BIO *bio, int cmd, long num, void *ptr)
+{
+ long ret;
+ BIO *next = BIO_next(bio);
+
+ if (next == NULL)
+ return 0;
+
+ switch (cmd) {
+ case BIO_CTRL_DUP:
+ ret = 0L;
+ break;
+ default:
+ ret = BIO_ctrl(next, cmd, num, ptr);
+ break;
+ }
+ return ret;
+}
+
+static int tls_dump_gets(BIO *bio, char *buf, int size)
+{
+ /* We don't support this - not needed anyway */
+ return -1;
+}
+
+static int tls_dump_puts(BIO *bio, const char *str)
+{
+ return tls_dump_write(bio, str, strlen(str));
+}
+
+
+typedef struct mempacket_st {
+ unsigned char *data;
+ int len;
+ unsigned int num;
+ unsigned int type;
+} MEMPACKET;
+
+/*
+ * These defines would normally be auto-generated and in safestack.h...but this
+ * is just for tests so its probably not an appropriate place
+ */
+# define sk_MEMPACKET_new(cmp) SKM_sk_new(MEMPACKET, (cmp))
+# define sk_MEMPACKET_new_null() SKM_sk_new_null(MEMPACKET)
+# define sk_MEMPACKET_free(st) SKM_sk_free(MEMPACKET, (st))
+# define sk_MEMPACKET_num(st) SKM_sk_num(MEMPACKET, (st))
+# define sk_MEMPACKET_value(st, i) SKM_sk_value(MEMPACKET, (st), (i))
+# define sk_MEMPACKET_set(st, i, val) SKM_sk_set(MEMPACKET, (st), (i), (val))
+# define sk_MEMPACKET_zero(st) SKM_sk_zero(MEMPACKET, (st))
+# define sk_MEMPACKET_push(st, val) SKM_sk_push(MEMPACKET, (st), (val))
+# define sk_MEMPACKET_unshift(st, val) SKM_sk_unshift(MEMPACKET, (st), (val))
+# define sk_MEMPACKET_find(st, val) SKM_sk_find(MEMPACKET, (st), (val))
+# define sk_MEMPACKET_find_ex(st, val) SKM_sk_find_ex(MEMPACKET, (st), (val))
+# define sk_MEMPACKET_delete(st, i) SKM_sk_delete(MEMPACKET, (st), (i))
+# define sk_MEMPACKET_delete_ptr(st, ptr) SKM_sk_delete_ptr(MEMPACKET, (st), (ptr))
+# define sk_MEMPACKET_insert(st, val, i) SKM_sk_insert(MEMPACKET, (st), (val), (i))
+# define sk_MEMPACKET_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(MEMPACKET, (st), (cmp))
+# define sk_MEMPACKET_dup(st) SKM_sk_dup(MEMPACKET, st)
+# define sk_MEMPACKET_pop_free(st, free_func) SKM_sk_pop_free(MEMPACKET, (st), (free_func))
+# define sk_MEMPACKET_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(MEMPACKET, (st), (copy_func), (free_func))
+# define sk_MEMPACKET_shift(st) SKM_sk_shift(MEMPACKET, (st))
+# define sk_MEMPACKET_pop(st) SKM_sk_pop(MEMPACKET, (st))
+# define sk_MEMPACKET_sort(st) SKM_sk_sort(MEMPACKET, (st))
+# define sk_MEMPACKET_is_sorted(st) SKM_sk_is_sorted(MEMPACKET, (st))
+
+static void mempacket_free(MEMPACKET *pkt)
+{
+ if (pkt->data != NULL)
+ OPENSSL_free(pkt->data);
+ OPENSSL_free(pkt);
+}
+
+typedef struct mempacket_test_ctx_st {
+ STACK_OF(MEMPACKET) *pkts;
+ unsigned int epoch;
+ unsigned int currrec;
+ unsigned int currpkt;
+ unsigned int lastpkt;
+ unsigned int noinject;
+} MEMPACKET_TEST_CTX;
+
+static int mempacket_test_new(BIO *bi);
+static int mempacket_test_free(BIO *a);
+static int mempacket_test_read(BIO *b, char *out, int outl);
+static int mempacket_test_write(BIO *b, const char *in, int inl);
+static long mempacket_test_ctrl(BIO *b, int cmd, long num, void *ptr);
+static int mempacket_test_gets(BIO *bp, char *buf, int size);
+static int mempacket_test_puts(BIO *bp, const char *str);
+
+static BIO_METHOD method_mempacket_test = {
+ BIO_TYPE_MEMPACKET_TEST,
+ "Mem Packet Test",
+ mempacket_test_write,
+ mempacket_test_read,
+ mempacket_test_puts,
+ mempacket_test_gets,
+ mempacket_test_ctrl,
+ mempacket_test_new,
+ mempacket_test_free
+};
+
+BIO_METHOD *bio_s_mempacket_test(void)
+{
+ return &method_mempacket_test;
+}
+
+static int mempacket_test_new(BIO *bio)
+{
+ MEMPACKET_TEST_CTX *ctx = OPENSSL_malloc(sizeof(*ctx));
+ if (ctx == NULL)
+ return 0;
+ memset(ctx, 0, sizeof(*ctx));
+
+ ctx->pkts = sk_MEMPACKET_new_null();
+ if (ctx->pkts == NULL) {
+ OPENSSL_free(ctx);
+ return 0;
+ }
+ bio->init = 1;
+ bio->ptr = ctx;
+ return 1;
+}
+
+static int mempacket_test_free(BIO *bio)
+{
+ MEMPACKET_TEST_CTX *ctx = bio->ptr;
+
+ sk_MEMPACKET_pop_free(ctx->pkts, mempacket_free);
+ OPENSSL_free(ctx);
+ bio->ptr = NULL;
+ bio->init = 0;
+
+ return 1;
+}
+
+/* Record Header values */
+#define EPOCH_HI 4
+#define EPOCH_LO 5
+#define RECORD_SEQUENCE 10
+#define RECORD_LEN_HI 11
+#define RECORD_LEN_LO 12
+
+#define STANDARD_PACKET 0
+
+static int mempacket_test_read(BIO *bio, char *out, int outl)
+{
+ MEMPACKET_TEST_CTX *ctx = bio->ptr;
+ MEMPACKET *thispkt;
+ unsigned char *rec;
+ int rem;
+ unsigned int seq, offset, len, epoch;
+
+ BIO_clear_retry_flags(bio);
+
+ thispkt = sk_MEMPACKET_value(ctx->pkts, 0);
+ if (thispkt == NULL || thispkt->num != ctx->currpkt) {
+ /* Probably run out of data */
+ BIO_set_retry_read(bio);
+ return -1;
+ }
+ (void)sk_MEMPACKET_shift(ctx->pkts);
+ ctx->currpkt++;
+
+ if (outl > thispkt->len)
+ outl = thispkt->len;
+
+ if (thispkt->type != INJECT_PACKET_IGNORE_REC_SEQ) {
+ /*
+ * Overwrite the record sequence number. We strictly number them in
+ * the order received. Since we are actually a reliable transport
+ * we know that there won't be any re-ordering. We overwrite to deal
+ * with any packets that have been injected
+ */
+ rem = thispkt->len;
+ rec = thispkt->data;
+ while (rem > 0) {
+ if (rem < DTLS1_RT_HEADER_LENGTH) {
+ return -1;
+ }
+ epoch = (rec[EPOCH_HI] << 8) | rec[EPOCH_LO];
+ if (epoch != ctx->epoch) {
+ ctx->epoch = epoch;
+ ctx->currrec = 0;
+ }
+ seq = ctx->currrec;
+ offset = 0;
+ do {
+ rec[RECORD_SEQUENCE - offset] = seq & 0xFF;
+ seq >>= 8;
+ offset++;
+ } while (seq > 0);
+ ctx->currrec++;
+
+ len = ((rec[RECORD_LEN_HI] << 8) | rec[RECORD_LEN_LO])
+ + DTLS1_RT_HEADER_LENGTH;
+
+ rec += len;
+ rem -= len;
+ }
+ }
+
+ memcpy(out, thispkt->data, outl);
+
+ mempacket_free(thispkt);
+
+ return outl;
+}
+
+int mempacket_test_inject(BIO *bio, const char *in, int inl, int pktnum,
+ int type)
+{
+ MEMPACKET_TEST_CTX *ctx = bio->ptr;
+ MEMPACKET *thispkt, *looppkt, *nextpkt;
+ int i;
+
+ if (ctx == NULL)
+ return -1;
+
+ /* We only allow injection before we've started writing any data */
+ if (pktnum >= 0) {
+ if (ctx->noinject)
+ return -1;
+ } else {
+ ctx->noinject = 1;
+ }
+
+ thispkt = OPENSSL_malloc(sizeof(MEMPACKET));
+ if (thispkt == NULL)
+ return -1;
+
+ thispkt->data = OPENSSL_malloc(inl);
+ if (thispkt->data == NULL) {
+ mempacket_free(thispkt);
+ return -1;
+ }
+
+ memcpy(thispkt->data, in, inl);
+ thispkt->len = inl;
+ thispkt->num = (pktnum >= 0) ? (unsigned int)pktnum : ctx->lastpkt;
+ thispkt->type = type;
+
+ for(i = 0; (looppkt = sk_MEMPACKET_value(ctx->pkts, i)) != NULL; i++) {
+ /* Check if we found the right place to insert this packet */
+ if (looppkt->num > thispkt->num) {
+ if (sk_MEMPACKET_insert(ctx->pkts, thispkt, i) == 0) {
+ mempacket_free(thispkt);
+ return -1;
+ }
+ /* If we're doing up front injection then we're done */
+ if (pktnum >= 0)
+ return inl;
+ /*
+ * We need to do some accounting on lastpkt. We increment it first,
+ * but it might now equal the value of injected packets, so we need
+ * to skip over those
+ */
+ ctx->lastpkt++;
+ do {
+ i++;
+ nextpkt = sk_MEMPACKET_value(ctx->pkts, i);
+ if (nextpkt != NULL && nextpkt->num == ctx->lastpkt)
+ ctx->lastpkt++;
+ else
+ return inl;
+ } while(1);
+ } else if(looppkt->num == thispkt->num) {
+ if (!ctx->noinject) {
+ /* We injected two packets with the same packet number! */
+ return -1;
+ }
+ ctx->lastpkt++;
+ thispkt->num++;
+ }
+ }
+ /*
+ * We didn't find any packets with a packet number equal to or greater than
+ * this one, so we just add it onto the end
+ */
+ if (!sk_MEMPACKET_push(ctx->pkts, thispkt)) {
+ mempacket_free(thispkt);
+ return -1;
+ }
+
+ if (pktnum < 0)
+ ctx->lastpkt++;
+
+ return inl;
+}
+
+static int mempacket_test_write(BIO *bio, const char *in, int inl)
+{
+ return mempacket_test_inject(bio, in, inl, -1, STANDARD_PACKET);
+}
+
+static long mempacket_test_ctrl(BIO *bio, int cmd, long num, void *ptr)
+{
+ long ret = 1;
+ MEMPACKET_TEST_CTX *ctx = bio->ptr;
+ MEMPACKET *thispkt;
+
+ switch (cmd) {
+ case BIO_CTRL_EOF:
+ ret = (long)(sk_MEMPACKET_num(ctx->pkts) == 0);
+ break;
+ case BIO_CTRL_GET_CLOSE:
+ ret = bio->shutdown;
+ break;
+ case BIO_CTRL_SET_CLOSE:
+ bio->shutdown = (int)num;
+ break;
+ case BIO_CTRL_WPENDING:
+ ret = 0L;
+ break;
+ case BIO_CTRL_PENDING:
+ thispkt = sk_MEMPACKET_value(ctx->pkts, 0);
+ if (thispkt == NULL)
+ ret = 0;
+ else
+ ret = thispkt->len;
+ break;
+ case BIO_CTRL_FLUSH:
+ ret = 1;
+ break;
+ case BIO_CTRL_RESET:
+ case BIO_CTRL_DUP:
+ case BIO_CTRL_PUSH:
+ case BIO_CTRL_POP:
+ default:
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
+static int mempacket_test_gets(BIO *bio, char *buf, int size)
+{
+ /* We don't support this - not needed anyway */
+ return -1;
+}
+
+static int mempacket_test_puts(BIO *bio, const char *str)
+{
+ return mempacket_test_write(bio, str, strlen(str));
+}
+
+int create_ssl_ctx_pair(const SSL_METHOD *sm, const SSL_METHOD *cm,
+ SSL_CTX **sctx, SSL_CTX **cctx, char *certfile,
+ char *privkeyfile)
+{
+ SSL_CTX *serverctx = NULL;
+ SSL_CTX *clientctx = NULL;
+
+ serverctx = SSL_CTX_new(sm);
+ clientctx = SSL_CTX_new(cm);
+ if (serverctx == NULL || clientctx == NULL) {
+ printf("Failed to create SSL_CTX\n");
+ goto err;
+ }
+
+ if (SSL_CTX_use_certificate_file(serverctx, certfile,
+ SSL_FILETYPE_PEM) <= 0) {
+ printf("Failed to load server certificate\n");
+ goto err;
+ }
+ if (SSL_CTX_use_PrivateKey_file(serverctx, privkeyfile,
+ SSL_FILETYPE_PEM) <= 0) {
+ printf("Failed to load server private key\n");
+ }
+ if (SSL_CTX_check_private_key(serverctx) <= 0) {
+ printf("Failed to check private key\n");
+ goto err;
+ }
+
+ *sctx = serverctx;
+ *cctx = clientctx;
+
+ return 1;
+ err:
+ SSL_CTX_free(serverctx);
+ SSL_CTX_free(clientctx);
+ return 0;
+}
+
+#define MAXLOOPS 100000
+
+/*
+ * NOTE: Transfers control of the BIOs - this function will free them on error
+ */
+int create_ssl_objects(SSL_CTX *serverctx, SSL_CTX *clientctx, SSL **sssl,
+ SSL **cssl, BIO *s_to_c_fbio, BIO *c_to_s_fbio)
+{
+ SSL *serverssl, *clientssl;
+ BIO *s_to_c_bio = NULL, *c_to_s_bio = NULL;
+
+ serverssl = SSL_new(serverctx);
+ clientssl = SSL_new(clientctx);
+
+ if (serverssl == NULL || clientssl == NULL) {
+ printf("Failed to create SSL object\n");
+ goto error;
+ }
+
+ if (SSL_IS_DTLS(clientssl)) {
+ s_to_c_bio = BIO_new(bio_s_mempacket_test());
+ c_to_s_bio = BIO_new(bio_s_mempacket_test());;
+ } else {
+ s_to_c_bio = BIO_new(BIO_s_mem());
+ c_to_s_bio = BIO_new(BIO_s_mem());
+ }
+ if (s_to_c_bio == NULL || c_to_s_bio == NULL) {
+ printf("Failed to create mem BIOs\n");
+ goto error;
+ }
+
+ if (s_to_c_fbio != NULL)
+ s_to_c_bio = BIO_push(s_to_c_fbio, s_to_c_bio);
+ if (c_to_s_fbio != NULL)
+ c_to_s_bio = BIO_push(c_to_s_fbio, c_to_s_bio);
+ if (s_to_c_bio == NULL || c_to_s_bio == NULL) {
+ printf("Failed to create chained BIOs\n");
+ goto error;
+ }
+
+ /* Set Non-blocking IO behaviour */
+ BIO_set_mem_eof_return(s_to_c_bio, -1);
+ BIO_set_mem_eof_return(c_to_s_bio, -1);
+
+ /* Up ref these as we are passing them to two SSL objects */
+ CRYPTO_add(&s_to_c_bio->references, 1, CRYPTO_LOCK_BIO);
+ CRYPTO_add(&c_to_s_bio->references, 1, CRYPTO_LOCK_BIO);
+
+ SSL_set_bio(serverssl, c_to_s_bio, s_to_c_bio);
+ SSL_set_bio(clientssl, s_to_c_bio, c_to_s_bio);
+
+ /* BIOs will now be freed when SSL objects are freed */
+ s_to_c_bio = c_to_s_bio = NULL;
+ s_to_c_fbio = c_to_s_fbio = NULL;
+
+ *sssl = serverssl;
+ *cssl = clientssl;
+
+ return 1;
+
+ error:
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ BIO_free(s_to_c_bio);
+ BIO_free(c_to_s_bio);
+ BIO_free(s_to_c_fbio);
+ BIO_free(c_to_s_fbio);
+
+ return 0;
+}
+
+int create_ssl_connection(SSL *serverssl, SSL *clientssl)
+{
+ int retc = -1, rets = -1, err, abortctr = 0;
+
+ do {
+ err = SSL_ERROR_WANT_WRITE;
+ while (retc <= 0 && err == SSL_ERROR_WANT_WRITE) {
+ retc = SSL_connect(clientssl);
+ if (retc <= 0)
+ err = SSL_get_error(clientssl, retc);
+ }
+
+ if (retc <= 0 && err != SSL_ERROR_WANT_READ) {
+ printf("SSL_connect() failed %d, %d\n", retc, err);
+ return 0;
+ }
+
+ err = SSL_ERROR_WANT_WRITE;
+ while (rets <= 0 && err == SSL_ERROR_WANT_WRITE) {
+ rets = SSL_accept(serverssl);
+ if (rets <= 0)
+ err = SSL_get_error(serverssl, rets);
+ }
+
+ if (rets <= 0 && err != SSL_ERROR_WANT_READ) {
+ printf("SSL_accept() failed %d, %d\n", retc, err);
+ return 0;
+ }
+ if (++abortctr == MAXLOOPS) {
+ printf("No progress made\n");
+ return 0;
+ }
+ } while (retc <=0 || rets <= 0);
+
+ return 1;
+}
diff --git a/test/ssltestlib.h b/test/ssltestlib.h
new file mode 100644
index 0000000000..b23d8f4d10
--- /dev/null
+++ b/test/ssltestlib.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016 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 HEADER_SSLTESTLIB_H
+# define HEADER_SSLTESTLIB_H
+
+# include <openssl/ssl.h>
+
+int create_ssl_ctx_pair(const SSL_METHOD *sm, const SSL_METHOD *cm,
+ SSL_CTX **sctx, SSL_CTX **cctx, char *certfile,
+ char *privkeyfile);
+int create_ssl_objects(SSL_CTX *serverctx, SSL_CTX *clientctx, SSL **sssl,
+ SSL **cssl, BIO *s_to_c_fbio, BIO *c_to_s_fbio);
+int create_ssl_connection(SSL *serverssl, SSL *clientssl);
+
+/* Note: Not thread safe! */
+BIO_METHOD *bio_f_tls_dump_filter(void);
+void bio_f_tls_dump_filter_free(void);
+
+BIO_METHOD *bio_s_mempacket_test(void);
+void bio_s_mempacket_test_free(void);
+
+/* Packet types - value 0 is reserved */
+#define INJECT_PACKET 1
+#define INJECT_PACKET_IGNORE_REC_SEQ 2
+
+int mempacket_test_inject(BIO *bio, const char *in, int inl, int pktnum,
+ int type);
+
+#endif /* HEADER_SSLTESTLIB_H */
diff --git a/test/tests.com b/test/tests.com
index 6e1c818e7a..59745e14c7 100644
--- a/test/tests.com
+++ b/test/tests.com
@@ -55,9 +55,9 @@ $ tests := -
test_rand,test_bn,test_ec,test_ecdsa,test_ecdh,-
test_enc,test_x509,test_rsa,test_crl,test_sid,-
test_gen,test_req,test_pkcs7,test_verify,test_dh,test_dsa,-
- test_ss,test_ca,test_engine,test_evp,test_ssl,test_tsa,test_ige,-
+ test_ss,test_ca,test_engine,test_evp,test_evp_extra,test_ssl,test_tsa,test_ige,-
test_jpake,test_srp,test_cms,test_ocsp,test_v3name,test_heartbeat,-
- test_constant_time
+ test_constant_time,test_verify_extra,test_clienthello,test_sslv2conftest,test_dtls
$ endif
$ tests = f$edit(tests,"COLLAPSE")
$
@@ -92,6 +92,7 @@ $ SSLTEST := ssltest
$ RSATEST := rsa_test
$ ENGINETEST := enginetest
$ EVPTEST := evp_test
+$ EVPEXTRATEST := evp_extra_test
$ IGETEST := igetest
$ JPAKETEST := jpaketest
$ SRPTEST := srptest
@@ -99,6 +100,10 @@ $ V3NAMETEST := v3nametest
$ ASN1TEST := asn1test
$ HEARTBEATTEST := heartbeat_test
$ CONSTTIMETEST := constant_time_test
+$ VERIFYEXTRATEST := verify_extra_test
+$ CLIENTHELLOTEST := clienthellotest
+$ SSLV2CONFTEST := sslv2conftest
+$ DTLSTEST := dtlstest
$!
$ tests_i = 0
$ loop_tests:
@@ -112,6 +117,9 @@ $
$ test_evp:
$ mcr 'texe_dir''evptest' 'ROOT'.CRYPTO.EVP]evptests.txt
$ return
+$ test_evp_extra:
+$ mcr 'texe_dir''evpextratest'
+$ return
$ test_des:
$ mcr 'texe_dir''destest'
$ return
@@ -386,7 +394,22 @@ $ test_constant_time:
$ write sys$output "Test constant time utilities"
$ mcr 'texe_dir''consttimetest'
$ return
-$
+$ test_verify_extra:
+$ write sys$output "''START' test_verify_extra"
+$ mcr 'texe_dir''verifyextratest'
+$ return
+$ test_clienthello:
+$ write sys$output "''START' test_clienthello"
+$ mcr 'texe_dir''clienthellotest'
+$ return
+$ test_sslv2conftest:
+$ write sys$output "''START' test_sslv2conftest"
+$ mcr 'texe_dir''sslv2conftest'
+$ return
+$ test_dtls:
+$ write sys$output "''START' test_dtls"
+$ mcr 'texe_dir''dtlstest' 'ROOT'.APPS]server.pem 'ROOT'.APPS]server.pem
+$ return
$
$ exit:
$ on error then goto exit2 ! In case openssl.exe didn't build.
diff --git a/util/mk1mf.pl b/util/mk1mf.pl
index 128a405efc..4eded5aafe 100755
--- a/util/mk1mf.pl
+++ b/util/mk1mf.pl
@@ -692,8 +692,8 @@ $rules.=&do_copy_rule("\$(INCL_D)",$header,"");
$defs.=&do_defs("EXHEADER",$exheader,"\$(INCO_D)","");
$rules.=&do_copy_rule("\$(INCO_D)",$exheader,"");
-$defs.=&do_defs("T_OBJ",$test,"\$(OBJ_D)",$obj);
-$rules.=&do_compile_rule("\$(OBJ_D)",$test,"\$(APP_CFLAGS)");
+$defs.=&do_defs("T_OBJ","$test test${o}ssltestlib","\$(OBJ_D)",$obj);
+$rules.=&do_compile_rule("\$(OBJ_D)","$test test${o}ssltestlib","\$(APP_CFLAGS)");
$defs.=&do_defs("E_OBJ",$e_exe,"\$(OBJ_D)",$obj);
$rules.=&do_compile_rule("\$(OBJ_D)",$e_exe,'-DMONOLITH $(APP_CFLAGS)');
@@ -764,6 +764,7 @@ foreach (split(/\s+/,$test))
{
$t=&bname($_);
$tt="\$(OBJ_D)${o}$t${obj}";
+ $tt.=" \$(OBJ_D)${o}ssltestlib${obj}" if $t eq "dtlstest";
$rules.=&do_link_rule("\$(TEST_D)$o$t$exep",$tt,"\$(LIBS_DEP)","\$(L_LIBS) \$(EX_LIBS)");
}