|
13 | 13 | # include <openssl/engine.h>
|
14 | 14 | #endif
|
15 | 15 |
|
| 16 | +#if OSSL_OPENSSL_PREREQ(3, 0, 0) |
| 17 | +# include <openssl/param_build.h> |
| 18 | +#endif |
| 19 | + |
16 | 20 | /*
|
17 | 21 | * Classes
|
18 | 22 | */
|
@@ -180,6 +184,150 @@ ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self)
|
180 | 184 | return ossl_pkey_new(pkey);
|
181 | 185 | }
|
182 | 186 |
|
| 187 | +struct ossl_params_build_args { |
| 188 | + const OSSL_PARAM *settable; |
| 189 | + VALUE hash, *memo; |
| 190 | + OSSL_PARAM_BLD *param_bld; |
| 191 | +}; |
| 192 | + |
| 193 | +static int |
| 194 | +ossl_params_set_i(VALUE key, VALUE value, VALUE _args) |
| 195 | +{ |
| 196 | + struct ossl_params_build_args *args = (void *)_args; |
| 197 | + const OSSL_PARAM *p; |
| 198 | + int ret; |
| 199 | + |
| 200 | + if (SYMBOL_P(key)) |
| 201 | + key = rb_sym2str(key); |
| 202 | + p = OSSL_PARAM_locate_const(args->settable, StringValueCStr(key)); |
| 203 | + if (p == NULL) |
| 204 | + rb_raise(eOSSLError, "key not settable: %"PRIsVALUE, key); |
| 205 | + |
| 206 | + switch (p->data_type) { |
| 207 | + case OSSL_PARAM_INTEGER: |
| 208 | + case OSSL_PARAM_UNSIGNED_INTEGER: |
| 209 | + ret = OSSL_PARAM_BLD_push_BN(args->param_bld, p->key, |
| 210 | + GetBNPtr(value)); |
| 211 | + break; |
| 212 | + case OSSL_PARAM_UTF8_STRING: |
| 213 | + ret = OSSL_PARAM_BLD_push_utf8_string(args->param_bld, p->key, |
| 214 | + StringValueCStr(value), |
| 215 | + RSTRING_LEN(value)); |
| 216 | + break; |
| 217 | + case OSSL_PARAM_OCTET_STRING: |
| 218 | + ret = OSSL_PARAM_BLD_push_octet_string(args->param_bld, p->key, |
| 219 | + StringValuePtr(value), |
| 220 | + RSTRING_LEN(value)); |
| 221 | + break; |
| 222 | + case OSSL_PARAM_UTF8_PTR: |
| 223 | + ret = OSSL_PARAM_BLD_push_utf8_ptr(args->param_bld, p->key, |
| 224 | + StringValueCStr(value), |
| 225 | + RSTRING_LEN(value)); |
| 226 | + if (*args->memo == Qundef) |
| 227 | + *args->memo = rb_ary_new(); |
| 228 | + rb_ary_push(*args->memo, value); |
| 229 | + break; |
| 230 | + case OSSL_PARAM_OCTET_PTR: |
| 231 | + ret = OSSL_PARAM_BLD_push_utf8_ptr(args->param_bld, p->key, |
| 232 | + StringValuePtr(value), |
| 233 | + RSTRING_LEN(value)); |
| 234 | + if (*args->memo == Qundef) |
| 235 | + *args->memo = rb_ary_new(); |
| 236 | + rb_ary_push(*args->memo, value); |
| 237 | + break; |
| 238 | + default: |
| 239 | + rb_raise(eOSSLError, "unsupported data type %d for key %s", |
| 240 | + (int)p->data_type, p->key); |
| 241 | + } |
| 242 | + |
| 243 | + if (ret <= 0) |
| 244 | + ossl_raise(eOSSLError, "OSSL_PARAM_BLD_push*"); |
| 245 | + |
| 246 | + return ST_CONTINUE; |
| 247 | +} |
| 248 | + |
| 249 | +static VALUE |
| 250 | +ossl_params_build(VALUE _args) |
| 251 | +{ |
| 252 | + struct ossl_params_build_args *args = (void *)_args; |
| 253 | + OSSL_PARAM *params; |
| 254 | + |
| 255 | + args->param_bld = OSSL_PARAM_BLD_new(); |
| 256 | + if (args->param_bld == NULL) |
| 257 | + ossl_raise(eOSSLError, "OSSL_PARAM_BLD_new"); |
| 258 | + |
| 259 | + rb_hash_foreach(args->hash, ossl_params_set_i, _args); |
| 260 | + |
| 261 | + params = OSSL_PARAM_BLD_to_param(args->param_bld); |
| 262 | + if (!params) |
| 263 | + ossl_raise(eOSSLError, "OSSL_PARAM_BLD_to_params"); |
| 264 | + |
| 265 | + return (VALUE)params; |
| 266 | +} |
| 267 | + |
| 268 | +static OSSL_PARAM * |
| 269 | +ossl_protect_params_build(const OSSL_PARAM *settable, VALUE hash, |
| 270 | + VALUE *memo, int *state) |
| 271 | +{ |
| 272 | + struct ossl_params_build_args args; |
| 273 | + OSSL_PARAM *params; |
| 274 | + |
| 275 | + args.settable = settable; |
| 276 | + args.hash = hash; |
| 277 | + args.memo = memo; |
| 278 | + |
| 279 | + params = (void *)rb_protect(ossl_params_build, (VALUE)&args, state); |
| 280 | + OSSL_PARAM_BLD_free(args.param_bld); |
| 281 | + return params; |
| 282 | +} |
| 283 | + |
| 284 | +/* |
| 285 | + * call-seq: |
| 286 | + * OpenSSL::PKey.from_data(algo, selection, hash) -> pkey |
| 287 | + */ |
| 288 | +static VALUE |
| 289 | +ossl_pkey_s_from_data(int argc, VALUE *argv, VALUE self) |
| 290 | +{ |
| 291 | + VALUE type, vselection, hash, memo; |
| 292 | + const OSSL_PARAM *settable; |
| 293 | + OSSL_PARAM *params; |
| 294 | + EVP_PKEY_CTX *pctx; |
| 295 | + EVP_PKEY *pkey = NULL; |
| 296 | + int selection, state, ret; |
| 297 | + |
| 298 | + rb_scan_args(argc, argv, "3", &type, &vselection, &hash); |
| 299 | + selection = NUM2INT(vselection); |
| 300 | + StringValueCStr(type); |
| 301 | + Check_Type(hash, T_HASH); |
| 302 | + |
| 303 | + pctx = EVP_PKEY_CTX_new_from_name(NULL, RSTRING_PTR(type), NULL); |
| 304 | + if (!pctx) |
| 305 | + ossl_raise(ePKeyError, "EVP_PKEY_CTX_new_from_name"); |
| 306 | + settable = EVP_PKEY_fromdata_settable(pctx, selection); |
| 307 | + if (!settable) { |
| 308 | + EVP_PKEY_CTX_free(pctx); |
| 309 | + ossl_raise(ePKeyError, "EVP_PKEY_fromdata_settable"); |
| 310 | + } |
| 311 | + |
| 312 | + params = ossl_protect_params_build(settable, hash, &memo, &state); |
| 313 | + if (state) { |
| 314 | + EVP_PKEY_CTX_free(pctx); |
| 315 | + rb_jump_tag(state); |
| 316 | + } |
| 317 | + |
| 318 | + if (EVP_PKEY_fromdata_init(pctx) <= 0) { |
| 319 | + EVP_PKEY_CTX_free(pctx); |
| 320 | + ossl_raise(ePKeyError, "EVP_PKEY_fromdata_init"); |
| 321 | + } |
| 322 | + ret = EVP_PKEY_fromdata(pctx, &pkey, selection, params); |
| 323 | + OSSL_PARAM_free(params); |
| 324 | + EVP_PKEY_CTX_free(pctx); |
| 325 | + |
| 326 | + if (ret <= 0) |
| 327 | + ossl_raise(ePKeyError, "EVP_PKEY_fromdata"); |
| 328 | + return ossl_pkey_new(pkey); |
| 329 | +} |
| 330 | + |
183 | 331 | static VALUE
|
184 | 332 | pkey_ctx_apply_options_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ctx_v))
|
185 | 333 | {
|
@@ -1687,6 +1835,7 @@ Init_ossl_pkey(void)
|
1687 | 1835 | */
|
1688 | 1836 | cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
|
1689 | 1837 |
|
| 1838 | + rb_define_module_function(mPKey, "from_data", ossl_pkey_s_from_data, -1); |
1690 | 1839 | rb_define_module_function(mPKey, "read", ossl_pkey_new_from_data, -1);
|
1691 | 1840 | rb_define_module_function(mPKey, "generate_parameters", ossl_pkey_s_generate_parameters, -1);
|
1692 | 1841 | rb_define_module_function(mPKey, "generate_key", ossl_pkey_s_generate_key, -1);
|
@@ -1718,6 +1867,10 @@ Init_ossl_pkey(void)
|
1718 | 1867 | rb_define_method(cPKey, "encrypt", ossl_pkey_encrypt, -1);
|
1719 | 1868 | rb_define_method(cPKey, "decrypt", ossl_pkey_decrypt, -1);
|
1720 | 1869 |
|
| 1870 | + rb_define_const(mPKey, "KEY_PARAMETERS", INT2NUM(EVP_PKEY_KEY_PARAMETERS)); |
| 1871 | + rb_define_const(mPKey, "PUBLIC_KEY", INT2NUM(EVP_PKEY_PUBLIC_KEY)); |
| 1872 | + rb_define_const(mPKey, "KEYPAIR", INT2NUM(EVP_PKEY_KEYPAIR)); |
| 1873 | + |
1721 | 1874 | id_private_q = rb_intern("private?");
|
1722 | 1875 |
|
1723 | 1876 | /*
|
|
0 commit comments