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 resoures 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 <[email protected]>
  • Loading branch information
pguyot committed Nov 5, 2023
1 parent b15cb45 commit 70d8d4d
Show file tree
Hide file tree
Showing 36 changed files with 2,138 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
2 changes: 1 addition & 1 deletion .github/workflows/build-and-test-on-freebsd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:
echo "%%"
echo "**freebsd-version:**"
freebsd-version
sudo pkg install -y curl cmake gperf erlang elixir
sudo pkg install -y curl cmake gperf erlang elixir mbedtls
echo "**uname:**"
uname -a
echo "**C Compiler version:**"
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
2 changes: 1 addition & 1 deletion .github/workflows/build-and-test.yaml
Original file line number Diff line number Diff line change
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
90 changes: 90 additions & 0 deletions CMakeModules/MbedTLS.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#
# This file is part of AtomVM.
#
# Copyright 2019 Riccardo Binetti <[email protected]>
#
# 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 thre 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()

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 (NOT MbedTLS_FOUND)
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_NOTFOUND AND NOT MBEDX509_NOTFOUND AND NOT MBEDTLS_NOTFOUND)
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 70d8d4d

Please sign in to comment.