+ bbs_privfree(&bp);
+}
+
+static void alg_ecparam(keyopts *k)
+{
+ static const char *pl[] = { "curve", 0 };
+ if (!copyparam(k, pl)) {
+ ec_info ei;
+ const char *e;
+ key_data *kd = &k->k->k;
+
+ /* --- Decide on a curve --- */
+
+ if (!k->bits) k->bits = 256;
+ if (k->curve && strcmp(k->curve, "list") == 0) {
+ const ecentry *ee;
+ printf("Built-in elliptic curves:\n");
+ for (ee = ectab; ee->name; ee++)
+ printf(" %s\n", ee->name);
+ exit(0);
+ }
+ if (!k->curve) {
+ if (k->bits <= 56) k->curve = "secp112r1";
+ else if (k->bits <= 64) k->curve = "secp128r1";
+ else if (k->bits <= 80) k->curve = "secp160r1";
+ else if (k->bits <= 96) k->curve = "secp192r1";
+ else if (k->bits <= 112) k->curve = "secp224r1";
+ else if (k->bits <= 128) k->curve = "secp256r1";
+ else if (k->bits <= 192) k->curve = "secp384r1";
+ else if (k->bits <= 256) k->curve = "secp521r1";
+ else
+ die(EXIT_FAILURE, "no built-in curves provide %u-bit security",
+ k->bits);
+ }
+
+ /* --- Check it --- */
+
+ if ((e = ec_getinfo(&ei, k->curve)) != 0)
+ die(EXIT_FAILURE, "error in curve spec: %s", e);
+ if (!(k->f & f_quiet) && (e = ec_checkinfo(&ei, k->r)) != 0)
+ moan("WARNING! curve check failed: %s", e);
+ ec_freeinfo(&ei);
+
+ /* --- Write out the answer --- */
+
+ key_structure(kd);
+ kd = key_structcreate(kd, "curve");
+ key_string(kd, k->curve);
+ kd->e |= KCAT_SHARE;
+ }
+}
+
+static void alg_ec(keyopts *k)
+{
+ key_data *kd = &k->k->k;
+ key_data *kkd;
+ mp *x = MP_NEW;
+ ec p = EC_INIT;
+ const char *e;
+ ec_info ei;
+
+ /* --- Get the curve --- */
+
+ alg_ecparam(k);
+ if ((kkd = key_structfind(kd, "curve")) == 0)
+ die(EXIT_FAILURE, "unexpected failure looking up subkey `curve')");
+ if ((kkd->e & KF_ENCMASK) != KENC_STRING)
+ die(EXIT_FAILURE, "subkey `curve' is not a string");
+ if ((e = ec_getinfo(&ei, kkd->u.p)) != 0)
+ die(EXIT_FAILURE, "error in curve spec: %s", e);
+
+ /* --- Invent a private exponent and compute the public key --- */
+
+ x = mprand_range(MP_NEWSEC, ei.r, k->r, 0);
+ ec_mul(ei.c, &p, &ei.g, x);
+
+ /* --- Store everything away --- */
+
+ kkd = key_structcreate(kd, "p");
+ key_ec(kkd, &p);
+ kkd->e |= KCAT_PUB;
+ kkd = key_structcreate(kd, "private");
+ key_structure(kkd);
+ mpkey(kkd, "x", x, KCAT_PRIV | KF_BURN);
+
+ /* --- Done --- */
+
+ ec_freeinfo(&ei);
+ mp_drop(x);