diff options
45 files changed, 1631 insertions, 160 deletions
@@ -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----- |