- djm@cvs.openbsd.org 2014/06/24 01:13:21
[Makefile.in auth-bsdauth.c auth-chall.c auth-options.c auth-rsa.c [auth2-none.c auth2-pubkey.c authfile.c authfile.h cipher-3des1.c [cipher-chachapoly.c cipher-chachapoly.h cipher.c cipher.h [digest-libc.c digest-openssl.c digest.h dns.c entropy.c hmac.h [hostfile.c key.c key.h krl.c monitor.c packet.c rsa.c rsa.h [ssh-add.c ssh-agent.c ssh-dss.c ssh-ecdsa.c ssh-ed25519.c [ssh-keygen.c ssh-pkcs11-client.c ssh-pkcs11-helper.c ssh-pkcs11.c [ssh-rsa.c sshbuf-misc.c sshbuf.h sshconnect.c sshconnect1.c [sshconnect2.c sshd.c sshkey.c sshkey.h [openbsd-compat/openssl-compat.c openbsd-compat/openssl-compat.h] New key API: refactor key-related functions to be more library-like, existing API is offered as a set of wrappers. with and ok markus@ Thanks also to Ben Hawkes, David Tomaschik, Ivan Fratric, Matthew Dempsky and Ron Bowes for a detailed review a few months ago. NB. This commit also removes portable OpenSSH support for OpenSSL <0.9.8e.
This commit is contained in:
parent
2cd7929250
commit
8668706d0f
20
ChangeLog
20
ChangeLog
|
@ -24,6 +24,26 @@
|
|||
|
||||
Readers of a broken KRL caused by this bug will fail closed, so no
|
||||
should-have-been-revoked key will be accepted.
|
||||
- djm@cvs.openbsd.org 2014/06/24 01:13:21
|
||||
[Makefile.in auth-bsdauth.c auth-chall.c auth-options.c auth-rsa.c
|
||||
[auth2-none.c auth2-pubkey.c authfile.c authfile.h cipher-3des1.c
|
||||
[cipher-chachapoly.c cipher-chachapoly.h cipher.c cipher.h
|
||||
[digest-libc.c digest-openssl.c digest.h dns.c entropy.c hmac.h
|
||||
[hostfile.c key.c key.h krl.c monitor.c packet.c rsa.c rsa.h
|
||||
[ssh-add.c ssh-agent.c ssh-dss.c ssh-ecdsa.c ssh-ed25519.c
|
||||
[ssh-keygen.c ssh-pkcs11-client.c ssh-pkcs11-helper.c ssh-pkcs11.c
|
||||
[ssh-rsa.c sshbuf-misc.c sshbuf.h sshconnect.c sshconnect1.c
|
||||
[sshconnect2.c sshd.c sshkey.c sshkey.h
|
||||
[openbsd-compat/openssl-compat.c openbsd-compat/openssl-compat.h]
|
||||
New key API: refactor key-related functions to be more library-like,
|
||||
existing API is offered as a set of wrappers.
|
||||
|
||||
with and ok markus@
|
||||
|
||||
Thanks also to Ben Hawkes, David Tomaschik, Ivan Fratric, Matthew
|
||||
Dempsky and Ron Bowes for a detailed review a few months ago.
|
||||
NB. This commit also removes portable OpenSSH support for OpenSSL
|
||||
<0.9.8e.
|
||||
|
||||
20140618
|
||||
- (tim) [openssh/session.c] Work around to get chroot sftp working on UnixWare
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $Id: Makefile.in,v 1.359 2014/05/21 22:23:59 djm Exp $
|
||||
# $Id: Makefile.in,v 1.360 2014/07/02 05:28:03 djm Exp $
|
||||
|
||||
# uncomment if you run a non bourne compatable shell. Ie. csh
|
||||
#SHELL = @SH@
|
||||
|
@ -68,7 +68,8 @@ LIBOPENSSH_OBJS=\
|
|||
sshbuf.o \
|
||||
sshbuf-getput-basic.o \
|
||||
sshbuf-misc.o \
|
||||
sshbuf-getput-crypto.o
|
||||
sshbuf-getput-crypto.o \
|
||||
sshkey.o
|
||||
|
||||
LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
|
||||
authfd.o authfile.o bufaux.o bufbn.o buffer.o \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: auth-bsdauth.c,v 1.12 2014/03/12 04:50:32 djm Exp $ */
|
||||
/* $OpenBSD: auth-bsdauth.c,v 1.13 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||
*
|
||||
|
@ -26,6 +26,8 @@
|
|||
#include "includes.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: auth-chall.c,v 1.13 2013/05/17 00:13:13 djm Exp $ */
|
||||
/* $OpenBSD: auth-chall.c,v 1.14 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||
*
|
||||
|
@ -26,6 +26,9 @@
|
|||
#include "includes.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: auth-options.c,v 1.62 2013/12/19 00:27:57 djm Exp $ */
|
||||
/* $OpenBSD: auth-options.c,v 1.63 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -586,8 +586,8 @@ auth_cert_options(Key *k, struct passwd *pw)
|
|||
|
||||
if (key_cert_is_legacy(k)) {
|
||||
/* All options are in the one field for v00 certs */
|
||||
if (parse_option_list(buffer_ptr(&k->cert->critical),
|
||||
buffer_len(&k->cert->critical), pw,
|
||||
if (parse_option_list(buffer_ptr(k->cert->critical),
|
||||
buffer_len(k->cert->critical), pw,
|
||||
OPTIONS_CRITICAL|OPTIONS_EXTENSIONS, 1,
|
||||
&cert_no_port_forwarding_flag,
|
||||
&cert_no_agent_forwarding_flag,
|
||||
|
@ -599,14 +599,14 @@ auth_cert_options(Key *k, struct passwd *pw)
|
|||
return -1;
|
||||
} else {
|
||||
/* Separate options and extensions for v01 certs */
|
||||
if (parse_option_list(buffer_ptr(&k->cert->critical),
|
||||
buffer_len(&k->cert->critical), pw,
|
||||
if (parse_option_list(buffer_ptr(k->cert->critical),
|
||||
buffer_len(k->cert->critical), pw,
|
||||
OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL,
|
||||
&cert_forced_command,
|
||||
&cert_source_address_done) == -1)
|
||||
return -1;
|
||||
if (parse_option_list(buffer_ptr(&k->cert->extensions),
|
||||
buffer_len(&k->cert->extensions), pw,
|
||||
if (parse_option_list(buffer_ptr(k->cert->extensions),
|
||||
buffer_len(k->cert->extensions), pw,
|
||||
OPTIONS_EXTENSIONS, 1,
|
||||
&cert_no_port_forwarding_flag,
|
||||
&cert_no_agent_forwarding_flag,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: auth-rsa.c,v 1.86 2014/01/27 19:18:54 markus Exp $ */
|
||||
/* $OpenBSD: auth-rsa.c,v 1.87 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -144,7 +144,8 @@ auth_rsa_challenge_dialog(Key *key)
|
|||
challenge = PRIVSEP(auth_rsa_generate_challenge(key));
|
||||
|
||||
/* Encrypt the challenge with the public key. */
|
||||
rsa_public_encrypt(encrypted_challenge, challenge, key->rsa);
|
||||
if (rsa_public_encrypt(encrypted_challenge, challenge, key->rsa) != 0)
|
||||
fatal("%s: rsa_public_encrypt failed", __func__);
|
||||
|
||||
/* Send the encrypted challenge to the client. */
|
||||
packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: auth2-none.c,v 1.16 2010/06/25 08:46:17 djm Exp $ */
|
||||
/* $OpenBSD: auth2-none.c,v 1.17 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
|
@ -30,9 +30,10 @@
|
|||
#include <sys/uio.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "atomicio.h"
|
||||
#include "xmalloc.h"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: auth2-pubkey.c,v 1.39 2013/12/30 23:52:27 djm Exp $ */
|
||||
/* $OpenBSD: auth2-pubkey.c,v 1.40 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
|
@ -230,7 +230,7 @@ pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...)
|
|||
}
|
||||
|
||||
static int
|
||||
match_principals_option(const char *principal_list, struct KeyCert *cert)
|
||||
match_principals_option(const char *principal_list, struct sshkey_cert *cert)
|
||||
{
|
||||
char *result;
|
||||
u_int i;
|
||||
|
@ -250,7 +250,7 @@ match_principals_option(const char *principal_list, struct KeyCert *cert)
|
|||
}
|
||||
|
||||
static int
|
||||
match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert)
|
||||
match_principals_file(char *file, struct passwd *pw, struct sshkey_cert *cert)
|
||||
{
|
||||
FILE *f;
|
||||
char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts;
|
||||
|
|
1389
authfile.c
1389
authfile.c
File diff suppressed because it is too large
Load Diff
63
authfile.h
63
authfile.h
|
@ -1,32 +1,51 @@
|
|||
/* $OpenBSD: authfile.h,v 1.17 2013/12/06 13:34:54 markus Exp $ */
|
||||
/* $OpenBSD: authfile.h,v 1.18 2014/06/24 01:13:21 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
* All rights reserved
|
||||
* Copyright (c) 2000, 2013 Markus Friedl. All rights reserved.
|
||||
*
|
||||
* As far as I am concerned, the code I have written for this software
|
||||
* can be used freely for any purpose. Any derived versions of this
|
||||
* software must be clearly marked as such, and if the derived work is
|
||||
* incompatible with the protocol description in the RFC file, it must be
|
||||
* called by a name other than "ssh" or "Secure Shell".
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef AUTHFILE_H
|
||||
#define AUTHFILE_H
|
||||
|
||||
int key_save_private(Key *, const char *, const char *, const char *,
|
||||
int, const char *, int);
|
||||
int key_load_file(int, const char *, Buffer *);
|
||||
Key *key_load_cert(const char *);
|
||||
Key *key_load_public(const char *, char **);
|
||||
Key *key_load_public_type(int, const char *, char **);
|
||||
Key *key_parse_private(Buffer *, const char *, const char *, char **);
|
||||
Key *key_load_private(const char *, const char *, char **);
|
||||
Key *key_load_private_cert(int, const char *, const char *, int *);
|
||||
Key *key_load_private_type(int, const char *, const char *, char **, int *);
|
||||
Key *key_load_private_pem(int, int, const char *, char **);
|
||||
int key_perm_ok(int, const char *);
|
||||
int key_in_file(Key *, const char *, int);
|
||||
#ifdef WITH_LEAKMALLOC
|
||||
#include "leakmalloc.h"
|
||||
#endif
|
||||
|
||||
struct sshbuf;
|
||||
struct sshkey;
|
||||
|
||||
int sshkey_save_private(struct sshkey *, const char *,
|
||||
const char *, const char *, int, const char *, int);
|
||||
int sshkey_load_file(int, const char *, struct sshbuf *);
|
||||
int sshkey_load_cert(const char *, struct sshkey **);
|
||||
int sshkey_load_public(const char *, struct sshkey **, char **);
|
||||
int sshkey_load_private(const char *, const char *, struct sshkey **, char **);
|
||||
int sshkey_load_private_cert(int, const char *, const char *,
|
||||
struct sshkey **, int *);
|
||||
int sshkey_load_private_type(int, const char *, const char *,
|
||||
struct sshkey **, char **, int *);
|
||||
int sshkey_load_private_pem(int, int, const char *, struct sshkey **, char **);
|
||||
int sshkey_perm_ok(int, const char *);
|
||||
int sshkey_in_file(struct sshkey *, const char *, int);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,13 +29,11 @@
|
|||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "log.h"
|
||||
|
||||
#include "openbsd-compat/openssl-compat.h"
|
||||
#include "ssherr.h"
|
||||
|
||||
/*
|
||||
* This is used by SSH1:
|
||||
|
@ -57,7 +55,7 @@ struct ssh1_3des_ctx
|
|||
};
|
||||
|
||||
const EVP_CIPHER * evp_ssh1_3des(void);
|
||||
void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
|
||||
int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
|
||||
|
||||
static int
|
||||
ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
|
||||
|
@ -67,11 +65,12 @@ ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
|
|||
u_char *k1, *k2, *k3;
|
||||
|
||||
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
|
||||
c = xcalloc(1, sizeof(*c));
|
||||
if ((c = calloc(1, sizeof(*c))) == NULL)
|
||||
return 0;
|
||||
EVP_CIPHER_CTX_set_app_data(ctx, c);
|
||||
}
|
||||
if (key == NULL)
|
||||
return (1);
|
||||
return 1;
|
||||
if (enc == -1)
|
||||
enc = ctx->encrypt;
|
||||
k1 = k2 = k3 = (u_char *) key;
|
||||
|
@ -85,44 +84,29 @@ ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
|
|||
EVP_CIPHER_CTX_init(&c->k1);
|
||||
EVP_CIPHER_CTX_init(&c->k2);
|
||||
EVP_CIPHER_CTX_init(&c->k3);
|
||||
#ifdef SSH_OLD_EVP
|
||||
EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc);
|
||||
EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc);
|
||||
EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc);
|
||||
#else
|
||||
if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
|
||||
EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
|
||||
EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
|
||||
explicit_bzero(c, sizeof(*c));
|
||||
free(c);
|
||||
EVP_CIPHER_CTX_set_app_data(ctx, NULL);
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
|
||||
LIBCRYPTO_EVP_INL_TYPE len)
|
||||
ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, size_t len)
|
||||
{
|
||||
struct ssh1_3des_ctx *c;
|
||||
|
||||
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
|
||||
error("ssh1_3des_cbc: no context");
|
||||
return (0);
|
||||
}
|
||||
#ifdef SSH_OLD_EVP
|
||||
EVP_Cipher(&c->k1, dest, (u_char *)src, len);
|
||||
EVP_Cipher(&c->k2, dest, dest, len);
|
||||
EVP_Cipher(&c->k3, dest, dest, len);
|
||||
#else
|
||||
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL)
|
||||
return 0;
|
||||
if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
|
||||
EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
|
||||
EVP_Cipher(&c->k3, dest, dest, len) == 0)
|
||||
return (0);
|
||||
#endif
|
||||
return (1);
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -138,29 +122,28 @@ ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
|
|||
free(c);
|
||||
EVP_CIPHER_CTX_set_app_data(ctx, NULL);
|
||||
}
|
||||
return (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
|
||||
{
|
||||
struct ssh1_3des_ctx *c;
|
||||
|
||||
if (len != 24)
|
||||
fatal("%s: bad 3des iv length: %d", __func__, len);
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
|
||||
fatal("%s: no 3des context", __func__);
|
||||
return SSH_ERR_INTERNAL_ERROR;
|
||||
if (doset) {
|
||||
debug3("%s: Installed 3DES IV", __func__);
|
||||
memcpy(c->k1.iv, iv, 8);
|
||||
memcpy(c->k2.iv, iv + 8, 8);
|
||||
memcpy(c->k3.iv, iv + 16, 8);
|
||||
} else {
|
||||
debug3("%s: Copying 3DES IV", __func__);
|
||||
memcpy(iv, c->k1.iv, 8);
|
||||
memcpy(iv + 8, c->k2.iv, 8);
|
||||
memcpy(iv + 16, c->k3.iv, 8);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const EVP_CIPHER *
|
||||
|
@ -176,8 +159,6 @@ evp_ssh1_3des(void)
|
|||
ssh1_3des.init = ssh1_3des_init;
|
||||
ssh1_3des.cleanup = ssh1_3des_cleanup;
|
||||
ssh1_3des.do_cipher = ssh1_3des_cbc;
|
||||
#ifndef SSH_OLD_EVP
|
||||
ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
|
||||
#endif
|
||||
return (&ssh1_3des);
|
||||
return &ssh1_3des;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $OpenBSD: cipher-chachapoly.c,v 1.4 2014/01/31 16:39:19 tedu Exp $ */
|
||||
/* $OpenBSD: cipher-chachapoly.c,v 1.5 2014/06/24 01:13:21 djm Exp $ */
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
|
@ -24,16 +24,18 @@
|
|||
#include <stdio.h> /* needed for misc.h */
|
||||
|
||||
#include "log.h"
|
||||
#include "misc.h"
|
||||
#include "sshbuf.h"
|
||||
#include "ssherr.h"
|
||||
#include "cipher-chachapoly.h"
|
||||
|
||||
void chachapoly_init(struct chachapoly_ctx *ctx,
|
||||
int chachapoly_init(struct chachapoly_ctx *ctx,
|
||||
const u_char *key, u_int keylen)
|
||||
{
|
||||
if (keylen != (32 + 32)) /* 2 x 256 bit keys */
|
||||
fatal("%s: invalid keylen %u", __func__, keylen);
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
chacha_keysetup(&ctx->main_ctx, key, 256);
|
||||
chacha_keysetup(&ctx->header_ctx, key + 32, 256);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -52,14 +54,14 @@ chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest,
|
|||
u_char seqbuf[8];
|
||||
const u_char one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */
|
||||
u_char expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN];
|
||||
int r = -1;
|
||||
int r = SSH_ERR_INTERNAL_ERROR;
|
||||
|
||||
/*
|
||||
* Run ChaCha20 once to generate the Poly1305 key. The IV is the
|
||||
* packet sequence number.
|
||||
*/
|
||||
memset(poly_key, 0, sizeof(poly_key));
|
||||
put_u64(seqbuf, seqnr);
|
||||
POKE_U64(seqbuf, seqnr);
|
||||
chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL);
|
||||
chacha_encrypt_bytes(&ctx->main_ctx,
|
||||
poly_key, poly_key, sizeof(poly_key));
|
||||
|
@ -71,9 +73,11 @@ chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest,
|
|||
const u_char *tag = src + aadlen + len;
|
||||
|
||||
poly1305_auth(expected_tag, src, aadlen + len, poly_key);
|
||||
if (timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN) != 0)
|
||||
if (timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN) != 0) {
|
||||
r = SSH_ERR_MAC_INVALID;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
/* Crypt additional data */
|
||||
if (aadlen) {
|
||||
chacha_ivsetup(&ctx->header_ctx, seqbuf, NULL);
|
||||
|
@ -88,7 +92,6 @@ chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest,
|
|||
poly_key);
|
||||
}
|
||||
r = 0;
|
||||
|
||||
out:
|
||||
explicit_bzero(expected_tag, sizeof(expected_tag));
|
||||
explicit_bzero(seqbuf, sizeof(seqbuf));
|
||||
|
@ -104,11 +107,11 @@ chachapoly_get_length(struct chachapoly_ctx *ctx,
|
|||
u_char buf[4], seqbuf[8];
|
||||
|
||||
if (len < 4)
|
||||
return -1; /* Insufficient length */
|
||||
put_u64(seqbuf, seqnr);
|
||||
return SSH_ERR_MESSAGE_INCOMPLETE;
|
||||
POKE_U64(seqbuf, seqnr);
|
||||
chacha_ivsetup(&ctx->header_ctx, seqbuf, NULL);
|
||||
chacha_encrypt_bytes(&ctx->header_ctx, cp, buf, 4);
|
||||
*plenp = get_u32(buf);
|
||||
*plenp = PEEK_U32(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: cipher-chachapoly.h,v 1.3 2014/05/02 03:27:54 djm Exp $ */
|
||||
/* $OpenBSD: cipher-chachapoly.h,v 1.4 2014/06/24 01:13:21 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) Damien Miller 2013 <djm@mindrot.org>
|
||||
|
@ -28,7 +28,7 @@ struct chachapoly_ctx {
|
|||
struct chacha_ctx main_ctx, header_ctx;
|
||||
};
|
||||
|
||||
void chachapoly_init(struct chachapoly_ctx *cpctx,
|
||||
int chachapoly_init(struct chachapoly_ctx *cpctx,
|
||||
const u_char *key, u_int keylen)
|
||||
__attribute__((__bounded__(__buffer__, 2, 3)));
|
||||
int chachapoly_crypt(struct chachapoly_ctx *cpctx, u_int seqnr,
|
||||
|
|
407
cipher.c
407
cipher.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: cipher.c,v 1.98 2014/04/29 18:01:49 markus Exp $ */
|
||||
/* $OpenBSD: cipher.c,v 1.99 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -43,23 +43,19 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "log.h"
|
||||
#include "misc.h"
|
||||
#include "cipher.h"
|
||||
#include "buffer.h"
|
||||
#include "misc.h"
|
||||
#include "sshbuf.h"
|
||||
#include "ssherr.h"
|
||||
#include "digest.h"
|
||||
|
||||
/* compatibility with old or broken OpenSSL versions */
|
||||
#include "openbsd-compat/openssl-compat.h"
|
||||
|
||||
#ifdef WITH_SSH1
|
||||
extern const EVP_CIPHER *evp_ssh1_bf(void);
|
||||
extern const EVP_CIPHER *evp_ssh1_3des(void);
|
||||
extern void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
|
||||
extern int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
|
||||
#endif
|
||||
|
||||
struct Cipher {
|
||||
struct sshcipher {
|
||||
char *name;
|
||||
int number; /* for ssh1 only */
|
||||
u_int block_size;
|
||||
|
@ -79,12 +75,12 @@ struct Cipher {
|
|||
#endif
|
||||
};
|
||||
|
||||
static const struct Cipher ciphers[] = {
|
||||
static const struct sshcipher ciphers[] = {
|
||||
#ifdef WITH_SSH1
|
||||
{ "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc },
|
||||
{ "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des },
|
||||
{ "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 0, 0, 1, evp_ssh1_bf },
|
||||
#endif
|
||||
#endif /* WITH_SSH1 */
|
||||
#ifdef WITH_OPENSSL
|
||||
{ "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null },
|
||||
{ "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc },
|
||||
|
@ -103,12 +99,12 @@ static const struct Cipher ciphers[] = {
|
|||
{ "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr },
|
||||
{ "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr },
|
||||
{ "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr },
|
||||
#ifdef OPENSSL_HAVE_EVPGCM
|
||||
# ifdef OPENSSL_HAVE_EVPGCM
|
||||
{ "aes128-gcm@openssh.com",
|
||||
SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm },
|
||||
{ "aes256-gcm@openssh.com",
|
||||
SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm },
|
||||
#endif
|
||||
# endif /* OPENSSL_HAVE_EVPGCM */
|
||||
#else /* WITH_OPENSSL */
|
||||
{ "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, CFLAG_AESCTR, NULL },
|
||||
{ "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, CFLAG_AESCTR, NULL },
|
||||
|
@ -117,18 +113,19 @@ static const struct Cipher ciphers[] = {
|
|||
#endif /* WITH_OPENSSL */
|
||||
{ "chacha20-poly1305@openssh.com",
|
||||
SSH_CIPHER_SSH2, 8, 64, 0, 16, 0, CFLAG_CHACHAPOLY, NULL },
|
||||
|
||||
{ NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL }
|
||||
};
|
||||
|
||||
/*--*/
|
||||
|
||||
/* Returns a list of supported ciphers separated by the specified char. */
|
||||
/* Returns a comma-separated list of supported ciphers. */
|
||||
char *
|
||||
cipher_alg_list(char sep, int auth_only)
|
||||
{
|
||||
char *ret = NULL;
|
||||
char *tmp, *ret = NULL;
|
||||
size_t nlen, rlen = 0;
|
||||
const Cipher *c;
|
||||
const struct sshcipher *c;
|
||||
|
||||
for (c = ciphers; c->name != NULL; c++) {
|
||||
if (c->number != SSH_CIPHER_SSH2)
|
||||
|
@ -138,7 +135,11 @@ cipher_alg_list(char sep, int auth_only)
|
|||
if (ret != NULL)
|
||||
ret[rlen++] = sep;
|
||||
nlen = strlen(c->name);
|
||||
ret = xrealloc(ret, 1, rlen + nlen + 2);
|
||||
if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
ret = tmp;
|
||||
memcpy(ret + rlen, c->name, nlen + 1);
|
||||
rlen += nlen;
|
||||
}
|
||||
|
@ -146,19 +147,19 @@ cipher_alg_list(char sep, int auth_only)
|
|||
}
|
||||
|
||||
u_int
|
||||
cipher_blocksize(const Cipher *c)
|
||||
cipher_blocksize(const struct sshcipher *c)
|
||||
{
|
||||
return (c->block_size);
|
||||
}
|
||||
|
||||
u_int
|
||||
cipher_keylen(const Cipher *c)
|
||||
cipher_keylen(const struct sshcipher *c)
|
||||
{
|
||||
return (c->key_len);
|
||||
}
|
||||
|
||||
u_int
|
||||
cipher_seclen(const Cipher *c)
|
||||
cipher_seclen(const struct sshcipher *c)
|
||||
{
|
||||
if (strcmp("3des-cbc", c->name) == 0)
|
||||
return 14;
|
||||
|
@ -166,13 +167,13 @@ cipher_seclen(const Cipher *c)
|
|||
}
|
||||
|
||||
u_int
|
||||
cipher_authlen(const Cipher *c)
|
||||
cipher_authlen(const struct sshcipher *c)
|
||||
{
|
||||
return (c->auth_len);
|
||||
}
|
||||
|
||||
u_int
|
||||
cipher_ivlen(const Cipher *c)
|
||||
cipher_ivlen(const struct sshcipher *c)
|
||||
{
|
||||
/*
|
||||
* Default is cipher block size, except for chacha20+poly1305 that
|
||||
|
@ -183,13 +184,13 @@ cipher_ivlen(const Cipher *c)
|
|||
}
|
||||
|
||||
u_int
|
||||
cipher_get_number(const Cipher *c)
|
||||
cipher_get_number(const struct sshcipher *c)
|
||||
{
|
||||
return (c->number);
|
||||
}
|
||||
|
||||
u_int
|
||||
cipher_is_cbc(const Cipher *c)
|
||||
cipher_is_cbc(const struct sshcipher *c)
|
||||
{
|
||||
return (c->flags & CFLAG_CBC) != 0;
|
||||
}
|
||||
|
@ -206,20 +207,20 @@ cipher_mask_ssh1(int client)
|
|||
return mask;
|
||||
}
|
||||
|
||||
const Cipher *
|
||||
const struct sshcipher *
|
||||
cipher_by_name(const char *name)
|
||||
{
|
||||
const Cipher *c;
|
||||
const struct sshcipher *c;
|
||||
for (c = ciphers; c->name != NULL; c++)
|
||||
if (strcmp(c->name, name) == 0)
|
||||
return c;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const Cipher *
|
||||
const struct sshcipher *
|
||||
cipher_by_number(int id)
|
||||
{
|
||||
const Cipher *c;
|
||||
const struct sshcipher *c;
|
||||
for (c = ciphers; c->name != NULL; c++)
|
||||
if (c->number == id)
|
||||
return c;
|
||||
|
@ -230,23 +231,22 @@ cipher_by_number(int id)
|
|||
int
|
||||
ciphers_valid(const char *names)
|
||||
{
|
||||
const Cipher *c;
|
||||
const struct sshcipher *c;
|
||||
char *cipher_list, *cp;
|
||||
char *p;
|
||||
|
||||
if (names == NULL || strcmp(names, "") == 0)
|
||||
return 0;
|
||||
cipher_list = cp = xstrdup(names);
|
||||
if ((cipher_list = cp = strdup(names)) == NULL)
|
||||
return 0;
|
||||
for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
|
||||
(p = strsep(&cp, CIPHER_SEP))) {
|
||||
c = cipher_by_name(p);
|
||||
if (c == NULL || c->number != SSH_CIPHER_SSH2) {
|
||||
debug("bad cipher %s [%s]", p, names);
|
||||
free(cipher_list);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
debug3("ciphers ok: [%s]", names);
|
||||
free(cipher_list);
|
||||
return 1;
|
||||
}
|
||||
|
@ -259,7 +259,7 @@ ciphers_valid(const char *names)
|
|||
int
|
||||
cipher_number(const char *name)
|
||||
{
|
||||
const Cipher *c;
|
||||
const struct sshcipher *c;
|
||||
if (name == NULL)
|
||||
return -1;
|
||||
for (c = ciphers; c->name != NULL; c++)
|
||||
|
@ -271,31 +271,33 @@ cipher_number(const char *name)
|
|||
char *
|
||||
cipher_name(int id)
|
||||
{
|
||||
const Cipher *c = cipher_by_number(id);
|
||||
const struct sshcipher *c = cipher_by_number(id);
|
||||
return (c==NULL) ? "<unknown>" : c->name;
|
||||
}
|
||||
|
||||
void
|
||||
cipher_init(CipherContext *cc, const Cipher *cipher,
|
||||
const char *
|
||||
cipher_warning_message(const struct sshcipher_ctx *cc)
|
||||
{
|
||||
if (cc == NULL || cc->cipher == NULL)
|
||||
return NULL;
|
||||
if (cc->cipher->number == SSH_CIPHER_DES)
|
||||
return "use of DES is strongly discouraged due to "
|
||||
"cryptographic weaknesses";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
cipher_init(struct sshcipher_ctx *cc, const struct sshcipher *cipher,
|
||||
const u_char *key, u_int keylen, const u_char *iv, u_int ivlen,
|
||||
int do_encrypt)
|
||||
{
|
||||
#ifdef WITH_OPENSSL
|
||||
static int dowarn = 1;
|
||||
#ifdef SSH_OLD_EVP
|
||||
EVP_CIPHER *type;
|
||||
#else
|
||||
int ret = SSH_ERR_INTERNAL_ERROR;
|
||||
const EVP_CIPHER *type;
|
||||
int klen;
|
||||
#endif
|
||||
u_char *junk, *discard;
|
||||
|
||||
if (cipher->number == SSH_CIPHER_DES) {
|
||||
if (dowarn) {
|
||||
error("Warning: use of DES is strongly discouraged "
|
||||
"due to cryptographic weaknesses");
|
||||
dowarn = 0;
|
||||
}
|
||||
if (keylen > 8)
|
||||
keylen = 8;
|
||||
}
|
||||
|
@ -303,71 +305,70 @@ cipher_init(CipherContext *cc, const Cipher *cipher,
|
|||
cc->plaintext = (cipher->number == SSH_CIPHER_NONE);
|
||||
cc->encrypt = do_encrypt;
|
||||
|
||||
if (keylen < cipher->key_len)
|
||||
fatal("cipher_init: key length %d is insufficient for %s.",
|
||||
keylen, cipher->name);
|
||||
if (iv != NULL && ivlen < cipher_ivlen(cipher))
|
||||
fatal("cipher_init: iv length %d is insufficient for %s.",
|
||||
ivlen, cipher->name);
|
||||
cc->cipher = cipher;
|
||||
if (keylen < cipher->key_len ||
|
||||
(iv != NULL && ivlen < cipher_ivlen(cipher)))
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
|
||||
cc->cipher = cipher;
|
||||
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
|
||||
chachapoly_init(&cc->cp_ctx, key, keylen);
|
||||
return;
|
||||
return chachapoly_init(&cc->cp_ctx, key, keylen);
|
||||
}
|
||||
#ifndef WITH_OPENSSL
|
||||
if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
|
||||
aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen);
|
||||
aesctr_ivsetup(&cc->ac_ctx, iv);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if ((cc->cipher->flags & CFLAG_NONE) != 0)
|
||||
return;
|
||||
fatal("unsupported cipher");
|
||||
return 0;
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
#else
|
||||
type = (*cipher->evptype)();
|
||||
EVP_CIPHER_CTX_init(&cc->evp);
|
||||
#ifdef SSH_OLD_EVP
|
||||
if (type->key_len > 0 && type->key_len != keylen) {
|
||||
debug("cipher_init: set keylen (%d -> %d)",
|
||||
type->key_len, keylen);
|
||||
type->key_len = keylen;
|
||||
}
|
||||
EVP_CipherInit(&cc->evp, type, (u_char *)key, (u_char *)iv,
|
||||
(do_encrypt == CIPHER_ENCRYPT));
|
||||
#else
|
||||
if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv,
|
||||
(do_encrypt == CIPHER_ENCRYPT)) == 0)
|
||||
fatal("cipher_init: EVP_CipherInit failed for %s",
|
||||
cipher->name);
|
||||
(do_encrypt == CIPHER_ENCRYPT)) == 0) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto bad;
|
||||
}
|
||||
if (cipher_authlen(cipher) &&
|
||||
!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_IV_FIXED,
|
||||
-1, (u_char *)iv))
|
||||
fatal("cipher_init: EVP_CTRL_GCM_SET_IV_FIXED failed for %s",
|
||||
cipher->name);
|
||||
-1, (u_char *)iv)) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto bad;
|
||||
}
|
||||
klen = EVP_CIPHER_CTX_key_length(&cc->evp);
|
||||
if (klen > 0 && keylen != (u_int)klen) {
|
||||
debug2("cipher_init: set keylen (%d -> %d)", klen, keylen);
|
||||
if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0)
|
||||
fatal("cipher_init: set keylen failed (%d -> %d)",
|
||||
klen, keylen);
|
||||
if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto bad;
|
||||
}
|
||||
if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0)
|
||||
fatal("cipher_init: EVP_CipherInit: set key failed for %s",
|
||||
cipher->name);
|
||||
#endif
|
||||
|
||||
if (cipher->discard_len > 0) {
|
||||
junk = xmalloc(cipher->discard_len);
|
||||
discard = xmalloc(cipher->discard_len);
|
||||
if (EVP_Cipher(&cc->evp, discard, junk,
|
||||
cipher->discard_len) == 0)
|
||||
fatal("evp_crypt: EVP_Cipher failed during discard");
|
||||
if ((junk = malloc(cipher->discard_len)) == NULL ||
|
||||
(discard = malloc(cipher->discard_len)) == NULL) {
|
||||
if (junk != NULL)
|
||||
free(junk);
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto bad;
|
||||
}
|
||||
ret = EVP_Cipher(&cc->evp, discard, junk, cipher->discard_len);
|
||||
explicit_bzero(discard, cipher->discard_len);
|
||||
free(junk);
|
||||
free(discard);
|
||||
if (ret != 1) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
bad:
|
||||
EVP_CIPHER_CTX_cleanup(&cc->evp);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -379,16 +380,15 @@ cipher_init(CipherContext *cc, const Cipher *cipher,
|
|||
* Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag.
|
||||
* This tag is written on encryption and verified on decryption.
|
||||
* Both 'aadlen' and 'authlen' can be set to 0.
|
||||
* cipher_crypt() returns 0 on success and -1 if the decryption integrity
|
||||
* check fails.
|
||||
*/
|
||||
int
|
||||
cipher_crypt(CipherContext *cc, u_int seqnr, u_char *dest, const u_char *src,
|
||||
u_int len, u_int aadlen, u_int authlen)
|
||||
cipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest,
|
||||
const u_char *src, u_int len, u_int aadlen, u_int authlen)
|
||||
{
|
||||
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
|
||||
return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src, len,
|
||||
aadlen, authlen, cc->encrypt);
|
||||
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
|
||||
return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src,
|
||||
len, aadlen, authlen, cc->encrypt);
|
||||
}
|
||||
#ifndef WITH_OPENSSL
|
||||
if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
|
||||
if (aadlen)
|
||||
|
@ -401,46 +401,43 @@ cipher_crypt(CipherContext *cc, u_int seqnr, u_char *dest, const u_char *src,
|
|||
memcpy(dest, src, aadlen + len);
|
||||
return 0;
|
||||
}
|
||||
fatal("unsupported cipher");
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
#else
|
||||
if (authlen) {
|
||||
u_char lastiv[1];
|
||||
|
||||
if (authlen != cipher_authlen(cc->cipher))
|
||||
fatal("%s: authlen mismatch %d", __func__, authlen);
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
/* increment IV */
|
||||
if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN,
|
||||
1, lastiv))
|
||||
fatal("%s: EVP_CTRL_GCM_IV_GEN", __func__);
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
/* set tag on decyption */
|
||||
if (!cc->encrypt &&
|
||||
!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_TAG,
|
||||
authlen, (u_char *)src + aadlen + len))
|
||||
fatal("%s: EVP_CTRL_GCM_SET_TAG", __func__);
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
}
|
||||
if (aadlen) {
|
||||
if (authlen &&
|
||||
EVP_Cipher(&cc->evp, NULL, (u_char *)src, aadlen) < 0)
|
||||
fatal("%s: EVP_Cipher(aad) failed", __func__);
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
memcpy(dest, src, aadlen);
|
||||
}
|
||||
if (len % cc->cipher->block_size)
|
||||
fatal("%s: bad plaintext length %d", __func__, len);
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
if (EVP_Cipher(&cc->evp, dest + aadlen, (u_char *)src + aadlen,
|
||||
len) < 0)
|
||||
fatal("%s: EVP_Cipher failed", __func__);
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
if (authlen) {
|
||||
/* compute tag (on encrypt) or verify tag (on decrypt) */
|
||||
if (EVP_Cipher(&cc->evp, NULL, NULL, 0) < 0) {
|
||||
if (cc->encrypt)
|
||||
fatal("%s: EVP_Cipher(final) failed", __func__);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
if (EVP_Cipher(&cc->evp, NULL, NULL, 0) < 0)
|
||||
return cc->encrypt ?
|
||||
SSH_ERR_LIBCRYPTO_ERROR : SSH_ERR_MAC_INVALID;
|
||||
if (cc->encrypt &&
|
||||
!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG,
|
||||
authlen, dest + aadlen + len))
|
||||
fatal("%s: EVP_CTRL_GCM_GET_TAG", __func__);
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
|
@ -448,61 +445,65 @@ cipher_crypt(CipherContext *cc, u_int seqnr, u_char *dest, const u_char *src,
|
|||
|
||||
/* Extract the packet length, including any decryption necessary beforehand */
|
||||
int
|
||||
cipher_get_length(CipherContext *cc, u_int *plenp, u_int seqnr,
|
||||
cipher_get_length(struct sshcipher_ctx *cc, u_int *plenp, u_int seqnr,
|
||||
const u_char *cp, u_int len)
|
||||
{
|
||||
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
|
||||
return chachapoly_get_length(&cc->cp_ctx, plenp, seqnr,
|
||||
cp, len);
|
||||
if (len < 4)
|
||||
return -1;
|
||||
return SSH_ERR_MESSAGE_INCOMPLETE;
|
||||
*plenp = get_u32(cp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
cipher_cleanup(CipherContext *cc)
|
||||
int
|
||||
cipher_cleanup(struct sshcipher_ctx *cc)
|
||||
{
|
||||
if (cc == NULL || cc->cipher == NULL)
|
||||
return 0;
|
||||
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
|
||||
explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx));
|
||||
else if ((cc->cipher->flags & CFLAG_AESCTR) != 0)
|
||||
explicit_bzero(&cc->ac_ctx, sizeof(cc->ac_ctx));
|
||||
#ifdef WITH_OPENSSL
|
||||
else if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0)
|
||||
error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed");
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Selects the cipher, and keys if by computing the MD5 checksum of the
|
||||
* passphrase and using the resulting 16 bytes as the key.
|
||||
*/
|
||||
|
||||
void
|
||||
cipher_set_key_string(CipherContext *cc, const Cipher *cipher,
|
||||
int
|
||||
cipher_set_key_string(struct sshcipher_ctx *cc, const struct sshcipher *cipher,
|
||||
const char *passphrase, int do_encrypt)
|
||||
{
|
||||
u_char digest[16];
|
||||
int r = SSH_ERR_INTERNAL_ERROR;
|
||||
|
||||
if (ssh_digest_memory(SSH_DIGEST_MD5, passphrase, strlen(passphrase),
|
||||
digest, sizeof(digest)) < 0)
|
||||
fatal("%s: md5 failed", __func__);
|
||||
|
||||
cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt);
|
||||
if ((r = ssh_digest_memory(SSH_DIGEST_MD5,
|
||||
passphrase, strlen(passphrase),
|
||||
digest, sizeof(digest))) != 0)
|
||||
goto out;
|
||||
|
||||
r = cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt);
|
||||
out:
|
||||
explicit_bzero(digest, sizeof(digest));
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Exports an IV from the CipherContext required to export the key
|
||||
* Exports an IV from the sshcipher_ctx required to export the key
|
||||
* state back from the unprivileged child to the privileged parent
|
||||
* process.
|
||||
*/
|
||||
|
||||
int
|
||||
cipher_get_keyiv_len(const CipherContext *cc)
|
||||
cipher_get_keyiv_len(const struct sshcipher_ctx *cc)
|
||||
{
|
||||
const Cipher *c = cc->cipher;
|
||||
const struct sshcipher *c = cc->cipher;
|
||||
int ivlen = 0;
|
||||
|
||||
if (c->number == SSH_CIPHER_3DES)
|
||||
|
@ -512,77 +513,25 @@ cipher_get_keyiv_len(const CipherContext *cc)
|
|||
#ifdef WITH_OPENSSL
|
||||
else
|
||||
ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp);
|
||||
#endif
|
||||
#endif /* WITH_OPENSSL */
|
||||
return (ivlen);
|
||||
}
|
||||
|
||||
void
|
||||
cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len)
|
||||
int
|
||||
cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len)
|
||||
{
|
||||
const Cipher *c = cc->cipher;
|
||||
const struct sshcipher *c = cc->cipher;
|
||||
#ifdef WITH_OPENSSL
|
||||
int evplen;
|
||||
#endif
|
||||
|
||||
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
|
||||
if (len != 0)
|
||||
fatal("%s: wrong iv length %d != %d", __func__, len, 0);
|
||||
return;
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
return 0;
|
||||
}
|
||||
if ((cc->cipher->flags & CFLAG_NONE) != 0)
|
||||
return;
|
||||
|
||||
switch (c->number) {
|
||||
#ifdef WITH_OPENSSL
|
||||
case SSH_CIPHER_SSH2:
|
||||
case SSH_CIPHER_DES:
|
||||
case SSH_CIPHER_BLOWFISH:
|
||||
evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
|
||||
if (evplen <= 0)
|
||||
return;
|
||||
if ((u_int)evplen != len)
|
||||
fatal("%s: wrong iv length %d != %d", __func__,
|
||||
evplen, len);
|
||||
#ifdef USE_BUILTIN_RIJNDAEL
|
||||
if (c->evptype == evp_rijndael)
|
||||
ssh_rijndael_iv(&cc->evp, 0, iv, len);
|
||||
else
|
||||
#endif /* USE_BUILTIN_RIJNDAEL */
|
||||
#ifndef OPENSSL_HAVE_EVPCTR
|
||||
if (c->evptype == evp_aes_128_ctr)
|
||||
ssh_aes_ctr_iv(&cc->evp, 0, iv, len);
|
||||
else
|
||||
#endif /* OPENSSL_HAVE_EVPCTR */
|
||||
if (cipher_authlen(c)) {
|
||||
if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN,
|
||||
len, iv))
|
||||
fatal("%s: EVP_CTRL_GCM_IV_GEN", __func__);
|
||||
} else
|
||||
memcpy(iv, cc->evp.iv, len);
|
||||
break;
|
||||
#endif /* WITH_OPENSSL */
|
||||
#ifdef WITH_SSH1
|
||||
case SSH_CIPHER_3DES:
|
||||
ssh1_3des_iv(&cc->evp, 0, iv, 24);
|
||||
break;
|
||||
#endif /* WITH_SSH1 */
|
||||
default:
|
||||
fatal("%s: bad cipher %d", __func__, c->number);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cipher_set_keyiv(CipherContext *cc, u_char *iv)
|
||||
{
|
||||
const Cipher *c = cc->cipher;
|
||||
#ifdef WITH_OPENSSL
|
||||
int evplen = 0;
|
||||
#endif
|
||||
|
||||
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
|
||||
return;
|
||||
if ((cc->cipher->flags & CFLAG_NONE) != 0)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
switch (c->number) {
|
||||
#ifdef WITH_OPENSSL
|
||||
|
@ -591,41 +540,79 @@ cipher_set_keyiv(CipherContext *cc, u_char *iv)
|
|||
case SSH_CIPHER_BLOWFISH:
|
||||
evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
|
||||
if (evplen == 0)
|
||||
return;
|
||||
#ifdef USE_BUILTIN_RIJNDAEL
|
||||
if (c->evptype == evp_rijndael)
|
||||
ssh_rijndael_iv(&cc->evp, 1, iv, evplen);
|
||||
else
|
||||
#endif /* USE_BUILTIN_RIJNDAEL */
|
||||
#ifndef OPENSSL_HAVE_EVPCTR
|
||||
if (c->evptype == evp_aes_128_ctr)
|
||||
ssh_aes_ctr_iv(&cc->evp, 1, iv, evplen);
|
||||
else
|
||||
#endif /* OPENSSL_HAVE_EVPCTR */
|
||||
return 0;
|
||||
else if (evplen < 0)
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
if ((u_int)evplen != len)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
if (cipher_authlen(c)) {
|
||||
if (!EVP_CIPHER_CTX_ctrl(&cc->evp,
|
||||
EVP_CTRL_GCM_SET_IV_FIXED, -1, iv))
|
||||
fatal("%s: EVP_CTRL_GCM_SET_IV_FIXED failed",
|
||||
__func__);
|
||||
if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN,
|
||||
len, iv))
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
} else
|
||||
memcpy(cc->evp.iv, iv, evplen);
|
||||
memcpy(iv, cc->evp.iv, len);
|
||||
break;
|
||||
#endif /* WITH_OPENSSL */
|
||||
#endif
|
||||
#ifdef WITH_SSH1
|
||||
case SSH_CIPHER_3DES:
|
||||
ssh1_3des_iv(&cc->evp, 1, iv, 24);
|
||||
break;
|
||||
#endif /* WITH_SSH1 */
|
||||
return ssh1_3des_iv(&cc->evp, 0, iv, 24);
|
||||
#endif
|
||||
default:
|
||||
fatal("%s: bad cipher %d", __func__, c->number);
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cipher_get_keycontext(const CipherContext *cc, u_char *dat)
|
||||
cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv)
|
||||
{
|
||||
const struct sshcipher *c = cc->cipher;
|
||||
#ifdef WITH_OPENSSL
|
||||
int evplen = 0;
|
||||
#endif
|
||||
|
||||
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
|
||||
return 0;
|
||||
if ((cc->cipher->flags & CFLAG_NONE) != 0)
|
||||
return 0;
|
||||
|
||||
switch (c->number) {
|
||||
#ifdef WITH_OPENSSL
|
||||
case SSH_CIPHER_SSH2:
|
||||
case SSH_CIPHER_DES:
|
||||
case SSH_CIPHER_BLOWFISH:
|
||||
evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
|
||||
if (evplen <= 0)
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
if (cipher_authlen(c)) {
|
||||
/* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */
|
||||
if (!EVP_CIPHER_CTX_ctrl(&cc->evp,
|
||||
EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv))
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
} else
|
||||
memcpy(cc->evp.iv, iv, evplen);
|
||||
break;
|
||||
#endif
|
||||
#ifdef WITH_SSH1
|
||||
case SSH_CIPHER_3DES:
|
||||
return ssh1_3des_iv(&cc->evp, 1, (u_char *)iv, 24);
|
||||
#endif
|
||||
default:
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
#define EVP_X_STATE(evp) (evp).cipher_data
|
||||
#define EVP_X_STATE_LEN(evp) (evp).cipher->ctx_size
|
||||
#endif
|
||||
|
||||
int
|
||||
cipher_get_keycontext(const struct sshcipher_ctx *cc, u_char *dat)
|
||||
{
|
||||
#ifdef WITH_OPENSSL
|
||||
const Cipher *c = cc->cipher;
|
||||
const struct sshcipher *c = cc->cipher;
|
||||
int plen = 0;
|
||||
|
||||
if (c->evptype == EVP_rc4) {
|
||||
|
@ -636,15 +623,15 @@ cipher_get_keycontext(const CipherContext *cc, u_char *dat)
|
|||
}
|
||||
return (plen);
|
||||
#else
|
||||
return (0);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
cipher_set_keycontext(CipherContext *cc, u_char *dat)
|
||||
cipher_set_keycontext(struct sshcipher_ctx *cc, const u_char *dat)
|
||||
{
|
||||
#ifdef WITH_OPENSSL
|
||||
const Cipher *c = cc->cipher;
|
||||
const struct sshcipher *c = cc->cipher;
|
||||
int plen;
|
||||
|
||||
if (c->evptype == EVP_rc4) {
|
||||
|
|
57
cipher.h
57
cipher.h
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: cipher.h,v 1.45 2014/04/29 18:01:49 markus Exp $ */
|
||||
/* $OpenBSD: cipher.h,v 1.46 2014/06/24 01:13:21 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
|
@ -37,6 +37,7 @@
|
|||
#ifndef CIPHER_H
|
||||
#define CIPHER_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <openssl/evp.h>
|
||||
#include "cipher-chachapoly.h"
|
||||
#include "cipher-aesctr.h"
|
||||
|
@ -61,45 +62,47 @@
|
|||
#define CIPHER_ENCRYPT 1
|
||||
#define CIPHER_DECRYPT 0
|
||||
|
||||
typedef struct Cipher Cipher;
|
||||
typedef struct CipherContext CipherContext;
|
||||
|
||||
struct Cipher;
|
||||
struct CipherContext {
|
||||
struct sshcipher;
|
||||
struct sshcipher_ctx {
|
||||
int plaintext;
|
||||
int encrypt;
|
||||
EVP_CIPHER_CTX evp;
|
||||
struct chachapoly_ctx cp_ctx; /* XXX union with evp? */
|
||||
struct aesctr_ctx ac_ctx; /* XXX union with evp? */
|
||||
const Cipher *cipher;
|
||||
const struct sshcipher *cipher;
|
||||
};
|
||||
|
||||
typedef struct sshcipher Cipher ;
|
||||
typedef struct sshcipher_ctx CipherContext ;
|
||||
|
||||
u_int cipher_mask_ssh1(int);
|
||||
const Cipher *cipher_by_name(const char *);
|
||||
const Cipher *cipher_by_number(int);
|
||||
const struct sshcipher *cipher_by_name(const char *);
|
||||
const struct sshcipher *cipher_by_number(int);
|
||||
int cipher_number(const char *);
|
||||
char *cipher_name(int);
|
||||
int ciphers_valid(const char *);
|
||||
char *cipher_alg_list(char, int);
|
||||
void cipher_init(CipherContext *, const Cipher *, const u_char *, u_int,
|
||||
const u_char *, u_int, int);
|
||||
int cipher_crypt(CipherContext *, u_int, u_char *, const u_char *,
|
||||
int cipher_init(struct sshcipher_ctx *, const struct sshcipher *,
|
||||
const u_char *, u_int, const u_char *, u_int, int);
|
||||
const char* cipher_warning_message(const struct sshcipher_ctx *);
|
||||
int cipher_crypt(struct sshcipher_ctx *, u_int, u_char *, const u_char *,
|
||||
u_int, u_int, u_int);
|
||||
int cipher_get_length(CipherContext *, u_int *, u_int,
|
||||
int cipher_get_length(struct sshcipher_ctx *, u_int *, u_int,
|
||||
const u_char *, u_int);
|
||||
void cipher_cleanup(CipherContext *);
|
||||
void cipher_set_key_string(CipherContext *, const Cipher *, const char *, int);
|
||||
u_int cipher_blocksize(const Cipher *);
|
||||
u_int cipher_keylen(const Cipher *);
|
||||
u_int cipher_seclen(const Cipher *);
|
||||
u_int cipher_authlen(const Cipher *);
|
||||
u_int cipher_ivlen(const Cipher *);
|
||||
u_int cipher_is_cbc(const Cipher *);
|
||||
int cipher_cleanup(struct sshcipher_ctx *);
|
||||
int cipher_set_key_string(struct sshcipher_ctx *, const struct sshcipher *,
|
||||
const char *, int);
|
||||
u_int cipher_blocksize(const struct sshcipher *);
|
||||
u_int cipher_keylen(const struct sshcipher *);
|
||||
u_int cipher_seclen(const struct sshcipher *);
|
||||
u_int cipher_authlen(const struct sshcipher *);
|
||||
u_int cipher_ivlen(const struct sshcipher *);
|
||||
u_int cipher_is_cbc(const struct sshcipher *);
|
||||
|
||||
u_int cipher_get_number(const Cipher *);
|
||||
void cipher_get_keyiv(CipherContext *, u_char *, u_int);
|
||||
void cipher_set_keyiv(CipherContext *, u_char *);
|
||||
int cipher_get_keyiv_len(const CipherContext *);
|
||||
int cipher_get_keycontext(const CipherContext *, u_char *);
|
||||
void cipher_set_keycontext(CipherContext *, u_char *);
|
||||
u_int cipher_get_number(const struct sshcipher *);
|
||||
int cipher_get_keyiv(struct sshcipher_ctx *, u_char *, u_int);
|
||||
int cipher_set_keyiv(struct sshcipher_ctx *, const u_char *);
|
||||
int cipher_get_keyiv_len(const struct sshcipher_ctx *);
|
||||
int cipher_get_keycontext(const struct sshcipher_ctx *, u_char *);
|
||||
void cipher_set_keycontext(struct sshcipher_ctx *, const u_char *);
|
||||
#endif /* CIPHER_H */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: digest-libc.c,v 1.2 2014/02/02 03:44:31 djm Exp $ */
|
||||
/* $OpenBSD: digest-libc.c,v 1.3 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2013 Damien Miller <djm@mindrot.org>
|
||||
* Copyright (c) 2014 Markus Friedl. All rights reserved.
|
||||
|
@ -28,7 +28,8 @@
|
|||
#include <sha1.h>
|
||||
#include <sha2.h>
|
||||
|
||||
#include "buffer.h"
|
||||
#include "ssherr.h"
|
||||
#include "sshbuf.h"
|
||||
#include "digest.h"
|
||||
|
||||
typedef void md_init_fn(void *mdctx);
|
||||
|
@ -164,7 +165,7 @@ ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to)
|
|||
const struct ssh_digest *digest = ssh_digest_by_alg(from->alg);
|
||||
|
||||
if (digest == NULL || from->alg != to->alg)
|
||||
return -1;
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
memcpy(to->mdctx, from->mdctx, digest->ctx_len);
|
||||
return 0;
|
||||
}
|
||||
|
@ -175,15 +176,15 @@ ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
|
|||
const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg);
|
||||
|
||||
if (digest == NULL)
|
||||
return -1;
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
digest->md_update(ctx->mdctx, m, mlen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const Buffer *b)
|
||||
ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const struct sshbuf *b)
|
||||
{
|
||||
return ssh_digest_update(ctx, buffer_ptr(b), buffer_len(b));
|
||||
return ssh_digest_update(ctx, sshbuf_ptr(b), sshbuf_len(b));
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -192,11 +193,11 @@ ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen)
|
|||
const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg);
|
||||
|
||||
if (digest == NULL)
|
||||
return -1;
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
if (dlen > UINT_MAX)
|
||||
return -1;
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
if (dlen < digest->digest_len) /* No truncation allowed */
|
||||
return -1;
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
digest->md_final(d, ctx->mdctx);
|
||||
return 0;
|
||||
}
|
||||
|
@ -223,16 +224,16 @@ ssh_digest_memory(int alg, const void *m, size_t mlen, u_char *d, size_t dlen)
|
|||
struct ssh_digest_ctx *ctx = ssh_digest_start(alg);
|
||||
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
if (ssh_digest_update(ctx, m, mlen) != 0 ||
|
||||
ssh_digest_final(ctx, d, dlen) != 0)
|
||||
return -1;
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
ssh_digest_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ssh_digest_buffer(int alg, const Buffer *b, u_char *d, size_t dlen)
|
||||
ssh_digest_buffer(int alg, const struct sshbuf *b, u_char *d, size_t dlen)
|
||||
{
|
||||
return ssh_digest_memory(alg, buffer_ptr(b), buffer_len(b), d, dlen);
|
||||
return ssh_digest_memory(alg, sshbuf_ptr(b), sshbuf_len(b), d, dlen);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: digest-openssl.c,v 1.2 2014/02/02 03:44:31 djm Exp $ */
|
||||
/* $OpenBSD: digest-openssl.c,v 1.3 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2013 Damien Miller <djm@mindrot.org>
|
||||
*
|
||||
|
@ -26,8 +26,9 @@
|
|||
|
||||
#include "openbsd-compat/openssl-compat.h"
|
||||
|
||||
#include "buffer.h"
|
||||
#include "sshbuf.h"
|
||||
#include "digest.h"
|
||||
#include "ssherr.h"
|
||||
|
||||
struct ssh_digest_ctx {
|
||||
int alg;
|
||||
|
@ -98,9 +99,11 @@ ssh_digest_start(int alg)
|
|||
int
|
||||
ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to)
|
||||
{
|
||||
if (from->alg != to->alg)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
/* we have bcopy-style order while openssl has memcpy-style */
|
||||
if (!EVP_MD_CTX_copy_ex(&to->mdctx, &from->mdctx))
|
||||
return -1;
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -108,14 +111,14 @@ int
|
|||
ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
|
||||
{
|
||||
if (EVP_DigestUpdate(&ctx->mdctx, m, mlen) != 1)
|
||||
return -1;
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const Buffer *b)
|
||||
ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const struct sshbuf *b)
|
||||
{
|
||||
return ssh_digest_update(ctx, buffer_ptr(b), buffer_len(b));
|
||||
return ssh_digest_update(ctx, sshbuf_ptr(b), sshbuf_len(b));
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -125,13 +128,13 @@ ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen)
|
|||
u_int l = dlen;
|
||||
|
||||
if (dlen > UINT_MAX)
|
||||
return -1;
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
if (dlen < digest->digest_len) /* No truncation allowed */
|
||||
return -1;
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
if (EVP_DigestFinal_ex(&ctx->mdctx, d, &l) != 1)
|
||||
return -1;
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
if (l != digest->digest_len) /* sanity */
|
||||
return -1;
|
||||
return SSH_ERR_INTERNAL_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -149,18 +152,19 @@ int
|
|||
ssh_digest_memory(int alg, const void *m, size_t mlen, u_char *d, size_t dlen)
|
||||
{
|
||||
struct ssh_digest_ctx *ctx = ssh_digest_start(alg);
|
||||
int r;
|
||||
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
if (ssh_digest_update(ctx, m, mlen) != 0 ||
|
||||
ssh_digest_final(ctx, d, dlen) != 0)
|
||||
return -1;
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
if ((r = ssh_digest_update(ctx, m, mlen) != 0) ||
|
||||
(r = ssh_digest_final(ctx, d, dlen) != 0))
|
||||
return r;
|
||||
ssh_digest_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ssh_digest_buffer(int alg, const Buffer *b, u_char *d, size_t dlen)
|
||||
ssh_digest_buffer(int alg, const struct sshbuf *b, u_char *d, size_t dlen)
|
||||
{
|
||||
return ssh_digest_memory(alg, buffer_ptr(b), buffer_len(b), d, dlen);
|
||||
return ssh_digest_memory(alg, sshbuf_ptr(b), sshbuf_len(b), d, dlen);
|
||||
}
|
||||
|
|
7
digest.h
7
digest.h
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: digest.h,v 1.4 2014/05/02 03:27:54 djm Exp $ */
|
||||
/* $OpenBSD: digest.h,v 1.5 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2013 Damien Miller <djm@mindrot.org>
|
||||
*
|
||||
|
@ -47,14 +47,15 @@ int ssh_digest_memory(int alg, const void *m, size_t mlen,
|
|||
u_char *d, size_t dlen)
|
||||
__attribute__((__bounded__(__buffer__, 2, 3)))
|
||||
__attribute__((__bounded__(__buffer__, 4, 5)));
|
||||
int ssh_digest_buffer(int alg, const Buffer *b, u_char *d, size_t dlen)
|
||||
int ssh_digest_buffer(int alg, const struct sshbuf *b, u_char *d, size_t dlen)
|
||||
__attribute__((__bounded__(__buffer__, 3, 4)));
|
||||
|
||||
/* Update API */
|
||||
struct ssh_digest_ctx *ssh_digest_start(int alg);
|
||||
int ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
|
||||
__attribute__((__bounded__(__buffer__, 2, 3)));
|
||||
int ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const Buffer *b);
|
||||
int ssh_digest_update_buffer(struct ssh_digest_ctx *ctx,
|
||||
const struct sshbuf *b);
|
||||
int ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen)
|
||||
__attribute__((__bounded__(__buffer__, 2, 3)));
|
||||
void ssh_digest_free(struct ssh_digest_ctx *ctx);
|
||||
|
|
4
dns.c
4
dns.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: dns.c,v 1.30 2014/04/20 09:24:26 logan Exp $ */
|
||||
/* $OpenBSD: dns.c,v 1.31 2014/06/24 01:13:21 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
|
||||
|
@ -34,6 +34,8 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "key.h"
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "openbsd-compat/openssl-compat.h"
|
||||
|
||||
#include "ssh.h"
|
||||
#include "misc.h"
|
||||
#include "xmalloc.h"
|
||||
|
|
5
hmac.h
5
hmac.h
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: hmac.h,v 1.8 2014/05/02 03:27:54 djm Exp $ */
|
||||
/* $OpenBSD: hmac.h,v 1.9 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2014 Markus Friedl. All rights reserved.
|
||||
*
|
||||
|
@ -21,6 +21,7 @@
|
|||
/* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */
|
||||
size_t ssh_hmac_bytes(int alg);
|
||||
|
||||
struct sshbuf;
|
||||
struct ssh_hmac_ctx;
|
||||
struct ssh_hmac_ctx *ssh_hmac_start(int alg);
|
||||
|
||||
|
@ -29,7 +30,7 @@ int ssh_hmac_init(struct ssh_hmac_ctx *ctx, const void *key, size_t klen)
|
|||
__attribute__((__bounded__(__buffer__, 2, 3)));
|
||||
int ssh_hmac_update(struct ssh_hmac_ctx *ctx, const void *m, size_t mlen)
|
||||
__attribute__((__bounded__(__buffer__, 2, 3)));
|
||||
int ssh_hmac_update_buffer(struct ssh_hmac_ctx *ctx, const Buffer *b);
|
||||
int ssh_hmac_update_buffer(struct ssh_hmac_ctx *ctx, const struct sshbuf *b);
|
||||
int ssh_hmac_final(struct ssh_hmac_ctx *ctx, u_char *d, size_t dlen)
|
||||
__attribute__((__bounded__(__buffer__, 2, 3)));
|
||||
void ssh_hmac_free(struct ssh_hmac_ctx *ctx);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: hostfile.c,v 1.56 2014/04/29 18:01:49 markus Exp $ */
|
||||
/* $OpenBSD: hostfile.c,v 1.57 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -47,6 +47,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "match.h"
|
||||
|
|
163
key.h
163
key.h
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: key.h,v 1.41 2014/01/09 23:20:00 djm Exp $ */
|
||||
/* $OpenBSD: key.h,v 1.42 2014/06/24 01:13:21 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
|
@ -26,141 +26,86 @@
|
|||
#ifndef KEY_H
|
||||
#define KEY_H
|
||||
|
||||
#include "buffer.h"
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/dsa.h>
|
||||
#ifdef OPENSSL_HAS_ECC
|
||||
#include <openssl/ec.h>
|
||||
#include "sshkey.h"
|
||||
|
||||
typedef struct sshkey Key;
|
||||
|
||||
#define types sshkey_types
|
||||
#define fp_type sshkey_fp_type
|
||||
#define fp_rep sshkey_fp_rep
|
||||
|
||||
#ifndef SSH_KEY_NO_DEFINE
|
||||
#define key_new sshkey_new
|
||||
#define key_free sshkey_free
|
||||
#define key_equal_public sshkey_equal_public
|
||||
#define key_equal sshkey_equal
|
||||
#define key_fingerprint sshkey_fingerprint
|
||||
#define key_type sshkey_type
|
||||
#define key_cert_type sshkey_cert_type
|
||||
#define key_ssh_name sshkey_ssh_name
|
||||
#define key_ssh_name_plain sshkey_ssh_name_plain
|
||||
#define key_type_from_name sshkey_type_from_name
|
||||
#define key_ecdsa_nid_from_name sshkey_ecdsa_nid_from_name
|
||||
#define key_type_is_cert sshkey_type_is_cert
|
||||
#define key_size sshkey_size
|
||||
#define key_ecdsa_bits_to_nid sshkey_ecdsa_bits_to_nid
|
||||
#define key_ecdsa_key_to_nid sshkey_ecdsa_key_to_nid
|
||||
#define key_names_valid2 sshkey_names_valid2
|
||||
#define key_is_cert sshkey_is_cert
|
||||
#define key_type_plain sshkey_type_plain
|
||||
#define key_cert_is_legacy sshkey_cert_is_legacy
|
||||
#define key_curve_name_to_nid sshkey_curve_name_to_nid
|
||||
#define key_curve_nid_to_bits sshkey_curve_nid_to_bits
|
||||
#define key_curve_nid_to_name sshkey_curve_nid_to_name
|
||||
#define key_ec_nid_to_hash_alg sshkey_ec_nid_to_hash_alg
|
||||
#define key_dump_ec_point sshkey_dump_ec_point
|
||||
#define key_dump_ec_key sshkey_dump_ec_key
|
||||
#define key_fingerprint sshkey_fingerprint
|
||||
#endif
|
||||
|
||||
typedef struct Key Key;
|
||||
enum types {
|
||||
KEY_RSA1,
|
||||
KEY_RSA,
|
||||
KEY_DSA,
|
||||
KEY_ECDSA,
|
||||
KEY_ED25519,
|
||||
KEY_RSA_CERT,
|
||||
KEY_DSA_CERT,
|
||||
KEY_ECDSA_CERT,
|
||||
KEY_ED25519_CERT,
|
||||
KEY_RSA_CERT_V00,
|
||||
KEY_DSA_CERT_V00,
|
||||
KEY_UNSPEC
|
||||
};
|
||||
enum fp_type {
|
||||
SSH_FP_SHA1,
|
||||
SSH_FP_MD5,
|
||||
SSH_FP_SHA256
|
||||
};
|
||||
enum fp_rep {
|
||||
SSH_FP_HEX,
|
||||
SSH_FP_BUBBLEBABBLE,
|
||||
SSH_FP_RANDOMART
|
||||
};
|
||||
|
||||
/* key is stored in external hardware */
|
||||
#define KEY_FLAG_EXT 0x0001
|
||||
|
||||
#define CERT_MAX_PRINCIPALS 256
|
||||
struct KeyCert {
|
||||
Buffer certblob; /* Kept around for use on wire */
|
||||
u_int type; /* SSH2_CERT_TYPE_USER or SSH2_CERT_TYPE_HOST */
|
||||
u_int64_t serial;
|
||||
char *key_id;
|
||||
u_int nprincipals;
|
||||
char **principals;
|
||||
u_int64_t valid_after, valid_before;
|
||||
Buffer critical;
|
||||
Buffer extensions;
|
||||
Key *signature_key;
|
||||
};
|
||||
|
||||
struct Key {
|
||||
int type;
|
||||
int flags;
|
||||
RSA *rsa;
|
||||
DSA *dsa;
|
||||
int ecdsa_nid; /* NID of curve */
|
||||
#ifdef OPENSSL_HAS_ECC
|
||||
EC_KEY *ecdsa;
|
||||
#else
|
||||
void *ecdsa;
|
||||
#endif
|
||||
struct KeyCert *cert;
|
||||
u_char *ed25519_sk;
|
||||
u_char *ed25519_pk;
|
||||
};
|
||||
|
||||
#define ED25519_SK_SZ crypto_sign_ed25519_SECRETKEYBYTES
|
||||
#define ED25519_PK_SZ crypto_sign_ed25519_PUBLICKEYBYTES
|
||||
|
||||
Key *key_new(int);
|
||||
void key_add_private(Key *);
|
||||
Key *key_new_private(int);
|
||||
void key_free(Key *);
|
||||
Key *key_demote(const Key *);
|
||||
int key_equal_public(const Key *, const Key *);
|
||||
int key_equal(const Key *, const Key *);
|
||||
char *key_fingerprint(const Key *, enum fp_type, enum fp_rep);
|
||||
u_char *key_fingerprint_raw(const Key *, enum fp_type, u_int *);
|
||||
const char *key_type(const Key *);
|
||||
const char *key_cert_type(const Key *);
|
||||
int key_write(const Key *, FILE *);
|
||||
int key_read(Key *, char **);
|
||||
u_int key_size(const Key *);
|
||||
|
||||
Key *key_generate(int, u_int);
|
||||
Key *key_from_private(const Key *);
|
||||
int key_type_from_name(char *);
|
||||
int key_is_cert(const Key *);
|
||||
int key_type_is_cert(int);
|
||||
int key_type_plain(int);
|
||||
int key_to_certified(Key *, int);
|
||||
int key_drop_cert(Key *);
|
||||
int key_certify(Key *, Key *);
|
||||
void key_cert_copy(const Key *, struct Key *);
|
||||
void key_cert_copy(const Key *, Key *);
|
||||
int key_cert_check_authority(const Key *, int, int, const char *,
|
||||
const char **);
|
||||
int key_cert_is_legacy(const Key *);
|
||||
char *key_alg_list(int, int);
|
||||
|
||||
int key_ecdsa_nid_from_name(const char *);
|
||||
int key_curve_name_to_nid(const char *);
|
||||
const char *key_curve_nid_to_name(int);
|
||||
u_int key_curve_nid_to_bits(int);
|
||||
int key_ecdsa_bits_to_nid(int);
|
||||
#ifdef OPENSSL_HAS_ECC
|
||||
int key_ecdsa_key_to_nid(EC_KEY *);
|
||||
int key_ec_nid_to_hash_alg(int nid);
|
||||
#ifdef WITH_OPENSSL
|
||||
int key_ec_validate_public(const EC_GROUP *, const EC_POINT *);
|
||||
int key_ec_validate_private(const EC_KEY *);
|
||||
#endif
|
||||
char *key_alg_list(int, int);
|
||||
#endif /* WITH_OPENSSL */
|
||||
|
||||
Key *key_from_blob(const u_char *, u_int);
|
||||
int key_to_blob(const Key *, u_char **, u_int *);
|
||||
const char *key_ssh_name(const Key *);
|
||||
const char *key_ssh_name_plain(const Key *);
|
||||
int key_names_valid2(const char *);
|
||||
|
||||
int key_sign(const Key *, u_char **, u_int *, const u_char *, u_int);
|
||||
int key_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
|
||||
|
||||
int ssh_dss_sign(const Key *, u_char **, u_int *, const u_char *, u_int);
|
||||
int ssh_dss_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
|
||||
int ssh_ecdsa_sign(const Key *, u_char **, u_int *, const u_char *, u_int);
|
||||
int ssh_ecdsa_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
|
||||
int ssh_rsa_sign(const Key *, u_char **, u_int *, const u_char *, u_int);
|
||||
int ssh_rsa_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
|
||||
int ssh_ed25519_sign(const Key *, u_char **, u_int *, const u_char *, u_int);
|
||||
int ssh_ed25519_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
|
||||
void key_private_serialize(const Key *, struct sshbuf *);
|
||||
Key *key_private_deserialize(struct sshbuf *);
|
||||
|
||||
#if defined(OPENSSL_HAS_ECC) && (defined(DEBUG_KEXECDH) || defined(DEBUG_PK))
|
||||
void key_dump_ec_point(const EC_GROUP *, const EC_POINT *);
|
||||
void key_dump_ec_key(const EC_KEY *);
|
||||
#endif
|
||||
|
||||
void key_private_serialize(const Key *, Buffer *);
|
||||
Key *key_private_deserialize(Buffer *);
|
||||
/* authfile.c */
|
||||
int key_save_private(Key *, const char *, const char *, const char *,
|
||||
int, const char *, int);
|
||||
int key_load_file(int, const char *, struct sshbuf *);
|
||||
Key *key_load_cert(const char *);
|
||||
Key *key_load_public(const char *, char **);
|
||||
Key *key_load_private(const char *, const char *, char **);
|
||||
Key *key_load_private_cert(int, const char *, const char *, int *);
|
||||
Key *key_load_private_type(int, const char *, const char *, char **, int *);
|
||||
Key *key_load_private_pem(int, int, const char *, char **);
|
||||
int key_perm_ok(int, const char *);
|
||||
int key_in_file(Key *, const char *, int);
|
||||
|
||||
#endif
|
||||
|
|
8
krl.c
8
krl.c
|
@ -14,7 +14,7 @@
|
|||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $OpenBSD: krl.c,v 1.16 2014/06/24 00:52:02 djm Exp $ */
|
||||
/* $OpenBSD: krl.c,v 1.17 2014/06/24 01:13:21 djm Exp $ */
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
|
@ -366,7 +366,7 @@ plain_key_blob(const Key *key, u_char **blob, u_int *blen)
|
|||
}
|
||||
r = key_to_blob(kcopy, blob, blen);
|
||||
free(kcopy);
|
||||
return r == 0 ? -1 : 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Revoke a key blob. Ownership of blob is transferred to the tree */
|
||||
|
@ -394,7 +394,7 @@ ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const Key *key)
|
|||
u_int len;
|
||||
|
||||
debug3("%s: revoke type %s", __func__, key_type(key));
|
||||
if (plain_key_blob(key, &blob, &len) != 0)
|
||||
if (plain_key_blob(key, &blob, &len) < 0)
|
||||
return -1;
|
||||
return revoke_blob(&krl->revoked_keys, blob, len);
|
||||
}
|
||||
|
@ -1130,7 +1130,7 @@ is_key_revoked(struct ssh_krl *krl, const Key *key)
|
|||
|
||||
/* Next, explicit keys */
|
||||
memset(&rb, 0, sizeof(rb));
|
||||
if (plain_key_blob(key, &rb.blob, &rb.len) != 0)
|
||||
if (plain_key_blob(key, &rb.blob, &rb.len) < 0)
|
||||
return -1;
|
||||
erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb);
|
||||
free(rb.blob);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: monitor.c,v 1.133 2014/05/03 17:20:34 markus Exp $ */
|
||||
/* $OpenBSD: monitor.c,v 1.134 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright 2002 Markus Friedl <markus@openbsd.org>
|
||||
|
@ -40,9 +40,10 @@
|
|||
#endif
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#ifdef HAVE_POLL_H
|
||||
#include <poll.h>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: openssl-compat.c,v 1.18 2014/06/17 13:06:08 dtucker Exp $ */
|
||||
/* $Id: openssl-compat.c,v 1.19 2014/07/02 05:28:07 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au>
|
||||
|
@ -16,6 +16,7 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#define SSH_DONT_OVERLOAD_OPENSSL_FUNCS
|
||||
#include "includes.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
@ -26,13 +27,8 @@
|
|||
# include <openssl/conf.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_RSA_GET_DEFAULT_METHOD
|
||||
# include <openssl/rsa.h>
|
||||
#endif
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#define SSH_DONT_OVERLOAD_OPENSSL_FUNCS
|
||||
#include "openssl-compat.h"
|
||||
|
||||
/*
|
||||
|
@ -70,139 +66,6 @@ ssh_compatible_openssl(long headerver, long libver)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef SSH_OLD_EVP
|
||||
int
|
||||
ssh_EVP_CipherInit(EVP_CIPHER_CTX *evp, const EVP_CIPHER *type,
|
||||
unsigned char *key, unsigned char *iv, int enc)
|
||||
{
|
||||
EVP_CipherInit(evp, type, key, iv, enc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ssh_EVP_Cipher(EVP_CIPHER_CTX *evp, char *dst, char *src, int len)
|
||||
{
|
||||
EVP_Cipher(evp, dst, src, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ssh_EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *evp)
|
||||
{
|
||||
EVP_CIPHER_CTX_cleanup(evp);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_EVP_DIGESTINIT_EX
|
||||
int
|
||||
EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *md, void *engine)
|
||||
{
|
||||
if (engine != NULL)
|
||||
fatal("%s: ENGINE is not supported", __func__);
|
||||
# ifdef OPENSSL_EVP_DIGESTUPDATE_VOID
|
||||
EVP_DigestInit(ctx, md);
|
||||
return 1;
|
||||
# else
|
||||
return EVP_DigestInit(ctx, md);
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_EVP_DIGESTFINAL_EX
|
||||
int
|
||||
EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s)
|
||||
{
|
||||
# ifdef OPENSSL_EVP_DIGESTUPDATE_VOID
|
||||
EVP_DigestFinal(ctx, md, s);
|
||||
return 1;
|
||||
# else
|
||||
return EVP_DigestFinal(ctx, md, s);
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OPENSSL_EVP_DIGESTUPDATE_VOID
|
||||
int
|
||||
ssh_EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt)
|
||||
{
|
||||
EVP_DigestUpdate(ctx, d, cnt);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_EVP_MD_CTX_COPY_EX
|
||||
int
|
||||
EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
|
||||
{
|
||||
return EVP_MD_CTX_copy(out, in);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_BN_IS_PRIME_EX
|
||||
int
|
||||
BN_is_prime_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, void *cb)
|
||||
{
|
||||
if (cb != NULL)
|
||||
fatal("%s: callback args not supported", __func__);
|
||||
return BN_is_prime(p, nchecks, NULL, ctx, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_RSA_GENERATE_KEY_EX
|
||||
int
|
||||
RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *bn_e, void *cb)
|
||||
{
|
||||
RSA *new_rsa, tmp_rsa;
|
||||
unsigned long e;
|
||||
|
||||
if (cb != NULL)
|
||||
fatal("%s: callback args not supported", __func__);
|
||||
e = BN_get_word(bn_e);
|
||||
if (e == 0xffffffffL)
|
||||
fatal("%s: value of e too large", __func__);
|
||||
new_rsa = RSA_generate_key(bits, e, NULL, NULL);
|
||||
if (new_rsa == NULL)
|
||||
return 0;
|
||||
/* swap rsa/new_rsa then free new_rsa */
|
||||
tmp_rsa = *rsa;
|
||||
*rsa = *new_rsa;
|
||||
*new_rsa = tmp_rsa;
|
||||
RSA_free(new_rsa);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_DSA_GENERATE_PARAMETERS_EX
|
||||
int
|
||||
DSA_generate_parameters_ex(DSA *dsa, int bits, const unsigned char *seed,
|
||||
int seed_len, int *counter_ret, unsigned long *h_ret, void *cb)
|
||||
{
|
||||
DSA *new_dsa, tmp_dsa;
|
||||
|
||||
if (cb != NULL)
|
||||
fatal("%s: callback args not supported", __func__);
|
||||
new_dsa = DSA_generate_parameters(bits, (unsigned char *)seed, seed_len,
|
||||
counter_ret, h_ret, NULL, NULL);
|
||||
if (new_dsa == NULL)
|
||||
return 0;
|
||||
/* swap dsa/new_dsa then free new_dsa */
|
||||
tmp_dsa = *dsa;
|
||||
*dsa = *new_dsa;
|
||||
*new_dsa = tmp_dsa;
|
||||
DSA_free(new_dsa);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_RSA_GET_DEFAULT_METHOD
|
||||
RSA_METHOD *
|
||||
RSA_get_default_method(void)
|
||||
{
|
||||
return RSA_PKCS1_SSLeay();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_OPENSSL_ENGINE
|
||||
void
|
||||
ssh_OpenSSL_add_all_algorithms(void)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: openssl-compat.h,v 1.27 2014/06/17 13:06:08 dtucker Exp $ */
|
||||
/* $Id: openssl-compat.h,v 1.28 2014/07/02 05:28:07 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au>
|
||||
|
@ -24,22 +24,8 @@
|
|||
|
||||
int ssh_compatible_openssl(long, long);
|
||||
|
||||
/* Only in 0.9.8 */
|
||||
#ifndef OPENSSL_DSA_MAX_MODULUS_BITS
|
||||
# define OPENSSL_DSA_MAX_MODULUS_BITS 10000
|
||||
#endif
|
||||
#ifndef OPENSSL_RSA_MAX_MODULUS_BITS
|
||||
# define OPENSSL_RSA_MAX_MODULUS_BITS 16384
|
||||
#endif
|
||||
|
||||
/* OPENSSL_free() is Free() in versions before OpenSSL 0.9.6 */
|
||||
#if !defined(OPENSSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x0090600f)
|
||||
# define OPENSSL_free(x) Free(x)
|
||||
#endif
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x00906000L
|
||||
# define SSH_OLD_EVP
|
||||
# define EVP_CIPHER_CTX_get_app_data(e) ((e)->app_data)
|
||||
#if (OPENSSL_VERSION_NUMBER <= 0x0090805fL)
|
||||
#error OpenSSL 0.9.8f or greater is required
|
||||
#endif
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10000001L
|
||||
|
@ -48,31 +34,6 @@ int ssh_compatible_openssl(long, long);
|
|||
# define LIBCRYPTO_EVP_INL_TYPE size_t
|
||||
#endif
|
||||
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x00907000L) || defined(OPENSSL_LOBOTOMISED_AES)
|
||||
# define USE_BUILTIN_RIJNDAEL
|
||||
#endif
|
||||
|
||||
#ifdef USE_BUILTIN_RIJNDAEL
|
||||
# include "rijndael.h"
|
||||
# define AES_KEY rijndael_ctx
|
||||
# define AES_BLOCK_SIZE 16
|
||||
# define AES_encrypt(a, b, c) rijndael_encrypt(c, a, b)
|
||||
# define AES_set_encrypt_key(a, b, c) rijndael_set_key(c, (char *)a, b, 1)
|
||||
# define EVP_aes_128_cbc evp_rijndael
|
||||
# define EVP_aes_192_cbc evp_rijndael
|
||||
# define EVP_aes_256_cbc evp_rijndael
|
||||
const EVP_CIPHER *evp_rijndael(void);
|
||||
void ssh_rijndael_iv(EVP_CIPHER_CTX *, int, u_char *, u_int);
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_HAVE_EVPCTR
|
||||
#define EVP_aes_128_ctr evp_aes_128_ctr
|
||||
#define EVP_aes_192_ctr evp_aes_128_ctr
|
||||
#define EVP_aes_256_ctr evp_aes_128_ctr
|
||||
const EVP_CIPHER *evp_aes_128_ctr(void);
|
||||
void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, size_t);
|
||||
#endif
|
||||
|
||||
/* Avoid some #ifdef. Code that uses these is unreachable without GCM */
|
||||
#if !defined(OPENSSL_HAVE_EVPGCM) && !defined(EVP_CTRL_GCM_SET_IV_FIXED)
|
||||
# define EVP_CTRL_GCM_SET_IV_FIXED -1
|
||||
|
@ -90,26 +51,9 @@ void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, size_t);
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x00907000L
|
||||
#define EVP_X_STATE(evp) &(evp).c
|
||||
#define EVP_X_STATE_LEN(evp) sizeof((evp).c)
|
||||
#else
|
||||
#define EVP_X_STATE(evp) (evp).cipher_data
|
||||
#define EVP_X_STATE_LEN(evp) (evp).cipher->ctx_size
|
||||
#endif
|
||||
|
||||
/* OpenSSL 0.9.8e returns cipher key len not context key len */
|
||||
#if (OPENSSL_VERSION_NUMBER == 0x0090805fL)
|
||||
# define EVP_CIPHER_CTX_key_length(c) ((c)->key_len)
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_RSA_GET_DEFAULT_METHOD
|
||||
RSA_METHOD *RSA_get_default_method(void);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We overload some of the OpenSSL crypto functions with ssh_* equivalents
|
||||
* which cater for older and/or less featureful OpenSSL version.
|
||||
* to automatically handle OpenSSL engine initialisation.
|
||||
*
|
||||
* In order for the compat library to call the real functions, it must
|
||||
* define SSH_DONT_OVERLOAD_OPENSSL_FUNCS before including this file and
|
||||
|
@ -117,19 +61,6 @@ RSA_METHOD *RSA_get_default_method(void);
|
|||
*/
|
||||
#ifndef SSH_DONT_OVERLOAD_OPENSSL_FUNCS
|
||||
|
||||
# ifdef SSH_OLD_EVP
|
||||
# ifdef EVP_Cipher
|
||||
# undef EVP_Cipher
|
||||
# endif
|
||||
# define EVP_CipherInit(a,b,c,d,e) ssh_EVP_CipherInit((a),(b),(c),(d),(e))
|
||||
# define EVP_Cipher(a,b,c,d) ssh_EVP_Cipher((a),(b),(c),(d))
|
||||
# define EVP_CIPHER_CTX_cleanup(a) ssh_EVP_CIPHER_CTX_cleanup((a))
|
||||
# endif /* SSH_OLD_EVP */
|
||||
|
||||
# ifdef OPENSSL_EVP_DIGESTUPDATE_VOID
|
||||
# define EVP_DigestUpdate(a,b,c) ssh_EVP_DigestUpdate((a),(b),(c))
|
||||
# endif
|
||||
|
||||
# ifdef USE_OPENSSL_ENGINE
|
||||
# ifdef OpenSSL_add_all_algorithms
|
||||
# undef OpenSSL_add_all_algorithms
|
||||
|
@ -137,48 +68,7 @@ RSA_METHOD *RSA_get_default_method(void);
|
|||
# define OpenSSL_add_all_algorithms() ssh_OpenSSL_add_all_algorithms()
|
||||
# endif
|
||||
|
||||
# ifndef HAVE_BN_IS_PRIME_EX
|
||||
int BN_is_prime_ex(const BIGNUM *, int, BN_CTX *, void *);
|
||||
# endif
|
||||
|
||||
# ifndef HAVE_DSA_GENERATE_PARAMETERS_EX
|
||||
int DSA_generate_parameters_ex(DSA *, int, const unsigned char *, int, int *,
|
||||
unsigned long *, void *);
|
||||
# endif
|
||||
|
||||
# ifndef HAVE_RSA_GENERATE_KEY_EX
|
||||
int RSA_generate_key_ex(RSA *, int, BIGNUM *, void *);
|
||||
# endif
|
||||
|
||||
# ifndef HAVE_EVP_DIGESTINIT_EX
|
||||
int EVP_DigestInit_ex(EVP_MD_CTX *, const EVP_MD *, void *);
|
||||
# endif
|
||||
|
||||
# ifndef HAVE_EVP_DISESTFINAL_EX
|
||||
int EVP_DigestFinal_ex(EVP_MD_CTX *, unsigned char *, unsigned int *);
|
||||
# endif
|
||||
|
||||
# ifndef EVP_MD_CTX_COPY_EX
|
||||
int EVP_MD_CTX_copy_ex(EVP_MD_CTX *, const EVP_MD_CTX *);
|
||||
# endif
|
||||
|
||||
int ssh_EVP_CipherInit(EVP_CIPHER_CTX *, const EVP_CIPHER *, unsigned char *,
|
||||
unsigned char *, int);
|
||||
int ssh_EVP_Cipher(EVP_CIPHER_CTX *, char *, char *, int);
|
||||
int ssh_EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *);
|
||||
void ssh_OpenSSL_add_all_algorithms(void);
|
||||
|
||||
# ifndef HAVE_HMAC_CTX_INIT
|
||||
# define HMAC_CTX_init(a)
|
||||
# endif
|
||||
|
||||
# ifndef HAVE_EVP_MD_CTX_INIT
|
||||
# define EVP_MD_CTX_init(a)
|
||||
# endif
|
||||
|
||||
# ifndef HAVE_EVP_MD_CTX_CLEANUP
|
||||
# define EVP_MD_CTX_cleanup(a)
|
||||
# endif
|
||||
|
||||
#endif /* SSH_DONT_OVERLOAD_OPENSSL_FUNCS */
|
||||
|
||||
|
|
38
packet.c
38
packet.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: packet.c,v 1.196 2014/05/03 17:20:34 markus Exp $ */
|
||||
/* $OpenBSD: packet.c,v 1.197 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -78,6 +78,7 @@
|
|||
#include "canohost.h"
|
||||
#include "misc.h"
|
||||
#include "ssh.h"
|
||||
#include "ssherr.h"
|
||||
#include "roaming.h"
|
||||
|
||||
#ifdef PACKET_DEBUG
|
||||
|
@ -222,6 +223,7 @@ void
|
|||
packet_set_connection(int fd_in, int fd_out)
|
||||
{
|
||||
const Cipher *none = cipher_by_name("none");
|
||||
int r;
|
||||
|
||||
if (none == NULL)
|
||||
fatal("packet_set_connection: cannot load cipher 'none'");
|
||||
|
@ -229,10 +231,11 @@ packet_set_connection(int fd_in, int fd_out)
|
|||
active_state = alloc_session_state();
|
||||
active_state->connection_in = fd_in;
|
||||
active_state->connection_out = fd_out;
|
||||
cipher_init(&active_state->send_context, none, (const u_char *)"",
|
||||
0, NULL, 0, CIPHER_ENCRYPT);
|
||||
cipher_init(&active_state->receive_context, none, (const u_char *)"",
|
||||
0, NULL, 0, CIPHER_DECRYPT);
|
||||
if ((r = cipher_init(&active_state->send_context, none,
|
||||
(const u_char *)"", 0, NULL, 0, CIPHER_ENCRYPT)) != 0 ||
|
||||
(r = cipher_init(&active_state->receive_context, none,
|
||||
(const u_char *)"", 0, NULL, 0, CIPHER_DECRYPT)) != 0)
|
||||
fatal("%s: cipher_init: %s", __func__, ssh_err(r));
|
||||
active_state->newkeys[MODE_IN] = active_state->newkeys[MODE_OUT] = NULL;
|
||||
if (!active_state->initialized) {
|
||||
active_state->initialized = 1;
|
||||
|
@ -329,13 +332,15 @@ void
|
|||
packet_get_keyiv(int mode, u_char *iv, u_int len)
|
||||
{
|
||||
CipherContext *cc;
|
||||
int r;
|
||||
|
||||
if (mode == MODE_OUT)
|
||||
cc = &active_state->send_context;
|
||||
else
|
||||
cc = &active_state->receive_context;
|
||||
|
||||
cipher_get_keyiv(cc, iv, len);
|
||||
if ((r = cipher_get_keyiv(cc, iv, len)) != 0)
|
||||
fatal("%s: cipher_get_keyiv: %s", __func__, ssh_err(r));
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -381,13 +386,15 @@ void
|
|||
packet_set_iv(int mode, u_char *dat)
|
||||
{
|
||||
CipherContext *cc;
|
||||
int r;
|
||||
|
||||
if (mode == MODE_OUT)
|
||||
cc = &active_state->send_context;
|
||||
else
|
||||
cc = &active_state->receive_context;
|
||||
|
||||
cipher_set_keyiv(cc, dat);
|
||||
if ((r = cipher_set_keyiv(cc, dat)) != 0)
|
||||
fatal("%s: cipher_set_keyiv: %s", __func__, ssh_err(r));
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -552,6 +559,7 @@ void
|
|||
packet_set_encryption_key(const u_char *key, u_int keylen, int number)
|
||||
{
|
||||
const Cipher *cipher = cipher_by_number(number);
|
||||
int r;
|
||||
|
||||
if (cipher == NULL)
|
||||
fatal("packet_set_encryption_key: unknown cipher number %d", number);
|
||||
|
@ -561,10 +569,11 @@ packet_set_encryption_key(const u_char *key, u_int keylen, int number)
|
|||
fatal("packet_set_encryption_key: keylen too big: %d", keylen);
|
||||
memcpy(active_state->ssh1_key, key, keylen);
|
||||
active_state->ssh1_keylen = keylen;
|
||||
cipher_init(&active_state->send_context, cipher, key, keylen, NULL,
|
||||
0, CIPHER_ENCRYPT);
|
||||
cipher_init(&active_state->receive_context, cipher, key, keylen, NULL,
|
||||
0, CIPHER_DECRYPT);
|
||||
if ((r = cipher_init(&active_state->send_context, cipher,
|
||||
key, keylen, NULL, 0, CIPHER_ENCRYPT)) != 0 ||
|
||||
(r = cipher_init(&active_state->receive_context, cipher,
|
||||
key, keylen, NULL, 0, CIPHER_DECRYPT)) != 0)
|
||||
fatal("%s: cipher_init: %s", __func__, ssh_err(r));
|
||||
}
|
||||
|
||||
u_int
|
||||
|
@ -744,7 +753,7 @@ set_newkeys(int mode)
|
|||
Comp *comp;
|
||||
CipherContext *cc;
|
||||
u_int64_t *max_blocks;
|
||||
int crypt_type;
|
||||
int r, crypt_type;
|
||||
|
||||
debug2("set_newkeys: mode %d", mode);
|
||||
|
||||
|
@ -786,8 +795,9 @@ set_newkeys(int mode)
|
|||
if (cipher_authlen(enc->cipher) == 0 && mac_init(mac) == 0)
|
||||
mac->enabled = 1;
|
||||
DBG(debug("cipher_init_context: %d", mode));
|
||||
cipher_init(cc, enc->cipher, enc->key, enc->key_len,
|
||||
enc->iv, enc->iv_len, crypt_type);
|
||||
if ((r = cipher_init(cc, enc->cipher, enc->key, enc->key_len,
|
||||
enc->iv, enc->iv_len, crypt_type)) != 0)
|
||||
fatal("%s: cipher_init: %s", __func__, ssh_err(r));
|
||||
/* Deleting the keys does not gain extra security */
|
||||
/* explicit_bzero(enc->iv, enc->block_size);
|
||||
explicit_bzero(enc->key, enc->key_len);
|
||||
|
|
101
rsa.c
101
rsa.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: rsa.c,v 1.31 2014/02/02 03:44:31 djm Exp $ */
|
||||
/* $OpenBSD: rsa.c,v 1.32 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -67,85 +67,122 @@
|
|||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "rsa.h"
|
||||
#include "log.h"
|
||||
#include "ssherr.h"
|
||||
|
||||
void
|
||||
int
|
||||
rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key)
|
||||
{
|
||||
u_char *inbuf, *outbuf;
|
||||
int len, ilen, olen;
|
||||
u_char *inbuf = NULL, *outbuf = NULL;
|
||||
int len, ilen, olen, r = SSH_ERR_INTERNAL_ERROR;
|
||||
|
||||
if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e))
|
||||
fatal("rsa_public_encrypt() exponent too small or not odd");
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
|
||||
olen = BN_num_bytes(key->n);
|
||||
outbuf = xmalloc(olen);
|
||||
if ((outbuf = malloc(olen)) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ilen = BN_num_bytes(in);
|
||||
inbuf = xmalloc(ilen);
|
||||
if ((inbuf = malloc(ilen)) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
BN_bn2bin(in, inbuf);
|
||||
|
||||
if ((len = RSA_public_encrypt(ilen, inbuf, outbuf, key,
|
||||
RSA_PKCS1_PADDING)) <= 0)
|
||||
fatal("rsa_public_encrypt() failed");
|
||||
RSA_PKCS1_PADDING)) <= 0) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (BN_bin2bn(outbuf, len, out) == NULL)
|
||||
fatal("rsa_public_encrypt: BN_bin2bn failed");
|
||||
if (BN_bin2bn(outbuf, len, out) == NULL) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
r = 0;
|
||||
|
||||
out:
|
||||
if (outbuf != NULL) {
|
||||
explicit_bzero(outbuf, olen);
|
||||
explicit_bzero(inbuf, ilen);
|
||||
free(outbuf);
|
||||
}
|
||||
if (inbuf != NULL) {
|
||||
explicit_bzero(inbuf, ilen);
|
||||
free(inbuf);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
|
||||
{
|
||||
u_char *inbuf, *outbuf;
|
||||
int len, ilen, olen;
|
||||
u_char *inbuf = NULL, *outbuf = NULL;
|
||||
int len, ilen, olen, r = SSH_ERR_INTERNAL_ERROR;
|
||||
|
||||
olen = BN_num_bytes(key->n);
|
||||
outbuf = xmalloc(olen);
|
||||
if ((outbuf = malloc(olen)) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ilen = BN_num_bytes(in);
|
||||
inbuf = xmalloc(ilen);
|
||||
if ((inbuf = malloc(ilen)) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
BN_bn2bin(in, inbuf);
|
||||
|
||||
if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key,
|
||||
RSA_PKCS1_PADDING)) <= 0) {
|
||||
error("rsa_private_decrypt() failed");
|
||||
} else {
|
||||
if (BN_bin2bn(outbuf, len, out) == NULL)
|
||||
fatal("rsa_private_decrypt: BN_bin2bn failed");
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
} else if (BN_bin2bn(outbuf, len, out) == NULL) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
r = 0;
|
||||
out:
|
||||
if (outbuf != NULL) {
|
||||
explicit_bzero(outbuf, olen);
|
||||
explicit_bzero(inbuf, ilen);
|
||||
free(outbuf);
|
||||
}
|
||||
if (inbuf != NULL) {
|
||||
explicit_bzero(inbuf, ilen);
|
||||
free(inbuf);
|
||||
return len;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* calculate p-1 and q-1 */
|
||||
void
|
||||
int
|
||||
rsa_generate_additional_parameters(RSA *rsa)
|
||||
{
|
||||
BIGNUM *aux;
|
||||
BN_CTX *ctx;
|
||||
BIGNUM *aux = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
int r;
|
||||
|
||||
if ((aux = BN_new()) == NULL)
|
||||
fatal("rsa_generate_additional_parameters: BN_new failed");
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
fatal("rsa_generate_additional_parameters: BN_CTX_new failed");
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
if ((aux = BN_new()) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((BN_sub(aux, rsa->q, BN_value_one()) == 0) ||
|
||||
(BN_mod(rsa->dmq1, rsa->d, aux, ctx) == 0) ||
|
||||
(BN_sub(aux, rsa->p, BN_value_one()) == 0) ||
|
||||
(BN_mod(rsa->dmp1, rsa->d, aux, ctx) == 0))
|
||||
fatal("rsa_generate_additional_parameters: BN_sub/mod failed");
|
||||
|
||||
(BN_mod(rsa->dmp1, rsa->d, aux, ctx) == 0)) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
r = 0;
|
||||
out:
|
||||
BN_clear_free(aux);
|
||||
BN_CTX_free(ctx);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
6
rsa.h
6
rsa.h
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: rsa.h,v 1.16 2006/03/25 22:22:43 djm Exp $ */
|
||||
/* $OpenBSD: rsa.h,v 1.17 2014/06/24 01:13:21 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
|
@ -19,8 +19,8 @@
|
|||
#include <openssl/bn.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
void rsa_public_encrypt(BIGNUM *, BIGNUM *, RSA *);
|
||||
int rsa_public_encrypt(BIGNUM *, BIGNUM *, RSA *);
|
||||
int rsa_private_decrypt(BIGNUM *, BIGNUM *, RSA *);
|
||||
void rsa_generate_additional_parameters(RSA *);
|
||||
int rsa_generate_additional_parameters(RSA *);
|
||||
|
||||
#endif /* RSA_H */
|
||||
|
|
24
ssh-add.c
24
ssh-add.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-add.c,v 1.109 2014/02/02 03:44:31 djm Exp $ */
|
||||
/* $OpenBSD: ssh-add.c,v 1.110 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -62,6 +62,7 @@
|
|||
#include "authfile.h"
|
||||
#include "pathnames.h"
|
||||
#include "misc.h"
|
||||
#include "ssherr.h"
|
||||
|
||||
/* argv0 */
|
||||
extern char *__progname;
|
||||
|
@ -170,7 +171,7 @@ add_file(AuthenticationConnection *ac, const char *filename, int key_only)
|
|||
Key *private, *cert;
|
||||
char *comment = NULL;
|
||||
char msg[1024], *certpath = NULL;
|
||||
int fd, perms_ok, ret = -1;
|
||||
int r, fd, perms_ok, ret = -1;
|
||||
Buffer keyblob;
|
||||
|
||||
if (strcmp(filename, "-") == 0) {
|
||||
|
@ -201,12 +202,18 @@ add_file(AuthenticationConnection *ac, const char *filename, int key_only)
|
|||
close(fd);
|
||||
|
||||
/* At first, try empty passphrase */
|
||||
private = key_parse_private(&keyblob, filename, "", &comment);
|
||||
if ((r = sshkey_parse_private_fileblob(&keyblob, filename, "",
|
||||
&private, &comment)) != 0 && r != SSH_ERR_KEY_WRONG_PASSPHRASE)
|
||||
fatal("Cannot parse %s: %s", filename, ssh_err(r));
|
||||
if (comment == NULL)
|
||||
comment = xstrdup(filename);
|
||||
/* try last */
|
||||
if (private == NULL && pass != NULL)
|
||||
private = key_parse_private(&keyblob, filename, pass, NULL);
|
||||
if (private == NULL && pass != NULL) {
|
||||
if ((r = sshkey_parse_private_fileblob(&keyblob, filename, pass,
|
||||
&private, &comment)) != 0 &&
|
||||
r != SSH_ERR_KEY_WRONG_PASSPHRASE)
|
||||
fatal("Cannot parse %s: %s", filename, ssh_err(r));
|
||||
}
|
||||
if (private == NULL) {
|
||||
/* clear passphrase since it did not work */
|
||||
clear_pass();
|
||||
|
@ -220,8 +227,11 @@ add_file(AuthenticationConnection *ac, const char *filename, int key_only)
|
|||
buffer_free(&keyblob);
|
||||
return -1;
|
||||
}
|
||||
private = key_parse_private(&keyblob, filename, pass,
|
||||
&comment);
|
||||
if ((r = sshkey_parse_private_fileblob(&keyblob,
|
||||
filename, pass, &private, &comment)) != 0 &&
|
||||
r != SSH_ERR_KEY_WRONG_PASSPHRASE)
|
||||
fatal("Cannot parse %s: %s",
|
||||
filename, ssh_err(r));
|
||||
if (private != NULL)
|
||||
break;
|
||||
clear_pass();
|
||||
|
|
24
ssh-agent.c
24
ssh-agent.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-agent.c,v 1.185 2014/04/29 18:01:49 markus Exp $ */
|
||||
/* $OpenBSD: ssh-agent.c,v 1.186 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -278,7 +278,7 @@ process_authentication_challenge1(SocketEntry *e)
|
|||
if (id != NULL && (!id->confirm || confirm_key(id) == 0)) {
|
||||
Key *private = id->key;
|
||||
/* Decrypt the challenge using the private key. */
|
||||
if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0)
|
||||
if (rsa_private_decrypt(challenge, challenge, private->rsa) != 0)
|
||||
goto failure;
|
||||
|
||||
/* The response is MD5 of decrypted challenge plus session id. */
|
||||
|
@ -365,12 +365,16 @@ process_sign_request2(SocketEntry *e)
|
|||
static void
|
||||
process_remove_identity(SocketEntry *e, int version)
|
||||
{
|
||||
u_int blen, bits;
|
||||
u_int blen;
|
||||
int success = 0;
|
||||
Key *key = NULL;
|
||||
u_char *blob;
|
||||
#ifdef WITH_SSH1
|
||||
u_int bits;
|
||||
#endif /* WITH_SSH1 */
|
||||
|
||||
switch (version) {
|
||||
#ifdef WITH_SSH1
|
||||
case 1:
|
||||
key = key_new(KEY_RSA1);
|
||||
bits = buffer_get_int(&e->request);
|
||||
|
@ -381,6 +385,7 @@ process_remove_identity(SocketEntry *e, int version)
|
|||
logit("Warning: identity keysize mismatch: actual %u, announced %u",
|
||||
key_size(key), bits);
|
||||
break;
|
||||
#endif /* WITH_SSH1 */
|
||||
case 2:
|
||||
blob = buffer_get_string(&e->request, &blen);
|
||||
key = key_from_blob(blob, blen);
|
||||
|
@ -477,6 +482,7 @@ process_add_identity(SocketEntry *e, int version)
|
|||
Key *k = NULL;
|
||||
|
||||
switch (version) {
|
||||
#ifdef WITH_SSH1
|
||||
case 1:
|
||||
k = key_new_private(KEY_RSA1);
|
||||
(void) buffer_get_int(&e->request); /* ignored */
|
||||
|
@ -490,7 +496,9 @@ process_add_identity(SocketEntry *e, int version)
|
|||
buffer_get_bignum(&e->request, k->rsa->p); /* q */
|
||||
|
||||
/* Generate additional parameters */
|
||||
rsa_generate_additional_parameters(k->rsa);
|
||||
if (rsa_generate_additional_parameters(k->rsa) != 0)
|
||||
fatal("%s: rsa_generate_additional_parameters "
|
||||
"error", __func__);
|
||||
|
||||
/* enable blinding */
|
||||
if (RSA_blinding_on(k->rsa, NULL) != 1) {
|
||||
|
@ -499,6 +507,7 @@ process_add_identity(SocketEntry *e, int version)
|
|||
goto send;
|
||||
}
|
||||
break;
|
||||
#endif /* WITH_SSH1 */
|
||||
case 2:
|
||||
k = key_private_deserialize(&e->request);
|
||||
if (k == NULL) {
|
||||
|
@ -507,11 +516,10 @@ process_add_identity(SocketEntry *e, int version)
|
|||
}
|
||||
break;
|
||||
}
|
||||
comment = buffer_get_string(&e->request, NULL);
|
||||
if (k == NULL) {
|
||||
free(comment);
|
||||
if (k == NULL)
|
||||
goto send;
|
||||
}
|
||||
comment = buffer_get_string(&e->request, NULL);
|
||||
|
||||
while (buffer_len(&e->request)) {
|
||||
switch ((type = buffer_get_char(&e->request))) {
|
||||
case SSH_AGENT_CONSTRAIN_LIFETIME:
|
||||
|
|
235
ssh-dss.c
235
ssh-dss.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-dss.c,v 1.31 2014/02/02 03:44:31 djm Exp $ */
|
||||
/* $OpenBSD: ssh-dss.c,v 1.32 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
|
@ -33,157 +33,186 @@
|
|||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "buffer.h"
|
||||
#include "sshbuf.h"
|
||||
#include "compat.h"
|
||||
#include "log.h"
|
||||
#include "key.h"
|
||||
#include "ssherr.h"
|
||||
#include "digest.h"
|
||||
#define SSHKEY_INTERNAL
|
||||
#include "sshkey.h"
|
||||
|
||||
#define INTBLOB_LEN 20
|
||||
#define SIGBLOB_LEN (2*INTBLOB_LEN)
|
||||
|
||||
int
|
||||
ssh_dss_sign(const Key *key, u_char **sigp, u_int *lenp,
|
||||
const u_char *data, u_int datalen)
|
||||
ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
|
||||
const u_char *data, size_t datalen, u_int compat)
|
||||
{
|
||||
DSA_SIG *sig;
|
||||
DSA_SIG *sig = NULL;
|
||||
u_char digest[SSH_DIGEST_MAX_LENGTH], sigblob[SIGBLOB_LEN];
|
||||
u_int rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
|
||||
Buffer b;
|
||||
size_t rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
|
||||
struct sshbuf *b = NULL;
|
||||
int ret = SSH_ERR_INVALID_ARGUMENT;
|
||||
|
||||
if (key == NULL || key_type_plain(key->type) != KEY_DSA ||
|
||||
key->dsa == NULL) {
|
||||
error("%s: no DSA key", __func__);
|
||||
return -1;
|
||||
}
|
||||
if (lenp != NULL)
|
||||
*lenp = 0;
|
||||
if (sigp != NULL)
|
||||
*sigp = NULL;
|
||||
|
||||
if (ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen,
|
||||
digest, sizeof(digest)) != 0) {
|
||||
error("%s: ssh_digest_memory failed", __func__);
|
||||
return -1;
|
||||
}
|
||||
if (key == NULL || key->dsa == NULL ||
|
||||
sshkey_type_plain(key->type) != KEY_DSA)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
if (dlen == 0)
|
||||
return SSH_ERR_INTERNAL_ERROR;
|
||||
|
||||
sig = DSA_do_sign(digest, dlen, key->dsa);
|
||||
explicit_bzero(digest, sizeof(digest));
|
||||
if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen,
|
||||
digest, sizeof(digest))) != 0)
|
||||
goto out;
|
||||
|
||||
if (sig == NULL) {
|
||||
error("ssh_dss_sign: sign failed");
|
||||
return -1;
|
||||
if ((sig = DSA_do_sign(digest, dlen, key->dsa)) == NULL) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rlen = BN_num_bytes(sig->r);
|
||||
slen = BN_num_bytes(sig->s);
|
||||
if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) {
|
||||
error("bad sig size %u %u", rlen, slen);
|
||||
DSA_SIG_free(sig);
|
||||
return -1;
|
||||
ret = SSH_ERR_INTERNAL_ERROR;
|
||||
goto out;
|
||||
}
|
||||
explicit_bzero(sigblob, SIGBLOB_LEN);
|
||||
BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen);
|
||||
BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen);
|
||||
DSA_SIG_free(sig);
|
||||
BN_bn2bin(sig->r, sigblob + SIGBLOB_LEN - INTBLOB_LEN - rlen);
|
||||
BN_bn2bin(sig->s, sigblob + SIGBLOB_LEN - slen);
|
||||
|
||||
if (datafellows & SSH_BUG_SIGBLOB) {
|
||||
if (lenp != NULL)
|
||||
*lenp = SIGBLOB_LEN;
|
||||
if (compat & SSH_BUG_SIGBLOB) {
|
||||
if (sigp != NULL) {
|
||||
*sigp = xmalloc(SIGBLOB_LEN);
|
||||
if ((*sigp = malloc(SIGBLOB_LEN)) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
memcpy(*sigp, sigblob, SIGBLOB_LEN);
|
||||
}
|
||||
if (lenp != NULL)
|
||||
*lenp = SIGBLOB_LEN;
|
||||
ret = 0;
|
||||
} else {
|
||||
/* ietf-drafts */
|
||||
buffer_init(&b);
|
||||
buffer_put_cstring(&b, "ssh-dss");
|
||||
buffer_put_string(&b, sigblob, SIGBLOB_LEN);
|
||||
len = buffer_len(&b);
|
||||
if ((b = sshbuf_new()) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if ((ret = sshbuf_put_cstring(b, "ssh-dss")) != 0 ||
|
||||
(ret = sshbuf_put_string(b, sigblob, SIGBLOB_LEN)) != 0)
|
||||
goto out;
|
||||
len = sshbuf_len(b);
|
||||
if (sigp != NULL) {
|
||||
if ((*sigp = malloc(len)) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
memcpy(*sigp, sshbuf_ptr(b), len);
|
||||
}
|
||||
if (lenp != NULL)
|
||||
*lenp = len;
|
||||
if (sigp != NULL) {
|
||||
*sigp = xmalloc(len);
|
||||
memcpy(*sigp, buffer_ptr(&b), len);
|
||||
ret = 0;
|
||||
}
|
||||
buffer_free(&b);
|
||||
}
|
||||
return 0;
|
||||
out:
|
||||
explicit_bzero(digest, sizeof(digest));
|
||||
if (sig != NULL)
|
||||
DSA_SIG_free(sig);
|
||||
if (b != NULL)
|
||||
sshbuf_free(b);
|
||||
return ret;
|
||||
}
|
||||
int
|
||||
ssh_dss_verify(const Key *key, const u_char *signature, u_int signaturelen,
|
||||
const u_char *data, u_int datalen)
|
||||
{
|
||||
DSA_SIG *sig;
|
||||
u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob;
|
||||
u_int len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
|
||||
int rlen, ret;
|
||||
Buffer b;
|
||||
|
||||
if (key == NULL || key_type_plain(key->type) != KEY_DSA ||
|
||||
key->dsa == NULL) {
|
||||
error("%s: no DSA key", __func__);
|
||||
return -1;
|
||||
}
|
||||
int
|
||||
ssh_dss_verify(const struct sshkey *key,
|
||||
const u_char *signature, size_t signaturelen,
|
||||
const u_char *data, size_t datalen, u_int compat)
|
||||
{
|
||||
DSA_SIG *sig = NULL;
|
||||
u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob = NULL;
|
||||
size_t len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
|
||||
int ret = SSH_ERR_INTERNAL_ERROR;
|
||||
struct sshbuf *b = NULL;
|
||||
char *ktype = NULL;
|
||||
|
||||
if (key == NULL || key->dsa == NULL ||
|
||||
sshkey_type_plain(key->type) != KEY_DSA)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
if (dlen == 0)
|
||||
return SSH_ERR_INTERNAL_ERROR;
|
||||
|
||||
/* fetch signature */
|
||||
if (datafellows & SSH_BUG_SIGBLOB) {
|
||||
sigblob = xmalloc(signaturelen);
|
||||
if (compat & SSH_BUG_SIGBLOB) {
|
||||
if ((sigblob = malloc(signaturelen)) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
memcpy(sigblob, signature, signaturelen);
|
||||
len = signaturelen;
|
||||
} else {
|
||||
/* ietf-drafts */
|
||||
char *ktype;
|
||||
buffer_init(&b);
|
||||
buffer_append(&b, signature, signaturelen);
|
||||
ktype = buffer_get_cstring(&b, NULL);
|
||||
if (strcmp("ssh-dss", ktype) != 0) {
|
||||
error("%s: cannot handle type %s", __func__, ktype);
|
||||
buffer_free(&b);
|
||||
free(ktype);
|
||||
return -1;
|
||||
if ((b = sshbuf_from(signature, signaturelen)) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
if (sshbuf_get_cstring(b, &ktype, NULL) != 0 ||
|
||||
sshbuf_get_string(b, &sigblob, &len) != 0) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
free(ktype);
|
||||
sigblob = buffer_get_string(&b, &len);
|
||||
rlen = buffer_len(&b);
|
||||
buffer_free(&b);
|
||||
if (rlen != 0) {
|
||||
error("%s: remaining bytes in signature %d",
|
||||
__func__, rlen);
|
||||
free(sigblob);
|
||||
return -1;
|
||||
if (strcmp("ssh-dss", ktype) != 0) {
|
||||
ret = SSH_ERR_KEY_TYPE_MISMATCH;
|
||||
goto out;
|
||||
}
|
||||
if (sshbuf_len(b) != 0) {
|
||||
ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (len != SIGBLOB_LEN) {
|
||||
fatal("bad sigbloblen %u != SIGBLOB_LEN", len);
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* parse signature */
|
||||
if ((sig = DSA_SIG_new()) == NULL)
|
||||
fatal("%s: DSA_SIG_new failed", __func__);
|
||||
if ((sig->r = BN_new()) == NULL)
|
||||
fatal("%s: BN_new failed", __func__);
|
||||
if ((sig->s = BN_new()) == NULL)
|
||||
fatal("ssh_dss_verify: BN_new failed");
|
||||
if ((sig = DSA_SIG_new()) == NULL ||
|
||||
(sig->r = BN_new()) == NULL ||
|
||||
(sig->s = BN_new()) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig->r) == NULL) ||
|
||||
(BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s) == NULL))
|
||||
fatal("%s: BN_bin2bn failed", __func__);
|
||||
|
||||
/* clean up */
|
||||
explicit_bzero(sigblob, len);
|
||||
free(sigblob);
|
||||
|
||||
/* sha1 the data */
|
||||
if (ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen,
|
||||
digest, sizeof(digest)) != 0) {
|
||||
error("%s: digest_memory failed", __func__);
|
||||
return -1;
|
||||
(BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s) == NULL)) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = DSA_do_verify(digest, dlen, sig, key->dsa);
|
||||
/* sha1 the data */
|
||||
if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen,
|
||||
digest, sizeof(digest))) != 0)
|
||||
goto out;
|
||||
|
||||
switch (DSA_do_verify(digest, dlen, sig, key->dsa)) {
|
||||
case 1:
|
||||
ret = 0;
|
||||
break;
|
||||
case 0:
|
||||
ret = SSH_ERR_SIGNATURE_INVALID;
|
||||
goto out;
|
||||
default:
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
explicit_bzero(digest, sizeof(digest));
|
||||
|
||||
if (sig != NULL)
|
||||
DSA_SIG_free(sig);
|
||||
|
||||
debug("%s: signature %s", __func__,
|
||||
ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error");
|
||||
if (b != NULL)
|
||||
sshbuf_free(b);
|
||||
if (ktype != NULL)
|
||||
free(ktype);
|
||||
if (sigblob != NULL) {
|
||||
explicit_bzero(sigblob, len);
|
||||
free(sigblob);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
232
ssh-ecdsa.c
232
ssh-ecdsa.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-ecdsa.c,v 1.10 2014/02/03 23:28:00 djm Exp $ */
|
||||
/* $OpenBSD: ssh-ecdsa.c,v 1.11 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2010 Damien Miller. All rights reserved.
|
||||
|
@ -37,141 +37,155 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "buffer.h"
|
||||
#include "compat.h"
|
||||
#include "log.h"
|
||||
#include "key.h"
|
||||
#include "sshbuf.h"
|
||||
#include "ssherr.h"
|
||||
#include "digest.h"
|
||||
#define SSHKEY_INTERNAL
|
||||
#include "sshkey.h"
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
ssh_ecdsa_sign(const Key *key, u_char **sigp, u_int *lenp,
|
||||
const u_char *data, u_int datalen)
|
||||
ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
|
||||
const u_char *data, size_t datalen, u_int compat)
|
||||
{
|
||||
ECDSA_SIG *sig;
|
||||
ECDSA_SIG *sig = NULL;
|
||||
int hash_alg;
|
||||
u_char digest[SSH_DIGEST_MAX_LENGTH];
|
||||
u_int len, dlen;
|
||||
Buffer b, bb;
|
||||
size_t len, dlen;
|
||||
struct sshbuf *b = NULL, *bb = NULL;
|
||||
int ret = SSH_ERR_INTERNAL_ERROR;
|
||||
|
||||
if (key == NULL || key_type_plain(key->type) != KEY_ECDSA ||
|
||||
key->ecdsa == NULL) {
|
||||
error("%s: no ECDSA key", __func__);
|
||||
return -1;
|
||||
if (lenp != NULL)
|
||||
*lenp = 0;
|
||||
if (sigp != NULL)
|
||||
*sigp = NULL;
|
||||
|
||||
if (key == NULL || key->ecdsa == NULL ||
|
||||
sshkey_type_plain(key->type) != KEY_ECDSA)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
|
||||
if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 ||
|
||||
(dlen = ssh_digest_bytes(hash_alg)) == 0)
|
||||
return SSH_ERR_INTERNAL_ERROR;
|
||||
if ((ret = ssh_digest_memory(hash_alg, data, datalen,
|
||||
digest, sizeof(digest))) != 0)
|
||||
goto out;
|
||||
|
||||
if ((sig = ECDSA_do_sign(digest, dlen, key->ecdsa)) == NULL) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hash_alg = key_ec_nid_to_hash_alg(key->ecdsa_nid);
|
||||
if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
|
||||
error("%s: bad hash algorithm %d", __func__, hash_alg);
|
||||
return -1;
|
||||
if ((bb = sshbuf_new()) == NULL || (b = sshbuf_new()) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if (ssh_digest_memory(hash_alg, data, datalen,
|
||||
digest, sizeof(digest)) != 0) {
|
||||
error("%s: digest_memory failed", __func__);
|
||||
return -1;
|
||||
if ((ret = sshbuf_put_bignum2(bb, sig->r)) != 0 ||
|
||||
(ret = sshbuf_put_bignum2(bb, sig->s)) != 0)
|
||||
goto out;
|
||||
if ((ret = sshbuf_put_cstring(b, sshkey_ssh_name_plain(key))) != 0 ||
|
||||
(ret = sshbuf_put_stringb(b, bb)) != 0)
|
||||
goto out;
|
||||
len = sshbuf_len(b);
|
||||
if (sigp != NULL) {
|
||||
if ((*sigp = malloc(len)) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sig = ECDSA_do_sign(digest, dlen, key->ecdsa);
|
||||
explicit_bzero(digest, sizeof(digest));
|
||||
|
||||
if (sig == NULL) {
|
||||
error("%s: sign failed", __func__);
|
||||
return -1;
|
||||
memcpy(*sigp, sshbuf_ptr(b), len);
|
||||
}
|
||||
|
||||
buffer_init(&bb);
|
||||
buffer_put_bignum2(&bb, sig->r);
|
||||
buffer_put_bignum2(&bb, sig->s);
|
||||
ECDSA_SIG_free(sig);
|
||||
|
||||
buffer_init(&b);
|
||||
buffer_put_cstring(&b, key_ssh_name_plain(key));
|
||||
buffer_put_string(&b, buffer_ptr(&bb), buffer_len(&bb));
|
||||
buffer_free(&bb);
|
||||
len = buffer_len(&b);
|
||||
if (lenp != NULL)
|
||||
*lenp = len;
|
||||
if (sigp != NULL) {
|
||||
*sigp = xmalloc(len);
|
||||
memcpy(*sigp, buffer_ptr(&b), len);
|
||||
}
|
||||
buffer_free(&b);
|
||||
|
||||
return 0;
|
||||
ret = 0;
|
||||
out:
|
||||
explicit_bzero(digest, sizeof(digest));
|
||||
if (b != NULL)
|
||||
sshbuf_free(b);
|
||||
if (bb != NULL)
|
||||
sshbuf_free(bb);
|
||||
if (sig != NULL)
|
||||
ECDSA_SIG_free(sig);
|
||||
return ret;
|
||||
}
|
||||
int
|
||||
ssh_ecdsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
|
||||
const u_char *data, u_int datalen)
|
||||
{
|
||||
ECDSA_SIG *sig;
|
||||
int hash_alg;
|
||||
u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob;
|
||||
u_int len, dlen;
|
||||
int rlen, ret;
|
||||
Buffer b, bb;
|
||||
char *ktype;
|
||||
|
||||
if (key == NULL || key_type_plain(key->type) != KEY_ECDSA ||
|
||||
key->ecdsa == NULL) {
|
||||
error("%s: no ECDSA key", __func__);
|
||||
return -1;
|
||||
}
|
||||
/* ARGSUSED */
|
||||
int
|
||||
ssh_ecdsa_verify(const struct sshkey *key,
|
||||
const u_char *signature, size_t signaturelen,
|
||||
const u_char *data, size_t datalen, u_int compat)
|
||||
{
|
||||
ECDSA_SIG *sig = NULL;
|
||||
int hash_alg;
|
||||
u_char digest[SSH_DIGEST_MAX_LENGTH];
|
||||
size_t dlen;
|
||||
int ret = SSH_ERR_INTERNAL_ERROR;
|
||||
struct sshbuf *b = NULL, *sigbuf = NULL;
|
||||
char *ktype = NULL;
|
||||
|
||||
if (key == NULL || key->ecdsa == NULL ||
|
||||
sshkey_type_plain(key->type) != KEY_ECDSA)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
|
||||
if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 ||
|
||||
(dlen = ssh_digest_bytes(hash_alg)) == 0)
|
||||
return SSH_ERR_INTERNAL_ERROR;
|
||||
|
||||
/* fetch signature */
|
||||
buffer_init(&b);
|
||||
buffer_append(&b, signature, signaturelen);
|
||||
ktype = buffer_get_string(&b, NULL);
|
||||
if (strcmp(key_ssh_name_plain(key), ktype) != 0) {
|
||||
error("%s: cannot handle type %s", __func__, ktype);
|
||||
buffer_free(&b);
|
||||
free(ktype);
|
||||
return -1;
|
||||
if ((b = sshbuf_from(signature, signaturelen)) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
if (sshbuf_get_cstring(b, &ktype, NULL) != 0 ||
|
||||
sshbuf_froms(b, &sigbuf) != 0) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
free(ktype);
|
||||
sigblob = buffer_get_string(&b, &len);
|
||||
rlen = buffer_len(&b);
|
||||
buffer_free(&b);
|
||||
if (rlen != 0) {
|
||||
error("%s: remaining bytes in signature %d", __func__, rlen);
|
||||
free(sigblob);
|
||||
return -1;
|
||||
if (strcmp(sshkey_ssh_name_plain(key), ktype) != 0) {
|
||||
ret = SSH_ERR_KEY_TYPE_MISMATCH;
|
||||
goto out;
|
||||
}
|
||||
if (sshbuf_len(b) != 0) {
|
||||
ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* parse signature */
|
||||
if ((sig = ECDSA_SIG_new()) == NULL)
|
||||
fatal("%s: ECDSA_SIG_new failed", __func__);
|
||||
|
||||
buffer_init(&bb);
|
||||
buffer_append(&bb, sigblob, len);
|
||||
buffer_get_bignum2(&bb, sig->r);
|
||||
buffer_get_bignum2(&bb, sig->s);
|
||||
if (buffer_len(&bb) != 0)
|
||||
fatal("%s: remaining bytes in inner sigblob", __func__);
|
||||
buffer_free(&bb);
|
||||
|
||||
/* clean up */
|
||||
explicit_bzero(sigblob, len);
|
||||
free(sigblob);
|
||||
|
||||
/* hash the data */
|
||||
hash_alg = key_ec_nid_to_hash_alg(key->ecdsa_nid);
|
||||
if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
|
||||
error("%s: bad hash algorithm %d", __func__, hash_alg);
|
||||
return -1;
|
||||
if ((sig = ECDSA_SIG_new()) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if (ssh_digest_memory(hash_alg, data, datalen,
|
||||
digest, sizeof(digest)) != 0) {
|
||||
error("%s: digest_memory failed", __func__);
|
||||
return -1;
|
||||
if (sshbuf_get_bignum2(sigbuf, sig->r) != 0 ||
|
||||
sshbuf_get_bignum2(sigbuf, sig->s) != 0) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
if (sshbuf_len(sigbuf) != 0) {
|
||||
ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
|
||||
goto out;
|
||||
}
|
||||
if ((ret = ssh_digest_memory(hash_alg, data, datalen,
|
||||
digest, sizeof(digest))) != 0)
|
||||
goto out;
|
||||
|
||||
switch (ECDSA_do_verify(digest, dlen, sig, key->ecdsa)) {
|
||||
case 1:
|
||||
ret = 0;
|
||||
break;
|
||||
case 0:
|
||||
ret = SSH_ERR_SIGNATURE_INVALID;
|
||||
goto out;
|
||||
default:
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = ECDSA_do_verify(digest, dlen, sig, key->ecdsa);
|
||||
out:
|
||||
explicit_bzero(digest, sizeof(digest));
|
||||
|
||||
if (sigbuf != NULL)
|
||||
sshbuf_free(sigbuf);
|
||||
if (b != NULL)
|
||||
sshbuf_free(b);
|
||||
if (sig != NULL)
|
||||
ECDSA_SIG_free(sig);
|
||||
|
||||
debug("%s: signature %s", __func__,
|
||||
ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error");
|
||||
free(ktype);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
175
ssh-ed25519.c
175
ssh-ed25519.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-ed25519.c,v 1.3 2014/02/23 20:03:42 djm Exp $ */
|
||||
/* $OpenBSD: ssh-ed25519.c,v 1.4 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2013 Markus Friedl <markus@openbsd.org>
|
||||
*
|
||||
|
@ -18,132 +18,149 @@
|
|||
#include "includes.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "crypto_api.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "log.h"
|
||||
#include "buffer.h"
|
||||
#include "key.h"
|
||||
#define SSHKEY_INTERNAL
|
||||
#include "sshkey.h"
|
||||
#include "ssherr.h"
|
||||
#include "ssh.h"
|
||||
|
||||
int
|
||||
ssh_ed25519_sign(const Key *key, u_char **sigp, u_int *lenp,
|
||||
const u_char *data, u_int datalen)
|
||||
ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
|
||||
const u_char *data, size_t datalen, u_int compat)
|
||||
{
|
||||
u_char *sig;
|
||||
u_int slen, len;
|
||||
u_char *sig = NULL;
|
||||
size_t slen = 0, len;
|
||||
unsigned long long smlen;
|
||||
int ret;
|
||||
Buffer b;
|
||||
int r, ret;
|
||||
struct sshbuf *b = NULL;
|
||||
|
||||
if (key == NULL || key_type_plain(key->type) != KEY_ED25519 ||
|
||||
key->ed25519_sk == NULL) {
|
||||
error("%s: no ED25519 key", __func__);
|
||||
return -1;
|
||||
}
|
||||
if (lenp != NULL)
|
||||
*lenp = 0;
|
||||
if (sigp != NULL)
|
||||
*sigp = NULL;
|
||||
|
||||
if (datalen >= UINT_MAX - crypto_sign_ed25519_BYTES) {
|
||||
error("%s: datalen %u too long", __func__, datalen);
|
||||
return -1;
|
||||
}
|
||||
if (key == NULL ||
|
||||
sshkey_type_plain(key->type) != KEY_ED25519 ||
|
||||
key->ed25519_sk == NULL ||
|
||||
datalen >= INT_MAX - crypto_sign_ed25519_BYTES)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
smlen = slen = datalen + crypto_sign_ed25519_BYTES;
|
||||
sig = xmalloc(slen);
|
||||
if ((sig = malloc(slen)) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
|
||||
if ((ret = crypto_sign_ed25519(sig, &smlen, data, datalen,
|
||||
key->ed25519_sk)) != 0 || smlen <= datalen) {
|
||||
error("%s: crypto_sign_ed25519 failed: %d", __func__, ret);
|
||||
free(sig);
|
||||
return -1;
|
||||
r = SSH_ERR_INVALID_ARGUMENT; /* XXX better error? */
|
||||
goto out;
|
||||
}
|
||||
/* encode signature */
|
||||
buffer_init(&b);
|
||||
buffer_put_cstring(&b, "ssh-ed25519");
|
||||
buffer_put_string(&b, sig, smlen - datalen);
|
||||
len = buffer_len(&b);
|
||||
if ((b = sshbuf_new()) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if ((r = sshbuf_put_cstring(b, "ssh-ed25519")) != 0 ||
|
||||
(r = sshbuf_put_string(b, sig, smlen - datalen)) != 0)
|
||||
goto out;
|
||||
len = sshbuf_len(b);
|
||||
if (sigp != NULL) {
|
||||
if ((*sigp = malloc(len)) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
memcpy(*sigp, sshbuf_ptr(b), len);
|
||||
}
|
||||
if (lenp != NULL)
|
||||
*lenp = len;
|
||||
if (sigp != NULL) {
|
||||
*sigp = xmalloc(len);
|
||||
memcpy(*sigp, buffer_ptr(&b), len);
|
||||
}
|
||||
buffer_free(&b);
|
||||
/* success */
|
||||
r = 0;
|
||||
out:
|
||||
sshbuf_free(b);
|
||||
if (sig != NULL) {
|
||||
explicit_bzero(sig, slen);
|
||||
free(sig);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
ssh_ed25519_verify(const Key *key, const u_char *signature, u_int signaturelen,
|
||||
const u_char *data, u_int datalen)
|
||||
ssh_ed25519_verify(const struct sshkey *key,
|
||||
const u_char *signature, size_t signaturelen,
|
||||
const u_char *data, size_t datalen, u_int compat)
|
||||
{
|
||||
Buffer b;
|
||||
char *ktype;
|
||||
u_char *sigblob, *sm, *m;
|
||||
u_int len;
|
||||
unsigned long long smlen, mlen;
|
||||
int rlen, ret;
|
||||
struct sshbuf *b = NULL;
|
||||
char *ktype = NULL;
|
||||
const u_char *sigblob;
|
||||
u_char *sm = NULL, *m = NULL;
|
||||
size_t len;
|
||||
unsigned long long smlen = 0, mlen = 0;
|
||||
int r, ret;
|
||||
|
||||
if (key == NULL || key_type_plain(key->type) != KEY_ED25519 ||
|
||||
key->ed25519_pk == NULL) {
|
||||
error("%s: no ED25519 key", __func__);
|
||||
return -1;
|
||||
}
|
||||
buffer_init(&b);
|
||||
buffer_append(&b, signature, signaturelen);
|
||||
ktype = buffer_get_cstring(&b, NULL);
|
||||
if (key == NULL ||
|
||||
sshkey_type_plain(key->type) != KEY_ED25519 ||
|
||||
key->ed25519_pk == NULL ||
|
||||
datalen >= INT_MAX - crypto_sign_ed25519_BYTES)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
|
||||
if ((b = sshbuf_from(signature, signaturelen)) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
if ((r = sshbuf_get_cstring(b, &ktype, NULL)) != 0 ||
|
||||
(r = sshbuf_get_string_direct(b, &sigblob, &len)) != 0)
|
||||
goto out;
|
||||
if (strcmp("ssh-ed25519", ktype) != 0) {
|
||||
error("%s: cannot handle type %s", __func__, ktype);
|
||||
buffer_free(&b);
|
||||
free(ktype);
|
||||
return -1;
|
||||
r = SSH_ERR_KEY_TYPE_MISMATCH;
|
||||
goto out;
|
||||
}
|
||||
free(ktype);
|
||||
sigblob = buffer_get_string(&b, &len);
|
||||
rlen = buffer_len(&b);
|
||||
buffer_free(&b);
|
||||
if (rlen != 0) {
|
||||
error("%s: remaining bytes in signature %d", __func__, rlen);
|
||||
free(sigblob);
|
||||
return -1;
|
||||
if (sshbuf_len(b) != 0) {
|
||||
r = SSH_ERR_UNEXPECTED_TRAILING_DATA;
|
||||
goto out;
|
||||
}
|
||||
if (len > crypto_sign_ed25519_BYTES) {
|
||||
error("%s: len %u > crypto_sign_ed25519_BYTES %u", __func__,
|
||||
len, crypto_sign_ed25519_BYTES);
|
||||
free(sigblob);
|
||||
return -1;
|
||||
r = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
if (datalen >= SIZE_MAX - len)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
smlen = len + datalen;
|
||||
sm = xmalloc(smlen);
|
||||
mlen = smlen;
|
||||
if ((sm = malloc(smlen)) == NULL || (m = xmalloc(mlen)) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
memcpy(sm, sigblob, len);
|
||||
memcpy(sm+len, data, datalen);
|
||||
mlen = smlen;
|
||||
m = xmalloc(mlen);
|
||||
if ((ret = crypto_sign_ed25519_open(m, &mlen, sm, smlen,
|
||||
key->ed25519_pk)) != 0) {
|
||||
debug2("%s: crypto_sign_ed25519_open failed: %d",
|
||||
__func__, ret);
|
||||
}
|
||||
if (ret == 0 && mlen != datalen) {
|
||||
debug2("%s: crypto_sign_ed25519_open "
|
||||
"mlen != datalen (%llu != %u)", __func__, mlen, datalen);
|
||||
ret = -1;
|
||||
if (ret != 0 || mlen != datalen) {
|
||||
r = SSH_ERR_SIGNATURE_INVALID;
|
||||
goto out;
|
||||
}
|
||||
/* XXX compare 'm' and 'data' ? */
|
||||
|
||||
explicit_bzero(sigblob, len);
|
||||
/* success */
|
||||
r = 0;
|
||||
out:
|
||||
if (sm != NULL) {
|
||||
explicit_bzero(sm, smlen);
|
||||
explicit_bzero(m, smlen); /* NB. mlen may be invalid if ret != 0 */
|
||||
free(sigblob);
|
||||
free(sm);
|
||||
}
|
||||
if (m != NULL) {
|
||||
explicit_bzero(m, smlen); /* NB mlen may be invalid if r != 0 */
|
||||
free(m);
|
||||
debug("%s: signature %scorrect", __func__, (ret != 0) ? "in" : "");
|
||||
|
||||
/* translate return code carefully */
|
||||
return (ret == 0) ? 1 : -1;
|
||||
}
|
||||
sshbuf_free(b);
|
||||
free(ktype);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
20
ssh-keygen.c
20
ssh-keygen.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-keygen.c,v 1.246 2014/04/29 18:01:49 markus Exp $ */
|
||||
/* $OpenBSD: ssh-keygen.c,v 1.247 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -482,7 +482,9 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
|
|||
buffer_get_bignum_bits(&b, key->rsa->iqmp);
|
||||
buffer_get_bignum_bits(&b, key->rsa->q);
|
||||
buffer_get_bignum_bits(&b, key->rsa->p);
|
||||
rsa_generate_additional_parameters(key->rsa);
|
||||
if (rsa_generate_additional_parameters(key->rsa) != 0)
|
||||
fatal("%s: rsa_generate_additional_parameters "
|
||||
"error", __func__);
|
||||
break;
|
||||
}
|
||||
rlen = buffer_len(&b);
|
||||
|
@ -1637,12 +1639,12 @@ do_ca_sign(struct passwd *pw, int argc, char **argv)
|
|||
public->cert->valid_after = cert_valid_from;
|
||||
public->cert->valid_before = cert_valid_to;
|
||||
if (v00) {
|
||||
prepare_options_buf(&public->cert->critical,
|
||||
prepare_options_buf(public->cert->critical,
|
||||
OPTIONS_CRITICAL|OPTIONS_EXTENSIONS);
|
||||
} else {
|
||||
prepare_options_buf(&public->cert->critical,
|
||||
prepare_options_buf(public->cert->critical,
|
||||
OPTIONS_CRITICAL);
|
||||
prepare_options_buf(&public->cert->extensions,
|
||||
prepare_options_buf(public->cert->extensions,
|
||||
OPTIONS_EXTENSIONS);
|
||||
}
|
||||
public->cert->signature_key = key_from_private(ca);
|
||||
|
@ -1913,19 +1915,19 @@ do_show_cert(struct passwd *pw)
|
|||
printf("\n");
|
||||
}
|
||||
printf(" Critical Options: ");
|
||||
if (buffer_len(&key->cert->critical) == 0)
|
||||
if (buffer_len(key->cert->critical) == 0)
|
||||
printf("(none)\n");
|
||||
else {
|
||||
printf("\n");
|
||||
show_options(&key->cert->critical, v00, 1);
|
||||
show_options(key->cert->critical, v00, 1);
|
||||
}
|
||||
if (!v00) {
|
||||
printf(" Extensions: ");
|
||||
if (buffer_len(&key->cert->extensions) == 0)
|
||||
if (buffer_len(key->cert->extensions) == 0)
|
||||
printf("(none)\n");
|
||||
else {
|
||||
printf("\n");
|
||||
show_options(&key->cert->extensions, v00, 0);
|
||||
show_options(key->cert->extensions, v00, 0);
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-pkcs11-client.c,v 1.4 2013/05/17 00:13:14 djm Exp $ */
|
||||
/* $OpenBSD: ssh-pkcs11-client.c,v 1.5 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2010 Markus Friedl. All rights reserved.
|
||||
*
|
||||
|
@ -30,6 +30,8 @@
|
|||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#include "pathnames.h"
|
||||
#include "xmalloc.h"
|
||||
#include "buffer.h"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-pkcs11-helper.c,v 1.7 2013/12/02 02:56:17 djm Exp $ */
|
||||
/* $OpenBSD: ssh-pkcs11-helper.c,v 1.8 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2010 Markus Friedl. All rights reserved.
|
||||
*
|
||||
|
@ -169,7 +169,7 @@ process_sign(void)
|
|||
{
|
||||
u_char *blob, *data, *signature = NULL;
|
||||
u_int blen, dlen, slen = 0;
|
||||
int ok = -1, ret;
|
||||
int ok = -1;
|
||||
Key *key, *found;
|
||||
Buffer msg;
|
||||
|
||||
|
@ -179,6 +179,9 @@ process_sign(void)
|
|||
|
||||
if ((key = key_from_blob(blob, blen)) != NULL) {
|
||||
if ((found = lookup_key(key)) != NULL) {
|
||||
#ifdef WITH_OPENSSL
|
||||
int ret;
|
||||
|
||||
slen = RSA_size(key->rsa);
|
||||
signature = xmalloc(slen);
|
||||
if ((ret = RSA_private_encrypt(dlen, data, signature,
|
||||
|
@ -186,6 +189,7 @@ process_sign(void)
|
|||
slen = ret;
|
||||
ok = 0;
|
||||
}
|
||||
#endif /* WITH_OPENSSL */
|
||||
}
|
||||
key_free(key);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-pkcs11.c,v 1.13 2014/05/02 03:27:54 djm Exp $ */
|
||||
/* $OpenBSD: ssh-pkcs11.c,v 1.14 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2010 Markus Friedl. All rights reserved.
|
||||
*
|
||||
|
@ -520,7 +520,7 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx,
|
|||
key = key_new(KEY_UNSPEC);
|
||||
key->rsa = rsa;
|
||||
key->type = KEY_RSA;
|
||||
key->flags |= KEY_FLAG_EXT;
|
||||
key->flags |= SSHKEY_FLAG_EXT;
|
||||
if (pkcs11_key_included(keysp, nkeys, key)) {
|
||||
key_free(key);
|
||||
} else {
|
||||
|
|
254
ssh-rsa.c
254
ssh-rsa.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-rsa.c,v 1.51 2014/02/02 03:44:31 djm Exp $ */
|
||||
/* $OpenBSD: ssh-rsa.c,v 1.52 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
|
||||
*
|
||||
|
@ -25,163 +25,167 @@
|
|||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "log.h"
|
||||
#include "buffer.h"
|
||||
#include "key.h"
|
||||
#include "sshbuf.h"
|
||||
#include "compat.h"
|
||||
#include "misc.h"
|
||||
#include "ssh.h"
|
||||
#include "ssherr.h"
|
||||
#define SSHKEY_INTERNAL
|
||||
#include "sshkey.h"
|
||||
#include "digest.h"
|
||||
|
||||
static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int, RSA *);
|
||||
static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *);
|
||||
|
||||
/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
|
||||
int
|
||||
ssh_rsa_sign(const Key *key, u_char **sigp, u_int *lenp,
|
||||
const u_char *data, u_int datalen)
|
||||
ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
|
||||
const u_char *data, size_t datalen, u_int compat)
|
||||
{
|
||||
int hash_alg;
|
||||
u_char digest[SSH_DIGEST_MAX_LENGTH], *sig;
|
||||
u_int slen, dlen, len;
|
||||
int ok, nid;
|
||||
Buffer b;
|
||||
u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL;
|
||||
size_t slen;
|
||||
u_int dlen, len;
|
||||
int nid, ret = SSH_ERR_INTERNAL_ERROR;
|
||||
struct sshbuf *b = NULL;
|
||||
|
||||
if (key == NULL || key_type_plain(key->type) != KEY_RSA ||
|
||||
key->rsa == NULL) {
|
||||
error("%s: no RSA key", __func__);
|
||||
return -1;
|
||||
}
|
||||
if (lenp != NULL)
|
||||
*lenp = 0;
|
||||
if (sigp != NULL)
|
||||
*sigp = NULL;
|
||||
|
||||
if (key == NULL || key->rsa == NULL ||
|
||||
sshkey_type_plain(key->type) != KEY_RSA)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
slen = RSA_size(key->rsa);
|
||||
if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
|
||||
/* hash the data */
|
||||
hash_alg = SSH_DIGEST_SHA1;
|
||||
nid = NID_sha1;
|
||||
if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
|
||||
error("%s: bad hash algorithm %d", __func__, hash_alg);
|
||||
return -1;
|
||||
}
|
||||
if (ssh_digest_memory(hash_alg, data, datalen,
|
||||
digest, sizeof(digest)) != 0) {
|
||||
error("%s: ssh_digest_memory failed", __func__);
|
||||
return -1;
|
||||
if ((dlen = ssh_digest_bytes(hash_alg)) == 0)
|
||||
return SSH_ERR_INTERNAL_ERROR;
|
||||
if ((ret = ssh_digest_memory(hash_alg, data, datalen,
|
||||
digest, sizeof(digest))) != 0)
|
||||
goto out;
|
||||
|
||||
if ((sig = malloc(slen)) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
slen = RSA_size(key->rsa);
|
||||
sig = xmalloc(slen);
|
||||
|
||||
ok = RSA_sign(nid, digest, dlen, sig, &len, key->rsa);
|
||||
explicit_bzero(digest, sizeof(digest));
|
||||
|
||||
if (ok != 1) {
|
||||
int ecode = ERR_get_error();
|
||||
|
||||
error("%s: RSA_sign failed: %s", __func__,
|
||||
ERR_error_string(ecode, NULL));
|
||||
free(sig);
|
||||
return -1;
|
||||
if (RSA_sign(nid, digest, dlen, sig, &len, key->rsa) != 1) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
if (len < slen) {
|
||||
u_int diff = slen - len;
|
||||
debug("slen %u > len %u", slen, len);
|
||||
size_t diff = slen - len;
|
||||
memmove(sig + diff, sig, len);
|
||||
explicit_bzero(sig, diff);
|
||||
} else if (len > slen) {
|
||||
error("%s: slen %u slen2 %u", __func__, slen, len);
|
||||
free(sig);
|
||||
return -1;
|
||||
ret = SSH_ERR_INTERNAL_ERROR;
|
||||
goto out;
|
||||
}
|
||||
/* encode signature */
|
||||
buffer_init(&b);
|
||||
buffer_put_cstring(&b, "ssh-rsa");
|
||||
buffer_put_string(&b, sig, slen);
|
||||
len = buffer_len(&b);
|
||||
if ((b = sshbuf_new()) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if ((ret = sshbuf_put_cstring(b, "ssh-rsa")) != 0 ||
|
||||
(ret = sshbuf_put_string(b, sig, slen)) != 0)
|
||||
goto out;
|
||||
len = sshbuf_len(b);
|
||||
if (sigp != NULL) {
|
||||
if ((*sigp = malloc(len)) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
memcpy(*sigp, sshbuf_ptr(b), len);
|
||||
}
|
||||
if (lenp != NULL)
|
||||
*lenp = len;
|
||||
if (sigp != NULL) {
|
||||
*sigp = xmalloc(len);
|
||||
memcpy(*sigp, buffer_ptr(&b), len);
|
||||
}
|
||||
buffer_free(&b);
|
||||
ret = 0;
|
||||
out:
|
||||
explicit_bzero(digest, sizeof(digest));
|
||||
if (sig != NULL) {
|
||||
explicit_bzero(sig, slen);
|
||||
free(sig);
|
||||
|
||||
}
|
||||
if (b != NULL)
|
||||
sshbuf_free(b);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
|
||||
const u_char *data, u_int datalen)
|
||||
ssh_rsa_verify(const struct sshkey *key,
|
||||
const u_char *signature, size_t signaturelen,
|
||||
const u_char *data, size_t datalen, u_int compat)
|
||||
{
|
||||
Buffer b;
|
||||
int hash_alg;
|
||||
char *ktype;
|
||||
u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob;
|
||||
u_int len, dlen, modlen;
|
||||
int rlen, ret;
|
||||
char *ktype = NULL;
|
||||
int hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
|
||||
size_t len, diff, modlen, dlen;
|
||||
struct sshbuf *b = NULL;
|
||||
u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL;
|
||||
|
||||
if (key == NULL || key_type_plain(key->type) != KEY_RSA ||
|
||||
key->rsa == NULL) {
|
||||
error("%s: no RSA key", __func__);
|
||||
return -1;
|
||||
}
|
||||
if (key == NULL || key->rsa == NULL ||
|
||||
sshkey_type_plain(key->type) != KEY_RSA ||
|
||||
BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
|
||||
if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
|
||||
error("%s: RSA modulus too small: %d < minimum %d bits",
|
||||
__func__, BN_num_bits(key->rsa->n),
|
||||
SSH_RSA_MINIMUM_MODULUS_SIZE);
|
||||
return -1;
|
||||
if ((b = sshbuf_from(signature, signaturelen)) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
if (sshbuf_get_cstring(b, &ktype, NULL) != 0) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
buffer_init(&b);
|
||||
buffer_append(&b, signature, signaturelen);
|
||||
ktype = buffer_get_cstring(&b, NULL);
|
||||
if (strcmp("ssh-rsa", ktype) != 0) {
|
||||
error("%s: cannot handle type %s", __func__, ktype);
|
||||
buffer_free(&b);
|
||||
free(ktype);
|
||||
return -1;
|
||||
ret = SSH_ERR_KEY_TYPE_MISMATCH;
|
||||
goto out;
|
||||
}
|
||||
free(ktype);
|
||||
sigblob = buffer_get_string(&b, &len);
|
||||
rlen = buffer_len(&b);
|
||||
buffer_free(&b);
|
||||
if (rlen != 0) {
|
||||
error("%s: remaining bytes in signature %d", __func__, rlen);
|
||||
free(sigblob);
|
||||
return -1;
|
||||
if (sshbuf_get_string(b, &sigblob, &len) != 0) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
if (sshbuf_len(b) != 0) {
|
||||
ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
|
||||
goto out;
|
||||
}
|
||||
/* RSA_verify expects a signature of RSA_size */
|
||||
modlen = RSA_size(key->rsa);
|
||||
if (len > modlen) {
|
||||
error("%s: len %u > modlen %u", __func__, len, modlen);
|
||||
free(sigblob);
|
||||
return -1;
|
||||
ret = SSH_ERR_KEY_BITS_MISMATCH;
|
||||
goto out;
|
||||
} else if (len < modlen) {
|
||||
u_int diff = modlen - len;
|
||||
debug("%s: add padding: modlen %u > len %u", __func__,
|
||||
modlen, len);
|
||||
sigblob = xrealloc(sigblob, 1, modlen);
|
||||
diff = modlen - len;
|
||||
osigblob = sigblob;
|
||||
if ((sigblob = realloc(sigblob, modlen)) == NULL) {
|
||||
sigblob = osigblob; /* put it back for clear/free */
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
memmove(sigblob + diff, sigblob, len);
|
||||
explicit_bzero(sigblob, diff);
|
||||
len = modlen;
|
||||
}
|
||||
/* hash the data */
|
||||
hash_alg = SSH_DIGEST_SHA1;
|
||||
if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
|
||||
error("%s: bad hash algorithm %d", __func__, hash_alg);
|
||||
return -1;
|
||||
}
|
||||
if (ssh_digest_memory(hash_alg, data, datalen,
|
||||
digest, sizeof(digest)) != 0) {
|
||||
error("%s: ssh_digest_memory failed", __func__);
|
||||
return -1;
|
||||
ret = SSH_ERR_INTERNAL_ERROR;
|
||||
goto out;
|
||||
}
|
||||
if ((ret = ssh_digest_memory(hash_alg, data, datalen,
|
||||
digest, sizeof(digest))) != 0)
|
||||
goto out;
|
||||
|
||||
ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len,
|
||||
key->rsa);
|
||||
explicit_bzero(digest, sizeof(digest));
|
||||
out:
|
||||
if (sigblob != NULL) {
|
||||
explicit_bzero(sigblob, len);
|
||||
free(sigblob);
|
||||
debug("%s: signature %scorrect", __func__, (ret == 0) ? "in" : "");
|
||||
}
|
||||
if (ktype != NULL)
|
||||
free(ktype);
|
||||
if (b != NULL)
|
||||
sshbuf_free(b);
|
||||
explicit_bzero(digest, sizeof(digest));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -204,15 +208,15 @@ static const u_char id_sha1[] = {
|
|||
};
|
||||
|
||||
static int
|
||||
openssh_RSA_verify(int hash_alg, u_char *hash, u_int hashlen,
|
||||
u_char *sigbuf, u_int siglen, RSA *rsa)
|
||||
openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen,
|
||||
u_char *sigbuf, size_t siglen, RSA *rsa)
|
||||
{
|
||||
u_int ret, rsasize, oidlen = 0, hlen = 0;
|
||||
size_t ret, rsasize = 0, oidlen = 0, hlen = 0;
|
||||
int len, oidmatch, hashmatch;
|
||||
const u_char *oid = NULL;
|
||||
u_char *decrypted = NULL;
|
||||
|
||||
ret = 0;
|
||||
ret = SSH_ERR_INTERNAL_ERROR;
|
||||
switch (hash_alg) {
|
||||
case SSH_DIGEST_SHA1:
|
||||
oid = id_sha1;
|
||||
|
@ -223,37 +227,39 @@ openssh_RSA_verify(int hash_alg, u_char *hash, u_int hashlen,
|
|||
goto done;
|
||||
}
|
||||
if (hashlen != hlen) {
|
||||
error("bad hashlen");
|
||||
ret = SSH_ERR_INVALID_ARGUMENT;
|
||||
goto done;
|
||||
}
|
||||
rsasize = RSA_size(rsa);
|
||||
if (siglen == 0 || siglen > rsasize) {
|
||||
error("bad siglen");
|
||||
if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM ||
|
||||
siglen == 0 || siglen > rsasize) {
|
||||
ret = SSH_ERR_INVALID_ARGUMENT;
|
||||
goto done;
|
||||
}
|
||||
if ((decrypted = malloc(rsasize)) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto done;
|
||||
}
|
||||
decrypted = xmalloc(rsasize);
|
||||
if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa,
|
||||
RSA_PKCS1_PADDING)) < 0) {
|
||||
error("RSA_public_decrypt failed: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto done;
|
||||
}
|
||||
if (len < 0 || (u_int)len != hlen + oidlen) {
|
||||
error("bad decrypted len: %d != %d + %d", len, hlen, oidlen);
|
||||
if (len < 0 || (size_t)len != hlen + oidlen) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto done;
|
||||
}
|
||||
oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0;
|
||||
hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0;
|
||||
if (!oidmatch) {
|
||||
error("oid mismatch");
|
||||
if (!oidmatch || !hashmatch) {
|
||||
ret = SSH_ERR_SIGNATURE_INVALID;
|
||||
goto done;
|
||||
}
|
||||
if (!hashmatch) {
|
||||
error("hash mismatch");
|
||||
goto done;
|
||||
}
|
||||
ret = 1;
|
||||
ret = 0;
|
||||
done:
|
||||
if (decrypted) {
|
||||
explicit_bzero(decrypted, rsasize);
|
||||
free(decrypted);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: sshbuf-misc.c,v 1.1 2014/04/30 05:29:56 djm Exp $ */
|
||||
/* $OpenBSD: sshbuf-misc.c,v 1.2 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011 Damien Miller
|
||||
*
|
||||
|
@ -33,12 +33,11 @@
|
|||
#include "sshbuf.h"
|
||||
|
||||
void
|
||||
sshbuf_dump(struct sshbuf *buf, FILE *f)
|
||||
sshbuf_dump_data(const void *s, size_t len, FILE *f)
|
||||
{
|
||||
const u_char *p = sshbuf_ptr(buf);
|
||||
size_t i, j, len = sshbuf_len(buf);
|
||||
size_t i, j;
|
||||
const u_char *p = (const u_char *)s;
|
||||
|
||||
fprintf(f, "buffer %p len = %zu\n", buf, len);
|
||||
for (i = 0; i < len; i += 16) {
|
||||
fprintf(f, "%.4zd: ", i);
|
||||
for (j = i; j < i + 16; j++) {
|
||||
|
@ -60,6 +59,13 @@ sshbuf_dump(struct sshbuf *buf, FILE *f)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
sshbuf_dump(struct sshbuf *buf, FILE *f)
|
||||
{
|
||||
fprintf(f, "buffer %p len = %zu\n", buf, sshbuf_len(buf));
|
||||
sshbuf_dump_data(sshbuf_ptr(buf), sshbuf_len(buf), f);
|
||||
}
|
||||
|
||||
char *
|
||||
sshbuf_dtob16(struct sshbuf *buf)
|
||||
{
|
||||
|
|
7
sshbuf.h
7
sshbuf.h
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: sshbuf.h,v 1.2 2014/06/10 21:46:11 dtucker Exp $ */
|
||||
/* $OpenBSD: sshbuf.h,v 1.3 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011 Damien Miller
|
||||
*
|
||||
|
@ -216,9 +216,12 @@ int sshbuf_put_ec(struct sshbuf *buf, const EC_POINT *v, const EC_GROUP *g);
|
|||
int sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v);
|
||||
#endif
|
||||
|
||||
/* Dump the contents of the buffer to stderr in a human-readable format */
|
||||
/* Dump the contents of the buffer in a human-readable format */
|
||||
void sshbuf_dump(struct sshbuf *buf, FILE *f);
|
||||
|
||||
/* Dump specified memory in a human-readable format */
|
||||
void sshbuf_dump_data(const void *s, size_t len, FILE *f);
|
||||
|
||||
/* Return the hexadecimal representation of the contents of the buffer */
|
||||
char *sshbuf_dtob16(struct sshbuf *buf);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: sshconnect.c,v 1.248 2014/04/29 18:01:49 markus Exp $ */
|
||||
/* $OpenBSD: sshconnect.c,v 1.249 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -709,7 +709,7 @@ check_host_cert(const char *host, const Key *host_key)
|
|||
error("%s", reason);
|
||||
return 0;
|
||||
}
|
||||
if (buffer_len(&host_key->cert->critical) != 0) {
|
||||
if (buffer_len(host_key->cert->critical) != 0) {
|
||||
error("Certificate for %s contains unsupported "
|
||||
"critical options(s)", host);
|
||||
return 0;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: sshconnect1.c,v 1.74 2014/02/02 03:44:32 djm Exp $ */
|
||||
/* $OpenBSD: sshconnect1.c,v 1.75 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -166,7 +166,7 @@ respond_to_rsa_challenge(BIGNUM * challenge, RSA * prv)
|
|||
|
||||
/* Decrypt the challenge using the private key. */
|
||||
/* XXX think about Bleichenbacher, too */
|
||||
if (rsa_private_decrypt(challenge, challenge, prv) <= 0)
|
||||
if (rsa_private_decrypt(challenge, challenge, prv) != 0)
|
||||
packet_disconnect(
|
||||
"respond_to_rsa_challenge: rsa_private_decrypt failed");
|
||||
|
||||
|
@ -253,7 +253,7 @@ try_rsa_authentication(int idx)
|
|||
* load the private key. Try first with empty passphrase; if it
|
||||
* fails, ask for a passphrase.
|
||||
*/
|
||||
if (public->flags & KEY_FLAG_EXT)
|
||||
if (public->flags & SSHKEY_FLAG_EXT)
|
||||
private = public;
|
||||
else
|
||||
private = key_load_private_type(KEY_RSA1, authfile, "", NULL,
|
||||
|
@ -302,7 +302,7 @@ try_rsa_authentication(int idx)
|
|||
respond_to_rsa_challenge(challenge, private->rsa);
|
||||
|
||||
/* Destroy the private key unless it in external hardware. */
|
||||
if (!(private->flags & KEY_FLAG_EXT))
|
||||
if (!(private->flags & SSHKEY_FLAG_EXT))
|
||||
key_free(private);
|
||||
|
||||
/* We no longer need the challenge. */
|
||||
|
@ -592,8 +592,9 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
|
|||
BN_num_bits(server_key->rsa->n),
|
||||
SSH_KEY_BITS_RESERVED);
|
||||
}
|
||||
rsa_public_encrypt(key, key, server_key->rsa);
|
||||
rsa_public_encrypt(key, key, host_key->rsa);
|
||||
if (rsa_public_encrypt(key, key, server_key->rsa) != 0 ||
|
||||
rsa_public_encrypt(key, key, host_key->rsa) != 0)
|
||||
fatal("%s: rsa_public_encrypt failed", __func__);
|
||||
} else {
|
||||
/* Host key has smaller modulus (or they are equal). */
|
||||
if (BN_num_bits(server_key->rsa->n) <
|
||||
|
@ -604,8 +605,9 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
|
|||
BN_num_bits(host_key->rsa->n),
|
||||
SSH_KEY_BITS_RESERVED);
|
||||
}
|
||||
rsa_public_encrypt(key, key, host_key->rsa);
|
||||
rsa_public_encrypt(key, key, server_key->rsa);
|
||||
if (rsa_public_encrypt(key, key, host_key->rsa) != 0 ||
|
||||
rsa_public_encrypt(key, key, server_key->rsa) != 0)
|
||||
fatal("%s: rsa_public_encrypt failed", __func__);
|
||||
}
|
||||
|
||||
/* Destroy the public keys since we no longer need them. */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: sshconnect2.c,v 1.208 2014/06/05 22:17:50 djm Exp $ */
|
||||
/* $OpenBSD: sshconnect2.c,v 1.209 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2008 Damien Miller. All rights reserved.
|
||||
|
@ -970,7 +970,7 @@ identity_sign(Identity *id, u_char **sigp, u_int *lenp,
|
|||
* we have already loaded the private key or
|
||||
* the private key is stored in external hardware
|
||||
*/
|
||||
if (id->isprivate || (id->key->flags & KEY_FLAG_EXT))
|
||||
if (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))
|
||||
return (key_sign(id->key, sigp, lenp, data, datalen));
|
||||
/* load the private key from the file */
|
||||
if ((prv = load_identity_file(id->filename, id->userprovided)) == NULL)
|
||||
|
@ -1178,12 +1178,12 @@ pubkey_prepare(Authctxt *authctxt)
|
|||
}
|
||||
/* Prefer PKCS11 keys that are explicitly listed */
|
||||
TAILQ_FOREACH_SAFE(id, &files, next, tmp) {
|
||||
if (id->key == NULL || (id->key->flags & KEY_FLAG_EXT) == 0)
|
||||
if (id->key == NULL || (id->key->flags & SSHKEY_FLAG_EXT) == 0)
|
||||
continue;
|
||||
found = 0;
|
||||
TAILQ_FOREACH(id2, &files, next) {
|
||||
if (id2->key == NULL ||
|
||||
(id2->key->flags & KEY_FLAG_EXT) == 0)
|
||||
(id2->key->flags & SSHKEY_FLAG_EXT) == 0)
|
||||
continue;
|
||||
if (key_equal(id->key, id2->key)) {
|
||||
TAILQ_REMOVE(&files, id, next);
|
||||
|
|
16
sshd.c
16
sshd.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: sshd.c,v 1.426 2014/04/29 18:01:49 markus Exp $ */
|
||||
/* $OpenBSD: sshd.c,v 1.427 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -1031,8 +1031,10 @@ recv_rexec_state(int fd, Buffer *conf)
|
|||
buffer_get_bignum(&m, sensitive_data.server_key->rsa->iqmp);
|
||||
buffer_get_bignum(&m, sensitive_data.server_key->rsa->p);
|
||||
buffer_get_bignum(&m, sensitive_data.server_key->rsa->q);
|
||||
rsa_generate_additional_parameters(
|
||||
sensitive_data.server_key->rsa);
|
||||
if (rsa_generate_additional_parameters(
|
||||
sensitive_data.server_key->rsa) != 0)
|
||||
fatal("%s: rsa_generate_additional_parameters "
|
||||
"error", __func__);
|
||||
#else
|
||||
fatal("ssh1 not supported");
|
||||
#endif
|
||||
|
@ -2215,10 +2217,10 @@ ssh1_session_key(BIGNUM *session_key_int)
|
|||
SSH_KEY_BITS_RESERVED);
|
||||
}
|
||||
if (rsa_private_decrypt(session_key_int, session_key_int,
|
||||
sensitive_data.server_key->rsa) <= 0)
|
||||
sensitive_data.server_key->rsa) != 0)
|
||||
rsafail++;
|
||||
if (rsa_private_decrypt(session_key_int, session_key_int,
|
||||
sensitive_data.ssh1_host_key->rsa) <= 0)
|
||||
sensitive_data.ssh1_host_key->rsa) != 0)
|
||||
rsafail++;
|
||||
} else {
|
||||
/* Host key has bigger modulus (or they are equal). */
|
||||
|
@ -2233,10 +2235,10 @@ ssh1_session_key(BIGNUM *session_key_int)
|
|||
SSH_KEY_BITS_RESERVED);
|
||||
}
|
||||
if (rsa_private_decrypt(session_key_int, session_key_int,
|
||||
sensitive_data.ssh1_host_key->rsa) < 0)
|
||||
sensitive_data.ssh1_host_key->rsa) != 0)
|
||||
rsafail++;
|
||||
if (rsa_private_decrypt(session_key_int, session_key_int,
|
||||
sensitive_data.server_key->rsa) < 0)
|
||||
sensitive_data.server_key->rsa) != 0)
|
||||
rsafail++;
|
||||
}
|
||||
return (rsafail);
|
||||
|
|
|
@ -0,0 +1,222 @@
|
|||
/* $OpenBSD: sshkey.h,v 1.1 2014/06/24 01:16:58 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef SSHKEY_H
|
||||
#define SSHKEY_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/ec.h>
|
||||
#else /* OPENSSL */
|
||||
#define RSA void
|
||||
#define DSA void
|
||||
#define EC_KEY void
|
||||
#define EC_GROUP void
|
||||
#define EC_POINT void
|
||||
#endif /* WITH_OPENSSL */
|
||||
|
||||
#define SSH_RSA_MINIMUM_MODULUS_SIZE 768
|
||||
#define SSH_KEY_MAX_SIGN_DATA_SIZE (1 << 20)
|
||||
|
||||
struct sshbuf;
|
||||
|
||||
/* Key types */
|
||||
enum sshkey_types {
|
||||
KEY_RSA1,
|
||||
KEY_RSA,
|
||||
KEY_DSA,
|
||||
KEY_ECDSA,
|
||||
KEY_ED25519,
|
||||
KEY_RSA_CERT,
|
||||
KEY_DSA_CERT,
|
||||
KEY_ECDSA_CERT,
|
||||
KEY_ED25519_CERT,
|
||||
KEY_RSA_CERT_V00,
|
||||
KEY_DSA_CERT_V00,
|
||||
KEY_UNSPEC
|
||||
};
|
||||
|
||||
/* Fingerprint hash algorithms */
|
||||
enum sshkey_fp_type {
|
||||
SSH_FP_SHA1,
|
||||
SSH_FP_MD5,
|
||||
SSH_FP_SHA256
|
||||
};
|
||||
|
||||
/* Fingerprint representation formats */
|
||||
enum sshkey_fp_rep {
|
||||
SSH_FP_HEX,
|
||||
SSH_FP_BUBBLEBABBLE,
|
||||
SSH_FP_RANDOMART
|
||||
};
|
||||
|
||||
/* key is stored in external hardware */
|
||||
#define SSHKEY_FLAG_EXT 0x0001
|
||||
|
||||
#define SSHKEY_CERT_MAX_PRINCIPALS 256
|
||||
/* XXX opaquify? */
|
||||
struct sshkey_cert {
|
||||
struct sshbuf *certblob; /* Kept around for use on wire */
|
||||
u_int type; /* SSH2_CERT_TYPE_USER or SSH2_CERT_TYPE_HOST */
|
||||
u_int64_t serial;
|
||||
char *key_id;
|
||||
u_int nprincipals;
|
||||
char **principals;
|
||||
u_int64_t valid_after, valid_before;
|
||||
struct sshbuf *critical;
|
||||
struct sshbuf *extensions;
|
||||
struct sshkey *signature_key;
|
||||
};
|
||||
|
||||
/* XXX opaquify? */
|
||||
struct sshkey {
|
||||
int type;
|
||||
int flags;
|
||||
RSA *rsa;
|
||||
DSA *dsa;
|
||||
int ecdsa_nid; /* NID of curve */
|
||||
EC_KEY *ecdsa;
|
||||
u_char *ed25519_sk;
|
||||
u_char *ed25519_pk;
|
||||
struct sshkey_cert *cert;
|
||||
};
|
||||
|
||||
#define ED25519_SK_SZ crypto_sign_ed25519_SECRETKEYBYTES
|
||||
#define ED25519_PK_SZ crypto_sign_ed25519_PUBLICKEYBYTES
|
||||
|
||||
struct sshkey *sshkey_new(int);
|
||||
int sshkey_add_private(struct sshkey *);
|
||||
struct sshkey *sshkey_new_private(int);
|
||||
void sshkey_free(struct sshkey *);
|
||||
int sshkey_demote(const struct sshkey *, struct sshkey **);
|
||||
int sshkey_equal_public(const struct sshkey *,
|
||||
const struct sshkey *);
|
||||
int sshkey_equal(const struct sshkey *, const struct sshkey *);
|
||||
char *sshkey_fingerprint(const struct sshkey *,
|
||||
enum sshkey_fp_type, enum sshkey_fp_rep);
|
||||
int sshkey_fingerprint_raw(const struct sshkey *k,
|
||||
enum sshkey_fp_type dgst_type, u_char **retp, size_t *lenp);
|
||||
const char *sshkey_type(const struct sshkey *);
|
||||
const char *sshkey_cert_type(const struct sshkey *);
|
||||
int sshkey_write(const struct sshkey *, FILE *);
|
||||
int sshkey_read(struct sshkey *, char **);
|
||||
u_int sshkey_size(const struct sshkey *);
|
||||
|
||||
int sshkey_generate(int type, u_int bits, struct sshkey **keyp);
|
||||
int sshkey_from_private(const struct sshkey *, struct sshkey **);
|
||||
int sshkey_type_from_name(const char *);
|
||||
int sshkey_is_cert(const struct sshkey *);
|
||||
int sshkey_type_is_cert(int);
|
||||
int sshkey_type_plain(int);
|
||||
int sshkey_to_certified(struct sshkey *, int);
|
||||
int sshkey_drop_cert(struct sshkey *);
|
||||
int sshkey_certify(struct sshkey *, struct sshkey *);
|
||||
int sshkey_cert_copy(const struct sshkey *, struct sshkey *);
|
||||
int sshkey_cert_check_authority(const struct sshkey *, int, int,
|
||||
const char *, const char **);
|
||||
int sshkey_cert_is_legacy(const struct sshkey *);
|
||||
|
||||
int sshkey_ecdsa_nid_from_name(const char *);
|
||||
int sshkey_curve_name_to_nid(const char *);
|
||||
const char * sshkey_curve_nid_to_name(int);
|
||||
u_int sshkey_curve_nid_to_bits(int);
|
||||
int sshkey_ecdsa_bits_to_nid(int);
|
||||
int sshkey_ecdsa_key_to_nid(EC_KEY *);
|
||||
int sshkey_ec_nid_to_hash_alg(int nid);
|
||||
int sshkey_ec_validate_public(const EC_GROUP *, const EC_POINT *);
|
||||
int sshkey_ec_validate_private(const EC_KEY *);
|
||||
const char *sshkey_ssh_name(const struct sshkey *);
|
||||
const char *sshkey_ssh_name_plain(const struct sshkey *);
|
||||
int sshkey_names_valid2(const char *);
|
||||
char *key_alg_list(int, int);
|
||||
|
||||
int sshkey_from_blob(const u_char *, size_t, struct sshkey **);
|
||||
int sshkey_to_blob_buf(const struct sshkey *, struct sshbuf *);
|
||||
int sshkey_to_blob(const struct sshkey *, u_char **, size_t *);
|
||||
int sshkey_plain_to_blob_buf(const struct sshkey *, struct sshbuf *);
|
||||
int sshkey_plain_to_blob(const struct sshkey *, u_char **, size_t *);
|
||||
|
||||
int sshkey_sign(const struct sshkey *, u_char **, size_t *,
|
||||
const u_char *, size_t, u_int);
|
||||
int sshkey_verify(const struct sshkey *, const u_char *, size_t,
|
||||
const u_char *, size_t, u_int);
|
||||
|
||||
/* for debug */
|
||||
void sshkey_dump_ec_point(const EC_GROUP *, const EC_POINT *);
|
||||
void sshkey_dump_ec_key(const EC_KEY *);
|
||||
|
||||
/* private key parsing and serialisation */
|
||||
int sshkey_private_serialize(const struct sshkey *key, struct sshbuf *buf);
|
||||
int sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **keyp);
|
||||
|
||||
/* private key file format parsing and serialisation */
|
||||
int sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
|
||||
const char *passphrase, const char *comment,
|
||||
int force_new_format, const char *new_format_cipher, int new_format_rounds);
|
||||
int sshkey_parse_public_rsa1_fileblob(struct sshbuf *blob,
|
||||
struct sshkey **keyp, char **commentp);
|
||||
int sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
|
||||
const char *passphrase, struct sshkey **keyp, char **commentp);
|
||||
int sshkey_parse_private_fileblob(struct sshbuf *buffer,
|
||||
const char *passphrase, const char *filename, struct sshkey **keyp,
|
||||
char **commentp);
|
||||
int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
|
||||
const char *passphrase, struct sshkey **keyp, char **commentp);
|
||||
|
||||
#ifdef SSHKEY_INTERNAL
|
||||
int ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
|
||||
const u_char *data, size_t datalen, u_int compat);
|
||||
int ssh_rsa_verify(const struct sshkey *key,
|
||||
const u_char *signature, size_t signaturelen,
|
||||
const u_char *data, size_t datalen, u_int compat);
|
||||
int ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
|
||||
const u_char *data, size_t datalen, u_int compat);
|
||||
int ssh_dss_verify(const struct sshkey *key,
|
||||
const u_char *signature, size_t signaturelen,
|
||||
const u_char *data, size_t datalen, u_int compat);
|
||||
int ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
|
||||
const u_char *data, size_t datalen, u_int compat);
|
||||
int ssh_ecdsa_verify(const struct sshkey *key,
|
||||
const u_char *signature, size_t signaturelen,
|
||||
const u_char *data, size_t datalen, u_int compat);
|
||||
int ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
|
||||
const u_char *data, size_t datalen, u_int compat);
|
||||
int ssh_ed25519_verify(const struct sshkey *key,
|
||||
const u_char *signature, size_t signaturelen,
|
||||
const u_char *data, size_t datalen, u_int compat);
|
||||
#endif
|
||||
|
||||
#ifndef WITH_OPENSSL
|
||||
#undef RSA
|
||||
#undef DSA
|
||||
#undef EC_KEY
|
||||
#undef EC_GROUP
|
||||
#undef EC_POINT
|
||||
#endif /* WITH_OPENSSL */
|
||||
|
||||
#endif /* SSHKEY_H */
|
Loading…
Reference in New Issue