+ const BIGNUM *bignums[] = {n, e, d, p, q};
+ const char *strings[] = {"n", "e", "d", "p", "q"};
+ int ret, bytes[ARRAY_SIZE(bignums)];
+ unsigned char *bufs[ARRAY_SIZE(bignums)];
+ OSSL_PARAM params[ARRAY_SIZE(bignums) + 1];
+ /*
+ * Convert bignums to buffers for OSSL_PARAM_construct_BN() and init
+ * params[].
+ */
+ for (int i = 0; i < ARRAY_SIZE(bignums); i++) {
+ bytes[i] = BN_num_bytes(bignums[i]);
+ PARA_DEBUG_LOG("%s: %d bits\n", strings[i], bytes[i] * 8);
+ bufs[i] = alloc(bytes[i]);
+ assert(BN_bn2nativepad(bignums[i], bufs[i], bytes[i]) > 0);
+ params[i] = OSSL_PARAM_construct_BN(strings[i], bufs[i],
+ bytes[i]);
+ }
+ params[ARRAY_SIZE(bignums)] = OSSL_PARAM_construct_end();
+ /* Transfer buffers to openssl to create the pkey from it */
+ priv->ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
+ assert(priv->ctx);
+ assert(EVP_PKEY_fromdata_init(priv->ctx) > 0);
+ ret = EVP_PKEY_fromdata(priv->ctx, &priv->pkey,
+ EVP_PKEY_KEYPAIR, params);
+ for (int i = 0; i < ARRAY_SIZE(bignums); i++)
+ free(bufs[i]);
+ if (ret <= 0) {
+ EVP_PKEY_CTX_free(priv->ctx);
+ return openssl_perror("EVP_PKEY_fromdata()");
+ }
+ assert(priv->pkey);
+ return BN_num_bytes(n) * 8;
+}
+
+/*
+ * Convert bignumns e and n to a pkey and context.
+ */
+static int generate_public_pkey(struct asymmetric_key *pub,
+ const BIGNUM *e, const BIGNUM *n)
+{
+ unsigned char *ebuf, *nbuf;
+ int ret, ebytes = BN_num_bytes(e), nbytes = BN_num_bytes(n);
+ OSSL_PARAM params[3];
+
+ /* Convert e and n to a buffer for OSSL_PARAM_construct_BN() */
+ ebuf = alloc(ebytes);
+ assert(BN_bn2nativepad(e, ebuf, ebytes) > 0);
+ nbuf = alloc(nbytes);
+ assert(BN_bn2nativepad(n, nbuf, nbytes) > 0);
+ /* Init params[] with {e,n}buf and create the pkey from it */
+ params[0] = OSSL_PARAM_construct_BN("e", ebuf, ebytes);
+ params[1] = OSSL_PARAM_construct_BN("n", nbuf, nbytes);
+ params[2] = OSSL_PARAM_construct_end();
+ pub->ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
+ assert(pub->ctx);
+ assert(EVP_PKEY_fromdata_init(pub->ctx) > 0);
+ ret = EVP_PKEY_fromdata(pub->ctx, &pub->pkey, EVP_PKEY_PUBLIC_KEY,
+ params);
+ free(nbuf);
+ free(ebuf);
+ if (ret <= 0) {
+ EVP_PKEY_CTX_free(pub->ctx);
+ return openssl_perror("EVP_PKEY_fromdata()");
+ }
+ assert(pub->pkey);
+ return nbytes * 8;
+}
+
+#endif /* HAVE_OSSL_PARAM */
+
+static int read_public_key(const unsigned char *blob, size_t blen,
+ struct asymmetric_key *pub)
+{
+ int ret, bits;