From 5ee357155da570228ff95d59550b4aa9aac24717 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Wed, 2 Sep 2020 17:59:21 +0300 Subject: [PATCH] Special branch reuires patching OpenSSL This branch is created for experiments with the patched OpenSSL version. The patch implements Russian GOST TLS 1.2 and TLS 1.3 support in OpenSSL. Some parts of the patch are already included in OpenSSL 3.0, some are not and possibly, will never be. This branch is recommended for ditribution builders and those who want make experiments. It MUST NOT be used instead of system OpenSSL. --- CMakeLists.txt | 2 +- README.md | 4 +- patches/openssl_111g.diff | 3372 +++++++++++++++++++++++++++++++++++++ 3 files changed, 3376 insertions(+), 2 deletions(-) create mode 100644 patches/openssl_111g.diff diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d4d65b..28236b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ include(CheckCSourceRuns) enable_testing() -find_package(OpenSSL 3.0 REQUIRED) +find_package(OpenSSL 1.1.1 REQUIRED) include_directories(${OPENSSL_INCLUDE_DIR}) if (CMAKE_C_COMPILER_ID MATCHES "Clang") diff --git a/README.md b/README.md index aa636d7..fde70cb 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ # engine A reference implementation of the Russian GOST crypto algorithms for OpenSSL -Compatibility: OpenSSL 1.0.2 (needs patches), OpenSSL 1.1.* +Compatibility: OpenSSL 1.1.1 (needs patches) +*This branch should not compile with vanilla OpenSSL 1.1.1! +It requires patching OpenSSL using the patches/openssl_111g.diff* License: same as the corresponding version of OpenSSL. diff --git a/patches/openssl_111g.diff b/patches/openssl_111g.diff new file mode 100644 index 0000000..fa3dd56 --- /dev/null +++ b/patches/openssl_111g.diff @@ -0,0 +1,3372 @@ +Index: apps/cms.c +=================================================================== +--- apps/cms.c (revision 14523) ++++ apps/cms.c (working copy) +@@ -75,15 +75,16 @@ + OPT_NOSIGS, OPT_NO_CONTENT_VERIFY, OPT_NO_ATTR_VERIFY, OPT_INDEF, + OPT_NOINDEF, OPT_CRLFEOL, OPT_NOOUT, OPT_RR_PRINT, + OPT_RR_ALL, OPT_RR_FIRST, OPT_RCTFORM, OPT_CERTFILE, OPT_CAFILE, +- OPT_CAPATH, OPT_NOCAPATH, OPT_NOCAFILE,OPT_CONTENT, OPT_PRINT, ++ OPT_CAPATH, OPT_NOCAPATH, OPT_NOCAFILE,OPT_CONTENT, OPT_PRINT, OPT_NAMEOPT, + OPT_SECRETKEY, OPT_SECRETKEYID, OPT_PWRI_PASSWORD, OPT_ECONTENT_TYPE, + OPT_PASSIN, OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP, + OPT_CERTSOUT, OPT_MD, OPT_INKEY, OPT_KEYFORM, OPT_KEYOPT, OPT_RR_FROM, + OPT_RR_TO, OPT_AES128_WRAP, OPT_AES192_WRAP, OPT_AES256_WRAP, +- OPT_3DES_WRAP, OPT_ENGINE, ++ OPT_3DES_WRAP, OPT_WRAP, OPT_ENGINE, + OPT_R_ENUM, + OPT_V_ENUM, +- OPT_CIPHER ++ OPT_CIPHER, ++ OPT_ORIGINATOR + } OPTION_CHOICE; + + const OPTIONS cms_options[] = { +@@ -150,6 +151,8 @@ + "Supply or override content for detached signature"}, + {"print", OPT_PRINT, '-', + "For the -cmsout operation print out all fields of the CMS structure"}, ++ {"nameopt", OPT_NAMEOPT, 's', ++ "For the -print option specifies various strings printing options"}, + {"secretkey", OPT_SECRETKEY, 's'}, + {"secretkeyid", OPT_SECRETKEYID, 's'}, + {"pwri_password", OPT_PWRI_PASSWORD, 's'}, +@@ -159,6 +162,7 @@ + {"from", OPT_FROM, 's', "From address"}, + {"subject", OPT_SUBJECT, 's', "Subject"}, + {"signer", OPT_SIGNER, 's', "Signer certificate file"}, ++ {"originator", OPT_ORIGINATOR, 's', "Originator certificate file"}, + {"recip", OPT_RECIP, '<', "Recipient cert file for decryption"}, + {"certsout", OPT_CERTSOUT, '>', "Certificate output file"}, + {"md", OPT_MD, 's', "Digest algorithm to use when signing or resigning"}, +@@ -177,6 +181,7 @@ + # ifndef OPENSSL_NO_DES + {"des3-wrap", OPT_3DES_WRAP, '-', "Use 3DES-EDE to wrap key"}, + # endif ++ {"wrap", OPT_WRAP, 's', "Any wrap cipher to wrap key"}, + # ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, + # endif +@@ -196,7 +201,7 @@ + STACK_OF(OPENSSL_STRING) *rr_to = NULL, *rr_from = NULL; + STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL; + STACK_OF(X509) *encerts = NULL, *other = NULL; +- X509 *cert = NULL, *recip = NULL, *signer = NULL; ++ X509 *cert = NULL, *recip = NULL, *signer = NULL, *originator = 0; + X509_STORE *store = NULL; + X509_VERIFY_PARAM *vpm = NULL; + char *certfile = NULL, *keyfile = NULL, *contfile = NULL; +@@ -204,7 +209,7 @@ + char *certsoutfile = NULL; + int noCAfile = 0, noCApath = 0; + char *infile = NULL, *outfile = NULL, *rctfile = NULL; +- char *passinarg = NULL, *passin = NULL, *signerfile = NULL, *recipfile = NULL; ++ char *passinarg = NULL, *passin = NULL, *signerfile = NULL, *originatorfile = NULL, *recipfile = NULL; + char *to = NULL, *from = NULL, *subject = NULL, *prog; + cms_key_param *key_first = NULL, *key_param = NULL; + int flags = CMS_DETACHED, noout = 0, print = 0, keyidx = -1, vpmtouched = 0; +@@ -406,6 +411,10 @@ + case OPT_PRINT: + noout = print = 1; + break; ++ case OPT_NAMEOPT: ++ if (!set_nameopt(opt_arg())) ++ goto opthelp; ++ break; + case OPT_SECRETKEY: + if (secret_key != NULL) { + BIO_printf(bio_err, "Invalid key (supplied twice) %s\n", +@@ -486,6 +495,9 @@ + } + signerfile = opt_arg(); + break; ++ case OPT_ORIGINATOR: ++ originatorfile = opt_arg(); ++ break; + case OPT_INKEY: + /* If previous -inkey argument add signer to list */ + if (keyfile != NULL) { +@@ -580,6 +592,10 @@ + case OPT_AES256_WRAP: + wrap_cipher = EVP_aes_256_wrap(); + break; ++ case OPT_WRAP: ++ if (!opt_cipher(opt_unknown(), &wrap_cipher)) ++ goto end; ++ break; + } + } + argc = opt_num_rest(); +@@ -687,11 +703,11 @@ + } + + if (certfile != NULL) { +- if (!load_certs(certfile, &other, FORMAT_PEM, NULL, +- "certificate file")) { +- ERR_print_errors(bio_err); +- goto end; +- } ++ if (!load_certs(certfile, &other, FORMAT_PEM, NULL, ++ "certificate file")) { ++ ERR_print_errors(bio_err); ++ goto end; ++ } + } + + if (recipfile != NULL && (operation == SMIME_DECRYPT)) { +@@ -702,6 +718,15 @@ + } + } + ++ if (originatorfile != NULL) ++ { ++ if ((originator = load_cert(originatorfile, FORMAT_PEM, ++ "originator certificate file")) == NULL) { ++ ERR_print_errors(bio_err); ++ goto end; ++ } ++ } ++ + if (operation == SMIME_SIGN_RECEIPT) { + if ((signer = load_cert(signerfile, FORMAT_PEM, + "receipt signer certificate file")) == NULL) { +@@ -710,7 +735,8 @@ + } + } + +- if (operation == SMIME_DECRYPT) { ++ if (operation == SMIME_DECRYPT || ++ operation == SMIME_ENCRYPT) { + if (keyfile == NULL) + keyfile = recipfile; + } else if ((operation == SMIME_SIGN) || (operation == SMIME_SIGN_RECEIPT)) { +@@ -819,23 +845,31 @@ + for (i = 0; i < sk_X509_num(encerts); i++) { + CMS_RecipientInfo *ri; + cms_key_param *kparam; +- int tflags = flags; ++ int tflags = flags | CMS_KEY_PARAM; /* This flag enforces allocating the EVP_PKEY_CTX for the recipient here */ ++ EVP_PKEY_CTX *pctx; + X509 *x = sk_X509_value(encerts, i); ++ int res; ++ + for (kparam = key_first; kparam; kparam = kparam->next) { + if (kparam->idx == i) { +- tflags |= CMS_KEY_PARAM; + break; + } + } +- ri = CMS_add1_recipient_cert(cms, x, tflags); ++ ri = CMS_add1_recipient(cms, x, key, originator, tflags); + if (ri == NULL) + goto end; ++ ++ pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); + if (kparam != NULL) { +- EVP_PKEY_CTX *pctx; +- pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); + if (!cms_set_pkey_param(pctx, kparam->param)) + goto end; + } ++ ++ res = EVP_PKEY_CTX_ctrl(pctx, -1, -1, ++ EVP_PKEY_CTRL_CIPHER, EVP_CIPHER_nid(cipher), NULL); ++ if (res <= 0 && res != -2) ++ goto end; ++ + if (CMS_RecipientInfo_type(ri) == CMS_RECIPINFO_AGREE + && wrap_cipher) { + EVP_CIPHER_CTX *wctx; +@@ -981,7 +1015,7 @@ + } + + if (key != NULL) { +- if (!CMS_decrypt_set1_pkey(cms, key, recip)) { ++ if (!CMS_decrypt_set1_pkey_and_peer(cms, key, recip, originator)) { + BIO_puts(bio_err, "Error decrypting CMS using private key\n"); + goto end; + } +@@ -1047,8 +1081,19 @@ + } + } else { + if (noout) { +- if (print) +- CMS_ContentInfo_print_ctx(out, cms, 0, NULL); ++ if (print) { ++ ASN1_PCTX *pctx = NULL; ++ if (get_nameopt() != XN_FLAG_ONELINE) { ++ pctx = ASN1_PCTX_new(); ++ if (pctx) { /* Print anyway if malloc failed */ ++ ASN1_PCTX_set_flags(pctx, ASN1_PCTX_FLAGS_SHOW_ABSENT); ++ ASN1_PCTX_set_str_flags(pctx, get_nameopt()); ++ ASN1_PCTX_set_nm_flags(pctx, get_nameopt()); ++ } ++ } ++ CMS_ContentInfo_print_ctx(out, cms, 0, pctx); ++ ASN1_PCTX_free(pctx); ++ } + } else if (outformat == FORMAT_SMIME) { + if (to) + BIO_printf(out, "To: %s%s", to, mime_eol); +Index: apps/s_cb.c +=================================================================== +--- apps/s_cb.c (revision 14523) ++++ apps/s_cb.c (working copy) +@@ -684,7 +684,7 @@ + {NULL} + }; + +-/* from rfc8446 4.2.3. + gost (https://tools.ietf.org/id/draft-smyshlyaev-tls12-gost-suites-04.html) */ ++/* from rfc8446 4.2.3. + GOST (https://tools.ietf.org/html/draft-smyshlyaev-tls13-gost-suites-01) */ + static STRINT_PAIR signature_tls13_scheme_list[] = { + {"rsa_pkcs1_sha1", 0x0201 /* TLSEXT_SIGALG_rsa_pkcs1_sha1 */}, + {"ecdsa_sha1", 0x0203 /* TLSEXT_SIGALG_ecdsa_sha1 */}, +@@ -696,6 +696,13 @@ + {"ecdsa_secp384r1_sha384", 0x0503 /* TLSEXT_SIGALG_ecdsa_secp384r1_sha384 */}, + {"rsa_pkcs1_sha512", 0x0601 /* TLSEXT_SIGALG_rsa_pkcs1_sha512 */}, + {"ecdsa_secp521r1_sha512", 0x0603 /* TLSEXT_SIGALG_ecdsa_secp521r1_sha512 */}, ++ {"gostr34102012_256a", 0x0709 /* TLSEXT_SIGALG_gostr34102012_256a */}, ++ {"gostr34102012_256b", 0x070A /* TLSEXT_SIGALG_gostr34102012_256b */}, ++ {"gostr34102012_256c", 0x070B /* TLSEXT_SIGALG_gostr34102012_256c */}, ++ {"gostr34102012_256d", 0x070C /* TLSEXT_SIGALG_gostr34102012_256d */}, ++ {"gostr34102012_512a", 0x070D /* TLSEXT_SIGALG_gostr34102012_512a */}, ++ {"gostr34102012_512b", 0x070E /* TLSEXT_SIGALG_gostr34102012_512b */}, ++ {"gostr34102012_512c", 0x070F /* TLSEXT_SIGALG_gostr34102012_512c */}, + {"rsa_pss_rsae_sha256", 0x0804 /* TLSEXT_SIGALG_rsa_pss_rsae_sha256 */}, + {"rsa_pss_rsae_sha384", 0x0805 /* TLSEXT_SIGALG_rsa_pss_rsae_sha384 */}, + {"rsa_pss_rsae_sha512", 0x0806 /* TLSEXT_SIGALG_rsa_pss_rsae_sha512 */}, +@@ -704,9 +711,6 @@ + {"rsa_pss_pss_sha256", 0x0809 /* TLSEXT_SIGALG_rsa_pss_pss_sha256 */}, + {"rsa_pss_pss_sha384", 0x080a /* TLSEXT_SIGALG_rsa_pss_pss_sha384 */}, + {"rsa_pss_pss_sha512", 0x080b /* TLSEXT_SIGALG_rsa_pss_pss_sha512 */}, +- {"gostr34102001", 0xeded /* TLSEXT_SIGALG_gostr34102001_gostr3411 */}, +- {"gostr34102012_256", 0xeeee /* TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256 */}, +- {"gostr34102012_512", 0xefef /* TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512 */}, + {NULL} + }; + +Index: crypto/objects/objects.txt +=================================================================== +--- crypto/objects/objects.txt (revision 14523) ++++ crypto/objects/objects.txt (working copy) +@@ -1321,6 +1321,14 @@ + + # TC26 GOST OIDs + ++id-tc26 0 : id-tc26-modules: GOST TC26 ASN.1 modules ++ ++id-tc26-modules 6 : id-tc26-cms: GOST TC26 SMS ++ ++id-tc26-cms 1 : id-tc26-cms-attrs: GOST TC26 SMS attributes ++ ++id-tc26-cms-attrs 1 : id-tc26-mac-attr: GOST TC26 SMS content-mac attribute ++ + id-tc26 1 : id-tc26-algorithms + id-tc26-algorithms 1 : id-tc26-sign + !Cname id-GostR3410-2012-256 +@@ -1344,11 +1352,11 @@ + + id-tc26-algorithms 5 : id-tc26-cipher + id-tc26-cipher 1 : id-tc26-cipher-gostr3412-2015-magma +-id-tc26-cipher-gostr3412-2015-magma 1 : id-tc26-cipher-gostr3412-2015-magma-ctracpkm +-id-tc26-cipher-gostr3412-2015-magma 2 : id-tc26-cipher-gostr3412-2015-magma-ctracpkm-omac ++id-tc26-cipher-gostr3412-2015-magma 1 : magma-ctr-acpkm ++id-tc26-cipher-gostr3412-2015-magma 2 : magma-ctr-acpkm-omac + id-tc26-cipher 2 : id-tc26-cipher-gostr3412-2015-kuznyechik +-id-tc26-cipher-gostr3412-2015-kuznyechik 1 : id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm +-id-tc26-cipher-gostr3412-2015-kuznyechik 2 : id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm-omac ++id-tc26-cipher-gostr3412-2015-kuznyechik 1 : kuznyechik-ctr-acpkm ++id-tc26-cipher-gostr3412-2015-kuznyechik 2 : kuznyechik-ctr-acpkm-omac + + id-tc26-algorithms 6 : id-tc26-agreement + id-tc26-agreement 1 : id-tc26-agreement-gost-3410-2012-256 +@@ -1356,9 +1364,9 @@ + + id-tc26-algorithms 7 : id-tc26-wrap + id-tc26-wrap 1 : id-tc26-wrap-gostr3412-2015-magma +-id-tc26-wrap-gostr3412-2015-magma 1 : id-tc26-wrap-gostr3412-2015-magma-kexp15 ++id-tc26-wrap-gostr3412-2015-magma 1 : magma-kexp15 + id-tc26-wrap 2 : id-tc26-wrap-gostr3412-2015-kuznyechik +-id-tc26-wrap-gostr3412-2015-kuznyechik 1 : id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15 ++id-tc26-wrap-gostr3412-2015-kuznyechik 1 : kuznyechik-kexp15 + + id-tc26 2 : id-tc26-constants + +@@ -1382,16 +1390,25 @@ + member-body 643 3 131 1 1 : INN : INN + member-body 643 100 1 : OGRN : OGRN + member-body 643 100 3 : SNILS : SNILS ++member-body 643 100 5 : OGRNIP : OGRNIP + member-body 643 100 111 : subjectSignTool : Signing Tool of Subject + member-body 643 100 112 : issuerSignTool : Signing Tool of Issuer ++member-body 643 100 113 : classSignTool : Class of Signing Tool ++member-body 643 100 113 1 : classSignToolKC1 : Class of Signing Tool KC1 ++member-body 643 100 113 2 : classSignToolKC2 : Class of Signing Tool KC2 ++member-body 643 100 113 3 : classSignToolKC3 : Class of Signing Tool KC3 ++member-body 643 100 113 4 : classSignToolKB1 : Class of Signing Tool KB1 ++member-body 643 100 113 5 : classSignToolKB2 : Class of Signing Tool KB2 ++member-body 643 100 113 6 : classSignToolKA1 : Class of Signing Tool KA1 + + #GOST R34.13-2015 Grasshopper "Kuznechik" +- : grasshopper-ecb +- : grasshopper-ctr +- : grasshopper-ofb +- : grasshopper-cbc +- : grasshopper-cfb +- : grasshopper-mac ++ : kuznyechik-ecb ++ : kuznyechik-ctr ++ : kuznyechik-ofb ++ : kuznyechik-cbc ++ : kuznyechik-cfb ++ : kuznyechik-mac ++ : kuznyechik-mgm + + #GOST R34.13-2015 Magma + : magma-ecb +@@ -1400,6 +1417,7 @@ + : magma-cbc + : magma-cfb + : magma-mac ++ : magma-mgm + + # Definitions for Camellia cipher - CBC MODE + +Index: crypto/cms/cms_local.h +=================================================================== +--- crypto/cms/cms_local.h (revision 14523) ++++ crypto/cms/cms_local.h (working copy) +@@ -403,12 +403,13 @@ + ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si); + + BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms); ++int cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain); + CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms); + int cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd); + int cms_pkey_get_ri_type(EVP_PKEY *pk); ++int cms_pkey_is_ri_type_supported(EVP_PKEY *pk, int ri_type); + /* KARI routines */ +-int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip, +- EVP_PKEY *pk, unsigned int flags); ++int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip, EVP_PKEY *recipPubKey, X509 * originator, EVP_PKEY *originatorPrivKey, unsigned int flags); + int cms_RecipientInfo_kari_encrypt(CMS_ContentInfo *cms, + CMS_RecipientInfo *ri); + +Index: crypto/cms/cms_lib.c +=================================================================== +--- crypto/cms/cms_lib.c (revision 14523) ++++ crypto/cms/cms_lib.c (working copy) +@@ -130,12 +130,14 @@ + switch (OBJ_obj2nid(cms->contentType)) { + + case NID_pkcs7_data: +- case NID_pkcs7_enveloped: + case NID_pkcs7_encrypted: + case NID_id_smime_ct_compressedData: + /* Nothing to do */ + return 1; + ++ case NID_pkcs7_enveloped: ++ return cms_EnvelopedData_final(cms, cmsbio); ++ + case NID_pkcs7_signed: + return cms_SignedData_final(cms, cmsbio); + +Index: crypto/cms/cms_smime.c +=================================================================== +--- crypto/cms/cms_smime.c (revision 14523) ++++ crypto/cms/cms_smime.c (working copy) +@@ -576,8 +576,8 @@ + return NULL; + } + +-static int cms_kari_set1_pkey(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, +- EVP_PKEY *pk, X509 *cert) ++static int cms_kari_set1_pkey_and_peer(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, ++ EVP_PKEY *pk, X509 *cert, X509 *peer) + { + int i; + STACK_OF(CMS_RecipientEncryptedKey) *reks; +@@ -588,7 +588,7 @@ + rek = sk_CMS_RecipientEncryptedKey_value(reks, i); + if (cert != NULL && CMS_RecipientEncryptedKey_cert_cmp(rek, cert)) + continue; +- CMS_RecipientInfo_kari_set0_pkey(ri, pk); ++ CMS_RecipientInfo_kari_set0_pkey_and_peer(ri, pk, peer); + rv = CMS_RecipientInfo_kari_decrypt(cms, ri, rek); + CMS_RecipientInfo_kari_set0_pkey(ri, NULL); + if (rv > 0) +@@ -600,27 +600,35 @@ + + int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert) + { ++ return CMS_decrypt_set1_pkey_and_peer(cms, pk, cert, NULL); ++} ++ ++int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert, X509 *peer) ++{ + STACK_OF(CMS_RecipientInfo) *ris; + CMS_RecipientInfo *ri; +- int i, r, ri_type; ++ int i, r, cms_pkey_ri_type; + int debug = 0, match_ri = 0; + ris = CMS_get0_RecipientInfos(cms); + if (ris) + debug = cms->d.envelopedData->encryptedContentInfo->debug; +- ri_type = cms_pkey_get_ri_type(pk); +- if (ri_type == CMS_RECIPINFO_NONE) { +- CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, +- CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); +- return 0; ++ ++ cms_pkey_ri_type = cms_pkey_get_ri_type(pk); ++ if (cms_pkey_ri_type == CMS_RECIPINFO_NONE) { ++ CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY_AND_PEER, ++ CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); ++ return 0; + } + + for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) { ++ int ri_type; + ri = sk_CMS_RecipientInfo_value(ris, i); +- if (CMS_RecipientInfo_type(ri) != ri_type) +- continue; ++ ri_type = CMS_RecipientInfo_type(ri); ++/* if (!cms_pkey_is_ri_type_supported(pk, ri_type)) ++ continue; */ + match_ri = 1; + if (ri_type == CMS_RECIPINFO_AGREE) { +- r = cms_kari_set1_pkey(cms, ri, pk, cert); ++ r = cms_kari_set1_pkey_and_peer(cms, ri, pk, cert, peer); + if (r > 0) + return 1; + if (r < 0) +@@ -640,13 +648,13 @@ + * If not debugging clear any error and return success to + * avoid leaking of information useful to MMA + */ +- if (!debug) { ++ if (!debug && cms_pkey_ri_type == CMS_RECIPINFO_TRANS) { + ERR_clear_error(); + return 1; + } + if (r > 0) + return 1; +- CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_DECRYPT_ERROR); ++ CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY_AND_PEER, CMS_R_DECRYPT_ERROR); + return 0; + } + /* +@@ -654,17 +662,17 @@ + * successful decrypt. Always attempt to decrypt all recipients + * to avoid leaking timing of a successful decrypt. + */ +- else if (r > 0 && debug) ++ else if (r > 0 && (debug || cms_pkey_ri_type != CMS_RECIPINFO_TRANS)) + return 1; + } + } + /* If no cert, key transport and not debugging always return success */ +- if (cert == NULL && ri_type == CMS_RECIPINFO_TRANS && match_ri && !debug) { ++ if (cert == NULL && cms_pkey_ri_type == CMS_RECIPINFO_TRANS && match_ri && !debug) { + ERR_clear_error(); + return 1; + } + +- CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_NO_MATCHING_RECIPIENT); ++ CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY_AND_PEER, CMS_R_NO_MATCHING_RECIPIENT); + return 0; + + } +Index: crypto/cms/cms_kari.c +=================================================================== +--- crypto/cms/cms_kari.c (revision 14523) ++++ crypto/cms/cms_kari.c (working copy) +@@ -152,7 +152,7 @@ + return -1; + } + +-int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk) ++int CMS_RecipientInfo_kari_set0_pkey_and_peer(CMS_RecipientInfo *ri, EVP_PKEY *pk, X509 *peer) + { + EVP_PKEY_CTX *pctx; + CMS_KeyAgreeRecipientInfo *kari = ri->d.kari; +@@ -164,6 +164,16 @@ + pctx = EVP_PKEY_CTX_new(pk, NULL); + if (!pctx || EVP_PKEY_derive_init(pctx) <= 0) + goto err; ++ ++ if (peer) ++ { ++ EVP_PKEY *pub_pkey = X509_get0_pubkey(peer); ++ if (0 >= EVP_PKEY_derive_set_peer(pctx, pub_pkey)) ++ { ++ goto err; ++ } ++ } ++ + kari->pctx = pctx; + return 1; + err: +@@ -171,6 +181,11 @@ + return 0; + } + ++int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk) ++{ ++ return CMS_RecipientInfo_kari_set0_pkey_and_peer(ri, pk, NULL); ++} ++ + EVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri) + { + if (ri->type == CMS_RECIPINFO_AGREE) +@@ -282,10 +297,27 @@ + return rv; + } + ++/* Set originator private key and initialise context based on it */ ++static int cms_kari_set_originator_private_key(CMS_KeyAgreeRecipientInfo *kari, EVP_PKEY *originatorPrivKey ) ++{ ++ EVP_PKEY_CTX *pctx = NULL; ++ int rv = 0; ++ pctx = EVP_PKEY_CTX_new(originatorPrivKey, NULL); ++ if (!pctx) ++ goto err; ++ if (EVP_PKEY_derive_init(pctx) <= 0) ++ goto err; ++ kari->pctx = pctx; ++ rv = 1; ++err: ++ if (!rv) ++ EVP_PKEY_CTX_free(pctx); ++ return rv; ++} ++ + /* Initialise a kari based on passed certificate and key */ + +-int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip, +- EVP_PKEY *pk, unsigned int flags) ++int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip, EVP_PKEY *recipPubKey, X509 * originator, EVP_PKEY *originatorPrivKey, unsigned int flags) + { + CMS_KeyAgreeRecipientInfo *kari; + CMS_RecipientEncryptedKey *rek = NULL; +@@ -320,12 +352,45 @@ + return 0; + } + +- /* Create ephemeral key */ +- if (!cms_kari_create_ephemeral_key(kari, pk)) +- return 0; ++ if (!originatorPrivKey && !originator) ++ { ++ /* Create ephemeral key */ ++ if (!cms_kari_create_ephemeral_key(kari, recipPubKey)) ++ return 0; ++ } ++ else ++ { ++ /* Use originator key */ ++ CMS_OriginatorIdentifierOrKey *oik = ri->d.kari->originator; + +- EVP_PKEY_up_ref(pk); +- rek->pkey = pk; ++ if (!originatorPrivKey && !originator) ++ { ++ return 0; ++ } ++ ++ if (flags & CMS_USE_ORIGINATOR_KEYID) { ++ //kari->originator->issuerAndSerialNumber ++ oik->type = CMS_OIK_KEYIDENTIFIER; ++ oik->d.subjectKeyIdentifier = ASN1_OCTET_STRING_new(); ++ if (oik->d.subjectKeyIdentifier == NULL) ++ return 0; ++ if (!cms_set1_keyid(&oik->d.subjectKeyIdentifier, originator)) ++ return 0; ++ } ++ else { ++ oik->type = CMS_REK_ISSUER_SERIAL; ++ if (!cms_set1_ias(&oik->d.issuerAndSerialNumber, originator)) ++ return 0; ++ } ++ ++ if (!cms_kari_set_originator_private_key(kari, originatorPrivKey)) ++ { ++ return 0; ++ } ++ } ++ ++ EVP_PKEY_up_ref(recipPubKey); ++ rek->pkey = recipPubKey; + return 1; + } + +@@ -335,14 +400,35 @@ + EVP_CIPHER_CTX *ctx = kari->ctx; + const EVP_CIPHER *kekcipher; + int keylen = EVP_CIPHER_key_length(cipher); ++ int ret; + /* If a suitable wrap algorithm is already set nothing to do */ + kekcipher = EVP_CIPHER_CTX_cipher(ctx); + +- if (kekcipher) { +- if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_WRAP_MODE) +- return 0; +- return 1; ++ if (kekcipher) ++ { ++ if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_WRAP_MODE) ++ return 0; ++ return 1; + } ++ /* Here the Infotecs patch begins */ ++ else if (cipher && (EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_GET_WRAP_CIPHER)) ++ { ++ ret = EVP_CIPHER_meth_get_ctrl(cipher)(NULL, EVP_CTRL_GET_WRAP_CIPHER, 0, &kekcipher); ++ if (0 >= ret) ++ { ++ return 0; ++ } ++ ++ if (kekcipher) ++ { ++ if (EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE) ++ return 0; ++ ++ return EVP_EncryptInit_ex(ctx, kekcipher, NULL, NULL, NULL); ++ } ++ } ++ /* Here the Infotecs patch ends */ ++ + /* + * Pick a cipher based on content encryption cipher. If it is DES3 use + * DES3 wrap otherwise use AES wrap similar to key size. +Index: crypto/cms/cms_env.c +=================================================================== +--- crypto/cms/cms_env.c (revision 14523) ++++ crypto/cms/cms_env.c (working copy) +@@ -20,6 +20,8 @@ + + /* CMS EnvelopedData Utilities */ + ++static void cms_env_set_version(CMS_EnvelopedData *env); ++ + CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms) + { + if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped) { +@@ -121,6 +123,39 @@ + return NULL; + } + ++int cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain) ++{ ++ CMS_EnvelopedData *env = NULL; ++ EVP_CIPHER_CTX *ctx = NULL; ++ BIO *mbio = BIO_find_type(chain, BIO_TYPE_CIPHER); ++ ++ env = cms_get0_enveloped(cms); ++ if (!env) ++ return 0; ++ ++ if (!mbio) { ++ CMSerr(CMS_F_CMS_ENVELOPEDDATA_FINAL, CMS_R_CONTENT_NOT_FOUND); ++ return 0; ++ } ++ ++ BIO_get_cipher_ctx(mbio, &ctx); ++ ++ /* ++ * If the selected cipher supports unprotected attributes, ++ * deal with it using special ctrl function ++ */ ++ if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_CIPHER_WITH_MAC) { ++ cms->d.envelopedData->unprotectedAttrs = sk_X509_ATTRIBUTE_new_null(); ++ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_PROCESS_UNPROTECTED, 1, env->unprotectedAttrs) <= 0) { ++ CMSerr(CMS_F_CMS_ENVELOPEDDATA_FINAL, CMS_R_CTRL_FAILURE); ++ return 0; ++ } ++ } ++ cms_env_set_version(cms->d.envelopedData); ++ ++ return 1; ++} ++ + /* Key Transport Recipient Info (KTRI) routines */ + + /* Initialise a ktri based on passed certificate and key */ +@@ -175,8 +210,8 @@ + * Add a recipient certificate using appropriate type of RecipientInfo + */ + +-CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, +- X509 *recip, unsigned int flags) ++CMS_RecipientInfo *CMS_add1_recipient(CMS_ContentInfo *cms, X509 *recip, ++ EVP_PKEY *originatorPrivKey, X509 * originator, unsigned int flags) + { + CMS_RecipientInfo *ri = NULL; + CMS_EnvelopedData *env; +@@ -192,7 +227,7 @@ + + pk = X509_get0_pubkey(recip); + if (!pk) { +- CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, CMS_R_ERROR_GETTING_PUBLIC_KEY); ++ CMSerr(CMS_F_CMS_ADD1_RECIPIENT, CMS_R_ERROR_GETTING_PUBLIC_KEY); + goto err; + } + +@@ -204,12 +239,12 @@ + break; + + case CMS_RECIPINFO_AGREE: +- if (!cms_RecipientInfo_kari_init(ri, recip, pk, flags)) ++ if (!cms_RecipientInfo_kari_init(ri, recip, pk, originator, originatorPrivKey, flags)) + goto err; + break; + + default: +- CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, ++ CMSerr(CMS_F_CMS_ADD1_RECIPIENT, + CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); + goto err; + +@@ -221,7 +256,7 @@ + return ri; + + merr: +- CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, ERR_R_MALLOC_FAILURE); ++ CMSerr(CMS_F_CMS_ADD1_RECIPIENT, ERR_R_MALLOC_FAILURE); + err: + M_ASN1_free_of(ri, CMS_RecipientInfo); + return NULL; +@@ -228,6 +263,12 @@ + + } + ++CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, ++ X509 *recip, unsigned int flags) ++{ ++ return CMS_add1_recipient(cms, recip, NULL, NULL, flags); ++} ++ + int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri, + EVP_PKEY **pk, X509 **recip, + X509_ALGOR **palg) +@@ -856,52 +897,90 @@ + env->version = 0; + } + +-BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms) ++static BIO *cms_EnvelopedData_Decryption_init_bio(CMS_ContentInfo *cms) + { +- CMS_EncryptedContentInfo *ec; +- STACK_OF(CMS_RecipientInfo) *rinfos; +- CMS_RecipientInfo *ri; +- int i, ok = 0; +- BIO *ret; ++ CMS_EncryptedContentInfo *ec = cms->d.envelopedData->encryptedContentInfo; ++ BIO *contentBio = cms_EncryptedContent_init_bio(ec); ++ EVP_CIPHER_CTX *ctx = NULL; + +- /* Get BIO first to set up key */ ++ if (!contentBio) ++ return NULL; + +- ec = cms->d.envelopedData->encryptedContentInfo; +- ret = cms_EncryptedContent_init_bio(ec); ++ BIO_get_cipher_ctx(contentBio, &ctx); ++ if (ctx == NULL) { ++ BIO_free(contentBio); ++ return NULL; ++ } ++/* ++ * If the selected cipher supports unprotected attributes, ++ * deal with it using special ctrl function ++ */ ++ if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_CIPHER_WITH_MAC && ++ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_PROCESS_UNPROTECTED, 0, cms->d.envelopedData->unprotectedAttrs) <= 0) { ++ BIO_free(contentBio); ++ return NULL; ++ } ++ return contentBio; ++} + +- /* If error or no cipher end of processing */ ++static BIO *cms_EnvelopedData_Encryption_init_bio(CMS_ContentInfo *cms) ++{ ++ CMS_EncryptedContentInfo *ec; ++ STACK_OF(CMS_RecipientInfo) *rinfos; ++ CMS_RecipientInfo *ri; ++ int i, ok = 0; ++ BIO *ret; + +- if (!ret || !ec->cipher) +- return ret; ++ /* Get BIO first to set up key */ + +- /* Now encrypt content key according to each RecipientInfo type */ ++ ec = cms->d.envelopedData->encryptedContentInfo; ++ ret = cms_EncryptedContent_init_bio(ec); + +- rinfos = cms->d.envelopedData->recipientInfos; ++ /* If error or no cipher end of processing */ + +- for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++) { +- ri = sk_CMS_RecipientInfo_value(rinfos, i); +- if (CMS_RecipientInfo_encrypt(cms, ri) <= 0) { +- CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO, +- CMS_R_ERROR_SETTING_RECIPIENTINFO); +- goto err; +- } +- } +- cms_env_set_version(cms->d.envelopedData); ++ if (!ret) ++ return ret; + +- ok = 1; ++ /* Now encrypt content key according to each RecipientInfo type */ + +- err: +- ec->cipher = NULL; +- OPENSSL_clear_free(ec->key, ec->keylen); +- ec->key = NULL; +- ec->keylen = 0; +- if (ok) +- return ret; +- BIO_free(ret); +- return NULL; ++ rinfos = cms->d.envelopedData->recipientInfos; + ++ for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++) { ++ ri = sk_CMS_RecipientInfo_value(rinfos, i); ++ if (CMS_RecipientInfo_encrypt(cms, ri) <= 0) { ++ CMSerr(CMS_F_CMS_ENVELOPEDDATA_ENCRYPTION_INIT_BIO, ++ CMS_R_ERROR_SETTING_RECIPIENTINFO); ++ goto err; ++ } ++ } ++ cms_env_set_version(cms->d.envelopedData); /* FIXME move lower? */ ++ ++ ok = 1; ++ ++err: ++ ec->cipher = NULL; ++ OPENSSL_clear_free(ec->key, ec->keylen); ++ ec->key = NULL; ++ ec->keylen = 0; ++ if (ok) ++ return ret; ++ BIO_free(ret); ++ return NULL; ++ + } + ++BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms) ++{ ++ if (cms->d.envelopedData->encryptedContentInfo->cipher) ++ { ++ //If cipher is set it's encrypting ++ return cms_EnvelopedData_Encryption_init_bio(cms); ++ } ++ ++ //If cipher is not set it's decrypting ++ return cms_EnvelopedData_Decryption_init_bio(cms); ++} ++ + /* + * Get RecipientInfo type (if any) supported by a key (public or private). To + * retain compatibility with previous behaviour if the ctrl value isn't +@@ -917,3 +996,25 @@ + } + return CMS_RECIPINFO_TRANS; + } ++ ++int cms_pkey_is_ri_type_supported(EVP_PKEY *pk, int ri_type) ++{ ++ if (pk->ameth && pk->ameth->pkey_ctrl) ++ { ++ int i, r; ++ i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_IS_RI_TYPE_SUPPORTED, ri_type, &r); ++ if (i > 0) ++ return r; ++ } ++ ++ //if ASN1_PKEY_CTRL_CMS_IS_RI_TYPE_SUPPORTED not supported ++ ++ int supportedRiType = cms_pkey_get_ri_type(pk); ++ ++ if (supportedRiType < 0) ++ { ++ return 0; ++ } ++ ++ return (supportedRiType == ri_type); ++} +Index: crypto/cms/cms_err.c +=================================================================== +--- crypto/cms/cms_err.c (revision 14523) ++++ crypto/cms/cms_err.c (working copy) +@@ -22,6 +22,7 @@ + "CMS_add0_recipient_password"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD1_RECEIPTREQUEST, 0), + "CMS_add1_ReceiptRequest"}, ++ {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD1_RECIPIENT, 0), "CMS_add1_recipient"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD1_RECIPIENT_CERT, 0), + "CMS_add1_recipient_cert"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD1_SIGNER, 0), "CMS_add1_signer"}, +@@ -45,6 +46,8 @@ + "CMS_decrypt_set1_password"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DECRYPT_SET1_PKEY, 0), + "CMS_decrypt_set1_pkey"}, ++ {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DECRYPT_SET1_PKEY_AND_PEER, 0), ++ "CMS_decrypt_set1_pkey_and_peer"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DIGESTALGORITHM_FIND_CTX, 0), + "cms_DigestAlgorithm_find_ctx"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, 0), +@@ -66,6 +69,12 @@ + "CMS_EncryptedData_set1_key"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENVELOPEDDATA_CREATE, 0), + "CMS_EnvelopedData_create"}, ++ {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENVELOPEDDATA_DECRYPTION_INIT_BIO, 0), ++ "cms_EnvelopedData_Decryption_init_bio"}, ++ {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENVELOPEDDATA_ENCRYPTION_INIT_BIO, 0), ++ "cms_EnvelopedData_Encryption_init_bio"}, ++ {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENVELOPEDDATA_FINAL, 0), ++ "cms_EnvelopedData_final"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENVELOPEDDATA_INIT_BIO, 0), + "cms_EnvelopedData_init_bio"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENVELOPED_DATA_INIT, 0), +Index: crypto/x509v3/standard_exts.h +=================================================================== +--- crypto/x509v3/standard_exts.h (revision 14523) ++++ crypto/x509v3/standard_exts.h (working copy) +@@ -68,6 +68,8 @@ + &v3_ct_scts[1], + &v3_ct_scts[2], + #endif ++ &v3_subject_sign_tool, ++ &v3_issuer_sign_tool, + &v3_tls_feature, + &v3_ext_admission + }; +Index: crypto/x509v3/v3err.c +=================================================================== +--- crypto/x509v3/v3err.c (revision 14523) ++++ crypto/x509v3/v3err.c (working copy) +@@ -1,6 +1,6 @@ + /* + * Generated by util/mkerr.pl DO NOT EDIT +- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy +@@ -37,6 +37,8 @@ + "i2s_ASN1_IA5STRING"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_I2S_ASN1_INTEGER, 0), + "i2s_ASN1_INTEGER"}, ++ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_I2S_ASN1_UTF8STRING, 0), ++ "i2s_ASN1_UTF8STRING"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_I2V_AUTHORITY_INFO_ACCESS, 0), + "i2v_AUTHORITY_INFO_ACCESS"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_LEVEL_ADD_NODE, 0), "level_add_node"}, +@@ -58,6 +60,8 @@ + "s2i_ASN1_INTEGER"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_S2I_ASN1_OCTET_STRING, 0), + "s2i_ASN1_OCTET_STRING"}, ++ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_S2I_ASN1_UTF8STRING, 0), ++ "s2i_ASN1_UTF8STRING"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_S2I_SKEY_ID, 0), "s2i_skey_id"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SET_DIST_POINT_NAME, 0), + "set_dist_point_name"}, +Index: crypto/x509v3/build.info +=================================================================== +--- crypto/x509v3/build.info (revision 14523) ++++ crypto/x509v3/build.info (working copy) +@@ -5,4 +5,4 @@ + v3_int.c v3_enum.c v3_sxnet.c v3_cpols.c v3_crld.c v3_purp.c v3_info.c \ + v3_akeya.c v3_pmaps.c v3_pcons.c v3_ncons.c v3_pcia.c v3_pci.c \ + pcy_cache.c pcy_node.c pcy_data.c pcy_map.c pcy_tree.c pcy_lib.c \ +- v3_asid.c v3_addr.c v3_tlsf.c v3_admis.c ++ v3_asid.c v3_addr.c v3_tlsf.c v3_admis.c v3_rus.c +Index: crypto/x509v3/v3_alt.c +=================================================================== +--- crypto/x509v3/v3_alt.c (revision 14523) ++++ crypto/x509v3/v3_alt.c (working copy) +@@ -24,13 +24,46 @@ + static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx); + static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx); + ++static int i2r_GENERAL_NAMES(X509V3_EXT_METHOD *method, ++ GENERAL_NAMES *gens, BIO *out, ++ int indent); ++ ++static int GENERAL_NAME_oneline_ex(char *name, GENERAL_NAME *gen, int len) ++{ ++ int i; ++ BIO *mem = NULL; ++ BUF_MEM *bptr; ++ ++ mem = BIO_new(BIO_s_mem()); ++ if (mem == 0) ++ return 0; ++ ++ switch (gen->type) { ++ case GEN_DIRNAME: ++ X509_NAME_print_ex(mem, gen->d.dirn, 0, XN_FLAG_SEP_COMMA_PLUS | ASN1_STRFLGS_UTF8_CONVERT); ++ break; ++ } ++ ++ BIO_get_mem_ptr(mem, &bptr); ++ i = BIO_set_close(mem, BIO_NOCLOSE); ++ BIO_free(mem); ++ if (i<=0) ++ return 0; ++ ++ if(bptr->length < len) ++ strncpy(name, bptr->data, bptr->length); ++ else ++ strncpy(name, bptr->data, len); ++ return 1; ++} ++ + const X509V3_EXT_METHOD v3_alt[3] = { + {NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), + 0, 0, 0, 0, + 0, 0, +- (X509V3_EXT_I2V) i2v_GENERAL_NAMES, ++ NULL, /* (X509V3_EXT_I2V) i2v_GENERAL_NAMES, */ + (X509V3_EXT_V2I)v2i_subject_alt, +- NULL, NULL, NULL}, ++ (X509V3_EXT_I2R)i2r_GENERAL_NAMES, NULL, NULL}, + + {NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), + 0, 0, 0, 0, +@@ -37,13 +70,13 @@ + 0, 0, + (X509V3_EXT_I2V) i2v_GENERAL_NAMES, + (X509V3_EXT_V2I)v2i_issuer_alt, +- NULL, NULL, NULL}, ++ (X509V3_EXT_I2R)i2r_GENERAL_NAMES/*NULL*/, NULL, NULL}, + + {NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES), + 0, 0, 0, 0, + 0, 0, + (X509V3_EXT_I2V) i2v_GENERAL_NAMES, +- NULL, NULL, NULL, NULL}, ++ NULL, (X509V3_EXT_I2R)i2r_GENERAL_NAMES/*NULL*/, NULL, NULL}, + }; + + STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, +@@ -79,7 +112,7 @@ + STACK_OF(CONF_VALUE) *ret) + { + unsigned char *p; +- char oline[256], htmp[5]; ++ char oline[1024], htmp[5]; + int i; + + switch (gen->type) { +@@ -114,7 +147,7 @@ + break; + + case GEN_DIRNAME: +- if (X509_NAME_oneline(gen->d.dirn, oline, sizeof(oline)) == NULL ++ if (GENERAL_NAME_oneline_ex(oline, gen, sizeof(oline)) <= 0 + || !X509V3_add_value("DirName", oline, &ret)) + return NULL; + break; +@@ -151,6 +184,96 @@ + return ret; + } + ++/* beldmit */ ++int i2r_GENERAL_NAME(X509V3_EXT_METHOD *method, ++ GENERAL_NAME *gen, BIO *out, ++ int indent) ++{ ++ unsigned char *p; ++ char oline[256], htmp[5]; ++ int i; ++ BIO_printf(out, "%*s", indent, ""); ++ switch (gen->type) { ++ case GEN_OTHERNAME: ++ BIO_write(out, "othername: ", 24); ++ break; ++ ++ case GEN_X400: ++ BIO_write(out, "X400Name: ", 24); ++ break; ++ ++ case GEN_EDIPARTY: ++ BIO_write(out, "EdiPartyName: ", 28); ++ break; ++ ++ case GEN_EMAIL: ++ BIO_write(out, "email: ", 7); ++ BIO_write(out, gen->d.ia5->data, gen->d.ia5->length); ++ break; ++ ++ case GEN_DNS: ++ BIO_write(out, "DNS: ", 5); ++ BIO_write(out, gen->d.ia5->data, gen->d.ia5->length); ++ break; ++ ++ case GEN_URI: ++ BIO_write(out, "URI: ", 5); ++ BIO_write(out, gen->d.ia5->data, gen->d.ia5->length); ++ break; ++ ++ case GEN_DIRNAME: ++ BIO_write(out, "DirName: ", 9); ++ X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_SEP_COMMA_PLUS|ASN1_STRFLGS_UTF8_CONVERT); ++ break; ++ ++ case GEN_IPADD: ++ p = gen->d.ip->data; ++ if (gen->d.ip->length == 4) ++ BIO_snprintf(oline, sizeof oline, ++ "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); ++ else if (gen->d.ip->length == 16) { ++ oline[0] = 0; ++ for (i = 0; i < 8; i++) { ++ BIO_snprintf(htmp, sizeof htmp, "%X", p[0] << 8 | p[1]); ++ p += 2; ++ strcat(oline, htmp); ++ if (i != 7) ++ strcat(oline, ":"); ++ } ++ } else { ++ BIO_write(out, "IP Address: ", 22); ++ break; ++ } ++ BIO_write(out, "IP Address: ", 12); ++ BIO_write(out, oline, strlen(oline)); ++ break; ++ ++ case GEN_RID: ++ i2t_ASN1_OBJECT(oline, 256, gen->d.rid); ++ BIO_write(out, "Registered ID: ", 15); ++ BIO_write(out, oline, strlen(oline)); ++ break; ++ } ++ BIO_write(out, "\n", 1); ++ return 1; ++} ++ ++int i2r_GENERAL_NAMES(X509V3_EXT_METHOD *method, ++ GENERAL_NAMES *gens, BIO *out, ++ int indent) ++{ ++ int i; ++ GENERAL_NAME *gen; ++ for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { ++ gen = sk_GENERAL_NAME_value(gens, i); ++ if (!i2r_GENERAL_NAME(method, gen, out, indent)) ++ return 0; ++ } ++ return 1; ++} ++ ++/* beldmit */ ++ + int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) + { + unsigned char *p; +Index: crypto/x509v3/ext_dat.h +=================================================================== +--- crypto/x509v3/ext_dat.h (revision 14523) ++++ crypto/x509v3/ext_dat.h (working copy) +@@ -21,5 +21,6 @@ + extern const X509V3_EXT_METHOD v3_name_constraints, v3_inhibit_anyp, v3_idp; + extern const X509V3_EXT_METHOD v3_addr, v3_asid; + extern const X509V3_EXT_METHOD v3_ct_scts[3]; ++extern const X509V3_EXT_METHOD v3_subject_sign_tool, v3_issuer_sign_tool; + extern const X509V3_EXT_METHOD v3_tls_feature; + extern const X509V3_EXT_METHOD v3_ext_admission; +Index: crypto/x509v3/v3_rus.c +=================================================================== +--- crypto/x509v3/v3_rus.c (nonexistent) ++++ crypto/x509v3/v3_rus.c (revision 14744) +@@ -0,0 +1,168 @@ ++/* v3_rus.c */ ++/* ++ * Written by Dmitry Belyavskiy for the OpenSSL project ++ * 2015. ++ */ ++/* ==================================================================== ++ * Copyright (c) 1999-2004 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 ++ * licensing@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. ++ * ==================================================================== ++ * ++ * This product includes cryptographic software written by Eric Young ++ * (eay@cryptsoft.com). This product includes software written by Tim ++ * Hudson (tjh@cryptsoft.com). ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++static char *i2s_ASN1_UTF8STRING(const X509V3_EXT_METHOD *method, ++ ASN1_UTF8STRING *utf8str) ++{ ++ char *tmp; ++ if (!utf8str || !utf8str->length) ++ return NULL; ++ if (!(tmp = OPENSSL_malloc(utf8str->length + 1))) { ++ X509V3err(X509V3_F_I2S_ASN1_UTF8STRING, ERR_R_MALLOC_FAILURE); ++ return NULL; ++ } ++ memcpy(tmp, utf8str->data, utf8str->length); ++ tmp[utf8str->length] = 0; ++ return tmp; ++} ++ ++static ASN1_UTF8STRING *s2i_ASN1_UTF8STRING(X509V3_EXT_METHOD *method, ++ X509V3_CTX *ctx, char *str) ++{ ++ ASN1_UTF8STRING *utf8str; ++ if (!str) { ++ X509V3err(X509V3_F_S2I_ASN1_UTF8STRING, ++ X509V3_R_INVALID_NULL_ARGUMENT); ++ return NULL; ++ } ++ if (!(utf8str = ASN1_STRING_type_new(V_ASN1_UTF8STRING))) ++ goto err; ++ if (!ASN1_STRING_set((ASN1_STRING *)utf8str, (unsigned char *)str, ++ strlen(str))) { ++ ASN1_STRING_free(utf8str); ++ goto err; ++ } ++#ifdef CHARSET_EBCDIC ++ ebcdic2ascii(utf8str->data, utf8str->data, utf8str->length); ++#endif /* CHARSET_EBCDIC */ ++ return utf8str; ++ err: ++ X509V3err(X509V3_F_S2I_ASN1_UTF8STRING, ERR_R_MALLOC_FAILURE); ++ return NULL; ++} ++ ++const X509V3_EXT_METHOD v3_subject_sign_tool = { ++ NID_subjectSignTool, 0, ASN1_ITEM_ref(ASN1_UTF8STRING), ++ 0, 0, 0, 0, ++ (X509V3_EXT_I2S)i2s_ASN1_UTF8STRING, ++ (X509V3_EXT_S2I)s2i_ASN1_UTF8STRING, ++ 0, 0, 0, 0, NULL ++}; ++ ++typedef struct ISSUER_SIGN_TOOL_st { ++ ASN1_UTF8STRING *signTool; ++ ASN1_UTF8STRING *cATool; ++ ASN1_UTF8STRING *signToolCert; ++ ASN1_UTF8STRING *cAToolCert; ++} ISSUER_SIGN_TOOL; ++ ++ASN1_SEQUENCE(ISSUER_SIGN_TOOL) = { ++ ASN1_SIMPLE(ISSUER_SIGN_TOOL, signTool, ASN1_UTF8STRING), ++ ASN1_SIMPLE(ISSUER_SIGN_TOOL, cATool, ASN1_UTF8STRING), ++ ASN1_SIMPLE(ISSUER_SIGN_TOOL, signToolCert, ASN1_UTF8STRING), ++ ASN1_SIMPLE(ISSUER_SIGN_TOOL, cAToolCert, ASN1_UTF8STRING) ++} ASN1_SEQUENCE_END(ISSUER_SIGN_TOOL) ++ ++IMPLEMENT_ASN1_FUNCTIONS(ISSUER_SIGN_TOOL) ++ ++static int i2r_ISSUER_SIGN_TOOL(X509V3_EXT_METHOD *method, ++ ISSUER_SIGN_TOOL *ist, BIO *out, ++ int indent) ++{ ++ if (ist->signTool) { ++ BIO_printf(out, "%*s", indent, ""); ++ BIO_write(out, "signTool: ", 14); ++ BIO_write(out, ist->signTool->data, ist->signTool->length); ++ BIO_write(out, "\n", 1); ++ } ++ if (ist->cATool) { ++ BIO_printf(out, "%*s", indent, ""); ++ BIO_write(out, "cATool: ", 14); ++ BIO_write(out, ist->cATool->data, ist->cATool->length); ++ BIO_write(out, "\n", 1); ++ } ++ if (ist->signToolCert) { ++ BIO_printf(out, "%*s", indent, ""); ++ BIO_write(out, "signToolCert: ", 14); ++ BIO_write(out, ist->signToolCert->data, ist->signToolCert->length); ++ BIO_write(out, "\n", 1); ++ } ++ if (ist->cAToolCert) { ++ BIO_printf(out, "%*s", indent, ""); ++ BIO_write(out, "cAToolCert: ", 14); ++ BIO_write(out, ist->cAToolCert->data, ist->cAToolCert->length); ++ BIO_write(out, "\n", 1); ++ } ++ return 1; ++} ++ ++const X509V3_EXT_METHOD v3_issuer_sign_tool = { ++ NID_issuerSignTool, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(ISSUER_SIGN_TOOL), ++ 0, 0, 0, 0, ++ 0, 0, ++ 0, /*(X509V3_EXT_I2V)i2v_ISSUER_SIGN_TOOL,*/ ++ 0, ++ (X509V3_EXT_I2R)i2r_ISSUER_SIGN_TOOL, 0, NULL ++}; +Index: crypto/err/openssl.txt +=================================================================== +--- crypto/err/openssl.txt (revision 14523) ++++ crypto/err/openssl.txt (working copy) +@@ -239,6 +239,7 @@ + CMS_F_CMS_ADD0_RECIPIENT_KEY:100:CMS_add0_recipient_key + CMS_F_CMS_ADD0_RECIPIENT_PASSWORD:165:CMS_add0_recipient_password + CMS_F_CMS_ADD1_RECEIPTREQUEST:158:CMS_add1_ReceiptRequest ++CMS_F_CMS_ADD1_RECIPIENT:181:CMS_add1_recipient + CMS_F_CMS_ADD1_RECIPIENT_CERT:101:CMS_add1_recipient_cert + CMS_F_CMS_ADD1_SIGNER:102:CMS_add1_signer + CMS_F_CMS_ADD1_SIGNINGTIME:103:cms_add1_signingTime +@@ -254,6 +255,7 @@ + CMS_F_CMS_DECRYPT_SET1_KEY:113:CMS_decrypt_set1_key + CMS_F_CMS_DECRYPT_SET1_PASSWORD:166:CMS_decrypt_set1_password + CMS_F_CMS_DECRYPT_SET1_PKEY:114:CMS_decrypt_set1_pkey ++CMS_F_CMS_DECRYPT_SET1_PKEY_AND_PEER:182:CMS_decrypt_set1_pkey_and_peer + CMS_F_CMS_DIGESTALGORITHM_FIND_CTX:115:cms_DigestAlgorithm_find_ctx + CMS_F_CMS_DIGESTALGORITHM_INIT_BIO:116:cms_DigestAlgorithm_init_bio + CMS_F_CMS_DIGESTEDDATA_DO_FINAL:117:cms_DigestedData_do_final +@@ -266,6 +268,11 @@ + CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT:122:CMS_EncryptedData_encrypt + CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY:123:CMS_EncryptedData_set1_key + CMS_F_CMS_ENVELOPEDDATA_CREATE:124:CMS_EnvelopedData_create ++CMS_F_CMS_ENVELOPEDDATA_DECRYPTION_INIT_BIO:184:\ ++ cms_EnvelopedData_Decryption_init_bio ++CMS_F_CMS_ENVELOPEDDATA_ENCRYPTION_INIT_BIO:185:\ ++ cms_EnvelopedData_Encryption_init_bio ++CMS_F_CMS_ENVELOPEDDATA_FINAL:186:cms_EnvelopedData_final + CMS_F_CMS_ENVELOPEDDATA_INIT_BIO:125:cms_EnvelopedData_init_bio + CMS_F_CMS_ENVELOPED_DATA_INIT:126:cms_enveloped_data_init + CMS_F_CMS_ENV_ASN1_CTRL:171:cms_env_asn1_ctrl +@@ -1180,7 +1187,7 @@ + SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE:601:\ + ossl_statem_server_post_process_message + SSL_F_OSSL_STATEM_SERVER_POST_WORK:602:ossl_statem_server_post_work +-SSL_F_OSSL_STATEM_SERVER_PRE_WORK:640: ++SSL_F_OSSL_STATEM_SERVER_PRE_WORK:640:ossl_statem_server_pre_work + SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE:603:ossl_statem_server_process_message + SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION:418:ossl_statem_server_read_transition + SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION:604:\ +@@ -1395,6 +1402,7 @@ + SSL_F_TLS_CONSTRUCT_CKE_DHE:404:tls_construct_cke_dhe + SSL_F_TLS_CONSTRUCT_CKE_ECDHE:405:tls_construct_cke_ecdhe + SSL_F_TLS_CONSTRUCT_CKE_GOST:406:tls_construct_cke_gost ++SSL_F_TLS_CONSTRUCT_CKE_GOST18:639:tls_construct_cke_gost18 + SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE:407:tls_construct_cke_psk_preamble + SSL_F_TLS_CONSTRUCT_CKE_RSA:409:tls_construct_cke_rsa + SSL_F_TLS_CONSTRUCT_CKE_SRP:410:tls_construct_cke_srp +@@ -1526,6 +1534,7 @@ + SSL_F_TLS_PROCESS_CKE_DHE:411:tls_process_cke_dhe + SSL_F_TLS_PROCESS_CKE_ECDHE:412:tls_process_cke_ecdhe + SSL_F_TLS_PROCESS_CKE_GOST:413:tls_process_cke_gost ++SSL_F_TLS_PROCESS_CKE_GOST18:641:tls_process_cke_gost18 + SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE:414:tls_process_cke_psk_preamble + SSL_F_TLS_PROCESS_CKE_RSA:415:tls_process_cke_rsa + SSL_F_TLS_PROCESS_CKE_SRP:416:tls_process_cke_srp +@@ -1648,6 +1657,7 @@ + X509V3_F_I2S_ASN1_ENUMERATED:121:i2s_ASN1_ENUMERATED + X509V3_F_I2S_ASN1_IA5STRING:149:i2s_ASN1_IA5STRING + X509V3_F_I2S_ASN1_INTEGER:120:i2s_ASN1_INTEGER ++X509V3_F_I2S_ASN1_UTF8STRING:173:i2s_ASN1_UTF8STRING + X509V3_F_I2V_AUTHORITY_INFO_ACCESS:138:i2v_AUTHORITY_INFO_ACCESS + X509V3_F_LEVEL_ADD_NODE:168:level_add_node + X509V3_F_NOTICE_SECTION:132:notice_section +@@ -1662,6 +1672,7 @@ + X509V3_F_S2I_ASN1_IA5STRING:100:s2i_ASN1_IA5STRING + X509V3_F_S2I_ASN1_INTEGER:108:s2i_ASN1_INTEGER + X509V3_F_S2I_ASN1_OCTET_STRING:112:s2i_ASN1_OCTET_STRING ++X509V3_F_S2I_ASN1_UTF8STRING:174:s2i_ASN1_UTF8STRING + X509V3_F_S2I_SKEY_ID:115:s2i_skey_id + X509V3_F_SET_DIST_POINT_NAME:158:set_dist_point_name + X509V3_F_SXNET_ADD_ID_ASC:125:SXNET_add_id_asc +Index: crypto/asn1/p8_pkey.c +=================================================================== +--- crypto/asn1/p8_pkey.c (revision 14523) ++++ crypto/asn1/p8_pkey.c (working copy) +@@ -78,3 +78,18 @@ + return 1; + return 0; + } ++ ++int PKCS8_pkey_add1_attr_by_OBJ(PKCS8_PRIV_KEY_INFO *p8, const ASN1_OBJECT *obj, int type, ++ const unsigned char *bytes, int len) ++{ ++ if (X509at_add1_attr_by_OBJ(&p8->attributes, obj, type, bytes, len) != NULL) ++ return 1; ++ return 0; ++} ++ ++int PKCS8_pkey_add1_attr(PKCS8_PRIV_KEY_INFO *p8, X509_ATTRIBUTE *attr) ++{ ++ if (X509at_add1_attr(&p8->attributes, attr) != NULL) ++ return 1; ++ return 0; ++} +Index: include/openssl/sslerr.h +=================================================================== +--- include/openssl/sslerr.h (revision 14523) ++++ include/openssl/sslerr.h (working copy) +@@ -11,9 +11,7 @@ + #ifndef HEADER_SSLERR_H + # define HEADER_SSLERR_H + +-# ifndef HEADER_SYMHACKS_H +-# include +-# endif ++# include + + # ifdef __cplusplus + extern "C" +@@ -296,6 +294,7 @@ + # define SSL_F_TLS_CONSTRUCT_CKE_DHE 404 + # define SSL_F_TLS_CONSTRUCT_CKE_ECDHE 405 + # define SSL_F_TLS_CONSTRUCT_CKE_GOST 406 ++# define SSL_F_TLS_CONSTRUCT_CKE_GOST18 639 + # define SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE 407 + # define SSL_F_TLS_CONSTRUCT_CKE_RSA 409 + # define SSL_F_TLS_CONSTRUCT_CKE_SRP 410 +@@ -420,6 +419,7 @@ + # define SSL_F_TLS_PROCESS_CKE_DHE 411 + # define SSL_F_TLS_PROCESS_CKE_ECDHE 412 + # define SSL_F_TLS_PROCESS_CKE_GOST 413 ++# define SSL_F_TLS_PROCESS_CKE_GOST18 641 + # define SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE 414 + # define SSL_F_TLS_PROCESS_CKE_RSA 415 + # define SSL_F_TLS_PROCESS_CKE_SRP 416 +Index: include/openssl/x509.h +=================================================================== +--- include/openssl/x509.h (revision 14523) ++++ include/openssl/x509.h (working copy) +@@ -1020,8 +1020,11 @@ + + const STACK_OF(X509_ATTRIBUTE) * + PKCS8_pkey_get0_attrs(const PKCS8_PRIV_KEY_INFO *p8); ++int PKCS8_pkey_add1_attr(PKCS8_PRIV_KEY_INFO *p8, X509_ATTRIBUTE *attr); + int PKCS8_pkey_add1_attr_by_NID(PKCS8_PRIV_KEY_INFO *p8, int nid, int type, + const unsigned char *bytes, int len); ++int PKCS8_pkey_add1_attr_by_OBJ(PKCS8_PRIV_KEY_INFO *p8, const ASN1_OBJECT *obj, ++ int type, const unsigned char *bytes, int len); + + int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj, + int ptype, void *pval, +Index: include/openssl/cms.h +=================================================================== +--- include/openssl/cms.h (revision 14523) ++++ include/openssl/cms.h (working copy) +@@ -73,6 +73,7 @@ + # define CMS_DEBUG_DECRYPT 0x20000 + # define CMS_KEY_PARAM 0x40000 + # define CMS_ASCIICRLF 0x80000 ++# define CMS_USE_ORIGINATOR_KEYID 0x100000 + + const ASN1_OBJECT *CMS_get0_type(const CMS_ContentInfo *cms); + +@@ -143,6 +144,7 @@ + BIO *dcont, BIO *out, unsigned int flags); + + int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert); ++int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert, X509 *peer); + int CMS_decrypt_set1_key(CMS_ContentInfo *cms, + unsigned char *key, size_t keylen, + const unsigned char *id, size_t idlen); +@@ -155,6 +157,8 @@ + CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher); + CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, + X509 *recip, unsigned int flags); ++CMS_RecipientInfo *CMS_add1_recipient(CMS_ContentInfo *cms, X509 *recip, ++ EVP_PKEY *originatorPrivKey, X509 * originator, unsigned int flags); + int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey); + int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert); + int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri, +@@ -319,6 +323,7 @@ + int CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek, + X509 *cert); + int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk); ++int CMS_RecipientInfo_kari_set0_pkey_and_peer(CMS_RecipientInfo *ri, EVP_PKEY *pk, X509 *peer); + EVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri); + int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms, + CMS_RecipientInfo *ri, +Index: include/openssl/tls1.h +=================================================================== +--- include/openssl/tls1.h (revision 14523) ++++ include/openssl/tls1.h (working copy) +@@ -613,6 +613,12 @@ + # define TLS1_3_CK_AES_128_CCM_SHA256 0x03001304 + # define TLS1_3_CK_AES_128_CCM_8_SHA256 0x03001305 + ++/* https://tools.ietf.org/html/draft-smyshlyaev-tls13-gost-suites */ ++# define TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_L 0x0300C103 ++# define TLS_GOSTR341112_256_WITH_MAGMA_MGM_L 0x0300C104 ++# define TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_S 0x0300C105 ++# define TLS_GOSTR341112_256_WITH_MAGMA_MGM_S 0x0300C106 ++ + /* Aria ciphersuites from RFC6209 */ + # define TLS1_CK_RSA_WITH_ARIA_128_GCM_SHA256 0x0300C050 + # define TLS1_CK_RSA_WITH_ARIA_256_GCM_SHA384 0x0300C051 +@@ -1135,8 +1141,10 @@ + # define TLS_CT_RSA_FIXED_ECDH 65 + # define TLS_CT_ECDSA_FIXED_ECDH 66 + # define TLS_CT_GOST01_SIGN 22 +-# define TLS_CT_GOST12_SIGN 238 +-# define TLS_CT_GOST12_512_SIGN 239 ++# define TLS_CT_GOST12_SIGN 67 ++# define TLS_CT_GOST12_512_SIGN 68 ++# define TLS_CT_GOST12_SIGN_LEGACY 238 ++# define TLS_CT_GOST12_512_SIGN_LEGACY 239 + + /* + * when correcting this number, correct also SSL3_CT_NUMBER in ssl3.h (see +Index: include/openssl/ssl.h +=================================================================== +--- include/openssl/ssl.h (revision 14523) ++++ include/openssl/ssl.h (working copy) +@@ -81,6 +81,7 @@ + # define SSL_TXT_kECDHEPSK "kECDHEPSK" + # define SSL_TXT_kDHEPSK "kDHEPSK" + # define SSL_TXT_kGOST "kGOST" ++# define SSL_TXT_kGOST18 "kGOST18" + # define SSL_TXT_kSRP "kSRP" + + # define SSL_TXT_aRSA "aRSA" +@@ -908,6 +909,8 @@ + + # define SSL_MAC_FLAG_READ_MAC_STREAM 1 + # define SSL_MAC_FLAG_WRITE_MAC_STREAM 2 ++# define SSL_MAC_FLAG_READ_MAC_TLSTREE 4 ++# define SSL_MAC_FLAG_WRITE_MAC_TLSTREE 8 + + /* + * A callback for logging out TLS key material. This callback should log out +Index: include/openssl/obj_mac.h +=================================================================== +--- include/openssl/obj_mac.h (revision 14523) ++++ include/openssl/obj_mac.h (working copy) +@@ -4162,6 +4162,26 @@ + #define NID_id_GostR3410_2001_ParamSet_cc 854 + #define OBJ_id_GostR3410_2001_ParamSet_cc OBJ_cryptocom,1L,8L,1L + ++#define SN_id_tc26_modules "id-tc26-modules" ++#define LN_id_tc26_modules "GOST TC26 ASN.1 modules" ++#define NID_id_tc26_modules 1203 ++#define OBJ_id_tc26_modules OBJ_id_tc26,0L ++ ++#define SN_id_tc26_cms "id-tc26-cms" ++#define LN_id_tc26_cms "GOST TC26 SMS" ++#define NID_id_tc26_cms 1204 ++#define OBJ_id_tc26_cms OBJ_id_tc26_modules,6L ++ ++#define SN_id_tc26_cms_attrs "id-tc26-cms-attrs" ++#define LN_id_tc26_cms_attrs "GOST TC26 SMS attributes" ++#define NID_id_tc26_cms_attrs 1205 ++#define OBJ_id_tc26_cms_attrs OBJ_id_tc26_cms,1L ++ ++#define SN_id_tc26_mac_attr "id-tc26-mac-attr" ++#define LN_id_tc26_mac_attr "GOST TC26 SMS content-mac attribute" ++#define NID_id_tc26_mac_attr 1206 ++#define OBJ_id_tc26_mac_attr OBJ_id_tc26_cms_attrs,1L ++ + #define SN_id_tc26_algorithms "id-tc26-algorithms" + #define NID_id_tc26_algorithms 977 + #define OBJ_id_tc26_algorithms OBJ_id_tc26,1L +@@ -4230,25 +4250,25 @@ + #define NID_id_tc26_cipher_gostr3412_2015_magma 1173 + #define OBJ_id_tc26_cipher_gostr3412_2015_magma OBJ_id_tc26_cipher,1L + +-#define SN_id_tc26_cipher_gostr3412_2015_magma_ctracpkm "id-tc26-cipher-gostr3412-2015-magma-ctracpkm" +-#define NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm 1174 +-#define OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm OBJ_id_tc26_cipher_gostr3412_2015_magma,1L ++#define SN_magma_ctr_acpkm "magma-ctr-acpkm" ++#define NID_magma_ctr_acpkm 1174 ++#define OBJ_magma_ctr_acpkm OBJ_id_tc26_cipher_gostr3412_2015_magma,1L + +-#define SN_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac "id-tc26-cipher-gostr3412-2015-magma-ctracpkm-omac" +-#define NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac 1175 +-#define OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac OBJ_id_tc26_cipher_gostr3412_2015_magma,2L ++#define SN_magma_ctr_acpkm_omac "magma-ctr-acpkm-omac" ++#define NID_magma_ctr_acpkm_omac 1175 ++#define OBJ_magma_ctr_acpkm_omac OBJ_id_tc26_cipher_gostr3412_2015_magma,2L + + #define SN_id_tc26_cipher_gostr3412_2015_kuznyechik "id-tc26-cipher-gostr3412-2015-kuznyechik" + #define NID_id_tc26_cipher_gostr3412_2015_kuznyechik 1176 + #define OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik OBJ_id_tc26_cipher,2L + +-#define SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm" +-#define NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm 1177 +-#define OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik,1L ++#define SN_kuznyechik_ctr_acpkm "kuznyechik-ctr-acpkm" ++#define NID_kuznyechik_ctr_acpkm 1177 ++#define OBJ_kuznyechik_ctr_acpkm OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik,1L + +-#define SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm-omac" +-#define NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac 1178 +-#define OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik,2L ++#define SN_kuznyechik_ctr_acpkm_omac "kuznyechik-ctr-acpkm-omac" ++#define NID_kuznyechik_ctr_acpkm_omac 1178 ++#define OBJ_kuznyechik_ctr_acpkm_omac OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik,2L + + #define SN_id_tc26_agreement "id-tc26-agreement" + #define NID_id_tc26_agreement 991 +@@ -4270,17 +4290,17 @@ + #define NID_id_tc26_wrap_gostr3412_2015_magma 1180 + #define OBJ_id_tc26_wrap_gostr3412_2015_magma OBJ_id_tc26_wrap,1L + +-#define SN_id_tc26_wrap_gostr3412_2015_magma_kexp15 "id-tc26-wrap-gostr3412-2015-magma-kexp15" +-#define NID_id_tc26_wrap_gostr3412_2015_magma_kexp15 1181 +-#define OBJ_id_tc26_wrap_gostr3412_2015_magma_kexp15 OBJ_id_tc26_wrap_gostr3412_2015_magma,1L ++#define SN_magma_kexp15 "magma-kexp15" ++#define NID_magma_kexp15 1181 ++#define OBJ_magma_kexp15 OBJ_id_tc26_wrap_gostr3412_2015_magma,1L + + #define SN_id_tc26_wrap_gostr3412_2015_kuznyechik "id-tc26-wrap-gostr3412-2015-kuznyechik" + #define NID_id_tc26_wrap_gostr3412_2015_kuznyechik 1182 + #define OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik OBJ_id_tc26_wrap,2L + +-#define SN_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 "id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15" +-#define NID_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 1183 +-#define OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik,1L ++#define SN_kuznyechik_kexp15 "kuznyechik-kexp15" ++#define NID_kuznyechik_kexp15 1183 ++#define OBJ_kuznyechik_kexp15 OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik,1L + + #define SN_id_tc26_constants "id-tc26-constants" + #define NID_id_tc26_constants 994 +@@ -4370,6 +4390,11 @@ + #define NID_SNILS 1006 + #define OBJ_SNILS OBJ_member_body,643L,100L,3L + ++#define SN_OGRNIP "OGRNIP" ++#define LN_OGRNIP "OGRNIP" ++#define NID_OGRNIP 1195 ++#define OBJ_OGRNIP OBJ_member_body,643L,100L,5L ++ + #define SN_subjectSignTool "subjectSignTool" + #define LN_subjectSignTool "Signing Tool of Subject" + #define NID_subjectSignTool 1007 +@@ -4380,24 +4405,62 @@ + #define NID_issuerSignTool 1008 + #define OBJ_issuerSignTool OBJ_member_body,643L,100L,112L + +-#define SN_grasshopper_ecb "grasshopper-ecb" +-#define NID_grasshopper_ecb 1012 ++#define SN_classSignTool "classSignTool" ++#define LN_classSignTool "Class of Signing Tool" ++#define NID_classSignTool 1196 ++#define OBJ_classSignTool OBJ_member_body,643L,100L,113L + +-#define SN_grasshopper_ctr "grasshopper-ctr" +-#define NID_grasshopper_ctr 1013 ++#define SN_classSignToolKC1 "classSignToolKC1" ++#define LN_classSignToolKC1 "Class of Signing Tool KC1" ++#define NID_classSignToolKC1 1197 ++#define OBJ_classSignToolKC1 OBJ_member_body,643L,100L,113L,1L + +-#define SN_grasshopper_ofb "grasshopper-ofb" +-#define NID_grasshopper_ofb 1014 ++#define SN_classSignToolKC2 "classSignToolKC2" ++#define LN_classSignToolKC2 "Class of Signing Tool KC2" ++#define NID_classSignToolKC2 1198 ++#define OBJ_classSignToolKC2 OBJ_member_body,643L,100L,113L,2L + +-#define SN_grasshopper_cbc "grasshopper-cbc" +-#define NID_grasshopper_cbc 1015 ++#define SN_classSignToolKC3 "classSignToolKC3" ++#define LN_classSignToolKC3 "Class of Signing Tool KC3" ++#define NID_classSignToolKC3 1199 ++#define OBJ_classSignToolKC3 OBJ_member_body,643L,100L,113L,3L + +-#define SN_grasshopper_cfb "grasshopper-cfb" +-#define NID_grasshopper_cfb 1016 ++#define SN_classSignToolKB1 "classSignToolKB1" ++#define LN_classSignToolKB1 "Class of Signing Tool KB1" ++#define NID_classSignToolKB1 1200 ++#define OBJ_classSignToolKB1 OBJ_member_body,643L,100L,113L,4L + +-#define SN_grasshopper_mac "grasshopper-mac" +-#define NID_grasshopper_mac 1017 ++#define SN_classSignToolKB2 "classSignToolKB2" ++#define LN_classSignToolKB2 "Class of Signing Tool KB2" ++#define NID_classSignToolKB2 1201 ++#define OBJ_classSignToolKB2 OBJ_member_body,643L,100L,113L,5L + ++#define SN_classSignToolKA1 "classSignToolKA1" ++#define LN_classSignToolKA1 "Class of Signing Tool KA1" ++#define NID_classSignToolKA1 1202 ++#define OBJ_classSignToolKA1 OBJ_member_body,643L,100L,113L,6L ++ ++#define SN_kuznyechik_ecb "kuznyechik-ecb" ++#define NID_kuznyechik_ecb 1012 ++ ++#define SN_kuznyechik_ctr "kuznyechik-ctr" ++#define NID_kuznyechik_ctr 1013 ++ ++#define SN_kuznyechik_ofb "kuznyechik-ofb" ++#define NID_kuznyechik_ofb 1014 ++ ++#define SN_kuznyechik_cbc "kuznyechik-cbc" ++#define NID_kuznyechik_cbc 1015 ++ ++#define SN_kuznyechik_cfb "kuznyechik-cfb" ++#define NID_kuznyechik_cfb 1016 ++ ++#define SN_kuznyechik_mac "kuznyechik-mac" ++#define NID_kuznyechik_mac 1017 ++ ++#define SN_kuznyechik_mgm "kuznyechik-mgm" ++#define NID_kuznyechik_mgm 1207 ++ + #define SN_magma_ecb "magma-ecb" + #define NID_magma_ecb 1187 + +@@ -4416,6 +4479,9 @@ + #define SN_magma_mac "magma-mac" + #define NID_magma_mac 1192 + ++#define SN_magma_mgm "magma-mgm" ++#define NID_magma_mgm 1208 ++ + #define SN_camellia_128_cbc "CAMELLIA-128-CBC" + #define LN_camellia_128_cbc "camellia-128-cbc" + #define NID_camellia_128_cbc 751 +@@ -5196,3 +5262,49 @@ + #define LN_uacurve9 "DSTU curve 9" + #define NID_uacurve9 1169 + #define OBJ_uacurve9 OBJ_dstu4145le,2L,9L ++ ++#ifndef OPENSSL_NO_DEPRECATED_3_0 ++ ++#define SN_id_tc26_cipher_gostr3412_2015_magma_ctracpkm SN_magma_ctr_acpkm ++#define NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm NID_magma_ctr_acpkm ++#define OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm OBJ_magma_ctr_acpkm ++ ++#define SN_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac SN_magma_ctr_acpkm_omac ++#define NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac NID_magma_ctr_acpkm_omac ++#define OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac OBJ_magma_ctr_acpkm_omac ++ ++#define SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm SN_kuznyechik_ctr_acpkm ++#define NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm NID_kuznyechik_ctr_acpkm ++#define OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm OBJ_kuznyechik_ctr_acpkm ++ ++#define SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac SN_kuznyechik_ctr_acpkm_omac ++#define NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac NID_kuznyechik_ctr_acpkm_omac ++#define OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac OBJ_kuznyechik_ctr_acpkm_omac ++ ++#define SN_id_tc26_wrap_gostr3412_2015_magma_kexp15 SN_magma_kexp15 ++#define NID_id_tc26_wrap_gostr3412_2015_magma_kexp15 NID_magma_kexp15 ++#define OBJ_id_tc26_wrap_gostr3412_2015_magma_kexp15 OBJ_magma_kexp15 ++ ++#define SN_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 SN_kuznyechik_kexp15 ++#define NID_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 NID_kuznyechik_kexp15 ++#define OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 OBJ_kuznyechik_kexp15 ++ ++#define SN_grasshopper_ecb SN_kuznyechik_ecb ++#define NID_grasshopper_ecb NID_kuznyechik_ecb ++ ++#define SN_grasshopper_ctr SN_kuznyechik_ctr ++#define NID_grasshopper_ctr NID_kuznyechik_ctr ++ ++#define SN_grasshopper_ofb SN_kuznyechik_ofb ++#define NID_grasshopper_ofb NID_kuznyechik_ofb ++ ++#define SN_grasshopper_cbc SN_kuznyechik_cbc ++#define NID_grasshopper_cbc NID_kuznyechik_cbc ++ ++#define SN_grasshopper_cfb SN_kuznyechik_cfb ++#define NID_grasshopper_cfb NID_kuznyechik_cfb ++ ++#define SN_grasshopper_mac SN_kuznyechik_mac ++#define NID_grasshopper_mac NID_kuznyechik_mac ++ ++#endif +Index: include/openssl/evp.h +=================================================================== +--- include/openssl/evp.h (revision 14523) ++++ include/openssl/evp.h (working copy) +@@ -20,7 +20,10 @@ + # define EVP_MAX_KEY_LENGTH 64 + # define EVP_MAX_IV_LENGTH 16 + # define EVP_MAX_BLOCK_LENGTH 32 ++# define EVP_MAX_AEAD_TAG_LEN 16/* longest known AEAD tag size */ + ++#define EVP_MAX_MAC_SIZE EVP_MAX_AEAD_TAG_LEN ++ + # define PKCS5_SALT_LEN 8 + /* Default PKCS#5 iteration count */ + # define PKCS5_DEFAULT_ITER 2048 +@@ -139,6 +142,7 @@ + # define EVP_MD_CTRL_DIGALGID 0x1 + # define EVP_MD_CTRL_MICALG 0x2 + # define EVP_MD_CTRL_XOF_LEN 0x3 ++# define EVP_MD_CTRL_TLSTREE 0x4 + + /* Minimum Algorithm specific ctrl value */ + +@@ -277,8 +281,9 @@ + # define EVP_CIPH_FLAG_AEAD_CIPHER 0x200000 + # define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0x400000 + /* Cipher can handle pipeline operations */ +-# define EVP_CIPH_FLAG_PIPELINE 0X800000 +- ++# define EVP_CIPH_FLAG_PIPELINE 0x800000 ++# define EVP_CIPH_FLAG_CIPHER_WITH_MAC 0x1000000 ++# define EVP_CIPH_FLAG_GET_WRAP_CIPHER 0X4000000 + /* + * Cipher context flag to indicate we can handle wrap mode: if allowed in + * older applications it could overflow buffers. +@@ -352,7 +357,21 @@ + # define EVP_CTRL_SET_PIPELINE_INPUT_LENS 0x24 + + # define EVP_CTRL_GET_IVLEN 0x25 ++/* Indicates TLSTREE key diversification during TLS processing */ ++# define EVP_CTRL_TLSTREE 0x26 + ++#define EVP_CTRL_AEAD_MAX_TAG_LEN 0x27 ++# define EVP_CTRL_GET_WRAP_CIPHER 0X28 ++ ++# define EVP_CTRL_GET_MAC_LEN EVP_CTRL_AEAD_MAX_TAG_LEN ++# define EVP_CTRL_GET_MAC EVP_CTRL_AEAD_GET_TAG ++# define EVP_CTRL_SET_EXPECTED_MAC EVP_CTRL_AEAD_SET_TAG ++/* GOST CMS requires processing unprotected attributes in some cases*/ ++# define EVP_CTRL_PROCESS_UNPROTECTED 0x29 ++/* Set GOST TLSTREE params */ ++# define EVP_CTRL_SET_TLSTREE_PARAMS 0x2A ++ ++ + /* Padding modes */ + #define EVP_PADDING_PKCS7 1 + #define EVP_PADDING_ISO7816_4 2 +@@ -390,6 +409,10 @@ + /* Length of CCM8 tag for TLS */ + # define EVP_CCM8_TLS_TAG_LEN 8 + ++/* GOST TLS 1.3 tag lengths */ ++# define EVP_MAGMA_TLS_TAG_LEN 8 ++# define EVP_KUZNYECHIK_TLS_TAG_LEN 16 ++ + /* Length of tag for TLS */ + # define EVP_CHACHAPOLY_TLS_TAG_LEN 16 + +@@ -1142,6 +1165,10 @@ + # define ASN1_PKEY_CTRL_SET1_TLS_ENCPT 0x9 + # define ASN1_PKEY_CTRL_GET1_TLS_ENCPT 0xa + ++// This control use for decryption ++// when algorithm support multiple ri types ++# define ASN1_PKEY_CTRL_CMS_IS_RI_TYPE_SUPPORTED 0xb ++ + int EVP_PKEY_asn1_get_count(void); + const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx); + const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type); +Index: include/openssl/cmserr.h +=================================================================== +--- include/openssl/cmserr.h (revision 14523) ++++ include/openssl/cmserr.h (working copy) +@@ -11,9 +11,7 @@ + #ifndef HEADER_CMSERR_H + # define HEADER_CMSERR_H + +-# ifndef HEADER_SYMHACKS_H +-# include +-# endif ++# include + + # include + +@@ -32,6 +30,7 @@ + # define CMS_F_CMS_ADD0_RECIPIENT_KEY 100 + # define CMS_F_CMS_ADD0_RECIPIENT_PASSWORD 165 + # define CMS_F_CMS_ADD1_RECEIPTREQUEST 158 ++# define CMS_F_CMS_ADD1_RECIPIENT 181 + # define CMS_F_CMS_ADD1_RECIPIENT_CERT 101 + # define CMS_F_CMS_ADD1_SIGNER 102 + # define CMS_F_CMS_ADD1_SIGNINGTIME 103 +@@ -47,6 +46,7 @@ + # define CMS_F_CMS_DECRYPT_SET1_KEY 113 + # define CMS_F_CMS_DECRYPT_SET1_PASSWORD 166 + # define CMS_F_CMS_DECRYPT_SET1_PKEY 114 ++# define CMS_F_CMS_DECRYPT_SET1_PKEY_AND_PEER 182 + # define CMS_F_CMS_DIGESTALGORITHM_FIND_CTX 115 + # define CMS_F_CMS_DIGESTALGORITHM_INIT_BIO 116 + # define CMS_F_CMS_DIGESTEDDATA_DO_FINAL 117 +@@ -59,6 +59,9 @@ + # define CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT 122 + # define CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY 123 + # define CMS_F_CMS_ENVELOPEDDATA_CREATE 124 ++# define CMS_F_CMS_ENVELOPEDDATA_DECRYPTION_INIT_BIO 184 ++# define CMS_F_CMS_ENVELOPEDDATA_ENCRYPTION_INIT_BIO 185 ++# define CMS_F_CMS_ENVELOPEDDATA_FINAL 186 + # define CMS_F_CMS_ENVELOPEDDATA_INIT_BIO 125 + # define CMS_F_CMS_ENVELOPED_DATA_INIT 126 + # define CMS_F_CMS_ENV_ASN1_CTRL 171 +Index: include/openssl/x509v3err.h +=================================================================== +--- include/openssl/x509v3err.h (revision 14523) ++++ include/openssl/x509v3err.h (working copy) +@@ -37,6 +37,7 @@ + # define X509V3_F_I2S_ASN1_ENUMERATED 121 + # define X509V3_F_I2S_ASN1_IA5STRING 149 + # define X509V3_F_I2S_ASN1_INTEGER 120 ++# define X509V3_F_I2S_ASN1_UTF8STRING 173 + # define X509V3_F_I2V_AUTHORITY_INFO_ACCESS 138 + # define X509V3_F_LEVEL_ADD_NODE 168 + # define X509V3_F_NOTICE_SECTION 132 +@@ -51,6 +52,7 @@ + # define X509V3_F_S2I_ASN1_IA5STRING 100 + # define X509V3_F_S2I_ASN1_INTEGER 108 + # define X509V3_F_S2I_ASN1_OCTET_STRING 112 ++# define X509V3_F_S2I_ASN1_UTF8STRING 174 + # define X509V3_F_S2I_SKEY_ID 115 + # define X509V3_F_SET_DIST_POINT_NAME 158 + # define X509V3_F_SXNET_ADD_ID_ASC 125 +Index: Configurations/unix-Makefile.tmpl +=================================================================== +--- Configurations/unix-Makefile.tmpl (revision 14523) ++++ Configurations/unix-Makefile.tmpl (working copy) +@@ -888,6 +888,7 @@ + crypto/objects/obj_mac.num \ + crypto/objects/obj_xref.txt \ + > crypto/objects/obj_xref.h ) ++ ( cd $(SRCDIR); cat crypto/objects/obj_compat.h >> include/openssl/obj_mac.h ) + + generate_crypto_conf: + ( cd $(SRCDIR); $(PERL) crypto/conf/keysets.pl \ +Index: ssl/t1_trce.c +=================================================================== +--- ssl/t1_trce.c (revision 14523) ++++ ssl/t1_trce.c (working copy) +@@ -443,6 +443,9 @@ + {0xFEFF, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA"}, + {0xFF85, "GOST2012-GOST8912-GOST8912"}, + {0xFF87, "GOST2012-NULL-GOST12"}, ++ {0xC100, "GOST2012-KUZNYECHIK-KUZNYECHIKOMAC"}, ++ {0xC101, "GOST2012-MAGMA-MAGMAOMAC"}, ++ {0xC102, "GOST2012-GOST8912-IANA"}, + }; + + /* Compression methods */ +@@ -522,6 +525,13 @@ + {28, "brainpoolP512r1"}, + {29, "ecdh_x25519"}, + {30, "ecdh_x448"}, ++ {34, "GC256A"}, ++ {35, "GC256B"}, ++ {36, "GC256C"}, ++ {37, "GC256D"}, ++ {38, "GC512A"}, ++ {39, "GC512B"}, ++ {40, "GC512C"}, + {256, "ffdhe2048"}, + {257, "ffdhe3072"}, + {258, "ffdhe4096"}, +@@ -571,6 +581,8 @@ + {TLSEXT_SIGALG_dsa_sha1, "dsa_sha1"}, + {TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256, "gost2012_256"}, + {TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512, "gost2012_512"}, ++ {TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256_legacy, "gost2012_256"}, ++ {TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512_legacy, "gost2012_512"}, + {TLSEXT_SIGALG_gostr34102001_gostr3411, "gost2001_gost94"}, + }; + +@@ -584,7 +596,9 @@ + {20, "fortezza_dms"}, + {64, "ecdsa_sign"}, + {65, "rsa_fixed_ecdh"}, +- {66, "ecdsa_fixed_ecdh"} ++ {66, "ecdsa_fixed_ecdh"}, ++ {67, "gost_sign256"}, ++ {68, "gost_sign512"}, + }; + + static const ssl_trace_tbl ssl_psk_kex_modes_tbl[] = { +@@ -1072,6 +1086,10 @@ + *pname = "GOST"; + return SSL_kGOST; + } ++ if (alg_k & SSL_kGOST18) { ++ *pname = "GOST18"; ++ return SSL_kGOST18; ++ } + *pname = "UNKNOWN"; + return 0; + } +@@ -1114,7 +1132,16 @@ + if (!ssl_print_hexbuf(bio, indent + 2, "ecdh_Yc", 1, &msg, &msglen)) + return 0; + break; +- ++#ifndef OPENSSL_NO_GOST ++ case SSL_kGOST: ++ ssl_print_hex(bio, indent + 2, "GOST-wrapped PreMasterSecret", msg, msglen); ++ break; ++ case SSL_kGOST18: ++ ssl_print_hex(bio, indent + 2, ++ "GOST-wrapped PreMasterSecret", msg, msglen); ++ return 0; ++ break; ++#endif + } + + return !msglen; +Index: ssl/ssl_err.c +=================================================================== +--- ssl/ssl_err.c (revision 14523) ++++ ssl/ssl_err.c (working copy) +@@ -1,6 +1,6 @@ + /* + * Generated by util/mkerr.pl DO NOT EDIT +- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy +@@ -112,6 +112,8 @@ + "ossl_statem_server_post_process_message"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_POST_WORK, 0), + "ossl_statem_server_post_work"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_PRE_WORK, 0), ++ "ossl_statem_server_pre_work"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE, 0), + "ossl_statem_server_process_message"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION, 0), +@@ -437,6 +439,8 @@ + "tls_construct_cke_ecdhe"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CKE_GOST, 0), + "tls_construct_cke_gost"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CKE_GOST18, 0), ++ "tls_construct_cke_gost18"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, 0), + "tls_construct_cke_psk_preamble"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CKE_RSA, 0), +@@ -664,6 +668,8 @@ + "tls_process_cke_ecdhe"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CKE_GOST, 0), + "tls_process_cke_gost"}, ++ {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CKE_GOST18, 0), ++ "tls_process_cke_gost18"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, 0), + "tls_process_cke_psk_preamble"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CKE_RSA, 0), +Index: ssl/t1_lib.c +=================================================================== +--- ssl/t1_lib.c (revision 14523) ++++ ssl/t1_lib.c (working copy) +@@ -169,6 +169,18 @@ + {NID_brainpoolP512r1, 256, TLS_CURVE_PRIME}, /* brainpool512r1 (28) */ + {EVP_PKEY_X25519, 128, TLS_CURVE_CUSTOM}, /* X25519 (29) */ + {EVP_PKEY_X448, 224, TLS_CURVE_CUSTOM}, /* X448 (30) */ ++#ifndef OPENSSL_NO_GOST ++ {NID_undef, 0, TLS_CURVE_CUSTOM}, /* 31 */ ++ {NID_undef, 0, TLS_CURVE_CUSTOM}, /* 32 */ ++ {NID_undef, 0, TLS_CURVE_CUSTOM}, /* 33 */ ++ {NID_id_tc26_gost_3410_2012_256_paramSetA, 128, TLS_CURVE_GOST}, ++ {NID_id_tc26_gost_3410_2012_256_paramSetB, 128, TLS_CURVE_GOST}, ++ {NID_id_tc26_gost_3410_2012_256_paramSetC, 128, TLS_CURVE_GOST}, ++ {NID_id_tc26_gost_3410_2012_256_paramSetD, 128, TLS_CURVE_GOST}, ++ {NID_id_tc26_gost_3410_2012_512_paramSetA, 256, TLS_CURVE_GOST}, ++ {NID_id_tc26_gost_3410_2012_512_paramSetB, 256, TLS_CURVE_GOST}, ++ {NID_id_tc26_gost_3410_2012_512_paramSetC, 256, TLS_CURVE_GOST}, ++#endif + }; + + static const unsigned char ecformats_default[] = { +@@ -184,6 +196,15 @@ + 30, /* X448 (30) */ + 25, /* secp521r1 (25) */ + 24, /* secp384r1 (24) */ ++#ifndef OPENSSL_NO_GOST ++ 34, ++ 35, ++ 36, ++ 37, ++ 38, ++ 39, ++ 40, ++#endif + }; + + static const uint16_t suiteb_curves[] = { +@@ -196,6 +217,8 @@ + /* ECC curves from RFC 4492 and RFC 7027 */ + if (group_id < 1 || group_id > OSSL_NELEM(nid_list)) + return NULL; ++ if (nid_list[group_id - 1].nid == NID_undef) ++ return NULL; + return &nid_list[group_id - 1]; + } + +@@ -380,6 +403,33 @@ + int nid_arr[MAX_CURVELIST]; + } nid_cb_st; + ++#ifndef OPENSSL_NO_GOST ++typedef struct { ++ const char *name; /* Name of GOST curve */ ++ int nid; /* Curve NID */ ++} EC_GOST_NAME; ++ ++static EC_GOST_NAME gost_curves[] = { ++ {"GC256A", NID_id_tc26_gost_3410_2012_256_paramSetA}, ++ {"GC256B", NID_id_tc26_gost_3410_2012_256_paramSetB}, ++ {"GC256C", NID_id_tc26_gost_3410_2012_256_paramSetC}, ++ {"GC256D", NID_id_tc26_gost_3410_2012_256_paramSetD}, ++ {"GC512A", NID_id_tc26_gost_3410_2012_512_paramSetA}, ++ {"GC512B", NID_id_tc26_gost_3410_2012_512_paramSetB}, ++ {"GC512C", NID_id_tc26_gost_3410_2012_512_paramSetC}, ++}; ++ ++int GOST_curve2nid(const char *name) ++{ ++ size_t i; ++ for (i = 0; i < OSSL_NELEM(gost_curves); i++) { ++ if (strcmp(gost_curves[i].name, name) == 0) ++ return gost_curves[i].nid; ++ } ++ return NID_undef; ++} ++#endif ++ + static int nid_cb(const char *elem, int len, void *arg) + { + nid_cb_st *narg = arg; +@@ -395,7 +445,12 @@ + memcpy(etmp, elem, len); + etmp[len] = 0; + nid = EC_curve_nist2nid(etmp); ++#ifndef OPENSSL_NO_GOST ++ /* FIXME beldmit */ + if (nid == NID_undef) ++ nid = GOST_curve2nid(etmp); ++#endif ++ if (nid == NID_undef) + nid = OBJ_sn2nid(etmp); + if (nid == NID_undef) + nid = OBJ_ln2nid(etmp); +@@ -670,8 +725,17 @@ + TLSEXT_SIGALG_dsa_sha512, + #endif + #ifndef OPENSSL_NO_GOST ++ TLSEXT_SIGALG_gostr34102012_256a, ++ TLSEXT_SIGALG_gostr34102012_256b, ++ TLSEXT_SIGALG_gostr34102012_256c, ++ TLSEXT_SIGALG_gostr34102012_256d, ++ TLSEXT_SIGALG_gostr34102012_512a, ++ TLSEXT_SIGALG_gostr34102012_512b, ++ TLSEXT_SIGALG_gostr34102012_512c, + TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256, + TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512, ++ TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256_legacy, ++ TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512_legacy, + TLSEXT_SIGALG_gostr34102001_gostr3411, + #endif + }; +@@ -758,6 +822,34 @@ + NID_dsaWithSHA1, NID_undef}, + #endif + #ifndef OPENSSL_NO_GOST ++ {"gostr34102012_256a", TLSEXT_SIGALG_gostr34102012_256a, ++ NID_id_GostR3411_2012_256, SSL_MD_GOST12_256_IDX, ++ NID_id_GostR3410_2012_256, SSL_PKEY_GOST12_256, ++ NID_undef, NID_undef}, ++ {"gostr34102012_256b", TLSEXT_SIGALG_gostr34102012_256b, ++ NID_id_GostR3411_2012_256, SSL_MD_GOST12_256_IDX, ++ NID_id_GostR3410_2012_256, SSL_PKEY_GOST12_256, ++ NID_undef, NID_undef}, ++ {"gostr34102012_256c", TLSEXT_SIGALG_gostr34102012_256c, ++ NID_id_GostR3411_2012_256, SSL_MD_GOST12_256_IDX, ++ NID_id_GostR3410_2012_256, SSL_PKEY_GOST12_256, ++ NID_undef, NID_undef}, ++ {"gostr34102012_256d", TLSEXT_SIGALG_gostr34102012_256d, ++ NID_id_GostR3411_2012_256, SSL_MD_GOST12_256_IDX, ++ NID_id_GostR3410_2012_256, SSL_PKEY_GOST12_256, ++ NID_undef, NID_undef}, ++ {"gostr34102012_512a", TLSEXT_SIGALG_gostr34102012_512a, ++ NID_id_GostR3411_2012_512, SSL_MD_GOST12_512_IDX, ++ NID_id_GostR3410_2012_512, SSL_PKEY_GOST12_512, ++ NID_undef, NID_undef}, ++ {"gostr34102012_512b", TLSEXT_SIGALG_gostr34102012_512b, ++ NID_id_GostR3411_2012_512, SSL_MD_GOST12_512_IDX, ++ NID_id_GostR3410_2012_512, SSL_PKEY_GOST12_512, ++ NID_undef, NID_undef}, ++ {"gostr34102012_512c", TLSEXT_SIGALG_gostr34102012_512c, ++ NID_id_GostR3411_2012_512, SSL_MD_GOST12_512_IDX, ++ NID_id_GostR3410_2012_512, SSL_PKEY_GOST12_512, ++ NID_undef, NID_undef}, + {NULL, TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256, + NID_id_GostR3411_2012_256, SSL_MD_GOST12_256_IDX, + NID_id_GostR3410_2012_256, SSL_PKEY_GOST12_256, +@@ -766,6 +858,14 @@ + NID_id_GostR3411_2012_512, SSL_MD_GOST12_512_IDX, + NID_id_GostR3410_2012_512, SSL_PKEY_GOST12_512, + NID_undef, NID_undef}, ++ {NULL, TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256_legacy, ++ NID_id_GostR3411_2012_256, SSL_MD_GOST12_256_IDX, ++ NID_id_GostR3410_2012_256, SSL_PKEY_GOST12_256, ++ NID_undef, NID_undef}, ++ {NULL, TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512_legacy, ++ NID_id_GostR3411_2012_512, SSL_MD_GOST12_512_IDX, ++ NID_id_GostR3410_2012_512, SSL_PKEY_GOST12_512, ++ NID_undef, NID_undef}, + {NULL, TLSEXT_SIGALG_gostr34102001_gostr3411, + NID_id_GostR3411_94, SSL_MD_GOST94_IDX, + NID_id_GostR3410_2001, SSL_PKEY_GOST01, +@@ -886,6 +986,24 @@ + } + } + } ++ /* ++ * Here is another fallback: when broken implementations did not sent ++ * proper signature_algorithm extension, we try to use this function. ++ * ++ * As both SSL_PKEY_GOST12_512 and SSL_PKEY_GOST12_256 indices can be used ++ * with new (aGOST12-only) ciphersuites, we should find out which one is available really. ++ * */ ++ else if (idx == SSL_PKEY_GOST12_256) { ++ int real_idx; ++ ++ for (real_idx = SSL_PKEY_GOST12_512; real_idx >= SSL_PKEY_GOST12_256; ++ real_idx--) { ++ if (s->cert->pkeys[real_idx].privatekey != NULL) { ++ idx = real_idx; ++ break; ++ } ++ } ++ } + } else { + idx = s->cert->key - s->cert->pkeys; + } +@@ -1612,10 +1730,8 @@ + if (ssl_cert_is_disabled(lu->sig_idx)) + return 0; + +- if (lu->sig == NID_id_GostR3410_2012_256 +- || lu->sig == NID_id_GostR3410_2012_512 +- || lu->sig == NID_id_GostR3410_2001) { +- /* We never allow GOST sig algs on the server with TLSv1.3 */ ++ if (lu->sig == NID_id_GostR3410_2001) { ++ /* GOST sig algs on the server with TLSv1.3 are allowed for GOST2012 */ + if (s->server && SSL_IS_TLS13(s)) + return 0; + if (!s->server +@@ -1643,7 +1759,7 @@ + if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0)) + continue; + +- if ((c->algorithm_mkey & SSL_kGOST) != 0) ++ if ((c->algorithm_mkey & (SSL_kGOST | SSL_kGOST18)) != 0) + break; + } + if (i == num) +Index: ssl/ssl_local.h +=================================================================== +--- ssl/ssl_local.h (revision 14523) ++++ ssl/ssl_local.h (working copy) +@@ -176,6 +176,8 @@ + # define SSL_kRSAPSK 0x00000040U + # define SSL_kECDHEPSK 0x00000080U + # define SSL_kDHEPSK 0x00000100U ++/* GOST KDF key exchange, draft-smyshlyaev-tls12-gost-suites */ ++# define SSL_kGOST18 0x00000200U + + /* all PSK */ + +@@ -230,6 +232,10 @@ + # define SSL_CHACHA20POLY1305 0x00080000U + # define SSL_ARIA128GCM 0x00100000U + # define SSL_ARIA256GCM 0x00200000U ++# define SSL_MAGMA 0x00400000U ++# define SSL_KUZNYECHIK 0x00800000U ++# define SSL_MAGMA_MGM 0x01000000U ++# define SSL_KUZNYECHIK_MGM 0x02000000U + + # define SSL_AESGCM (SSL_AES128GCM | SSL_AES256GCM) + # define SSL_AESCCM (SSL_AES128CCM | SSL_AES256CCM | SSL_AES128CCM8 | SSL_AES256CCM8) +@@ -252,6 +258,8 @@ + # define SSL_GOST12_256 0x00000080U + # define SSL_GOST89MAC12 0x00000100U + # define SSL_GOST12_512 0x00000200U ++# define SSL_MAGMAOMAC 0x00000400U ++# define SSL_KUZNYECHIKOMAC 0x00000800U + + /* + * When adding new digest in the ssl_ciph.c and increment SSL_MD_NUM_IDX make +@@ -270,7 +278,9 @@ + # define SSL_MD_MD5_SHA1_IDX 9 + # define SSL_MD_SHA224_IDX 10 + # define SSL_MD_SHA512_IDX 11 +-# define SSL_MAX_DIGEST 12 ++# define SSL_MD_MAGMAOMAC_IDX 12 ++# define SSL_MD_KUZNYECHIKOMAC_IDX 13 ++# define SSL_MAX_DIGEST 14 + + /* Bits for algorithm2 (handshake digests and other extra flags) */ + +@@ -299,6 +309,13 @@ + * goes into algorithm2) + */ + # define TLS1_STREAM_MAC 0x10000 ++/* ++ * TLSTREE cipher/mac key derivation used for GOST TLS 1.2/1.3 ciphersuites ++ * (currently this also goes into algorithm2) ++ */ ++# define TLS1_TLSTREE 0x20000 ++# define TLS1_TLSTREE_S 0x40000 ++# define TLS1_TLSTREE_L 0x80000 + + # define SSL_STRONG_MASK 0x0000001FU + # define SSL_DEFAULT_MASK 0X00000020U +@@ -1512,10 +1529,11 @@ + } TLS_GROUP_INFO; + + /* flags values */ +-# define TLS_CURVE_TYPE 0x3 /* Mask for group type */ ++# define TLS_CURVE_TYPE 0x7 /* Mask for group type */ + # define TLS_CURVE_PRIME 0x0 + # define TLS_CURVE_CHAR2 0x1 + # define TLS_CURVE_CUSTOM 0x2 ++# define TLS_CURVE_GOST 0x4 + + typedef struct cert_pkey_st CERT_PKEY; + +@@ -2043,8 +2061,17 @@ + #define TLSEXT_SIGALG_dsa_sha512 0x0602 + #define TLSEXT_SIGALG_dsa_sha224 0x0302 + #define TLSEXT_SIGALG_dsa_sha1 0x0202 +-#define TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256 0xeeee +-#define TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512 0xefef ++#define TLSEXT_SIGALG_gostr34102012_256a 0x0709 ++#define TLSEXT_SIGALG_gostr34102012_256b 0x070A ++#define TLSEXT_SIGALG_gostr34102012_256c 0x070B ++#define TLSEXT_SIGALG_gostr34102012_256d 0x070C ++#define TLSEXT_SIGALG_gostr34102012_512a 0x070D ++#define TLSEXT_SIGALG_gostr34102012_512b 0x070E ++#define TLSEXT_SIGALG_gostr34102012_512c 0x070F ++#define TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256 0x0840 ++#define TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512 0x0841 ++#define TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256_legacy 0xeeee ++#define TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512_legacy 0xefef + #define TLSEXT_SIGALG_gostr34102001_gostr3411 0xeded + + #define TLSEXT_SIGALG_ed25519 0x0807 +Index: ssl/ssl_lib.c +=================================================================== +--- ssl/ssl_lib.c (revision 14523) ++++ ssl/ssl_lib.c (working copy) +@@ -3327,11 +3327,11 @@ + + #ifndef OPENSSL_NO_GOST + if (ssl_has_cert(s, SSL_PKEY_GOST12_512)) { +- mask_k |= SSL_kGOST; ++ mask_k |= SSL_kGOST | SSL_kGOST18; + mask_a |= SSL_aGOST12; + } + if (ssl_has_cert(s, SSL_PKEY_GOST12_256)) { +- mask_k |= SSL_kGOST; ++ mask_k |= SSL_kGOST | SSL_kGOST18; + mask_a |= SSL_aGOST12; + } + if (ssl_has_cert(s, SSL_PKEY_GOST01)) { +Index: ssl/tls13_enc.c +=================================================================== +--- ssl/tls13_enc.c (revision 14523) ++++ ssl/tls13_enc.c (working copy) +@@ -421,6 +421,21 @@ + goto err; + } + ++ if (s->s3->tmp.new_cipher->algorithm2 & TLS1_TLSTREE) { ++ int res = 0; ++ if (s->s3->tmp.new_cipher->algorithm2 & TLS1_TLSTREE_S) { ++ res = EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_SET_TLSTREE_PARAMS, 0, "short"); ++ } else if (s->s3->tmp.new_cipher->algorithm2 & TLS1_TLSTREE_L) { ++ res = EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_SET_TLSTREE_PARAMS, 0, "long"); ++ } ++ ++ if (res <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DERIVE_SECRET_KEY_AND_IV, ++ ERR_R_EVP_LIB); ++ goto err; ++ } ++ } ++ + return 1; + err: + OPENSSL_cleanse(key, sizeof(key)); +Index: ssl/record/ssl3_record.c +=================================================================== +--- ssl/record/ssl3_record.c (revision 14523) ++++ ssl/record/ssl3_record.c (working copy) +@@ -944,6 +944,8 @@ + unsigned char padval; + int imac_size; + const EVP_CIPHER *enc; ++ int tlstree_enc = (sending ? (s->mac_flags & SSL_MAC_FLAG_WRITE_MAC_TLSTREE) ++ : (s->mac_flags & SSL_MAC_FLAG_READ_MAC_TLSTREE)); + + if (n_recs == 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC, +@@ -1036,7 +1038,6 @@ + + seq = sending ? RECORD_LAYER_get_write_sequence(&s->rlayer) + : RECORD_LAYER_get_read_sequence(&s->rlayer); +- + if (SSL_IS_DTLS(s)) { + /* DTLS does not support pipelining */ + unsigned char dtlsseq[9], *p = dtlsseq; +@@ -1122,6 +1123,27 @@ + } + } + ++ if (!SSL_IS_DTLS(s) && tlstree_enc) { ++ unsigned char *seq; ++ int decrement_seq = 0; ++ /* ++ * When sending, seq is incremented after MAC calculation. ++ * So if we are in ETM mode, we use seq 'as is' in the ctrl-function. ++ * Otherwise we have to decrease it in the implementation ++ */ ++ if (sending && !SSL_WRITE_ETM(s)) ++ decrement_seq = 1; ++ ++ seq = sending ? RECORD_LAYER_get_write_sequence(&s->rlayer) ++ : RECORD_LAYER_get_read_sequence(&s->rlayer); ++ if(EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_TLSTREE, decrement_seq, seq) <= 0) ++ { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC, ++ ERR_R_INTERNAL_ERROR); ++ return -1; ++ } ++ } ++ + /* TODO(size_t): Convert this call */ + tmpr = EVP_Cipher(ds, recs[0].data, recs[0].input, + (unsigned int)reclen[0]); +@@ -1287,6 +1309,8 @@ + unsigned char header[13]; + int stream_mac = (sending ? (ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM) + : (ssl->mac_flags & SSL_MAC_FLAG_READ_MAC_STREAM)); ++ int tlstree_mac = (sending ? (ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_TLSTREE) ++ : (ssl->mac_flags & SSL_MAC_FLAG_READ_MAC_TLSTREE)); + int t; + + if (sending) { +@@ -1314,6 +1338,11 @@ + mac_ctx = hmac; + } + ++ if (!SSL_IS_DTLS(ssl) && tlstree_mac && EVP_MD_CTX_ctrl(mac_ctx, EVP_MD_CTRL_TLSTREE, 0, seq) <= 0) { ++ EVP_MD_CTX_free(hmac); ++ return 0; ++ } ++ + if (SSL_IS_DTLS(ssl)) { + unsigned char dtlsseq[8], *p = dtlsseq; + +Index: ssl/record/ssl3_record_tls13.c +=================================================================== +--- ssl/record/ssl3_record_tls13.c (revision 14523) ++++ ssl/record/ssl3_record_tls13.c (working copy) +@@ -107,6 +107,10 @@ + taglen = EVP_GCM_TLS_TAG_LEN; + } else if (alg_enc & SSL_CHACHA20) { + taglen = EVP_CHACHAPOLY_TLS_TAG_LEN; ++ } else if (alg_enc & SSL_MAGMA_MGM) { ++ taglen = EVP_MAGMA_TLS_TAG_LEN; ++ } else if (alg_enc & SSL_KUZNYECHIK_MGM) { ++ taglen = EVP_KUZNYECHIK_TLS_TAG_LEN; + } else { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC, + ERR_R_INTERNAL_ERROR); +@@ -135,6 +139,15 @@ + for (loop = 0; loop < SEQ_NUM_SIZE; loop++) + iv[offset + loop] = staticiv[offset + loop] ^ seq[loop]; + ++ if (s->s3->tmp.new_cipher->algorithm2 & TLS1_TLSTREE) { ++ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_TLSTREE, ++ 0, seq) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC, ++ ERR_R_INTERNAL_ERROR); ++ return -1; ++ } ++ } ++ + /* Increment the sequence counter */ + for (loop = SEQ_NUM_SIZE; loop > 0; loop--) { + ++seq[loop - 1]; +Index: ssl/ssl_ciph.c +=================================================================== +--- ssl/ssl_ciph.c (revision 14523) ++++ ssl/ssl_ciph.c (working copy) +@@ -43,7 +43,11 @@ + #define SSL_ENC_CHACHA_IDX 19 + #define SSL_ENC_ARIA128GCM_IDX 20 + #define SSL_ENC_ARIA256GCM_IDX 21 +-#define SSL_ENC_NUM_IDX 22 ++#define SSL_ENC_MAGMA_IDX 22 ++#define SSL_ENC_KUZNYECHIK_IDX 23 ++#define SSL_ENC_MAGMA_MGM_IDX 24 ++#define SSL_ENC_KUZNYECHIK_MGM_IDX 25 ++#define SSL_ENC_NUM_IDX 26 + + /* NB: make sure indices in these tables match values above */ + +@@ -76,6 +80,10 @@ + {SSL_CHACHA20POLY1305, NID_chacha20_poly1305}, /* SSL_ENC_CHACHA_IDX 19 */ + {SSL_ARIA128GCM, NID_aria_128_gcm}, /* SSL_ENC_ARIA128GCM_IDX 20 */ + {SSL_ARIA256GCM, NID_aria_256_gcm}, /* SSL_ENC_ARIA256GCM_IDX 21 */ ++ {SSL_MAGMA, NID_magma_ctr_acpkm}, /* SSL_ENC_MAGMA_IDX */ ++ {SSL_KUZNYECHIK, NID_kuznyechik_ctr_acpkm}, /* SSL_ENC_KUZNYECHIK_IDX */ ++ {SSL_MAGMA_MGM, NID_magma_mgm}, /* SSL_ENC_MAGMA_MGM_IDX */ ++ {SSL_KUZNYECHIK_MGM, NID_kuznyechik_mgm}, /* SSL_ENC_KUZNYECHIK_MGM_IDX */ + }; + + static const EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX]; +@@ -110,11 +118,13 @@ + {SSL_GOST12_512, NID_id_GostR3411_2012_512}, /* SSL_MD_GOST12_512_IDX 8 */ + {0, NID_md5_sha1}, /* SSL_MD_MD5_SHA1_IDX 9 */ + {0, NID_sha224}, /* SSL_MD_SHA224_IDX 10 */ +- {0, NID_sha512} /* SSL_MD_SHA512_IDX 11 */ ++ {0, NID_sha512}, /* SSL_MD_SHA512_IDX 11 */ ++ {SSL_MAGMAOMAC, NID_magma_mac}, /* SSL_MD_MAGMAOMAC_IDX */ ++ {SSL_KUZNYECHIKOMAC, NID_kuznyechik_mac}, /* SSL_MD_KUZNYECHIKOMAC_IDX */ + }; + + static const EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX] = { +- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + }; + + /* *INDENT-OFF* */ +@@ -128,6 +138,7 @@ + {SSL_kPSK, NID_kx_psk}, + {SSL_kSRP, NID_kx_srp}, + {SSL_kGOST, NID_kx_gost}, ++ {SSL_kGOST18, NID_kx_gost},/* FIXME beldmit */ + {SSL_kANY, NID_kx_any} + }; + +@@ -171,8 +182,8 @@ + EVP_PKEY_HMAC, EVP_PKEY_HMAC, EVP_PKEY_HMAC, NID_undef, + /* GOST2012_512 */ + EVP_PKEY_HMAC, +- /* MD5/SHA1, SHA224, SHA512 */ +- NID_undef, NID_undef, NID_undef ++ /* MD5/SHA1, SHA224, SHA512, MAGMAOMAC, KUZNYECHIKOMAC */ ++ NID_undef, NID_undef, NID_undef, NID_undef, NID_undef + }; + + static size_t ssl_mac_secret_size[SSL_MD_NUM_IDX]; +@@ -228,6 +239,7 @@ + {0, SSL_TXT_kDHEPSK, NULL, 0, SSL_kDHEPSK}, + {0, SSL_TXT_kSRP, NULL, 0, SSL_kSRP}, + {0, SSL_TXT_kGOST, NULL, 0, SSL_kGOST}, ++ {0, SSL_TXT_kGOST18, NULL, 0, SSL_kGOST18}, + + /* server authentication aliases */ + {0, SSL_TXT_aRSA, NULL, 0, 0, SSL_aRSA}, +@@ -261,7 +273,7 @@ + {0, SSL_TXT_IDEA, NULL, 0, 0, 0, SSL_IDEA}, + {0, SSL_TXT_SEED, NULL, 0, 0, 0, SSL_SEED}, + {0, SSL_TXT_eNULL, NULL, 0, 0, 0, SSL_eNULL}, +- {0, SSL_TXT_GOST, NULL, 0, 0, 0, SSL_eGOST2814789CNT | SSL_eGOST2814789CNT12}, ++ {0, SSL_TXT_GOST, NULL, 0, 0, 0, SSL_eGOST2814789CNT | SSL_eGOST2814789CNT12 | SSL_MAGMA | SSL_KUZNYECHIK}, + {0, SSL_TXT_AES128, NULL, 0, 0, 0, + SSL_AES128 | SSL_AES128GCM | SSL_AES128CCM | SSL_AES128CCM8}, + {0, SSL_TXT_AES256, NULL, 0, 0, 0, +@@ -419,7 +431,7 @@ + * Check for presence of GOST 34.10 algorithms, and if they are not + * present, disable appropriate auth and key exchange + */ +- ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX] = get_optional_pkey_id("gost-mac"); ++ ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX] = get_optional_pkey_id(SN_id_Gost28147_89_MAC); + if (ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX]) + ssl_mac_secret_size[SSL_MD_GOST89MAC_IDX] = 32; + else +@@ -426,17 +438,31 @@ + disabled_mac_mask |= SSL_GOST89MAC; + + ssl_mac_pkey_id[SSL_MD_GOST89MAC12_IDX] = +- get_optional_pkey_id("gost-mac-12"); ++ get_optional_pkey_id(SN_gost_mac_12); + if (ssl_mac_pkey_id[SSL_MD_GOST89MAC12_IDX]) + ssl_mac_secret_size[SSL_MD_GOST89MAC12_IDX] = 32; + else + disabled_mac_mask |= SSL_GOST89MAC12; + +- if (!get_optional_pkey_id("gost2001")) ++ ssl_mac_pkey_id[SSL_MD_MAGMAOMAC_IDX] = ++ get_optional_pkey_id(SN_magma_mac); ++ if (ssl_mac_pkey_id[SSL_MD_MAGMAOMAC_IDX]) ++ ssl_mac_secret_size[SSL_MD_MAGMAOMAC_IDX] = 32; ++ else ++ disabled_mac_mask |= SSL_MAGMAOMAC; ++ ++ ssl_mac_pkey_id[SSL_MD_KUZNYECHIKOMAC_IDX] = ++ get_optional_pkey_id(SN_kuznyechik_mac); ++ if (ssl_mac_pkey_id[SSL_MD_KUZNYECHIKOMAC_IDX]) ++ ssl_mac_secret_size[SSL_MD_KUZNYECHIKOMAC_IDX] = 32; ++ else ++ disabled_mac_mask |= SSL_KUZNYECHIKOMAC; ++ ++ if (!get_optional_pkey_id(SN_id_GostR3410_2001)) + disabled_auth_mask |= SSL_aGOST01 | SSL_aGOST12; +- if (!get_optional_pkey_id("gost2012_256")) ++ if (!get_optional_pkey_id(SN_id_GostR3410_2012_256)) + disabled_auth_mask |= SSL_aGOST12; +- if (!get_optional_pkey_id("gost2012_512")) ++ if (!get_optional_pkey_id(SN_id_GostR3410_2012_512)) + disabled_auth_mask |= SSL_aGOST12; + /* + * Disable GOST key exchange if no GOST signature algs are available * +@@ -445,6 +471,9 @@ + (SSL_aGOST01 | SSL_aGOST12)) + disabled_mkey_mask |= SSL_kGOST; + ++ if ((disabled_auth_mask & SSL_aGOST12) == SSL_aGOST12) ++ disabled_mkey_mask |= SSL_kGOST18; ++ + return 1; + } + +@@ -1686,6 +1715,9 @@ + case SSL_kGOST: + kx = "GOST"; + break; ++ case SSL_kGOST18: ++ kx = "GOST18"; ++ break; + case SSL_kANY: + kx = "any"; + break; +@@ -1789,6 +1821,14 @@ + case SSL_eGOST2814789CNT12: + enc = "GOST89(256)"; + break; ++ case SSL_MAGMA: ++ case SSL_MAGMA_MGM: ++ enc = "MAGMA"; ++ break; ++ case SSL_KUZNYECHIK: ++ case SSL_KUZNYECHIK_MGM: ++ enc = "KUZNYECHIK"; ++ break; + case SSL_CHACHA20POLY1305: + enc = "CHACHA20/POLY1305(256)"; + break; +Index: ssl/t1_enc.c +=================================================================== +--- ssl/t1_enc.c (revision 14523) ++++ ssl/t1_enc.c (working copy) +@@ -113,6 +113,11 @@ + else + s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM; + ++ if (s->s3->tmp.new_cipher->algorithm2 & TLS1_TLSTREE) ++ s->mac_flags |= SSL_MAC_FLAG_READ_MAC_TLSTREE; ++ else ++ s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_TLSTREE; ++ + if (s->enc_read_ctx != NULL) { + reuse_dd = 1; + } else if ((s->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL) { +@@ -160,6 +165,11 @@ + s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM; + else + s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_STREAM; ++ ++ if (s->s3->tmp.new_cipher->algorithm2 & TLS1_TLSTREE) ++ s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_TLSTREE; ++ else ++ s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_TLSTREE; + if (s->enc_write_ctx != NULL && !SSL_IS_DTLS(s)) { + reuse_dd = 1; + } else if ((s->enc_write_ctx = EVP_CIPHER_CTX_new()) == NULL) { +@@ -298,11 +308,11 @@ + goto err; + } + } else { +- if (!EVP_CipherInit_ex(dd, c, NULL, key, iv, (which & SSL3_CC_WRITE))) { +- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE, +- ERR_R_INTERNAL_ERROR); +- goto err; +- } ++ if (!EVP_CipherInit_ex(dd, c, NULL, key, iv, (which & SSL3_CC_WRITE))) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } + } + /* Needed for "composite" AEADs, such as RC4-HMAC-MD5 */ + if ((EVP_CIPHER_flags(c) & EVP_CIPH_FLAG_AEAD_CIPHER) && *mac_secret_size +@@ -438,7 +448,11 @@ + { + size_t hashlen; + unsigned char hash[EVP_MAX_MD_SIZE]; ++ size_t finished_size = TLS1_FINISH_MAC_LENGTH; + ++ if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kGOST18) ++ finished_size = 32; ++ + if (!ssl3_digest_cached_records(s, 0)) { + /* SSLfatal() already called */ + return 0; +@@ -451,12 +465,12 @@ + + if (!tls1_PRF(s, str, slen, hash, hashlen, NULL, 0, NULL, 0, NULL, 0, + s->session->master_key, s->session->master_key_length, +- out, TLS1_FINISH_MAC_LENGTH, 1)) { ++ out, finished_size, 1)) { + /* SSLfatal() already called */ + return 0; + } + OPENSSL_cleanse(hash, hashlen); +- return TLS1_FINISH_MAC_LENGTH; ++ return finished_size; + } + + int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, +Index: ssl/s3_lib.c +=================================================================== +--- ssl/s3_lib.c (revision 14523) ++++ ssl/s3_lib.c (working copy) +@@ -111,7 +111,74 @@ + SSL_HANDSHAKE_MAC_SHA256, + 128, + 128, +- } ++ }, ++#ifndef OPENSSL_NO_GOST ++/* https://tools.ietf.org/html/draft-smyshlyaev-tls13-gost-suites */ ++ { ++ 1, ++ "TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_L", /* FIXME */ ++ "TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_L", /* FIXME */ ++ TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_L, ++ SSL_kANY, ++ SSL_aANY, ++ SSL_KUZNYECHIK_MGM, ++ SSL_AEAD, ++ TLS1_3_VERSION, TLS1_3_VERSION, ++ 0, 0, ++ SSL_HIGH, ++ SSL_HANDSHAKE_MAC_GOST12_256 | TLS1_TLSTREE | TLS1_TLSTREE_L, ++ 256, ++ 256, ++ }, ++ { ++ 1, ++ "TLS_GOSTR341112_256_WITH_MAGMA_MGM_L", /* FIXME */ ++ "TLS_GOSTR341112_256_WITH_MAGMA_MGM_L", /* FIXME */ ++ TLS_GOSTR341112_256_WITH_MAGMA_MGM_L, ++ SSL_kANY, ++ SSL_aANY, ++ SSL_MAGMA_MGM, ++ SSL_AEAD, ++ TLS1_3_VERSION, TLS1_3_VERSION, ++ 0, 0, ++ SSL_HIGH, ++ SSL_HANDSHAKE_MAC_GOST12_256 | TLS1_TLSTREE | TLS1_TLSTREE_L, ++ 256, ++ 256, ++ }, ++ { ++ 1, ++ "TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_S", /* FIXME */ ++ "TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_S", /* FIXME */ ++ TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_S, ++ SSL_kANY, ++ SSL_aANY, ++ SSL_KUZNYECHIK_MGM, ++ SSL_AEAD, ++ TLS1_3_VERSION, TLS1_3_VERSION, ++ 0, 0, ++ SSL_HIGH, ++ SSL_HANDSHAKE_MAC_GOST12_256 | TLS1_TLSTREE | TLS1_TLSTREE_S, ++ 256, ++ 256, ++ }, ++ { ++ 1, ++ "TLS_GOSTR341112_256_WITH_MAGMA_MGM_S", /* FIXME */ ++ "TLS_GOSTR341112_256_WITH_MAGMA_MGM_S", /* FIXME */ ++ TLS_GOSTR341112_256_WITH_MAGMA_MGM_S, ++ SSL_kANY, ++ SSL_aANY, ++ SSL_MAGMA_MGM, ++ SSL_AEAD, ++ TLS1_3_VERSION, TLS1_3_VERSION, ++ 0, 0, ++ SSL_HIGH, ++ SSL_HANDSHAKE_MAC_GOST12_256 | TLS1_TLSTREE | TLS1_TLSTREE_S, ++ 256, ++ 256, ++ }, ++#endif + }; + + /* +@@ -2665,6 +2732,54 @@ + 0, + 0, + }, ++ { ++ 1, ++ "GOST2012-KUZNYECHIK-KUZNYECHIKOMAC", ++ NULL, ++ 0x0300C100, ++ SSL_kGOST18, ++ SSL_aGOST12, ++ SSL_KUZNYECHIK, ++ SSL_KUZNYECHIKOMAC, ++ TLS1_2_VERSION, TLS1_2_VERSION, ++ 0, 0, ++ SSL_HIGH, ++ SSL_HANDSHAKE_MAC_GOST12_256 | TLS1_PRF_GOST12_256 | TLS1_TLSTREE, ++ 256, ++ 256, ++ }, ++ { ++ 1, ++ "GOST2012-MAGMA-MAGMAOMAC", ++ NULL, ++ 0x0300C101, ++ SSL_kGOST18, ++ SSL_aGOST12, ++ SSL_MAGMA, ++ SSL_MAGMAOMAC, ++ TLS1_2_VERSION, TLS1_2_VERSION, ++ 0, 0, ++ SSL_HIGH, ++ SSL_HANDSHAKE_MAC_GOST12_256 | TLS1_PRF_GOST12_256 | TLS1_TLSTREE, ++ 256, ++ 256, ++ }, ++ { ++ 1, ++ "GOST2012-GOST8912-IANA", ++ NULL, ++ 0x0300C102, ++ SSL_kGOST, ++ SSL_aGOST12 | SSL_aGOST01, ++ SSL_eGOST2814789CNT12, ++ SSL_GOST89MAC12, ++ TLS1_VERSION, TLS1_2_VERSION, ++ 0, 0, ++ SSL_HIGH, ++ SSL_HANDSHAKE_MAC_GOST12_256 | TLS1_PRF_GOST12_256 | TLS1_STREAM_MAC, ++ 256, ++ 256, ++ }, + #endif /* OPENSSL_NO_GOST */ + + #ifndef OPENSSL_NO_IDEA +@@ -4348,6 +4463,11 @@ + if (s->version >= TLS1_VERSION && (alg_k & SSL_kGOST)) + return WPACKET_put_bytes_u8(pkt, TLS_CT_GOST01_SIGN) + && WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_SIGN) ++ && WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_512_SIGN) ++ && WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_SIGN_LEGACY) ++ && WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_512_SIGN_LEGACY); ++ if (s->version >= TLS1_2_VERSION && (alg_k & SSL_kGOST18)) ++ return WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_SIGN) + && WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_512_SIGN); + #endif + +@@ -4695,6 +4815,52 @@ + return pkey; + } + #ifndef OPENSSL_NO_EC ++#ifndef OPENSSL_NO_GOST ++ ++typedef struct tls_gost_group_param_st { ++ int nid; /* Curve params NID */ ++ int alg_nid; /* GOST algorithm nid */ ++ const char *params; /* GOST paramset mnemonics */ ++} TLS_GOST_GROUP_PARAM; ++ ++TLS_GOST_GROUP_PARAM gost_param[] = { ++ {NID_id_tc26_gost_3410_2012_256_paramSetA, NID_id_GostR3410_2012_256, "TCA"}, ++ {NID_id_tc26_gost_3410_2012_256_paramSetB, NID_id_GostR3410_2012_256, "TCB"}, ++ {NID_id_tc26_gost_3410_2012_256_paramSetC, NID_id_GostR3410_2012_256, "TCC"}, ++ {NID_id_tc26_gost_3410_2012_256_paramSetD, NID_id_GostR3410_2012_256, "TCD"}, ++ {NID_id_tc26_gost_3410_2012_512_paramSetA, NID_id_GostR3410_2012_512, "A"}, ++ {NID_id_tc26_gost_3410_2012_512_paramSetB, NID_id_GostR3410_2012_512, "B"}, ++ {NID_id_tc26_gost_3410_2012_512_paramSetC, NID_id_GostR3410_2012_512, "C"}, ++}; ++ ++static EVP_PKEY_CTX *gost_pkey_nid2ctx(int nid) ++{ ++ int i = 0; ++ TLS_GOST_GROUP_PARAM *pGostParam = NULL; ++ EVP_PKEY_CTX *pctx = NULL; ++ ++ for (i = 0; i < OSSL_NELEM(gost_param); i++) { ++ if (gost_param[i].nid == nid) { ++ pGostParam = gost_param + i; ++ break; ++ } ++ } ++ ++ if (pGostParam == NULL) { ++ return NULL; ++ } ++ ++ pctx = EVP_PKEY_CTX_new_id(pGostParam->alg_nid, NULL); ++ if (pctx == NULL ++ || EVP_PKEY_CTX_ctrl_str(pctx, "paramset", pGostParam->params) <= 0) { ++ EVP_PKEY_CTX_free(pctx); ++ return NULL; ++ } ++ ++ return pctx; ++} ++ ++#endif + /* Generate a private key from a group ID */ + EVP_PKEY *ssl_generate_pkey_group(SSL *s, uint16_t id) + { +@@ -4711,8 +4877,13 @@ + gtype = ginf->flags & TLS_CURVE_TYPE; + if (gtype == TLS_CURVE_CUSTOM) + pctx = EVP_PKEY_CTX_new_id(ginf->nid, NULL); ++#ifndef OPENSSL_NO_GOST ++ else if (gtype == TLS_CURVE_GOST) ++ pctx = gost_pkey_nid2ctx(ginf->nid); ++#endif + else + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); ++ + if (pctx == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_PKEY_GROUP, + ERR_R_MALLOC_FAILURE); +@@ -4723,7 +4894,7 @@ + ERR_R_EVP_LIB); + goto err; + } +- if (gtype != TLS_CURVE_CUSTOM ++ if (gtype != TLS_CURVE_CUSTOM && gtype != TLS_CURVE_GOST + && EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, ginf->nid) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_PKEY_GROUP, + ERR_R_EVP_LIB); +@@ -4761,13 +4932,21 @@ + return NULL; + } + ++#ifndef OPENSSL_NO_GOST ++ if ((ginf->flags & TLS_CURVE_TYPE) == TLS_CURVE_GOST) ++ pctx = gost_pkey_nid2ctx(ginf->nid); ++ else ++#endif + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); ++ + if (pctx == NULL) + goto err; + if (EVP_PKEY_paramgen_init(pctx) <= 0) + goto err; +- if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, ginf->nid) <= 0) ++ if ((ginf->flags & TLS_CURVE_TYPE) != TLS_CURVE_GOST) { ++ if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, ginf->nid) <= 0) + goto err; ++ } + if (EVP_PKEY_paramgen(pctx, &pkey) <= 0) { + EVP_PKEY_free(pkey); + pkey = NULL; +Index: ssl/statem/statem_lib.c +=================================================================== +--- ssl/statem/statem_lib.c (revision 14523) ++++ ssl/statem/statem_lib.c (working copy) +@@ -410,7 +410,6 @@ + md == NULL ? "n/a" : EVP_MD_name(md)); + #endif + +- /* Check for broken implementations of GOST ciphersuites */ + /* + * If key is GOST and len is exactly 64 or 128, it is signature without + * length field (CryptoPro implementations at least till TLS 1.2) +@@ -1527,8 +1526,6 @@ + switch (i) { + case SSL_PKEY_DSA_SIGN: + case SSL_PKEY_GOST01: +- case SSL_PKEY_GOST12_256: +- case SSL_PKEY_GOST12_512: + continue; + default: + break; +Index: ssl/statem/statem_srvr.c +=================================================================== +--- ssl/statem/statem_srvr.c (revision 14523) ++++ ssl/statem/statem_srvr.c (working copy) +@@ -3446,6 +3446,93 @@ + #endif + } + ++static int tls_process_cke_gost18(SSL *s, PACKET *pkt) ++{/* FIXME beldmit - function id to be renamed either*/ ++#ifndef OPENSSL_NO_GOST ++ unsigned char rnd_dgst[32]; ++ EVP_PKEY_CTX *pkey_ctx = NULL; ++ EVP_PKEY *pk = NULL; ++ unsigned char premaster_secret[32]; ++ const unsigned char *start = NULL; ++ size_t outlen = 32, inlen = 0; ++ int ret = 0; ++ int cipher_nid = gost18_cke_cipher_nid(s); ++ ++ if (cipher_nid == NID_undef) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18, ++ ERR_R_INTERNAL_ERROR); ++ return 0; ++ } ++ ++ if (gost_ukm(s, rnd_dgst) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ /* Get our certificate private key */ ++ pk = s->cert->pkeys[SSL_PKEY_GOST12_512].privatekey ++ ? s->cert->pkeys[SSL_PKEY_GOST12_512].privatekey : s->cert->pkeys[SSL_PKEY_GOST12_256].privatekey; ++ if (pk == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18, ++ SSL_R_BAD_HANDSHAKE_STATE); ++ return 0; ++ } ++ ++ pkey_ctx = EVP_PKEY_CTX_new(pk, NULL); ++ if (pkey_ctx == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18, ++ ERR_R_MALLOC_FAILURE); ++ return 0; ++ } ++ if (EVP_PKEY_decrypt_init(pkey_ctx) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18, ++ ERR_R_INTERNAL_ERROR); ++ return 0; ++ } ++ /* ++ * Reuse EVP_PKEY_CTRL_SET_IV, make choice in engine code depending on size ++ * */ ++ if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_DECRYPT, ++ EVP_PKEY_CTRL_SET_IV, 32, rnd_dgst) < 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18, ++ SSL_R_LIBRARY_BUG); ++ goto err; ++ } ++ ++ if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_DECRYPT, ++ EVP_PKEY_CTRL_CIPHER, cipher_nid, NULL) < 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18, ++ SSL_R_LIBRARY_BUG); ++ goto err; ++ } ++ inlen = PACKET_remaining(pkt); ++ start = PACKET_data(pkt); ++ ++ if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, start, ++ inlen) <= 0) { ++ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18, ++ SSL_R_DECRYPTION_FAILED); ++ goto err; ++ } ++ /* Generate master secret */ ++ if (!ssl_generate_master_secret(s, premaster_secret, ++ sizeof(premaster_secret), 0)) { ++ /* SSLfatal() already called */ ++ goto err; ++ } ++ ret = 1; ++err: ++ EVP_PKEY_CTX_free(pkey_ctx); ++ return ret; ++#else ++ /* Should never happen */ ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18, ++ ERR_R_INTERNAL_ERROR); ++ return 0; ++#endif ++} ++ + MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt) + { + unsigned long alg_k; +@@ -3496,6 +3583,11 @@ + /* SSLfatal() already called */ + goto err; + } ++ } else if (alg_k & SSL_kGOST18) { ++ if (!tls_process_cke_gost18(s, pkt)) { ++ /* SSLfatal() already called */ ++ goto err; ++ } + } else { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, +Index: ssl/statem/extensions_srvr.c +=================================================================== +--- ssl/statem/extensions_srvr.c (revision 14523) ++++ ssl/statem/extensions_srvr.c (working copy) +@@ -624,7 +624,7 @@ + + if (s->hit && (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE) == 0) + return 1; +- ++/* FIXME beldmit GOST */ + /* Sanity check */ + if (s->s3->peer_tmp != NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE, +@@ -1623,7 +1623,9 @@ + if (s->s3->tmp.new_cipher->algorithm_mac == SSL_AEAD + || s->s3->tmp.new_cipher->algorithm_enc == SSL_RC4 + || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT +- || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12) { ++ || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12 ++ || s->s3->tmp.new_cipher->algorithm_enc == SSL_MAGMA ++ || s->s3->tmp.new_cipher->algorithm_enc == SSL_KUZNYECHIK) { + s->ext.use_etm = 0; + return EXT_RETURN_NOT_SENT; + } +@@ -1682,6 +1684,7 @@ + unsigned int context, X509 *x, + size_t chainidx) + { ++/* FIXME beldmit GOST */ + #ifndef OPENSSL_NO_TLS1_3 + unsigned char *encodedPoint; + size_t encoded_pt_len = 0; +Index: ssl/statem/statem_local.h +=================================================================== +--- ssl/statem/statem_local.h (revision 14523) ++++ ssl/statem/statem_local.h (working copy) +@@ -153,6 +153,11 @@ + __owur int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt); + MSG_PROCESS_RETURN tls_process_end_of_early_data(SSL *s, PACKET *pkt); + ++#ifndef OPENSSL_NO_GOST ++/* These functions are used in GOST18 CKE, both for client and server */ ++int gost18_cke_cipher_nid(const SSL *s); ++int gost_ukm(const SSL *s, unsigned char *dgst_buf); ++#endif + + /* Extension processing */ + +Index: ssl/statem/statem_clnt.c +=================================================================== +--- ssl/statem/statem_clnt.c (revision 14523) ++++ ssl/statem/statem_clnt.c (working copy) +@@ -3280,6 +3280,144 @@ + #endif + } + ++#ifndef OPENSSL_NO_GOST ++int gost18_cke_cipher_nid(const SSL *s) ++{ ++ if ((s->s3->tmp.new_cipher->algorithm_enc & SSL_MAGMA) != 0) ++ return NID_magma_ctr; ++ else if ((s->s3->tmp.new_cipher->algorithm_enc & SSL_KUZNYECHIK) != 0) ++ return NID_kuznyechik_ctr; ++ ++ return NID_undef; ++} ++ ++int gost_ukm(const SSL *s, unsigned char *dgst_buf) ++{ ++ EVP_MD_CTX * hash = NULL; ++ unsigned int md_len; ++ ++ hash = EVP_MD_CTX_new(); ++ if (hash == NULL ++ || EVP_DigestInit(hash, EVP_get_digestbynid(NID_id_GostR3411_2012_256)) <= 0 ++ || EVP_DigestUpdate(hash, s->s3->client_random, SSL3_RANDOM_SIZE) <= 0 ++ || EVP_DigestUpdate(hash, s->s3->server_random, SSL3_RANDOM_SIZE) <= 0 ++ || EVP_DigestFinal_ex(hash, dgst_buf, &md_len) <= 0) { ++ EVP_MD_CTX_free(hash); ++ return 0; ++ } else { ++ EVP_MD_CTX_free(hash); ++ return 1; ++ } ++} ++#endif ++ ++static int tls_construct_cke_gost18(SSL *s, WPACKET *pkt) ++{ ++#ifndef OPENSSL_NO_GOST ++ /* GOST 2018 key exchange message creation */ ++ unsigned char rnd_dgst[32], tmp[255]; ++ EVP_PKEY_CTX *pkey_ctx = NULL; ++ X509 *peer_cert; ++ unsigned char *pms = NULL; ++ size_t pmslen = 0; ++ size_t msglen; ++ int cipher_nid = gost18_cke_cipher_nid(s); ++ ++ if (cipher_nid == NID_undef) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18, ++ ERR_R_INTERNAL_ERROR); ++ return 0; ++ } ++ ++ if (gost_ukm(s, rnd_dgst) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ /* Pre-master secret - random bytes */ ++ pmslen = 32; ++ pms = OPENSSL_malloc(pmslen); ++ if (pms == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18, ++ ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ if (RAND_bytes(pms, (int)pmslen) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ /* ++ * Get server certificate PKEY and create ctx from it ++ */ ++ peer_cert = s->session->peer; ++ if (!peer_cert) { ++ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_CONSTRUCT_CKE_GOST18, ++ SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER); ++ return 0; ++ } ++ ++ pkey_ctx = EVP_PKEY_CTX_new(X509_get0_pubkey(peer_cert), NULL); ++ if (pkey_ctx == NULL) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18, ++ ERR_R_MALLOC_FAILURE); ++ return 0; ++ } ++ ++ if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0 ) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ }; ++ ++ /* ++ * Reuse EVP_PKEY_CTRL_SET_IV, make choice in engine code ++ * */ ++ if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT, ++ EVP_PKEY_CTRL_SET_IV, 32, rnd_dgst) < 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18, ++ SSL_R_LIBRARY_BUG); ++ goto err; ++ } ++ ++ if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT, ++ EVP_PKEY_CTRL_CIPHER, cipher_nid, NULL) < 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18, ++ SSL_R_LIBRARY_BUG); ++ goto err; ++ } ++ ++ msglen = 255; ++ if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) <= 0) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18, ++ SSL_R_LIBRARY_BUG); ++ goto err; ++ } ++ ++ if (!WPACKET_memcpy(pkt, tmp, msglen)) { ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18, ++ ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ ++ EVP_PKEY_CTX_free(pkey_ctx); ++ s->s3->tmp.pms = pms; ++ s->s3->tmp.pmslen = pmslen; ++ return 1; ++ err: ++ EVP_PKEY_CTX_free(pkey_ctx); ++ OPENSSL_clear_free(pms, pmslen); ++ return 0; ++#else ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18, ++ ERR_R_INTERNAL_ERROR); ++ return 0; ++#endif ++} ++ + static int tls_construct_cke_srp(SSL *s, WPACKET *pkt) + { + #ifndef OPENSSL_NO_SRP +@@ -3336,6 +3474,9 @@ + } else if (alg_k & SSL_kGOST) { + if (!tls_construct_cke_gost(s, pkt)) + goto err; ++ } else if (alg_k & SSL_kGOST18) { ++ if (!tls_construct_cke_gost18(s, pkt)) ++ goto err; + } else if (alg_k & SSL_kSRP) { + if (!tls_construct_cke_srp(s, pkt)) + goto err; +Index: util/libcrypto.num +=================================================================== +--- util/libcrypto.num (revision 14523) ++++ util/libcrypto.num (working copy) +@@ -4587,3 +4587,8 @@ + EVP_PKEY_meth_get_digestverify 4541 1_1_1e EXIST::FUNCTION: + EVP_PKEY_meth_get_digestsign 4542 1_1_1e EXIST::FUNCTION: + RSA_get0_pss_params 4543 1_1_1e EXIST::FUNCTION:RSA ++CMS_add1_recipient 4544 1_1_1g EXIST::FUNCTION:CMS ++PKCS8_pkey_add1_attr 4545 1_1_1g EXIST::FUNCTION: ++PKCS8_pkey_add1_attr_by_OBJ 4546 1_1_1g EXIST::FUNCTION: ++CMS_decrypt_set1_pkey_and_peer 4547 1_1_1g EXIST::FUNCTION:CMS ++CMS_RecipientInfo_kari_set0_pkey_and_peer 4548 1_1_1g EXIST::FUNCTION:CMS -- 2.39.2