if (len > cipherlen-4) {
if (len < 0 || len > cipherlen-4) {
struct ssh2_userkey *sshcom_read(const Filename *filename, char *passphrase){    struct sshcom_key *key = load_sshcom_key(filename);    char *errmsg;    int pos, len;    const char prefix_rsa[] = "if-modn{sign{rsa";    const char prefix_dsa[] = "dl-modp{sign{dsa";    enum { RSA, DSA } type;    int encrypted;    char *ciphertext;    int cipherlen;    struct ssh2_userkey *ret = NULL, *retkey;    const struct ssh_signkey *alg;    unsigned char *blob = NULL;    int blobsize = 0, publen, privlen;    if (!key)        return NULL;    /*     * Check magic number.     */    if (GET_32BIT(key->keyblob) != SSHCOM_MAGIC_NUMBER) {        errmsg = "Key does not begin with magic number";        goto error;    }    /*     * Determine the key type.     */    pos = 8;    if (key->keyblob_len < pos+4 ||        (len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) {        errmsg = "Key blob does not contain a key type string";        goto error;    }    if (len > sizeof(prefix_rsa) - 1 &&        !memcmp(key->keyblob+pos+4, prefix_rsa, sizeof(prefix_rsa) - 1)) {        type = RSA;    } else if (len > sizeof(prefix_dsa) - 1 &&        !memcmp(key->keyblob+pos+4, prefix_dsa, sizeof(prefix_dsa) - 1)) {        type = DSA;    } else {        errmsg = "Key is of unknown type";        goto error;    }    pos += 4+len;    /*     * Determine the cipher type.     */    if (key->keyblob_len < pos+4 ||        (len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) {        errmsg = "Key blob does not contain a cipher type string";        goto error;    }    if (len == 4 && !memcmp(key->keyblob+pos+4, "none", 4))        encrypted = 0;    else if (len == 8 && !memcmp(key->keyblob+pos+4, "3des-cbc", 8))        encrypted = 1;    else {        errmsg = "Key encryption is of unknown type";        goto error;    }    pos += 4+len;    /*     * Get hold of the encrypted part of the key.     */    if (key->keyblob_len < pos+4 ||        (len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) {        errmsg = "Key blob does not contain actual key data";        goto error;    }    ciphertext = (char *)key->keyblob + pos + 4;    cipherlen = len;    if (cipherlen == 0) {        errmsg = "Length of key data is zero";        goto error;    }    /*     * Decrypt it if necessary.     */    if (encrypted) {	/*	 * Derive encryption key from passphrase and iv/salt:	 * 	 *  - let block A equal MD5(passphrase)	 *  - let block B equal MD5(passphrase || A)	 *  - block C would be MD5(passphrase || A || B) and so on	 *  - encryption key is the first N bytes of A || B	 */	struct MD5Context md5c;	unsigned char keybuf[32], iv[8];        if (cipherlen % 8 != 0) {            errmsg = "Encrypted part of key is not a multiple of cipher block"                " size";            goto error;        }	MD5Init(&md5c);	MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));	MD5Final(keybuf, &md5c);	MD5Init(&md5c);	MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));	MD5Update(&md5c, keybuf, 16);	MD5Final(keybuf+16, &md5c);	/*	 * Now decrypt the key blob.	 */        memset(iv, 0, sizeof(iv));	des3_decrypt_pubkey_ossh(keybuf, iv, (unsigned char *)ciphertext,				 cipherlen);        memset(&md5c, 0, sizeof(md5c));        memset(keybuf, 0, sizeof(keybuf));        /*         * Hereafter we return WRONG_PASSPHRASE for any parsing         * error. (But only if we've just tried to decrypt it!         * Returning WRONG_PASSPHRASE for an unencrypted key is         * automatic doom.)         */        if (encrypted)            ret = SSH2_WRONG_PASSPHRASE;    }    /*     * Strip away the containing string to get to the real meat.     */    len = GET_32BIT(ciphertext);    if (len > cipherlen-4) {        errmsg = "containing string was ill-formed";        goto error;    }    ciphertext += 4;    cipherlen = len;    /*     * Now we break down into RSA versus DSA. In either case we'll     * construct public and private blobs in our own format, and     * end up feeding them to alg->createkey().     */    blobsize = cipherlen + 256;    blob = snewn(blobsize, unsigned char);    privlen = 0;    if (type == RSA) {        struct mpint_pos n, e, d, u, p, q;        int pos = 0;        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &e);        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &d);        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &n);        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &u);        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &p);        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &q);        if (!q.start) {            errmsg = "key data did not contain six integers";            goto error;        }        alg = &ssh_rsa;        pos = 0;        pos += put_string(blob+pos, "ssh-rsa", 7);        pos += put_mp(blob+pos, e.start, e.bytes);        pos += put_mp(blob+pos, n.start, n.bytes);        publen = pos;        pos += put_string(blob+pos, d.start, d.bytes);        pos += put_mp(blob+pos, q.start, q.bytes);        pos += put_mp(blob+pos, p.start, p.bytes);        pos += put_mp(blob+pos, u.start, u.bytes);        privlen = pos - publen;    } else if (type == DSA) {        struct mpint_pos p, q, g, x, y;        int pos = 4;        if (GET_32BIT(ciphertext) != 0) {            errmsg = "predefined DSA parameters not supported";            goto error;        }        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &p);        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &g);        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &q);        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &y);        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &x);        if (!x.start) {            errmsg = "key data did not contain five integers";            goto error;        }        alg = &ssh_dss;        pos = 0;        pos += put_string(blob+pos, "ssh-dss", 7);        pos += put_mp(blob+pos, p.start, p.bytes);        pos += put_mp(blob+pos, q.start, q.bytes);        pos += put_mp(blob+pos, g.start, g.bytes);        pos += put_mp(blob+pos, y.start, y.bytes);        publen = pos;        pos += put_mp(blob+pos, x.start, x.bytes);        privlen = pos - publen;    } else	return NULL;    assert(privlen > 0);	       /* should have bombed by now if not */    retkey = snew(struct ssh2_userkey);    retkey->alg = alg;    retkey->data = alg->createkey(blob, publen, blob+publen, privlen);    if (!retkey->data) {	sfree(retkey);	errmsg = "unable to create key data structure";	goto error;    }    retkey->comment = dupstr(key->comment);    errmsg = NULL; /* no error */    ret = retkey;    error:    if (blob) {        memset(blob, 0, blobsize);        sfree(blob);    }    memset(key->keyblob, 0, key->keyblob_size);    sfree(key->keyblob);    memset(&key, 0, sizeof(key));    sfree(key);    return ret;}