@@ -423,6 +423,141 @@ pkey_generate(int argc, VALUE *argv, VALUE self, int genparam)
423
423
return ossl_pkey_new (gen_arg .pkey );
424
424
}
425
425
426
+ #if OSSL_OPENSSL_PREREQ (3 , 0 , 0 )
427
+ #include <openssl/param_build.h>
428
+ #include <openssl/core_names.h>
429
+
430
+ static int
431
+ add_ec_parameters_to_builder (VALUE key , VALUE value , VALUE arg ) {
432
+ OSSL_PARAM_BLD * params_builder = (OSSL_PARAM_BLD * ) arg ;
433
+
434
+ if (NIL_P (value ))
435
+ return ST_CONTINUE ;
436
+
437
+ if (SYMBOL_P (key ))
438
+ key = rb_sym2str (key );
439
+
440
+ const char * key_ptr = StringValueCStr (key );
441
+
442
+ if (strcmp (OSSL_PKEY_PARAM_GROUP_NAME , key_ptr ) == 0 )
443
+ if (!OSSL_PARAM_BLD_push_utf8_string (params_builder , key_ptr , StringValueCStr (value ), 0 ))
444
+ ossl_raise (ePKeyError , "OSSL_PARAM_BLD_push_utf8_string" );
445
+
446
+ return ST_CONTINUE ;
447
+ }
448
+
449
+ static int
450
+ add_rsa_parameters_to_builder (VALUE key , VALUE value , VALUE arg ) {
451
+ OSSL_PARAM_BLD * params_builder = (OSSL_PARAM_BLD * ) arg ;
452
+
453
+ if (NIL_P (value ))
454
+ return ST_CONTINUE ;
455
+
456
+ if (SYMBOL_P (key ))
457
+ key = rb_sym2str (key );
458
+
459
+ static const struct {
460
+ char alias [5 ];
461
+ char param_name [20 ];
462
+ } key_aliases [] = {
463
+ { "p" , OSSL_PKEY_PARAM_RSA_FACTOR1 },
464
+ { "q" , OSSL_PKEY_PARAM_RSA_FACTOR2 },
465
+ { "dmp1" , OSSL_PKEY_PARAM_RSA_EXPONENT1 },
466
+ { "dmq1" , OSSL_PKEY_PARAM_RSA_EXPONENT2 },
467
+ { "iqmp" , OSSL_PKEY_PARAM_RSA_COEFFICIENT1 }
468
+ };
469
+
470
+ const char * key_ptr = StringValueCStr (key );
471
+
472
+ for (int i = 0 ; i < (int )(sizeof (key_aliases )/sizeof ((key_aliases )[0 ])); i ++ ) {
473
+ if (strcmp (key_aliases [i ].alias , key_ptr ) == 0 ) {
474
+ key_ptr = key_aliases [i ].param_name ;
475
+ break ;
476
+ }
477
+ }
478
+
479
+ if ((strcmp (OSSL_PKEY_PARAM_RSA_N , key_ptr ) != 0 &&
480
+ strcmp (OSSL_PKEY_PARAM_RSA_E , key_ptr ) != 0 &&
481
+ strcmp (OSSL_PKEY_PARAM_RSA_D , key_ptr ) != 0 &&
482
+ strcmp (OSSL_PKEY_PARAM_RSA_FACTOR1 , key_ptr ) != 0 &&
483
+ strcmp (OSSL_PKEY_PARAM_RSA_FACTOR2 , key_ptr ) != 0 &&
484
+ strcmp (OSSL_PKEY_PARAM_RSA_FACTOR3 , key_ptr ) != 0 &&
485
+ strcmp (OSSL_PKEY_PARAM_RSA_FACTOR4 , key_ptr ) != 0 &&
486
+ strcmp (OSSL_PKEY_PARAM_RSA_FACTOR5 , key_ptr ) != 0 &&
487
+ strcmp (OSSL_PKEY_PARAM_RSA_FACTOR6 , key_ptr ) != 0 &&
488
+ strcmp (OSSL_PKEY_PARAM_RSA_FACTOR7 , key_ptr ) != 0 &&
489
+ strcmp (OSSL_PKEY_PARAM_RSA_FACTOR8 , key_ptr ) != 0 &&
490
+ strcmp (OSSL_PKEY_PARAM_RSA_FACTOR9 , key_ptr ) != 0 &&
491
+ strcmp (OSSL_PKEY_PARAM_RSA_FACTOR10 , key_ptr ) != 0 &&
492
+ strcmp (OSSL_PKEY_PARAM_RSA_EXPONENT1 , key_ptr ) != 0 &&
493
+ strcmp (OSSL_PKEY_PARAM_RSA_EXPONENT2 , key_ptr ) != 0 &&
494
+ strcmp (OSSL_PKEY_PARAM_RSA_EXPONENT3 , key_ptr ) != 0 &&
495
+ strcmp (OSSL_PKEY_PARAM_RSA_EXPONENT4 , key_ptr ) != 0 &&
496
+ strcmp (OSSL_PKEY_PARAM_RSA_EXPONENT5 , key_ptr ) != 0 &&
497
+ strcmp (OSSL_PKEY_PARAM_RSA_EXPONENT6 , key_ptr ) != 0 &&
498
+ strcmp (OSSL_PKEY_PARAM_RSA_EXPONENT7 , key_ptr ) != 0 &&
499
+ strcmp (OSSL_PKEY_PARAM_RSA_EXPONENT8 , key_ptr ) != 0 &&
500
+ strcmp (OSSL_PKEY_PARAM_RSA_EXPONENT9 , key_ptr ) != 0 &&
501
+ strcmp (OSSL_PKEY_PARAM_RSA_EXPONENT10 , key_ptr ) != 0 &&
502
+ strcmp (OSSL_PKEY_PARAM_RSA_COEFFICIENT1 , key_ptr ) != 0 &&
503
+ strcmp (OSSL_PKEY_PARAM_RSA_COEFFICIENT2 , key_ptr ) != 0 &&
504
+ strcmp (OSSL_PKEY_PARAM_RSA_COEFFICIENT3 , key_ptr ) != 0 &&
505
+ strcmp (OSSL_PKEY_PARAM_RSA_COEFFICIENT4 , key_ptr ) != 0 &&
506
+ strcmp (OSSL_PKEY_PARAM_RSA_COEFFICIENT5 , key_ptr ) != 0 &&
507
+ strcmp (OSSL_PKEY_PARAM_RSA_COEFFICIENT6 , key_ptr ) != 0 &&
508
+ strcmp (OSSL_PKEY_PARAM_RSA_COEFFICIENT7 , key_ptr ) != 0 &&
509
+ strcmp (OSSL_PKEY_PARAM_RSA_COEFFICIENT8 , key_ptr ) != 0 &&
510
+ strcmp (OSSL_PKEY_PARAM_RSA_COEFFICIENT9 , key_ptr )) != 0 )
511
+ ossl_raise (ePKeyError , "Unsupported RSA parameter \"%s\"" , key_ptr );
512
+
513
+ if (!OSSL_PARAM_BLD_push_BN (params_builder , key_ptr , GetBNPtr (value )))
514
+ ossl_raise (ePKeyError , "OSSL_PARAM_BLD_push_BN" );
515
+
516
+ return ST_CONTINUE ;
517
+ }
518
+
519
+ static VALUE
520
+ pkey_from_parameters (int argc , VALUE * argv , VALUE self )
521
+ {
522
+ VALUE alg , options ;
523
+ rb_scan_args (argc , argv , "11" , & alg , & options );
524
+
525
+ OSSL_PARAM_BLD * params_builder = OSSL_PARAM_BLD_new ();
526
+
527
+ if (params_builder == NULL )
528
+ ossl_raise (ePKeyError , "OSSL_PARAM_BLD_new" );
529
+
530
+ int (* param_adder )(VALUE , VALUE , VALUE ) = NULL ;
531
+
532
+ if (strcmp ("RSA" , StringValueCStr (alg )) == 0 )
533
+ param_adder = & add_rsa_parameters_to_builder ;
534
+ else if (strcmp ("EC" , StringValueCStr (alg )) == 0 )
535
+ param_adder = & add_ec_parameters_to_builder ;
536
+ else
537
+ ossl_raise (ePKeyError , "\"%s\" is not a supported algorithm" , StringValueCStr (alg ));
538
+
539
+ rb_hash_foreach (options , param_adder , (VALUE ) params_builder );
540
+
541
+ OSSL_PARAM * params = OSSL_PARAM_BLD_to_param (params_builder );
542
+ OSSL_PARAM_BLD_free (params_builder );
543
+
544
+ if (params == NULL )
545
+ ossl_raise (ePKeyError , "OSSL_PARAM_BLD_to_param" );
546
+
547
+ EVP_PKEY_CTX * ctx = EVP_PKEY_CTX_new_from_name (NULL , StringValueCStr (alg ), NULL );
548
+ EVP_PKEY * pkey = NULL ;
549
+
550
+ if (ctx == NULL ||
551
+ EVP_PKEY_fromdata_init (ctx ) <= 0 ||
552
+ EVP_PKEY_fromdata (ctx , & pkey , EVP_PKEY_KEYPAIR , params ) <= 0 ) {
553
+ ossl_clear_error ();
554
+ ossl_raise (ePKeyError , "EVP_PKEY_fromdata" );
555
+ }
556
+
557
+ return ossl_pkey_new (pkey );
558
+ }
559
+ #endif
560
+
426
561
/*
427
562
* call-seq:
428
563
* OpenSSL::PKey.generate_parameters(algo_name [, options]) -> pkey
@@ -475,6 +610,17 @@ ossl_pkey_s_generate_key(int argc, VALUE *argv, VALUE self)
475
610
return pkey_generate (argc , argv , self , 0 );
476
611
}
477
612
613
+ static VALUE
614
+ ossl_pkey_s_from_parameters (int argc , VALUE * argv , VALUE self )
615
+ {
616
+ // TODO: A version that works with OpenSSL 1.1
617
+ #if OSSL_OPENSSL_PREREQ (3 , 0 , 0 )
618
+ return pkey_from_parameters (argc , argv , self );
619
+ #else
620
+ rb_raise (ePKeyError , "Only supported with OpenSSL 3.0" );
621
+ #endif
622
+ }
623
+
478
624
/*
479
625
* TODO: There is no convenient way to check the presence of public key
480
626
* components on OpenSSL 3.0. But since keys are immutable on 3.0, pkeys without
@@ -1586,6 +1732,7 @@ Init_ossl_pkey(void)
1586
1732
rb_define_module_function (mPKey , "read" , ossl_pkey_new_from_data , -1 );
1587
1733
rb_define_module_function (mPKey , "generate_parameters" , ossl_pkey_s_generate_parameters , -1 );
1588
1734
rb_define_module_function (mPKey , "generate_key" , ossl_pkey_s_generate_key , -1 );
1735
+ rb_define_module_function (mPKey , "from_parameters" , ossl_pkey_s_from_parameters , -1 );
1589
1736
1590
1737
rb_define_alloc_func (cPKey , ossl_pkey_alloc );
1591
1738
rb_define_method (cPKey , "initialize" , ossl_pkey_initialize , 0 );
0 commit comments