mirror of
https://github.com/PowerShell/Win32-OpenSSH.git
synced 2025-07-22 13:34:43 +02:00
CTR and CBC mode CNG ciphers replacing OpenSSL ciphers
This commit is contained in:
parent
d59177d82e
commit
bafc1df7c5
3
.gitignore
vendored
3
.gitignore
vendored
@ -262,4 +262,5 @@ regress/rsa_ssh2_crnl.prv
|
||||
regress/t7.out.pub
|
||||
regress/t6.out2
|
||||
config.h
|
||||
configure
|
||||
configure
|
||||
config.h
|
@ -44,7 +44,7 @@ CC=@CC@
|
||||
LD=@LD@
|
||||
CFLAGS=@CFLAGS@
|
||||
CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
|
||||
LIBS=@LIBS@
|
||||
LIBS=@LIBS@ -lbcrypt
|
||||
K5LIBS=@K5LIBS@
|
||||
GSSLIBS=@GSSLIBS@
|
||||
SSHLIBS=@SSHLIBS@
|
||||
@ -58,7 +58,7 @@ PERL=@PERL@
|
||||
SED=@SED@
|
||||
ENT=@ENT@
|
||||
XAUTH_PATH=@XAUTH_PATH@
|
||||
LDFLAGS=-L. -Lopenbsd-compat/ -Lcontrib/win32/win32compat @LDFLAGS@
|
||||
LDFLAGS=-L. -Lopenbsd-compat/ -Lcontrib/win32/win32compat @LDFLAGS@ -L/cygdrive/C/cygwin-32/lib/w32api
|
||||
EXEEXT=@EXEEXT@
|
||||
MANFMT=@MANFMT@
|
||||
|
||||
|
68
cipher.c
68
cipher.c
@ -34,7 +34,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
@ -43,6 +43,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#include "cipher.h"
|
||||
#include "misc.h"
|
||||
#include "sshbuf.h"
|
||||
@ -51,6 +52,12 @@
|
||||
|
||||
#include "openbsd-compat/openssl-compat.h"
|
||||
|
||||
|
||||
|
||||
#ifdef USE_MSCNG
|
||||
#undef WITH_OPENSSL
|
||||
#endif
|
||||
|
||||
#ifdef WITH_SSH1
|
||||
extern const EVP_CIPHER *evp_ssh1_bf(void);
|
||||
extern const EVP_CIPHER *evp_ssh1_3des(void);
|
||||
@ -108,9 +115,19 @@ static const struct sshcipher ciphers[] = {
|
||||
SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm },
|
||||
# endif /* OPENSSL_HAVE_EVPGCM */
|
||||
#else /* WITH_OPENSSL */
|
||||
|
||||
#ifdef USE_MSCNG
|
||||
{ "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, _CNG_CIPHER_AES | _CNG_MODE_CTR, NULL },
|
||||
{ "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, _CNG_CIPHER_AES | _CNG_MODE_CTR, NULL },
|
||||
{ "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, _CNG_CIPHER_AES | _CNG_MODE_CTR, NULL },
|
||||
{ "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, _CNG_CIPHER_AES | _CNG_MODE_CBC, NULL },
|
||||
{ "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, _CNG_CIPHER_AES | _CNG_MODE_CBC, NULL },
|
||||
{ "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, _CNG_CIPHER_AES | _CNG_MODE_CBC, NULL },
|
||||
#else
|
||||
{ "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 },
|
||||
{ "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, CFLAG_AESCTR, NULL },
|
||||
#endif
|
||||
{ "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, CFLAG_NONE, NULL },
|
||||
#endif /* WITH_OPENSSL */
|
||||
{ "chacha20-poly1305@openssh.com",
|
||||
@ -293,6 +310,8 @@ 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
|
||||
int ret = SSH_ERR_INTERNAL_ERROR;
|
||||
const EVP_CIPHER *type;
|
||||
@ -316,11 +335,25 @@ cipher_init(struct sshcipher_ctx *cc, const struct sshcipher *cipher,
|
||||
return chachapoly_init(&cc->cp_ctx, key, keylen);
|
||||
}
|
||||
#ifndef WITH_OPENSSL
|
||||
|
||||
#ifdef USE_MSCNG
|
||||
|
||||
/* cng shares cipher flag with NONE. Make sure the NONE cipher isn't requested */
|
||||
if ((cc->cipher->flags & CFLAG_NONE) == 0)
|
||||
{
|
||||
|
||||
if (cng_cipher_init(&cc->cng_ctx,key,keylen,iv, ivlen,cc->cipher->flags))
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
|
||||
aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen);
|
||||
aesctr_ivsetup(&cc->ac_ctx, iv);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if ((cc->cipher->flags & CFLAG_NONE) != 0)
|
||||
return 0;
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
@ -373,6 +406,7 @@ cipher_init(struct sshcipher_ctx *cc, const struct sshcipher *cipher,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* cipher_crypt() operates as following:
|
||||
* Copy 'aadlen' bytes (without en/decryption) from 'src' to 'dest'.
|
||||
@ -387,18 +421,44 @@ int
|
||||
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)
|
||||
{
|
||||
#ifdef USE_MSCNG
|
||||
int ret = 0;
|
||||
#endif
|
||||
|
||||
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) {
|
||||
|
||||
#ifdef USE_MSCNG
|
||||
|
||||
/* cng shares cipher flag with NONE. Make sure the NONE cipher isn't requested */
|
||||
if ((cc->cipher->flags & CFLAG_NONE) == 0)
|
||||
{
|
||||
if (aadlen)
|
||||
memcpy(dest, src, aadlen);
|
||||
if (cc->encrypt)
|
||||
ret = cng_cipher_encrypt(&cc->cng_ctx,dest+aadlen, len, src+aadlen,len);
|
||||
else
|
||||
ret = cng_cipher_decrypt(&cc->cng_ctx,dest+aadlen, len, src+aadlen, len);
|
||||
|
||||
if (ret != len){
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
|
||||
if (aadlen)
|
||||
memcpy(dest, src, aadlen);
|
||||
aesctr_encrypt_bytes(&cc->ac_ctx, src + aadlen,
|
||||
dest + aadlen, len);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if ((cc->cipher->flags & CFLAG_NONE) != 0) {
|
||||
memcpy(dest, src, aadlen + len);
|
||||
return 0;
|
||||
@ -472,6 +532,10 @@ cipher_cleanup(struct sshcipher_ctx *cc)
|
||||
else if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0)
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
#endif
|
||||
#ifdef USE_MSCNG
|
||||
else
|
||||
cng_cipher_cleanup(&cc->cng_ctx);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
8
cipher.h
8
cipher.h
@ -41,7 +41,9 @@
|
||||
#include <openssl/evp.h>
|
||||
#include "cipher-chachapoly.h"
|
||||
#include "cipher-aesctr.h"
|
||||
|
||||
#ifdef USE_MSCNG
|
||||
#include "contrib/win32/win32compat/cng_cipher.h"
|
||||
#endif
|
||||
/*
|
||||
* Cipher types for SSH-1. New types can be added, but old types should not
|
||||
* be removed for compatibility. The maximum allowed value is 31.
|
||||
@ -70,6 +72,10 @@ struct sshcipher_ctx {
|
||||
struct chachapoly_ctx cp_ctx; /* XXX union with evp? */
|
||||
struct aesctr_ctx ac_ctx; /* XXX union with evp? */
|
||||
const struct sshcipher *cipher;
|
||||
#ifdef USE_MSCNG
|
||||
struct ssh_cng_cipher_ctx cng_ctx;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
u_int cipher_mask_ssh1(int);
|
||||
|
211
config.h
211
config.h
@ -83,7 +83,7 @@
|
||||
/* #undef BSD_AUTH */
|
||||
|
||||
/* Define if you want to specify the path to your lastlog file */
|
||||
/* #undef CONF_LASTLOG_FILE */
|
||||
#define CONF_LASTLOG_FILE "/var/log/lastlog"
|
||||
|
||||
/* Define if you want to specify the path to your utmp file */
|
||||
#define CONF_UTMP_FILE "/var/run/utmp"
|
||||
@ -1540,107 +1540,108 @@
|
||||
|
||||
/* type to use in place of socklen_t if not defined */
|
||||
/* #undef socklen_t */
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#define _CRT_SECURE_NO_DEPRECATE 1
|
||||
#define _CRT_NONSTDC_NO_DEPRECATE 1
|
||||
#define WIN32_FIXME 1
|
||||
#undef USE_NTCREATETOKEN
|
||||
|
||||
/* Define if you must implement a startup_needs function for your platform */
|
||||
#define HAVE_STARTUP_NEEDS 1
|
||||
|
||||
/* Define if your platform uses Winsock instead of BSD sockets (yeah, there are a lot of platforms like this :) */
|
||||
#define HAVE_WINSOCK 1
|
||||
|
||||
#define snprintf _snprintf
|
||||
|
||||
#define BROKEN_READV_COMPARISON
|
||||
|
||||
/* Override detection of some headers and functions on MinGW */
|
||||
#undef BROKEN_SNPRINTF
|
||||
#define GETPGRP_VOID 1
|
||||
#undef HAVE_CRYPT_H
|
||||
#define HAVE_DAEMON 1
|
||||
#undef HAVE_ENDIAN_H
|
||||
#undef HAVE_FCNTL_H
|
||||
#define HAVE_FREEADDRINFO 1
|
||||
#define HAVE_GAI_STRERROR 1
|
||||
#define HAVE_GETADDRINFO 1
|
||||
#define HAVE_GETGROUPLIST 1
|
||||
#define HAVE_GETNAMEINFO 1
|
||||
#undef HAVE_ID_IN_UTMPX
|
||||
#define HAVE_INET_ATON 1
|
||||
#define HAVE_INET_NTOA 1
|
||||
#define HAVE_INNETGR 1
|
||||
#undef HAVE_LIBCRYPT
|
||||
#define HAVE_MKDTEMP 1
|
||||
#define HAVE_NANOSLEEP 1
|
||||
#undef HAVE_PATHS_H
|
||||
#undef HAVE_POLL_H
|
||||
#undef HAVE_PROC_PID
|
||||
#undef HAVE_PTY_H
|
||||
#define HAVE_NANOSLEEP 1
|
||||
#define HAVE_READPASSPHRASE 1
|
||||
#define HAVE_REALPATH 1
|
||||
#undef HAVE_SIG_ATOMIC_T
|
||||
#define HAVE_SIZE_T 1
|
||||
#undef HAVE_STRERROR
|
||||
#define HAVE_STRMODE 1
|
||||
#undef __USE_W32_SOCKETS
|
||||
|
||||
#ifdef __MINGW32__ /* FIXME: Use autoconf to set this correctly */
|
||||
/* Define to 1 if you have the `strcasecmp' function. */
|
||||
#define HAVE_STRCASECMP 1
|
||||
|
||||
/* Define to 1 if you have the `strncasecmp' function. */
|
||||
#define HAVE_STRNCASECMP 1
|
||||
#endif
|
||||
|
||||
#define HAVE_STRUCT_IN6_ADDR 1
|
||||
#define HAVE_STRUCT_SOCKADDR_IN6 1
|
||||
#define HAVE_STRUCT_TIMEVAL 1
|
||||
#undef HAVE_SYS_CDEFS_H
|
||||
#undef HAVE_SYS_SYSMACROS_H
|
||||
#undef HAVE_SYS_MMAN_H
|
||||
#undef HAVE_SYS_UN_H
|
||||
|
||||
#define HAVE_TCGETPGRP 1
|
||||
|
||||
#undef HAVE_TIME
|
||||
|
||||
#define HAVE_TRUNCATE 1
|
||||
|
||||
#define HAVE_VIS_H 1
|
||||
|
||||
#define MISSING_FD_MASK 1
|
||||
#define MISSING_HOWMANY 1
|
||||
#define MISSING_NFDBITS 1
|
||||
|
||||
#undef SSH_PRIVSEP_USER
|
||||
|
||||
#define HAVE_OPENPTY 1
|
||||
|
||||
/* Fixes for loginrec.c */
|
||||
#undef CONF_UTMP_FILE
|
||||
#undef CONF_WTMPX_FILE
|
||||
#undef CONF_WTMP_FILE
|
||||
#undef CONF_UTMPX_FILE
|
||||
#undef CONF_LASTLOG_FILE
|
||||
|
||||
#define BROKEN_SYS_TERMIO_H
|
||||
|
||||
#define strerror strerror_win32
|
||||
|
||||
#define strerror strerror_win32
|
||||
|
||||
// PRAGMA SYS PORT
|
||||
#define WITH_OPENSSL 1
|
||||
#define HAVE_KRB5_GET_ERROR_MESSAGE 1
|
||||
#define HAVE_KRB5_FREE_ERROR_MESSAGE 1
|
||||
#define HAVE_DECL_NFDBITS 0
|
||||
#define HAVE_DECL_HOWMANY 0
|
||||
|
||||
#define WIN32_ZLIB_NO 1
|
||||
|
||||
//#define HAVE_ARC4RANDOM_UNIFORM 1
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#define _CRT_SECURE_NO_DEPRECATE 1
|
||||
#define _CRT_NONSTDC_NO_DEPRECATE 1
|
||||
#define WIN32_FIXME 1
|
||||
#undef USE_NTCREATETOKEN
|
||||
|
||||
/* Define if you must implement a startup_needs function for your platform */
|
||||
#define HAVE_STARTUP_NEEDS 1
|
||||
|
||||
/* Define if your platform uses Winsock instead of BSD sockets (yeah, there are a lot of platforms like this :) */
|
||||
#define HAVE_WINSOCK 1
|
||||
|
||||
#define snprintf _snprintf
|
||||
|
||||
#define BROKEN_READV_COMPARISON
|
||||
|
||||
/* Override detection of some headers and functions on MinGW */
|
||||
#undef BROKEN_SNPRINTF
|
||||
#define GETPGRP_VOID 1
|
||||
#undef HAVE_CRYPT_H
|
||||
#define HAVE_DAEMON 1
|
||||
#undef HAVE_ENDIAN_H
|
||||
#undef HAVE_FCNTL_H
|
||||
#define HAVE_FREEADDRINFO 1
|
||||
#define HAVE_GAI_STRERROR 1
|
||||
#define HAVE_GETADDRINFO 1
|
||||
#define HAVE_GETGROUPLIST 1
|
||||
#define HAVE_GETNAMEINFO 1
|
||||
#undef HAVE_ID_IN_UTMPX
|
||||
#define HAVE_INET_ATON 1
|
||||
#define HAVE_INET_NTOA 1
|
||||
#define HAVE_INNETGR 1
|
||||
#undef HAVE_LIBCRYPT
|
||||
#define HAVE_MKDTEMP 1
|
||||
#define HAVE_NANOSLEEP 1
|
||||
#undef HAVE_PATHS_H
|
||||
#undef HAVE_POLL_H
|
||||
#undef HAVE_PROC_PID
|
||||
#undef HAVE_PTY_H
|
||||
#define HAVE_NANOSLEEP 1
|
||||
#define HAVE_READPASSPHRASE 1
|
||||
#define HAVE_REALPATH 1
|
||||
#undef HAVE_SIG_ATOMIC_T
|
||||
#define HAVE_SIZE_T 1
|
||||
#undef HAVE_STRERROR
|
||||
#define HAVE_STRMODE 1
|
||||
#undef __USE_W32_SOCKETS
|
||||
|
||||
#ifdef __MINGW32__ /* FIXME: Use autoconf to set this correctly */
|
||||
/* Define to 1 if you have the `strcasecmp' function. */
|
||||
#define HAVE_STRCASECMP 1
|
||||
|
||||
/* Define to 1 if you have the `strncasecmp' function. */
|
||||
#define HAVE_STRNCASECMP 1
|
||||
#endif
|
||||
|
||||
#define HAVE_STRUCT_IN6_ADDR 1
|
||||
#define HAVE_STRUCT_SOCKADDR_IN6 1
|
||||
#define HAVE_STRUCT_TIMEVAL 1
|
||||
#undef HAVE_SYS_CDEFS_H
|
||||
#undef HAVE_SYS_SYSMACROS_H
|
||||
#undef HAVE_SYS_MMAN_H
|
||||
#undef HAVE_SYS_UN_H
|
||||
|
||||
#define HAVE_TCGETPGRP 1
|
||||
|
||||
#undef HAVE_TIME
|
||||
|
||||
#define HAVE_TRUNCATE 1
|
||||
|
||||
#define HAVE_VIS_H 1
|
||||
|
||||
#define MISSING_FD_MASK 1
|
||||
#define MISSING_HOWMANY 1
|
||||
#define MISSING_NFDBITS 1
|
||||
|
||||
#undef SSH_PRIVSEP_USER
|
||||
|
||||
#define HAVE_OPENPTY 1
|
||||
|
||||
/* Fixes for loginrec.c */
|
||||
#undef CONF_UTMP_FILE
|
||||
#undef CONF_WTMPX_FILE
|
||||
#undef CONF_WTMP_FILE
|
||||
#undef CONF_UTMPX_FILE
|
||||
#undef CONF_LASTLOG_FILE
|
||||
|
||||
#define BROKEN_SYS_TERMIO_H
|
||||
|
||||
#define strerror strerror_win32
|
||||
|
||||
#define strerror strerror_win32
|
||||
|
||||
// PRAGMA SYS PORT
|
||||
#define WITH_OPENSSL 1
|
||||
#define HAVE_KRB5_GET_ERROR_MESSAGE 1
|
||||
#define HAVE_KRB5_FREE_ERROR_MESSAGE 1
|
||||
#define HAVE_DECL_NFDBITS 0
|
||||
#define HAVE_DECL_HOWMANY 0
|
||||
|
||||
#define WIN32_ZLIB_NO 1
|
||||
#define USE_MSCNG 1
|
||||
|
||||
//#define HAVE_ARC4RANDOM_UNIFORM 1
|
||||
|
||||
|
@ -99,6 +99,7 @@
|
||||
#define HAVE_DECL_HOWMANY 0
|
||||
|
||||
#define WIN32_ZLIB_NO 1
|
||||
#define USE_MSCNG 1
|
||||
|
||||
//#define HAVE_ARC4RANDOM_UNIFORM 1
|
||||
|
||||
|
@ -8,25 +8,32 @@ top_srcdir=@top_srcdir@
|
||||
VPATH=@srcdir@
|
||||
CC=@CC@
|
||||
LD=@LD@
|
||||
CFLAGS=@CFLAGS@
|
||||
CPPFLAGS=-I. -I../../.. -I$(srcdir) -I$(top_srcdir) -I$(srcdir)/includes @CPPFLAGS@ @DEFS@
|
||||
LIBS=@LIBS@
|
||||
BCRYPTFLAGS=-I/usr/include/w32api
|
||||
CFLAGS=@CFLAGS@
|
||||
CPPFLAGS=-I. -I../../.. -I$(srcdir) -I$(top_srcdir) -I$(srcdir)/includes @CPPFLAGS@ @DEFS@ -DUSE_MSCNG
|
||||
LIBS=@LIBS@ -lbcrypt
|
||||
AR=@AR@
|
||||
RANLIB=@RANLIB@
|
||||
INSTALL=@INSTALL@
|
||||
LDFLAGS=-L. @LDFLAGS@
|
||||
LDFLAGS=-L. @LDFLAGS@ -L/lib/win32api
|
||||
|
||||
WIN32COMPATFILES = daemon.o gettimeofday.o homedirhelp.o pwd.o sfds.o \
|
||||
socket.o startupneeds.o strcasecmp.o syslog.o lsalogon.o lsastring.o \
|
||||
stringhelp.o deskright.o win32auth.o kerberos.o ansiprsr.o console.o tnnet.o
|
||||
stringhelp.o deskright.o win32auth.o kerberos.o cng_cipher.o ansiprsr.o console.o tnnet.o
|
||||
|
||||
WIN32COMPATLIB=@LIBWIN32COMPAT@
|
||||
|
||||
CNGFILES=cng_cipher.o
|
||||
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
|
||||
|
||||
all: $(WIN32COMPATLIB)
|
||||
|
||||
$(CNGFILES): %.o: %.c
|
||||
$(CC) $(CFLAGS) $(BCRYPTFLAGS) $(CPPFLAGS) -c $<
|
||||
|
||||
install:
|
||||
|
||||
clean:
|
||||
|
298
contrib/win32/win32compat/cng_cipher.c
Normal file
298
contrib/win32/win32compat/cng_cipher.c
Normal file
@ -0,0 +1,298 @@
|
||||
/* cng_cipher.c
|
||||
* Author: Pragma Systems, Inc. <www.pragmasys.com>
|
||||
* Contribution by Pragma Systems, Inc. for Microsoft openssh win32 port
|
||||
* Copyright (c) 2011, 2015 Pragma Systems, Inc.
|
||||
* All rights reserved
|
||||
*
|
||||
* Common library for Windows Console Screen IO.
|
||||
* Contains Windows console related definition so that emulation code can draw
|
||||
* on Windows console screen surface.
|
||||
*
|
||||
* 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.
|
||||
* 2. Binaries produced provide no direct or implied warranties or any
|
||||
* guarantee of performance or suitability.
|
||||
*/
|
||||
|
||||
#include <Windows.h>
|
||||
#include <bcrypt.h>
|
||||
|
||||
#include "cng_cipher.h"
|
||||
|
||||
#ifdef USE_MSCNG
|
||||
|
||||
|
||||
#define AES_BLOCK_SIZE 16
|
||||
|
||||
|
||||
/*
|
||||
* increment the aes counter (iv)
|
||||
*/
|
||||
static void aesctr_inc(unsigned char *ctr, unsigned int len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
#ifndef CONSTANT_TIME_INCREMENT
|
||||
for (i = len - 1; i >= 0; i--)
|
||||
if (++ctr[i]) /* continue on overflow */
|
||||
return;
|
||||
#else
|
||||
u8 x, add = 1;
|
||||
|
||||
for (i = len - 1; i >= 0; i--) {
|
||||
ctr[i] += add;
|
||||
/* constant time for: x = ctr[i] ? 1 : 0 */
|
||||
x = ctr[i];
|
||||
x = (x | (x >> 4)) & 0xf;
|
||||
x = (x | (x >> 2)) & 0x3;
|
||||
x = (x | (x >> 1)) & 0x1;
|
||||
add *= (x ^ 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Routine to encrypt a counter for ctr encryption. This requries
|
||||
* us to use an IV that is reset for each call to avoid cng attempting
|
||||
* to chain encryptions.
|
||||
*/
|
||||
DWORD cng_counter_encrypt(const unsigned char *in, unsigned char *out, BCRYPT_KEY_HANDLE key, unsigned int blocklen)
|
||||
{
|
||||
HRESULT status = S_OK;
|
||||
DWORD cbResult = 0;
|
||||
|
||||
unsigned char iv[AES_BLOCK_SIZE] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
status = BCryptEncrypt(
|
||||
key,
|
||||
(PUCHAR)in,
|
||||
blocklen,
|
||||
NULL,
|
||||
iv,
|
||||
blocklen,
|
||||
out,
|
||||
blocklen,
|
||||
&cbResult,
|
||||
0);
|
||||
|
||||
return cbResult;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encrypt/Decrypt data using a CTR mode.
|
||||
* In this mode, we can't call CNG encryption/decription directly. The mode requires
|
||||
* the use of the iv as a counter that is incremented and encrypted. The
|
||||
* encrypted counter is then XORd with the data to produce the cipher text.
|
||||
*/
|
||||
int cng_aesctr_encrypt_bytes(PSSH_CNG_CIPHER_CTX x, const unsigned char *m, unsigned char *c, unsigned int bytes)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned int n = 0;
|
||||
unsigned char buf[AES_BLOCK_SIZE];
|
||||
|
||||
while ((bytes--) > 0) {
|
||||
if (n == 0) {
|
||||
if (!cng_counter_encrypt(x->pbIV, buf, x->hKey, AES_BLOCK_SIZE))
|
||||
{
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
aesctr_inc(x->pbIV, AES_BLOCK_SIZE);
|
||||
}
|
||||
*(c++) = *(m++) ^ buf[n];
|
||||
n = (n + 1) % AES_BLOCK_SIZE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Encrypt data using a provided cipher context
|
||||
*/
|
||||
unsigned int cng_cipher_encrypt(PSSH_CNG_CIPHER_CTX x, unsigned char *dest, unsigned int dest_len, const unsigned char *src, unsigned int len)
|
||||
{
|
||||
DWORD cbResult = 0;
|
||||
HRESULT status = S_OK;
|
||||
|
||||
if (x->flags & _CNG_MODE_CTR)
|
||||
{
|
||||
if (-1 == cng_aesctr_encrypt_bytes(x, src, dest, len))
|
||||
{
|
||||
status = GetLastError();
|
||||
}
|
||||
cbResult = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
status = BCryptEncrypt(
|
||||
x->hKey,
|
||||
(PUCHAR)src,
|
||||
len,
|
||||
NULL,
|
||||
x->pbIV,
|
||||
x->cbBlockSize,
|
||||
dest,
|
||||
dest_len,
|
||||
&cbResult,
|
||||
0);
|
||||
if (S_OK != status)
|
||||
{
|
||||
cbResult = 0;
|
||||
SetLastError(status);
|
||||
}
|
||||
}
|
||||
return cbResult;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decrypt encrypted data using a provided cipher context
|
||||
*/
|
||||
unsigned int cng_cipher_decrypt(PSSH_CNG_CIPHER_CTX x, unsigned char *dest, unsigned int dest_len, const unsigned char *src, unsigned int len)
|
||||
{
|
||||
DWORD cbResult = 0;
|
||||
HRESULT status = S_OK;
|
||||
|
||||
if (x->flags & _CNG_MODE_CTR)
|
||||
{
|
||||
// ctr mode is just an XOR so encrypt=decrypt
|
||||
if (-1 == cng_aesctr_encrypt_bytes(x, src, dest, len))
|
||||
{
|
||||
status = GetLastError();
|
||||
}
|
||||
cbResult = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
status = BCryptDecrypt(
|
||||
x->hKey,
|
||||
(PUCHAR)src,
|
||||
len,
|
||||
NULL,
|
||||
x->pbIV,
|
||||
x->cbBlockSize,
|
||||
dest,
|
||||
dest_len,
|
||||
&cbResult,
|
||||
0);
|
||||
if (S_OK != status)
|
||||
{
|
||||
cbResult = 0;
|
||||
SetLastError(status);
|
||||
}
|
||||
}
|
||||
return cbResult;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize cipher context
|
||||
*/
|
||||
unsigned int cng_cipher_init(PSSH_CNG_CIPHER_CTX x, const unsigned char *key, unsigned int keylen, const unsigned char *iv, size_t ivlen, unsigned int flags)
|
||||
{
|
||||
HRESULT status = S_OK;
|
||||
BCRYPT_ALG_HANDLE hAlg = NULL;
|
||||
DWORD cbData = 0;
|
||||
LPCWSTR pAlg = NULL;
|
||||
DWORD cbBlockLen = 0;
|
||||
|
||||
if ((0 == (flags & _CNG_CIPHER_AES)) || (0 == (flags & (_CNG_MODE_CBC | _CNG_MODE_CTR))))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
|
||||
|
||||
// wipe out old context
|
||||
memset(x, 0, sizeof(SSH_CNG_CIPHER_CTX));
|
||||
|
||||
|
||||
// initialize simple context fields
|
||||
x->flags = flags;
|
||||
|
||||
// only one cipher supported right now
|
||||
if (flags & _CNG_CIPHER_AES)
|
||||
pAlg = BCRYPT_AES_ALGORITHM;
|
||||
|
||||
|
||||
// Generate BCrypt Key and set mode if applicable
|
||||
if (NT_SUCCESS(status = BCryptOpenAlgorithmProvider(
|
||||
&hAlg,
|
||||
pAlg,
|
||||
NULL,
|
||||
0)))
|
||||
{
|
||||
|
||||
if (NT_SUCCESS(status = BCryptGetProperty(
|
||||
hAlg,
|
||||
BCRYPT_BLOCK_LENGTH,
|
||||
(PBYTE)&cbBlockLen,
|
||||
sizeof(DWORD),
|
||||
&cbData,
|
||||
0)))
|
||||
{
|
||||
x->cbBlockSize = cbBlockLen;
|
||||
if (cbBlockLen != ivlen)
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
else
|
||||
{
|
||||
x->pbIV = (PBYTE)HeapAlloc(GetProcessHeap(), 0, ivlen);
|
||||
if (NULL == x->pbIV)
|
||||
{
|
||||
status = GetLastError();
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(x->pbIV, iv, ivlen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (status == S_OK && flags & _CNG_MODE_CBC)
|
||||
{
|
||||
status = BCryptSetProperty(
|
||||
hAlg,
|
||||
BCRYPT_CHAINING_MODE,
|
||||
(PBYTE)BCRYPT_CHAIN_MODE_CBC,
|
||||
sizeof(BCRYPT_CHAIN_MODE_CBC),
|
||||
0);
|
||||
}
|
||||
|
||||
if (status == S_OK)
|
||||
{
|
||||
status = BCryptGenerateSymmetricKey(
|
||||
hAlg,
|
||||
&(x->hKey),
|
||||
NULL,
|
||||
0,
|
||||
(PBYTE)key,
|
||||
keylen,
|
||||
0);
|
||||
}
|
||||
BCryptCloseAlgorithmProvider(hAlg, 0);
|
||||
|
||||
// if we got an error along the way, free up the iv
|
||||
if (status != S_OK && x->pbIV)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, x->pbIV);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
/*
|
||||
* Cleanup cipher context fields
|
||||
*/
|
||||
void cng_cipher_cleanup(PSSH_CNG_CIPHER_CTX x)
|
||||
{
|
||||
if (x->pbIV)
|
||||
HeapFree(GetProcessHeap(), 0, x->pbIV);
|
||||
if (x->hKey)
|
||||
BCryptDestroyKey(x->hKey);
|
||||
}
|
||||
|
||||
#endif
|
64
contrib/win32/win32compat/cng_cipher.h
Normal file
64
contrib/win32/win32compat/cng_cipher.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* cng_cipher.h
|
||||
* Author: Pragma Systems, Inc. <www.pragmasys.com>
|
||||
* Contribution by Pragma Systems, Inc. for Microsoft openssh win32 port
|
||||
* Copyright (c) 2011, 2015 Pragma Systems, Inc.
|
||||
* All rights reserved
|
||||
*
|
||||
* Common library for Windows Console Screen IO.
|
||||
* Contains Windows console related definition so that emulation code can draw
|
||||
* on Windows console screen surface.
|
||||
*
|
||||
* 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.
|
||||
* 2. Binaries produced provide no direct or implied warranties or any
|
||||
* guarantee of performance or suitability.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CNG_CIPHER_H
|
||||
#define CNG_CIPHER_H
|
||||
|
||||
#ifdef USE_MSCNG
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
|
||||
|
||||
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
|
||||
|
||||
/* CIPHER/MODE bits specify cipher and mode in the flags
|
||||
* field of the context
|
||||
*/
|
||||
#define _CNG_CIPHER_AES 0x00000001
|
||||
#define _CNG_MODE_CTR 0x00010000
|
||||
#define _CNG_MODE_CBC 0x00020000
|
||||
|
||||
#define _CNG_CIPHER_MASK 0x0000FFFF
|
||||
#define _CNG_MODE_MASK 0xFFFF0000
|
||||
|
||||
typedef struct ssh_cng_cipher_ctx
|
||||
{
|
||||
void * hKey;
|
||||
unsigned char * pbIV;
|
||||
unsigned int cbBlockSize;
|
||||
unsigned int flags;
|
||||
} SSH_CNG_CIPHER_CTX, *PSSH_CNG_CIPHER_CTX;
|
||||
|
||||
|
||||
unsigned int cng_cipher_encrypt(PSSH_CNG_CIPHER_CTX x, unsigned char *dest, unsigned int dest_len, const unsigned char *src, unsigned int len);
|
||||
unsigned int cng_cipher_decrypt(PSSH_CNG_CIPHER_CTX x, unsigned char *dest, unsigned int dest_len, const unsigned char *src, unsigned int len);
|
||||
unsigned int cng_cipher_init(PSSH_CNG_CIPHER_CTX x, const unsigned char *key, unsigned int keylen, const unsigned char *iv, size_t ivlen, unsigned int flags);
|
||||
void cng_cipher_cleanup(PSSH_CNG_CIPHER_CTX x);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
1
contrib/win32/win32compat/libwin32compat.q
Normal file
1
contrib/win32/win32compat/libwin32compat.q
Normal file
@ -0,0 +1 @@
|
||||
!<arch>
|
50
contrib/win32/win32compat/makefile.save
Normal file
50
contrib/win32/win32compat/makefile.save
Normal file
@ -0,0 +1,50 @@
|
||||
# $Id $
|
||||
|
||||
sysconfdir=${prefix}/etc
|
||||
piddir=/var/run
|
||||
srcdir=.
|
||||
top_srcdir=../../..
|
||||
|
||||
|
||||
CC=i686-pc-mingw32-gcc
|
||||
LD=i686-pc-mingw32-gcc
|
||||
CFLAGS=-g -O2 -Wall -Wpointer-arith -Wuninitialized -Wsign-compare -Wformat-security -Wno-pointer-sign -Wno-unused-result -fno-strict-aliasing -fno-builtin-memset -I/cygdrive/c/openssh/Win32-OpenSSH/contrib/win32/win32compat/includes -I/cygdrive/c/openssh/Win32-OpenSSH/openbsd-compat -I/cygdrive/c/openssh/Win32-OpenSSH/contrib/win32/win32compat/includes -I/cygdrive/c/openssh/Win32-OpenSSH/libkrb -I/usr/local
|
||||
BCRYPTFLAGS=-I/usr/include/w32api
|
||||
CPPFLAGS=-I. -I../../.. -I$(srcdir) -I$(top_srcdir) -I$(srcdir)/includes -I/cygdrive/c/openssh/Win32-OpenSSH/../openssl-1.0.2d/include -DHAVE_CONFIG_H -DUSE_MSCNG
|
||||
LIBS=-lcrypto -lz -lws2_32 -lgdi32 -lNetAPI32 -luserenv -lsecur32 -lshlwapi -lbcrypt
|
||||
AR=/usr/bin/ar
|
||||
RANLIB=i686-pc-mingw32-ranlib
|
||||
INSTALL=/usr/bin/install -c
|
||||
LDFLAGS=-L. -L/cygdrive/c/openssh/Win32-OpenSSH/../openssl-1.0.2d -L/lib/win32api
|
||||
|
||||
WIN32COMPATFILES = daemon.o gettimeofday.o homedirhelp.o pwd.o sfds.o \
|
||||
socket.o startupneeds.o strcasecmp.o syslog.o lsalogon.o lsastring.o \
|
||||
stringhelp.o deskright.o win32auth.o kerberos.o cng_cipher.o ansiprsr.o console.o tnnet.o
|
||||
|
||||
WIN32COMPATLIB=libwin32compat.a
|
||||
|
||||
CNGFILES=cng_cipher.o
|
||||
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
|
||||
|
||||
all: $(WIN32COMPATLIB)
|
||||
|
||||
|
||||
$(CNGFILES): %.o: %.c
|
||||
$(CC) $(CFLAGS) $(BCRYPTFLAGS) $(CPPFLAGS) -c $<
|
||||
|
||||
install:
|
||||
|
||||
clean:
|
||||
rm -f *.o *.a core
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile *~
|
||||
|
||||
$(WIN32COMPATFILES): ../../../config.h
|
||||
|
||||
$(WIN32COMPATLIB): $(WIN32COMPATFILES)
|
||||
$(AR) rv $@ $(WIN32COMPATFILES)
|
||||
$(RANLIB) $@
|
@ -8,12 +8,12 @@ top_srcdir=../..
|
||||
|
||||
CC=i686-pc-mingw32-gcc
|
||||
LD=i686-pc-mingw32-gcc
|
||||
CFLAGS=-g -O2 -Wall -Wpointer-arith -Wuninitialized -Wsign-compare -Wformat-security -Wno-pointer-sign -Wno-unused-result -fno-strict-aliasing -fno-builtin-memset -fstack-protector-all -I/cygdrive/c/openssh/Win32-OpenSSH/contrib/win32/win32compat/includes -I/cygdrive/c/openssh/Win32-OpenSSH/openbsd-compat -I/cygdrive/c/openssh/Win32-OpenSSH/contrib/win32/win32compat/includes -I/cygdrive/c/openssh/Win32-OpenSSH/libkrb -I/usr/local
|
||||
CPPFLAGS=-I. -I.. -I$(srcdir) -I$(srcdir)/.. -I/cygdrive/c/openssh/openssl-1.0.2d/include -I/cygdrive/c/openssh/zlib-1.2.8 -DHAVE_CONFIG_H
|
||||
CFLAGS=-g -O2 -Wall -Wpointer-arith -Wuninitialized -Wsign-compare -Wformat-security -Wno-pointer-sign -Wno-unused-result -fno-strict-aliasing -fno-builtin-memset -I/cygdrive/c/openssh/Win32-OpenSSH/contrib/win32/win32compat/includes -I/cygdrive/c/openssh/Win32-OpenSSH/openbsd-compat -I/cygdrive/c/openssh/Win32-OpenSSH/contrib/win32/win32compat/includes -I/cygdrive/c/openssh/Win32-OpenSSH/libkrb -I/usr/local
|
||||
CPPFLAGS=-I. -I.. -I$(srcdir) -I$(srcdir)/.. -I/cygdrive/c/openssh/Win32-OpenSSH/../openssl-1.0.2d/include -DHAVE_CONFIG_H
|
||||
EXEEXT=.exe
|
||||
LIBCOMPAT=../libopenbsd-compat.a
|
||||
LIBS=-lcrypto -lz -lws2_32 -lgdi32 -lNetAPI32 -luserenv -lsecur32 -lshlwapi
|
||||
LDFLAGS=-L/cygdrive/c/openssh/openssl-1.0.2d -L/cygdrive/c/openssh/zlib-1.2.8 -fstack-protector-all $(LIBCOMPAT)
|
||||
LDFLAGS=-L/cygdrive/c/openssh/Win32-OpenSSH/../openssl-1.0.2d $(LIBCOMPAT)
|
||||
|
||||
TESTPROGS=closefromtest$(EXEEXT) snprintftest$(EXEEXT) strduptest$(EXEEXT) \
|
||||
strtonumtest$(EXEEXT) opensslvertest$(EXEEXT)
|
||||
|
Loading…
x
Reference in New Issue
Block a user