├── .gitignore ├── LICENSE ├── examples ├── httpget.c ├── httppost.c └── lowerlevel.c ├── include └── internet.h ├── makefile ├── readme.md ├── src ├── internetce │ ├── arp.c │ ├── core.c │ ├── crypto │ │ ├── aes.asm │ │ ├── aes.c │ │ ├── generate_mult.py │ │ ├── hkdf.c │ │ ├── key_schedule.c │ │ ├── ports.asm │ │ ├── random.c │ │ ├── sha256.c │ │ └── x25519.asm │ ├── debug.c │ ├── dhcp.c │ ├── dns.c │ ├── ethernet.c │ ├── http.c │ ├── icmpv4.c │ ├── include │ │ ├── arp.h │ │ ├── core.h │ │ ├── crypto.h │ │ ├── debug.h │ │ ├── dhcp.h │ │ ├── dns.h │ │ ├── ethernet.h │ │ ├── http.h │ │ ├── icmpv4.h │ │ ├── ipv4.h │ │ ├── rndis.h │ │ ├── scheduler.h │ │ ├── tcp.h │ │ ├── tls.h │ │ ├── transport_layer.h │ │ ├── udp.h │ │ ├── usb.h │ │ └── utils.h │ ├── ipv4.c │ ├── rndis.c │ ├── scheduler.c │ ├── tcp.c │ ├── tls.c │ ├── transport_layer.c │ ├── udp.c │ ├── usb.c │ └── utils.asm └── minimal.c └── tests ├── makefile ├── sha256 ├── gen_sha256_autotest.py ├── makefile └── src │ └── sha256_test.c └── x25519 ├── gen_x25519_autotest.py ├── makefile └── src └── x25519_test.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | *.lto 15 | *.bin 16 | 17 | # Precompiled Headers 18 | *.gch 19 | *.pch 20 | 21 | # Libraries 22 | *.a 23 | *.la 24 | *.lo 25 | 26 | # Shared objects (inc. Windows DLLs) 27 | *.dll 28 | *.so 29 | *.so.* 30 | *.dylib 31 | 32 | # Executables 33 | *.exe 34 | *.out 35 | *.app 36 | *.i*86 37 | *.x86_64 38 | *.hex 39 | *.8xp 40 | 41 | # Debug files 42 | *.dSYM/ 43 | *.su 44 | *.idb 45 | *.pdb 46 | *.src 47 | *.bc 48 | 49 | # Kernel Module Compile Results 50 | *.mod* 51 | *.cmd 52 | .tmp_versions/ 53 | modules.order 54 | Module.symvers 55 | Mkfile.old 56 | dkms.conf 57 | 58 | # folders 59 | bin/* 60 | obj/* 61 | old/* 62 | !.vscode/* 63 | 64 | # dependancies 65 | !clibs.8xg 66 | !*.rom 67 | 68 | # JSON autotest files 69 | tests/**/*.json 70 | 71 | # Generated multiplication file 72 | src/internetce/crypto/mult256.asm 73 | -------------------------------------------------------------------------------- /examples/httpget.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Performs an HTTP GET request to www.perdu.com. Used features : 3 | * - Initializing and cleaning up the library. 4 | * - Performing an HTTP GET request. 5 | */ 6 | 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | int main(void) 15 | { 16 | os_ClrHome(); 17 | printf("WEB Connection... "); 18 | 19 | web_Init(); 20 | while(!web_Connected()) { 21 | web_WaitForEvents(); 22 | if(os_GetCSC()) { 23 | printf("Canceled!\n"); 24 | goto _end; 25 | } 26 | } 27 | printf("Done!\n"); 28 | 29 | printf("HTTP Request...\n"); 30 | http_data_t *data = NULL; 31 | web_status_t status = web_HTTPGet("geometrydash.fr.nf", &data, false); 32 | if(status == HTTP_STATUS_OK) { 33 | os_ClrHome(); 34 | printf("%.*s", data->size, data->data); 35 | } else { 36 | printf("Err %u: couldn't retrieve foreign data\n", status); 37 | } 38 | 39 | _end: 40 | while(!os_GetCSC()) {} 41 | web_Cleanup(); 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /examples/httppost.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Performs a HTTP POST request to a custom website. Used features : 3 | * - Performing a HTTP POST request. 4 | * 5 | * This is the content of the target file (post.php) : 6 | * \code 7 | * 10 | * \endcode 11 | */ 12 | 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | 20 | int main(void) 21 | { 22 | os_ClrHome(); 23 | printf("WEB Connection... "); 24 | 25 | web_Init(); 26 | while(!web_Connected() && !os_GetCSC()) { 27 | web_WaitForEvents(); 28 | } 29 | if(!web_Connected()) { 30 | printf("\nCanceled!\n"); 31 | goto _end; 32 | } 33 | printf("Done!\n"); 34 | 35 | printf("HTTP Request..."); 36 | http_data_t *data = NULL; 37 | web_status_t status = web_HTTPPost("geometrydash.fr.nf/internetce/post.php", &data, false, 2, "azer", "wesh", 38 | "83pce", "yeet"); 39 | if(status == HTTP_STATUS_OK) { 40 | os_ClrHome(); 41 | printf("%.*s", data->size, data->data); 42 | } else { 43 | printf("Err %u: couldn't retrieve foreign data\n", status); 44 | } 45 | 46 | _end: 47 | while(!os_GetCSC()) {} 48 | web_Cleanup(); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /examples/lowerlevel.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Sends a DNS request to Google DNS server (8.8.8.8). Used features : 3 | * - Listening a port. 4 | * - Using callbacks. 5 | * - Sending UDP datagrams. 6 | */ 7 | 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | static bool ended = false; 15 | 16 | void disp_hex(const void *addr, size_t len) { 17 | uint8_t *content = (uint8_t *)addr; 18 | for(size_t i = 0; i < len; i++) { 19 | if(i && i % 8 == 0) { 20 | printf("\n"); 21 | } 22 | printf("%.2X ", *(content + i)); 23 | } 24 | printf("\n"); 25 | } 26 | 27 | 28 | web_status_t user_dns_callback(web_port_t port, uint8_t protocol, void *msg, size_t length, web_callback_data_t *user_data) { 29 | (void)protocol; (void)length; 30 | msg_queue_t *queued = (msg_queue_t *)user_data; 31 | web_PopMessage(queued); 32 | 33 | disp_hex(msg, length); 34 | while(!os_GetCSC()) {} 35 | 36 | web_UnlistenPort(port); 37 | ended = true; 38 | return WEB_SUCCESS; 39 | } 40 | 41 | 42 | int main(void) 43 | { 44 | os_ClrHome(); 45 | printf("WEB Connection... "); 46 | 47 | web_Init(); 48 | while(!web_Connected() && !os_GetCSC()) { 49 | web_WaitForEvents(); 50 | } 51 | if(!web_Connected()) { 52 | printf("\nCanceled!\n"); 53 | while(!os_GetCSC()) {} 54 | goto _end; 55 | } 56 | printf("Done!\n"); 57 | 58 | /* Beginning of the DNS stuffs */ 59 | const char url[] = "www.perdu.com"; 60 | size_t length = sizeof(dns_message_t) + strlen(url) + 2 + 4; /* dns_message_t : CF internet.h */ 61 | uint8_t *query = calloc(length, 1); 62 | 63 | query[2] = 0x01; 64 | query[5] = 0x01; 65 | 66 | /* formating address for dns purposes */ 67 | char *cursor_qry = (char *)(query + sizeof(dns_message_t) + 1); 68 | const char *cursor_str = url; 69 | uint8_t i = 1; 70 | while(*cursor_str) { 71 | if(*cursor_str == '.') { 72 | *(cursor_qry - i) = i - 1; 73 | i = 0; 74 | } else 75 | *cursor_qry = *cursor_str; 76 | i++; 77 | cursor_str++; 78 | cursor_qry++; 79 | } 80 | *(cursor_qry - i) = i - 1; 81 | *cursor_qry = 0; 82 | *(cursor_qry + 2) = 1; /* A (IPv4) */ 83 | *(cursor_qry + 4) = 1; /* IN (internet) */ 84 | 85 | web_port_t client_port = web_RequestPort(); 86 | msg_queue_t *queued = web_PushUDPDatagram(query, length, 0x08080808, client_port, DNS_PORT); 87 | _free(query); 88 | web_ListenPort(client_port, user_dns_callback, queued); 89 | 90 | while(!os_GetCSC() && !ended) { // ended : global variable 91 | web_WaitForEvents(); 92 | } 93 | 94 | _end: 95 | web_Cleanup(); 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | # ---------------------------- 2 | # Makefile Options 3 | # ---------------------------- 4 | 5 | NAME = INTERNET 6 | COMPRESSED = NO 7 | ARCHIVED = NO 8 | 9 | CFLAGS = -Wall -Wextra -Oz 10 | CXXFLAGS = -Wall -Wextra -Oz 11 | 12 | PYTHON = python3 13 | CRYPTO_ROOT = src/internetce/crypto 14 | 15 | # ---------------------------- 16 | # Generate crypto files 17 | # ---------------------------- 18 | 19 | all: $(CRYPTO_ROOT)/mult256.asm 20 | 21 | $(CRYPTO_ROOT)/mult256.asm: $(CRYPTO_ROOT)/generate_mult.py 22 | @$(PYTHON) $(CRYPTO_ROOT)/generate_mult.py $(CRYPTO_ROOT)/mult256.asm 32 32 > /dev/null 23 | 24 | autotest: 25 | @$(MAKE) -C tests/ 26 | 27 | clean: clean_all 28 | 29 | clean_all: 30 | @git clean -Xfd 31 | 32 | # ---------------------------- 33 | # Includes 34 | # ---------------------------- 35 | 36 | include $(shell cedev-config --makefile) 37 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Internet on your Ti-84+CE and Ti-83 Premium CE 2 | 3 | This is a high-level library for interfacing with the internet on Ti-84+CE and Ti-83 Premium CE. 4 | 5 | ## The scope of the library 6 | **What InternetCE can do:** 7 | * Acquire an IP address with DHCP. 8 | * Make HTTP Get and Post requests. 9 | * Make HTTPS (Secured HTTP) Get and Post requests. 10 | * Send DNS requests. 11 | * Send UDP/TCP/IPv4/Ethernet. In particular, you can handle any web protocol that the lib don't, such as IRC, SSH, etc. 12 | * Handle ICMP and ping requests (however, you won't be able to receive ping requests because of the way USB tethering works) 13 | 14 | **What InternetCE canNOT do:** 15 | * Display the content of the accessed URL (it only provides you the data). 16 | * Handle IPv6. 17 | * Download resources bigger than 25KB (I'm trying to increase this value but it won't be bigger than 64KiB). 18 | 19 | ## Getting started 20 | * Plug the calculator to any RNDIS device (basically your phone). To this end, you may need to buy an adapter. The "final cable" you need is something that has a male mini USB Type A at one end (for the calculator) and a male micro USB or USB Type C at the other end (for your phone). You can use for example : 21 | * The charger of your phone (USB <-> Micro USB or USB Type C) (you should already have this). 22 | * A Mini USB Type A Male <-> USB Female cable - For example : https://aliexpress.com/item/32780744354.html 23 | Warning : Make sure you choose the Mini A cable (in the color section)! 24 | * Transfer a program that has been compiled with the library. 25 | * Run it, and enable the USB internet connection sharing. On Android, it should be near the Wi-Fi Tethering menu. 26 | 27 | ## Example of use 28 | `git clone` this project and put the `include/internet.h` file into the `include` folder of your toolchain. 29 | Then modify the file `src/minimal.c` as you wish. You can find other examples of what you can do with the lib in the `examples` folder. 30 | For information, the minimal program using this library would be: 31 | ```c 32 | #include 33 | 34 | int main(void) { 35 | web_Init(); 36 | while(!web_Connected()) { 37 | web_WaitForEvents(); 38 | } 39 | // Do whatever you want 40 | web_Cleanup(); 41 | return 0; 42 | } 43 | ``` 44 | 45 | ## HTTPS ? 46 | HTTPS is made possible thanks to the support of the TLS 1.3 protocol that is between the TCP and the HTTP layer. 47 | 48 | **WARNING: THIS DOES NOT MEAN YOU ARE SAFE!!!** 49 | 50 | Please, be aware that implementing cryptography primitives is NOT something that anyone can do alone in their room. Good cryptography libraries such as OpenSSL are made by hundreds of experts and is not completely safe either. Moreover, this implementation does not even check the certificate of the server. Anyone can make a Man In The Middle attack and you wouldn't even know you've been stolen. 51 | 52 | **THAT'S WHY YOU MUST NOT SEND SENSITIVE DATA THROUGH AN HTTPS CONNECTION WITH THIS LIBRARY** 53 | 54 | You are warned. 55 | 56 | ## Help & Bug report 57 | As mentioned, some examples of use are available in the [examples folder](examples/). You can draw inspiration from those programs. 58 | If you can't find what you want, feel free to ask your questions on forums such as Ti-Planet or Cemetech. 59 | This library may contain bugs. If you encounter one, please contact me on www.tiplanet.org or www.cemetech.net (Epharius). 60 | -------------------------------------------------------------------------------- /src/internetce/arp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "include/arp.h" 5 | #include "include/core.h" 6 | #include "include/debug.h" 7 | 8 | 9 | /**********************************************************************************************************************\ 10 | * Public functions * 11 | \**********************************************************************************************************************/ 12 | 13 | web_status_t web_SendARPRequest(uint8_t MAC_dst[6]) { 14 | arp_message_t arp_msg = { 15 | .HwType = 0x01, 16 | .ProtocolType = ETH_IPV4, 17 | .HwAddrLength = 0x06, 18 | .ProtocolAddrLength = 0x04, 19 | .Operation = 0x01, 20 | .MAC_src = {}, 21 | .IP_src = 0x00, 22 | .MAC_dst = {}, 23 | .IP_dst = 0x00, 24 | }; 25 | memcpy(arp_msg.MAC_src, netinfo.my_MAC_addr, 6); 26 | memcpy(arp_msg.MAC_dst, MAC_dst, 6); 27 | return web_SendEthernetFrame(&arp_msg, sizeof(arp_message_t), ETH_ARP); 28 | } 29 | 30 | 31 | /**********************************************************************************************************************\ 32 | * Private functions * 33 | \**********************************************************************************************************************/ 34 | 35 | void fetch_arp_msg(eth_frame_t *ethernet_frame) { 36 | arp_message_t *arp_msg = (arp_message_t *)((uint8_t *)ethernet_frame + sizeof(eth_frame_t)); 37 | 38 | if(ethernet_frame->Ethertype != ETH_ARP || arp_msg->HwType != 0x0100 || arp_msg->Operation != 0x0100 || 39 | arp_msg->ProtocolType != ETH_IPV4 || arp_msg->IP_dst != netinfo.IP_addr) { 40 | return; 41 | } 42 | 43 | dbg_info("Who has %d.%d.%d.%d? Tell %d.%d.%d.%d", 44 | (uint8_t)(arp_msg->IP_dst >> 0) & 0xFF, (uint8_t)(arp_msg->IP_dst >> 8) & 0xFF, 45 | (uint8_t)(arp_msg->IP_dst >> 16) & 0xFF, (uint8_t)(arp_msg->IP_dst >> 24) & 0xFF, 46 | (uint8_t)(arp_msg->IP_src >> 0) & 0xFF, (uint8_t)(arp_msg->IP_src >> 8) & 0xFF, 47 | (uint8_t)(arp_msg->IP_src >> 16) & 0xFF, (uint8_t)(arp_msg->IP_src >> 24) & 0xFF); 48 | 49 | arp_message_t resp; 50 | resp.HwType = 0x0100; 51 | resp.ProtocolType = ETH_IPV4; 52 | resp.HwAddrLength = 0x06; 53 | resp.ProtocolAddrLength = 0x04; 54 | resp.Operation = 0x0200; 55 | memcpy(resp.MAC_src, netinfo.my_MAC_addr, 6); 56 | resp.IP_src = netinfo.IP_addr; 57 | memcpy(resp.MAC_dst, arp_msg->MAC_src, 6); 58 | resp.IP_dst = arp_msg->IP_src; 59 | 60 | web_SendEthernetFrame(&resp, sizeof(arp_message_t), ETH_ARP); 61 | } 62 | -------------------------------------------------------------------------------- /src/internetce/core.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "include/core.h" 8 | #include "include/usb.h" 9 | #include "include/dhcp.h" 10 | #include "include/tcp.h" 11 | #include "include/debug.h" 12 | #include "include/utils.h" 13 | #include "include/http.h" 14 | #include "include/rndis.h" 15 | #include "include/scheduler.h" 16 | #include "include/transport_layer.h" 17 | #include "include/crypto.h" 18 | 19 | 20 | /**********************************************************************************************************************\ 21 | * Global variables * 22 | \**********************************************************************************************************************/ 23 | 24 | network_info_t netinfo; 25 | uint8_t *src_mac_addr; 26 | static void *msg_buffer = NULL; 27 | 28 | 29 | /**********************************************************************************************************************\ 30 | * Public functions * 31 | \**********************************************************************************************************************/ 32 | 33 | void web_Init() { 34 | srand(rtc_Time()); 35 | reset_netinfo_struct(); 36 | netinfo.state = STATE_USB_INITIALIZED; 37 | netinfo.temp_usb_buffer = NULL; 38 | uint8_t default_mac[6] = DEFAULT_MAC_ADDRESS; 39 | default_mac[5] = randInt(0, 0xFF); 40 | memcpy(netinfo.my_MAC_addr, default_mac, 6); 41 | memset(netinfo.router_MAC_addr, 0xFF, 6); 42 | flash_setup(); 43 | rng_Init(); 44 | 45 | usb_Init(usbHandler, NULL, NULL, USB_DEFAULT_INIT_FLAGS); 46 | } 47 | 48 | void web_Cleanup() { 49 | /** 50 | * If no connection is ingoing, there should be 3 allocated memories: 51 | * - msg_buffer (used to receive the incoming packets) 52 | * - The listen structure for port 0x44 (DHCP) 53 | * - The event structure for RNDIS keepalives 54 | * There might be more memory allocated if: 55 | * - An HTTP request was made (and created a http_data_list_t structure) 56 | * - A TCP connection is still active 57 | */ 58 | 59 | /* Freeing the appvars used for saving what the lib receives */ 60 | http_data_list_t *cur_data = http_data_list; 61 | http_data_list_t *next_data = NULL; 62 | while(cur_data) { 63 | next_data = cur_data->next; 64 | ti_Delete(cur_data->varname); 65 | _free(cur_data); 66 | cur_data = next_data; 67 | } 68 | http_data_list = NULL; 69 | 70 | /* Freeing the TLS session ticket list */ 71 | free_session_tickets(); 72 | 73 | /* Removing all pending TCP connections */ 74 | flush_tcp_connections(); 75 | 76 | /* Freeing scheduled events */ 77 | flush_event_list(); 78 | 79 | /* Freeing listened_ports */ 80 | port_list_t *cur_port = listened_ports; 81 | port_list_t *next_port = NULL; 82 | while(cur_port) { 83 | next_port = cur_port->next; 84 | _free(cur_port); 85 | cur_port = next_port; 86 | } 87 | listened_ports = NULL; 88 | 89 | reset_netinfo_struct(); 90 | 91 | if(msg_buffer != NULL) { 92 | _free(msg_buffer); 93 | msg_buffer = NULL; 94 | } 95 | 96 | if(netinfo.temp_usb_buffer != NULL) { 97 | _free(netinfo.temp_usb_buffer); 98 | } 99 | 100 | free_rndis_data(); 101 | 102 | usb_Cleanup(); 103 | 104 | /* Debugging feature, more or less a valgrind for calculator */ 105 | print_allocated_memory(); 106 | } 107 | 108 | uint32_t web_getMyIPAddr() { 109 | return netinfo.IP_addr; 110 | } 111 | 112 | bool web_Connected() { 113 | return netinfo.state == STATE_NETWORK_CONFIGURED; 114 | } 115 | 116 | web_status_t web_WaitForEvents() { 117 | web_status_t ret_val = WEB_SUCCESS; 118 | 119 | switch(netinfo.state) { 120 | case STATE_UNKNOWN: 121 | /* Nothing to do */ 122 | return WEB_SUCCESS; 123 | case STATE_USB_LOST: 124 | web_Cleanup(); 125 | web_Init(); 126 | break; /* WEB_SUCCESS */ 127 | 128 | case STATE_USB_ENABLED: 129 | if(configure_usb_device() != WEB_SUCCESS) { 130 | netinfo.state = STATE_USB_INITIALIZED; 131 | } else { 132 | netinfo.state = STATE_RNDIS_INIT; 133 | } 134 | break; /* WEB_SUCCESS */ 135 | 136 | case STATE_RNDIS_DATA_INIT: 137 | /* We need sufficent entropy to continue (otherwise the RNG will not work) */ 138 | if(dhcp_init() == 0) { 139 | netinfo.state = STATE_DHCP_CONFIGURING; 140 | } 141 | break; /* WEB_SUCCESS */ 142 | 143 | case STATE_DHCP_CONFIGURING: 144 | case STATE_NETWORK_CONFIGURED: { 145 | /* Retrieving potential messages */ 146 | if(msg_buffer == NULL) { 147 | msg_buffer = _malloc(netinfo.in_buffer_size, "input"); 148 | if(msg_buffer == NULL) { 149 | dbg_err("No memory left"); 150 | return WEB_NOT_ENOUGH_MEM; 151 | } 152 | usb_error_t err = usb_ScheduleTransfer(usb_GetDeviceEndpoint(netinfo.device, netinfo.ep_cdc_in), 153 | msg_buffer, netinfo.in_buffer_size, packets_callback, &msg_buffer); 154 | if(err != USB_SUCCESS) { 155 | dbg_warn("USB err: %u", err); 156 | _free(msg_buffer); 157 | return WEB_USB_ERROR; 158 | } 159 | } 160 | 161 | } default: 162 | break; /* nothing */ 163 | } 164 | 165 | /* Handling time events */ 166 | dispatch_time_events(); 167 | 168 | /* Handling USB events */ 169 | usb_error_t err = usb_HandleEvents(); 170 | if(err != USB_SUCCESS) { 171 | ret_val = WEB_USB_ERROR; 172 | } 173 | 174 | return ret_val; 175 | } 176 | 177 | msg_queue_t *web_PushMessage(void *msg, size_t length) { 178 | msg_queue_t *new_msg = _malloc(sizeof(msg_queue_t), "push"); 179 | if(new_msg == NULL) { 180 | _free(msg); 181 | return NULL; 182 | } 183 | new_msg->length = length; 184 | new_msg->msg = msg; 185 | new_msg->send_once = false; /* Modified in upper layers if needed */ 186 | new_msg->endpoint = usb_GetDeviceEndpoint(netinfo.device, netinfo.ep_cdc_out); 187 | web_status_t ret_val = schedule(SEND_EVERY, send_packet_scheduler, send_packet_destructor, new_msg); 188 | if(ret_val != WEB_SUCCESS) { 189 | _free(msg); 190 | _free(new_msg); 191 | dbg_err("Failed to schedule message"); 192 | return NULL; 193 | } 194 | return new_msg; 195 | } 196 | 197 | void web_PopMessage(msg_queue_t *msg) { 198 | remove_event(msg); 199 | } 200 | 201 | 202 | /**********************************************************************************************************************\ 203 | * Private functions * 204 | \**********************************************************************************************************************/ 205 | 206 | void reset_netinfo_struct() { 207 | netinfo.ep_wc_in = 0; 208 | netinfo.ep_cdc_in = 0; 209 | netinfo.ep_cdc_out = 0; 210 | netinfo.state = STATE_UNKNOWN; 211 | netinfo.dhcp_cur_state = DHCP_STATE_BIND; 212 | netinfo.device = NULL; 213 | netinfo.IP_addr = 0; 214 | } 215 | 216 | void *_alloc_msg_buffer(void *data, size_t length_data, size_t headers_total_size, bool has_eth_header) { 217 | const size_t size = length_data + headers_total_size; 218 | void *buffer = _malloc(size, "alloc"); 219 | if(buffer == NULL) { 220 | dbg_err("No memory left"); 221 | return NULL; 222 | } 223 | memcpy(buffer + headers_total_size - (has_eth_header ? 4 : 0), data, length_data); 224 | return buffer; 225 | } 226 | 227 | scheduler_status_t send_packet_scheduler(web_callback_data_t *user_data) { 228 | msg_queue_t *cur_msg = (msg_queue_t *)user_data; 229 | 230 | const usb_error_t status = usb_ScheduleTransfer(cur_msg->endpoint, cur_msg->msg, cur_msg->length, NULL, NULL); 231 | if(status != USB_SUCCESS) { 232 | dbg_warn("Failed to send packet"); 233 | return SCHEDULER_AGAIN; 234 | } 235 | 236 | return cur_msg->send_once ? SCHEDULER_DESTROY : SCHEDULER_AGAIN; 237 | } 238 | 239 | void send_packet_destructor(web_callback_data_t *user_data) { 240 | msg_queue_t *msg = (msg_queue_t *)user_data; 241 | _free(msg->msg); 242 | _free(msg); 243 | } 244 | 245 | void free_allocated_memory(allocated_memory_t **list, allocated_memory_t *allocated) { 246 | allocated_memory_t *current = *list; 247 | allocated_memory_t *previous = NULL; 248 | while(current != NULL) { 249 | if(current == allocated) { 250 | if(previous == NULL) { 251 | *list = current->next; 252 | } else { 253 | previous->next = current->next; 254 | } 255 | _free(current); 256 | return; 257 | } 258 | previous = current; 259 | current = current->next; 260 | } 261 | dbg_warn("Loose free"); 262 | } 263 | 264 | void free_allocated_memory_list(allocated_memory_t *memory_list) { 265 | while(memory_list != NULL) { 266 | allocated_memory_t *next = memory_list->next; 267 | _free(memory_list); 268 | memory_list = next; 269 | } 270 | } 271 | -------------------------------------------------------------------------------- /src/internetce/crypto/aes.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../include/crypto.h" 5 | #include "../include/debug.h" 6 | 7 | cipher_callbacks_t aes128gcm_callbacks = { 8 | .init = aes128gcm_init_callback, 9 | .free = aes128gcm_free_callback, 10 | .cipher = aes128gcm_cipher_callback, 11 | .decipher = aes128gcm_decipher_callback, 12 | .extra_size = AES_128_TAG_SIZE, 13 | .key_size = AES_128_KEY_SIZE, 14 | .iv_size = AES_128_IV_SIZE 15 | }; 16 | 17 | 18 | /**********************************************************************************************************************\ 19 | * Public functions * 20 | \**********************************************************************************************************************/ 21 | 22 | web_callback_data_t *aes128gcm_init_callback(uint8_t cipher_key[AES_128_KEY_SIZE], uint8_t cipher_iv[AES_128_IV_SIZE], 23 | uint8_t decipher_key[AES_128_KEY_SIZE], uint8_t decipher_iv[AES_128_IV_SIZE]) { 24 | aes128gcm_data_t *cipher_struct = _malloc(sizeof(aes128gcm_data_t), "aesi"); 25 | if(cipher_struct == NULL) { 26 | dbg_err("No memory"); 27 | return NULL; 28 | } 29 | 30 | /* Local cipher data */ 31 | memcpy(cipher_struct->cipher_data.static_iv, cipher_iv, AES_128_IV_SIZE); 32 | memcpy(cipher_struct->cipher_data.round_keys, cipher_key, AES_128_KEY_SIZE); 33 | compute_round_keys(cipher_struct->cipher_data.round_keys); 34 | cipher_struct->cipher_data.sequence_number = 0; 35 | 36 | /* Distant cipher data */ 37 | memcpy(cipher_struct->decipher_data.static_iv, decipher_iv, AES_128_IV_SIZE); 38 | memcpy(cipher_struct->decipher_data.round_keys, decipher_key, AES_128_KEY_SIZE); 39 | compute_round_keys(cipher_struct->decipher_data.round_keys); 40 | cipher_struct->decipher_data.sequence_number = 0; 41 | 42 | return cipher_struct; 43 | } 44 | 45 | void aes128gcm_free_callback(web_callback_data_t *cipher_data) { 46 | _free(cipher_data); 47 | } 48 | 49 | web_status_t aes128gcm_cipher_callback(void *dest, void *source, size_t length, void *aad, size_t aad_length, 50 | web_callback_data_t *user_data) { 51 | if(user_data == NULL) { 52 | dbg_err("NULL cipher_data"); 53 | } 54 | aes128gcm_endpoint_data_t *cipher_data = &((aes128gcm_data_t *)user_data)->cipher_data; 55 | uint8_t current_iv[12]; 56 | memcpy(current_iv, cipher_data->static_iv, 12); 57 | uint8_t *seq_number_bytes = (uint8_t *)&cipher_data->sequence_number; 58 | current_iv[11] ^= seq_number_bytes[0]; /* little to big endian */ 59 | current_iv[10] ^= seq_number_bytes[1]; 60 | current_iv[9] ^= seq_number_bytes[2]; 61 | cipher_data->sequence_number++; 62 | cipher_aes128gcm(cipher_data->round_keys, source, length, current_iv, aad, aad_length, dest + length, dest); 63 | 64 | return WEB_SUCCESS; 65 | } 66 | 67 | web_status_t aes128gcm_decipher_callback(void *dest, void *source, size_t length, void *aad, size_t aad_length, 68 | web_callback_data_t *user_data) { 69 | if(user_data == NULL) { 70 | dbg_err("NULL cipher_data"); 71 | } 72 | aes128gcm_endpoint_data_t *decipher_data = &((aes128gcm_data_t *)user_data)->decipher_data; 73 | uint8_t current_iv[12]; 74 | memcpy(current_iv, decipher_data->static_iv, 12); 75 | uint8_t *seq_number_bytes = (void *)&decipher_data->sequence_number; 76 | current_iv[11] ^= seq_number_bytes[0]; /* little to big endian */ 77 | current_iv[10] ^= seq_number_bytes[1]; 78 | current_iv[9] ^= seq_number_bytes[2]; 79 | decipher_data->sequence_number++; 80 | const int ret_val = decipher_aes128gcm(decipher_data->round_keys, source, length - AES_128_TAG_SIZE, current_iv, 81 | aad, aad_length, source + length - AES_128_TAG_SIZE, dest); 82 | 83 | return ret_val == 0 ? WEB_SUCCESS : WEB_ERROR_FAILED; 84 | } 85 | -------------------------------------------------------------------------------- /src/internetce/crypto/generate_mult.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from os.path import basename 3 | 4 | 5 | def gen_mult(output_file, degree_a, degree_b): 6 | tstates = 0 7 | size = 0 8 | degree_a = int(degree_a) 9 | degree_b = int(degree_b) 10 | with open(output_file, "w") as output: 11 | output.write(f"; Generated by {basename(__file__)}\n\n") 12 | output.write(f"macro {basename(output_file).split('.')[0]}?\n") 13 | for degree in range(0, degree_a + degree_b - 1): 14 | is_first = True 15 | value_in_d = False 16 | for idxa in range(0, degree_a): 17 | for idxb in range(0, degree_b): 18 | if idxa + idxb == degree: 19 | if degree % 2 == 0 and is_first: 20 | tstates += 16+16+12 21 | size += 3+3+2 22 | output.write(f"\tld d, (ix+{idxa})\n") 23 | output.write(f"\tld e, (iy+{idxb})\n") 24 | output.write("\tmlt de\n") 25 | elif value_in_d: 26 | tstates += 16+12 27 | size += 3+2 28 | value_in_d = False 29 | register = "bc" 30 | output.write(f"\tld c, (iy+{idxb})\n") 31 | output.write("\tmlt bc\n") 32 | else: 33 | tstates += 24+4+16+12 34 | size += 3+1+3+2 35 | register = "de" 36 | value_in_d = True 37 | output.write(f"\tld bc, (ix+{idxa})\n") 38 | output.write("\tld e, c\n") 39 | output.write(f"\tld d, (iy+{idxb})\n") 40 | output.write("\tmlt de\n") 41 | if degree != 0: 42 | tstates += 4 43 | size += 1 44 | if is_first: 45 | output.write("\tex de, hl\n") 46 | is_first = False 47 | else: 48 | output.write(f"\tadd hl, {register}\n") 49 | 50 | tstates += 26+8 51 | size += 4 52 | if degree != 0: 53 | output.write("\tpop de\n") 54 | else: 55 | output.write("\tpop hl\n") 56 | output.write("\tadd hl, de\n") 57 | output.write(f"\tpush hl\n") 58 | output.write("\tinc sp\n\n") 59 | 60 | output.write("end macro\n") 61 | 62 | stats = f"; TOTAL CYCLES: {tstates} cycles\n" 63 | stats += f"; TIME ESTIMATION: {tstates*2800/48000000} seconds\n" 64 | stats += f"; TOTAL SIZE: {size} bytes\n\n" 65 | 66 | with open(output_file, "r+") as output: 67 | lines = output.readlines() 68 | lines.insert(0, stats) 69 | output.seek(0) 70 | output.writelines(lines) 71 | print(stats[:-2]) 72 | 73 | if __name__ == "__main__": 74 | if len(sys.argv) != 4: 75 | print(f"Usage:\n\t{basename(__file__)} filename degree_a degree_b") 76 | exit(-1) 77 | 78 | gen_mult(*sys.argv[1:]) 79 | -------------------------------------------------------------------------------- /src/internetce/crypto/hkdf.c: -------------------------------------------------------------------------------- 1 | /** 2 | * HKDF (HMAC Key Derivation Function) module 3 | * The HMAC Hash function is SHA256. 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "../include/crypto.h" 11 | #include "../include/debug.h" 12 | 13 | 14 | web_status_t hkdf_Extract(const uint8_t salt[], size_t salt_size, const uint8_t ikm[], size_t ikm_size, uint8_t prk[]) { 15 | uint8_t default_salt[CIPHER_SUITE_HASH_SIZE]; 16 | const uint8_t *actual_salt = salt; 17 | if(salt == NULL) { 18 | memset(default_salt, 0, CIPHER_SUITE_HASH_SIZE); 19 | actual_salt = default_salt; 20 | salt_size = CIPHER_SUITE_HASH_SIZE; 21 | } 22 | 23 | return hkdf_HMAC(actual_salt, salt_size, ikm, ikm_size, prk); 24 | } 25 | 26 | web_status_t hkdf_Expand(const uint8_t prk[], const uint8_t info[], size_t info_size, uint8_t dst[], size_t dst_size) { 27 | web_status_t ret_val = WEB_NO_DATA; 28 | const unsigned int nb_iterations = (dst_size + CIPHER_SUITE_HASH_SIZE - 1) / CIPHER_SUITE_HASH_SIZE; 29 | const size_t max_context_size = CIPHER_SUITE_HASH_SIZE + info_size + 1; 30 | uint8_t previous_hash[CIPHER_SUITE_HASH_SIZE]; 31 | uint8_t context_buffer[max_context_size]; 32 | size_t context_buffer_size; 33 | size_t size_left = dst_size; 34 | for(unsigned int i=1; i<=nb_iterations; i++) { 35 | if(i != 1) { 36 | context_buffer_size = CIPHER_SUITE_HASH_SIZE + info_size + 1; 37 | memcpy(context_buffer, previous_hash, CIPHER_SUITE_HASH_SIZE); 38 | memcpy(context_buffer + CIPHER_SUITE_HASH_SIZE, info, info_size); 39 | } else { 40 | context_buffer_size = info_size + 1; 41 | memcpy(context_buffer, info, info_size); 42 | } 43 | context_buffer[context_buffer_size - 1] = i; 44 | 45 | ret_val = hkdf_HMAC(prk, CIPHER_SUITE_HASH_SIZE, context_buffer, context_buffer_size, previous_hash); 46 | if(ret_val != WEB_SUCCESS) { 47 | memset(dst, 0, i * CIPHER_SUITE_HASH_SIZE); 48 | break; 49 | } 50 | memcpy(dst + (i - 1) * CIPHER_SUITE_HASH_SIZE, previous_hash, min(size_left, CIPHER_SUITE_HASH_SIZE)); 51 | size_left -= CIPHER_SUITE_HASH_SIZE; 52 | } 53 | 54 | /* Clearing any contextual info on the stack for security purposes */ 55 | memset(previous_hash, 0, CIPHER_SUITE_HASH_SIZE); 56 | memset(context_buffer, 0, max_context_size); 57 | 58 | return ret_val; 59 | } 60 | 61 | web_status_t hkdf_ExpandLabel(const uint8_t secret[], const char *label, const uint8_t hash[], size_t hash_size, 62 | uint8_t dst[], size_t dst_size) { 63 | const char *tls_str = "tls13 "; 64 | size_t hkdfLabel_size = sizeof(uint16_t) + 1 + strlen(tls_str) + strlen(label) + 1 + hash_size; 65 | uint8_t hkdfLabel[hkdfLabel_size]; 66 | *(uint16_t *)hkdfLabel = htons(dst_size); 67 | 68 | uint8_t *buf_label = hkdfLabel + 2; 69 | buf_label[0] = strlen(tls_str) + strlen(label); 70 | memcpy(buf_label + 1, tls_str, strlen(tls_str)); 71 | memcpy(buf_label + 1 + strlen(tls_str), label, strlen(label)); 72 | 73 | uint8_t *buf_context = buf_label + 1 + strlen(tls_str) + strlen(label); 74 | buf_context[0] = hash_size; 75 | memcpy(buf_context + 1, hash, hash_size); 76 | 77 | return hkdf_Expand(secret, hkdfLabel, hkdfLabel_size, dst, dst_size); 78 | } 79 | 80 | web_status_t hkdf_HMAC(const uint8_t key[], size_t key_size, const uint8_t msg[], size_t size, uint8_t dst[]) { 81 | uint8_t padded_key[CIPHER_SUITE_BLOCK_SIZE]; 82 | 83 | if(sha256_IsEnabled()) { 84 | dbg_err("SHA256 chip already in use"); 85 | return WEB_SHA256_IN_USE; 86 | } 87 | 88 | if(key_size > CIPHER_SUITE_BLOCK_SIZE) { 89 | dbg_info("Key too long, hashing"); 90 | sha256_Init(); 91 | sha256_Part(key, key_size); 92 | sha256_Hash(padded_key); 93 | key_size = CIPHER_SUITE_HASH_SIZE; 94 | } else { 95 | memcpy(padded_key, key, key_size); 96 | } 97 | 98 | if(key_size != CIPHER_SUITE_BLOCK_SIZE) { 99 | memset(padded_key + key_size, 0, CIPHER_SUITE_BLOCK_SIZE - key_size); 100 | } 101 | 102 | uint8_t o_key_pad[CIPHER_SUITE_BLOCK_SIZE]; 103 | uint8_t i_key_pad[CIPHER_SUITE_BLOCK_SIZE]; 104 | for(size_t i = 0; i < CIPHER_SUITE_BLOCK_SIZE; i++) { 105 | o_key_pad[i] = padded_key[i] ^ 0x5c; 106 | i_key_pad[i] = padded_key[i] ^ 0x36; 107 | } 108 | 109 | sha256_Init(); 110 | sha256_Part(i_key_pad, CIPHER_SUITE_BLOCK_SIZE); 111 | sha256_Part(msg, size); 112 | sha256_Hash(dst); /* temp buffer for inner hash */ 113 | 114 | sha256_Init(); 115 | sha256_Part(o_key_pad, CIPHER_SUITE_BLOCK_SIZE); 116 | sha256_Part(dst, CIPHER_SUITE_HASH_SIZE); 117 | sha256_Hash(dst); 118 | 119 | /* Clearing any contextual info on the stack for security purposes */ 120 | memset(o_key_pad, 0, CIPHER_SUITE_BLOCK_SIZE); 121 | memset(i_key_pad, 0, CIPHER_SUITE_BLOCK_SIZE); 122 | memset(padded_key, 0, CIPHER_SUITE_BLOCK_SIZE); 123 | 124 | return WEB_SUCCESS; 125 | } 126 | -------------------------------------------------------------------------------- /src/internetce/crypto/key_schedule.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../include/crypto.h" 5 | #include "../include/tls.h" 6 | #include "../include/debug.h" 7 | 8 | 9 | web_status_t add_transcript_message(linked_transcript_msg_t **transcript, const void *data, size_t size, tls_sender_t sender) { 10 | /* Note: Messages are already in the correct order (ordering is expected by the TLS client FSM) */ 11 | void *buffer = _malloc(size, "addt"); 12 | if(buffer == NULL) { 13 | return WEB_NOT_ENOUGH_MEM; 14 | } 15 | memcpy(buffer, data, size); 16 | linked_transcript_msg_t *adding = _malloc(sizeof(linked_transcript_msg_t), "ltm"); 17 | if(adding == NULL) { 18 | _free(buffer); 19 | return WEB_NOT_ENOUGH_MEM; 20 | } 21 | adding->length = size; 22 | tls_hs_msg_type_t hs_type = ((tls_hello_t *)data)->header.hs_type; 23 | if(hs_type <= TLS_HS_TYPE_SERVER_HELLO) { 24 | /* Edge case for the way I've chosen to order HS messages... is there any better solution? */ 25 | adding->msg_type = (tls_hs_sender_msg_type_t)hs_type; 26 | } else { 27 | adding->msg_type = (tls_hs_sender_msg_type_t)TO_HS_SENDER_TYPE(hs_type, sender); 28 | } 29 | adding->data = buffer; 30 | 31 | linked_transcript_msg_t *current = *transcript; 32 | linked_transcript_msg_t *prev = NULL; 33 | while(current != NULL && current->msg_type < adding->msg_type) { 34 | prev = current; 35 | current = current->next; 36 | } 37 | adding->next = current; 38 | if(prev != NULL) { 39 | prev->next = adding; 40 | } else { 41 | *transcript = adding; 42 | } 43 | 44 | return WEB_SUCCESS; 45 | } 46 | 47 | web_status_t compute_transcript_hash(const linked_transcript_msg_t *transcript, tls_hs_sender_msg_type_t until, uint8_t hash[]) { 48 | const web_status_t status = sha256_Init(); 49 | if(status != WEB_SUCCESS) { 50 | return status; 51 | } 52 | 53 | if(transcript != NULL) { 54 | const linked_transcript_msg_t *message = transcript; 55 | while(message != NULL && message->msg_type <= until) { 56 | sha256_Part(message->data, message->length); 57 | message = message->next; 58 | } 59 | } 60 | 61 | return sha256_Hash(hash); 62 | } 63 | 64 | web_status_t compute_early_secret(const linked_transcript_msg_t *transcript, uint8_t current_secret[], const uint8_t psk[], 65 | size_t psk_length, uint8_t binder_key[], uint8_t client_early_traffic_secret[], 66 | uint8_t early_exporter_master_secret[]) { 67 | (void)transcript; /* might be useful later */ 68 | web_status_t status; 69 | uint8_t secret[CIPHER_SUITE_HASH_SIZE]; 70 | if(psk_length == 0 || psk == NULL) { 71 | uint8_t zero_psk[CIPHER_SUITE_HASH_SIZE] = {0}; 72 | status = hkdf_Extract(NULL, 0, zero_psk, CIPHER_SUITE_HASH_SIZE, secret); 73 | } else { 74 | status = hkdf_Extract(NULL, 0, psk, psk_length, secret); 75 | } 76 | if(status != WEB_SUCCESS) { 77 | return status; 78 | } 79 | 80 | if(binder_key != NULL) { 81 | uint8_t hash_empty_str[CIPHER_SUITE_HASH_SIZE]; 82 | status = compute_transcript_hash(NULL, 0, hash_empty_str); 83 | if(status == WEB_SUCCESS) { 84 | status = hkdf_ExpandLabel(secret, "res binder", hash_empty_str, CIPHER_SUITE_HASH_SIZE, binder_key, CIPHER_SUITE_HASH_SIZE); 85 | } 86 | } 87 | if(client_early_traffic_secret != NULL) { 88 | /* No PSK support, so don't care */ 89 | } 90 | if(early_exporter_master_secret != NULL) { 91 | /* No PSK support, so don't care */ 92 | } 93 | 94 | uint8_t hash_empty_str[CIPHER_SUITE_HASH_SIZE]; 95 | status = compute_transcript_hash(NULL, 0, hash_empty_str); 96 | if(status == WEB_SUCCESS) { 97 | status = hkdf_ExpandLabel(secret, "derived", hash_empty_str, CIPHER_SUITE_HASH_SIZE, current_secret, CIPHER_SUITE_HASH_SIZE); 98 | } 99 | memset(secret, 0, CIPHER_SUITE_HASH_SIZE); 100 | return status; 101 | } 102 | 103 | web_status_t compute_handshake_secret(const linked_transcript_msg_t *transcript, uint8_t current_secret[], const uint8_t dhe_ss[], 104 | size_t dhe_ss_size, uint8_t client_hs_traffic_secret[], uint8_t server_hs_traffic_secret[]) { 105 | web_status_t status; 106 | uint8_t hash[CIPHER_SUITE_HASH_SIZE]; 107 | uint8_t secret[CIPHER_SUITE_HASH_SIZE]; 108 | if(dhe_ss_size == 0 || dhe_ss == NULL) { 109 | uint8_t zero_dhe[CIPHER_SUITE_HASH_SIZE] = {0}; 110 | status = hkdf_Extract(current_secret, CIPHER_SUITE_HASH_SIZE, zero_dhe, CIPHER_SUITE_HASH_SIZE, secret); 111 | } else { 112 | status = hkdf_Extract(current_secret, CIPHER_SUITE_HASH_SIZE, dhe_ss, dhe_ss_size, secret); 113 | } 114 | if(status != WEB_SUCCESS) { 115 | return status; 116 | } 117 | 118 | status = compute_transcript_hash(transcript, TLS_HS_SERVER_SERVER_HELLO, hash); 119 | if(client_hs_traffic_secret != NULL && status == WEB_SUCCESS) { 120 | status = hkdf_ExpandLabel(secret, "c hs traffic", hash, CIPHER_SUITE_HASH_SIZE, client_hs_traffic_secret, CIPHER_SUITE_HASH_SIZE); 121 | } 122 | if(server_hs_traffic_secret != NULL && status == WEB_SUCCESS) { 123 | status = hkdf_ExpandLabel(secret, "s hs traffic", hash, CIPHER_SUITE_HASH_SIZE, server_hs_traffic_secret, CIPHER_SUITE_HASH_SIZE); 124 | } 125 | 126 | if(status == WEB_SUCCESS) { 127 | status = compute_transcript_hash(NULL, 0, hash); 128 | if(status == WEB_SUCCESS) { 129 | status = hkdf_ExpandLabel(secret, "derived", hash, CIPHER_SUITE_HASH_SIZE, current_secret, CIPHER_SUITE_HASH_SIZE); 130 | } 131 | } 132 | 133 | memset(secret, 0, CIPHER_SUITE_HASH_SIZE); 134 | memset(hash, 0, CIPHER_SUITE_HASH_SIZE); 135 | return status; 136 | } 137 | 138 | web_status_t compute_master_secret(const linked_transcript_msg_t *transcript, uint8_t current_secret[], 139 | uint8_t client_ap_traffic_secret[], uint8_t server_ap_traffic_secret[], 140 | uint8_t exporter_master_secret[], uint8_t resumption_master_secret[]) { 141 | web_status_t status; 142 | uint8_t hash[CIPHER_SUITE_HASH_SIZE]; 143 | uint8_t secret[CIPHER_SUITE_HASH_SIZE]; 144 | uint8_t zero_psk[CIPHER_SUITE_HASH_SIZE] = {0}; 145 | status = hkdf_Extract(current_secret, CIPHER_SUITE_HASH_SIZE, zero_psk, CIPHER_SUITE_HASH_SIZE, secret); 146 | if(status != WEB_SUCCESS) { 147 | return status; 148 | } 149 | 150 | if(client_ap_traffic_secret != NULL) { 151 | status = compute_transcript_hash(transcript, TLS_HS_SERVER_FINISHED, hash); 152 | if(status == WEB_SUCCESS) { 153 | status = hkdf_ExpandLabel(secret, "c ap traffic", hash, CIPHER_SUITE_HASH_SIZE, client_ap_traffic_secret, CIPHER_SUITE_HASH_SIZE); 154 | } 155 | if(status != WEB_SUCCESS) { 156 | goto end; 157 | } 158 | } 159 | if(server_ap_traffic_secret != NULL) { 160 | status = compute_transcript_hash(transcript, TLS_HS_SERVER_FINISHED, hash); 161 | if(status == WEB_SUCCESS) { 162 | status = hkdf_ExpandLabel(secret, "s ap traffic", hash, CIPHER_SUITE_HASH_SIZE, server_ap_traffic_secret, CIPHER_SUITE_HASH_SIZE); 163 | } 164 | if(status != WEB_SUCCESS) { 165 | goto end; 166 | } 167 | } 168 | if(exporter_master_secret != NULL) { 169 | /* Don't care for now */ 170 | } 171 | if(resumption_master_secret != NULL) { 172 | status = compute_transcript_hash(transcript, TLS_HS_CLIENT_FINISHED, hash); 173 | if(status == WEB_SUCCESS) { 174 | status = hkdf_ExpandLabel(secret, "res master", hash, CIPHER_SUITE_HASH_SIZE, resumption_master_secret, CIPHER_SUITE_HASH_SIZE); 175 | } 176 | if(status != WEB_SUCCESS) { 177 | goto end; 178 | } 179 | } 180 | 181 | end: 182 | memset(secret, 0, CIPHER_SUITE_HASH_SIZE); 183 | memset(hash, 0, CIPHER_SUITE_HASH_SIZE); 184 | return status; 185 | } 186 | 187 | web_status_t update_traffic_secret(const uint8_t current_traffic_secret[], uint8_t new_traffic_secret[]) { 188 | web_status_t status; 189 | uint8_t hash[CIPHER_SUITE_HASH_SIZE]; 190 | status = compute_transcript_hash(NULL, 0, hash); 191 | if(status == WEB_SUCCESS) { 192 | status = hkdf_ExpandLabel(current_traffic_secret, "traffic upd", hash, CIPHER_SUITE_HASH_SIZE, new_traffic_secret, CIPHER_SUITE_HASH_SIZE); 193 | memset(hash, 0, CIPHER_SUITE_HASH_SIZE); 194 | } 195 | return status; 196 | } 197 | 198 | web_status_t compute_key_iv_pair(const uint8_t secret[], uint8_t key[], size_t key_size, uint8_t iv[], size_t iv_size) { 199 | web_status_t status; 200 | status = hkdf_ExpandLabel(secret, "key", NULL, 0, key, key_size); 201 | if(status == WEB_SUCCESS) { 202 | status = hkdf_ExpandLabel(secret, "iv", NULL, 0, iv, iv_size); 203 | } 204 | return status; 205 | } 206 | 207 | void _free_transcript(linked_transcript_msg_t **transcript) { 208 | linked_transcript_msg_t *message = *transcript; 209 | linked_transcript_msg_t *next; 210 | while(message != NULL) { 211 | next = message->next; 212 | _free(message->data); 213 | _free(message); 214 | message = next; 215 | } 216 | *transcript = NULL; 217 | } 218 | -------------------------------------------------------------------------------- /src/internetce/crypto/ports.asm: -------------------------------------------------------------------------------- 1 | ; Copyright 2015-2024 Matt "MateoConLechuga" Waltz 2 | ; 3 | ; Redistribution and use in source and binary forms, with or without 4 | ; modification, are permitted provided that the following conditions are met: 5 | ; 6 | ; 1. Redistributions of source code must retain the above copyright notice, 7 | ; this list of conditions and the following disclaimer. 8 | ; 9 | ; 2. Redistributions in binary form must reproduce the above copyright notice, 10 | ; this list of conditions and the following disclaimer in the documentation 11 | ; and/or other materials provided with the distribution. 12 | ; 13 | ; 3. Neither the name of the copyright holder nor the names of its contributors 14 | ; may be used to endorse or promote products derived from this software 15 | ; without specific prior written permission. 16 | ; 17 | ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | ; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | ; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 21 | ; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | ; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | ; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | ; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | ; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | ; POSSIBILITY OF SUCH DAMAGE. 28 | 29 | ; This code is part of the Cesium code base. 30 | ; It is used in InternetCE to access the SHA256 port. 31 | ; A few lines have been modified to make it C compliant. 32 | 33 | ; ******* equates ******* 34 | _frameset0 equ 0000130h 35 | WriteFlashA equ 00002E8h 36 | 37 | 38 | assume adl=1 39 | section .text 40 | 41 | public _flash_setup 42 | _flash_setup: 43 | di 44 | ld b,1 45 | or a,a 46 | sbc hl,hl 47 | .find: 48 | ld a,(hl) 49 | inc hl 50 | cp a,$80 51 | jq z,.found_80 52 | cp a,$ed 53 | jq nz,.find 54 | ld a,(hl) 55 | sub a,$41 56 | jq z,.found_ed41 57 | cp a,$73 58 | jq nz,.find 59 | dec b 60 | dec hl 61 | ld (port_new.target),hl 62 | inc hl 63 | jq .find 64 | .found_80: 65 | ld a,(hl) 66 | cp a,$0f 67 | jq nz,.find 68 | and a,b 69 | ret nz 70 | ld hl,port_new.unlock 71 | jq .store_smc 72 | .found_ed41: 73 | dec hl 74 | ld (port_old.target),hl 75 | inc hl 76 | ex de, hl 77 | ld hl, 4 78 | add hl, de 79 | bit 0, (hl) 80 | ex de, hl 81 | jq nz,.find 82 | ld hl,port_old.unlock 83 | .store_smc: 84 | ld (port_unlock.code),hl 85 | ret 86 | 87 | 88 | port_old: 89 | .unlock: 90 | ; Move the unlock sequence under the memory protection range (heapBot) 91 | or a, a 92 | sbc hl, hl 93 | push hl 94 | ld bc, port_old.end - port_old.start 95 | push bc 96 | call __malloc 97 | pop bc 98 | pop de 99 | ld (.malloc_target), hl 100 | ld (.free_target), hl 101 | ex de, hl 102 | ld hl, port_old.start 103 | ldir 104 | call 0 105 | .malloc_target := $-3 106 | ld hl, 0 107 | .free_target := $-3 108 | push hl 109 | call __free 110 | pop hl 111 | ret 112 | .unlockhelper: 113 | call _frameset0 114 | push de 115 | ld bc,$0022 116 | jp 0 117 | .target := $-3 118 | .start: 119 | call .unlockhelper 120 | .unlockfinish: 121 | ld a,$D4 122 | out0 ($25),a 123 | in0 a,($06) 124 | or a,4 125 | out0 ($06),a 126 | ret 127 | .end: 128 | 129 | port_new: 130 | .unlock: 131 | ld de,$d19881 132 | push de 133 | or a,a 134 | sbc hl,hl 135 | push hl 136 | ld de,$03d4 137 | push de 138 | push hl 139 | call .unlockhelper 140 | ld hl,12 141 | add hl,sp 142 | ld sp,hl 143 | jq port_old.unlockfinish 144 | .unlockhelper: 145 | push hl 146 | ex (sp),ix 147 | add ix,sp 148 | push hl 149 | push de 150 | ld de,$887c00 151 | push de 152 | ld bc,$10de 153 | ld de,$0f22 154 | add hl,sp 155 | jp 0 156 | .target := $-3 157 | .lock: 158 | xor a,a 159 | out0 ($28),a 160 | in0 a,($06) 161 | res 2,a 162 | out0 ($06),a 163 | ld a,$d1 164 | out0 ($22),a 165 | out0 ($25),a 166 | ret 167 | 168 | port_unlock: 169 | push iy,de,bc,hl 170 | call 0 171 | .code := $-3 172 | jr port_lock.pop 173 | 174 | public _flash_lock 175 | _flash_lock: 176 | port_lock: 177 | push iy,de,bc,hl 178 | call port_new.lock 179 | .pop: 180 | pop hl,bc,de,iy 181 | ret 182 | 183 | public _flash_unlock 184 | _flash_unlock: 185 | call port_unlock 186 | ; Dummy write: Unlock Flash 187 | ld a, 0xff 188 | ld de, 0x3fffff 189 | call WriteFlashA 190 | ret 191 | 192 | 193 | extern __malloc 194 | extern __free 195 | -------------------------------------------------------------------------------- /src/internetce/crypto/random.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Random module 3 | * Seek for entropy from various sources, in particular from the USB bus activity 4 | * Unfortunately not as secured as it could be, since making a good True RNG would require more and better entropy sources. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "../include/crypto.h" 12 | #include "../include/debug.h" 13 | 14 | #define MINIMUM_ENTROPY 16 15 | #define ENTROPY_BUFFER_SIZE (MINIMUM_ENTROPY * 2) 16 | 17 | 18 | /* Internal state variables */ 19 | static size_t entropy = 0; /* This is actually not entropy but the number of random bytes gathered until now */ 20 | static uint8_t entropy_bits; /* Temporary buffer that stores the entropy bits until there are 8 of them */ 21 | static uint8_t nb_entropy_bits; /* Number of entropy bits (8 bits => store the byte into entropy_buffer) */ 22 | static uint8_t entropy_buffer[ENTROPY_BUFFER_SIZE]; /* Buffer that gathers entropy waiting to be fed */ 23 | static uint8_t current_buffer_index; /* Current index in entropy_buffer */ 24 | static uint8_t K[CIPHER_SUITE_HASH_SIZE]; /* Key used with HMAC */ 25 | static uint8_t V[CIPHER_SUITE_HASH_SIZE]; /* Current state */ 26 | 27 | void rng_Init() { 28 | memset(K, 0, CIPHER_SUITE_HASH_SIZE); 29 | memset(V, 1, CIPHER_SUITE_HASH_SIZE); 30 | entropy = 0; 31 | current_buffer_index = 0; 32 | entropy_bits = 0; 33 | nb_entropy_bits = 0; 34 | } 35 | 36 | bool rng_IsAvailable() { 37 | return entropy >= MINIMUM_ENTROPY; 38 | } 39 | 40 | web_status_t rng_Update() { 41 | if(current_buffer_index == 0) { 42 | dbg_verb("No available entropy"); 43 | return 0; 44 | } 45 | if(sha256_IsEnabled()) { 46 | return WEB_SHA256_IN_USE; 47 | } 48 | 49 | const size_t buffer_size = CIPHER_SUITE_HASH_SIZE + 1 + current_buffer_index; 50 | uint8_t buffer[buffer_size]; 51 | 52 | memcpy(buffer, V, CIPHER_SUITE_HASH_SIZE); 53 | buffer[CIPHER_SUITE_HASH_SIZE] = 0; 54 | memcpy(buffer + CIPHER_SUITE_HASH_SIZE, entropy_buffer, current_buffer_index); 55 | hkdf_HMAC(K, CIPHER_SUITE_HASH_SIZE, buffer, buffer_size, K); 56 | hkdf_HMAC(K, CIPHER_SUITE_HASH_SIZE, V, CIPHER_SUITE_HASH_SIZE, V); 57 | 58 | memcpy(buffer, V, CIPHER_SUITE_HASH_SIZE); 59 | buffer[CIPHER_SUITE_HASH_SIZE] = 1; 60 | hkdf_HMAC(K, CIPHER_SUITE_HASH_SIZE, buffer, buffer_size, K); 61 | hkdf_HMAC(K, CIPHER_SUITE_HASH_SIZE, V, CIPHER_SUITE_HASH_SIZE, V); 62 | 63 | /* Clearing buffer for security purposes */ 64 | memset(buffer, 0, buffer_size); 65 | 66 | entropy += current_buffer_index; 67 | current_buffer_index = 0; 68 | dbg_verb("Random module seeded"); 69 | 70 | return 0; 71 | } 72 | 73 | void rng_Feed(const uint8_t seed[], size_t seed_size) { 74 | const size_t to_be_fed = min(seed_size, ENTROPY_BUFFER_SIZE - current_buffer_index); 75 | for(size_t i=0; i= MINIMUM_ENTROPY) { 83 | rng_Update(); /* Only done if the SHA256 chip is available */ 84 | } 85 | } 86 | 87 | void rng_FeedBit(uint8_t bit) { 88 | bit = bit == 0 ? 0 : 1; 89 | entropy_bits = (entropy_bits << 1) + bit; 90 | nb_entropy_bits++; 91 | 92 | if(nb_entropy_bits == 8) { 93 | rng_Feed(&entropy_bits, 1); 94 | nb_entropy_bits = 0; 95 | } 96 | } 97 | 98 | void rng_FeedFromEvent() { 99 | /** 100 | * Usualy called when an USB event occurs. 101 | * As this is not a perfect entropy source, it only takes the 4 most significant bits of the LSB of the current timer value 102 | */ 103 | uint8_t seed = (uint8_t)((usb_GetCycleCounter() >> 4) & 0b1111); 104 | for(uint8_t i=0; i<4; i++) { 105 | rng_FeedBit((seed >> i) & 0b1); 106 | } 107 | } 108 | 109 | web_status_t rng_Random256b(uint8_t dst[32]) { 110 | if(!rng_IsAvailable()) { 111 | dbg_err("Not enough entropy"); 112 | return WEB_NOT_ENOUGH_ENTROPY; 113 | } 114 | 115 | const int ret_val = hkdf_HMAC(K, 32, V, 32, V); 116 | if(ret_val == 0) { 117 | memcpy(dst, V, 32); 118 | } 119 | 120 | return ret_val; 121 | } 122 | 123 | web_status_t rng_Random32b(uint32_t *var) { 124 | if(!rng_IsAvailable()) { 125 | dbg_warn("Not enough entropy"); 126 | return WEB_NOT_ENOUGH_ENTROPY; 127 | } 128 | 129 | uint8_t buffer[32]; 130 | int ret_val = rng_Random256b(buffer); 131 | if(ret_val == 0) { 132 | *var = ((uint32_t *)buffer)[0]; 133 | } 134 | memset(buffer, 0, 32); /* Clearing buffer for security purposes */ 135 | return ret_val; 136 | } 137 | -------------------------------------------------------------------------------- /src/internetce/crypto/sha256.c: -------------------------------------------------------------------------------- 1 | /** 2 | * SHA256 module 3 | * Inspired from Ti romcalls (but with the correct endianness...) 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #include "../include/crypto.h" 10 | #include "../include/debug.h" 11 | #include "../include/core.h" 12 | 13 | /* Internal state variables */ 14 | static bool enabled = false; 15 | static size_t total_bytes; 16 | static uint8_t next_command; 17 | 18 | 19 | bool sha256_IsEnabled() { 20 | return enabled; 21 | } 22 | 23 | web_status_t sha256_Init() { 24 | if(enabled) { 25 | dbg_warn("SHA256 module already initialized"); 26 | return WEB_SHA256_IN_USE; 27 | } 28 | 29 | flash_unlock(); 30 | 31 | enabled = true; 32 | *SHA256_ENABLE = 1; 33 | *SHA256_CTRL = 0x10; 34 | *SHA256_CTRL = 0; 35 | total_bytes = 0; 36 | next_command = SHA256_BEGIN_HASH; 37 | 38 | return WEB_SUCCESS; 39 | } 40 | 41 | 42 | web_status_t sha256_Part(const void *data, size_t size) { 43 | if(!enabled) { 44 | dbg_warn("SHA256 module not initialized"); 45 | return WEB_SHA256_NOT_INITIALIZED; 46 | } 47 | 48 | uint32_t *data_array = (uint32_t *)data; 49 | size_t already_filled = total_bytes & 0x3F; 50 | 51 | // Just wanted to say thank you SHA256 chip for being little-endian *sigh* 52 | const uint8_t modulo = already_filled % 4; 53 | if(modulo != 0) { 54 | uint32_t mask_block, mask_data; 55 | switch(modulo) { 56 | case 1: 57 | mask_block = 0xff000000; 58 | mask_data = 0x00ffffff; 59 | break; 60 | case 2: 61 | mask_block = 0xffff0000; 62 | mask_data = 0x0000ffff; 63 | break; 64 | case 3: 65 | mask_block = 0xffffff00; 66 | mask_data = 0x000000ff; 67 | break; 68 | default: 69 | /* Impossible */ 70 | dbg_err("SHA256: impossible branch"); 71 | return WEB_NOT_SUPPORTED; 72 | } 73 | SHA256_BLOCK[already_filled / 4] = (SHA256_BLOCK[already_filled / 4] & mask_block) | \ 74 | ((htonl(data_array[0]) >> ((modulo) * 8)) & mask_data); 75 | data_array = (uint32_t *)(data + (4 - modulo)); 76 | size -= 4 - modulo; 77 | already_filled += 4 - modulo; 78 | total_bytes += 4 - modulo; 79 | 80 | if(already_filled == 0x40) { 81 | already_filled = 0; 82 | *SHA256_CTRL = next_command; 83 | next_command = SHA256_CONTINUE_HASH; 84 | while((*SHA256_STATUS & 0b00001000) != 0); 85 | } 86 | } 87 | 88 | while(size != 0) { 89 | const size_t rem_size = min(0x40 - already_filled, size); 90 | for(size_t i = 0; i < (rem_size + 3) >> 2; i++) { 91 | SHA256_BLOCK[(already_filled >> 2) + i] = htonl(*data_array); 92 | data_array++; 93 | } 94 | 95 | size = size - rem_size; 96 | total_bytes += rem_size; 97 | already_filled += rem_size; 98 | if(already_filled == 0x40) { 99 | already_filled = 0; 100 | *SHA256_CTRL = next_command; 101 | next_command = SHA256_CONTINUE_HASH; 102 | while((*SHA256_STATUS & 0b00001000) != 0); 103 | } else if(already_filled > 0x40) { 104 | dbg_err("already_filled > 0x40"); 105 | } 106 | } 107 | 108 | return WEB_SUCCESS; 109 | } 110 | 111 | 112 | web_status_t sha256_Hash(void *dst) { 113 | if(!enabled) { 114 | dbg_warn("SHA256 module not initialized"); 115 | return WEB_SHA256_NOT_INITIALIZED; 116 | } 117 | 118 | const uint32_t total_bits_be = htonl(total_bytes << 3); 119 | const int modulo = total_bytes & 0x3F; 120 | if(modulo < 0x38) { 121 | const uint8_t tail[0x3c] = {0x80, 0}; 122 | sha256_Part(tail, 0x3c - modulo); 123 | } else { 124 | const uint8_t tail[0x7c] = {0x80, 0}; 125 | sha256_Part(tail, 0x7c - modulo); 126 | } 127 | 128 | sha256_Part(&total_bits_be, sizeof(uint32_t)); 129 | 130 | *SHA256_CTRL = 9; 131 | 132 | uint32_t *dst_array = (uint32_t *)dst; 133 | for(int i = 0; i < 0x20 / 4; i++) { 134 | dst_array[i] = ntohl(SHA256_HASH_DATA[i]); 135 | } 136 | 137 | *SHA256_ENABLE = 0; 138 | enabled = false; 139 | 140 | flash_lock(); 141 | 142 | return WEB_SUCCESS; 143 | } 144 | -------------------------------------------------------------------------------- /src/internetce/crypto/x25519.asm: -------------------------------------------------------------------------------- 1 | ; x25519 implementation 2 | ; Inspired by: https://martin.kleppmann.com/papers/curve25519.pdf 3 | ; 4 | ; This gives the two entrypoints: 5 | ; void x25519_scalarmult(uint8_t out[32], const uint8_t point[32], const uint8_t scalar[32]) 6 | ; void x25519_clampscalar(uint8_t scalar[32]) 7 | ; 8 | ; Currrently, x25519_scalarmult takes 3.57s to run 9 | 10 | 11 | include "mult256.asm" ; Generated by generate_mult.py 12 | 13 | ?_frameset0 := 0000130h 14 | 15 | 16 | ; --------------------- START SECTION .TEXT --------------------- 17 | 18 | section .text 19 | 20 | clampscalar: 21 | ; IY -> scalar to modify in place 22 | ld a, 0xf8 23 | and a, (iy+0) 24 | ld (iy+0), a 25 | ld a, 0x7f 26 | and a, (iy+31) 27 | or a, 0x40 28 | ld (iy+31), a 29 | ret 30 | 31 | public _x25519_scalarmult 32 | _x25519_scalarmult: 33 | ; IX+6 -> out 34 | ; IX+9 -> point 35 | ; IX+12 -> scalar 36 | di ; The implementation uses the shadow registers 37 | call _frameset0 ; reset carry flag 38 | push ix 39 | 40 | ; a=u, b=v, c=x, d=y, point=x 41 | ld hl, point_u 42 | ld (pointer_a), hl 43 | ld hl, point_v 44 | ld (pointer_b), hl 45 | ld hl, point_x 46 | ld (pointer_c), hl 47 | ld hl, point_y 48 | ld (pointer_d), hl 49 | ld hl, (ix+9) 50 | ld (pointer_point), hl 51 | 52 | ; 0-ing a, b, c, d 53 | or a, a 54 | sbc hl, hl 55 | ex de, hl 56 | sbc hl, hl 57 | add hl, sp 58 | ld sp, point_y + 33 59 | ld b, 11 60 | .zero_space: 61 | repeat 4 ; 3*4*11 == 4*33 == 132 62 | push de 63 | end repeat 64 | djnz .zero_space 65 | ld sp, hl 66 | 67 | ; a[0] = d[0] = 1 68 | ld a, 1 69 | ld (point_u), a 70 | ld (point_y), a 71 | 72 | ; b[0] = point 73 | ld hl, (ix+9) 74 | ld de, point_v 75 | ld bc, 32 76 | ldir 77 | 78 | ld iy, (ix+12) 79 | call clampscalar 80 | lea hl, iy+31 ; from MSB to LSB 81 | ld a, (hl) 82 | rla ; skipping bit 256 (always reset) 83 | ld (current_scalar_byte), a 84 | push hl 85 | ld a, 255 86 | .scalar_mult_loop: 87 | ex af, af' 88 | 89 | ; Swapping (or not) A/B, C/D 90 | xor a, a 91 | ld hl, current_scalar_byte 92 | rl (hl) 93 | swap25519 94 | 95 | ld iy, point_e 96 | ld ix, (pointer_a) 97 | ld de, (pointer_c) 98 | call x25519_add ; fadd(e, a, c) 99 | 100 | ld iy, (pointer_a) 101 | ; (pointer_a) is already in IX 102 | ld hl, (pointer_c) 103 | call x25519_sub ; fsub(a, a, c) 104 | 105 | ld iy, (pointer_c) 106 | ld ix, (pointer_b) 107 | ld de, (pointer_d) 108 | call x25519_add ; fadd(c, b, d) 109 | 110 | ld iy, (pointer_b) 111 | ; (pointer_b) is already in IX 112 | ld hl, (pointer_d) 113 | call x25519_sub ; fsub(b, b, d) 114 | 115 | ld de, (pointer_d) 116 | ld ix, point_e 117 | lea iy, ix 118 | call x25519_mult ; fmul(d, e, e) 119 | 120 | ld de, point_f 121 | ld ix, (pointer_a) 122 | lea iy, ix 123 | call x25519_mult ; fmul(f, a, a) 124 | 125 | ld iy, (pointer_a) 126 | lea de, iy 127 | ld ix, (pointer_c) 128 | call x25519_mult ; fmul(a, c, a) 129 | 130 | ld de, (pointer_c) 131 | ld ix, (pointer_b) 132 | ld iy, point_e 133 | call x25519_mult ; fmul(c, b, e) 134 | 135 | ld iy, point_e 136 | ld ix, (pointer_a) 137 | ld de, (pointer_c) 138 | call x25519_add ; fadd(e, a, c) 139 | 140 | ; (pointer_a) is already set in IX 141 | lea iy, ix 142 | ld hl, (pointer_c) 143 | call x25519_sub ; fadd(a, a, c) 144 | 145 | ld de, (pointer_b) 146 | ; (pointer_a) is already set in IX 147 | ; (pointer_a) is already set in IY 148 | call x25519_mult ; fmul(b, a, a) 149 | 150 | ld iy, (pointer_c) 151 | ld ix, (pointer_d) 152 | ld hl, point_f 153 | call x25519_sub ; fsub(c, d, f) 154 | 155 | ld de, (pointer_a) 156 | ld ix, (pointer_c) 157 | call x25519_mult121665 ; fmul_121665(a, c) 158 | 159 | ld iy, (pointer_a) 160 | lea ix, iy 161 | ld de, (pointer_d) 162 | call x25519_add ; fadd(a, a, d) 163 | 164 | ld ix, (pointer_c) 165 | lea de, ix 166 | ; (pointer_a) is already set in IY 167 | call x25519_mult ; fmul(c, c, a) 168 | 169 | ld de, (pointer_a) 170 | ld ix, (pointer_d) 171 | ld iy, point_f 172 | call x25519_mult ; fmul(a, d, f) 173 | 174 | ld de, (pointer_d) 175 | ld ix, (pointer_b) 176 | ld iy, (pointer_point) 177 | call x25519_mult ; fmul(d, b, x) 178 | 179 | ld de, (pointer_b) 180 | ld ix, point_e 181 | lea iy, ix 182 | call x25519_mult ; fmul(b, e, e) 183 | 184 | ; Swapping back (or not) A/B, C/D 185 | ld hl, point_u 186 | ld (pointer_a), hl 187 | ld hl, point_v 188 | ld (pointer_b), hl 189 | ld hl, point_x 190 | ld (pointer_c), hl 191 | ld hl, point_y 192 | ld (pointer_d), hl 193 | 194 | ex af, af' 195 | dec a 196 | jr z, .end_scalar_mult 197 | ; a = 0 [8] ? 198 | ; if a matches .....000 this means HL must be decremented 199 | tst a, 7 200 | jp nz, .scalar_mult_loop 201 | 202 | ; Taking next byte in scalar 203 | pop hl 204 | dec hl 205 | push hl 206 | ld b, (hl) 207 | ld hl, current_scalar_byte 208 | ld (hl), b 209 | jp .scalar_mult_loop 210 | 211 | .end_scalar_mult: 212 | inc sp ; poping HL from stack 213 | inc sp 214 | inc sp 215 | 216 | x25519_mult_inverse point_x ; finverse(c) => (pointer_c) equals to point_x 217 | 218 | ld ix, point_x ; (pointer_c) equals to point_x 219 | ld iy, point_u ; equals to (pointer_a) 220 | lea de, iy 221 | call x25519_mult ; fmul(a, c, a) 222 | 223 | pop ix 224 | ld de, (ix+6) 225 | ld hl, point_u 226 | ld bc, 32 227 | ldir 228 | 229 | pop ix 230 | ei 231 | ret 232 | 233 | 234 | ; 315 cycles according to CEmu 235 | ; 248 cycles in theory 236 | macro swap25519? 237 | ; If carry flag is set: exchange A/B, C/D 238 | ; Otherwise, "do nothing" 239 | rla 240 | ld e, a 241 | add a, e 242 | add a, e ; A = [bit0]*3 243 | ; For A/B 244 | sbc hl, hl 245 | ex de, hl 246 | ld e, a 247 | ld hl, pointer_a 248 | ld bc, (hl) 249 | add hl, de 250 | ld de, (hl) 251 | ld (hl), bc 252 | ld (pointer_a), de 253 | ; For C/D 254 | sbc hl, hl 255 | ex de, hl 256 | ld e, a 257 | ld hl, pointer_c 258 | ld bc, (hl) 259 | add hl, de 260 | ld de, (hl) 261 | ld (hl), bc 262 | ld (pointer_c), de 263 | end macro 264 | 265 | 266 | ; 121665 == 0x01DB41 267 | ; Size: 229 bytes 268 | x25519_mult121665: 269 | ; IX: src 270 | ; DE: dst 271 | or a, a 272 | sbc hl, hl 273 | add hl, sp ; reset carry flag 274 | exx 275 | 276 | sbc hl, hl 277 | ld sp, tmp_buffer+(12*3) 278 | repeat 12 ; only needing 255(op1)+17(op2)+5(19)=277 bits => 35 bytes 279 | push hl 280 | end repeat 281 | 282 | ld sp, tmp_buffer 283 | 284 | ld d, (ix+0) 285 | ld e, 0x41 286 | mlt de 287 | pop hl 288 | add hl, de 289 | push hl 290 | inc sp 291 | 292 | ld bc, (ix+0) 293 | ld e, c 294 | ld d, 0xdb 295 | mlt de 296 | ex de, hl 297 | ld c, 0x41 298 | mlt bc 299 | add hl, bc 300 | pop de 301 | add hl, de 302 | push hl 303 | inc sp 304 | 305 | lea de, ix 306 | or a, a 307 | exx 308 | ld b, 30 309 | .mult121665_loop: 310 | exx 311 | sbc hl, hl 312 | ld a, (de) 313 | ld l, a 314 | inc de 315 | ld a, (de) 316 | ld c, a 317 | ld b, 0xdb 318 | mlt bc 319 | add hl, bc 320 | inc de 321 | ld a, (de) 322 | ld c, a 323 | ld b, 0x41 324 | mlt bc 325 | add hl, bc 326 | pop bc 327 | add hl, bc 328 | push hl 329 | inc sp 330 | dec de 331 | exx 332 | djnz .mult121665_loop 333 | exx 334 | 335 | sbc hl, hl 336 | ld c, (ix+30) 337 | ld l, c 338 | ld e, (ix+31) 339 | ld d, 0xdb 340 | mlt de 341 | add hl, de 342 | pop de 343 | add hl, de 344 | push hl 345 | inc sp 346 | 347 | sbc hl, hl 348 | ld c, (ix+31) 349 | ld l, c 350 | pop de 351 | add hl, de ;IY+33 352 | push hl 353 | 354 | exx 355 | ld sp, hl ; restore SP 356 | exx 357 | 358 | ; modulo on only 17 bits x19 -> 17+5=22 bits of carry <24 359 | ld ix, tmp_buffer 360 | lea hl, ix+31 361 | ld a, (hl) 362 | rla ; bit 7 of (hl) in carry flag 363 | res 7, (hl) 364 | inc hl 365 | ld d, (hl) 366 | rl d 367 | ld a, 19 368 | ld e, a ; 19 369 | mlt de 370 | inc hl 371 | ld b, (hl) 372 | rl b 373 | ld c, a ; 19 374 | mlt bc 375 | ; BC*256 376 | push bc 377 | dec sp 378 | pop bc 379 | inc sp 380 | ld c, 0 381 | ; ----- 382 | ex de, hl 383 | ex af, af' ; saving carry 384 | add hl, bc 385 | ex af, af' 386 | ex de, hl 387 | inc hl 388 | ld c, (hl) 389 | rl c 390 | ld b, a ; 19 391 | mlt bc ; only C should be non-0 392 | ; BC*65536 393 | ld (ix+50), c ; ix+50 == saferam 394 | ld hl, (ix+48) 395 | ld l, 0 396 | ld h, l 397 | ; ----- 398 | add hl, de 399 | 400 | ld a, 2 401 | .repeat_carry: 402 | ld de, (ix+0) 403 | add hl, de 404 | ld (ix+0), hl 405 | ld b, 10 406 | ld de, 0 ; carry must be preserved so not using sbc 407 | .carry_loop: 408 | lea ix, ix+3 409 | ld hl, (ix) 410 | adc hl, de ; DE == 0 411 | ld (ix), hl 412 | djnz .carry_loop 413 | 414 | ld ix, tmp_buffer 415 | ; bit 256 may remain set 416 | dec a 417 | jr z, .no_more_carry 418 | 419 | sbc hl, hl 420 | ld b, (ix+31) 421 | rl b 422 | res 7, (ix+31) 423 | rl l 424 | ld h, 19 425 | mlt hl 426 | jr .repeat_carry 427 | .no_more_carry: 428 | 429 | ld (ix+32), 0 ; might be >0 430 | jq modulo_last_step 431 | 432 | 433 | macro x25519_mult_inverse point 434 | ld hl, point 435 | ld de, point_e ; not used anymore 436 | ld bc, 33 437 | ldir ; point_e contains a copy of point 438 | 439 | ld a, 254 440 | .inverse_loop: 441 | ex af, af' 442 | ld iy, point 443 | lea ix, iy 444 | lea de, iy 445 | call x25519_mult 446 | ex af, af' 447 | cp a, 5 448 | jr z, .bit_0 449 | cp a, 3 450 | jr z, .bit_0 451 | ex af, af' 452 | ld iy, point 453 | lea de, iy 454 | ld ix, point_e 455 | call x25519_mult 456 | ex af, af' 457 | .bit_0: 458 | dec a 459 | jr nz, .inverse_loop 460 | end macro 461 | 462 | 463 | ; x25519_square: 464 | ; ; TODO make fast square 465 | ; ret 466 | 467 | ; ~750 cycles with call/ret without modulo and mult 468 | ; 55K cycles in total 469 | ; ~8820 bytes with tmp_buffer and ret 470 | x25519_mult: 471 | ; IX -> OP1 472 | ; IY -> OP2 473 | ; DE -> RES 474 | ; destroys IX and IY 475 | or a, a 476 | sbc hl, hl 477 | add hl, sp ; reset carry flag 478 | exx 479 | 480 | ; Set RES to 0 (244 cycles / 28 Bytes) 481 | sbc hl, hl 482 | ld sp, tmp_buffer_end 483 | repeat 22 484 | push hl 485 | end repeat 486 | 487 | ; Do the mult 488 | ; SP, IX, IY are set beforehand 489 | mult256 490 | 491 | ld ix, tmp_buffer 492 | exx 493 | ld sp, hl 494 | exx 495 | x25519_modulo 496 | exx 497 | 498 | ; 402 cycles 499 | ; 51 bytes 500 | ; IX == the result 501 | ; DE == the destination 502 | ; HL == SP 503 | ex de, hl 504 | ld bc, 33 505 | add hl, bc 506 | ld sp, hl 507 | iterate idx, 30, 27, 24, 21, 18, 15, 12, 9, 6, 3, 0 508 | ld bc, (ix+idx) 509 | push bc 510 | end iterate 511 | 512 | ex de, hl 513 | ld sp, hl 514 | ret 515 | 516 | 517 | ; 5014 cycles 518 | ; 185 bytes 519 | macro x25519_modulo? 520 | ; IX+0/65 521 | ; First phase: IX+32/63 - 1bit is multiplied by 19 and shifted 1 byte to the right to make room for IX+0/31->32 522 | xor a, a 523 | ex af, af' 524 | or a, a 525 | ld b, 33 526 | ld c, 19 527 | lea hl, ix+31 528 | ld e, (hl) 529 | rl e 530 | res 7, (hl) 531 | inc hl 532 | ld e, (hl) 533 | ld (hl), 0 ; shifting op2 -> making room for 33 bits 534 | .loop_modulo: 535 | rl e 536 | ex af, af' 537 | ld d, c 538 | mlt de 539 | adc a, e 540 | inc hl 541 | ld e, (hl) 542 | ld (hl), a 543 | ld a, d 544 | ex af, af' 545 | djnz .loop_modulo 546 | ex af, af' 547 | 548 | lea de, ix+33 549 | lea iy, ix 550 | call x25519_add 551 | 552 | ; The modulo can still be > 255 bits (max 263 bits) 553 | lea hl, ix+31 554 | ld a, (hl) 555 | rla 556 | res 7, (hl) 557 | inc hl 558 | ld d, (hl) 559 | ld (hl), 0 560 | rl d 561 | ld e, 19 562 | mlt de 563 | 564 | sbc hl, hl ; carry flag should be reset by rl 565 | ex de, hl 566 | ld bc, (ix+0) 567 | add hl, bc 568 | ld (ix+0), hl 569 | iterate idx, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30 570 | ld hl, (ix+idx) 571 | adc hl, de ; DE == 0 572 | ld (ix+idx), hl 573 | end iterate 574 | 575 | ; Number can still be between 2**255-19 and 2**255 576 | ; Substract the number by 2**255-19: 577 | ; - if the carry flag is reset, then keeping the result 578 | ; - otherwise the number is unchanged 579 | ; After this, IX might have changed 580 | modulo_last_step: 581 | lea hl, ix 582 | lea de, ix+33 583 | ld (ix+65), 0 584 | ld a, (hl) 585 | sub a, 0xed 586 | ld (de), a 587 | inc hl 588 | inc de 589 | ld c, 0xff 590 | ld b, 2 591 | .inv_loop: ; adding 8+13+8 -> 29 cycles but winning 60B 592 | repeat 15 593 | ld a, (hl) 594 | sbc a, c 595 | ld (de), a 596 | inc hl 597 | inc de 598 | end repeat 599 | djnz .inv_loop 600 | ld a, (hl) 601 | sbc a, 0x7f 602 | ld (de), a 603 | 604 | ; if no carry -> number was > than 2**255-19 605 | ccf 606 | rl b ; Before: B == 0 607 | ld c, 33 608 | mlt bc 609 | add ix, bc 610 | end macro 611 | 612 | 613 | x25519_sub: 614 | ; IX first operand 615 | ; HL second operand 616 | ; IY destination 617 | ; Precondition: no add or sub before, because (DE) must be lower than 2**255-19 618 | ; Postcondition: The result might be greater than 2**255-19, but will always overflow 2**256 619 | ; -> So the next op should be a multiplication 620 | ld de, tmp_buffer 621 | x25519_inv 622 | ld de, tmp_buffer 623 | ; the ADD is following 624 | 625 | 626 | ; cycles: 758 (without modulo and call/ret) 627 | ; size: 107 bytes (no ret) 628 | x25519_add: 629 | ; ix -> one BIG number (32 B with 1 byte to 0 at the end) 630 | ; de -> one BIG number (32 B with 1 byte to 0 at the end) 631 | ; iy -> BIG number destination (32 B with 1 byte to 0 at the end) 632 | or a, a ; 4 633 | sbc hl, hl ; 8 634 | add hl, sp ; 4 635 | ex de, hl ; 4 636 | 637 | ld sp, hl ; 4 638 | iterate idx, 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30 639 | ld hl, (ix+idx) ; 24 640 | pop bc ; 16 641 | adc hl, bc ; 8 642 | ld (iy+idx), hl ; 18 643 | end iterate 644 | 645 | ex de, hl ; 4 646 | ld sp, hl ; 4 647 | ret 648 | 649 | 650 | ; cycles: 883 651 | ; Size: 109 bytes 652 | macro x25519_inv? 653 | ; HL -> number 654 | ; DE -> dest 655 | ld a, 0xed 656 | sub a, (hl) 657 | ld (de), a 658 | inc hl 659 | inc de 660 | ld c, 0xff 661 | ld b, 2 662 | .inv_loop: ; adding 8+13+8 -> 29 cycles but winning 60B 663 | repeat 15 664 | ld a, c 665 | sbc a, (hl) 666 | ld (de), a 667 | inc hl 668 | inc de 669 | end repeat 670 | djnz .inv_loop 671 | ld a, 0x7f 672 | sbc a, (hl) 673 | ld (de), a 674 | inc de 675 | xor a, a 676 | ld (de), a 677 | end macro 678 | 679 | 680 | extern _mult256 681 | 682 | ; ---------------------- END SECTION .TEXT ---------------------- 683 | 684 | 685 | ; --------------------- START SECTION .DATA --------------------- 686 | 687 | ; Numbers are stored little endian (LSB first) 688 | 689 | section .data 690 | ; These are pointers to point_uvxy 691 | pointer_a: 692 | db 0,0,0 693 | pointer_b: 694 | db 0,0,0 695 | pointer_c: 696 | db 0,0,0 697 | pointer_d: 698 | db 0,0,0 699 | pointer_point: 700 | db 0,0,0 701 | 702 | ; These are the actual points (only x coordinate) 703 | point_u: 704 | db 33 dup (0) 705 | point_v: 706 | db 33 dup (0) 707 | point_x: 708 | db 33 dup (0) 709 | point_y: 710 | db 33 dup (0) 711 | point_e: 712 | db 33 dup (0) 713 | point_f: 714 | db 33 dup (0) 715 | tmp_buffer: 716 | db 66 dup (0) ; 33*2 717 | tmp_buffer_end: 718 | 719 | current_scalar_byte: 720 | db 0 721 | 722 | private tmp_buffer 723 | private tmp_buffer_end 724 | private point_u 725 | private point_v 726 | private point_x 727 | private point_y 728 | private point_e 729 | private point_f 730 | private pointer_a 731 | private pointer_b 732 | private pointer_c 733 | private pointer_d 734 | private pointer_point 735 | private current_scalar_byte 736 | 737 | ; ---------------------- END SECTION .DATA ---------------------- 738 | -------------------------------------------------------------------------------- /src/internetce/debug.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "include/debug.h" 8 | #include "include/core.h" 9 | 10 | 11 | #if DEBUG_LEVEL >= DEBUG_ERRORS 12 | void debug(const void *addr, size_t len) { 13 | uint8_t *content = (uint8_t *)addr; 14 | for(size_t i = 0; i < len; i++) { 15 | if(i && i % 8 == 0) { 16 | printf("\n"); 17 | } 18 | printf("%.2X ", *(content + i)); 19 | } 20 | printf("\n"); 21 | } 22 | 23 | void printf_xy(unsigned int xpos, unsigned int ypos, const char *format, ...) { 24 | unsigned int x, y; 25 | os_GetCursorPos(&x, &y); 26 | os_SetCursorPos(xpos, ypos); 27 | va_list args; 28 | va_start(args, format); 29 | vprintf(format, args); 30 | va_end(args); 31 | os_SetCursorPos(x, y); 32 | } 33 | #endif 34 | 35 | #if DEBUG_LEVEL >= DEBUG_INFO 36 | void print_tcp_info(const tcp_segment_t *seg, tcp_exchange_t *tcp_exch, size_t length, bool is_me) { 37 | if(is_me) { 38 | printf("SND:"); 39 | } else { 40 | printf("RCV:"); 41 | } 42 | if(seg->dataOffset_flags & htons(FLAG_TCP_SYN)) { 43 | printf("S"); 44 | } 45 | if(seg->dataOffset_flags & htons(FLAG_TCP_ACK)) { 46 | printf("A"); 47 | } 48 | if(seg->dataOffset_flags & htons(FLAG_TCP_RST)) { 49 | printf("R"); 50 | } 51 | if(seg->dataOffset_flags & htons(FLAG_TCP_FIN)) { 52 | printf("F"); 53 | } 54 | if(seg->dataOffset_flags & htons(FLAG_TCP_PSH)) { 55 | printf("P"); 56 | } 57 | if(seg->dataOffset_flags & htons(FLAG_TCP_URG)) { 58 | printf("U"); 59 | } 60 | 61 | uint32_t seq_number = htonl(seg->seq_number); 62 | uint32_t ack_number = htonl(seg->ack_number); 63 | if(is_me) { 64 | seq_number -= tcp_exch->beg_sn; 65 | ack_number -= tcp_exch->beg_ackn; 66 | } else { 67 | seq_number -= tcp_exch->beg_ackn; 68 | ack_number -= tcp_exch->beg_sn; 69 | } 70 | if(tcp_exch->beg_ackn != 0 && tcp_exch->beg_sn != 0) { 71 | printf(" (%lu+%d)", seq_number, length - 4 * (seg->dataOffset_flags >> 4 & 0x0f)); 72 | } 73 | printf(" a=%lu\n", ack_number); 74 | } 75 | 76 | static alloced_mem_t *alloced_mem_list = NULL; 77 | void *_malloc(size_t size, const char *id) { 78 | alloced_mem_t *alloced_mem = malloc(sizeof(alloced_mem_t)); 79 | alloced_mem->next = alloced_mem_list; 80 | alloced_mem_list = alloced_mem; 81 | alloced_mem->ptr = malloc(size); 82 | if(id != NULL) { 83 | strncpy(alloced_mem->id, id, 10); 84 | } else { 85 | alloced_mem->id[0] = 0x00; 86 | } 87 | return alloced_mem->ptr; 88 | } 89 | 90 | void *_realloc(void *ptr, size_t size) { 91 | alloced_mem_t *cur_alloced = alloced_mem_list; 92 | while(cur_alloced) { 93 | if(cur_alloced->ptr == ptr) { 94 | void *new_ptr = realloc(ptr, size); 95 | if(new_ptr == NULL) { 96 | return NULL; 97 | } 98 | cur_alloced->ptr = new_ptr; 99 | return new_ptr; 100 | } 101 | cur_alloced = cur_alloced->next; 102 | } 103 | dbg_err("NOT FOUND REALLOC %p", ptr); 104 | return NULL; 105 | } 106 | 107 | void _free(void *ptr) { 108 | alloced_mem_t *cur_alloced = alloced_mem_list; 109 | alloced_mem_t *prev_alloced = NULL; 110 | while(cur_alloced) { 111 | if(cur_alloced->ptr == ptr) { 112 | free(ptr); 113 | if(prev_alloced) { 114 | prev_alloced->next = cur_alloced->next; 115 | } else { 116 | alloced_mem_list = cur_alloced->next; 117 | } 118 | free(cur_alloced); 119 | return; 120 | } 121 | prev_alloced = cur_alloced; 122 | cur_alloced = cur_alloced->next; 123 | } 124 | dbg_err("NOT FOUND %p", ptr); 125 | } 126 | 127 | void print_allocated_memory() { 128 | alloced_mem_t *cur_alloced = alloced_mem_list; 129 | if(alloced_mem_list == NULL) { 130 | printf("Good memory state!\n"); 131 | return; 132 | } 133 | while(cur_alloced) { 134 | if(cur_alloced->id[0] != 0x00) { 135 | printf("%s ", cur_alloced->id); 136 | } else { 137 | debug(cur_alloced->ptr - 4, 15); 138 | } 139 | cur_alloced = cur_alloced->next; 140 | } 141 | } 142 | #else 143 | void *_malloc(size_t size, const char *id) { 144 | (void)id; /* Unused parameter */ 145 | return malloc(size); 146 | } 147 | 148 | void *_realloc(void *ptr, size_t size) { 149 | return realloc(ptr, size); 150 | } 151 | 152 | void _free(void *ptr) { 153 | free(ptr); 154 | } 155 | #endif 156 | 157 | #if DEBUG_LEVEL >= DEBUG_VERBOSE 158 | void monitor_usb_connection(usb_event_t event, device_state_t state) { 159 | static const char *usb_event_names[] = { 160 | "USB_ROLE_CHANGED_EVENT", 161 | "USB_DEVICE_DISCONNECTED_EVENT", 162 | "USB_DEVICE_CONNECTED_EVENT", 163 | "USB_DEVICE_DISABLED_EVENT", 164 | "USB_DEVICE_ENABLED_EVENT", 165 | "USB_HUB_LOCAL_POWER_GOOD_EVENT", 166 | "USB_HUB_LOCAL_POWER_LOST_EVENT", 167 | "USB_DEVICE_RESUMED_EVENT", 168 | "USB_DEVICE_SUSPENDED_EVENT", 169 | "USB_DEVICE_OVERCURRENT_DEACTIVATED_EVENT", 170 | "USB_DEVICE_OVERCURRENT_ACTIVATED_EVENT", 171 | "USB_DEFAULT_SETUP_EVENT", 172 | "USB_HOST_CONFIGURE_EVENT", 173 | "USB_DEVICE_INTERRUPT", 174 | "USB_DEVICE_CONTROL_INTERRUPT", 175 | "USB_DEVICE_DEVICE_INTERRUPT", 176 | "USB_OTG_INTERRUPT", 177 | "USB_HOST_INTERRUPT", 178 | "USB_CONTROL_ERROR_INTERRUPT", 179 | "USB_CONTROL_ABORT_INTERRUPT", 180 | "USB_FIFO0_SHORT_PACKET_INTERRUPT", 181 | "USB_FIFO1_SHORT_PACKET_INTERRUPT", 182 | "USB_FIFO2_SHORT_PACKET_INTERRUPT", 183 | "USB_FIFO3_SHORT_PACKET_INTERRUPT", 184 | "USB_DEVICE_ISOCHRONOUS_ERROR_INTERRUPT", 185 | "USB_DEVICE_ISOCHRONOUS_ABORT_INTERRUPT", 186 | "USB_DEVICE_DMA_FINISH_INTERRUPT", 187 | "USB_DEVICE_DMA_ERROR_INTERRUPT", 188 | "USB_DEVICE_IDLE_INTERRUPT", 189 | "USB_DEVICE_WAKEUP_INTERRUPT", 190 | "USB_B_SRP_COMPLETE_INTERRUPT", 191 | "USB_A_SRP_DETECT_INTERRUPT", 192 | "USB_A_VBUS_ERROR_INTERRUPT", 193 | "USB_B_SESSION_END_INTERRUPT", 194 | "USB_OVERCURRENT_INTERRUPT", 195 | "USB_HOST_PORT_CONNECT_STATUS_CHANGE_INTERRUPT", 196 | "USB_HOST_PORT_ENABLE_DISABLE_CHANGE_INTERRUPT", 197 | "USB_HOST_PORT_OVERCURRENT_CHANGE_INTERRUPT", 198 | "USB_HOST_PORT_FORCE_PORT_RESUME_INTERRUPT", 199 | "USB_HOST_SYSTEM_ERROR_INTERRUPT", 200 | }; 201 | if(event != USB_DEVICE_WAKEUP_INTERRUPT && event != USB_OTG_INTERRUPT && event != USB_DEVICE_DEVICE_INTERRUPT && 202 | event != USB_DEVICE_INTERRUPT && event != USB_HOST_INTERRUPT) { 203 | printf("%s\n", usb_event_names[event]); 204 | } 205 | unsigned int x, y; 206 | os_GetCursorPos(&x, &y); 207 | os_SetCursorPos(0, 0); 208 | printf("%lu ", usb_GetCycleCounter()); 209 | switch(state) { 210 | case STATE_USB_CONNECTED: 211 | printf("CONNECTED "); 212 | break; 213 | case STATE_USB_ENABLED: 214 | printf("ENABLED "); 215 | break; 216 | case STATE_DHCP_CONFIGURING: 217 | printf("DHCP "); 218 | break; 219 | case STATE_NETWORK_CONFIGURED: 220 | printf("NETWORK "); 221 | break; 222 | case STATE_UNKNOWN: 223 | printf("UNKNOWN "); 224 | break; 225 | case STATE_USB_INITIALIZED: 226 | printf("INITIALIZED "); 227 | break; 228 | case STATE_USB_LOST: 229 | printf("LOST "); 230 | break; 231 | default: 232 | printf("??? "); 233 | break; 234 | } 235 | os_SetCursorPos(x, y); 236 | } 237 | #endif 238 | -------------------------------------------------------------------------------- /src/internetce/dhcp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "include/dhcp.h" 7 | #include "include/core.h" 8 | #include "include/debug.h" 9 | #include "include/crypto.h" 10 | 11 | 12 | /**********************************************************************************************************************\ 13 | * Global Variables * 14 | \**********************************************************************************************************************/ 15 | 16 | static msg_queue_t *dhcp_last_msg_queue = NULL; 17 | 18 | 19 | /**********************************************************************************************************************\ 20 | * Private functions * 21 | \**********************************************************************************************************************/ 22 | 23 | /* Note: This file has only internal functions */ 24 | 25 | msg_queue_t *push_dhcp_message(size_t opt_size, const uint8_t *options, uint32_t dhcp_server_ip) { 26 | static uint32_t xid = 0; 27 | if(xid == 0) { /* If not initialized yet */ 28 | if(rng_Random32b(&xid) != 0) { 29 | return NULL; 30 | } 31 | } 32 | 33 | const size_t size = sizeof(dhcp_message_t) + opt_size; 34 | uint8_t buffer[size]; 35 | memset(buffer, 0, size); 36 | dhcp_message_t *dhcp_query = (dhcp_message_t *)buffer; 37 | dhcp_query->op = DHCP_OP_REQUEST; 38 | dhcp_query->htype = DHCP_HTYPE_MAC; 39 | dhcp_query->hlen = DHCP_HLEN_MAC; 40 | dhcp_query->hops = 0x00; 41 | dhcp_query->xid = xid; 42 | memcpy(dhcp_query->chaddr, netinfo.my_MAC_addr, 6); 43 | /* 192 zeros */ 44 | dhcp_query->magicCookie = DHCP_MAGIC_COOKIE; 45 | memcpy(dhcp_query->options, options, opt_size); 46 | dhcp_query->siaddr = dhcp_server_ip; /* = 0 at first */ 47 | 48 | return web_PushUDPDatagram(dhcp_query, sizeof(dhcp_message_t) + opt_size, 0xffffffff, CLIENT_DHCP_PORT, 49 | SERVER_DHCP_PORT); 50 | } 51 | 52 | int dhcp_init() { 53 | const uint8_t options_disc[] = { 54 | DHCP_OPT_TYPE_ID, DHCP_OPT_TYPE_LEN, DHCP_OPT_V_DISCOVER, 55 | DHCP_OPT_END_OPTIONS}; 56 | dhcp_last_msg_queue = push_dhcp_message(sizeof(options_disc), options_disc, 0x00); 57 | if(dhcp_last_msg_queue == NULL) { 58 | dbg_err("An error occurred in dhcp_init"); 59 | return -1; 60 | } 61 | const web_status_t ret_val = web_ListenPort(CLIENT_DHCP_PORT, fetch_dhcp_msg, NULL); 62 | if(ret_val != WEB_SUCCESS) { 63 | web_PopMessage(dhcp_last_msg_queue); 64 | dhcp_last_msg_queue = NULL; 65 | dbg_err("An error occurred in dhcp_init"); 66 | return -2; 67 | } 68 | netinfo.dhcp_cur_state = DHCP_STATE_INIT; 69 | return 0; 70 | } 71 | 72 | web_status_t fetch_dhcp_msg(web_port_t port, uint8_t protocol, void *msg, size_t length, 73 | web_callback_data_t *user_data) { 74 | (void)port; (void)length; (void)user_data; /* Unused parameters */ 75 | if(protocol != UDP_PROTOCOL) 76 | return WEB_SUCCESS; 77 | 78 | const dhcp_message_t *dhcp_msg = (dhcp_message_t *)((uint8_t *)msg + sizeof(udp_datagram_t)); 79 | 80 | if(dhcp_msg->op == DHCP_OP_REPLY) { 81 | const uint8_t *cur_opt = (uint8_t *)((uint8_t *)dhcp_msg + sizeof(dhcp_message_t)); 82 | while(cur_opt[0] != DHCP_OPT_END_OPTIONS) { 83 | switch(cur_opt[0]) { 84 | case DHCP_OPT_TYPE_ID: 85 | if(cur_opt[2] == DHCP_OPT_V_OFFER && netinfo.dhcp_cur_state == DHCP_STATE_INIT) { 86 | if(dhcp_last_msg_queue != NULL) { 87 | web_PopMessage(dhcp_last_msg_queue); 88 | } 89 | uint8_t options_req[] = { 90 | DHCP_OPT_TYPE_ID, DHCP_OPT_TYPE_LEN, DHCP_OPT_V_REQUEST, 91 | DHCP_OPT_PARAM_REQ_LIST_ID, 1, DHCP_OPT_DNS_ID, 92 | DHCP_OPT_SERVER_ID, DHCP_OPT_IP_LEN, 0, 0, 0, 0, 93 | DHCP_OPT_REQ_IP_ID, DHCP_OPT_IP_LEN, 0, 0, 0, 0, 94 | DHCP_OPT_END_OPTIONS}; 95 | 96 | *(uint32_t *)(options_req + 8) = dhcp_msg->siaddr; 97 | *(uint32_t *)(options_req + 14) = dhcp_msg->yiaddr; 98 | dhcp_last_msg_queue = push_dhcp_message(sizeof(options_req), options_req, dhcp_msg->siaddr); 99 | if(dhcp_last_msg_queue != NULL) { 100 | netinfo.dhcp_cur_state = DHCP_STATE_SELECTING; 101 | } else { 102 | dbg_err("An error occurred in fetch_dhcp_msg"); 103 | } 104 | } else if(cur_opt[2] == DHCP_OPT_V_ACK && netinfo.dhcp_cur_state == DHCP_STATE_SELECTING) { 105 | if(dhcp_last_msg_queue != NULL) { 106 | web_PopMessage(dhcp_last_msg_queue); 107 | dhcp_last_msg_queue = NULL; 108 | } 109 | netinfo.IP_addr = dhcp_msg->yiaddr; 110 | memcpy(netinfo.router_MAC_addr, src_mac_addr, 6); 111 | netinfo.dhcp_cur_state = DHCP_STATE_BIND; 112 | netinfo.state = STATE_NETWORK_CONFIGURED; 113 | } else if(cur_opt[2] == DHCP_OPT_V_NAK && netinfo.dhcp_cur_state == DHCP_STATE_SELECTING) { 114 | dbg_warn("DHCP NACK"); 115 | if(dhcp_last_msg_queue != NULL) { 116 | web_PopMessage(dhcp_last_msg_queue); 117 | dhcp_last_msg_queue = NULL; 118 | } 119 | web_UnlistenPort(CLIENT_DHCP_PORT); 120 | dhcp_init(); 121 | } else { 122 | dbg_err("Unknown DHCP message"); 123 | } 124 | break; 125 | case DHCP_OPT_DNS_ID: 126 | if(netinfo.dhcp_cur_state != DHCP_STATE_BIND) { 127 | netinfo.DNS_IP_addr = *((uint32_t *)(cur_opt + 2)); /* we only take the first entry */ 128 | } 129 | break; 130 | case 58: /* T1 Lease time */ 131 | // TODO t1_leasetime = rtc_Time() + htonl(*(cur_opt + 2)); 132 | break; 133 | default: 134 | break; 135 | } 136 | cur_opt += *(cur_opt + 1) + 2; 137 | } 138 | } 139 | return WEB_SUCCESS; 140 | } 141 | -------------------------------------------------------------------------------- /src/internetce/dns.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "include/dns.h" 6 | #include "include/core.h" 7 | #include "include/debug.h" 8 | #include "include/scheduler.h" 9 | 10 | 11 | /**********************************************************************************************************************\ 12 | * Public functions * 13 | \**********************************************************************************************************************/ 14 | 15 | uint32_t web_SendDNSRequest(const char *url) { 16 | uint32_t res_ip = 0; 17 | web_status_t status = web_PushDNSRequest(url, &dns_callback, &res_ip); 18 | if(status != WEB_SUCCESS) { 19 | return 0xffffffff; 20 | } 21 | 22 | while(!res_ip) { 23 | web_WaitForEvents(); 24 | } 25 | return res_ip; 26 | } 27 | 28 | web_status_t web_PushDNSRequest(const char *url, web_dns_callback_t *callback, web_callback_data_t *user_data) { 29 | static unsigned int id_request = 0x01; 30 | /* 2=length byte at the begining of the string+0 terminated string */ 31 | size_t length_data = sizeof(dns_message_t) + strlen(url) + 2 + 4; 32 | uint8_t buffer[length_data]; 33 | memset(buffer, 0, length_data); 34 | dns_message_t *query = (dns_message_t *)buffer; 35 | 36 | query->id = id_request++; /* osef endianness */ 37 | query->flags = htons(0x0100); /* Recursion allowed */ 38 | query->questions = htons(0x0001); 39 | 40 | /* formating address for dns purposes */ 41 | char *cursor_qry = (char *)(buffer + sizeof(dns_message_t) + 1); 42 | char *cursor_str = (char *)url; 43 | uint8_t i = 1; 44 | while(*cursor_str != '\0' && *cursor_str != '/') { 45 | if(*cursor_str == '.') { 46 | *(cursor_qry - i) = i - 1; 47 | i = 0; 48 | } else { 49 | *cursor_qry = *cursor_str; 50 | } 51 | i++; 52 | cursor_str++; 53 | cursor_qry++; 54 | } 55 | *(cursor_qry - i) = i - 1; 56 | *(cursor_qry + 2) = 1; /* A (IPv4) */ 57 | *(cursor_qry + 4) = 1; /* IN (internet) */ 58 | 59 | dns_exchange_t *dns_exch = _malloc(sizeof(dns_exchange_t), "dns"); 60 | if(dns_exch == NULL) { 61 | return WEB_NOT_ENOUGH_MEM; 62 | } 63 | web_port_t client_port = web_RequestPort(); 64 | dns_exch->port_src = client_port; 65 | dns_exch->callback = callback; 66 | dns_exch->user_data = user_data; 67 | dns_exch->queued_request = web_PushUDPDatagram(query, length_data, 0x08080808, client_port, DNS_PORT); 68 | if(dns_exch->queued_request == NULL) { 69 | _free(dns_exch); 70 | return WEB_ERROR_FAILED; 71 | } 72 | web_status_t ret_val = web_ListenPort(client_port, fetch_dns_msg, dns_exch); 73 | if(ret_val != WEB_SUCCESS) { 74 | web_PopMessage(dns_exch->queued_request); 75 | _free(dns_exch); 76 | return ret_val; 77 | } 78 | 79 | ret_val = delay_event(TIMEOUT_NET * 1000, dns_timeout_scheduler, dns_timeout_destructor, dns_exch); 80 | if(ret_val != WEB_SUCCESS) { 81 | web_UnlistenPort(client_port); 82 | web_PopMessage(dns_exch->queued_request); 83 | _free(dns_exch); 84 | } 85 | return ret_val; 86 | } 87 | 88 | 89 | /**********************************************************************************************************************\ 90 | * Private functions * 91 | \**********************************************************************************************************************/ 92 | 93 | web_status_t dns_callback(web_port_t port, uint32_t res_ip, web_callback_data_t *user_data) { 94 | (void)port; 95 | *((uint32_t*)user_data) = res_ip; 96 | return WEB_SUCCESS; 97 | } 98 | 99 | scheduler_status_t dns_timeout_scheduler(web_callback_data_t *user_data) { 100 | dns_exchange_t *dns_exch = (dns_exchange_t *)user_data; 101 | dns_exch->callback(dns_exch->port_src, 0xffffffff, dns_exch->user_data); 102 | return SCHEDULER_DESTROY; 103 | } 104 | 105 | void dns_timeout_destructor(web_callback_data_t *user_data) { 106 | dns_exchange_t *dns_exch = (dns_exchange_t *)user_data; 107 | web_PopMessage(dns_exch->queued_request); 108 | web_UnlistenPort(dns_exch->port_src); 109 | _free(dns_exch); 110 | } 111 | 112 | web_status_t fetch_dns_msg(web_port_t port, uint8_t protocol, void *msg, size_t length, web_callback_data_t *user_data){ 113 | (void)port; (void)length; /* Unused parameters */ 114 | dns_exchange_t *exch = (dns_exchange_t *)user_data; 115 | const udp_datagram_t *udp_dtgm = (udp_datagram_t *)msg; 116 | if(protocol != UDP_PROTOCOL || htons(udp_dtgm->port_src) != DNS_PORT) { 117 | return WEB_SUCCESS; 118 | } 119 | 120 | web_status_t ret_val = WEB_SUCCESS; 121 | uint32_t found_ip = 0xffffffff; 122 | const dns_message_t *dns_msg = (dns_message_t*)((uint8_t*)udp_dtgm + sizeof(udp_datagram_t)); 123 | 124 | /* if -> it isn't a response OR the recursion wasn't available OR an error occurred */ 125 | if((dns_msg->flags & 0x8000) && (dns_msg->flags & 0x0080) && !(dns_msg->flags & 0x0F00)) { 126 | const uint8_t nb_answers = dns_msg->answerRRs >> 8; 127 | const uint8_t nb_queries = dns_msg->questions >> 8; 128 | 129 | const uint8_t *ptr = (uint8_t *)dns_msg + sizeof(dns_message_t); 130 | for(int i = 0; i < nb_queries; i++) { 131 | while(*(ptr++)) {} 132 | ptr += 4; 133 | } 134 | 135 | int i = 0; 136 | while(i < nb_answers && (*((uint16_t *)(ptr + 2)) != 0x0100 || *((uint16_t *)(ptr + 4)) != 0x0100)) { 137 | ptr += 11; 138 | ptr += *ptr + 1; 139 | i++; 140 | } 141 | 142 | if(i != nb_answers) { 143 | ptr += 12; 144 | found_ip = *((uint32_t *)ptr); 145 | } 146 | } 147 | 148 | ret_val = (*exch->callback)(port, found_ip, exch->user_data); 149 | remove_event(exch); /* Deletes all data structures allocated */ 150 | return ret_val; 151 | } 152 | -------------------------------------------------------------------------------- /src/internetce/ethernet.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "include/ethernet.h" 8 | #include "include/core.h" 9 | #include "include/ipv4.h" 10 | #include "include/debug.h" 11 | #include "include/rndis.h" 12 | #include "include/arp.h" 13 | 14 | 15 | /**********************************************************************************************************************\ 16 | * Public functions * 17 | \**********************************************************************************************************************/ 18 | 19 | msg_queue_t *web_PushEthernetFrame(void *data, size_t length_data, uint16_t protocol) { 20 | void *buffer = _alloc_msg_buffer(data, length_data, ETH_HEADERS_SIZE, true); 21 | if(buffer == NULL) { 22 | return NULL; 23 | } 24 | return _recursive_PushEthernetFrame(buffer, buffer + ETH_HEADERS_SIZE - 4, length_data, protocol); 25 | } 26 | 27 | web_status_t web_SendEthernetFrame(void *data, size_t length_data, uint16_t protocol) { 28 | msg_queue_t *queued = web_PushEthernetFrame(data, length_data, protocol); 29 | if(queued != NULL) { 30 | queued->send_once = true; /* Send once */ 31 | } 32 | return queued ? WEB_SUCCESS : WEB_NOT_ENOUGH_MEM; 33 | } 34 | 35 | 36 | /**********************************************************************************************************************\ 37 | * Private functions * 38 | \**********************************************************************************************************************/ 39 | 40 | msg_queue_t *_recursive_PushEthernetFrame(void *buffer, void *data, size_t length_data, uint16_t protocol) { 41 | /* @Warning: 4 bytes must be reserved for CRC after the data */ 42 | /* Ethernet frame must be at least 64B */ 43 | const size_t min_payload_size = MIN_ETH_HDR_SIZE - (sizeof(eth_frame_t) + 4); /* = 46 */ 44 | if(length_data < min_payload_size) { 45 | /* Reallocating so it is 64B large */ 46 | uint8_t *new_buffer = _malloc(MIN_ETH_HDR_SIZE + sizeof(rndis_packet_msg_t), "eth"); 47 | if(new_buffer == NULL) { 48 | _free(buffer); 49 | return NULL; 50 | } 51 | void *new_data = new_buffer + sizeof(rndis_packet_msg_t) + sizeof(eth_frame_t); 52 | memcpy(new_data, data, length_data); 53 | memset(new_data + length_data, 0, min_payload_size - length_data); 54 | _free(buffer); 55 | buffer = new_buffer; 56 | data = new_data; 57 | length_data = min_payload_size; 58 | } 59 | if(data - sizeof(eth_frame_t) < buffer) { 60 | dbg_err("Can't push ethernet frame"); 61 | _free(buffer); 62 | return NULL; 63 | } 64 | 65 | const size_t size = length_data + sizeof(eth_frame_t) + 4; 66 | eth_frame_t *frame = (eth_frame_t *)(data - sizeof(eth_frame_t)); 67 | memcpy(frame->MAC_dst, netinfo.router_MAC_addr, 6); 68 | memcpy(frame->MAC_src, netinfo.my_MAC_addr, 6); 69 | frame->Ethertype = protocol; 70 | const uint32_t crc = crc32b(frame, size - 4); 71 | memcpy((void *)frame + size - 4, &crc, 4); 72 | 73 | return _recursive_PushRNDISPacket(buffer, frame, size); 74 | } 75 | 76 | uint32_t crc32b(void *data, size_t length) { 77 | const uint32_t crc_poly = 0xEDB88320; 78 | uint32_t crc; 79 | unsigned int i, j; 80 | 81 | if(!data || !length) { 82 | return 0; 83 | } 84 | crc = 0xFFFFFFFF; 85 | for(j = 0; j < length; j++) { 86 | crc ^= ((uint8_t *)data)[j]; 87 | for(i = 0; i < 8; i++) { 88 | crc = (crc & 1) ? ((crc >> 1) ^ crc_poly) : (crc >> 1); 89 | } 90 | } 91 | return ~crc; 92 | } 93 | 94 | bool cmpbroadcast(const uint8_t *mac_addr) { 95 | const uint24_t *mac24b = (uint24_t *)mac_addr; 96 | return (mac24b[0] & mac24b[1]) == 0xffffff; 97 | } 98 | 99 | web_status_t fetch_ethernet_frame(eth_frame_t *frame, size_t length) { 100 | web_status_t ret_val = WEB_SUCCESS; 101 | if(!memcmp(frame->MAC_dst, netinfo.my_MAC_addr, 6) || cmpbroadcast(frame->MAC_dst)) { 102 | switch(frame->Ethertype) { 103 | case ETH_IPV4: 104 | src_mac_addr = frame->MAC_src; 105 | ipv4_packet_t *ipv4_pckt = (ipv4_packet_t *)((uint8_t *)frame + sizeof(eth_frame_t)); 106 | ret_val = fetch_IPv4_packet(ipv4_pckt, length - sizeof(eth_frame_t)); 107 | break; 108 | case ETH_ARP: 109 | fetch_arp_msg(frame); 110 | break; 111 | default: 112 | dbg_warn("Unknown Ethertype: 0x%04x", frame->Ethertype); 113 | ret_val = WEB_ERROR_FAILED; 114 | break; 115 | } 116 | } 117 | return ret_val; 118 | } 119 | -------------------------------------------------------------------------------- /src/internetce/icmpv4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "include/icmpv4.h" 5 | #include "include/ipv4.h" 6 | #include "include/debug.h" 7 | #include "include/scheduler.h" 8 | 9 | 10 | /**********************************************************************************************************************\ 11 | * Global Variables * 12 | \**********************************************************************************************************************/ 13 | 14 | /* 15 | IP address from which is expected a ping reply, or 0 if there is no ping waiting. 16 | For now, only 1 address can be expected as web_Ping is blocking. 17 | */ 18 | uint32_t waiting_ping = 0; 19 | 20 | 21 | /**********************************************************************************************************************\ 22 | * Public functions * 23 | \**********************************************************************************************************************/ 24 | 25 | web_status_t web_Ping(uint32_t ip_dst) { 26 | icmpv4_echo_t icmp_echo = { 27 | .type = ICMP_ECHO_REQUEST, 28 | .code = 0x00, 29 | .checksum = 0x00, 30 | .identifier = 0x00, 31 | .seq_number = 0x00, 32 | }; 33 | icmp_echo.checksum = ipv4_checksum(&icmp_echo, sizeof(icmp_echo)); 34 | if(web_SendIPv4Packet(&icmp_echo, sizeof(icmpv4_echo_t), ip_dst, ICMP_PROTOCOL) != WEB_SUCCESS) { 35 | return WEB_ERROR_FAILED; 36 | } 37 | 38 | bool is_timeout = false; 39 | web_status_t ret_val = delay_event(TIMEOUT_PING * 1000, boolean_scheduler, boolean_destructor, &is_timeout); 40 | if(ret_val != WEB_SUCCESS) { 41 | return ret_val; 42 | } 43 | waiting_ping = ip_dst; 44 | while(waiting_ping == ip_dst) { 45 | web_WaitForEvents(); 46 | if(is_timeout) { 47 | waiting_ping = 0; 48 | return WEB_TIMEOUT; 49 | } 50 | } 51 | remove_event(&is_timeout); 52 | 53 | return WEB_SUCCESS; 54 | } 55 | 56 | 57 | /**********************************************************************************************************************\ 58 | * Private functions * 59 | \**********************************************************************************************************************/ 60 | 61 | web_status_t fetch_icmpv4_msg(icmpv4_echo_t *msg, size_t length, uint32_t ip_src) { 62 | /* 63 | * Note: Given the RNDIS restrictions (which is just a LAN behind NAT/PAT rules, with no personal public IP), 64 | * we can't really receive ICMP packets from the outside world, even from the local "home network" devices. 65 | * But it may be possible later if the library supports other physical layer types (Wi-Fi, ECM, etc). 66 | */ 67 | if(msg->type == ICMP_ECHO_REQUEST && msg->code == 0) { 68 | dbg_info("Received ping request from 0x%lx", ip_src); 69 | msg->type = ICMP_ECHO_REPLY; 70 | msg->checksum += ICMP_ECHO_REQUEST - ICMP_ECHO_REPLY; /* Difference between the two messages */ 71 | return web_SendIPv4Packet((uint8_t*)msg, length, ip_src, ICMP_PROTOCOL); 72 | } else if(msg->type == ICMP_ECHO_REPLY && msg->code == 0) { 73 | dbg_info("Received ping reply from 0x%lx", ip_src); 74 | if(ip_src == waiting_ping) { 75 | waiting_ping = 0; 76 | } 77 | } 78 | return WEB_SUCCESS; 79 | } 80 | -------------------------------------------------------------------------------- /src/internetce/include/arp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ARP related functions 3 | */ 4 | 5 | #ifndef INTERNET_ARP 6 | #define INTERNET_ARP 7 | 8 | 9 | #include 10 | 11 | 12 | /** 13 | * Internal functions prototype 14 | */ 15 | 16 | void fetch_arp_msg(eth_frame_t *ethernet_frame); 17 | 18 | 19 | #endif // INTERNET_ARP 20 | -------------------------------------------------------------------------------- /src/internetce/include/core.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Core functions 3 | */ 4 | 5 | #ifndef INTERNET_CORE 6 | #define INTERNET_CORE 7 | 8 | 9 | #include 10 | #include 11 | 12 | #include "scheduler.h" 13 | 14 | 15 | #define DEFAULT_MAC_ADDRESS {0xEA, 0xA5, 0x59, 0x9C, 0xC1, 0x00} 16 | 17 | #define min(x, y) (x < y ? x : y) 18 | 19 | 20 | /** 21 | * Enums & structs 22 | */ 23 | 24 | /* A list of the different states of the device */ 25 | typedef enum device_state { 26 | STATE_UNKNOWN, 27 | STATE_USB_INITIALIZED, 28 | STATE_USB_CONNECTED, 29 | STATE_USB_ENABLED, 30 | STATE_RNDIS_INIT, 31 | STATE_RNDIS_DATA_INIT, 32 | STATE_DHCP_CONFIGURING, 33 | STATE_NETWORK_CONFIGURED, 34 | STATE_USB_LOST 35 | } device_state_t; 36 | 37 | typedef struct network_info { 38 | usb_device_t device; 39 | device_state_t state; 40 | uint8_t ep_cdc_in; 41 | uint8_t ep_cdc_out; 42 | uint8_t ep_wc_in; 43 | uint8_t router_MAC_addr[6]; 44 | uint8_t my_MAC_addr[6]; 45 | uint32_t DNS_IP_addr; 46 | uint32_t IP_addr; 47 | dhcp_state_t dhcp_cur_state; 48 | size_t in_buffer_size; 49 | void *temp_usb_buffer; /* Pointer to a temporary buffer, allocated to reassemble splitted USB packet */ 50 | size_t received_size; /* How many bytes in temp_usb_buffer are already received */ 51 | } network_info_t; 52 | 53 | typedef struct allocated_memory { 54 | struct allocated_memory *next; 55 | uint8_t memory[]; 56 | } allocated_memory_t; 57 | 58 | 59 | /** 60 | * Exported global variables 61 | */ 62 | 63 | extern network_info_t netinfo; 64 | extern uint8_t *src_mac_addr; /* For dhcp purposes (we need to acknowledge the router's mac address) */ 65 | 66 | 67 | /** 68 | * Internal functions prototype 69 | */ 70 | 71 | void reset_netinfo_struct(); 72 | 73 | void *_alloc_msg_buffer(void *data, size_t length_data, size_t headers_total_size, bool has_eth_header); 74 | 75 | scheduler_status_t send_packet_scheduler(web_callback_data_t *user_data); 76 | 77 | void send_packet_destructor(web_callback_data_t *user_data); 78 | 79 | void free_allocated_memory(allocated_memory_t **list, allocated_memory_t *allocated); 80 | 81 | void free_allocated_memory_list(allocated_memory_t *memory_list); 82 | 83 | inline uint32_t htonl(uint32_t val) { 84 | uint8_t *pval = (uint8_t *)&val; 85 | return (((uint32_t)pval[0] * ((uint32_t)1 << 24)) + 86 | ((uint32_t)pval[1] * ((uint32_t)1 << 16)) + 87 | ((uint32_t)pval[2] * ((uint32_t)1 << 8)) + 88 | (uint32_t)pval[3]); 89 | } 90 | 91 | inline uint16_t htons(uint16_t val) { 92 | uint8_t *pval = (uint8_t *)&val; 93 | return ((uint16_t)pval[0] * 256) + pval[1]; 94 | } 95 | 96 | inline uint24_t htonl24(uint24_t val) { 97 | uint8_t *pval = (uint8_t *)&val; 98 | return ((uint24_t)pval[0] << 16) + ((uint24_t)pval[1] << 8) + pval[2]; 99 | } 100 | 101 | #define ntohl htonl 102 | #define ntohs htons 103 | #define ntohl24 htonl24 104 | 105 | #define force_send_queue() dispatch_time_events() 106 | 107 | 108 | #endif // INTERNET_CORE 109 | -------------------------------------------------------------------------------- /src/internetce/include/crypto.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Cryptography functions 3 | */ 4 | 5 | #ifndef INTERNET_CRYPTO 6 | #define INTERNET_CRYPTO 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include "tls.h" 13 | 14 | 15 | /** 16 | * Constants 17 | */ 18 | 19 | /* Sent during client hello so the server does not send a too large TLS ciphered payload. 20 | * 2^13-1 = 2^16 / 8 - 1 = limitation in aes128gcm where the number of bits must not be greater than 2**16-1 21 | * Taking 2^12 to be safe 22 | */ 23 | #define AES_MAX_BLOCK_SIZE (1 << 12) 24 | #define AES_128_TAG_SIZE 16 25 | #define AES_128_KEY_SIZE 16 26 | #define AES_128_IV_SIZE 12 27 | 28 | /* Port layout for SHA256 memory mapped port */ 29 | #define SHA256_CTRL ((volatile uint8_t *)0xe10000) 30 | #define SHA256_STATUS ((volatile uint8_t *)0xe10001) 31 | #define SHA256_ENABLE ((volatile uint8_t *)0xe10009) 32 | #define SHA256_BLOCK ((volatile uint32_t *)0xe10010) 33 | #define SHA256_HASH_DATA ((volatile uint32_t *)0xe10060) 34 | 35 | /* SHA256_CTRL commands */ 36 | #define SHA256_BEGIN_HASH 0x0A 37 | #define SHA256_CONTINUE_HASH 0x0E 38 | 39 | #define SHA256_HASH_SIZE 32 40 | #define SHA256_BLOCK_SIZE 64 41 | 42 | /* X25519 */ 43 | #define X25519_SECRET_SIZE 32 44 | 45 | /* In case I choose to add other hash functions */ 46 | #define CIPHER_SUITE_HASH_SIZE SHA256_HASH_SIZE 47 | #define CIPHER_SUITE_BLOCK_SIZE SHA256_BLOCK_SIZE 48 | 49 | 50 | /** 51 | * Types 52 | */ 53 | 54 | typedef struct aes128gcm_endpoint_data { 55 | uint8_t round_keys[176]; 56 | uint8_t static_iv[12]; 57 | size_t sequence_number; /**< In theory the seq_num is 64-bit wide, in practice, 24 bits is enough */ 58 | } aes128gcm_endpoint_data_t; 59 | 60 | typedef struct aes128gcm_data { 61 | aes128gcm_endpoint_data_t cipher_data; 62 | aes128gcm_endpoint_data_t decipher_data; 63 | } aes128gcm_data_t; 64 | 65 | 66 | /** 67 | * Cryptography functions 68 | */ 69 | 70 | /* AES-128 GCM */ 71 | 72 | web_callback_data_t *aes128gcm_init_callback(uint8_t cipher_key[AES_128_KEY_SIZE], uint8_t cipher_iv[AES_128_IV_SIZE], 73 | uint8_t decipher_key[AES_128_KEY_SIZE], uint8_t decipher_iv[AES_128_IV_SIZE]); 74 | 75 | void aes128gcm_free_callback(web_callback_data_t *cipher_data); 76 | 77 | web_status_t aes128gcm_cipher_callback(void *dest, void *source, size_t length, void *aad, size_t aad_length, 78 | web_callback_data_t *user_data); 79 | 80 | web_status_t aes128gcm_decipher_callback(void *dest, void *source, size_t length, void *aad, size_t aad_length, 81 | web_callback_data_t *user_data); 82 | 83 | void compute_round_keys(uint8_t key_space[176]); 84 | 85 | void cipher_aes128gcm(/* IN */ const uint8_t round_keys[176], 86 | /* IN */ const void *plaintext, 87 | /* IN */ size_t length_plaintext, 88 | /* IN */ const uint8_t IV[12], 89 | /* IN */ const void *AAD, 90 | /* IN */ size_t length_aad, 91 | /* OUT */ uint8_t tag[16], 92 | /* OUT */ void *ciphertext); 93 | 94 | int decipher_aes128gcm(/* IN */ const uint8_t round_keys[176], 95 | /* IN */ const void *ciphertext, 96 | /* IN */ size_t length_ciphertext, 97 | /* IN */ const uint8_t IV[12], 98 | /* IN */ const void *AAD, 99 | /* IN */ size_t length_aad, 100 | /* IN */ const uint8_t tag[16], 101 | /* OUT */ void *plaintext); 102 | 103 | /* Random */ 104 | 105 | void rng_Init(); 106 | 107 | bool rng_IsAvailable(); 108 | 109 | web_status_t rng_Update(); 110 | 111 | void rng_Feed(const uint8_t seed[], size_t seed_size); 112 | 113 | void rng_FeedBit(uint8_t bit); 114 | 115 | void rng_FeedFromEvent(); 116 | 117 | web_status_t rng_Random256b(uint8_t dst[32]); 118 | 119 | web_status_t rng_Random32b(uint32_t *var); 120 | 121 | /* HKDF - HMAC Key Derivation Function */ 122 | 123 | web_status_t hkdf_Extract(const uint8_t salt[], size_t salt_size, const uint8_t ikm[], size_t ikm_size, uint8_t prk[]); 124 | 125 | web_status_t hkdf_Expand(const uint8_t prk[], const uint8_t info[], size_t info_size, uint8_t dst[], size_t dst_size); 126 | 127 | web_status_t hkdf_ExpandLabel(const uint8_t secret[], const char *label, const uint8_t hash[], size_t hash_size, 128 | uint8_t dst[], size_t dst_size); 129 | 130 | web_status_t hkdf_HMAC(const uint8_t key[], size_t key_size, const uint8_t msg[], size_t size, uint8_t dst[]); 131 | 132 | /* Key Schedule */ 133 | 134 | web_status_t add_transcript_message(linked_transcript_msg_t **transcript, const void *data, size_t size, tls_sender_t sender); 135 | 136 | web_status_t compute_transcript_hash(const linked_transcript_msg_t *transcript, tls_hs_sender_msg_type_t until, uint8_t hash[]); 137 | 138 | web_status_t compute_early_secret(const linked_transcript_msg_t *transcript, uint8_t current_secret[], const uint8_t psk[], 139 | size_t psk_length, uint8_t binder_key[], uint8_t client_early_traffic_secret[], 140 | uint8_t early_exporter_master_secret[]); 141 | 142 | web_status_t compute_handshake_secret(const linked_transcript_msg_t *transcript, uint8_t current_secret[], const uint8_t dhe_ss[], 143 | size_t dhe_ss_size, uint8_t client_hs_traffic_secret[], uint8_t server_hs_traffic_secret[]); 144 | 145 | web_status_t compute_master_secret(const linked_transcript_msg_t *transcript, uint8_t current_secret[], 146 | uint8_t client_ap_traffic_secret[], uint8_t server_ap_traffic_secret[], 147 | uint8_t exporter_master_secret[], uint8_t resumption_master_secret[]); 148 | 149 | web_status_t update_traffic_secret(const uint8_t current_traffic_secret[], uint8_t new_traffic_secret[]); 150 | 151 | web_status_t compute_key_iv_pair(const uint8_t secret[], uint8_t key[], size_t key_size, uint8_t iv[], size_t iv_size); 152 | 153 | void _free_transcript(linked_transcript_msg_t **transcript); 154 | 155 | /* Ports */ 156 | 157 | void flash_setup(); 158 | 159 | void flash_unlock(); 160 | 161 | void flash_lock(); 162 | 163 | /* SHA256 */ 164 | 165 | bool sha256_IsEnabled(); 166 | 167 | web_status_t sha256_Init(); 168 | 169 | web_status_t sha256_Part(const void *src, size_t size); 170 | 171 | web_status_t sha256_Hash(void *dst); 172 | 173 | /* X25519 */ 174 | 175 | void x25519_scalarmult(uint8_t out[32], const uint8_t base_point[32], uint8_t scalar[32]); 176 | 177 | 178 | #endif // INTERNET_CRYPTO 179 | -------------------------------------------------------------------------------- /src/internetce/include/debug.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Debugging stuffs 3 | */ 4 | 5 | #ifndef INTERNET_DEBUG 6 | #define INTERNET_DEBUG 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include "core.h" 13 | 14 | 15 | #define NO_DEBUG 0 16 | #define DEBUG_ERRORS 1 17 | #define DEBUG_WARNINGS 2 18 | #define DEBUG_INFO 3 19 | #define DEBUG_VERBOSE 4 20 | 21 | /** 22 | * Change this define to make the lib more or less verbose 23 | */ 24 | #define DEBUG_LEVEL NO_DEBUG 25 | 26 | typedef struct alloced_mem { 27 | void *ptr; 28 | struct alloced_mem *next; 29 | char id[10]; 30 | } alloced_mem_t; 31 | 32 | 33 | #if DEBUG_LEVEL == NO_DEBUG 34 | #define debug(...) 35 | #define pause(...) 36 | #define printf_xy(...) 37 | #define print_tcp_info(...) 38 | #define monitor_usb_connection(...) 39 | #define dbg_err(...) 40 | #define dbg_warn(...) 41 | #define dbg_info(...) 42 | #define dbg_verb(...) 43 | #define print_allocated_memory() 44 | #elif DEBUG_LEVEL == DEBUG_ERRORS 45 | void debug(const void *addr, size_t len); 46 | void printf_xy(unsigned int xpos, unsigned int ypos, const char *format, ...); 47 | #define print_tcp_info(...) 48 | #define monitor_usb_connection(...) 49 | #define pause() while(!os_GetCSC()) {} 50 | #define dbg_err(...) printf("E: " __VA_ARGS__); printf("\n") 51 | #define dbg_warn(...) 52 | #define dbg_info(...) 53 | #define dbg_verb(...) 54 | #define print_allocated_memory() 55 | #elif DEBUG_LEVEL == DEBUG_WARNINGS 56 | void debug(const void *addr, size_t len); 57 | void printf_xy(unsigned int xpos, unsigned int ypos, const char *format, ...); 58 | #define print_tcp_info(...) 59 | #define monitor_usb_connection(...) 60 | #define pause() while(!os_GetCSC()) {} 61 | #define dbg_err(...) printf("E: " __VA_ARGS__); printf("\n") 62 | #define dbg_warn(...) printf("W: " __VA_ARGS__); printf("\n") 63 | #define dbg_info(...) 64 | #define dbg_verb(...) 65 | #define print_allocated_memory() 66 | #elif DEBUG_LEVEL == DEBUG_INFO 67 | void debug(const void *addr, size_t len); 68 | void printf_xy(unsigned int xpos, unsigned int ypos, const char *format, ...); 69 | void print_tcp_info(const tcp_segment_t *seg, tcp_exchange_t *tcp_exch, size_t length, bool is_me); 70 | void print_allocated_memory(); 71 | #define monitor_usb_connection(...) 72 | #define pause() while(!os_GetCSC()) {} 73 | #define dbg_err(...) printf("E: " __VA_ARGS__); printf("\n") 74 | #define dbg_warn(...) printf("W: " __VA_ARGS__); printf("\n") 75 | #define dbg_info(...) printf("I: " __VA_ARGS__); printf("\n") 76 | #define dbg_verb(...) 77 | #elif DEBUG_LEVEL == DEBUG_VERBOSE 78 | void debug(const void *addr, size_t len); 79 | void printf_xy(unsigned int xpos, unsigned int ypos, const char *format, ...); 80 | void print_tcp_info(const tcp_segment_t *seg, tcp_exchange_t *tcp_exch, size_t length, bool is_me); 81 | void print_allocated_memory(); 82 | void monitor_usb_connection(usb_event_t event, device_state_t state); 83 | #define pause() while(!os_GetCSC()) {} 84 | #define dbg_err(...) printf("E: " __VA_ARGS__); printf("\n") 85 | #define dbg_warn(...) printf("W: " __VA_ARGS__); printf("\n") 86 | #define dbg_info(...) printf("I: " __VA_ARGS__); printf("\n") 87 | #define dbg_verb(...) printf("V: " __VA_ARGS__); printf("\n") 88 | #endif 89 | 90 | 91 | void *_malloc(size_t size, const char *id); 92 | 93 | void *_realloc(void *ptr, size_t size); 94 | 95 | void _free(void *ptr); 96 | 97 | 98 | #endif // INTERNET_DEBUG 99 | -------------------------------------------------------------------------------- /src/internetce/include/dhcp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * DHCP related functions 3 | */ 4 | 5 | #ifndef INTERNET_DHCP 6 | #define INTERNET_DHCP 7 | 8 | 9 | #include 10 | #include 11 | 12 | 13 | /** 14 | * Constants 15 | */ 16 | 17 | /* General */ 18 | #define DHCP_OP_REQUEST 0x01 19 | #define DHCP_OP_REPLY 0x02 20 | #define DHCP_HTYPE_MAC 0x01 21 | #define DHCP_HLEN_MAC 0x06 22 | #define DHCP_MAGIC_COOKIE 0x63538263 23 | 24 | /* DHCP Options */ 25 | #define DHCP_OPT_TYPE_ID 53 26 | #define DHCP_OPT_TYPE_LEN 1 27 | #define DHCP_OPT_V_DISCOVER 1 28 | #define DHCP_OPT_V_OFFER 2 29 | #define DHCP_OPT_V_REQUEST 3 30 | #define DHCP_OPT_V_DECLINE 4 31 | #define DHCP_OPT_V_ACK 5 32 | #define DHCP_OPT_V_NAK 6 33 | #define DHCP_OPT_V_RELEASE 7 34 | 35 | #define DHCP_OPT_REQ_IP_ID 50 36 | #define DHCP_OPT_SERVER_ID 54 37 | #define DHCP_OPT_IP_LEN 4 38 | 39 | #define DHCP_OPT_PARAM_REQ_LIST_ID 55 40 | #define DHCP_OPT_SUBNET_MASK_ID 1 41 | #define DHCP_OPT_ROUTER_ID 3 42 | #define DHCP_OPT_DNS_ID 6 43 | 44 | #define DHCP_OPT_END_OPTIONS 255 45 | 46 | 47 | /** 48 | * Internal functions prototype 49 | */ 50 | 51 | int dhcp_init(); 52 | 53 | web_status_t fetch_dhcp_msg(web_port_t port, uint8_t protocol, void *msg, size_t length, 54 | web_callback_data_t *user_data); 55 | 56 | 57 | #endif // INTERNET_DHCP 58 | -------------------------------------------------------------------------------- /src/internetce/include/dns.h: -------------------------------------------------------------------------------- 1 | /** 2 | * DNS related functions 3 | */ 4 | 5 | #ifndef INTERNET_DNS 6 | #define INTERNET_DNS 7 | 8 | 9 | #include 10 | #include 11 | 12 | 13 | /** 14 | * Internal functions prototype 15 | */ 16 | 17 | web_status_t dns_callback(web_port_t port, uint32_t res_ip, web_callback_data_t *user_data); 18 | 19 | scheduler_status_t dns_timeout_scheduler(web_callback_data_t *user_data); 20 | 21 | void dns_timeout_destructor(web_callback_data_t *user_data); 22 | 23 | web_status_t fetch_dns_msg(web_port_t port, uint8_t protocol, void *msg, size_t length, web_callback_data_t *user_data); 24 | 25 | 26 | #endif // INTERNET_DNS 27 | -------------------------------------------------------------------------------- /src/internetce/include/ethernet.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Ethernet related functions 3 | */ 4 | 5 | #ifndef INTERNET_ETHERNET 6 | #define INTERNET_ETHERNET 7 | 8 | 9 | #include 10 | #include 11 | 12 | 13 | /** 14 | * Internal functions prototype 15 | */ 16 | 17 | msg_queue_t *_recursive_PushEthernetFrame(void *buffer, void *data, size_t length_data, uint16_t protocol); 18 | 19 | uint32_t crc32b(void *data, size_t length); 20 | 21 | bool cmpbroadcast(const uint8_t *mac_addr); 22 | 23 | web_status_t fetch_ethernet_frame(eth_frame_t *frame, size_t length); 24 | 25 | 26 | #endif // INTERNET_ETHERNET 27 | -------------------------------------------------------------------------------- /src/internetce/include/http.h: -------------------------------------------------------------------------------- 1 | /** 2 | * HTTP related functions 3 | */ 4 | 5 | #ifndef INTERNET_HTTP 6 | #define INTERNET_HTTP 7 | 8 | 9 | #include 10 | #include 11 | 12 | /** 13 | * Constants 14 | */ 15 | 16 | #define BASIC_HTTP_REQUEST "%s %s HTTP/1.1\r\nHost: %s\r\n%s\r\n" 17 | #define POST_HTTP_INFO "Content-Type: application/x-www-form-urlencoded\r\nContent-Length: %d\r\n\r\n%s" 18 | 19 | 20 | /** 21 | * Enums & structs 22 | */ 23 | 24 | typedef struct http_exchange { 25 | bool data_chunked; 26 | size_t content_length; 27 | size_t content_received; 28 | size_t header_length; 29 | size_t chunks_metadata_length; /**< Size of all the characters encoding chunks metadata */ 30 | size_t offset_next_chunk; /**< Offset from beggining of the next chunk */ 31 | http_data_t **data; /**< Where to put the result */ 32 | void *buffer; /**< Temporary buffer while receiving data */ 33 | size_t buffer_size; 34 | bool keep_http_header; 35 | bool timeout; 36 | web_status_t status; /**< Set when the request is finished (successfuly or with an error) */ 37 | bool dirty; 38 | } http_exchange_t; 39 | 40 | typedef struct http_data_list { 41 | char varname[9]; 42 | struct http_data_list *next; 43 | } http_data_list_t; 44 | 45 | 46 | /** 47 | * Global variable 48 | */ 49 | 50 | extern http_data_list_t *http_data_list; 51 | 52 | 53 | /** 54 | * Internal functions prototype 55 | */ 56 | 57 | uint32_t ip_ascii_to_hex(const char *ipstr); 58 | 59 | web_status_t http_request(const char *request_type, const char* url, http_data_t **data, bool keep_http_header, 60 | char *params, bool is_https); 61 | 62 | web_status_t return_http_data(http_exchange_t *exch); 63 | 64 | size_t search_in_str(const char *data, size_t length, const char *str, size_t size_str); 65 | 66 | char *lowercase(char *dst_str, const char *src_str, size_t length); 67 | 68 | const char *search_field_header(const char *data, size_t length, const char *str, size_t size_str); 69 | 70 | int search_content_size(http_exchange_t *exch); 71 | 72 | web_status_t fetch_http_msg(web_port_t port, link_msg_type_t msg_type, void *msg, size_t length, 73 | web_callback_data_t *user_data); 74 | 75 | uint24_t get_chunk_size(const char *ascii, const char *max_ptr, uint24_t *chunk_chars); 76 | 77 | 78 | #endif // INTERNET_HTTP 79 | -------------------------------------------------------------------------------- /src/internetce/include/icmpv4.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ICMPv4 related functions 3 | */ 4 | 5 | #ifndef INTERNET_ICMPV4 6 | #define INTERNET_ICMPV4 7 | 8 | 9 | #include 10 | #include 11 | 12 | 13 | /** 14 | * Constants 15 | */ 16 | 17 | #define TIMEOUT_PING 2 /* 2 seconds timeout */ 18 | 19 | 20 | /** 21 | * Internal functions prototype 22 | */ 23 | 24 | web_status_t fetch_icmpv4_msg(icmpv4_echo_t *msg, size_t length, uint32_t ip_src); 25 | 26 | scheduler_status_t ping_timeout_scheduler(web_callback_data_t *user_data); 27 | 28 | void ping_timeout_destructor(web_callback_data_t *user_data); 29 | 30 | 31 | #endif // INTERNET_ICMPV4 32 | -------------------------------------------------------------------------------- /src/internetce/include/ipv4.h: -------------------------------------------------------------------------------- 1 | /** 2 | * IPv4 related functions 3 | */ 4 | 5 | #ifndef INTERNET_IPV4 6 | #define INTERNET_IPV4 7 | 8 | 9 | #include 10 | #include 11 | 12 | 13 | /** 14 | * Internal functions prototype 15 | */ 16 | 17 | msg_queue_t *_recursive_PushIPv4Packet(void *buffer, void *data, size_t length_data, uint32_t ip_dst, uint8_t protocol); 18 | 19 | uint16_t ipv4_checksum(void *header, size_t count); 20 | 21 | web_status_t fetch_IPv4_packet(ipv4_packet_t *pckt, size_t length); 22 | 23 | 24 | #endif // INTERNET_IPV4 25 | -------------------------------------------------------------------------------- /src/internetce/include/rndis.h: -------------------------------------------------------------------------------- 1 | /** 2 | * RNDIS related functions 3 | */ 4 | 5 | #ifndef INTERNET_RNDIS 6 | #define INTERNET_RNDIS 7 | 8 | 9 | #include 10 | #include 11 | 12 | #include "core.h" 13 | 14 | 15 | /** 16 | * Constants 17 | */ 18 | 19 | #define RNDIS_CONTROL_BUFFER_SIZE 64 /* 64 should be enough */ 20 | 21 | #define RNDIS_THRESHOLD_KEEPALIVE_FILTER 2 22 | 23 | #define MAX_RNDIS_TRANSFER_SIZE MAX_SEGMENT_SIZE + TCP_HEADERS_SIZE // 1562B 24 | 25 | #define SEND_KEEPALIVE_INTERVAL 5 * 1000 /* Send Keepalive every 5 seconds according to RNDIS requirements */ 26 | 27 | /* RNDIS version */ 28 | #define RNDIS_MAJOR_VERSION 0x01 29 | #define RNDIS_MINOR_VERSION 0x00 30 | 31 | /* Device flag */ 32 | #define RNDIS_DF_CONNECTIONLESS 0x01 33 | #define RNDIS_DF_CONNECTION_ORIENTED 0x02 34 | 35 | /* Medium */ 36 | #define RNDIS_MEDIUM_802_3 0x00000000 37 | 38 | /* General OIDs */ 39 | #define OID_GEN_SUPPORTED_LIST 0x00010101 40 | #define OID_GEN_HARDWARE_STATUS 0x00010102 41 | #define OID_GEN_MEDIA_SUPPORTED 0x00010103 42 | #define OID_GEN_MEDIA_IN_USE 0x00010104 43 | #define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 44 | #define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 45 | #define OID_GEN_LINK_SPEED 0x00010107 46 | #define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 47 | #define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 48 | #define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A 49 | #define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B 50 | #define OID_GEN_VENDOR_ID 0x0001010C 51 | #define OID_GEN_VENDOR_DESCRIPTION 0x0001010D 52 | #define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E 53 | #define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F 54 | #define OID_GEN_DRIVER_VERSION 0x00010110 55 | #define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 56 | #define OID_GEN_PROTOCOL_OPTIONS 0x00010112 57 | #define OID_GEN_MAC_OPTIONS 0x00010113 58 | #define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 59 | #define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 60 | #define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 61 | #define OID_GEN_SUPPORTED_GUIDS 0x00010117 62 | #define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118 63 | #define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119 64 | #define OID_GEN_MACHINE_NAME 0x0001021A 65 | #define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B 66 | #define OID_GEN_VLAN_ID 0x0001021C 67 | 68 | /* Values of RNDIS_OID_GEN_CURRENT_PACKET_FILTER */ 69 | #define RNDIS_PACKET_TYPE_DIRECTED 0x00000001 70 | #define RNDIS_PACKET_TYPE_MULTICAST 0x00000002 71 | #define RNDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 72 | #define RNDIS_PACKET_TYPE_BROADCAST 0x00000008 73 | #define RNDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010 74 | #define RNDIS_PACKET_TYPE_PROMISCUOUS 0x00000020 75 | #define RNDIS_PACKET_TYPE_SMT 0x00000040 76 | #define RNDIS_PACKET_TYPE_ALL_LOCAL 0x00000080 77 | #define RNDIS_PACKET_TYPE_GROUP 0x00001000 78 | #define RNDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00002000 79 | #define RNDIS_PACKET_TYPE_FUNCTIONAL 0x00004000 80 | #define RNDIS_PACKET_TYPE_MAC_FRAME 0x00008000 81 | 82 | 83 | /** 84 | * Type definitions 85 | */ 86 | 87 | /* struct rndis_state: Describe the current RNDIS state machine */ 88 | typedef struct rndis_state { 89 | unsigned int cur_request_id; /* Current request ID */ 90 | uint8_t not_received_keepalives_filter; /* Check that the previous keepalive message got a response */ 91 | uint8_t interrupt_buffer[8]; /* Where to store the response in the interrupt endpoint */ 92 | usb_control_setup_t ctrl_setup_buffer; 93 | size_t max_transfer_size; /* Max RNDIS message size. The minimum value bewteen host & device's is chosen */ 94 | bool is_resetting; 95 | void *receive_buffer; 96 | allocated_memory_t *send_buffer_list; 97 | } rndis_state_t; 98 | 99 | 100 | /** 101 | * Internal functions prototype 102 | */ 103 | 104 | msg_queue_t *_recursive_PushRNDISPacket(void *buffer, void *data, size_t length_data); 105 | 106 | void send_control_rndis(void *rndis_msg, size_t length); 107 | 108 | scheduler_status_t send_control_rndis_scheduler(web_callback_data_t *buffer); 109 | 110 | usb_error_t send_control_rndis_callback(usb_endpoint_t endpoint, usb_transfer_status_t status, size_t transferred, 111 | usb_transfer_data_t *data); 112 | 113 | void init_rndis_exchange(); 114 | 115 | void send_rndis_set_msg(uint32_t oid, const void *value, size_t value_size); 116 | 117 | void send_rndis_keepalive_msg(); 118 | 119 | void send_rndis_keepalive_cmplt(uint32_t request_id); 120 | 121 | void send_rndis_reset_msg(); 122 | 123 | usb_error_t interrupt_handler(usb_endpoint_t endpoint, usb_transfer_status_t status, size_t transferred, 124 | usb_transfer_data_t *data); 125 | 126 | usb_error_t ctrl_rndis_callback(usb_endpoint_t endpoint, usb_transfer_status_t status, size_t transferred, 127 | usb_transfer_data_t *data); 128 | 129 | scheduler_status_t poll_interrupt_scheduler(web_callback_data_t *user_data); 130 | 131 | scheduler_status_t send_keepalive_scheduler(web_callback_data_t *user_data); 132 | 133 | void free_rndis_data(); 134 | 135 | 136 | #endif // INTERNET_RNDIS 137 | -------------------------------------------------------------------------------- /src/internetce/include/scheduler.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Scheduling utility functions 3 | */ 4 | 5 | #ifndef INTERNET_SCHEDULER 6 | #define INTERNET_SCHEDULER 7 | 8 | #include 9 | 10 | #define MS_TO_TICK(x) (x * 375 / 2) /* <=> x*48000/256 */ 11 | 12 | /** 13 | * Constants 14 | */ 15 | 16 | #define SEND_KEEPALIVE_SCHED_ID ((web_callback_data_t *)0x01) 17 | #define POLL_INTERRUPT_SCHED_ID ((web_callback_data_t *)0x02) 18 | 19 | 20 | /** 21 | * Enums & structs 22 | */ 23 | 24 | typedef struct schedule_list { 25 | uint24_t date; 26 | uint24_t every; 27 | web_schedule_callback_t *schedule_callback; 28 | web_destructor_callback_t *destructor_callback; 29 | web_callback_data_t *user_data; 30 | struct schedule_list *next; 31 | } schedule_list_t; 32 | 33 | 34 | /** 35 | * Internal functions prototype 36 | */ 37 | 38 | void insert_event(schedule_list_t *new_event); 39 | 40 | web_status_t dispatch_time_events(); 41 | 42 | web_status_t schedule(uint24_t every, web_schedule_callback_t *schedule_callback, 43 | web_destructor_callback_t *destructor_callback, web_callback_data_t *user_data); 44 | 45 | web_status_t delay_event(uint24_t offset_ms, web_schedule_callback_t *schedule_callback, 46 | web_destructor_callback_t *destructor_callback, web_callback_data_t *user_data); 47 | 48 | web_status_t remove_event(web_callback_data_t *user_data); 49 | 50 | void flush_event_list(); 51 | 52 | void reset_event(web_callback_data_t *user_data); 53 | 54 | scheduler_status_t boolean_scheduler(web_callback_data_t *user_data); 55 | 56 | void boolean_destructor(web_callback_data_t *user_data); 57 | 58 | 59 | #endif // INTERNET_SCHEDULER 60 | -------------------------------------------------------------------------------- /src/internetce/include/tcp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * TCP related functions 3 | */ 4 | 5 | #ifndef INTERNET_TCP 6 | #define INTERNET_TCP 7 | 8 | 9 | #include 10 | #include 11 | #include "core.h" 12 | 13 | /** 14 | * Internal constants 15 | */ 16 | 17 | #define TCP_OPTION_MSS 0x02 18 | 19 | 20 | /** 21 | * Internal functions prototype 22 | */ 23 | 24 | web_status_t internal_deliver_segment(tcp_exchange_t *tcp_exch, void *data, size_t length, uint16_t flags); 25 | 26 | int add_tcp_queue(char *data, size_t length, tcp_exchange_t *exchange, uint16_t flags, size_t opt_size, 27 | const uint8_t *options); 28 | 29 | web_status_t fetch_ack(tcp_exchange_t *tcp_exch, uint32_t ackn); 30 | 31 | msg_queue_t *_recursive_PushTCPSegment(void *buffer, void *data, size_t length_data, uint32_t ip_dst, 32 | web_port_t port_src, web_port_t port_dst, uint32_t seq_number, 33 | uint32_t ack_number, uint16_t flags, size_t opt_size, const uint8_t *options); 34 | 35 | web_status_t add_in_segment(tcp_exchange_t *tcp_exch, tcp_segment_t *segment, size_t length); 36 | 37 | web_status_t send_rst_segment(uint32_t ip_dst, tcp_segment_t *received, size_t length); 38 | 39 | web_status_t fetch_conntrack_tcp(web_port_t port, uint8_t protocol, void *data, size_t length, 40 | web_callback_data_t *user_data); 41 | 42 | web_status_t fetch_raw_tcp_segment(tcp_segment_t *seg, size_t length, uint32_t ip_src, uint32_t ip_dst); 43 | 44 | web_status_t fetch_tcp_flags(const tcp_segment_list_t *tcp_seg, tcp_exchange_t *tcp_exch); 45 | 46 | void flush_tcp_connections(); 47 | 48 | void flush_sending_queue(tcp_exchange_t *tcp_exch); 49 | 50 | void flush_receiving_queue(tcp_exchange_t *tcp_exch); 51 | 52 | scheduler_status_t time_wait_scheduler(web_callback_data_t *user_data); 53 | 54 | void time_wait_destructor(web_callback_data_t *user_data); 55 | 56 | inline char *get_payload_addr(const tcp_segment_t *seg) { 57 | return (char *)seg + 4 * (seg->dataOffset_flags >> 4 & 0x0f); 58 | } 59 | 60 | inline uint32_t get_segment_sn_length(size_t payload_length, uint16_t flags) { 61 | return payload_length + (flags & htons(FLAG_TCP_RST | FLAG_TCP_FIN | FLAG_TCP_SYN) ? 1 : 0); 62 | } 63 | 64 | #define schedule_free_exchange(tcp_exch, x) delay_event(x * 1000, time_wait_scheduler, time_wait_destructor, tcp_exch) 65 | 66 | 67 | #endif // INTERNET_TCP 68 | -------------------------------------------------------------------------------- /src/internetce/include/tls.h: -------------------------------------------------------------------------------- 1 | /** 2 | * TLS related functions 3 | */ 4 | 5 | #ifndef INTERNET_TLS 6 | #define INTERNET_TLS 7 | 8 | #include 9 | #include "core.h" 10 | #include "crypto.h" 11 | 12 | 13 | /** 14 | * External structures 15 | */ 16 | 17 | extern cipher_callbacks_t aes128gcm_callbacks; 18 | 19 | /** 20 | * Constants 21 | */ 22 | 23 | #define TIMEOUT_TLS_HANDSHAKE 20 24 | 25 | #define TLS_VERSION_1_0 htons(0x0301) 26 | #define TLS_VERSION_1_2 htons(0x0303) 27 | #define TLS_VERSION_1_3 htons(0x0304) 28 | 29 | #define NUMBER_SUPPORTED_CIPHER_SUITES 2 30 | #define TLS_AES_128_GCM_SHA256 htons(0x1301) 31 | #define TLS_EMPTY_RENEGOTIATION_INFO_SCSV htons(0x00ff) 32 | #define LIST_SUPPORTED_CIPHER_SUITES {TLS_AES_128_GCM_SHA256, TLS_EMPTY_RENEGOTIATION_INFO_SCSV} 33 | #define SIZE_CIPHER_SUITES (NUMBER_SUPPORTED_CIPHER_SUITES * sizeof(uint16_t)) 34 | 35 | #define NUMBER_SUPPORTED_GROUPS 1 36 | #define GROUP_EC_X25519 htons(0x001d) 37 | #define LIST_SUPPORTED_GROUPS {GROUP_EC_X25519} 38 | #define SIZE_GROUPS (NUMBER_SUPPORTED_GROUPS * sizeof(uint16_t)) 39 | 40 | #define NUMBER_SUPPORTED_SIGNATURE_ALGO 2 41 | #define SIGN_RSA_PSS_RSAE_SHA256 htons(0x0804) // Not implemented yet 42 | #define SIGN_ECDSA_SECP256R1_SHA256 htons(0x0403) // Not implemented yet 43 | #define LIST_SUPPORTED_SIGNATURE_ALGO {SIGN_RSA_PSS_RSAE_SHA256, SIGN_ECDSA_SECP256R1_SHA256} 44 | #define SIZE_SIGNATURE_ALGO (NUMBER_SUPPORTED_SIGNATURE_ALGO * sizeof(uint16_t)) 45 | 46 | #define TLS_MAX_FRAGMENT_LENGTH_EXT_ID htons(0x0001) 47 | #define TLS_SUPPORTED_VERSIONS_EXT_ID htons(0x002b) 48 | #define TLS_EC_POINT_FORMATS_EXT_ID htons(0x000b) 49 | #define TLS_SUPPORTED_GROUPS_EXT_ID htons(0x000a) 50 | #define TLS_SIGNATURE_ALGO_EXT_ID htons(0x000d) 51 | #define TLS_KEY_SHARE_EXT_ID htons(0x0033) 52 | #define TLS_ALPN_EXT_ID htons(0x0010) 53 | #define TLS_EXTENDED_MSECRET_EXT_ID htons(0x0017) 54 | #define TLS_PSK_KEY_EXCHANGE_MODE_EXT_ID htons(0x002d) 55 | #define TLS_PRE_SHARED_KEY_EXT_ID htons(0x0029) 56 | #define TLS_RECORD_SIZE_LIMIT_EXT_ID htons(0x001c) 57 | #define TLS_SERVER_NAME_EXT_ID htons(0x0000) 58 | #define TLS_PADDING_EXT_ID htons(0x0015) 59 | 60 | #define TLS_SERVER_NAME_MAX_LENGTH 128 61 | 62 | #define HELLO_RETRY_VALUE {0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,\ 63 | 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C} 64 | 65 | #define TLS_MAX_BLOCK_SIZE AES_MAX_BLOCK_SIZE /* Limiting factor */ 66 | 67 | 68 | /** 69 | * Enums 70 | */ 71 | 72 | typedef enum tls_key_exch_mode { 73 | TLS_PSK_MODE_KE = 0, 74 | TLS_PSK_MODE_DHE_KE = 1, 75 | } tls_key_exch_mode_t; 76 | 77 | typedef enum tls_alert_level { 78 | TLS_ALERT_LEVEL_WARNING = 1, 79 | TLS_ALERT_LEVEL_FATAL = 2 80 | } tls_alert_level_t; 81 | 82 | typedef enum tls_alert { 83 | TLS_ALERT_CLOSE_NOTIFY = 0, 84 | TLS_ALERT_UNEXPECTED_MESSAGE = 10, 85 | TLS_ALERT_BAD_RECORD_MAC = 20, 86 | TLS_ALERT_DECRYPTION_FAILED_RESERVED = 21, 87 | TLS_ALERT_RECORD_OVERFLOW = 22, 88 | TLS_ALERT_DECOMPRESSION_FAILURE_RESERVED = 30, 89 | TLS_ALERT_HANDSHAKE_FAILURE = 40, 90 | TLS_ALERT_NO_CERTIFICATE_RESERVED = 41, 91 | TLS_ALERT_BAD_CERTIFICATE = 42, 92 | TLS_ALERT_UNSUPPORTED_CERTIFICATE = 43, 93 | TLS_ALERT_CERTIFICATE_REVOKED = 44, 94 | TLS_ALERT_CERTIFICATE_EXPIRED = 45, 95 | TLS_ALERT_CERTIFICATE_UNKNOWN = 46, 96 | TLS_ALERT_ILLEGAL_PARAMETER = 47, 97 | TLS_ALERT_UNKNOWN_CA = 48, 98 | TLS_ALERT_ACCESS_DENIED = 49, 99 | TLS_ALERT_DECODE_ERROR = 50, 100 | TLS_ALERT_DECRYPT_ERROR = 51, 101 | TLS_ALERT_EXPORT_RESTRICTION_RESERVED = 60, 102 | TLS_ALERT_PROTOCOL_VERSION = 70, 103 | TLS_ALERT_INSUFFICIENT_SECURITY = 71, 104 | TLS_ALERT_INTERNAL_ERROR = 80, 105 | TLS_ALERT_INAPPROPRIATE_FALLBACK = 86, 106 | TLS_ALERT_USER_CANCELED = 90, 107 | TLS_ALERT_NO_RENEGOTIATION_RESERVED = 100, 108 | TLS_ALERT_MISSING_EXTENSION = 109, 109 | TLS_ALERT_UNSUPPORTED_EXTENSION = 110, 110 | TLS_ALERT_CERTIFICATE_UNOBTAINABLE_RESERVED = 111, 111 | TLS_ALERT_UNRECOGNIZED_NAME = 112, 112 | TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE = 113, 113 | TLS_ALERT_BAD_CERTIFICATE_HASH_VALUE_RESERVED = 114, 114 | TLS_ALERT_UNKNOWN_PSK_IDENTITY = 115, 115 | TLS_ALERT_CERTIFICATE_REQUIRED = 116, 116 | TLS_ALERT_NO_APPLICATION_PROTOCOL = 120, 117 | TLS_ALERT_NONE = 255, 118 | } tls_alert_t; 119 | 120 | typedef enum tls_max_frag_length { 121 | TLS_MAX_FRAGMENT_LENGTH_2_9 = 1, 122 | TLS_MAX_FRAGMENT_LENGTH_2_10 = 2, 123 | TLS_MAX_FRAGMENT_LENGTH_2_11 = 3, 124 | TLS_MAX_FRAGMENT_LENGTH_2_12 = 4, 125 | } tls_max_frag_length_t; 126 | 127 | 128 | /** 129 | * Internal structures 130 | */ 131 | 132 | typedef struct tls_supported_versions_ce { 133 | uint16_t extension_id; /**< 0x002b */ 134 | uint16_t extension_length; /**< 3 */ 135 | uint8_t data_length; /**< 2 */ 136 | uint16_t version_tls_13; /**< 0x0304 */ 137 | } tls_supported_versions_ce_t; 138 | 139 | typedef struct tls_ec_point_formats_ce { 140 | uint16_t extension_id; /**< 0x000b */ 141 | uint16_t extension_length; /**< 2 */ 142 | uint8_t data_length; /**< 1 */ 143 | uint8_t uncompressed; /**< 0 */ 144 | } tls_ec_point_formats_ce_t; 145 | 146 | typedef struct tls_supported_groups_ce { 147 | uint16_t extension_id; /**< 0x000a */ 148 | uint16_t extension_length; /**< 4 */ 149 | uint16_t data_length; /**< 2 */ 150 | uint16_t ec_x25519; /**< 0x001d */ 151 | } tls_supported_groups_ce_t; 152 | 153 | typedef struct tls_signature_algo_ce { 154 | uint16_t extension_id; /**< 0x000d */ 155 | uint16_t extension_length; /**< 4 */ 156 | uint16_t data_length; /**< 2 */ 157 | uint16_t algorithms[NUMBER_SUPPORTED_SIGNATURE_ALGO]; 158 | } tls_signature_algo_ce_t; 159 | 160 | typedef struct tls_key_share_ce { 161 | uint16_t extension_id; /**< 0x0033 */ 162 | uint16_t extension_length; /**< 38 */ 163 | uint16_t data_length; /**< 36 */ 164 | uint16_t x25519_type; /**< 0x001d */ 165 | uint16_t x25519_size; /**< 32 */ 166 | uint8_t x25519_pub_key[32]; /**< Variable */ 167 | } tls_key_share_ce_t; 168 | 169 | typedef struct tls_empty_key_share_ce { 170 | uint16_t extension_id; /**< 0x0033 */ 171 | uint16_t extension_length; /**< 2 */ 172 | uint16_t data_length; /**< 0 */ 173 | } tls_empty_key_share_ce_t; 174 | 175 | typedef struct tls_alpn_ce { 176 | uint16_t extension_id; /**< 0x0010 */ 177 | uint16_t extension_length; /**< 11 */ 178 | uint16_t data_length; /**< 9 */ 179 | uint8_t http_1_1_length; /**< 8 */ 180 | char http_1_1_id[8]; /*< http/1.1 */ 181 | } tls_alpn_ce_t; 182 | 183 | typedef struct tls_record_size_limit_ce { 184 | uint16_t extension_id; /**< 0x001c */ 185 | uint16_t extension_length; /**< 2 */ 186 | uint16_t record_size_limit; 187 | } tls_record_size_limit_ce_t; 188 | 189 | typedef struct tls_max_fragment_length_ce { 190 | uint16_t extension_id; /**< 0x0001 */ 191 | uint16_t extension_length; /**< 1 */ 192 | uint8_t max_fragment_length; 193 | } tls_max_fragment_length_ce_t; 194 | 195 | typedef struct tls_server_name_ce { 196 | uint16_t extension_id; /**< 0x0000 */ 197 | uint16_t extension_length; 198 | uint16_t entry_length; 199 | uint8_t dns_type; 200 | uint16_t hostname_length; 201 | uint8_t hostname[]; /**< Variable-length extension */ 202 | } tls_server_name_ce_t; 203 | 204 | typedef struct tls_psk_key_exchange_mode_ce { 205 | uint16_t extension_id; /**< 0x002d */ 206 | uint16_t extension_length; 207 | uint8_t psk_key_exchange_mode_length; 208 | uint8_t psk_key_exchange_mode_ke; /**< TLS_PSK_MODE_KE only */ 209 | } tls_psk_key_exchange_mode_ce_t; 210 | 211 | typedef struct tls_pre_shared_key_ce { 212 | uint16_t extension_id; /**< 0x0029 */ 213 | uint16_t extension_length; 214 | uint16_t identities_length; 215 | uint16_t identity_length; 216 | uint8_t identity[]; /**< Variable-length extension */ 217 | // uint32_t obfuscated_ticket_age; 218 | // uint16_t binders_length; 219 | // uint8_t binder_entry_length; 220 | // uint8_t binder_entry[]; 221 | } tls_pre_shared_key_ce_t; 222 | 223 | typedef struct tls_pre_shared_key_end_ce { 224 | uint32_t obfuscated_ticket_age; 225 | uint16_t binders_length; 226 | uint8_t binder_entry_length; 227 | uint8_t binder_entry[]; 228 | } tls_pre_shared_key_end_ce_t; 229 | 230 | 231 | /** 232 | * Actual TLS handhsake structure, used in this lib according to the supported features 233 | */ 234 | typedef struct tls_client_hello_header { 235 | uint8_t hs_type; 236 | uint24_t client_hello_length; 237 | uint16_t version; 238 | uint8_t random[32]; 239 | uint8_t session_id_length; /**< Session ID not used in TLS 1.3 */ 240 | uint8_t session_id[32]; 241 | uint16_t cipher_suite_length; 242 | uint16_t cipher_suites[NUMBER_SUPPORTED_CIPHER_SUITES]; 243 | uint8_t comp_methods_length; /**< Always 1 */ 244 | uint8_t null_compression; /**< no compression methods in TLS 1.3 */ 245 | uint16_t extensions_length; 246 | } tls_client_hello_header_t; 247 | 248 | /** 249 | * Message sent in response to a certificate request: the calc does not have any certificate 250 | */ 251 | typedef struct tls_empty_certificate { 252 | tls_handshake_t header; 253 | uint8_t context_size; 254 | uint8_t context[]; 255 | // uint24_t certificate_list_size; /**< 0 here */ 256 | } tls_empty_certificate_t; 257 | 258 | 259 | typedef struct tls_ticket_list { 260 | /** The following field is the IP of the server that sent the ticket. 261 | * In theory, the compared data should be the SNI, but for size and time optimization purposes, we keep the IP. 262 | * If the server IP changed => the ticket is useless and will be dropped once its lifetime is reached. 263 | * If the another server took this IP => the ticket is sent, the server will reject it and the ticket will be dropped 264 | */ 265 | uint32_t ip_server; 266 | uint32_t start_date; 267 | uint8_t psk_length; 268 | void *psk; 269 | struct tls_ticket_list *next; 270 | tls_session_ticket_t ticket; 271 | // only one cipher suite available, so no need to store these data 272 | } tls_ticket_list_t; 273 | 274 | 275 | /** 276 | * Internal functions prototype 277 | */ 278 | 279 | web_status_t deliver_tls_record(tls_exchange_t *tls_exch, void *data, size_t length_data, tls_content_type_t tls_type); 280 | 281 | web_status_t _recursive_DeliverTLSRecord(tls_exchange_t *tls_exch, void *buffer, void *data, size_t length_data, 282 | uint8_t opaque_type); 283 | 284 | web_status_t send_alert(tls_exchange_t *tls_exch, tls_alert_t alert_desc); 285 | 286 | void fill_client_hello_header(void **ptr, size_t client_hello_size); 287 | 288 | void fill_supported_versions_ext(void **ptr); 289 | 290 | void fill_ec_point_formats_ext(void **ptr); 291 | 292 | void fill_supported_groups_ext(void **ptr); 293 | 294 | void fill_signature_algorithms_ext(void **ptr); 295 | 296 | void fill_key_share_ext(void **ptr, uint8_t client_private_key[]); 297 | 298 | void fill_alpn_ext(void **ptr); 299 | 300 | void fill_psk_key_exchange_mode_ext(void **ptr); 301 | 302 | void fill_record_size_limit_ext(void **ptr); 303 | 304 | void fill_max_fragment_length(void **ptr); 305 | 306 | void fill_server_name_ext(void **ptr, const char *sni, size_t sni_length); 307 | 308 | void fill_pre_shared_key_ext(void **ptr, const void *buffer, const uint8_t ticket[], uint8_t ticket_length, uint32_t obfuscated_age, 309 | uint8_t binder_key[]); 310 | 311 | web_status_t send_new_connection(tls_exchange_t *tls_exch, const char *sni, size_t sni_length); 312 | 313 | tls_ticket_list_t *find_session_ticket(uint32_t ip); 314 | 315 | web_status_t send_resumption_connection(tls_exchange_t *tls_exch, const char *sni, size_t sni_length, tls_ticket_list_t *ticket); 316 | 317 | tls_alert_t fetch_handshake_extensions(const uint8_t extensions[], size_t length, const uint8_t **server_public_key); 318 | 319 | tls_alert_t compute_cipher_data(tls_exchange_t *tls_exch); 320 | 321 | tls_alert_t fetch_server_hello(tls_exchange_t *tls_exch, tls_hello_t *server_hello, size_t length); 322 | 323 | tls_alert_t fetch_encrypted_extension(tls_exchange_t *tls_exch, const tls_encrypted_extensions_t *encrypted_ext, size_t length); 324 | 325 | tls_alert_t fetch_server_finished(tls_exchange_t *tls_exch, tls_finished_t *server_finished, size_t length); 326 | 327 | tls_alert_t fetch_new_session_ticket(tls_exchange_t *tls_exch, const tls_new_session_ticket_t *session_ticket, size_t length); 328 | 329 | tls_alert_t fetch_key_update_request(tls_exchange_t *tls_exch, tls_key_update_t *key_upd_msg, size_t length); 330 | 331 | tls_alert_t fetch_certificate_request(tls_exchange_t *tls_exch, const tls_cert_request_t *cert_request, size_t length); 332 | 333 | tls_alert_t fetch_handshake_message(tls_exchange_t *tls_exch, tls_handshake_t *handshake_msg, size_t length); 334 | 335 | void received_close_signal(tls_exchange_t *tls_exch); 336 | 337 | tls_alert_t fetch_alert_record(tls_exchange_t *tls_exch, tls_alert_record_t *alert_record); 338 | 339 | tls_alert_t fetch_tls_record(tls_exchange_t *tls_exch, void *payload, size_t length, tls_content_type_t content_type); 340 | 341 | tls_alert_t fetch_tls_encrypted_record(tls_exchange_t *tls_exch, tls_record_t *record, size_t record_length); 342 | 343 | web_status_t fetch_tls_part(web_port_t port, link_msg_type_t msg_type, void *data, size_t length, 344 | web_callback_data_t *user_data); 345 | 346 | void free_session_tickets(); 347 | 348 | void unexpected_abort(tls_exchange_t *tls_exch, tls_alert_t reason); 349 | 350 | void tls_close(tls_exchange_t *tls_exch, tls_alert_t reason, bool is_from_appli); 351 | 352 | 353 | #endif // INTERNET_TLS 354 | -------------------------------------------------------------------------------- /src/internetce/include/transport_layer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Transort layer related functions 3 | */ 4 | 5 | #ifndef INTERNET_TRANSPORT_LAYER 6 | #define INTERNET_TRANSPORT_LAYER 7 | 8 | 9 | #include 10 | #include 11 | 12 | 13 | /** 14 | * Defines 15 | */ 16 | 17 | #define PORT_LOWER_LIMIT 0x8000 /* Totally randomly chosen numbers */ 18 | #define PORT_UPPER_LIMIT 0xfff0 /* Totally randomly chosen numbers */ 19 | 20 | 21 | /** 22 | * Enums & structs 23 | */ 24 | 25 | typedef struct port_list { 26 | web_port_t port; 27 | web_port_callback_t *callback; 28 | web_callback_data_t *callback_data; 29 | struct port_list *next; 30 | } port_list_t; 31 | 32 | 33 | /** 34 | * Global variable 35 | */ 36 | 37 | extern port_list_t *listened_ports; 38 | 39 | 40 | /** 41 | * Internal functions prototype 42 | */ 43 | 44 | int call_callbacks(uint8_t protocol, void *data, size_t length, web_port_t port); 45 | 46 | bool is_port_in_use(web_port_t port); 47 | 48 | uint16_t transport_checksum(void *data, size_t length, uint32_t ip_src, uint32_t ip_dst, uint8_t protocol); 49 | 50 | 51 | #endif // INTERNET_TRANSPORT_LAYER 52 | -------------------------------------------------------------------------------- /src/internetce/include/udp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * UDP related functions 3 | */ 4 | 5 | #ifndef INTERNET_UDP 6 | #define INTERNET_UDP 7 | 8 | 9 | #include 10 | #include 11 | 12 | 13 | /** 14 | * Internal functions prototype 15 | */ 16 | 17 | msg_queue_t *_recursive_PushUDPDatagram(void *buffer, void *data, size_t length_data, uint32_t ip_dst, 18 | web_port_t port_src, web_port_t port_dst); 19 | 20 | web_status_t fetch_udp_datagram(udp_datagram_t *datagram, size_t length, uint32_t ip_src, uint32_t ip_dst); 21 | 22 | 23 | #endif // INTERNET_UDP 24 | -------------------------------------------------------------------------------- /src/internetce/include/usb.h: -------------------------------------------------------------------------------- 1 | /** 2 | * USB functions 3 | */ 4 | 5 | #ifndef INTERNET_USB 6 | #define INTERNET_USB 7 | 8 | 9 | #include 10 | 11 | 12 | /** 13 | * Internal functions prototype 14 | */ 15 | 16 | usb_error_t usbHandler(usb_event_t event, void *event_data, usb_callback_data_t *data); 17 | 18 | web_status_t configure_usb_device(); 19 | 20 | usb_error_t packets_callback(usb_endpoint_t endpoint, usb_transfer_status_t status, size_t transferred, 21 | usb_transfer_data_t *data); 22 | 23 | 24 | #endif // INTERNET_USB 25 | -------------------------------------------------------------------------------- /src/internetce/include/utils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Assembly functions 3 | */ 4 | 5 | #ifndef INTERNET_ASSEMBLY 6 | #define INTERNET_ASSEMBLY 7 | 8 | 9 | #include 10 | #include 11 | 12 | 13 | /** 14 | * Assembly functions 15 | */ 16 | 17 | var_t *MoveToArc(const char* name); 18 | 19 | var_t *MoveToRam(const char* name); 20 | 21 | bool os_EnoughMem(size_t mem); 22 | 23 | int ResizeAppVar(const char* name, size_t new_size); /* 1=the resizing happened, 0 if not */ 24 | 25 | 26 | #endif // INTERNET_ASSEMBLY 27 | -------------------------------------------------------------------------------- /src/internetce/ipv4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "include/ipv4.h" 7 | #include "include/core.h" 8 | #include "include/debug.h" 9 | #include "include/ethernet.h" 10 | #include "include/tcp.h" 11 | #include "include/udp.h" 12 | #include "include/icmpv4.h" 13 | 14 | 15 | /**********************************************************************************************************************\ 16 | * Public functions * 17 | \**********************************************************************************************************************/ 18 | 19 | msg_queue_t *web_PushIPv4Packet(void *data, size_t length_data, uint32_t ip_dst, uint8_t protocol) { 20 | void *buffer = _alloc_msg_buffer(data, length_data, IPV4_HEADERS_SIZE, true); 21 | if(buffer == NULL) { 22 | return NULL; 23 | } 24 | return _recursive_PushIPv4Packet(buffer, buffer + IPV4_HEADERS_SIZE - 4, length_data, ip_dst, 25 | protocol); 26 | } 27 | 28 | web_status_t web_SendIPv4Packet(void *data, size_t length_data, uint32_t ip_dst, uint8_t protocol) { 29 | msg_queue_t *queued = web_PushIPv4Packet(data, length_data, ip_dst, protocol); 30 | if(queued != NULL) { 31 | queued->send_once = true; /* Send once */ 32 | } 33 | return queued ? WEB_SUCCESS : WEB_NOT_ENOUGH_MEM; 34 | } 35 | 36 | 37 | /**********************************************************************************************************************\ 38 | * Private functions * 39 | \**********************************************************************************************************************/ 40 | 41 | msg_queue_t *_recursive_PushIPv4Packet(void *buffer, void *data, size_t length_data, uint32_t ip_dst, uint8_t protocol){ 42 | static unsigned int nbpacket = 0; 43 | if(data - sizeof(ipv4_packet_t) < buffer) { 44 | dbg_err("Can't push IPv4 packet"); 45 | _free(buffer); 46 | return NULL; 47 | } 48 | 49 | /* Filling the IPv4 header */ 50 | size_t size = length_data + sizeof(ipv4_packet_t); 51 | ipv4_packet_t *ipv4_pckt = (ipv4_packet_t *)(data - sizeof(ipv4_packet_t)); 52 | ipv4_pckt->VerIHL = 0x45; 53 | ipv4_pckt->ToS = 0x00; 54 | ipv4_pckt->TotalLength = htons(size); 55 | ipv4_pckt->Id = htons(nbpacket++); 56 | ipv4_pckt->FlagsFragmentOffset = htons(0x4000); 57 | ipv4_pckt->TTL = 0x80; 58 | ipv4_pckt->Protocol = protocol; 59 | ipv4_pckt->HeaderChecksum = 0x0000; 60 | ipv4_pckt->IP_addr_src = netinfo.IP_addr; 61 | ipv4_pckt->IP_addr_dst = ip_dst; 62 | 63 | /* Computing the header checksum */ 64 | uint16_t chksm = ipv4_checksum(ipv4_pckt, sizeof(ipv4_packet_t)); 65 | ipv4_pckt->HeaderChecksum = chksm; 66 | 67 | return _recursive_PushEthernetFrame(buffer, ipv4_pckt, size, ETH_IPV4); 68 | } 69 | 70 | uint16_t ipv4_checksum(void *header, size_t count) { 71 | uint32_t sum = 0; 72 | uint16_t *data = (uint16_t *)header; 73 | 74 | while(count > 1) { 75 | sum += *(uint16_t *)data++; 76 | count -= 2; 77 | } 78 | 79 | if(count != 0) { 80 | sum += *(uint8_t *)data; 81 | } 82 | 83 | while(sum >> 16 != 0) { 84 | sum = (sum & 0xffff) + (sum >> 16); 85 | } 86 | 87 | return (uint16_t)~sum; 88 | } 89 | 90 | web_status_t fetch_IPv4_packet(ipv4_packet_t *pckt, size_t length) { 91 | const size_t header_size = (pckt->VerIHL & 0x0F) * 4; 92 | void *payload = (void *)pckt + header_size; 93 | web_status_t ret_val; 94 | 95 | if(ipv4_checksum(pckt, header_size) != 0) { 96 | dbg_warn("Received bad checksumed IPv4 packet"); 97 | return WEB_ERROR_FAILED; 98 | } 99 | if(pckt->FlagsFragmentOffset != 0 && pckt->FlagsFragmentOffset != 0x40) { 100 | dbg_warn("Received fragmented IPv4 packet"); 101 | } 102 | 103 | switch(pckt->Protocol) { 104 | case TCP_PROTOCOL: { 105 | tcp_segment_t *tcp_seg = (tcp_segment_t *)payload; 106 | ret_val = fetch_raw_tcp_segment(tcp_seg, length - header_size, pckt->IP_addr_src, pckt->IP_addr_dst); 107 | break; 108 | } case UDP_PROTOCOL: { 109 | udp_datagram_t *udp_dtgm = (udp_datagram_t *)payload; 110 | ret_val = fetch_udp_datagram(udp_dtgm, length - header_size, pckt->IP_addr_src, pckt->IP_addr_dst); 111 | break; 112 | } case ICMP_PROTOCOL: { 113 | icmpv4_echo_t *msg = (icmpv4_echo_t *)payload; 114 | ret_val = fetch_icmpv4_msg(msg, length - header_size, pckt->IP_addr_src); 115 | break; 116 | } default: 117 | ret_val = WEB_SUCCESS; 118 | } 119 | return ret_val; 120 | } 121 | -------------------------------------------------------------------------------- /src/internetce/rndis.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "include/rndis.h" 7 | #include "include/debug.h" 8 | #include "include/core.h" 9 | #include "include/scheduler.h" 10 | 11 | 12 | /**********************************************************************************************************************\ 13 | * Global Variables * 14 | \**********************************************************************************************************************/ 15 | 16 | static rndis_state_t rndis_state = { 17 | .cur_request_id = 1, 18 | .max_transfer_size = 0, /* Set later */ 19 | .is_resetting = false, 20 | .receive_buffer = NULL, 21 | .send_buffer_list = NULL, 22 | }; 23 | 24 | static const usb_control_setup_t in_setup_buffer = (usb_control_setup_t){ 25 | .bmRequestType = USB_DEVICE_TO_HOST | USB_CLASS_REQUEST | USB_RECIPIENT_INTERFACE, 26 | .bRequest = 1, 27 | .wValue = 0, 28 | .wIndex = 0, 29 | .wLength = RNDIS_CONTROL_BUFFER_SIZE 30 | }; 31 | 32 | 33 | /**********************************************************************************************************************\ 34 | * Public functions * 35 | \**********************************************************************************************************************/ 36 | 37 | msg_queue_t *web_PushRNDISPacket(void *data, size_t length_data) { 38 | void *buffer = _alloc_msg_buffer(data, length_data, sizeof(rndis_packet_msg_t), false); 39 | if(buffer == NULL) { 40 | return NULL; 41 | } 42 | return _recursive_PushRNDISPacket(buffer, buffer + sizeof(rndis_packet_msg_t), length_data); 43 | } 44 | 45 | web_status_t web_SendRNDISPacket(void *data, size_t length_data) { 46 | msg_queue_t *queued = web_PushRNDISPacket(data, length_data); 47 | if(queued != NULL) { 48 | queued->send_once = true; /* Send once */ 49 | } 50 | return queued ? WEB_SUCCESS : WEB_NOT_ENOUGH_MEM; 51 | } 52 | 53 | 54 | /**********************************************************************************************************************\ 55 | * Private functions * 56 | \**********************************************************************************************************************/ 57 | 58 | msg_queue_t *_recursive_PushRNDISPacket(void *buffer, void *data, size_t length_data) { 59 | if(data - sizeof(rndis_packet_msg_t) != buffer) { 60 | dbg_err("Can't push RNDIS packet"); 61 | _free(buffer); 62 | return NULL; 63 | } 64 | 65 | if(length_data + sizeof(rndis_packet_msg_t) > rndis_state.max_transfer_size) { 66 | dbg_err("Trying to send a too large RNDIS packet"); 67 | _free(buffer); 68 | return NULL; 69 | } 70 | 71 | rndis_packet_msg_t *pckt = (rndis_packet_msg_t *)(data - sizeof(rndis_packet_msg_t)); 72 | memset(pckt, 0, sizeof(rndis_packet_msg_t)); 73 | pckt->MessageType = RNDIS_PACKET_MSG; 74 | pckt->MessageLength = sizeof(rndis_packet_msg_t) + length_data; 75 | pckt->DataOffset = 36; 76 | pckt->DataLength = length_data; 77 | memcpy((void *)pckt + sizeof(rndis_packet_msg_t), data, length_data); 78 | 79 | return web_PushMessage(pckt, length_data + sizeof(rndis_packet_msg_t)); 80 | } 81 | 82 | void send_control_rndis(void *rndis_msg, size_t length) { 83 | const usb_control_setup_t out_ctrl = { 84 | .bmRequestType = USB_HOST_TO_DEVICE | USB_CLASS_REQUEST | USB_RECIPIENT_INTERFACE, 85 | .bRequest = 0, 86 | .wValue = 0, 87 | .wIndex = 0, 88 | .wLength = length}; 89 | allocated_memory_t *alloc_buffer = _malloc(sizeof(allocated_memory_t) + sizeof(usb_control_setup_t) + length, "rndisc"); 90 | if(alloc_buffer == NULL) { 91 | dbg_err("No memory"); 92 | return; 93 | } 94 | alloc_buffer->next = rndis_state.send_buffer_list; 95 | rndis_state.send_buffer_list = alloc_buffer; 96 | void *data = alloc_buffer->memory + sizeof(usb_control_setup_t); 97 | memcpy(alloc_buffer->memory, &out_ctrl, sizeof(usb_control_setup_t)); 98 | memcpy(data, rndis_msg, length); 99 | 100 | schedule(100, send_control_rndis_scheduler, NULL, alloc_buffer); 101 | } 102 | 103 | scheduler_status_t send_control_rndis_scheduler(web_callback_data_t *buffer) { 104 | void *message = ((allocated_memory_t *)buffer)->memory; 105 | usb_error_t err = usb_ScheduleDefaultControlTransfer(netinfo.device, (usb_control_setup_t *)message, 106 | message + sizeof(usb_control_setup_t), send_control_rndis_callback, 107 | buffer); 108 | 109 | if(err & USB_ERROR_NO_DEVICE) { 110 | dbg_warn("Lost connection (int)"); 111 | netinfo.state = STATE_USB_LOST; 112 | return SCHEDULER_DESTROY; 113 | } else if(err != USB_SUCCESS) { 114 | dbg_warn("(RNDIS) Unable to send"); 115 | return SCHEDULER_AGAIN; 116 | } 117 | 118 | return SCHEDULER_DESTROY; 119 | } 120 | 121 | usb_error_t send_control_rndis_callback(usb_endpoint_t endpoint, usb_transfer_status_t status, size_t transferred, 122 | usb_transfer_data_t *data) { 123 | (void)transferred; (void)endpoint; /* Unused parameter */ 124 | 125 | if(transferred == 0 || status != USB_SUCCESS) { 126 | dbg_warn("Failed to send data"); 127 | schedule(100, send_control_rndis_scheduler, NULL, data); 128 | } else { 129 | free_allocated_memory(&rndis_state.send_buffer_list, data); 130 | } 131 | 132 | return USB_SUCCESS; 133 | } 134 | 135 | void init_rndis_exchange() { 136 | rndis_init_msg_t rndis_initmsg = { 137 | .MessageType = RNDIS_INIT_MSG, 138 | .MessageLength = sizeof(rndis_init_msg_t), 139 | .RequestId = rndis_state.cur_request_id++, 140 | .MajorVersion = RNDIS_MAJOR_VERSION, 141 | .MinorVersion = RNDIS_MINOR_VERSION, 142 | .MaxTransferSize = MAX_RNDIS_TRANSFER_SIZE, 143 | }; 144 | rndis_state.not_received_keepalives_filter = 0; 145 | send_control_rndis(&rndis_initmsg, sizeof(rndis_init_msg_t)); 146 | 147 | schedule(1 * 1000, poll_interrupt_scheduler, NULL, POLL_INTERRUPT_SCHED_ID); 148 | } 149 | 150 | void send_rndis_halt() { 151 | rndis_halt_msg_t rndis_haltmsg = { 152 | .MessageType = RNDIS_HALT_MSG, 153 | .MessageLength = sizeof(rndis_halt_msg_t), 154 | .RequestId = rndis_state.cur_request_id++, 155 | }; 156 | send_control_rndis(&rndis_haltmsg, sizeof(rndis_halt_msg_t)); 157 | netinfo.state = STATE_USB_LOST; 158 | dbg_warn("Halt RNDIS /!\\"); 159 | } 160 | 161 | void send_rndis_set_msg(uint32_t oid, const void *value, size_t value_size) { 162 | uint8_t rndis_set_filter_buffer[sizeof(rndis_set_msg_t) + value_size]; 163 | rndis_set_msg_t *rndis_set_filter = (rndis_set_msg_t *)rndis_set_filter_buffer; 164 | rndis_set_filter->MessageType = RNDIS_SET_MSG; 165 | rndis_set_filter->MessageLength = sizeof(rndis_set_msg_t) + value_size; 166 | rndis_set_filter->RequestId = rndis_state.cur_request_id++; 167 | rndis_set_filter->Oid = oid; 168 | rndis_set_filter->InformationBufferLength = value_size; 169 | rndis_set_filter->InformationBufferOffset = 20; 170 | rndis_set_filter->DeviceVcHandle = 0; 171 | memcpy(rndis_set_filter_buffer + sizeof(rndis_set_msg_t), value, value_size); 172 | send_control_rndis(rndis_set_filter_buffer, sizeof(rndis_set_msg_t) + value_size); 173 | } 174 | 175 | void send_rndis_keepalive_msg() { 176 | if(rndis_state.not_received_keepalives_filter >= RNDIS_THRESHOLD_KEEPALIVE_FILTER) { 177 | dbg_warn("Too many missed KA!"); 178 | send_rndis_reset_msg(); 179 | return; 180 | } 181 | 182 | rndis_keepalive_msg_t keepalive_msg = { 183 | .MessageType = RNDIS_KEEPALIVE_MSG, 184 | .MessageLength = sizeof(rndis_keepalive_msg_t), 185 | .RequestId = rndis_state.cur_request_id++, 186 | }; 187 | send_control_rndis(&keepalive_msg, sizeof(rndis_keepalive_msg_t)); 188 | } 189 | 190 | 191 | void send_rndis_keepalive_cmplt(uint32_t request_id) { 192 | rndis_keepalive_msg_t keepalive_msg = { 193 | .MessageType = RNDIS_KEEPALIVE_CMPLT, 194 | .MessageLength = sizeof(rndis_keepalive_msg_t), 195 | .RequestId = request_id, 196 | }; 197 | 198 | send_control_rndis(&keepalive_msg, sizeof(rndis_keepalive_msg_t)); 199 | dbg_info("Keepalive rcvd"); 200 | } 201 | 202 | void send_rndis_reset_msg() { 203 | rndis_reset_msg_t reset_msg = { 204 | .MessageType = RNDIS_RESET_MSG, 205 | .MessageLength = sizeof(rndis_ctrl_msg_t), 206 | .Reserved = 0, 207 | }; 208 | 209 | dbg_warn("Reset RNDIS /!\\"); 210 | rndis_state.is_resetting = true; 211 | send_control_rndis(&reset_msg, sizeof(rndis_reset_msg_t)); 212 | netinfo.state = STATE_RNDIS_INIT; 213 | } 214 | 215 | usb_error_t interrupt_handler(usb_endpoint_t endpoint, usb_transfer_status_t status, size_t transferred, 216 | usb_transfer_data_t *data) { 217 | (void)endpoint; (void)status; (void)transferred; (void)data; 218 | 219 | /* Reschedule next */ 220 | schedule(1 * 1000, poll_interrupt_scheduler, NULL, POLL_INTERRUPT_SCHED_ID); 221 | 222 | if(status & USB_ERROR_NO_DEVICE) { 223 | dbg_warn("Lost connection (int)"); 224 | send_rndis_reset_msg(); 225 | return USB_ERROR_FAILED; 226 | } 227 | 228 | if(rndis_state.receive_buffer == NULL) { 229 | rndis_state.receive_buffer = _malloc(RNDIS_CONTROL_BUFFER_SIZE, "inth"); 230 | if(rndis_state.receive_buffer == NULL) { 231 | dbg_err("No memory"); 232 | return USB_ERROR_FAILED; 233 | } 234 | } else { 235 | dbg_warn("Last received timeouted"); 236 | } 237 | 238 | usb_ScheduleDefaultControlTransfer(netinfo.device, &in_setup_buffer, rndis_state.receive_buffer, ctrl_rndis_callback, NULL); 239 | return USB_SUCCESS; 240 | } 241 | 242 | usb_error_t ctrl_rndis_callback(usb_endpoint_t endpoint, usb_transfer_status_t status, size_t transferred, 243 | usb_transfer_data_t *data) { 244 | (void)transferred; (void)endpoint; (void)data; /* Unused parameter */ 245 | 246 | if(status & USB_ERROR_NO_DEVICE) { 247 | dbg_warn("Lost connection (ctrl)"); 248 | netinfo.state = STATE_USB_LOST; 249 | return USB_ERROR_FAILED; 250 | } 251 | 252 | rndis_ctrl_msg_t *rndis_msg = (rndis_ctrl_msg_t *)rndis_state.receive_buffer; 253 | if(rndis_msg->MessageType & CMPLT_TYPE && rndis_msg->MessageType != RNDIS_RESET_CMPLT && 254 | ((rndis_ctrl_cmplt_t *)rndis_msg)->Status != RNDIS_STATUS_SUCCESS) { 255 | dbg_warn("An RNDIS error occurred"); 256 | send_rndis_reset_msg(); 257 | return USB_SUCCESS; 258 | } 259 | 260 | switch(rndis_msg->MessageType) { 261 | case RNDIS_INIT_CMPLT: { 262 | /* Checking everything's OK */ 263 | const rndis_init_cmplt_t *init_cmplt = (rndis_init_cmplt_t *)rndis_state.receive_buffer; 264 | if(init_cmplt->MessageLength != sizeof(rndis_init_cmplt_t) || init_cmplt->DeviceFlags != RNDIS_DF_CONNECTIONLESS \ 265 | || init_cmplt->MajorVersion != RNDIS_MAJOR_VERSION || init_cmplt->MinorVersion != RNDIS_MINOR_VERSION \ 266 | || init_cmplt->MaxPacketsPerTransfer == 0 || init_cmplt->MaxTransferSize < 536 + TCP_HEADERS_SIZE \ 267 | || init_cmplt->Medium != RNDIS_MEDIUM_802_3) { 268 | send_rndis_reset_msg(); 269 | } else { 270 | rndis_state.max_transfer_size = min(init_cmplt->MaxTransferSize, MAX_RNDIS_TRANSFER_SIZE); 271 | const uint32_t filter_value = RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_ALL_MULTICAST | 272 | RNDIS_PACKET_TYPE_BROADCAST | RNDIS_PACKET_TYPE_PROMISCUOUS; 273 | send_rndis_set_msg(OID_GEN_CURRENT_PACKET_FILTER, &filter_value, sizeof(uint32_t)); 274 | } 275 | break; 276 | } 277 | case RNDIS_QUERY_CMPLT: 278 | dbg_err("Not supported yet"); 279 | break; 280 | case RNDIS_SET_CMPLT: /* Only one Set for now */ 281 | /* If an RNDIS reset, we don't want to make DHCP again */ 282 | if(rndis_state.is_resetting) { 283 | netinfo.state = STATE_NETWORK_CONFIGURED; 284 | rndis_state.is_resetting = false; 285 | } else { 286 | netinfo.state = STATE_RNDIS_DATA_INIT; 287 | } 288 | /* 289 | Send Keepalives every SEND_KEEPALIVE_INTERVAL (5s). 290 | For now, keepalives are sent no matter if messages have been received in between. 291 | */ 292 | web_status_t ret_val = schedule(SEND_KEEPALIVE_INTERVAL, send_keepalive_scheduler, NULL, SEND_KEEPALIVE_SCHED_ID); 293 | if(ret_val != WEB_SUCCESS) { 294 | dbg_err("Failed to schedule keepalive"); 295 | } 296 | break; 297 | case RNDIS_RESET_CMPLT: 298 | dbg_info("Received reset cmplt"); 299 | if(((rndis_reset_cmplt_t *)rndis_msg)->Status != RNDIS_STATUS_SUCCESS) { 300 | dbg_err("Wow, this device is lost, amen..."); 301 | send_rndis_halt(); 302 | } else { 303 | flush_event_list(); 304 | init_rndis_exchange(); 305 | } 306 | break; 307 | case RNDIS_INDICATE_MSG: 308 | dbg_warn("Device sent an Indicate Status Message: %lx", ((rndis_ctrl_cmplt_t *)rndis_msg)->Status); 309 | break; 310 | case RNDIS_KEEPALIVE_MSG: /* The device is conceited enough to send us a KEEPALIVE request... */ 311 | send_rndis_keepalive_cmplt(rndis_msg->RequestId); 312 | break; 313 | case RNDIS_KEEPALIVE_CMPLT: 314 | rndis_state.not_received_keepalives_filter = 0; 315 | break; 316 | /* 317 | case RNDIS_PACKET_MSG: 318 | case RNDIS_INIT_MSG: 319 | case RNDIS_HALT_MSG: 320 | case RNDIS_QUERY_MSG: 321 | case RNDIS_SET_MSG: 322 | */ 323 | default: 324 | dbg_warn("Unexpected RNDIS message: %lx", rndis_msg->MessageType); 325 | break; 326 | } 327 | 328 | _free(rndis_state.receive_buffer); 329 | rndis_state.receive_buffer = NULL; 330 | return USB_SUCCESS; 331 | } 332 | 333 | scheduler_status_t poll_interrupt_scheduler(web_callback_data_t *user_data) { 334 | (void)user_data; /* should be POLL_INTERRUPT_SCHED_ID */ 335 | usb_error_t status = usb_ScheduleInterruptTransfer(usb_GetDeviceEndpoint(netinfo.device, netinfo.ep_wc_in), 336 | rndis_state.interrupt_buffer, 8, interrupt_handler, NULL); 337 | 338 | if(status != USB_SUCCESS) { 339 | return SCHEDULER_AGAIN; 340 | } 341 | 342 | return SCHEDULER_DESTROY; 343 | } 344 | 345 | scheduler_status_t send_keepalive_scheduler(web_callback_data_t *user_data) { 346 | (void)user_data; /* should be SEND_KEEPALIVE_SCHED_ID */ 347 | send_rndis_keepalive_msg(); 348 | return SCHEDULER_AGAIN; 349 | } 350 | 351 | void free_rndis_data() { 352 | /* Free receive buffer */ 353 | if(rndis_state.receive_buffer != NULL) { 354 | _free(rndis_state.receive_buffer); 355 | rndis_state.receive_buffer = NULL; 356 | } 357 | 358 | /* Free send buffers */ 359 | free_allocated_memory_list(rndis_state.send_buffer_list); 360 | rndis_state.send_buffer_list = NULL; 361 | } 362 | -------------------------------------------------------------------------------- /src/internetce/scheduler.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "include/scheduler.h" 5 | #include "include/debug.h" 6 | #include "include/core.h" 7 | 8 | 9 | /**********************************************************************************************************************\ 10 | * Global Variables * 11 | \**********************************************************************************************************************/ 12 | 13 | schedule_list_t *event_list = NULL; 14 | 15 | 16 | /**********************************************************************************************************************\ 17 | * Private functions * 18 | \**********************************************************************************************************************/ 19 | 20 | /* Note: This file has only internal functions */ 21 | 22 | web_status_t schedule(uint24_t every, web_schedule_callback_t *schedule_callback, 23 | web_destructor_callback_t *destructor_callback, web_callback_data_t *user_data) { 24 | /* 25 | Preconditions: 26 | - user_data is a unique number (among all currently valid events) 27 | - every is in range [1, 44*1000] as counter overflows every ~ 90s 28 | */ 29 | if(every == 0 || every > 44 * 1000) { 30 | dbg_err("schedule has been given bad arguments"); 31 | return WEB_INVALID_ARGUMENTS; 32 | } 33 | schedule_list_t *new_event = _malloc(sizeof(schedule_list_t), "sched"); 34 | if(new_event == NULL) { 35 | return WEB_NOT_ENOUGH_MEM; 36 | } 37 | new_event->every = MS_TO_TICK(every); 38 | new_event->schedule_callback = schedule_callback; 39 | new_event->destructor_callback = destructor_callback; 40 | new_event->user_data = user_data; 41 | new_event->date = usb_GetCounter(); 42 | 43 | insert_event(new_event); 44 | return WEB_SUCCESS; 45 | } 46 | 47 | web_status_t delay_event(uint24_t offset_ms, web_schedule_callback_t *schedule_callback, 48 | web_destructor_callback_t *destructor_callback, web_callback_data_t *user_data) { 49 | /* 50 | Preconditions: 51 | - user_data is a unique number (among all currently valid events) 52 | - offset_ms is in range [0, 44*1000] as counter overflows every ~ 90s 53 | */ 54 | if(offset_ms > 44 * 1000) { 55 | dbg_err("delay has been given bad arguments"); 56 | return WEB_INVALID_ARGUMENTS; 57 | } 58 | 59 | schedule_list_t *new_event = _malloc(sizeof(schedule_list_t), "delay"); 60 | if(new_event == NULL) { 61 | return WEB_NOT_ENOUGH_MEM; 62 | } 63 | new_event->every = 0; /* only once */ 64 | new_event->schedule_callback = schedule_callback; 65 | new_event->destructor_callback = destructor_callback; 66 | new_event->user_data = user_data; 67 | new_event->date = usb_GetCounter() + MS_TO_TICK(offset_ms); 68 | 69 | insert_event(new_event); 70 | return WEB_SUCCESS; 71 | } 72 | 73 | web_status_t remove_event(web_callback_data_t *user_data) { 74 | schedule_list_t *cur_event = event_list; 75 | schedule_list_t *prv_event = NULL; 76 | while(cur_event != NULL) { 77 | if(cur_event->user_data == user_data) { 78 | if(prv_event != NULL) { 79 | prv_event->next = cur_event->next; 80 | } else { 81 | event_list = cur_event->next; 82 | } 83 | if(cur_event->destructor_callback != NULL) { 84 | cur_event->destructor_callback(cur_event->user_data); 85 | } 86 | _free(cur_event); 87 | return WEB_SUCCESS; 88 | } 89 | prv_event = cur_event; 90 | cur_event = cur_event->next; 91 | } 92 | return WEB_ERROR_FAILED; 93 | } 94 | 95 | void flush_event_list() { 96 | schedule_list_t *cur_event = event_list; 97 | schedule_list_t *next_event; 98 | while(cur_event != NULL) { 99 | next_event = cur_event->next; 100 | if(cur_event->destructor_callback != NULL) { 101 | cur_event->destructor_callback(cur_event->user_data); 102 | } 103 | _free(cur_event); 104 | cur_event = next_event; 105 | } 106 | event_list = NULL; 107 | } 108 | 109 | void reset_event(web_callback_data_t *user_data) { 110 | schedule_list_t *prv_event = NULL; 111 | schedule_list_t *cur_event = event_list; 112 | while(cur_event != NULL) { 113 | if(cur_event->user_data == user_data) { 114 | cur_event->date = usb_GetCounter(); 115 | if(prv_event != NULL) { 116 | prv_event->next = cur_event->next; 117 | } else { 118 | event_list = cur_event->next; 119 | } 120 | insert_event(cur_event); 121 | break; 122 | } 123 | prv_event = cur_event; 124 | cur_event = cur_event->next; 125 | } 126 | } 127 | 128 | void insert_event(schedule_list_t *new_event) { 129 | schedule_list_t *cur_event = event_list; 130 | schedule_list_t *prv_event = NULL; 131 | while(cur_event != NULL && (int24_t)(new_event->date - cur_event->date) > 0) { 132 | prv_event = cur_event; 133 | cur_event = cur_event->next; 134 | } 135 | if(prv_event != NULL) { 136 | new_event->next = prv_event->next; 137 | prv_event->next = new_event; 138 | } else { 139 | new_event->next = event_list; 140 | event_list = new_event; 141 | } 142 | } 143 | 144 | web_status_t dispatch_time_events() { 145 | const uint24_t now = usb_GetCounter(); 146 | schedule_list_t *cur_event; 147 | while(event_list != NULL && (int24_t)(now - event_list->date) > 0) { 148 | cur_event = event_list; 149 | event_list = cur_event->next; 150 | scheduler_status_t status = SCHEDULER_DESTROY; 151 | if(cur_event->schedule_callback != NULL) { 152 | status = cur_event->schedule_callback(cur_event->user_data); 153 | } 154 | if(cur_event->every == 0 || status == SCHEDULER_DESTROY) { 155 | if(cur_event->destructor_callback != NULL) { 156 | cur_event->destructor_callback(cur_event->user_data); 157 | } 158 | _free(cur_event); 159 | } else { 160 | cur_event->date = usb_GetCounter() + cur_event->every; 161 | insert_event(cur_event); 162 | } 163 | } 164 | return WEB_SUCCESS; 165 | } 166 | 167 | scheduler_status_t boolean_scheduler(web_callback_data_t *user_data) { 168 | bool *is_timeout = (bool *)user_data; 169 | *is_timeout = true; 170 | return SCHEDULER_DESTROY; 171 | } 172 | 173 | void boolean_destructor(web_callback_data_t *user_data) { 174 | bool *is_timeout = (bool *)user_data; 175 | *is_timeout = true; 176 | } 177 | -------------------------------------------------------------------------------- /src/internetce/transport_layer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "include/transport_layer.h" 6 | #include "include/core.h" 7 | #include "include/ipv4.h" 8 | #include "include/debug.h" 9 | 10 | 11 | /**********************************************************************************************************************\ 12 | * Global Variables * 13 | \**********************************************************************************************************************/ 14 | 15 | port_list_t *listened_ports = NULL; 16 | 17 | 18 | /**********************************************************************************************************************\ 19 | * Public functions * 20 | \**********************************************************************************************************************/ 21 | 22 | web_port_t web_RequestPort() { 23 | /* This function search for an unused port, starting from a random port number */ 24 | const web_port_t starting_port = randInt(PORT_LOWER_LIMIT, PORT_UPPER_LIMIT); 25 | web_port_t current_port = starting_port; 26 | while(is_port_in_use(current_port)) { 27 | if(current_port == PORT_UPPER_LIMIT) { 28 | current_port = PORT_LOWER_LIMIT; 29 | } else { 30 | current_port++; 31 | } 32 | if(current_port == starting_port) { 33 | return 0; 34 | } 35 | } 36 | return current_port; 37 | } 38 | 39 | web_status_t web_ListenPort(web_port_t port, web_port_callback_t *callback, web_callback_data_t *user_data) { 40 | port_list_t *new_port = _malloc(sizeof(port_list_t), "lport"); 41 | if(new_port == NULL) { 42 | return WEB_NOT_ENOUGH_MEM; 43 | } 44 | new_port->port = port; 45 | new_port->callback = callback; 46 | new_port->callback_data = user_data; 47 | new_port->next = listened_ports; 48 | listened_ports = new_port; 49 | return WEB_SUCCESS; 50 | } 51 | 52 | web_status_t web_UnlistenPort(web_port_t port) { 53 | web_status_t ret_val = WEB_ERROR_FAILED; 54 | port_list_t *cur_port = listened_ports; 55 | port_list_t *prev_port = NULL; 56 | port_list_t *next_port = NULL; 57 | while(cur_port) { 58 | next_port = cur_port->next; 59 | if(cur_port->port == port) { 60 | if(prev_port) { 61 | prev_port->next = cur_port->next; 62 | } else { 63 | listened_ports = cur_port->next; 64 | } 65 | _free(cur_port); 66 | ret_val = WEB_SUCCESS; 67 | } 68 | prev_port = cur_port; 69 | cur_port = next_port; 70 | } 71 | return ret_val; 72 | } 73 | 74 | /**********************************************************************************************************************\ 75 | * Private functions * 76 | \**********************************************************************************************************************/ 77 | 78 | int call_callbacks(uint8_t protocol, void *data, size_t length, web_port_t port) { 79 | int nb_matches = 0; 80 | port_list_t *cur_listenedPort = listened_ports; 81 | while(cur_listenedPort) { 82 | if(port == cur_listenedPort->port) { 83 | nb_matches++; 84 | if(cur_listenedPort->callback(port, protocol, data, length, cur_listenedPort->callback_data) != WEB_IGNORE){ 85 | break; 86 | } 87 | } 88 | cur_listenedPort = cur_listenedPort->next; 89 | } 90 | return nb_matches; 91 | } 92 | 93 | bool is_port_in_use(web_port_t port) { 94 | port_list_t *cur_listenedPort = listened_ports; 95 | while(cur_listenedPort) { 96 | if(port == cur_listenedPort->port) { 97 | return true; 98 | } 99 | cur_listenedPort = cur_listenedPort->next; 100 | } 101 | return false; 102 | } 103 | 104 | uint16_t transport_checksum(void *data, size_t length, uint32_t ip_src, uint32_t ip_dst, uint8_t protocol) { 105 | uint8_t checksum_hdr[sizeof(network_pseudo_hdr_t) + length]; 106 | network_pseudo_hdr_t *pseudo_hdr = (network_pseudo_hdr_t *)checksum_hdr; 107 | pseudo_hdr->ip_src = ip_src; 108 | pseudo_hdr->ip_dst = ip_dst; 109 | pseudo_hdr->zero = 0x00; 110 | pseudo_hdr->protocol = protocol; 111 | pseudo_hdr->length = htons(length); 112 | memcpy(checksum_hdr + sizeof(network_pseudo_hdr_t), data, length); 113 | return ipv4_checksum(checksum_hdr, length + sizeof(network_pseudo_hdr_t)); 114 | } 115 | -------------------------------------------------------------------------------- /src/internetce/udp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "include/udp.h" 7 | #include "include/core.h" 8 | #include "include/transport_layer.h" 9 | #include "include/ipv4.h" 10 | #include "include/debug.h" 11 | 12 | 13 | /**********************************************************************************************************************\ 14 | * Public functions * 15 | \**********************************************************************************************************************/ 16 | 17 | msg_queue_t *web_PushUDPDatagram(void *data, size_t length_data, uint32_t ip_dst, web_port_t port_src, 18 | web_port_t port_dst) { 19 | void *buffer = _alloc_msg_buffer(data, length_data, UDP_HEADERS_SIZE, true); 20 | if(buffer == NULL) { 21 | return NULL; 22 | } 23 | return _recursive_PushUDPDatagram(buffer, buffer + UDP_HEADERS_SIZE - 4, length_data, ip_dst, port_src, port_dst); 24 | } 25 | 26 | web_status_t web_SendUDPDatagram(void *data, size_t length_data, uint32_t ip_dst, web_port_t port_src, 27 | web_port_t port_dst) { 28 | msg_queue_t *queued = web_PushUDPDatagram(data, length_data, ip_dst, port_src, port_dst); 29 | if(queued != NULL) { 30 | queued->send_once = true; /* Send once */ 31 | } 32 | return queued ? WEB_SUCCESS : WEB_NOT_ENOUGH_MEM; 33 | } 34 | 35 | 36 | /**********************************************************************************************************************\ 37 | * Private functions * 38 | \**********************************************************************************************************************/ 39 | 40 | msg_queue_t *_recursive_PushUDPDatagram(void *buffer, void *data, size_t length_data, uint32_t ip_dst, 41 | web_port_t port_src, web_port_t port_dst) { 42 | if(data - sizeof(udp_datagram_t) < buffer) { 43 | dbg_err("Can't push UDP datagram"); 44 | _free(buffer); 45 | return NULL; 46 | } 47 | 48 | /* Filling the UDP datagram header */ 49 | size_t size = length_data + sizeof(udp_datagram_t); 50 | udp_datagram_t *datagram = (udp_datagram_t *)(data - sizeof(udp_datagram_t)); 51 | datagram->port_src = htons(port_src); 52 | datagram->port_dst = htons(port_dst); 53 | datagram->length = htons(size); 54 | datagram->checksum = 0x0000; 55 | 56 | /* Computing the header & data checksum */ 57 | uint16_t chksm = transport_checksum(datagram, size, netinfo.IP_addr, ip_dst, UDP_PROTOCOL); 58 | datagram->checksum = chksm; 59 | 60 | return _recursive_PushIPv4Packet(buffer, datagram, size, ip_dst, UDP_PROTOCOL); 61 | } 62 | 63 | web_status_t fetch_udp_datagram(udp_datagram_t *datagram, size_t length, uint32_t ip_src, uint32_t ip_dst) { 64 | if(!datagram->checksum || !transport_checksum((uint8_t*)datagram, length, ip_src, ip_dst, UDP_PROTOCOL)) { 65 | const int nb_matches = call_callbacks(UDP_PROTOCOL, datagram, length, htons(datagram->port_dst)); 66 | /* For now, no further processing is done, but it should send an ICMP port unreachable packet */ 67 | if(nb_matches <= 0) { 68 | dbg_warn("No callback found for port %u", htons(datagram->port_dst)); 69 | } 70 | return WEB_SUCCESS; 71 | } else { 72 | dbg_warn("Received bad checksumed UDP packet"); 73 | return WEB_ERROR_FAILED; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/internetce/usb.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "include/usb.h" 7 | #include "include/core.h" 8 | #include "include/rndis.h" 9 | #include "include/debug.h" 10 | #include "include/crypto.h" 11 | #include "include/ethernet.h" 12 | 13 | 14 | usb_error_t usbHandler(usb_event_t event, void *event_data, usb_callback_data_t *data) { 15 | (void)data; /* Unused parameter */ 16 | switch(event) 17 | { 18 | case USB_DEVICE_CONNECTED_EVENT: 19 | netinfo.device = (usb_device_t)event_data; 20 | netinfo.state = STATE_USB_CONNECTED; 21 | usb_ResetDevice(netinfo.device); 22 | break; 23 | case USB_DEVICE_ENABLED_EVENT: 24 | usb_RefDevice(netinfo.device); 25 | if(!(usb_GetRole() & USB_ROLE_DEVICE)) { 26 | netinfo.state = STATE_USB_ENABLED; 27 | } else { 28 | usb_DisableDevice(netinfo.device); 29 | netinfo.state = STATE_USB_INITIALIZED; 30 | } 31 | break; 32 | case USB_DEVICE_DISABLED_EVENT: 33 | case USB_DEVICE_DISCONNECTED_EVENT: 34 | netinfo.state = STATE_USB_LOST; 35 | usb_UnrefDevice(netinfo.device); 36 | netinfo.device = NULL; 37 | break; 38 | default: 39 | break; 40 | } 41 | 42 | /** 43 | * Feeding the Random Number Generator module with the current timer value. 44 | * Only doing this at the beggining, when we need fast (but not perfect) entropy. 45 | * Then, better entropy is given by the timing the lib receives USB packets. 46 | */ 47 | if(!rng_IsAvailable()) { 48 | rng_FeedFromEvent(); 49 | } 50 | 51 | monitor_usb_connection(event, netinfo.state); 52 | 53 | return USB_SUCCESS; 54 | } 55 | 56 | web_status_t configure_usb_device() { 57 | uint8_t buffer[256] = {0}; /* Allocating 256 bytes for the messages buffer, should be enough */ 58 | size_t len = 0; 59 | size_t total_length; 60 | bool is_wireless_int = false, is_cdc_int = false; 61 | uint8_t i = 0; 62 | 63 | /* First, let's retrieve the configuration descriptor total size */ 64 | usb_GetDescriptor(netinfo.device, USB_CONFIGURATION_DESCRIPTOR, 0, buffer, 9, &len); 65 | if(len != 9) { 66 | return WEB_ERROR_FAILED; 67 | } 68 | total_length = ((usb_configuration_descriptor_t*)buffer)->wTotalLength; /* More or less 40 bytes */ 69 | if(total_length > 256) { 70 | return WEB_NOT_ENOUGH_MEM; 71 | } 72 | 73 | usb_GetDescriptor(netinfo.device, USB_CONFIGURATION_DESCRIPTOR, 0, buffer, total_length, &len); 74 | if(len != total_length) { 75 | return WEB_ERROR_FAILED; 76 | } 77 | 78 | /* Iterating through all the descriptors to see if there are an rndis and cdc interfaces */ 79 | while(i < len) { 80 | usb_descriptor_t *usb_descr = (usb_descriptor_t*)(buffer + i); 81 | switch(usb_descr->bDescriptorType) { 82 | /* USB Interface Descriptor */ 83 | case USB_INTERFACE_DESCRIPTOR: { 84 | usb_interface_descriptor_t *interface_desc = (usb_interface_descriptor_t*)usb_descr; 85 | if(interface_desc->bInterfaceClass == USB_WIRELESS_CONTROLLER_CLASS && 86 | interface_desc->bInterfaceSubClass == WIRELESS_RNDIS_SUBCLASS && 87 | interface_desc->bInterfaceProtocol == WIRELESS_RNDIS_PROTOCOL) 88 | { 89 | is_wireless_int = true; 90 | is_cdc_int = false; 91 | } else if(interface_desc->bInterfaceClass == USB_MISCELLANEOUS_CLASS && 92 | interface_desc->bInterfaceSubClass == MISC_RNDIS_SUBCLASS && 93 | interface_desc->bInterfaceProtocol == MISC_RNDIS_PROTOCOL) 94 | { 95 | is_wireless_int = true; 96 | is_cdc_int = false; 97 | } else if(interface_desc->bInterfaceClass == USB_CDC_DATA_CLASS && 98 | interface_desc->bInterfaceSubClass == 0x00 && 99 | interface_desc->bInterfaceProtocol == 0x00) 100 | { 101 | is_wireless_int = false; 102 | is_cdc_int = true; 103 | } else { 104 | is_wireless_int = false; 105 | is_cdc_int = false; 106 | } 107 | break; 108 | } 109 | /* USB Endpoint Descriptor */ 110 | case USB_ENDPOINT_DESCRIPTOR: { 111 | usb_endpoint_descriptor_t *endpoint_desc = (usb_endpoint_descriptor_t*)usb_descr; 112 | if(is_wireless_int) { 113 | netinfo.ep_wc_in = endpoint_desc->bEndpointAddress; 114 | } else if(is_cdc_int && (endpoint_desc->bEndpointAddress & 0x80) != 0) { /* IN endpoint */ 115 | netinfo.ep_cdc_in = endpoint_desc->bEndpointAddress; 116 | /* The USB input buffer must be a multiple of the max packet size (see usbdrvce.h) 117 | * Considering this number is a power of 2 */ 118 | netinfo.in_buffer_size = ((MAX_RNDIS_TRANSFER_SIZE + endpoint_desc->wMaxPacketSize) & 119 | ~(endpoint_desc->wMaxPacketSize - 1)); 120 | } else if(is_cdc_int && (endpoint_desc->bEndpointAddress & 0x80) == 0) { /* OUT endpoint */ 121 | netinfo.ep_cdc_out = endpoint_desc->bEndpointAddress; 122 | } 123 | break; 124 | } 125 | /* Unknown, Unrelevant Descriptor */ 126 | default: 127 | break; 128 | } 129 | 130 | i += usb_descr->bLength; 131 | } 132 | 133 | /* If one is missing, ignoring the device */ 134 | if(netinfo.ep_wc_in == 0 || netinfo.ep_cdc_in == 0 || netinfo.ep_cdc_out == 0) { 135 | netinfo.state = STATE_USB_INITIALIZED; 136 | netinfo.ep_wc_in = 0; 137 | netinfo.ep_cdc_in = 0; 138 | netinfo.ep_cdc_out = 0; 139 | return WEB_IGNORE; 140 | } 141 | 142 | /* Otherwise, let's goooo */ 143 | if(usb_SetConfiguration(netinfo.device, (usb_configuration_descriptor_t*)buffer, len) != USB_SUCCESS) { 144 | return WEB_ERROR_FAILED; 145 | } 146 | 147 | init_rndis_exchange(); 148 | 149 | return WEB_SUCCESS; 150 | } 151 | 152 | usb_error_t packets_callback(usb_endpoint_t endpoint, usb_transfer_status_t status, size_t transferred, 153 | usb_transfer_data_t *data) { 154 | (void)endpoint; /* Unused parameter */ 155 | 156 | void *packet = *(void **)data; 157 | *(void **)data = NULL; 158 | 159 | /* Seeding Random Number Generation module */ 160 | rng_FeedFromEvent(); 161 | 162 | if(status & USB_ERROR_NO_DEVICE) { 163 | dbg_warn("Lost connection (pckt)"); 164 | netinfo.state = STATE_USB_LOST; 165 | _free(packet); 166 | return USB_ERROR_FAILED; 167 | } else if(status != USB_SUCCESS) { 168 | dbg_warn("Packet callback returned %u", status); 169 | netinfo.state = STATE_USB_LOST; 170 | _free(packet); 171 | return USB_SUCCESS; 172 | } 173 | 174 | /* Several messages can be queued in the same transfer */ 175 | size_t handled_length = 0; 176 | 177 | /* The beggining of the RNDIS packet was received in the previous USB frame */ 178 | if(netinfo.temp_usb_buffer != NULL) { 179 | rndis_packet_msg_t *const rndis_packet = (rndis_packet_msg_t *)netinfo.temp_usb_buffer; 180 | const size_t remaining = rndis_packet->MessageLength - netinfo.received_size; 181 | 182 | /* If this it still not the end of the packet... */ 183 | if(remaining > transferred) { 184 | memcpy(netinfo.temp_usb_buffer + netinfo.received_size, packet, transferred); 185 | netinfo.received_size += transferred; 186 | return USB_SUCCESS; 187 | } else { 188 | memcpy(netinfo.temp_usb_buffer + netinfo.received_size, packet, remaining); 189 | eth_frame_t *frame = (eth_frame_t *)rndis_packet->data; 190 | fetch_ethernet_frame(frame, rndis_packet->DataLength); 191 | handled_length += rndis_packet->MessageLength; 192 | _free(netinfo.temp_usb_buffer); 193 | netinfo.temp_usb_buffer = NULL; 194 | } 195 | } 196 | 197 | while(handled_length < transferred) { 198 | rndis_packet_msg_t *const cur_packet = packet + handled_length; 199 | /* If the RNDIS data has been splitted between 2 USB packets: not cool */ 200 | if(transferred - handled_length < cur_packet->MessageLength) { 201 | netinfo.temp_usb_buffer = _malloc(cur_packet->MessageLength, "tmpusb"); 202 | netinfo.received_size = transferred - handled_length; 203 | memcpy(netinfo.temp_usb_buffer, cur_packet, netinfo.received_size); 204 | _free(packet); 205 | return USB_SUCCESS; 206 | } 207 | eth_frame_t *frame = (eth_frame_t *)cur_packet->data; 208 | fetch_ethernet_frame(frame, cur_packet->DataLength); 209 | handled_length += cur_packet->MessageLength; 210 | } 211 | 212 | _free(packet); 213 | return USB_SUCCESS; 214 | } 215 | -------------------------------------------------------------------------------- /src/internetce/utils.asm: -------------------------------------------------------------------------------- 1 | ; ******************************************* 2 | ; * Author: Epharius * 3 | ; * Miscellaneous assembly stuffs * 4 | ; * You can reuse this code as you wish * 5 | ; ******************************************* 6 | 7 | assume adl=1 8 | 9 | 10 | ; ******* equates ******* 11 | AppVarObj equ 15h 12 | OP1 equ 0D005F8h 13 | _ChkFindSym equ 002050Ch 14 | _ChkInRam equ 0021F98h 15 | _Arc_Unarc equ 0021448h 16 | _OP1ToOP6 equ 00202E8h 17 | _OP6ToOP1 equ 00202C4h 18 | _EnoughMem equ 002051Ch 19 | _DelMem equ 0020590h 20 | _InsertMem equ 0020514h 21 | 22 | 23 | section .text 24 | public _MoveToArc 25 | _MoveToArc: 26 | call __frameset0 27 | ld hl,(ix+6) 28 | ld de,OP1+1 29 | ld bc,9 30 | ldir 31 | ld a,AppVarObj 32 | ld (OP1),a 33 | call _OP1ToOP6 34 | call _ChkFindSym 35 | ld hl,0 36 | jq c,.quit 37 | call _ChkInRam 38 | jq nz,.quit 39 | call _Arc_Unarc 40 | call _OP6ToOP1 41 | call _ChkFindSym 42 | ex de,hl 43 | .quit: 44 | pop ix 45 | ret 46 | 47 | 48 | section .text 49 | public _MoveToRam 50 | _MoveToRam: 51 | call __frameset0 52 | ld hl,(ix+6) 53 | ld de,OP1+1 54 | ld bc,9 55 | ldir 56 | ld a,AppVarObj 57 | ld (OP1),a 58 | call _OP1ToOP6 59 | call _ChkFindSym 60 | ld hl,0 61 | jq c,.quit 62 | call _ChkInRam 63 | jq z,.quit 64 | call _Arc_Unarc 65 | call _OP6ToOP1 66 | call _ChkFindSym 67 | ex de,hl 68 | .quit: 69 | pop ix 70 | ret 71 | 72 | 73 | section .text 74 | public _os_EnoughMem 75 | _os_EnoughMem: 76 | pop de 77 | pop hl 78 | push hl 79 | push de 80 | call _EnoughMem 81 | ld hl,0 82 | ret c 83 | inc hl 84 | ret 85 | 86 | 87 | section .text 88 | public _ResizeAppVar 89 | _ResizeAppVar: 90 | ; @warning The AppVar must reside in RAM 91 | ; @return 1 if the resizing happened, 0 if not 92 | ; @note This code can easily be used for other types of variable by replacing ld a,AppVarObj by ld a,whatyouwant 93 | call __frameset0 94 | ld a,AppVarObj 95 | ld (OP1),a 96 | ld hl,(ix+6) 97 | ld de,OP1+1 98 | ld bc,9 99 | ldir 100 | call _ChkFindSym 101 | ld hl,0 102 | jq c,.quit_return_0 103 | call _ChkInRam 104 | jq nz,.quit_return_0 105 | ex de,hl 106 | ld e,(hl) 107 | inc hl 108 | ld d,(hl) 109 | ld bc,(ix+9) 110 | ld (hl),b 111 | dec hl 112 | ld (hl),c 113 | push de 114 | ex de,hl 115 | or a 116 | sbc hl,bc 117 | pop ix 118 | jq z,.quit_return_0 119 | push ix 120 | jq nc,.shrinkSize 121 | 122 | push de 123 | ex de,hl 124 | or a 125 | sbc hl,hl 126 | sbc hl,de 127 | ex de,hl 128 | pop hl 129 | pop bc 130 | add hl,bc 131 | ex de,hl 132 | call _InsertMem 133 | jq .quit_return_1 134 | 135 | .shrinkSize: 136 | ex de,hl 137 | add hl,bc 138 | inc hl 139 | inc hl 140 | call _DelMem 141 | pop de ; reset stack 142 | 143 | .quit_return_1: 144 | ld hl,1 145 | pop ix 146 | ret 147 | 148 | .quit_return_0: 149 | or a,a 150 | sbc hl,hl 151 | pop ix 152 | ret 153 | 154 | 155 | extern __frameset0 156 | -------------------------------------------------------------------------------- /src/minimal.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Modify this file as you want. 3 | */ 4 | 5 | 6 | #include 7 | #include 8 | 9 | 10 | int main(void) 11 | { 12 | os_ClrHome(); 13 | 14 | web_Init(); 15 | while(!web_Connected() && !os_GetCSC()) { 16 | web_WaitForEvents(); 17 | } 18 | 19 | // Do whatever you want 20 | 21 | web_Cleanup(); 22 | return 0; 23 | } -------------------------------------------------------------------------------- /tests/makefile: -------------------------------------------------------------------------------- 1 | # Makefile for the autotests 2 | 3 | SUBDIRS := $(shell find . -mindepth 1 -maxdepth 1 -type d) 4 | 5 | .PHONY: all autotest $(SUBDIRS) 6 | all: $(SUBDIRS) 7 | autotest: $(SUBDIRS) 8 | 9 | $(SUBDIRS): 10 | @$(MAKE) -C $@ $(MAKECMDGOALS) 11 | -------------------------------------------------------------------------------- /tests/sha256/gen_sha256_autotest.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import json 3 | import hashlib 4 | 5 | TESTED_CASES = (("Les sanglots longs des violons de l'automne blessent mon coeur d'une langueur monotone.", "basic"), 6 | ("", "empty"), 7 | ("Les sondages c'est pour que les gens sachent ce qu'ils pensent", "62_bytes"), 8 | ("Aucune loi n'oblige les dieux à être justes, Achille, reprit Chiron. Et après tout, peut-être que l'ultime chagrin consiste à se retrouver seul sur terre une fois que l'autre est parti.", "185_bytes"), 9 | ("\0" * 56, "56_null_bytes"), 10 | ("A" * 55, "55_A")) 11 | 12 | 13 | def crc32(buf): 14 | crc32c_tab = [ 15 | 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, 16 | 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, 17 | 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, 18 | 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, 19 | 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, 20 | 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, 21 | 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, 22 | 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, 23 | 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, 24 | 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, 25 | 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 26 | 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, 27 | 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, 28 | 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, 29 | 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, 30 | 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, 31 | 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, 32 | 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, 33 | 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, 34 | 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, 35 | 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, 36 | 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, 37 | 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 38 | 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, 39 | 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, 40 | 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, 41 | 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, 42 | 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, 43 | 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, 44 | 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, 45 | 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, 46 | 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351 47 | ] 48 | 49 | crc = 0 50 | crc ^= 0xFFFFFFFF 51 | for byte in buf: 52 | crc = crc32c_tab[(crc ^ byte) & 0xFF] ^ (crc >> 8) 53 | return crc ^ 0xFFFFFFFF 54 | 55 | 56 | def generate_autotest(filename): 57 | json_dict = { 58 | "transfer_files": [ 59 | "bin/SHA256.8xp" 60 | ], 61 | "target": { 62 | "name": "SHA256", 63 | "isASM": True 64 | }, 65 | "sequence": ["action|launch"], 66 | "hashes": {}} 67 | 68 | for data, hint in TESTED_CASES: 69 | value = hashlib.sha256(data.encode("utf-8")).digest() 70 | json_dict["hashes"][f"case_{hint}"] = { 71 | "description": f"{hint}", 72 | "start": hex(0xd40000 + 320*240*2 - 32), "size": "32", 73 | "expected_CRCs": [hex(crc32(value))[2:].upper()]} 74 | json_dict["sequence"].append(f"delay|1000") 75 | json_dict["sequence"].append(f"hashWait|case_{hint}") 76 | json_dict["sequence"].append("key|enter") 77 | 78 | with open(filename, "w") as json_file: 79 | json_file.write(json.dumps(json_dict, indent=2)) 80 | 81 | print(f"{filename} created successfuly") 82 | 83 | 84 | if __name__ == "__main__": 85 | if len(sys.argv) == 2: 86 | generate_autotest(sys.argv[1]) 87 | else: 88 | print("Err: Missing autotest filename") 89 | exit(-1) 90 | -------------------------------------------------------------------------------- /tests/sha256/makefile: -------------------------------------------------------------------------------- 1 | # Autotest Makefile 2 | 3 | # ---------------------------- 4 | # Makefile Options 5 | # ---------------------------- 6 | 7 | PYTHON = python3 8 | CEDEV_ROOT = $(call cedev-config --prefix) 9 | INTERNET_ROOT = ../../src/internetce 10 | CRYPTO_ROOT = $(INTERNET_ROOT)/crypto 11 | AUTOTESTER_ROM = $(shell echo $$AUTOTESTER_ROM) 12 | 13 | # For program compilation 14 | NAME = SHA256 15 | COMPRESSED = NO 16 | ARCHIVED = NO 17 | EXTRA_ASM_SOURCES = $(CRYPTO_ROOT)/ports.asm 18 | EXTRA_C_SOURCES = $(INTERNET_ROOT)/debug.c $(CRYPTO_ROOT)/sha256.c 19 | CFLAGS = -Wall -Wextra -Oz 20 | CXXFLAGS = -Wall -Wextra -Oz 21 | 22 | # ---------------------------- 23 | # Targets 24 | # ---------------------------- 25 | 26 | all: autotest.json build autotest 27 | 28 | build: autotest.json 29 | @$(MAKE) -f $(shell cedev-config --makefile) NAME="$(NAME)" COMPRESSED="$(COMPRESSED)" ARCHIVED="$(ARCHIVED)" EXTRA_ASM_SOURCES="$(EXTRA_ASM_SOURCES)" EXTRA_C_SOURCES="$(EXTRA_C_SOURCES)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" 30 | 31 | autotest.json: gen_sha256_autotest.py 32 | @$(PYTHON) gen_sha256_autotest.py autotest.json 33 | 34 | autotest: 35 | @if [ -z "${AUTOTESTER_ROM}" ]; then \ 36 | echo "\033[31mYou need to define the AUTOTESTER_ROM variable to your CEmu ROM\033[0m"; \ 37 | else \ 38 | $(MAKE) -f $(shell cedev-config --makefile) test; \ 39 | fi 40 | -------------------------------------------------------------------------------- /tests/sha256/src/sha256_test.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Autotest for SHA256 collection 3 | * Warning: It cannot be used in CLI as CEmu does not emulate the SHA256 chip in this case. 4 | * The autotest.json file must be provided directly to the GUI autotest dock of CEmu. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "../../../src/internetce/include/crypto.h" 12 | 13 | #define TEST_1 "Les sanglots longs des violons de l'automne blessent mon coeur d'une langueur monotone." 14 | #define TEST_2 "" /* empty */ 15 | #define TEST_3 "Les sondages c'est pour que les gens sachent ce qu'ils pensent" /* Edge case because it fits in 64 bytes but the size doesn't */ 16 | #define TEST_4 "Aucune loi n'oblige les dieux à être justes, Achille, reprit Chiron. Et après tout, peut-être que l'ultime chagrin consiste à se retrouver seul sur terre une fois que l'autre est parti." 17 | #define TEST_5 {0} /* Edge case: exactly 56 bytes */ 18 | #define TEST_6 /* Edge case: exactly 55 bytes */ 19 | 20 | 21 | int main(void) 22 | { 23 | uint8_t *out = (uint8_t *)(0xd40000 + 320*240*2 - 32); /* Should be safe enough */ 24 | 25 | flash_setup(); 26 | 27 | sha256_Init(); 28 | sha256_Part((uint8_t *)TEST_1, strlen(TEST_1)); 29 | sha256_Hash(out); 30 | while(!os_GetCSC()); 31 | 32 | sha256_Init(); 33 | sha256_Part((uint8_t *)TEST_2, strlen(TEST_2)); 34 | sha256_Hash(out); 35 | while(!os_GetCSC()); 36 | 37 | sha256_Init(); 38 | sha256_Part((uint8_t *)TEST_3, strlen(TEST_3)); 39 | sha256_Hash(out); 40 | while(!os_GetCSC()); 41 | 42 | sha256_Init(); 43 | sha256_Part((uint8_t *)TEST_4, strlen(TEST_4)); 44 | sha256_Hash(out); 45 | while(!os_GetCSC()); 46 | 47 | uint8_t test5[56] = TEST_5; 48 | sha256_Init(); 49 | sha256_Part(test5, 56); 50 | sha256_Hash(out); 51 | while(!os_GetCSC()); 52 | 53 | uint8_t test6[55]; 54 | memset(test6, 'A', 55); 55 | sha256_Init(); 56 | sha256_Part(test6, 55); 57 | sha256_Hash(out); 58 | while(!os_GetCSC()); 59 | 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /tests/x25519/gen_x25519_autotest.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import json 3 | 4 | TESTED_SCALARS = ((0, "null"), 5 | (0x0100000000000000000000000000000000000000000000000000000000000000, "unit"), 6 | (0x0200000000000000000000000000000000000000000000000000000000000000, "two"), 7 | (0x202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f, "xargs example"), 8 | (0x4040404040404040404040404040404040404040404040404040404040404040, "fourties"), 9 | (0x1111111111111111111111111111111111111111111111111111111111111111, "ones"), 10 | (0x123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0, "straight flush"), 11 | (0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, "max")) 12 | 13 | 14 | def crc32(buf): 15 | crc32c_tab = [ 16 | 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, 17 | 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, 18 | 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, 19 | 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, 20 | 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, 21 | 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, 22 | 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, 23 | 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, 24 | 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, 25 | 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, 26 | 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 27 | 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, 28 | 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, 29 | 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, 30 | 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, 31 | 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, 32 | 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, 33 | 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, 34 | 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, 35 | 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, 36 | 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, 37 | 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, 38 | 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 39 | 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, 40 | 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, 41 | 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, 42 | 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, 43 | 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, 44 | 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, 45 | 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, 46 | 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, 47 | 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351 48 | ] 49 | 50 | crc = 0 51 | crc ^= 0xFFFFFFFF 52 | for byte in buf: 53 | crc = crc32c_tab[(crc ^ byte) & 0xFF] ^ (crc >> 8) 54 | return crc ^ 0xFFFFFFFF 55 | 56 | def crc32_of_list(number): 57 | bnumber = [number // 2**e % 256 for e in range(0, 249, 8)] 58 | checksum = crc32(bnumber) 59 | return checksum 60 | 61 | def finv(x): 62 | p = x 63 | for r in range(253, -1, -1): 64 | p = p*p % (2**255 - 19) 65 | if r != 2 and r != 4: 66 | p = p*x % (2**255 - 19) 67 | return p 68 | 69 | def encode_scalar(k): 70 | k_list = [k // 2**e % 256 for e in range(0, 249, 8)][::-1] 71 | k_list[0] &= 248 72 | k_list[31] &= 127 73 | k_list[31] |= 64 74 | k = sum([k_list[i] << 8*i for i in range(32)]) 75 | return k 76 | 77 | def ladder(point, k): 78 | # a, b, c, d, e, f 79 | a = d = 1 80 | c = 0 81 | b = point 82 | 83 | k = encode_scalar(k) 84 | binary = bin(k)[2:] 85 | filln = 255 - len(binary) 86 | binary = ("0" * filln) + binary 87 | for i in binary: 88 | if i == "1": 89 | a, b = b, a 90 | c, d = d, c 91 | 92 | e = a+c 93 | a = 2**255 - 19 + (a-c) # substractions are done like this in x25519.asm 94 | c = b+d 95 | b = 2**255 - 19 + (b-d) 96 | d = (e*e) % (2**255 - 19) 97 | f = (a*a) % (2**255 - 19) 98 | a = (c*a) % (2**255 - 19) 99 | c = (b*e) % (2**255 - 19) 100 | e = a+c 101 | a = 2**255 - 19 + (a-c) 102 | b = (a*a) % (2**255 - 19) 103 | c = 2**255 - 19 + (d-f) 104 | a = (c*121665) % (2**255 - 19) 105 | a = a+d 106 | c = (c*a) % (2**255 - 19) 107 | a = (d*f) % (2**255 - 19) 108 | d = (b*point) % (2**255 - 19) 109 | b = (e*e) % (2**255 - 19) 110 | 111 | if i == "1": 112 | a, b = b, a 113 | c, d = d, c 114 | 115 | c = finv(c) 116 | a = a*c % (2**255 - 19) 117 | 118 | return a 119 | 120 | def generate_autotest(filename): 121 | json_dict = { 122 | "transfer_files": [ 123 | "bin/X25519.8xp" 124 | ], 125 | "target": { 126 | "name": "X25519", 127 | "isASM": True 128 | }, 129 | "sequence": ["action|launch"], 130 | "hashes": {}} 131 | 132 | for scalar, hint in TESTED_SCALARS: 133 | value = ladder(9, scalar) 134 | json_dict["hashes"][f"scalar_{hint}"] = { 135 | "description": f"Point 9, Scalar {hint}", 136 | "start": hex(0xd40000 + 320*240*2 - 32), "size": "32", 137 | "expected_CRCs": [hex(crc32_of_list(value))[2:].upper()]} 138 | json_dict["sequence"].append(f"delay|6000") 139 | json_dict["sequence"].append(f"hashWait|scalar_{hint}") 140 | json_dict["sequence"].append("key|enter") 141 | 142 | with open(filename, "w") as json_file: 143 | json_file.write(json.dumps(json_dict, indent=2)) 144 | 145 | print(f"{filename} created successfuly") 146 | 147 | 148 | if __name__ == "__main__": 149 | if len(sys.argv) == 2: 150 | generate_autotest(sys.argv[1]) 151 | else: 152 | print("Err: Missing autotest filename") 153 | exit(-1) 154 | -------------------------------------------------------------------------------- /tests/x25519/makefile: -------------------------------------------------------------------------------- 1 | # Autotest Makefile 2 | 3 | # ---------------------------- 4 | # Makefile Options 5 | # ---------------------------- 6 | 7 | PYTHON = python3 8 | CEDEV_ROOT = $(call cedev-config --prefix) 9 | CRYPTO_ROOT = ../../src/internetce/crypto 10 | AUTOTESTER_ROM = $(shell echo $$AUTOTESTER_ROM) 11 | 12 | # For program compilation 13 | NAME = X25519 14 | COMPRESSED = NO 15 | ARCHIVED = NO 16 | EXTRA_ASM_SOURCES = $(CRYPTO_ROOT)/x25519.asm 17 | CFLAGS = -Wall -Wextra -Oz 18 | CXXFLAGS = -Wall -Wextra -Oz 19 | 20 | # ---------------------------- 21 | # Targets 22 | # ---------------------------- 23 | 24 | all: $(CRYPTO_ROOT)/mult256.asm autotest.json build autotest 25 | 26 | $(CRYPTO_ROOT)/mult256.asm: $(CRYPTO_ROOT)/generate_mult.py 27 | @$(PYTHON) $(CRYPTO_ROOT)/generate_mult.py $(CRYPTO_ROOT)/mult256.asm 32 32 > /dev/null 28 | 29 | autotest.json: gen_x25519_autotest.py 30 | @$(PYTHON) gen_x25519_autotest.py autotest.json 31 | 32 | build: 33 | @$(MAKE) -f $(shell cedev-config --makefile) NAME="$(NAME)" COMPRESSED="$(COMPRESSED)" ARCHIVED="$(ARCHIVED)" EXTRA_ASM_SOURCES="$(EXTRA_ASM_SOURCES)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" 34 | 35 | autotest: 36 | @if [ -z "${AUTOTESTER_ROM}" ]; then \ 37 | echo "\033[31mYou need to define the AUTOTESTER_ROM variable to your CEmu ROM\033[0m"; \ 38 | else \ 39 | $(MAKE) -f $(shell cedev-config --makefile) test; \ 40 | fi 41 | -------------------------------------------------------------------------------- /tests/x25519/src/x25519_test.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Autotest for x25519 scalar multiplication 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | void x25519_scalarmult(uint8_t out[32], const uint8_t point[32], const uint8_t scalar[32]); 9 | 10 | #define NUMBER_AUTOTESTS 8 11 | static const uint8_t scalars[NUMBER_AUTOTESTS][32] = { 12 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13 | {0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14 | {0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15 | {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f}, 16 | {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}, 17 | {0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 18 | {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}, 19 | {0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 20 | }; 21 | 22 | static const uint8_t point9[32] = {9, 0 /* 30 zeros */}; 23 | 24 | 25 | int main(void) 26 | { 27 | uint8_t *out = (uint8_t *)(0xd40000 + 320*240*2 - 32); /* Should be safe enough */ 28 | 29 | for(int i=0; i