aboutsummaryrefslogtreecommitdiff
path: root/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'crypto')
-rw-r--r--crypto/heimdal/kadmin/dump.c29
-rw-r--r--crypto/heimdal/kadmin/kadmin-commands.in6
-rw-r--r--crypto/heimdal/kadmin/kadmin.829
-rw-r--r--crypto/heimdal/kdc/hpropd.c68
-rw-r--r--crypto/heimdal/kdc/mit_dump.c383
-rw-r--r--crypto/heimdal/lib/hdb/Makefile.am1
-rw-r--r--crypto/heimdal/lib/hdb/common.c68
-rw-r--r--crypto/heimdal/lib/hdb/ext.c31
-rw-r--r--crypto/heimdal/lib/hdb/hdb-mitdb.c477
-rw-r--r--crypto/heimdal/lib/hdb/hdb-protos.h25
-rw-r--r--crypto/heimdal/lib/hdb/hdb.asn114
-rw-r--r--crypto/heimdal/lib/hdb/hdb.c7
-rw-r--r--crypto/heimdal/lib/hdb/hdb.h15
-rw-r--r--crypto/heimdal/lib/hdb/hdb_locl.h7
-rw-r--r--crypto/heimdal/lib/hdb/keys.c69
-rw-r--r--crypto/heimdal/lib/hdb/mkey.c211
-rw-r--r--crypto/heimdal/lib/hdb/print.c407
-rw-r--r--crypto/heimdal/lib/hdb/version-script.map6
-rw-r--r--crypto/heimdal/lib/kadm5/chpass_s.c7
-rw-r--r--crypto/heimdal/lib/kadm5/randkey_s.c4
-rw-r--r--crypto/openssl/CHANGES.md69
-rw-r--r--crypto/openssl/NEWS.md40
-rw-r--r--crypto/openssl/VERSION.dat4
-rw-r--r--crypto/openssl/apps/storeutl.c16
-rw-r--r--crypto/openssl/crypto/bio/bss_file.c2
-rw-r--r--crypto/openssl/crypto/ec/ecp_sm2p256.c2
-rw-r--r--crypto/openssl/crypto/evp/bio_ok.c27
-rw-r--r--crypto/openssl/crypto/evp/ctrl_params_translate.c2
-rw-r--r--crypto/openssl/crypto/evp/p_lib.c17
-rw-r--r--crypto/openssl/crypto/info.c14
-rw-r--r--crypto/openssl/crypto/ml_dsa/ml_dsa_key.c4
-rw-r--r--crypto/openssl/crypto/ml_kem/ml_kem.c2
-rw-r--r--crypto/openssl/crypto/modes/siv128.c3
-rw-r--r--crypto/openssl/crypto/property/property_parse.c2
-rw-r--r--crypto/openssl/crypto/rsa/rsa_gen.c15
-rw-r--r--crypto/openssl/crypto/rsa/rsa_sign.c4
-rw-r--r--crypto/openssl/crypto/threads_pthread.c12
-rw-r--r--crypto/openssl/crypto/x509/t_x509.c3
-rw-r--r--crypto/openssl/crypto/x509/x509_lu.c1
-rw-r--r--crypto/openssl/doc/man3/DEFINE_STACK_OF.pod19
-rw-r--r--crypto/openssl/doc/man3/OpenSSL_version.pod9
-rw-r--r--crypto/openssl/doc/man3/SSL_CIPHER_get_name.pod4
-rw-r--r--crypto/openssl/doc/man3/SSL_SESSION_get0_hostname.pod10
-rw-r--r--crypto/openssl/include/crypto/rsa.h4
-rw-r--r--crypto/openssl/include/openssl/opensslv.h.in4
-rw-r--r--crypto/openssl/providers/fips-sources.checksums20
-rw-r--r--crypto/openssl/providers/fips.checksum2
-rw-r--r--crypto/openssl/providers/fips/self_test_data.inc42
-rw-r--r--crypto/openssl/providers/fips/self_test_kats.c100
-rw-r--r--crypto/openssl/providers/implementations/kdfs/krb5kdf.c7
-rw-r--r--crypto/openssl/providers/implementations/keymgmt/ecx_kmgmt.c8
-rw-r--r--crypto/openssl/ssl/quic/quic_impl.c7
-rw-r--r--crypto/openssl/ssl/record/methods/tls_common.c11
-rw-r--r--crypto/openssl/ssl/ssl_rsa.c5
-rw-r--r--crypto/openssl/ssl/t1_trce.c4
-rw-r--r--crypto/openssl/test/build.info3
-rw-r--r--crypto/openssl/test/fake_rsaprov.c4
-rw-r--r--crypto/openssl/test/fake_rsaprov.h11
-rw-r--r--crypto/openssl/test/ml_kem_evp_extra_test.c10
-rw-r--r--crypto/openssl/test/property_test.c19
-rw-r--r--crypto/openssl/test/provider_pkey_test.c72
-rw-r--r--crypto/openssl/test/quicapitest.c95
-rw-r--r--crypto/openssl/test/radix/terp.c6
-rw-r--r--crypto/openssl/test/recipes/03-test_fipsinstall.t12
-rw-r--r--crypto/openssl/test/recipes/25-test_verify.t5
-rw-r--r--crypto/openssl/test/recipes/30-test_evp_data/evpkdf_krb5.txt10
-rw-r--r--crypto/openssl/test/recipes/30-test_evp_data/evppkey_rsa_sigalg.txt4
-rw-r--r--crypto/openssl/test/recipes/90-test_sslapi.t17
-rw-r--r--crypto/openssl/test/recipes/90-test_sslapi_data/ssltraceref-zlib.txt255
-rw-r--r--crypto/openssl/test/recipes/90-test_sslapi_data/ssltraceref.txt253
-rw-r--r--crypto/openssl/test/sslapitest.c87
-rw-r--r--crypto/openssl/test/testutil.h2
-rw-r--r--crypto/openssl/test/testutil/compare.c88
-rw-r--r--crypto/openssl/test/threadstest.c11
-rw-r--r--crypto/openssl/test/wpackettest.c2
75 files changed, 2637 insertions, 688 deletions
diff --git a/crypto/heimdal/kadmin/dump.c b/crypto/heimdal/kadmin/dump.c
index 91a5ada86607..2c302eced210 100644
--- a/crypto/heimdal/kadmin/dump.c
+++ b/crypto/heimdal/kadmin/dump.c
@@ -42,32 +42,51 @@ dump(struct dump_options *opt, int argc, char **argv)
{
krb5_error_code ret;
FILE *f;
+ struct hdb_print_entry_arg parg;
HDB *db = NULL;
- if(!local_flag) {
+ if (!local_flag) {
krb5_warnx(context, "dump is only available in local (-l) mode");
return 0;
}
db = _kadm5_s_get_db(kadm_handle);
- if(argc == 0)
+ if (argc == 0)
f = stdout;
else
f = fopen(argv[0], "w");
- if(f == NULL) {
+ if (f == NULL) {
krb5_warn(context, errno, "open: %s", argv[0]);
goto out;
}
ret = db->hdb_open(context, db, O_RDONLY, 0600);
- if(ret) {
+ if (ret) {
krb5_warn(context, ret, "hdb_open");
goto out;
}
+ if (!opt->format_string || strcmp(opt->format_string, "Heimdal") == 0) {
+ parg.fmt = HDB_DUMP_HEIMDAL;
+ } else if (opt->format_string && strcmp(opt->format_string, "MIT") == 0) {
+ parg.fmt = HDB_DUMP_MIT;
+ fprintf(f, "kdb5_util load_dump version 5\n"); /* 5||6, either way */
+ } else if (opt->format_string) {
+ /* Open the format string as a MIT mkey file. */
+ ret = hdb_read_master_key(context, opt->format_string, &db->hdb_mit_key);
+ if (ret)
+ krb5_errx(context, 1, "Cannot open MIT mkey file");
+ db->hdb_mit_key_set = 1;
+ parg.fmt = HDB_DUMP_MIT;
+ opt->decrypt_flag = 1;
+ fprintf(f, "kdb5_util load_dump version 5\n"); /* 5||6, either way */
+ } else {
+ krb5_errx(context, 1, "Supported dump formats: Heimdal and MIT");
+ }
+ parg.out = f;
hdb_foreach(context, db, opt->decrypt_flag ? HDB_F_DECRYPT : 0,
- hdb_print_entry, f);
+ hdb_print_entry, &parg);
db->hdb_close(context, db);
out:
diff --git a/crypto/heimdal/kadmin/kadmin-commands.in b/crypto/heimdal/kadmin/kadmin-commands.in
index 4396ff800441..dc36db4e0a00 100644
--- a/crypto/heimdal/kadmin/kadmin-commands.in
+++ b/crypto/heimdal/kadmin/kadmin-commands.in
@@ -76,6 +76,12 @@ command = {
type = "flag"
help = "decrypt keys"
}
+ option = {
+ long = "format"
+ short = "f"
+ type = "string"
+ help = "dump format, mit or heimdal (default: heimdal)"
+ }
argument = "[dump-file]"
min_args = "0"
max_args = "1"
diff --git a/crypto/heimdal/kadmin/kadmin.8 b/crypto/heimdal/kadmin/kadmin.8
index bd2fd4e7363f..e4555cd529f4 100644
--- a/crypto/heimdal/kadmin/kadmin.8
+++ b/crypto/heimdal/kadmin/kadmin.8
@@ -31,7 +31,7 @@
.\"
.\" $Id$
.\"
-.Dd Feb 22, 2007
+.Dd October 5, 2025
.Dt KADMIN 8
.Os HEIMDAL
.Sh NAME
@@ -286,14 +286,39 @@ When running in local mode, the following commands can also be used:
.Pp
.Nm dump
.Op Fl d | Fl Fl decrypt
+.Op Fl f Ns Ar format | Fl Fl format= Ns Ar format
.Op Ar dump-file
.Bd -ragged -offset indent
Writes the database in
-.Dq human readable
+.Dq machine readable text
form to the specified file, or standard out. If the database is
encrypted, the dump will also have encrypted keys, unless
.Fl Fl decrypt
is used.
+.Pp
+If
+.Fl Fl format=MIT
+is used then the dump will be in MIT format.
+This option may be used if you require that all principal
+passwords be changed after loading the dump into an MIT KDC database.
+.Pp
+If
+.Fl Fl format=<keytab-file>
+is used, the
+.Dq <keytab-file>
+should hold the master key for the
+MIT KDC (usually a file called /var/db/krb5kdc/.k5.YOUR.REALM).
+This will cause the keys to be re-encrypted in the MIT master
+key as well as doing the dump in MIT format.
+When this dump is loaded into the MIT KDC's database,
+the principals that had at least one strong encryption type
+key should work and any keytabs for those principals should still work.
+The principcals with only weak encryption keys will require a
+.Dq change_password
+be done on the MIT KDC to get them working.
+The
+.Fl Fl decrypt
+flag is meaningless for this case.
.Ed
.Pp
.Nm init
diff --git a/crypto/heimdal/kdc/hpropd.c b/crypto/heimdal/kdc/hpropd.c
index 1cfc688b2a6c..c76be0446705 100644
--- a/crypto/heimdal/kdc/hpropd.c
+++ b/crypto/heimdal/kdc/hpropd.c
@@ -85,23 +85,23 @@ main(int argc, char **argv)
setprogname(argv[0]);
ret = krb5_init_context(&context);
- if(ret)
+ if (ret)
exit(1);
ret = krb5_openlog(context, "hpropd", &fac);
- if(ret)
+ if (ret)
errx(1, "krb5_openlog");
krb5_set_warn_dest(context, fac);
- if(getarg(args, num_args, argc, argv, &optidx))
+ if (getarg(args, num_args, argc, argv, &optidx))
usage(1);
- if(local_realm != NULL)
+ if (local_realm != NULL)
krb5_set_default_realm(context, local_realm);
- if(help_flag)
+ if (help_flag)
usage(0);
- if(version_flag) {
+ if (version_flag) {
print_version(NULL);
exit(0);
}
@@ -117,7 +117,7 @@ main(int argc, char **argv)
if (database == NULL)
database = hdb_default_db(context);
- if(from_stdin) {
+ if (from_stdin) {
sock = STDIN_FILENO;
} else {
struct sockaddr_storage ss;
@@ -145,7 +145,7 @@ main(int argc, char **argv)
HPROP_PORT), &sock);
}
sin_len = sizeof(ss);
- if(getpeername(sock, sa, &sin_len) < 0)
+ if (getpeername(sock, sa, &sin_len) < 0)
krb5_err(context, 1, errno, "getpeername");
if (inet_ntop(sa->sa_family,
@@ -158,7 +158,7 @@ main(int argc, char **argv)
krb5_log(context, fac, 0, "Connection from %s", addr_name);
ret = krb5_kt_register(context, &hdb_kt_ops);
- if(ret)
+ if (ret)
krb5_err(context, 1, ret, "krb5_kt_register");
if (ktname != NULL) {
@@ -173,7 +173,7 @@ main(int argc, char **argv)
ret = krb5_recvauth(context, &ac, &sock, HPROP_VERSION, NULL,
0, keytab, &ticket);
- if(ret)
+ if (ret)
krb5_err(context, 1, ret, "krb5_recvauth");
ret = krb5_unparse_name(context, ticket->server, &server);
@@ -186,15 +186,15 @@ main(int argc, char **argv)
krb5_free_ticket (context, ticket);
ret = krb5_auth_con_getauthenticator(context, ac, &authent);
- if(ret)
+ if (ret)
krb5_err(context, 1, ret, "krb5_auth_con_getauthenticator");
ret = krb5_make_principal(context, &c1, NULL, "kadmin", "hprop", NULL);
- if(ret)
+ if (ret)
krb5_err(context, 1, ret, "krb5_make_principal");
_krb5_principalname2krb5_principal(context, &c2,
authent->cname, authent->crealm);
- if(!krb5_principal_compare(context, c1, c2)) {
+ if (!krb5_principal_compare(context, c1, c2)) {
char *s;
ret = krb5_unparse_name(context, c2, &s);
if (ret)
@@ -205,48 +205,48 @@ main(int argc, char **argv)
krb5_free_principal(context, c2);
ret = krb5_kt_close(context, keytab);
- if(ret)
+ if (ret)
krb5_err(context, 1, ret, "krb5_kt_close");
}
- if(!print_dump) {
+ if (!print_dump) {
asprintf(&tmp_db, "%s~", database);
ret = hdb_create(context, &db, tmp_db);
- if(ret)
+ if (ret)
krb5_err(context, 1, ret, "hdb_create(%s)", tmp_db);
ret = db->hdb_open(context, db, O_RDWR | O_CREAT | O_TRUNC, 0600);
- if(ret)
+ if (ret)
krb5_err(context, 1, ret, "hdb_open(%s)", tmp_db);
}
nprincs = 0;
- while(1){
+ while (1){
krb5_data data;
hdb_entry_ex entry;
- if(from_stdin) {
+ if (from_stdin) {
ret = krb5_read_message(context, &sock, &data);
- if(ret != 0 && ret != HEIM_ERR_EOF)
+ if (ret != 0 && ret != HEIM_ERR_EOF)
krb5_err(context, 1, ret, "krb5_read_message");
} else {
ret = krb5_read_priv_message(context, ac, &sock, &data);
- if(ret)
+ if (ret)
krb5_err(context, 1, ret, "krb5_read_priv_message");
}
- if(ret == HEIM_ERR_EOF || data.length == 0) {
- if(!from_stdin) {
+ if (ret == HEIM_ERR_EOF || data.length == 0) {
+ if (!from_stdin) {
data.data = NULL;
data.length = 0;
krb5_write_priv_message(context, ac, &sock, &data);
}
- if(!print_dump) {
+ if (!print_dump) {
ret = db->hdb_close(context, db);
- if(ret)
+ if (ret)
krb5_err(context, 1, ret, "db_close");
ret = db->hdb_rename(context, db, database);
- if(ret)
+ if (ret)
krb5_err(context, 1, ret, "db_rename");
}
break;
@@ -254,20 +254,24 @@ main(int argc, char **argv)
memset(&entry, 0, sizeof(entry));
ret = hdb_value2entry(context, &data, &entry.entry);
krb5_data_free(&data);
- if(ret)
+ if (ret)
krb5_err(context, 1, ret, "hdb_value2entry");
- if(print_dump)
- hdb_print_entry(context, db, &entry, stdout);
- else {
+ if (print_dump) {
+ struct hdb_print_entry_arg parg;
+
+ parg.out = stdout;
+ parg.fmt = HDB_DUMP_HEIMDAL;
+ hdb_print_entry(context, db, &entry, &parg);
+ } else {
ret = db->hdb_store(context, db, 0, &entry);
- if(ret == HDB_ERR_EXISTS) {
+ if (ret == HDB_ERR_EXISTS) {
char *s;
ret = krb5_unparse_name(context, entry.entry.principal, &s);
if (ret)
s = strdup(unparseable_name);
krb5_warnx(context, "Entry exists: %s", s);
free(s);
- } else if(ret)
+ } else if (ret)
krb5_err(context, 1, ret, "db_store");
else
nprincs++;
diff --git a/crypto/heimdal/kdc/mit_dump.c b/crypto/heimdal/kdc/mit_dump.c
index f28e932b15b4..4397d1ad897d 100644
--- a/crypto/heimdal/kdc/mit_dump.c
+++ b/crypto/heimdal/kdc/mit_dump.c
@@ -33,6 +33,17 @@
#include "hprop.h"
+extern krb5_error_code _hdb_mdb_value2entry(krb5_context context,
+ krb5_data *data,
+ krb5_kvno target_kvno,
+ hdb_entry *entry);
+
+extern int _hdb_mit_dump2mitdb_entry(krb5_context context,
+ char *line,
+ krb5_storage *sp);
+
+
+
/*
can have any number of princ stanzas.
format is as follows (only \n indicates newlines)
@@ -74,19 +85,6 @@ unless no extra data
*/
-static int
-hex_to_octet_string(const char *ptr, krb5_data *data)
-{
- size_t i;
- unsigned int v;
- for(i = 0; i < data->length; i++) {
- if(sscanf(ptr + 2 * i, "%02x", &v) != 1)
- return -1;
- ((unsigned char*)data->data)[i] = v;
- }
- return 2 * i;
-}
-
static char *
nexttoken(char **p)
{
@@ -97,321 +95,116 @@ nexttoken(char **p)
return q;
}
-static size_t
-getdata(char **p, unsigned char *buf, size_t len)
-{
- size_t i;
- int v;
- char *q = nexttoken(p);
- i = 0;
- while(*q && i < len) {
- if(sscanf(q, "%02x", &v) != 1)
- break;
- buf[i++] = v;
- q += 2;
- }
- return i;
-}
-
-static int
-getint(char **p)
-{
- int val;
- char *q = nexttoken(p);
- sscanf(q, "%d", &val);
- return val;
-}
-
#include <kadm5/admin.h>
-static void
-attr_to_flags(unsigned attr, HDBFlags *flags)
-{
- flags->postdate = !(attr & KRB5_KDB_DISALLOW_POSTDATED);
- flags->forwardable = !(attr & KRB5_KDB_DISALLOW_FORWARDABLE);
- flags->initial = !!(attr & KRB5_KDB_DISALLOW_TGT_BASED);
- flags->renewable = !(attr & KRB5_KDB_DISALLOW_RENEWABLE);
- flags->proxiable = !(attr & KRB5_KDB_DISALLOW_PROXIABLE);
- /* DUP_SKEY */
- flags->invalid = !!(attr & KRB5_KDB_DISALLOW_ALL_TIX);
- flags->require_preauth = !!(attr & KRB5_KDB_REQUIRES_PRE_AUTH);
- flags->require_hwauth = !!(attr & KRB5_KDB_REQUIRES_HW_AUTH);
- flags->server = !(attr & KRB5_KDB_DISALLOW_SVR);
- flags->change_pw = !!(attr & KRB5_KDB_PWCHANGE_SERVICE);
- flags->client = 1; /* XXX */
-}
-
-#define KRB5_KDB_SALTTYPE_NORMAL 0
-#define KRB5_KDB_SALTTYPE_V4 1
-#define KRB5_KDB_SALTTYPE_NOREALM 2
-#define KRB5_KDB_SALTTYPE_ONLYREALM 3
-#define KRB5_KDB_SALTTYPE_SPECIAL 4
-#define KRB5_KDB_SALTTYPE_AFS3 5
-
-static krb5_error_code
-fix_salt(krb5_context context, hdb_entry *ent, int key_num)
+static int
+my_fgetln(FILE *f, char **buf, size_t *sz, size_t *len)
{
- krb5_error_code ret;
- Salt *salt = ent->keys.val[key_num].salt;
- /* fix salt type */
- switch((int)salt->type) {
- case KRB5_KDB_SALTTYPE_NORMAL:
- salt->type = KRB5_PADATA_PW_SALT;
- break;
- case KRB5_KDB_SALTTYPE_V4:
- krb5_data_free(&salt->salt);
- salt->type = KRB5_PADATA_PW_SALT;
- break;
- case KRB5_KDB_SALTTYPE_NOREALM:
- {
- size_t len;
- size_t i;
- char *p;
-
- len = 0;
- for (i = 0; i < ent->principal->name.name_string.len; ++i)
- len += strlen(ent->principal->name.name_string.val[i]);
- ret = krb5_data_alloc (&salt->salt, len);
- if (ret)
- return ret;
- p = salt->salt.data;
- for (i = 0; i < ent->principal->name.name_string.len; ++i) {
- memcpy (p,
- ent->principal->name.name_string.val[i],
- strlen(ent->principal->name.name_string.val[i]));
- p += strlen(ent->principal->name.name_string.val[i]);
- }
-
- salt->type = KRB5_PADATA_PW_SALT;
- break;
+ char *p, *n;
+
+ if (!*buf) {
+ *buf = malloc(*sz ? *sz : 2048);
+ if (!*buf)
+ return ENOMEM;
+ if (!*sz)
+ *sz = 2048;
}
- case KRB5_KDB_SALTTYPE_ONLYREALM:
- krb5_data_free(&salt->salt);
- ret = krb5_data_copy(&salt->salt,
- ent->principal->realm,
- strlen(ent->principal->realm));
- if(ret)
- return ret;
- salt->type = KRB5_PADATA_PW_SALT;
- break;
- case KRB5_KDB_SALTTYPE_SPECIAL:
- salt->type = KRB5_PADATA_PW_SALT;
- break;
- case KRB5_KDB_SALTTYPE_AFS3:
- krb5_data_free(&salt->salt);
- ret = krb5_data_copy(&salt->salt,
- ent->principal->realm,
- strlen(ent->principal->realm));
- if(ret)
- return ret;
- salt->type = KRB5_PADATA_AFS3_SALT;
- break;
- default:
- abort();
+ *len = 0;
+ while ((p = fgets(&(*buf)[*len], *sz, f))) {
+ if (strcspn(*buf, "\r\n") || feof(f)) {
+ *len = strlen(*buf);
+ return 0;
+ }
+ *len += strlen(&(*buf)[*len]); /* *len should be == *sz */
+ n = realloc(buf, *sz + (*sz >> 1));
+ if (!n) {
+ free(*buf);
+ *buf = NULL;
+ *sz = 0;
+ *len = 0;
+ return ENOMEM;
+ }
+ *buf = n;
+ *sz += *sz >> 1;
}
- return 0;
+ return 0; /* *len == 0 || no EOL -> EOF */
}
int
mit_prop_dump(void *arg, const char *file)
{
krb5_error_code ret;
- char line [2048];
- FILE *f;
+ size_t line_bufsz = 0;
+ size_t line_len = 0;
+ char *line = NULL;
int lineno = 0;
+ FILE *f;
struct hdb_entry_ex ent;
-
struct prop_data *pd = arg;
+ krb5_storage *sp = NULL;
+ krb5_data kdb_ent;
+ memset(&ent, 0, sizeof (ent));
f = fopen(file, "r");
- if(f == NULL)
+ if (f == NULL)
return errno;
- while(fgets(line, sizeof(line), f)) {
- char *p = line, *q;
-
- int i;
-
- int num_tl_data;
- int num_key_data;
- int high_kvno;
- int attributes;
+ ret = ENOMEM;
+ sp = krb5_storage_emem();
+ if (!sp)
+ goto out;
+ while ((ret = my_fgetln(f, &line, &line_bufsz, &line_len)) == 0) {
+ char *p = line;
+ char *q;
+ lineno++;
- int tmp;
-
- lineno++;
-
- memset(&ent, 0, sizeof(ent));
-
- q = nexttoken(&p);
- if(strcmp(q, "kdb5_util") == 0) {
+ if(strncmp(line, "kdb5_util", strlen("kdb5_util")) == 0) {
int major;
+ q = nexttoken(&p);
+ if (strcmp(q, "kdb5_util"))
+ errx(1, "line %d: unknown version", lineno);
q = nexttoken(&p); /* load_dump */
- if(strcmp(q, "load_dump"))
+ if (strcmp(q, "load_dump"))
errx(1, "line %d: unknown version", lineno);
q = nexttoken(&p); /* load_dump */
- if(strcmp(q, "version"))
+ if (strcmp(q, "version"))
errx(1, "line %d: unknown version", lineno);
q = nexttoken(&p); /* x.0 */
- if(sscanf(q, "%d", &major) != 1)
+ if (sscanf(q, "%d", &major) != 1)
errx(1, "line %d: unknown version", lineno);
- if(major != 4 && major != 5 && major != 6)
+ if (major != 4 && major != 5 && major != 6)
errx(1, "unknown dump file format, got %d, expected 4-6",
major);
continue;
- } else if(strcmp(q, "policy") == 0) {
+ } else if(strncmp(p, "policy", strlen("policy")) == 0) {
+ warnx("line: %d: ignoring policy (not supported)", lineno);
continue;
- } else if(strcmp(q, "princ") != 0) {
+ } else if(strncmp(p, "princ", strlen("princ")) != 0) {
warnx("line %d: not a principal", lineno);
continue;
}
- tmp = getint(&p);
- if(tmp != 38) {
- warnx("line %d: bad base length %d != 38", lineno, tmp);
- continue;
- }
- nexttoken(&p); /* length of principal */
- num_tl_data = getint(&p); /* number of tl-data */
- num_key_data = getint(&p); /* number of key-data */
- getint(&p); /* length of extra data */
- q = nexttoken(&p); /* principal name */
- krb5_parse_name(pd->context, q, &ent.entry.principal);
- attributes = getint(&p); /* attributes */
- attr_to_flags(attributes, &ent.entry.flags);
- tmp = getint(&p); /* max life */
- if(tmp != 0) {
- ALLOC(ent.entry.max_life);
- *ent.entry.max_life = tmp;
- }
- tmp = getint(&p); /* max renewable life */
- if(tmp != 0) {
- ALLOC(ent.entry.max_renew);
- *ent.entry.max_renew = tmp;
- }
- tmp = getint(&p); /* expiration */
- if(tmp != 0 && tmp != 2145830400) {
- ALLOC(ent.entry.valid_end);
- *ent.entry.valid_end = tmp;
- }
- tmp = getint(&p); /* pw expiration */
- if(tmp != 0) {
- ALLOC(ent.entry.pw_end);
- *ent.entry.pw_end = tmp;
- }
- nexttoken(&p); /* last auth */
- nexttoken(&p); /* last failed auth */
- nexttoken(&p); /* fail auth count */
- for(i = 0; i < num_tl_data; i++) {
- unsigned long val;
- int tl_type, tl_length;
- unsigned char *buf;
- krb5_principal princ;
-
- tl_type = getint(&p); /* data type */
- tl_length = getint(&p); /* data length */
-
-#define mit_KRB5_TL_LAST_PWD_CHANGE 1
-#define mit_KRB5_TL_MOD_PRINC 2
- switch(tl_type) {
- case mit_KRB5_TL_LAST_PWD_CHANGE:
- buf = malloc(tl_length);
- if (buf == NULL)
- errx(ENOMEM, "malloc");
- getdata(&p, buf, tl_length); /* data itself */
- val = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
- free(buf);
- ALLOC(ent.entry.extensions);
- ALLOC_SEQ(ent.entry.extensions, 1);
- ent.entry.extensions->val[0].mandatory = 0;
- ent.entry.extensions->val[0].data.element
- = choice_HDB_extension_data_last_pw_change;
- ent.entry.extensions->val[0].data.u.last_pw_change = val;
- break;
- case mit_KRB5_TL_MOD_PRINC:
- buf = malloc(tl_length);
- if (buf == NULL)
- errx(ENOMEM, "malloc");
- getdata(&p, buf, tl_length); /* data itself */
- val = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
- ret = krb5_parse_name(pd->context, (char *)buf + 4, &princ);
- if (ret)
- krb5_err(pd->context, 1, ret,
- "parse_name: %s", (char *)buf + 4);
- free(buf);
- ALLOC(ent.entry.modified_by);
- ent.entry.modified_by->time = val;
- ent.entry.modified_by->principal = princ;
- break;
- default:
- nexttoken(&p);
- break;
- }
- }
- ALLOC_SEQ(&ent.entry.keys, num_key_data);
- high_kvno = -1;
- for(i = 0; i < num_key_data; i++) {
- int key_versions;
- int kvno;
- key_versions = getint(&p); /* key data version */
- kvno = getint(&p);
-
- /*
- * An MIT dump file may contain multiple sets of keys with
- * different kvnos. Since the Heimdal database can only represent
- * one kvno per principal, we only want the highest set. Assume
- * that set will be given first, and discard all keys with lower
- * kvnos.
- */
- if (kvno > high_kvno && high_kvno != -1)
- errx(1, "line %d: high kvno keys given after low kvno keys",
- lineno);
- else if (kvno < high_kvno) {
- nexttoken(&p); /* key type */
- nexttoken(&p); /* key length */
- nexttoken(&p); /* key */
- if (key_versions > 1) {
- nexttoken(&p); /* salt type */
- nexttoken(&p); /* salt length */
- nexttoken(&p); /* salt */
- }
- ent.entry.keys.len--;
- continue;
- }
- ent.entry.kvno = kvno;
- high_kvno = kvno;
- ALLOC(ent.entry.keys.val[i].mkvno);
- *ent.entry.keys.val[i].mkvno = 1;
-
- /* key version 0 -- actual key */
- ent.entry.keys.val[i].key.keytype = getint(&p); /* key type */
- tmp = getint(&p); /* key length */
- /* the first two bytes of the key is the key length --
- skip it */
- krb5_data_alloc(&ent.entry.keys.val[i].key.keyvalue, tmp - 2);
- q = nexttoken(&p); /* key itself */
- hex_to_octet_string(q + 4, &ent.entry.keys.val[i].key.keyvalue);
-
- if(key_versions > 1) {
- /* key version 1 -- optional salt */
- ALLOC(ent.entry.keys.val[i].salt);
- ent.entry.keys.val[i].salt->type = getint(&p); /* salt type */
- tmp = getint(&p); /* salt length */
- if(tmp > 0) {
- krb5_data_alloc(&ent.entry.keys.val[i].salt->salt, tmp - 2);
- q = nexttoken(&p); /* salt itself */
- hex_to_octet_string(q + 4,
- &ent.entry.keys.val[i].salt->salt);
- } else {
- ent.entry.keys.val[i].salt->salt.length = 0;
- ent.entry.keys.val[i].salt->salt.data = NULL;
- getint(&p); /* -1, if no data. */
- }
- fix_salt(pd->context, &ent.entry, i);
- }
- }
- nexttoken(&p); /* extra data */
- v5_prop(pd->context, NULL, &ent, arg);
+ krb5_storage_truncate(sp, 0);
+ ret = _hdb_mit_dump2mitdb_entry(pd->context, line, sp);
+ if (ret) break;
+ ret = krb5_storage_to_data(sp, &kdb_ent);
+ if (ret) break;
+ ret = _hdb_mdb_value2entry(pd->context, &kdb_ent, 0, &ent.entry);
+ krb5_data_free(&kdb_ent);
+ if (ret) break;
+ ret = v5_prop(pd->context, NULL, &ent, arg);
+ hdb_free_entry(pd->context, &ent);
+ if (ret) break;
}
+
+out:
fclose(f);
- return 0;
+ free(line);
+ if (sp)
+ krb5_storage_free(sp);
+ if (ret && ret == ENOMEM)
+ errx(1, "out of memory");
+ if (ret)
+ errx(1, "line %d: problem parsing dump line", lineno);
+ return ret;
}
+
diff --git a/crypto/heimdal/lib/hdb/Makefile.am b/crypto/heimdal/lib/hdb/Makefile.am
index b629f56258d2..fd009bd26867 100644
--- a/crypto/heimdal/lib/hdb/Makefile.am
+++ b/crypto/heimdal/lib/hdb/Makefile.am
@@ -29,6 +29,7 @@ gen_files_hdb = \
asn1_HDB_Ext_Lan_Manager_OWF.x \
asn1_HDB_Ext_Password.x \
asn1_HDB_Ext_Aliases.x \
+ asn1_HDB_Ext_KeySet.x \
asn1_HDB_extension.x \
asn1_HDB_extensions.x \
asn1_hdb_entry.x \
diff --git a/crypto/heimdal/lib/hdb/common.c b/crypto/heimdal/lib/hdb/common.c
index 2715adf63dca..80482e7a4c1c 100644
--- a/crypto/heimdal/lib/hdb/common.c
+++ b/crypto/heimdal/lib/hdb/common.c
@@ -105,7 +105,6 @@ _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal,
krb5_principal enterprise_principal = NULL;
krb5_data key, value;
krb5_error_code ret;
- int code;
if (principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) {
if (principal->name.name_string.len != 1) {
@@ -125,43 +124,74 @@ _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal,
hdb_principal2key(context, principal, &key);
if (enterprise_principal)
krb5_free_principal(context, enterprise_principal);
- code = db->hdb__get(context, db, key, &value);
+ ret = db->hdb__get(context, db, key, &value);
krb5_data_free(&key);
- if(code)
- return code;
- code = hdb_value2entry(context, &value, &entry->entry);
- if (code == ASN1_BAD_ID && (flags & HDB_F_CANON) == 0) {
+ if(ret)
+ return ret;
+ ret = hdb_value2entry(context, &value, &entry->entry);
+ if (ret == ASN1_BAD_ID && (flags & HDB_F_CANON) == 0) {
krb5_data_free(&value);
return HDB_ERR_NOENTRY;
- } else if (code == ASN1_BAD_ID) {
+ } else if (ret == ASN1_BAD_ID) {
hdb_entry_alias alias;
- code = hdb_value2entry_alias(context, &value, &alias);
- if (code) {
+ ret = hdb_value2entry_alias(context, &value, &alias);
+ if (ret) {
krb5_data_free(&value);
- return code;
+ return ret;
}
hdb_principal2key(context, alias.principal, &key);
krb5_data_free(&value);
free_hdb_entry_alias(&alias);
- code = db->hdb__get(context, db, key, &value);
+ ret = db->hdb__get(context, db, key, &value);
krb5_data_free(&key);
- if (code)
- return code;
- code = hdb_value2entry(context, &value, &entry->entry);
- if (code) {
+ if (ret)
+ return ret;
+ ret = hdb_value2entry(context, &value, &entry->entry);
+ if (ret) {
krb5_data_free(&value);
- return code;
+ return ret;
}
}
krb5_data_free(&value);
if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
- code = hdb_unseal_keys (context, db, &entry->entry);
- if (code)
+#ifdef notnow
+ if ((flags & HDB_F_KVNO_SPECIFIED) == 0 &&
+ (flags & HDB_F_CURRENT_KVNO) == 0) {
+
+ /*
+ * Decrypt all the old keys too, since we don't know which
+ * the caller will need.
+ */
+ ret = hdb_unseal_keys_kvno(context, db, 0, &entry->entry);
+ if (ret) {
+ hdb_free_entry(context, entry);
+ return ret;
+ }
+ } else if ((flags & HDB_F_KVNO_SPECIFIED) != 0 &&
+ kvno != entry->entry.kvno &&
+ kvno < entry->entry.kvno &&
+ kvno > 0) {
+
+ /* Decrypt the keys we were asked for, if not the current ones */
+ ret = hdb_unseal_keys_kvno(context, db, kvno, &entry->entry);
+ if (ret) {
+ hdb_free_entry(context, entry);
+ return ret;
+ }
+ }
+#endif
+
+ /* Always decrypt the current keys too */
+ ret = hdb_unseal_keys(context, db, &entry->entry);
+ if (ret) {
hdb_free_entry(context, entry);
+ return ret;
+ }
}
- return code;
+
+ return ret;
}
static krb5_error_code
diff --git a/crypto/heimdal/lib/hdb/ext.c b/crypto/heimdal/lib/hdb/ext.c
index d2a4373b9b38..5f7a19a55e04 100644
--- a/crypto/heimdal/lib/hdb/ext.c
+++ b/crypto/heimdal/lib/hdb/ext.c
@@ -432,3 +432,34 @@ hdb_entry_get_aliases(const hdb_entry *entry, const HDB_Ext_Aliases **a)
return 0;
}
+
+krb5_error_code
+hdb_set_last_modified_by(krb5_context context, hdb_entry *entry,
+ krb5_principal modby, time_t modtime)
+{
+ krb5_error_code ret;
+ Event *old_ev;
+ Event *ev;
+
+ old_ev = entry->modified_by;
+
+ ev = calloc(1, sizeof (*ev));
+ if (!ev)
+ return ENOMEM;
+ if (modby)
+ ret = krb5_copy_principal(context, modby, &ev->principal);
+ else
+ ret = krb5_parse_name(context, "root/admin", &ev->principal);
+ if (ret) {
+ free(ev);
+ return ret;
+ }
+ ev->time = modtime;
+ if (!ev->time)
+ time(&ev->time);
+
+ entry->modified_by = ev;
+ if (old_ev)
+ free_Event(old_ev);
+ return 0;
+}
diff --git a/crypto/heimdal/lib/hdb/hdb-mitdb.c b/crypto/heimdal/lib/hdb/hdb-mitdb.c
index 02c575050fe2..1dfe7835cb4d 100644
--- a/crypto/heimdal/lib/hdb/hdb-mitdb.c
+++ b/crypto/heimdal/lib/hdb/hdb-mitdb.c
@@ -91,18 +91,28 @@ salt:
#include "hdb_locl.h"
-#define KDB_V1_BASE_LENGTH 38
-
-#if HAVE_DB1
+static void
+attr_to_flags(unsigned attr, HDBFlags *flags)
+{
+ flags->postdate = !(attr & KRB5_KDB_DISALLOW_POSTDATED);
+ flags->forwardable = !(attr & KRB5_KDB_DISALLOW_FORWARDABLE);
+ flags->initial = !!(attr & KRB5_KDB_DISALLOW_TGT_BASED);
+ flags->renewable = !(attr & KRB5_KDB_DISALLOW_RENEWABLE);
+ flags->proxiable = !(attr & KRB5_KDB_DISALLOW_PROXIABLE);
+ /* DUP_SKEY */
+ flags->invalid = !!(attr & KRB5_KDB_DISALLOW_ALL_TIX);
+ flags->require_preauth = !!(attr & KRB5_KDB_REQUIRES_PRE_AUTH);
+ flags->require_hwauth = !!(attr & KRB5_KDB_REQUIRES_HW_AUTH);
+ flags->server = !(attr & KRB5_KDB_DISALLOW_SVR);
+ flags->change_pw = !!(attr & KRB5_KDB_PWCHANGE_SERVICE);
+ flags->client = 1; /* XXX */
+}
-#if defined(HAVE_DB_185_H)
-#include <db_185.h>
-#elif defined(HAVE_DB_H)
-#include <db.h>
-#endif
+#define KDB_V1_BASE_LENGTH 38
#define CHECK(x) do { if ((x)) goto out; } while(0)
+#ifdef HAVE_DB1
static krb5_error_code
mdb_principal2key(krb5_context context,
krb5_const_principal principal,
@@ -118,6 +128,7 @@ mdb_principal2key(krb5_context context,
key->length = strlen(str) + 1;
return 0;
}
+#endif /* HAVE_DB1 */
#define KRB5_KDB_SALTTYPE_NORMAL 0
#define KRB5_KDB_SALTTYPE_V4 1
@@ -197,13 +208,15 @@ fix_salt(krb5_context context, hdb_entry *ent, int key_num)
}
-static krb5_error_code
-mdb_value2entry(krb5_context context, krb5_data *data, krb5_kvno kvno, hdb_entry *entry)
+krb5_error_code
+_hdb_mdb_value2entry(krb5_context context, krb5_data *data,
+ krb5_kvno kvno, hdb_entry *entry)
{
krb5_error_code ret;
krb5_storage *sp;
uint32_t u32;
uint16_t u16, num_keys, num_tl;
+ ssize_t sz;
size_t i, j;
char *p;
@@ -234,18 +247,7 @@ mdb_value2entry(krb5_context context, krb5_data *data, krb5_kvno kvno, hdb_entry
if (u16 != KDB_V1_BASE_LENGTH) { ret = EINVAL; goto out; }
/* 32: attributes */
CHECK(ret = krb5_ret_uint32(sp, &u32));
- entry->flags.postdate = !(u32 & KRB5_KDB_DISALLOW_POSTDATED);
- entry->flags.forwardable = !(u32 & KRB5_KDB_DISALLOW_FORWARDABLE);
- entry->flags.initial = !!(u32 & KRB5_KDB_DISALLOW_TGT_BASED);
- entry->flags.renewable = !(u32 & KRB5_KDB_DISALLOW_RENEWABLE);
- entry->flags.proxiable = !(u32 & KRB5_KDB_DISALLOW_PROXIABLE);
- /* DUP_SKEY */
- entry->flags.invalid = !!(u32 & KRB5_KDB_DISALLOW_ALL_TIX);
- entry->flags.require_preauth =!!(u32 & KRB5_KDB_REQUIRES_PRE_AUTH);
- entry->flags.require_hwauth =!!(u32 & KRB5_KDB_REQUIRES_HW_AUTH);
- entry->flags.server = !(u32 & KRB5_KDB_DISALLOW_SVR);
- entry->flags.change_pw = !!(u32 & KRB5_KDB_PWCHANGE_SERVICE);
- entry->flags.client = 1; /* XXX */
+ attr_to_flags(u32, &entry->flags);
/* 32: max time */
CHECK(ret = krb5_ret_uint32(sp, &u32));
@@ -296,7 +298,11 @@ mdb_value2entry(krb5_context context, krb5_data *data, krb5_kvno kvno, hdb_entry
ret = ENOMEM;
goto out;
}
- krb5_storage_read(sp, p, u16);
+ sz = krb5_storage_read(sp, p, u16);
+ if (sz != u16) {
+ ret = EINVAL; /* XXX */
+ goto out;
+ }
p[u16] = '\0';
CHECK(ret = krb5_parse_name(context, p, &entry->principal));
free(p);
@@ -305,12 +311,53 @@ mdb_value2entry(krb5_context context, krb5_data *data, krb5_kvno kvno, hdb_entry
16: tl data type
16: tl data length
length: length */
+#define mit_KRB5_TL_LAST_PWD_CHANGE 1
+#define mit_KRB5_TL_MOD_PRINC 2
for (i = 0; i < num_tl; i++) {
+ int tl_type;
+ krb5_principal modby;
/* 16: TL data type */
CHECK(ret = krb5_ret_uint16(sp, &u16));
+ tl_type = u16;
/* 16: TL data length */
CHECK(ret = krb5_ret_uint16(sp, &u16));
- krb5_storage_seek(sp, u16, SEEK_CUR);
+ /*
+ * For rollback to MIT purposes we really must understand some
+ * TL data!
+ *
+ * XXX Move all this to separate functions, one per-TL type.
+ */
+ switch (tl_type) {
+ case mit_KRB5_TL_LAST_PWD_CHANGE:
+ CHECK(ret = krb5_ret_uint32(sp, &u32));
+ CHECK(ret = hdb_entry_set_pw_change_time(context, entry, u32));
+ break;
+ case mit_KRB5_TL_MOD_PRINC:
+ if (u16 < 5) {
+ ret = EINVAL; /* XXX */
+ goto out;
+ }
+ CHECK(ret = krb5_ret_uint32(sp, &u32)); /* mod time */
+ p = malloc(u16 - 4 + 1);
+ if (!p) {
+ ret = ENOMEM;
+ goto out;
+ }
+ p[u16 - 4] = '\0';
+ sz = krb5_storage_read(sp, p, u16 - 4);
+ if (sz != u16 - 4) {
+ ret = EINVAL; /* XXX */
+ goto out;
+ }
+ CHECK(ret = krb5_parse_name(context, p, &modby));
+ ret = hdb_set_last_modified_by(context, entry, modby, u32);
+ krb5_free_principal(context, modby);
+ free(p);
+ break;
+ default:
+ krb5_storage_seek(sp, u16, SEEK_CUR);
+ break;
+ }
}
/*
* for num key data times
@@ -471,6 +518,14 @@ mdb_entry2value(krb5_context context, hdb_entry *entry, krb5_data *data)
}
#endif
+#if HAVE_DB1
+
+#if defined(HAVE_DB_185_H)
+#include <db_185.h>
+#elif defined(HAVE_DB_H)
+#include <db.h>
+#endif
+
static krb5_error_code
mdb_close(krb5_context context, HDB *db)
@@ -551,7 +606,7 @@ mdb_seq(krb5_context context, HDB *db,
data.length = value.size;
memset(entry, 0, sizeof(*entry));
- if (mdb_value2entry(context, &data, 0, &entry->entry))
+ if (_hdb_mdb_value2entry(context, &data, 0, &entry->entry))
return mdb_seq(context, db, flags, entry, R_NEXT);
if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
@@ -684,24 +739,26 @@ mdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal,
unsigned flags, krb5_kvno kvno, hdb_entry_ex *entry)
{
krb5_data key, value;
- krb5_error_code code;
+ krb5_error_code ret;
- code = mdb_principal2key(context, principal, &key);
- if (code)
- return code;
- code = db->hdb__get(context, db, key, &value);
+ ret = mdb_principal2key(context, principal, &key);
+ if (ret)
+ return ret;
+ ret = db->hdb__get(context, db, key, &value);
krb5_data_free(&key);
- if(code)
- return code;
- code = mdb_value2entry(context, &value, kvno, &entry->entry);
+ if(ret)
+ return ret;
+ ret = _hdb_mdb_value2entry(context, &value, kvno, &entry->entry);
krb5_data_free(&value);
- if (code)
- return code;
+ if (ret)
+ return ret;
if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
- code = hdb_unseal_keys (context, db, &entry->entry);
- if (code)
+ ret = hdb_unseal_keys (context, db, &entry->entry);
+ if (ret) {
hdb_free_entry(context, entry);
+ return ret;
+ }
}
return 0;
@@ -710,8 +767,48 @@ mdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal,
static krb5_error_code
mdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
{
- krb5_set_error_message(context, EINVAL, "can't set principal in mdb");
- return EINVAL;
+ krb5_error_code ret;
+ krb5_storage *sp = NULL;
+ krb5_storage *spent = NULL;
+ krb5_data line = { 0, 0 };
+ krb5_data kdb_ent = { 0, 0 };
+ krb5_data key = { 0, 0 };
+ ssize_t sz;
+
+ sp = krb5_storage_emem();
+ if (!sp) return ENOMEM;
+ ret = _hdb_set_master_key_usage(context, db, 0); /* MIT KDB uses KU 0 */
+ ret = hdb_seal_keys(context, db, &entry->entry);
+ if (ret) return ret;
+ ret = entry2mit_string_int(context, sp, &entry->entry);
+ if (ret) goto out;
+ sz = krb5_storage_write(sp, "\n", 2); /* NUL-terminate */
+ ret = ENOMEM;
+ if (sz == -1) goto out;
+ ret = krb5_storage_to_data(sp, &line);
+ if (ret) goto out;
+
+ ret = ENOMEM;
+ spent = krb5_storage_emem();
+ if (!spent) goto out;
+ ret = _hdb_mit_dump2mitdb_entry(context, line.data, spent);
+ if (ret) goto out;
+ ret = krb5_storage_to_data(spent, &kdb_ent);
+ if (ret) goto out;
+ ret = mdb_principal2key(context, entry->entry.principal, &key);
+ if (ret) goto out;
+ ret = mdb__put(context, db, 1, key, kdb_ent);
+
+out:
+ if (sp)
+ krb5_storage_free(sp);
+ if (spent)
+ krb5_storage_free(spent);
+ krb5_data_free(&line);
+ krb5_data_free(&kdb_ent);
+ krb5_data_free(&key);
+
+ return ret;
}
static krb5_error_code
@@ -729,25 +826,31 @@ static krb5_error_code
mdb_open(krb5_context context, HDB *db, int flags, mode_t mode)
{
char *fn;
+ char *actual_fn;
krb5_error_code ret;
+ struct stat st;
asprintf(&fn, "%s.db", db->hdb_name);
if (fn == NULL) {
krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
return ENOMEM;
}
- db->hdb_db = dbopen(fn, flags, mode, DB_BTREE, NULL);
- free(fn);
+ if (stat(fn, &st) == 0)
+ actual_fn = fn;
+ else
+ actual_fn = db->hdb_name;
+ db->hdb_db = dbopen(actual_fn, flags, mode, DB_BTREE, NULL);
if (db->hdb_db == NULL) {
switch (errno) {
#ifdef EFTYPE
case EFTYPE:
#endif
case EINVAL:
- db->hdb_db = dbopen(fn, flags, mode, DB_BTREE, NULL);
+ db->hdb_db = dbopen(actual_fn, flags, mode, DB_BTREE, NULL);
}
}
+ free(fn);
/* try to open without .db extension */
if(db->hdb_db == NULL && errno == ENOENT)
@@ -758,11 +861,16 @@ mdb_open(krb5_context context, HDB *db, int flags, mode_t mode)
db->hdb_name, strerror(ret));
return ret;
}
- if((flags & O_ACCMODE) == O_RDONLY)
- ret = hdb_check_db_format(context, db);
- else
+#if 0
+ /*
+ * Don't do this -- MIT won't be able to handle the
+ * HDB_DB_FORMAT_ENTRY key.
+ */
+ if ((flags & O_ACCMODE) != O_RDONLY)
ret = hdb_init_db(context, db);
- if(ret == HDB_ERR_NOENTRY) {
+#endif
+ ret = hdb_check_db_format(context, db);
+ if (ret == HDB_ERR_NOENTRY) {
krb5_clear_error_message(context);
return 0;
}
@@ -815,3 +923,280 @@ hdb_mdb_create(krb5_context context, HDB **db,
}
#endif /* HAVE_DB1 */
+
+/*
+can have any number of princ stanzas.
+format is as follows (only \n indicates newlines)
+princ\t%d\t (%d is KRB5_KDB_V1_BASE_LENGTH, always 38)
+%d\t (strlen of principal e.g. shadow/foo@ANDREW.CMU.EDU)
+%d\t (number of tl_data)
+%d\t (number of key data, e.g. how many keys for this user)
+%d\t (extra data length)
+%s\t (principal name)
+%d\t (attributes)
+%d\t (max lifetime, seconds)
+%d\t (max renewable life, seconds)
+%d\t (expiration, seconds since epoch or 2145830400 for never)
+%d\t (password expiration, seconds, 0 for never)
+%d\t (last successful auth, seconds since epoch)
+%d\t (last failed auth, per above)
+%d\t (failed auth count)
+foreach tl_data 0 to number of tl_data - 1 as above
+ %d\t%d\t (data type, data length)
+ foreach tl_data 0 to length-1
+ %02x (tl data contents[element n])
+ except if tl_data length is 0
+ %d (always -1)
+ \t
+foreach key 0 to number of keys - 1 as above
+ %d\t%d\t (key data version, kvno)
+ foreach version 0 to key data version - 1 (a key or a salt)
+ %d\t%d\t(data type for this key, data length for this key)
+ foreach key data length 0 to length-1
+ %02x (key data contents[element n])
+ except if key_data length is 0
+ %d (always -1)
+ \t
+foreach extra data length 0 to length - 1
+ %02x (extra data part)
+unless no extra data
+ %d (always -1)
+;\n
+
+*/
+
+static char *
+nexttoken(char **p)
+{
+ char *q;
+ do {
+ q = strsep(p, " \t");
+ } while(q && *q == '\0');
+ return q;
+}
+
+static size_t
+getdata(char **p, unsigned char *buf, size_t len)
+{
+ size_t i;
+ int v;
+ char *q = nexttoken(p);
+ i = 0;
+ while(*q && i < len) {
+ if(sscanf(q, "%02x", &v) != 1)
+ break;
+ buf[i++] = v;
+ q += 2;
+ }
+ return i;
+}
+
+static int
+getint(char **p)
+{
+ int val;
+ char *q = nexttoken(p);
+ sscanf(q, "%d", &val);
+ return val;
+}
+
+static unsigned int
+getuint(char **p)
+{
+ int val;
+ char *q = nexttoken(p);
+ sscanf(q, "%u", &val);
+ return val;
+}
+
+#define KRB5_KDB_SALTTYPE_NORMAL 0
+#define KRB5_KDB_SALTTYPE_V4 1
+#define KRB5_KDB_SALTTYPE_NOREALM 2
+#define KRB5_KDB_SALTTYPE_ONLYREALM 3
+#define KRB5_KDB_SALTTYPE_SPECIAL 4
+#define KRB5_KDB_SALTTYPE_AFS3 5
+
+#define CHECK_UINT(num) \
+ if ((num) < 0 || (num) > INT_MAX) return EINVAL
+#define CHECK_UINT16(num) \
+ if ((num) < 0 || (num) > 1<<15) return EINVAL
+#define CHECK_NUM(num, maxv) \
+ if ((num) > (maxv)) return EINVAL
+
+/*
+ * This utility function converts an MIT dump entry to an MIT on-disk
+ * encoded entry, which can then be decoded with _hdb_mdb_value2entry().
+ * This allows us to have a single decoding function (_hdb_mdb_value2entry),
+ * which makes the code cleaner (less code duplication), if a bit less
+ * efficient. It also will allow us to have a function to dump an HDB
+ * entry in MIT format so we can dump HDB into MIT format for rollback
+ * purposes. And that will allow us to write to MIT KDBs, again
+ * somewhat inefficiently, also for migration/rollback purposes.
+ */
+int
+_hdb_mit_dump2mitdb_entry(krb5_context context, char *line, krb5_storage *sp)
+{
+ krb5_error_code ret = EINVAL;
+ char *p = line, *q;
+ char *princ;
+ ssize_t sz;
+ size_t i;
+ size_t princ_len;
+ unsigned int num_tl_data;
+ size_t num_key_data;
+ unsigned int attributes;
+ int tmp;
+
+ krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE);
+
+ q = nexttoken(&p);
+ if (strcmp(q, "kdb5_util") == 0 || strcmp(q, "policy") == 0 ||
+ strcmp(q, "princ") != 0) {
+ return -1;
+ }
+ if (getint(&p) != 38)
+ return EINVAL;
+#define KDB_V1_BASE_LENGTH 38
+ ret = krb5_store_int16(sp, KDB_V1_BASE_LENGTH);
+ if (ret) return ret;
+
+ nexttoken(&p); /* length of principal */
+ num_tl_data = getuint(&p); /* number of tl-data */
+ num_key_data = getuint(&p); /* number of key-data */
+ getint(&p); /* length of extra data */
+ princ = nexttoken(&p); /* principal name */
+
+ attributes = getuint(&p); /* attributes */
+ ret = krb5_store_uint32(sp, attributes);
+ if (ret) return ret;
+
+ tmp = getint(&p); /* max life */
+ CHECK_UINT(tmp);
+ ret = krb5_store_uint32(sp, tmp);
+ if (ret) return ret;
+
+ tmp = getint(&p); /* max renewable life */
+ CHECK_UINT(tmp);
+ ret = krb5_store_uint32(sp, tmp);
+ if (ret) return ret;
+
+ tmp = getint(&p); /* expiration */
+ CHECK_UINT(tmp);
+ ret = krb5_store_uint32(sp, tmp);
+ if (ret) return ret;
+
+ tmp = getint(&p); /* pw expiration */
+ CHECK_UINT(tmp);
+ ret = krb5_store_uint32(sp, tmp);
+ if (ret) return ret;
+
+ tmp = getint(&p); /* last auth */
+ CHECK_UINT(tmp);
+ ret = krb5_store_uint32(sp, tmp);
+ if (ret) return ret;
+
+ tmp = getint(&p); /* last failed auth */
+ CHECK_UINT(tmp);
+ ret = krb5_store_uint32(sp, tmp);
+ if (ret) return ret;
+
+ tmp = getint(&p); /* fail auth count */
+ CHECK_UINT(tmp);
+ ret = krb5_store_uint32(sp, tmp);
+ if (ret) return ret;
+
+ /* add TL data count */
+ CHECK_NUM(num_tl_data, 1023);
+ ret = krb5_store_uint16(sp, num_tl_data);
+ if (ret) return ret;
+
+ /* add key count */
+ CHECK_NUM(num_key_data, 1023);
+ ret = krb5_store_uint16(sp, num_key_data);
+ if (ret) return ret;
+
+ /* add principal unparsed name length and unparsed name */
+ princ_len = strlen(princ);
+ if (princ_len > (1<<15) - 1) return EINVAL;
+ princ_len++; /* must count and write the NUL in the on-disk encoding */
+ ret = krb5_store_uint16(sp, princ_len);
+ if (ret) return ret;
+ sz = krb5_storage_write(sp, princ, princ_len);
+ if (sz == -1) return ENOMEM;
+
+ /* scan and write TL data */
+ for (i = 0; i < num_tl_data; i++) {
+ int tl_type, tl_length;
+ unsigned char *buf;
+
+ tl_type = getint(&p); /* data type */
+ tl_length = getint(&p); /* data length */
+
+ CHECK_UINT16(tl_type);
+ ret = krb5_store_uint16(sp, tl_type);
+ if (ret) return ret;
+ CHECK_UINT16(tl_length);
+ ret = krb5_store_uint16(sp, tl_length);
+ if (ret) return ret;
+
+ if (tl_length) {
+ buf = malloc(tl_length);
+ if (!buf) return ENOMEM;
+ if (getdata(&p, buf, tl_length) != tl_length) return EINVAL;
+ sz = krb5_storage_write(sp, buf, tl_length);
+ free(buf);
+ if (sz == -1) return ENOMEM;
+ } else {
+ if (strcmp(nexttoken(&p), "-1") != 0) return EINVAL;
+ }
+ }
+
+ for (i = 0; i < num_key_data; i++) {
+ unsigned char *buf;
+ int key_versions;
+ int kvno;
+ int keytype;
+ int keylen;
+ size_t k;
+
+ key_versions = getint(&p); /* key data version */
+ CHECK_UINT16(key_versions);
+ ret = krb5_store_int16(sp, key_versions);
+ if (ret) return ret;
+
+ kvno = getint(&p);
+ CHECK_UINT16(kvno);
+ ret = krb5_store_int16(sp, kvno);
+ if (ret) return ret;
+
+ for (k = 0; k < key_versions; k++) {
+ keytype = getint(&p);
+ CHECK_UINT16(keytype);
+ ret = krb5_store_int16(sp, keytype);
+ if (ret) return ret;
+
+ keylen = getint(&p);
+ CHECK_UINT16(keylen);
+ ret = krb5_store_int16(sp, keylen);
+ if (ret) return ret;
+
+ if (keylen) {
+ buf = malloc(keylen);
+ if (!buf) return ENOMEM;
+ if (getdata(&p, buf, keylen) != keylen) return EINVAL;
+ sz = krb5_storage_write(sp, buf, keylen);
+ free(buf);
+ if (sz == -1) return ENOMEM;
+ } else {
+ if (strcmp(nexttoken(&p), "-1") != 0) return EINVAL;
+ }
+ }
+ }
+ /*
+ * The rest is "extra data", but there's never any and we wouldn't
+ * know what to do with it.
+ */
+ /* nexttoken(&p); */
+ return 0;
+}
+
diff --git a/crypto/heimdal/lib/hdb/hdb-protos.h b/crypto/heimdal/lib/hdb/hdb-protos.h
index 44a1bddc7625..2b692855c405 100644
--- a/crypto/heimdal/lib/hdb/hdb-protos.h
+++ b/crypto/heimdal/lib/hdb/hdb-protos.h
@@ -9,6 +9,17 @@ extern "C" {
#endif
krb5_error_code
+entry2mit_string_int (
+ krb5_context /*context*/,
+ krb5_storage */*sp*/,
+ hdb_entry */*ent*/);
+
+krb5_error_code
+hdb_add_current_keys_to_history (
+ krb5_context /*context*/,
+ hdb_entry */*entry*/);
+
+krb5_error_code
hdb_add_master_key (
krb5_context /*context*/,
krb5_keyblock */*key*/,
@@ -347,6 +358,13 @@ hdb_seal_keys_mkey (
hdb_master_key /*mkey*/);
krb5_error_code
+hdb_set_last_modified_by (
+ krb5_context /*context*/,
+ hdb_entry */*entry*/,
+ krb5_principal /*modby*/,
+ time_t /*modtime*/);
+
+krb5_error_code
hdb_set_master_key (
krb5_context /*context*/,
HDB */*db*/,
@@ -386,6 +404,13 @@ hdb_unseal_keys (
hdb_entry */*ent*/);
krb5_error_code
+hdb_unseal_keys_kvno (
+ krb5_context /*context*/,
+ HDB */*db*/,
+ krb5_kvno /*kvno*/,
+ hdb_entry */*ent*/);
+
+krb5_error_code
hdb_unseal_keys_mkey (
krb5_context /*context*/,
hdb_entry */*ent*/,
diff --git a/crypto/heimdal/lib/hdb/hdb.asn1 b/crypto/heimdal/lib/hdb/hdb.asn1
index a72851c9f201..d24737fbf6e8 100644
--- a/crypto/heimdal/lib/hdb/hdb.asn1
+++ b/crypto/heimdal/lib/hdb/hdb.asn1
@@ -87,6 +87,14 @@ HDB-Ext-Aliases ::= SEQUENCE {
aliases[1] SEQUENCE OF Principal -- all names, inc primary
}
+hdb_keyset ::= SEQUENCE {
+ kvno[0] INTEGER (0..4294967295),
+ replace-time[1] KerberosTime, -- time this key was replaced
+ keys[2] SEQUENCE OF Key
+}
+
+HDB-Ext-KeySet ::= SEQUENCE OF hdb_keyset
+
HDB-extension ::= SEQUENCE {
mandatory[0] BOOLEAN, -- kdc MUST understand this extension,
@@ -102,6 +110,7 @@ HDB-extension ::= SEQUENCE {
aliases[6] HDB-Ext-Aliases,
last-pw-change[7] KerberosTime,
pkinit-cert[8] HDB-Ext-PKINIT-cert,
+ hist-keys[9] HDB-Ext-KeySet,
...
},
...
@@ -109,11 +118,6 @@ HDB-extension ::= SEQUENCE {
HDB-extensions ::= SEQUENCE OF HDB-extension
-hdb_keyset ::= SEQUENCE {
- kvno[1] INTEGER (0..4294967295),
- keys[0] SEQUENCE OF Key
-}
-
hdb_entry ::= SEQUENCE {
principal[0] Principal OPTIONAL, -- this is optional only
-- for compatibility with libkrb5
diff --git a/crypto/heimdal/lib/hdb/hdb.c b/crypto/heimdal/lib/hdb/hdb.c
index ca05cc4a1785..aff576a30d37 100644
--- a/crypto/heimdal/lib/hdb/hdb.c
+++ b/crypto/heimdal/lib/hdb/hdb.c
@@ -168,13 +168,14 @@ hdb_unlock(int fd)
void
hdb_free_entry(krb5_context context, hdb_entry_ex *ent)
{
- size_t i;
+ Key *k;
+ int i;
if (ent->free_entry)
(*ent->free_entry)(context, ent);
- for(i = 0; i < ent->entry.keys.len; ++i) {
- Key *k = &ent->entry.keys.val[i];
+ for(i = 0; i < ent->entry.keys.len; i++) {
+ k = &ent->entry.keys.val[i];
memset (k->key.keyvalue.data, 0, k->key.keyvalue.length);
}
diff --git a/crypto/heimdal/lib/hdb/hdb.h b/crypto/heimdal/lib/hdb/hdb.h
index a1692ce82ca2..4c4c2c2b1a5c 100644
--- a/crypto/heimdal/lib/hdb/hdb.h
+++ b/crypto/heimdal/lib/hdb/hdb.h
@@ -99,7 +99,7 @@ typedef struct hdb_entry_ex {
* query the backend database when talking about principals.
*/
-typedef struct HDB{
+typedef struct HDB {
void *hdb_db;
void *hdb_dbc; /** don't use, only for DB3 */
char *hdb_name;
@@ -256,6 +256,8 @@ typedef struct HDB{
* Check if s4u2self is allowed from this client to this server
*/
krb5_error_code (*hdb_check_s4u2self)(krb5_context, struct HDB *, hdb_entry_ex *, krb5_const_principal);
+ int hdb_mit_key_set;
+ hdb_master_key hdb_mit_key;
}HDB;
#define HDB_INTERFACE_VERSION 7
@@ -266,6 +268,17 @@ struct hdb_so_method {
krb5_error_code (*create)(krb5_context, HDB **, const char *filename);
};
+/* dump entry format, for hdb_print_entry() */
+typedef enum hdb_dump_format {
+ HDB_DUMP_HEIMDAL = 0,
+ HDB_DUMP_MIT = 1,
+} hdb_dump_format_t;
+
+struct hdb_print_entry_arg {
+ FILE *out;
+ hdb_dump_format_t fmt;
+};
+
typedef krb5_error_code (*hdb_foreach_func_t)(krb5_context, HDB*,
hdb_entry_ex*, void*);
extern krb5_kt_ops hdb_kt_ops;
diff --git a/crypto/heimdal/lib/hdb/hdb_locl.h b/crypto/heimdal/lib/hdb/hdb_locl.h
index e896b5802575..5aad504589df 100644
--- a/crypto/heimdal/lib/hdb/hdb_locl.h
+++ b/crypto/heimdal/lib/hdb/hdb_locl.h
@@ -38,6 +38,8 @@
#include <config.h>
+#include <heimbase.h>
+
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -67,4 +69,9 @@
#define HDB_DEFAULT_DB HDB_DB_DIR "/heimdal"
#define HDB_DB_FORMAT_ENTRY "hdb/db-format"
+/* Test for strong key etypes accepted by MIT's KDC. */
+#define mit_strong_etype(t) \
+ ((t) == ETYPE_AES128_CTS_HMAC_SHA1_96 || \
+ (t) == ETYPE_AES256_CTS_HMAC_SHA1_96)
+
#endif /* __HDB_LOCL_H__ */
diff --git a/crypto/heimdal/lib/hdb/keys.c b/crypto/heimdal/lib/hdb/keys.c
index 3d0b9d7c1b31..9c0af5c47f23 100644
--- a/crypto/heimdal/lib/hdb/keys.c
+++ b/crypto/heimdal/lib/hdb/keys.c
@@ -39,7 +39,7 @@
*/
void
-hdb_free_keys (krb5_context context, int len, Key *keys)
+hdb_free_keys(krb5_context context, int len, Key *keys)
{
int i;
@@ -56,6 +56,19 @@ hdb_free_keys (krb5_context context, int len, Key *keys)
free (keys);
}
+void
+hdb_free_keysets(krb5_context context, int len, hdb_keyset *keysets)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ hdb_free_keys(context, keysets[i].keys.len, keysets[i].keys.val);
+ keysets[i].keys.val = NULL;
+ keysets[i].keys.len = 0;
+ }
+ free (keysets);
+}
+
/*
* for each entry in `default_keys' try to parse it as a sequence
* of etype:salttype:salt, syntax of this if something like:
@@ -196,6 +209,60 @@ parse_key_set(krb5_context context, const char *key,
return 0;
}
+
+krb5_error_code
+hdb_add_current_keys_to_history(krb5_context context, hdb_entry *entry)
+{
+ krb5_error_code ret;
+ HDB_extension *ext;
+ HDB_Ext_KeySet *hist_keys;
+ hdb_keyset *tmp_keysets;
+ int add = 0;
+
+ ext = hdb_find_extension(entry, choice_HDB_extension_data_hist_keys);
+ if (ext != NULL) {
+ hist_keys = &ext->data.u.hist_keys;
+ tmp_keysets = realloc(hist_keys->val,
+ sizeof (*hist_keys->val) * (hist_keys->len + 1));
+ if (tmp_keysets == NULL)
+ return ENOMEM;
+ hist_keys->val = tmp_keysets;
+ memmove(&hist_keys->val[1], hist_keys->val,
+ sizeof (*hist_keys->val) * hist_keys->len++);
+ } else {
+ add = 1;
+ ext = calloc(1, sizeof (*ext));
+ if (ext == NULL)
+ return ENOMEM;
+ ext->data.element = choice_HDB_extension_data_hist_keys;
+ hist_keys = &ext->data.u.hist_keys;
+ hist_keys->val = calloc(1, sizeof (*hist_keys->val));
+ if (hist_keys->val == NULL) {
+ free(hist_keys);
+ return ENOMEM;
+ }
+ hist_keys->len = 1;
+ }
+
+ hist_keys->val[0].keys.val = entry->keys.val;
+ hist_keys->val[0].keys.len = entry->keys.len;
+ hist_keys->val[0].kvno = entry->kvno;
+ hist_keys->val[0].replace_time = time(NULL);
+
+ if (add) {
+ ret = hdb_replace_extension(context, entry, ext);
+ if (ret) {
+ free_HDB_extension(ext);
+ return ret;
+ }
+ }
+
+ /* hdb_replace_extension() copies ext, so we have to free it */
+ free_HDB_extension(ext);
+ return 0;
+}
+
+
static krb5_error_code
add_enctype_to_key_set(Key **key_set, size_t *nkeyset,
krb5_enctype enctype, krb5_salt *salt)
diff --git a/crypto/heimdal/lib/hdb/mkey.c b/crypto/heimdal/lib/hdb/mkey.c
index 9eb98fca32c0..78a9e51a132c 100644
--- a/crypto/heimdal/lib/hdb/mkey.c
+++ b/crypto/heimdal/lib/hdb/mkey.c
@@ -32,6 +32,7 @@
*/
#include "hdb_locl.h"
+#include <assert.h>
#ifndef O_BINARY
#define O_BINARY 0
#endif
@@ -40,6 +41,7 @@ struct hdb_master_key_data {
krb5_keytab_entry keytab;
krb5_crypto crypto;
struct hdb_master_key_data *next;
+ unsigned int key_usage;
};
void
@@ -68,6 +70,7 @@ hdb_process_master_key(krb5_context context,
krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
return ENOMEM;
}
+ (*mkey)->key_usage = HDB_KU_MKEY;
(*mkey)->keytab.vno = kvno;
ret = krb5_parse_name(context, "K/M", &(*mkey)->keytab.principal);
if(ret)
@@ -362,6 +365,15 @@ hdb_write_master_key(krb5_context context, const char *filename,
return ret;
}
+krb5_error_code
+_hdb_set_master_key_usage(krb5_context context, HDB *db, unsigned int key_usage)
+{
+ if (db->hdb_master_key_set == 0)
+ return HDB_ERR_NO_MKEY;
+ db->hdb_master_key->key_usage = key_usage;
+ return 0;
+}
+
hdb_master_key
_hdb_find_master_key(uint32_t *mkvno, hdb_master_key mkey)
{
@@ -403,15 +415,20 @@ _hdb_mkey_encrypt(krb5_context context, hdb_master_key key,
ptr, size, res);
}
-krb5_error_code
-hdb_unseal_key_mkey(krb5_context context, Key *k, hdb_master_key mkey)
+/*
+ * Unseal and optionally reseal the key in the MIT KDC master key.
+ * If mit_key != NULL, the key is sealed using this key.
+ */
+static krb5_error_code
+_hdb_reseal_key_mkey(krb5_context context, Key *k, hdb_master_key mkey,
+ hdb_master_key mit_key)
{
krb5_error_code ret;
- krb5_data res;
+ krb5_data mitres, res;
size_t keysize;
- hdb_master_key key;
+ hdb_master_key key, mitkey;
if(k->mkvno == NULL)
return 0;
@@ -428,9 +445,9 @@ hdb_unseal_key_mkey(krb5_context context, Key *k, hdb_master_key mkey)
if(ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
/* try to decrypt with MIT key usage */
ret = _hdb_mkey_decrypt(context, key, 0,
- k->key.keyvalue.data,
- k->key.keyvalue.length,
- &res);
+ k->key.keyvalue.data,
+ k->key.keyvalue.length,
+ &res);
}
if (ret)
return ret;
@@ -446,25 +463,81 @@ hdb_unseal_key_mkey(krb5_context context, Key *k, hdb_master_key mkey)
return KRB5_BAD_KEYSIZE;
}
- memset(k->key.keyvalue.data, 0, k->key.keyvalue.length);
- free(k->key.keyvalue.data);
- k->key.keyvalue = res;
- k->key.keyvalue.length = keysize;
- free(k->mkvno);
- k->mkvno = NULL;
+ /* For mit_key != NULL, re-encrypt the key using the mitkey. */
+ if (mit_key != NULL) {
+ mitkey = _hdb_find_master_key(NULL, mit_key);
+ if (mitkey == NULL) {
+ krb5_data_free(&res);
+ return HDB_ERR_NO_MKEY;
+ }
+
+ ret = _hdb_mkey_encrypt(context, mitkey, 0,
+ res.data,
+ keysize,
+ &mitres);
+ krb5_data_free(&res);
+ if (ret)
+ return ret;
+ }
+
+ krb5_data_free(&k->key.keyvalue);
+ if (mit_key == NULL) {
+ k->key.keyvalue = res;
+ k->key.keyvalue.length = keysize;
+ free(k->mkvno);
+ k->mkvno = NULL;
+ } else {
+ k->key.keyvalue = mitres;
+ *k->mkvno = mitkey->keytab.vno;
+ }
return 0;
}
krb5_error_code
-hdb_unseal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey)
+hdb_unseal_key_mkey(krb5_context context, Key *k, hdb_master_key mkey)
+{
+
+ krb5_error_code ret;
+
+ ret = _hdb_reseal_key_mkey(context, k, mkey, NULL);
+ return ret;
+}
+
+static krb5_error_code
+_hdb_unseal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey,
+ hdb_master_key mitkey)
{
+ krb5_error_code ret;
size_t i;
+ int got_one = 0;
for(i = 0; i < ent->keys.len; i++){
- krb5_error_code ret;
+ if (mitkey == NULL || mit_strong_etype(ent->keys.val[i].key.keytype)) {
+ ret = _hdb_reseal_key_mkey(context, &ent->keys.val[i], mkey,
+ mitkey);
+ if (ret)
+ return ret;
+ got_one = 1;
+ }
+ }
- ret = hdb_unseal_key_mkey(context, &ent->keys.val[i], mkey);
+ /*
+ * If none of the keys were string enough, create a strong key,
+ * but one that is not encrypted in the MIT master key. As such,
+ * it will require a "change_password" once in the MIT KDC to
+ * make it work.
+ */
+ if (got_one == 0 && mitkey != NULL && ent->keys.len > 0) {
+ krb5_keyblock key;
+ krb5_salt salt;
+
+ krb5_free_keyblock_contents(context, &ent->keys.val[0].key);
+ salt.salttype = KRB5_PW_SALT;
+ salt.saltvalue.data = NULL;
+ salt.saltvalue.length = 0;
+ ret = krb5_string_to_key_salt(context, ETYPE_AES256_CTS_HMAC_SHA1_96,
+ "XXXX", salt, &ent->keys.val[0].key);
if (ret)
return ret;
}
@@ -472,19 +545,114 @@ hdb_unseal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey)
}
krb5_error_code
+hdb_unseal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey)
+{
+ krb5_error_code ret;
+
+ ret = _hdb_unseal_keys_mkey(context, ent, mkey, NULL);
+ return ret;
+}
+
+krb5_error_code
hdb_unseal_keys(krb5_context context, HDB *db, hdb_entry *ent)
{
if (db->hdb_master_key_set == 0)
return 0;
- return hdb_unseal_keys_mkey(context, ent, db->hdb_master_key);
+ if (db->hdb_mit_key_set != 0)
+ return _hdb_unseal_keys_mkey(context, ent, db->hdb_master_key,
+ db->hdb_mit_key);
+ else
+ return _hdb_unseal_keys_mkey(context, ent, db->hdb_master_key,
+ NULL);
+}
+
+#ifdef notnow
+krb5_error_code
+hdb_unseal_keys_kvno(krb5_context context, HDB *db, krb5_kvno kvno,
+ hdb_entry *ent)
+{
+ krb5_error_code ret = KRB5KRB_AP_ERR_NOKEY; /* XXX need a better code? */
+ HDB_extension *tmp;
+ HDB_Ext_KeySet *hist_keys;
+ hdb_keyset *tmp_keys;
+ Key *tmp_val;
+ unsigned int tmp_len;
+ krb5_kvno tmp_kvno;
+ int i, k;
+
+ assert(kvno == 0 || kvno < ent->kvno);
+
+ tmp = hdb_find_extension(ent, choice_HDB_extension_data_hist_keys);
+ if (tmp == NULL)
+ return ret;
+
+ tmp_len = ent->keys.len;
+ tmp_val = ent->keys.val;
+ tmp_kvno = ent->kvno;
+
+ hist_keys = &tmp->data.u.hist_keys;
+
+ for (i = hist_keys->len - 1; i >= 0; i++) {
+ if (kvno != 0 && hist_keys->val[i].kvno != kvno)
+ continue;
+ for (k = 0; k < hist_keys->val[i].keys.len; k++) {
+ ret = _hdb_reseal_key_mkey(context,
+ &hist_keys->val[i].keys.val[k],
+ db->hdb_master_key, NULL);
+ if (ret)
+ return (ret);
+ }
+
+ if (kvno == 0)
+ continue;
+
+ /*
+ * NOTE: What follows is a bit of an ugly hack.
+ *
+ * This is the keyset we're being asked for, so we add the
+ * current keyset to the history, leave the one we were asked
+ * for in the history, and pretend the one we were asked for is
+ * also the current keyset.
+ *
+ * This is a bit of a defensive hack in case an entry fetched
+ * this way ever gets modified then stored: if the keyset is not
+ * changed we can detect this and put things back, else we won't
+ * drop any keysets from history by accident.
+ *
+ * Note too that we only ever get called with a non-zero kvno
+ * either in the KDC or in cases where we aren't changing the
+ * HDB entry anyways, which is why this is just a defensive
+ * hack. We also don't fetch specific kvnos in the dump case,
+ * so there's no danger that we'll dump this entry and load it
+ * again, repeatedly causing the history to grow boundelessly.
+ */
+ tmp_keys = realloc(hist_keys->val,
+ sizeof (*hist_keys->val) * (hist_keys->len + 1));
+ if (tmp_keys == NULL)
+ return ENOMEM;
+
+ memmove(&tmp_keys[1], tmp_keys,
+ sizeof (*hist_keys->val) * hist_keys->len++);
+ tmp_keys[0].keys.len = ent->keys.len;
+ tmp_keys[0].keys.val = ent->keys.val;
+ tmp_keys[0].kvno = ent->kvno;
+ tmp_keys[0].replace_time = time(NULL);
+ i++;
+ ent->keys.len = hist_keys->val[i].keys.len;
+ ent->keys.val = hist_keys->val[i].keys.val;
+ ent->kvno = kvno;
+ }
+
+ return (ret);
}
+#endif
krb5_error_code
hdb_unseal_key(krb5_context context, HDB *db, Key *k)
{
if (db->hdb_master_key_set == 0)
return 0;
- return hdb_unseal_key_mkey(context, k, db->hdb_master_key);
+ return _hdb_reseal_key_mkey(context, k, db->hdb_master_key, NULL);
}
krb5_error_code
@@ -556,9 +724,9 @@ hdb_seal_key(krb5_context context, HDB *db, Key *k)
}
krb5_error_code
-hdb_set_master_key (krb5_context context,
- HDB *db,
- krb5_keyblock *key)
+hdb_set_master_key(krb5_context context,
+ HDB *db,
+ krb5_keyblock *key)
{
krb5_error_code ret;
hdb_master_key mkey;
@@ -571,6 +739,7 @@ hdb_set_master_key (krb5_context context,
des_set_random_generator_seed(key.keyvalue.data);
#endif
db->hdb_master_key_set = 1;
+ db->hdb_master_key->key_usage = HDB_KU_MKEY;
return 0;
}
diff --git a/crypto/heimdal/lib/hdb/print.c b/crypto/heimdal/lib/hdb/print.c
index 697d32d2909c..d5359f538056 100644
--- a/crypto/heimdal/lib/hdb/print.c
+++ b/crypto/heimdal/lib/hdb/print.c
@@ -57,44 +57,57 @@
generation number
*/
-static krb5_error_code
+/*
+ * These utility functions return the number of bytes written or -1, and
+ * they set an error in the context.
+ */
+static ssize_t
append_string(krb5_context context, krb5_storage *sp, const char *fmt, ...)
{
- krb5_error_code ret;
+ ssize_t sz;
char *s;
+ int rc;
va_list ap;
va_start(ap, fmt);
- vasprintf(&s, fmt, ap);
+ rc = vasprintf(&s, fmt, ap);
va_end(ap);
- if(s == NULL) {
+ if(rc < 0) {
krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
- return ENOMEM;
+ return -1;
}
- ret = krb5_storage_write(sp, s, strlen(s));
+ sz = krb5_storage_write(sp, s, strlen(s));
free(s);
- return ret;
+ return sz;
}
static krb5_error_code
-append_hex(krb5_context context, krb5_storage *sp, krb5_data *data)
+append_hex(krb5_context context, krb5_storage *sp,
+ int always_encode, int lower, krb5_data *data)
{
+ ssize_t sz;
int printable = 1;
size_t i;
char *p;
p = data->data;
- for(i = 0; i < data->length; i++)
- if(!isalnum((unsigned char)p[i]) && p[i] != '.'){
- printable = 0;
- break;
- }
- if(printable)
+ if (!always_encode) {
+ for (i = 0; i < data->length; i++) {
+ if (!isalnum((unsigned char)p[i]) && p[i] != '.'){
+ printable = 0;
+ break;
+ }
+ }
+ }
+ if (printable && !always_encode)
return append_string(context, sp, "\"%.*s\"",
data->length, data->data);
- hex_encode(data->data, data->length, &p);
- append_string(context, sp, "%s", p);
+ sz = hex_encode(data->data, data->length, &p);
+ if (sz == -1) return sz;
+ if (lower)
+ strlwr(p);
+ sz = append_string(context, sp, "%s", p);
free(p);
- return 0;
+ return sz;
}
static char *
@@ -105,29 +118,97 @@ time2str(time_t t)
return buf;
}
-static krb5_error_code
+static ssize_t
append_event(krb5_context context, krb5_storage *sp, Event *ev)
{
- char *pr = NULL;
krb5_error_code ret;
+ ssize_t sz;
+ char *pr = NULL;
if(ev == NULL)
return append_string(context, sp, "- ");
if (ev->principal != NULL) {
ret = krb5_unparse_name(context, ev->principal, &pr);
- if(ret)
- return ret;
+ if (ret) return -1; /* krb5_unparse_name() sets error info */
}
- ret = append_string(context, sp, "%s:%s ",
- time2str(ev->time), pr ? pr : "UNKNOWN");
+ sz = append_string(context, sp, "%s:%s ", time2str(ev->time),
+ pr ? pr : "UNKNOWN");
free(pr);
- return ret;
+ return sz;
+}
+
+#define KRB5_KDB_SALTTYPE_NORMAL 0
+#define KRB5_KDB_SALTTYPE_V4 1
+#define KRB5_KDB_SALTTYPE_NOREALM 2
+#define KRB5_KDB_SALTTYPE_ONLYREALM 3
+#define KRB5_KDB_SALTTYPE_SPECIAL 4
+#define KRB5_KDB_SALTTYPE_AFS3 5
+
+static ssize_t
+append_mit_key(krb5_context context, krb5_storage *sp,
+ krb5_const_principal princ,
+ unsigned int kvno, Key *key)
+{
+ krb5_error_code ret;
+ ssize_t sz;
+ size_t key_versions = key->salt ? 2 : 1;
+ size_t decrypted_key_length;
+ char buf[2];
+ krb5_data keylenbytes;
+ unsigned int salttype;
+
+ sz = append_string(context, sp, "\t%u\t%u\t%d\t%d\t", key_versions, kvno,
+ key->key.keytype, key->key.keyvalue.length + 2);
+ if (sz == -1) return sz;
+ ret = krb5_enctype_keysize(context, key->key.keytype, &decrypted_key_length);
+ if (ret) return -1; /* XXX we lose the error code */
+ buf[0] = decrypted_key_length & 0xff;
+ buf[1] = (decrypted_key_length & 0xff00) >> 8;
+ keylenbytes.data = buf;
+ keylenbytes.length = sizeof (buf);
+ sz = append_hex(context, sp, 1, 1, &keylenbytes);
+ if (sz == -1) return sz;
+ sz = append_hex(context, sp, 1, 1, &key->key.keyvalue);
+ if (!key->salt)
+ return sz;
+
+ /* Map salt to MIT KDB style */
+ if (key->salt->type == KRB5_PADATA_PW_SALT) {
+ krb5_salt k5salt;
+
+ /*
+ * Compute normal salt and then see whether it matches the stored one
+ */
+ ret = krb5_get_pw_salt(context, princ, &k5salt);
+ if (ret) return -1;
+ if (k5salt.saltvalue.length == key->salt->salt.length &&
+ memcmp(k5salt.saltvalue.data, key->salt->salt.data,
+ k5salt.saltvalue.length) == 0)
+ salttype = KRB5_KDB_SALTTYPE_NORMAL; /* matches */
+ else if (key->salt->salt.length == strlen(princ->realm) &&
+ memcmp(key->salt->salt.data, princ->realm,
+ key->salt->salt.length) == 0)
+ salttype = KRB5_KDB_SALTTYPE_ONLYREALM; /* matches realm */
+ else if (key->salt->salt.length == k5salt.saltvalue.length - strlen(princ->realm) &&
+ memcmp((char *)k5salt.saltvalue.data + strlen(princ->realm),
+ key->salt->salt.data, key->salt->salt.length) == 0)
+ salttype = KRB5_KDB_SALTTYPE_NOREALM; /* matches w/o realm */
+ else
+ salttype = KRB5_KDB_SALTTYPE_NORMAL; /* hope for best */
+
+ } else if (key->salt->type == KRB5_PADATA_AFS3_SALT) {
+ salttype = KRB5_KDB_SALTTYPE_AFS3;
+ }
+ sz = append_string(context, sp, "\t%u\t%u\t", salttype,
+ key->salt->salt.length);
+ if (sz == -1) return sz;
+ return append_hex(context, sp, 1, 1, &key->salt->salt);
}
static krb5_error_code
entry2string_int (krb5_context context, krb5_storage *sp, hdb_entry *ent)
{
char *p;
- size_t i;
+ int i;
krb5_error_code ret;
/* --- principal */
@@ -149,12 +230,12 @@ entry2string_int (krb5_context context, krb5_storage *sp, hdb_entry *ent)
append_string(context, sp, "::%d:",
ent->keys.val[i].key.keytype);
/* --- keydata */
- append_hex(context, sp, &ent->keys.val[i].key.keyvalue);
+ append_hex(context, sp, 0, 0, &ent->keys.val[i].key.keyvalue);
append_string(context, sp, ":");
/* --- salt */
if(ent->keys.val[i].salt){
append_string(context, sp, "%u/", ent->keys.val[i].salt->type);
- append_hex(context, sp, &ent->keys.val[i].salt->salt);
+ append_hex(context, sp, 0, 0, &ent->keys.val[i].salt->salt);
}else
append_string(context, sp, "-");
}
@@ -234,25 +315,266 @@ entry2string_int (krb5_context context, krb5_storage *sp, hdb_entry *ent)
} else
append_string(context, sp, "-");
+ return 0;
+}
+
+#define KRB5_KDB_DISALLOW_POSTDATED 0x00000001
+#define KRB5_KDB_DISALLOW_FORWARDABLE 0x00000002
+#define KRB5_KDB_DISALLOW_TGT_BASED 0x00000004
+#define KRB5_KDB_DISALLOW_RENEWABLE 0x00000008
+#define KRB5_KDB_DISALLOW_PROXIABLE 0x00000010
+#define KRB5_KDB_DISALLOW_DUP_SKEY 0x00000020
+#define KRB5_KDB_DISALLOW_ALL_TIX 0x00000040
+#define KRB5_KDB_REQUIRES_PRE_AUTH 0x00000080
+#define KRB5_KDB_REQUIRES_HW_AUTH 0x00000100
+#define KRB5_KDB_REQUIRES_PWCHANGE 0x00000200
+#define KRB5_KDB_DISALLOW_SVR 0x00001000
+#define KRB5_KDB_PWCHANGE_SERVICE 0x00002000
+#define KRB5_KDB_SUPPORT_DESMD5 0x00004000
+#define KRB5_KDB_NEW_PRINC 0x00008000
+
+static int
+flags_to_attr(HDBFlags flags)
+{
+ int a = 0;
+
+ if (!flags.postdate)
+ a |= KRB5_KDB_DISALLOW_POSTDATED;
+ if (!flags.forwardable)
+ a |= KRB5_KDB_DISALLOW_FORWARDABLE;
+ if (flags.initial)
+ a |= KRB5_KDB_DISALLOW_TGT_BASED;
+ if (!flags.renewable)
+ a |= KRB5_KDB_DISALLOW_RENEWABLE;
+ if (!flags.proxiable)
+ a |= KRB5_KDB_DISALLOW_PROXIABLE;
+ if (flags.invalid)
+ a |= KRB5_KDB_DISALLOW_ALL_TIX;
+ if (flags.require_preauth)
+ a |= KRB5_KDB_REQUIRES_PRE_AUTH;
+ if (flags.require_hwauth)
+ a |= KRB5_KDB_REQUIRES_HW_AUTH;
+ if (!flags.server)
+ a |= KRB5_KDB_DISALLOW_SVR;
+ if (flags.change_pw)
+ a |= KRB5_KDB_PWCHANGE_SERVICE;
+ return a;
+}
+krb5_error_code
+entry2mit_string_int(krb5_context context, krb5_storage *sp, hdb_entry *ent)
+{
+ krb5_error_code ret;
+ ssize_t sz;
+ size_t i, k;
+ size_t num_tl_data = 0;
+ size_t num_key_data = 0;
+ char *p;
+ HDB_Ext_KeySet *hist_keys = NULL;
+ HDB_extension *extp;
+ time_t last_pw_chg = 0;
+ time_t exp = 0;
+ time_t pwexp = 0;
+ unsigned int max_life = 0;
+ unsigned int max_renew = 0;
+
+ /* Always create a modified_by entry. */
+ num_tl_data++;
+
+ ret = hdb_entry_get_pw_change_time(ent, &last_pw_chg);
+ if (ret) return ret;
+ if (last_pw_chg)
+ num_tl_data++;
+
+ extp = hdb_find_extension(ent, choice_HDB_extension_data_hist_keys);
+ if (extp)
+ hist_keys = &extp->data.u.hist_keys;
+
+ for (i = 0; i < ent->keys.len;i++) {
+ if (!mit_strong_etype(ent->keys.val[i].key.keytype))
+ continue;
+ num_key_data++;
+ }
+ if (hist_keys) {
+ for (i = 0; i < hist_keys->len; i++) {
+ /*
+ * MIT uses the highest kvno as the current kvno instead of
+ * tracking kvno separately, so we can't dump keysets with kvno
+ * higher than the entry's kvno.
+ */
+ if (hist_keys->val[i].kvno >= ent->kvno)
+ continue;
+ for (k = 0; k < hist_keys->val[i].keys.len; k++) {
+ if (ent->keys.val[k].key.keytype == ETYPE_DES_CBC_MD4 ||
+ ent->keys.val[k].key.keytype == ETYPE_DES_CBC_MD5)
+ continue;
+ num_key_data++;
+ }
+ }
+ }
+
+ ret = krb5_unparse_name(context, ent->principal, &p);
+ if (ret) return ret;
+ sz = append_string(context, sp, "princ\t38\t%u\t%u\t%u\t0\t%s\t%d",
+ strlen(p), num_tl_data, num_key_data, p,
+ flags_to_attr(ent->flags));
+ if (sz == -1) {
+ free(p);
+ return ENOMEM;
+ }
+
+ if (ent->max_life)
+ max_life = *ent->max_life;
+ if (ent->max_renew)
+ max_renew = *ent->max_renew;
+ if (ent->valid_end)
+ exp = *ent->valid_end;
+ if (ent->pw_end)
+ pwexp = *ent->pw_end;
+
+ sz = append_string(context, sp, "\t%u\t%u\t%u\t%u\t0\t0\t0",
+ max_life, max_renew, exp, pwexp);
+ if (sz == -1) {
+ free(p);
+ return ENOMEM;
+ }
+
+ /* Dump TL data we know: last pw chg and modified_by */
+#define mit_KRB5_TL_LAST_PWD_CHANGE 1
+#define mit_KRB5_TL_MOD_PRINC 2
+ if (last_pw_chg) {
+ krb5_data d;
+ time_t val;
+ unsigned char *ptr;
+
+ ptr = (unsigned char *)&last_pw_chg;
+ val = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
+ d.data = &val;
+ d.length = sizeof (last_pw_chg);
+ sz = append_string(context, sp, "\t%u\t%u\t",
+ mit_KRB5_TL_LAST_PWD_CHANGE, d.length);
+ if (sz == -1) {
+ free(p);
+ return ENOMEM;
+ }
+ sz = append_hex(context, sp, 1, 1, &d);
+ if (sz == -1) {
+ free(p);
+ return ENOMEM;
+ }
+ }
+ if (ent->modified_by) {
+ krb5_data d;
+ unsigned int val;
+ size_t plen;
+ unsigned char *ptr;
+ char *modby_p;
+
+ free(p);
+ ptr = (unsigned char *)&ent->modified_by->time;
+ val = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
+ d.data = &val;
+ d.length = sizeof (ent->modified_by->time);
+ ret = krb5_unparse_name(context, ent->modified_by->principal, &modby_p);
+ if (ret) return ret;
+ plen = strlen(modby_p);
+ sz = append_string(context, sp, "\t%u\t%u\t",
+ mit_KRB5_TL_MOD_PRINC,
+ d.length + plen + 1 /* NULL counted */);
+ if (sz == -1) {
+ free(modby_p);
+ return ENOMEM;
+ }
+ sz = append_hex(context, sp, 1, 1, &d);
+ if (sz == -1) {
+ free(modby_p);
+ return ENOMEM;
+ }
+ d.data = modby_p;
+ d.length = plen + 1;
+ sz = append_hex(context, sp, 1, 1, &d);
+ free(modby_p);
+ if (sz == -1) return ENOMEM;
+ } else {
+ krb5_data d;
+ unsigned int val;
+ size_t plen;
+ unsigned char *ptr;
+
+ /* Fake the entry to make MIT happy. */
+ ptr = (unsigned char *)&last_pw_chg;
+ val = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
+ d.data = &val;
+ d.length = sizeof (last_pw_chg);
+ plen = strlen(p);
+ sz = append_string(context, sp, "\t%u\t%u\t",
+ mit_KRB5_TL_MOD_PRINC,
+ d.length + plen + 1 /* NULL counted */);
+ if (sz == -1) {
+ free(p);
+ return ENOMEM;
+ }
+ sz = append_hex(context, sp, 1, 1, &d);
+ if (sz == -1) {
+ free(p);
+ return ENOMEM;
+ }
+ d.data = p;
+ d.length = plen + 1;
+ sz = append_hex(context, sp, 1, 1, &d);
+ free(p);
+ if (sz == -1) return ENOMEM;
+ }
+ /*
+ * Dump keys (remembering to not include any with kvno higher than
+ * the entry's because MIT doesn't track entry kvno separately from
+ * the entry's keys -- max kvno is it)
+ */
+ for (i = 0; i < ent->keys.len; i++) {
+ if (!mit_strong_etype(ent->keys.val[i].key.keytype))
+ continue;
+ sz = append_mit_key(context, sp, ent->principal, ent->kvno,
+ &ent->keys.val[i]);
+ if (sz == -1) return ENOMEM;
+ }
+ for (i = 0; hist_keys && i < ent->kvno; i++) {
+ size_t m;
+
+ /* dump historical keys */
+ for (k = 0; k < hist_keys->len; k++) {
+ if (hist_keys->val[k].kvno != ent->kvno - i)
+ continue;
+ for (m = 0; m < hist_keys->val[k].keys.len; m++) {
+ if (ent->keys.val[k].key.keytype == ETYPE_DES_CBC_MD4 ||
+ ent->keys.val[k].key.keytype == ETYPE_DES_CBC_MD5)
+ continue;
+ sz = append_mit_key(context, sp, ent->principal,
+ hist_keys->val[k].kvno,
+ &hist_keys->val[k].keys.val[m]);
+ if (sz == -1) return ENOMEM;
+ }
+ }
+ }
+ sz = append_string(context, sp, "\t-1;"); /* "extra data" */
+ if (sz == -1) return ENOMEM;
return 0;
}
krb5_error_code
-hdb_entry2string (krb5_context context, hdb_entry *ent, char **str)
+hdb_entry2string(krb5_context context, hdb_entry *ent, char **str)
{
krb5_error_code ret;
krb5_data data;
krb5_storage *sp;
sp = krb5_storage_emem();
- if(sp == NULL) {
+ if (sp == NULL) {
krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
return ENOMEM;
}
ret = entry2string_int(context, sp, ent);
- if(ret) {
+ if (ret) {
krb5_storage_free(sp);
return ret;
}
@@ -267,22 +589,31 @@ hdb_entry2string (krb5_context context, hdb_entry *ent, char **str)
/* print a hdb_entry to (FILE*)data; suitable for hdb_foreach */
krb5_error_code
-hdb_print_entry(krb5_context context, HDB *db, hdb_entry_ex *entry, void *data)
+hdb_print_entry(krb5_context context, HDB *db, hdb_entry_ex *entry,
+ void *data)
{
+ struct hdb_print_entry_arg *parg = data;
krb5_error_code ret;
krb5_storage *sp;
- FILE *f = data;
-
- fflush(f);
- sp = krb5_storage_from_fd(fileno(f));
- if(sp == NULL) {
+ fflush(parg->out);
+ sp = krb5_storage_from_fd(fileno(parg->out));
+ if (sp == NULL) {
krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
return ENOMEM;
}
- ret = entry2string_int(context, sp, &entry->entry);
- if(ret) {
+ switch (parg->fmt) {
+ case HDB_DUMP_HEIMDAL:
+ ret = entry2string_int(context, sp, &entry->entry);
+ break;
+ case HDB_DUMP_MIT:
+ ret = entry2mit_string_int(context, sp, &entry->entry);
+ break;
+ default:
+ heim_abort("Only two dump formats supported: Heimdal and MIT");
+ }
+ if (ret) {
krb5_storage_free(sp);
return ret;
}
diff --git a/crypto/heimdal/lib/hdb/version-script.map b/crypto/heimdal/lib/hdb/version-script.map
index 50a36cec0aa9..42e2043b4b47 100644
--- a/crypto/heimdal/lib/hdb/version-script.map
+++ b/crypto/heimdal/lib/hdb/version-script.map
@@ -4,6 +4,7 @@ HEIMDAL_HDB_1.0 {
global:
encode_hdb_keyset;
hdb_add_master_key;
+ hdb_add_current_keys_to_history;
hdb_check_db_format;
hdb_clear_extension;
hdb_clear_master_key;
@@ -57,6 +58,7 @@ HEIMDAL_HDB_1.0 {
hdb_seal_key_mkey;
hdb_seal_keys;
hdb_seal_keys_mkey;
+ hdb_set_last_modified_by;
hdb_set_master_key;
hdb_set_master_keyfile;
hdb_unlock;
@@ -71,6 +73,10 @@ HEIMDAL_HDB_1.0 {
hdb_interface_version;
initialize_hdb_error_table_r;
+ # MIT KDB related entries
+ _hdb_mdb_value2entry;
+ _hdb_mit_dump2mitdb_entry;
+
hdb_kt_ops;
# some random bits needed for libkadm
diff --git a/crypto/heimdal/lib/kadm5/chpass_s.c b/crypto/heimdal/lib/kadm5/chpass_s.c
index 624293e5c3a3..22f65517fcc5 100644
--- a/crypto/heimdal/lib/kadm5/chpass_s.c
+++ b/crypto/heimdal/lib/kadm5/chpass_s.c
@@ -58,6 +58,10 @@ change(void *server_handle,
if(ret)
goto out;
+ ret = hdb_add_current_keys_to_history(context->context, &ent.entry);
+ if (ret)
+ goto out;
+
if (context->db->hdb_capability_flags & HDB_CAP_F_HANDLE_PASSWORDS) {
ret = context->db->hdb_password(context->context, context->db,
&ent, password, cond);
@@ -170,6 +174,9 @@ kadm5_s_chpass_principal_with_key(void *server_handle,
HDB_F_GET_ANY|HDB_F_ADMIN_DATA, &ent);
if(ret)
goto out;
+ ret = hdb_add_current_keys_to_history(context->context, &ent.entry);
+ if (ret)
+ goto out2;
ret = _kadm5_set_keys2(context, &ent.entry, n_key_data, key_data);
if(ret)
goto out2;
diff --git a/crypto/heimdal/lib/kadm5/randkey_s.c b/crypto/heimdal/lib/kadm5/randkey_s.c
index dcb179aac40f..adb3564be719 100644
--- a/crypto/heimdal/lib/kadm5/randkey_s.c
+++ b/crypto/heimdal/lib/kadm5/randkey_s.c
@@ -59,6 +59,10 @@ kadm5_s_randkey_principal(void *server_handle,
if(ret)
goto out;
+ ret = hdb_add_current_keys_to_history(context->context, &ent.entry);
+ if (ret)
+ goto out2;
+
ret = _kadm5_set_keys_randomly (context,
&ent.entry,
new_keys,
diff --git a/crypto/openssl/CHANGES.md b/crypto/openssl/CHANGES.md
index 5f5ba3ef1751..b991285aedb2 100644
--- a/crypto/openssl/CHANGES.md
+++ b/crypto/openssl/CHANGES.md
@@ -28,6 +28,72 @@ OpenSSL Releases
OpenSSL 3.5
-----------
+### Changes between 3.5.3 and 3.5.4 [30 Sep 2025]
+
+ * Fix Out-of-bounds read & write in RFC 3211 KEK Unwrap
+
+ Issue summary: An application trying to decrypt CMS messages encrypted using
+ password based encryption can trigger an out-of-bounds read and write.
+
+ Impact summary: This out-of-bounds read may trigger a crash which leads to
+ Denial of Service for an application. The out-of-bounds write can cause
+ a memory corruption which can have various consequences including
+ a Denial of Service or Execution of attacker-supplied code.
+
+ The issue was reported by Stanislav Fort (Aisle Research).
+
+ ([CVE-2025-9230])
+
+ *Viktor Dukhovni*
+
+ * Fix Timing side-channel in SM2 algorithm on 64 bit ARM
+
+ Issue summary: A timing side-channel which could potentially allow remote
+ recovery of the private key exists in the SM2 algorithm implementation on
+ 64 bit ARM platforms.
+
+ Impact summary: A timing side-channel in SM2 signature computations on
+ 64 bit ARM platforms could allow recovering the private key by an attacker.
+
+ The issue was reported by Stanislav Fort (Aisle Research).
+
+ ([CVE-2025-9231])
+
+ *Stanislav Fort and Tomáš Mráz*
+
+ * Fix Out-of-bounds read in HTTP client no_proxy handling
+
+ Issue summary: An application using the OpenSSL HTTP client API functions
+ may trigger an out-of-bounds read if the "no_proxy" environment variable is
+ set and the host portion of the authority component of the HTTP URL is an
+ IPv6 address.
+
+ Impact summary: An out-of-bounds read can trigger a crash which leads to
+ Denial of Service for an application.
+
+ The issue was reported by Stanislav Fort (Aisle Research).
+
+ ([CVE-2025-9232])
+
+ *Stanislav Fort*
+
+ * The FIPS provider no longer performs a PCT on key import for ECX keys
+ (that was introduced in 3.5.2), following the latest update
+ on that requirement in FIPS 140-3 IG 10.3.A additional comment 1.
+
+ *Eugene Syromiatnikov*
+
+ * Fixed the length of the ASN.1 sequence for the SM3 digests of RSA-encrypted
+ signatures.
+
+ *Xiao Lou Dong Feng*
+
+ * Reverted the synthesised `OPENSSL_VERSION_NUMBER` change for the release
+ builds, as it broke some exiting applications that relied on the previous
+ 3.x semantics, as documented in `OpenSSL_version(3)`.
+
+ *Richard Levitte*
+
### Changes between 3.5.2 and 3.5.3 [16 Sep 2025]
* Avoided a potential race condition introduced in 3.5.1, where
@@ -21284,6 +21350,9 @@ ndif
<!-- Links -->
+[CVE-2025-9232]: https://www.openssl.org/news/vulnerabilities.html#CVE-2025-9232
+[CVE-2025-9231]: https://www.openssl.org/news/vulnerabilities.html#CVE-2025-9231
+[CVE-2025-9230]: https://www.openssl.org/news/vulnerabilities.html#CVE-2025-9230
[CVE-2025-4575]: https://www.openssl.org/news/vulnerabilities.html#CVE-2025-4575
[CVE-2024-13176]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-13176
[CVE-2024-9143]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-9143
diff --git a/crypto/openssl/NEWS.md b/crypto/openssl/NEWS.md
index 5d8a83f43068..b194dfb7cb06 100644
--- a/crypto/openssl/NEWS.md
+++ b/crypto/openssl/NEWS.md
@@ -23,19 +23,46 @@ OpenSSL Releases
OpenSSL 3.5
-----------
+### Major changes between OpenSSL 3.5.3 and OpenSSL 3.5.4 [30 Sep 2025]
+
+OpenSSL 3.5.4 is a security patch release. The most severe CVE fixed in this
+release is Moderate.
+
+This release incorporates the following bug fixes and mitigations:
+
+ * Fix Out-of-bounds read & write in RFC 3211 KEK Unwrap.
+ ([CVE-2025-9230])
+
+ * Fix Timing side-channel in SM2 algorithm on 64 bit ARM.
+ ([CVE-2025-9231])
+
+ * Fix Out-of-bounds read in HTTP client no_proxy handling.
+ ([CVE-2025-9232])
+
+ * Reverted the synthesised `OPENSSL_VERSION_NUMBER` change for the release
+ builds, as it broke some exiting applications that relied on the previous
+ 3.x semantics, as documented in `OpenSSL_version(3)`.
+
### Major changes between OpenSSL 3.5.2 and OpenSSL 3.5.3 [16 Sep 2025]
- * Added FIPS 140-3 PCT on DH key generation.
+OpenSSL 3.5.3 is a bug fix release.
+
+This release incorporates the following bug fixes and mitigations:
- *Nikola Pajkovsky*
+ * Added FIPS 140-3 PCT on DH key generation.
* Fixed the synthesised `OPENSSL_VERSION_NUMBER`.
- *Richard Levitte*
+ * Removed PCT on key import in the FIPS provider as it is not required by
+ the standard.
### Major changes between OpenSSL 3.5.1 and OpenSSL 3.5.2 [5 Aug 2025]
- * none
+OpenSSL 3.5.2 is a bug fix release.
+
+This release incorporates the following bug fixes and mitigations:
+
+ * The FIPS provider now performs a PCT on key import for RSA, EC and ECX.
### Major changes between OpenSSL 3.5.0 and OpenSSL 3.5.1 [1 Jul 2025]
@@ -45,7 +72,7 @@ release is Low.
This release incorporates the following bug fixes and mitigations:
* Fix x509 application adds trusted use instead of rejected use.
- ([CVE-2025-4575])
+ ([CVE-2025-4575])
### Major changes between OpenSSL 3.4 and OpenSSL 3.5.0 [8 Apr 2025]
@@ -1913,6 +1940,9 @@ OpenSSL 0.9.x
* Support for various new platforms
<!-- Links -->
+[CVE-2025-9232]: https://www.openssl.org/news/vulnerabilities.html#CVE-2025-9232
+[CVE-2025-9231]: https://www.openssl.org/news/vulnerabilities.html#CVE-2025-9231
+[CVE-2025-9230]: https://www.openssl.org/news/vulnerabilities.html#CVE-2025-9230
[CVE-2025-4575]: https://www.openssl.org/news/vulnerabilities.html#CVE-2025-4575
[CVE-2024-13176]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-13176
[CVE-2024-9143]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-9143
diff --git a/crypto/openssl/VERSION.dat b/crypto/openssl/VERSION.dat
index 8a2893b68006..a8eb3ac9c421 100644
--- a/crypto/openssl/VERSION.dat
+++ b/crypto/openssl/VERSION.dat
@@ -1,7 +1,7 @@
MAJOR=3
MINOR=5
-PATCH=3
+PATCH=4
PRE_RELEASE_TAG=
BUILD_METADATA=
-RELEASE_DATE="16 Sep 2025"
+RELEASE_DATE="30 Sep 2025"
SHLIB_VERSION=3
diff --git a/crypto/openssl/apps/storeutl.c b/crypto/openssl/apps/storeutl.c
index 62f0e6135640..f8ebde44481c 100644
--- a/crypto/openssl/apps/storeutl.c
+++ b/crypto/openssl/apps/storeutl.c
@@ -331,14 +331,22 @@ int storeutl_main(int argc, char *argv[])
static int indent_printf(int indent, BIO *bio, const char *format, ...)
{
va_list args;
- int ret;
+ int ret, vret;
+
+ ret = BIO_printf(bio, "%*s", indent, "");
+ if (ret < 0)
+ return ret;
va_start(args, format);
+ vret = BIO_vprintf(bio, format, args);
+ va_end(args);
- ret = BIO_printf(bio, "%*s", indent, "") + BIO_vprintf(bio, format, args);
+ if (vret < 0)
+ return vret;
+ if (vret > INT_MAX - ret)
+ return INT_MAX;
- va_end(args);
- return ret;
+ return ret + vret;
}
static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
diff --git a/crypto/openssl/crypto/bio/bss_file.c b/crypto/openssl/crypto/bio/bss_file.c
index 2743a14417cf..ddcb4feb6a58 100644
--- a/crypto/openssl/crypto/bio/bss_file.c
+++ b/crypto/openssl/crypto/bio/bss_file.c
@@ -287,7 +287,7 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr)
if (fp == NULL) {
ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
"calling fopen(%s, %s)",
- ptr, p);
+ (const char *)ptr, p);
ERR_raise(ERR_LIB_BIO, ERR_R_SYS_LIB);
ret = 0;
break;
diff --git a/crypto/openssl/crypto/ec/ecp_sm2p256.c b/crypto/openssl/crypto/ec/ecp_sm2p256.c
index ffb58399dfd0..4c39be2186fb 100644
--- a/crypto/openssl/crypto/ec/ecp_sm2p256.c
+++ b/crypto/openssl/crypto/ec/ecp_sm2p256.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2023-2025 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
diff --git a/crypto/openssl/crypto/evp/bio_ok.c b/crypto/openssl/crypto/evp/bio_ok.c
index 20811ffded6f..d7f6c71ee1ad 100644
--- a/crypto/openssl/crypto/evp/bio_ok.c
+++ b/crypto/openssl/crypto/evp/bio_ok.c
@@ -1,5 +1,5 @@
/*
- * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2025 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
@@ -560,7 +560,7 @@ static int block_in(BIO *b)
{
BIO_OK_CTX *ctx;
EVP_MD_CTX *md;
- unsigned long tl = 0;
+ size_t tl = 0;
unsigned char tmp[EVP_MAX_MD_SIZE];
int md_size;
@@ -571,15 +571,18 @@ static int block_in(BIO *b)
goto berr;
assert(sizeof(tl) >= OK_BLOCK_BLOCK); /* always true */
- tl = ctx->buf[0];
- tl <<= 8;
- tl |= ctx->buf[1];
- tl <<= 8;
- tl |= ctx->buf[2];
- tl <<= 8;
- tl |= ctx->buf[3];
-
- if (ctx->buf_len < tl + OK_BLOCK_BLOCK + md_size)
+ tl = ((size_t)ctx->buf[0] << 24)
+ | ((size_t)ctx->buf[1] << 16)
+ | ((size_t)ctx->buf[2] << 8)
+ | ((size_t)ctx->buf[3]);
+
+ if (tl > OK_BLOCK_SIZE)
+ goto berr;
+
+ if (tl > SIZE_MAX - OK_BLOCK_BLOCK - (size_t)md_size)
+ goto berr;
+
+ if (ctx->buf_len < tl + OK_BLOCK_BLOCK + (size_t)md_size)
return 1;
if (!EVP_DigestUpdate(md,
@@ -587,7 +590,7 @@ static int block_in(BIO *b)
goto berr;
if (!EVP_DigestFinal_ex(md, tmp, NULL))
goto berr;
- if (memcmp(&(ctx->buf[tl + OK_BLOCK_BLOCK]), tmp, md_size) == 0) {
+ if (memcmp(&(ctx->buf[tl + OK_BLOCK_BLOCK]), tmp, (size_t)md_size) == 0) {
/* there might be parts from next block lurking around ! */
ctx->buf_off_save = tl + OK_BLOCK_BLOCK + md_size;
ctx->buf_len_save = ctx->buf_len;
diff --git a/crypto/openssl/crypto/evp/ctrl_params_translate.c b/crypto/openssl/crypto/evp/ctrl_params_translate.c
index ed73fc0fbb8d..c846353200b2 100644
--- a/crypto/openssl/crypto/evp/ctrl_params_translate.c
+++ b/crypto/openssl/crypto/evp/ctrl_params_translate.c
@@ -1356,7 +1356,7 @@ static int fix_rsa_padding_mode(enum state state,
if (i == OSSL_NELEM(str_value_map)) {
ERR_raise_data(ERR_LIB_RSA, RSA_R_UNKNOWN_PADDING_TYPE,
"[action:%d, state:%d] padding name %s",
- ctx->action_type, state, ctx->p1);
+ ctx->action_type, state, (const char *)ctx->p2);
ctx->p1 = ret = -2;
} else if (state == POST_CTRL_TO_PARAMS) {
/* EVP_PKEY_CTRL_GET_RSA_PADDING weirdness explained further up */
diff --git a/crypto/openssl/crypto/evp/p_lib.c b/crypto/openssl/crypto/evp/p_lib.c
index 7f4508169dfa..63953a84e1f5 100644
--- a/crypto/openssl/crypto/evp/p_lib.c
+++ b/crypto/openssl/crypto/evp/p_lib.c
@@ -1146,15 +1146,14 @@ int EVP_PKEY_can_sign(const EVP_PKEY *pkey)
} else {
const OSSL_PROVIDER *prov = EVP_KEYMGMT_get0_provider(pkey->keymgmt);
OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
- const char *supported_sig =
- pkey->keymgmt->query_operation_name != NULL
- ? pkey->keymgmt->query_operation_name(OSSL_OP_SIGNATURE)
- : EVP_KEYMGMT_get0_name(pkey->keymgmt);
- EVP_SIGNATURE *signature = NULL;
-
- signature = EVP_SIGNATURE_fetch(libctx, supported_sig, NULL);
- if (signature != NULL) {
- EVP_SIGNATURE_free(signature);
+ EVP_SIGNATURE *sig;
+ const char *name;
+
+ name = evp_keymgmt_util_query_operation_name(pkey->keymgmt,
+ OSSL_OP_SIGNATURE);
+ sig = EVP_SIGNATURE_fetch(libctx, name, NULL);
+ if (sig != NULL) {
+ EVP_SIGNATURE_free(sig);
return 1;
}
}
diff --git a/crypto/openssl/crypto/info.c b/crypto/openssl/crypto/info.c
index 4d70471be255..e760ec094027 100644
--- a/crypto/openssl/crypto/info.c
+++ b/crypto/openssl/crypto/info.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-2025 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
@@ -23,6 +23,9 @@
#if defined(__arm__) || defined(__arm) || defined(__aarch64__)
# include "arm_arch.h"
# define CPU_INFO_STR_LEN 128
+#elif defined(__powerpc__) || defined(__POWERPC__) || defined(_ARCH_PPC)
+# include "crypto/ppc_arch.h"
+# define CPU_INFO_STR_LEN 128
#elif defined(__s390__) || defined(__s390x__)
# include "s390x_arch.h"
# define CPU_INFO_STR_LEN 2048
@@ -77,6 +80,15 @@ DEFINE_RUN_ONCE_STATIC(init_info_strings)
BIO_snprintf(ossl_cpu_info_str + strlen(ossl_cpu_info_str),
sizeof(ossl_cpu_info_str) - strlen(ossl_cpu_info_str),
" env:%s", env);
+# elif defined(__powerpc__) || defined(__POWERPC__) || defined(_ARCH_PPC)
+ const char *env;
+
+ BIO_snprintf(ossl_cpu_info_str, sizeof(ossl_cpu_info_str),
+ CPUINFO_PREFIX "OPENSSL_ppccap=0x%x", OPENSSL_ppccap_P);
+ if ((env = getenv("OPENSSL_ppccap")) != NULL)
+ BIO_snprintf(ossl_cpu_info_str + strlen(ossl_cpu_info_str),
+ sizeof(ossl_cpu_info_str) - strlen(ossl_cpu_info_str),
+ " env:%s", env);
# elif defined(__s390__) || defined(__s390x__)
const char *env;
diff --git a/crypto/openssl/crypto/ml_dsa/ml_dsa_key.c b/crypto/openssl/crypto/ml_dsa/ml_dsa_key.c
index 41df1a956fb8..50e3b5433085 100644
--- a/crypto/openssl/crypto/ml_dsa/ml_dsa_key.c
+++ b/crypto/openssl/crypto/ml_dsa/ml_dsa_key.c
@@ -311,6 +311,7 @@ int ossl_ml_dsa_key_has(const ML_DSA_KEY *key, int selection)
static int public_from_private(const ML_DSA_KEY *key, EVP_MD_CTX *md_ctx,
VECTOR *t1, VECTOR *t0)
{
+ int ret = 0;
const ML_DSA_PARAMS *params = key->params;
uint32_t k = params->k, l = params->l;
POLY *polys;
@@ -343,9 +344,10 @@ static int public_from_private(const ML_DSA_KEY *key, EVP_MD_CTX *md_ctx,
/* Zeroize secret */
vector_zero(&s1_ntt);
+ ret = 1;
err:
OPENSSL_free(polys);
- return 1;
+ return ret;
}
int ossl_ml_dsa_key_public_from_private(ML_DSA_KEY *key)
diff --git a/crypto/openssl/crypto/ml_kem/ml_kem.c b/crypto/openssl/crypto/ml_kem/ml_kem.c
index 4474af0f87cb..716c3bf4275e 100644
--- a/crypto/openssl/crypto/ml_kem/ml_kem.c
+++ b/crypto/openssl/crypto/ml_kem/ml_kem.c
@@ -2046,5 +2046,5 @@ int ossl_ml_kem_pubkey_cmp(const ML_KEM_KEY *key1, const ML_KEM_KEY *key2)
* No match if just one of the public keys is not available, otherwise both
* are unavailable, and for now such keys are considered equal.
*/
- return (ossl_ml_kem_have_pubkey(key1) ^ ossl_ml_kem_have_pubkey(key2));
+ return (!(ossl_ml_kem_have_pubkey(key1) ^ ossl_ml_kem_have_pubkey(key2)));
}
diff --git a/crypto/openssl/crypto/modes/siv128.c b/crypto/openssl/crypto/modes/siv128.c
index 72526b849eaf..4e52d8eb8782 100644
--- a/crypto/openssl/crypto/modes/siv128.c
+++ b/crypto/openssl/crypto/modes/siv128.c
@@ -202,9 +202,12 @@ int ossl_siv128_init(SIV128_CONTEXT *ctx, const unsigned char *key, int klen,
|| !EVP_MAC_final(mac_ctx, ctx->d.byte, &out_len,
sizeof(ctx->d.byte))) {
EVP_CIPHER_CTX_free(ctx->cipher_ctx);
+ ctx->cipher_ctx = NULL;
EVP_MAC_CTX_free(ctx->mac_ctx_init);
+ ctx->mac_ctx_init = NULL;
EVP_MAC_CTX_free(mac_ctx);
EVP_MAC_free(ctx->mac);
+ ctx->mac = NULL;
return 0;
}
EVP_MAC_CTX_free(mac_ctx);
diff --git a/crypto/openssl/crypto/property/property_parse.c b/crypto/openssl/crypto/property/property_parse.c
index 3a67754224f0..23963c89bc46 100644
--- a/crypto/openssl/crypto/property/property_parse.c
+++ b/crypto/openssl/crypto/property/property_parse.c
@@ -641,7 +641,7 @@ static void put_str(const char *str, char **buf, size_t *remain, size_t *needed)
}
quotes = quote != '\0';
- if (*remain == 0) {
+ if (*remain <= (size_t)quotes) {
*needed += 2 * quotes;
return;
}
diff --git a/crypto/openssl/crypto/rsa/rsa_gen.c b/crypto/openssl/crypto/rsa/rsa_gen.c
index 033f66714add..f76bb7748369 100644
--- a/crypto/openssl/crypto/rsa/rsa_gen.c
+++ b/crypto/openssl/crypto/rsa/rsa_gen.c
@@ -734,18 +734,3 @@ err:
return ret;
}
-
-#ifdef FIPS_MODULE
-int ossl_rsa_key_pairwise_test(RSA *rsa)
-{
- OSSL_CALLBACK *stcb;
- void *stcbarg;
- int res;
-
- OSSL_SELF_TEST_get_callback(rsa->libctx, &stcb, &stcbarg);
- res = rsa_keygen_pairwise_test(rsa, stcb, stcbarg);
- if (res <= 0)
- ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT_IMPORT);
- return res;
-}
-#endif /* FIPS_MODULE */
diff --git a/crypto/openssl/crypto/rsa/rsa_sign.c b/crypto/openssl/crypto/rsa/rsa_sign.c
index 78e4bad69e49..bb6e99acf9d3 100644
--- a/crypto/openssl/crypto/rsa/rsa_sign.c
+++ b/crypto/openssl/crypto/rsa/rsa_sign.c
@@ -1,5 +1,5 @@
/*
- * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2025 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
@@ -129,7 +129,7 @@ static const unsigned char digestinfo_ripemd160_der[] = {
# ifndef OPENSSL_NO_SM3
/* SM3 (1 2 156 10197 1 401) */
static const unsigned char digestinfo_sm3_der[] = {
- ASN1_SEQUENCE, 0x0f + SM3_DIGEST_LENGTH,
+ ASN1_SEQUENCE, 0x10 + SM3_DIGEST_LENGTH,
ASN1_SEQUENCE, 0x0c,
ASN1_OID, 0x08, 1 * 40 + 2, 0x81, 0x1c, 0xcf, 0x55, 1, 0x83, 0x78,
ASN1_NULL, 0x00,
diff --git a/crypto/openssl/crypto/threads_pthread.c b/crypto/openssl/crypto/threads_pthread.c
index 44d6ebe09231..ace2dc499061 100644
--- a/crypto/openssl/crypto/threads_pthread.c
+++ b/crypto/openssl/crypto/threads_pthread.c
@@ -62,8 +62,10 @@ __tsan_mutex_post_lock((x), 0, 0)
/*
* The Non-Stop KLT thread model currently seems broken in its rwlock
* implementation
+ * Likewise is there a problem with the glibc implementation on riscv.
*/
-# if defined(PTHREAD_RWLOCK_INITIALIZER) && !defined(_KLT_MODEL_)
+# if defined(PTHREAD_RWLOCK_INITIALIZER) && !defined(_KLT_MODEL_) \
+ && !defined(__riscv)
# define USE_RWLOCK
# endif
@@ -279,7 +281,7 @@ static struct rcu_qp *get_hold_current_qp(struct rcu_lock_st *lock)
/* if the idx hasn't changed, we're good, else try again */
if (qp_idx == ATOMIC_LOAD_N(uint32_t, &lock->reader_idx,
- __ATOMIC_RELAXED))
+ __ATOMIC_ACQUIRE))
break;
ATOMIC_SUB_FETCH(&lock->qp_group[qp_idx].users, (uint64_t)1,
@@ -403,8 +405,12 @@ static struct rcu_qp *update_qp(CRYPTO_RCU_LOCK *lock, uint32_t *curr_id)
*curr_id = lock->id_ctr;
lock->id_ctr++;
+ /*
+ * make the current state of everything visible by this release
+ * when get_hold_current_qp acquires the next qp
+ */
ATOMIC_STORE_N(uint32_t, &lock->reader_idx, lock->current_alloc_idx,
- __ATOMIC_RELAXED);
+ __ATOMIC_RELEASE);
/*
* this should make sure that the new value of reader_idx is visible in
diff --git a/crypto/openssl/crypto/x509/t_x509.c b/crypto/openssl/crypto/x509/t_x509.c
index 7d693669cd36..d849e642ce8b 100644
--- a/crypto/openssl/crypto/x509/t_x509.c
+++ b/crypto/openssl/crypto/x509/t_x509.c
@@ -219,7 +219,8 @@ int X509_ocspid_print(BIO *bp, X509 *x)
goto err;
if ((der = dertmp = OPENSSL_malloc(derlen)) == NULL)
goto err;
- i2d_X509_NAME(subj, &dertmp);
+ if (i2d_X509_NAME(subj, &dertmp) < 0)
+ goto err;
md = EVP_MD_fetch(x->libctx, SN_sha1, x->propq);
if (md == NULL)
diff --git a/crypto/openssl/crypto/x509/x509_lu.c b/crypto/openssl/crypto/x509/x509_lu.c
index 05ee7c8c6b51..eb2d47955b2e 100644
--- a/crypto/openssl/crypto/x509/x509_lu.c
+++ b/crypto/openssl/crypto/x509/x509_lu.c
@@ -408,7 +408,6 @@ static int x509_store_add(X509_STORE *store, void *x, int crl)
}
if (!X509_STORE_lock(store)) {
- obj->type = X509_LU_NONE;
X509_OBJECT_free(obj);
return 0;
}
diff --git a/crypto/openssl/doc/man3/DEFINE_STACK_OF.pod b/crypto/openssl/doc/man3/DEFINE_STACK_OF.pod
index ff2074820f68..eeb882f291e4 100644
--- a/crypto/openssl/doc/man3/DEFINE_STACK_OF.pod
+++ b/crypto/openssl/doc/man3/DEFINE_STACK_OF.pod
@@ -170,15 +170,14 @@ B<sk_I<TYPE>_set>() sets element I<idx> of I<sk> to I<ptr> replacing the current
element. The new element value is returned or NULL if an error occurred:
this will only happen if I<sk> is NULL or I<idx> is out of range.
-B<sk_I<TYPE>_find>() searches I<sk> for the element I<ptr>. In the case
-where no comparison function has been specified, the function performs
-a linear search for a pointer equal to I<ptr>. The index of the first
-matching element is returned or B<-1> if there is no match. In the case
-where a comparison function has been specified, I<sk> is sorted and
-B<sk_I<TYPE>_find>() returns the index of a matching element or B<-1> if there
-is no match. Note that, in this case the comparison function will usually
-compare the values pointed to rather than the pointers themselves and
-the order of elements in I<sk> can change.
+B<sk_I<TYPE>_find>() searches I<sk> for the element I<ptr>. In the
+case where no comparison function has been specified, the function
+performs a linear search for a pointer equal to I<ptr>. In the case
+where a comparison function has been specified, the function performs
+a search for a element that the comparison function indicates is a
+match. If the stack is sorted, a binary search is used, otherwise, a
+linear search is used. B<sk_I<TYPE>_find>() returns the index of a
+matching element or B<-1> if there is no match.
B<sk_I<TYPE>_find_ex>() operates like B<sk_I<TYPE>_find>() except when a
comparison function has been specified and no matching element is found.
@@ -301,7 +300,7 @@ was changed to return 0 in this condition as for other errors.
=head1 COPYRIGHT
-Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2025 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
diff --git a/crypto/openssl/doc/man3/OpenSSL_version.pod b/crypto/openssl/doc/man3/OpenSSL_version.pod
index e5dff33dcdda..6b899cbe5438 100644
--- a/crypto/openssl/doc/man3/OpenSSL_version.pod
+++ b/crypto/openssl/doc/man3/OpenSSL_version.pod
@@ -256,9 +256,16 @@ L<crypto(7)>
The macros and functions described here were added in OpenSSL 3.0,
except for OPENSSL_VERSION_NUMBER and OpenSSL_version_num().
+=head1 BUGS
+
+There was a discrepancy between this manual and commentary + code
+in F<< <openssl/opensslv.h> >>, where the latter suggested that the
+four least significant bits of B<OPENSSL_VERSION_NUMBER> could be
+C<0x0f> in released OpenSSL versions.
+
=head1 COPYRIGHT
-Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2018-2025 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
diff --git a/crypto/openssl/doc/man3/SSL_CIPHER_get_name.pod b/crypto/openssl/doc/man3/SSL_CIPHER_get_name.pod
index 09b7280bdd58..a10942433aa7 100644
--- a/crypto/openssl/doc/man3/SSL_CIPHER_get_name.pod
+++ b/crypto/openssl/doc/man3/SSL_CIPHER_get_name.pod
@@ -37,7 +37,7 @@ SSL_CIPHER_get_protocol_id
int SSL_CIPHER_is_aead(const SSL_CIPHER *c);
const SSL_CIPHER *SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr);
uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *c);
- uint32_t SSL_CIPHER_get_protocol_id(const SSL_CIPHER *c);
+ uint16_t SSL_CIPHER_get_protocol_id(const SSL_CIPHER *c);
=head1 DESCRIPTION
@@ -203,7 +203,7 @@ The OPENSSL_cipher_name() function was added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2025 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
diff --git a/crypto/openssl/doc/man3/SSL_SESSION_get0_hostname.pod b/crypto/openssl/doc/man3/SSL_SESSION_get0_hostname.pod
index f7add16d7bdd..0140deee9a5e 100644
--- a/crypto/openssl/doc/man3/SSL_SESSION_get0_hostname.pod
+++ b/crypto/openssl/doc/man3/SSL_SESSION_get0_hostname.pod
@@ -23,9 +23,10 @@ SSL_SESSION_set1_alpn_selected
=head1 DESCRIPTION
-SSL_SESSION_get0_hostname() retrieves the SNI value that was sent by the
-client when the session was created if it was accepted by the server. Otherwise
-NULL is returned.
+SSL_SESSION_get0_hostname() retrieves the Server Name Indication (SNI) value
+that was sent by the client when the session was created if the server
+acknowledged the client's SNI extension by including an empty SNI extension
+in response. Otherwise NULL is returned.
The value returned is a pointer to memory maintained within B<s> and
should not be free'd.
@@ -44,8 +45,7 @@ B<alpn>.
=head1 RETURN VALUES
-SSL_SESSION_get0_hostname() returns either a string or NULL based on if there
-is the SNI value sent by client.
+SSL_SESSION_get0_hostname() returns the SNI string if available, or NULL if not.
SSL_SESSION_set1_hostname() returns 1 on success or 0 on error.
diff --git a/crypto/openssl/include/crypto/rsa.h b/crypto/openssl/include/crypto/rsa.h
index ffbc95a77888..55cc814ce913 100644
--- a/crypto/openssl/include/crypto/rsa.h
+++ b/crypto/openssl/include/crypto/rsa.h
@@ -124,10 +124,6 @@ ASN1_STRING *ossl_rsa_ctx_to_pss_string(EVP_PKEY_CTX *pkctx);
int ossl_rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx,
const X509_ALGOR *sigalg, EVP_PKEY *pkey);
-# ifdef FIPS_MODULE
-int ossl_rsa_key_pairwise_test(RSA *rsa);
-# endif /* FIPS_MODULE */
-
# if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
int ossl_rsa_acvp_test_gen_params_new(OSSL_PARAM **dst, const OSSL_PARAM src[]);
void ossl_rsa_acvp_test_gen_params_free(OSSL_PARAM *dst);
diff --git a/crypto/openssl/include/openssl/opensslv.h.in b/crypto/openssl/include/openssl/opensslv.h.in
index e547281ff527..69b9caacf4dc 100644
--- a/crypto/openssl/include/openssl/opensslv.h.in
+++ b/crypto/openssl/include/openssl/opensslv.h.in
@@ -89,12 +89,12 @@ extern "C" {
# define OPENSSL_VERSION_TEXT "OpenSSL {- "$config{full_version} $config{release_date}" -}"
-/* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
+/* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PP0L */
# define OPENSSL_VERSION_NUMBER \
( (OPENSSL_VERSION_MAJOR<<28) \
|(OPENSSL_VERSION_MINOR<<20) \
|(OPENSSL_VERSION_PATCH<<4) \
- |{- @config{prerelease} ? "0x0L" : "0xfL" -} )
+ |0x0L )
# ifdef __cplusplus
}
diff --git a/crypto/openssl/providers/fips-sources.checksums b/crypto/openssl/providers/fips-sources.checksums
index d48a9c85f57b..334b4ad6b7f2 100644
--- a/crypto/openssl/providers/fips-sources.checksums
+++ b/crypto/openssl/providers/fips-sources.checksums
@@ -250,7 +250,7 @@ c685813be6ad35b0861ba888670ef54aa2b399d003472698e39426de6e52db59 crypto/initthr
f866aafae928db1b439ac950dc90744a2397dfe222672fe68b3798396190c8b0 crypto/mem_clr.c
18127868d868ca5705444c24f7dc385391ba31154fc04ff54949739e8fa7fdfc crypto/ml_dsa/ml_dsa_encoders.c
825105b0a2c4844b2b4229001650ff7e61e1348e52f1072210f70b97cd4adb71 crypto/ml_dsa/ml_dsa_hash.h
-c82201cf1a17ff2d4b169dcd4402d3d56f4685e460a1447e021db4abd67f7f0e crypto/ml_dsa/ml_dsa_key.c
+c467f4400d399aad6b51746ef2575d1e04d260a1bf901b35ca55624fe62e650e crypto/ml_dsa/ml_dsa_key.c
579c1a12a5c5f014476a6bf695dc271f63074fb187e23ffc3f9ccb5b7ea044f1 crypto/ml_dsa/ml_dsa_key.h
3f98eb0467033d0a40867ef1c1036dcfea5d231eeac2321196f7d7c7243edace crypto/ml_dsa/ml_dsa_key_compress.c
983d164bfa3dbe8d85ad1fdc24d897e79d9246d96d9c1862855c6c538b387ad9 crypto/ml_dsa/ml_dsa_local.h
@@ -263,7 +263,7 @@ ff65c82c56e341f47df03d0c74de7fb537de0e68a4fa23fa07a9fdb51c511f1c crypto/ml_dsa/
1d7f57a41034988a4e7d4c9a998760d2ef802c5e90275d09a3ca31c5f3403d94 crypto/ml_dsa/ml_dsa_sign.c
5217ef237e21872205703b95577290c34898423466a465c7bd609b2eb4627964 crypto/ml_dsa/ml_dsa_sign.h
abd934284bcd8061027a69f437fa4410c6b72cd950be1ebe048244d036371208 crypto/ml_dsa/ml_dsa_vector.h
-defc2e4e81ff1b78056c795bc0565f4241a259c2957abe84a51bcbc1e4ace3f1 crypto/ml_kem/ml_kem.c
+8c4f7238f68f959f2ad1e2529c567364c5a8818898355c82818521e03239ea76 crypto/ml_kem/ml_kem.c
36e24eae5d38cc9666ae40e4e8a2dc12328e1159fea68447cb19dab174d25adf crypto/modes/asm/aes-gcm-armv8-unroll8_64.pl
33357356cd739d4ae89d52f0804b6900e4b94d8829323819c6f64c8908e978df crypto/modes/asm/aes-gcm-armv8_64.pl
bcc09bdb474f045d04c983fa09c31a010c5a25513f53a5d3653ade91304f0f96 crypto/modes/asm/aes-gcm-avx512.pl
@@ -306,7 +306,7 @@ f50450f7e5f6896fb8e3cde2fdc11cc543124c854ef9d88252a166606ca80081 crypto/params_
467c416422ecf61e3b713c5eb259fdbcb4aa73ae8dee61804d0b85cfd3fff4f7 crypto/property/defn_cache.c
91c1f1f8eb5588ed9da17386c244ae68a6a81717b1c7ab6c9f1a6a57973a039f crypto/property/property.c
66da4f28d408133fb544b14aeb9ad4913e7c5c67e2826e53f0dc5bf4d8fada26 crypto/property/property_local.h
-d32105cb087d708d0504a787f74bc163cc398c299faf2e98d6bb5ae02f5ce9b7 crypto/property/property_parse.c
+1e99a3934812f99dad79cbfbb6727ad61b6093711c1a6c74d4b50f9318152611 crypto/property/property_parse.c
a7cefda6a117550e2c76e0f307565ce1e11640b11ba10c80e469a837fd1212a3 crypto/property/property_query.c
20e69b9d594dfc443075eddbb0e6bcc0ed36ca51993cd50cc5a4f86eb31127f8 crypto/property/property_string.c
10644e9d20214660706de58d34edf635c110d4e4f2628cd5284a08c60ed9aff8 crypto/provider_core.c
@@ -322,7 +322,7 @@ f0c8792a99132e0b9c027cfa7370f45594a115934cdc9e8f23bdd64abecaf7fd crypto/rsa/rsa
1b828f428f0e78b591378f7b780164c4574620c68f9097de041cbd576f811bf6 crypto/rsa/rsa_backend.c
38a102cd1da1f6ca5a46e6a22f018237964336274385f5c70cbedcaa6997647e crypto/rsa/rsa_chk.c
e762c599b17d5c89f4b1c9eb7d0ca1f04a95d815c86a3e72c30b231ce57fb199 crypto/rsa/rsa_crpt.c
-0fa3e4687510e2d91c8f4b1c460b1d51375d9855ed825b3d6697620b146b52d1 crypto/rsa/rsa_gen.c
+a3d20f27ae3cb41af5b62febd0bb19025e59d401b136306d570cdba103b15542 crypto/rsa/rsa_gen.c
f22bc4e2c3acab83e67820c906c1caf048ec1f0d4fcb7472c1bec753c75f8e93 crypto/rsa/rsa_lib.c
5ae8edaf654645996385fbd420ef73030762fc146bf41deb5294d6d83e257a16 crypto/rsa/rsa_local.h
cf0b75cd54b61b9b9a290ef18d0ddce9fb26a029a54eb3f720d9b25188440f00 crypto/rsa/rsa_mp_names.c
@@ -416,7 +416,7 @@ a00e16963e1e2a0126c6a8e62da8a14f98de9736027654c925925dadd0ca3cc1 crypto/thread/
27ec0090f4243c96e4fbe1babfd4320c2a16615ffa368275433217d50a1ef76c crypto/thread/internal.c
67ba8d87fbbb7c9a9e438018e7ecfd1cedd4d00224be05755580d044f5f1317a crypto/threads_lib.c
b1a828491d9ce305802662561788facac92dff70cca9ead807f3e28741ff21e0 crypto/threads_none.c
-c659f7ce5c4b59d2a1cff78485fa8e89c8d20d5798df4afc1b94ff635ffc0262 crypto/threads_pthread.c
+491e9c29d4a7b4dd627ea25c20ce4a33103565b3108b618c41c6816dfc675569 crypto/threads_pthread.c
9c3bf7b4baa302a4017150fbcaa114ee9df935b18d5a3a8c8015003780d4e7de crypto/threads_win.c
7edd638df588b14711a50c98d458c4fc83f223ed03bc6c39c7c8edf7915b7cfa crypto/time.c
88c5f9f4d2611223d283ebd2ae10ae5ecbb9972d00f747d93fcb74b62641e3f9 crypto/x86_64cpuid.pl
@@ -445,7 +445,7 @@ bbe5e52d84e65449a13e42cd2d6adce59b8ed6e73d6950917aa77dc1f3f5dff6 include/crypto
6e7762e7fb63f56d25b24f70209f4dc834c59a87f74467531ec81646f565dbe3 include/crypto/modes.h
920bc48a4dad3712bdcef188c0ce8e8a8304e0ce332b54843bab366fc5eab472 include/crypto/rand.h
71f23915ea74e93971fb0205901031be3abea7ffef2c52e4cc4848515079f68d include/crypto/rand_pool.h
-b1df067691f9741ef9c42b2e5f12461bcd87b745514fc5701b9c9402fb10b224 include/crypto/rsa.h
+6f16685ffbc97dc2ac1240bfddf4bbac2dd1ad83fff6da91aee6f3f64c6ee8ff include/crypto/rsa.h
32f0149ab1d82fddbdfbbc44e3078b4a4cc6936d35187e0f8d02cc0bc19f2401 include/crypto/security_bits.h
80338f3865b7c74aab343879432a6399507b834e2f55dd0e9ee7a5eeba11242a include/crypto/sha.h
dc7808729c3231a08bbe470b3e1b562420030f59f7bc05b14d7b516fa77b4f3a include/crypto/slh_dsa.h
@@ -546,7 +546,7 @@ a8a45996fd21411cb7ed610bc202dbd06570cdfa0a2d14f7dfc8bfadc820e636 include/openss
cb6bca3913c60a57bac39583eee0f789d49c3d29be3ecde9aecc7f3287117aa5 include/openssl/objects.h
d25537af264684dff033dd8ae62b0348f868fcfec4aa51fa8f07bcfa4bd807ad include/openssl/objectserr.h
fe6acd42c3e90db31aaafc2236a7d30ebfa53c4c07ea4d8265064c7fcb951970 include/openssl/opensslconf.h
-fc914a750d798ac9fc9287e6359cfa1da214b91651deaaaa7e1a46b595cd0425 include/openssl/opensslv.h.in
+6c1a8837bbba633db2a8951ff29ccfe09e7d2a24a37ee2af90f2d897c190da9a include/openssl/opensslv.h.in
767d9d7d5051c937a3ce8a268c702902fda93eeaa210a94dfde1f45c23277d20 include/openssl/param_build.h
1c442aaaa4dda7fbf727a451bc676fb4d855ef617c14dc77ff2a5e958ae33c3e include/openssl/params.h
44f178176293c6ce8142890ff9dc2d466364c734e4e811f56bd62010c5403183 include/openssl/pkcs7.h.in
@@ -618,8 +618,8 @@ f2581d7b4e105f2bb6d30908f3c2d9959313be08cec6dbeb49030c125a7676d3 providers/fips
669f76f742bcaaf28846b057bfab97da7c162d69da244de71b7c743bf16e430f providers/fips/include/fipscommon.h
f111fd7e016af8cc6f96cd8059c28227b328dd466ed137ae0c0bc0c3c3eec3ba providers/fips/self_test.c
5c2c6c2f69e2eb01b88fa35630f27948e00dd2c2fd351735c74f34ccb2005cbe providers/fips/self_test.h
-663441de9aba1d1b81ce02b3acded520b88cc460330d4d98adb7450d9664c474 providers/fips/self_test_data.inc
-2e568e2b161131240e97bd77a730c2299f961c2f1409ea8466422fc07f9be23f providers/fips/self_test_kats.c
+df83c901ad13675fbbb4708b6087feba6099870ad3dd0e8d09cfdb6798419770 providers/fips/self_test_data.inc
+6779d5afb3f48d82868b247ffb0a6a572f6e3964738296ad47e7ccafdb263c88 providers/fips/self_test_kats.c
dde79dfdedfe0e73006a0cf912fdde1ff109dfbc5ba6ecab319c938bc4275950 providers/implementations/asymciphers/rsa_enc.c
c2f1b12c64fc369dfc3b9bc9e76a76de7280e6429adaee55d332eb1971ad1879 providers/implementations/ciphers/cipher_aes.c
6ba7d817081cf0d87ba7bfb38cd9d70e41505480bb8bc796ef896f68d4514ea6 providers/implementations/ciphers/cipher_aes.h
@@ -699,7 +699,7 @@ c764555b9dc9b273c280514a5d2d44156f82f3e99155a77c627f2c773209bcd7 providers/impl
24cc3cc8e8681c77b7f96c83293bd66045fd8ad69f756e673ca7f8ca9e82b0af providers/implementations/keymgmt/dsa_kmgmt.c
36a9c1c8658ce7918453827cb58ed52787e590e3f148c5510deeb2c16c25a29d providers/implementations/keymgmt/ec_kmgmt.c
258ae17bb2dd87ed1511a8eb3fe99eed9b77f5c2f757215ff6b3d0e8791fc251 providers/implementations/keymgmt/ec_kmgmt_imexport.inc
-9728d696d249b2d224724c9872138a60e1998e5cfa5c49f3f48ad0666f7eed34 providers/implementations/keymgmt/ecx_kmgmt.c
+11c27cc3c9f38885c484f25d11987e93f197aa90bef2fc1d6e8f508c2d014d4d providers/implementations/keymgmt/ecx_kmgmt.c
daf35a7ab961ef70aefca981d80407935904c5da39dca6692432d6e6bc98759d providers/implementations/keymgmt/kdf_legacy_kmgmt.c
d97d7c8d3410b3e560ef2becaea2a47948e22205be5162f964c5e51a7eef08cb providers/implementations/keymgmt/mac_legacy_kmgmt.c
a428de71082fd01e5dcfa030a6fc34f6700b86d037b4e22f015c917862a158ce providers/implementations/keymgmt/ml_dsa_kmgmt.c
diff --git a/crypto/openssl/providers/fips.checksum b/crypto/openssl/providers/fips.checksum
index 7fa4ea19bba3..5d1117361d27 100644
--- a/crypto/openssl/providers/fips.checksum
+++ b/crypto/openssl/providers/fips.checksum
@@ -1 +1 @@
-8d0c2c2b986f4c98f511c9aa020e98aa984dce5976d8e1966a7721f8b559cda8 providers/fips-sources.checksums
+c342f9dc7075a6ecd0e4b3c9db06e180765278a7bbae233ec1a65095a0e524ec providers/fips-sources.checksums
diff --git a/crypto/openssl/providers/fips/self_test_data.inc b/crypto/openssl/providers/fips/self_test_data.inc
index b6aa433ca93c..6abab0a7a173 100644
--- a/crypto/openssl/providers/fips/self_test_data.inc
+++ b/crypto/openssl/providers/fips/self_test_data.inc
@@ -1308,6 +1308,18 @@ static const ST_KAT_PARAM rsa_priv_key[] = {
ST_KAT_PARAM_END()
};
+/*-
+ * Using OSSL_PKEY_RSA_PAD_MODE_NONE directly in the expansion of the
+ * ST_KAT_PARAM_UTF8STRING macro below causes a failure on ancient
+ * HP/UX PA-RISC compilers.
+ */
+static const char pad_mode_none[] = OSSL_PKEY_RSA_PAD_MODE_NONE;
+
+static const ST_KAT_PARAM rsa_enc_params[] = {
+ ST_KAT_PARAM_UTF8STRING(OSSL_ASYM_CIPHER_PARAM_PAD_MODE, pad_mode_none),
+ ST_KAT_PARAM_END()
+};
+
static const unsigned char rsa_sig_msg[] = "Hello World!";
static const unsigned char rsa_expected_sig[256] = {
@@ -3497,3 +3509,33 @@ static const ST_KAT_ASYM_KEYGEN st_kat_asym_keygen_tests[] = {
# endif
};
#endif /* !OPENSSL_NO_ML_DSA || !OPENSSL_NO_SLH_DSA */
+
+static const ST_KAT_ASYM_CIPHER st_kat_asym_cipher_tests[] = {
+ {
+ OSSL_SELF_TEST_DESC_ASYM_RSA_ENC,
+ "RSA",
+ 1,
+ rsa_pub_key,
+ rsa_enc_params,
+ ITM(rsa_asym_plaintext_encrypt),
+ ITM(rsa_asym_expected_encrypt),
+ },
+ {
+ OSSL_SELF_TEST_DESC_ASYM_RSA_DEC,
+ "RSA",
+ 0,
+ rsa_priv_key,
+ rsa_enc_params,
+ ITM(rsa_asym_expected_encrypt),
+ ITM(rsa_asym_plaintext_encrypt),
+ },
+ {
+ OSSL_SELF_TEST_DESC_ASYM_RSA_DEC,
+ "RSA",
+ 0,
+ rsa_crt_key,
+ rsa_enc_params,
+ ITM(rsa_asym_expected_encrypt),
+ ITM(rsa_asym_plaintext_encrypt),
+ },
+};
diff --git a/crypto/openssl/providers/fips/self_test_kats.c b/crypto/openssl/providers/fips/self_test_kats.c
index 35ecb43598ee..acb0b85f7343 100644
--- a/crypto/openssl/providers/fips/self_test_kats.c
+++ b/crypto/openssl/providers/fips/self_test_kats.c
@@ -813,6 +813,93 @@ err:
#endif
/*
+ * Test an encrypt or decrypt KAT..
+ *
+ * FIPS 140-2 IG D.9 states that separate KAT tests are needed for encrypt
+ * and decrypt..
+ */
+static int self_test_asym_cipher(const ST_KAT_ASYM_CIPHER *t, OSSL_SELF_TEST *st,
+ OSSL_LIB_CTX *libctx)
+{
+ int ret = 0;
+ OSSL_PARAM *keyparams = NULL, *initparams = NULL;
+ OSSL_PARAM_BLD *keybld = NULL, *initbld = NULL;
+ EVP_PKEY_CTX *encctx = NULL, *keyctx = NULL;
+ EVP_PKEY *key = NULL;
+ BN_CTX *bnctx = NULL;
+ unsigned char out[256];
+ size_t outlen = sizeof(out);
+
+ OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_ASYM_CIPHER, t->desc);
+
+ bnctx = BN_CTX_new_ex(libctx);
+ if (bnctx == NULL)
+ goto err;
+
+ /* Load a public or private key from data */
+ keybld = OSSL_PARAM_BLD_new();
+ if (keybld == NULL
+ || !add_params(keybld, t->key, bnctx))
+ goto err;
+ keyparams = OSSL_PARAM_BLD_to_param(keybld);
+ keyctx = EVP_PKEY_CTX_new_from_name(libctx, t->algorithm, NULL);
+ if (keyctx == NULL || keyparams == NULL)
+ goto err;
+ if (EVP_PKEY_fromdata_init(keyctx) <= 0
+ || EVP_PKEY_fromdata(keyctx, &key, EVP_PKEY_KEYPAIR, keyparams) <= 0)
+ goto err;
+
+ /* Create a EVP_PKEY_CTX to use for the encrypt or decrypt operation */
+ encctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL);
+ if (encctx == NULL
+ || (t->encrypt && EVP_PKEY_encrypt_init(encctx) <= 0)
+ || (!t->encrypt && EVP_PKEY_decrypt_init(encctx) <= 0))
+ goto err;
+
+ /* Add any additional parameters such as padding */
+ if (t->postinit != NULL) {
+ initbld = OSSL_PARAM_BLD_new();
+ if (initbld == NULL)
+ goto err;
+ if (!add_params(initbld, t->postinit, bnctx))
+ goto err;
+ initparams = OSSL_PARAM_BLD_to_param(initbld);
+ if (initparams == NULL)
+ goto err;
+ if (EVP_PKEY_CTX_set_params(encctx, initparams) <= 0)
+ goto err;
+ }
+
+ if (t->encrypt) {
+ if (EVP_PKEY_encrypt(encctx, out, &outlen,
+ t->in, t->in_len) <= 0)
+ goto err;
+ } else {
+ if (EVP_PKEY_decrypt(encctx, out, &outlen,
+ t->in, t->in_len) <= 0)
+ goto err;
+ }
+ /* Check the KAT */
+ OSSL_SELF_TEST_oncorrupt_byte(st, out);
+ if (outlen != t->expected_len
+ || memcmp(out, t->expected, t->expected_len) != 0)
+ goto err;
+
+ ret = 1;
+err:
+ BN_CTX_free(bnctx);
+ EVP_PKEY_free(key);
+ EVP_PKEY_CTX_free(encctx);
+ EVP_PKEY_CTX_free(keyctx);
+ OSSL_PARAM_free(keyparams);
+ OSSL_PARAM_BLD_free(keybld);
+ OSSL_PARAM_free(initparams);
+ OSSL_PARAM_BLD_free(initbld);
+ OSSL_SELF_TEST_onend(st, ret);
+ return ret;
+}
+
+/*
* Test a data driven list of KAT's for digest algorithms.
* All tests are run regardless of if they fail or not.
* Return 0 if any test fails.
@@ -853,6 +940,17 @@ static int self_test_kems(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
return ret;
}
+static int self_test_asym_ciphers(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
+{
+ int i, ret = 1;
+
+ for (i = 0; i < (int)OSSL_NELEM(st_kat_asym_cipher_tests); ++i) {
+ if (!self_test_asym_cipher(&st_kat_asym_cipher_tests[i], st, libctx))
+ ret = 0;
+ }
+ return ret;
+}
+
static int self_test_kdfs(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
{
int i, ret = 1;
@@ -1092,6 +1190,8 @@ int SELF_TEST_kats(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
ret = 0;
if (!self_test_kems(st, libctx))
ret = 0;
+ if (!self_test_asym_ciphers(st, libctx))
+ ret = 0;
RAND_set0_private(libctx, saved_rand);
return ret;
diff --git a/crypto/openssl/providers/implementations/kdfs/krb5kdf.c b/crypto/openssl/providers/implementations/kdfs/krb5kdf.c
index 566afa74fece..13623ec7302e 100644
--- a/crypto/openssl/providers/implementations/kdfs/krb5kdf.c
+++ b/crypto/openssl/providers/implementations/kdfs/krb5kdf.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2018-2024 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2018-2025 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
@@ -350,7 +350,7 @@ static int cipher_init(EVP_CIPHER_CTX *ctx,
{
int klen, ret;
- ret = EVP_EncryptInit_ex(ctx, cipher, engine, key, NULL);
+ ret = EVP_EncryptInit_ex(ctx, cipher, engine, NULL, NULL);
if (!ret)
goto out;
/* set the key len for the odd variable key len cipher */
@@ -362,6 +362,9 @@ static int cipher_init(EVP_CIPHER_CTX *ctx,
goto out;
}
}
+ ret = EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL);
+ if (!ret)
+ goto out;
/* we never want padding, either the length requested is a multiple of
* the cipher block size or we are passed a cipher that can cope with
* partial blocks via techniques like cipher text stealing */
diff --git a/crypto/openssl/providers/implementations/keymgmt/ecx_kmgmt.c b/crypto/openssl/providers/implementations/keymgmt/ecx_kmgmt.c
index e6d326a90705..0ebe8b4d59b1 100644
--- a/crypto/openssl/providers/implementations/keymgmt/ecx_kmgmt.c
+++ b/crypto/openssl/providers/implementations/keymgmt/ecx_kmgmt.c
@@ -218,14 +218,6 @@ static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[])
include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
ok = ok && ossl_ecx_key_fromdata(key, params, include_private);
-#ifdef FIPS_MODULE
- if (ok > 0 && ecx_key_type_is_ed(key->type) && !ossl_fips_self_testing())
- if (key->haspubkey && key->privkey != NULL) {
- ok = ecd_fips140_pairwise_test(key, key->type, 1);
- if (ok <= 0)
- ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT_IMPORT);
- }
-#endif /* FIPS_MODULE */
return ok;
}
diff --git a/crypto/openssl/ssl/quic/quic_impl.c b/crypto/openssl/ssl/quic/quic_impl.c
index c44e6b33c2a8..cec05d5bd37b 100644
--- a/crypto/openssl/ssl/quic/quic_impl.c
+++ b/crypto/openssl/ssl/quic/quic_impl.c
@@ -3197,6 +3197,7 @@ int ossl_quic_conn_stream_conclude(SSL *s)
QCTX ctx;
QUIC_STREAM *qs;
int err;
+ int ret;
if (!expect_quic_with_stream_lock(s, /*remote_init=*/0, /*io=*/0, &ctx))
return 0;
@@ -3204,13 +3205,15 @@ int ossl_quic_conn_stream_conclude(SSL *s)
qs = ctx.xso->stream;
if (!quic_mutation_allowed(ctx.qc, /*req_active=*/1)) {
+ ret = QUIC_RAISE_NON_NORMAL_ERROR(&ctx, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL);
qctx_unlock(&ctx);
- return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL);
+ return ret;
}
if (!quic_validate_for_write(ctx.xso, &err)) {
+ ret = QUIC_RAISE_NON_NORMAL_ERROR(&ctx, err, NULL);
qctx_unlock(&ctx);
- return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, err, NULL);
+ return ret;
}
if (ossl_quic_sstream_get_final_size(qs->sstream, NULL)) {
diff --git a/crypto/openssl/ssl/record/methods/tls_common.c b/crypto/openssl/ssl/record/methods/tls_common.c
index 80d4477bd0c0..b9c79099462d 100644
--- a/crypto/openssl/ssl/record/methods/tls_common.c
+++ b/crypto/openssl/ssl/record/methods/tls_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2022-2025 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
@@ -1093,9 +1093,12 @@ int tls13_common_post_process_record(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *rec)
return 0;
}
- if (rl->msg_callback != NULL)
- rl->msg_callback(0, rl->version, SSL3_RT_INNER_CONTENT_TYPE, &rec->type,
- 1, rl->cbarg);
+ if (rl->msg_callback != NULL) {
+ unsigned char ctype = (unsigned char)rec->type;
+
+ rl->msg_callback(0, rl->version, SSL3_RT_INNER_CONTENT_TYPE, &ctype,
+ 1, rl->cbarg);
+ }
/*
* TLSv1.3 alert and handshake records are required to be non-zero in
diff --git a/crypto/openssl/ssl/ssl_rsa.c b/crypto/openssl/ssl/ssl_rsa.c
index e833bcdbc377..f4731a87af90 100644
--- a/crypto/openssl/ssl/ssl_rsa.c
+++ b/crypto/openssl/ssl/ssl_rsa.c
@@ -1056,10 +1056,13 @@ static int ssl_set_cert_and_key(SSL *ssl, SSL_CTX *ctx, X509 *x509, EVP_PKEY *pr
}
}
- if (!X509_up_ref(x509))
+ if (!X509_up_ref(x509)) {
+ OSSL_STACK_OF_X509_free(dup_chain);
goto out;
+ }
if (!EVP_PKEY_up_ref(privatekey)) {
+ OSSL_STACK_OF_X509_free(dup_chain);
X509_free(x509);
goto out;
}
diff --git a/crypto/openssl/ssl/t1_trce.c b/crypto/openssl/ssl/t1_trce.c
index 35c60feb4371..73fd4ebaa4b0 100644
--- a/crypto/openssl/ssl/t1_trce.c
+++ b/crypto/openssl/ssl/t1_trce.c
@@ -549,8 +549,12 @@ static const ssl_trace_tbl ssl_groups_tbl[] = {
{258, "ffdhe4096"},
{259, "ffdhe6144"},
{260, "ffdhe8192"},
+ {512, "MLKEM512"},
+ {513, "MLKEM768"},
+ {514, "MLKEM1024"},
{4587, "SecP256r1MLKEM768"},
{4588, "X25519MLKEM768"},
+ {4589, "SecP384r1MLKEM1024"},
{25497, "X25519Kyber768Draft00"},
{25498, "SecP256r1Kyber768Draft00"},
{0xFF01, "arbitrary_explicit_prime_curves"},
diff --git a/crypto/openssl/test/build.info b/crypto/openssl/test/build.info
index 9d9be6b642e9..3dca6117796b 100644
--- a/crypto/openssl/test/build.info
+++ b/crypto/openssl/test/build.info
@@ -31,7 +31,8 @@ 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 testutil/helper.c $LIBAPPSSRC
+ testutil/apps_shims.c testutil/random.c testutil/helper.c \
+ testutil/compare.c $LIBAPPSSRC
INCLUDE[libtestutil.a]=../include ../apps/include ..
DEPEND[libtestutil.a]=../libcrypto
diff --git a/crypto/openssl/test/fake_rsaprov.c b/crypto/openssl/test/fake_rsaprov.c
index 46fc9104ef95..6ed121554336 100644
--- a/crypto/openssl/test/fake_rsaprov.c
+++ b/crypto/openssl/test/fake_rsaprov.c
@@ -35,6 +35,8 @@ static int exptypes_selection;
static int query_id;
static int key_deleted;
+unsigned fake_rsa_query_operation_name = 0;
+
typedef struct {
OSSL_LIB_CTX *libctx;
} PROV_FAKE_RSA_CTX;
@@ -90,7 +92,7 @@ static const char *fake_rsa_keymgmt_query(int id)
/* record global for checking */
query_id = id;
- return "RSA";
+ return fake_rsa_query_operation_name ? NULL: "RSA";
}
static int fake_rsa_keymgmt_import(void *keydata, int selection,
diff --git a/crypto/openssl/test/fake_rsaprov.h b/crypto/openssl/test/fake_rsaprov.h
index cb2e66eb68ef..00e7dccb4872 100644
--- a/crypto/openssl/test/fake_rsaprov.h
+++ b/crypto/openssl/test/fake_rsaprov.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2021-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2021-2025 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
@@ -14,5 +14,14 @@
/* Fake RSA provider implementation */
OSSL_PROVIDER *fake_rsa_start(OSSL_LIB_CTX *libctx);
void fake_rsa_finish(OSSL_PROVIDER *p);
+
OSSL_PARAM *fake_rsa_key_params(int priv);
void fake_rsa_restore_store_state(void);
+
+/*
+ * When fake_rsa_query_operation_name is set to a non-zero value,
+ * query_operation_name() will return NULL.
+ *
+ * By default, it is 0, in which case query_operation_name() will return "RSA".
+ */
+extern unsigned fake_rsa_query_operation_name;
diff --git a/crypto/openssl/test/ml_kem_evp_extra_test.c b/crypto/openssl/test/ml_kem_evp_extra_test.c
index bfa52c9af2e6..b867b14ad1d4 100644
--- a/crypto/openssl/test/ml_kem_evp_extra_test.c
+++ b/crypto/openssl/test/ml_kem_evp_extra_test.c
@@ -140,9 +140,19 @@ static int test_ml_kem(void)
if (!TEST_int_gt(EVP_PKEY_copy_parameters(bkey, akey), 0))
goto err;
+ /* Bob's empty key is not equal to Alice's */
+ if (!TEST_false(EVP_PKEY_eq(akey, bkey))
+ || !TEST_false(EVP_PKEY_eq(bkey, akey)))
+ goto err;
+
if (!TEST_true(EVP_PKEY_set1_encoded_public_key(bkey, rawpub, publen)))
goto err;
+ /* Bob's copy of Alice's public key makes the two equal */
+ if (!TEST_true(EVP_PKEY_eq(akey, bkey))
+ || !TEST_true(EVP_PKEY_eq(bkey, akey)))
+ goto err;
+
/* Encapsulate Bob's key */
ctx = EVP_PKEY_CTX_new_from_pkey(testctx, bkey, NULL);
if (!TEST_ptr(ctx))
diff --git a/crypto/openssl/test/property_test.c b/crypto/openssl/test/property_test.c
index 18f8cc8740e0..e62ff247c42c 100644
--- a/crypto/openssl/test/property_test.c
+++ b/crypto/openssl/test/property_test.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
@@ -687,6 +687,22 @@ static int test_property_list_to_string(int i)
return ret;
}
+static int test_property_list_to_string_bounds(void)
+{
+ OSSL_PROPERTY_LIST *pl = NULL;
+ char buf[16];
+ int ret = 0;
+
+ if (!TEST_ptr(pl = ossl_parse_query(NULL, "provider='$1'", 1)))
+ goto err;
+ if (!TEST_size_t_eq(ossl_property_list_to_string(NULL, pl, buf, 10), 14))
+ goto err;
+ ret = 1;
+ err:
+ ossl_property_free(pl);
+ return ret;
+}
+
int setup_tests(void)
{
ADD_TEST(test_property_string);
@@ -701,5 +717,6 @@ int setup_tests(void)
ADD_TEST(test_query_cache_stochastic);
ADD_TEST(test_fips_mode);
ADD_ALL_TESTS(test_property_list_to_string, OSSL_NELEM(to_string_tests));
+ ADD_TEST(test_property_list_to_string_bounds);
return 1;
}
diff --git a/crypto/openssl/test/provider_pkey_test.c b/crypto/openssl/test/provider_pkey_test.c
index cb656a62a650..9ffe3581d62a 100644
--- a/crypto/openssl/test/provider_pkey_test.c
+++ b/crypto/openssl/test/provider_pkey_test.c
@@ -239,6 +239,77 @@ end:
return ret;
}
+static int test_pkey_can_sign(void)
+{
+ OSSL_PROVIDER *fake_rsa = NULL;
+ EVP_PKEY *pkey_fake = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ OSSL_PARAM *params = NULL;
+ int ret = 0;
+
+ if (!TEST_ptr(fake_rsa = fake_rsa_start(libctx)))
+ return 0;
+
+ /*
+ * Ensure other tests did not forget to reset fake_rsa_query_operation_name
+ * to its default value: 0
+ */
+ if (!TEST_int_eq(fake_rsa_query_operation_name, 0))
+ goto end;
+
+ if (!TEST_ptr(params = fake_rsa_key_params(0))
+ || !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA",
+ "provider=fake-rsa"))
+ || !TEST_true(EVP_PKEY_fromdata_init(ctx))
+ || !TEST_true(EVP_PKEY_fromdata(ctx, &pkey_fake, EVP_PKEY_PUBLIC_KEY,
+ params))
+ || !TEST_true(EVP_PKEY_can_sign(pkey_fake))
+ || !TEST_ptr(pkey_fake))
+ goto end;
+
+ EVP_PKEY_CTX_free(ctx);
+ ctx = NULL;
+ EVP_PKEY_free(pkey_fake);
+ pkey_fake = NULL;
+ OSSL_PARAM_free(params);
+ params = NULL;
+
+ /*
+ * Documented behavior for OSSL_FUNC_keymgmt_query_operation_name()
+ * allows it to return NULL, in which case the fallback should be to use
+ * EVP_KEYMGMT_get0_name(). That is exactly the thing we are testing here.
+ */
+ fake_rsa_query_operation_name = 1;
+
+ if (!TEST_ptr(params = fake_rsa_key_params(0))
+ || !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA",
+ "provider=fake-rsa"))
+ || !TEST_true(EVP_PKEY_fromdata_init(ctx))
+ || !TEST_true(EVP_PKEY_fromdata(ctx, &pkey_fake, EVP_PKEY_PUBLIC_KEY,
+ params))
+ || !TEST_true(EVP_PKEY_can_sign(pkey_fake))
+ || !TEST_ptr(pkey_fake))
+ goto end;
+
+ EVP_PKEY_CTX_free(ctx);
+ ctx = NULL;
+ EVP_PKEY_free(pkey_fake);
+ pkey_fake = NULL;
+ OSSL_PARAM_free(params);
+ params = NULL;
+
+ ret = 1;
+end:
+
+ EVP_PKEY_CTX_free(ctx);
+ EVP_PKEY_free(pkey_fake);
+ OSSL_PARAM_free(params);
+ fake_rsa_query_operation_name = 0;
+
+ fake_rsa_finish(fake_rsa);
+ return ret;
+}
+
static int test_pkey_store(int idx)
{
OSSL_PROVIDER *deflt = NULL;
@@ -719,6 +790,7 @@ int setup_tests(void)
ADD_TEST(test_pkey_sig);
ADD_TEST(test_alternative_keygen_init);
ADD_TEST(test_pkey_eq);
+ ADD_TEST(test_pkey_can_sign);
ADD_ALL_TESTS(test_pkey_store, 2);
ADD_TEST(test_pkey_delete);
ADD_TEST(test_pkey_store_open_ex);
diff --git a/crypto/openssl/test/quicapitest.c b/crypto/openssl/test/quicapitest.c
index f665c511bb72..4e887c13d14c 100644
--- a/crypto/openssl/test/quicapitest.c
+++ b/crypto/openssl/test/quicapitest.c
@@ -428,91 +428,6 @@ static int test_version(void)
}
#if defined(DO_SSL_TRACE_TEST)
-static void strip_line_ends(char *str)
-{
- size_t i;
-
- for (i = strlen(str);
- i > 0 && (str[i - 1] == '\n' || str[i - 1] == '\r');
- i--);
-
- str[i] = '\0';
-}
-
-static int compare_with_file(BIO *membio)
-{
- BIO *file = NULL, *newfile = NULL;
- char buf1[8192], buf2[8192];
- char *reffile;
- int ret = 0;
- size_t i;
-
-#ifdef OPENSSL_NO_ZLIB
- reffile = test_mk_file_path(datadir, "ssltraceref.txt");
-#else
- reffile = test_mk_file_path(datadir, "ssltraceref-zlib.txt");
-#endif
- if (!TEST_ptr(reffile))
- goto err;
-
- file = BIO_new_file(reffile, "rb");
- if (!TEST_ptr(file))
- goto err;
-
- newfile = BIO_new_file("ssltraceref-new.txt", "wb");
- if (!TEST_ptr(newfile))
- goto err;
-
- while (BIO_gets(membio, buf2, sizeof(buf2)) > 0)
- if (BIO_puts(newfile, buf2) <= 0) {
- TEST_error("Failed writing new file data");
- goto err;
- }
-
- if (!TEST_int_ge(BIO_seek(membio, 0), 0))
- goto err;
-
- while (BIO_gets(file, buf1, sizeof(buf1)) > 0) {
- size_t line_len;
-
- if (BIO_gets(membio, buf2, sizeof(buf2)) <= 0) {
- TEST_error("Failed reading mem data");
- goto err;
- }
- strip_line_ends(buf1);
- strip_line_ends(buf2);
- line_len = strlen(buf1);
- if (line_len > 0 && buf1[line_len - 1] == '?') {
- /* Wildcard at the EOL means ignore anything after it */
- if (strlen(buf2) > line_len)
- buf2[line_len] = '\0';
- }
- if (line_len != strlen(buf2)) {
- TEST_error("Actual and ref line data length mismatch");
- TEST_info("%s", buf1);
- TEST_info("%s", buf2);
- goto err;
- }
- for (i = 0; i < line_len; i++) {
- /* '?' is a wild card character in the reference text */
- if (buf1[i] == '?')
- buf2[i] = '?';
- }
- if (!TEST_str_eq(buf1, buf2))
- goto err;
- }
- if (!TEST_true(BIO_eof(file))
- || !TEST_true(BIO_eof(membio)))
- goto err;
-
- ret = 1;
- err:
- OPENSSL_free(reffile);
- BIO_free(file);
- BIO_free(newfile);
- return ret;
-}
-
/*
* Tests that the SSL_trace() msg_callback works as expected with a QUIC
* connection. This also provides testing of the msg_callback at the same time.
@@ -524,6 +439,7 @@ static int test_ssl_trace(void)
QUIC_TSERVER *qtserv = NULL;
int testresult = 0;
BIO *bio = NULL;
+ char *reffile = NULL;
if (!TEST_ptr(cctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_client_method()))
|| !TEST_ptr(bio = BIO_new(BIO_s_mem()))
@@ -547,7 +463,13 @@ static int test_ssl_trace(void)
if (!TEST_int_gt(BIO_pending(bio), 0))
goto err;
} else {
- if (!TEST_true(compare_with_file(bio)))
+
+# ifdef OPENSSL_NO_ZLIB
+ reffile = test_mk_file_path(datadir, "ssltraceref.txt");
+# else
+ reffile = test_mk_file_path(datadir, "ssltraceref-zlib.txt");
+# endif
+ if (!TEST_true(compare_with_reference_file(bio, reffile)))
goto err;
}
@@ -557,6 +479,7 @@ static int test_ssl_trace(void)
SSL_free(clientquic);
SSL_CTX_free(cctx);
BIO_free(bio);
+ OPENSSL_free(reffile);
return testresult;
}
diff --git a/crypto/openssl/test/radix/terp.c b/crypto/openssl/test/radix/terp.c
index 3c83fd9b18b0..41d3bdeb9fd4 100644
--- a/crypto/openssl/test/radix/terp.c
+++ b/crypto/openssl/test/radix/terp.c
@@ -871,8 +871,10 @@ err:
}
GEN_SCRIPT_cleanup(&gen_script);
- BIO_printf(debug_bio, "Stats:\n Ops executed: %16llu\n\n",
- (unsigned long long)terp.ops_executed);
+ if (have_terp) {
+ BIO_printf(debug_bio, "Stats:\n Ops executed: %16llu\n\n",
+ (unsigned long long)terp.ops_executed);
+ }
SCRIPT_INFO_print(script_info, debug_bio, /*error=*/!ok,
ok ? "completed" : "failed, exiting");
return ok;
diff --git a/crypto/openssl/test/recipes/03-test_fipsinstall.t b/crypto/openssl/test/recipes/03-test_fipsinstall.t
index 1f9110ef600a..3dcbe67c6d55 100644
--- a/crypto/openssl/test/recipes/03-test_fipsinstall.t
+++ b/crypto/openssl/test/recipes/03-test_fipsinstall.t
@@ -63,7 +63,7 @@ my @commandline =
( 'x942kdf_key_check', 'x942kdf-key-check' )
);
-plan tests => 40 + (scalar @pedantic_okay) + (scalar @pedantic_fail)
+plan tests => 41 + (scalar @pedantic_okay) + (scalar @pedantic_fail)
+ 4 * (scalar @commandline);
my $infile = bldtop_file('providers', platform->dso('fips'));
@@ -392,6 +392,16 @@ SKIP: {
"fipsinstall fails when the ML-KEM decapsulate implicit failure result is corrupted");
}
+# corrupt an Asymmetric cipher test
+SKIP: {
+ skip "Skipping Asymmetric RSA corruption test because of no rsa in this build", 1
+ if disabled("rsa") || disabled("fips-post");
+ ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile,
+ '-corrupt_desc', 'RSA_Encrypt',
+ '-corrupt_type', 'KAT_AsymmetricCipher'])),
+ "fipsinstall fails when the asymmetric cipher result is corrupted");
+}
+
# 'local' ensures that this change is only done in this file.
local $ENV{OPENSSL_CONF_INCLUDE} = abs2rel(curdir());
diff --git a/crypto/openssl/test/recipes/25-test_verify.t b/crypto/openssl/test/recipes/25-test_verify.t
index 271f499690bf..673c3d5f1772 100644
--- a/crypto/openssl/test/recipes/25-test_verify.t
+++ b/crypto/openssl/test/recipes/25-test_verify.t
@@ -602,9 +602,10 @@ ok(vfy_root("-CAfile", $rootcert), "CAfile");
ok(vfy_root("-CAstore", $rootcert), "CAstore");
ok(vfy_root("-CAstore", $rootcert, "-CAfile", $rootcert), "CAfile and existing CAstore");
ok(!vfy_root("-CAstore", "non-existing", "-CAfile", $rootcert), "CAfile and non-existing CAstore");
+
SKIP: {
- skip "file names with colons aren't supported on Windows and VMS", 2
- if $^O =~ /^(MsWin32|VMS)$/;
+ skip "file names with colons aren't supported on Windows and VMS", 1
+ if $^O =~ /^(MSWin32|VMS)$/;
my $foo_file = "foo:cert.pem";
copy($rootcert, $foo_file);
ok(vfy_root("-CAstore", $foo_file), "CAstore foo:file");
diff --git a/crypto/openssl/test/recipes/30-test_evp_data/evpkdf_krb5.txt b/crypto/openssl/test/recipes/30-test_evp_data/evpkdf_krb5.txt
index d8f6aa72a175..e2de4754fa74 100644
--- a/crypto/openssl/test/recipes/30-test_evp_data/evpkdf_krb5.txt
+++ b/crypto/openssl/test/recipes/30-test_evp_data/evpkdf_krb5.txt
@@ -1,5 +1,5 @@
#
-# Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2001-2025 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
@@ -129,3 +129,11 @@ Ctrl.cipher = cipher:DES-EDE3-CBC
Ctrl.hexkey = hexkey:dce06b1f64c857a11c3db57c51899b2cc1791008ce973b92
Ctrl.hexconstant = hexconstant:0000000155
Output = 935079d14490a75c3093c4a6e8c3b049c71e6ee705
+
+#Erroneous key size for the cipher as XTS has double key size
+KDF = KRB5KDF
+Ctrl.cipher = cipher:AES-256-XTS
+Ctrl.hexkey = hexkey:FE697B52BC0D3CE14432BA036A92E65BBB52280990A2FA27883998D72AF30161
+Ctrl.hexconstant = hexconstant:0000000255
+Output = 97151B4C76945063E2EB0529DC067D97D7BBA90776D8126D91F34F3101AEA8BA
+Result = KDF_DERIVE_ERROR
diff --git a/crypto/openssl/test/recipes/30-test_evp_data/evppkey_rsa_sigalg.txt b/crypto/openssl/test/recipes/30-test_evp_data/evppkey_rsa_sigalg.txt
index 5083cc2bde24..f258700670ab 100644
--- a/crypto/openssl/test/recipes/30-test_evp_data/evppkey_rsa_sigalg.txt
+++ b/crypto/openssl/test/recipes/30-test_evp_data/evppkey_rsa_sigalg.txt
@@ -1,5 +1,5 @@
#
-# Copyright 2001-2024 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2001-2025 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
@@ -186,4 +186,4 @@ Output = 6a7fc08e9999fc9d50cda476e973a01a06efeb52eece1c78cb1422950476cbff67408c6
Availablein = default
Sign-Message = RSA-SM3:RSA-2048
Input = "Hello World"
-Output = 92657e22036214c343d8e95d129c0c47430d5a1ae452371a7847a963f533f96e018aa6658958e6a584cf0d380aa9435175cf2de3dfa60100aca893b76aa6d8f0cc9154ee982cb5ea8f19153fe8a9c801aa2da8bb4451c7ec6fd836e81ecdacf022b68294db068efa47decf3a7c548ea7088a16433029b8733b9573053b7e7122ea10b662726fc97bd149c663617434a9707b672b024f95865d91077edfb79c8ed4c8528032204c46c984a6c82b17794cbf9c4dfe4c1af1d59535f7755540ff36d6a2b55accbf046896c4aae9287a33f38c2a269a02abdac46c17b1b55ee89cc9eb3011a84916596f982c5375dd2110633be6dc43532919466d83bd0f3e406978
+Output = b74e03c18050807541bde949aa0ac91d43fb9730f0b529d5100d5776f4f446d0ca0f0992359dc5f89386ed45bc3bf52cac1f75fbcc088fc2ea77624fd962569d2d317e90886dec424fb6757c4eba1e881ddf4f7942e8003b54e05cc974558dea171ce23a2fc158f71a5621c9a2c3ce45c9af4c706d3f60efe0c0f087a6ec504f771b08e2a1d78e0316c74706c678869bf121d5da00e2e8c8dc1cd273315b4ad8ab9962c62f81cebc5fb393b7f8860ee68545578413feada82b1c2bbfabfa157e298f0354bffc1cc6aa68f058a5d34b6b70ffacd3532c6b2c6a0de059bf605edf392ac8adbf1769555a0a50b2b13c63cae98a461498fae7f0d1729b710f05f39e
diff --git a/crypto/openssl/test/recipes/90-test_sslapi.t b/crypto/openssl/test/recipes/90-test_sslapi.t
index 650e0d1ffb16..70c2c24d8661 100644
--- a/crypto/openssl/test/recipes/90-test_sslapi.t
+++ b/crypto/openssl/test/recipes/90-test_sslapi.t
@@ -1,5 +1,5 @@
#! /usr/bin/env perl
-# Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2016-2025 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
@@ -45,7 +45,10 @@ ok(run(test(["sslapitest", srctop_dir("test", "certs"),
srctop_file("test",
"recipes",
"90-test_sslapi_data",
- "dhparams.pem")])),
+ "dhparams.pem"),
+ srctop_dir("test",
+ "recipes",
+ "90-test_sslapi_data")])),
"running sslapitest");
SKIP: {
@@ -62,7 +65,10 @@ SKIP: {
srctop_file("test",
"recipes",
"90-test_sslapi_data",
- "dhparams.pem")])),
+ "dhparams.pem"),
+ srctop_dir("test",
+ "recipes",
+ "90-test_sslapi_data")])),
"running sslapitest with default fips config");
run(test(["fips_version_test", "-config", $provconf, ">=3.1.0"]),
@@ -140,7 +146,10 @@ SKIP: {
srctop_file("test",
"recipes",
"90-test_sslapi_data",
- "dhparams.pem")])),
+ "dhparams.pem"),
+ srctop_dir("test",
+ "recipes",
+ "90-test_sslapi_data")])),
"running sslapitest with modified fips config");
}
diff --git a/crypto/openssl/test/recipes/90-test_sslapi_data/ssltraceref-zlib.txt b/crypto/openssl/test/recipes/90-test_sslapi_data/ssltraceref-zlib.txt
new file mode 100644
index 000000000000..05aed8299b0e
--- /dev/null
+++ b/crypto/openssl/test/recipes/90-test_sslapi_data/ssltraceref-zlib.txt
@@ -0,0 +1,255 @@
+Sent TLS Record
+Header:
+ Version = TLS 1.0 (0x301)
+ Content Type = Handshake (22)
+ Length = ?
+ ClientHello, Length=?
+ client_version=0x303 (TLS 1.2)
+ Random:
+ gmt_unix_time=0x?
+ random_bytes (len=28): ?
+ session_id (len=?
+ cipher_suites (len=2)
+ {0x13, 0x01} TLS_AES_128_GCM_SHA256
+ compression_methods (len=1)
+ No Compression (0x00)
+ extensions, length = ?
+ extension_type=ec_point_formats(11), length=4
+ uncompressed (0)
+ ansiX962_compressed_prime (1)
+ ansiX962_compressed_char2 (2)
+ extension_type=supported_groups(10), length=20
+ MLKEM512 (512)
+ MLKEM768 (513)
+ MLKEM1024 (514)
+ X25519MLKEM768 (4588)
+ SecP256r1MLKEM768 (4587)
+ SecP384r1MLKEM1024 (4589)
+ secp521r1 (P-521) (25)
+ secp384r1 (P-384) (24)
+ secp256r1 (P-256) (23)
+ extension_type=session_ticket(35), length=0
+ extension_type=encrypt_then_mac(22), length=0
+ extension_type=extended_master_secret(23), length=0
+ extension_type=signature_algorithms(13), length=?
+ mldsa65 (0x0905)
+ mldsa87 (0x0906)
+ mldsa44 (0x0904)
+ ecdsa_secp256r1_sha256 (0x0403)
+ ecdsa_secp384r1_sha384 (0x0503)
+ ecdsa_secp521r1_sha512 (0x0603)
+ ed25519 (0x0807)
+ ed448 (0x0808)
+ ecdsa_brainpoolP256r1tls13_sha256 (0x081a)
+ ecdsa_brainpoolP384r1tls13_sha384 (0x081b)
+ ecdsa_brainpoolP512r1tls13_sha512 (0x081c)
+ rsa_pss_pss_sha256 (0x0809)
+ rsa_pss_pss_sha384 (0x080a)
+ rsa_pss_pss_sha512 (0x080b)
+ rsa_pss_rsae_sha256 (0x0804)
+ rsa_pss_rsae_sha384 (0x0805)
+ rsa_pss_rsae_sha512 (0x0806)
+ rsa_pkcs1_sha256 (0x0401)
+ rsa_pkcs1_sha384 (0x0501)
+ rsa_pkcs1_sha512 (0x0601)
+ extension_type=supported_versions(43), length=3
+ TLS 1.3 (772)
+ extension_type=psk_key_exchange_modes(45), length=2
+ psk_dhe_ke (1)
+ extension_type=key_share(51), length=806
+ NamedGroup: MLKEM512 (512)
+ key_exchange: (len=800): ?
+ extension_type=compress_certificate(27), length=3
+ zlib (1)
+
+Received TLS Record
+Header:
+ Version = TLS 1.2 (0x303)
+ Content Type = Handshake (22)
+ Length = 858
+ ServerHello, Length=854
+ server_version=0x303 (TLS 1.2)
+ Random:
+ gmt_unix_time=0x?
+ random_bytes (len=28): ?
+ session_id (len=?
+ cipher_suite {0x13, 0x01} TLS_AES_128_GCM_SHA256
+ compression_method: No Compression (0x00)
+ extensions, length = ?
+ extension_type=supported_versions(43), length=2
+ TLS 1.3 (772)
+ extension_type=key_share(51), length=772
+ NamedGroup: MLKEM512 (512)
+ key_exchange: (len=768): ?
+
+Received TLS Record
+Header:
+ Version = TLS 1.2 (0x303)
+ Content Type = ChangeCipherSpec (20)
+ Length = 1
+ change_cipher_spec (1)
+
+Received TLS Record
+Header:
+ Version = TLS 1.2 (0x303)
+ Content Type = ApplicationData (23)
+ Length = 23
+ Inner Content Type = Handshake (22)
+ EncryptedExtensions, Length=2
+ No extensions
+
+Received TLS Record
+Header:
+ Version = TLS 1.2 (0x303)
+ Content Type = ApplicationData (23)
+ Length = 839
+ Inner Content Type = Handshake (22)
+ Certificate, Length=818
+ context (len=0):
+ certificate_list, length=814
+ ASN.1Cert, length=809
+------details-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2 (0x2)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN = Root CA
+ Validity
+ Not Before: Jan 14 22:29:46 2016 GMT
+ Not After : Jan 15 22:29:46 2116 GMT
+ Subject: CN = server.example
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:d5:5d:60:6a:df:fc:61:ee:48:aa:8c:11:48:43:
+ a5:6d:b6:52:5d:aa:98:49:b1:61:92:35:b1:fc:3a:
+ 04:25:0c:6d:79:ff:b4:d5:c9:e9:5c:1c:3b:e0:ab:
+ b3:b8:7d:a3:de:6d:bd:e0:dd:d7:5a:bf:14:47:11:
+ 42:5e:a6:82:d0:61:c1:7f:dd:13:46:e6:09:85:07:
+ 0e:f2:d4:fc:1a:64:d2:0a:ad:20:ab:20:6b:96:f0:
+ ad:cc:c4:19:53:55:dc:01:1d:a4:b3:ef:8a:b4:49:
+ 53:5d:8a:05:1c:f1:dc:e1:44:bf:c5:d7:e2:77:19:
+ 57:5c:97:0b:75:ee:88:43:71:0f:ca:6c:c1:b4:b2:
+ 50:a7:77:46:6c:58:0f:11:bf:f1:76:24:5a:ae:39:
+ 42:b7:51:67:29:e1:d0:55:30:6f:17:e4:91:ea:ad:
+ f8:28:c2:43:6f:a2:64:a9:fb:9d:98:92:62:48:3e:
+ eb:0d:4f:82:4a:8a:ff:3f:72:ee:96:b5:ae:a1:c1:
+ 98:ba:ef:7d:90:75:6d:ff:5a:52:9e:ab:f5:c0:7e:
+ d0:87:43:db:85:07:07:0f:7d:38:7a:fd:d1:d3:ee:
+ 65:1d:d3:ea:39:6a:87:37:ee:4a:d3:e0:0d:6e:f5:
+ 70:ac:c2:bd:f1:6e:f3:92:95:5e:a9:f0:a1:65:95:
+ 93:8d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ C0:E7:84:BF:E8:59:27:33:10:B0:52:4F:51:52:2F:06:D6:C0:7A:CD
+ X509v3 Authority Key Identifier:
+ 70:7F:2E:AE:83:68:59:98:04:23:2A:CD:EB:3E:17:CD:24:DD:01:49
+ X509v3 Basic Constraints:
+ CA:FALSE
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication
+ X509v3 Subject Alternative Name:
+ DNS:server.example
+ Signature Algorithm: sha256WithRSAEncryption
+ Signature Value:
+ 7b:d3:04:43:75:8a:0f:11:ae:c4:fb:d7:a1:a2:9e:fe:20:18:
+ d5:f4:2f:31:88:46:b6:75:8c:ee:e5:9b:97:a6:b9:a3:cd:60:
+ 9a:46:c3:48:97:e5:97:68:f7:5a:86:35:73:d9:69:9e:f9:5f:
+ 74:b9:e6:94:13:01:cb:6a:dc:e3:c4:04:e9:65:da:9c:a4:8b:
+ 28:f3:f9:9a:7f:bf:97:1f:45:92:e5:05:b1:56:e6:0b:f6:47:
+ de:1e:89:b6:2b:e1:4d:df:4a:7e:01:d3:23:dc:97:8c:47:fe:
+ 5f:c7:cc:98:46:0e:c4:83:5b:ca:8a:f1:52:09:be:6b:ec:3f:
+ 09:8b:d0:93:02:bf:e1:51:e7:d1:7e:34:56:19:74:d0:ff:28:
+ 25:de:b7:9f:56:52:91:7d:20:29:85:0a:80:44:5f:71:32:25:
+ 71:0f:c2:16:e2:5f:6b:1d:3f:32:5b:0a:3c:74:1c:b9:62:f1:
+ ed:07:50:a3:6d:b4:b4:31:0a:c0:53:44:6a:3a:88:84:8b:2d:
+ a9:b0:37:8e:e6:18:36:bd:9a:20:40:0f:01:92:8b:3d:aa:61:
+ e7:ae:2c:ed:36:cd:3a:07:86:74:3a:29:b3:d7:3a:b4:00:a9:
+ c2:f5:92:78:0e:e2:0f:a3:fe:bb:be:e0:06:53:84:59:1d:90:
+ 69:e5:b6:f9
+-----BEGIN CERTIFICATE-----
+MIIDJTCCAg2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290
+IENBMCAXDTE2MDExNDIyMjk0NloYDzIxMTYwMTE1MjIyOTQ2WjAZMRcwFQYDVQQD
+DA5zZXJ2ZXIuZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ANVdYGrf/GHuSKqMEUhDpW22Ul2qmEmxYZI1sfw6BCUMbXn/tNXJ6VwcO+Crs7h9
+o95tveDd11q/FEcRQl6mgtBhwX/dE0bmCYUHDvLU/Bpk0gqtIKsga5bwrczEGVNV
+3AEdpLPvirRJU12KBRzx3OFEv8XX4ncZV1yXC3XuiENxD8pswbSyUKd3RmxYDxG/
+8XYkWq45QrdRZynh0FUwbxfkkeqt+CjCQ2+iZKn7nZiSYkg+6w1PgkqK/z9y7pa1
+rqHBmLrvfZB1bf9aUp6r9cB+0IdD24UHBw99OHr90dPuZR3T6jlqhzfuStPgDW71
+cKzCvfFu85KVXqnwoWWVk40CAwEAAaN9MHswHQYDVR0OBBYEFMDnhL/oWSczELBS
+T1FSLwbWwHrNMB8GA1UdIwQYMBaAFHB/Lq6DaFmYBCMqzes+F80k3QFJMAkGA1Ud
+EwQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwGQYDVR0RBBIwEIIOc2VydmVyLmV4
+YW1wbGUwDQYJKoZIhvcNAQELBQADggEBAHvTBEN1ig8RrsT716Ginv4gGNX0LzGI
+RrZ1jO7lm5emuaPNYJpGw0iX5Zdo91qGNXPZaZ75X3S55pQTActq3OPEBOll2pyk
+iyjz+Zp/v5cfRZLlBbFW5gv2R94eibYr4U3fSn4B0yPcl4xH/l/HzJhGDsSDW8qK
+8VIJvmvsPwmL0JMCv+FR59F+NFYZdND/KCXet59WUpF9ICmFCoBEX3EyJXEPwhbi
+X2sdPzJbCjx0HLli8e0HUKNttLQxCsBTRGo6iISLLamwN47mGDa9miBADwGSiz2q
+YeeuLO02zToHhnQ6KbPXOrQAqcL1kngO4g+j/ru+4AZThFkdkGnltvk=
+-----END CERTIFICATE-----
+------------------
+ No extensions
+
+Received TLS Record
+Header:
+ Version = TLS 1.2 (0x303)
+ Content Type = ApplicationData (23)
+ Length = 281
+ Inner Content Type = Handshake (22)
+ CertificateVerify, Length=260
+ Signature Algorithm: rsa_pss_rsae_sha256 (0x0804)
+ Signature (len=256): ?
+
+Received TLS Record
+Header:
+ Version = TLS 1.2 (0x303)
+ Content Type = ApplicationData (23)
+ Length = 53
+ Inner Content Type = Handshake (22)
+ Finished, Length=32
+ verify_data (len=32): ?
+
+Sent TLS Record
+Header:
+ Version = TLS 1.2 (0x303)
+ Content Type = ChangeCipherSpec (20)
+ Length = 1
+ change_cipher_spec (1)
+
+Sent TLS Record
+Header:
+ Version = TLS 1.2 (0x303)
+ Content Type = ApplicationData (23)
+ Length = 53
+ Inner Content Type = Handshake (22)
+ Finished, Length=32
+ verify_data (len=32): ?
+
+Received TLS Record
+Header:
+ Version = TLS 1.2 (0x303)
+ Content Type = ApplicationData (23)
+ Length = 234
+ Inner Content Type = Handshake (22)
+ NewSessionTicket, Length=213
+ ticket_lifetime_hint=7200
+ ticket_age_add=?
+ ticket_nonce (len=8): ?
+ ticket (len=192): ?
+ No extensions
+
+Received TLS Record
+Header:
+ Version = TLS 1.2 (0x303)
+ Content Type = ApplicationData (23)
+ Length = 234
+ Inner Content Type = Handshake (22)
+ NewSessionTicket, Length=213
+ ticket_lifetime_hint=7200
+ ticket_age_add=?
+ ticket_nonce (len=8): ?
+ ticket (len=192): ?
+ No extensions
+
diff --git a/crypto/openssl/test/recipes/90-test_sslapi_data/ssltraceref.txt b/crypto/openssl/test/recipes/90-test_sslapi_data/ssltraceref.txt
new file mode 100644
index 000000000000..5d332da235fb
--- /dev/null
+++ b/crypto/openssl/test/recipes/90-test_sslapi_data/ssltraceref.txt
@@ -0,0 +1,253 @@
+Sent TLS Record
+Header:
+ Version = TLS 1.0 (0x301)
+ Content Type = Handshake (22)
+ Length = ?
+ ClientHello, Length=?
+ client_version=0x303 (TLS 1.2)
+ Random:
+ gmt_unix_time=0x?
+ random_bytes (len=28): ?
+ session_id (len=?
+ cipher_suites (len=2)
+ {0x13, 0x01} TLS_AES_128_GCM_SHA256
+ compression_methods (len=1)
+ No Compression (0x00)
+ extensions, length = ?
+ extension_type=ec_point_formats(11), length=4
+ uncompressed (0)
+ ansiX962_compressed_prime (1)
+ ansiX962_compressed_char2 (2)
+ extension_type=supported_groups(10), length=20
+ MLKEM512 (512)
+ MLKEM768 (513)
+ MLKEM1024 (514)
+ X25519MLKEM768 (4588)
+ SecP256r1MLKEM768 (4587)
+ SecP384r1MLKEM1024 (4589)
+ secp521r1 (P-521) (25)
+ secp384r1 (P-384) (24)
+ secp256r1 (P-256) (23)
+ extension_type=session_ticket(35), length=0
+ extension_type=encrypt_then_mac(22), length=0
+ extension_type=extended_master_secret(23), length=0
+ extension_type=signature_algorithms(13), length=?
+ mldsa65 (0x0905)
+ mldsa87 (0x0906)
+ mldsa44 (0x0904)
+ ecdsa_secp256r1_sha256 (0x0403)
+ ecdsa_secp384r1_sha384 (0x0503)
+ ecdsa_secp521r1_sha512 (0x0603)
+ ed25519 (0x0807)
+ ed448 (0x0808)
+ ecdsa_brainpoolP256r1tls13_sha256 (0x081a)
+ ecdsa_brainpoolP384r1tls13_sha384 (0x081b)
+ ecdsa_brainpoolP512r1tls13_sha512 (0x081c)
+ rsa_pss_pss_sha256 (0x0809)
+ rsa_pss_pss_sha384 (0x080a)
+ rsa_pss_pss_sha512 (0x080b)
+ rsa_pss_rsae_sha256 (0x0804)
+ rsa_pss_rsae_sha384 (0x0805)
+ rsa_pss_rsae_sha512 (0x0806)
+ rsa_pkcs1_sha256 (0x0401)
+ rsa_pkcs1_sha384 (0x0501)
+ rsa_pkcs1_sha512 (0x0601)
+ extension_type=supported_versions(43), length=3
+ TLS 1.3 (772)
+ extension_type=psk_key_exchange_modes(45), length=2
+ psk_dhe_ke (1)
+ extension_type=key_share(51), length=806
+ NamedGroup: MLKEM512 (512)
+ key_exchange: (len=800): ?
+
+Received TLS Record
+Header:
+ Version = TLS 1.2 (0x303)
+ Content Type = Handshake (22)
+ Length = 858
+ ServerHello, Length=854
+ server_version=0x303 (TLS 1.2)
+ Random:
+ gmt_unix_time=0x?
+ random_bytes (len=28): ?
+ session_id (len=?
+ cipher_suite {0x13, 0x01} TLS_AES_128_GCM_SHA256
+ compression_method: No Compression (0x00)
+ extensions, length = ?
+ extension_type=supported_versions(43), length=2
+ TLS 1.3 (772)
+ extension_type=key_share(51), length=772
+ NamedGroup: MLKEM512 (512)
+ key_exchange: (len=768): ?
+
+Received TLS Record
+Header:
+ Version = TLS 1.2 (0x303)
+ Content Type = ChangeCipherSpec (20)
+ Length = 1
+ change_cipher_spec (1)
+
+Received TLS Record
+Header:
+ Version = TLS 1.2 (0x303)
+ Content Type = ApplicationData (23)
+ Length = 23
+ Inner Content Type = Handshake (22)
+ EncryptedExtensions, Length=2
+ No extensions
+
+Received TLS Record
+Header:
+ Version = TLS 1.2 (0x303)
+ Content Type = ApplicationData (23)
+ Length = 839
+ Inner Content Type = Handshake (22)
+ Certificate, Length=818
+ context (len=0):
+ certificate_list, length=814
+ ASN.1Cert, length=809
+------details-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2 (0x2)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN = Root CA
+ Validity
+ Not Before: Jan 14 22:29:46 2016 GMT
+ Not After : Jan 15 22:29:46 2116 GMT
+ Subject: CN = server.example
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:d5:5d:60:6a:df:fc:61:ee:48:aa:8c:11:48:43:
+ a5:6d:b6:52:5d:aa:98:49:b1:61:92:35:b1:fc:3a:
+ 04:25:0c:6d:79:ff:b4:d5:c9:e9:5c:1c:3b:e0:ab:
+ b3:b8:7d:a3:de:6d:bd:e0:dd:d7:5a:bf:14:47:11:
+ 42:5e:a6:82:d0:61:c1:7f:dd:13:46:e6:09:85:07:
+ 0e:f2:d4:fc:1a:64:d2:0a:ad:20:ab:20:6b:96:f0:
+ ad:cc:c4:19:53:55:dc:01:1d:a4:b3:ef:8a:b4:49:
+ 53:5d:8a:05:1c:f1:dc:e1:44:bf:c5:d7:e2:77:19:
+ 57:5c:97:0b:75:ee:88:43:71:0f:ca:6c:c1:b4:b2:
+ 50:a7:77:46:6c:58:0f:11:bf:f1:76:24:5a:ae:39:
+ 42:b7:51:67:29:e1:d0:55:30:6f:17:e4:91:ea:ad:
+ f8:28:c2:43:6f:a2:64:a9:fb:9d:98:92:62:48:3e:
+ eb:0d:4f:82:4a:8a:ff:3f:72:ee:96:b5:ae:a1:c1:
+ 98:ba:ef:7d:90:75:6d:ff:5a:52:9e:ab:f5:c0:7e:
+ d0:87:43:db:85:07:07:0f:7d:38:7a:fd:d1:d3:ee:
+ 65:1d:d3:ea:39:6a:87:37:ee:4a:d3:e0:0d:6e:f5:
+ 70:ac:c2:bd:f1:6e:f3:92:95:5e:a9:f0:a1:65:95:
+ 93:8d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ C0:E7:84:BF:E8:59:27:33:10:B0:52:4F:51:52:2F:06:D6:C0:7A:CD
+ X509v3 Authority Key Identifier:
+ 70:7F:2E:AE:83:68:59:98:04:23:2A:CD:EB:3E:17:CD:24:DD:01:49
+ X509v3 Basic Constraints:
+ CA:FALSE
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication
+ X509v3 Subject Alternative Name:
+ DNS:server.example
+ Signature Algorithm: sha256WithRSAEncryption
+ Signature Value:
+ 7b:d3:04:43:75:8a:0f:11:ae:c4:fb:d7:a1:a2:9e:fe:20:18:
+ d5:f4:2f:31:88:46:b6:75:8c:ee:e5:9b:97:a6:b9:a3:cd:60:
+ 9a:46:c3:48:97:e5:97:68:f7:5a:86:35:73:d9:69:9e:f9:5f:
+ 74:b9:e6:94:13:01:cb:6a:dc:e3:c4:04:e9:65:da:9c:a4:8b:
+ 28:f3:f9:9a:7f:bf:97:1f:45:92:e5:05:b1:56:e6:0b:f6:47:
+ de:1e:89:b6:2b:e1:4d:df:4a:7e:01:d3:23:dc:97:8c:47:fe:
+ 5f:c7:cc:98:46:0e:c4:83:5b:ca:8a:f1:52:09:be:6b:ec:3f:
+ 09:8b:d0:93:02:bf:e1:51:e7:d1:7e:34:56:19:74:d0:ff:28:
+ 25:de:b7:9f:56:52:91:7d:20:29:85:0a:80:44:5f:71:32:25:
+ 71:0f:c2:16:e2:5f:6b:1d:3f:32:5b:0a:3c:74:1c:b9:62:f1:
+ ed:07:50:a3:6d:b4:b4:31:0a:c0:53:44:6a:3a:88:84:8b:2d:
+ a9:b0:37:8e:e6:18:36:bd:9a:20:40:0f:01:92:8b:3d:aa:61:
+ e7:ae:2c:ed:36:cd:3a:07:86:74:3a:29:b3:d7:3a:b4:00:a9:
+ c2:f5:92:78:0e:e2:0f:a3:fe:bb:be:e0:06:53:84:59:1d:90:
+ 69:e5:b6:f9
+-----BEGIN CERTIFICATE-----
+MIIDJTCCAg2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290
+IENBMCAXDTE2MDExNDIyMjk0NloYDzIxMTYwMTE1MjIyOTQ2WjAZMRcwFQYDVQQD
+DA5zZXJ2ZXIuZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ANVdYGrf/GHuSKqMEUhDpW22Ul2qmEmxYZI1sfw6BCUMbXn/tNXJ6VwcO+Crs7h9
+o95tveDd11q/FEcRQl6mgtBhwX/dE0bmCYUHDvLU/Bpk0gqtIKsga5bwrczEGVNV
+3AEdpLPvirRJU12KBRzx3OFEv8XX4ncZV1yXC3XuiENxD8pswbSyUKd3RmxYDxG/
+8XYkWq45QrdRZynh0FUwbxfkkeqt+CjCQ2+iZKn7nZiSYkg+6w1PgkqK/z9y7pa1
+rqHBmLrvfZB1bf9aUp6r9cB+0IdD24UHBw99OHr90dPuZR3T6jlqhzfuStPgDW71
+cKzCvfFu85KVXqnwoWWVk40CAwEAAaN9MHswHQYDVR0OBBYEFMDnhL/oWSczELBS
+T1FSLwbWwHrNMB8GA1UdIwQYMBaAFHB/Lq6DaFmYBCMqzes+F80k3QFJMAkGA1Ud
+EwQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwGQYDVR0RBBIwEIIOc2VydmVyLmV4
+YW1wbGUwDQYJKoZIhvcNAQELBQADggEBAHvTBEN1ig8RrsT716Ginv4gGNX0LzGI
+RrZ1jO7lm5emuaPNYJpGw0iX5Zdo91qGNXPZaZ75X3S55pQTActq3OPEBOll2pyk
+iyjz+Zp/v5cfRZLlBbFW5gv2R94eibYr4U3fSn4B0yPcl4xH/l/HzJhGDsSDW8qK
+8VIJvmvsPwmL0JMCv+FR59F+NFYZdND/KCXet59WUpF9ICmFCoBEX3EyJXEPwhbi
+X2sdPzJbCjx0HLli8e0HUKNttLQxCsBTRGo6iISLLamwN47mGDa9miBADwGSiz2q
+YeeuLO02zToHhnQ6KbPXOrQAqcL1kngO4g+j/ru+4AZThFkdkGnltvk=
+-----END CERTIFICATE-----
+------------------
+ No extensions
+
+Received TLS Record
+Header:
+ Version = TLS 1.2 (0x303)
+ Content Type = ApplicationData (23)
+ Length = 281
+ Inner Content Type = Handshake (22)
+ CertificateVerify, Length=260
+ Signature Algorithm: rsa_pss_rsae_sha256 (0x0804)
+ Signature (len=256): ?
+
+Received TLS Record
+Header:
+ Version = TLS 1.2 (0x303)
+ Content Type = ApplicationData (23)
+ Length = 53
+ Inner Content Type = Handshake (22)
+ Finished, Length=32
+ verify_data (len=32): ?
+
+Sent TLS Record
+Header:
+ Version = TLS 1.2 (0x303)
+ Content Type = ChangeCipherSpec (20)
+ Length = 1
+ change_cipher_spec (1)
+
+Sent TLS Record
+Header:
+ Version = TLS 1.2 (0x303)
+ Content Type = ApplicationData (23)
+ Length = 53
+ Inner Content Type = Handshake (22)
+ Finished, Length=32
+ verify_data (len=32): ?
+
+Received TLS Record
+Header:
+ Version = TLS 1.2 (0x303)
+ Content Type = ApplicationData (23)
+ Length = 234
+ Inner Content Type = Handshake (22)
+ NewSessionTicket, Length=213
+ ticket_lifetime_hint=7200
+ ticket_age_add=?
+ ticket_nonce (len=8): ?
+ ticket (len=192): ?
+ No extensions
+
+Received TLS Record
+Header:
+ Version = TLS 1.2 (0x303)
+ Content Type = ApplicationData (23)
+ Length = 234
+ Inner Content Type = Handshake (22)
+ NewSessionTicket, Length=213
+ ticket_lifetime_hint=7200
+ ticket_age_add=?
+ ticket_nonce (len=8): ?
+ ticket (len=192): ?
+ No extensions
+
diff --git a/crypto/openssl/test/sslapitest.c b/crypto/openssl/test/sslapitest.c
index b83dd6c552de..fbe284b9ff1e 100644
--- a/crypto/openssl/test/sslapitest.c
+++ b/crypto/openssl/test/sslapitest.c
@@ -98,6 +98,7 @@ static char *privkey8192 = NULL;
static char *srpvfile = NULL;
static char *tmpfilename = NULL;
static char *dhfile = NULL;
+static char *datadir = NULL;
static int is_fips = 0;
static int fips_ems_check = 0;
@@ -120,6 +121,15 @@ static X509 *ocspcert = NULL;
#define CLIENT_VERSION_LEN 2
+/* The ssltrace test assumes some options are switched on/off */
+#if !defined(OPENSSL_NO_SSL_TRACE) \
+ && defined(OPENSSL_NO_BROTLI) && defined(OPENSSL_NO_ZSTD) \
+ && !defined(OPENSSL_NO_ECX) && !defined(OPENSSL_NO_DH) \
+ && !defined(OPENSSL_NO_ML_DSA) && !defined(OPENSSL_NO_ML_KEM) \
+ && !defined(OPENSSL_NO_TLS1_3)
+# define DO_SSL_TRACE_TEST
+#endif
+
/*
* This structure is used to validate that the correct number of log messages
* of various types are emitted when emitting secret logs.
@@ -13269,6 +13279,77 @@ static int test_no_renegotiation(int idx)
return testresult;
}
+#if defined(DO_SSL_TRACE_TEST)
+/*
+ * Tests that the SSL_trace() msg_callback works as expected with a PQ Groups.
+ */
+static int test_ssl_trace(void)
+{
+ SSL_CTX *sctx = NULL, *cctx = NULL;
+ SSL *serverssl = NULL, *clientssl = NULL;
+ int testresult = 0;
+ BIO *bio = NULL;
+ char *reffile = NULL;
+ char *grouplist = "MLKEM512:MLKEM768:MLKEM1024:X25519MLKEM768:SecP256r1MLKEM768"
+ ":SecP384r1MLKEM1024:secp521r1:secp384r1:secp256r1";
+
+ if (!fips_provider_version_ge(libctx, 3, 5, 0))
+ return TEST_skip("FIPS provider does not support MLKEM algorithms");
+
+ if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
+ TLS_client_method(),
+ TLS1_3_VERSION, TLS1_3_VERSION,
+ &sctx, &cctx, cert, privkey))
+ || !TEST_ptr(bio = BIO_new(BIO_s_mem()))
+ || !TEST_true(SSL_CTX_set1_groups_list(sctx, grouplist))
+ || !TEST_true(SSL_CTX_set1_groups_list(cctx, grouplist))
+ || !TEST_true(SSL_CTX_set_ciphersuites(cctx,
+ "TLS_AES_128_GCM_SHA256"))
+ || !TEST_true(SSL_CTX_set_ciphersuites(sctx,
+ "TLS_AES_128_GCM_SHA256"))
+# ifdef SSL_OP_LEGACY_EC_POINT_FORMATS
+ || !TEST_true(SSL_CTX_set_options(cctx, SSL_OP_LEGACY_EC_POINT_FORMATS))
+ || !TEST_true(SSL_CTX_set_options(sctx, SSL_OP_LEGACY_EC_POINT_FORMATS))
+# endif
+ || !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
+ NULL, NULL)))
+ goto err;
+
+ SSL_set_msg_callback(clientssl, SSL_trace);
+ SSL_set_msg_callback_arg(clientssl, bio);
+
+ if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
+ goto err;
+
+ /* Skip the comparison of the trace when the fips provider is used. */
+ if (is_fips) {
+ /* Check whether there was something written. */
+ if (!TEST_int_gt(BIO_pending(bio), 0))
+ goto err;
+ } else {
+
+# ifdef OPENSSL_NO_ZLIB
+ reffile = test_mk_file_path(datadir, "ssltraceref.txt");
+# else
+ reffile = test_mk_file_path(datadir, "ssltraceref-zlib.txt");
+# endif
+ if (!TEST_true(compare_with_reference_file(bio, reffile)))
+ goto err;
+ }
+
+ testresult = 1;
+ err:
+ BIO_free(bio);
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ SSL_CTX_free(sctx);
+ SSL_CTX_free(cctx);
+ OPENSSL_free(reffile);
+
+ return testresult;
+}
+#endif
+
OPT_TEST_DECLARE_USAGE("certfile privkeyfile srpvfile tmpfile provider config dhfile\n")
int setup_tests(void)
@@ -13303,6 +13384,8 @@ int setup_tests(void)
|| !TEST_ptr(dhfile = test_get_argument(5)))
return 0;
+ datadir = test_get_argument(6);
+
if (!TEST_true(OSSL_LIB_CTX_load_config(libctx, configfile)))
return 0;
@@ -13598,6 +13681,10 @@ int setup_tests(void)
ADD_TEST(test_quic_tls_early_data);
#endif
ADD_ALL_TESTS(test_no_renegotiation, 2);
+#if defined(DO_SSL_TRACE_TEST)
+ if (datadir != NULL)
+ ADD_TEST(test_ssl_trace);
+#endif
return 1;
err:
diff --git a/crypto/openssl/test/testutil.h b/crypto/openssl/test/testutil.h
index f02dcdfba6f9..a262d9371955 100644
--- a/crypto/openssl/test/testutil.h
+++ b/crypto/openssl/test/testutil.h
@@ -652,4 +652,6 @@ 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);
+
+int compare_with_reference_file(BIO *membio, const char *reffile);
#endif /* OSSL_TESTUTIL_H */
diff --git a/crypto/openssl/test/testutil/compare.c b/crypto/openssl/test/testutil/compare.c
new file mode 100644
index 000000000000..067fb878b58e
--- /dev/null
+++ b/crypto/openssl/test/testutil/compare.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2017-2025 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 "../testutil.h"
+
+static void strip_line_ends(char *str)
+{
+ size_t i;
+
+ for (i = strlen(str);
+ i > 0 && (str[i - 1] == '\n' || str[i - 1] == '\r');
+ i--);
+
+ str[i] = '\0';
+}
+
+int compare_with_reference_file(BIO *membio, const char *reffile)
+{
+ BIO *file = NULL, *newfile = NULL;
+ char buf1[8192], buf2[8192];
+ int ret = 0;
+ size_t i;
+
+ if (!TEST_ptr(reffile))
+ goto err;
+
+ file = BIO_new_file(reffile, "rb");
+ if (!TEST_ptr(file))
+ goto err;
+
+ newfile = BIO_new_file("ssltraceref-new.txt", "wb");
+ if (!TEST_ptr(newfile))
+ goto err;
+
+ while (BIO_gets(membio, buf2, sizeof(buf2)) > 0)
+ if (BIO_puts(newfile, buf2) <= 0) {
+ TEST_error("Failed writing new file data");
+ goto err;
+ }
+
+ if (!TEST_int_ge(BIO_seek(membio, 0), 0))
+ goto err;
+
+ while (BIO_gets(file, buf1, sizeof(buf1)) > 0) {
+ size_t line_len;
+
+ if (BIO_gets(membio, buf2, sizeof(buf2)) <= 0) {
+ TEST_error("Failed reading mem data");
+ goto err;
+ }
+ strip_line_ends(buf1);
+ strip_line_ends(buf2);
+ line_len = strlen(buf1);
+ if (line_len > 0 && buf1[line_len - 1] == '?') {
+ /* Wildcard at the EOL means ignore anything after it */
+ if (strlen(buf2) > line_len)
+ buf2[line_len] = '\0';
+ }
+ if (line_len != strlen(buf2)) {
+ TEST_error("Actual and ref line data length mismatch");
+ TEST_info("%s", buf1);
+ TEST_info("%s", buf2);
+ goto err;
+ }
+ for (i = 0; i < line_len; i++) {
+ /* '?' is a wild card character in the reference text */
+ if (buf1[i] == '?')
+ buf2[i] = '?';
+ }
+ if (!TEST_str_eq(buf1, buf2))
+ goto err;
+ }
+ if (!TEST_true(BIO_eof(file))
+ || !TEST_true(BIO_eof(membio)))
+ goto err;
+
+ ret = 1;
+ err:
+ BIO_free(file);
+ BIO_free(newfile);
+ return ret;
+}
diff --git a/crypto/openssl/test/threadstest.c b/crypto/openssl/test/threadstest.c
index 38401911d87f..d33ad46999c6 100644
--- a/crypto/openssl/test/threadstest.c
+++ b/crypto/openssl/test/threadstest.c
@@ -183,13 +183,16 @@ static void rwreader_fn(int *iterations)
CRYPTO_atomic_add(&rwwriter2_done, 0, &lw2, atomiclock);
count++;
- if (rwwriter_ptr != NULL && old > *rwwriter_ptr) {
- TEST_info("rwwriter pointer went backwards\n");
- rw_torture_result = 0;
+ if (rwwriter_ptr != NULL) {
+ if (old > *rwwriter_ptr) {
+ TEST_info("rwwriter pointer went backwards! %d : %d\n",
+ old, *rwwriter_ptr);
+ rw_torture_result = 0;
+ }
+ old = *rwwriter_ptr;
}
if (CRYPTO_THREAD_unlock(rwtorturelock) == 0)
abort();
- *iterations = count;
if (rw_torture_result == 0) {
*iterations = count;
return;
diff --git a/crypto/openssl/test/wpackettest.c b/crypto/openssl/test/wpackettest.c
index bd696e007407..c6d6faf5c485 100644
--- a/crypto/openssl/test/wpackettest.c
+++ b/crypto/openssl/test/wpackettest.c
@@ -588,7 +588,7 @@ static int test_WPACKET_quic_vlint_random(void)
for (i = 0; i < 10000; ++i) {
if (!TEST_int_gt(RAND_bytes(rand_data, sizeof(rand_data)), 0))
- return cleanup(&pkt);
+ return 0;
memcpy(&expected, rand_data, sizeof(expected));