From 0bfd744f8d2b593455b11066cff59f3764bd313c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= Date: Thu, 27 Jul 2023 12:03:47 +0200 Subject: [PATCH 01/21] Add option for setting size of processed data chunks For tests in `evp_test`, which support processing in batches. When not set or set to 0, data are processed with default sizes (as before). Reviewed-by: Dmitry Belyavskiy Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/21727) --- test/evp_test.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/evp_test.c b/test/evp_test.c index 5634631703240..662ac9400d5b4 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -75,6 +75,7 @@ typedef enum OPTION_choice { OPT_IN_PLACE, OPT_PROVIDER_NAME, OPT_PROV_PROPQUERY, + OPT_DATA_CHUNK, OPT_TEST_ENUM } OPTION_CHOICE; @@ -118,6 +119,7 @@ static int memory_err_compare(EVP_TEST *t, const char *err, /* Option specific for evp test */ static int process_mode_in_place; static const char *propquery = NULL; +static int data_chunk_size; static int evp_test_process_mode(char *mode) { @@ -4161,6 +4163,7 @@ const OPTIONS *test_get_options(void) "The provider to load (when no configuration file, the default value is 'default')" }, { "propquery", OPT_PROV_PROPQUERY, 's', "Property query used when fetching algorithms" }, + { "chunk", OPT_DATA_CHUNK, 'N', "Size of data chunks to be processed, 0 for default size"}, { OPT_HELP_STR, 1, '-', "file\tFile to run tests on.\n" }, { NULL } }; @@ -4182,6 +4185,8 @@ int setup_tests(void) break; case OPT_IN_PLACE: if ((process_mode_in_place = evp_test_process_mode(opt_arg())) == -1) + case OPT_DATA_CHUNK: + if (!opt_int(opt_arg(), &data_chunk_size)) return 0; break; case OPT_PROVIDER_NAME: From 2c8dc43bff22e0ce221157738cc1d6d31f3125f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= Date: Thu, 27 Jul 2023 15:11:57 +0200 Subject: [PATCH 02/21] Add processing by chunks to cipher tests in evp_test When cipher does not support variable fragmentation, the test is skipped. Reviewed-by: Dmitry Belyavskiy Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/21727) --- test/evp_test.c | 83 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 26 deletions(-) diff --git a/test/evp_test.c b/test/evp_test.c index 662ac9400d5b4..416faa5da824e 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -601,6 +601,24 @@ typedef struct cipher_data_st { const char *xts_standard; } CIPHER_DATA; + +/* + * XTS, SIV, CCM, stitched ciphers and Wrap modes have special + * requirements about input lengths so we don't fragment for those + */ +static int cipher_test_valid_fragmentation(CIPHER_DATA *cdat) +{ + return (cdat->aead == EVP_CIPH_CCM_MODE + || cdat->aead == EVP_CIPH_CBC_MODE + || (cdat->aead == -1 + && EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_STREAM_CIPHER) + || ((EVP_CIPHER_get_flags(cdat->cipher) & EVP_CIPH_FLAG_CTS) != 0) + || EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_SIV_MODE + || EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_GCM_SIV_MODE + || EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_XTS_MODE + || EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_WRAP_MODE) ? 0 : 1; +} + static int cipher_test_init(EVP_TEST *t, const char *alg) { const EVP_CIPHER *cipher; @@ -641,6 +659,13 @@ static int cipher_test_init(EVP_TEST *t, const char *alg) else cdat->aead = 0; + if (data_chunk_size != 0 && !cipher_test_valid_fragmentation(cdat)) { + ERR_pop_to_mark(); + t->skip = 1; + TEST_info("skipping, '%s' does not support fragmentation", alg); + return 1; + } + t->data = cdat; if (fetched_cipher != NULL) TEST_info("%s is fetched", alg); @@ -948,15 +973,26 @@ static int cipher_test_enc(EVP_TEST *t, int enc, size_t out_misalign, if (expected->aad[0] != NULL && !expected->tls_aad) { t->err = "AAD_SET_ERROR"; if (!frag) { + /* Supply the data all in one go or according to data_chunk_size */ for (i = 0; expected->aad[i] != NULL; i++) { - if (!EVP_CipherUpdate(ctx, NULL, &chunklen, expected->aad[i], - expected->aad_len[i])) - goto err; + size_t aad_len = expected->aad_len[i]; + donelen = 0; + + do { + size_t current_aad_len = (size_t) data_chunk_size; + + if (data_chunk_size == 0 || (size_t) data_chunk_size > aad_len) + current_aad_len = aad_len; + if (!EVP_CipherUpdate(ctx, NULL, &chunklen, + expected->aad[i] + donelen, + current_aad_len)) + goto err; + donelen += current_aad_len; + aad_len -= current_aad_len; + } while (aad_len > 0); } } else { - /* - * Supply the AAD in chunks less than the block size where possible - */ + /* Supply the AAD in chunks less than the block size where possible */ for (i = 0; expected->aad[i] != NULL; i++) { if (expected->aad_len[i] > 0) { if (!EVP_CipherUpdate(ctx, NULL, &chunklen, expected->aad[i], 1)) @@ -1020,9 +1056,19 @@ static int cipher_test_enc(EVP_TEST *t, int enc, size_t out_misalign, t->err = "CIPHERUPDATE_ERROR"; tmplen = 0; if (!frag) { - /* We supply the data all in one go */ - if (!EVP_CipherUpdate(ctx, tmp + out_misalign, &tmplen, in, in_len)) - goto err; + do { + /* Supply the data all in one go or according to data_chunk_size */ + size_t current_in_len = (size_t) data_chunk_size; + + if (data_chunk_size == 0 || (size_t) data_chunk_size > in_len) + current_in_len = in_len; + if (!EVP_CipherUpdate(ctx, tmp + out_misalign + tmplen, &chunklen, + in, current_in_len)) + goto err; + tmplen += chunklen; + in += current_in_len; + in_len -= current_in_len; + } while (in_len > 0); } else { /* Supply the data in chunks less than the block size where possible */ if (in_len > 0) { @@ -1105,23 +1151,6 @@ static int cipher_test_enc(EVP_TEST *t, int enc, size_t out_misalign, return ok; } -/* - * XTS, SIV, CCM, stitched ciphers and Wrap modes have special - * requirements about input lengths so we don't fragment for those - */ -static int cipher_test_valid_fragmentation(CIPHER_DATA *cdat) -{ - return (cdat->aead == EVP_CIPH_CCM_MODE - || cdat->aead == EVP_CIPH_CBC_MODE - || (cdat->aead == -1 - && EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_STREAM_CIPHER) - || ((EVP_CIPHER_get_flags(cdat->cipher) & EVP_CIPH_FLAG_CTS) != 0) - || EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_SIV_MODE - || EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_GCM_SIV_MODE - || EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_XTS_MODE - || EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_WRAP_MODE) ? 0 : 1; -} - static int cipher_test_run(EVP_TEST *t) { CIPHER_DATA *cdat = t->data; @@ -1155,6 +1184,8 @@ static int cipher_test_run(EVP_TEST *t) break; for (frag = 0; frag <= fragmax; frag++) { + if (frag == 1 && data_chunk_size != 0) + break; for (out_misalign = 0; out_misalign <= 1; out_misalign++) { for (inp_misalign = 0; inp_misalign <= 1; inp_misalign++) { /* Skip input misalign tests for in-place processing */ From 1208d526d340b5869d5369d0d4930cc3576aabbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= Date: Fri, 28 Jul 2023 12:35:37 +0200 Subject: [PATCH 03/21] Add processing by chunks to digest, sign, verify tests Input value is parsed into chunks, which are separately stored in the buffer stack. When chunk size is set, "Count" and "Copy" parameters are skipped. Reviewed-by: Dmitry Belyavskiy Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/21727) --- test/evp_test.c | 107 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 94 insertions(+), 13 deletions(-) diff --git a/test/evp_test.c b/test/evp_test.c index 416faa5da824e..d08ce28971941 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -89,6 +89,8 @@ static KEY_LIST *public_keys; static int find_key(EVP_PKEY **ppk, const char *name, KEY_LIST *lst); static int parse_bin(const char *value, unsigned char **buf, size_t *buflen); +static int parse_bin_chunk(const char *value, size_t offset, size_t max, + unsigned char **buf, size_t *buflen, size_t *out_offset); static int is_digest_disabled(const char *name); static int is_pkey_disabled(const char *name); static int is_mac_disabled(const char *name); @@ -150,23 +152,42 @@ static void evp_test_buffer_free(EVP_TEST_BUFFER *db) } /* append buffer to a list */ -static int evp_test_buffer_append(const char *value, +static int evp_test_buffer_append(const char *value, size_t max_len, STACK_OF(EVP_TEST_BUFFER) **sk) { EVP_TEST_BUFFER *db = NULL; + int rv = 0; + size_t offset = 0; - if (!TEST_ptr(db = OPENSSL_malloc(sizeof(*db)))) + if (*sk == NULL && !TEST_ptr(*sk = sk_EVP_TEST_BUFFER_new_null())) goto err; - if (!parse_bin(value, &db->buf, &db->buflen)) - goto err; - db->count = 1; - db->count_set = 0; + do { + if (!TEST_ptr(db = OPENSSL_zalloc(sizeof(*db)))) + goto err; + if (max_len == 0) { + /* parse all in one shot */ + if ((rv = parse_bin(value, &db->buf, &db->buflen)) != 1) + goto err; + } else { + /* parse in chunks */ + size_t new_offset = 0; - if (*sk == NULL && !TEST_ptr(*sk = sk_EVP_TEST_BUFFER_new_null())) - goto err; - if (!sk_EVP_TEST_BUFFER_push(*sk, db)) - goto err; + if ((rv = parse_bin_chunk(value, offset, max_len, &db->buf, + &db->buflen, &new_offset)) == -1) + goto err; + offset = new_offset; + } + + db->count = 1; + db->count_set = 0; + + if (db->buf == NULL) + evp_test_buffer_free(db); + else if (db->buf != NULL && !sk_EVP_TEST_BUFFER_push(*sk, db)) + goto err; + /* if processing by chunks, continue until the whole value is parsed */ + } while (rv == 1 && max_len != 0); return 1; @@ -340,6 +361,66 @@ static int parse_bin(const char *value, unsigned char **buf, size_t *buflen) return 1; } +/* + * Convert at maximum "max" bytes to a binary allocated buffer. + * Return 1 on success, -1 on failure or 0 for end of value string. + */ +static int parse_bin_chunk(const char *value, size_t offset, size_t max, + unsigned char **buf, size_t *buflen, size_t *out_offset) +{ + size_t vlen; + size_t chunk_len; + const char *value_str = value[0] == '"' ? value + offset + 1 : value + offset; + + if (max < 1) + return -1; + + if (*value == '\0' || strcmp(value, "\"\"") == 0) { + *buf = OPENSSL_malloc(1); + if (*buf == NULL) + return 0; + **buf = 0; + *buflen = 0; + return 0; + } + + if (*value_str == '\0') + return 0; + + vlen = strlen(value_str); + if (value[0] == '"') { + /* Parse string literal */ + if (vlen == 1 && value_str[0] != '"') + /* Missing ending quotation mark */ + return -1; + if (vlen == 1 && value_str[0] == '"') + /* End of value */ + return 0; + vlen--; + chunk_len = max > vlen ? vlen : max; + if ((*buf = unescape(value_str, chunk_len, buflen)) == NULL) + return -1; + } else { + /* Parse hex string chunk */ + long len; + char *chunk = NULL; + + chunk_len = 2 * max > vlen ? vlen : 2 * max; + chunk = OPENSSL_strndup(value_str, chunk_len); + if (chunk == NULL) + return -1; + if (!TEST_ptr(*buf = OPENSSL_hexstr2buf(chunk, &len))) { + OPENSSL_free(chunk); + TEST_info("Can't convert chunk %s", chunk); + TEST_openssl_errors(); + return -1; + } + *buflen = len; + } + *out_offset = value[0] == '"' ? offset + (*buflen) : offset + 2 * (*buflen); + return 1; +} + /** ** MESSAGE DIGEST TESTS **/ @@ -403,7 +484,7 @@ static int digest_test_parse(EVP_TEST *t, DIGEST_DATA *mdata = t->data; if (strcmp(keyword, "Input") == 0) - return evp_test_buffer_append(value, &mdata->input); + return evp_test_buffer_append(value, data_chunk_size, &mdata->input); if (strcmp(keyword, "Output") == 0) return parse_bin(value, &mdata->output, &mdata->output_len); if (strcmp(keyword, "Count") == 0) @@ -3482,12 +3563,12 @@ static int digestsigver_test_parse(EVP_TEST *t, if (strcmp(keyword, "Input") == 0) { if (mdata->is_oneshot) return parse_bin(value, &mdata->osin, &mdata->osin_len); - return evp_test_buffer_append(value, &mdata->input); + return evp_test_buffer_append(value, data_chunk_size, &mdata->input); } if (strcmp(keyword, "Output") == 0) return parse_bin(value, &mdata->output, &mdata->output_len); - if (!mdata->is_oneshot) { + if (!mdata->is_oneshot && data_chunk_size == 0) { if (strcmp(keyword, "Count") == 0) return evp_test_buffer_set_count(value, mdata->input); if (strcmp(keyword, "Ncopy") == 0) From 5f4983f99b50b02392336da93ada70ea4f77b1eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= Date: Wed, 2 Aug 2023 16:34:12 +0200 Subject: [PATCH 04/21] Add processing by chunks to encoding tests Reviewed-by: Dmitry Belyavskiy Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/21727) --- test/evp_test.c | 49 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/test/evp_test.c b/test/evp_test.c index d08ce28971941..76e3b0c521653 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -2552,6 +2552,7 @@ static int encode_test_run(EVP_TEST *t) unsigned char *encode_out = NULL, *decode_out = NULL; int output_len, chunk_len; EVP_ENCODE_CTX *decode_ctx = NULL, *encode_ctx = NULL; + size_t input_len, donelen; if (!TEST_ptr(decode_ctx = EVP_ENCODE_CTX_new())) { t->err = "INTERNAL_ERROR"; @@ -2566,13 +2567,25 @@ static int encode_test_run(EVP_TEST *t) goto err; EVP_EncodeInit(encode_ctx); - if (!TEST_true(EVP_EncodeUpdate(encode_ctx, encode_out, &chunk_len, - expected->input, expected->input_len))) - goto err; - output_len = chunk_len; + input_len = expected->input_len; + donelen = 0; + output_len = 0; + do { + size_t current_len = (size_t) data_chunk_size; + + if (data_chunk_size == 0 || (size_t) data_chunk_size > input_len) + current_len = input_len; + if (!TEST_true(EVP_EncodeUpdate(encode_ctx, encode_out, &chunk_len, + expected->input + donelen, + current_len))) + goto err; + donelen += current_len; + input_len -= current_len; + output_len += chunk_len; + } while (input_len > 0); - EVP_EncodeFinal(encode_ctx, encode_out + chunk_len, &chunk_len); + EVP_EncodeFinal(encode_ctx, encode_out + output_len, &chunk_len); output_len += chunk_len; if (!memory_err_compare(t, "BAD_ENCODING", @@ -2585,15 +2598,27 @@ static int encode_test_run(EVP_TEST *t) OPENSSL_malloc(EVP_DECODE_LENGTH(expected->output_len)))) goto err; + output_len = 0; EVP_DecodeInit(decode_ctx); - if (EVP_DecodeUpdate(decode_ctx, decode_out, &chunk_len, expected->output, - expected->output_len) < 0) { - t->err = "DECODE_ERROR"; - goto err; - } - output_len = chunk_len; - if (EVP_DecodeFinal(decode_ctx, decode_out + chunk_len, &chunk_len) != 1) { + input_len = expected->output_len; + donelen = 0; + do { + size_t current_len = (size_t) data_chunk_size; + + if (data_chunk_size == 0 || (size_t) data_chunk_size > input_len) + current_len = input_len; + if (EVP_DecodeUpdate(decode_ctx, decode_out + output_len, &chunk_len, + expected->output + donelen, current_len) < 0) { + t->err = "DECODE_ERROR"; + goto err; + } + donelen += current_len; + input_len -= current_len; + output_len += chunk_len; + } while (input_len > 0); + + if (EVP_DecodeFinal(decode_ctx, decode_out + output_len, &chunk_len) != 1) { t->err = "DECODE_ERROR"; goto err; } From fedbfff42d790c7b7824351c35b4823c75da6417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= Date: Tue, 8 Aug 2023 16:04:03 +0200 Subject: [PATCH 05/21] Add processing by chunks to mac tests Reviewed-by: Dmitry Belyavskiy Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/21727) --- test/evp_test.c | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/test/evp_test.c b/test/evp_test.c index 76e3b0c521653..5da782d0def45 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -1524,6 +1524,7 @@ static int mac_test_run_pkey(EVP_TEST *t) unsigned char *got = NULL; size_t got_len; int i; + size_t input_len, donelen; /* We don't do XOF mode via PKEY */ if (expected->xof) @@ -1593,10 +1594,21 @@ static int mac_test_run_pkey(EVP_TEST *t) t->err = "EVPPKEYCTXCTRL_ERROR"; goto err; } - if (!EVP_DigestSignUpdate(mctx, expected->input, expected->input_len)) { - t->err = "DIGESTSIGNUPDATE_ERROR"; - goto err; - } + input_len = expected->input_len; + donelen = 0; + do { + size_t current_len = (size_t) data_chunk_size; + + if (data_chunk_size == 0 || (size_t) data_chunk_size > input_len) + current_len = input_len; + if (!EVP_DigestSignUpdate(mctx, expected->input + donelen, current_len)) { + t->err = "DIGESTSIGNUPDATE_ERROR"; + goto err; + } + donelen += current_len; + input_len -= current_len; + } while (input_len > 0); + if (!EVP_DigestSignFinal(mctx, NULL, &got_len)) { t->err = "DIGESTSIGNFINAL_LENGTH_ERROR"; goto err; @@ -1637,6 +1649,7 @@ static int mac_test_run_mac(EVP_TEST *t) EVP_MAC_settable_ctx_params(expected->mac); int xof; int reinit = 1; + size_t input_len, donelen ; if (expected->alg == NULL) TEST_info("Trying the EVP_MAC %s test", expected->mac_name); @@ -1783,10 +1796,21 @@ static int mac_test_run_mac(EVP_TEST *t) } } retry: - if (!EVP_MAC_update(ctx, expected->input, expected->input_len)) { - t->err = "MAC_UPDATE_ERROR"; - goto err; - } + input_len = expected->input_len; + donelen = 0; + do { + size_t current_len = (size_t) data_chunk_size; + + if (data_chunk_size == 0 || (size_t) data_chunk_size > input_len) + current_len = input_len; + if (!EVP_MAC_update(ctx, expected->input + donelen, current_len)) { + t->err = "MAC_UPDATE_ERROR"; + goto err; + } + donelen += current_len; + input_len -= current_len; + } while (input_len > 0); + xof = expected->xof; if (xof) { if (!TEST_ptr(got = OPENSSL_malloc(expected->output_len))) { From 6d2a01cdfb56fdb8ea5d5dd417724e6906c8b8e2 Mon Sep 17 00:00:00 2001 From: Bernd Edlinger Date: Thu, 7 Sep 2023 18:05:44 +0200 Subject: [PATCH 06/21] Fix error handling in CMS_EncryptedData_encrypt That caused several memory leaks in case of error. Also when the CMS object that is created by CMS_EncryptedData_encrypt is not used in the normal way, but instead just deleted by CMS_ContentInfo_free some memory was lost. Fixes #21985 Reviewed-by: Todd Short Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/22031) --- crypto/cms/cms_asn1.c | 19 +++++++++++++++++-- crypto/cms/cms_env.c | 13 +++---------- crypto/cms/cms_lib.c | 15 +-------------- crypto/cms/cms_local.h | 2 +- crypto/cms/cms_sd.c | 20 ++++++++++++++++++-- crypto/cms/cms_smime.c | 3 ++- test/recipes/80-test_cms.t | 7 +++++++ 7 files changed, 49 insertions(+), 30 deletions(-) diff --git a/crypto/cms/cms_asn1.c b/crypto/cms/cms_asn1.c index bc6b2769f98cd..9ac848e448b94 100644 --- a/crypto/cms/cms_asn1.c +++ b/crypto/cms/cms_asn1.c @@ -51,6 +51,7 @@ static int cms_si_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, EVP_PKEY_free(si->pkey); X509_free(si->signer); EVP_MD_CTX_free(si->mctx); + EVP_PKEY_CTX_free(si->pctx); } return 1; } @@ -90,11 +91,21 @@ ASN1_SEQUENCE(CMS_OriginatorInfo) = { ASN1_IMP_SET_OF_OPT(CMS_OriginatorInfo, crls, CMS_RevocationInfoChoice, 1) } static_ASN1_SEQUENCE_END(CMS_OriginatorInfo) -ASN1_NDEF_SEQUENCE(CMS_EncryptedContentInfo) = { +static int cms_ec_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + CMS_EncryptedContentInfo *ec = (CMS_EncryptedContentInfo *)*pval; + + if (operation == ASN1_OP_FREE_POST) + OPENSSL_clear_free(ec->key, ec->keylen); + return 1; +} + +ASN1_NDEF_SEQUENCE_cb(CMS_EncryptedContentInfo, cms_ec_cb) = { ASN1_SIMPLE(CMS_EncryptedContentInfo, contentType, ASN1_OBJECT), ASN1_SIMPLE(CMS_EncryptedContentInfo, contentEncryptionAlgorithm, X509_ALGOR), ASN1_IMP_OPT(CMS_EncryptedContentInfo, encryptedContent, ASN1_OCTET_STRING_NDEF, 0) -} static_ASN1_NDEF_SEQUENCE_END(CMS_EncryptedContentInfo) +} ASN1_NDEF_SEQUENCE_END_cb(CMS_EncryptedContentInfo, CMS_EncryptedContentInfo) ASN1_SEQUENCE(CMS_KeyTransRecipientInfo) = { ASN1_EMBED(CMS_KeyTransRecipientInfo, version, INT32), @@ -318,6 +329,10 @@ static int cms_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, return 0; break; + case ASN1_OP_FREE_POST: + OPENSSL_free(cms->ctx.propq); + break; + } return 1; } diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c index b877e106199ae..37dfbe538935f 100644 --- a/crypto/cms/cms_env.c +++ b/crypto/cms/cms_env.c @@ -51,15 +51,6 @@ static int cms_get_enveloped_type(const CMS_ContentInfo *cms) return ret; } -void ossl_cms_env_enc_content_free(const CMS_ContentInfo *cinf) -{ - if (cms_get_enveloped_type_simple(cinf) != 0) { - CMS_EncryptedContentInfo *ec = ossl_cms_get0_env_enc_content(cinf); - if (ec != NULL) - OPENSSL_clear_free(ec->key, ec->keylen); - } -} - CMS_EnvelopedData *ossl_cms_get0_enveloped(CMS_ContentInfo *cms) { if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped) { @@ -289,8 +280,10 @@ BIO *CMS_EnvelopedData_decrypt(CMS_EnvelopedData *env, BIO *detached_data, secret == NULL ? cert : NULL, detached_data, bio, flags); end: - if (ci != NULL) + if (ci != NULL) { ci->d.envelopedData = NULL; /* do not indirectly free |env| */ + ci->contentType = NULL; + } CMS_ContentInfo_free(ci); if (!res) { BIO_free(bio); diff --git a/crypto/cms/cms_lib.c b/crypto/cms/cms_lib.c index afc210c9d0c8a..759e1d46af4cc 100644 --- a/crypto/cms/cms_lib.c +++ b/crypto/cms/cms_lib.c @@ -21,6 +21,7 @@ static STACK_OF(CMS_CertificateChoices) **cms_get0_certificate_choices(CMS_ContentInfo *cms); +IMPLEMENT_ASN1_ALLOC_FUNCTIONS(CMS_ContentInfo) IMPLEMENT_ASN1_PRINT_FUNCTION(CMS_ContentInfo) CMS_ContentInfo *d2i_CMS_ContentInfo(CMS_ContentInfo **a, @@ -66,20 +67,6 @@ CMS_ContentInfo *CMS_ContentInfo_new_ex(OSSL_LIB_CTX *libctx, const char *propq) return ci; } -CMS_ContentInfo *CMS_ContentInfo_new(void) -{ - return CMS_ContentInfo_new_ex(NULL, NULL); -} - -void CMS_ContentInfo_free(CMS_ContentInfo *cms) -{ - if (cms != NULL) { - ossl_cms_env_enc_content_free(cms); - OPENSSL_free(cms->ctx.propq); - ASN1_item_free((ASN1_VALUE *)cms, ASN1_ITEM_rptr(CMS_ContentInfo)); - } -} - const CMS_CTX *ossl_cms_get0_cmsctx(const CMS_ContentInfo *cms) { return cms != NULL ? &cms->ctx : NULL; diff --git a/crypto/cms/cms_local.h b/crypto/cms/cms_local.h index 7069021267def..a2b72484c633c 100644 --- a/crypto/cms/cms_local.h +++ b/crypto/cms/cms_local.h @@ -366,6 +366,7 @@ struct CMS_Receipt_st { DECLARE_ASN1_FUNCTIONS(CMS_ContentInfo) DECLARE_ASN1_ITEM(CMS_SignerInfo) +DECLARE_ASN1_ITEM(CMS_EncryptedContentInfo) DECLARE_ASN1_ITEM(CMS_IssuerAndSerialNumber) DECLARE_ASN1_ITEM(CMS_Attributes_Sign) DECLARE_ASN1_ITEM(CMS_Attributes_Verify) @@ -447,7 +448,6 @@ BIO *ossl_cms_EnvelopedData_init_bio(CMS_ContentInfo *cms); int ossl_cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain); BIO *ossl_cms_AuthEnvelopedData_init_bio(CMS_ContentInfo *cms); int ossl_cms_AuthEnvelopedData_final(CMS_ContentInfo *cms, BIO *cmsbio); -void ossl_cms_env_enc_content_free(const CMS_ContentInfo *cinf); CMS_EnvelopedData *ossl_cms_get0_enveloped(CMS_ContentInfo *cms); CMS_AuthEnvelopedData *ossl_cms_get0_auth_enveloped(CMS_ContentInfo *cms); CMS_EncryptedContentInfo *ossl_cms_get0_env_enc_content(const CMS_ContentInfo *cms); diff --git a/crypto/cms/cms_sd.c b/crypto/cms/cms_sd.c index b41e3571b2ff7..a76e795df588b 100644 --- a/crypto/cms/cms_sd.c +++ b/crypto/cms/cms_sd.c @@ -512,8 +512,12 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, ossl_cms_ctx_get0_libctx(ctx), ossl_cms_ctx_get0_propq(ctx), pk, NULL) <= 0) { + si->pctx = NULL; goto err; } + else { + EVP_MD_CTX_set_flags(si->mctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX); + } } if (sd->signerInfos == NULL) @@ -758,6 +762,7 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, unsigned char computed_md[EVP_MAX_MD_SIZE]; pctx = si->pctx; + si->pctx = NULL; if (md == NULL) { if (!EVP_DigestFinal_ex(mctx, computed_md, &mdlen)) goto err; @@ -851,6 +856,7 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si) ossl_cms_ctx_get0_propq(ctx), si->pkey, NULL) <= 0) goto err; + EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX); si->pctx = pctx; } @@ -922,9 +928,16 @@ int CMS_SignerInfo_verify(CMS_SignerInfo *si) goto err; } mctx = si->mctx; + if (si->pctx != NULL) { + EVP_PKEY_CTX_free(si->pctx); + si->pctx = NULL; + } if (EVP_DigestVerifyInit_ex(mctx, &si->pctx, EVP_MD_get0_name(md), libctx, - propq, si->pkey, NULL) <= 0) + propq, si->pkey, NULL) <= 0) { + si->pctx = NULL; goto err; + } + EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX); if (!cms_sd_asn1_ctrl(si, 1)) goto err; @@ -1040,8 +1053,11 @@ int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain) if (EVP_PKEY_CTX_set_signature_md(pkctx, md) <= 0) goto err; si->pctx = pkctx; - if (!cms_sd_asn1_ctrl(si, 1)) + if (!cms_sd_asn1_ctrl(si, 1)) { + si->pctx = NULL; goto err; + } + si->pctx = NULL; r = EVP_PKEY_verify(pkctx, si->signature->data, si->signature->length, mval, mlen); if (r <= 0) { diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c index 99a72f4dffe3c..4df4487cbc28f 100644 --- a/crypto/cms/cms_smime.c +++ b/crypto/cms/cms_smime.c @@ -236,7 +236,7 @@ CMS_ContentInfo *CMS_EncryptedData_encrypt_ex(BIO *in, const EVP_CIPHER *cipher, if (cms == NULL) return NULL; if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen)) - return NULL; + goto err; if (!(flags & CMS_DETACHED)) CMS_set_detached(cms, 0); @@ -245,6 +245,7 @@ CMS_ContentInfo *CMS_EncryptedData_encrypt_ex(BIO *in, const EVP_CIPHER *cipher, || CMS_final(cms, in, NULL, flags)) return cms; + err: CMS_ContentInfo_free(cms); return NULL; } diff --git a/test/recipes/80-test_cms.t b/test/recipes/80-test_cms.t index 6a9792128be15..07014945a7d82 100644 --- a/test/recipes/80-test_cms.t +++ b/test/recipes/80-test_cms.t @@ -394,6 +394,13 @@ my @smime_cms_tests = ( "-out", "{output}.txt" ], \&final_compare ], + + [ "encrypted content test streaming PEM format -noout, 128 bit AES key", + [ "{cmd1}", @prov, "-EncryptedData_encrypt", "-in", $smcont, "-outform", "PEM", + "-aes128", "-secretkey", "000102030405060708090A0B0C0D0E0F", + "-stream", "-noout" ], + [ "{cmd2}", @prov, "-help" ] + ], ); my @smime_cms_cades_tests = ( From 51fd52b8a791528971ca13aa4db94e5d50804b29 Mon Sep 17 00:00:00 2001 From: Dimitri John Ledkov Date: Sun, 28 Apr 2024 20:27:22 +0100 Subject: [PATCH 07/21] gitignore: ignore newly generated header Ignore generated include/openssl/x509_acert.h introduced in https://github.com/openssl/openssl/pull/15857 Signed-off-by: Dimitri John Ledkov Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/24287) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 98184721f2285..d2de49876dde9 100644 --- a/.gitignore +++ b/.gitignore @@ -54,6 +54,7 @@ /include/openssl/ui.h /include/openssl/x509.h /include/openssl/x509v3.h +/include/openssl/x509_acert.h /include/openssl/x509_vfy.h /include/openssl/core_names.h /include/internal/param_names.h From 327261c076b8468382e1effea14d79446cc22b4d Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Wed, 1 May 2024 20:03:13 +0000 Subject: [PATCH 08/21] test/threadstest.c: Add checks for CRYPTO_THREAD_lock_new() Add checks for the return value of CRYPTO_THREAD_lock_new() in order to avoid Null pointer dereference. Fixes: 5f8b812931 ("Add locking to atomic operations in rw/rcu tests") Fixes: d0e1a0ae70 ("RCU lock implementation") Fixes: 71a04cfca0 ("Implement new multi-threading API") Signed-off-by: Jiasheng Jiang Reviewed-by: Neil Horman Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/24313) --- test/threadstest.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/threadstest.c b/test/threadstest.c index 0e42d63e10f94..9a961bb5c4cc3 100644 --- a/test/threadstest.c +++ b/test/threadstest.c @@ -90,6 +90,9 @@ static int test_lock(void) CRYPTO_RWLOCK *lock = CRYPTO_THREAD_lock_new(); int res; + if (!TEST_ptr(lock)) + return 0; + res = TEST_true(CRYPTO_THREAD_read_lock(lock)) && TEST_true(CRYPTO_THREAD_unlock(lock)) && TEST_true(CRYPTO_THREAD_write_lock(lock)) @@ -225,6 +228,9 @@ static int _torture_rw(void) rwtorturelock = CRYPTO_THREAD_lock_new(); atomiclock = CRYPTO_THREAD_lock_new(); + if (!TEST_ptr(rwtorturelock) || !TEST_ptr(atomiclock)) + goto out; + rwwriter1_iterations = 0; rwwriter2_iterations = 0; rwreader1_iterations = 0; @@ -413,6 +419,9 @@ static int _torture_rcu(void) int rc = 0; atomiclock = CRYPTO_THREAD_lock_new(); + if (!TEST_ptr(atomiclock)) + goto out; + memset(&writer1, 0, sizeof(thread_t)); memset(&writer2, 0, sizeof(thread_t)); memset(&reader1, 0, sizeof(thread_t)); @@ -427,6 +436,8 @@ static int _torture_rcu(void) rcu_torture_result = 1; rcu_lock = ossl_rcu_lock_new(1, NULL); + if (!rcu_lock) + goto out; TEST_info("Staring rcu torture"); t1 = ossl_time_now(); From c8dddc61d49f84d1667de97e9548f07ccc92dddf Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Mon, 29 Apr 2024 16:58:24 +0100 Subject: [PATCH 09/21] Add a test for the session_secret_cb Ensure that if a session_secret_cb is being used that a connection can be successfully made Reviewed-by: Neil Horman Reviewed-by: Dmitry Belyavskiy Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/24309) --- test/sslapitest.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/test/sslapitest.c b/test/sslapitest.c index b57ca8b113333..e948ae01a2a9c 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -10121,6 +10121,94 @@ static int test_ssl_dup(void) return testresult; } +static int secret_cb(SSL *s, void *secretin, int *secret_len, + STACK_OF(SSL_CIPHER) *peer_ciphers, + const SSL_CIPHER **cipher, void *arg) +{ + int i; + unsigned char *secret = secretin; + + /* Just use a fixed master secret */ + for (i = 0; i < *secret_len; i++) + secret[i] = 0xff; + + /* We don't set a preferred cipher */ + + return 1; +} + +/* + * Test the session_secret_cb which is designed for use with EAP-FAST + */ +static int test_session_secret_cb(void) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + SSL_SESSION *secret_sess = NULL; + int testresult = 0; + + if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), + TLS_client_method(), + 0, + 0, + &sctx, &cctx, cert, privkey))) + goto end; + + /* Create an initial connection and save the session */ + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL))) + goto end; + + /* session_secret_cb does not support TLSv1.3 */ + if (!TEST_true(SSL_set_min_proto_version(clientssl, TLS1_2_VERSION)) + || !TEST_true(SSL_set_max_proto_version(serverssl, TLS1_2_VERSION))) + goto end; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) + goto end; + + if (!TEST_ptr(secret_sess = SSL_get1_session(clientssl))) + goto end; + + shutdown_ssl_connection(serverssl, clientssl); + serverssl = clientssl = NULL; + + /* Resume the earlier session */ + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL))) + goto end; + + /* + * No session ids for EAP-FAST - otherwise the state machine gets very + * confused. + */ + if (!TEST_true(SSL_SESSION_set1_id(secret_sess, NULL, 0))) + goto end; + + if (!TEST_true(SSL_set_min_proto_version(clientssl, TLS1_2_VERSION)) + || !TEST_true(SSL_set_max_proto_version(serverssl, TLS1_2_VERSION)) + || !TEST_true(SSL_set_session_secret_cb(serverssl, secret_cb, + NULL)) + || !TEST_true(SSL_set_session_secret_cb(clientssl, secret_cb, + NULL)) + || !TEST_true(SSL_set_session(clientssl, secret_sess))) + goto end; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) + goto end; + + testresult = 1; + + end: + SSL_SESSION_free(secret_sess); + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + + return testresult; +} + # ifndef OPENSSL_NO_DH static EVP_PKEY *tmp_dh_params = NULL; @@ -12144,6 +12232,7 @@ int setup_tests(void) #endif #ifndef OPENSSL_NO_TLS1_2 ADD_TEST(test_ssl_dup); + ADD_TEST(test_session_secret_cb); # ifndef OPENSSL_NO_DH ADD_ALL_TESTS(test_set_tmp_dh, 11); ADD_ALL_TESTS(test_dh_auto, 7); From 91c7ab27cebe4e6f6a6376e0a691736a2534fdd0 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Tue, 30 Apr 2024 14:31:26 +0100 Subject: [PATCH 10/21] Set the server sig algs before calling the session_secret_cb Setting the server sig algs sets up the certificate "s3->tmp.valid_flags". These are needed when calling ssl3_choose_cipher() which can happen immediately after calling the session_secret_cb Fixes #24213 Reviewed-by: Neil Horman Reviewed-by: Dmitry Belyavskiy Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/24309) --- ssl/statem/statem_srvr.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index 47855da5bd13b..1c38548fe047d 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -1959,6 +1959,11 @@ static int tls_early_post_process_client_hello(SSL_CONNECTION *s) } } + if (!s->hit && !tls1_set_server_sigalgs(s)) { + /* SSLfatal() already called */ + goto err; + } + if (!s->hit && s->version >= TLS1_VERSION && !SSL_CONNECTION_IS_TLS13(s) @@ -2110,10 +2115,6 @@ static int tls_early_post_process_client_hello(SSL_CONNECTION *s) #else s->session->compress_meth = (comp == NULL) ? 0 : comp->id; #endif - if (!tls1_set_server_sigalgs(s)) { - /* SSLfatal() already called */ - goto err; - } } sk_SSL_CIPHER_free(ciphers); From aecaaccaf93c4b36dd830accf08f2175059c5782 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Tue, 30 Apr 2024 15:35:42 +0100 Subject: [PATCH 11/21] Document the SSL_set_session_secret_cb() function This function is only useful for EAP-FAST, but was previously undocumented. Reviewed-by: Neil Horman Reviewed-by: Dmitry Belyavskiy Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/24309) --- doc/build.info | 6 +++ doc/man3/SSL_set_session_secret_cb.pod | 69 ++++++++++++++++++++++++++ util/missingssl.txt | 1 - util/other.syms | 1 + 4 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 doc/man3/SSL_set_session_secret_cb.pod diff --git a/doc/build.info b/doc/build.info index aab005baaef8d..3214d0843b474 100644 --- a/doc/build.info +++ b/doc/build.info @@ -2747,6 +2747,10 @@ DEPEND[html/man3/SSL_set_session.html]=man3/SSL_set_session.pod GENERATE[html/man3/SSL_set_session.html]=man3/SSL_set_session.pod DEPEND[man/man3/SSL_set_session.3]=man3/SSL_set_session.pod GENERATE[man/man3/SSL_set_session.3]=man3/SSL_set_session.pod +DEPEND[html/man3/SSL_set_session_secret_cb.html]=man3/SSL_set_session_secret_cb.pod +GENERATE[html/man3/SSL_set_session_secret_cb.html]=man3/SSL_set_session_secret_cb.pod +DEPEND[man/man3/SSL_set_session_secret_cb.3]=man3/SSL_set_session_secret_cb.pod +GENERATE[man/man3/SSL_set_session_secret_cb.3]=man3/SSL_set_session_secret_cb.pod DEPEND[html/man3/SSL_set_shutdown.html]=man3/SSL_set_shutdown.pod GENERATE[html/man3/SSL_set_shutdown.html]=man3/SSL_set_shutdown.pod DEPEND[man/man3/SSL_set_shutdown.3]=man3/SSL_set_shutdown.pod @@ -3650,6 +3654,7 @@ html/man3/SSL_set_fd.html \ html/man3/SSL_set_incoming_stream_policy.html \ html/man3/SSL_set_retry_verify.html \ html/man3/SSL_set_session.html \ +html/man3/SSL_set_session_secret_cb.html \ html/man3/SSL_set_shutdown.html \ html/man3/SSL_set_verify_result.html \ html/man3/SSL_shutdown.html \ @@ -4303,6 +4308,7 @@ man/man3/SSL_set_fd.3 \ man/man3/SSL_set_incoming_stream_policy.3 \ man/man3/SSL_set_retry_verify.3 \ man/man3/SSL_set_session.3 \ +man/man3/SSL_set_session_secret_cb.3 \ man/man3/SSL_set_shutdown.3 \ man/man3/SSL_set_verify_result.3 \ man/man3/SSL_shutdown.3 \ diff --git a/doc/man3/SSL_set_session_secret_cb.pod b/doc/man3/SSL_set_session_secret_cb.pod new file mode 100644 index 0000000000000..e79d81d40a3ff --- /dev/null +++ b/doc/man3/SSL_set_session_secret_cb.pod @@ -0,0 +1,69 @@ +=pod + +=head1 NAME + +SSL_set_session_secret_cb, tls_session_secret_cb_fn +- set the session secret callback + +=head1 SYNOPSIS + + #include + + typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, + STACK_OF(SSL_CIPHER) *peer_ciphers, + const SSL_CIPHER **cipher, void *arg); + + int SSL_set_session_secret_cb(SSL *s, + tls_session_secret_cb_fn session_secret_cb, + void *arg); + +=head1 DESCRIPTION + +SSL_set_session_secret_cb() sets the session secret callback to be used +(I), and an optional argument (I) to be passed to that +callback when it is called. This is only useful for an implementation of +EAP-FAST (RFC4851). The presence of the callback also modifies the internal +OpenSSL TLS state machine to match the modified TLS behaviour as described in +RFC4851. Therefore this callback should not be used except when implementing +EAP-FAST. + +The callback is expected to set the master secret to be used by filling in the +data pointed to by I<*secret>. The size of the secret buffer is initially +available in I<*secret_len> and may be updated by the callback (but must not be +larger than the initial value). + +On the server side the set of ciphersuites offered by the peer is provided in +the I stack. Optionally the callback may select the preferred +ciphersuite by setting it in I<*cipher>. + +On the client side the I stack will always be NULL. The callback +may specify the preferred cipher in I<*cipher> and this will be associated with +the B - but it does not affect the ciphersuite selected by the +server. + +The callback is also supplied with an additional argument in I which is the +argument that was provided to the original SSL_set_session_secret_cb() call. + +=head1 RETURN VALUES + +SSL_set_session_secret_cb() returns 1 on success and 0 on failure. + +If the callback returns 1 then this indicates it has successfully set the +secret. A return value of 0 indicates that the secret has not been set. On the +client this will cause an immediate abort of the handshake. + +=head1 SEE ALSO + +L, +L + +=head1 COPYRIGHT + +Copyright 2024 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/util/missingssl.txt b/util/missingssl.txt index 1338feed71188..8da9842a0b57d 100644 --- a/util/missingssl.txt +++ b/util/missingssl.txt @@ -25,7 +25,6 @@ SSL_get_peer_finished(3) SSL_set_SSL_CTX(3) SSL_set_debug(3) SSL_set_not_resumable_session_callback(3) -SSL_set_session_secret_cb(3) SSL_set_session_ticket_ext(3) SSL_set_session_ticket_ext_cb(3) SSL_srp_server_param_with_username(3) diff --git a/util/other.syms b/util/other.syms index df47478f5207c..6bffe6bf186f9 100644 --- a/util/other.syms +++ b/util/other.syms @@ -145,6 +145,7 @@ custom_ext_free_cb datatype custom_ext_parse_cb datatype pem_password_cb datatype ssl_ct_validation_cb datatype +tls_session_secret_cb_fn datatype ASYNC_stack_alloc_fn datatype ASYNC_stack_free_fn datatype PKCS12_create_cb datatype From 97c6489b39c966c6e5169b9b92ec5fa9a35c7ba3 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Wed, 1 May 2024 11:23:57 +0100 Subject: [PATCH 12/21] Fix undefined behaviour in the event of a zero length session id Don't attempt to memcpy a NULL pointer if the length is 0. Reviewed-by: Neil Horman Reviewed-by: Dmitry Belyavskiy Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/24309) --- ssl/ssl_sess.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index eaa9595f8c2f2..3857e027ee0d1 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c @@ -907,8 +907,9 @@ int SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid, return 0; } s->session_id_length = sid_len; - if (sid != s->session_id) + if (sid != s->session_id && sid_len > 0) memcpy(s->session_id, sid, sid_len); + return 1; } From 1c4f9684696bad3a602b388a414f2051f0365b3d Mon Sep 17 00:00:00 2001 From: Craig Lorentzen Date: Mon, 1 Apr 2024 11:49:44 -0400 Subject: [PATCH 13/21] Security hardening: Expose Build flags for Position Independed Execution (PIE) Reviewed-by: Tom Cosgrove Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/22596) --- .github/workflows/run-checker-merge.yml | 1 + CHANGES.md | 7 +++++++ Configurations/00-base-templates.conf | 16 ++++++++++++++++ Configure | 6 ++++++ INSTALL.md | 4 ++++ 5 files changed, 34 insertions(+) diff --git a/.github/workflows/run-checker-merge.yml b/.github/workflows/run-checker-merge.yml index e5746d75bdf8c..8a1da0c2f2a5b 100644 --- a/.github/workflows/run-checker-merge.yml +++ b/.github/workflows/run-checker-merge.yml @@ -35,6 +35,7 @@ jobs: no-ts, enable-weak-ssl-ciphers, enable-zlib, + enable-pie, ] runs-on: ubuntu-latest steps: diff --git a/CHANGES.md b/CHANGES.md index 21fd185444d77..1258a44b5239e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -59,6 +59,13 @@ OpenSSL 3.4 *Damian Hobson-Garcia* + * Added support to build Position Independent Executables (PIE). Configuration + option `enable-pie` configures the cflag '-fPIE' and ldflag '-pie' to + support Address Space Layout Randomization (ASLR) in the openssl executable, + removes reliance on external toolchain configurations. + + *Craig Lorentzen* + OpenSSL 3.3 ----------- diff --git a/Configurations/00-base-templates.conf b/Configurations/00-base-templates.conf index 55da5ec56c200..a9ccb0ced8792 100644 --- a/Configurations/00-base-templates.conf +++ b/Configurations/00-base-templates.conf @@ -76,6 +76,22 @@ my %targets=( AR => "ar", ARFLAGS => "qc", CC => "cc", + bin_cflags => + sub { + my @flags = (); + if (!defined($disabled{pie})) { + push(@flags, "-fPIE"); + } + return join(" ", @flags); + }, + bin_lflags => + sub { + my @flags = (); + if (!defined($disabled{pie})) { + push(@flags, "-pie"); + } + return join(" ", @flags); + }, lflags => sub { my @libs = (); diff --git a/Configure b/Configure index cef9e8c3e6662..f7fc016c8cab2 100755 --- a/Configure +++ b/Configure @@ -492,6 +492,7 @@ my @disablables = ( "ocsp", "padlockeng", "pic", + "pie", "pinshared", "poly1305", "posix-io", @@ -584,6 +585,7 @@ our %disabled = ( # "what" => "comment" "external-tests" => "default", "fuzz-afl" => "default", "fuzz-libfuzzer" => "default", + "pie" => "default", "ktls" => "default", "md2" => "default", "msan" => "default", @@ -943,6 +945,10 @@ while (@argvcopy) { delete $disabled{"brotli"}; } + elsif ($1 eq "pie") + { + delete $disabled{"pie"}; + } elsif ($1 eq "zstd-dynamic") { delete $disabled{"zstd"}; diff --git a/INSTALL.md b/INSTALL.md index b486ee1556a25..a34de9bbf8c9e 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -870,6 +870,10 @@ As synonym for `no-padlockeng`. Deprecated and should not be used. Don't build with support for Position Independent Code. +### enable-pie + +Build with support for Position Independent Execution. + ### no-pinshared Don't pin the shared libraries. From 0fff6a2cf4c00bc7ead235099af350db61413bd2 Mon Sep 17 00:00:00 2001 From: Florian Greinacher Date: Fri, 3 May 2024 10:46:47 +0200 Subject: [PATCH 14/21] Fix invalid expression syntax The expression had an extra '$' character which made it always evaluate to true. See https://github.com/boostsecurityio/poutine/blob/main/docs/content/en/rules/if_always_true.md. CLA: trivial Reviewed-by: Neil Horman Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/24325) --- .github/workflows/windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 1df44c4f0094b..c24e7f894d1e0 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -66,7 +66,7 @@ jobs: run: nmake test VERBOSE_FAILURE=yes TESTS=-test_fuzz* HARNESS_JOBS=4 - name: install # Run on 64 bit only as 32 bit is slow enough already - if: $${{ matrix.platform.arch == 'win64' }} + if: ${{ matrix.platform.arch == 'win64' }} run: | mkdir _dest nmake install DESTDIR=_dest From 69bd5e4fff8ac9bf4dc3ed6fd87b5a5858edbb01 Mon Sep 17 00:00:00 2001 From: Huiyue Xu Date: Thu, 9 Nov 2023 10:54:02 +0800 Subject: [PATCH 15/21] Add linux-arm64ilp32-clang target While clang 15 config target by '--target', not cannot support '-mabi=ilp32', so add the linux-arm64ilp32-clang target. Signed-off-by: Huiyue Xu Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/22666) --- Configurations/10-main.conf | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Configurations/10-main.conf b/Configurations/10-main.conf index ac30adc2c9ffe..36ecf3b263093 100644 --- a/Configurations/10-main.conf +++ b/Configurations/10-main.conf @@ -777,7 +777,14 @@ my %targets = ( asm_arch => 'aarch64', perlasm_scheme => "linux64", }, - + "linux-arm64ilp32-clang" => { # clang config abi by --target + inherit_from => [ "linux-generic32" ], + CC => "clang", + CXX => "clang++", + bn_ops => "SIXTY_FOUR_BIT RC4_CHAR", + asm_arch => 'aarch64', + perlasm_scheme => "linux64", + }, "linux-mips32" => { # Configure script adds minimally required -march for assembly # support, if no -march was specified at command line. From 57bb112c07116d1cdbf5bc8562ebb3e7990f291c Mon Sep 17 00:00:00 2001 From: shridhar kalavagunta Date: Thu, 11 Jan 2024 17:01:23 -0600 Subject: [PATCH 16/21] Move ossl_asn1_string_to_time_t() to libtestutil It is not used anywhere else than in tests. Fixes #22965 Reviewed-by: Hugo Landau Reviewed-by: Tom Cosgrove Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/23269) --- crypto/asn1/a_time.c | 75 --------------------------------- include/crypto/asn1.h | 1 - test/asn1_time_test.c | 4 +- test/build.info | 2 +- test/ca_internals_test.c | 2 +- test/testutil.h | 2 +- test/testutil/helper.c | 90 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 95 insertions(+), 81 deletions(-) create mode 100644 test/testutil/helper.c diff --git a/crypto/asn1/a_time.c b/crypto/asn1/a_time.c index 96ee63d3104ce..7dfbc5faabd15 100644 --- a/crypto/asn1/a_time.c +++ b/crypto/asn1/a_time.c @@ -591,78 +591,3 @@ int ASN1_TIME_compare(const ASN1_TIME *a, const ASN1_TIME *b) return -1; return 0; } - -/* - * tweak for Windows - */ -#ifdef WIN32 -# define timezone _timezone -#endif - -#if defined(__FreeBSD__) || defined(__wasi__) -# define USE_TIMEGM -#endif - -time_t ossl_asn1_string_to_time_t(const char *asn1_string) -{ - ASN1_TIME *timestamp_asn1 = NULL; - struct tm *timestamp_tm = NULL; -#if defined(__DJGPP__) - char *tz = NULL; -#elif !defined(USE_TIMEGM) - time_t timestamp_local; -#endif - time_t timestamp_utc; - - timestamp_asn1 = ASN1_TIME_new(); - if (!ASN1_TIME_set_string(timestamp_asn1, asn1_string)) - { - ASN1_TIME_free(timestamp_asn1); - return -1; - } - - timestamp_tm = OPENSSL_malloc(sizeof(*timestamp_tm)); - if (timestamp_tm == NULL) { - ASN1_TIME_free(timestamp_asn1); - return -1; - } - if (!(ASN1_TIME_to_tm(timestamp_asn1, timestamp_tm))) { - OPENSSL_free(timestamp_tm); - ASN1_TIME_free(timestamp_asn1); - return -1; - } - ASN1_TIME_free(timestamp_asn1); - -#if defined(__DJGPP__) - /* - * This is NOT thread-safe. Do not use this method for platforms other - * than djgpp. - */ - tz = getenv("TZ"); - if (tz != NULL) { - tz = OPENSSL_strdup(tz); - if (tz == NULL) { - OPENSSL_free(timestamp_tm); - return -1; - } - } - setenv("TZ", "UTC", 1); - - timestamp_utc = mktime(timestamp_tm); - - if (tz != NULL) { - setenv("TZ", tz, 1); - OPENSSL_free(tz); - } else { - unsetenv("TZ"); - } -#elif defined(USE_TIMEGM) - timestamp_utc = timegm(timestamp_tm); -#else - timestamp_local = mktime(timestamp_tm); - timestamp_utc = timestamp_local - timezone; -#endif - OPENSSL_free(timestamp_tm); - - return timestamp_utc; -} diff --git a/include/crypto/asn1.h b/include/crypto/asn1.h index 36af1d7689293..b5683f007cf48 100644 --- a/include/crypto/asn1.h +++ b/include/crypto/asn1.h @@ -147,7 +147,6 @@ EVP_PKEY *ossl_d2i_PrivateKey_legacy(int keytype, EVP_PKEY **a, OSSL_LIB_CTX *libctx, const char *propq); X509_ALGOR *ossl_X509_ALGOR_from_nid(int nid, int ptype, void *pval); -time_t ossl_asn1_string_to_time_t(const char *asn1_string); void ossl_asn1_string_set_bits_left(ASN1_STRING *str, unsigned int num); #endif /* ndef OSSL_CRYPTO_ASN1_H */ diff --git a/test/asn1_time_test.c b/test/asn1_time_test.c index 7736fd34161e7..32bc4ff2adb1b 100644 --- a/test/asn1_time_test.c +++ b/test/asn1_time_test.c @@ -434,10 +434,10 @@ static int convert_asn1_to_time_t(int idx) { time_t testdateutc; - testdateutc = ossl_asn1_string_to_time_t(asn1_to_utc[idx].input); + testdateutc = test_asn1_string_to_time_t(asn1_to_utc[idx].input); if (!TEST_time_t_eq(testdateutc, asn1_to_utc[idx].expected)) { - TEST_info("ossl_asn1_string_to_time_t (%s) failed: expected %lli, got %lli\n", + TEST_info("test_asn1_string_to_time_t (%s) failed: expected %lli, got %lli\n", asn1_to_utc[idx].input, (long long int)asn1_to_utc[idx].expected, (long long int)testdateutc); diff --git a/test/build.info b/test/build.info index 9cbca834c8ae0..e2b09ae9650b1 100644 --- a/test/build.info +++ b/test/build.info @@ -26,7 +26,7 @@ IF[{- !$disabled{tests} -}] testutil/format_output.c testutil/load.c testutil/fake_random.c \ testutil/test_cleanup.c testutil/main.c testutil/testutil_init.c \ testutil/options.c testutil/test_options.c testutil/provider.c \ - testutil/apps_shims.c testutil/random.c $LIBAPPSSRC + testutil/apps_shims.c testutil/random.c testutil/helper.c $LIBAPPSSRC INCLUDE[libtestutil.a]=../include ../apps/include .. DEPEND[libtestutil.a]=../libcrypto diff --git a/test/ca_internals_test.c b/test/ca_internals_test.c index 24f7ba3884384..776996b4acad1 100644 --- a/test/ca_internals_test.c +++ b/test/ca_internals_test.c @@ -47,7 +47,7 @@ static int test_do_updatedb(void) } testdate = test_get_argument(2); - testdateutc = ossl_asn1_string_to_time_t(testdate); + testdateutc = test_asn1_string_to_time_t(testdate); if (TEST_time_t_lt(testdateutc, 0)) { return 0; } diff --git a/test/testutil.h b/test/testutil.h index a247f55ed6b83..35fbdab84e85f 100644 --- a/test/testutil.h +++ b/test/testutil.h @@ -648,5 +648,5 @@ X509 *load_cert_pem(const char *file, OSSL_LIB_CTX *libctx); X509 *load_cert_der(const unsigned char *bytes, int len); STACK_OF(X509) *load_certs_pem(const char *file); X509_REQ *load_csr_der(const char *file, OSSL_LIB_CTX *libctx); - +time_t test_asn1_string_to_time_t(const char *asn1_string); #endif /* OSSL_TESTUTIL_H */ diff --git a/test/testutil/helper.c b/test/testutil/helper.c new file mode 100644 index 0000000000000..8da42b0facdb7 --- /dev/null +++ b/test/testutil/helper.c @@ -0,0 +1,90 @@ +/* + * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "../testutil.h" + +/* + * tweak for Windows + */ +#ifdef WIN32 +# define timezone _timezone +#endif + +#if defined(__FreeBSD__) || defined(__wasi__) +# define USE_TIMEGM +#endif + +time_t test_asn1_string_to_time_t(const char *asn1_string) +{ + ASN1_TIME *timestamp_asn1 = NULL; + struct tm *timestamp_tm = NULL; +#if defined(__DJGPP__) + char *tz = NULL; +#elif !defined(USE_TIMEGM) + time_t timestamp_local; +#endif + time_t timestamp_utc; + + timestamp_asn1 = ASN1_TIME_new(); + if(timestamp_asn1 == NULL) + return -1; + if (!ASN1_TIME_set_string(timestamp_asn1, asn1_string)) + { + ASN1_TIME_free(timestamp_asn1); + return -1; + } + + timestamp_tm = OPENSSL_malloc(sizeof(*timestamp_tm)); + if (timestamp_tm == NULL) { + ASN1_TIME_free(timestamp_asn1); + return -1; + } + if (!(ASN1_TIME_to_tm(timestamp_asn1, timestamp_tm))) { + OPENSSL_free(timestamp_tm); + ASN1_TIME_free(timestamp_asn1); + return -1; + } + ASN1_TIME_free(timestamp_asn1); + +#if defined(__DJGPP__) + /* + * This is NOT thread-safe. Do not use this method for platforms other + * than djgpp. + */ + tz = getenv("TZ"); + if (tz != NULL) { + tz = OPENSSL_strdup(tz); + if (tz == NULL) { + OPENSSL_free(timestamp_tm); + return -1; + } + } + setenv("TZ", "UTC", 1); + + timestamp_utc = mktime(timestamp_tm); + + if (tz != NULL) { + setenv("TZ", tz, 1); + OPENSSL_free(tz); + } else { + unsetenv("TZ"); + } +#elif defined(USE_TIMEGM) + timestamp_utc = timegm(timestamp_tm); +#else + timestamp_local = mktime(timestamp_tm); + timestamp_utc = timestamp_local - timezone; +#endif + OPENSSL_free(timestamp_tm); + + return timestamp_utc; +} From deaa83af700113c99835a1db7d45d33baba05bd3 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Mon, 6 May 2024 20:13:52 +0200 Subject: [PATCH 17/21] Fix Coverity issues 1596850, 1596851 and 1596852 These are newly introduced memory leaks and UAF in evp_test.c Reviewed-by: Neil Horman Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/24339) --- test/evp_test.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/evp_test.c b/test/evp_test.c index 5da782d0def45..21106dd63343d 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -411,10 +411,10 @@ static int parse_bin_chunk(const char *value, size_t offset, size_t max, return -1; if (!TEST_ptr(*buf = OPENSSL_hexstr2buf(chunk, &len))) { OPENSSL_free(chunk); - TEST_info("Can't convert chunk %s", chunk); TEST_openssl_errors(); return -1; } + OPENSSL_free(chunk); *buflen = len; } *out_offset = value[0] == '"' ? offset + (*buflen) : offset + 2 * (*buflen); @@ -742,6 +742,8 @@ static int cipher_test_init(EVP_TEST *t, const char *alg) if (data_chunk_size != 0 && !cipher_test_valid_fragmentation(cdat)) { ERR_pop_to_mark(); + EVP_CIPHER_free(fetched_cipher); + OPENSSL_free(cdat); t->skip = 1; TEST_info("skipping, '%s' does not support fragmentation", alg); return 1; From 7cbca5a6d6e792c75c414e1f3fb22e2afae67988 Mon Sep 17 00:00:00 2001 From: Viktor Dukhovni Date: Wed, 27 Mar 2024 18:15:29 -0400 Subject: [PATCH 18/21] Avoid memory leak in x509_test error path Fixes #23897 Reviewed-by: Neil Horman Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/23991) --- test/v3ext.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/test/v3ext.c b/test/v3ext.c index 3cd6ee6907f36..5ebdef2ebe996 100644 --- a/test/v3ext.c +++ b/test/v3ext.c @@ -269,17 +269,20 @@ static int test_addr_fam_len(void) goto end; if (!ASN1_OCTET_STRING_set(f1->addressFamily, key, keylen)) goto end; + + /* Push and transfer memory ownership to stack */ if (!sk_IPAddressFamily_push(addr, f1)) goto end; + f1 = NULL; /* Shouldn't be able to canonize this as the len is > 3*/ if (!TEST_false(X509v3_addr_canonize(addr))) goto end; - /* Create a well formed IPAddressFamily */ - f1 = sk_IPAddressFamily_pop(addr); - IPAddressFamily_free(f1); + /* Pop and free the new stack element */ + IPAddressFamily_free(sk_IPAddressFamily_pop(addr)); + /* Create a well-formed IPAddressFamily */ key[0] = (afi >> 8) & 0xFF; key[1] = afi & 0xFF; key[2] = 0x1; @@ -297,8 +300,11 @@ static int test_addr_fam_len(void) /* Mark this as inheritance so we skip some of the is_canonize checks */ f1->ipAddressChoice->type = IPAddressChoice_inherit; + + /* Push and transfer memory ownership to stack */ if (!sk_IPAddressFamily_push(addr, f1)) goto end; + f1 = NULL; /* Should be able to canonize now */ if (!TEST_true(X509v3_addr_canonize(addr))) @@ -306,7 +312,10 @@ static int test_addr_fam_len(void) testresult = 1; end: + /* Free stack and any memory owned by detached element */ + IPAddressFamily_free(f1); sk_IPAddressFamily_pop_free(addr, IPAddressFamily_free); + ASN1_OCTET_STRING_free(ip1); ASN1_OCTET_STRING_free(ip2); return testresult; From 03ce37e11729bbe9964bd613c0eed6156b920208 Mon Sep 17 00:00:00 2001 From: Yangyu Chen Date: Fri, 19 Apr 2024 11:49:59 +0800 Subject: [PATCH 19/21] riscv: Provide a vector only implementation of Chacha20 cipher Although we have a Zvkb version of Chacha20, the Zvkb from the RISC-V Vector Cryptography Bit-manipulation extension was ratified in late 2023 and does not come to the RVA23 Profile. Many CPUs in 2024 currently do not support Zvkb but may have Vector and Bit-manipulation, which are already in the RVA22 Profile. This commit provides a vector-only implementation that replaced the vror with vsll+vsrl+vor and can provide enough speed for Chacha20 for new CPUs this year. Signed-off-by: Yangyu Chen Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/24069) --- ...64-zbb-zvkb.pl => chacha-riscv64-v-zbb.pl} | 254 ++++++++++-------- crypto/chacha/build.info | 5 +- crypto/chacha/chacha_riscv.c | 19 +- crypto/perlasm/riscv.pm | 18 ++ 4 files changed, 182 insertions(+), 114 deletions(-) rename crypto/chacha/asm/{chacha-riscv64-zbb-zvkb.pl => chacha-riscv64-v-zbb.pl} (71%) mode change 100644 => 100755 diff --git a/crypto/chacha/asm/chacha-riscv64-zbb-zvkb.pl b/crypto/chacha/asm/chacha-riscv64-v-zbb.pl old mode 100644 new mode 100755 similarity index 71% rename from crypto/chacha/asm/chacha-riscv64-zbb-zvkb.pl rename to crypto/chacha/asm/chacha-riscv64-v-zbb.pl index 6508af4765388..5252ae842a9ac --- a/crypto/chacha/asm/chacha-riscv64-zbb-zvkb.pl +++ b/crypto/chacha/asm/chacha-riscv64-v-zbb.pl @@ -37,9 +37,10 @@ # - RV64I # - RISC-V Vector ('V') with VLEN >= 128 -# - RISC-V Vector Cryptography Bit-manipulation extension ('Zvkb') # - RISC-V Basic Bit-manipulation extension ('Zbb') # - RISC-V Zicclsm(Main memory supports misaligned loads/stores) +# Optional: +# - RISC-V Vector Cryptography Bit-manipulation extension ('Zvkb') use strict; use warnings; @@ -54,15 +55,18 @@ my $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; my $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; +my $use_zvkb = $flavour && $flavour =~ /zvkb/i ? 1 : 0; +my $isaext = "_v_zbb" . ( $use_zvkb ? "_zvkb" : "" ); + $output and open STDOUT, ">$output"; my $code = <<___; .text ___ -# void ChaCha20_ctr32_zbb_zvkb(unsigned char *out, const unsigned char *inp, -# size_t len, const unsigned int key[8], -# const unsigned int counter[4]); +# void ChaCha20_ctr32@{[$isaext]}(unsigned char *out, const unsigned char *inp, +# size_t len, const unsigned int key[8], +# const unsigned int counter[4]); ################################################################################ my ( $OUTPUT, $INPUT, $LEN, $KEY, $COUNTER ) = ( "a0", "a1", "a2", "a3", "a4" ); my ( $CONST_DATA0, $CONST_DATA1, $CONST_DATA2, $CONST_DATA3 ) = ( "a5", "a6", @@ -90,6 +94,92 @@ $V22, $V23, $V24, $V25, $V26, $V27, $V28, $V29, $V30, $V31, ) = map( "v$_", ( 0 .. 31 ) ); +sub chacha_sub_round { + my ( + $A0, $B0, $C0, + $A1, $B1, $C1, + $A2, $B2, $C2, + $A3, $B3, $C3, + + $S_A0, $S_B0, $S_C0, + $S_A1, $S_B1, $S_C1, + $S_A2, $S_B2, $S_C2, + $S_A3, $S_B3, $S_C3, + + $ROL_SHIFT, + + $V_T0, $V_T1, $V_T2, $V_T3, + ) = @_; + + # a += b; c ^= a; c <<<= $ROL_SHIFT; + + if ($use_zvkb) { + my $code = <<___; + @{[vadd_vv $A0, $A0, $B0]} + add $S_A0, $S_A0, $S_B0 + @{[vadd_vv $A1, $A1, $B1]} + add $S_A1, $S_A1, $S_B1 + @{[vadd_vv $A2, $A2, $B2]} + add $S_A2, $S_A2, $S_B2 + @{[vadd_vv $A3, $A3, $B3]} + add $S_A3, $S_A3, $S_B3 + @{[vxor_vv $C0, $C0, $A0]} + xor $S_C0, $S_C0, $S_A0 + @{[vxor_vv $C1, $C1, $A1]} + xor $S_C1, $S_C1, $S_A1 + @{[vxor_vv $C2, $C2, $A2]} + xor $S_C2, $S_C2, $S_A2 + @{[vxor_vv $C3, $C3, $A3]} + xor $S_C3, $S_C3, $S_A3 + @{[vror_vi $C0, $C0, 32 - $ROL_SHIFT]} + @{[roriw $S_C0, $S_C0, 32 - $ROL_SHIFT]} + @{[vror_vi $C1, $C1, 32 - $ROL_SHIFT]} + @{[roriw $S_C1, $S_C1, 32 - $ROL_SHIFT]} + @{[vror_vi $C2, $C2, 32 - $ROL_SHIFT]} + @{[roriw $S_C2, $S_C2, 32 - $ROL_SHIFT]} + @{[vror_vi $C3, $C3, 32 - $ROL_SHIFT]} + @{[roriw $S_C3, $S_C3, 32 - $ROL_SHIFT]} +___ + return $code; + } else { + my $code = <<___; + @{[vadd_vv $A0, $A0, $B0]} + add $S_A0, $S_A0, $S_B0 + @{[vadd_vv $A1, $A1, $B1]} + add $S_A1, $S_A1, $S_B1 + @{[vadd_vv $A2, $A2, $B2]} + add $S_A2, $S_A2, $S_B2 + @{[vadd_vv $A3, $A3, $B3]} + add $S_A3, $S_A3, $S_B3 + @{[vxor_vv $C0, $C0, $A0]} + xor $S_C0, $S_C0, $S_A0 + @{[vxor_vv $C1, $C1, $A1]} + xor $S_C1, $S_C1, $S_A1 + @{[vxor_vv $C2, $C2, $A2]} + xor $S_C2, $S_C2, $S_A2 + @{[vxor_vv $C3, $C3, $A3]} + xor $S_C3, $S_C3, $S_A3 + @{[vsll_vi $V_T0, $C0, $ROL_SHIFT]} + @{[vsll_vi $V_T1, $C1, $ROL_SHIFT]} + @{[vsll_vi $V_T2, $C2, $ROL_SHIFT]} + @{[vsll_vi $V_T3, $C3, $ROL_SHIFT]} + @{[vsrl_vi $C0, $C0, 32 - $ROL_SHIFT]} + @{[vsrl_vi $C1, $C1, 32 - $ROL_SHIFT]} + @{[vsrl_vi $C2, $C2, 32 - $ROL_SHIFT]} + @{[vsrl_vi $C3, $C3, 32 - $ROL_SHIFT]} + @{[vor_vv $C0, $C0, $V_T0]} + @{[roriw $S_C0, $S_C0, 32 - $ROL_SHIFT]} + @{[vor_vv $C1, $C1, $V_T1]} + @{[roriw $S_C1, $S_C1, 32 - $ROL_SHIFT]} + @{[vor_vv $C2, $C2, $V_T2]} + @{[roriw $S_C2, $S_C2, 32 - $ROL_SHIFT]} + @{[vor_vv $C3, $C3, $V_T3]} + @{[roriw $S_C3, $S_C3, 32 - $ROL_SHIFT]} +___ + return $code; + } +} + sub chacha_quad_round_group { my ( $A0, $B0, $C0, $D0, @@ -101,109 +191,59 @@ sub chacha_quad_round_group { $S_A1, $S_B1, $S_C1, $S_D1, $S_A2, $S_B2, $S_C2, $S_D2, $S_A3, $S_B3, $S_C3, $S_D3, + + $V_T0, $V_T1, $V_T2, $V_T3, ) = @_; my $code = <<___; # a += b; d ^= a; d <<<= 16; - @{[vadd_vv $A0, $A0, $B0]} - add $S_A0, $S_A0, $S_B0 - @{[vadd_vv $A1, $A1, $B1]} - add $S_A1, $S_A1, $S_B1 - @{[vadd_vv $A2, $A2, $B2]} - add $S_A2, $S_A2, $S_B2 - @{[vadd_vv $A3, $A3, $B3]} - add $S_A3, $S_A3, $S_B3 - @{[vxor_vv $D0, $D0, $A0]} - xor $S_D0, $S_D0, $S_A0 - @{[vxor_vv $D1, $D1, $A1]} - xor $S_D1, $S_D1, $S_A1 - @{[vxor_vv $D2, $D2, $A2]} - xor $S_D2, $S_D2, $S_A2 - @{[vxor_vv $D3, $D3, $A3]} - xor $S_D3, $S_D3, $S_A3 - @{[vror_vi $D0, $D0, 32 - 16]} - @{[roriw $S_D0, $S_D0, 32 - 16]} - @{[vror_vi $D1, $D1, 32 - 16]} - @{[roriw $S_D1, $S_D1, 32 - 16]} - @{[vror_vi $D2, $D2, 32 - 16]} - @{[roriw $S_D2, $S_D2, 32 - 16]} - @{[vror_vi $D3, $D3, 32 - 16]} - @{[roriw $S_D3, $S_D3, 32 - 16]} + @{[chacha_sub_round + $A0, $B0, $D0, + $A1, $B1, $D1, + $A2, $B2, $D2, + $A3, $B3, $D3, + $S_A0, $S_B0, $S_D0, + $S_A1, $S_B1, $S_D1, + $S_A2, $S_B2, $S_D2, + $S_A3, $S_B3, $S_D3, + 16, + $V_T0, $V_T1, $V_T2, $V_T3]} # c += d; b ^= c; b <<<= 12; - @{[vadd_vv $C0, $C0, $D0]} - add $S_C0, $S_C0, $S_D0 - @{[vadd_vv $C1, $C1, $D1]} - add $S_C1, $S_C1, $S_D1 - @{[vadd_vv $C2, $C2, $D2]} - add $S_C2, $S_C2, $S_D2 - @{[vadd_vv $C3, $C3, $D3]} - add $S_C3, $S_C3, $S_D3 - @{[vxor_vv $B0, $B0, $C0]} - xor $S_B0, $S_B0, $S_C0 - @{[vxor_vv $B1, $B1, $C1]} - xor $S_B1, $S_B1, $S_C1 - @{[vxor_vv $B2, $B2, $C2]} - xor $S_B2, $S_B2, $S_C2 - @{[vxor_vv $B3, $B3, $C3]} - xor $S_B3, $S_B3, $S_C3 - @{[vror_vi $B0, $B0, 32 - 12]} - @{[roriw $S_B0, $S_B0, 32 - 12]} - @{[vror_vi $B1, $B1, 32 - 12]} - @{[roriw $S_B1, $S_B1, 32 - 12]} - @{[vror_vi $B2, $B2, 32 - 12]} - @{[roriw $S_B2, $S_B2, 32 - 12]} - @{[vror_vi $B3, $B3, 32 - 12]} - @{[roriw $S_B3, $S_B3, 32 - 12]} + @{[chacha_sub_round + $C0, $D0, $B0, + $C1, $D1, $B1, + $C2, $D2, $B2, + $C3, $D3, $B3, + $S_C0, $S_D0, $S_B0, + $S_C1, $S_D1, $S_B1, + $S_C2, $S_D2, $S_B2, + $S_C3, $S_D3, $S_B3, + 12, + $V_T0, $V_T1, $V_T2, $V_T3]} # a += b; d ^= a; d <<<= 8; - @{[vadd_vv $A0, $A0, $B0]} - add $S_A0, $S_A0, $S_B0 - @{[vadd_vv $A1, $A1, $B1]} - add $S_A1, $S_A1, $S_B1 - @{[vadd_vv $A2, $A2, $B2]} - add $S_A2, $S_A2, $S_B2 - @{[vadd_vv $A3, $A3, $B3]} - add $S_A3, $S_A3, $S_B3 - @{[vxor_vv $D0, $D0, $A0]} - xor $S_D0, $S_D0, $S_A0 - @{[vxor_vv $D1, $D1, $A1]} - xor $S_D1, $S_D1, $S_A1 - @{[vxor_vv $D2, $D2, $A2]} - xor $S_D2, $S_D2, $S_A2 - @{[vxor_vv $D3, $D3, $A3]} - xor $S_D3, $S_D3, $S_A3 - @{[vror_vi $D0, $D0, 32 - 8]} - @{[roriw $S_D0, $S_D0, 32 - 8]} - @{[vror_vi $D1, $D1, 32 - 8]} - @{[roriw $S_D1, $S_D1, 32 - 8]} - @{[vror_vi $D2, $D2, 32 - 8]} - @{[roriw $S_D2, $S_D2, 32 - 8]} - @{[vror_vi $D3, $D3, 32 - 8]} - @{[roriw $S_D3, $S_D3, 32 - 8]} + @{[chacha_sub_round + $A0, $B0, $D0, + $A1, $B1, $D1, + $A2, $B2, $D2, + $A3, $B3, $D3, + $S_A0, $S_B0, $S_D0, + $S_A1, $S_B1, $S_D1, + $S_A2, $S_B2, $S_D2, + $S_A3, $S_B3, $S_D3, + 8, + $V_T0, $V_T1, $V_T2, $V_T3]} # c += d; b ^= c; b <<<= 7; - @{[vadd_vv $C0, $C0, $D0]} - add $S_C0, $S_C0, $S_D0 - @{[vadd_vv $C1, $C1, $D1]} - add $S_C1, $S_C1, $S_D1 - @{[vadd_vv $C2, $C2, $D2]} - add $S_C2, $S_C2, $S_D2 - @{[vadd_vv $C3, $C3, $D3]} - add $S_C3, $S_C3, $S_D3 - @{[vxor_vv $B0, $B0, $C0]} - xor $S_B0, $S_B0, $S_C0 - @{[vxor_vv $B1, $B1, $C1]} - xor $S_B1, $S_B1, $S_C1 - @{[vxor_vv $B2, $B2, $C2]} - xor $S_B2, $S_B2, $S_C2 - @{[vxor_vv $B3, $B3, $C3]} - xor $S_B3, $S_B3, $S_C3 - @{[vror_vi $B0, $B0, 32 - 7]} - @{[roriw $S_B0, $S_B0, 32 - 7]} - @{[vror_vi $B1, $B1, 32 - 7]} - @{[roriw $S_B1, $S_B1, 32 - 7]} - @{[vror_vi $B2, $B2, 32 - 7]} - @{[roriw $S_B2, $S_B2, 32 - 7]} - @{[vror_vi $B3, $B3, 32 - 7]} - @{[roriw $S_B3, $S_B3, 32 - 7]} + @{[chacha_sub_round + $C0, $D0, $B0, + $C1, $D1, $B1, + $C2, $D2, $B2, + $C3, $D3, $B3, + $S_C0, $S_D0, $S_B0, + $S_C1, $S_D1, $S_B1, + $S_C2, $S_D2, $S_B2, + $S_C3, $S_D3, $S_B3, + 7, + $V_T0, $V_T1, $V_T2, $V_T3]} ___ return $code; @@ -211,9 +251,9 @@ sub chacha_quad_round_group { $code .= <<___; .p2align 3 -.globl ChaCha20_ctr32_zbb_zvkb -.type ChaCha20_ctr32_zbb_zvkb,\@function -ChaCha20_ctr32_zbb_zvkb: +.globl ChaCha20_ctr32@{[$isaext]} +.type ChaCha20_ctr32@{[$isaext]},\@function +ChaCha20_ctr32@{[$isaext]}: addi sp, sp, -96 sd s0, 0(sp) sd s1, 8(sp) @@ -305,7 +345,8 @@ sub chacha_quad_round_group { $STATE0, $STATE4, $STATE8, $STATE12, $STATE1, $STATE5, $STATE9, $STATE13, $STATE2, $STATE6, $STATE10, $STATE14, - $STATE3, $STATE7, $STATE11, $STATE15]} + $STATE3, $STATE7, $STATE11, $STATE15, + $V24, $V25, $V26, $V27]} @{[chacha_quad_round_group $V3, $V4, $V9, $V14, $V0, $V5, $V10, $V15, @@ -314,7 +355,8 @@ sub chacha_quad_round_group { $STATE3, $STATE4, $STATE9, $STATE14, $STATE0, $STATE5, $STATE10, $STATE15, $STATE1, $STATE6, $STATE11, $STATE12, - $STATE2, $STATE7, $STATE8, $STATE13]} + $STATE2, $STATE7, $STATE8, $STATE13, + $V24, $V25, $V26, $V27]} bnez $T0, .Lround_loop li $T0, 64 @@ -468,7 +510,7 @@ sub chacha_quad_round_group { addi sp, sp, 96 ret -.size ChaCha20_ctr32_zbb_zvkb,.-ChaCha20_ctr32_zbb_zvkb +.size ChaCha20_ctr32@{[$isaext]},.-ChaCha20_ctr32@{[$isaext]} ___ print $code; diff --git a/crypto/chacha/build.info b/crypto/chacha/build.info index c1352c9b62dee..c151e190429d1 100644 --- a/crypto/chacha/build.info +++ b/crypto/chacha/build.info @@ -22,7 +22,7 @@ IF[{- !$disabled{asm} -}] $CHACHAASM_c64xplus=chacha-c64xplus.s - $CHACHAASM_riscv64=chacha_riscv.c chacha_enc.c chacha-riscv64-zbb-zvkb.s + $CHACHAASM_riscv64=chacha_riscv.c chacha_enc.c chacha-riscv64-v-zbb.s chacha-riscv64-v-zbb-zvkb.s $CHACHADEF_riscv64=INCLUDE_C_CHACHA20 # Now that we have defined all the arch specific variables, use the @@ -53,4 +53,5 @@ GENERATE[chacha-s390x.S]=asm/chacha-s390x.pl GENERATE[chacha-ia64.S]=asm/chacha-ia64.pl GENERATE[chacha-ia64.s]=chacha-ia64.S GENERATE[chacha-loongarch64.S]=asm/chacha-loongarch64.pl -GENERATE[chacha-riscv64-zbb-zvkb.s]=asm/chacha-riscv64-zbb-zvkb.pl +GENERATE[chacha-riscv64-v-zbb.s]=asm/chacha-riscv64-v-zbb.pl +GENERATE[chacha-riscv64-v-zbb-zvkb.s]=asm/chacha-riscv64-v-zbb.pl zvkb diff --git a/crypto/chacha/chacha_riscv.c b/crypto/chacha/chacha_riscv.c index 8873460e5efe0..9baa39bec3723 100644 --- a/crypto/chacha/chacha_riscv.c +++ b/crypto/chacha/chacha_riscv.c @@ -40,16 +40,23 @@ #include "crypto/chacha.h" #include "crypto/riscv_arch.h" -void ChaCha20_ctr32_zbb_zvkb(unsigned char *out, const unsigned char *inp, - size_t len, const unsigned int key[8], - const unsigned int counter[4]); +void ChaCha20_ctr32_v_zbb_zvkb(unsigned char *out, const unsigned char *inp, + size_t len, const unsigned int key[8], + const unsigned int counter[4]); + +void ChaCha20_ctr32_v_zbb(unsigned char *out, const unsigned char *inp, + size_t len, const unsigned int key[8], + const unsigned int counter[4]); void ChaCha20_ctr32(unsigned char *out, const unsigned char *inp, size_t len, const unsigned int key[8], const unsigned int counter[4]) { - if (len > CHACHA_BLK_SIZE && RISCV_HAS_ZVKB() && RISCV_HAS_ZBB() && - riscv_vlen() >= 128) { - ChaCha20_ctr32_zbb_zvkb(out, inp, len, key, counter); + if (len > CHACHA_BLK_SIZE && RISCV_HAS_ZBB() && riscv_vlen() >= 128) { + if (RISCV_HAS_ZVKB()) { + ChaCha20_ctr32_v_zbb_zvkb(out, inp, len, key, counter); + } else { + ChaCha20_ctr32_v_zbb(out, inp, len, key, counter); + } } else { ChaCha20_ctr32_c(out, inp, len, key, counter); } diff --git a/crypto/perlasm/riscv.pm b/crypto/perlasm/riscv.pm index 7e45bec812d7f..bd1c3d90a19f7 100644 --- a/crypto/perlasm/riscv.pm +++ b/crypto/perlasm/riscv.pm @@ -598,6 +598,15 @@ sub vmv_v_v { return ".word ".($template | ($vs1 << 15) | ($vd << 7)); } +sub vor_vv { + # vor.vv vd, vs2, vs1 + my $template = 0b0010101_00000_00000_000_00000_1010111; + my $vd = read_vreg shift; + my $vs2 = read_vreg shift; + my $vs1 = read_vreg shift; + return ".word ".($template | ($vs2 << 20) | ($vs1 << 15) | ($vd << 7)); +} + sub vor_vv_v0t { # vor.vv vd, vs2, vs1, v0.t my $template = 0b0010100_00000_00000_000_00000_1010111; @@ -747,6 +756,15 @@ sub vsll_vi { return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7)); } +sub vsrl_vi { + # vsrl.vi vd, vs2, uimm, vm + my $template = 0b1010001_00000_00000_011_00000_1010111; + my $vd = read_vreg shift; + my $vs2 = read_vreg shift; + my $uimm = shift; + return ".word ".($template | ($vs2 << 20) | ($uimm << 15) | ($vd << 7)); +} + sub vsrl_vx { # vsrl.vx vd, vs2, rs1 my $template = 0b1010001_00000_00000_100_00000_1010111; From c857205407a0a074baf0db7fa7237a469f297c83 Mon Sep 17 00:00:00 2001 From: Yangyu Chen Date: Fri, 19 Apr 2024 21:49:44 +0800 Subject: [PATCH 20/21] chacha-riscv64-v-zbb.pl: add comment about vector register allocation Since we can do group operations on vector registers in RISC-V, some vector registers will be used without being explicitly referenced. Thus, comments on vector register allocation should be added to improve the code readability and maintainability. Signed-off-by: Yangyu Chen Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/24069) --- crypto/chacha/asm/chacha-riscv64-v-zbb.pl | 25 +++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/crypto/chacha/asm/chacha-riscv64-v-zbb.pl b/crypto/chacha/asm/chacha-riscv64-v-zbb.pl index 5252ae842a9ac..8bc7fbc4adad4 100755 --- a/crypto/chacha/asm/chacha-riscv64-v-zbb.pl +++ b/crypto/chacha/asm/chacha-riscv64-v-zbb.pl @@ -284,7 +284,7 @@ sub chacha_quad_round_group { 1: #### chacha block data - # init chacha const states + # init chacha const states into $V0~$V3 # "expa" little endian li $CONST_DATA0, 0x61707865 @{[vmv_v_x $V0, $CONST_DATA0]} @@ -299,7 +299,7 @@ sub chacha_quad_round_group { lw $KEY0, 0($KEY) @{[vmv_v_x $V3, $CONST_DATA3]} - # init chacha key states + # init chacha key states into $V4~$V11 lw $KEY1, 4($KEY) @{[vmv_v_x $V4, $KEY0]} lw $KEY2, 8($KEY) @@ -316,7 +316,7 @@ sub chacha_quad_round_group { @{[vmv_v_x $V10, $KEY6]} @{[vmv_v_x $V11, $KEY7]} - # init chacha key states + # init chacha key states into $V12~$V13 lw $COUNTER1, 4($COUNTER) @{[vid_v $V12]} lw $NONCE0, 8($COUNTER) @@ -325,17 +325,23 @@ sub chacha_quad_round_group { @{[vmv_v_x $V13, $COUNTER1]} add $COUNTER0, $CURRENT_COUNTER, $VL - # init chacha nonce states + # init chacha nonce states into $V14~$V15 @{[vmv_v_x $V14, $NONCE0]} @{[vmv_v_x $V15, $NONCE1]} li $T0, 64 - # load the top-half of input data + # load the top-half of input data into $V16~$V23 @{[vlsseg_nf_e32_v 8, $V16, $INPUT, $T0]} + # till now in block_loop, we used: + # - $V0~$V15 for chacha states. + # - $V16~$V23 for top-half of input data. + # - $V24~$V31 haven't been used yet. + # 20 round groups li $T0, 10 .Lround_loop: + # we can use $V24~$V31 as temporary registers in round_loop. addi $T0, $T0, -1 @{[chacha_quad_round_group $V0, $V4, $V8, $V12, @@ -360,10 +366,12 @@ sub chacha_quad_round_group { bnez $T0, .Lround_loop li $T0, 64 - # load the bottom-half of input data + # load the bottom-half of input data into $V24~$V31 addi $T1, $INPUT, 32 @{[vlsseg_nf_e32_v 8, $V24, $T1, $T0]} + # now, there are no free vector registers until the round_loop exits. + # add chacha top-half initial block states # "expa" little endian li $T0, 0x61707865 @@ -415,7 +423,7 @@ sub chacha_quad_round_group { lw $T2, 24($KEY) @{[vxor_vv $V23, $V23, $V7]} - # save the top-half of output + # save the top-half of output from $V16~$V23 li $T3, 64 @{[vssseg_nf_e32_v 8, $V16, $OUTPUT, $T3]} @@ -461,7 +469,7 @@ sub chacha_quad_round_group { @{[vxor_vv $V31, $V31, $V15]} sw $STATE15, 60(sp) - # save the bottom-half of output + # save the bottom-half of output from $V24~$V31 li $T0, 64 addi $T1, $OUTPUT, 32 @{[vssseg_nf_e32_v 8, $V24, $T1, $T0]} @@ -482,6 +490,7 @@ sub chacha_quad_round_group { mv $T2, sp .Lscalar_data_loop: @{[vsetvli $VL, $T1, "e8", "m8", "ta", "ma"]} + # from this on, vector registers are grouped with lmul = 8 @{[vle8_v $V8, $INPUT]} @{[vle8_v $V16, $T2]} @{[vxor_vv $V8, $V8, $V16]} From f6ce48f5b8ad4d8d748ea87d2490cbed08db9936 Mon Sep 17 00:00:00 2001 From: Yangyu Chen Date: Mon, 22 Apr 2024 10:40:25 +0800 Subject: [PATCH 21/21] chacha-riscv64-v-zbb.pl: better format This patch merged the `add` and `xor` part of chacha_sub_round, which are same in RISC-V Vector only and Zvkb implementation. There is no change to the generated ASM code except for the indent. Signed-off-by: Yangyu Chen Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/24069) --- crypto/chacha/asm/chacha-riscv64-v-zbb.pl | 65 ++++++++++------------- 1 file changed, 28 insertions(+), 37 deletions(-) diff --git a/crypto/chacha/asm/chacha-riscv64-v-zbb.pl b/crypto/chacha/asm/chacha-riscv64-v-zbb.pl index 8bc7fbc4adad4..6518e3fc2441c 100755 --- a/crypto/chacha/asm/chacha-riscv64-v-zbb.pl +++ b/crypto/chacha/asm/chacha-riscv64-v-zbb.pl @@ -111,26 +111,29 @@ sub chacha_sub_round { $V_T0, $V_T1, $V_T2, $V_T3, ) = @_; - # a += b; c ^= a; c <<<= $ROL_SHIFT; + # a += b; c ^= a; + my $code = <<___; + @{[vadd_vv $A0, $A0, $B0]} + add $S_A0, $S_A0, $S_B0 + @{[vadd_vv $A1, $A1, $B1]} + add $S_A1, $S_A1, $S_B1 + @{[vadd_vv $A2, $A2, $B2]} + add $S_A2, $S_A2, $S_B2 + @{[vadd_vv $A3, $A3, $B3]} + add $S_A3, $S_A3, $S_B3 + @{[vxor_vv $C0, $C0, $A0]} + xor $S_C0, $S_C0, $S_A0 + @{[vxor_vv $C1, $C1, $A1]} + xor $S_C1, $S_C1, $S_A1 + @{[vxor_vv $C2, $C2, $A2]} + xor $S_C2, $S_C2, $S_A2 + @{[vxor_vv $C3, $C3, $A3]} + xor $S_C3, $S_C3, $S_A3 +___ + # c <<<= $ROL_SHIFT; if ($use_zvkb) { - my $code = <<___; - @{[vadd_vv $A0, $A0, $B0]} - add $S_A0, $S_A0, $S_B0 - @{[vadd_vv $A1, $A1, $B1]} - add $S_A1, $S_A1, $S_B1 - @{[vadd_vv $A2, $A2, $B2]} - add $S_A2, $S_A2, $S_B2 - @{[vadd_vv $A3, $A3, $B3]} - add $S_A3, $S_A3, $S_B3 - @{[vxor_vv $C0, $C0, $A0]} - xor $S_C0, $S_C0, $S_A0 - @{[vxor_vv $C1, $C1, $A1]} - xor $S_C1, $S_C1, $S_A1 - @{[vxor_vv $C2, $C2, $A2]} - xor $S_C2, $S_C2, $S_A2 - @{[vxor_vv $C3, $C3, $A3]} - xor $S_C3, $S_C3, $S_A3 + my $ror_part = <<___; @{[vror_vi $C0, $C0, 32 - $ROL_SHIFT]} @{[roriw $S_C0, $S_C0, 32 - $ROL_SHIFT]} @{[vror_vi $C1, $C1, 32 - $ROL_SHIFT]} @@ -140,25 +143,10 @@ sub chacha_sub_round { @{[vror_vi $C3, $C3, 32 - $ROL_SHIFT]} @{[roriw $S_C3, $S_C3, 32 - $ROL_SHIFT]} ___ - return $code; + + $code .= $ror_part; } else { - my $code = <<___; - @{[vadd_vv $A0, $A0, $B0]} - add $S_A0, $S_A0, $S_B0 - @{[vadd_vv $A1, $A1, $B1]} - add $S_A1, $S_A1, $S_B1 - @{[vadd_vv $A2, $A2, $B2]} - add $S_A2, $S_A2, $S_B2 - @{[vadd_vv $A3, $A3, $B3]} - add $S_A3, $S_A3, $S_B3 - @{[vxor_vv $C0, $C0, $A0]} - xor $S_C0, $S_C0, $S_A0 - @{[vxor_vv $C1, $C1, $A1]} - xor $S_C1, $S_C1, $S_A1 - @{[vxor_vv $C2, $C2, $A2]} - xor $S_C2, $S_C2, $S_A2 - @{[vxor_vv $C3, $C3, $A3]} - xor $S_C3, $S_C3, $S_A3 + my $ror_part = <<___; @{[vsll_vi $V_T0, $C0, $ROL_SHIFT]} @{[vsll_vi $V_T1, $C1, $ROL_SHIFT]} @{[vsll_vi $V_T2, $C2, $ROL_SHIFT]} @@ -176,8 +164,11 @@ sub chacha_sub_round { @{[vor_vv $C3, $C3, $V_T3]} @{[roriw $S_C3, $S_C3, 32 - $ROL_SHIFT]} ___ - return $code; + + $code .= $ror_part; } + + return $code; } sub chacha_quad_round_group {