version 1.103, 2020/04/08 00:01:52 |
version 1.104, 2020/04/08 00:04:32 |
|
|
} |
} |
|
|
static int |
static int |
private2_decrypt(struct sshbuf *decoded, struct sshbuf **decryptedp, |
private2_decrypt(struct sshbuf *decoded, const char *passphrase, |
const char *passphrase) |
struct sshbuf **decryptedp, struct sshkey **pubkeyp) |
{ |
{ |
char *ciphername = NULL, *kdfname = NULL; |
char *ciphername = NULL, *kdfname = NULL; |
const struct sshcipher *cipher = NULL; |
const struct sshcipher *cipher = NULL; |
|
|
size_t keylen = 0, ivlen = 0, authlen = 0, slen = 0; |
size_t keylen = 0, ivlen = 0, authlen = 0, slen = 0; |
struct sshbuf *kdf = NULL, *decrypted = NULL; |
struct sshbuf *kdf = NULL, *decrypted = NULL; |
struct sshcipher_ctx *ciphercontext = NULL; |
struct sshcipher_ctx *ciphercontext = NULL; |
|
struct sshkey *pubkey = NULL; |
u_char *key = NULL, *salt = NULL, *dp; |
u_char *key = NULL, *salt = NULL, *dp; |
u_int blocksize, rounds, nkeys, encrypted_len, check1, check2; |
u_int blocksize, rounds, nkeys, encrypted_len, check1, check2; |
|
|
if (decoded == NULL || decryptedp == NULL) |
if (decoded == NULL || decryptedp == NULL || pubkeyp == NULL) |
return SSH_ERR_INVALID_ARGUMENT; |
return SSH_ERR_INVALID_ARGUMENT; |
|
|
*decryptedp = NULL; |
*decryptedp = NULL; |
|
*pubkeyp = NULL; |
|
|
if ((decrypted = sshbuf_new()) == NULL) { |
if ((decrypted = sshbuf_new()) == NULL) { |
r = SSH_ERR_ALLOC_FAIL; |
r = SSH_ERR_ALLOC_FAIL; |
|
|
goto out; |
goto out; |
} |
} |
|
|
if ((r = sshbuf_skip_string(decoded)) != 0 || /* pubkey */ |
if ((r = sshkey_froms(decoded, &pubkey)) != 0 || |
(r = sshbuf_get_u32(decoded, &encrypted_len)) != 0) |
(r = sshbuf_get_u32(decoded, &encrypted_len)) != 0) |
goto out; |
goto out; |
|
|
|
|
/* success */ |
/* success */ |
*decryptedp = decrypted; |
*decryptedp = decrypted; |
decrypted = NULL; |
decrypted = NULL; |
|
*pubkeyp = pubkey; |
|
pubkey = NULL; |
r = 0; |
r = 0; |
out: |
out: |
cipher_free(ciphercontext); |
cipher_free(ciphercontext); |
free(ciphername); |
free(ciphername); |
free(kdfname); |
free(kdfname); |
|
sshkey_free(pubkey); |
if (salt != NULL) { |
if (salt != NULL) { |
explicit_bzero(salt, slen); |
explicit_bzero(salt, slen); |
free(salt); |
free(salt); |
|
|
char *comment = NULL; |
char *comment = NULL; |
int r = SSH_ERR_INTERNAL_ERROR; |
int r = SSH_ERR_INTERNAL_ERROR; |
struct sshbuf *decoded = NULL, *decrypted = NULL; |
struct sshbuf *decoded = NULL, *decrypted = NULL; |
struct sshkey *k = NULL; |
struct sshkey *k = NULL, *pubkey = NULL; |
|
|
if (keyp != NULL) |
if (keyp != NULL) |
*keyp = NULL; |
*keyp = NULL; |
|
|
|
|
/* Undo base64 encoding and decrypt the private section */ |
/* Undo base64 encoding and decrypt the private section */ |
if ((r = private2_uudecode(blob, &decoded)) != 0 || |
if ((r = private2_uudecode(blob, &decoded)) != 0 || |
(r = private2_decrypt(decoded, &decrypted, passphrase)) != 0) |
(r = private2_decrypt(decoded, passphrase, |
|
&decrypted, &pubkey)) != 0) |
goto out; |
goto out; |
|
|
/* Load the private key and comment */ |
/* Load the private key and comment */ |
|
|
if ((r = private2_check_padding(decrypted)) != 0) |
if ((r = private2_check_padding(decrypted)) != 0) |
goto out; |
goto out; |
|
|
/* XXX decode pubkey and check against private */ |
/* Check that the public key in the envelope matches the private key */ |
|
if (!sshkey_equal(pubkey, k)) { |
|
r = SSH_ERR_INVALID_FORMAT; |
|
goto out; |
|
} |
|
|
/* success */ |
/* success */ |
r = 0; |
r = 0; |
|
|
sshbuf_free(decoded); |
sshbuf_free(decoded); |
sshbuf_free(decrypted); |
sshbuf_free(decrypted); |
sshkey_free(k); |
sshkey_free(k); |
|
sshkey_free(pubkey); |
return r; |
return r; |
} |
} |
|
|