]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Fix OpenSSL 1.0 and 1.1 support in PKINIT 1333/head
authorGreg Hudson <ghudson@mit.edu>
Thu, 21 Mar 2024 23:04:13 +0000 (19:04 -0400)
committerGreg Hudson <ghudson@mit.edu>
Tue, 26 Mar 2024 15:20:23 +0000 (11:20 -0400)
Commit f745c9a9bd6c0c73b944182173f1ac305d03dc3a uses ECDSA_SIG_set0(),
which was added in OpenSSL 1.1.  Add a compatibility version for
OpenSSL 1.0.

Commit bdcd6075bd4593c8f67722ce075c9519faec58b7 uses
EVP_PKEY_get_base_id(), which was added in OpenSSL 3.0.  Add a
compatibility macro to use the old name for OpenSSL 1.0 and 1.1.

Commit 0f870b1bcad960fd5319a3f97aafd7f4a289e2fb added ECDH support,
but did not change the OpenSSL 1.0 versions of encode_spki(),
decode_spki(), or generate_dh_pkey() to work with elliptic curve
public keys.  In each function, check the key type and skip the
DH-specific handling for key types other than DH.

src/plugins/preauth/pkinit/pkinit_crypto_openssl.c

index d9cc248d76f9075b0aef1449c6c734e0369c03cc..2f26197b19a7262b4f596497cf6e3dd6b84612e0 100644 (file)
@@ -268,6 +268,15 @@ compat_get0_EC(const EVP_PKEY *pkey)
     return pkey->pkey.ec;
 }
 
+#define ECDSA_SIG_set0 compat_ECDSA_SIG_set0
+static int
+compat_ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
+{
+    sig->r = r;
+    sig->s = s;
+    return 1;
+}
+
 /* Return true if the cert c includes a key usage which doesn't include u.
  * Define using direct member access for pre-1.1. */
 #define ku_reject(c, u)                                                 \
@@ -285,6 +294,7 @@ compat_get0_EC(const EVP_PKEY *pkey)
 #define EVP_PKEY_parameters_eq EVP_PKEY_cmp_parameters
 #define EVP_PKEY_get_size EVP_PKEY_size
 #define EVP_PKEY_get_bits EVP_PKEY_bits
+#define EVP_PKEY_get_base_id EVP_PKEY_base_id
 
 /*
  * Convert *dh to an EVP_PKEY object, taking ownership of *dh and setting it to
@@ -496,6 +506,17 @@ encode_spki(EVP_PKEY *pkey, krb5_data *spki_out)
     ASN1_TYPE parameter;
     ASN1_STRING param_str, pubkey_str;
 
+    if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH) {
+        /* Only DH keys require special encoding. */
+        len = i2d_PUBKEY(pkey, NULL);
+        ret = alloc_data(spki_out, len);
+        if (ret)
+            goto cleanup;
+        outptr = (uint8_t *)spki_out->data;
+        (void)i2d_PUBKEY(pkey, &outptr);
+        return 0;
+    }
+
     dh = EVP_PKEY_get0_DH(pkey);
     if (dh == NULL)
         goto cleanup;
@@ -563,6 +584,13 @@ decode_spki(const krb5_data *spki)
     if (pubkey == NULL)
         goto cleanup;
 
+    if (OBJ_cmp(pubkey->algor->algorithm, OBJ_nid2obj(NID_dhKeyAgreement))) {
+        /* This is not a DH key, so we don't need special decoding. */
+        X509_PUBKEY_free(pubkey);
+        inptr = (uint8_t *)spki->data;
+        return d2i_PUBKEY(NULL, &inptr, spki->length);
+    }
+
     if (pubkey->algor->parameter->type != V_ASN1_SEQUENCE)
         goto cleanup;
     params = pubkey->algor->parameter->value.sequence;
@@ -802,7 +830,8 @@ generate_dh_pkey(EVP_PKEY *params)
         goto cleanup;
     if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
         goto cleanup;
-    if (!copy_q_openssl10(params, pkey)) {
+    if (EVP_PKEY_get_base_id(pkey) == EVP_PKEY_DH &&
+        !copy_q_openssl10(params, pkey)) {
         EVP_PKEY_free(pkey);
         pkey = NULL;
     }