summaryrefslogtreecommitdiff
path: root/libs/libssh2/src/wincng.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libssh2/src/wincng.c')
-rw-r--r--libs/libssh2/src/wincng.c2168
1 files changed, 0 insertions, 2168 deletions
diff --git a/libs/libssh2/src/wincng.c b/libs/libssh2/src/wincng.c
deleted file mode 100644
index 4bebc6407a..0000000000
--- a/libs/libssh2/src/wincng.c
+++ /dev/null
@@ -1,2168 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Marc Hoersken <info@marc-hoersken.de>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms,
- * with or without modification, are permitted provided
- * that the following conditions are met:
- *
- * Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the
- * following disclaimer.
- *
- * 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.
- *
- * Neither the name of the copyright holder nor the names
- * of any other contributors may be used to endorse or
- * promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "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 COPYRIGHT OWNER OR
- * CONTRIBUTORS 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.
- */
-
-#include "libssh2_priv.h"
-
-#ifdef LIBSSH2_WINCNG /* compile only if we build with wincng */
-
-/* required for cross-compilation against the w64 mingw-runtime package */
-#if defined(_WIN32_WINNT) && (_WIN32_WINNT < 0x0600)
-#undef _WIN32_WINNT
-#endif
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x0600
-#endif
-
-/* specify the required libraries for dependencies using MSVC */
-#ifdef _MSC_VER
-#pragma comment(lib, "bcrypt.lib")
-#ifdef HAVE_LIBCRYPT32
-#pragma comment(lib, "crypt32.lib")
-#endif
-#endif
-
-#include <windows.h>
-#include <bcrypt.h>
-#include <math.h>
-#include "misc.h"
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_LIBCRYPT32
-#include <wincrypt.h>
-#endif
-
-#define PEM_RSA_HEADER "-----BEGIN RSA PRIVATE KEY-----"
-#define PEM_RSA_FOOTER "-----END RSA PRIVATE KEY-----"
-#define PEM_DSA_HEADER "-----BEGIN DSA PRIVATE KEY-----"
-#define PEM_DSA_FOOTER "-----END DSA PRIVATE KEY-----"
-
-
-/*******************************************************************/
-/*
- * Windows CNG backend: Missing definitions (for MinGW[-w64])
- */
-#ifndef BCRYPT_SUCCESS
-#define BCRYPT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
-#endif
-
-#ifndef BCRYPT_RNG_ALGORITHM
-#define BCRYPT_RNG_ALGORITHM L"RNG"
-#endif
-
-#ifndef BCRYPT_MD5_ALGORITHM
-#define BCRYPT_MD5_ALGORITHM L"MD5"
-#endif
-
-#ifndef BCRYPT_SHA1_ALGORITHM
-#define BCRYPT_SHA1_ALGORITHM L"SHA1"
-#endif
-
-#ifndef BCRYPT_SHA256_ALGORITHM
-#define BCRYPT_SHA256_ALGORITHM L"SHA256"
-#endif
-
-#ifndef BCRYPT_SHA512_ALGORITHM
-#define BCRYPT_SHA512_ALGORITHM L"SHA512"
-#endif
-
-#ifndef BCRYPT_RSA_ALGORITHM
-#define BCRYPT_RSA_ALGORITHM L"RSA"
-#endif
-
-#ifndef BCRYPT_DSA_ALGORITHM
-#define BCRYPT_DSA_ALGORITHM L"DSA"
-#endif
-
-#ifndef BCRYPT_AES_ALGORITHM
-#define BCRYPT_AES_ALGORITHM L"AES"
-#endif
-
-#ifndef BCRYPT_RC4_ALGORITHM
-#define BCRYPT_RC4_ALGORITHM L"RC4"
-#endif
-
-#ifndef BCRYPT_3DES_ALGORITHM
-#define BCRYPT_3DES_ALGORITHM L"3DES"
-#endif
-
-#ifndef BCRYPT_ALG_HANDLE_HMAC_FLAG
-#define BCRYPT_ALG_HANDLE_HMAC_FLAG 0x00000008
-#endif
-
-#ifndef BCRYPT_DSA_PUBLIC_BLOB
-#define BCRYPT_DSA_PUBLIC_BLOB L"DSAPUBLICBLOB"
-#endif
-
-#ifndef BCRYPT_DSA_PUBLIC_MAGIC
-#define BCRYPT_DSA_PUBLIC_MAGIC 0x42505344 /* DSPB */
-#endif
-
-#ifndef BCRYPT_DSA_PRIVATE_BLOB
-#define BCRYPT_DSA_PRIVATE_BLOB L"DSAPRIVATEBLOB"
-#endif
-
-#ifndef BCRYPT_DSA_PRIVATE_MAGIC
-#define BCRYPT_DSA_PRIVATE_MAGIC 0x56505344 /* DSPV */
-#endif
-
-#ifndef BCRYPT_RSAPUBLIC_BLOB
-#define BCRYPT_RSAPUBLIC_BLOB L"RSAPUBLICBLOB"
-#endif
-
-#ifndef BCRYPT_RSAPUBLIC_MAGIC
-#define BCRYPT_RSAPUBLIC_MAGIC 0x31415352 /* RSA1 */
-#endif
-
-#ifndef BCRYPT_RSAFULLPRIVATE_BLOB
-#define BCRYPT_RSAFULLPRIVATE_BLOB L"RSAFULLPRIVATEBLOB"
-#endif
-
-#ifndef BCRYPT_RSAFULLPRIVATE_MAGIC
-#define BCRYPT_RSAFULLPRIVATE_MAGIC 0x33415352 /* RSA3 */
-#endif
-
-#ifndef BCRYPT_KEY_DATA_BLOB
-#define BCRYPT_KEY_DATA_BLOB L"KeyDataBlob"
-#endif
-
-#ifndef BCRYPT_MESSAGE_BLOCK_LENGTH
-#define BCRYPT_MESSAGE_BLOCK_LENGTH L"MessageBlockLength"
-#endif
-
-#ifndef BCRYPT_NO_KEY_VALIDATION
-#define BCRYPT_NO_KEY_VALIDATION 0x00000008
-#endif
-
-#ifndef BCRYPT_BLOCK_PADDING
-#define BCRYPT_BLOCK_PADDING 0x00000001
-#endif
-
-#ifndef BCRYPT_PAD_NONE
-#define BCRYPT_PAD_NONE 0x00000001
-#endif
-
-#ifndef BCRYPT_PAD_PKCS1
-#define BCRYPT_PAD_PKCS1 0x00000002
-#endif
-
-#ifndef BCRYPT_PAD_OAEP
-#define BCRYPT_PAD_OAEP 0x00000004
-#endif
-
-#ifndef BCRYPT_PAD_PSS
-#define BCRYPT_PAD_PSS 0x00000008
-#endif
-
-#ifndef CRYPT_STRING_ANY
-#define CRYPT_STRING_ANY 0x00000007
-#endif
-
-#ifndef LEGACY_RSAPRIVATE_BLOB
-#define LEGACY_RSAPRIVATE_BLOB L"CAPIPRIVATEBLOB"
-#endif
-
-#ifndef PKCS_RSA_PRIVATE_KEY
-#define PKCS_RSA_PRIVATE_KEY (LPCSTR)43
-#endif
-
-
-/*******************************************************************/
-/*
- * Windows CNG backend: Generic functions
- */
-
-void
-_libssh2_wincng_init(void)
-{
- int ret;
-
- (void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgRNG,
- BCRYPT_RNG_ALGORITHM, NULL, 0);
-
- (void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashMD5,
- BCRYPT_MD5_ALGORITHM, NULL, 0);
- (void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashSHA1,
- BCRYPT_SHA1_ALGORITHM, NULL, 0);
- (void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashSHA256,
- BCRYPT_SHA256_ALGORITHM, NULL, 0);
- (void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashSHA512,
- BCRYPT_SHA512_ALGORITHM, NULL, 0);
-
- (void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacMD5,
- BCRYPT_MD5_ALGORITHM, NULL,
- BCRYPT_ALG_HANDLE_HMAC_FLAG);
- (void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacSHA1,
- BCRYPT_SHA1_ALGORITHM, NULL,
- BCRYPT_ALG_HANDLE_HMAC_FLAG);
- (void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacSHA256,
- BCRYPT_SHA256_ALGORITHM, NULL,
- BCRYPT_ALG_HANDLE_HMAC_FLAG);
- (void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacSHA512,
- BCRYPT_SHA512_ALGORITHM, NULL,
- BCRYPT_ALG_HANDLE_HMAC_FLAG);
-
- (void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgRSA,
- BCRYPT_RSA_ALGORITHM, NULL, 0);
- (void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgDSA,
- BCRYPT_DSA_ALGORITHM, NULL, 0);
-
- ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgAES_CBC,
- BCRYPT_AES_ALGORITHM, NULL, 0);
- if(BCRYPT_SUCCESS(ret)) {
- ret = BCryptSetProperty(_libssh2_wincng.hAlgAES_CBC,
- BCRYPT_CHAINING_MODE,
- (PBYTE)BCRYPT_CHAIN_MODE_CBC,
- sizeof(BCRYPT_CHAIN_MODE_CBC), 0);
- if(!BCRYPT_SUCCESS(ret)) {
- (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgAES_CBC, 0);
- }
- }
-
- ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgAES_ECB,
- BCRYPT_AES_ALGORITHM, NULL, 0);
- if(BCRYPT_SUCCESS(ret)) {
- ret = BCryptSetProperty(_libssh2_wincng.hAlgAES_ECB,
- BCRYPT_CHAINING_MODE,
- (PBYTE)BCRYPT_CHAIN_MODE_ECB,
- sizeof(BCRYPT_CHAIN_MODE_ECB), 0);
- if(!BCRYPT_SUCCESS(ret)) {
- (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgAES_ECB, 0);
- }
- }
-
- ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgRC4_NA,
- BCRYPT_RC4_ALGORITHM, NULL, 0);
- if(BCRYPT_SUCCESS(ret)) {
- ret = BCryptSetProperty(_libssh2_wincng.hAlgRC4_NA,
- BCRYPT_CHAINING_MODE,
- (PBYTE)BCRYPT_CHAIN_MODE_NA,
- sizeof(BCRYPT_CHAIN_MODE_NA), 0);
- if(!BCRYPT_SUCCESS(ret)) {
- (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRC4_NA, 0);
- }
- }
-
- ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlg3DES_CBC,
- BCRYPT_3DES_ALGORITHM, NULL, 0);
- if(BCRYPT_SUCCESS(ret)) {
- ret = BCryptSetProperty(_libssh2_wincng.hAlg3DES_CBC,
- BCRYPT_CHAINING_MODE,
- (PBYTE)BCRYPT_CHAIN_MODE_CBC,
- sizeof(BCRYPT_CHAIN_MODE_CBC), 0);
- if(!BCRYPT_SUCCESS(ret)) {
- (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlg3DES_CBC,
- 0);
- }
- }
-}
-
-void
-_libssh2_wincng_free(void)
-{
- (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRNG, 0);
- (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashMD5, 0);
- (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA1, 0);
- (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA256, 0);
- (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA512, 0);
- (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacMD5, 0);
- (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacSHA1, 0);
- (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacSHA256, 0);
- (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacSHA512, 0);
- (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRSA, 0);
- (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgDSA, 0);
- (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgAES_CBC, 0);
- (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRC4_NA, 0);
- (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlg3DES_CBC, 0);
-
- memset(&_libssh2_wincng, 0, sizeof(_libssh2_wincng));
-}
-
-int
-_libssh2_wincng_random(void *buf, int len)
-{
- int ret;
-
- ret = BCryptGenRandom(_libssh2_wincng.hAlgRNG, buf, len, 0);
-
- return BCRYPT_SUCCESS(ret) ? 0 : -1;
-}
-
-static void
-_libssh2_wincng_safe_free(void *buf, int len)
-{
-#ifndef LIBSSH2_CLEAR_MEMORY
- (void)len;
-#endif
-
- if(!buf)
- return;
-
-#ifdef LIBSSH2_CLEAR_MEMORY
- if(len > 0)
- SecureZeroMemory(buf, len);
-#endif
-
- free(buf);
-}
-
-
-/*******************************************************************/
-/*
- * Windows CNG backend: Hash functions
- */
-
-int
-_libssh2_wincng_hash_init(_libssh2_wincng_hash_ctx *ctx,
- BCRYPT_ALG_HANDLE hAlg, unsigned long hashlen,
- unsigned char *key, unsigned long keylen)
-{
- BCRYPT_HASH_HANDLE hHash;
- unsigned char *pbHashObject;
- unsigned long dwHashObject, dwHash, cbData;
- int ret;
-
- ret = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH,
- (unsigned char *)&dwHash,
- sizeof(dwHash),
- &cbData, 0);
- if((!BCRYPT_SUCCESS(ret)) || dwHash != hashlen) {
- return -1;
- }
-
- ret = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH,
- (unsigned char *)&dwHashObject,
- sizeof(dwHashObject),
- &cbData, 0);
- if(!BCRYPT_SUCCESS(ret)) {
- return -1;
- }
-
- pbHashObject = malloc(dwHashObject);
- if(!pbHashObject) {
- return -1;
- }
-
-
- ret = BCryptCreateHash(hAlg, &hHash,
- pbHashObject, dwHashObject,
- key, keylen, 0);
- if(!BCRYPT_SUCCESS(ret)) {
- _libssh2_wincng_safe_free(pbHashObject, dwHashObject);
- return -1;
- }
-
-
- ctx->hHash = hHash;
- ctx->pbHashObject = pbHashObject;
- ctx->dwHashObject = dwHashObject;
- ctx->cbHash = dwHash;
-
- return 0;
-}
-
-int
-_libssh2_wincng_hash_update(_libssh2_wincng_hash_ctx *ctx,
- const unsigned char *data, unsigned long datalen)
-{
- int ret;
-
- ret = BCryptHashData(ctx->hHash, (unsigned char *)data, datalen, 0);
-
- return BCRYPT_SUCCESS(ret) ? 0 : -1;
-}
-
-int
-_libssh2_wincng_hash_final(_libssh2_wincng_hash_ctx *ctx,
- unsigned char *hash)
-{
- int ret;
-
- ret = BCryptFinishHash(ctx->hHash, hash, ctx->cbHash, 0);
-
- BCryptDestroyHash(ctx->hHash);
- ctx->hHash = NULL;
-
- _libssh2_wincng_safe_free(ctx->pbHashObject, ctx->dwHashObject);
- ctx->pbHashObject = NULL;
- ctx->dwHashObject = 0;
-
- return BCRYPT_SUCCESS(ret) ? 0 : -1;
-}
-
-int
-_libssh2_wincng_hash(unsigned char *data, unsigned long datalen,
- BCRYPT_ALG_HANDLE hAlg,
- unsigned char *hash, unsigned long hashlen)
-{
- _libssh2_wincng_hash_ctx ctx;
- int ret;
-
- ret = _libssh2_wincng_hash_init(&ctx, hAlg, hashlen, NULL, 0);
- if(!ret) {
- ret = _libssh2_wincng_hash_update(&ctx, data, datalen);
- ret |= _libssh2_wincng_hash_final(&ctx, hash);
- }
-
- return ret;
-}
-
-
-/*******************************************************************/
-/*
- * Windows CNG backend: HMAC functions
- */
-
-int
-_libssh2_wincng_hmac_final(_libssh2_wincng_hash_ctx *ctx,
- unsigned char *hash)
-{
- int ret;
-
- ret = BCryptFinishHash(ctx->hHash, hash, ctx->cbHash, 0);
-
- return BCRYPT_SUCCESS(ret) ? 0 : -1;
-}
-
-void
-_libssh2_wincng_hmac_cleanup(_libssh2_wincng_hash_ctx *ctx)
-{
- BCryptDestroyHash(ctx->hHash);
- ctx->hHash = NULL;
-
- _libssh2_wincng_safe_free(ctx->pbHashObject, ctx->dwHashObject);
- ctx->pbHashObject = NULL;
- ctx->dwHashObject = 0;
-}
-
-
-/*******************************************************************/
-/*
- * Windows CNG backend: Key functions
- */
-
-int
-_libssh2_wincng_key_sha1_verify(_libssh2_wincng_key_ctx *ctx,
- const unsigned char *sig,
- unsigned long sig_len,
- const unsigned char *m,
- unsigned long m_len,
- unsigned long flags)
-{
- BCRYPT_PKCS1_PADDING_INFO paddingInfoPKCS1;
- void *pPaddingInfo;
- unsigned char *data, *hash;
- unsigned long datalen, hashlen;
- int ret;
-
- datalen = m_len;
- data = malloc(datalen);
- if(!data) {
- return -1;
- }
-
- hashlen = SHA_DIGEST_LENGTH;
- hash = malloc(hashlen);
- if(!hash) {
- free(data);
- return -1;
- }
-
- memcpy(data, m, datalen);
-
- ret = _libssh2_wincng_hash(data, datalen,
- _libssh2_wincng.hAlgHashSHA1,
- hash, hashlen);
-
- _libssh2_wincng_safe_free(data, datalen);
-
- if(ret) {
- _libssh2_wincng_safe_free(hash, hashlen);
- return -1;
- }
-
- datalen = sig_len;
- data = malloc(datalen);
- if(!data) {
- _libssh2_wincng_safe_free(hash, hashlen);
- return -1;
- }
-
- if(flags & BCRYPT_PAD_PKCS1) {
- paddingInfoPKCS1.pszAlgId = BCRYPT_SHA1_ALGORITHM;
- pPaddingInfo = &paddingInfoPKCS1;
- }
- else
- pPaddingInfo = NULL;
-
- memcpy(data, sig, datalen);
-
- ret = BCryptVerifySignature(ctx->hKey, pPaddingInfo,
- hash, hashlen, data, datalen, flags);
-
- _libssh2_wincng_safe_free(hash, hashlen);
- _libssh2_wincng_safe_free(data, datalen);
-
- return BCRYPT_SUCCESS(ret) ? 0 : -1;
-}
-
-#ifdef HAVE_LIBCRYPT32
-static int
-_libssh2_wincng_load_pem(LIBSSH2_SESSION *session,
- const char *filename,
- const char *passphrase,
- const char *headerbegin,
- const char *headerend,
- unsigned char **data,
- unsigned int *datalen)
-{
- FILE *fp;
- int ret;
-
- fp = fopen(filename, FOPEN_READTEXT);
- if(!fp) {
- return -1;
- }
-
- ret = _libssh2_pem_parse(session, headerbegin, headerend,
- passphrase,
- fp, data, datalen);
-
- fclose(fp);
-
- return ret;
-}
-
-static int
-_libssh2_wincng_load_private(LIBSSH2_SESSION *session,
- const char *filename,
- const char *passphrase,
- unsigned char **ppbEncoded,
- unsigned long *pcbEncoded,
- int tryLoadRSA, int tryLoadDSA)
-{
- unsigned char *data = NULL;
- unsigned int datalen = 0;
- int ret = -1;
-
- if(ret && tryLoadRSA) {
- ret = _libssh2_wincng_load_pem(session, filename, passphrase,
- PEM_RSA_HEADER, PEM_RSA_FOOTER,
- &data, &datalen);
- }
-
- if(ret && tryLoadDSA) {
- ret = _libssh2_wincng_load_pem(session, filename, passphrase,
- PEM_DSA_HEADER, PEM_DSA_FOOTER,
- &data, &datalen);
- }
-
- if(!ret) {
- *ppbEncoded = data;
- *pcbEncoded = datalen;
- }
-
- return ret;
-}
-
-static int
-_libssh2_wincng_load_private_memory(LIBSSH2_SESSION *session,
- const char *privatekeydata,
- size_t privatekeydata_len,
- const char *passphrase,
- unsigned char **ppbEncoded,
- unsigned long *pcbEncoded,
- int tryLoadRSA, int tryLoadDSA)
-{
- unsigned char *data = NULL;
- unsigned int datalen = 0;
- int ret = -1;
-
- (void)passphrase;
-
- if(ret && tryLoadRSA) {
- ret = _libssh2_pem_parse_memory(session,
- PEM_RSA_HEADER, PEM_RSA_FOOTER,
- privatekeydata, privatekeydata_len,
- &data, &datalen);
- }
-
- if(ret && tryLoadDSA) {
- ret = _libssh2_pem_parse_memory(session,
- PEM_DSA_HEADER, PEM_DSA_FOOTER,
- privatekeydata, privatekeydata_len,
- &data, &datalen);
- }
-
- if(!ret) {
- *ppbEncoded = data;
- *pcbEncoded = datalen;
- }
-
- return ret;
-}
-
-static int
-_libssh2_wincng_asn_decode(unsigned char *pbEncoded,
- unsigned long cbEncoded,
- LPCSTR lpszStructType,
- unsigned char **ppbDecoded,
- unsigned long *pcbDecoded)
-{
- unsigned char *pbDecoded = NULL;
- unsigned long cbDecoded = 0;
- int ret;
-
- ret = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
- lpszStructType,
- pbEncoded, cbEncoded, 0, NULL,
- NULL, &cbDecoded);
- if(!ret) {
- return -1;
- }
-
- pbDecoded = malloc(cbDecoded);
- if(!pbDecoded) {
- return -1;
- }
-
- ret = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
- lpszStructType,
- pbEncoded, cbEncoded, 0, NULL,
- pbDecoded, &cbDecoded);
- if(!ret) {
- _libssh2_wincng_safe_free(pbDecoded, cbDecoded);
- return -1;
- }
-
-
- *ppbDecoded = pbDecoded;
- *pcbDecoded = cbDecoded;
-
- return 0;
-}
-
-static int
-_libssh2_wincng_bn_ltob(unsigned char *pbInput,
- unsigned long cbInput,
- unsigned char **ppbOutput,
- unsigned long *pcbOutput)
-{
- unsigned char *pbOutput;
- unsigned long cbOutput, index, offset, length;
-
- if(cbInput < 1) {
- return 0;
- }
-
- offset = 0;
- length = cbInput - 1;
- cbOutput = cbInput;
- if(pbInput[length] & (1 << 7)) {
- offset++;
- cbOutput += offset;
- }
-
- pbOutput = (unsigned char *)malloc(cbOutput);
- if(!pbOutput) {
- return -1;
- }
-
- pbOutput[0] = 0;
- for(index = 0; ((index + offset) < cbOutput)
- && (index < cbInput); index++) {
- pbOutput[index + offset] = pbInput[length - index];
- }
-
-
- *ppbOutput = pbOutput;
- *pcbOutput = cbOutput;
-
- return 0;
-}
-
-static int
-_libssh2_wincng_asn_decode_bn(unsigned char *pbEncoded,
- unsigned long cbEncoded,
- unsigned char **ppbDecoded,
- unsigned long *pcbDecoded)
-{
- unsigned char *pbDecoded = NULL, *pbInteger;
- unsigned long cbDecoded = 0, cbInteger;
- int ret;
-
- ret = _libssh2_wincng_asn_decode(pbEncoded, cbEncoded,
- X509_MULTI_BYTE_UINT,
- &pbInteger, &cbInteger);
- if(!ret) {
- ret = _libssh2_wincng_bn_ltob(((PCRYPT_DATA_BLOB)pbInteger)->pbData,
- ((PCRYPT_DATA_BLOB)pbInteger)->cbData,
- &pbDecoded, &cbDecoded);
- if(!ret) {
- *ppbDecoded = pbDecoded;
- *pcbDecoded = cbDecoded;
- }
- _libssh2_wincng_safe_free(pbInteger, cbInteger);
- }
-
- return ret;
-}
-
-static int
-_libssh2_wincng_asn_decode_bns(unsigned char *pbEncoded,
- unsigned long cbEncoded,
- unsigned char ***prpbDecoded,
- unsigned long **prcbDecoded,
- unsigned long *pcbCount)
-{
- PCRYPT_DER_BLOB pBlob;
- unsigned char *pbDecoded, **rpbDecoded;
- unsigned long cbDecoded, *rcbDecoded, index, length;
- int ret;
-
- ret = _libssh2_wincng_asn_decode(pbEncoded, cbEncoded,
- X509_SEQUENCE_OF_ANY,
- &pbDecoded, &cbDecoded);
- if(!ret) {
- length = ((PCRYPT_DATA_BLOB)pbDecoded)->cbData;
-
- rpbDecoded = malloc(sizeof(PBYTE) * length);
- if(rpbDecoded) {
- rcbDecoded = malloc(sizeof(DWORD) * length);
- if(rcbDecoded) {
- for(index = 0; index < length; index++) {
- pBlob = &((PCRYPT_DER_BLOB)
- ((PCRYPT_DATA_BLOB)pbDecoded)->pbData)[index];
- ret = _libssh2_wincng_asn_decode_bn(pBlob->pbData,
- pBlob->cbData,
- &rpbDecoded[index],
- &rcbDecoded[index]);
- if(ret)
- break;
- }
-
- if(!ret) {
- *prpbDecoded = rpbDecoded;
- *prcbDecoded = rcbDecoded;
- *pcbCount = length;
- }
- else {
- for(length = 0; length < index; length++) {
- _libssh2_wincng_safe_free(rpbDecoded[length],
- rcbDecoded[length]);
- rpbDecoded[length] = NULL;
- rcbDecoded[length] = 0;
- }
- free(rpbDecoded);
- free(rcbDecoded);
- }
- }
- else {
- free(rpbDecoded);
- ret = -1;
- }
- }
- else {
- ret = -1;
- }
-
- _libssh2_wincng_safe_free(pbDecoded, cbDecoded);
- }
-
- return ret;
-}
-#endif /* HAVE_LIBCRYPT32 */
-
-static unsigned long
-_libssh2_wincng_bn_size(const unsigned char *bignum,
- unsigned long length)
-{
- unsigned long offset;
-
- if(!bignum)
- return 0;
-
- length--;
-
- offset = 0;
- while(!(*(bignum + offset)) && (offset < length))
- offset++;
-
- length++;
-
- return length - offset;
-}
-
-
-/*******************************************************************/
-/*
- * Windows CNG backend: RSA functions
- */
-
-int
-_libssh2_wincng_rsa_new(libssh2_rsa_ctx **rsa,
- const unsigned char *edata,
- unsigned long elen,
- const unsigned char *ndata,
- unsigned long nlen,
- const unsigned char *ddata,
- unsigned long dlen,
- const unsigned char *pdata,
- unsigned long plen,
- const unsigned char *qdata,
- unsigned long qlen,
- const unsigned char *e1data,
- unsigned long e1len,
- const unsigned char *e2data,
- unsigned long e2len,
- const unsigned char *coeffdata,
- unsigned long coefflen)
-{
- BCRYPT_KEY_HANDLE hKey;
- BCRYPT_RSAKEY_BLOB *rsakey;
- LPCWSTR lpszBlobType;
- unsigned char *key;
- unsigned long keylen, offset, mlen, p1len = 0, p2len = 0;
- int ret;
-
- mlen = max(_libssh2_wincng_bn_size(ndata, nlen),
- _libssh2_wincng_bn_size(ddata, dlen));
- offset = sizeof(BCRYPT_RSAKEY_BLOB);
- keylen = offset + elen + mlen;
- if(ddata && dlen > 0) {
- p1len = max(_libssh2_wincng_bn_size(pdata, plen),
- _libssh2_wincng_bn_size(e1data, e1len));
- p2len = max(_libssh2_wincng_bn_size(qdata, qlen),
- _libssh2_wincng_bn_size(e2data, e2len));
- keylen += p1len * 3 + p2len * 2 + mlen;
- }
-
- key = malloc(keylen);
- if(!key) {
- return -1;
- }
-
- memset(key, 0, keylen);
-
-
- /* https://msdn.microsoft.com/library/windows/desktop/aa375531.aspx */
- rsakey = (BCRYPT_RSAKEY_BLOB *)key;
- rsakey->BitLength = mlen * 8;
- rsakey->cbPublicExp = elen;
- rsakey->cbModulus = mlen;
-
- memcpy(key + offset, edata, elen);
- offset += elen;
-
- if(nlen < mlen)
- memcpy(key + offset + mlen - nlen, ndata, nlen);
- else
- memcpy(key + offset, ndata + nlen - mlen, mlen);
-
- if(ddata && dlen > 0) {
- offset += mlen;
-
- if(plen < p1len)
- memcpy(key + offset + p1len - plen, pdata, plen);
- else
- memcpy(key + offset, pdata + plen - p1len, p1len);
- offset += p1len;
-
- if(qlen < p2len)
- memcpy(key + offset + p2len - qlen, qdata, qlen);
- else
- memcpy(key + offset, qdata + qlen - p2len, p2len);
- offset += p2len;
-
- if(e1len < p1len)
- memcpy(key + offset + p1len - e1len, e1data, e1len);
- else
- memcpy(key + offset, e1data + e1len - p1len, p1len);
- offset += p1len;
-
- if(e2len < p2len)
- memcpy(key + offset + p2len - e2len, e2data, e2len);
- else
- memcpy(key + offset, e2data + e2len - p2len, p2len);
- offset += p2len;
-
- if(coefflen < p1len)
- memcpy(key + offset + p1len - coefflen, coeffdata, coefflen);
- else
- memcpy(key + offset, coeffdata + coefflen - p1len, p1len);
- offset += p1len;
-
- if(dlen < mlen)
- memcpy(key + offset + mlen - dlen, ddata, dlen);
- else
- memcpy(key + offset, ddata + dlen - mlen, mlen);
-
- lpszBlobType = BCRYPT_RSAFULLPRIVATE_BLOB;
- rsakey->Magic = BCRYPT_RSAFULLPRIVATE_MAGIC;
- rsakey->cbPrime1 = p1len;
- rsakey->cbPrime2 = p2len;
- }
- else {
- lpszBlobType = BCRYPT_RSAPUBLIC_BLOB;
- rsakey->Magic = BCRYPT_RSAPUBLIC_MAGIC;
- rsakey->cbPrime1 = 0;
- rsakey->cbPrime2 = 0;
- }
-
-
- ret = BCryptImportKeyPair(_libssh2_wincng.hAlgRSA, NULL, lpszBlobType,
- &hKey, key, keylen, 0);
- if(!BCRYPT_SUCCESS(ret)) {
- _libssh2_wincng_safe_free(key, keylen);
- return -1;
- }
-
-
- *rsa = malloc(sizeof(libssh2_rsa_ctx));
- if(!(*rsa)) {
- BCryptDestroyKey(hKey);
- _libssh2_wincng_safe_free(key, keylen);
- return -1;
- }
-
- (*rsa)->hKey = hKey;
- (*rsa)->pbKeyObject = key;
- (*rsa)->cbKeyObject = keylen;
-
- return 0;
-}
-
-#ifdef HAVE_LIBCRYPT32
-static int
-_libssh2_wincng_rsa_new_private_parse(libssh2_rsa_ctx **rsa,
- LIBSSH2_SESSION *session,
- unsigned char *pbEncoded,
- unsigned long cbEncoded)
-{
- BCRYPT_KEY_HANDLE hKey;
- unsigned char *pbStructInfo;
- unsigned long cbStructInfo;
- int ret;
-
- (void)session;
-
- ret = _libssh2_wincng_asn_decode(pbEncoded, cbEncoded,
- PKCS_RSA_PRIVATE_KEY,
- &pbStructInfo, &cbStructInfo);
-
- _libssh2_wincng_safe_free(pbEncoded, cbEncoded);
-
- if(ret) {
- return -1;
- }
-
-
- ret = BCryptImportKeyPair(_libssh2_wincng.hAlgRSA, NULL,
- LEGACY_RSAPRIVATE_BLOB, &hKey,
- pbStructInfo, cbStructInfo, 0);
- if(!BCRYPT_SUCCESS(ret)) {
- _libssh2_wincng_safe_free(pbStructInfo, cbStructInfo);
- return -1;
- }
-
-
- *rsa = malloc(sizeof(libssh2_rsa_ctx));
- if(!(*rsa)) {
- BCryptDestroyKey(hKey);
- _libssh2_wincng_safe_free(pbStructInfo, cbStructInfo);
- return -1;
- }
-
- (*rsa)->hKey = hKey;
- (*rsa)->pbKeyObject = pbStructInfo;
- (*rsa)->cbKeyObject = cbStructInfo;
-
- return 0;
-}
-#endif /* HAVE_LIBCRYPT32 */
-
-int
-_libssh2_wincng_rsa_new_private(libssh2_rsa_ctx **rsa,
- LIBSSH2_SESSION *session,
- const char *filename,
- const unsigned char *passphrase)
-{
-#ifdef HAVE_LIBCRYPT32
- unsigned char *pbEncoded;
- unsigned long cbEncoded;
- int ret;
-
- (void)session;
-
- ret = _libssh2_wincng_load_private(session, filename,
- (const char *)passphrase,
- &pbEncoded, &cbEncoded, 1, 0);
- if(ret) {
- return -1;
- }
-
- return _libssh2_wincng_rsa_new_private_parse(rsa, session,
- pbEncoded, cbEncoded);
-#else
- (void)rsa;
- (void)filename;
- (void)passphrase;
-
- return _libssh2_error(session, LIBSSH2_ERROR_FILE,
- "Unable to load RSA key from private key file: "
- "Method unsupported in Windows CNG backend");
-#endif /* HAVE_LIBCRYPT32 */
-}
-
-int
-_libssh2_wincng_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa,
- LIBSSH2_SESSION *session,
- const char *filedata,
- size_t filedata_len,
- unsigned const char *passphrase)
-{
-#ifdef HAVE_LIBCRYPT32
- unsigned char *pbEncoded;
- unsigned long cbEncoded;
- int ret;
-
- (void)session;
-
- ret = _libssh2_wincng_load_private_memory(session, filedata, filedata_len,
- (const char *)passphrase,
- &pbEncoded, &cbEncoded, 1, 0);
- if(ret) {
- return -1;
- }
-
- return _libssh2_wincng_rsa_new_private_parse(rsa, session,
- pbEncoded, cbEncoded);
-#else
- (void)rsa;
- (void)filedata;
- (void)filedata_len;
- (void)passphrase;
-
- return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
- "Unable to extract private key from memory: "
- "Method unsupported in Windows CNG backend");
-#endif /* HAVE_LIBCRYPT32 */
-}
-
-int
-_libssh2_wincng_rsa_sha1_verify(libssh2_rsa_ctx *rsa,
- const unsigned char *sig,
- unsigned long sig_len,
- const unsigned char *m,
- unsigned long m_len)
-{
- return _libssh2_wincng_key_sha1_verify(rsa, sig, sig_len, m, m_len,
- BCRYPT_PAD_PKCS1);
-}
-
-int
-_libssh2_wincng_rsa_sha1_sign(LIBSSH2_SESSION *session,
- libssh2_rsa_ctx *rsa,
- const unsigned char *hash,
- size_t hash_len,
- unsigned char **signature,
- size_t *signature_len)
-{
- BCRYPT_PKCS1_PADDING_INFO paddingInfo;
- unsigned char *data, *sig;
- unsigned long cbData, datalen, siglen;
- int ret;
-
- datalen = (unsigned long)hash_len;
- data = malloc(datalen);
- if(!data) {
- return -1;
- }
-
- paddingInfo.pszAlgId = BCRYPT_SHA1_ALGORITHM;
-
- memcpy(data, hash, datalen);
-
- ret = BCryptSignHash(rsa->hKey, &paddingInfo,
- data, datalen, NULL, 0,
- &cbData, BCRYPT_PAD_PKCS1);
- if(BCRYPT_SUCCESS(ret)) {
- siglen = cbData;
- sig = LIBSSH2_ALLOC(session, siglen);
- if(sig) {
- ret = BCryptSignHash(rsa->hKey, &paddingInfo,
- data, datalen, sig, siglen,
- &cbData, BCRYPT_PAD_PKCS1);
- if(BCRYPT_SUCCESS(ret)) {
- *signature_len = siglen;
- *signature = sig;
- }
- else {
- LIBSSH2_FREE(session, sig);
- }
- }
- else
- ret = STATUS_NO_MEMORY;
- }
-
- _libssh2_wincng_safe_free(data, datalen);
-
- return BCRYPT_SUCCESS(ret) ? 0 : -1;
-}
-
-void
-_libssh2_wincng_rsa_free(libssh2_rsa_ctx *rsa)
-{
- if(!rsa)
- return;
-
- BCryptDestroyKey(rsa->hKey);
- rsa->hKey = NULL;
-
- _libssh2_wincng_safe_free(rsa->pbKeyObject, rsa->cbKeyObject);
- _libssh2_wincng_safe_free(rsa, sizeof(libssh2_rsa_ctx));
-}
-
-
-/*******************************************************************/
-/*
- * Windows CNG backend: DSA functions
- */
-
-#if LIBSSH2_DSA
-int
-_libssh2_wincng_dsa_new(libssh2_dsa_ctx **dsa,
- const unsigned char *pdata,
- unsigned long plen,
- const unsigned char *qdata,
- unsigned long qlen,
- const unsigned char *gdata,
- unsigned long glen,
- const unsigned char *ydata,
- unsigned long ylen,
- const unsigned char *xdata,
- unsigned long xlen)
-{
- BCRYPT_KEY_HANDLE hKey;
- BCRYPT_DSA_KEY_BLOB *dsakey;
- LPCWSTR lpszBlobType;
- unsigned char *key;
- unsigned long keylen, offset, length;
- int ret;
-
- length = max(max(_libssh2_wincng_bn_size(pdata, plen),
- _libssh2_wincng_bn_size(gdata, glen)),
- _libssh2_wincng_bn_size(ydata, ylen));
- offset = sizeof(BCRYPT_DSA_KEY_BLOB);
- keylen = offset + length * 3;
- if(xdata && xlen > 0)
- keylen += 20;
-
- key = malloc(keylen);
- if(!key) {
- return -1;
- }
-
- memset(key, 0, keylen);
-
-
- /* https://msdn.microsoft.com/library/windows/desktop/aa833126.aspx */
- dsakey = (BCRYPT_DSA_KEY_BLOB *)key;
- dsakey->cbKey = length;
-
- memset(dsakey->Count, -1, sizeof(dsakey->Count));
- memset(dsakey->Seed, -1, sizeof(dsakey->Seed));
-
- if(qlen < 20)
- memcpy(dsakey->q + 20 - qlen, qdata, qlen);
- else
- memcpy(dsakey->q, qdata + qlen - 20, 20);
-
- if(plen < length)
- memcpy(key + offset + length - plen, pdata, plen);
- else
- memcpy(key + offset, pdata + plen - length, length);
- offset += length;
-
- if(glen < length)
- memcpy(key + offset + length - glen, gdata, glen);
- else
- memcpy(key + offset, gdata + glen - length, length);
- offset += length;
-
- if(ylen < length)
- memcpy(key + offset + length - ylen, ydata, ylen);
- else
- memcpy(key + offset, ydata + ylen - length, length);
-
- if(xdata && xlen > 0) {
- offset += length;
-
- if(xlen < 20)
- memcpy(key + offset + 20 - xlen, xdata, xlen);
- else
- memcpy(key + offset, xdata + xlen - 20, 20);
-
- lpszBlobType = BCRYPT_DSA_PRIVATE_BLOB;
- dsakey->dwMagic = BCRYPT_DSA_PRIVATE_MAGIC;
- }
- else {
- lpszBlobType = BCRYPT_DSA_PUBLIC_BLOB;
- dsakey->dwMagic = BCRYPT_DSA_PUBLIC_MAGIC;
- }
-
-
- ret = BCryptImportKeyPair(_libssh2_wincng.hAlgDSA, NULL, lpszBlobType,
- &hKey, key, keylen, 0);
- if(!BCRYPT_SUCCESS(ret)) {
- _libssh2_wincng_safe_free(key, keylen);
- return -1;
- }
-
-
- *dsa = malloc(sizeof(libssh2_dsa_ctx));
- if(!(*dsa)) {
- BCryptDestroyKey(hKey);
- _libssh2_wincng_safe_free(key, keylen);
- return -1;
- }
-
- (*dsa)->hKey = hKey;
- (*dsa)->pbKeyObject = key;
- (*dsa)->cbKeyObject = keylen;
-
- return 0;
-}
-
-#ifdef HAVE_LIBCRYPT32
-static int
-_libssh2_wincng_dsa_new_private_parse(libssh2_dsa_ctx **dsa,
- LIBSSH2_SESSION *session,
- unsigned char *pbEncoded,
- unsigned long cbEncoded)
-{
- unsigned char **rpbDecoded;
- unsigned long *rcbDecoded, index, length;
- int ret;
-
- (void)session;
-
- ret = _libssh2_wincng_asn_decode_bns(pbEncoded, cbEncoded,
- &rpbDecoded, &rcbDecoded, &length);
-
- _libssh2_wincng_safe_free(pbEncoded, cbEncoded);
-
- if(ret) {
- return -1;
- }
-
-
- if(length == 6) {
- ret = _libssh2_wincng_dsa_new(dsa,
- rpbDecoded[1], rcbDecoded[1],
- rpbDecoded[2], rcbDecoded[2],
- rpbDecoded[3], rcbDecoded[3],
- rpbDecoded[4], rcbDecoded[4],
- rpbDecoded[5], rcbDecoded[5]);
- }
- else {
- ret = -1;
- }
-
- for(index = 0; index < length; index++) {
- _libssh2_wincng_safe_free(rpbDecoded[index], rcbDecoded[index]);
- rpbDecoded[index] = NULL;
- rcbDecoded[index] = 0;
- }
-
- free(rpbDecoded);
- free(rcbDecoded);
-
- return ret;
-}
-#endif /* HAVE_LIBCRYPT32 */
-
-int
-_libssh2_wincng_dsa_new_private(libssh2_dsa_ctx **dsa,
- LIBSSH2_SESSION *session,
- const char *filename,
- const unsigned char *passphrase)
-{
-#ifdef HAVE_LIBCRYPT32
- unsigned char *pbEncoded;
- unsigned long cbEncoded;
- int ret;
-
- ret = _libssh2_wincng_load_private(session, filename,
- (const char *)passphrase,
- &pbEncoded, &cbEncoded, 0, 1);
- if(ret) {
- return -1;
- }
-
- return _libssh2_wincng_dsa_new_private_parse(dsa, session,
- pbEncoded, cbEncoded);
-#else
- (void)dsa;
- (void)filename;
- (void)passphrase;
-
- return _libssh2_error(session, LIBSSH2_ERROR_FILE,
- "Unable to load DSA key from private key file: "
- "Method unsupported in Windows CNG backend");
-#endif /* HAVE_LIBCRYPT32 */
-}
-
-int
-_libssh2_wincng_dsa_new_private_frommemory(libssh2_dsa_ctx **dsa,
- LIBSSH2_SESSION *session,
- const char *filedata,
- size_t filedata_len,
- unsigned const char *passphrase)
-{
-#ifdef HAVE_LIBCRYPT32
- unsigned char *pbEncoded;
- unsigned long cbEncoded;
- int ret;
-
- ret = _libssh2_wincng_load_private_memory(session, filedata, filedata_len,
- (const char *)passphrase,
- &pbEncoded, &cbEncoded, 0, 1);
- if(ret) {
- return -1;
- }
-
- return _libssh2_wincng_dsa_new_private_parse(dsa, session,
- pbEncoded, cbEncoded);
-#else
- (void)dsa;
- (void)filedata;
- (void)filedata_len;
- (void)passphrase;
-
- return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
- "Unable to extract private key from memory: "
- "Method unsupported in Windows CNG backend");
-#endif /* HAVE_LIBCRYPT32 */
-}
-
-int
-_libssh2_wincng_dsa_sha1_verify(libssh2_dsa_ctx *dsa,
- const unsigned char *sig_fixed,
- const unsigned char *m,
- unsigned long m_len)
-{
- return _libssh2_wincng_key_sha1_verify(dsa, sig_fixed, 40, m, m_len, 0);
-}
-
-int
-_libssh2_wincng_dsa_sha1_sign(libssh2_dsa_ctx *dsa,
- const unsigned char *hash,
- unsigned long hash_len,
- unsigned char *sig_fixed)
-{
- unsigned char *data, *sig;
- unsigned long cbData, datalen, siglen;
- int ret;
-
- datalen = hash_len;
- data = malloc(datalen);
- if(!data) {
- return -1;
- }
-
- memcpy(data, hash, datalen);
-
- ret = BCryptSignHash(dsa->hKey, NULL, data, datalen,
- NULL, 0, &cbData, 0);
- if(BCRYPT_SUCCESS(ret)) {
- siglen = cbData;
- if(siglen == 40) {
- sig = malloc(siglen);
- if(sig) {
- ret = BCryptSignHash(dsa->hKey, NULL, data, datalen,
- sig, siglen, &cbData, 0);
- if(BCRYPT_SUCCESS(ret)) {
- memcpy(sig_fixed, sig, siglen);
- }
-
- _libssh2_wincng_safe_free(sig, siglen);
- }
- else
- ret = STATUS_NO_MEMORY;
- }
- else
- ret = STATUS_NO_MEMORY;
- }
-
- _libssh2_wincng_safe_free(data, datalen);
-
- return BCRYPT_SUCCESS(ret) ? 0 : -1;
-}
-
-void
-_libssh2_wincng_dsa_free(libssh2_dsa_ctx *dsa)
-{
- if(!dsa)
- return;
-
- BCryptDestroyKey(dsa->hKey);
- dsa->hKey = NULL;
-
- _libssh2_wincng_safe_free(dsa->pbKeyObject, dsa->cbKeyObject);
- _libssh2_wincng_safe_free(dsa, sizeof(libssh2_dsa_ctx));
-}
-#endif
-
-
-/*******************************************************************/
-/*
- * Windows CNG backend: Key functions
- */
-
-#ifdef HAVE_LIBCRYPT32
-static unsigned long
-_libssh2_wincng_pub_priv_write(unsigned char *key,
- unsigned long offset,
- const unsigned char *bignum,
- const unsigned long length)
-{
- _libssh2_htonu32(key + offset, length);
- offset += 4;
-
- memcpy(key + offset, bignum, length);
- offset += length;
-
- return offset;
-}
-
-static int
-_libssh2_wincng_pub_priv_keyfile_parse(LIBSSH2_SESSION *session,
- unsigned char **method,
- size_t *method_len,
- unsigned char **pubkeydata,
- size_t *pubkeydata_len,
- unsigned char *pbEncoded,
- unsigned long cbEncoded)
-{
- unsigned char **rpbDecoded;
- unsigned long *rcbDecoded;
- unsigned char *key = NULL, *mth = NULL;
- unsigned long keylen = 0, mthlen = 0;
- unsigned long index, offset, length;
- int ret;
-
- ret = _libssh2_wincng_asn_decode_bns(pbEncoded, cbEncoded,
- &rpbDecoded, &rcbDecoded, &length);
-
- _libssh2_wincng_safe_free(pbEncoded, cbEncoded);
-
- if(ret) {
- return -1;
- }
-
-
- if(length == 9) { /* private RSA key */
- mthlen = 7;
- mth = LIBSSH2_ALLOC(session, mthlen);
- if(mth) {
- memcpy(mth, "ssh-rsa", mthlen);
- }
- else {
- ret = -1;
- }
-
-
- keylen = 4 + mthlen + 4 + rcbDecoded[2] + 4 + rcbDecoded[1];
- key = LIBSSH2_ALLOC(session, keylen);
- if(key) {
- offset = _libssh2_wincng_pub_priv_write(key, 0, mth, mthlen);
-
- offset = _libssh2_wincng_pub_priv_write(key, offset,
- rpbDecoded[2],
- rcbDecoded[2]);
-
- _libssh2_wincng_pub_priv_write(key, offset,
- rpbDecoded[1],
- rcbDecoded[1]);
- }
- else {
- ret = -1;
- }
-
- }
- else if(length == 6) { /* private DSA key */
- mthlen = 7;
- mth = LIBSSH2_ALLOC(session, mthlen);
- if(mth) {
- memcpy(mth, "ssh-dss", mthlen);
- }
- else {
- ret = -1;
- }
-
- keylen = 4 + mthlen + 4 + rcbDecoded[1] + 4 + rcbDecoded[2]
- + 4 + rcbDecoded[3] + 4 + rcbDecoded[4];
- key = LIBSSH2_ALLOC(session, keylen);
- if(key) {
- offset = _libssh2_wincng_pub_priv_write(key, 0, mth, mthlen);
-
- offset = _libssh2_wincng_pub_priv_write(key, offset,
- rpbDecoded[1],
- rcbDecoded[1]);
-
- offset = _libssh2_wincng_pub_priv_write(key, offset,
- rpbDecoded[2],
- rcbDecoded[2]);
-
- offset = _libssh2_wincng_pub_priv_write(key, offset,
- rpbDecoded[3],
- rcbDecoded[3]);
-
- _libssh2_wincng_pub_priv_write(key, offset,
- rpbDecoded[4],
- rcbDecoded[4]);
- }
- else {
- ret = -1;
- }
-
- }
- else {
- ret = -1;
- }
-
-
- for(index = 0; index < length; index++) {
- _libssh2_wincng_safe_free(rpbDecoded[index], rcbDecoded[index]);
- rpbDecoded[index] = NULL;
- rcbDecoded[index] = 0;
- }
-
- free(rpbDecoded);
- free(rcbDecoded);
-
-
- if(ret) {
- if(mth)
- LIBSSH2_FREE(session, mth);
- if(key)
- LIBSSH2_FREE(session, key);
- }
- else {
- *method = mth;
- *method_len = mthlen;
- *pubkeydata = key;
- *pubkeydata_len = keylen;
- }
-
- return ret;
-}
-#endif /* HAVE_LIBCRYPT32 */
-
-int
-_libssh2_wincng_pub_priv_keyfile(LIBSSH2_SESSION *session,
- unsigned char **method,
- size_t *method_len,
- unsigned char **pubkeydata,
- size_t *pubkeydata_len,
- const char *privatekey,
- const char *passphrase)
-{
-#ifdef HAVE_LIBCRYPT32
- unsigned char *pbEncoded;
- unsigned long cbEncoded;
- int ret;
-
- ret = _libssh2_wincng_load_private(session, privatekey, passphrase,
- &pbEncoded, &cbEncoded, 1, 1);
- if(ret) {
- return -1;
- }
-
- return _libssh2_wincng_pub_priv_keyfile_parse(session, method, method_len,
- pubkeydata, pubkeydata_len,
- pbEncoded, cbEncoded);
-#else
- (void)method;
- (void)method_len;
- (void)pubkeydata;
- (void)pubkeydata_len;
- (void)privatekey;
- (void)passphrase;
-
- return _libssh2_error(session, LIBSSH2_ERROR_FILE,
- "Unable to load public key from private key file: "
- "Method unsupported in Windows CNG backend");
-#endif /* HAVE_LIBCRYPT32 */
-}
-
-int
-_libssh2_wincng_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
- unsigned char **method,
- size_t *method_len,
- unsigned char **pubkeydata,
- size_t *pubkeydata_len,
- const char *privatekeydata,
- size_t privatekeydata_len,
- const char *passphrase)
-{
-#ifdef HAVE_LIBCRYPT32
- unsigned char *pbEncoded;
- unsigned long cbEncoded;
- int ret;
-
- ret = _libssh2_wincng_load_private_memory(session, privatekeydata,
- privatekeydata_len, passphrase,
- &pbEncoded, &cbEncoded, 1, 1);
- if(ret) {
- return -1;
- }
-
- return _libssh2_wincng_pub_priv_keyfile_parse(session, method, method_len,
- pubkeydata, pubkeydata_len,
- pbEncoded, cbEncoded);
-#else
- (void)method;
- (void)method_len;
- (void)pubkeydata_len;
- (void)pubkeydata;
- (void)privatekeydata;
- (void)privatekeydata_len;
- (void)passphrase;
-
- return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
- "Unable to extract public key from private key in memory: "
- "Method unsupported in Windows CNG backend");
-#endif /* HAVE_LIBCRYPT32 */
-}
-
-/*******************************************************************/
-/*
- * Windows CNG backend: Cipher functions
- */
-
-int
-_libssh2_wincng_cipher_init(_libssh2_cipher_ctx *ctx,
- _libssh2_cipher_type(type),
- unsigned char *iv,
- unsigned char *secret,
- int encrypt)
-{
- BCRYPT_KEY_HANDLE hKey;
- BCRYPT_KEY_DATA_BLOB_HEADER *header;
- unsigned char *pbKeyObject, *pbIV, *key, *pbCtr, *pbIVCopy;
- unsigned long dwKeyObject, dwIV, dwCtrLength, dwBlockLength,
- cbData, keylen;
- int ret;
-
- (void)encrypt;
-
- ret = BCryptGetProperty(*type.phAlg, BCRYPT_OBJECT_LENGTH,
- (unsigned char *)&dwKeyObject,
- sizeof(dwKeyObject),
- &cbData, 0);
- if(!BCRYPT_SUCCESS(ret)) {
- return -1;
- }
-
- ret = BCryptGetProperty(*type.phAlg, BCRYPT_BLOCK_LENGTH,
- (unsigned char *)&dwBlockLength,
- sizeof(dwBlockLength),
- &cbData, 0);
- if(!BCRYPT_SUCCESS(ret)) {
- return -1;
- }
-
- pbKeyObject = malloc(dwKeyObject);
- if(!pbKeyObject) {
- return -1;
- }
-
-
- keylen = sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + type.dwKeyLength;
- key = malloc(keylen);
- if(!key) {
- free(pbKeyObject);
- return -1;
- }
-
-
- header = (BCRYPT_KEY_DATA_BLOB_HEADER *)key;
- header->dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC;
- header->dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1;
- header->cbKeyData = type.dwKeyLength;
-
- memcpy(key + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER),
- secret, type.dwKeyLength);
-
- ret = BCryptImportKey(*type.phAlg, NULL, BCRYPT_KEY_DATA_BLOB, &hKey,
- pbKeyObject, dwKeyObject, key, keylen, 0);
-
- _libssh2_wincng_safe_free(key, keylen);
-
- if(!BCRYPT_SUCCESS(ret)) {
- _libssh2_wincng_safe_free(pbKeyObject, dwKeyObject);
- return -1;
- }
-
- pbIV = NULL;
- pbCtr = NULL;
- dwIV = 0;
- dwCtrLength = 0;
-
- if(type.useIV || type.ctrMode) {
- pbIVCopy = malloc(dwBlockLength);
- if(!pbIVCopy) {
- BCryptDestroyKey(hKey);
- _libssh2_wincng_safe_free(pbKeyObject, dwKeyObject);
- return -1;
- }
- memcpy(pbIVCopy, iv, dwBlockLength);
-
- if(type.ctrMode) {
- pbCtr = pbIVCopy;
- dwCtrLength = dwBlockLength;
- }
- else if(type.useIV) {
- pbIV = pbIVCopy;
- dwIV = dwBlockLength;
- }
- }
-
- ctx->hKey = hKey;
- ctx->pbKeyObject = pbKeyObject;
- ctx->pbIV = pbIV;
- ctx->pbCtr = pbCtr;
- ctx->dwKeyObject = dwKeyObject;
- ctx->dwIV = dwIV;
- ctx->dwBlockLength = dwBlockLength;
- ctx->dwCtrLength = dwCtrLength;
-
- return 0;
-}
-int
-_libssh2_wincng_cipher_crypt(_libssh2_cipher_ctx *ctx,
- _libssh2_cipher_type(type),
- int encrypt,
- unsigned char *block,
- size_t blocklen)
-{
- unsigned char *pbOutput, *pbInput;
- unsigned long cbOutput, cbInput;
- int ret;
-
- (void)type;
-
- cbInput = (unsigned long)blocklen;
-
- if(type.ctrMode) {
- pbInput = ctx->pbCtr;
- }
- else {
- pbInput = block;
- }
-
- if(encrypt || type.ctrMode) {
- ret = BCryptEncrypt(ctx->hKey, pbInput, cbInput, NULL,
- ctx->pbIV, ctx->dwIV, NULL, 0, &cbOutput, 0);
- }
- else {
- ret = BCryptDecrypt(ctx->hKey, pbInput, cbInput, NULL,
- ctx->pbIV, ctx->dwIV, NULL, 0, &cbOutput, 0);
- }
- if(BCRYPT_SUCCESS(ret)) {
- pbOutput = malloc(cbOutput);
- if(pbOutput) {
- if(encrypt || type.ctrMode) {
- ret = BCryptEncrypt(ctx->hKey, pbInput, cbInput, NULL,
- ctx->pbIV, ctx->dwIV,
- pbOutput, cbOutput, &cbOutput, 0);
- }
- else {
- ret = BCryptDecrypt(ctx->hKey, pbInput, cbInput, NULL,
- ctx->pbIV, ctx->dwIV,
- pbOutput, cbOutput, &cbOutput, 0);
- }
- if(BCRYPT_SUCCESS(ret)) {
- if(type.ctrMode) {
- _libssh2_xor_data(block, block, pbOutput, blocklen);
- _libssh2_aes_ctr_increment(ctx->pbCtr, ctx->dwCtrLength);
- }
- else {
- memcpy(block, pbOutput, cbOutput);
- }
- }
-
- _libssh2_wincng_safe_free(pbOutput, cbOutput);
- }
- else
- ret = STATUS_NO_MEMORY;
- }
-
- return BCRYPT_SUCCESS(ret) ? 0 : -1;
-}
-
-void
-_libssh2_wincng_cipher_dtor(_libssh2_cipher_ctx *ctx)
-{
- BCryptDestroyKey(ctx->hKey);
- ctx->hKey = NULL;
-
- _libssh2_wincng_safe_free(ctx->pbKeyObject, ctx->dwKeyObject);
- ctx->pbKeyObject = NULL;
- ctx->dwKeyObject = 0;
-
- _libssh2_wincng_safe_free(ctx->pbIV, ctx->dwBlockLength);
- ctx->pbIV = NULL;
- ctx->dwBlockLength = 0;
-
- _libssh2_wincng_safe_free(ctx->pbCtr, ctx->dwCtrLength);
- ctx->pbCtr = NULL;
- ctx->dwCtrLength = 0;
-}
-
-
-/*******************************************************************/
-/*
- * Windows CNG backend: BigNumber functions
- */
-
-_libssh2_bn *
-_libssh2_wincng_bignum_init(void)
-{
- _libssh2_bn *bignum;
-
- bignum = (_libssh2_bn *)malloc(sizeof(_libssh2_bn));
- if(bignum) {
- bignum->bignum = NULL;
- bignum->length = 0;
- }
-
- return bignum;
-}
-
-static int
-_libssh2_wincng_bignum_resize(_libssh2_bn *bn, unsigned long length)
-{
- unsigned char *bignum;
-
- if(!bn)
- return -1;
-
- if(length == bn->length)
- return 0;
-
-#ifdef LIBSSH2_CLEAR_MEMORY
- if(bn->bignum && bn->length > 0 && length < bn->length) {
- SecureZeroMemory(bn->bignum + length, bn->length - length);
- }
-#endif
-
- bignum = realloc(bn->bignum, length);
- if(!bignum)
- return -1;
-
- bn->bignum = bignum;
- bn->length = length;
-
- return 0;
-}
-
-static int
-_libssh2_wincng_bignum_rand(_libssh2_bn *rnd, int bits, int top, int bottom)
-{
- unsigned char *bignum;
- unsigned long length;
-
- if(!rnd)
- return -1;
-
- length = (unsigned long)(ceil((float)bits / 8) * sizeof(unsigned char));
- if(_libssh2_wincng_bignum_resize(rnd, length))
- return -1;
-
- bignum = rnd->bignum;
-
- if(_libssh2_wincng_random(bignum, length))
- return -1;
-
- /* calculate significant bits in most significant byte */
- bits %= 8;
-
- /* fill most significant byte with zero padding */
- bignum[0] &= (1 << (8 - bits)) - 1;
-
- /* set some special last bits in most significant byte */
- if(top == 0)
- bignum[0] |= (1 << (7 - bits));
- else if(top == 1)
- bignum[0] |= (3 << (6 - bits));
-
- /* make odd by setting first bit in least significant byte */
- if(bottom)
- bignum[length - 1] |= 1;
-
- return 0;
-}
-
-static int
-_libssh2_wincng_bignum_mod_exp(_libssh2_bn *r,
- _libssh2_bn *a,
- _libssh2_bn *p,
- _libssh2_bn *m)
-{
- BCRYPT_KEY_HANDLE hKey;
- BCRYPT_RSAKEY_BLOB *rsakey;
- unsigned char *key, *bignum;
- unsigned long keylen, offset, length;
- int ret;
-
- if(!r || !a || !p || !m)
- return -1;
-
- offset = sizeof(BCRYPT_RSAKEY_BLOB);
- keylen = offset + p->length + m->length;
-
- key = malloc(keylen);
- if(!key)
- return -1;
-
-
- /* https://msdn.microsoft.com/library/windows/desktop/aa375531.aspx */
- rsakey = (BCRYPT_RSAKEY_BLOB *)key;
- rsakey->Magic = BCRYPT_RSAPUBLIC_MAGIC;
- rsakey->BitLength = m->length * 8;
- rsakey->cbPublicExp = p->length;
- rsakey->cbModulus = m->length;
- rsakey->cbPrime1 = 0;
- rsakey->cbPrime2 = 0;
-
- memcpy(key + offset, p->bignum, p->length);
- offset += p->length;
-
- memcpy(key + offset, m->bignum, m->length);
-
- ret = BCryptImportKeyPair(_libssh2_wincng.hAlgRSA, NULL,
- BCRYPT_RSAPUBLIC_BLOB, &hKey, key, keylen,
- BCRYPT_NO_KEY_VALIDATION);
-
- if(BCRYPT_SUCCESS(ret)) {
- ret = BCryptEncrypt(hKey, a->bignum, a->length, NULL, NULL, 0,
- NULL, 0, &length, BCRYPT_PAD_NONE);
- if(BCRYPT_SUCCESS(ret)) {
- if(!_libssh2_wincng_bignum_resize(r, length)) {
- length = max(a->length, length);
- bignum = malloc(length);
- if(bignum) {
- offset = length - a->length;
- memset(bignum, 0, offset);
- memcpy(bignum + offset, a->bignum, a->length);
-
- ret = BCryptEncrypt(hKey, bignum, length, NULL, NULL, 0,
- r->bignum, r->length, &offset,
- BCRYPT_PAD_NONE);
-
- _libssh2_wincng_safe_free(bignum, length);
-
- if(BCRYPT_SUCCESS(ret)) {
- _libssh2_wincng_bignum_resize(r, offset);
- }
- }
- else
- ret = STATUS_NO_MEMORY;
- }
- else
- ret = STATUS_NO_MEMORY;
- }
-
- BCryptDestroyKey(hKey);
- }
-
- _libssh2_wincng_safe_free(key, keylen);
-
- return BCRYPT_SUCCESS(ret) ? 0 : -1;
-}
-
-int
-_libssh2_wincng_bignum_set_word(_libssh2_bn *bn, unsigned long word)
-{
- unsigned long offset, number, bits, length;
-
- if(!bn)
- return -1;
-
- bits = 0;
- number = word;
- while(number >>= 1)
- bits++;
-
- length = (unsigned long) (ceil(((double)(bits + 1)) / 8.0) *
- sizeof(unsigned char));
- if(_libssh2_wincng_bignum_resize(bn, length))
- return -1;
-
- for(offset = 0; offset < length; offset++)
- bn->bignum[offset] = (word >> (offset * 8)) & 0xff;
-
- return 0;
-}
-
-unsigned long
-_libssh2_wincng_bignum_bits(const _libssh2_bn *bn)
-{
- unsigned char number;
- unsigned long offset, length, bits;
-
- if(!bn)
- return 0;
-
- length = bn->length - 1;
-
- offset = 0;
- while(!(*(bn->bignum + offset)) && (offset < length))
- offset++;
-
- bits = (length - offset) * 8;
- number = bn->bignum[offset];
-
- while(number >>= 1)
- bits++;
-
- bits++;
-
- return bits;
-}
-
-void
-_libssh2_wincng_bignum_from_bin(_libssh2_bn *bn, unsigned long len,
- const unsigned char *bin)
-{
- unsigned char *bignum;
- unsigned long offset, length, bits;
-
- if(!bn || !bin || !len)
- return;
-
- if(_libssh2_wincng_bignum_resize(bn, len))
- return;
-
- memcpy(bn->bignum, bin, len);
-
- bits = _libssh2_wincng_bignum_bits(bn);
- length = (unsigned long) (ceil(((double)bits) / 8.0) *
- sizeof(unsigned char));
-
- offset = bn->length - length;
- if(offset > 0) {
- memmove(bn->bignum, bn->bignum + offset, length);
-
-#ifdef LIBSSH2_CLEAR_MEMORY
- SecureZeroMemory(bn->bignum + length, offset);
-#endif
-
- bignum = realloc(bn->bignum, length);
- if(bignum) {
- bn->bignum = bignum;
- bn->length = length;
- }
- }
-}
-
-void
-_libssh2_wincng_bignum_to_bin(const _libssh2_bn *bn, unsigned char *bin)
-{
- if(bin && bn && bn->bignum && bn->length > 0) {
- memcpy(bin, bn->bignum, bn->length);
- }
-}
-
-void
-_libssh2_wincng_bignum_free(_libssh2_bn *bn)
-{
- if(bn) {
- if(bn->bignum) {
- _libssh2_wincng_safe_free(bn->bignum, bn->length);
- bn->bignum = NULL;
- }
- bn->length = 0;
- _libssh2_wincng_safe_free(bn, sizeof(_libssh2_bn));
- }
-}
-
-
-/*
- * Windows CNG backend: Diffie-Hellman support.
- */
-
-void
-_libssh2_dh_init(_libssh2_dh_ctx *dhctx)
-{
- *dhctx = _libssh2_wincng_bignum_init(); /* Random from client */
-}
-
-int
-_libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
- _libssh2_bn *g, _libssh2_bn *p, int group_order)
-{
- /* Generate x and e */
- if(_libssh2_wincng_bignum_rand(*dhctx, group_order * 8 - 1, 0, -1))
- return -1;
- if(_libssh2_wincng_bignum_mod_exp(public, g, *dhctx, p))
- return -1;
- return 0;
-}
-
-int
-_libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
- _libssh2_bn *f, _libssh2_bn *p)
-{
- /* Compute the shared secret */
- _libssh2_wincng_bignum_mod_exp(secret, f, *dhctx, p);
- return 0;
-}
-
-void
-_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx)
-{
- _libssh2_wincng_bignum_free(*dhctx);
- *dhctx = NULL;
-}
-
-#endif /* LIBSSH2_WINCNG */