i += 4;
/* Now the serious stuff. An ordinary SSH-1 public key. */
- i += makekey(buf + i, len, key, NULL, 1);
- if (i < 0)
+ j = makekey(buf + i, len - i, key, NULL, 1);
+ if (j < 0)
goto end; /* overran */
+ i += j;
/* Next, the comment field. */
- j = GET_32BIT(buf + i);
+ j = toint(GET_32BIT(buf + i));
i += 4;
- if (len - i < j)
+ if (j < 0 || len - i < j)
goto end;
comment = snewn(j + 1, char);
if (comment) {
MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
MD5Final(keybuf, &md5c);
des3_decrypt_pubkey(keybuf, buf + i, (len - i + 7) & ~7);
- memset(keybuf, 0, sizeof(keybuf)); /* burn the evidence */
+ smemclr(keybuf, sizeof(keybuf)); /* burn the evidence */
}
/*
ret = 1;
end:
- memset(buf, 0, sizeof(buf)); /* burn the evidence */
+ smemclr(buf, sizeof(buf)); /* burn the evidence */
return ret;
}
int ret = 0;
const char *error = NULL;
- fp = f_open(*filename, "rb");
+ fp = f_open(filename, "rb", FALSE);
if (!fp) {
error = "can't open file";
goto end;
FILE *fp;
char buf[64];
- fp = f_open(*filename, "rb");
+ fp = f_open(filename, "rb", FALSE);
if (!fp)
return 0; /* doesn't even exist */
*bloblen = 0;
ret = 0;
- fp = f_open(*filename, "rb");
+ fp = f_open(filename, "rb", FALSE);
if (!fp) {
error = "can't open file";
goto end;
*blob = rsa_public_blob(&key, bloblen);
freersakey(&key);
ret = 1;
- fp = NULL;
}
+ fp = NULL; /* loadrsakey_main unconditionally closes fp */
} else {
error = "not an SSH-1 RSA file";
}
MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
MD5Final(keybuf, &md5c);
des3_encrypt_pubkey(keybuf, estart, p - estart);
- memset(keybuf, 0, sizeof(keybuf)); /* burn the evidence */
+ smemclr(keybuf, sizeof(keybuf)); /* burn the evidence */
}
/*
* Done. Write the result to the file.
*/
- fp = f_open(*filename, "wb");
+ fp = f_open(filename, "wb", TRUE);
if (fp) {
int ret = (fwrite(buf, 1, p - buf, fp) == (size_t) (p - buf));
if (fclose(fp))
int len = 39;
int c;
- while (len > 0) {
+ while (1) {
c = fgetc(fp);
if (c == '\n' || c == '\r' || c == EOF)
return 0; /* failure */
while (1) {
c = fgetc(fp);
- if (c == '\r' || c == '\n') {
- c = fgetc(fp);
- if (c != '\r' && c != '\n' && c != EOF)
- ungetc(c, fp);
+ if (c == '\r' || c == '\n' || c == EOF) {
+ if (c != EOF) {
+ c = fgetc(fp);
+ if (c != '\r' && c != '\n')
+ ungetc(c, fp);
+ }
return text;
}
- if (c == EOF) {
- sfree(text);
- return NULL;
- }
if (len + 1 >= size) {
size += 128;
text = sresize(text, size, char);
}
}
-int base64_decode_atom(char *atom, unsigned char *out)
-{
- int vals[4];
- int i, v, len;
- unsigned word;
- char c;
-
- for (i = 0; i < 4; i++) {
- c = atom[i];
- if (c >= 'A' && c <= 'Z')
- v = c - 'A';
- else if (c >= 'a' && c <= 'z')
- v = c - 'a' + 26;
- else if (c >= '0' && c <= '9')
- v = c - '0' + 52;
- else if (c == '+')
- v = 62;
- else if (c == '/')
- v = 63;
- else if (c == '=')
- v = -1;
- else
- return 0; /* invalid atom */
- vals[i] = v;
- }
-
- if (vals[0] == -1 || vals[1] == -1)
- return 0;
- if (vals[2] == -1 && vals[3] != -1)
- return 0;
-
- if (vals[3] != -1)
- len = 3;
- else if (vals[2] != -1)
- len = 2;
- else
- len = 1;
-
- word = ((vals[0] << 18) |
- (vals[1] << 12) | ((vals[2] & 0x3F) << 6) | (vals[3] & 0x3F));
- out[0] = (word >> 16) & 0xFF;
- if (len > 1)
- out[1] = (word >> 8) & 0xFF;
- if (len > 2)
- out[2] = word & 0xFF;
- return len;
-}
-
static unsigned char *read_blob(FILE * fp, int nlines, int *bloblen)
{
unsigned char *blob;
encryption = comment = mac = NULL;
public_blob = private_blob = NULL;
- fp = f_open(*filename, "rb");
+ fp = f_open(filename, "rb", FALSE);
if (!fp) {
error = "can't open file";
goto error;
/* this is an old key file; warn and then continue */
old_keyfile_warning();
old_fmt = 1;
+ } else if (0 == strncmp(header, "PuTTY-User-Key-File-", 20)) {
+ /* this is a key file FROM THE FUTURE; refuse it, but with a
+ * more specific error message than the generic one below */
+ error = "PuTTY key format too new";
+ goto error;
} else {
error = "not a PuTTY SSH-2 private key";
goto error;
cipher = 0;
cipherblk = 1;
} else {
- sfree(encryption);
goto error;
}
hmac_sha1_simple(mackey, 20, macdata, maclen, binary);
- memset(mackey, 0, sizeof(mackey));
- memset(&s, 0, sizeof(s));
+ smemclr(mackey, sizeof(mackey));
+ smemclr(&s, sizeof(s));
} else {
SHA_Simple(macdata, maclen, binary);
}
if (free_macdata) {
- memset(macdata, 0, maclen);
+ smemclr(macdata, maclen);
sfree(macdata);
}
}
}
sfree(mac);
+ mac = NULL;
/*
* Create and return the key.
ret->data = alg->createkey(public_blob, public_blob_len,
private_blob, private_blob_len);
if (!ret->data) {
- sfree(ret->comment);
sfree(ret);
ret = NULL;
error = "createkey failed";
goto error;
}
sfree(public_blob);
+ smemclr(private_blob, private_blob_len);
sfree(private_blob);
sfree(encryption);
if (errorstr)
sfree(mac);
if (public_blob)
sfree(public_blob);
- if (private_blob)
- sfree(private_blob);
+ if (private_blob) {
+ smemclr(private_blob, private_blob_len);
+ sfree(private_blob);
+ }
if (errorstr)
*errorstr = error;
return ret;
}
-char *ssh2_userkey_loadpub(const Filename *filename, char **algorithm,
- int *pub_blob_len, char **commentptr,
- const char **errorstr)
+unsigned char *ssh2_userkey_loadpub(const Filename *filename, char **algorithm,
+ int *pub_blob_len, char **commentptr,
+ const char **errorstr)
{
FILE *fp;
char header[40], *b;
int public_blob_len;
int i;
const char *error = NULL;
- char *comment;
+ char *comment = NULL;
public_blob = NULL;
- fp = f_open(*filename, "rb");
+ fp = f_open(filename, "rb", FALSE);
if (!fp) {
error = "can't open file";
goto error;
if (!read_header(fp, header)
|| (0 != strcmp(header, "PuTTY-User-Key-File-2") &&
0 != strcmp(header, "PuTTY-User-Key-File-1"))) {
- error = "not a PuTTY SSH-2 private key";
+ if (0 == strncmp(header, "PuTTY-User-Key-File-", 20))
+ error = "PuTTY key format too new";
+ else
+ error = "not a PuTTY SSH-2 private key";
goto error;
}
error = "file format error";
goto error;
/* Select key algorithm structure. */
alg = find_pubkey_alg(b);
+ sfree(b);
if (!alg) {
- sfree(b);
goto error;
}
- sfree(b);
/* Read the Encryption header line. */
if (!read_header(fp, header) || 0 != strcmp(header, "Encryption"))
*pub_blob_len = public_blob_len;
if (algorithm)
*algorithm = alg->name;
- return (char *)public_blob;
+ return public_blob;
/*
* Error processing.
sfree(public_blob);
if (errorstr)
*errorstr = error;
+ if (comment && commentptr) {
+ sfree(comment);
+ *commentptr = NULL;
+ }
return NULL;
}
if (commentptr)
*commentptr = NULL;
- fp = f_open(*filename, "rb");
+ fp = f_open(filename, "rb", FALSE);
if (!fp)
return 0;
if (!read_header(fp, header)
if (commentptr)
*commentptr = comment;
+ else
+ sfree(comment);
fclose(fp);
if (!strcmp(b, "aes256-cbc"))
SHA_Bytes(&s, passphrase, strlen(passphrase));
SHA_Final(&s, mackey);
hmac_sha1_simple(mackey, 20, macdata, maclen, priv_mac);
- memset(macdata, 0, maclen);
+ smemclr(macdata, maclen);
sfree(macdata);
- memset(mackey, 0, sizeof(mackey));
- memset(&s, 0, sizeof(s));
+ smemclr(mackey, sizeof(mackey));
+ smemclr(&s, sizeof(s));
}
if (passphrase) {
aes256_encrypt_pubkey(key, priv_blob_encrypted,
priv_encrypted_len);
- memset(key, 0, sizeof(key));
- memset(&s, 0, sizeof(s));
+ smemclr(key, sizeof(key));
+ smemclr(&s, sizeof(s));
}
- fp = f_open(*filename, "w");
- if (!fp)
- return 0;
+ fp = f_open(filename, "w", TRUE);
+ if (!fp) {
+ sfree(pub_blob);
+ smemclr(priv_blob, priv_blob_len);
+ sfree(priv_blob);
+ smemclr(priv_blob_encrypted, priv_blob_len);
+ sfree(priv_blob_encrypted);
+ return 0;
+ }
fprintf(fp, "PuTTY-User-Key-File-2: %s\n", key->alg->name);
fprintf(fp, "Encryption: %s\n", cipherstr);
fprintf(fp, "Comment: %s\n", key->comment);
fclose(fp);
sfree(pub_blob);
- memset(priv_blob, 0, priv_blob_len);
+ smemclr(priv_blob, priv_blob_len);
sfree(priv_blob);
+ smemclr(priv_blob_encrypted, priv_blob_len);
sfree(priv_blob_encrypted);
return 1;
}
const char openssh_sig[] = "-----BEGIN ";
int i;
- fp = f_open(*filename, "r");
+ fp = f_open(filename, "r", FALSE);
if (!fp)
return SSH_KEYTYPE_UNOPENABLE;
i = fread(buf, 1, sizeof(buf), fp);