Net-Dropbear

 view release on metacpan or  search on metacpan

dropbear/keyimport.c  view on Meta::CPAN

		buf_putstring(blobbuf, "ssh-rsa", 7);
		retkey->type = DROPBEAR_SIGNKEY_RSA;
	}
#endif

	for (i = 0; i < num_integers; i++) {
		ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
							  &id, &len, &flags);
		p += ret;
		if (ret < 0 || id != 2 || len < 0 ||
			key->keyblob+key->keyblob_len-p < len) {
			errmsg = "ASN.1 decoding failure";
			goto error;
		}

		if (i == 0) {
			/* First integer is a version indicator */
			int expected = -1;
			switch (key->type) {
				case OSSH_RSA:
				case OSSH_DSA:
					expected = 0;
					break;
				case OSSH_EC:
					expected = 1;
					break;
			}
			if (len != 1 || p[0] != expected) {
				errmsg = "Version number mismatch";
				goto error;
			}
		} else if (key->type == OSSH_RSA) {
			/*
			 * OpenSSH key order is n, e, d, p, q, dmp1, dmq1, iqmp
			 * but we want e, n, d, p, q
			 */
			if (i == 1) {
				/* Save the details for after we deal with number 2. */
				modptr = p;
				modlen = len;
			} else if (i >= 2 && i <= 5) {
				buf_putstring(blobbuf, (const char*)p, len);
				if (i == 2) {
					buf_putstring(blobbuf, (const char*)modptr, modlen);
				}
			}
		} else if (key->type == OSSH_DSA) {
			/*
			 * OpenSSH key order is p, q, g, y, x,
			 * we want the same.
			 */
			buf_putstring(blobbuf, (const char*)p, len);
		}

		/* Skip past the number. */
		p += len;
	}

#if DROPBEAR_ECDSA
	if (key->type == OSSH_EC) {
		unsigned char* private_key_bytes = NULL;
		int private_key_len = 0;
		unsigned char* public_key_bytes = NULL;
		int public_key_len = 0;
		ecc_key *ecc = NULL;
		const struct dropbear_ecc_curve *curve = NULL;

		/* See SEC1 v2, Appendix C.4 */
		/* OpenSSL (so OpenSSH) seems to include the optional parts. */

		/* privateKey OCTET STRING, */
		ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
							  &id, &len, &flags);
		p += ret;
		/* id==4 for octet string */
		if (ret < 0 || id != 4 || len < 0 ||
			key->keyblob+key->keyblob_len-p < len) {
			errmsg = "ASN.1 decoding failure";
			goto error;
		}
		private_key_bytes = p;
		private_key_len = len;
		p += len;

		/* parameters [0] ECDomainParameters {{ SECGCurveNames }} OPTIONAL, */
		ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
							  &id, &len, &flags);
		p += ret;
		/* id==0 */
		if (ret < 0 || id != 0 || len < 0) {
			errmsg = "ASN.1 decoding failure";
			goto error;
		}

		ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
							  &id, &len, &flags);
		p += ret;
		/* id==6 for object */
		if (ret < 0 || id != 6 || len < 0 ||
			key->keyblob+key->keyblob_len-p < len) {
			errmsg = "ASN.1 decoding failure";
			goto error;
		}

		if (0) {}
#if DROPBEAR_ECC_256
		else if (len == sizeof(OID_SEC256R1_BLOB) 
			&& memcmp(p, OID_SEC256R1_BLOB, len) == 0) {
			retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
			curve = &ecc_curve_nistp256;
		} 
#endif
#if DROPBEAR_ECC_384
		else if (len == sizeof(OID_SEC384R1_BLOB)
			&& memcmp(p, OID_SEC384R1_BLOB, len) == 0) {
			retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP384;
			curve = &ecc_curve_nistp384;
		} 
#endif
#if DROPBEAR_ECC_521
		else if (len == sizeof(OID_SEC521R1_BLOB)
			&& memcmp(p, OID_SEC521R1_BLOB, len) == 0) {
			retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP521;
			curve = &ecc_curve_nistp521;
		} 
#endif
		else {
			errmsg = "Unknown ECC key type";
			goto error;
		}
		p += len;

		/* publicKey [1] BIT STRING OPTIONAL */
		ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
							  &id, &len, &flags);
		p += ret;
		/* id==1 */
		if (ret < 0 || id != 1 || len < 0) {
			errmsg = "ASN.1 decoding failure";
			goto error;
		}

		ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
							  &id, &len, &flags);
		p += ret;
		/* id==3 for bit string */
		if (ret < 0 || id != 3 || len < 0 ||
			key->keyblob+key->keyblob_len-p < len) {
			errmsg = "ASN.1 decoding failure";
			goto error;
		}
		public_key_bytes = p+1;
		public_key_len = len-1;
		p += len;

		buf_putbytes(blobbuf, public_key_bytes, public_key_len);
		ecc = buf_get_ecc_raw_pubkey(blobbuf, curve);
		if (!ecc) {
			errmsg = "Error parsing ECC key";
			goto error;
		}
		m_mp_alloc_init_multi((mp_int**)&ecc->k, NULL);
		if (mp_from_ubin(ecc->k, private_key_bytes, private_key_len)
			!= MP_OKAY) {
			errmsg = "Error parsing ECC key";
			goto error;
		}

		*signkey_key_ptr(retkey, retkey->type) = ecc;
	}
#endif /* DROPBEAR_ECDSA */

	/*
	 * Now put together the actual key. Simplest way to do this is
	 * to assemble our own key blobs and feed them to the createkey
	 * functions; this is a bit faffy but it does mean we get all
	 * the sanity checks for free.
	 */
	if (key->type == OSSH_RSA || key->type == OSSH_DSA) {
		buf_setpos(blobbuf, 0);
		type = DROPBEAR_SIGNKEY_ANY;
		if (buf_get_priv_key(blobbuf, retkey, &type)
				!= DROPBEAR_SUCCESS) {
			errmsg = "unable to create key structure";
			sign_key_free(retkey);
			retkey = NULL;
			goto error;
		}
	}

	errmsg = NULL;					 /* no error */
	retval = retkey;

	error:
	if (blobbuf) {
		buf_burn_free(blobbuf);
	}
	m_burn(key->keyblob, key->keyblob_size);
	m_free(key->keyblob);
	m_burn(key, sizeof(*key));
	m_free(key);
	if (errmsg) {
		fprintf(stderr, "Error: %s\n", errmsg);
	}
	return retval;
}

static int openssh_write(const char *filename, sign_key *key,
				  const char *passphrase)
{
	buffer * keyblob = NULL;
	buffer * extrablob = NULL; /* used for calculated values to write */
	unsigned char *outblob = NULL;
	int outlen = -9999;
	struct mpint_pos numbers[9];
	int nnumbers = -1, pos = 0, len = 0, seqlen, i;
	char *header = NULL, *footer = NULL;
	char zero[1];
	int ret = 0;
	FILE *fp;

#if DROPBEAR_DSS
	if (key->type == DROPBEAR_SIGNKEY_DSS) {



( run in 1.357 second using v1.01-cache-2.11-cpan-39bf76dae61 )