static void cipher_encrypt(struct ssh_cipher_struct *cipher, void *in, void *out, unsigned long len) { size_t outlen = 0; size_t total_len = 0; int rc = 0; rc = mbedtls_cipher_update(&cipher->encrypt_ctx, in, len, out, &outlen); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update failed during encryption"); return; } total_len += outlen; if (total_len == len) { return; } rc = mbedtls_cipher_finish(&cipher->encrypt_ctx, (unsigned char *) out + outlen, &outlen); total_len += outlen; if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_finish failed during encryption"); return; } if (total_len != len) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update: output size %zu for %zu", outlen, len); return; } }
static void cipher_decrypt_cbc(struct ssh_cipher_struct *cipher, void *in, void *out, unsigned long len) { size_t outlen = 0; int rc = 0; rc = mbedtls_cipher_update(&cipher->decrypt_ctx, in, len, out, &outlen); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update failed during decryption"); return; } /* MbedTLS caches the last block when decrypting with cbc. * By calling finish the block is flushed to out, however the unprocessed * data counter is not reset. * Calling mbedtls_cipher_reset resets the unprocessed data counter. */ if (outlen == 0) { rc = mbedtls_cipher_finish(&cipher->decrypt_ctx, out, &outlen); } else if (outlen == len) { return; } else { rc = mbedtls_cipher_finish(&cipher->decrypt_ctx, (unsigned char *) out + outlen , &outlen); } if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_finish failed during decryption"); return; } rc = mbedtls_cipher_reset(&cipher->decrypt_ctx); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed during decryption"); return; } if (outlen != len) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update: output size %zu for %zu", outlen, len); return; } }
result_t Cipher::process(const mbedtls_operation_t operation, Buffer_base *data, obj_ptr<Buffer_base> &retVal) { int32_t ret; ret = mbedtls_cipher_setkey(&m_ctx, (unsigned char *)m_key.c_str(), (int32_t)m_key.length() * 8, operation); if (ret != 0) return CHECK_ERROR(_ssl::setError(ret)); ret = mbedtls_cipher_reset(&m_ctx); if (ret != 0) return CHECK_ERROR(_ssl::setError(ret)); exlib::string input; exlib::string output; unsigned char buffer[1024]; size_t olen, ilen, offset, block_size, data_size; data->toString(input); block_size = mbedtls_cipher_get_block_size(&m_ctx); data_size = input.length(); for (offset = 0; offset < data_size; offset += block_size) { ilen = ((uint32_t)data_size - offset > block_size) ? block_size : (uint32_t)(data_size - offset); ret = mbedtls_cipher_update(&m_ctx, (unsigned char *)input.c_str() + offset, ilen, buffer, &olen); if (ret != 0) { reset(); return CHECK_ERROR(_ssl::setError(ret)); } output.append((const char *)buffer, olen); } ret = mbedtls_cipher_finish(&m_ctx, buffer, &olen); reset(); if (ret != 0) return CHECK_ERROR(_ssl::setError(ret)); output.append((const char *)buffer, olen); retVal = new Buffer(output); return 0; }
int cipher_ctx_final(mbedtls_cipher_context_t *ctx, uint8_t *dst, int *dst_len) { size_t s_dst_len = *dst_len; if (!mbed_ok(mbedtls_cipher_finish(ctx, dst, &s_dst_len))) { return 0; } *dst_len = s_dst_len; return 1; }
int CipherContext::finish(State & state, mbedtls_cipher_context_t * context){ Stack * stack = state.stack; if (stack->is<LUA_TNUMBER>(1)){ size_t outputSize = stack->to<int>(1); unsigned char * output = new unsigned char[outputSize]; int result = mbedtls_cipher_finish(context, output, &outputSize); if (result == 0){ stack->pushLString(std::string(reinterpret_cast<char*>(output), outputSize)); } else{ stack->push<int>(result); } return 1; } return 0; }
int cipher_ctx_final_check_tag(mbedtls_cipher_context_t *ctx, uint8_t *dst, int *dst_len, uint8_t *tag, size_t tag_len) { #ifdef HAVE_AEAD_CIPHER_MODES size_t olen = 0; if (MBEDTLS_DECRYPT != ctx->operation) { return 0; } if (tag_len > SIZE_MAX) { return 0; } if (!mbed_ok(mbedtls_cipher_finish(ctx, dst, &olen))) { msg(D_CRYPT_ERRORS, "%s: cipher_ctx_final() failed", __func__); return 0; } if (olen > INT_MAX) { return 0; } *dst_len = olen; if (!mbed_ok(mbedtls_cipher_check_tag(ctx, (const unsigned char *) tag, tag_len))) { return 0; } return 1; #else /* ifdef HAVE_AEAD_CIPHER_MODES */ ASSERT(0); #endif /* HAVE_AEAD_CIPHER_MODES */ }
/* * Packet-oriented wrapper for non-AEAD modes */ int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen ) { int ret; size_t finish_olen; if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 ) return( ret ); if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 ) return( ret ); if( ( ret = mbedtls_cipher_update( ctx, input, ilen, output, olen ) ) != 0 ) return( ret ); if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 ) return( ret ); *olen += finish_olen; return( 0 ); }