+ goto free_iqmp;
+ cp += ret;
+ ret = read_bignum(cp, end - cp, &q);
+ if (ret < 0)
+ goto free_p;
+ ret = -E_BIGNUM;
+ if (!BN_sub(tmp, q, BN_value_one()))
+ goto free_q;
+ if (!BN_mod(dmp1, d, tmp, ctx))
+ goto free_q;
+ if (!BN_sub(tmp, q, BN_value_one()))
+ goto free_q;
+ if (!BN_mod(dmq1, d, tmp, ctx))
+ goto free_q;
+#ifdef HAVE_RSA_SET0_KEY
+ RSA_set0_key(rsa, n, e, d);
+ RSA_set0_factors(rsa, p, q);
+ RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp);
+#else
+ rsa->n = n;
+ rsa->e = e;
+ rsa->d = d;
+ rsa->p = p;
+ rsa->q = q;
+ rsa->dmp1 = dmp1;
+ rsa->dmq1 = dmq1;
+ rsa->iqmp = iqmp;
+#endif
+ *result = rsa;
+ ret = 1;
+ goto free_ctx;
+free_q:
+ BN_clear_free(q);
+free_p:
+ BN_clear_free(p);
+free_iqmp:
+ BN_clear_free(iqmp);
+free_d:
+ BN_clear_free(d);
+free_e:
+ BN_free(e);
+free_n:
+ BN_free(n);
+free_dmq1:
+ BN_clear_free(dmq1);
+free_dmp1:
+ BN_clear_free(dmp1);
+free_ctx:
+ BN_CTX_free(ctx);
+free_tmp:
+ BN_clear_free(tmp);
+free_rsa:
+ if (ret < 0)
+ RSA_free(rsa);
+ return ret;
+}
+
+static int get_private_key(const char *path, RSA **rsa)
+{
+ int ret;
+ unsigned char *blob, *end;
+ size_t blob_size;
+
+ *rsa = NULL;
+ ret = decode_private_key(path, &blob, &blob_size);
+ if (ret < 0)
+ return ret;
+ end = blob + blob_size;
+ if (ret == PKT_OPENSSH) {
+ ret = find_openssh_bignum_offset(blob, blob_size);
+ if (ret < 0)
+ goto free_blob;
+ PARA_INFO_LOG("reading RSA params at offset %d\n", ret);
+ ret = read_private_rsa_params(blob + ret, end, rsa);
+ } else
+ ret = read_pem_private_key(path, rsa);
+free_blob:
+ free(blob);
+ return ret;
+}
+
+int apc_get_pubkey(const char *key_file, struct asymmetric_key **result)
+{
+ unsigned char *blob;
+ size_t decoded_size;
+ int ret;
+ struct asymmetric_key *key = para_malloc(sizeof(*key));
+
+ ret = decode_public_key(key_file, &blob, &decoded_size);
+ if (ret < 0)
+ goto out;