[php-src] Issue #21083: openssl_pkey_new() fails for EC keys on OpenSSL 3.6 - incorrectly requires private_key_bits

[email protected] (ben182)
Newsgroups php.bugs
Message-ID <[email protected]>
Issue: https://github.com/php/php-src/issues/21083
Author: ben182

### Description

### Description                                                                                                  
                                                                                                                   
  When using `openssl_pkey_new()` to generate EC keys with OpenSSL 3.6.0, the function incorrectly requires        
  `private_key_bits` even though this parameter is not relevant for elliptic curve keys (the key size is determined
   by the curve itself).                                                                                           
                                                                                                                   
  The workaround requires setting `private_key_bits` to 384, which is semantically incorrect for a 256-bit curve   
  like `prime256v1`. Setting it to 256 (the actual curve size) still fails.                                        
                                                                                                                   
  The OpenSSL CLI generates EC keys without issues (`openssl ecparam -name prime256v1 -genkey -noout`), suggesting 
  this is a PHP bindings issue.                                                                                    
                                                                                                                   
  **Environment:** PHP 8.5.2, OpenSSL 3.6.0                                                                        
                                                                                                                   
  ### Possible cause                                                                                               
                                                                                                                   
  OpenSSL 3.6 requires C-99 compilers (no longer ANSI-C), which changes integer behavior and sizes. Additionally,  
  OpenSSL 3.6 modified EC keygen error handling.                                                                   
                                                                                                                   
  The `private_key_bits` parameter should not apply to EC keys at all - the curve name (e.g., `prime256v1`)        
  implicitly defines the key size. It appears PHP's OpenSSL bindings incorrectly validate `private_key_bits` for EC
   keys when linked against OpenSSL 3.6.                                                                           
                                                                                                                   
  This same error has been reported in other projects:                                                             
  - https://community.librenms.org/t/new-install-openssl-pkey-new-private-key-length-must-be-at-least-384-bits-conf
  igured-to-0/22396                                                                                                
  - https://github.com/laravel/passport/issues/757                                                                 
                                                                                                                   
  ### References                                                                                                   
                                                                                                                   
  - https://github.com/web-push-libs/web-push-php/issues/445                                                       
  - https://github.com/openssl/openssl/blob/openssl-3.6.0/CHANGES.md                                               
  - https://github.com/openssl/technical-policies/pull/50 (C-99 requirement)                                       
                                                                                                                   
  ---                                                                                                              
                                                                                                                   
  The following code:                                                                                              
                                                                                                                   
  ```php                                                                                                           
  <?php                                                                                                            
  $key = openssl_pkey_new([                                                                                        
      'curve_name'       => 'prime256v1',                                                                          
      'private_key_type' => OPENSSL_KEYTYPE_EC,                                                                    
  ]);                                                                                                              
                                                                                                                   
  var_dump($key);                                                                                                  
  var_dump(openssl_error_string());                                                                                
                                                                                                                   
  Resulted in this output:                                                                                         
  bool(false)                                                                                                      
  string(63) "Private key length must be at least 384 bits, configured to 0"                                       
                                                                                                                   
  But I expected this output instead:                                                                              
  object(OpenSSLAsymmetricKey)#1 (0) {}                                                                            
  bool(false)

### PHP Version

```plain
PHP 8.5.2 (cli) (built: Jan 17 2026 23:04:39) (NTS clang 15.0.0)                                                 
  Copyright (c) The PHP Group                                                                                      
  Built by Laravel Herd                                                                                            
  Zend Engine v4.5.2, Copyright (c) Zend Technologies                                                              
      with Zend OPcache v8.5.2, Copyright (c), by Zend Technologies
```

### Operating System

macOS (Darwin 25.2.0)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.