Skip to content

Commit 9683dfa

Browse files
committed
Support for generating DSA keys from parameters
1 parent c85f7a1 commit 9683dfa

File tree

2 files changed

+145
-55
lines changed

2 files changed

+145
-55
lines changed

ext/openssl/ossl_pkey.c

Lines changed: 95 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ add_ec_parameters_to_builder(VALUE key, VALUE value, VALUE arg) {
455455

456456
if(strcmp(OSSL_PKEY_PARAM_PRIV_KEY, key_ptr) == 0) {
457457
if(!OSSL_PARAM_BLD_push_BN(params_builder, OSSL_PKEY_PARAM_PRIV_KEY, GetBNPtr(value))) // unsigned integer, but presented as BN will work just fine
458-
ossl_raise(ePKeyError, "OSSL_PARAM_BLD_push_octet_string");
458+
ossl_raise(ePKeyError, "OSSL_PARAM_BLD_push_BN");
459459
return ST_CONTINUE;
460460
}
461461

@@ -492,44 +492,98 @@ add_rsa_parameters_to_builder(VALUE key, VALUE value, VALUE arg) {
492492
}
493493
}
494494

495-
if((strcmp(OSSL_PKEY_PARAM_RSA_N, key_ptr) != 0 &&
496-
strcmp(OSSL_PKEY_PARAM_RSA_E, key_ptr) != 0 &&
497-
strcmp(OSSL_PKEY_PARAM_RSA_D, key_ptr) != 0 &&
498-
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR1, key_ptr) != 0 &&
499-
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR2, key_ptr) != 0 &&
500-
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR3, key_ptr) != 0 &&
501-
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR4, key_ptr) != 0 &&
502-
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR5, key_ptr) != 0 &&
503-
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR6, key_ptr) != 0 &&
504-
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR7, key_ptr) != 0 &&
505-
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR8, key_ptr) != 0 &&
506-
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR9, key_ptr) != 0 &&
507-
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR10, key_ptr) != 0 &&
508-
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT1, key_ptr) != 0 &&
509-
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT2, key_ptr) != 0 &&
510-
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT3, key_ptr) != 0 &&
511-
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT4, key_ptr) != 0 &&
512-
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT5, key_ptr) != 0 &&
513-
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT6, key_ptr) != 0 &&
514-
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT7, key_ptr) != 0 &&
515-
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT8, key_ptr) != 0 &&
516-
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT9, key_ptr) != 0 &&
517-
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT10, key_ptr) != 0 &&
518-
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT1, key_ptr) != 0 &&
519-
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT2, key_ptr) != 0 &&
520-
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT3, key_ptr) != 0 &&
521-
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT4, key_ptr) != 0 &&
522-
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT5, key_ptr) != 0 &&
523-
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT6, key_ptr) != 0 &&
524-
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT7, key_ptr) != 0 &&
525-
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT8, key_ptr) != 0 &&
526-
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT9, key_ptr)) != 0)
527-
ossl_raise(ePKeyError, "Unsupported RSA parameter \"%s\"", key_ptr);
528-
529-
if(!OSSL_PARAM_BLD_push_BN(params_builder, key_ptr, GetBNPtr(value)))
530-
ossl_raise(ePKeyError, "OSSL_PARAM_BLD_push_BN");
531-
532-
return ST_CONTINUE;
495+
if(strcmp(OSSL_PKEY_PARAM_RSA_N, key_ptr) == 0 ||
496+
strcmp(OSSL_PKEY_PARAM_RSA_E, key_ptr) == 0 ||
497+
strcmp(OSSL_PKEY_PARAM_RSA_D, key_ptr) == 0 ||
498+
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR1, key_ptr) == 0 ||
499+
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR2, key_ptr) == 0 ||
500+
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR3, key_ptr) == 0 ||
501+
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR4, key_ptr) == 0 ||
502+
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR5, key_ptr) == 0 ||
503+
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR6, key_ptr) == 0 ||
504+
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR7, key_ptr) == 0 ||
505+
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR8, key_ptr) == 0 ||
506+
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR9, key_ptr) == 0 ||
507+
strcmp(OSSL_PKEY_PARAM_RSA_FACTOR10, key_ptr) == 0 ||
508+
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT1, key_ptr) == 0 ||
509+
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT2, key_ptr) == 0 ||
510+
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT3, key_ptr) == 0 ||
511+
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT4, key_ptr) == 0 ||
512+
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT5, key_ptr) == 0 ||
513+
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT6, key_ptr) == 0 ||
514+
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT7, key_ptr) == 0 ||
515+
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT8, key_ptr) == 0 ||
516+
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT9, key_ptr) == 0 ||
517+
strcmp(OSSL_PKEY_PARAM_RSA_EXPONENT10, key_ptr) == 0 ||
518+
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT1, key_ptr) == 0 ||
519+
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT2, key_ptr) == 0 ||
520+
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT3, key_ptr) == 0 ||
521+
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT4, key_ptr) == 0 ||
522+
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT5, key_ptr) == 0 ||
523+
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT6, key_ptr) == 0 ||
524+
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT7, key_ptr) == 0 ||
525+
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT8, key_ptr) == 0 ||
526+
strcmp(OSSL_PKEY_PARAM_RSA_COEFFICIENT9, key_ptr) == 0) {
527+
if(!OSSL_PARAM_BLD_push_BN(params_builder, key_ptr, GetBNPtr(value)))
528+
ossl_raise(ePKeyError, "OSSL_PARAM_BLD_push_BN");
529+
return ST_CONTINUE;
530+
}
531+
532+
ossl_raise(ePKeyError, "Unsupported RSA parameter \"%s\"", key_ptr);
533+
}
534+
535+
static int
536+
add_dsa_parameters_to_builder(VALUE key, VALUE value, VALUE arg) {
537+
OSSL_PARAM_BLD *params_builder = (OSSL_PARAM_BLD *) arg;
538+
539+
if(NIL_P(value))
540+
return ST_CONTINUE;
541+
542+
if (SYMBOL_P(key))
543+
key = rb_sym2str(key);
544+
545+
static const struct {
546+
char alias[10];
547+
char param_name[20];
548+
} key_aliases[] = {
549+
{ "pub_key", OSSL_PKEY_PARAM_PUB_KEY },
550+
{ "priv_key", OSSL_PKEY_PARAM_PRIV_KEY }
551+
};
552+
553+
const char * key_ptr = StringValueCStr(key);
554+
555+
for(int i = 0; i < (int)(sizeof(key_aliases)/sizeof((key_aliases)[0])); i++) {
556+
if(strcmp(key_aliases[i].alias, key_ptr) == 0) {
557+
key_ptr = key_aliases[i].param_name;
558+
break;
559+
}
560+
}
561+
562+
if(strcmp(OSSL_PKEY_PARAM_PUB_KEY, key_ptr) == 0 ||
563+
strcmp(OSSL_PKEY_PARAM_PRIV_KEY, key_ptr) == 0 ||
564+
strcmp(OSSL_PKEY_PARAM_FFC_P, key_ptr) == 0 ||
565+
strcmp(OSSL_PKEY_PARAM_FFC_G, key_ptr) == 0 ||
566+
strcmp(OSSL_PKEY_PARAM_FFC_Q, key_ptr) == 0 ||
567+
strcmp(OSSL_PKEY_PARAM_FFC_GINDEX, key_ptr) == 0 ||
568+
strcmp(OSSL_PKEY_PARAM_FFC_PCOUNTER, key_ptr) == 0 ||
569+
strcmp(OSSL_PKEY_PARAM_FFC_H, key_ptr) == 0 ||
570+
strcmp(OSSL_PKEY_PARAM_FFC_COFACTOR, key_ptr) == 0 ||
571+
strcmp(OSSL_PKEY_PARAM_FFC_VALIDATE_PQ, key_ptr) == 0 ||
572+
strcmp(OSSL_PKEY_PARAM_FFC_VALIDATE_G, key_ptr) == 0 ||
573+
strcmp(OSSL_PKEY_PARAM_FFC_VALIDATE_LEGACY, key_ptr) == 0) {
574+
if(!OSSL_PARAM_BLD_push_BN(params_builder, key_ptr, GetBNPtr(value)))
575+
ossl_raise(ePKeyError, "OSSL_PARAM_BLD_push_BN");
576+
return ST_CONTINUE;
577+
}
578+
579+
if(strcmp(OSSL_PKEY_PARAM_FFC_SEED, key_ptr) == 0) {
580+
StringValue(value);
581+
if(!OSSL_PARAM_BLD_push_octet_string(params_builder, key_ptr, RSTRING_PTR(value), RSTRING_LENINT(value)))
582+
ossl_raise(ePKeyError, "OSSL_PARAM_BLD_push_octet_string");
583+
return ST_CONTINUE;
584+
}
585+
586+
ossl_raise(ePKeyError, "Unsupported DSA parameter \"%s\"", key_ptr);
533587
}
534588

535589
static VALUE
@@ -549,6 +603,8 @@ pkey_from_parameters(int argc, VALUE *argv, VALUE self)
549603
param_adder = &add_rsa_parameters_to_builder;
550604
else if (strcmp("EC", StringValueCStr(alg)) == 0)
551605
param_adder = &add_ec_parameters_to_builder;
606+
else if (strcmp("DSA", StringValueCStr(alg)) == 0)
607+
param_adder = &add_dsa_parameters_to_builder;
552608
else
553609
ossl_raise(ePKeyError, "\"%s\" is not a supported algorithm", StringValueCStr(alg));
554610

test/openssl/test_pkey.rb

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,14 @@ def test_to_text
176176
end
177177

178178
if openssl?(3, 0, 0)
179-
def test_rsa_from_parameters_with_n_e_and_d_given_as_integers
179+
def test_from_parameters_with_invalid_alg
180+
e = assert_raise(OpenSSL::PKey::PKeyError) {
181+
OpenSSL::PKey.from_parameters("ASR", {})
182+
}
183+
assert_equal e.message, '"ASR" is not a supported algorithm'
184+
end
185+
186+
def test_s_from_parameters_rsa_with_n_e_and_d_given_as_integers
180187
new_key = OpenSSL::PKey.from_parameters("RSA", n: 3161751493,
181188
e: 65537,
182189
d: 2064855961)
@@ -188,8 +195,7 @@ def test_rsa_from_parameters_with_n_e_and_d_given_as_integers
188195
assert_equal OpenSSL::BN.new(2064855961), new_key.d
189196
end
190197

191-
192-
def test_rsa_from_parameters_with_n_e_and_d_given
198+
def test_s_from_parameters_rsa_with_n_e_and_d_given
193199
new_key = OpenSSL::PKey.from_parameters("RSA", "n" => OpenSSL::BN.new(3161751493),
194200
"e" => OpenSSL::BN.new(65537),
195201
"d" => OpenSSL::BN.new(2064855961))
@@ -201,7 +207,7 @@ def test_rsa_from_parameters_with_n_e_and_d_given
201207
assert_equal OpenSSL::BN.new(2064855961), new_key.d
202208
end
203209

204-
def test_rsa_from_parameters_with_n_and_e_given
210+
def test_s_from_parameters_rsa_with_n_and_e_given
205211
new_key = OpenSSL::PKey.from_parameters("RSA", n: OpenSSL::BN.new(3161751493),
206212
e: OpenSSL::BN.new(65537))
207213

@@ -212,7 +218,7 @@ def test_rsa_from_parameters_with_n_and_e_given
212218
assert_equal nil, new_key.d
213219
end
214220

215-
def test_rsa_from_parameters_with_openssl_internal_names
221+
def test_s_from_parameters_rsa_with_openssl_internal_names
216222
source = OpenSSL::PKey::RSA.generate(2048)
217223
new_key = OpenSSL::PKey.from_parameters("RSA", n: source.n,
218224
e: source.e,
@@ -236,7 +242,7 @@ def test_rsa_from_parameters_with_openssl_internal_names
236242
assert_equal source.to_pem, new_key.to_pem
237243
end
238244

239-
def test_rsa_from_parameters_with_simple_names
245+
def test_s_from_parameters_rsa_with_simple_names
240246
source = OpenSSL::PKey::RSA.generate(2048)
241247
new_key = OpenSSL::PKey.from_parameters("RSA", n: source.n,
242248
e: source.e,
@@ -260,14 +266,12 @@ def test_rsa_from_parameters_with_simple_names
260266
assert_equal source.to_pem, new_key.to_pem
261267
end
262268

263-
def test_from_parameters_with_invalid_alg
264-
e = assert_raise(OpenSSL::PKey::PKeyError) {
265-
OpenSSL::PKey.from_parameters("ASR", {})
266-
}
267-
assert_equal e.message, '"ASR" is not a supported algorithm'
269+
def test_s_from_parameters_rsa_with_invalid_parameter
270+
e = assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.from_parameters("RSA", invalid: 1234) }
271+
assert_equal 'Unsupported RSA parameter "invalid"', e.message
268272
end
269273

270-
def test_ec_from_parameters_pub_given_as_string
274+
def test_s_from_parameters_ec_pub_given_as_string
271275
source = OpenSSL::PKey::EC.generate("prime256v1")
272276
new_key = OpenSSL::PKey.from_parameters("EC", { group: source.group.curve_name,
273277
pub: source.public_key.to_bn.to_s(2) })
@@ -277,7 +281,7 @@ def test_ec_from_parameters_pub_given_as_string
277281
assert_equal nil, new_key.private_key
278282
end
279283

280-
def test_ec_from_parameters_priv_given_as_bn
284+
def test_s_from_parameters_ec_priv_given_as_bn
281285
source = OpenSSL::PKey::EC.generate("prime256v1")
282286
new_key = OpenSSL::PKey.from_parameters("EC", { group: source.group.curve_name,
283287
priv: source.private_key.to_bn })
@@ -287,7 +291,7 @@ def test_ec_from_parameters_priv_given_as_bn
287291
assert_equal nil, new_key.public_key
288292
end
289293

290-
def test_ec_from_parameters_priv_given_as_integer
294+
def test_s_from_parameters_ec_priv_given_as_integer
291295
source = OpenSSL::PKey::EC.generate("prime256v1")
292296
new_key = OpenSSL::PKey.from_parameters("EC", { group: source.group.curve_name,
293297
priv: source.private_key.to_i })
@@ -297,7 +301,7 @@ def test_ec_from_parameters_priv_given_as_integer
297301
assert_equal nil, new_key.public_key
298302
end
299303

300-
def test_ec_from_parameters_priv_and_pub_given_for_different_curves
304+
def test_s_from_parameters_ec_priv_and_pub_given_for_different_curves
301305
["prime256v1", "secp256k1", "secp384r1", "secp521r1"].each do |curve|
302306
source = OpenSSL::PKey::EC.generate(curve)
303307
new_key = OpenSSL::PKey.from_parameters("EC", { group: source.group.curve_name,
@@ -310,10 +314,40 @@ def test_ec_from_parameters_priv_and_pub_given_for_different_curves
310314
end
311315
end
312316

313-
def test_ec_from_parameters_pub_given_as_integer
317+
def test_s_from_parameters_ec_pub_given_as_integer
314318
e = assert_raise(TypeError) { OpenSSL::PKey.from_parameters("EC", { group: "prime256v1", pub: 12345 }) }
315319
assert_equal "no implicit conversion of Integer into String", e.message
316320
end
321+
322+
def test_s_from_parameters_ec_with_invalid_parameter
323+
e = assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.from_parameters("EC", invalid: 1234) }
324+
assert_equal 'Unsupported EC parameter "invalid"', e.message
325+
end
326+
327+
def test_s_from_parameters_dsa_with_all_supported_parameters
328+
source = OpenSSL::PKey::DSA.generate(2048)
329+
330+
new_key = OpenSSL::PKey.from_parameters("DSA", pub: source.params["pub_key"],
331+
priv: source.params["priv_key"],
332+
p: source.params["p"],
333+
q: source.params["q"],
334+
g: source.params["g"])
335+
336+
assert_equal source.params, new_key.params
337+
end
338+
339+
def test_s_from_parameters_dsa_with_gem_specific_keys
340+
source = OpenSSL::PKey::DSA.generate(2048)
341+
342+
new_key = OpenSSL::PKey.from_parameters("DSA", source.params)
343+
344+
assert_equal source.params, new_key.params
345+
end
346+
347+
def test_s_from_parameters_dsa_with_invalid_parameter
348+
e = assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.from_parameters("DSA", invalid: 1234) }
349+
assert_equal 'Unsupported DSA parameter "invalid"', e.message
350+
end
317351
else
318352
def test_from_parameter_raises_on_pre_3_openssl
319353
e = assert_raise(OpenSSL::PKey::PKeyError) {

0 commit comments

Comments
 (0)