Skip to content

Commit

Permalink
Add minimal support for ssl module using Mbed TLS and sockets
Browse files Browse the repository at this point in the history
Add support for ssl client in binary and passive modes, with no certificate
verification

Add APIs to otp_socket so it can be called from ssl bio callbacks

Fix a bug in lwIP otp_socket's recv revealed by ssl tests

Fix a bug in BSD otp_socket's recvfrom revealed by refactoring

Fix a bug in esp32 tests where main context and its resources were not properly
destroyed

Update documentation and workflows to reflect the requirement on Mbed TLS

Fix exported types of inet module

Signed-off-by: Paul Guyot <pguyot@kallisys.net>
  • Loading branch information
pguyot committed Nov 6, 2023
1 parent f908ef4 commit 71cc082
Show file tree
Hide file tree
Showing 35 changed files with 2,157 additions and 221 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-and-test-macos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
submodules: 'recursive'

- name: "Install deps"
run: brew install gperf doxygen erlang@${{ matrix.otp }} ninja
run: brew install gperf doxygen erlang@${{ matrix.otp }} ninja mbedtls

# Builder info
- name: "System info"
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/build-and-test-on-freebsd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ jobs:
echo "%%"
echo "**freebsd-version:**"
freebsd-version
sudo pkg install -y cmake gperf erlang elixir
sudo pkg install -y cmake gperf erlang elixir mbedtls
echo "**uname:**"
uname -a
echo "**C Compiler version:**"
Expand All @@ -73,7 +73,7 @@ jobs:
echo "%%"
mkdir build
cd build
cmake ..
cmake .. -DMBEDTLS_ROOT_DIR=/usr/local
echo "%%"
echo "%% Building AtomVM ..."
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-and-test-other.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ jobs:
apt update &&
apt install -y -t stretch-backports-sloppy libarchive13 &&
apt install -y -t stretch-backports cmake &&
apt install -y file gcc g++ binutils make doxygen gperf zlib1g-dev libssl-dev
apt install -y file gcc g++ binutils make doxygen gperf zlib1g-dev libssl-dev libmbedtls-dev
- arch: "arm32v7"
platform: "arm/v7"
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/build-and-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ jobs:
cmake_opts_other: "-DOPENSSL_CRYPTO_LIBRARY=/usr/lib/i386-linux-gnu/libcrypto.so -DAVM_CREATE_STACKTRACES=off"
arch: "i386"
compiler_pkgs: "gcc-10 g++-10 gcc-10-multilib g++-10-multilib libc6-dev-i386
libc6-dbg:i386 zlib1g-dev:i386 libssl-dev:i386"
libc6-dbg:i386 zlib1g-dev:i386 libssl-dev:i386 libmbedtls-dev:i386"

env:
CC: ${{ matrix.cc }}
Expand Down Expand Up @@ -202,7 +202,7 @@ jobs:
run: sudo apt update -y

- name: "Install deps"
run: sudo apt install -y ${{ matrix.compiler_pkgs}} cmake gperf zlib1g-dev doxygen valgrind
run: sudo apt install -y ${{ matrix.compiler_pkgs}} cmake gperf zlib1g-dev doxygen valgrind libmbedtls-dev

# Builder info
- name: "System info"
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added support for interrupts to STM32 GPIO port driver.
- Added suppoprt for PicoW extra gpio pins (led) to the gpio driver.
- Added support for `net:getaddrinfo/1,2`
- Added minimal support for the OTP `ssl` interface.

## [0.6.0-alpha.1] - 2023-10-09

Expand Down
97 changes: 97 additions & 0 deletions CMakeModules/MbedTLS.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#
# This file is part of AtomVM.
#
# Copyright 2023 Paul Guyot <pguyot@kallisys.net>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
#

# Find MbedTLS
# Search for MbedTLS 2.x or 3.x and define libraries like MbedTLS 3.x does.

# This script is not called FindMbedTLS.cmake because it would conflict with
# installed MbedTLS 3.x

# If MBEDTLS_ROOT_DIR is set, no heuristic is applied.
# It must be set to the parent directory of include/mbedtls/version.h
# Libraries are at ${MBEDTLS_LIBRARIES_DIR} or, if unset, ${MBEDTLS_ROOT_DIR}/lib/

# If MBEDTLS_ROOT_DIR is not set, apply the following heuristic:
# Try to find mbedtls 3.x CMake package with find_package
# If it doesn't work, search for MBEDTLS_VERSION_NUMBER symbol as well as
# the three libraries we need with check_symbol_exists and find_library

if (MBEDTLS_ROOT_DIR)
set(MbedTLS_FOUND TRUE)
if (NOT MBEDTLS_LIBRARIES_DIR)
set(MBEDTLS_LIBRARIES_DIR ${MBEDTLS_ROOT_DIR}/lib)
endif()
message(STATUS "Will use MbedTLS from ${MBEDTLS_ROOT_DIR} and ${MBEDTLS_LIBRARIES_DIR}")

add_library(MbedTLS::mbedcrypto SHARED IMPORTED)
set_target_properties(MbedTLS::mbedcrypto PROPERTIES
IMPORTED_LOCATION "${MBEDTLS_LIBRARIES_DIR}/libmbedcrypto${CMAKE_SHARED_LIBRARY_SUFFIX}"
INTERFACE_INCLUDE_DIRECTORIES "${MBEDTLS_ROOT_DIR}/include/"
)

add_library(MbedTLS::mbedx509 SHARED IMPORTED)
set_target_properties(MbedTLS::mbedx509 PROPERTIES
IMPORTED_LOCATION "${MBEDTLS_LIBRARIES_DIR}/libmbedx509${CMAKE_SHARED_LIBRARY_SUFFIX}"
INTERFACE_INCLUDE_DIRECTORIES "${MBEDTLS_ROOT_DIR}/include/"
INTERFACE_LINK_LIBRARIES "MbedTLS::mbedcrypto"
)

add_library(MbedTLS::mbedtls SHARED IMPORTED)
set_target_properties(MbedTLS::mbedtls PROPERTIES
IMPORTED_LOCATION "${MBEDTLS_LIBRARIES_DIR}/libmbedtls${CMAKE_SHARED_LIBRARY_SUFFIX}"
INTERFACE_INCLUDE_DIRECTORIES "${MBEDTLS_ROOT_DIR}/include/"
INTERFACE_LINK_LIBRARIES "MbedTLS::mbedx509"
)
else()
# MbedTLS 3.x is installed as a CMake package
find_package(MbedTLS QUIET)
if (MbedTLS_FOUND)
message(STATUS "Found MbedTLS package ${MbedTLS_FOUND}")
else()
include(CheckSymbolExists)
check_symbol_exists(MBEDTLS_VERSION_NUMBER "mbedtls/version.h" HAVE_MBEDTLS_VERSION_NUMBER)
find_library(MBEDCRYPTO mbedcrypto)
find_library(MBEDX509 mbedx509)
find_library(MBEDTLS mbedtls)
if (HAVE_MBEDTLS_VERSION_NUMBER
AND NOT ${MBEDCRYPTO} STREQUAL "MBEDCRYPTO-NOTFOUND"
AND NOT ${MBEDX509} STREQUAL "MBEDX509-NOTFOUND"
AND NOT ${MBEDTLS} STREQUAL "MBEDTLS-NOTFOUND")
message(STATUS "Found MbedTLS with mbedcrypto ${MBEDCRYPTO}, mbedx509 ${MBEDX509} and mbedtls ${MBEDTLS}")
set(MbedTLS_FOUND TRUE)
add_library(MbedTLS::mbedcrypto SHARED IMPORTED)
set_target_properties(MbedTLS::mbedcrypto PROPERTIES
IMPORTED_LOCATION "${MBEDCRYPTO}"
)

add_library(MbedTLS::mbedx509 SHARED IMPORTED)
set_target_properties(MbedTLS::mbedx509 PROPERTIES
IMPORTED_LOCATION "${MBEDX509}"
INTERFACE_LINK_LIBRARIES "MbedTLS::mbedcrypto"
)

add_library(MbedTLS::mbedtls SHARED IMPORTED)
set_target_properties(MbedTLS::mbedtls PROPERTIES
IMPORTED_LOCATION "${MBEDTLS}"
INTERFACE_LINK_LIBRARIES "MbedTLS::mbedx509"
)
endif()
endif()
endif()
1 change: 1 addition & 0 deletions README.Md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Required for building:
* gperf ([GNU Perfect Hash Function Generator](https://www.gnu.org/software/gperf/manual/gperf.html))
* erlc ([erlang compiler](https://www.erlang.org/))
* elixirc ([elixir compiler](https://elixir-lang.org))
* Mbed TLS ([portable TLS library, optionally required to support SSL](https://www.trustedfirmware.org/projects/mbed-tls/))
* zlib ([zlib compression and decompression library](https://zlib.net/))

Documentation and Coverage:
Expand Down
1 change: 1 addition & 0 deletions doc/src/build-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ The following software is required in order to build AtomVM in generic UNIX syst
* `make`
* `gperf`
* `zlib`
* `Mbed TLS`
* Erlang/OTP compiler (`erlc`)
* Elixir compiler

Expand Down
1 change: 1 addition & 0 deletions libs/estdlib/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ set(ERLANG_MODULES
logger_std_h
proplists
socket
ssl
string
timer
unicode
Expand Down
2 changes: 1 addition & 1 deletion libs/estdlib/src/gen_tcp.erl
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
%% @end
%%-----------------------------------------------------------------------------
-spec connect(
Address :: inet:address() | inet:hostname(),
Address :: inet:ip_address() | inet:hostname(),
Port :: inet:port_number(),
Options :: [connect_option()]
) ->
Expand Down
6 changes: 3 additions & 3 deletions libs/estdlib/src/gen_udp.erl
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ open(PortNum, Options) ->
%%-----------------------------------------------------------------------------
-spec send(
Socket :: inet:socket(),
Address :: inet:address(),
Address :: inet:ip_address(),
PortNum :: inet:port_number(),
Packet :: packet()
) -> ok | {error, reason()}.
Expand All @@ -121,7 +121,7 @@ send(Socket, Address, PortNum, Packet) ->
%% @end
%%-----------------------------------------------------------------------------
-spec recv(Socket :: inet:socket(), Length :: non_neg_integer()) ->
{ok, {inet:address(), inet:port_number(), packet()}} | {error, reason()}.
{ok, {inet:ip_address(), inet:port_number(), packet()}} | {error, reason()}.
recv(Socket, Length) ->
recv(Socket, Length, infinity).

Expand All @@ -143,7 +143,7 @@ recv(Socket, Length) ->
%% @end
%%-----------------------------------------------------------------------------
-spec recv(Socket :: inet:socket(), Length :: non_neg_integer(), Timeout :: timeout()) ->
{ok, {inet:address(), inet:port_number(), packet()}} | {error, reason()}.
{ok, {inet:ip_address(), inet:port_number(), packet()}} | {error, reason()}.
recv(Socket, Length, Timeout) ->
call(Socket, {recvfrom, Length, Timeout}).

Expand Down
13 changes: 7 additions & 6 deletions libs/estdlib/src/inet.erl
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,11 @@

-type port_number() :: 0..65535.
-type socket() :: pid().
-type address() :: ipv4_address().
-type ipv4_address() :: {octet(), octet(), octet(), octet()}.
-type octet() :: 0..255.
-type ip_address() :: ip4_address().
-type ip4_address() :: {0..255, 0..255, 0..255, 0..255}.
-type hostname() :: iodata().

-export_type([socket/0, port_number/0, address/0, ipv4_address/0, octet/0, hostname/0]).
-export_type([socket/0, port_number/0, ip_address/0, ip4_address/0, hostname/0]).

%%-----------------------------------------------------------------------------
%% @param Socket the socket from which to obtain the port number
Expand Down Expand Up @@ -61,7 +60,8 @@ close(Socket) ->
%% This function should be called on a running socket instance.
%% @end
%%-----------------------------------------------------------------------------
-spec sockname(Socket :: socket()) -> {ok, {address(), port_number()}} | {error, Reason :: term()}.
-spec sockname(Socket :: socket()) ->
{ok, {ip_address(), port_number()}} | {error, Reason :: term()}.
sockname(Socket) ->
call(Socket, {sockname}).

Expand All @@ -72,7 +72,8 @@ sockname(Socket) ->
%% This function should be called on a running socket instance.
%% @end
%%-----------------------------------------------------------------------------
-spec peername(Socket :: socket()) -> {ok, {address(), port_number()}} | {error, Reason :: term()}.
-spec peername(Socket :: socket()) ->
{ok, {ip_address(), port_number()}} | {error, Reason :: term()}.
peername(Socket) ->
call(Socket, {peername}).

Expand Down
Loading

0 comments on commit 71cc082

Please sign in to comment.