+static int read_openssh_bignum(unsigned char *start, unsigned char *end,
+ gcry_mpi_t *bn, unsigned *bitsp)
+{
+ gcry_error_t gret;
+ size_t nscanned;
+ unsigned bits;
+
+ gret = gcry_mpi_scan(bn, GCRYMPI_FMT_SSH, start, end - start, &nscanned);
+ if (gret) {
+ PARA_ERROR_LOG("gcry_mpi_scan: %s\n",
+ gcry_strerror(gcry_err_code(gret)));
+ return -E_MPI_SCAN;
+ }
+ bits = (nscanned - 4 - (start[4] == '\0')) * 8;
+ if (bitsp)
+ *bitsp = bits;
+ PARA_DEBUG_LOG("scanned %u-bit bignum\n", bits);
+ return nscanned;
+}
+
+static int read_openssh_rsa_params(unsigned char *start, unsigned char *end,
+ struct rsa_params *p)
+{
+ unsigned char *cp = start;
+ unsigned bits;
+ int ret;
+
+ ret = read_openssh_bignum(cp, end, &p->n, &bits);
+ if (ret < 0)
+ return ret;
+ cp += ret;
+ ret = read_openssh_bignum(cp, end, &p->e, NULL);
+ if (ret < 0)
+ goto release_n;
+ cp += ret;
+ ret = read_openssh_bignum(cp, end, &p->d, NULL);
+ if (ret < 0)
+ goto release_e;
+ cp += ret;
+ ret = read_openssh_bignum(cp, end, &p->u, NULL);
+ if (ret < 0)
+ goto release_d;
+ cp += ret;
+ ret = read_openssh_bignum(cp, end, &p->p, NULL);
+ if (ret < 0)
+ goto release_u;
+ cp += ret;
+ ret = read_openssh_bignum(cp, end, &p->q, NULL);
+ if (ret < 0)
+ goto release_p;
+ return bits;
+release_p:
+ gcry_mpi_release(p->p);
+release_u:
+ gcry_mpi_release(p->u);
+release_d:
+ gcry_mpi_release(p->d);
+release_e:
+ gcry_mpi_release(p->e);
+release_n:
+ gcry_mpi_release(p->n);
+ return ret;
+}
+