diff --git a/docs/HACKING-CRYPTO b/docs/HACKING-CRYPTO index 233cb325..e23ac228 100644 --- a/docs/HACKING-CRYPTO +++ b/docs/HACKING-CRYPTO @@ -406,6 +406,21 @@ TripleDES-CBC algorithm identifier initializer. 5) Diffie-Hellman support. +LIBSSH2_DH_GEX_MINGROUP +The minimum Diffie-Hellman group length in bits supported by the backend. +Usually defined as 2048. + +LIBSSH2_DH_GEX_OPTGROUP +The preferred Diffie-Hellman group length in bits. Usually defined as 4096. + +LIBSSH2_DH_GEX_MAXGROUP +The maximum Diffie-Hellman group length in bits supported by the backend. +Usually defined as 8192. + +LIBSSH2_DH_MAX_MODULUS_BITS +The maximum Diffie-Hellman modulus bit count accepted from the server. This +value must be supported by the backend. Usually 16384. + 5.1) Diffie-Hellman context. _libssh2_dh_ctx Type of a Diffie-Hellman computation context. @@ -658,7 +673,28 @@ the allocated signature at (signature, signature_len). Signature buffer must be allocated from the given session. Returns 0 if OK, else -1. This procedure is already prototyped in crypto.h. -Note: this procedure is not used if macro _libssh2_rsa_sha1_signv() is defined. +Note: this procedure is not used if both macros _libssh2_rsa_sha2_256_signv() +and _libssh2_rsa_sha2_512_signv are defined. + +int _libssh2_rsa_sha2_256_signv(LIBSSH2_SESSION *session, + unsigned char **sig, size_t *siglen, + int count, const struct iovec vector[], + libssh2_rsa_ctx *ctx); +RSA signs the SHA-256 hash computed over the count data chunks in vector. +Signature is stored at (sig, siglen). +Signature buffer must be allocated from the given session. +Returns 0 if OK, else -1. +Note: this procedure is optional: if provided, it MUST be defined as a macro. + +int _libssh2_rsa_sha2_512_signv(LIBSSH2_SESSION *session, + unsigned char **sig, size_t *siglen, + int count, const struct iovec vector[], + libssh2_rsa_ctx *ctx); +RSA signs the SHA-512 hash computed over the count data chunks in vector. +Signature is stored at (sig, siglen). +Signature buffer must be allocated from the given session. +Returns 0 if OK, else -1. +Note: this procedure is optional: if provided, it MUST be defined as a macro. int _libssh2_rsa_sha2_verify(libssh2_rsa_ctx * rsa, size_t hash_len, diff --git a/include/libssh2.h b/include/libssh2.h index 657e12bc..6bce4e26 100644 --- a/include/libssh2.h +++ b/include/libssh2.h @@ -228,14 +228,6 @@ typedef off_t libssh2_struct_stat_size; #define LIBSSH2_SSH_DEFAULT_BANNER LIBSSH2_SSH_BANNER #define LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF LIBSSH2_SSH_DEFAULT_BANNER "\r\n" -/* Default generate and safe prime sizes for - diffie-hellman-group-exchange-sha1 */ -#define LIBSSH2_DH_GEX_MINGROUP 2048 -#define LIBSSH2_DH_GEX_OPTGROUP 4096 -#define LIBSSH2_DH_GEX_MAXGROUP 8192 - -#define LIBSSH2_DH_MAX_MODULUS_BITS 16384 - /* Defaults for pty requests */ #define LIBSSH2_TERM_WIDTH 80 #define LIBSSH2_TERM_HEIGHT 24 diff --git a/os400/README400 b/os400/README400 index 870c3634..e14bcf36 100644 --- a/os400/README400 +++ b/os400/README400 @@ -38,7 +38,8 @@ familiar with. _ As a prerequisite, QADRT development environment must be installed. _ Install the libssh2 sources directory in IFS. -_ Enter shell (QSH) +_ Enter shell (QSH). You may need to change the LANG environment variable + to be in phase with the libssh2 source files CCSID. _ Change current directory to the libssh2 sources installation directory _ Change current directory to os400 _ Edit file iniscript.sh. You may want to change tunable configuration diff --git a/os400/include/assert.h b/os400/include/assert.h new file mode 100644 index 00000000..33ea3477 --- /dev/null +++ b/os400/include/assert.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2023 Patrick Monnerat + * 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. + */ + +#ifndef LIBSSH2_ASSERT_H +#define LIBSSH2_ASSERT_H + +#include +#include + +/* Ascii assert() macro. */ + +#ifndef NDEBUG +#pragma convert(819) + +#define assert(expr) ((expr)? ((void) 0): (fprintf(stderr, \ + "Assertion failed: %s in file %s line %u. Aborting\n", \ + #expr, __FILE__, __LINE__), abort())) +#else +#define assert(expr) ((void) 0) +#endif +#endif + +/* vim: set expandtab ts=4 sw=4: */ diff --git a/os400/initscript.sh b/os400/initscript.sh index 9b773d01..931c8cd8 100644 --- a/os400/initscript.sh +++ b/os400/initscript.sh @@ -49,8 +49,9 @@ 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 'V6R1M0' # Target OS release. +setenv TGTRLS 'V7R3M0' # Target OS release. setenv IFSDIR '/libssh2' # Installation IFS directory. +setenv QADRTDIR '/QIBM/ProdData/qadrt' # QADRT IFS directory. # Define ZLIB availability and locations. @@ -182,7 +183,7 @@ make_module() CMD="${CMD} SYSIFCOPT(*IFS64IO) OPTION(*INCDIRFIRST)" CMD="${CMD} LOCALETYPE(*LOCALE) FLAG(10)" CMD="${CMD} INCDIR('${TOPDIR}/os400/include'" - CMD="${CMD} '/QIBM/ProdData/qadrt/include' '${TOPDIR}/include'" + CMD="${CMD} '${QADRTDIR}/include' '${TOPDIR}/include'" CMD="${CMD} '${TOPDIR}/os400' '${SRCDIR}'" if [ "${WITH_ZLIB}" != "0" ] diff --git a/src/kex.c b/src/kex.c index b7a27645..66ca6350 100644 --- a/src/kex.c +++ b/src/kex.c @@ -263,8 +263,11 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session, rc = libssh2_dh_key_pair(&exchange_state->x, exchange_state->e, g, p, group_order, exchange_state->ctx); - if(rc) + if(rc) { + ret = _libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE, + "dh key pair generation failed"); goto clean_exit; + } /* Send KEX init */ /* packet_type(1) + String Length(4) + leading 0(1) */ diff --git a/src/libgcrypt.h b/src/libgcrypt.h index d1c09b5a..7f87ba82 100644 --- a/src/libgcrypt.h +++ b/src/libgcrypt.h @@ -222,6 +222,14 @@ #define _libssh2_bn_bits(bn) gcry_mpi_get_nbits (bn) #define _libssh2_bn_free(bn) gcry_mpi_release(bn) +/* Default generate and safe prime sizes for + diffie-hellman-group-exchange-sha1 */ +#define LIBSSH2_DH_GEX_MINGROUP 2048 +#define LIBSSH2_DH_GEX_OPTGROUP 4096 +#define LIBSSH2_DH_GEX_MAXGROUP 8192 + +#define LIBSSH2_DH_MAX_MODULUS_BITS 16384 + #define _libssh2_dh_ctx struct gcry_mpi * #define libssh2_dh_init(dhctx) _libssh2_dh_init(dhctx) #define libssh2_dh_key_pair(dhctx, public, g, p, group_order, bnctx) \ diff --git a/src/mbedtls.h b/src/mbedtls.h index 3fd7a8b1..f379e6cf 100644 --- a/src/mbedtls.h +++ b/src/mbedtls.h @@ -429,6 +429,14 @@ typedef enum { * mbedTLS backend: Diffie-Hellman support. */ +/* Default generate and safe prime sizes for + diffie-hellman-group-exchange-sha1 */ +#define LIBSSH2_DH_GEX_MINGROUP 2048 +#define LIBSSH2_DH_GEX_OPTGROUP 4096 +#define LIBSSH2_DH_GEX_MAXGROUP 8192 + +#define LIBSSH2_DH_MAX_MODULUS_BITS 16384 + #define _libssh2_dh_ctx mbedtls_mpi * #define libssh2_dh_init(dhctx) _libssh2_dh_init(dhctx) #define libssh2_dh_key_pair(dhctx, public, g, p, group_order, bnctx) \ diff --git a/src/openssl.h b/src/openssl.h index 2f347c36..cf623c14 100644 --- a/src/openssl.h +++ b/src/openssl.h @@ -419,6 +419,14 @@ libssh2_curve_type; #define _libssh2_bn_bits(bn) BN_num_bits(bn) #define _libssh2_bn_free(bn) BN_clear_free(bn) +/* Default generate and safe prime sizes for + diffie-hellman-group-exchange-sha1 */ +#define LIBSSH2_DH_GEX_MINGROUP 2048 +#define LIBSSH2_DH_GEX_OPTGROUP 4096 +#define LIBSSH2_DH_GEX_MAXGROUP 8192 + +#define LIBSSH2_DH_MAX_MODULUS_BITS 16384 + #define _libssh2_dh_ctx BIGNUM * #define libssh2_dh_init(dhctx) _libssh2_dh_init(dhctx) #define libssh2_dh_key_pair(dhctx, public, g, p, group_order, bnctx) \ diff --git a/src/os400qc3.c b/src/os400qc3.c index b7fc7487..f531bbd1 100644 --- a/src/os400qc3.c +++ b/src/os400qc3.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2015-2016 Patrick Monnerat, D+H - * Copyright (C) 2020 Patrick Monnerat . + * Copyright (C) 2020-2023 Patrick Monnerat . * All rights reserved. * * Redistribution and use in source and binary forms, @@ -348,6 +348,169 @@ static asn1Element lastbytebitcount = { }; +/******************************************************************* + * + * OS/400 QC3 crypto-library backend: big numbers support. + * + *******************************************************************/ + +int +_libssh2_random(unsigned char *buf, size_t len) +{ + Qus_EC_t errcode; + + set_EC_length(errcode, sizeof errcode); + Qc3GenPRNs(buf, len, + Qc3PRN_TYPE_NORMAL, Qc3PRN_NO_PARITY, (char *) &errcode); + return errcode.Bytes_Available? -1: 0; +} + +_libssh2_bn * +_libssh2_bn_init(void) +{ + _libssh2_bn *bignum; + + bignum = (_libssh2_bn *) malloc(sizeof *bignum); + if(bignum) { + bignum->bignum = NULL; + bignum->length = 0; + } + + return bignum; +} + +void +_libssh2_bn_free(_libssh2_bn *bn) +{ + if(bn) { + if(bn->bignum) { + if(bn->length) + _libssh2_explicit_zero(bn->bignum, bn->length); + + free(bn->bignum); + } + + free((char *) bn); + } +} + +static int +_libssh2_bn_resize(_libssh2_bn *bn, size_t newlen) +{ + unsigned char *bignum; + + if(!bn) + return -1; + if(newlen == bn->length) + return 0; + + if(!bn->bignum) + bignum = (unsigned char *) malloc(newlen); + else { + if(newlen < bn->length) + _libssh2_explicit_zero(bn->bignum + newlen, bn->length - newlen); + + if(!newlen) { + free((char *) bn->bignum); + bn->bignum = NULL; + bn->length = 0; + return 0; + } + bignum = (unsigned char *) realloc((char *) bn->bignum, newlen); + } + + if(!bignum) + return -1; + + if(newlen > bn->length) + memset((char *) bignum + bn->length, 0, newlen - bn->length); + + bn->bignum = bignum; + bn->length = newlen; + return 0; +} + +unsigned long +_libssh2_bn_bits(_libssh2_bn *bn) +{ + unsigned int i; + unsigned char b; + + if(bn && bn->bignum) { + for(i = bn->length; i--;) { + b = bn->bignum[i]; + if(b) { + i *= 8; + do { + i++; + } while(b >>= 1); + return i; + } + } + } + + return 0; +} + +int +_libssh2_bn_from_bin(_libssh2_bn *bn, int len, const unsigned char *val) +{ + int i; + + if(!bn || (len && !val)) + return -1; + + for(; len && !*val; len--) + val++; + + if(_libssh2_bn_resize(bn, len)) + return -1; + + for(i = len; i--;) + bn->bignum[i] = *val++; + + return 0; +} + +int +_libssh2_bn_set_word(_libssh2_bn *bn, unsigned long val) +{ + val = htonl(val); + return _libssh2_bn_from_bin(bn, sizeof val, (unsigned char *) &val); +} + +int +_libssh2_bn_to_bin(_libssh2_bn *bn, unsigned char *val) +{ + int i; + + if(!bn || !val) + return -1; + + for(i = bn->length; i--;) + *val++ = bn->bignum[i]; + + return 0; +} + +static int +_libssh2_bn_from_bn(_libssh2_bn *to, _libssh2_bn *from) +{ + int i; + + if(!to || !from) + return -1; + + if(_libssh2_bn_resize(to, from->length)) + return -1; + + for(i = to->length; i--;) + to->bignum[i] = from->bignum[i]; + + return 0; +} + + /******************************************************************* * * OS/400 QC3 crypto-library backend: ASN.1 support. @@ -727,167 +890,6 @@ rsaprivatekeyinfo(asn1Element *privkey) return privkeyinfo; } -/******************************************************************* - * - * OS/400 QC3 crypto-library backend: big numbers support. - * - *******************************************************************/ - - -_libssh2_bn * -_libssh2_bn_init(void) -{ - _libssh2_bn *bignum; - - bignum = (_libssh2_bn *) malloc(sizeof *bignum); - if(bignum) { - bignum->bignum = NULL; - bignum->length = 0; - } - - return bignum; -} - -void -_libssh2_bn_free(_libssh2_bn *bn) -{ - if(bn) { - if(bn->bignum) { - if(bn->length) - _libssh2_explicit_zero(bn->bignum, bn->length); - - free(bn->bignum); - } - - free((char *) bn); - } -} - -static int -_libssh2_bn_resize(_libssh2_bn *bn, size_t newlen) -{ - unsigned char *bignum; - - if(!bn) - return -1; - if(newlen == bn->length) - return 0; - - if(!bn->bignum) - bignum = (unsigned char *) malloc(newlen); - else { - if(newlen < bn->length) - _libssh2_explicit_zero(bn->bignum + newlen, bn->length - newlen); - - if(!newlen) { - free((char *) bn->bignum); - bn->bignum = NULL; - bn->length = 0; - return 0; - } - bignum = (unsigned char *) realloc((char *) bn->bignum, newlen); - } - - if(!bignum) - return -1; - - if(newlen > bn->length) - memset((char *) bignum + bn->length, 0, newlen - bn->length); - - bn->bignum = bignum; - bn->length = newlen; - return 0; -} - -unsigned long -_libssh2_bn_bits(_libssh2_bn *bn) -{ - unsigned int i; - unsigned char b; - - if(bn && bn->bignum) { - for(i = bn->length; i--;) - b = bn->bignum[i]; - if(b) { - i *= 8; - do { - i++; - } while(b >>= 1); - return i; - } - } - - return 0; -} - -int -_libssh2_bn_from_bin(_libssh2_bn *bn, int len, const unsigned char *val) -{ - int i; - - if(!bn || (len && !val)) - return -1; - - for(; len && !*val; len--) - val++; - - if(_libssh2_bn_resize(bn, len)) - return -1; - - for(i = len; i--;) - bn->bignum[i] = *val++; - - return 0; -} - -int -_libssh2_bn_set_word(_libssh2_bn *bn, unsigned long val) -{ - val = htonl(val); - return _libssh2_bn_from_bin(bn, sizeof val, (unsigned char *) &val); -} - -int -_libssh2_bn_to_bin(_libssh2_bn *bn, unsigned char *val) -{ - int i; - - if(!bn || !val) - return -1; - - for(i = bn->length; i--;) - *val++ = bn->bignum[i]; - - return 0; -} - -static int -_libssh2_bn_from_bn(_libssh2_bn *to, _libssh2_bn *from) -{ - int i; - - if(!to || !from) - return -1; - - if(_libssh2_bn_resize(to, from->length)) - return -1; - - for(i = to->length; i--;) - to->bignum[i] = from->bignum[i]; - - return 0; -} - -int -_libssh2_random(unsigned char *buf, size_t len) -{ - Qc3GenPRNs(buf, len, - Qc3PRN_TYPE_NORMAL, Qc3PRN_NO_PARITY, (char *) &ecnull); - /* FIXME: any error is silently discarded! But Qc3GenPRNs could fail, - including if "The system seed digest is not ready" dixit IBM doc. */ - return 0; -} - /******************************************************************* * @@ -1145,8 +1147,6 @@ _libssh2_rsa_new(libssh2_rsa_ctx **rsa, _libssh2_bn *coeff = NULL; asn1Element *key = NULL; asn1Element *structkey = NULL; - Qc3_Format_ALGD0400_T algd; - Qus_EC_t errcode; int keytype; int ret = 0; int i; @@ -1192,23 +1192,11 @@ _libssh2_rsa_new(libssh2_rsa_ctx **rsa, if(!key || !structkey) ret = -1; - set_EC_length(errcode, sizeof errcode); - - if(!ret) { - /* Create the algorithm context. */ - algd.Public_Key_Alg = Qc3_RSA; - algd.PKA_Block_Format = Qc3_PKCS1_01; - memset(algd.Reserved, 0, sizeof algd.Reserved); - algd.Signing_Hash_Alg = Qc3_SHA1; - Qc3CreateAlgorithmContext((char *) &algd, Qc3_Alg_Public_Key, - ctx->hash.Alg_Context_Token, &errcode); - if(errcode.Bytes_Available) - ret = -1; - ctx->hash.Final_Op_Flag = Qc3_Continue; - } - /* Create the key context. */ if(!ret) { + Qus_EC_t errcode; + + set_EC_length(errcode, sizeof errcode); i = structkey->end - structkey->header; Qc3CreateKeyContext(structkey->header, &i, berstring, &keytype, qc3clear, NULL, NULL, ctx->key.Key_Context_Token, @@ -2105,26 +2093,12 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx **rsa, LIBSSH2_SESSION *session, { libssh2_rsa_ctx *ctx = libssh2_init_crypto_ctx(NULL); int ret; - Qc3_Format_ALGD0400_T algd; - Qus_EC_t errcode; if(!ctx) return -1; ret = load_rsa_private_file(session, filename, passphrase, rsapkcs1privkey, rsapkcs8privkey, (void *) ctx); - if(!ret) { - /* Create the algorithm context. */ - algd.Public_Key_Alg = Qc3_RSA; - algd.PKA_Block_Format = Qc3_PKCS1_01; - memset(algd.Reserved, 0, sizeof algd.Reserved); - algd.Signing_Hash_Alg = Qc3_SHA1; - set_EC_length(errcode, sizeof errcode); - Qc3CreateAlgorithmContext((char *) &algd, Qc3_Alg_Public_Key, - ctx->hash.Alg_Context_Token, &errcode); - if(errcode.Bytes_Available) - ret = -1; - } if(ret) { _libssh2_os400qc3_crypto_dtor(ctx); ctx = NULL; @@ -2185,8 +2159,6 @@ _libssh2_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa, unsigned char *data = NULL; unsigned int datalen = 0; int ret; - Qc3_Format_ALGD0400_T algd; - Qus_EC_t errcode; if(!ctx) return -1; @@ -2238,19 +2210,6 @@ _libssh2_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa, if(data) LIBSSH2_FREE(session, data); - if(!ret) { - /* Create the algorithm context. */ - algd.Public_Key_Alg = Qc3_RSA; - algd.PKA_Block_Format = Qc3_PKCS1_01; - memset(algd.Reserved, 0, sizeof algd.Reserved); - algd.Signing_Hash_Alg = Qc3_SHA1; - set_EC_length(errcode, sizeof errcode); - Qc3CreateAlgorithmContext((char *) &algd, Qc3_Alg_Public_Key, - ctx->hash.Alg_Context_Token, &errcode); - if(errcode.Bytes_Available) - ret = -1; - } - if(ret) { _libssh2_os400qc3_crypto_dtor(ctx); ctx = NULL; @@ -2373,44 +2332,75 @@ _libssh2_sk_pub_keyfilememory(LIBSSH2_SESSION *session, } int -_libssh2_rsa_sha1_verify(libssh2_rsa_ctx *rsa, +_libssh2_rsa_sha2_verify(libssh2_rsa_ctx *rsa, size_t hash_len, const unsigned char *sig, size_t sig_len, const unsigned char *m, size_t m_len) { Qus_EC_t errcode; + Qc3_Format_ALGD0400_T algd; int slen = (int)sig_len; int mlen = (int)m_len; + memset(&algd, 0, sizeof algd); + algd.Public_Key_Alg = Qc3_RSA; + algd.PKA_Block_Format = Qc3_PKCS1_01; + switch(hash_len) { + case SHA_DIGEST_LENGTH: + algd.Signing_Hash_Alg = Qc3_SHA1; + break; + case SHA256_DIGEST_LENGTH: + algd.Signing_Hash_Alg = Qc3_SHA256; + break; + case SHA512_DIGEST_LENGTH: + algd.Signing_Hash_Alg = Qc3_SHA512; + break; + default: + return -1; + } + set_EC_length(errcode, sizeof errcode); Qc3VerifySignature((char *) sig, &slen, (char *) m, &mlen, Qc3_Data, - rsa->hash.Alg_Context_Token, Qc3_Alg_Token, - rsa->key.Key_Context_Token, Qc3_Key_Token, anycsp, + (char *) &algd, Qc3_Alg_Public_Key, + (char *) &rsa->key, Qc3_Key_Token, anycsp, NULL, (char *) &errcode); return errcode.Bytes_Available? -1: 0; } int -_libssh2_os400qc3_rsa_sha1_signv(LIBSSH2_SESSION *session, - unsigned char **signature, - size_t *signature_len, - int veccount, - const struct iovec vector[], - libssh2_rsa_ctx *ctx) +_libssh2_rsa_sha1_verify(libssh2_rsa_ctx *rsa, + const unsigned char *sig, size_t sig_len, + const unsigned char *m, size_t m_len) +{ + return _libssh2_rsa_sha2_verify(rsa, SHA_DIGEST_LENGTH, + sig, sig_len, m, m_len); +} + +int +_libssh2_os400qc3_rsa_signv(LIBSSH2_SESSION *session, + int algo, + unsigned char **signature, + size_t *signature_len, + int veccount, + const struct iovec vector[], + libssh2_rsa_ctx *ctx) { Qus_EC_t errcode; + Qc3_Format_ALGD0400_T algd; int siglen; unsigned char *sig; char sigbuf[8192]; int sigbufsize = sizeof sigbuf; - ctx->hash.Final_Op_Flag = Qc3_Final; + algd.Public_Key_Alg = Qc3_RSA; + algd.PKA_Block_Format = Qc3_PKCS1_01; + memset(algd.Reserved, 0, sizeof algd.Reserved); + algd.Signing_Hash_Alg = algo; set_EC_length(errcode, sizeof errcode); Qc3CalculateSignature((char *) vector, &veccount, Qc3_Array, - (char *) &ctx->hash, Qc3_Alg_Token, + (char *) &algd, Qc3_Alg_Public_Key, (char *) &ctx->key, Qc3_Key_Token, anycsp, NULL, sigbuf, &sigbufsize, &siglen, (char *) &errcode); - ctx->hash.Final_Op_Flag = Qc3_Continue; if(errcode.Bytes_Available) return -1; sig = LIBSSH2_ALLOC(session, siglen); @@ -2434,8 +2424,11 @@ _libssh2_supported_key_sign_algorithms(LIBSSH2_SESSION *session, size_t key_method_len) { (void)session; - (void)key_method; - (void)key_method_len; + + if(key_method_len == 7 && + memcmp(key_method, "ssh-rsa", key_method_len) == 0) { + return "rsa-sha2-512,rsa-sha2-256,ssh-rsa"; + } return NULL; } diff --git a/src/os400qc3.h b/src/os400qc3.h index 8d26dfbf..68ef0b98 100644 --- a/src/os400qc3.h +++ b/src/os400qc3.h @@ -2,7 +2,7 @@ #define __LIBSSH2_OS400QC3_H /* * Copyright (C) 2015-2016 Patrick Monnerat, D+H - * Copyright (C) 2020 Patrick Monnerat . + * Copyright (C) 2020-2023 Patrick Monnerat . * All rights reserved. * * Redistribution and use in source and binary forms, @@ -177,7 +177,7 @@ #define LIBSSH2_3DES 1 #define LIBSSH2_RSA 1 -#define LIBSSH2_RSA_SHA2 0 +#define LIBSSH2_RSA_SHA2 1 #define LIBSSH2_DSA 0 #define LIBSSH2_ECDSA 0 #define LIBSSH2_ED25519 0 @@ -316,19 +316,19 @@ typedef struct { /* Diffie-Hellman context. */ #define _libssh2_cipher_type(name) _libssh2_os400qc3_cipher_t name #define _libssh2_cipher_aes128 {Qc3_Alg_Block_Cipher, Qc3_AES, 16, \ Qc3_CBC, 16} -#define _libssh2_cipher_aes192 {Qc3_Alg_Block_Cipher, Qc3_AES, 24, \ +#define _libssh2_cipher_aes192 {Qc3_Alg_Block_Cipher, Qc3_AES, 16, \ Qc3_CBC, 24} -#define _libssh2_cipher_aes256 {Qc3_Alg_Block_Cipher, Qc3_AES, 32, \ +#define _libssh2_cipher_aes256 {Qc3_Alg_Block_Cipher, Qc3_AES, 16, \ Qc3_CBC, 32} #define _libssh2_cipher_aes128ctr {Qc3_Alg_Block_Cipher, Qc3_AES, 16, \ Qc3_CTR, 16} -#define _libssh2_cipher_aes192ctr {Qc3_Alg_Block_Cipher, Qc3_AES, 24, \ +#define _libssh2_cipher_aes192ctr {Qc3_Alg_Block_Cipher, Qc3_AES, 16, \ Qc3_CTR, 24} -#define _libssh2_cipher_aes256ctr {Qc3_Alg_Block_Cipher, Qc3_AES, 32, \ +#define _libssh2_cipher_aes256ctr {Qc3_Alg_Block_Cipher, Qc3_AES, 16, \ Qc3_CTR, 32} -#define _libssh2_cipher_3des {Qc3_Alg_Block_Cipher, Qc3_TDES, 0, \ +#define _libssh2_cipher_3des {Qc3_Alg_Block_Cipher, Qc3_TDES, 8, \ Qc3_CBC, 24} -#define _libssh2_cipher_arcfour {Qc3_Alg_Stream_Cipher, Qc3_RC4, 0, 0, 16} +#define _libssh2_cipher_arcfour {Qc3_Alg_Stream_Cipher, Qc3_RC4, 8, 0, 16} #define _libssh2_cipher_dtor(ctx) _libssh2_os400qc3_crypto_dtor(ctx) @@ -338,8 +338,22 @@ typedef struct { /* Diffie-Hellman context. */ #define libssh2_prepare_iovec(vec, len) memset((char *) (vec), 0, \ (len) * sizeof(struct iovec)) #define _libssh2_rsa_sha1_signv(session, sig, siglen, count, vector, ctx) \ - _libssh2_os400qc3_rsa_sha1_signv(session, sig, siglen, \ + _libssh2_os400qc3_rsa_signv(session, Qc3_SHA1, sig, siglen, \ count, vector, ctx) +#define _libssh2_rsa_sha2_256_signv(session, sig, siglen, cnt, vector, ctx) \ + _libssh2_os400qc3_rsa_signv(session, Qc3_SHA256, sig, siglen, \ + cnt, vector, ctx) +#define _libssh2_rsa_sha2_512_signv(session, sig, siglen, cnt, vector, ctx) \ + _libssh2_os400qc3_rsa_signv(session, Qc3_SHA512, sig, siglen, \ + cnt, vector, ctx) + +/* Default generate and safe prime sizes for diffie-hellman-group-exchange-sha1 + Qc3 is limited to a maximum 2048-bit modulus/key size. */ +#define LIBSSH2_DH_GEX_MINGROUP 1024 +#define LIBSSH2_DH_GEX_OPTGROUP 1536 +#define LIBSSH2_DH_GEX_MAXGROUP 2048 + +#define LIBSSH2_DH_MAX_MODULUS_BITS 2048 #define _libssh2_dh_ctx _libssh2_os400qc3_dh_ctx #define libssh2_dh_init(dhctx) _libssh2_os400qc3_dh_init(dhctx) @@ -383,12 +397,12 @@ extern void libssh2_os400qc3_hmac_update(_libssh2_os400qc3_crypto_ctx *ctx, int len); extern void libssh2_os400qc3_hmac_final(_libssh2_os400qc3_crypto_ctx *ctx, unsigned char *out); -extern int _libssh2_os400qc3_rsa_sha1_signv(LIBSSH2_SESSION *session, - unsigned char **signature, - size_t *signature_len, - int veccount, - const struct iovec vector[], - libssh2_rsa_ctx *ctx); +extern int _libssh2_os400qc3_rsa_signv(LIBSSH2_SESSION *session, int algo, + unsigned char **signature, + size_t *signature_len, + 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, diff --git a/src/userauth_kbd_packet.c b/src/userauth_kbd_packet.c index 56cd0efe..29868387 100644 --- a/src/userauth_kbd_packet.c +++ b/src/userauth_kbd_packet.c @@ -44,6 +44,7 @@ int userauth_keyboard_interactive_decode_info_request(LIBSSH2_SESSION *session) size_t language_tag_len; unsigned int i; unsigned char packet_type; + uint32_t tmp_u32; struct string_buf decoded; @@ -95,7 +96,8 @@ int userauth_keyboard_interactive_decode_info_request(LIBSSH2_SESSION *session) } /* int num-prompts */ - if(_libssh2_get_u32(&decoded, &session->userauth_kybd_num_prompts) == -1) { + if(_libssh2_get_u32(&decoded, &tmp_u32) == -1 || + (session->userauth_kybd_num_prompts = tmp_u32) != tmp_u32) { _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, "Unable to decode " "keyboard-interactive number of keyboard prompts"); diff --git a/src/wincng.h b/src/wincng.h index 32410d1e..94aeef75 100644 --- a/src/wincng.h +++ b/src/wincng.h @@ -423,6 +423,14 @@ _libssh2_bn *_libssh2_wincng_bignum_init(void); * Windows CNG backend: Diffie-Hellman support */ +/* Default generate and safe prime sizes for + diffie-hellman-group-exchange-sha1 */ +#define LIBSSH2_DH_GEX_MINGROUP 2048 +#define LIBSSH2_DH_GEX_OPTGROUP 4096 +#define LIBSSH2_DH_GEX_MAXGROUP 8192 + +#define LIBSSH2_DH_MAX_MODULUS_BITS 16384 + typedef struct { /* holds our private and public key components */ BCRYPT_KEY_HANDLE dh_handle;