diff options
Diffstat (limited to 'libs/libssh2/src/mbedtls.c')
-rw-r--r-- | libs/libssh2/src/mbedtls.c | 283 |
1 files changed, 205 insertions, 78 deletions
diff --git a/libs/libssh2/src/mbedtls.c b/libs/libssh2/src/mbedtls.c index 1d181e18ff..8bbcfd8d0d 100644 --- a/libs/libssh2/src/mbedtls.c +++ b/libs/libssh2/src/mbedtls.c @@ -1,9 +1,54 @@ +/* Copyright (c) 2016, Art <https://github.com/wildart> + * 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_MBEDTLS /* compile only if we build with mbedtls */ /*******************************************************************/ /* + * mbedTLS backend: Global context handles + */ + +static mbedtls_entropy_context _libssh2_mbedtls_entropy; +static mbedtls_ctr_drbg_context _libssh2_mbedtls_ctr_drbg; + +/*******************************************************************/ +/* * mbedTLS backend: Generic functions */ @@ -18,7 +63,7 @@ _libssh2_mbedtls_init(void) ret = mbedtls_ctr_drbg_seed(&_libssh2_mbedtls_ctr_drbg, mbedtls_entropy_func, &_libssh2_mbedtls_entropy, NULL, 0); - if (ret != 0) + if(ret != 0) mbedtls_ctr_drbg_free(&_libssh2_mbedtls_ctr_drbg); } @@ -44,11 +89,11 @@ _libssh2_mbedtls_safe_free(void *buf, int len) (void)len; #endif - if (!buf) + if(!buf) return; #ifdef LIBSSH2_CLEAR_MEMORY - if (len > 0) + if(len > 0) memset(buf, 0, len); #endif @@ -65,7 +110,7 @@ _libssh2_mbedtls_cipher_init(_libssh2_cipher_ctx *ctx, const mbedtls_cipher_info_t *cipher_info; int ret, op; - if (!ctx) + if(!ctx) return -1; op = encrypt == 0 ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT; @@ -99,11 +144,10 @@ _libssh2_mbedtls_cipher_crypt(_libssh2_cipher_ctx *ctx, (void) encrypt; (void) algo; - osize = blocklen+mbedtls_cipher_get_block_size(ctx); + osize = blocklen + mbedtls_cipher_get_block_size(ctx); output = (unsigned char *)mbedtls_calloc(osize, sizeof(char)); - if(output) - { + if(output) { ret = mbedtls_cipher_reset(ctx); if(!ret) @@ -112,7 +156,7 @@ _libssh2_mbedtls_cipher_crypt(_libssh2_cipher_ctx *ctx, if(!ret) ret = mbedtls_cipher_finish(ctx, output + olen, &finish_olen); - if (!ret) { + if(!ret) { olen += finish_olen; memcpy(block, output, olen); } @@ -148,8 +192,8 @@ _libssh2_mbedtls_hash_init(mbedtls_md_context_t *ctx, mbedtls_md_init(ctx); ret = mbedtls_md_setup(ctx, md_info, hmac); - if (!ret){ - if (hmac) + if(!ret) { + if(hmac) ret = mbedtls_md_hmac_starts(ctx, key, keylen); else ret = mbedtls_md_starts(ctx); @@ -196,50 +240,61 @@ _libssh2_mbedtls_bignum_init(void) _libssh2_bn *bignum; bignum = (_libssh2_bn *)mbedtls_calloc(1, sizeof(_libssh2_bn)); - if (bignum) { + if(bignum) { mbedtls_mpi_init(bignum); } return bignum; } -int +void +_libssh2_mbedtls_bignum_free(_libssh2_bn *bn) +{ + if(bn) { + mbedtls_mpi_free(bn); + mbedtls_free(bn); + } +} + +static int _libssh2_mbedtls_bignum_random(_libssh2_bn *bn, int bits, int top, int bottom) { size_t len; int err; int i; - if (!bn || bits <= 0) + if(!bn || bits <= 0) return -1; len = (bits + 7) >> 3; - err = mbedtls_mpi_fill_random(bn, len, mbedtls_ctr_drbg_random, &_libssh2_mbedtls_ctr_drbg); - if (err) + err = mbedtls_mpi_fill_random(bn, len, mbedtls_ctr_drbg_random, + &_libssh2_mbedtls_ctr_drbg); + if(err) return -1; /* Zero unsued bits above the most significant bit*/ - for(i=len*8-1;bits<=i;--i) { + for(i = len*8 - 1; bits <= i; --i) { err = mbedtls_mpi_set_bit(bn, i, 0); - if (err) + if(err) return -1; } - /* If `top` is -1, the most significant bit of the random number can be zero. - If top is 0, the most significant bit of the random number 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 `top` is -1, the most significant bit of the random number can be + zero. If top is 0, the most significant bit of the random number 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. */ - for(i=0;i<=top;++i) { + for(i = 0; i <= top; ++i) { err = mbedtls_mpi_set_bit(bn, bits-i-1, 1); - if (err) + if(err) return -1; } /* make odd by setting first bit in least significant byte */ - if (bottom) { + if(bottom) { err = mbedtls_mpi_set_bit(bn, 0, 1); - if (err) + if(err) return -1; } @@ -275,42 +330,40 @@ _libssh2_mbedtls_rsa_new(libssh2_rsa_ctx **rsa, libssh2_rsa_ctx *ctx; ctx = (libssh2_rsa_ctx *) mbedtls_calloc(1, sizeof(libssh2_rsa_ctx)); - if (ctx != NULL) { + if(ctx != NULL) { mbedtls_rsa_init(ctx, MBEDTLS_RSA_PKCS_V15, 0); } else return -1; - if( (ret = mbedtls_mpi_read_binary(&(ctx->E), edata, elen) ) != 0 || - (ret = mbedtls_mpi_read_binary(&(ctx->N), ndata, nlen) ) != 0 ) - { + /* !checksrc! disable ASSIGNWITHINCONDITION 1 */ + if((ret = mbedtls_mpi_read_binary(&(ctx->E), edata, elen) ) != 0 || + (ret = mbedtls_mpi_read_binary(&(ctx->N), ndata, nlen) ) != 0) { ret = -1; } - if (!ret) - { + if(!ret) { ctx->len = mbedtls_mpi_size(&(ctx->N)); } - if (!ret && ddata) - { - if( (ret = mbedtls_mpi_read_binary(&(ctx->D) , ddata, dlen) ) != 0 || - (ret = mbedtls_mpi_read_binary(&(ctx->P) , pdata, plen) ) != 0 || - (ret = mbedtls_mpi_read_binary(&(ctx->Q) , qdata, qlen) ) != 0 || - (ret = mbedtls_mpi_read_binary(&(ctx->DP), e1data, e1len) ) != 0 || - (ret = mbedtls_mpi_read_binary(&(ctx->DQ), e2data, e2len) ) != 0 || - (ret = mbedtls_mpi_read_binary(&(ctx->QP), coeffdata, coefflen) ) != 0 ) - { + if(!ret && ddata) { + /* !checksrc! disable ASSIGNWITHINCONDITION 1 */ + if((ret = mbedtls_mpi_read_binary(&(ctx->D), ddata, dlen) ) != 0 || + (ret = mbedtls_mpi_read_binary(&(ctx->P), pdata, plen) ) != 0 || + (ret = mbedtls_mpi_read_binary(&(ctx->Q), qdata, qlen) ) != 0 || + (ret = mbedtls_mpi_read_binary(&(ctx->DP), e1data, e1len) ) != 0 || + (ret = mbedtls_mpi_read_binary(&(ctx->DQ), e2data, e2len) ) != 0 || + (ret = mbedtls_mpi_read_binary(&(ctx->QP), coeffdata, coefflen) ) + != 0) { ret = -1; } ret = mbedtls_rsa_check_privkey(ctx); } - else if (!ret) - { + else if(!ret) { ret = mbedtls_rsa_check_pubkey(ctx); } - if (ret && ctx) { + if(ret && ctx) { _libssh2_mbedtls_rsa_free(ctx); ctx = NULL; } @@ -326,17 +379,17 @@ _libssh2_mbedtls_rsa_new_private(libssh2_rsa_ctx **rsa, { int ret; mbedtls_pk_context pkey; + mbedtls_rsa_context *pk_rsa; *rsa = (libssh2_rsa_ctx *) LIBSSH2_ALLOC(session, sizeof(libssh2_rsa_ctx)); - if (*rsa == NULL) + if(*rsa == NULL) return -1; mbedtls_rsa_init(*rsa, MBEDTLS_RSA_PKCS_V15, 0); mbedtls_pk_init(&pkey); ret = mbedtls_pk_parse_keyfile(&pkey, filename, (char *)passphrase); - if( ret != 0 || mbedtls_pk_get_type(&pkey) != MBEDTLS_PK_RSA) - { + if(ret != 0 || mbedtls_pk_get_type(&pkey) != MBEDTLS_PK_RSA) { mbedtls_pk_free(&pkey); mbedtls_rsa_free(*rsa); LIBSSH2_FREE(session, *rsa); @@ -344,7 +397,7 @@ _libssh2_mbedtls_rsa_new_private(libssh2_rsa_ctx **rsa, return -1; } - mbedtls_rsa_context *pk_rsa = mbedtls_pk_rsa(pkey); + pk_rsa = mbedtls_pk_rsa(pkey); mbedtls_rsa_copy(*rsa, pk_rsa); mbedtls_pk_free(&pkey); @@ -360,17 +413,33 @@ _libssh2_mbedtls_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa, { int ret; mbedtls_pk_context pkey; + mbedtls_rsa_context *pk_rsa; + void *filedata_nullterm; + size_t pwd_len; - *rsa = (libssh2_rsa_ctx *) mbedtls_calloc( 1, sizeof( libssh2_rsa_ctx ) ); - if (*rsa == NULL) + *rsa = (libssh2_rsa_ctx *) mbedtls_calloc(1, sizeof(libssh2_rsa_ctx)); + if(*rsa == NULL) return -1; + /* + mbedtls checks in "mbedtls/pkparse.c:1184" if "key[keylen - 1] != '\0'" + private-key from memory will fail if the last byte is not a null byte + */ + filedata_nullterm = mbedtls_calloc(filedata_len + 1, 1); + if(filedata_nullterm == NULL) { + return -1; + } + memcpy(filedata_nullterm, filedata, filedata_len); + mbedtls_pk_init(&pkey); - ret = mbedtls_pk_parse_key(&pkey, (unsigned char *)filedata, - filedata_len, NULL, 0); - if( ret != 0 || mbedtls_pk_get_type(&pkey) != MBEDTLS_PK_RSA) - { + pwd_len = passphrase != NULL ? strlen((const char *)passphrase) : 0; + ret = mbedtls_pk_parse_key(&pkey, (unsigned char *)filedata_nullterm, + filedata_len + 1, + passphrase, pwd_len); + _libssh2_mbedtls_safe_free(filedata_nullterm, filedata_len); + + if(ret != 0 || mbedtls_pk_get_type(&pkey) != MBEDTLS_PK_RSA) { mbedtls_pk_free(&pkey); mbedtls_rsa_free(*rsa); LIBSSH2_FREE(session, *rsa); @@ -378,7 +447,7 @@ _libssh2_mbedtls_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa, return -1; } - mbedtls_rsa_context *pk_rsa = mbedtls_pk_rsa(pkey); + pk_rsa = mbedtls_pk_rsa(pkey); mbedtls_rsa_copy(*rsa, pk_rsa); mbedtls_pk_free(&pkey); @@ -400,7 +469,8 @@ _libssh2_mbedtls_rsa_sha1_verify(libssh2_rsa_ctx *rsa, return -1; /* failure */ ret = mbedtls_rsa_pkcs1_verify(rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, - MBEDTLS_MD_SHA1, SHA_DIGEST_LENGTH, hash, sig); + MBEDTLS_MD_SHA1, SHA_DIGEST_LENGTH, + hash, sig); return (ret == 0) ? 0 : -1; } @@ -421,14 +491,14 @@ _libssh2_mbedtls_rsa_sha1_sign(LIBSSH2_SESSION *session, sig_len = rsa->len; sig = LIBSSH2_ALLOC(session, sig_len); - if (!sig) { + if(!sig) { return -1; } ret = mbedtls_rsa_pkcs1_sign(rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, SHA_DIGEST_LENGTH, hash, sig); - if (ret) { + if(ret) { LIBSSH2_FREE(session, sig); return -1; } @@ -453,8 +523,8 @@ gen_publickey_from_rsa(LIBSSH2_SESSION *session, { int e_bytes, n_bytes; unsigned long len; - unsigned char* key; - unsigned char* p; + unsigned char *key; + unsigned char *p; e_bytes = mbedtls_mpi_size(&rsa->E); n_bytes = mbedtls_mpi_size(&rsa->N); @@ -463,7 +533,7 @@ gen_publickey_from_rsa(LIBSSH2_SESSION *session, len = 4 + 7 + 4 + e_bytes + 4 + n_bytes; key = LIBSSH2_ALLOC(session, len); - if (!key) { + if(!key) { return NULL; } @@ -498,36 +568,38 @@ _libssh2_mbedtls_pub_priv_key(LIBSSH2_SESSION *session, unsigned char *key = NULL, *mth = NULL; size_t keylen = 0, mthlen = 0; int ret; + mbedtls_rsa_context *rsa; - if( mbedtls_pk_get_type(pkey) != MBEDTLS_PK_RSA ) - { + if(mbedtls_pk_get_type(pkey) != MBEDTLS_PK_RSA) { mbedtls_pk_free(pkey); return _libssh2_error(session, LIBSSH2_ERROR_FILE, "Key type not supported"); } - // write method + /* write method */ mthlen = 7; mth = LIBSSH2_ALLOC(session, mthlen); - if (mth) { + if(mth) { memcpy(mth, "ssh-rsa", mthlen); - } else { + } + else { ret = -1; } - mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pkey); + rsa = mbedtls_pk_rsa(*pkey); key = gen_publickey_from_rsa(session, rsa, &keylen); - if (key == NULL) { + if(key == NULL) { ret = -1; } - // write output - if (ret) { - if (mth) + /* write output */ + if(ret) { + if(mth) LIBSSH2_FREE(session, mth); - if (key) + if(key) LIBSSH2_FREE(session, key); - } else { + } + else { *method = mth; *method_len = mthlen; *pubkeydata = key; @@ -552,8 +624,7 @@ _libssh2_mbedtls_pub_priv_keyfile(LIBSSH2_SESSION *session, mbedtls_pk_init(&pkey); ret = mbedtls_pk_parse_keyfile(&pkey, privatekey, passphrase); - if( ret != 0 ) - { + if(ret != 0) { mbedtls_strerror(ret, (char *)buf, sizeof(buf)); mbedtls_pk_free(&pkey); return _libssh2_error(session, LIBSSH2_ERROR_FILE, buf); @@ -580,12 +651,29 @@ _libssh2_mbedtls_pub_priv_keyfilememory(LIBSSH2_SESSION *session, mbedtls_pk_context pkey; char buf[1024]; int ret; + void *privatekeydata_nullterm; + size_t pwd_len; + + /* + mbedtls checks in "mbedtls/pkparse.c:1184" if "key[keylen - 1] != '\0'" + private-key from memory will fail if the last byte is not a null byte + */ + privatekeydata_nullterm = mbedtls_calloc(privatekeydata_len + 1, 1); + if(privatekeydata_nullterm == NULL) { + return -1; + } + memcpy(privatekeydata_nullterm, privatekeydata, privatekeydata_len); mbedtls_pk_init(&pkey); - ret = mbedtls_pk_parse_key(&pkey, (unsigned char *)privatekeydata, - privatekeydata_len, NULL, 0); - if( ret != 0 ) - { + + pwd_len = passphrase != NULL ? strlen((const char *)passphrase) : 0; + ret = mbedtls_pk_parse_key(&pkey, + (unsigned char *)privatekeydata_nullterm, + privatekeydata_len + 1, + (const unsigned char *)passphrase, pwd_len); + _libssh2_mbedtls_safe_free(privatekeydata_nullterm, privatekeydata_len); + + if(ret != 0) { mbedtls_strerror(ret, (char *)buf, sizeof(buf)); mbedtls_pk_free(&pkey); return _libssh2_error(session, LIBSSH2_ERROR_FILE, buf); @@ -603,4 +691,43 @@ void _libssh2_init_aes_ctr(void) { /* no implementation */ } + + +/*******************************************************************/ +/* + * mbedTLS backend: Diffie-Hellman functions + */ + +void +_libssh2_dh_init(_libssh2_dh_ctx *dhctx) +{ + *dhctx = _libssh2_mbedtls_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 */ + _libssh2_mbedtls_bignum_random(*dhctx, group_order * 8 - 1, 0, -1); + mbedtls_mpi_exp_mod(public, g, *dhctx, p, NULL); + return 0; +} + +int +_libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret, + _libssh2_bn *f, _libssh2_bn *p) +{ + /* Compute the shared secret */ + mbedtls_mpi_exp_mod(secret, f, *dhctx, p, NULL); + return 0; +} + +void +_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx) +{ + _libssh2_mbedtls_bignum_free(*dhctx); + *dhctx = NULL; +} + #endif /* LIBSSH2_MBEDTLS */ |