Skip to content

DH_check takes >20s on RFC 3526 groups #3335

Description

@reaperhulk

DH_check() on well-known safe-prime groups is orders of magnitude slower in AWS-LC than in OpenSSL 3.x.

OpenSSL 3.x's DH_check calls DH_get_nid() first and returns early when (p, g) matches a named group, skipping primality testing. AWS-LC's DH_check has no such shortcut and runs BN_is_prime_ex to do a primality check.

We hit this in pyca/cryptography, where we validate loaded DH paramters with DH_check. This makes two tests take 19s/32s on AWS-LC vs. milliseconds on OpenSSL.

Would you consider recognizing named groups (RFC 3526 / RFC 7919) in DH_check and skipping the primality tests, as OpenSSL does?

Reproducer

#include <openssl/bn.h>
#include <openssl/dh.h>

/* RFC 3526 group 18 (8192-bit MODP) */
static const char *P_HEX =
    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74"
    "020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437"
    "4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05"
    "98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB"
    "9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
    "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718"
    "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33"
    "A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
    "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864"
    "D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E2"
    "08E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
    "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8"
    "DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2"
    "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
    "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026"
    "C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AE"
    "B06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B"
    "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92EC"
    "F032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E"
    "59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
    "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76"
    "F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468"
    "043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4"
    "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED"
    "2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652D"
    "E3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B"
    "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A6"
    "6D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851D"
    "F9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92"
    "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA"
    "9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF";

int main(void) {
    BIGNUM *p = NULL, *g = NULL;
    BN_hex2bn(&p, P_HEX);
    BN_dec2bn(&g, "2");
    DH *dh = DH_new();
    DH_set0_pqg(dh, p, NULL, g);
    int flags = 0;
    int ok = DH_check(dh, &flags);
    DH_free(dh);
    return !(ok && flags == 0);
}
$ time ./repro_openssl   # OpenSSL 3.0.13
real    0m0.003s
$ time ./repro_awslc     # AWS-LC 5.1.0
real    0m27.707s

I'm very sorry to file a FFDH issue since I'd strongly prefer it to not exist, but while it's in pyca/cryptography's API surface area I'd love for it to be faster. LibreSSL has a similar pathology here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions