Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add IPv6 support #294

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions app/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#define STORAGE_NAMESPACE "storage"
#define OWNERSHIP_TRANSFER_FILE "data/owner_transfer"
#define ERROR_RETRY_COUNT 5
#define MAX_INTERFACE_SIZE 12

static bool is_ownership_transfer(bool do_resale)
{
Expand Down Expand Up @@ -271,20 +272,26 @@ int app_main(bool is_resale)
#if defined SELF_SIGNED_CERTS_SUPPORTED
useSelfSignedCerts = true;
LOG(LOG_INFO, "Set connection for self signed "
"certificate usage.\n");
"certificate usage.\n");
#endif
} else if (!strcmp_s((char *)argv[index], DATA_CONTENT_SIZE,
"-r", &strcmp_res) &&
!strcmp_res) {
resale = true;
} else if (!strcmp_s((char *)argv[index], MAX_INTERFACE_SIZE,
"-interface", &strcmp_res) &&
!strcmp_res) {
index++;
curl_interface = argv[index];
} else {
printf("Usage: linux-client -ip <http|https>://<mfg "
"addr>:<port>\n"
"\tif -ip not specified, manufacturer_addr.bin "
"will be used\n"
"\t-ss: specify if backend servers are using "
"self-signed certificates\n"
"\t-r: enable resale\n");
"\t-r: enable resale\n"
"\t-interface: ethernet interface\n");
exit(1);
}
}
Expand Down
5 changes: 4 additions & 1 deletion docs/cse.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,11 @@ After a successful compilation, the Intel<sup>&reg;</sup> CSE enabled FDO Client
>if -ip not specified, manufacturer_addr.bin will be used
>-ss: specify if backend servers are using self-signed certificates
>-r: enable resale
>-interface: ethernet interface
>```
>

>***NOTE***: For IPv6 link-local addresses (addresses starting with fe80::), you must specify the interface because these addresses are only valid within a single network segment. The interface identifier helps the system determine which network segment to use.

> ***NOTE***: To do the DI again we need to clear the Device status from CSE storage.
> To clear the storage, compile the code with "-DCSE_CLEAR=true" flag and then execute the following command
```shell
Expand Down
3 changes: 3 additions & 0 deletions docs/linux.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,4 +236,7 @@ After a successful compilation, the FDO Client SDK Linux device executable can b
>if -ip not specified, manufacturer_addr.bin will be used
>-ss: specify if backend servers are using self-signed certificates
>-r: enable resale
>-interface: ethernet interface
>```

>***NOTE***: For IPv6 link-local addresses (addresses starting with fe80::), you must specify the interface because these addresses are only valid within a single network segment. The interface identifier helps the system determine which network segment to use.
3 changes: 3 additions & 0 deletions docs/tpm.md
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,11 @@ After a successful compilation, the FDO Client SDK Linux device executable can b
>if -ip not specified, manufacturer_addr.bin will be used
>-ss: specify if backend servers are using self-signed certificates
>-r: enable resale
>-interface: ethernet interface
>```

>***NOTE***: For IPv6 link-local addresses (addresses starting with fe80::), you must specify the interface because these addresses are only valid within a single network segment. The interface identifier helps the system determine which network segment to use.

> ***NOTE***: linux-client may require elevated privileges. Please use 'sudo' to execute.
> ***NOTE***: To do the DI again we need to clear the Device status from TPM storage.
> To clear the TPM storage, execute the clear TPM* script. Refer to [Clear TPM](../utils/clear_tpm_nv.sh).
Expand Down
3 changes: 3 additions & 0 deletions include/fdo.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ extern bool use_mfg_addr_bin;
extern bool useSelfSignedCerts;
#endif

extern bool is_ipv6;
extern char *curl_interface;

fdo_sdk_status fdo_sdk_run(void);

fdo_sdk_status fdo_sdk_resale(void);
Expand Down
2 changes: 1 addition & 1 deletion lib/credentials_from_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1033,7 +1033,7 @@ bool load_device_status(fdo_sdk_device_status *state)
*state = FDO_DEVICE_STATE_PC;
} else {
LOG(LOG_DEBUG, "DeviceCredential is non-empty. Set state to "
"run TO1/TO2\n");
"run TO1/TO2\n");
// No Device state is being set currently
}
return true;
Expand Down
75 changes: 60 additions & 15 deletions lib/fdo.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "safe_lib.h"
#include "fdodeviceinfo.h"
#include <ctype.h>
#include <arpa/inet.h>
#if defined(DEVICE_CSE_ENABLED)
#include <linux/mei.h>
#include <metee.h>
Expand Down Expand Up @@ -54,6 +55,8 @@ typedef struct app_data_s {
static app_data_t *g_fdo_data = NULL;
extern int g_argc;
extern char **g_argv;
bool is_ipv6 = false;
char *curl_interface = NULL;

char *mfg_addr = NULL;
bool use_mfg_addr_bin = true;
Expand Down Expand Up @@ -969,24 +972,50 @@ bool parse_manufacturer_address(char *buffer, size_t buffer_sz, bool *tls,
LOG(LOG_ERROR, "memset failed\n");
goto end;
}
while (buffer[index] != ':' && (dns_index < mfg_dns_sz - 1) &&
index < buffer_sz) {
if (!isalnum(buffer[index]) && buffer[index] != '-' &&
buffer[index] != '.') {
LOG(LOG_ERROR, "Invalid DNS/IP or missing separator in "
"Manufacturer address\n");
goto end;
} else {
mfg_dns[dns_index] = buffer[index];
if (isalpha(buffer[index])) {
count_dns_alphabets++;

// remove '[]' from the network address if present
if (buffer[index] == '[') {
index++;
while (buffer[index] != ']' && (dns_index < mfg_dns_sz - 1) &&
index < buffer_sz) {
if (!isalnum(buffer[index]) && buffer[index] != '-' &&
buffer[index] != '.' && buffer[index] != ':') {
LOG(LOG_ERROR,
"Invalid DNS/IP or missing separator in "
"Manufacturer address\n");
goto end;
} else {
mfg_dns[dns_index] = buffer[index];
if (isalpha(buffer[index])) {
count_dns_alphabets++;
}
}
index++;
dns_index++;
}
index++;
dns_index++;
} else {
while (buffer[index] != ':' && (dns_index < mfg_dns_sz - 1) &&
index < buffer_sz) {
if (!isalnum(buffer[index]) && buffer[index] != '-' &&
buffer[index] != '.') {
LOG(LOG_ERROR,
"Invalid DNS/IP or missing separator in "
"Manufacturer address\n");
goto end;
} else {
mfg_dns[dns_index] = buffer[index];
if (isalpha(buffer[index])) {
count_dns_alphabets++;
}
}
index++;
dns_index++;
}
}

if (!isalnum(mfg_dns[0]) || !isalnum(mfg_dns[dns_index - 1])) {
if ((!isalnum(mfg_dns[0]) && mfg_dns[0] != ':') ||
!isalnum(mfg_dns[dns_index - 1])) {
LOG(LOG_ERROR, "Invalid DNS/IP in Manufacturer address\n");
goto end;
}
Expand Down Expand Up @@ -1059,9 +1088,21 @@ bool parse_manufacturer_address(char *buffer, size_t buffer_sz, bool *tls,

// validate IP/DNS, check for IP first, if it fails, treat it as DNS
// allocate IP structure here
// if a valid IP is found, return the IP structure conatining IP, that
// if a valid IP is found, return the IP structure containing IP, that
// must be freed by caller if a valid IP is not found, free the IP
// structure immediately and return NULL IP structure
int ip_info = check_ip_version(mfg_dns);

if (ip_info == AF_INET) {
LOG(LOG_INFO, "%s is an ipv4 address\n", mfg_dns);
} else if (ip_info == AF_INET6) {
LOG(LOG_INFO, "%s is an ipv6 address\n", mfg_dns);
is_ipv6 = true;
} else {
LOG(LOG_DEBUG, "%s is an unknown address format %d\n", mfg_dns,
ip_info);
}

*mfg_ip = fdo_ipaddress_alloc();
if (!*mfg_ip) {
LOG(LOG_ERROR, "Failed to alloc memory\n");
Expand All @@ -1071,7 +1112,11 @@ bool parse_manufacturer_address(char *buffer, size_t buffer_sz, bool *tls,
result = fdo_printable_to_net(mfg_dns, (*mfg_ip)->addr);
if (result > 0) {
// valid IP address
(*mfg_ip)->length = IPV4_ADDR_LEN;
if (is_ipv6) {
(*mfg_ip)->length = IPV6_ADDR_LEN;
} else {
(*mfg_ip)->length = IPV4_ADDR_LEN;
}
LOG(LOG_DEBUG, "Manufacturer IP will be used\n");
} else if (result == 0) {
// not an IP address, so treat it as DNS address
Expand Down
34 changes: 26 additions & 8 deletions lib/fdonet.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,25 +361,37 @@ void fdo_net_init(void)
* @return ret
* true if successful. false in case of error.
*/
bool resolve_dn(const char *dn, fdo_ip_address_t **ip, uint16_t port, bool tls,
bool resolve_dn(char *dn, fdo_ip_address_t **ip, uint16_t port, bool tls,
bool proxy)
{
bool ret = false;
int connect_ok = -1;
uint32_t num_ofIPs = 0;
fdo_ip_address_t *ip_list = NULL;
rest_ctx_t *rest = NULL;
int dn_size = 0;

if (!dn || !ip) {
LOG(LOG_ERROR, "Invalid inputs\n");
goto end;
}

// Remove '[]' from IPv6 domain name
dn_size = strnlen_s(dn, HTTP_MAX_URL_SIZE);

if (dn[0] == '[' && dn[dn_size - 1] == ']') {
int i;
for (i = 1; i < dn_size - 1; i++) {
dn[i - 1] = dn[i];
}
dn[i - 1] = '\0';
}

/* DNS is non-NULL, */
LOG(LOG_DEBUG, "using DNS: %s\n", dn);

if (proxy) {

/* cache DNS to REST */
/* Cache DNS to REST */
rest = get_rest_context();

if (!rest) {
Expand All @@ -394,7 +406,8 @@ bool resolve_dn(const char *dn, fdo_ip_address_t **ip, uint16_t port, bool tls,
}
goto end;
}
// get list of IPs resolved to given DNS

// Get list of IPs resolved to given DNS
if (fdo_con_dns_lookup(dn, &ip_list, &num_ofIPs) == -1) {
LOG(LOG_ERROR, "DNS look-up failed!\n");
goto end;
Expand All @@ -405,13 +418,18 @@ bool resolve_dn(const char *dn, fdo_ip_address_t **ip, uint16_t port, bool tls,
uint32_t iter = 0;

while (iter != num_ofIPs && connect_ok == -1) {

curl = curl_easy_init();
if (!curl) {
LOG(LOG_ERROR, "curl_easy_init() failed!\n");
goto end;
}

connect_ok =
fdo_con_connect((ip_list + iter), dn, port, tls);
if (connect_ok == -1) {
LOG(LOG_ERROR, "Failed to connect to "
"server: retrying...\n");
LOG(LOG_ERROR, "Failed to connect to server: "
"retrying...\n");
// curl_easy_cleanup(curl);
}
iter++;
}
Expand Down Expand Up @@ -441,7 +459,7 @@ bool resolve_dn(const char *dn, fdo_ip_address_t **ip, uint16_t port, bool tls,
}
}
end:
if (ip_list) { // free ip_list
if (ip_list) { // Free ip_list
fdo_free(ip_list);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/fdotypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1001,7 +1001,7 @@ bool fdo_read_ipaddress(fdor_t *fdor, fdo_ip_address_t *fdoip)

size_t ip_length;
if (!fdor_string_length(fdor, &ip_length) ||
ip_length != IPV4_ADDR_LEN) {
(ip_length != IPV6_ADDR_LEN && ip_length != IPV4_ADDR_LEN)) {
LOG(LOG_ERROR, "Invalid IP Address length\n");
fdo_byte_array_free(IP);
return false;
Expand Down
2 changes: 1 addition & 1 deletion lib/include/fdonet.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ bool is_owner_proxy_defined(void);
bool setup_http_proxy(const char *filename, fdo_ip_address_t *fdoip,
uint16_t *port_num);

bool resolve_dn(const char *dn, fdo_ip_address_t **ip, uint16_t port, bool tls,
bool resolve_dn(char *dn, fdo_ip_address_t **ip, uint16_t port, bool tls,
bool proxy);

bool connect_to_manufacturer(fdo_ip_address_t *ip, const char *dn,
Expand Down
2 changes: 1 addition & 1 deletion lib/include/fdoprot.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ typedef struct fdo_prot_s {
fdo_dev_cred_t *dev_cred;
fdo_public_key_t *owner_public_key; // Owner's public key
fdo_service_info_t *service_info; // store System ServiceInfo
// (devmod+unsupported module list)
// (devmod+unsupported module list)
fdo_byte_array_t *ext_service_info; // store External module
// ServiceInfoVal (fdo_sys, for ex.)
fdo_public_key_t *tls_key; // unused for now
Expand Down
3 changes: 2 additions & 1 deletion lib/include/fdotypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "fdoblockio.h"
#include "fdomodules.h"
#include <stddef.h>
#include <netinet/in.h>

/*
* Wrapper around a URL
Expand Down Expand Up @@ -119,7 +120,7 @@ typedef fdo_byte_array_t fdo_key_exchange_t;

typedef struct {
uint8_t length;
uint8_t addr[16];
uint8_t addr[INET6_ADDRSTRLEN];
} fdo_ip_address_t;

fdo_ip_address_t *fdo_ipaddress_alloc(void);
Expand Down
9 changes: 9 additions & 0 deletions network/include/network_al.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <stdint.h>
#include <stddef.h>
#define IPV4_ADDR_LEN 4
#define IPV6_ADDR_LEN 16
#define MAX_TIME_OUT 60000L

#ifndef TARGET_OS_MBEDOS
Expand Down Expand Up @@ -152,6 +153,14 @@ uint32_t fdo_host_to_net_long(uint32_t value);
/* Convert from ASCII to Network byte order format */
int32_t fdo_printable_to_net(const char *src, void *addr);

/**
* @brief Check the version of given IP address
*
* @param ip_addr input IP address
* @return int protocol family no. of socket
*/
int check_ip_version(char *ip_addr);

/* get device model number */
const char *get_device_model(void);

Expand Down
2 changes: 1 addition & 1 deletion network/include/rest_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
// maximum supported length is 64000 + 700.
#define REST_MAX_MSGBODY_SIZE MAX_SERVICEINFO_SZ + MSG_METADATA_SIZE
#define HTTP_SUCCESS_OK 200
#define IP_TAG_LEN 16 // e.g. 192.168.111.111
#define IP_TAG_LEN 46 // max IP length
#define MAX_PORT_SIZE 6 // max port size is 65536 + 1null char

#define ISASCII(ch) ((ch & ~0x7f) == 0)
Expand Down
Loading
Loading