if (len < 4)
goto error;
- bytes = GET_32BIT(d);
- if (len < 4+bytes)
+ bytes = toint(GET_32BIT(d));
+ if (bytes < 0 || len-4 < bytes)
goto error;
ret->start = d + 4;
}
strip_crlf(line);
if (0 == strncmp(line, "-----END ", 9) &&
- 0 == strcmp(line+strlen(line)-16, "PRIVATE KEY-----"))
+ 0 == strcmp(line+strlen(line)-16, "PRIVATE KEY-----")) {
+ sfree(line);
break; /* done */
+ }
if ((p = strchr(line, ':')) != NULL) {
if (headers_done) {
errmsg = "header found in body of key data";
p = key->keyblob;
- /* Expect the SEQUENCE header. Take its absence as a failure to decrypt. */
+ /* Expect the SEQUENCE header. Take its absence as a failure to
+ * decrypt, if the key was encrypted. */
ret = ber_read_id_len(p, key->keyblob_len, &id, &len, &flags);
p += ret;
if (ret < 0 || id != 16) {
errmsg = "ASN.1 decoding failure";
- retval = SSH2_WRONG_PASSPHRASE;
+ retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL;
goto error;
}
if (ret < 0 || id != 2 ||
key->keyblob+key->keyblob_len-p < len) {
errmsg = "ASN.1 decoding failure";
- retval = SSH2_WRONG_PASSPHRASE;
+ retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL;
goto error;
}
struct mpint_pos n, e, d, p, q, iqmp, dmp1, dmq1;
Bignum bd, bp, bq, bdmp1, bdmq1;
+ /*
+ * These blobs were generated from inside PuTTY, so we needn't
+ * treat them as untrusted.
+ */
pos = 4 + GET_32BIT(pubblob);
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &e);
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &n);
int pos;
struct mpint_pos p, q, g, y, x;
+ /*
+ * These blobs were generated from inside PuTTY, so we needn't
+ * treat them as untrusted.
+ */
pos = 4 + GET_32BIT(pubblob);
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &p);
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &q);
goto error;
}
strip_crlf(line);
- if (!strcmp(line, "---- END SSH2 ENCRYPTED PRIVATE KEY ----"))
+ if (!strcmp(line, "---- END SSH2 ENCRYPTED PRIVATE KEY ----")) {
+ sfree(line);
break; /* done */
+ }
if ((p = strchr(line, ':')) != NULL) {
if (headers_done) {
errmsg = "header found in body of key data";
goto error;
}
+ fclose(fp);
if (errmsg_p) *errmsg_p = NULL;
return ret;
error:
+ if (fp)
+ fclose(fp);
+
if (line) {
smemclr(line, strlen(line));
sfree(line);
struct sshcom_key *key = load_sshcom_key(filename, NULL);
int pos, len, answer;
+ answer = 0;
+
*comment = NULL;
if (!key)
- return 0;
+ goto done;
/*
* Check magic number.
*/
- if (GET_32BIT(key->keyblob) != 0x3f6ff9eb)
- return 0; /* key is invalid */
+ if (GET_32BIT(key->keyblob) != 0x3f6ff9eb) {
+ goto done; /* key is invalid */
+ }
/*
* Find the cipher-type string.
*/
- answer = 0;
pos = 8;
if (key->keyblob_len < pos+4)
goto done; /* key is far too short */
- pos += 4 + GET_32BIT(key->keyblob + pos); /* skip key type */
- if (key->keyblob_len < pos+4)
+ len = toint(GET_32BIT(key->keyblob + pos));
+ if (len < 0 || len > key->keyblob_len - pos - 4)
goto done; /* key is far too short */
- len = GET_32BIT(key->keyblob + pos); /* find cipher-type length */
- if (key->keyblob_len < pos+4+len)
+ pos += 4 + len; /* skip key type */
+ len = toint(GET_32BIT(key->keyblob + pos)); /* find cipher-type length */
+ if (len < 0 || len > key->keyblob_len - pos - 4)
goto done; /* cipher type string is incomplete */
if (len != 4 || 0 != memcmp(key->keyblob + pos + 4, "none", 4))
answer = 1;
done:
- *comment = dupstr(key->comment);
+ *comment = dupstr(key ? key->comment : "");
smemclr(key->keyblob, key->keyblob_size);
sfree(key->keyblob);
smemclr(key, sizeof(*key));
static int sshcom_read_mpint(void *data, int len, struct mpint_pos *ret)
{
- int bits;
- int bytes;
+ unsigned bits, bytes;
unsigned char *d = (unsigned char *) data;
if (len < 4)
*/
pos = 8;
if (key->keyblob_len < pos+4 ||
- (len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) {
+ (len = toint(GET_32BIT(key->keyblob + pos))) < 0 ||
+ len > key->keyblob_len - pos - 4) {
errmsg = "key blob does not contain a key type string";
goto error;
}
* Determine the cipher type.
*/
if (key->keyblob_len < pos+4 ||
- (len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) {
+ (len = toint(GET_32BIT(key->keyblob + pos))) < 0 ||
+ len > key->keyblob_len - pos - 4) {
errmsg = "key blob does not contain a cipher type string";
goto error;
}
* 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) {
+ (len = toint(GET_32BIT(key->keyblob + pos))) < 0 ||
+ len > key->keyblob_len - pos - 4) {
errmsg = "key blob does not contain actual key data";
goto error;
}
/*
* Strip away the containing string to get to the real meat.
*/
- len = GET_32BIT(ciphertext);
+ len = toint(GET_32BIT(ciphertext));
if (len < 0 || len > cipherlen-4) {
errmsg = "containing string was ill-formed";
goto error;
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) {
+ } else {
struct mpint_pos p, q, g, x, y;
int pos = 4;
+
+ assert(type == DSA); /* the only other option from the if above */
+
if (GET_32BIT(ciphertext) != 0) {
errmsg = "predefined DSA parameters not supported";
goto error;
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 */
int pos;
struct mpint_pos n, e, d, p, q, iqmp;
+ /*
+ * These blobs were generated from inside PuTTY, so we needn't
+ * treat them as untrusted.
+ */
pos = 4 + GET_32BIT(pubblob);
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &e);
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &n);
int pos;
struct mpint_pos p, q, g, y, x;
+ /*
+ * These blobs were generated from inside PuTTY, so we needn't
+ * treat them as untrusted.
+ */
pos = 4 + GET_32BIT(pubblob);
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &p);
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &q);