+ if (ferror(f)) {
+ fatal_perror("rsa-private (%s:%d): ferror",loc.file,loc.line);
+ }
+
+ rsa_sethash(l,&st->common,&st->ops.hash);
+
+ /*
+ * Now verify the validity of the key, and set up the auxiliary
+ * values for fast CRT signing.
+ */
+ valid=False;
+ if (do_validity_check) {
+ /* Verify that p*q is equal to n. */
+ mpz_mul(&tmp, &st->p, &st->q);
+ if (mpz_cmp(&tmp, &st->n) != 0)
+ goto done_checks;
+
+ /*
+ * Verify that d*e is congruent to 1 mod (p-1), and mod
+ * (q-1). This is equivalent to it being congruent to 1 mod
+ * lambda(n) = lcm(p-1,q-1). The usual `textbook' condition,
+ * that d e == 1 (mod (p-1)(q-1)) is sufficient, but not
+ * actually necessary.
+ */
+ mpz_mul(&tmp, &d, &e);
+ mpz_sub_ui(&tmp2, &st->p, 1);
+ mpz_mod(&tmp3, &tmp, &tmp2);
+ if (mpz_cmp_si(&tmp3, 1) != 0)
+ goto done_checks;
+ mpz_sub_ui(&tmp2, &st->q, 1);
+ mpz_mod(&tmp3, &tmp, &tmp2);
+ if (mpz_cmp_si(&tmp3, 1) != 0)
+ goto done_checks;
+
+ /* Verify that q*iqmp is congruent to 1 mod p. */
+ mpz_mul(&tmp, &st->q, &iqmp);
+ mpz_mod(&tmp2, &tmp, &st->p);
+ if (mpz_cmp_si(&tmp2, 1) != 0)
+ goto done_checks;
+ }
+ /* Now we know the key is valid (or we don't care). */
+ valid = True;
+
+ /*
+ * Now we compute auxiliary values dp, dq and w to allow us
+ * to use the CRT optimisation when signing.
+ *
+ * dp == d mod (p-1) so that a^dp == a^d mod p, for all a
+ * dq == d mod (q-1) similarly mod q
+ * w == iqmp * q so that w == 0 mod q, and w == 1 mod p
+ */
+ mpz_sub_ui(&tmp, &st->p, 1);
+ mpz_mod(&st->dp, &d, &tmp);
+ mpz_sub_ui(&tmp, &st->q, 1);
+ mpz_mod(&st->dq, &d, &tmp);
+ mpz_mul(&st->w, &iqmp, &st->q);
+
+done_checks:
+ if (!valid) {
+ LDFATAL("file does not contain a "
+ "valid RSA key!\n");
+ }
+
+assume_valid:
+out:
+ mpz_clear(&tmp);
+ mpz_clear(&tmp2);
+ mpz_clear(&tmp3);
+
+ FREE(b);
+ FREE(c);
+ mpz_clear(&e);
+ mpz_clear(&d);
+ mpz_clear(&iqmp);
+
+ return st;
+
+error_out:
+ if (st) rsapriv_dispose(st);
+ st=0;
+ goto out;
+}
+
+static bool_t postreadcheck_tryload(struct load_ctx *l, FILE *f)
+{
+ assert(!ferror(f));
+ if (feof(f)) { load_err(l,0,0,"eof mid-integer"); return False; }
+ return True;
+}
+
+bool_t rsa1_loadpriv(const struct sigscheme_info *algo,
+ struct buffer_if *privkeydata,
+ struct sigprivkey_if **sigpriv_r,
+ closure_t **closure_r,
+ struct log_if *log, struct cloc loc)
+{
+ FILE *f=0;
+ struct rsapriv *st=0;
+
+ f=fmemopen(privkeydata->start,privkeydata->size,"r");
+ if (!f) {
+ slilog(log,M_ERR,"failed to fmemopen private key file\n");
+ goto error_out;