Skip to content

Commit d91d660

Browse files
committed
Use EVP_PKEY_fromdata_settable to figure out the supported parameters
1 parent 82c4de0 commit d91d660

File tree

2 files changed

+100
-177
lines changed

2 files changed

+100
-177
lines changed

ext/openssl/ossl_pkey.c

Lines changed: 99 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -427,178 +427,87 @@ pkey_generate(int argc, VALUE *argv, VALUE self, int genparam)
427427
#include <openssl/param_build.h>
428428
#include <openssl/core_names.h>
429429

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-
StringValue(value);
444-
if(!OSSL_PARAM_BLD_push_utf8_string(params_builder, key_ptr, RSTRING_PTR(value), RSTRING_LENINT(value))) {
445-
OSSL_PARAM_BLD_free(params_builder);
446-
ossl_raise(ePKeyError, "OSSL_PARAM_BLD_push_utf8_string");
447-
}
448-
return ST_CONTINUE;
449-
}
450-
451-
if(strcmp(OSSL_PKEY_PARAM_PUB_KEY, key_ptr) == 0) {
452-
StringValue(value);
453-
if(!OSSL_PARAM_BLD_push_octet_string(params_builder, OSSL_PKEY_PARAM_PUB_KEY, RSTRING_PTR(value), RSTRING_LENINT(value))) {
454-
OSSL_PARAM_BLD_free(params_builder);
455-
ossl_raise(ePKeyError, "OSSL_PARAM_BLD_push_octet_string");
456-
}
457-
return ST_CONTINUE;
458-
}
459-
460-
if(strcmp(OSSL_PKEY_PARAM_PRIV_KEY, key_ptr) == 0) {
461-
if(!OSSL_PARAM_BLD_push_BN(params_builder, OSSL_PKEY_PARAM_PRIV_KEY, GetBNPtr(value))) {
462-
OSSL_PARAM_BLD_free(params_builder);
463-
ossl_raise(ePKeyError, "OSSL_PARAM_BLD_push_BN");
464-
}
465-
return ST_CONTINUE;
466-
}
467-
468-
OSSL_PARAM_BLD_free(params_builder);
469-
ossl_raise(ePKeyError, "Unsupported parameter \"%s\"", key_ptr);
470-
}
471-
472-
static int
473-
add_rsa_parameters_to_builder(VALUE key, VALUE value, VALUE arg) {
474-
OSSL_PARAM_BLD *params_builder = (OSSL_PARAM_BLD *) arg;
475-
476-
if(NIL_P(value))
477-
return ST_CONTINUE;
478-
479-
if (SYMBOL_P(key))
480-
key = rb_sym2str(key);
481-
482-
static const struct {
483-
char alias[5];
484-
char param_name[20];
485-
} key_aliases[] = {
486-
{ "p", OSSL_PKEY_PARAM_RSA_FACTOR1 },
487-
{ "q", OSSL_PKEY_PARAM_RSA_FACTOR2 },
488-
{ "dmp1", OSSL_PKEY_PARAM_RSA_EXPONENT1 },
489-
{ "dmq1", OSSL_PKEY_PARAM_RSA_EXPONENT2 },
490-
{ "iqmp", OSSL_PKEY_PARAM_RSA_COEFFICIENT1 }
491-
};
492-
493-
const char * key_ptr = StringValueCStr(key);
494-
495-
for(int i = 0; i < (int)(sizeof(key_aliases)/sizeof((key_aliases)[0])); i++) {
496-
if(strcmp(key_aliases[i].alias, key_ptr) == 0) {
497-
key_ptr = key_aliases[i].param_name;
498-
break;
499-
}
500-
}
430+
struct pkey_from_parameters_alias {
431+
char alias[10];
432+
char param_name[20];
433+
};
501434

502-
if(strcmp(OSSL_PKEY_PARAM_RSA_N, key_ptr) == 0 ||
503-
strcmp(OSSL_PKEY_PARAM_RSA_E, key_ptr) == 0 ||
504-
strcmp(OSSL_PKEY_PARAM_RSA_D, key_ptr) == 0 ||
505-
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR1, key_ptr) == 0 ||
506-
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR2, key_ptr) == 0 ||
507-
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR3, key_ptr) == 0 ||
508-
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR4, key_ptr) == 0 ||
509-
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR5, key_ptr) == 0 ||
510-
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR6, key_ptr) == 0 ||
511-
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR7, key_ptr) == 0 ||
512-
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR8, key_ptr) == 0 ||
513-
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR9, key_ptr) == 0 ||
514-
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR10, key_ptr) == 0 ||
515-
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT1, key_ptr) == 0 ||
516-
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT2, key_ptr) == 0 ||
517-
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT3, key_ptr) == 0 ||
518-
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT4, key_ptr) == 0 ||
519-
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT5, key_ptr) == 0 ||
520-
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT6, key_ptr) == 0 ||
521-
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT7, key_ptr) == 0 ||
522-
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT8, key_ptr) == 0 ||
523-
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT9, key_ptr) == 0 ||
524-
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT10, key_ptr) == 0 ||
525-
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT1, key_ptr) == 0 ||
526-
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT2, key_ptr) == 0 ||
527-
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT3, key_ptr) == 0 ||
528-
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT4, key_ptr) == 0 ||
529-
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT5, key_ptr) == 0 ||
530-
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT6, key_ptr) == 0 ||
531-
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT7, key_ptr) == 0 ||
532-
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT8, key_ptr) == 0 ||
533-
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT9, key_ptr) == 0) {
534-
if(!OSSL_PARAM_BLD_push_BN(params_builder, key_ptr, GetBNPtr(value))) {
535-
OSSL_PARAM_BLD_free(params_builder);
536-
ossl_raise(ePKeyError, "OSSL_PARAM_BLD_push_BN");
537-
}
435+
static const struct pkey_from_parameters_alias rsa_aliases[] = {
436+
{ "p", OSSL_PKEY_PARAM_RSA_FACTOR1 },
437+
{ "q", OSSL_PKEY_PARAM_RSA_FACTOR2 },
438+
{ "dmp1", OSSL_PKEY_PARAM_RSA_EXPONENT1 },
439+
{ "dmq1", OSSL_PKEY_PARAM_RSA_EXPONENT2 },
440+
{ "iqmp", OSSL_PKEY_PARAM_RSA_COEFFICIENT1 }
441+
};
538442

539-
return ST_CONTINUE;
540-
}
443+
static const struct pkey_from_parameters_alias fcc_aliases[] = {
444+
{ "pub_key", OSSL_PKEY_PARAM_PUB_KEY },
445+
{ "priv_key", OSSL_PKEY_PARAM_PRIV_KEY }
446+
};
541447

542-
OSSL_PARAM_BLD_free(params_builder);
543-
ossl_raise(ePKeyError, "Unsupported parameter \"%s\"", key_ptr);
544-
}
448+
struct pkey_from_parameters_arg {
449+
OSSL_PARAM_BLD *param_bld;
450+
const OSSL_PARAM *settable_params;
451+
const struct pkey_from_parameters_alias *aliases;
452+
size_t nAliases;
453+
};
545454

546455
static int
547-
add_ffc_parameters_to_builder(VALUE key, VALUE value, VALUE arg) {
548-
OSSL_PARAM_BLD *params_builder = (OSSL_PARAM_BLD *) arg;
549-
456+
add_parameter_to_builder(VALUE key, VALUE value, VALUE arg) {
550457
if(NIL_P(value))
551458
return ST_CONTINUE;
552459

553460
if (SYMBOL_P(key))
554461
key = rb_sym2str(key);
555462

556-
static const struct {
557-
char alias[10];
558-
char param_name[20];
559-
} key_aliases[] = {
560-
{ "pub_key", OSSL_PKEY_PARAM_PUB_KEY },
561-
{ "priv_key", OSSL_PKEY_PARAM_PRIV_KEY }
562-
};
463+
const char *key_ptr = StringValueCStr(key);
464+
const struct pkey_from_parameters_arg *params = (const struct pkey_from_parameters_arg *) arg;
465+
const OSSL_PARAM *settable_params = params->settable_params;
563466

564-
const char * key_ptr = StringValueCStr(key);
565-
566-
for(int i = 0; i < (int)(sizeof(key_aliases)/sizeof((key_aliases)[0])); i++) {
567-
if(strcmp(key_aliases[i].alias, key_ptr) == 0) {
568-
key_ptr = key_aliases[i].param_name;
467+
for(size_t i = 0; i < params->nAliases; i++) {
468+
if(strcmp(params->aliases[i].alias, key_ptr) == 0) {
469+
key_ptr = params->aliases[i].param_name;
569470
break;
570471
}
571472
}
572473

573-
if(strcmp(OSSL_PKEY_PARAM_PUB_KEY, key_ptr) == 0 ||
574-
strcmp(OSSL_PKEY_PARAM_PRIV_KEY, key_ptr) == 0 ||
575-
strcmp(OSSL_PKEY_PARAM_FFC_P, key_ptr) == 0 ||
576-
strcmp(OSSL_PKEY_PARAM_FFC_G, key_ptr) == 0 ||
577-
strcmp(OSSL_PKEY_PARAM_FFC_Q, key_ptr) == 0 ||
578-
strcmp(OSSL_PKEY_PARAM_FFC_GINDEX, key_ptr) == 0 ||
579-
strcmp(OSSL_PKEY_PARAM_FFC_PCOUNTER, key_ptr) == 0 ||
580-
strcmp(OSSL_PKEY_PARAM_FFC_H, key_ptr) == 0 ||
581-
strcmp(OSSL_PKEY_PARAM_FFC_COFACTOR, key_ptr) == 0 ||
582-
strcmp(OSSL_PKEY_PARAM_FFC_VALIDATE_PQ, key_ptr) == 0 ||
583-
strcmp(OSSL_PKEY_PARAM_FFC_VALIDATE_G, key_ptr) == 0 ||
584-
strcmp(OSSL_PKEY_PARAM_FFC_VALIDATE_LEGACY, key_ptr) == 0) {
585-
if(!OSSL_PARAM_BLD_push_BN(params_builder, key_ptr, GetBNPtr(value))) {
586-
OSSL_PARAM_BLD_free(params_builder);
587-
ossl_raise(ePKeyError, "OSSL_PARAM_BLD_push_BN");
588-
}
589-
return ST_CONTINUE;
590-
}
591-
592-
if(strcmp(OSSL_PKEY_PARAM_FFC_SEED, key_ptr) == 0) {
593-
StringValue(value);
594-
if(!OSSL_PARAM_BLD_push_octet_string(params_builder, key_ptr, RSTRING_PTR(value), RSTRING_LENINT(value))) {
595-
OSSL_PARAM_BLD_free(params_builder);
596-
ossl_raise(ePKeyError, "OSSL_PARAM_BLD_push_octet_string");
474+
for (; settable_params->key != NULL; settable_params++) {
475+
if(strcmp(settable_params->key, key_ptr) == 0) {
476+
switch (settable_params->data_type) {
477+
case OSSL_PARAM_INTEGER:
478+
case OSSL_PARAM_UNSIGNED_INTEGER:
479+
if(!OSSL_PARAM_BLD_push_BN(params->param_bld, key_ptr, GetBNPtr(value))) {
480+
OSSL_PARAM_BLD_free(params->param_bld);
481+
ossl_raise(ePKeyError, "OSSL_PARAM_BLD_push_BN");
482+
}
483+
break;
484+
case OSSL_PARAM_UTF8_STRING:
485+
StringValue(value);
486+
if(!OSSL_PARAM_BLD_push_utf8_string(params->param_bld, key_ptr, RSTRING_PTR(value), RSTRING_LENINT(value))) {
487+
OSSL_PARAM_BLD_free(params->param_bld);
488+
ossl_raise(ePKeyError, "OSSL_PARAM_BLD_push_utf8_string");
489+
}
490+
break;
491+
492+
case OSSL_PARAM_OCTET_STRING:
493+
StringValue(value);
494+
if(!OSSL_PARAM_BLD_push_octet_string(params->param_bld, key_ptr, RSTRING_PTR(value), RSTRING_LENINT(value))) {
495+
OSSL_PARAM_BLD_free(params->param_bld);
496+
ossl_raise(ePKeyError, "OSSL_PARAM_BLD_push_octet_string");
497+
}
498+
break;
499+
case OSSL_PARAM_UTF8_PTR:
500+
case OSSL_PARAM_OCTET_PTR:
501+
OSSL_PARAM_BLD_free(params->param_bld);
502+
ossl_raise(ePKeyError, "Unsupported parameter \"%s\", type is not implemented", key_ptr);
503+
break;
504+
}
505+
506+
return ST_CONTINUE;
597507
}
598-
return ST_CONTINUE;
599508
}
600509

601-
OSSL_PARAM_BLD_free(params_builder);
510+
OSSL_PARAM_BLD_free(params->param_bld);
602511
ossl_raise(ePKeyError, "Unsupported parameter \"%s\"", key_ptr);
603512
}
604513

@@ -608,42 +517,56 @@ pkey_from_parameters(int argc, VALUE *argv, VALUE self)
608517
VALUE alg, options;
609518
rb_scan_args(argc, argv, "11", &alg, &options);
610519

611-
OSSL_PARAM_BLD *params_builder = OSSL_PARAM_BLD_new();
520+
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, StringValueCStr(alg), NULL);
521+
522+
if (ctx == NULL)
523+
ossl_raise(ePKeyError, "EVP_PKEY_CTX_new_from_name");
524+
525+
struct pkey_from_parameters_arg from_params_args;
612526

613-
if (params_builder == NULL)
527+
from_params_args.param_bld = OSSL_PARAM_BLD_new();
528+
529+
if (from_params_args.param_bld == NULL)
614530
ossl_raise(ePKeyError, "OSSL_PARAM_BLD_new");
615531

616-
int (*param_adder)(VALUE, VALUE, VALUE) = NULL;
532+
from_params_args.settable_params = EVP_PKEY_fromdata_settable(ctx, EVP_PKEY_KEYPAIR);
617533

618-
if(strcmp("RSA", StringValueCStr(alg)) == 0)
619-
param_adder = &add_rsa_parameters_to_builder;
620-
else if (strcmp("EC", StringValueCStr(alg)) == 0)
621-
param_adder = &add_ec_parameters_to_builder;
622-
else if (strcmp("DSA", StringValueCStr(alg)) == 0)
623-
param_adder = &add_ffc_parameters_to_builder;
624-
else if (strcmp("DH", StringValueCStr(alg)) == 0)
625-
param_adder = &add_ffc_parameters_to_builder;
626-
else
627-
ossl_raise(ePKeyError, "\"%s\" is not a supported algorithm", StringValueCStr(alg));
534+
if (strcmp("RSA", StringValueCStr(alg)) == 0) {
535+
from_params_args.aliases = rsa_aliases;
536+
from_params_args.nAliases = sizeof(rsa_aliases)/sizeof((rsa_aliases)[0]);
537+
} else if (strcmp("DSA", StringValueCStr(alg)) == 0 ||
538+
strcmp("DH", StringValueCStr(alg)) == 0) {
539+
from_params_args.aliases = fcc_aliases;
540+
from_params_args.nAliases = sizeof(fcc_aliases)/sizeof((fcc_aliases)[0]);
541+
} else {
542+
from_params_args.nAliases = 0;
543+
}
628544

629-
rb_hash_foreach(options, param_adder, (VALUE) params_builder);
545+
rb_hash_foreach(options, &add_parameter_to_builder, (VALUE) &from_params_args);
630546

631-
OSSL_PARAM *params = OSSL_PARAM_BLD_to_param(params_builder);
632-
OSSL_PARAM_BLD_free(params_builder);
547+
OSSL_PARAM *params = OSSL_PARAM_BLD_to_param(from_params_args.param_bld);
548+
OSSL_PARAM_BLD_free(from_params_args.param_bld);
633549

634-
if (params == NULL)
550+
if (params == NULL) {
551+
EVP_PKEY_CTX_free(ctx);
635552
ossl_raise(ePKeyError, "OSSL_PARAM_BLD_to_param");
553+
}
636554

637-
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, StringValueCStr(alg), NULL);
638-
EVP_PKEY *pkey = NULL;
555+
EVP_PKEY *pkey = NULL;
639556

640-
if (ctx == NULL ||
641-
EVP_PKEY_fromdata_init(ctx) <= 0 ||
642-
EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) {
643-
ossl_clear_error();
557+
if (EVP_PKEY_fromdata_init(ctx) <= 0) {
558+
EVP_PKEY_CTX_free(ctx);
559+
ossl_raise(ePKeyError, "EVP_PKEY_fromdata_init");
560+
}
561+
562+
if(EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) {
563+
EVP_PKEY_CTX_free(ctx);
564+
EVP_PKEY_free(pkey);
644565
ossl_raise(ePKeyError, "EVP_PKEY_fromdata");
645566
}
646567

568+
EVP_PKEY_CTX_free(ctx);
569+
647570
return ossl_pkey_new(pkey);
648571
}
649572
#endif

test/openssl/test_pkey.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ def test_from_parameters_with_invalid_alg
180180
e = assert_raise(OpenSSL::PKey::PKeyError) {
181181
OpenSSL::PKey.from_parameters("ASR", {})
182182
}
183-
assert_equal e.message, '"ASR" is not a supported algorithm'
183+
assert_equal e.message, 'EVP_PKEY_CTX_new_from_name: unsupported'
184184
end
185185

186186
def test_s_from_parameters_rsa_with_n_e_and_d_given_as_integers

0 commit comments

Comments
 (0)