+static void
+buffer_get_bignum_bits(Buffer *b, BIGNUM *value)
+{
+ int bits = buffer_get_int(b);
+ int bytes = (bits + 7) / 8;
+
+ if (buffer_len(b) < bytes)
+ fatal("buffer_get_bignum_bits: input buffer too small: "
+ "need %d have %d", bytes, buffer_len(b));
+ BN_bin2bn(buffer_ptr(b), bytes, value);
+ buffer_consume(b, bytes);
+}
+
+static Key *
+do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
+{
+ Buffer b;
+ Key *key = NULL;
+ char *type, *cipher;
+ u_char *sig, data[] = "abcde12345";
+ int magic, rlen, ktype, i1, i2, i3, i4;
+ u_int slen;
+ u_long e;
+
+ buffer_init(&b);
+ buffer_append(&b, blob, blen);
+
+ magic = buffer_get_int(&b);
+ if (magic != SSH_COM_PRIVATE_KEY_MAGIC) {
+ error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC);
+ buffer_free(&b);
+ return NULL;
+ }
+ i1 = buffer_get_int(&b);
+ type = buffer_get_string(&b, NULL);
+ cipher = buffer_get_string(&b, NULL);
+ i2 = buffer_get_int(&b);
+ i3 = buffer_get_int(&b);
+ i4 = buffer_get_int(&b);
+ debug("ignore (%d %d %d %d)", i1,i2,i3,i4);
+ if (strcmp(cipher, "none") != 0) {
+ error("unsupported cipher %s", cipher);
+ xfree(cipher);
+ buffer_free(&b);
+ xfree(type);
+ return NULL;
+ }
+ xfree(cipher);
+
+ if (strstr(type, "dsa")) {
+ ktype = KEY_DSA;
+ } else if (strstr(type, "rsa")) {
+ ktype = KEY_RSA;
+ } else {
+ xfree(type);
+ return NULL;
+ }
+ key = key_new_private(ktype);
+ xfree(type);
+
+ switch (key->type) {
+ case KEY_DSA:
+ buffer_get_bignum_bits(&b, key->dsa->p);
+ buffer_get_bignum_bits(&b, key->dsa->g);
+ buffer_get_bignum_bits(&b, key->dsa->q);
+ buffer_get_bignum_bits(&b, key->dsa->pub_key);
+ buffer_get_bignum_bits(&b, key->dsa->priv_key);
+ break;
+ case KEY_RSA:
+ e = buffer_get_char(&b);
+ debug("e %lx", e);
+ if (e < 30) {
+ e <<= 8;
+ e += buffer_get_char(&b);
+ debug("e %lx", e);
+ e <<= 8;
+ e += buffer_get_char(&b);
+ debug("e %lx", e);
+ }
+ if (!BN_set_word(key->rsa->e, e)) {
+ buffer_free(&b);
+ key_free(key);
+ return NULL;
+ }
+ buffer_get_bignum_bits(&b, key->rsa->d);
+ buffer_get_bignum_bits(&b, key->rsa->n);
+ buffer_get_bignum_bits(&b, key->rsa->iqmp);
+ buffer_get_bignum_bits(&b, key->rsa->q);
+ buffer_get_bignum_bits(&b, key->rsa->p);
+ rsa_generate_additional_parameters(key->rsa);
+ break;
+ }
+ rlen = buffer_len(&b);
+ if (rlen != 0)
+ error("do_convert_private_ssh2_from_blob: "
+ "remaining bytes in key blob %d", rlen);
+ buffer_free(&b);
+
+ /* try the key */
+ key_sign(key, &sig, &slen, data, sizeof(data));
+ key_verify(key, sig, slen, data, sizeof(data));
+ xfree(sig);
+ return key;
+}
+
+static void