On Tue, Feb 18, 2025 at 03:54:42AM +0100, Christian Schulte wrote:
> Hi @ports,
> 
> I am currently trying to create a port (first time doing this) for a library
> using an OpenSSL function which does not seem to be available in LibreSSL in
> base. The FAQ mentions "The most important thing to do is to communicate." so 
> I
> am asking for help here.

EVP_PKEY_get_group_name() is OpenSSL 3 API and should therefore be
guarded by the OPENSSL_VERSION_NUMBER path. This is a bug introduced in

https://github.com/benmcollins/libjwt/commit/e12bba8a4463788f1b327b4cb522b484e269c433

I don't know why secp256k1 neeeds this extra check while all other curves
don't but it is easy to implement it:

> Script done on Tue Feb 18 03:34:29 2025
> 
> The function in question looks like this:
> 
> static int jwt_degree_for_key(EVP_PKEY *pkey, jwt_t *jwt)
> {
>       int degree = 0;

Add

#if OPENSSL_VERSION_NUMBER >= 0x30000000L

>       char groupNameBuffer[24] = {0};
>       size_t groupNameBufferLen = 0;
> 
>       if (!EVP_PKEY_get_group_name(pkey, groupNameBuffer, 
> sizeof(groupNameBuffer), &groupNameBufferLen))
>               return -EINVAL;
> 
>       groupNameBuffer[groupNameBufferLen] = '\0';
> 
>       /* We only perform this check for ES256K. All others we just check
>        * the degree (bits). */
>       if (jwt->alg == JWT_ALG_ES256K) {
>               if (strcmp(groupNameBuffer, "secp256k1"))
>                       return -EINVAL;
>       }
> 
> #if OPENSSL_VERSION_NUMBER >= 0x30000000L

remove the above line

>       int curve_nid;
>       EC_GROUP *group;
>       /* OpenSSL 3.0.0 and later has a new API for this. */
> 
>       curve_nid = OBJ_txt2nid(groupNameBuffer);
>       if (curve_nid == NID_undef)
>               return -EINVAL;
> 
>       group = EC_GROUP_new_by_curve_name(curve_nid);
>       if (group == NULL)
>               return -ENOMEM;
> 
>       /* Get the degree of the curve */
>       degree = EC_GROUP_get_degree(group);
> 
>       EC_GROUP_free(group);
> #else
>       EC_KEY *ec_key;
> 
>       if (EVP_PKEY_id(pkey) != EVP_PKEY_EC)
>               return -EINVAL;
> 
>       /* Get the actual ec_key */
>       ec_key = EVP_PKEY_get1_EC_KEY(pkey);
>       if (ec_key == NULL)
>               return -ENOMEM;

Add this:

        if (jwt-alg == JWT_ALG_ES256K) {
                const EC_GROUP *group;

                if ((group = EC_KEY_get0_group(ec_key)) == NULL) {
                        EC_KEY_free(ec_key);
                        return -EINVAL;
                }
                if (EC_GROUP_get_curve_name(group)) != NID_secp256k1) {
                        EC_KEY_free(ec_key);
                        return -EINVAL;
                }
        }

> 
>       degree = EC_GROUP_get_degree(EC_KEY_get0_group(ec_key));
> 
>       EC_KEY_free(ec_key);
> #endif
> 
>       /* Final check for matching degree */
>       switch (jwt->alg) {
>       case JWT_ALG_ES256:
>       case JWT_ALG_ES256K:
>               if (degree != 256)
>                       return -EINVAL;
>               break;
>       case JWT_ALG_ES384:
>               if (degree != 384)
>                       return -EINVAL;
>               break;
>       case JWT_ALG_ES512:
>               /* This is not a typo. ES512 uses secp521r1 */
>               if (degree != 521)
>                       return -EINVAL;
>               break;
>       default:
>               return -EINVAL;
>       }
> 
>       return degree;
> }
> 
> I would not want to remove that extra "secp256k1" check. It will be there for 
> a
> reason I do not understand. I would like to ask what to do about it. Is there
> a similar function I could use from LibreSSL?
> 
> Regards,
> -- 
> Christian
> 

Reply via email to