diff options
Diffstat (limited to 'sshkey.c')
-rw-r--r-- | sshkey.c | 27 |
1 files changed, 19 insertions, 8 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshkey.c,v 1.103 2020/04/08 00:01:52 djm Exp $ */ | 1 | /* $OpenBSD: sshkey.c,v 1.104 2020/04/08 00:04:32 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2008 Alexander von Gernler. All rights reserved. | 4 | * Copyright (c) 2008 Alexander von Gernler. All rights reserved. |
@@ -4135,8 +4135,8 @@ private2_uudecode(struct sshbuf *blob, struct sshbuf **decodedp) | |||
4135 | } | 4135 | } |
4136 | 4136 | ||
4137 | static int | 4137 | static int |
4138 | private2_decrypt(struct sshbuf *decoded, struct sshbuf **decryptedp, | 4138 | private2_decrypt(struct sshbuf *decoded, const char *passphrase, |
4139 | const char *passphrase) | 4139 | struct sshbuf **decryptedp, struct sshkey **pubkeyp) |
4140 | { | 4140 | { |
4141 | char *ciphername = NULL, *kdfname = NULL; | 4141 | char *ciphername = NULL, *kdfname = NULL; |
4142 | const struct sshcipher *cipher = NULL; | 4142 | const struct sshcipher *cipher = NULL; |
@@ -4144,13 +4144,15 @@ private2_decrypt(struct sshbuf *decoded, struct sshbuf **decryptedp, | |||
4144 | size_t keylen = 0, ivlen = 0, authlen = 0, slen = 0; | 4144 | size_t keylen = 0, ivlen = 0, authlen = 0, slen = 0; |
4145 | struct sshbuf *kdf = NULL, *decrypted = NULL; | 4145 | struct sshbuf *kdf = NULL, *decrypted = NULL; |
4146 | struct sshcipher_ctx *ciphercontext = NULL; | 4146 | struct sshcipher_ctx *ciphercontext = NULL; |
4147 | struct sshkey *pubkey = NULL; | ||
4147 | u_char *key = NULL, *salt = NULL, *dp; | 4148 | u_char *key = NULL, *salt = NULL, *dp; |
4148 | u_int blocksize, rounds, nkeys, encrypted_len, check1, check2; | 4149 | u_int blocksize, rounds, nkeys, encrypted_len, check1, check2; |
4149 | 4150 | ||
4150 | if (decoded == NULL || decryptedp == NULL) | 4151 | if (decoded == NULL || decryptedp == NULL || pubkeyp == NULL) |
4151 | return SSH_ERR_INVALID_ARGUMENT; | 4152 | return SSH_ERR_INVALID_ARGUMENT; |
4152 | 4153 | ||
4153 | *decryptedp = NULL; | 4154 | *decryptedp = NULL; |
4155 | *pubkeyp = NULL; | ||
4154 | 4156 | ||
4155 | if ((decrypted = sshbuf_new()) == NULL) { | 4157 | if ((decrypted = sshbuf_new()) == NULL) { |
4156 | r = SSH_ERR_ALLOC_FAIL; | 4158 | r = SSH_ERR_ALLOC_FAIL; |
@@ -4171,7 +4173,7 @@ private2_decrypt(struct sshbuf *decoded, struct sshbuf **decryptedp, | |||
4171 | goto out; | 4173 | goto out; |
4172 | } | 4174 | } |
4173 | 4175 | ||
4174 | if ((r = sshbuf_skip_string(decoded)) != 0 || /* pubkey */ | 4176 | if ((r = sshkey_froms(decoded, &pubkey)) != 0 || |
4175 | (r = sshbuf_get_u32(decoded, &encrypted_len)) != 0) | 4177 | (r = sshbuf_get_u32(decoded, &encrypted_len)) != 0) |
4176 | goto out; | 4178 | goto out; |
4177 | 4179 | ||
@@ -4258,11 +4260,14 @@ private2_decrypt(struct sshbuf *decoded, struct sshbuf **decryptedp, | |||
4258 | /* success */ | 4260 | /* success */ |
4259 | *decryptedp = decrypted; | 4261 | *decryptedp = decrypted; |
4260 | decrypted = NULL; | 4262 | decrypted = NULL; |
4263 | *pubkeyp = pubkey; | ||
4264 | pubkey = NULL; | ||
4261 | r = 0; | 4265 | r = 0; |
4262 | out: | 4266 | out: |
4263 | cipher_free(ciphercontext); | 4267 | cipher_free(ciphercontext); |
4264 | free(ciphername); | 4268 | free(ciphername); |
4265 | free(kdfname); | 4269 | free(kdfname); |
4270 | sshkey_free(pubkey); | ||
4266 | if (salt != NULL) { | 4271 | if (salt != NULL) { |
4267 | explicit_bzero(salt, slen); | 4272 | explicit_bzero(salt, slen); |
4268 | free(salt); | 4273 | free(salt); |
@@ -4308,7 +4313,7 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, | |||
4308 | char *comment = NULL; | 4313 | char *comment = NULL; |
4309 | int r = SSH_ERR_INTERNAL_ERROR; | 4314 | int r = SSH_ERR_INTERNAL_ERROR; |
4310 | struct sshbuf *decoded = NULL, *decrypted = NULL; | 4315 | struct sshbuf *decoded = NULL, *decrypted = NULL; |
4311 | struct sshkey *k = NULL; | 4316 | struct sshkey *k = NULL, *pubkey = NULL; |
4312 | 4317 | ||
4313 | if (keyp != NULL) | 4318 | if (keyp != NULL) |
4314 | *keyp = NULL; | 4319 | *keyp = NULL; |
@@ -4317,7 +4322,8 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, | |||
4317 | 4322 | ||
4318 | /* Undo base64 encoding and decrypt the private section */ | 4323 | /* Undo base64 encoding and decrypt the private section */ |
4319 | if ((r = private2_uudecode(blob, &decoded)) != 0 || | 4324 | if ((r = private2_uudecode(blob, &decoded)) != 0 || |
4320 | (r = private2_decrypt(decoded, &decrypted, passphrase)) != 0) | 4325 | (r = private2_decrypt(decoded, passphrase, |
4326 | &decrypted, &pubkey)) != 0) | ||
4321 | goto out; | 4327 | goto out; |
4322 | 4328 | ||
4323 | /* Load the private key and comment */ | 4329 | /* Load the private key and comment */ |
@@ -4329,7 +4335,11 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, | |||
4329 | if ((r = private2_check_padding(decrypted)) != 0) | 4335 | if ((r = private2_check_padding(decrypted)) != 0) |
4330 | goto out; | 4336 | goto out; |
4331 | 4337 | ||
4332 | /* XXX decode pubkey and check against private */ | 4338 | /* Check that the public key in the envelope matches the private key */ |
4339 | if (!sshkey_equal(pubkey, k)) { | ||
4340 | r = SSH_ERR_INVALID_FORMAT; | ||
4341 | goto out; | ||
4342 | } | ||
4333 | 4343 | ||
4334 | /* success */ | 4344 | /* success */ |
4335 | r = 0; | 4345 | r = 0; |
@@ -4346,6 +4356,7 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, | |||
4346 | sshbuf_free(decoded); | 4356 | sshbuf_free(decoded); |
4347 | sshbuf_free(decrypted); | 4357 | sshbuf_free(decrypted); |
4348 | sshkey_free(k); | 4358 | sshkey_free(k); |
4359 | sshkey_free(pubkey); | ||
4349 | return r; | 4360 | return r; |
4350 | } | 4361 | } |
4351 | 4362 | ||