oh they set themselves up so hard
Different models of computation can be more or less realistic and, accordingly, lead to more or less accurate estimates of security strength.
nodding yes jack nicholson gif
oh they set themselves up so hard
Different models of computation can be more or less realistic and, accordingly, lead to more or less accurate estimates of security strength.
nodding yes jack nicholson gif
zero normal names
For the default “hedged” version of ML-DSA signing
shut the fuck up you're not cute
for the optional deterministic variant,
that's definitely a line to only write out in the pseudocode of algorithm 2 and nowhere else. bet you wish you could do that to my code huh
It may be that this is inadvisable.
you can't say that man. your code is on my laptop and you are actively obfuscating it in linux-fs
Note that whilst ML-DSA does allow for an "external mu", CMS doesn't yet have that standardised.
hey is it good when the IETF refers to the CMS and doesn't link it
Errata Exist
oh thanks
This is because in most situations, CMS signatures are computed over a set of signed attributes that contain a hash of the content, rather than being computed over the message content itself.
see the thing about the IETF? they never let me down
ML-DSA signature generation and verification is significantly faster than SLH-DSA.
no clue what SLH is but it must be a new form of quantum
ML-DSA depends on high-quality random numbers that are suitable for use in cryptography.
yeah the problem was your low-quality commoner randoms
The use of inadequate pseudo-random number generators (PRNGs) to generate such values can
significantly undermine the security properties offered by a cryptographic algorithm.
if i know the IETF the next line "don't worry buddy, [whispers] we all do it like this!"
oh DAMN i forgot their trick move
For instance, an attacker may find it much easier to reproduce the PRNG environment that produced
any private keys, searching the resulting small set of possibilities, rather than brute-force
searching the whole key space.
when they tell you an extremely specific and nonobvious attack strategy
who the hell is this guy https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/commit/?h=keys-next&id=965e9a2cf23b066d8bdeb690dff9cd7089c5f667
Only display the "PKCS7: Waived invalid module sig (has authattrs)" once.
it's not just him
Suggested-by: Lenny Szubowicz <[email protected]>
Signed-off-by: David Howells <[email protected]>
Tested-by: Lenny Szubowicz <[email protected]>
cc: Lukas Wunner <[email protected]>
cc: Ignat Korchagin <[email protected]>
cc: Jarkko Sakkinen <[email protected]>
cc: Stephan Mueller <[email protected]>
cc: Eric Biggers <[email protected]>
cc: Herbert Xu <[email protected]>
cc: [email protected]
cc: [email protected]
omg choose your fighter
git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git
https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git
https://kernel.googlesource.com/pub/scm/linux/kernel/git/dhowells/linux-fs.git
which domain+protocol is least likely to pwn me from orbit for cloning it
didn't post this earlier but this is what it looks like if you happened to pull master randomly this week like i did (keyword ML-DSA)
*
* Public-key cryptography
*
RSA (Rivest-Shamir-Adleman) (CRYPTO_RSA) [Y/?] y
DH (Diffie-Hellman) (CRYPTO_DH) [Y/?] y
RFC 7919 FFDHE groups (CRYPTO_DH_RFC7919_GROUPS) [Y/n/?] y
ECDH (Elliptic Curve Diffie-Hellman) (CRYPTO_ECDH) [Y/?] y
ECDSA (Elliptic Curve Digital Signature Algorithm) (CRYPTO_ECDSA) [Y/?] y
EC-RDSA (Elliptic Curve Russian Digital Signature Algorithm) (CRYPTO_ECRDSA) [M/n/y/?] m
ML-DSA (Module-Lattice-Based Digital Signature Algorithm) (CRYPTO_MLDSA) [N/m/y/?] (NEW) y
*
* Asymmetric (public-key cryptographic) key type
*
Asymmetric (public-key cryptographic) key type (ASYMMETRIC_KEY_TYPE) [Y/?] y
Asymmetric public-key crypto algorithm subtype (ASYMMETRIC_PUBLIC_KEY_SUBTYPE) [Y/?] y
X.509 certificate parser (X509_CERTIFICATE_PARSER) [Y/?] y
PKCS#8 private key parser (PKCS8_PRIVATE_KEY_PARSER) [M/n/y/?] m
PKCS#7 message parser (PKCS7_MESSAGE_PARSER) [Y/?] y
Waive rejection of authenticatedAttributes for ML-DSA (PKCS7_WAIVE_AUTHATTRS_REJECTION_FOR_MLDSA) [N/y/?] (NEW) n
PKCS#7 testing key type (PKCS7_TEST_KEY) [N/m/y/?] n
Support for PE file signature verification (SIGNED_PE_FILE_VERIFICATION) [Y/n/?] y
Run FIPS selftests on the X.509+PKCS7 signature verification (FIPS_SIGNATURE_SELFTEST) [N/m/y/?] n
*
* Certificates for signature checking
*
File name or PKCS#11 URI of module signing key (MODULE_SIG_KEY) [certs/signing_key.pem] certs/signing_key.pem
Type of module signing key to be generated
1. RSA (MODULE_SIG_KEY_TYPE_RSA)
> 2. ECDSA (MODULE_SIG_KEY_TYPE_ECDSA)
3. ML-DSA-44 (MODULE_SIG_KEY_TYPE_MLDSA_44) (NEW)
4. ML-DSA-65 (MODULE_SIG_KEY_TYPE_MLDSA_65) (NEW)
5. ML-DSA-87 (MODULE_SIG_KEY_TYPE_MLDSA_87) (NEW)
choice[1-5?]: 2
Provide system-wide ring of trusted keys (SYSTEM_TRUSTED_KEYRING) [Y/?] y
Additional X.509 keys for default system keyring (SYSTEM_TRUSTED_KEYS) []
Reserve area for inserting a certificate without recompiling (SYSTEM_EXTRA_CERTIFICATE) [N/y/?] n
Provide a keyring to which extra trustable keys may be added (SECONDARY_TRUSTED_KEYRING) [Y/n/?] y
Only allow additional certs signed by keys on the builtin trusted keyring (SECONDARY_TRUSTED_KEYRING_SIGNED_BY_BUILTIN) [N/y/?] n
Provide system-wide ring of blacklisted keys (SYSTEM_BLACKLIST_KEYRING) [Y/n/?] y
Hashes to be preloaded into the system blacklist keyring (SYSTEM_BLACKLIST_HASH_LIST) []
Provide system-wide ring of revocation certificates (SYSTEM_REVOCATION_LIST) [Y/n/?] y
X.509 certificates to be preloaded into the system blacklist keyring (SYSTEM_REVOCATION_KEYS) []
Allow root to add signed blacklist keys (SYSTEM_BLACKLIST_AUTH_UPDATE) [Y/n/?] y
so of course i was like:
Waive rejection of authenticatedAttributes for ML-DSA (PKCS7_WAIVE_AUTHATTRS_REJECTION_FOR_MLDSA) [N/y/?] (NEW) n
ok
crypto/asymmetric_keys/Kconfig
47-config PKCS7_MESSAGE_PARSER
48- tristate "PKCS#7 message parser"
49- depends on X509_CERTIFICATE_PARSER
50- select CRYPTO_HASH
51- select ASN1
52- select OID_REGISTRY
53- help
54- This option provides support for parsing PKCS#7 format messages for
55- signature data and provides the ability to verify the signature.
56-
57:config PKCS7_WAIVE_AUTHATTRS_REJECTION_FOR_MLDSA
58- bool "Waive rejection of authenticatedAttributes for ML-DSA"
59- depends on PKCS7_MESSAGE_PARSER
60- depends on CRYPTO_MLDSA
61- help
62- Due to use of CMS_NOATTR with ML-DSA not being supported in
63- OpenSSL < 4.0 (and thus any released version), enabling this
64- allows authenticatedAttributes to be used with ML-DSA for
65- module signing. Use of authenticatedAttributes in this
66- context is normally rejected.
67-
crypto/asymmetric_keys/pkcs7_parser.c
85- */
86-static int pkcs7_check_authattrs(struct pkcs7_message *msg)
87-{
88- struct pkcs7_signed_info *sinfo;
89- bool want = false;
90-
91- sinfo = msg->signed_infos;
92- if (!sinfo)
93- goto inconsistent;
94-
95:#ifdef CONFIG_PKCS7_WAIVE_AUTHATTRS_REJECTION_FOR_MLDSA
96- msg->authattrs_rej_waivable = true;
97-#endif
98-
99- if (sinfo->authattrs) {
100- want = true;
101- msg->have_authattrs = true;
102:#ifdef CONFIG_PKCS7_WAIVE_AUTHATTRS_REJECTION_FOR_MLDSA
103- if (strncmp(sinfo->sig->pkey_algo, "mldsa", 5) != 0)
104- msg->authattrs_rej_waivable = false;
105-#endif
106- } else if (sinfo->sig->algo_takes_data) {
107- sinfo->sig->hash_algo = "none";
108- }
109-
110- for (sinfo = sinfo->next; sinfo; sinfo = sinfo->next) {
111- if (!!sinfo->authattrs != want)
112- goto inconsistent;
.config gitignored in the first place? the exact same as bootstrap.toml in the rustc repo, despite being incredibly important and not remotely something you want to risk deleting. many hours/days of work i've put into bothwhatever. anyway you read the commit messages
modsign: Enable ML-DSA module signing
Allow ML-DSA module signing to be enabled.
don't care but ok. "allow". "enable". "allow to be enabled" whatever quantum is fake
Note that OpenSSL's CMS_*() function suite does not, as of OpenSSL-3.6,
support the use of CMS_NOATTR with ML-DSA, so the prohibition against using
signedAttrs with module signing has to be removed. The selected digest
then applies only to the algorithm used to calculate the digest stored in
the messageDigest attribute. The OpenSSL development branch has patches
applied that fix this[1], but it appears that that will only be available
in OpenSSL-4.
good documentation of version compat, ok
[1] https://github.com/openssl/openssl/pull/28923
sign-file won't set CMS_NOATTR if openssl is earlier than v4, resulting in
the use of signed attributes.
The ML-DSA algorithm takes the raw data to be signed without regard to what
digest algorithm is specified in the CMS message. The CMS specified digest
algorithm is ignored unless signedAttrs are used; in such a case, only
SHA512 is permitted.
this is complete word salad. that's a huge red flag
...
maybe fine for a dev branch but they are on master! call coming from inside the house!
git show 0ad9a71933e73c8a2af101d28e9a1dc35bae02d5
[...]
ML-DSA does its own hashing,
spent an hour destroying my brain with this shit
https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.204.pdf
it does not "do its own hashing"
In the HashML-DSA version, the message input to ML-DSA.Sign_internal is the result of applying either a hash function or a XOF to the content to be signed.
do they really think they can be more brain destroying than working on build and packaging

Add support for hashless signing schemes, such as ML-DSA, SLH-DSA, and EdDSA, for the case that signed attributes are absent. Add test cases for all newly supported signing schemes. Enable the abil...
this fucking guy thinks he's really cute https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git because he puts his work on filesystem shit in the same clone url. i think master seems to have more than keys-next but i'm not sure
he's a REALLY funny guy too
git show 645427b7a6c59e0074df29bf939aec2e9d6f2819
commit 645427b7a6c59e0074df29bf939aec2e9d6f2819
Author: David Howells <[email protected]>
Date: Wed Dec 17 09:42:22 2025 +0000
cifs: SMB1 split: Separate out SMB1 decls into smb1proto.h
Separate out SMB1 declarations scriptedly into smb1proto.h. Script below:
#!/usr/bin/perl -w
use strict;
perl? you think perl is enough to stop me?
git show 645427b7a6c59e0074df29bf939aec2e9d6f2819 | wc -l
1049
sir i use emacs not sure if you've heard of it we just added package-review for people like you
here's some really representative stuff that was what turned me on to the possibility that he was overreaching in the crypto api. i think this was when i realized it was on master
GIT_PAGER='grep -F -C 3 OPENSSL_VERSION_NUMBER' git show 0ad9a71933e73c8a2af101d28e9a1dc35bae02d5
#include <openssl/pem.h>
#include <openssl/err.h>
-#if OPENSSL_VERSION_MAJOR >= 3
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
# define USE_PKCS11_PROVIDER
# include <openssl/provider.h>
# include <openssl/store.h>
this is word for word the cpython playbook. i spent so many hours trying to parse what the hell was happening with openssl cause i didn't change anything. oh man. here's an example of a change you should not be seeing someone make to cryptographic apis in ring 0
[image]
https://github.com/python/cpython/blob/8d21aa21f2cbc6d50aab3f420bb23be1d081dac4/setup.py#L884-L922 this is why cpython 2.7 up to 3.6 won't build with newer openssl
# find out which version of OpenSSL we have
openssl_ver = 0
openssl_ver_re = re.compile(
'^\s*#\s*define\s+OPENSSL_VERSION_NUMBER\s+(0x[0-9a-fA-F]+)' )
# look for the openssl version header on the compiler search path.
opensslv_h = find_file('openssl/opensslv.h', [],
inc_dirs + search_for_ssl_incs_in)
if opensslv_h:
name = os.path.join(opensslv_h[0], 'openssl/opensslv.h')
if host_platform == 'darwin' and is_macosx_sdk_path(name):
name = os.path.join(macosx_sdk_root(), name[1:])
try:
incfile = open(name, 'r')
for line in incfile:
m = openssl_ver_re.match(line)
if m:
openssl_ver = eval(m.group(1))
except IOError, msg:
print "IOError while reading opensshv.h:", msg
pass
min_openssl_ver = 0x00907000
have_any_openssl = ssl_incs is not None and ssl_libs is not None
have_usable_openssl = (have_any_openssl and
openssl_ver >= min_openssl_ver)
if have_any_openssl:
if have_usable_openssl:
# The _hashlib module wraps optimized implementations
# of hash functions from the OpenSSL library.
exts.append( Extension('_hashlib', ['_hashopenssl.c'],
include_dirs = ssl_incs,
library_dirs = ssl_libs,
libraries = ['ssl', 'crypto']) )
else:
print ("warning: openssl 0x%08x is too old for _hashlib" %
openssl_ver)
missing.append('_hashlib')
that is regex matching on the content of a c header file....and!
print ("warning: openssl 0x%08x is too old for _hashlib" %
openssl_ver)
"too old". sicko shit
so then you find the commit that set it off
git show 91db696adea4d76017b1e1f45915a5cbf04e8da3
commit 91db696adea4d76017b1e1f45915a5cbf04e8da3
Author: David Howells <[email protected]>
Date: Mon Jan 26 11:46:58 2026 +0000
pkcs7: Allow authenticatedAttributes for ML-DSA
Allow the rejection of authenticatedAttributes in PKCS#7 (signedAttrs in
CMS) to be waived in the kernel config for ML-DSA when used for module
signing. This reflects the issue that openssl < 4.0 cannot do this and
openssl-4 has not yet been released.
This does not permit RSA, ECDSA or ECRDSA to be so waived (behaviour
unchanged).
(1) when people blame a project for not having functionality that's one thing
(2) when this fuckin guy says yeah backdoor in the kernel sounds like the right way to solve this that's another thing
(3) READ this shit "Allow authenticatedAttributes" => "Allow the rejection of authenticatedAttributes"
(4) WHEN USED FOR MODULE SIGNING!!!!!!!!!!
(5) oh i bet i'm about to see some behaviour that's so unchanged
It's tempting to search for a clever cryptographic solution, but nobody has yet proposed one.
not a cryptographic problem, fuckboy. diffoscope is the problem. 'oh i can calculate granular diffs but can't ignore a specified list of files"
+config PKCS7_WAIVE_AUTHATTRS_REJECTION_FOR_MLDSA
+ bool "Waive rejection of authenticatedAttributes for ML-DSA"
+ depends on PKCS7_MESSAGE_PARSER
+ depends on CRYPTO_MLDSA
+ help
+ Due to use of CMS_NOATTR with ML-DSA not being supported in
+ OpenSSL < 4.0 (and thus any released version), enabling this
+ allows authenticatedAttributes to be used with ML-DSA for
+ module signing. Use of authenticatedAttributes in this
+ context is normally rejected.
why is this considered a normal thing to push
Use of authenticatedAttributes in this context is normally rejected.
do people think when they pull in kernel kconfig they learn about new ways to hack people and then try to run this and get hacked
do you think linus has done the full kconfig cannonball run recently
i have
insane shit
+#ifdef CONFIG_PKCS7_WAIVE_AUTHATTRS_REJECTION_FOR_MLDSA
+ bool authattrs_rej_waivable; /* T if authatts rejection can be waived */
+#endif
"authatts" what is the purpose of this typo besides signaling a typo
this one is low-effort. get a real job
git show 965e9a2cf23b066d8bdeb690dff9cd7089c5f667
commit 965e9a2cf23b066d8bdeb690dff9cd7089c5f667 (tag: keys-next-20260206, dhowells/keys-next)
Author: David Howells <[email protected]>
Date: Thu Feb 5 13:02:41 2026 +0000
pkcs7: Change a pr_warn() to pr_warn_once()
Only display the "PKCS7: Waived invalid module sig (has authattrs)" once.
Suggested-by: Lenny Szubowicz <[email protected]>
Signed-off-by: David Howells <[email protected]>
Tested-by: Lenny Szubowicz <[email protected]>
cc: Lukas Wunner <[email protected]>
cc: Ignat Korchagin <[email protected]>
cc: Jarkko Sakkinen <[email protected]>
cc: Stephan Mueller <[email protected]>
cc: Eric Biggers <[email protected]>
cc: Herbert Xu <[email protected]>
cc: [email protected]
cc: [email protected]
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
index 519eecfe6778..474e2c1ae21b 100644
--- a/crypto/asymmetric_keys/pkcs7_verify.c
+++ b/crypto/asymmetric_keys/pkcs7_verify.c
@@ -427,7 +427,7 @@ int pkcs7_verify(struct pkcs7_message *pkcs7,
if (pkcs7->have_authattrs) {
#ifdef CONFIG_PKCS7_WAIVE_AUTHATTRS_REJECTION_FOR_MLDSA
if (pkcs7->authattrs_rej_waivable) {
- pr_warn("Waived invalid module sig (has authattrs)\n");
+ pr_warn_once("Waived invalid module sig (has authattrs)\n");
break;
}
#endif
linux-crypto is notthis is the one that had me reading that brain destroying nist spec
git show f3eccecd782dbaf33d5ad0d1fd22ea277300acdb
commit f3eccecd782dbaf33d5ad0d1fd22ea277300acdb
Author: David Howells <[email protected]>
Date: Wed Jan 21 12:41:42 2026 +0000
pkcs7: Allow the signing algo to do whatever digestion it wants itself
this one is SO close to sounding like a real commit message. except for all the specifics
Allow the data to be verified in a PKCS#7 or CMS message to be passed
directly to an asymmetric cipher algorithm (e.g. ML-DSA) if it wants to do
whatever passes for hashing/digestion itself.
so GODDAMN pissed he would create a capability that does not exist like this
this is, btw, one intended result of NIST's document that frames a "signature" as distinct from "hashing"
these people don't deserve to work for the government
The normal digestion of the
data is then skipped as that would be ignored unless another signed info in
the message has some other algorithm that needs it.
The normal digestion of the data is then skipped
nope! nope. not something that you would ever allow in the real world
Note that whilst ML-DSA does allow for an "external mu", CMS doesn't yet
have that standardised.
i didn't actually spend any time looking this up because i assumed it was completely made up
no fucking way am i adding an early return 0 to my real crypto because someone thinks quantum computing is real and can hurt you. pascal's wager
+ if (!sinfo->authattrs && sig->algo_takes_data) {
+ /* There's no intermediate digest and the signature algo
+ * doesn't want the data prehashing.
+ */
+ sig->m = (void *)pkcs7->data;
+ sig->m_size = pkcs7->data_len;
+ sig->m_free = false;
+ return 0;
+ }
+
oh yeah this is where i started screaming and saying this is all completely insane shit to be doing in the kernel
this would be headline on lwn if it was in a gnu project
+ if (!sinfo->sig->m_free) {
+ pr_notice_once("%s: No digest available\n", __func__);
+ return -EINVAL; /* TODO: MLDSA doesn't necessarily calculate an
+ * intermediate digest. */
+ }
none of this shit makes any sense btw. you can just type shit. IETF material
this is i think when i became convinced oh this is for real like this is gonna be released with signed modules upon 7.0
diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
index bd38ba4d217d..4c5199b20338 100644
--- a/include/crypto/public_key.h
+++ b/include/crypto/public_key.h
@@ -46,6 +46,8 @@ struct public_key_signature {
u8 *m; /* Message data to pass to verifier */
u32 s_size; /* Number of bytes in signature */
u32 m_size; /* Number of bytes in ->m */
+ bool m_free; /* T if ->m needs freeing */
+ bool algo_takes_data; /* T if public key algo operates on data, not a hash */
const char *pkey_algo;
const char *hash_algo;
const char *encoding;
the fuck are you doing in public_key.h asshole?????
i'm going backwards so this comes before the previous
git show f728074f1f577565c97e465652c3d4afb0964013
commit f728074f1f577565c97e465652c3d4afb0964013
Author: David Howells <[email protected]>
Date: Mon Jan 26 09:49:24 2026 +0000
pkcs7, x509: Rename ->digest to ->m
went into a brief fugue state
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
index 348966ea2175..2326743310b1 100644
--- a/crypto/asymmetric_keys/asymmetric_type.c
+++ b/crypto/asymmetric_keys/asymmetric_type.c
@@ -593,10 +593,10 @@ static int asymmetric_key_verify_signature(struct kernel_pkey_params *params,
{
struct public_key_signature sig = {
.s_size = params->in2_len,
- .digest_size = params->in_len,
+ .m_size = params->in_len,
.encoding = params->encoding,
.hash_algo = params->hash_algo,
- .digest = (void *)in,
+ .m = (void *)in,
.s = (void *)in2,
};
this is very pythonic
diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
index 81098e00c08f..bd38ba4d217d 100644
--- a/include/crypto/public_key.h
+++ b/include/crypto/public_key.h
@@ -43,9 +43,9 @@ extern void public_key_free(struct public_key *key);
struct public_key_signature {
struct asymmetric_key_id *auth_ids[3];
u8 *s; /* Signature */
- u8 *digest;
+ u8 *m; /* Message data to pass to verifier */
u32 s_size; /* Number of bytes in signature */
- u32 digest_size; /* Number of bytes in digest */
+ u32 m_size; /* Number of bytes in ->m */
const char *pkey_algo;
const char *hash_algo;
const char *encoding;
no. no. that's not real. that's not a thing
he keeps getting his boys to rizz him up
Signed-off-by: David Howells <[email protected]>
Reviewed-by: Jarkko Sakkinen <[email protected]>
cc: Lukas Wunner <[email protected]>
cc: Ignat Korchagin <[email protected]>
cc: Stephan Mueller <[email protected]>
cc: Eric Biggers <[email protected]>
cc: Herbert Xu <[email protected]>
cc: [email protected]
cc: [email protected]
this one's where he acts like people think that going back through time in git is more invisible?
git show 2c62068ac86bdd917a12eef49ba82ec8b091208b
commit 2c62068ac86bdd917a12eef49ba82ec8b091208b
Author: David Howells <[email protected]>
Date: Wed Jan 21 13:33:37 2026 +0000
x509: Separately calculate sha256 for blacklist
Calculate the SHA256 hash for blacklisting purposes independently of the
signature hash (which may be something other than SHA256).
This is necessary because when ML-DSA is used, no digest is calculated.
Note that this represents a change of behaviour in that the hash used for
the blacklist check would previously have been whatever digest was used
for, say, RSA-based signatures. It may be that this is inadvisable.
This is necessary because when ML-DSA is used, no digest is calculated.
yeah figured that out after wasting an hour of my life
Note that this represents a change of behaviour
yeah i mean the only thing i don't know is why you would say this out loud. i was literally reading the kbuild docs should i keep going
It may be that this is inadvisable.
i can't understand the theory of this process? like you can act like the IETF in the linux kernel? the place where people do close review?
public_key.h in ring 0 like it's a fucking joke (it has to be a joke for long enough until it's real)