Skip to content

Commit 5d0d25c

Browse files
committed
Support for generating DSA keys from parameters
1 parent 1588b2c commit 5d0d25c

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
@@ -171,7 +171,14 @@ def test_to_text
171171
end
172172

173173
if openssl?(3, 0, 0)
174-
def test_rsa_from_parameters_with_n_e_and_d_given_as_integers
174+
def test_from_parameters_with_invalid_alg
175+
e = assert_raise(OpenSSL::PKey::PKeyError) {
176+
OpenSSL::PKey.from_parameters("ASR", {})
177+
}
178+
assert_equal e.message, '"ASR" is not a supported algorithm'
179+
end
180+
181+
def test_s_from_parameters_rsa_with_n_e_and_d_given_as_integers
175182
new_key = OpenSSL::PKey.from_parameters("RSA", n: 3161751493,
176183
e: 65537,
177184
d: 2064855961)
@@ -183,8 +190,7 @@ def test_rsa_from_parameters_with_n_e_and_d_given_as_integers
183190
assert_equal OpenSSL::BN.new(2064855961), new_key.d
184191
end
185192

186-
187-
def test_rsa_from_parameters_with_n_e_and_d_given
193+
def test_s_from_parameters_rsa_with_n_e_and_d_given
188194
new_key = OpenSSL::PKey.from_parameters("RSA", "n" => OpenSSL::BN.new(3161751493),
189195
"e" => OpenSSL::BN.new(65537),
190196
"d" => OpenSSL::BN.new(2064855961))
@@ -196,7 +202,7 @@ def test_rsa_from_parameters_with_n_e_and_d_given
196202
assert_equal OpenSSL::BN.new(2064855961), new_key.d
197203
end
198204

199-
def test_rsa_from_parameters_with_n_and_e_given
205+
def test_s_from_parameters_rsa_with_n_and_e_given
200206
new_key = OpenSSL::PKey.from_parameters("RSA", n: OpenSSL::BN.new(3161751493),
201207
e: OpenSSL::BN.new(65537))
202208

@@ -207,7 +213,7 @@ def test_rsa_from_parameters_with_n_and_e_given
207213
assert_equal nil, new_key.d
208214
end
209215

210-
def test_rsa_from_parameters_with_openssl_internal_names
216+
def test_s_from_parameters_rsa_with_openssl_internal_names
211217
source = OpenSSL::PKey::RSA.generate(2048)
212218
new_key = OpenSSL::PKey.from_parameters("RSA", n: source.n,
213219
e: source.e,
@@ -231,7 +237,7 @@ def test_rsa_from_parameters_with_openssl_internal_names
231237
assert_equal source.to_pem, new_key.to_pem
232238
end
233239

234-
def test_rsa_from_parameters_with_simple_names
240+
def test_s_from_parameters_rsa_with_simple_names
235241
source = OpenSSL::PKey::RSA.generate(2048)
236242
new_key = OpenSSL::PKey.from_parameters("RSA", n: source.n,
237243
e: source.e,
@@ -255,14 +261,12 @@ def test_rsa_from_parameters_with_simple_names
255261
assert_equal source.to_pem, new_key.to_pem
256262
end
257263

258-
def test_from_parameters_with_invalid_alg
259-
e = assert_raise(OpenSSL::PKey::PKeyError) {
260-
OpenSSL::PKey.from_parameters("ASR", {})
261-
}
262-
assert_equal e.message, '"ASR" is not a supported algorithm'
264+
def test_s_from_parameters_rsa_with_invalid_parameter
265+
e = assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.from_parameters("RSA", invalid: 1234) }
266+
assert_equal 'Unsupported RSA parameter "invalid"', e.message
263267
end
264268

265-
def test_ec_from_parameters_pub_given_as_string
269+
def test_s_from_parameters_ec_pub_given_as_string
266270
source = OpenSSL::PKey::EC.generate("prime256v1")
267271
new_key = OpenSSL::PKey.from_parameters("EC", { group: source.group.curve_name,
268272
pub: source.public_key.to_bn.to_s(2) })
@@ -272,7 +276,7 @@ def test_ec_from_parameters_pub_given_as_string
272276
assert_equal nil, new_key.private_key
273277
end
274278

275-
def test_ec_from_parameters_priv_given_as_bn
279+
def test_s_from_parameters_ec_priv_given_as_bn
276280
source = OpenSSL::PKey::EC.generate("prime256v1")
277281
new_key = OpenSSL::PKey.from_parameters("EC", { group: source.group.curve_name,
278282
priv: source.private_key.to_bn })
@@ -282,7 +286,7 @@ def test_ec_from_parameters_priv_given_as_bn
282286
assert_equal nil, new_key.public_key
283287
end
284288

285-
def test_ec_from_parameters_priv_given_as_integer
289+
def test_s_from_parameters_ec_priv_given_as_integer
286290
source = OpenSSL::PKey::EC.generate("prime256v1")
287291
new_key = OpenSSL::PKey.from_parameters("EC", { group: source.group.curve_name,
288292
priv: source.private_key.to_i })
@@ -292,7 +296,7 @@ def test_ec_from_parameters_priv_given_as_integer
292296
assert_equal nil, new_key.public_key
293297
end
294298

295-
def test_ec_from_parameters_priv_and_pub_given_for_different_curves
299+
def test_s_from_parameters_ec_priv_and_pub_given_for_different_curves
296300
["prime256v1", "secp256k1", "secp384r1", "secp521r1"].each do |curve|
297301
source = OpenSSL::PKey::EC.generate(curve)
298302
new_key = OpenSSL::PKey.from_parameters("EC", { group: source.group.curve_name,
@@ -305,10 +309,40 @@ def test_ec_from_parameters_priv_and_pub_given_for_different_curves
305309
end
306310
end
307311

308-
def test_ec_from_parameters_pub_given_as_integer
312+
def test_s_from_parameters_ec_pub_given_as_integer
309313
e = assert_raise(TypeError) { OpenSSL::PKey.from_parameters("EC", { group: "prime256v1", pub: 12345 }) }
310314
assert_equal "no implicit conversion of Integer into String", e.message
311315
end
316+
317+
def test_s_from_parameters_ec_with_invalid_parameter
318+
e = assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.from_parameters("EC", invalid: 1234) }
319+
assert_equal 'Unsupported EC parameter "invalid"', e.message
320+
end
321+
322+
def test_s_from_parameters_dsa_with_all_supported_parameters
323+
source = OpenSSL::PKey::DSA.generate(2048)
324+
325+
new_key = OpenSSL::PKey.from_parameters("DSA", pub: source.params["pub_key"],
326+
priv: source.params["priv_key"],
327+
p: source.params["p"],
328+
q: source.params["q"],
329+
g: source.params["g"])
330+
331+
assert_equal source.params, new_key.params
332+
end
333+
334+
def test_s_from_parameters_dsa_with_gem_specific_keys
335+
source = OpenSSL::PKey::DSA.generate(2048)
336+
337+
new_key = OpenSSL::PKey.from_parameters("DSA", source.params)
338+
339+
assert_equal source.params, new_key.params
340+
end
341+
342+
def test_s_from_parameters_dsa_with_invalid_parameter
343+
e = assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.from_parameters("DSA", invalid: 1234) }
344+
assert_equal 'Unsupported DSA parameter "invalid"', e.message
345+
end
312346
else
313347
def test_from_parameter_raises_on_pre_3_openssl
314348
e = assert_raise(OpenSSL::PKey::PKeyError) {

0 commit comments

Comments
 (0)