Make libssh2 work again on os400. (#118)
* os400: minimum supported OS version is now V6R1. Do not log compiler informational messages. * Implement crypto backend specific Diffie-Hellman computation. This feature is now needed on os400 because the QC3 library does not implement bn_mod_exp() natively. Up to now, this function was emulated using an RSA encryption, but commits ca5222ea819cc5ed797860070b4c6c1aeeb28420 and 7934c9ce2a029c43e3642a492d3b9e494d1542be (CVE-2016-0787) broke the emulation because QC3 only supports RSA exponents up to 512 bits. Happily, QC3 supports a native API for Diffie-Hellman computation, with opaque random value: this commit implements the use of this API and, as a side effect, enables support of this feature for any other crypto backend that would use it. A "generic" Diffie-Hellman computation internal API supports crypto backends not implementing their own: this generic API uses the same functions as before. * Fix typos in docs/HACKING.CRYPTO.
Этот коммит содержится в:
родитель
c81b2384ac
Коммит
c8c1b4a050
@ -88,7 +88,7 @@ SHA_DIGEST_LENGTH
|
||||
#define to 20, the SHA-1 digest length.
|
||||
|
||||
libssh2_sha1_ctx
|
||||
Type of an SHA1 computation context. Generally a struct.
|
||||
Type of an SHA-1 computation context. Generally a struct.
|
||||
|
||||
int libssh2_sha1_init(libssh2_sha1_ctx *x);
|
||||
Initializes the SHA-1 computation context at x.
|
||||
@ -102,7 +102,7 @@ Note: if the ctx parameter is modified by the underlying code,
|
||||
this procedure must be implemented as a macro to map ctx --> &ctx.
|
||||
|
||||
void libssh2_sha1_final(libssh2_sha1_ctx ctx,
|
||||
unsigned char output[SHA1_DIGEST_LEN]);
|
||||
unsigned char output[SHA_DIGEST_LEN]);
|
||||
Get the computed SHA-1 signature from context ctx and store it into the
|
||||
output buffer.
|
||||
Release the context.
|
||||
@ -223,7 +223,7 @@ the keylen-byte key. Is invoked just after libssh2_hmac_ctx_init().
|
||||
Returns 1 for success and 0 for failure.
|
||||
|
||||
|
||||
4) Bidirectional Key ciphers.
|
||||
4) Bidirectional key ciphers.
|
||||
|
||||
_libssh2_cipher_ctx
|
||||
Type of a cipher computation context.
|
||||
@ -332,10 +332,50 @@ TripleDES-CBC algorithm identifier initializer.
|
||||
#define with constant value of type _libssh2_cipher_type().
|
||||
|
||||
|
||||
5) Big numbers.
|
||||
5) Diffie-Hellman support.
|
||||
If the crypto-library supports opaque Diffie-Hellman computations, symbol
|
||||
`libssh2_dh_key_pair' should be #defined as described below and the rest of
|
||||
this section applies.
|
||||
Else, the Diffie-Hellman context MUST be defined as `_libssh2_bn *' and
|
||||
the computation is emulated via calls to _libssh2_bn_rand() and
|
||||
_libssh2_bn_mod_exp(): all other symbols in this section are unused in this
|
||||
case.
|
||||
|
||||
5.1) Diffie-Hellman context.
|
||||
_libssh2_dh_ctx
|
||||
Type of a Diffie-Hellman computation context.
|
||||
Must always be defined.
|
||||
|
||||
5.2) Diffie-Hellman computation procedures.
|
||||
void libssh2_dh_init(_libssh2_dh_ctx *dhctx);
|
||||
Initializes the Diffie-Hellman context at `dhctx'. No effective context
|
||||
creation needed here.
|
||||
|
||||
int libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
|
||||
_libssh2_bn *g, _libssh2_bn *p, int group_order,
|
||||
_libssh2_bn_ctx *bnctx);
|
||||
Generates a Diffie-Hellman key pair using base `g', prime `p' and the given
|
||||
`group_order'. Can use the given big number context `bnctx' if needed.
|
||||
The private key is stored as opaque in the Diffie-Hellman context `*dhctx' and
|
||||
the public key is returned in `public'.
|
||||
0 is returned upon success, else -1.
|
||||
If defined, this procedure MUST be implemented as a #define'd macro.
|
||||
|
||||
int libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
|
||||
_libssh2_bn *f, _libssh2_bn *p, _libssh2_bn_ctx * bnctx)
|
||||
Computes the Diffie-Hellman secret from the previouly created context `*dhctx',
|
||||
the public key `f' from the other party and the same prime `p' used at
|
||||
context creation. The result is stored in `secret'.
|
||||
0 is returned upon success, else -1.
|
||||
|
||||
void libssh2_dh_dtor(_libssh2_dh_ctx *dhctx)
|
||||
Destroys Diffie-Hellman context at `dhctx' and resets its storage.
|
||||
|
||||
|
||||
6) Big numbers.
|
||||
Positive multi-byte integers support is sufficient.
|
||||
|
||||
5.1) Computation contexts.
|
||||
6.1) Computation contexts.
|
||||
This has a real meaning if the big numbers computations need some context
|
||||
storage. If not, use a dummy type and functions (macros).
|
||||
|
||||
@ -349,7 +389,7 @@ Returns a new multiple precision computation context.
|
||||
void _libssh2_bn_ctx_free(_libssh2_bn_ctx ctx);
|
||||
Releases a multiple precision computation context.
|
||||
|
||||
5.2) Computation support.
|
||||
6.2) Computation support.
|
||||
_libssh2_bn
|
||||
Type of multiple precision numbers (aka bignumbers or huge integers) for the
|
||||
crypto library.
|
||||
@ -396,15 +436,17 @@ random number can be zero. If top is 0, it is set to 1, and if top is 1, the
|
||||
two most significant bits of the number will be set to 1, so that the product
|
||||
of two such random numbers will always have 2*bits length. If bottom is true,
|
||||
the number will be odd.
|
||||
This procedure is only needed if no specific Diffie-Hellman support is provided.
|
||||
|
||||
void _libssh2_bn_mod_exp(_libssh2_bn *r, _libssh2_bn *a,
|
||||
_libssh2_bn *p, _libssh2_bn *m,
|
||||
_libssh2_bn_ctx *ctx);
|
||||
Computes a to the p-th power modulo m and stores the result into r (r=a^p % m).
|
||||
May use the given context.
|
||||
This procedure is only needed if no specific Diffie-Hellman support is provided.
|
||||
|
||||
|
||||
6) Private key algorithms.
|
||||
7) Private key algorithms.
|
||||
Format of an RSA public key:
|
||||
a) "ssh-rsa".
|
||||
b) RSA exponent, MSB first, with high order bit = 0.
|
||||
@ -448,7 +490,7 @@ Both buffers have to be allocated using LIBSSH2_ALLOC().
|
||||
Returns 0 if OK, else -1.
|
||||
This procedure is already prototyped in crypto.h.
|
||||
|
||||
6.1) RSA
|
||||
7.1) RSA
|
||||
LIBSSH2_RSA
|
||||
#define as 1 if the crypto library supports RSA, else 0.
|
||||
If defined as 0, the rest of this section can be omitted.
|
||||
@ -542,7 +584,7 @@ void _libssh2_rsa_free(libssh2_rsa_ctx *rsactx);
|
||||
Releases the RSA computation context at rsactx.
|
||||
|
||||
|
||||
6.2) DSA
|
||||
7.2) DSA
|
||||
LIBSSH2_DSA
|
||||
#define as 1 if the crypto library supports DSA, else 0.
|
||||
If defined as 0, the rest of this section can be omitted.
|
||||
@ -592,7 +634,7 @@ This procedure is already prototyped in crypto.h.
|
||||
int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx *dsactx,
|
||||
const unsigned char *sig,
|
||||
const unsigned char *m, unsigned long m_len);
|
||||
Verify (sig, siglen) signature of (m, m_len) using an SHA1 hash and the
|
||||
Verify (sig, siglen) signature of (m, m_len) using an SHA-1 hash and the
|
||||
DSA context.
|
||||
Returns 0 if OK, else -1.
|
||||
This procedure is already prototyped in crypto.h.
|
||||
@ -608,7 +650,7 @@ void _libssh2_dsa_free(libssh2_dsa_ctx *dsactx);
|
||||
Releases the DSA computation context at dsactx.
|
||||
|
||||
|
||||
7) Miscellaneous
|
||||
8) Miscellaneous
|
||||
|
||||
void libssh2_prepare_iovec(struct iovec *vector, unsigned int len);
|
||||
Prepare len consecutive iovec slots before using them.
|
||||
|
@ -49,7 +49,7 @@ setenv TGTCCSID '500' # Target CCSID of objects.
|
||||
setenv DEBUG '*ALL' # Debug level.
|
||||
setenv OPTIMIZE '10' # Optimisation level
|
||||
setenv OUTPUT '*NONE' # Compilation output option.
|
||||
setenv TGTRLS 'V5R3M0' # Target OS release.
|
||||
setenv TGTRLS 'V6R1M0' # Target OS release.
|
||||
setenv IFSDIR '/libssh2' # Installation IFS directory.
|
||||
|
||||
# Define ZLIB availability and locations.
|
||||
@ -180,7 +180,7 @@ make_module()
|
||||
CMD="CRTCMOD MODULE(${TARGETLIB}/${1}) SRCSTMF('__tmpsrcf.c')"
|
||||
# CMD="${CMD} SYSIFCOPT(*IFS64IO) OPTION(*INCDIRFIRST *SHOWINC *SHOWSYS)"
|
||||
CMD="${CMD} SYSIFCOPT(*IFS64IO) OPTION(*INCDIRFIRST)"
|
||||
CMD="${CMD} LOCALETYPE(*LOCALE)"
|
||||
CMD="${CMD} LOCALETYPE(*LOCALE) FLAG(10)"
|
||||
CMD="${CMD} INCDIR('${TOPDIR}/os400/include'"
|
||||
CMD="${CMD} '/QIBM/ProdData/qadrt/include' '${TOPDIR}/include'"
|
||||
CMD="${CMD} '${TOPDIR}/os400' '${SRCDIR}'"
|
||||
|
66
src/kex.c
66
src/kex.c
@ -98,6 +98,44 @@
|
||||
} \
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic Diffie-Hellman computation support.
|
||||
*
|
||||
* DH context should be a _libssh2_bn *.
|
||||
*/
|
||||
|
||||
#ifndef libssh2_dh_key_pair
|
||||
static void libssh2_dh_init(_libssh2_dh_ctx *dhctx)
|
||||
{
|
||||
*dhctx = _libssh2_bn_init(); /* Random from client */
|
||||
}
|
||||
|
||||
static int libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
|
||||
_libssh2_bn *g, _libssh2_bn *p, int group_order,
|
||||
_libssh2_bn_ctx *bnctx)
|
||||
{
|
||||
/* Generate x and e */
|
||||
_libssh2_bn_rand(*dhctx, group_order * 8 - 1, 0, -1);
|
||||
_libssh2_bn_mod_exp(public, g, *dhctx, p, bnctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
|
||||
_libssh2_bn *f, _libssh2_bn *p,
|
||||
_libssh2_bn_ctx * bnctx)
|
||||
{
|
||||
/* Compute the shared secret */
|
||||
_libssh2_bn_mod_exp(secret, f, *dhctx, p, bnctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void libssh2_dh_dtor(_libssh2_dh_ctx *dhctx)
|
||||
{
|
||||
_libssh2_bn_free(*dhctx);
|
||||
*dhctx = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* diffie_hellman_sha1
|
||||
@ -124,7 +162,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
|
||||
exchange_state->s_packet = NULL;
|
||||
exchange_state->k_value = NULL;
|
||||
exchange_state->ctx = _libssh2_bn_ctx_new();
|
||||
exchange_state->x = _libssh2_bn_init(); /* Random from client */
|
||||
libssh2_dh_init(&exchange_state->x);
|
||||
exchange_state->e = _libssh2_bn_init(); /* g^x mod p */
|
||||
exchange_state->f = _libssh2_bn_init_from_bin(); /* g^(Random from server) mod p */
|
||||
exchange_state->k = _libssh2_bn_init(); /* The shared secret: f^x mod p */
|
||||
@ -133,9 +171,8 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
|
||||
memset(&exchange_state->req_state, 0, sizeof(packet_require_state_t));
|
||||
|
||||
/* Generate x and e */
|
||||
_libssh2_bn_rand(exchange_state->x, group_order * 8 - 1, 0, -1);
|
||||
_libssh2_bn_mod_exp(exchange_state->e, g, exchange_state->x, p,
|
||||
exchange_state->ctx);
|
||||
libssh2_dh_key_pair(&exchange_state->x, exchange_state->e, g, p,
|
||||
group_order, exchange_state->ctx);
|
||||
|
||||
/* Send KEX init */
|
||||
/* packet_type(1) + String Length(4) + leading 0(1) */
|
||||
@ -325,8 +362,8 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
|
||||
exchange_state->h_sig = exchange_state->s;
|
||||
|
||||
/* Compute the shared secret */
|
||||
_libssh2_bn_mod_exp(exchange_state->k, exchange_state->f,
|
||||
exchange_state->x, p, exchange_state->ctx);
|
||||
libssh2_dh_secret(&exchange_state->x, exchange_state->k,
|
||||
exchange_state->f, p, exchange_state->ctx);
|
||||
exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5;
|
||||
if (_libssh2_bn_bits(exchange_state->k) % 8) {
|
||||
/* don't need leading 00 */
|
||||
@ -693,8 +730,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
|
||||
}
|
||||
|
||||
clean_exit:
|
||||
_libssh2_bn_free(exchange_state->x);
|
||||
exchange_state->x = NULL;
|
||||
libssh2_dh_dtor(&exchange_state->x);
|
||||
_libssh2_bn_free(exchange_state->e);
|
||||
exchange_state->e = NULL;
|
||||
_libssh2_bn_free(exchange_state->f);
|
||||
@ -750,7 +786,7 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
|
||||
exchange_state->s_packet = NULL;
|
||||
exchange_state->k_value = NULL;
|
||||
exchange_state->ctx = _libssh2_bn_ctx_new();
|
||||
exchange_state->x = _libssh2_bn_init(); /* Random from client */
|
||||
libssh2_dh_init(&exchange_state->x);
|
||||
exchange_state->e = _libssh2_bn_init(); /* g^x mod p */
|
||||
exchange_state->f = _libssh2_bn_init_from_bin(); /* g^(Random from server) mod p */
|
||||
exchange_state->k = _libssh2_bn_init(); /* The shared secret: f^x mod p */
|
||||
@ -759,9 +795,8 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
|
||||
memset(&exchange_state->req_state, 0, sizeof(packet_require_state_t));
|
||||
|
||||
/* Generate x and e */
|
||||
_libssh2_bn_rand(exchange_state->x, group_order * 8 - 1, 0, -1);
|
||||
_libssh2_bn_mod_exp(exchange_state->e, g, exchange_state->x, p,
|
||||
exchange_state->ctx);
|
||||
libssh2_dh_key_pair(&exchange_state->x, exchange_state->e, g, p,
|
||||
group_order, exchange_state->ctx);
|
||||
|
||||
/* Send KEX init */
|
||||
/* packet_type(1) + String Length(4) + leading 0(1) */
|
||||
@ -951,8 +986,8 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
|
||||
exchange_state->h_sig = exchange_state->s;
|
||||
|
||||
/* Compute the shared secret */
|
||||
_libssh2_bn_mod_exp(exchange_state->k, exchange_state->f,
|
||||
exchange_state->x, p, exchange_state->ctx);
|
||||
libssh2_dh_secret(&exchange_state->x, exchange_state->k,
|
||||
exchange_state->f, p, exchange_state->ctx);
|
||||
exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5;
|
||||
if (_libssh2_bn_bits(exchange_state->k) % 8) {
|
||||
/* don't need leading 00 */
|
||||
@ -1321,8 +1356,7 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
|
||||
}
|
||||
|
||||
clean_exit:
|
||||
_libssh2_bn_free(exchange_state->x);
|
||||
exchange_state->x = NULL;
|
||||
libssh2_dh_dtor(&exchange_state->x);
|
||||
_libssh2_bn_free(exchange_state->e);
|
||||
exchange_state->e = NULL;
|
||||
_libssh2_bn_free(exchange_state->f);
|
||||
|
@ -181,3 +181,5 @@
|
||||
#define _libssh2_bn_bits(bn) gcry_mpi_get_nbits (bn)
|
||||
#define _libssh2_bn_free(bn) gcry_mpi_release(bn)
|
||||
|
||||
#define _libssh2_dh_ctx _libssh2_bn *
|
||||
|
||||
|
@ -248,7 +248,7 @@ typedef struct kmdhgGPshakex_state_t
|
||||
size_t s_packet_len;
|
||||
size_t tmp_len;
|
||||
_libssh2_bn_ctx *ctx;
|
||||
_libssh2_bn *x;
|
||||
_libssh2_dh_ctx x;
|
||||
_libssh2_bn *e;
|
||||
_libssh2_bn *f;
|
||||
_libssh2_bn *k;
|
||||
|
@ -287,6 +287,8 @@ int _libssh2_md5_init(libssh2_md5_ctx *ctx);
|
||||
#define _libssh2_bn_bits(bn) BN_num_bits(bn)
|
||||
#define _libssh2_bn_free(bn) BN_clear_free(bn)
|
||||
|
||||
#define _libssh2_dh_ctx _libssh2_bn *
|
||||
|
||||
const EVP_CIPHER *_libssh2_EVP_aes_128_ctr(void);
|
||||
const EVP_CIPHER *_libssh2_EVP_aes_192_ctr(void);
|
||||
const EVP_CIPHER *_libssh2_EVP_aes_256_ctr(void);
|
||||
|
317
src/os400qc3.c
317
src/os400qc3.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Patrick Monnerat, D+H <patrick.monnerat@dh.com>
|
||||
* Copyright (C) 2015-2016 Patrick Monnerat, D+H <patrick.monnerat@dh.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
@ -115,6 +115,9 @@ static int sshdsapubkey(LIBSSH2_SESSION *session, char **sshpubkey,
|
||||
const char *method);
|
||||
#endif
|
||||
|
||||
static unsigned char OID_dhKeyAgreement[] =
|
||||
{9, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 1, 3, 1};
|
||||
|
||||
|
||||
/* PKCS#5 support. */
|
||||
|
||||
@ -206,7 +209,7 @@ static const pkcs5algo des_EDE3_CBC = {
|
||||
OID_des_EDE3_CBC, parse_iv, Qc3_TDES, 8, Qc3_CBC, Qc3_Pad_Counter,
|
||||
'\0', 24, 0, 0, 8, 8, 0
|
||||
};
|
||||
|
||||
|
||||
/* rc2CBC OID: 1.2.840.113549.3.2 */
|
||||
static const unsigned char OID_rc2CBC[] = {
|
||||
8, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x03, 0x02
|
||||
@ -330,6 +333,7 @@ static const char fopenrbmode[] = "rb";
|
||||
#include <qc3sigvr.h>
|
||||
#include <qc3sigcl.h>
|
||||
#include <qc3pbext.h>
|
||||
#include <qc3dh.h>
|
||||
|
||||
static Qc3_Format_KEYD0100_T nulltoken = {""};
|
||||
|
||||
@ -883,220 +887,6 @@ _libssh2_random(unsigned char *buf, int len)
|
||||
Qc3PRN_TYPE_NORMAL, Qc3PRN_NO_PARITY, (char *) &ecnull);
|
||||
}
|
||||
|
||||
int
|
||||
_libssh2_bn_rand(_libssh2_bn *bn, int bits, int top, int bottom)
|
||||
{
|
||||
int len;
|
||||
int i;
|
||||
|
||||
if (!bn || bits <= 0)
|
||||
return -1;
|
||||
len = (bits + 7) >> 3;
|
||||
if (_libssh2_bn_resize(bn, len))
|
||||
return -1;
|
||||
_libssh2_random(bn->bignum, len);
|
||||
i = ((bits - 1) & 07) + 1;
|
||||
bn->bignum[len - 1] &= (1 << i) - 1;
|
||||
switch (top) {
|
||||
case 1:
|
||||
if (bits > 1)
|
||||
if (i > 1)
|
||||
bn->bignum[len - 1] |= 1 << (i - 2);
|
||||
else
|
||||
bn->bignum[len - 2] |= 0x80;
|
||||
/* Fall into. */
|
||||
case 0:
|
||||
bn->bignum[len - 1] |= 1 << (i - 1);
|
||||
break;
|
||||
}
|
||||
if (bottom)
|
||||
*bn->bignum |= 0x01;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_libssh2_bn_lshift(_libssh2_bn *bn)
|
||||
{
|
||||
int i;
|
||||
int c = 0;
|
||||
|
||||
if (!bn)
|
||||
return -1;
|
||||
|
||||
if (_libssh2_bn_resize(bn, (_libssh2_bn_bits(bn) + 8) >> 3))
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < bn->length; i++) {
|
||||
if (bn->bignum[i] & 0x80)
|
||||
c |= 0x02;
|
||||
bn->bignum[i] = (bn->bignum[i] << 1) | (c & 0x01);
|
||||
c >>= 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_libssh2_bn_rshift(_libssh2_bn *bn)
|
||||
{
|
||||
int i;
|
||||
int c = 0;
|
||||
|
||||
if (!bn)
|
||||
return -1;
|
||||
|
||||
for (i = bn->length; i--;) {
|
||||
if (bn->bignum[i] & 0x01)
|
||||
c |= 0x100;
|
||||
bn->bignum[i] = (bn->bignum[i] >> 1) | (c & 0x80);
|
||||
c >>= 1;
|
||||
}
|
||||
|
||||
if (_libssh2_bn_resize(bn, (_libssh2_bn_bits(bn) + 7) >> 3))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_libssh2_bn_swap(_libssh2_bn *bn1, _libssh2_bn *bn2)
|
||||
{
|
||||
_libssh2_bn t = *bn1;
|
||||
|
||||
*bn1 = *bn2;
|
||||
*bn2 = t;
|
||||
}
|
||||
|
||||
static int
|
||||
_libssh2_bn_subtract(_libssh2_bn *d, _libssh2_bn *bn1, _libssh2_bn *bn2)
|
||||
{
|
||||
int c = 0;
|
||||
int i;
|
||||
|
||||
if (bn1->length < bn2->length)
|
||||
return -1;
|
||||
|
||||
if (_libssh2_bn_resize(d, bn1->length))
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < bn2->length; i++) {
|
||||
c += (int) bn1->bignum[i] - (int) bn2->bignum[i];
|
||||
d->bignum[i] = c;
|
||||
c = c < 0? -1: 0;
|
||||
}
|
||||
|
||||
for (; c && i < bn1->length; i++) {
|
||||
c += (int) bn1->bignum[i];
|
||||
d->bignum[i] = c;
|
||||
c = c < 0? -1: 0;
|
||||
}
|
||||
|
||||
if (_libssh2_bn_resize(d, (_libssh2_bn_bits(d) + 7) >> 3))
|
||||
return -1;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int
|
||||
_libssh2_os400qc3_bn_mod_exp(_libssh2_bn *r, _libssh2_bn *a, _libssh2_bn *p,
|
||||
_libssh2_bn *m)
|
||||
{
|
||||
_libssh2_bn *mp;
|
||||
_libssh2_bn *rp;
|
||||
asn1Element *rsapubkey;
|
||||
asn1Element *subjpubkeyinfo;
|
||||
unsigned char *av;
|
||||
unsigned char *rv;
|
||||
char *keydbuf;
|
||||
Qc3_Format_ALGD0400_T algd;
|
||||
Qc3_Format_KEYD0200_T *keyd;
|
||||
Qus_EC_t errcode;
|
||||
int sc;
|
||||
int outlen;
|
||||
int ret = -1;
|
||||
|
||||
/* There is no support for this function in the Qc3 crypto-library.
|
||||
Since a RSA encryption performs this function, we can emulate it
|
||||
by creating an RSA public key in ASN.1 SubjectPublicKeyInfo format
|
||||
from p (exponent) and m (modulus) and encrypt a with this key. The
|
||||
encryption output is the function result.
|
||||
Problem: the Qc3EncryptData procedure only succeeds if the data bit
|
||||
count is less than the modulus bit count. To satisfy this condition,
|
||||
we multiply the modulus by a power of two and adjust the result
|
||||
accordingly. */
|
||||
|
||||
if (!r || !a || !p)
|
||||
return ret;
|
||||
|
||||
mp = _libssh2_bn_init();
|
||||
if (!mp)
|
||||
return ret;
|
||||
if (_libssh2_bn_from_bn(mp, m)) {
|
||||
_libssh2_bn_free(mp);
|
||||
return ret;
|
||||
}
|
||||
for (sc = 0; _libssh2_bn_bits(mp) <= 8 * a->length; sc++)
|
||||
if (_libssh2_bn_lshift(mp)) {
|
||||
_libssh2_bn_free(mp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
rsapubkey = rsapublickey(p, mp);
|
||||
subjpubkeyinfo = rsasubjectpublickeyinfo(rsapubkey);
|
||||
asn1delete(rsapubkey);
|
||||
|
||||
if (!rsapubkey || !subjpubkeyinfo) {
|
||||
asn1delete(rsapubkey);
|
||||
asn1delete(subjpubkeyinfo);
|
||||
_libssh2_bn_free(mp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
av = (unsigned char *) alloca(a->length);
|
||||
rv = (unsigned char *) alloca(mp->length);
|
||||
keydbuf = alloca(sizeof *keyd +
|
||||
subjpubkeyinfo->end - subjpubkeyinfo->header);
|
||||
|
||||
if (av && rv && keydbuf) {
|
||||
_libssh2_bn_to_bin(a, av);
|
||||
algd.Public_Key_Alg = Qc3_RSA;
|
||||
algd.PKA_Block_Format = Qc3_Zero_Pad;
|
||||
memset(algd.Reserved, 0, sizeof algd.Reserved);
|
||||
algd.Signing_Hash_Alg = 0;
|
||||
keyd = (Qc3_Format_KEYD0200_T *) keydbuf;
|
||||
keyd->Key_Type = Qc3_RSA_Public;
|
||||
keyd->Key_String_Len = subjpubkeyinfo->end - subjpubkeyinfo->header;
|
||||
keyd->Key_Format = Qc3_BER_String;
|
||||
memset(keyd->Reserved, 0, sizeof keyd->Reserved);
|
||||
memcpy(keydbuf + sizeof *keyd, subjpubkeyinfo->header,
|
||||
keyd->Key_String_Len);
|
||||
set_EC_length(errcode, sizeof errcode);
|
||||
Qc3EncryptData(av, (int *) &a->length, Qc3_Data, (char *) &algd,
|
||||
Qc3_Alg_Public_Key, keydbuf, Qc3_Key_Parms, anycsp,
|
||||
NULL, rv, (int *) &mp->length, &outlen, &errcode);
|
||||
if (!errcode.Bytes_Available) {
|
||||
_libssh2_bn_from_bin(r, outlen, rv);
|
||||
if (!sc)
|
||||
ret = 0;
|
||||
else {
|
||||
rp = _libssh2_bn_init();
|
||||
if (rp) {
|
||||
do {
|
||||
_libssh2_bn_rshift(mp);
|
||||
if (!_libssh2_bn_subtract(rp, r, mp))
|
||||
_libssh2_bn_swap(r, rp);
|
||||
} while (--sc);
|
||||
_libssh2_bn_free(rp);
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
asn1delete(subjpubkeyinfo);
|
||||
_libssh2_bn_free(mp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
@ -1443,6 +1233,101 @@ _libssh2_rsa_new(libssh2_rsa_ctx **rsa,
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* OS/400 QC3 crypto-library backend: Diffie-Hellman support.
|
||||
*
|
||||
*******************************************************************/
|
||||
|
||||
void
|
||||
_libssh2_os400qc3_dh_init(_libssh2_dh_ctx *dhctx)
|
||||
{
|
||||
memset((char *) dhctx, 0, sizeof *dhctx);
|
||||
}
|
||||
|
||||
int
|
||||
_libssh2_os400qc3_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
|
||||
_libssh2_bn *g, _libssh2_bn *p, int group_order)
|
||||
{
|
||||
asn1Element *prime;
|
||||
asn1Element *base;
|
||||
asn1Element *dhparameter;
|
||||
asn1Element *dhkeyagreement;
|
||||
asn1Element *pkcs3;
|
||||
int pkcs3len;
|
||||
char *pubkey;
|
||||
int pubkeysize;
|
||||
int pubkeylen;
|
||||
Qus_EC_t errcode;
|
||||
|
||||
(void) group_order;
|
||||
|
||||
/* Build the PKCS#3 structure. */
|
||||
|
||||
base = asn1uint(g);
|
||||
prime = asn1uint(p);
|
||||
dhparameter = asn1container(ASN1_SEQ | ASN1_CONSTRUCTED,
|
||||
prime, base, NULL);
|
||||
asn1delete(base);
|
||||
asn1delete(prime);
|
||||
dhkeyagreement = asn1bytes(ASN1_OBJ_ID,
|
||||
OID_dhKeyAgreement + 1, OID_dhKeyAgreement[0]);
|
||||
pkcs3 = asn1container(ASN1_SEQ | ASN1_CONSTRUCTED,
|
||||
dhkeyagreement, dhparameter, NULL);
|
||||
asn1delete(dhkeyagreement);
|
||||
asn1delete(dhparameter);
|
||||
if (!base || !prime || !dhparameter ||
|
||||
!dhkeyagreement || !dhparameter || !pkcs3) {
|
||||
asn1delete(pkcs3);
|
||||
return -1;
|
||||
}
|
||||
pkcs3len = pkcs3->end - pkcs3->header;
|
||||
pubkeysize = (_libssh2_bn_bits(p) + 7) >> 3;
|
||||
pubkey = alloca(pubkeysize);
|
||||
set_EC_length(errcode, sizeof errcode);
|
||||
Qc3GenDHKeyPair((char *) pkcs3->header, &pkcs3len, anycsp, NULL,
|
||||
dhctx->token, pubkey, &pubkeysize, &pubkeylen, &errcode);
|
||||
asn1delete(pkcs3);
|
||||
if (errcode.Bytes_Available)
|
||||
return -1;
|
||||
return _libssh2_bn_from_bin(public, pubkeylen, (unsigned char *) pubkey);
|
||||
}
|
||||
|
||||
int
|
||||
_libssh2_os400qc3_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
|
||||
_libssh2_bn *f, _libssh2_bn *p)
|
||||
{
|
||||
char *pubkey;
|
||||
int pubkeysize;
|
||||
char *secretbuf;
|
||||
int secretbufsize;
|
||||
int secretbuflen;
|
||||
Qus_EC_t errcode;
|
||||
|
||||
pubkeysize = (_libssh2_bn_bits(f) + 7) >> 3;
|
||||
pubkey = alloca(pubkeysize);
|
||||
_libssh2_bn_to_bin(f, pubkey);
|
||||
secretbufsize = (_libssh2_bn_bits(p) + 7) >> 3;
|
||||
secretbuf = alloca(pubkeysize);
|
||||
set_EC_length(errcode, sizeof errcode);
|
||||
Qc3CalculateDHSecretKey(dhctx->token, pubkey, &pubkeysize,
|
||||
secretbuf, &secretbufsize, &secretbuflen, &errcode);
|
||||
if (errcode.Bytes_Available)
|
||||
return -1;
|
||||
return _libssh2_bn_from_bin(secret,
|
||||
secretbuflen, (unsigned char *) secretbuf);
|
||||
}
|
||||
|
||||
void
|
||||
_libssh2_os400qc3_dh_dtor(_libssh2_dh_ctx *dhctx)
|
||||
{
|
||||
if (!null_token(dhctx->token)) {
|
||||
Qc3DestroyAlgorithmContext(dhctx->token, (char *) &ecnull);
|
||||
memset((char *) dhctx, 0, sizeof *dhctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* OS/400 QC3 crypto-library backend: PKCS#5 supplement.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Patrick Monnerat, D+H <patrick.monnerat@dh.com>
|
||||
* Copyright (C) 2015-2016 Patrick Monnerat, D+H <patrick.monnerat@dh.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms,
|
||||
@ -210,6 +210,10 @@ typedef struct { /* Algorithm description. */
|
||||
int keylen; /* Key length. */
|
||||
} _libssh2_os400qc3_cipher_t;
|
||||
|
||||
typedef struct { /* Diffie-Hellman context. */
|
||||
char token[8]; /* Context token. */
|
||||
} _libssh2_os400qc3_dh_ctx;
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* OS/400 QC3 crypto-library backend: Define global types/codes.
|
||||
@ -277,8 +281,6 @@ typedef struct { /* Algorithm description. */
|
||||
#define _libssh2_bn_ctx_free(bnctx) ((void) 0)
|
||||
|
||||
#define _libssh2_bn_init_from_bin() _libssh2_bn_init()
|
||||
#define _libssh2_bn_mod_exp(r, a, p, m, ctx) \
|
||||
_libssh2_os400qc3_bn_mod_exp(r, a, p, m)
|
||||
#define _libssh2_bn_bytes(bn) ((bn)->length)
|
||||
|
||||
#define _libssh2_cipher_type(name) _libssh2_os400qc3_cipher_t name
|
||||
@ -309,6 +311,14 @@ typedef struct { /* Algorithm description. */
|
||||
_libssh2_os400qc3_rsa_sha1_signv(session, sig, siglen, \
|
||||
count, vector, ctx)
|
||||
|
||||
#define _libssh2_dh_ctx _libssh2_os400qc3_dh_ctx
|
||||
#define libssh2_dh_init(dhctx) _libssh2_os400qc3_dh_init(dhctx)
|
||||
#define libssh2_dh_key_pair(dhctx, public, g, p, group_order, bnctx) \
|
||||
_libssh2_os400qc3_dh_key_pair(dhctx, public, g, p, group_order)
|
||||
#define libssh2_dh_secret(dhctx, secret, f, p, bnctx) \
|
||||
_libssh2_os400qc3_dh_secret(dhctx, secret, f, p)
|
||||
#define libssh2_dh_dtor(dhctx) _libssh2_os400qc3_dh_dtor(dhctx)
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
@ -324,10 +334,6 @@ extern int _libssh2_bn_from_bin(_libssh2_bn *bn, int len,
|
||||
extern int _libssh2_bn_set_word(_libssh2_bn *bn, unsigned long val);
|
||||
extern int _libssh2_bn_to_bin(_libssh2_bn *bn, unsigned char *val);
|
||||
extern void _libssh2_random(unsigned char *buf, int len);
|
||||
extern int _libssh2_bn_rand(_libssh2_bn *bn, int bits,
|
||||
int top, int bottom);
|
||||
extern int _libssh2_os400qc3_bn_mod_exp(_libssh2_bn *r, _libssh2_bn *a,
|
||||
_libssh2_bn *p, _libssh2_bn *m);
|
||||
extern void _libssh2_os400qc3_crypto_dtor(_libssh2_os400qc3_crypto_ctx *x);
|
||||
extern int libssh2_os400qc3_hash_init(Qc3_Format_ALGD0100_T *x,
|
||||
unsigned int algo);
|
||||
@ -352,6 +358,15 @@ extern int _libssh2_os400qc3_rsa_sha1_signv(LIBSSH2_SESSION *session,
|
||||
int veccount,
|
||||
const struct iovec vector[],
|
||||
libssh2_rsa_ctx *ctx);
|
||||
extern void _libssh2_os400qc3_dh_init(_libssh2_dh_ctx *dhctx);
|
||||
extern int _libssh2_os400qc3_dh_key_pair(_libssh2_dh_ctx *dhctx,
|
||||
_libssh2_bn *public,
|
||||
_libssh2_bn *g,
|
||||
_libssh2_bn *p, int group_order);
|
||||
extern int _libssh2_os400qc3_dh_secret(_libssh2_dh_ctx *dhctx,
|
||||
_libssh2_bn *secret,
|
||||
_libssh2_bn *f, _libssh2_bn *p);
|
||||
extern void _libssh2_os400qc3_dh_dtor(_libssh2_dh_ctx *dhctx);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -374,6 +374,8 @@ _libssh2_bn *_libssh2_wincng_bignum_init(void);
|
||||
#define _libssh2_bn_free(bn) \
|
||||
_libssh2_wincng_bignum_free(bn)
|
||||
|
||||
#define _libssh2_dh_ctx _libssh2_bn *
|
||||
|
||||
/*******************************************************************/
|
||||
/*
|
||||
* Windows CNG backend: forward declarations
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user