summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--FAQ11
-rw-r--r--apps/apps.h2
-rw-r--r--apps/s_cb.c12
-rw-r--r--apps/s_server.c4
-rw-r--r--crypto/asn1/asn1.h4
-rwxr-xr-xcrypto/bn/asm/rsaz-x86_64.pl18
-rw-r--r--crypto/cms/cms.h3
-rw-r--r--crypto/cms/cms_asn1.c43
-rw-r--r--crypto/dh/Makefile4
-rw-r--r--crypto/dh/dh.h87
-rw-r--r--crypto/dh/dh_ameth.c453
-rw-r--r--crypto/dh/dh_asn1.c5
-rw-r--r--crypto/dh/dh_err.c8
-rw-r--r--crypto/dh/dh_kdf.c197
-rw-r--r--crypto/dh/dh_pmeth.c259
-rw-r--r--crypto/ec/ec_ameth.c92
-rw-r--r--crypto/ecdh/ech_kdf.c2
-rw-r--r--crypto/evp/e_aes.c18
-rw-r--r--crypto/evp/e_des3.c3
-rw-r--r--crypto/evp/evp_lib.c14
-rw-r--r--crypto/ossl_typ.h2
-rw-r--r--crypto/pem/pem_info.c1
-rwxr-xr-xcrypto/sha/asm/sha1-x86_64.pl4
-rwxr-xr-xcrypto/sha/asm/sha512-x86_64.pl12
-rw-r--r--crypto/x509/x509_cmp.c16
-rw-r--r--doc/apps/cms.pod18
-rw-r--r--doc/apps/x509.pod10
-rw-r--r--doc/crypto/ecdsa.pod10
-rw-r--r--doc/ssl/SSL_CTX_add1_chain_cert.pod92
-rw-r--r--doc/ssl/SSL_CTX_add_extra_chain_cert.pod19
-rw-r--r--doc/ssl/SSL_CTX_set1_curves.pod100
-rw-r--r--doc/ssl/SSL_CTX_set1_verify_cert_store.pod93
-rw-r--r--doc/ssl/SSL_CTX_set_cert_store.pod7
-rw-r--r--fips/rand/fips_randtest.c2
-rw-r--r--ssl/d1_pkt.c7
-rw-r--r--ssl/d1_srvr.c3
-rw-r--r--ssl/s3_lib.c24
-rw-r--r--ssl/ssl_ciph.c7
-rw-r--r--ssl/ssl_conf.c6
-rw-r--r--ssl/ssl_lib.c15
-rw-r--r--ssl/ssl_rsa.c9
-rw-r--r--ssl/t1_lib.c19
-rw-r--r--test/cms-test.pl28
-rw-r--r--test/smime-certs/mksmime-certs.sh15
-rw-r--r--test/smime-certs/smdh.pem33
45 files changed, 1631 insertions, 160 deletions
diff --git a/FAQ b/FAQ
index df681c8168..612e33060c 100644
--- a/FAQ
+++ b/FAQ
@@ -35,6 +35,7 @@ OpenSSL - Frequently Asked Questions
* What is a "128 bit certificate"? Can I create one with OpenSSL?
* Why does OpenSSL set the authority key identifier extension incorrectly?
* How can I set up a bundle of commercial root CA certificates?
+* Some secure servers 'hang' with OpenSSL 1.0.1, is this a bug?
[BUILD] Questions about building and testing OpenSSL
@@ -491,6 +492,16 @@ bundle used by Mozilla and/or modssl as described in this article:
<URL: http://www.mail-archive.com/modssl-users@modssl.org/msg16980.html>
+* Some secure servers 'hang' with OpenSSL 1.0.1, is this a bug?
+
+OpenSSL 1.0.1 is the first release to support TLS 1.2, among other things,
+this increases the size of the default ClientHello message to more than
+255 bytes in length. Some software cannot handle this and hangs. For more
+details and workarounds see:
+
+ <URL: http://rt.openssl.org/Ticket/Display.html?user=guest&pass=guest&id=2771>
+
+
[BUILD] =======================================================================
* Why does the linker complain about undefined symbols?
diff --git a/apps/apps.h b/apps/apps.h
index 0a9d90bcb5..3f15f1034a 100644
--- a/apps/apps.h
+++ b/apps/apps.h
@@ -183,7 +183,6 @@ extern BIO *bio_err;
# define apps_startup() \
do { do_pipe_sig(); CRYPTO_malloc_init(); \
ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); \
- RAND_cleanup(); \
ENGINE_load_builtin_engines(); setup_ui_method(); } while(0)
# define apps_shutdown() \
do { CONF_modules_unload(1); destroy_ui_method(); \
@@ -200,6 +199,7 @@ extern BIO *bio_err;
do { CONF_modules_unload(1); destroy_ui_method(); \
OBJ_cleanup(); EVP_cleanup(); \
CRYPTO_cleanup_all_ex_data(); ERR_remove_thread_state(NULL); \
+ RAND_cleanup(); \
ERR_free_strings(); zlib_cleanup(); } while(0)
# endif
#endif
diff --git a/apps/s_cb.c b/apps/s_cb.c
index f28fa318d4..8127e77143 100644
--- a/apps/s_cb.c
+++ b/apps/s_cb.c
@@ -423,7 +423,7 @@ int ssl_print_sigalgs(BIO *out, SSL *s)
BIO_printf(out, "Peer signing digest: %s\n", OBJ_nid2sn(mdnid));
return 1;
}
-
+#ifndef OPENSSL_NO_EC
int ssl_print_point_formats(BIO *out, SSL *s)
{
int i, nformats;
@@ -515,7 +515,7 @@ int ssl_print_curves(BIO *out, SSL *s, int noshared)
BIO_puts(out, "\n");
return 1;
}
-
+#endif
int ssl_print_tmp_key(BIO *out, SSL *s)
{
EVP_PKEY *key;
@@ -531,7 +531,7 @@ int ssl_print_tmp_key(BIO *out, SSL *s)
case EVP_PKEY_DH:
BIO_printf(out, "DH, %d bits\n", EVP_PKEY_bits(key));
break;
-
+#ifndef OPENSSL_NO_ECDH
case EVP_PKEY_EC:
{
EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key);
@@ -545,6 +545,7 @@ int ssl_print_tmp_key(BIO *out, SSL *s)
BIO_printf(out, "ECDH, %s, %d bits\n",
cname, EVP_PKEY_bits(key));
}
+#endif
}
EVP_PKEY_free(key);
return 1;
@@ -1568,11 +1569,16 @@ void print_ssl_summary(BIO *bio, SSL *s)
BIO_puts(bio, "No peer certificate\n");
if (peer)
X509_free(peer);
+#ifndef OPENSSL_NO_EC
ssl_print_point_formats(bio, s);
if (SSL_is_server(s))
ssl_print_curves(bio, s, 1);
else
ssl_print_tmp_key(bio, s);
+#else
+ if (!SSL_is_server(s))
+ ssl_print_tmp_key(bio, s);
+#endif
}
int args_ssl(char ***pargs, int *pargc, SSL_CONF_CTX *cctx,
diff --git a/apps/s_server.c b/apps/s_server.c
index 80df0fd966..c3eca2bca5 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -2723,8 +2723,10 @@ static int init_ssl_connection(SSL *con)
BIO_printf(bio_s_out,"Shared ciphers:%s\n",buf);
str=SSL_CIPHER_get_name(SSL_get_current_cipher(con));
ssl_print_sigalgs(bio_s_out, con);
+#ifndef OPENSSL_NO_EC
ssl_print_point_formats(bio_s_out, con);
ssl_print_curves(bio_s_out, con, 0);
+#endif
BIO_printf(bio_s_out,"CIPHER is %s\n",(str != NULL)?str:"(NONE)");
#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
@@ -3067,7 +3069,9 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context)
BIO_puts(io,"\n");
}
ssl_print_sigalgs(io, con);
+#ifndef OPENSSL_NO_EC
ssl_print_curves(io, con, 0);
+#endif
BIO_printf(io,(SSL_cache_hit(con)
?"---\nReused, "
:"---\nNew, "));
diff --git a/crypto/asn1/asn1.h b/crypto/asn1/asn1.h
index accc1e946b..8bc24d3225 100644
--- a/crypto/asn1/asn1.h
+++ b/crypto/asn1/asn1.h
@@ -208,14 +208,14 @@ typedef struct asn1_const_ctx_st
#define ASN1_OBJECT_FLAG_CRITICAL 0x02 /* critical x509v3 object id */
#define ASN1_OBJECT_FLAG_DYNAMIC_STRINGS 0x04 /* internal use */
#define ASN1_OBJECT_FLAG_DYNAMIC_DATA 0x08 /* internal use */
-typedef struct asn1_object_st
+struct asn1_object_st
{
const char *sn,*ln;
int nid;
int length;
const unsigned char *data; /* data remains const after init */
int flags; /* Should we free this one */
- } ASN1_OBJECT;
+ };
#define ASN1_STRING_FLAG_BITS_LEFT 0x08 /* Set if 0x07 has bits left value */
/* This indicates that the ASN1_STRING is not a real value but just a place
diff --git a/crypto/bn/asm/rsaz-x86_64.pl b/crypto/bn/asm/rsaz-x86_64.pl
index ed84463697..f6adb30b7b 100755
--- a/crypto/bn/asm/rsaz-x86_64.pl
+++ b/crypto/bn/asm/rsaz-x86_64.pl
@@ -729,7 +729,7 @@ ___
{
my ($out,$ap,$bp,$mod,$n0) = ("%rdi","%rsi","%rdx","%rcx","%r8");
$code.=<<___;
-.global rsaz_512_mul
+.globl rsaz_512_mul
.type rsaz_512_mul,\@function,5
.align 32
rsaz_512_mul:
@@ -747,7 +747,7 @@ rsaz_512_mul:
movq $n0, 128(%rsp)
movq $bp, %rbp # pass argument
- call _rsaz_512_mul
+ call __rsaz_512_mul
movq %xmm0, $out
movq %xmm1, %rbp
@@ -791,7 +791,7 @@ ___
{
my ($out,$ap,$bp,$mod,$n0,$pwr) = ("%rdi","%rsi","%rdx","%rcx","%r8","%r9d");
$code.=<<___;
-.global rsaz_512_mul_gather4
+.globl rsaz_512_mul_gather4
.type rsaz_512_mul_gather4,\@function,6
.align 32
rsaz_512_mul_gather4:
@@ -999,7 +999,7 @@ ___
{
my ($out,$ap,$mod,$n0,$tbl,$pwr) = ("%rdi","%rsi","%rdx","%rcx","%r8","%r9d");
$code.=<<___;
-.global rsaz_512_mul_scatter4
+.globl rsaz_512_mul_scatter4
.type rsaz_512_mul_scatter4,\@function,6
.align 32
rsaz_512_mul_scatter4:
@@ -1019,7 +1019,7 @@ rsaz_512_mul_scatter4:
movq $n0, 128(%rsp)
movq $out, %rbp
- call _rsaz_512_mul
+ call __rsaz_512_mul
movq %xmm0, $out
movq %xmm1, %rbp
@@ -1359,16 +1359,16 @@ _rsaz_512_subtract:
.size _rsaz_512_subtract,.-_rsaz_512_subtract
___
}
-{ # _rsaz_512_mul
+{ # __rsaz_512_mul
#
# input: %rsi - ap, %rbp - bp
# ouput:
# clobbers: everything
my ($ap,$bp) = ("%rsi","%rbp");
$code.=<<___;
-.type _rsaz_512_mul,\@abi-omnipotent
+.type __rsaz_512_mul,\@abi-omnipotent
.align 32
-_rsaz_512_mul:
+__rsaz_512_mul:
leaq 8(%rsp), %rdi
movq ($bp), %rbx
@@ -1508,7 +1508,7 @@ _rsaz_512_mul:
movq %r15, 56(%rdi)
ret
-.size _rsaz_512_mul,.-_rsaz_512_mul
+.size __rsaz_512_mul,.-__rsaz_512_mul
___
}
{
diff --git a/crypto/cms/cms.h b/crypto/cms/cms.h
index f644cbfbc4..8b1d29f0c1 100644
--- a/crypto/cms/cms.h
+++ b/crypto/cms/cms.h
@@ -364,6 +364,9 @@ EVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri);
int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
CMS_RecipientEncryptedKey *rek);
+int CMS_SharedInfo_encode(unsigned char **pder, X509_ALGOR *kekalg,
+ ASN1_OCTET_STRING *ukm, int keylen);
+
/* BEGIN ERROR CODES */
/* 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.
diff --git a/crypto/cms/cms_asn1.c b/crypto/cms/cms_asn1.c
index 7d79db221a..83ae2cc0f3 100644
--- a/crypto/cms/cms_asn1.c
+++ b/crypto/cms/cms_asn1.c
@@ -423,3 +423,46 @@ ASN1_SEQUENCE(CMS_Receipt) = {
ASN1_SIMPLE(CMS_Receipt, originatorSignatureValue, ASN1_OCTET_STRING)
} ASN1_SEQUENCE_END(CMS_Receipt)
+/* Utilities to encode the CMS_SharedInfo structure used during key
+ * derivation.
+ */
+
+typedef struct {
+ X509_ALGOR *keyInfo;
+ ASN1_OCTET_STRING *entityUInfo;
+ ASN1_OCTET_STRING *suppPubInfo;
+} CMS_SharedInfo;
+
+ASN1_SEQUENCE(CMS_SharedInfo) = {
+ ASN1_SIMPLE(CMS_SharedInfo, keyInfo, X509_ALGOR),
+ ASN1_EXP_OPT(CMS_SharedInfo, entityUInfo, ASN1_OCTET_STRING, 0),
+ ASN1_EXP_OPT(CMS_SharedInfo, suppPubInfo, ASN1_OCTET_STRING, 2),
+} ASN1_SEQUENCE_END(CMS_SharedInfo)
+
+int CMS_SharedInfo_encode(unsigned char **pder, X509_ALGOR *kekalg,
+ ASN1_OCTET_STRING *ukm, int keylen)
+ {
+ union {
+ CMS_SharedInfo *pecsi;
+ ASN1_VALUE *a;
+ } intsi = {NULL};
+
+ ASN1_OCTET_STRING oklen;
+ unsigned char kl[4];
+ CMS_SharedInfo ecsi;
+
+ keylen <<= 3;
+ kl[0] = (keylen >> 24) & 0xff;
+ kl[1] = (keylen >> 16) & 0xff;
+ kl[2] = (keylen >> 8) & 0xff;
+ kl[3] = keylen & 0xff;
+ oklen.length = 4;
+ oklen.data = kl;
+ oklen.type = V_ASN1_OCTET_STRING;
+ oklen.flags = 0;
+ ecsi.keyInfo = kekalg;
+ ecsi.entityUInfo = ukm;
+ ecsi.suppPubInfo = &oklen;
+ intsi.pecsi = &ecsi;
+ return ASN1_item_i2d(intsi.a, pder, ASN1_ITEM_rptr(CMS_SharedInfo));
+ }
diff --git a/crypto/dh/Makefile b/crypto/dh/Makefile
index 9dd08d617b..ca01f373b4 100644
--- a/crypto/dh/Makefile
+++ b/crypto/dh/Makefile
@@ -18,9 +18,9 @@ APPS=
LIB=$(TOP)/libcrypto.a
LIBSRC= dh_asn1.c dh_gen.c dh_key.c dh_lib.c dh_check.c dh_err.c dh_depr.c \
- dh_ameth.c dh_pmeth.c dh_prn.c dh_rfc5114.c
+ dh_ameth.c dh_pmeth.c dh_prn.c dh_rfc5114.c dh_kdf.c
LIBOBJ= dh_asn1.o dh_gen.o dh_key.o dh_lib.o dh_check.o dh_err.o dh_depr.o \
- dh_ameth.o dh_pmeth.o dh_prn.o dh_rfc5114.o
+ dh_ameth.o dh_pmeth.o dh_prn.o dh_rfc5114.o dh_kdf.o
SRC= $(LIBSRC)
diff --git a/crypto/dh/dh.h b/crypto/dh/dh.h
index ce5fee9c79..0cbb32e336 100644
--- a/crypto/dh/dh.h
+++ b/crypto/dh/dh.h
@@ -239,10 +239,25 @@ DH *DH_get_1024_160(void);
DH *DH_get_2048_224(void);
DH *DH_get_2048_256(void);
+/* RFC2631 KDF */
+int DH_KDF_X9_42(unsigned char *out, size_t outlen,
+ const unsigned char *Z, size_t Zlen,
+ ASN1_OBJECT *key_oid,
+ const unsigned char *ukm, size_t ukmlen,
+ const EVP_MD *md);
+
#define EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \
EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN, len, NULL)
+#define EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, len) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \
+ EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN, len, NULL)
+
+#define EVP_PKEY_CTX_set_dh_paramgen_type(ctx, typ) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \
+ EVP_PKEY_CTRL_DH_PARAMGEN_TYPE, typ, NULL)
+
#define EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, gen) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \
EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR, gen, NULL)
@@ -255,10 +270,74 @@ DH *DH_get_2048_256(void);
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_PARAMGEN, \
EVP_PKEY_CTRL_DH_RFC5114, gen, NULL)
+#define EVP_PKEY_CTX_set_dh_kdf_type(ctx, kdf) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
+ EVP_PKEY_OP_DERIVE, \
+ EVP_PKEY_CTRL_DH_KDF_TYPE, kdf, NULL)
+
+#define EVP_PKEY_CTX_get_dh_kdf_type(ctx) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
+ EVP_PKEY_OP_DERIVE, \
+ EVP_PKEY_CTRL_DH_KDF_TYPE, -2, NULL)
+
+#define EVP_PKEY_CTX_set0_dh_kdf_oid(ctx, oid) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
+ EVP_PKEY_OP_DERIVE, \
+ EVP_PKEY_CTRL_DH_KDF_OID, 0, (void *)oid)
+
+#define EVP_PKEY_CTX_get0_dh_kdf_oid(ctx, poid) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
+ EVP_PKEY_OP_DERIVE, \
+ EVP_PKEY_CTRL_GET_DH_KDF_OID, 0, (void *)poid)
+
+#define EVP_PKEY_CTX_set_dh_kdf_md(ctx, md) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
+ EVP_PKEY_OP_DERIVE, \
+ EVP_PKEY_CTRL_DH_KDF_MD, 0, (void *)md)
+
+#define EVP_PKEY_CTX_get_dh_kdf_md(ctx, pmd) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
+ EVP_PKEY_OP_DERIVE, \
+ EVP_PKEY_CTRL_GET_DH_KDF_MD, 0, (void *)pmd)
+
+#define EVP_PKEY_CTX_set_dh_kdf_outlen(ctx, len) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
+ EVP_PKEY_OP_DERIVE, \
+ EVP_PKEY_CTRL_DH_KDF_OUTLEN, len, NULL)
+
+#define EVP_PKEY_CTX_get_dh_kdf_outlen(ctx, plen) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
+ EVP_PKEY_OP_DERIVE, \
+ EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN, 0, (void *)plen)
+
+#define EVP_PKEY_CTX_set0_dh_kdf_ukm(ctx, p, plen) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
+ EVP_PKEY_OP_DERIVE, \
+ EVP_PKEY_CTRL_DH_KDF_UKM, plen, (void *)p)
+
+#define EVP_PKEY_CTX_get0_dh_kdf_ukm(ctx, p) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
+ EVP_PKEY_OP_DERIVE, \
+ EVP_PKEY_CTRL_GET_DH_KDF_UKM, 0, (void *)p)
+
#define EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN (EVP_PKEY_ALG_CTRL + 1)
#define EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR (EVP_PKEY_ALG_CTRL + 2)
#define EVP_PKEY_CTRL_DH_RFC5114 (EVP_PKEY_ALG_CTRL + 3)
-
+#define EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN (EVP_PKEY_ALG_CTRL + 4)
+#define EVP_PKEY_CTRL_DH_PARAMGEN_TYPE (EVP_PKEY_ALG_CTRL + 5)
+#define EVP_PKEY_CTRL_DH_KDF_TYPE (EVP_PKEY_ALG_CTRL + 6)
+#define EVP_PKEY_CTRL_DH_KDF_MD (EVP_PKEY_ALG_CTRL + 7)
+#define EVP_PKEY_CTRL_GET_DH_KDF_MD (EVP_PKEY_ALG_CTRL + 8)
+#define EVP_PKEY_CTRL_DH_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 9)
+#define EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 10)
+#define EVP_PKEY_CTRL_DH_KDF_UKM (EVP_PKEY_ALG_CTRL + 11)
+#define EVP_PKEY_CTRL_GET_DH_KDF_UKM (EVP_PKEY_ALG_CTRL + 12)
+#define EVP_PKEY_CTRL_DH_KDF_OID (EVP_PKEY_ALG_CTRL + 13)
+#define EVP_PKEY_CTRL_GET_DH_KDF_OID (EVP_PKEY_ALG_CTRL + 14)
+
+/* KDF types */
+#define EVP_PKEY_DH_KDF_NONE 1
+#define EVP_PKEY_DH_KDF_X9_42 2
/* BEGIN ERROR CODES */
/* The following lines are auto generated by the script mkerr.pl. Any changes
@@ -272,6 +351,9 @@ void ERR_load_DH_strings(void);
#define DH_F_COMPUTE_KEY 102
#define DH_F_DHPARAMS_PRINT_FP 101
#define DH_F_DH_BUILTIN_GENPARAMS 106
+#define DH_F_DH_CMS_DECRYPT 114
+#define DH_F_DH_CMS_SET_PEERKEY 115
+#define DH_F_DH_CMS_SET_SHARED_INFO 116
#define DH_F_DH_NEW_METHOD 105
#define DH_F_DH_PARAM_DECODE 107
#define DH_F_DH_PRIV_DECODE 110
@@ -290,12 +372,15 @@ void ERR_load_DH_strings(void);
#define DH_R_BN_ERROR 106
#define DH_R_DECODE_ERROR 104
#define DH_R_INVALID_PUBKEY 102
+#define DH_R_KDF_PARAMETER_ERROR 112
#define DH_R_KEYS_NOT_SET 108
#define DH_R_KEY_SIZE_TOO_SMALL 110
#define DH_R_MODULUS_TOO_LARGE 103
#define DH_R_NO_PARAMETERS_SET 107
#define DH_R_NO_PRIVATE_VALUE 100
#define DH_R_PARAMETER_ENCODING_ERROR 105
+#define DH_R_PEER_KEY_ERROR 111
+#define DH_R_SHARED_INFO_ERROR 113
#ifdef __cplusplus
}
diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c
index 8d0fe2e3f7..8b0a153ef3 100644
--- a/crypto/dh/dh_ameth.c
+++ b/crypto/dh/dh_ameth.c
@@ -62,6 +62,9 @@
#include <openssl/dh.h>
#include <openssl/bn.h>
#include "asn1_locl.h"
+#ifndef OPENSSL_NO_CMS
+#include <openssl/cms.h>
+#endif
extern const EVP_PKEY_ASN1_METHOD dhx_asn1_meth;
@@ -364,6 +367,8 @@ static int do_dh_print(BIO *bp, const DH *x, int indent,
update_buflen(x->g, &buf_len);
update_buflen(x->q, &buf_len);
+ update_buflen(x->j, &buf_len);
+ update_buflen(x->counter, &buf_len);
update_buflen(pub_key, &buf_len);
update_buflen(priv_key, &buf_len);
@@ -392,6 +397,29 @@ static int do_dh_print(BIO *bp, const DH *x, int indent,
if (!ASN1_bn_print(bp,"prime:",x->p,m,indent)) goto err;
if (!ASN1_bn_print(bp,"generator:",x->g,m,indent)) goto err;
if (x->q && !ASN1_bn_print(bp,"subgroup order:",x->q,m,indent)) goto err;
+ if (x->j && !ASN1_bn_print(bp,"subgroup factor:",x->j,m,indent))
+ goto err;
+ if (x->seed)
+ {
+ int i;
+ BIO_indent(bp, indent, 128);
+ BIO_puts(bp, "seed:");
+ for (i=0; i < x->seedlen; i++)
+ {
+ if ((i%15) == 0)
+ {
+ if(BIO_puts(bp,"\n") <= 0
+ || !BIO_indent(bp,indent+4,128))
+ goto err;
+ }
+ if (BIO_printf(bp,"%02x%s", x->seed[i],
+ ((i+1) == x->seedlen)?"":":") <= 0)
+ goto err;
+ }
+ if (BIO_write(bp,"\n",1) <= 0) return(0);
+ }
+ if (x->counter && !ASN1_bn_print(bp,"counter:",x->counter,m,indent))
+ goto err;
if (x->length != 0)
{
BIO_indent(bp, indent, 128);
@@ -433,34 +461,77 @@ static int dh_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
return 1;
}
-static int dh_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
+static int int_dh_bn_cpy(BIGNUM **dst, const BIGNUM *src)
{
BIGNUM *a;
+ if (src)
+ {
+ a = BN_dup(src);
+ if (!a)
+ return 0;
+ }
+ else
+ a = NULL;
+ if (*dst)
+ BN_free(*dst);
+ *dst = a;
+ return 1;
+ }
- if ((a=BN_dup(from->pkey.dh->p)) == NULL)
+static int int_dh_param_copy(DH *to, const DH *from, int is_x942)
+ {
+ if (is_x942 == -1)
+ is_x942 = !!from->q;
+ if (!int_dh_bn_cpy(&to->p, from->p))
return 0;
- if (to->pkey.dh->p != NULL)
- BN_free(to->pkey.dh->p);
- to->pkey.dh->p=a;
-
- if ((a=BN_dup(from->pkey.dh->g)) == NULL)
+ if (!int_dh_bn_cpy(&to->g, from->g))
return 0;
- if (to->pkey.dh->g != NULL)
- BN_free(to->pkey.dh->g);
- to->pkey.dh->g=a;
- if (from->ameth == &dhx_asn1_meth)
+ if (is_x942)
{
- a = BN_dup(from->pkey.dh->q);
- if (!a)
+ if (!int_dh_bn_cpy(&to->q, from->q))
return 0;
- if (to->pkey.dh->q)
- BN_free(to->pkey.dh->q);
- to->pkey.dh->q = a;
+ if (!int_dh_bn_cpy(&to->j, from->j))
+ return 0;
+ if(to->seed)
+ {
+ OPENSSL_free(to->seed);
+ to->seed = NULL;
+ to->seedlen = 0;
+ }
+ if (from->seed)
+ {
+ to->seed = BUF_memdup(from->seed, from->seedlen);
+ if (!to->seed)
+ return 0;
+ to->seedlen = from->seedlen;
+ }
}
-
+ else
+ to->length = from->length;
return 1;
}
+
+DH *DHparams_dup(DH *dh)
+ {
+ DH *ret;
+ ret = DH_new();
+ if (!ret)
+ return NULL;
+ if (!int_dh_param_copy(ret, dh, -1))
+ {
+ DH_free(ret);
+ return NULL;
+ }
+ return ret;
+ }
+
+static int dh_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
+ {
+ return int_dh_param_copy(to->pkey.dh, from->pkey.dh,
+ from->ameth == &dhx_asn1_meth);
+ }
+
static int dh_missing_parameters(const EVP_PKEY *a)
{
if (!a->pkey.dh->p || !a->pkey.dh->g)
@@ -501,6 +572,34 @@ int DHparams_print(BIO *bp, const DH *x)
return do_dh_print(bp, x, 4, NULL, 0);
}
+#ifndef OPENSSL_NO_CMS
+static int dh_cms_decrypt(CMS_RecipientInfo *ri);
+static int dh_cms_encrypt(CMS_RecipientInfo *ri);
+#endif
+
+static int dh_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
+ {
+ switch (op)
+ {
+#ifndef OPENSSL_NO_CMS
+
+ case ASN1_PKEY_CTRL_CMS_ENVELOPE:
+ if (arg1 == 1)
+ return dh_cms_decrypt(arg2);
+ else if (arg1 == 0)
+ return dh_cms_encrypt(arg2);
+ return -2;
+
+ case ASN1_PKEY_CTRL_CMS_RI_TYPE:
+ *(int *)arg2 = CMS_RECIPINFO_AGREE;
+ return 1;
+#endif
+ default:
+ return -2;
+ }
+
+ }
+
const EVP_PKEY_ASN1_METHOD dh_asn1_meth =
{
EVP_PKEY_DH,
@@ -564,6 +663,324 @@ const EVP_PKEY_ASN1_METHOD dhx_asn1_meth =
0,
int_dh_free,
- 0
+ dh_pkey_ctrl
};
+#ifndef OPENSSL_NO_CMS
+
+static int dh_cms_set_peerkey(EVP_PKEY_CTX *pctx,
+ X509_ALGOR *alg, ASN1_BIT_STRING *pubkey)
+ {
+ ASN1_OBJECT *aoid;
+ int atype;
+ void *aval;
+ ASN1_INTEGER *public_key = NULL;
+ int rv = 0;
+ EVP_PKEY *pkpeer = NULL, *pk = NULL;
+ DH *dhpeer = NULL;
+ const unsigned char *p;
+ int plen;
+
+ X509_ALGOR_get0(&aoid, &atype, &aval, alg);
+ if (OBJ_obj2nid(aoid) != NID_dhpublicnumber)
+ goto err;
+ /* Only absent parameters allowed in RFC XXXX */
+ if (atype != V_ASN1_UNDEF && atype == V_ASN1_NULL)
+ goto err;
+
+ pk = EVP_PKEY_CTX_get0_pkey(pctx);
+ if (!pk)
+ goto err;
+ if (pk->type != EVP_PKEY_DHX)
+ goto err;
+ /* Get parameters from parent key */
+ dhpeer = DHparams_dup(pk->pkey.dh);
+ /* We have parameters now set public key */
+ plen = ASN1_STRING_length(pubkey);
+ p = ASN1_STRING_data(pubkey);
+ if (!p || !plen)
+ goto err;
+
+ if (!(public_key=d2i_ASN1_INTEGER(NULL, &p, plen)))
+ {
+ DHerr(DH_F_DH_CMS_SET_PEERKEY, DH_R_DECODE_ERROR);
+ goto err;
+ }
+
+ /* We have parameters now set public key */
+ if (!(dhpeer->pub_key = ASN1_INTEGER_to_BN(public_key, NULL)))
+ {
+ DHerr(DH_F_DH_CMS_SET_PEERKEY, DH_R_BN_DECODE_ERROR);
+ goto err;
+ }
+
+ pkpeer = EVP_PKEY_new();
+ if (!pkpeer)
+ goto err;
+ EVP_PKEY_assign(pkpeer, pk->ameth->pkey_id, dhpeer);
+ dhpeer = NULL;
+ if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0)
+ rv = 1;
+ err:
+ if (public_key)
+ ASN1_INTEGER_free(public_key);
+ if (pkpeer)
+ EVP_PKEY_free(pkpeer);
+ if (dhpeer)
+ DH_free(dhpeer);
+ return rv;
+ }
+
+static int dh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
+ {
+ int rv = 0;
+
+ X509_ALGOR *alg, *kekalg = NULL;
+ ASN1_OCTET_STRING *ukm;
+ const unsigned char *p;
+ unsigned char *dukm = NULL;
+ size_t dukmlen = 0;
+ int keylen, plen;
+ const EVP_CIPHER *kekcipher;
+ EVP_CIPHER_CTX *kekctx;
+
+ if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
+ goto err;
+
+ /* For DH we only have one OID permissible. If ever any more get
+ * defined we will need something cleverer.
+ */
+ if (OBJ_obj2nid(alg->algorithm) != NID_id_smime_alg_ESDH)
+ {
+ DHerr(DH_F_DH_CMS_SET_SHARED_INFO, DH_R_KDF_PARAMETER_ERROR);
+ goto err;
+ }
+
+ if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, EVP_PKEY_DH_KDF_X9_42) <= 0)
+ goto err;
+
+ if (EVP_PKEY_CTX_set_dh_kdf_md(pctx, EVP_sha1()) <= 0)
+ goto err;
+
+ if (alg->parameter->type != V_ASN1_SEQUENCE)
+ goto err;
+
+ p = alg->parameter->value.sequence->data;
+ plen = alg->parameter->value.sequence->length;
+ kekalg = d2i_X509_ALGOR(NULL, &p, plen);
+ if (!kekalg)
+ goto err;
+ kekctx = CMS_RecipientInfo_kari_get0_ctx(ri);
+ if (!kekctx)
+ goto err;
+ kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
+ if (!kekcipher || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
+ goto err;
+ if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL))
+ goto err;
+ if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0)
+ goto err;
+
+ keylen = EVP_CIPHER_CTX_key_length(kekctx);
+ if (EVP_PKEY_CTX_set_dh_kdf_outlen(pctx, keylen) <= 0)
+ goto err;
+ /* Use OBJ_nid2obj to ensure we use built in OID that isn't freed */
+ if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx,
+ OBJ_nid2obj(EVP_CIPHER_type(kekcipher))) <= 0)
+ goto err;
+
+ if (ukm)
+ {
+ dukmlen = ASN1_STRING_length(ukm);
+ dukm = BUF_memdup(ASN1_STRING_data(ukm), dukmlen);
+ if (!dukm)
+ goto err;
+ }
+
+ if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0)
+ goto err;
+ dukm = NULL;
+
+ rv = 1;
+ err:
+ if (kekalg)
+ X509_ALGOR_free(kekalg);
+ if (dukm)
+ OPENSSL_free(dukm);
+ return rv;
+ }
+
+static int dh_cms_decrypt(CMS_RecipientInfo *ri)
+ {
+ EVP_PKEY_CTX *pctx;
+ pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
+ if (!pctx)
+ return 0;
+ /* See if we need to set peer key */
+ if (!EVP_PKEY_CTX_get0_peerkey(pctx))
+ {
+ X509_ALGOR *alg;
+ ASN1_BIT_STRING *pubkey;
+ if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey,
+ NULL, NULL, NULL))
+ return 0;
+ if (!alg || !pubkey)
+ return 0;
+ if (!dh_cms_set_peerkey(pctx, alg, pubkey))
+ {
+ DHerr(DH_F_DH_CMS_DECRYPT, DH_R_PEER_KEY_ERROR);
+ return 0;
+ }
+ }
+ /* Set DH derivation parameters and initialise unwrap context */
+ if (!dh_cms_set_shared_info(pctx, ri))
+ {
+ DHerr(DH_F_DH_CMS_DECRYPT, DH_R_SHARED_INFO_ERROR);
+ return 0;
+ }
+ return 1;
+ }
+
+static int dh_cms_encrypt(CMS_RecipientInfo *ri)
+ {
+ EVP_PKEY_CTX *pctx;
+ EVP_PKEY *pkey;
+ EVP_CIPHER_CTX *ctx;
+ int keylen;
+ X509_ALGOR *talg, *wrap_alg = NULL;
+ ASN1_OBJECT *aoid;
+ ASN1_BIT_STRING *pubkey;
+ ASN1_STRING *wrap_str;
+ ASN1_OCTET_STRING *ukm;
+ unsigned char *penc = NULL, *dukm = NULL;
+ int penclen;
+ size_t dukmlen = 0;
+ int rv = 0;
+ int kdf_type, wrap_nid;
+ const EVP_MD *kdf_md;
+ pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
+ if (!pctx)
+ return 0;
+ /* Get ephemeral key */
+ pkey = EVP_PKEY_CTX_get0_pkey(pctx);
+ if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey,
+ NULL, NULL, NULL))
+ goto err;
+ X509_ALGOR_get0(&aoid, NULL, NULL, talg);
+ /* Is everything uninitialised? */
+ if (aoid == OBJ_nid2obj(NID_undef))
+ {
+ ASN1_INTEGER *pubk;
+ pubk = BN_to_ASN1_INTEGER(pkey->pkey.dh->pub_key, NULL);
+ if (!pubk)
+ goto err;
+ /* Set the key */
+
+ penclen = i2d_ASN1_INTEGER(pubk, &penc);
+ ASN1_INTEGER_free(pubk);
+ if (penclen <= 0)
+ goto err;
+ ASN1_STRING_set0(pubkey, penc, penclen);
+ pubkey->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
+ pubkey->flags|=ASN1_STRING_FLAG_BITS_LEFT;
+
+ penc = NULL;
+ X509_ALGOR_set0(talg, OBJ_nid2obj(NID_dhpublicnumber),
+ V_ASN1_UNDEF, NULL);
+ }
+
+ /* See if custom paraneters set */
+ kdf_type = EVP_PKEY_CTX_get_dh_kdf_type(pctx);
+ if (kdf_type <= 0)
+ goto err;
+ if (!EVP_PKEY_CTX_get_dh_kdf_md(pctx, &kdf_md))
+ goto err;
+
+ if (kdf_type == EVP_PKEY_DH_KDF_NONE)
+ {
+ kdf_type = EVP_PKEY_DH_KDF_X9_42;
+ if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, kdf_type) <= 0)
+ goto err;
+ }
+ else if (kdf_type != EVP_PKEY_DH_KDF_X9_42)
+ /* Unknown KDF */
+ goto err;
+ if (kdf_md == NULL)
+ {
+ /* Only SHA1 supported */
+ kdf_md = EVP_sha1();
+ if (EVP_PKEY_CTX_set_dh_kdf_md(pctx, kdf_md) <= 0)
+ goto err;
+ }
+ else if (EVP_MD_type(kdf_md) != NID_sha1)
+ /* Unsupported digest */
+ goto err;
+
+ if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm))
+ goto err;
+
+ /* Get wrap NID */
+ ctx = CMS_RecipientInfo_kari_get0_ctx(ri);
+ wrap_nid = EVP_CIPHER_CTX_type(ctx);
+ if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx, OBJ_nid2obj(wrap_nid)) <= 0)
+ goto err;
+ keylen = EVP_CIPHER_CTX_key_length(ctx);
+
+ /* Package wrap algorithm in an AlgorithmIdentifier */
+
+ wrap_alg = X509_ALGOR_new();
+ if (!wrap_alg)
+ goto err;
+ wrap_alg->algorithm = OBJ_nid2obj(wrap_nid);
+ wrap_alg->parameter = ASN1_TYPE_new();
+ if (!wrap_alg->parameter)
+ goto err;
+ if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0)
+ goto err;
+ if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef)
+ {
+ ASN1_TYPE_free(wrap_alg->parameter);
+ wrap_alg->parameter = NULL;
+ }
+
+ if (EVP_PKEY_CTX_set_dh_kdf_outlen(pctx, keylen) <= 0)
+ goto err;
+
+ if (ukm)
+ {
+ dukmlen = ASN1_STRING_length(ukm);
+ dukm = BUF_memdup(ASN1_STRING_data(ukm), dukmlen);
+ if (!dukm)
+ goto err;
+ }
+
+ if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0)
+ goto err;
+ dukm = NULL;
+
+ /* Now need to wrap encoding of wrap AlgorithmIdentifier into
+ * parameter of another AlgorithmIdentifier.
+ */
+ penc = NULL;
+ penclen = i2d_X509_ALGOR(wrap_alg, &penc);
+ if (!penc || !penclen)
+ goto err;
+ wrap_str = ASN1_STRING_new();
+ if (!wrap_str)
+ goto err;
+ ASN1_STRING_set0(wrap_str, penc, penclen);
+ penc = NULL;
+ X509_ALGOR_set0(talg, OBJ_nid2obj(NID_id_smime_alg_ESDH),
+ V_ASN1_SEQUENCE, wrap_str);
+
+ rv = 1;
+
+ err:
+ if (penc)
+ OPENSSL_free(penc);
+ if (wrap_alg)
+ X509_ALGOR_free(wrap_alg);
+ return rv;
+ }
+
+#endif
diff --git a/crypto/dh/dh_asn1.c b/crypto/dh/dh_asn1.c
index 6de297f17e..96ea475c63 100644
--- a/crypto/dh/dh_asn1.c
+++ b/crypto/dh/dh_asn1.c
@@ -87,11 +87,6 @@ ASN1_SEQUENCE_cb(DHparams, dh_cb) = {
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DH, DHparams, DHparams)
-DH *DHparams_dup(DH *dh)
- {
- return ASN1_item_dup(ASN1_ITEM_rptr(DHparams), dh);
- }
-
/* Internal only structures for handling X9.42 DH: this gets translated
* to or from a DH structure straight away.
*/
diff --git a/crypto/dh/dh_err.c b/crypto/dh/dh_err.c
index a4c30b7ace..848c3cbf11 100644
--- a/crypto/dh/dh_err.c
+++ b/crypto/dh/dh_err.c
@@ -1,6 +1,6 @@
/* crypto/dh/dh_err.c */
/* ====================================================================
- * Copyright (c) 1999-2010 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2013 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
@@ -73,6 +73,9 @@ static ERR_STRING_DATA DH_str_functs[]=
{ERR_FUNC(DH_F_COMPUTE_KEY), "COMPUTE_KEY"},
{ERR_FUNC(DH_F_DHPARAMS_PRINT_FP), "DHparams_print_fp"},
{ERR_FUNC(DH_F_DH_BUILTIN_GENPARAMS), "DH_BUILTIN_GENPARAMS"},
+{ERR_FUNC(DH_F_DH_CMS_DECRYPT), "DH_CMS_DECRYPT"},
+{ERR_FUNC(DH_F_DH_CMS_SET_PEERKEY), "DH_CMS_SET_PEERKEY"},
+{ERR_FUNC(DH_F_DH_CMS_SET_SHARED_INFO), "DH_CMS_SET_SHARED_INFO"},
{ERR_FUNC(DH_F_DH_NEW_METHOD), "DH_new_method"},
{ERR_FUNC(DH_F_DH_PARAM_DECODE), "DH_PARAM_DECODE"},
{ERR_FUNC(DH_F_DH_PRIV_DECODE), "DH_PRIV_DECODE"},
@@ -94,12 +97,15 @@ static ERR_STRING_DATA DH_str_reasons[]=
{ERR_REASON(DH_R_BN_ERROR) ,"bn error"},
{ERR_REASON(DH_R_DECODE_ERROR) ,"decode error"},
{ERR_REASON(DH_R_INVALID_PUBKEY) ,"invalid public key"},
+{ERR_REASON(DH_R_KDF_PARAMETER_ERROR) ,"kdf parameter error"},
{ERR_REASON(DH_R_KEYS_NOT_SET) ,"keys not set"},
{ERR_REASON(DH_R_KEY_SIZE_TOO_SMALL) ,"key size too small"},
{ERR_REASON(DH_R_MODULUS_TOO_LARGE) ,"modulus too large"},
{ERR_REASON(DH_R_NO_PARAMETERS_SET) ,"no parameters set"},
{ERR_REASON(DH_R_NO_PRIVATE_VALUE) ,"no private value"},
{ERR_REASON(DH_R_PARAMETER_ENCODING_ERROR),"parameter encoding error"},
+{ERR_REASON(DH_R_PEER_KEY_ERROR) ,"peer key error"},
+{ERR_REASON(DH_R_SHARED_INFO_ERROR) ,"shared info error"},
{0,NULL}
};
diff --git a/crypto/dh/dh_kdf.c b/crypto/dh/dh_kdf.c
new file mode 100644
index 0000000000..dbdd0b9ba6
--- /dev/null
+++ b/crypto/dh/dh_kdf.c
@@ -0,0 +1,197 @@
+/* crypto/dh/dh_kdf.c */
+/*
+ * Written by Stephen Henson for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 2013 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include <string.h>
+#include <openssl/dh.h>
+#include <openssl/evp.h>
+#include <openssl/asn1.h>
+#include <openssl/cms.h>
+
+
+/* Key derivation from X9.42/RFC2631 */
+
+#define DH_KDF_MAX (1L << 30)
+
+/* Skip past an ASN1 structure: for OBJECT skip content octets too */
+
+static int skip_asn1(unsigned char **pp, long *plen, int exptag)
+ {
+ const unsigned char *q = *pp;
+ int i, tag, xclass;
+ long tmplen;
+ i = ASN1_get_object(&q, &tmplen, &tag, &xclass, *plen);
+ if (i & 0x80)
+ return 0;
+ if (tag != exptag || xclass != V_ASN1_UNIVERSAL)
+ return 0;
+ if (tag == V_ASN1_OBJECT)
+ q += tmplen;
+ *plen -= q - *pp;
+ *pp = (unsigned char *)q;
+ return 1;
+ }
+
+/* Encode the DH shared info structure, return an offset to the counter
+ * value so we can update the structure without reencoding it.
+ */
+
+
+static int dh_sharedinfo_encode(unsigned char **pder, unsigned char **pctr,
+ ASN1_OBJECT *key_oid, size_t outlen,
+ const unsigned char *ukm, size_t ukmlen)
+ {
+ unsigned char *p;
+ int derlen;
+ long tlen;
+ /* "magic" value to check offset is sane */
+ static unsigned char ctr[4] = {0xF3, 0x17, 0x22, 0x53};
+ X509_ALGOR atmp;
+ ASN1_OCTET_STRING ctr_oct, ukm_oct, *pukm_oct;
+ ASN1_TYPE ctr_atype;
+ if (ukmlen > DH_KDF_MAX || outlen > DH_KDF_MAX)
+ return 0;
+ ctr_oct.data = ctr;
+ ctr_oct.length = 4;
+ ctr_oct.flags = 0;
+ ctr_oct.type = V_ASN1_OCTET_STRING;
+ ctr_atype.type = V_ASN1_OCTET_STRING;
+ ctr_atype.value.octet_string = &ctr_oct;
+ atmp.algorithm = key_oid;
+ atmp.parameter = &ctr_atype;
+ if (ukm)
+ {
+ ukm_oct.type = V_ASN1_OCTET_STRING;
+ ukm_oct.flags = 0;
+ ukm_oct.data = (unsigned char *)ukm;
+ ukm_oct.length = ukmlen;
+ pukm_oct = &ukm_oct;
+ }
+ else
+ pukm_oct = NULL;
+ derlen = CMS_SharedInfo_encode(pder, &atmp, pukm_oct, outlen);
+ if (derlen <= 0)
+ return 0;
+ p = *pder;
+ tlen = derlen;
+ if (!skip_asn1(&p, &tlen, V_ASN1_SEQUENCE))
+ return 0;
+ if (!skip_asn1(&p, &tlen, V_ASN1_SEQUENCE))
+ return 0;
+ if (!skip_asn1(&p, &tlen, V_ASN1_OBJECT))
+ return 0;
+ if (!skip_asn1(&p, &tlen, V_ASN1_OCTET_STRING))
+ return 0;
+ if (memcmp(p, ctr, 4))
+ return 0;
+ *pctr = p;
+ return derlen;
+ }
+
+int DH_KDF_X9_42(unsigned char *out, size_t outlen,
+ const unsigned char *Z, size_t Zlen,
+ ASN1_OBJECT *key_oid,
+ const unsigned char *ukm, size_t ukmlen,
+ const EVP_MD *md)
+ {
+ EVP_MD_CTX mctx;
+ int rv = 0;
+ unsigned int i;
+ size_t mdlen;
+ unsigned char *der = NULL, *ctr;
+ int derlen;
+ if (Zlen > DH_KDF_MAX)
+ return 0;
+ mdlen = EVP_MD_size(md);
+ EVP_MD_CTX_init(&mctx);
+ derlen = dh_sharedinfo_encode(&der, &ctr, key_oid, outlen,
+ ukm, ukmlen);
+ if (derlen == 0)
+ goto err;
+ for (i = 1;;i++)
+ {
+ unsigned char mtmp[EVP_MAX_MD_SIZE];
+ EVP_DigestInit_ex(&mctx, md, NULL);
+ if (!EVP_DigestUpdate(&mctx, Z, Zlen))
+ goto err;
+ ctr[3] = i & 0xFF;
+ ctr[2] = (i >> 8) & 0xFF;
+ ctr[1] = (i >> 16) & 0xFF;
+ ctr[0] = (i >> 24) & 0xFF;
+ if (!EVP_DigestUpdate(&mctx, der, derlen))
+ goto err;
+ if (outlen >= mdlen)
+ {
+ if (!EVP_DigestFinal(&mctx, out, NULL))
+ goto err;
+ outlen -= mdlen;
+ if (outlen == 0)
+ break;
+ out += mdlen;
+ }
+ else
+ {
+ if (!EVP_DigestFinal(&mctx, mtmp, NULL))
+ goto err;
+ memcpy(out, mtmp, outlen);
+ OPENSSL_cleanse(mtmp, mdlen);
+ break;
+ }
+ }
+ rv = 1;
+ err:
+ if (der)
+ OPENSSL_free(der);
+ EVP_MD_CTX_cleanup(&mctx);
+ return rv;
+ }
+
diff --git a/crypto/dh/dh_pmeth.c b/crypto/dh/dh_pmeth.c
index 58283132c7..941801df46 100644
--- a/crypto/dh/dh_pmeth.c
+++ b/crypto/dh/dh_pmeth.c
@@ -62,6 +62,10 @@
#include <openssl/evp.h>
#include <openssl/dh.h>
#include <openssl/bn.h>
+#ifndef OPENSSL_NO_DSA
+#include <openssl/dsa.h>
+#endif
+#include <openssl/objects.h>
#include "evp_locl.h"
/* DH pkey context structure */
@@ -72,10 +76,23 @@ typedef struct
int prime_len;
int generator;
int use_dsa;
+ int subprime_len;
+ /* message digest used for parameter generation */
+ const EVP_MD *md;
int rfc5114_param;
/* Keygen callback info */
int gentmp[2];
- /* message digest */
+ /* KDF (if any) to use for DH */
+ char kdf_type;
+ /* OID to use for KDF */
+ ASN1_OBJECT *kdf_oid;
+ /* Message digest to use for key derivation */
+ const EVP_MD *kdf_md;
+ /* User key material */
+ unsigned char *kdf_ukm;
+ size_t kdf_ukmlen;
+ /* KDF output length */
+ size_t kdf_outlen;
} DH_PKEY_CTX;
static int pkey_dh_init(EVP_PKEY_CTX *ctx)
@@ -85,10 +102,19 @@ static int pkey_dh_init(EVP_PKEY_CTX *ctx)
if (!dctx)
return 0;
dctx->prime_len = 1024;
+ dctx->subprime_len = -1;
dctx->generator = 2;
dctx->use_dsa = 0;
+ dctx->md = NULL;
dctx->rfc5114_param = 0;
+ dctx->kdf_type = EVP_PKEY_DH_KDF_NONE;
+ dctx->kdf_oid = NULL;
+ dctx->kdf_md = NULL;
+ dctx->kdf_ukm = NULL;
+ dctx->kdf_ukmlen = 0;
+ dctx->kdf_outlen = 0;
+
ctx->data = dctx;
ctx->keygen_info = dctx->gentmp;
ctx->keygen_info_count = 2;
@@ -104,9 +130,23 @@ static int pkey_dh_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
sctx = src->data;
dctx = dst->data;
dctx->prime_len = sctx->prime_len;
+ dctx->subprime_len = sctx->subprime_len;
dctx->generator = sctx->generator;
dctx->use_dsa = sctx->use_dsa;
+ dctx->md = sctx->md;
dctx->rfc5114_param = sctx->rfc5114_param;
+
+ dctx->kdf_type = sctx->kdf_type;
+ dctx->kdf_oid = OBJ_dup(sctx->kdf_oid);
+ if (!dctx->kdf_oid)
+ return 0;
+ dctx->kdf_md = sctx->kdf_md;
+ if (dctx->kdf_ukm)
+ {
+ dctx->kdf_ukm = BUF_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen);
+ dctx->kdf_ukmlen = sctx->kdf_ukmlen;
+ }
+ dctx->kdf_outlen = sctx->kdf_outlen;
return 1;
}
@@ -114,7 +154,13 @@ static void pkey_dh_cleanup(EVP_PKEY_CTX *ctx)
{
DH_PKEY_CTX *dctx = ctx->data;
if (dctx)
+ {
+ if (dctx->kdf_ukm)
+ OPENSSL_free(dctx->kdf_ukm);
+ if (dctx->kdf_oid)
+ ASN1_OBJECT_free(dctx->kdf_oid);
OPENSSL_free(dctx);
+ }
}
static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
@@ -128,10 +174,29 @@ static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
dctx->prime_len = p1;
return 1;
+ case EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN:
+ if (dctx->use_dsa == 0)
+ return -2;
+ dctx->subprime_len = p1;
+ return 1;
+
case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR:
+ if (dctx->use_dsa)
+ return -2;
dctx->generator = p1;
return 1;
+ case EVP_PKEY_CTRL_DH_PARAMGEN_TYPE:
+#ifdef OPENSSL_NO_DSA
+ if (p1 != 0)
+ return -2;
+#else
+ if (p1 < 0 || p1 > 2)
+ return -2;
+#endif
+ dctx->use_dsa = p1;
+ return 1;
+
case EVP_PKEY_CTRL_DH_RFC5114:
if (p1 < 1 || p1 > 3)
return -2;
@@ -142,13 +207,64 @@ static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
/* Default behaviour is OK */
return 1;
+ case EVP_PKEY_CTRL_DH_KDF_TYPE:
+ if (p1 == -2)
+ return dctx->kdf_type;
+ if (p1 != EVP_PKEY_DH_KDF_NONE &&
+ p1 != EVP_PKEY_DH_KDF_X9_42)
+ return -2;
+ dctx->kdf_type = p1;
+ return 1;
+
+ case EVP_PKEY_CTRL_DH_KDF_MD:
+ dctx->kdf_md = p2;
+ return 1;
+
+ case EVP_PKEY_CTRL_GET_DH_KDF_MD:
+ *(const EVP_MD **)p2 = dctx->kdf_md;
+ return 1;
+
+ case EVP_PKEY_CTRL_DH_KDF_OUTLEN:
+ if (p1 <= 0)
+ return -2;
+ dctx->kdf_outlen = (size_t)p1;
+ return 1;
+
+ case EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN:
+ *(int *)p2 = dctx->kdf_outlen;
+ return 1;
+
+ case EVP_PKEY_CTRL_DH_KDF_UKM:
+ if (dctx->kdf_ukm)
+ OPENSSL_free(dctx->kdf_ukm);
+ dctx->kdf_ukm = p2;
+ if (p2)
+ dctx->kdf_ukmlen = p1;
+ else
+ dctx->kdf_ukmlen = 0;
+ return 1;
+
+ case EVP_PKEY_CTRL_GET_DH_KDF_UKM:
+ *(unsigned char **)p2 = dctx->kdf_ukm;
+ return dctx->kdf_ukmlen;
+
+ case EVP_PKEY_CTRL_DH_KDF_OID:
+ if (dctx->kdf_oid)
+ ASN1_OBJECT_free(dctx->kdf_oid);
+ dctx->kdf_oid = p2;
+ return 1;
+
+ case EVP_PKEY_CTRL_GET_DH_KDF_OID:
+ *(ASN1_OBJECT **)p2 = dctx->kdf_oid;
+ return 1;
+
default:
return -2;
}
}
-
+
static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value)
{
@@ -174,9 +290,75 @@ static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx,
len = atoi(value);
return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len);
}
+ if (!strcmp(type, "dh_paramgen_subprime_len"))
+ {
+ int len;
+ len = atoi(value);
+ return EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, len);
+ }
+ if (!strcmp(type, "dh_paramgen_type"))
+ {
+ int typ;
+ typ = atoi(value);
+ return EVP_PKEY_CTX_set_dh_paramgen_type(ctx, typ);
+ }
return -2;
}
+#ifndef OPENSSL_NO_DSA
+
+extern int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits,
+ const EVP_MD *evpmd, const unsigned char *seed_in, size_t seed_len,
+ unsigned char *seed_out,
+ int *counter_ret, unsigned long *h_ret, BN_GENCB *cb);
+
+extern int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
+ const EVP_MD *evpmd, const unsigned char *seed_in, size_t seed_len,
+ int idx, unsigned char *seed_out,
+ int *counter_ret, unsigned long *h_ret, BN_GENCB *cb);
+
+static DSA *dsa_dh_generate(DH_PKEY_CTX *dctx, BN_GENCB *pcb)
+ {
+ DSA *ret;
+ int rv = 0;
+ int prime_len = dctx->prime_len;
+ int subprime_len = dctx->subprime_len;
+ const EVP_MD *md = dctx->md;
+ if (dctx->use_dsa > 2)
+ return NULL;
+ ret = DSA_new();
+ if (!ret)
+ return NULL;
+ if (subprime_len == -1)
+ {
+ if (prime_len >= 2048)
+ subprime_len = 256;
+ else
+ subprime_len = 160;
+ }
+ if (md == NULL)
+ {
+ if (prime_len >= 2048)
+ md = EVP_sha256();
+ else
+ md = EVP_sha1();
+ }
+ if (dctx->use_dsa == 1)
+ rv = dsa_builtin_paramgen(ret, prime_len, subprime_len, md,
+ NULL, 0, NULL, NULL, NULL, pcb);
+ else if(dctx->use_dsa == 2)
+ rv = dsa_builtin_paramgen2(ret, prime_len, subprime_len, md,
+ NULL, 0, -1, NULL, NULL, NULL, pcb);
+ if (rv <= 0)
+ {
+ DSA_free(ret);
+ return NULL;
+ }
+ return ret;
+ }
+
+#endif
+
static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
DH *dh = NULL;
@@ -213,11 +395,27 @@ static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
}
else
pcb = NULL;
+#ifndef OPENSSL_NO_DSA
+ if (dctx->use_dsa)
+ {
+ DSA *dsa_dh;
+ dsa_dh = dsa_dh_generate(dctx, pcb);
+ if (!dsa_dh)
+ return 0;
+ dh = DSA_dup_DH(dsa_dh);
+ DSA_free(dsa_dh);
+ if (!dh)
+ return 0;
+ EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh);
+ return 1;
+ }
+#endif
dh = DH_new();
if (!dh)
return 0;
ret = DH_generate_parameters_ex(dh,
dctx->prime_len, dctx->generator, pcb);
+
if (ret)
EVP_PKEY_assign_DH(pkey, dh);
else
@@ -246,23 +444,68 @@ static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
{
int ret;
+ DH *dh;
+ DH_PKEY_CTX *dctx = ctx->data;
+ BIGNUM *dhpub;
if (!ctx->pkey || !ctx->peerkey)
{
DHerr(DH_F_PKEY_DH_DERIVE, DH_R_KEYS_NOT_SET);
return 0;
}
- ret = DH_compute_key(key, ctx->peerkey->pkey.dh->pub_key,
- ctx->pkey->pkey.dh);
- if (ret < 0)
+ dh = ctx->pkey->pkey.dh;
+ dhpub = ctx->peerkey->pkey.dh->pub_key;
+ if (dctx->kdf_type == EVP_PKEY_DH_KDF_NONE)
+ {
+ if (key == NULL)
+ {
+ *keylen = DH_size(dh);
+ return 1;
+ }
+ ret = DH_compute_key(key, dhpub, dh);
+ if (ret < 0)
+ return ret;
+ *keylen = ret;
+ return 1;
+ }
+ else if (dctx->kdf_type == EVP_PKEY_DH_KDF_X9_42)
+ {
+ unsigned char *Z = NULL;
+ size_t Zlen = 0;
+ if (!dctx->kdf_outlen || !dctx->kdf_oid)
+ return 0;
+ if (key == NULL)
+ {
+ *keylen = dctx->kdf_outlen;
+ return 1;
+ }
+ if (*keylen != dctx->kdf_outlen)
+ return 0;
+ ret = 0;
+ Zlen = DH_size(dh);
+ Z = OPENSSL_malloc(Zlen);
+ if (DH_compute_key_padded(Z, dhpub, dh) <= 0)
+ goto err;
+ if (!DH_KDF_X9_42(key, *keylen, Z, Zlen, dctx->kdf_oid,
+ dctx->kdf_ukm, dctx->kdf_ukmlen,
+ dctx->kdf_md))
+ goto err;
+ *keylen = dctx->kdf_outlen;
+ ret = 1;
+ err:
+ if (Z)
+ {
+ OPENSSL_cleanse(Z, Zlen);
+ OPENSSL_free(Z);
+ }
return ret;
- *keylen = ret;
+ }
return 1;
}
const EVP_PKEY_METHOD dh_pkey_meth =
{
EVP_PKEY_DH,
- EVP_PKEY_FLAG_AUTOARGLEN,
+ 0,
pkey_dh_init,
pkey_dh_copy,
pkey_dh_cleanup,
@@ -298,7 +541,7 @@ const EVP_PKEY_METHOD dh_pkey_meth =
const EVP_PKEY_METHOD dhx_pkey_meth =
{
EVP_PKEY_DHX,
- EVP_PKEY_FLAG_AUTOARGLEN,
+ 0,
pkey_dh_init,
pkey_dh_copy,
pkey_dh_cleanup,
diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c
index ff0870d7bb..f024f90497 100644
--- a/crypto/ec/ec_ameth.c
+++ b/crypto/ec/ec_ameth.c
@@ -764,63 +764,6 @@ static int ecdh_cms_set_kdf_param(EVP_PKEY_CTX *pctx, int eckdf_nid)
return 1;
}
-/* Utilities to encode the ECC_CMS_SharedInfo structure used during key
- * derivation.
- */
-
-typedef struct {
- X509_ALGOR *keyInfo;
- ASN1_OCTET_STRING *entityUInfo;
- ASN1_OCTET_STRING *suppPubInfo;
-} ECC_CMS_SharedInfo;
-
-ASN1_SEQUENCE(ECC_CMS_SharedInfo) = {
- ASN1_SIMPLE(ECC_CMS_SharedInfo, keyInfo, X509_ALGOR),
- ASN1_EXP_OPT(ECC_CMS_SharedInfo, entityUInfo, ASN1_OCTET_STRING, 0),
- ASN1_EXP_OPT(ECC_CMS_SharedInfo, suppPubInfo, ASN1_OCTET_STRING, 2),
-} ASN1_SEQUENCE_END(ECC_CMS_SharedInfo)
-
-static int ecdh_cms_set_ukm(EVP_PKEY_CTX *pctx,
- X509_ALGOR *kekalg,
- ASN1_OCTET_STRING *ukm,
- int keylen)
- {
- union {
- ECC_CMS_SharedInfo *pecsi;
- ASN1_VALUE *a;
- } intsi = {NULL};
-
- unsigned char *der = NULL;
- int plen;
- ASN1_OCTET_STRING oklen;
- unsigned char kl[4];
- ECC_CMS_SharedInfo ecsi;
-
- keylen <<= 3;
- kl[0] = (keylen >> 24) & 0xff;
- kl[1] = (keylen >> 16) & 0xff;
- kl[2] = (keylen >> 8) & 0xff;
- kl[3] = keylen & 0xff;
- oklen.length = 4;
- oklen.data = kl;
- oklen.type = V_ASN1_OCTET_STRING;
- oklen.flags = 0;
- ecsi.keyInfo = kekalg;
- ecsi.entityUInfo = ukm;
- ecsi.suppPubInfo = &oklen;
- intsi.pecsi = &ecsi;
- plen = ASN1_item_i2d(intsi.a, &der, ASN1_ITEM_rptr(ECC_CMS_SharedInfo));
- if (!der || !plen)
- goto err;
- if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, der, plen) <= 0)
- goto err;
- return 1;
- err:
- if (der)
- OPENSSL_free(der);
- return 0;
- }
-
static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
{
int rv = 0;
@@ -828,6 +771,7 @@ static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
X509_ALGOR *alg, *kekalg = NULL;
ASN1_OCTET_STRING *ukm;
const unsigned char *p;
+ unsigned char *der = NULL;
int plen, keylen;
const EVP_CIPHER *kekcipher;
EVP_CIPHER_CTX *kekctx;
@@ -857,18 +801,28 @@ static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
goto err;
if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL))
goto err;
+ if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0)
+ goto err;
keylen = EVP_CIPHER_CTX_key_length(kekctx);
if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
goto err;
- if (!ecdh_cms_set_ukm(pctx, kekalg, ukm, keylen))
+ plen = CMS_SharedInfo_encode(&der, kekalg, ukm, keylen);
+
+ if (!plen)
+ goto err;
+
+ if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, der, plen) <= 0)
goto err;
+ der = NULL;
rv = 1;
err:
if (kekalg)
X509_ALGOR_free(kekalg);
+ if (der)
+ OPENSSL_free(der);
return rv;
}
@@ -1003,17 +957,33 @@ static int ecdh_cms_encrypt(CMS_RecipientInfo *ri)
wrap_alg = X509_ALGOR_new();
if (!wrap_alg)
goto err;
- X509_ALGOR_set0(wrap_alg, OBJ_nid2obj(wrap_nid), V_ASN1_UNDEF, NULL);
+ wrap_alg->algorithm = OBJ_nid2obj(wrap_nid);
+ wrap_alg->parameter = ASN1_TYPE_new();
+ if (!wrap_alg->parameter)
+ goto err;
+ if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0)
+ goto err;
+ if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef)
+ {
+ ASN1_TYPE_free(wrap_alg->parameter);
+ wrap_alg->parameter = NULL;
+ }
if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
goto err;
- if (!ecdh_cms_set_ukm(pctx, wrap_alg, ukm, keylen))
+
+ penclen = CMS_SharedInfo_encode(&penc, wrap_alg, ukm, keylen);
+
+ if (!penclen)
+ goto err;
+
+ if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, penc, penclen) <= 0)
goto err;
+ penc = NULL;
/* Now need to wrap encoding of wrap AlgorithmIdentifier into
* parameter of another AlgorithmIdentifier.
*/
- penc = NULL;
penclen = i2d_X509_ALGOR(wrap_alg, &penc);
if (!penc || !penclen)
goto err;
diff --git a/crypto/ecdh/ech_kdf.c b/crypto/ecdh/ech_kdf.c
index 84bf108b90..848b91745f 100644
--- a/crypto/ecdh/ech_kdf.c
+++ b/crypto/ecdh/ech_kdf.c
@@ -90,7 +90,7 @@ int ECDH_KDF_X9_62(unsigned char *out, size_t outlen,
goto err;
if (!EVP_DigestUpdate(&mctx, sinfo, sinfolen))
goto err;
- if (outlen > mdlen)
+ if (outlen >= mdlen)
{
if (!EVP_DigestFinal(&mctx, out, NULL))
goto err;
diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c
index 857587b672..d1972a77e6 100644
--- a/crypto/evp/e_aes.c
+++ b/crypto/evp/e_aes.c
@@ -1260,7 +1260,10 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
gctx->ctr = NULL;
break;
}
+ else
#endif
+ (void)0; /* terminate potentially open 'else' */
+
AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks);
CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f)AES_encrypt);
#ifdef AES_CTR_ASM
@@ -1653,14 +1656,17 @@ static int aes_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
xctx->xts.block1 = (block128_f)vpaes_decrypt;
}
- vpaes_set_encrypt_key(key + ctx->key_len/2,
+ vpaes_set_encrypt_key(key + ctx->key_len/2,
ctx->key_len * 4, &xctx->ks2.ks);
- xctx->xts.block2 = (block128_f)vpaes_encrypt;
+ xctx->xts.block2 = (block128_f)vpaes_encrypt;
- xctx->xts.key1 = &xctx->ks1;
- break;
- }
+ xctx->xts.key1 = &xctx->ks1;
+ break;
+ }
+ else
#endif
+ (void)0; /* terminate potentially open 'else' */
+
if (enc)
{
AES_set_encrypt_key(key, ctx->key_len * 4, &xctx->ks1.ks);
@@ -1937,7 +1943,7 @@ static int aes_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
#define WRAP_FLAGS (EVP_CIPH_WRAP_MODE \
| EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
- | EVP_CIPH_ALWAYS_CALL_INIT)
+ | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_FLAG_DEFAULT_ASN1)
static const EVP_CIPHER aes_128_wrap = {
NID_id_aes128_wrap,
diff --git a/crypto/evp/e_des3.c b/crypto/evp/e_des3.c
index cfd49bbe7f..dd44ac325c 100644
--- a/crypto/evp/e_des3.c
+++ b/crypto/evp/e_des3.c
@@ -468,7 +468,8 @@ static int des_ede3_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static const EVP_CIPHER des3_wrap = {
NID_id_smime_alg_CMS3DESwrap,
8, 24, 0,
- EVP_CIPH_WRAP_MODE|EVP_CIPH_CUSTOM_IV|EVP_CIPH_FLAG_CUSTOM_CIPHER,
+ EVP_CIPH_WRAP_MODE|EVP_CIPH_CUSTOM_IV|EVP_CIPH_FLAG_CUSTOM_CIPHER
+ |EVP_CIPH_FLAG_DEFAULT_ASN1,
des_ede3_init_key, des_ede3_wrap_cipher,
NULL,
sizeof(DES_EDE_KEY),
diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c
index b180e4828a..2a87570b9e 100644
--- a/crypto/evp/evp_lib.c
+++ b/crypto/evp/evp_lib.c
@@ -68,7 +68,15 @@ int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
if (c->cipher->set_asn1_parameters != NULL)
ret=c->cipher->set_asn1_parameters(c,type);
else if (c->cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1)
- ret=EVP_CIPHER_set_asn1_iv(c, type);
+ {
+ if (EVP_CIPHER_CTX_mode(c) == EVP_CIPH_WRAP_MODE)
+ {
+ ASN1_TYPE_set(type, V_ASN1_NULL, NULL);
+ ret = 1;
+ }
+ else
+ ret=EVP_CIPHER_set_asn1_iv(c, type);
+ }
else
ret=-1;
return(ret);
@@ -81,7 +89,11 @@ int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
if (c->cipher->get_asn1_parameters != NULL)
ret=c->cipher->get_asn1_parameters(c,type);
else if (c->cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1)
+ {
+ if (EVP_CIPHER_CTX_mode(c) == EVP_CIPH_WRAP_MODE)
+ return 1;
ret=EVP_CIPHER_get_asn1_iv(c, type);
+ }
else
ret=-1;
return(ret);
diff --git a/crypto/ossl_typ.h b/crypto/ossl_typ.h
index 9e6995d37f..e78a0347db 100644
--- a/crypto/ossl_typ.h
+++ b/crypto/ossl_typ.h
@@ -96,6 +96,8 @@ typedef int ASN1_BOOLEAN;
typedef int ASN1_NULL;
#endif
+typedef struct asn1_object_st ASN1_OBJECT;
+
typedef struct ASN1_ITEM_st ASN1_ITEM;
typedef struct asn1_pctx_st ASN1_PCTX;
typedef struct asn1_sctx_st ASN1_SCTX;
diff --git a/crypto/pem/pem_info.c b/crypto/pem/pem_info.c
index 1b2be527ed..cc7f24a9c1 100644
--- a/crypto/pem/pem_info.c
+++ b/crypto/pem/pem_info.c
@@ -167,6 +167,7 @@ start:
#ifndef OPENSSL_NO_RSA
if (strcmp(name,PEM_STRING_RSA) == 0)
{
+ d2i=(D2I_OF(void))d2i_RSAPrivateKey;
if (xi->x_pkey != NULL)
{
if (!sk_X509_INFO_push(ret,xi)) goto err;
diff --git a/crypto/sha/asm/sha1-x86_64.pl b/crypto/sha/asm/sha1-x86_64.pl
index ff94ac5f18..2c89b1feea 100755
--- a/crypto/sha/asm/sha1-x86_64.pl
+++ b/crypto/sha/asm/sha1-x86_64.pl
@@ -806,7 +806,7 @@ $code.=<<___;
mov %rdi,$ctx # reassigned argument
mov %rsi,$inp # reassigned argument
mov %rdx,$num # reassigned argument
- vzeroall
+ vzeroupper
shl \$6,$num
add $inp,$num
@@ -1096,7 +1096,7 @@ ___
&Xtail_avx(\&body_20_39);
$code.=<<___;
- vzeroall
+ vzeroupper
add 0($ctx),$A # update context
add 4($ctx),@T[0]
diff --git a/crypto/sha/asm/sha512-x86_64.pl b/crypto/sha/asm/sha512-x86_64.pl
index d1d20914a5..8070d09c94 100755
--- a/crypto/sha/asm/sha512-x86_64.pl
+++ b/crypto/sha/asm/sha512-x86_64.pl
@@ -948,7 +948,7 @@ ___
$code.=<<___;
.Lprologue_xop:
- vzeroall
+ vzeroupper
mov $SZ*0($ctx),$A
mov $SZ*1($ctx),$B
mov $SZ*2($ctx),$C
@@ -1260,7 +1260,7 @@ $code.=<<___;
jb .Lloop_xop
mov $_rsp,%rsi
- vzeroall
+ vzeroupper
___
$code.=<<___ if ($win64);
movaps 16*$SZ+32(%rsp),%xmm6
@@ -1324,7 +1324,7 @@ ___
$code.=<<___;
.Lprologue_avx:
- vzeroall
+ vzeroupper
mov $SZ*0($ctx),$A
mov $SZ*1($ctx),$B
mov $SZ*2($ctx),$C
@@ -1568,7 +1568,7 @@ $code.=<<___;
jb .Lloop_avx
mov $_rsp,%rsi
- vzeroall
+ vzeroupper
___
$code.=<<___ if ($win64);
movaps 16*$SZ+32(%rsp),%xmm6
@@ -1676,7 +1676,7 @@ ___
$code.=<<___;
.Lprologue_avx2:
- vzeroall
+ vzeroupper
sub \$-16*$SZ,$inp # inp++, size optimization
mov $SZ*0($ctx),$A
mov $inp,%r12 # borrow $T1
@@ -1942,7 +1942,7 @@ $code.=<<___;
.Ldone_avx2:
lea ($Tbl),%rsp
mov $_rsp,%rsi
- vzeroall
+ vzeroupper
___
$code.=<<___ if ($win64);
movaps 16*$SZ+32(%rsp),%xmm6
diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c
index 7b294b1d5e..36cc48e625 100644
--- a/crypto/x509/x509_cmp.c
+++ b/crypto/x509/x509_cmp.c
@@ -349,6 +349,8 @@ int X509_check_private_key(X509 *x, EVP_PKEY *k)
* flags.
*/
+#ifndef OPENSSL_NO_EC
+
static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags)
{
const EC_GROUP *grp = NULL;
@@ -465,6 +467,20 @@ int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags)
sign_nid = OBJ_obj2nid(crl->crl->sig_alg->algorithm);
return check_suite_b(pk, sign_nid, &flags);
}
+
+#else
+int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain,
+ unsigned long flags)
+ {
+ return 0;
+ }
+
+int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags)
+ {
+ return 0;
+ }
+
+#endif
/* Not strictly speaking an "up_ref" as a STACK doesn't have a reference
* count but it has the same effect by duping the STACK and upping the ref
* of each X509 structure.
diff --git a/doc/apps/cms.pod b/doc/apps/cms.pod
index 18fe43caa9..dc337039a6 100644
--- a/doc/apps/cms.pod
+++ b/doc/apps/cms.pod
@@ -57,6 +57,7 @@ B<openssl> B<cms>
[B<-secretkeyid id>]
[B<-econtent_type type>]
[B<-inkey file>]
+[B<-keyopt name:parameter>]
[B<-passin arg>]
[B<-rand file(s)>]
[B<cert.pem...>]
@@ -385,7 +386,8 @@ multiple times to specify successive keys.
for signing and encryption this option can be used multiple times to
set customised parameters for the preceding key or certificate. It can
-currently be used to set RSA-PSS for signing or RSA-OAEP for encryption.
+currently be used to set RSA-PSS for signing, RSA-OAEP for encryption
+or to modify default parameters for ECDH.
=item B<-passin arg>
@@ -504,6 +506,10 @@ The B<-compress> option.
The B<-secretkey> option when used with B<-encrypt>.
+The use of PSS with B<-sign>.
+
+The use of OAEP or non-RSA keys with B<-encrypt>.
+
Additionally the B<-EncryptedData_create> and B<-data_create> type cannot
be processed by the older B<smime> command.
@@ -591,9 +597,14 @@ Sign mail using RSA-PSS:
Create encrypted mail using RSA-OAEP:
- openssl cms -encrypt -in plain.txt -camellia128 -out mail.msg \
+ openssl cms -encrypt -in plain.txt -out mail.msg \
-recip cert.pem -keyopt rsa_padding_mode:oaep
+Use SHA256 KDF with an ECDH certificate:
+
+ openssl cms -encrypt -in plain.txt -out mail.msg \
+ -recip ecdhcert.pem -keyopt ecdh_kdf_md:sha256
+
=head1 BUGS
The MIME parser isn't very clever: it seems to handle most messages that I've
@@ -626,4 +637,7 @@ added to OpenSSL 1.1.0
Support for RSA-OAEP and RSA-PSS was first added to OpenSSL 1.1.0.
+The use of non-RSA keys with B<-encrypt> and B<-decrypt> was first added
+to OpenSSL 1.1.0.
+
=cut
diff --git a/doc/apps/x509.pod b/doc/apps/x509.pod
index d2d9eb812a..19fae07e48 100644
--- a/doc/apps/x509.pod
+++ b/doc/apps/x509.pod
@@ -48,6 +48,7 @@ B<openssl> B<x509>
[B<-CAkey filename>]
[B<-CAcreateserial>]
[B<-CAserial filename>]
+[B<-force_pubkey key>]
[B<-text>]
[B<-C>]
[B<-md2|-md5|-sha1|-mdc2>]
@@ -400,6 +401,15 @@ specified then the extensions should either be contained in the unnamed
L<x509v3_config(5)|x509v3_config(5)> manual page for details of the
extension section format.
+=item B<-force_pubkey key>
+
+when a certificate is created set its public key to B<key> instead of the
+key in the certificate or certificate request. This option is useful for
+creating certificates where the algorithm can't normally sign requests, for
+example DH.
+
+The format or B<key> can be specified using the B<-keyform> option.
+
=back
=head2 NAME OPTIONS
diff --git a/doc/crypto/ecdsa.pod b/doc/crypto/ecdsa.pod
index 123784ee16..46c071b733 100644
--- a/doc/crypto/ecdsa.pod
+++ b/doc/crypto/ecdsa.pod
@@ -95,7 +95,7 @@ is ignored.
ECDSA_verify() verifies that the signature in B<sig> of size
B<siglen> is a valid ECDSA signature of the hash value
-value B<dgst> of size B<dgstlen> using the public key B<eckey>.
+B<dgst> of size B<dgstlen> using the public key B<eckey>.
The parameter B<type> is ignored.
ECDSA_do_sign() is wrapper function for ECDSA_do_sign_ex with B<kinv>
@@ -131,16 +131,12 @@ specific)
int ret;
ECDSA_SIG *sig;
- EC_KEY *eckey = EC_KEY_new();
+ EC_KEY *eckey;
+ eckey = EC_KEY_new_by_curve_name(NID_secp192k1);
if (eckey == NULL)
{
/* error */
}
- key->group = EC_GROUP_new_by_nid(NID_secp192k1);
- if (key->group == NULL)
- {
- /* error */
- }
if (!EC_KEY_generate_key(eckey))
{
/* error */
diff --git a/doc/ssl/SSL_CTX_add1_chain_cert.pod b/doc/ssl/SSL_CTX_add1_chain_cert.pod
new file mode 100644
index 0000000000..ef26c9f86b
--- /dev/null
+++ b/doc/ssl/SSL_CTX_add1_chain_cert.pod
@@ -0,0 +1,92 @@
+=pod
+
+=head1 NAME
+
+SSL_CTX_set0_chain, SSL_CTX_set1_chain, SSL_CTX_add0_chain_cert,
+SSL_CTX_add1_chain_cert, SSL_set0_chain, SSL_set1_chain,
+SSL_add0_chain_cert, SSL_add1_chain_cert, SSL_CTX_build_cert_chain,
+SSL_build_cert_chain - extra chain certificate processing
+
+=head1 SYNOPSIS
+
+ #include <openssl/ssl.h>
+
+ int SSL_CTX_set0_chain(SSL_CTX *ctx, STACK_OF(X509) *sk);
+ int SSL_CTX_set1_chain(SSL_CTX *ctx, STACK_OF(X509) *sk);
+ int SSL_CTX_add0_chain_cert(SSL_CTX *ctx, STACK_OF(X509) *x509);
+ int SSL_CTX_add1_chain_cert(SSL_CTX *ctx, X509 *x509);
+
+ int SSL_set0_chain(SSL *ssl, STACK_OF(X509) *sk);
+ int SSL_set1_chain(SSL *ssl, STACK_OF(X509) *sk);
+ int SSL_add0_chain_cert(SSL *ssl, STACK_OF(X509) *x509);
+ int SSL_add1_chain_cert(SSL *ssl, X509 *x509);
+
+ int SSL_CTX_build_cert_chain(SSL_CTX *ctx, flags);
+ int SSL_build_cert_chain(SSL_CTX *ctx, flags);
+
+=head1 DESCRIPTION
+
+SSL_CTX_set0_chain() and SSL_CTX_set1_chain() set the certificate chain
+associated with the current certificate of B<ctx> to B<sk>. If B<sk> is set
+to B<NULL> any existing chain is cleared.
+
+SSL_CTX_add0_chain_cert() and SSL_CTX_add1_chain_cert() append the single
+certificate B<x509> to the chain associated with the current certificate of
+B<ctx>.
+
+SSL_CTX_build_cert_chain() builds the certificate chain for B<ctx> using the
+chain store. Any existing chain certificates are used as untrusted CAs.
+If the function is successful the built chain will replace any existing chain.
+The B<flags> parameter can be set to B<SSL_BUILD_CHAIN_FLAG_NO_ROOT> to omit
+the root CA from the built chain.
+
+SSL_set0_chain(), SSL_set1_chain(), SSL_add0_chain_cert(), SSL_add0_chain_cert()
+and SSL_build_cert_chain() are similar except they apply to SSL structure
+B<ssl>.
+
+All these functions are implemented as macros. Those containing a B<1>
+increment the reference count of the supplied certificate or chain so it must
+be freed at some point after the operation. Those containing a B<0> do
+not increment reference counts and the supplied certificate or chain
+B<MUST NOT> be freed after the operation.
+
+=head1 NOTES
+
+The chains associate with an SSL_CTX structure are copied to any SSL
+structures when SSL_new() is called. SSL structures will not be affected
+by any chains subsequently changed in the parent SSL_CTX.
+
+Each of these functions operates on the I<current> end entity
+(i.e. server or client) certificate. This is the last certificate set
+on the corresponding B<ctx> or B<ssl> structure.
+
+One chain can be set for each key type supported by a server. So, for example,
+an RSA and a DSA certificate can (and often will) have different chains.
+
+The functions SSL_CTX_build_cert_chain() and SSL_build_cert_chain() can
+be used to check application configuration and to ensure any necessary
+subordinate CAs are sent in the correct order. Misconfigured applications
+sending incorrect certificate chains often cause problems with peers.
+
+Calling SSL_CTX_build_cert_chain() or SSL_build_cert_chain() is more
+efficient than the automatic chain building as it is only performed once.
+Automatic chain building is performed on each new session.
+
+If any certificates are added using these functions no certificates added
+using SSL_CTX_add_extra_chain_cert() will be used.
+
+=head1 RETURN VALUES
+
+All these functions return 1 for success and 0 for failure.
+
+=back
+
+=head1 SEE ALSO
+
+L<SSL_CTX_add_extra_chain_cert(3)|SSL_CTX_add_extra_chain_cert(3)>
+
+=head1 HISTORY
+
+These functions were first added to OpenSSL 1.0.2.
+
+=cut
diff --git a/doc/ssl/SSL_CTX_add_extra_chain_cert.pod b/doc/ssl/SSL_CTX_add_extra_chain_cert.pod
index ee28f5ccc3..11b3b4bbe3 100644
--- a/doc/ssl/SSL_CTX_add_extra_chain_cert.pod
+++ b/doc/ssl/SSL_CTX_add_extra_chain_cert.pod
@@ -24,6 +24,15 @@ the library will try to complete the chain from the available CA
certificates in the trusted CA storage, see
L<SSL_CTX_load_verify_locations(3)|SSL_CTX_load_verify_locations(3)>.
+=head1 RESTRICTIONS
+
+Only one set of extra chain certificates can be specified per SSL_CTX
+structure. Different chains for different certificates (for example if both
+RSA and DSA certificates are specified by the same server) or different SSL
+structures with the same parent SSL_CTX cannot be specified using this
+function. For more flexibility functions such as SSL_add1_chain_cert() should
+be used instead.
+
=head1 RETURN VALUES
SSL_CTX_add_extra_chain_cert() returns 1 on success. Check out the
@@ -35,5 +44,15 @@ L<ssl(3)|ssl(3)>,
L<SSL_CTX_use_certificate(3)|SSL_CTX_use_certificate(3)>,
L<SSL_CTX_set_client_cert_cb(3)|SSL_CTX_set_client_cert_cb(3)>,
L<SSL_CTX_load_verify_locations(3)|SSL_CTX_load_verify_locations(3)>
+L<SSL_CTX_set0_chain(3)|SSL_CTX_set0_chain(3)>
+L<SSL_CTX_set1_chain(3)|SSL_CTX_set1_chain(3)>
+L<SSL_CTX_add0_chain_cert(3)|SSL_CTX_add0_chain_cert(3)>
+L<SSL_CTX_add1_chain_cert(3)|SSL_CTX_add1_chain_cert(3)>
+L<SSL_set0_chain(3)|SSL_set0_chain(3)>
+L<SSL_set1_chain(3)|SSL_set1_chain(3)>
+L<SSL_add0_chain_cert(3)|SSL_add0_chain_cert(3)>
+L<SSL_add1_chain_cert(3)|SSL_add1_chain_cert(3)>
+L<SSL_CTX_build_cert_chain(3)|SSL_CTX_build_cert_chain(3)>
+L<SSL_build_cert_chain(3)|SSL_build_cert_chain(3)>
=cut
diff --git a/doc/ssl/SSL_CTX_set1_curves.pod b/doc/ssl/SSL_CTX_set1_curves.pod
new file mode 100644
index 0000000000..711f5639ad
--- /dev/null
+++ b/doc/ssl/SSL_CTX_set1_curves.pod
@@ -0,0 +1,100 @@
+=pod
+
+=head1 NAME
+
+SSL_CTX_set1_curves, SSL_CTX_set1_curves_list, SSL_set1_curves,
+SSL_set1_curves_list, SSL_get1_curves, SSL_get_shared_curve,
+SSL_CTX_set_ecdh_auto, SSL_set_ecdh_auto - EC supported curve functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/ssl.h>
+
+ int SSL_CTX_set1_curves(SSL_CTX *ctx, int *clist, int clistlen);
+ int SSL_CTX_set1_curves_list(SSL_CTX *ctx, char *list);
+
+ int SSL_set1_curves(SSL *ssl, int *clist, int clistlen);
+ int SSL_set1_curves_list(SSL *ssl, char *list);
+
+ int SSL_get1_curves(SSL *ssl, int *curves);
+ int SSL_get_shared_curve(SSL *s, int n);
+
+ int SSL_CTX_set_ecdh_auto(SSL_CTX *ctx, int onoff);
+ int SSL_set_ecdh_auto(SSL *s, int onoff);
+
+=head1 DESCRIPTION
+
+SSL_CTX_set1_curves() sets the supported curves for B<ctx> to B<clistlen>
+curves in the array B<clist>. The array consist of all NIDs of curves in
+preference order. For a TLS client the curves are used directly in the
+supported curves extension. For a TLS server the curves are used to
+determine the set of shared curves.
+
+SSL_CTX_set1_curves_list() sets the supported curves for B<ctx> to
+string B<list>. The string is a colon separated list of curve NIDs or
+names, for example "P-521:P-384:P-256".
+
+SSL_set1_curves() and SSL_set1_curves_list() are similar except they set
+supported curves for the SSL structure B<ssl>.
+
+SSL_get1_curves() returns the set of supported curves sent by a client
+in the supported curves extension. It returns the total number of
+supported curves. The B<curves> parameter can be B<NULL> to simply
+return the number of curves for memory allocation purposes. The
+B<curves> array is in the form of a set of curve NIDs in preference
+order. It can return zero if the client did not send a supported curves
+extension.
+
+SSL_get1_shared_curve() returns shared curve B<n> for B<ssl>. If B<n> is
+-1 then the total number of shared curves is returned, which may be
+zero. Other than for diagnostic purposes, most applications will only
+be interested in the first shared curve so B<n> is normally set to zero.
+If the value B<n> is out of range zero is returned.
+
+SSL_CTX_set_ecdh_auto() and SSL_set_ecdh_auto() set automatic curve
+selection for server B<ctx> or B<ssl> to B<onoff>. If B<onoff> is 1 then
+the highest preference curve is automatically used for ECDH temporary
+keys used during key exchange.
+
+All these functions are implemented as macros.
+
+=head1 NOTES
+
+If an application wishes to make use of several of these functions for
+configuration purposes either on a command line or in a file it should
+consider using the SSL_CONF interface instead of manually parsing options.
+
+The functions SSL_CTX_set_ecdh_auto() and SSL_set_ecdh_auto() can be used to
+make a server always choose the most appropriate curve for a client. If set
+it will override any temporary ECDH parameters set by a server. Previous
+versions of OpenSSL could effectively only use a single ECDH curve set
+using a function such as SSL_CTX_set_ecdh_tmp(). Newer applications should
+just call:
+
+ SSL_CTX_set_ecdh_auto(ctx, 1);
+
+and they will automatically support ECDH using the most appropriate shared
+curve.
+
+=head1 RETURN VALUES
+
+SSL_CTX_set1_curves(), SSL_CTX_set1_curves_list(), SSL_set1_curves(),
+SSL_set1_curves_list(), SSL_CTX_set_ecdh_auto() and SSL_set_ecdh_auto()
+return 1 for success and 0 for failure.
+
+SSL_get1_curves() returns the number of curves, which may be zero.
+
+SSL_get1_shared_curve() returns the NID of shared curve B<n> of zero if there
+is no shared curve B<n> or the number of shared curves if B<n> is -1.
+
+=back
+
+=head1 SEE ALSO
+
+L<SSL_CTX_add_extra_chain_cert(3)|SSL_CTX_add_extra_chain_cert(3)>
+
+=head1 HISTORY
+
+These functions were first added to OpenSSL 1.0.2.
+
+=cut
diff --git a/doc/ssl/SSL_CTX_set1_verify_cert_store.pod b/doc/ssl/SSL_CTX_set1_verify_cert_store.pod
new file mode 100644
index 0000000000..a30ae93cf9
--- /dev/null
+++ b/doc/ssl/SSL_CTX_set1_verify_cert_store.pod
@@ -0,0 +1,93 @@
+=pod
+
+=head1 NAME
+
+SSL_CTX_set0_verify_cert_store, SSL_CTX_set1_verify_cert_store,
+SSL_CTX_set0_chain_cert_store, SSL_CTX_set1_chain_cert_store,
+SSL_set0_verify_cert_store, SSL_set1_verify_cert_store,
+SSL_set0_chain_cert_store, SSL_set1_chain_cert_store - set certificate
+verification or chain store
+
+=head1 SYNOPSIS
+
+ #include <openssl/ssl.h>
+
+ int SSL_CTX_set0_verify_cert_store(SSL_CTX *ctx, X509_STORE *st);
+ int SSL_CTX_set1_verify_cert_store(SSL_CTX *ctx, X509_STORE *st);
+ int SSL_CTX_set0_chain_cert_store(SSL_CTX *ctx, X509_STORE *st);
+ int SSL_CTX_set1_chain_cert_store(SSL_CTX *ctx, X509_STORE *st);
+
+ int SSL_set0_verify_cert_store(SSL_CTX *ctx, X509_STORE *st);
+ int SSL_set1_verify_cert_store(SSL_CTX *ctx, X509_STORE *st);
+ int SSL_set0_chain_cert_store(SSL_CTX *ctx, X509_STORE *st);
+ int SSL_set1_chain_cert_store(SSL_CTX *ctx, X509_STORE *st);
+
+=head1 DESCRIPTION
+
+SSL_CTX_set0_verify_cert_store() and SSL_CTX_set1_verify_cert_store()
+set the certificate store used for certificate verification to B<st>.
+
+SSL_CTX_set0_chain_cert_store() and SSL_CTX_set1_chain_cert_store()
+set the certificate store used for certificate chain building to B<st>.
+
+SSL_set0_verify_cert_store(), SSL_set1_verify_cert_store(),
+SSL_set0_chain_cert_store() and SSL_set1_chain_cert_store() are similar
+except they apply to SSL structure B<ssl>.
+
+All these functions are implemented as macros. Those containing a B<1>
+increment the reference count of the supplied store so it must
+be freed at some point after the operation. Those containing a B<0> do
+not increment reference counts and the supplied store B<MUST NOT> be freed
+after the operation.
+
+=head1 NOTES
+
+The stores pointers associated with an SSL_CTX structure are copied to any SSL
+structures when SSL_new() is called. As a result SSL structures will not be
+affected if the parent SSL_CTX store pointer is set to a new value.
+
+The verification store is used to verify the certificate chain sent by the
+peer: that is an SSL/TLS client will use the verification store to verify
+the server's certificate chain and a SSL/TLS server will use it to verify
+any client certificate chain.
+
+The chain store is used to build the certificate chain.
+
+If the mode B<SSL_MODE_NO_AUTO_CHAIN> is set or a certificate chain is
+configured already (for example using the functions such as
+L<SSL_CTX_add1_chain_cert(3)|SSL_CTX_add1_chain_cert(3)> or
+L<SSL_CTX_add_extra_chain_cert(3)|SSL_CTX_add_extra_chain_cert(3)>) then
+automatic chain building is disabled.
+
+If the mode B<SSL_MODE_NO_AUTO_CHAIN> is set then automatic chain building
+is disabled.
+
+If the chain or the verification store is not set then the store associated
+with the parent SSL_CTX is used instead to retain compatibility with previous
+versions of OpenSSL.
+
+=head1 RETURN VALUES
+
+All these functions return 1 for success and 0 for failure.
+
+=back
+
+=head1 SEE ALSO
+
+L<SSL_CTX_add_extra_chain_cert(3)|SSL_CTX_add_extra_chain_cert(3)>
+L<SSL_CTX_set0_chain(3)|SSL_CTX_set0_chain(3)>
+L<SSL_CTX_set1_chain(3)|SSL_CTX_set1_chain(3)>
+L<SSL_CTX_add0_chain_cert(3)|SSL_CTX_add0_chain_cert(3)>
+L<SSL_CTX_add1_chain_cert(3)|SSL_CTX_add1_chain_cert(3)>
+L<SSL_set0_chain(3)|SSL_set0_chain(3)>
+L<SSL_set1_chain(3)|SSL_set1_chain(3)>
+L<SSL_add0_chain_cert(3)|SSL_add0_chain_cert(3)>
+L<SSL_add1_chain_cert(3)|SSL_add1_chain_cert(3)>
+L<SSL_CTX_build_cert_chain(3)|SSL_CTX_build_cert_chain(3)>
+L<SSL_build_cert_chain(3)|SSL_build_cert_chain(3)>
+
+=head1 HISTORY
+
+These functions were first added to OpenSSL 1.0.2.
+
+=cut
diff --git a/doc/ssl/SSL_CTX_set_cert_store.pod b/doc/ssl/SSL_CTX_set_cert_store.pod
index 6acf0d9f9b..846416e069 100644
--- a/doc/ssl/SSL_CTX_set_cert_store.pod
+++ b/doc/ssl/SSL_CTX_set_cert_store.pod
@@ -42,6 +42,13 @@ L<SSL_CTX_set_verify(3)|SSL_CTX_set_verify(3)> family of functions.
This document must therefore be updated when documentation about the
X509_STORE object and its handling becomes available.
+=head1 RESTRICTIONS
+
+The X509_STORE structure used by an SSL_CTX is used for verifying peer
+certificates and building certificate chains, it is also shared by
+every child SSL structure. Applications wanting finer control can use
+functions such as SSL_CTX_set1_verify_cert_store() instead.
+
=head1 RETURN VALUES
SSL_CTX_set_cert_store() does not return diagnostic output.
diff --git a/fips/rand/fips_randtest.c b/fips/rand/fips_randtest.c
index 58c1acecf5..9185783d54 100644
--- a/fips/rand/fips_randtest.c
+++ b/fips/rand/fips_randtest.c
@@ -110,7 +110,6 @@
#include <string.h>
#include <ctype.h>
#include <openssl/rand.h>
-#include <openssl/fips_rand.h>
#include <openssl/err.h>
#include <openssl/bn.h>
@@ -129,6 +128,7 @@ int main(int argc, char *argv[])
#include "fips_utl.h"
#include <openssl/fips.h>
+#include <openssl/fips_rand.h>
typedef struct
{
diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c
index 9b600fdf53..39587039aa 100644
--- a/ssl/d1_pkt.c
+++ b/ssl/d1_pkt.c
@@ -848,6 +848,12 @@ start:
}
}
+ if (s->d1->listen && rr->type != SSL3_RT_HANDSHAKE)
+ {
+ rr->length = 0;
+ goto start;
+ }
+
/* we now have a packet which can be read and processed */
if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec,
@@ -1052,6 +1058,7 @@ start:
!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) &&
!s->s3->renegotiate)
{
+ s->d1->handshake_read_seq++;
s->new_session = 1;
ssl3_renegotiate(s);
if (ssl3_renegotiate_check(s))
diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c
index c628db56ef..d3afec993d 100644
--- a/ssl/d1_srvr.c
+++ b/ssl/d1_srvr.c
@@ -294,10 +294,11 @@ int dtls1_accept(SSL *s)
case SSL3_ST_SW_HELLO_REQ_B:
s->shutdown=0;
+ dtls1_clear_record_buffer(s);
dtls1_start_timer(s);
ret=ssl3_send_hello_request(s);
if (ret <= 0) goto end;
- s->s3->tmp.next_state=SSL3_ST_SW_HELLO_REQ_C;
+ s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A;
s->state=SSL3_ST_SW_FLUSH;
s->init_num=0;
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 7efc77fca3..18eb300c14 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -3421,6 +3421,7 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
else
return ssl_cert_add0_chain_cert(s->cert, (X509 *)parg);
+#ifndef OPENSSL_NO_EC
case SSL_CTRL_GET_CURVES:
{
unsigned char *clist;
@@ -3462,8 +3463,8 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
case SSL_CTRL_SET_ECDH_AUTO:
s->cert->ecdh_tmp_auto = larg;
- break;
-
+ return 1;
+#endif
case SSL_CTRL_SET_SIGALGS:
return tls1_set_sigalgs(s->cert, parg, larg, 0);
@@ -3534,9 +3535,11 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
EVP_PKEY *ptmp;
int rv = 0;
sc = s->session->sess_cert;
+#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DH) && !defined(OPENSSL_NO_EC)
if (!sc->peer_rsa_tmp && !sc->peer_dh_tmp
&& !sc->peer_ecdh_tmp)
return 0;
+#endif
ptmp = EVP_PKEY_new();
if (!ptmp)
return 0;
@@ -3561,7 +3564,7 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
EVP_PKEY_free(ptmp);
return 0;
}
-
+#ifndef OPENSSL_NO_EC
case SSL_CTRL_GET_EC_POINT_FORMATS:
{
SSL_SESSION *sess = s->session;
@@ -3571,7 +3574,7 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
*pformat = sess->tlsext_ecpointformatlist;
return (int)sess->tlsext_ecpointformatlist_length;
}
-
+#endif
default:
break;
}
@@ -3841,6 +3844,7 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
break;
#endif
+#ifndef OPENSSL_NO_EC
case SSL_CTRL_SET_CURVES:
return tls1_set_curves(&ctx->tlsext_ellipticcurvelist,
&ctx->tlsext_ellipticcurvelist_length,
@@ -3852,8 +3856,8 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
parg);
case SSL_CTRL_SET_ECDH_AUTO:
ctx->cert->ecdh_tmp_auto = larg;
- break;
-
+ return 1;
+#endif
case SSL_CTRL_SET_SIGALGS:
return tls1_set_sigalgs(ctx->cert, parg, larg, 0);
@@ -4161,7 +4165,10 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
int ret=0;
const unsigned char *sig;
size_t i, siglen;
- int have_rsa_sign = 0, have_dsa_sign = 0, have_ecdsa_sign = 0;
+ int have_rsa_sign = 0, have_dsa_sign = 0;
+#ifndef OPENSSL_NO_ECDSA
+ int have_ecdsa_sign = 0;
+#endif
int nostrict = 1;
unsigned long alg_k;
@@ -4186,10 +4193,11 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
case TLSEXT_signature_dsa:
have_dsa_sign = 1;
break;
-
+#ifndef OPENSSL_NO_ECDSA
case TLSEXT_signature_ecdsa:
have_ecdsa_sign = 1;
break;
+#endif
}
}
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index afdc8ff5df..99e6c2f126 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -1358,7 +1358,7 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
return(retval);
}
-
+#ifndef OPENSSL_NO_EC
static int check_suiteb_cipher_list(const SSL_METHOD *meth, CERT *c,
const char **prule_str)
{
@@ -1417,6 +1417,7 @@ static int check_suiteb_cipher_list(const SSL_METHOD *meth, CERT *c,
c->ecdh_tmp_auto = 1;
return 1;
}
+#endif
STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
@@ -1436,10 +1437,10 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
*/
if (rule_str == NULL || cipher_list == NULL || cipher_list_by_id == NULL)
return NULL;
-
+#ifndef OPENSSL_NO_EC
if (!check_suiteb_cipher_list(ssl_method, c, &rule_str))
return NULL;
-
+#endif
/*
* To reduce the work to do we only want to process the compiled
diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c
index 437f385f05..1f4c4dd153 100644
--- a/ssl/ssl_conf.c
+++ b/ssl/ssl_conf.c
@@ -253,7 +253,7 @@ static int cmd_curves(SSL_CONF_CTX *cctx, const char *value)
rv = SSL_CTX_set1_curves_list(cctx->ctx, value);
return rv > 0;
}
-
+#ifndef OPENSSL_NO_ECDH
/* ECDH temporary parameters */
static int cmd_ecdhparam(SSL_CONF_CTX *cctx, const char *value)
{
@@ -314,7 +314,7 @@ static int cmd_ecdhparam(SSL_CONF_CTX *cctx, const char *value)
return rv > 0;
}
-
+#endif
static int cmd_cipher_list(SSL_CONF_CTX *cctx, const char *value)
{
int rv = 1;
@@ -378,7 +378,9 @@ static ssl_conf_cmd_tbl ssl_conf_cmds[] = {
{cmd_sigalgs, "SignatureAlgorithms", "sigalgs"},
{cmd_client_sigalgs, "ClientSignatureAlgorithms", "client_sigalgs"},
{cmd_curves, "Curves", "curves"},
+#ifndef OPENSSL_NO_ECDH
{cmd_ecdhparam, "ECDHParameters", "named_curve"},
+#endif
{cmd_cipher_list, "CipherString", "cipher"},
{cmd_protocol, "Protocol", NULL},
{cmd_options, "Options", NULL},
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index a4e9174528..54f02a67c4 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1186,8 +1186,10 @@ long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd,long larg,void *parg)
{
switch (cmd)
{
+#ifndef OPENSSL_NO_EC
case SSL_CTRL_SET_CURVES_LIST:
return tls1_set_curves_list(NULL, NULL, parg);
+#endif
case SSL_CTRL_SET_SIGALGS_LIST:
case SSL_CTRL_SET_CLIENT_SIGALGS_LIST:
return tls1_set_sigalgs_list(NULL, parg, 0);
@@ -2318,14 +2320,17 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
int rsa_enc_export,dh_rsa_export,dh_dsa_export;
int rsa_tmp_export,dh_tmp_export,kl;
unsigned long mask_k,mask_a,emask_k,emask_a;
- int have_ecc_cert, ecdh_ok, ecdsa_ok, ecc_pkey_size;
+#ifndef OPENSSL_NO_ECDSA
+ int have_ecc_cert, ecdsa_ok, ecc_pkey_size;
+#endif
#ifndef OPENSSL_NO_ECDH
- int have_ecdh_tmp;
+ int have_ecdh_tmp, ecdh_ok;
#endif
+#ifndef OPENSSL_NO_EC
X509 *x = NULL;
EVP_PKEY *ecc_pkey = NULL;
int signature_nid = 0, pk_nid = 0, md_nid = 0;
-
+#endif
if (c == NULL) return;
kl=SSL_C_EXPORT_PKEYLENGTH(cipher);
@@ -2363,7 +2368,9 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
dh_dsa= cpk->valid_flags & CERT_PKEY_VALID;
dh_dsa_export=(dh_dsa && EVP_PKEY_size(cpk->privatekey)*8 <= kl);
cpk= &(c->pkeys[SSL_PKEY_ECC]);
+#ifndef OPENSSL_NO_EC
have_ecc_cert= cpk->valid_flags & CERT_PKEY_VALID;
+#endif
mask_k=0;
mask_a=0;
emask_k=0;
@@ -2443,6 +2450,7 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
/* An ECC certificate may be usable for ECDH and/or
* ECDSA cipher suites depending on the key usage extension.
*/
+#ifndef OPENSSL_NO_EC
if (have_ecc_cert)
{
cpk = &c->pkeys[SSL_PKEY_ECC];
@@ -2499,6 +2507,7 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
}
#endif
}
+#endif
#ifndef OPENSSL_NO_ECDH
if (have_ecdh_tmp)
diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c
index b6765a30e1..41878776ec 100644
--- a/ssl/ssl_rsa.c
+++ b/ssl/ssl_rsa.c
@@ -459,6 +459,15 @@ static int ssl_set_cert(CERT *c, X509 *x)
X509_free(c->pkeys[i].x509);
CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
c->pkeys[i].x509=x;
+#ifndef OPENSSL_NO_TLSEXT
+ /* Free the old serverinfo data, if it exists. */
+ if (c->pkeys[i].serverinfo != NULL)
+ {
+ OPENSSL_free(c->pkeys[i].serverinfo);
+ c->pkeys[i].serverinfo = NULL;
+ c->pkeys[i].serverinfo_length = 0;
+ }
+#endif
c->key= &(c->pkeys[i]);
c->valid=0;
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 9372f34cb5..3cc673eb17 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -814,6 +814,13 @@ int tls1_check_ec_tmp_key(SSL *s, unsigned long cid)
#endif
}
+#else
+
+static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md)
+ {
+ return 1;
+ }
+
#endif /* OPENSSL_NO_EC */
#ifndef OPENSSL_NO_TLSEXT
@@ -861,17 +868,18 @@ static unsigned char tls12_sigalgs[] = {
tlsext_sigalg_rsa(TLSEXT_hash_md5)
#endif
};
-
+#ifndef OPENSSL_NO_ECDSA
static unsigned char suiteb_sigalgs[] = {
tlsext_sigalg_ecdsa(TLSEXT_hash_sha256)
tlsext_sigalg_ecdsa(TLSEXT_hash_sha384)
};
-
+#endif
size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs)
{
/* If Suite B mode use Suite B sigalgs only, ignore any other
* preferences.
*/
+#ifndef OPENSSL_NO_EC
switch (tls1_suiteb(s))
{
case SSL_CERT_FLAG_SUITEB_128_LOS:
@@ -886,7 +894,7 @@ size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs)
*psigs = suiteb_sigalgs + 2;
return 2;
}
-
+#endif
/* If server use client authentication sigalgs if not NULL */
if (s->server && s->cert->client_sigalgs)
{
@@ -928,6 +936,7 @@ int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
+#ifndef OPENSSL_NO_EC
if (pkey->type == EVP_PKEY_EC)
{
unsigned char curve_id[2], comp_id;
@@ -968,6 +977,7 @@ int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
}
else if (tls1_suiteb(s))
return 0;
+#endif
/* Check signature matches a type we sent */
sent_sigslen = tls12_get_psigalgs(s, &sent_sigs);
@@ -1470,11 +1480,12 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
#ifndef OPENSSL_NO_NEXTPROTONEG
int next_proto_neg_seen;
#endif
+#ifndef OPENSSL_NO_EC
unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
int using_ecc = (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)) || (alg_a & SSL_aECDSA);
using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL);
-
+#endif
/* don't add extensions for SSLv3, unless doing secure renegotiation */
if (s->version == SSL3_VERSION && !s->s3->send_connection_binding)
return p;
diff --git a/test/cms-test.pl b/test/cms-test.pl
index fa4394cff9..006733a6be 100644
--- a/test/cms-test.pl
+++ b/test/cms-test.pl
@@ -82,8 +82,23 @@ my $smdir = "smime-certs";
my $halt_err = 1;
my $badcmd = 0;
+my $no_ec;
my $ossl8 = `$ossl_path version -v` =~ /0\.9\.8/;
+system ("$ossl_path no-ec >/dev/null");
+if ($? == 0)
+ {
+ $no_ec = 1;
+ }
+elsif ($? == 256)
+ {
+ $no_ec = 0;
+ }
+else
+ {
+ die "Error checking for EC support\n";
+ }
+
my @smime_pkcs7_tests = (
[
@@ -409,6 +424,14 @@ my @smime_cms_param_tests = (
. " -recip $smdir/smec2.pem -aes128"
. " -keyopt ecdh_kdf_md:sha256 -keyopt ecdh_cofactor_mode:1",
"-decrypt -recip $smdir/smec2.pem -in test.cms -out smtst.txt"
+ ],
+
+ [
+"enveloped content test streaming S/MIME format, X9.42 DH",
+ "-encrypt -in smcont.txt"
+ . " -stream -out test.cms"
+ . " -recip $smdir/smdh.pem -aes128",
+ "-decrypt -recip $smdir/smdh.pem -in test.cms -out smtst.txt"
]
);
@@ -464,6 +487,11 @@ sub run_smime_tests {
$rscmd =~ s/-stream//;
$rvcmd =~ s/-stream//;
}
+ if ($no_ec && $tnam =~ /ECDH/)
+ {
+ print "$tnam: skipped, EC disabled\n";
+ next;
+ }
system("$scmd$rscmd$redir");
if ($?) {
print "$tnam: generation error\n";
diff --git a/test/smime-certs/mksmime-certs.sh b/test/smime-certs/mksmime-certs.sh
index 37c5633dc0..f01f66427c 100644
--- a/test/smime-certs/mksmime-certs.sh
+++ b/test/smime-certs/mksmime-certs.sh
@@ -57,5 +57,18 @@ CN="Test S/MIME EE EC #2" $OPENSSL req -config ca.cnf -nodes \
-keyout smec2.pem -out req.pem -newkey ec:ecp2.pem
$OPENSSL x509 -req -in req.pem -CA smroot.pem -days 3600 \
-extfile ca.cnf -extensions usr_cert -CAcreateserial >>smec2.pem
+# Create X9.42 DH parameters.
+$OPENSSL genpkey -genparam -algorithm DH -pkeyopt dh_paramgen_type:2 \
+ -out dhp.pem
+# Generate X9.42 DH key.
+$OPENSSL genpkey -paramfile dhp.pem -out smdh.pem
+$OPENSSL pkey -pubout -in smdh.pem -out dhpub.pem
+# Generate dummy request.
+CN="Test S/MIME EE DH #1" $OPENSSL req -config ca.cnf -nodes \
+ -keyout smtmp.pem -out req.pem -newkey rsa:2048
+# Sign request but force public key to DH
+$OPENSSL x509 -req -in req.pem -CA smroot.pem -days 3600 \
+ -force_pubkey dhpub.pem \
+ -extfile ca.cnf -extensions usr_cert -CAcreateserial >>smdh.pem
# Remove temp files.
-rm -f req.pem ecp.pem ecp2.pem dsap.pem smroot.srl
+rm -f req.pem ecp.pem ecp2.pem dsap.pem dhp.pem dhpub.pem smtmp.pem smroot.srl
diff --git a/test/smime-certs/smdh.pem b/test/smime-certs/smdh.pem
new file mode 100644
index 0000000000..f831b0713b
--- /dev/null
+++ b/test/smime-certs/smdh.pem
@@ -0,0 +1,33 @@
+-----BEGIN PRIVATE KEY-----
+MIIBSgIBADCCASsGByqGSM4+AgEwggEeAoGBANQMSgwEcnEZ31kZxa9Ef8qOK/AJ
+9dMlsXMWVYnf/QevGdN/0Aei/j9a8QHG+CvvTm0DOEKhN9QUtABKsYZag865CA7B
+mSdHjQuFqILtzA25sDJ+3+jk9vbss+56ETRll/wasJVLGbmmHNkBMvc1fC1d/sGF
+cEn4zJnQvvFaeMgDAoGAaQD9ZvL8FYsJuNxN6qp5VfnfRqYvyi2PWSqtRKPGGC+V
+thYg49PRjwPOcXzvOsdEOQ7iH9jTiSvnUdwSSEwYTZkSBuQXAgOMJAWOpoXyaRvh
+atziBDoBnWS+/kX5RBhxvS0+em9yfRqAQleuGG+R1mEDihyJc8dWQQPT+O1l4oUC
+FQCJlKsQZ0VBrWPGcUCNa54ZW6TH9QQWAhRR2NMZrQSfWthXDO8Lj5WZ34zQrA==
+-----END PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIID/zCCAuegAwIBAgIJANv1TSKgememMA0GCSqGSIb3DQEBBQUAMEQxCzAJBgNV
+BAYTAlVLMRYwFAYDVQQKDA1PcGVuU1NMIEdyb3VwMR0wGwYDVQQDDBRUZXN0IFMv
+TUlNRSBSU0EgUm9vdDAeFw0xMzA4MDIxNDQ5MjlaFw0yMzA2MTExNDQ5MjlaMEQx
+CzAJBgNVBAYTAlVLMRYwFAYDVQQKDA1PcGVuU1NMIEdyb3VwMR0wGwYDVQQDDBRU
+ZXN0IFMvTUlNRSBFRSBESCAjMTCCAbYwggErBgcqhkjOPgIBMIIBHgKBgQDUDEoM
+BHJxGd9ZGcWvRH/KjivwCfXTJbFzFlWJ3/0HrxnTf9AHov4/WvEBxvgr705tAzhC
+oTfUFLQASrGGWoPOuQgOwZknR40LhaiC7cwNubAyft/o5Pb27LPuehE0ZZf8GrCV
+Sxm5phzZATL3NXwtXf7BhXBJ+MyZ0L7xWnjIAwKBgGkA/Wby/BWLCbjcTeqqeVX5
+30amL8otj1kqrUSjxhgvlbYWIOPT0Y8DznF87zrHRDkO4h/Y04kr51HcEkhMGE2Z
+EgbkFwIDjCQFjqaF8mkb4Wrc4gQ6AZ1kvv5F+UQYcb0tPnpvcn0agEJXrhhvkdZh
+A4ociXPHVkED0/jtZeKFAhUAiZSrEGdFQa1jxnFAjWueGVukx/UDgYQAAoGAL1ve
+cgI2awBeJH8ULBhSQpdL224VUDxFPiXzt8Vu5VLnxPv0pfA5En+8VByTuV7u6RSw
+3/78NuTyr/sTyN8YlB1AuXHdTJynA1ICte1xgD4j2ijlq+dv8goOAFt9xkvXx7LD
+umJ/cCignXETcNGfMi8+0s0bpMZyoHRdce8DQ26jYDBeMAwGA1UdEwEB/wQCMAAw
+DgYDVR0PAQH/BAQDAgXgMB0GA1UdDgQWBBQLWk1ffSXH8p3Bqrdjgi/6jzLnwDAf
+BgNVHSMEGDAWgBTffl6IBSQzCN0igQKXzJq3sTMnMDANBgkqhkiG9w0BAQUFAAOC
+AQEAWvJj79MW1/Wq3RIANgAhonsI1jufYqxTH+1M0RU0ZXHulgem77Le2Ls1bizi
+0SbvfpTiiFGkbKonKtO2wvfqwwuptSg3omMI5IjAGxYbyv2KBzIpp1O1LTDk9RbD
+48JMMF01gByi2+NLUQ1MYF+5RqyoRqcyp5x2+Om1GeIM4Q/GRuI4p4dybWy8iC+d
+LeXQfR7HXfh+tAum+WzjfLJwbnWbHmPhTbKB01U4lBp6+r8BGHAtNdPjEHqap4/z
+vVZVXti9ThZ20EhM+VFU3y2wyapeQjhQvw/A2YRES0Ik7BSj3hHfWH/CTbLVQnhu
+Uj6tw18ExOYxqoEGixNLPA5qsQ==
+-----END CERTIFICATE-----